fmode-ng 0.0.83 → 0.0.85
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/esm2022/lib/aigc/avatar/comp-avatar-talk/comp-avatar-talk.component.mjs +1 -1
- package/esm2022/lib/aigc/avatar/modal-chat-voice-input/modal-chat-voice-input.component.mjs +1 -1
- package/esm2022/lib/aigc/chat/chat-header-area/comp-header-area.component.mjs +1 -1
- package/esm2022/lib/aigc/chat/chat-message-card/comp-message-card.component.mjs +1 -1
- package/esm2022/lib/aigc/chat/chat-modal-input/modal-audio-message/modal-audio-message.component.mjs +1 -1
- package/esm2022/lib/aigc/chat/chat-modal-input/modal-input.component.mjs +1 -1
- package/esm2022/lib/aigc/chat/chat-panel/chat-panel.component.mjs +1 -1
- package/esm2022/lib/aigc/index.mjs +1 -1
- package/esm2022/lib/aigc/story/fm-office-viewer/fm-office-viewer.component.mjs +10 -0
- package/esm2022/lib/aigc/story/fm-story-card/fm-story-card.component.mjs +10 -0
- package/esm2022/lib/aigc/story/fm-story-list/fm-story-list.component.mjs +10 -0
- package/esm2022/lib/aigc/story/fm-story-list/story-preview.mjs +10 -0
- package/esm2022/lib/aigc/story/fm-story-loader/fm-story-loader.component.mjs +10 -0
- package/esm2022/lib/aigc/story/fm-story-splitter/fm-story-splitter.component.mjs +10 -0
- package/esm2022/lib/aigc/story/index.mjs +10 -0
- package/esm2022/lib/aigc/story/modal-chat-story/comp-chat-story-json/comp-chat-story-json.component.mjs +10 -0
- package/esm2022/lib/aigc/story/modal-chat-story/comp-diary-story/comp-diary-story.component.mjs +10 -0
- package/esm2022/lib/aigc/story/modal-chat-story/modal-chat-story.component.mjs +10 -0
- package/esm2022/lib/aigc/story/story.service.mjs +10 -0
- package/esm2022/lib/aigc/voice/fmode-voice.service.mjs +1 -1
- package/esm2022/lib/aigc/voice/index.mjs +1 -1
- package/esm2022/lib/aigc/voice/{audio.player.mjs → lib/audio/audio.player.mjs} +2 -2
- package/esm2022/lib/aigc/voice/lib/audio/audio.streamer.mjs +10 -0
- package/esm2022/lib/aigc/voice/lib/audio/streamer.microsoft.mjs +10 -0
- package/esm2022/lib/aigc/voice/lib/audio/streamer.pcm.mjs +10 -0
- package/esm2022/lib/aigc/voice/tts/fmode-tts-class.mjs +1 -1
- package/esm2022/lib/aigc/voice/tts/index.mjs +1 -1
- package/esm2022/lib/aigc/voice/tts/int-tts-provider.mjs +10 -0
- package/esm2022/lib/aigc/voice/tts/provider-doubao.mjs +10 -0
- package/esm2022/lib/aigc/voice/tts/provider-microsoft.mjs +10 -0
- package/esm2022/lib/core/agent/chat/completion/fmode-completion.mjs +1 -1
- package/esm2022/lib/core/agent/chat/completion/int-gpt-chat-options.mjs +10 -0
- package/esm2022/lib/core/agent/chat/fmode-chat.mjs +1 -1
- package/esm2022/lib/core/agent/chat/index.mjs +1 -1
- package/esm2022/lib/core/agent/prompt/agent.prompt.mjs +1 -1
- package/esm2022/lib/core/index.mjs +10 -0
- package/esm2022/lib/core/voice/index.mjs +10 -0
- package/esm2022/lib/icon/filetype/audio.svg.mjs +10 -0
- package/esm2022/lib/icon/filetype/avatar.svg.mjs +10 -0
- package/esm2022/lib/icon/filetype/chat.svg.mjs +10 -0
- package/esm2022/lib/icon/filetype/docx.svg.mjs +10 -0
- package/esm2022/lib/icon/filetype/file.svg.mjs +10 -0
- package/esm2022/lib/icon/filetype/filetype.pipe.mjs +10 -0
- package/esm2022/lib/icon/filetype/index.mjs +10 -0
- package/esm2022/lib/icon/filetype/md.svg.mjs +10 -0
- package/esm2022/lib/icon/filetype/pdf.svg.mjs +10 -0
- package/esm2022/lib/icon/filetype/pptx.svg.mjs +10 -0
- package/esm2022/lib/icon/filetype/svgtoblob.mjs +10 -0
- package/esm2022/lib/icon/filetype/video.svg.mjs +10 -0
- package/esm2022/lib/icon/filetype/xlsx.svg.mjs +10 -0
- package/esm2022/lib/icon/index.mjs +10 -0
- package/esm2022/lib/person/comp-person-gender-icon/comp-person-gender-icon.component.mjs +10 -0
- package/esm2022/lib/person/comp-person-item/comp-person-item.component.mjs +10 -0
- package/esm2022/lib/person/comp-person-story/comp-person-story.component.mjs +10 -0
- package/esm2022/lib/person/edit-upload/edit-upload.component.mjs +10 -0
- package/esm2022/lib/person/edit-upload/edit-upload.module.mjs +10 -0
- package/esm2022/lib/person/index.mjs +10 -0
- package/esm2022/lib/person/modal-person-select/modal-person-select.component.mjs +10 -0
- package/esm2022/lib/person/modal-user-verify/secret-text.pipe.mjs +10 -0
- package/esm2022/lib/person/modal-user-verify/user-verify.component.mjs +10 -0
- package/esm2022/lib/person/person-detail/person-detail.component.mjs +10 -0
- package/esm2022/lib/person/person.service.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/article-editor-topbar/article-editor-topbar.component.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/article.service.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/comp-upload-book-banners/comp-upload-book-banners.component.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/draft.service.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/fm-article-aitool/fm-article-aitool.component.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/fm-article-draft/fm-article-draft.component.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/fm-article-editor.component.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/fm-article-outline/fm-article-outline.component.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/fm-article-outline-leftitem/fm-article-outline-leftitem.component.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/fm-article-preview/fm-article-preview.component.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/fm-article-write-options/fm-article-write-options.component.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/outline-count.pipe.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/prompt/prompt-insertion-article.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/task-article-generation.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/tasks/task-article-draft-create.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/tasks/task-article-outline-edit.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/tasks/task-article-outline.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/tasks/task-article-preview.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/tasks/task-article-writing-options.mjs +10 -0
- package/esm2022/lib/text/fm-article-editor/tasks/task-document-select.mjs +10 -0
- package/esm2022/lib/text/fm-text-quill/fm-text-quill.component.mjs +10 -0
- package/esm2022/lib/text/index.mjs +10 -0
- package/esm2022/public-api.mjs +1 -1
- package/fesm2022/fmode-ng.mjs +1 -1
- package/fesm2022/fmode-ng.mjs.map +1 -1
- package/lib/aigc/avatar/comp-avatar-talk/comp-avatar-talk.component.d.ts +5 -3
- package/lib/aigc/avatar/modal-chat-voice-input/modal-chat-voice-input.component.d.ts +4 -2
- package/lib/aigc/chat/chat-message-card/comp-message-card.component.d.ts +6 -1
- package/lib/aigc/chat/chat-modal-input/modal-audio-message/modal-audio-message.component.d.ts +6 -3
- package/lib/aigc/chat/chat-modal-input/modal-input.component.d.ts +5 -1
- package/lib/aigc/index.d.ts +1 -0
- package/lib/aigc/story/fm-office-viewer/fm-office-viewer.component.d.ts +23 -0
- package/lib/aigc/story/fm-story-card/fm-story-card.component.d.ts +26 -0
- package/lib/aigc/story/fm-story-list/fm-story-list.component.d.ts +71 -0
- package/lib/aigc/story/fm-story-list/story-preview.d.ts +20 -0
- package/lib/aigc/story/fm-story-loader/fm-story-loader.component.d.ts +38 -0
- package/lib/aigc/story/fm-story-splitter/fm-story-splitter.component.d.ts +13 -0
- package/lib/aigc/story/index.d.ts +5 -0
- package/lib/aigc/story/modal-chat-story/comp-chat-story-json/comp-chat-story-json.component.d.ts +14 -0
- package/lib/aigc/story/modal-chat-story/comp-diary-story/comp-diary-story.component.d.ts +29 -0
- package/lib/aigc/story/modal-chat-story/modal-chat-story.component.d.ts +44 -0
- package/lib/aigc/story/story.service.d.ts +12 -0
- package/lib/aigc/voice/fmode-voice.service.d.ts +3 -6
- package/lib/aigc/voice/index.d.ts +3 -2
- package/lib/aigc/voice/lib/audio/audio.streamer.d.ts +33 -0
- package/lib/aigc/voice/{stream.player.d.ts → lib/audio/streamer.microsoft.d.ts} +2 -2
- package/lib/aigc/voice/lib/audio/streamer.pcm.d.ts +45 -0
- package/lib/aigc/voice/tts/fmode-tts-class.d.ts +17 -37
- package/lib/aigc/voice/tts/index.d.ts +3 -0
- package/lib/aigc/voice/tts/int-tts-provider.d.ts +35 -0
- package/lib/aigc/voice/tts/provider-doubao.d.ts +43 -0
- package/lib/aigc/voice/tts/provider-microsoft.d.ts +21 -0
- package/lib/core/agent/chat/completion/fmode-completion.d.ts +2 -1
- package/lib/core/agent/chat/completion/int-gpt-chat-options.d.ts +72 -0
- package/lib/core/agent/chat/index.d.ts +1 -1
- package/lib/core/agent/chat/interface.d.ts +3 -0
- package/lib/core/agent/prompt/agent.prompt.d.ts +2 -1
- package/lib/core/index.d.ts +2 -0
- package/lib/core/voice/index.d.ts +1 -0
- package/lib/icon/filetype/audio.svg.d.ts +1 -0
- package/lib/icon/filetype/avatar.svg.d.ts +1 -0
- package/lib/icon/filetype/chat.svg.d.ts +1 -0
- package/lib/icon/filetype/docx.svg.d.ts +1 -0
- package/lib/icon/filetype/file.svg.d.ts +1 -0
- package/lib/icon/filetype/filetype.pipe.d.ts +8 -0
- package/lib/icon/filetype/index.d.ts +11 -0
- package/lib/icon/filetype/md.svg.d.ts +1 -0
- package/lib/icon/filetype/pdf.svg.d.ts +1 -0
- package/lib/icon/filetype/pptx.svg.d.ts +1 -0
- package/lib/icon/filetype/svgtoblob.d.ts +1 -0
- package/lib/icon/filetype/video.svg.d.ts +1 -0
- package/lib/icon/filetype/xlsx.svg.d.ts +1 -0
- package/lib/icon/index.d.ts +1 -0
- package/lib/person/comp-person-gender-icon/comp-person-gender-icon.component.d.ts +20 -0
- package/lib/person/comp-person-item/comp-person-item.component.d.ts +10 -0
- package/lib/person/comp-person-story/comp-person-story.component.d.ts +67 -0
- package/lib/person/edit-upload/edit-upload.component.d.ts +81 -0
- package/lib/person/edit-upload/edit-upload.module.d.ts +11 -0
- package/lib/person/index.d.ts +4 -0
- package/lib/person/modal-person-select/modal-person-select.component.d.ts +25 -0
- package/lib/person/modal-user-verify/secret-text.pipe.d.ts +7 -0
- package/lib/person/modal-user-verify/user-verify.component.d.ts +88 -0
- package/lib/person/person-detail/person-detail.component.d.ts +41 -0
- package/lib/person/person.service.d.ts +33 -0
- package/lib/text/fm-article-editor/article-editor-topbar/article-editor-topbar.component.d.ts +23 -0
- package/lib/text/fm-article-editor/article.service.d.ts +41 -0
- package/lib/text/fm-article-editor/comp-upload-book-banners/comp-upload-book-banners.component.d.ts +19 -0
- package/lib/text/fm-article-editor/draft.service.d.ts +33 -0
- package/lib/text/fm-article-editor/fm-article-aitool/fm-article-aitool.component.d.ts +73 -0
- package/lib/text/fm-article-editor/fm-article-draft/fm-article-draft.component.d.ts +81 -0
- package/lib/text/fm-article-editor/fm-article-editor.component.d.ts +90 -0
- package/lib/text/fm-article-editor/fm-article-outline/fm-article-outline.component.d.ts +36 -0
- package/lib/text/fm-article-editor/fm-article-outline-leftitem/fm-article-outline-leftitem.component.d.ts +12 -0
- package/lib/text/fm-article-editor/fm-article-preview/fm-article-preview.component.d.ts +55 -0
- package/lib/text/fm-article-editor/fm-article-write-options/fm-article-write-options.component.d.ts +31 -0
- package/lib/text/fm-article-editor/outline-count.pipe.d.ts +7 -0
- package/lib/text/fm-article-editor/prompt/prompt-insertion-article.d.ts +6 -0
- package/lib/text/fm-article-editor/task-article-generation.d.ts +23 -0
- package/lib/text/fm-article-editor/tasks/task-article-draft-create.d.ts +18 -0
- package/lib/text/fm-article-editor/tasks/task-article-outline-edit.d.ts +14 -0
- package/lib/text/fm-article-editor/tasks/task-article-outline.d.ts +19 -0
- package/lib/text/fm-article-editor/tasks/task-article-preview.d.ts +7 -0
- package/lib/text/fm-article-editor/tasks/task-article-writing-options.d.ts +14 -0
- package/lib/text/fm-article-editor/tasks/task-document-select.d.ts +14 -0
- package/lib/text/fm-text-quill/fm-text-quill.component.d.ts +39 -0
- package/lib/text/index.d.ts +3 -0
- package/package.json +6 -2
- package/public-api.d.ts +4 -0
- package/esm2022/lib/aigc/voice/lib/recorder/engine-pcm.mjs +0 -10
- package/esm2022/lib/aigc/voice/lib/recorder/engine-wav.mjs +0 -10
- package/esm2022/lib/aigc/voice/stream.player.mjs +0 -10
- package/lib/aigc/voice/lib/recorder/engine-pcm.d.ts +0 -1
- package/lib/aigc/voice/lib/recorder/engine-wav.d.ts +0 -1
- /package/lib/aigc/voice/{audio.player.d.ts → lib/audio/audio.player.d.ts} +0 -0
package/fesm2022/fmode-ng.mjs
CHANGED
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
* 保留所有权利 All Rights Reserved.
|
|
6
6
|
* /home/ryan/workspace/nova/nova-admin/dist/fmode-ng/fesm2022/fmode-ng.mjs
|
|
7
7
|
*/
|
|
8
|
-
import*as i0 from"@angular/core";import{Injectable,Pipe,Input,ViewChild,Component,NgModule,EventEmitter,Output,Inject,HostListener}from"@angular/core";import*as i1$1 from"@angular/router";import{RouterModule}from"@angular/router";import{Subject,Observable,bufferTime,concatMap,delay,finalize,interval,take,map,of,combineLatest}from"rxjs";import*as Parse from"parse";import Parse__default from"parse";import{SpeechConfig,AudioConfig,SpeechSynthesizer,ResultReason}from"microsoft-cognitiveservices-speech-sdk/distrib/browser/microsoft.cognitiveservices.speech.sdk.bundle-min";import{PushAudioOutputStreamCallback}from"microsoft-cognitiveservices-speech-sdk/distrib/lib/src/sdk/Audio/PushAudioOutputStreamCallback";import{bufferWhen,takeUntil,filter}from"rxjs/operators";import{PromptTemplate}from"@langchain/core/prompts";import*as i1 from"@angular/common/http";import{HttpClientModule}from"@angular/common/http";import*as i3 from"@ionic/angular";import{IonicModule,ModalController,IonModal as IonModal$1}from"@ionic/angular";import*as i2$1 from"@angular/common";import{DatePipe,CommonModule}from"@angular/common";import{Camera,CameraResultType,CameraSource}from"@capacitor/camera";import{Capacitor}from"@capacitor/core";import{Filesystem}from"@capacitor/filesystem";import{FilesystemWeb}from"@capacitor/filesystem/dist/esm/web.js";import*as qiniu from"qiniu-js";import*as i2 from"@awesome-cordova-plugins/diagnostic/ngx";import{Diagnostic}from"@awesome-cordova-plugins/diagnostic/ngx";import CryptoJS from"crypto-js";import{MediaCapture}from"@awesome-cordova-plugins/media-capture/ngx";import SparkMD5 from"spark-md5";import{mathjax}from"mathjax-full/js/mathjax";import{TeX}from"mathjax-full/js/input/tex";import{SVG}from"mathjax-full/js/output/svg";import{CHTML}from"mathjax-full/js/output/chtml";import{AllPackages}from"mathjax-full/js/input/tex/AllPackages";import{liteAdaptor}from"mathjax-full/js/adaptors/liteAdaptor";import{RegisterHTMLHandler}from"mathjax-full/js/handlers/html";import hljs from"highlight.js";import MarkdownIt from"markdown-it";import $ from"jquery";import abbr from"markdown-it-abbr";import footnote from"markdown-it-footnote";import deflist from"markdown-it-deflist";import mark from"markdown-it-mark";import ins from"markdown-it-ins";import sub from"markdown-it-sub";import sup from"markdown-it-sup";import ruby from"markdown-it-ruby";import plantumlEncoder from"plantuml-encoder";import*as i1$2 from"@angular/platform-browser";import{Clipboard}from"@capacitor/clipboard";import Recorder from"recorder-core";import*as i6 from"@angular/forms";import{FormsModule,ReactiveFormsModule,Validators}from"@angular/forms";import*as BABYLON from"@babylonjs/core";import"@babylonjs/loaders";import*as i2$2 from"@ionic/angular/standalone";import{IonIcon,IonToolbar,IonButtons,IonButton,IonModal,IonTitle,IonHeader,IonList,IonItem,IonCard,IonLabel,IonNote,IonAvatar,IonSegment,IonSpinner,ModalController as ModalController$1,IonTextarea,IonPopover,IonContent,IonInput,IonText,IonCheckbox}from"@ionic/angular/standalone";import*as i3$1 from"@angular/material/button";import{MatButtonModule}from"@angular/material/button";import*as i1$3 from"@angular/material/dialog";import{MAT_DIALOG_DATA,MatDialogModule}from"@angular/material/dialog";import{MatFormFieldModule}from"@angular/material/form-field";import{MatInputModule}from"@angular/material/input";import*as i5 from"@angular/material/progress-bar";import{MatProgressBarModule}from"@angular/material/progress-bar";import*as i4 from"@angular/material/stepper";import{MatStepperModule,MatStepper}from"@angular/material/stepper";import{addIcons}from"ionicons";import{ellipsisHorizontalOutline,chevronBackOutline,person,copyOutline,wifiOutline,chevronForward,settingsOutline,shareSocialOutline,paperPlaneOutline,micOutline,chatboxEllipsesOutline,chevronDownOutline,imageOutline,alertOutline,peopleOutline,colorWandOutline}from"ionicons/icons";import{NzSanitizerPipe}from"ng-zorro-antd/pipes";import*as AMapLoader from"@amap/amap-jsapi-loader";import ObsClient from"esdk-obs-browserjs";import*as i8 from"ng-zorro-antd/input";import{NzInputModule}from"ng-zorro-antd/input";import*as i9 from"ng-zorro-antd/button";import{NzButtonModule}from"ng-zorro-antd/button";import*as i12 from"ng-zorro-antd/modal";import{NzModalModule}from"ng-zorro-antd/modal";import{NzRadioModule}from"ng-zorro-antd/radio";import*as i13 from"ng-zorro-antd/spin";import{NzSpinModule}from"ng-zorro-antd/spin";import*as i14 from"ng-zorro-antd/tabs";import{NzTabsModule}from"ng-zorro-antd/tabs";import*as i16 from"ng-zorro-antd/form";import{NzFormModule}from"ng-zorro-antd/form";import*as i10 from"ng-zorro-antd/core/transition-patch";import*as i11 from"ng-zorro-antd/core/wave";import*as i15 from"ng-zorro-antd/grid";import{NzMessageModule}from"ng-zorro-antd/message";class AudioPlayer{static{this.instance=null}constructor(){this.audio=new Audio}static getInstance(){return AudioPlayer.instance||(AudioPlayer.instance=new AudioPlayer),AudioPlayer.instance}setAudioEvent(e,t){this.audio[e]=t}get duration(){return this.audio.duration}get src(){return this.audio.src}stop(){this.audio.pause()}async play(e){return new Promise(((t,n)=>{this.audio.src!==e?(this.audio.src=e,this.audio.play().then((()=>{t()})).catch((()=>{n()}))):this.audio.paused?this.audio.play().then((()=>{t()})).catch((()=>{n()})):this.audio.pause()}))}}class FmPushAudioOutputStreamCallback extends PushAudioOutputStreamCallback{constructor(){super(),this.audioDataSubject=new Subject,this.playedSubject=new Subject,this.isPlaying=!1,this.isClosed=!1,this.audioBufferQueue=[],this.maxBufferSize=10,this.writeCount=0,this.audioContext=new(window.AudioContext||window.webkitAudioContext),this.audioDataSubject.pipe(bufferWhen((()=>this.playedSubject)),takeUntil(this.audioDataSubject.pipe(filter((()=>this.isClosed))))).subscribe((e=>{this.playAudio(e)}))}async write(e){this.writeCount++,10==this.writeCount&&this.playedSubject.next(!0),this.audioDataSubject.next(e)}async playAudio(e){this.isPlaying=!0;const t=this.mergeArrayBuffers(e);let n;try{n=await this.audioContext.decodeAudioData(t)}catch(e){}if(n){const e=this.audioContext.createBufferSource();e.buffer=n,e.connect(this.audioContext.destination),e.start(),await new Promise((t=>{e.onended=t})),this.playedSubject.next(!0)}this.isPlaying=!1}mergeArrayBuffers(e){const t=e.reduce(((e,t)=>e+t.byteLength),0),n=new Uint8Array(t);let o=0;for(const t of e){const e=new Uint8Array(t);n.set(e,o),o+=e.length}return n.buffer}async stop(){this.isClosed=!0,this.audioDataSubject&&this.audioDataSubject.unsubscribe(),this.playedSubject&&this.playedSubject.unsubscribe(),this.audioContext&&this.audioContext.close()}async close(){console.log("close 数据加载完成"),this.isClosed=!0}}class FmodeTTS{stop(){this.audioPlayer&&this.audioPlayer?.stop(),this.audioStream&&this.audioStream?.stop()}constructor(e,t){this.isPlaying=!1,this.uploadServ=t,this.subscriptionKey=e?.subscriptionKey,this.authorizationToken=e?.token,this.region=e?.region,this.subscriptionKey&&(this.speechConfig=SpeechConfig.fromSubscription(this.subscriptionKey,this.region)),this.authorizationToken&&(this.speechConfig=SpeechConfig.fromAuthorizationToken(this.authorizationToken,this.region)),this.audioStream=new FmPushAudioOutputStreamCallback,this.audioConfig=AudioConfig.fromStreamOutput(this.audioStream),this.synthesizer=new SpeechSynthesizer(this.speechConfig,this.audioConfig),this.audioPlayer=AudioPlayer.getInstance()}extractTextFromXML(e){const t=/>([^<]+)</g;let n,o=[];for(;null!==(n=t.exec(e));){const e=n[1].trim();e&&o.push(e)}return o.join(" ")}extractSSMLContent(e){var t=e.match(/<speak.*?<\/speak>/s);return t?t[0]:e}async speakAsync(e,t,n){if(!t){let n=Parse__default.Object.extend("ChatVoice");(t=new n).set("ssml",e),t.set("content",this.extractTextFromXML(e));let o=localStorage.getItem("company");o&&t.set("company",{__type:"Pointer",className:"Company",objectId:o}),Parse__default.User.current()?.id&&t.set("user",Parse__default.User.current().toPointer())}if(!t?.get("voiceFile")){let n=[];t?.get("content")&&n.push({content:t?.get("content")}),e&&n.push({ssml:e});let o=Parse__default.Query.fromJSON("ChatVoice",{include:"voiceFile",where:{$or:n}}),i=await o.first();t.set("voiceFile",i?.get("voiceFile"))}return t?.get("voiceFile")?(this.playAudioData(t?.get("voiceFile")?.get("url"),t,n),t):(e=this.extractSSMLContent(e),this.isPlaying=!0,new Promise(((o,i)=>{const a=Date.now();let r="speakTextAsync";e?.indexOf("<")>-1&&(r="speakSsmlAsync"),e=this.fixMarkdownChar(e),this.eventMap?.onSpeakBefore&&this.eventMap?.onSpeakBefore(),this.synthesizer[r](e,(e=>{if(console.log(e),e.reason===ResultReason.SynthesizingAudioStarted&&(this.isPlaying=!0),e.reason===ResultReason.SynthesizingAudioCompleted){this.eventMap?.onAudioCompleted&&this.eventMap?.onAudioCompleted();const i=Date.now();let r=e?.audioData;t.set("duration",Number(e?.audioDuration)/1e4),this.playAudioData(r,t,n),console.log(`Audio synthesis finished. Duration: ${i-a} ms`),setTimeout((()=>{this.isPlaying=!1,n?.onStop()&&n?.onStop()}),2e3),o(t)}else i(`Speech synthesis failed. Reason: ${e.errorDetails}`)}),(e=>{i(`Error occurred during synthesis: ${e}`)}))})))}onBreak(e){}fixMarkdownChar(e){return e.replaceAll("*","")}async playAudioData(e,t,n){let o;if(console.log("audioData",e),!(e?.indexOf&&e?.indexOf("http")>=-1)){let n=new Blob([e],{type:"audio/wav"});return o=URL.createObjectURL(n),void this.uploadAndSaveVoice(n,t)}o=e;let i=this.audioPlayer;n?.onStart&&n?.onStart(t),this.isPlaying=!0,i.setAudioEvent("onloadeddata",(()=>{let e=1e3*i.duration;console.log("duration",e),t?.get("duration")||(t?.set("duration",e),t?.save()),n?.onLoaded&&n?.onLoaded(i)})),console.log("event setting"),i.setAudioEvent("onabort",(()=>{this.isPlaying=!1,n?.onStop&&n?.onStop()})),i.setAudioEvent("onerror",(()=>{this.isPlaying=!1,n?.onStop&&n?.onStop()})),i.setAudioEvent("onpause",(()=>{this.isPlaying=!1,n?.onStop&&n?.onStop()})),i.setAudioEvent("onended",(()=>{this.isPlaying=!1,n?.onStop&&n?.onStop()})),i.setAudioEvent("onclose",(()=>{this.isPlaying=!1,n?.onStop&&n?.onStop()})),console.log("playAudio",o);let playAudio=()=>{i.play(o).then((()=>{})).catch((()=>{setTimeout((()=>{console.log("playAudio"),playAudio()}),200)}))};playAudio()}async uploadAndSaveVoice(e,t){if(console.log("blob",e),this.uploadServ){let n=t?.id||this.uploadServ?.genMd5(t?.get("content")||t?.get("ssml")),o=new Date,i=n+o.getFullYear()+(o.getMonth()+1)+o.getDate()+o.getHours()+o.getMinutes()+o.getSeconds()+".wav",a=new File([e],i,{type:"audio/wav"}),r=await this.uploadServ.upload(a,(e=>{console.log(e)})),s={__type:"Pointer",className:"Attachment",objectId:r?.id};return s?.objectId&&(t.set("voiceFile",s),t=await t.save()),r?.url}return null}}async function getFormatTpl(e,t){let n=await getPromptTpl(e);return await n.format(t)}async function getPromptTpl(e){let t=new Parse__default.Query("PromptTemplate");t.equalTo("code",e);let n=await t.first();return PromptTemplate.fromTemplate(n?.get("template"),{templateFormat:"mustache"})}const API_BASE="https://server.fmode.cn/api/apig/aigc/gpt";class FmodeChatCompletion{constructor(e,t){this.content="",this.contentBuffer=[],this.isCompleted=!1,this.indexOfList=Number(e.length),this.messages=e,this.model=t?.model||"fmode-4.5-128k"}sendCompletion(e={}){e.intTime=e?.intTime||50,e.isDirect=e?.isDirect||!1,e?.isDirect&&(e.intTime=1);let t={messages:this.messages,stream:!0,model:this.model,temperature:.5,presence_penalty:0,frequency_penalty:0};return new Observable((n=>{let o=RequestFmodeChatApi("/v1/chat/completions",t).subscribe((t=>{let i,a=String(t);try{i=chunkToJson(a)}catch(e){}if(("data: [DONE]"==a||i?.created&&i?.choices?.[0]?.finish_reason)&&(this.isCompleted=!0,e?.isDirect&&this.isCompleted&&(n.next({role:"assistant",content:this.content,complete:!0,createdAt:new Date}),o.unsubscribe(),e?.onComplete&&e.onComplete({role:"assistant",content:this.content,complete:!0,createdAt:new Date}),n.complete())),a.indexOf("data: {")>-1){let t=i?.choices?.[0]?.delta?.content||"";this.contentBuffer.push(t),e?.isDirect&&(this.content+=t||"",this.isCompleted||n.next({role:"assistant",cid:i?.id,content:this.content,createdAt:new Date})),e?.isDirect||this.contentPusher||(this.contentPusher=setInterval((()=>{this.isCompleted&&0==this.contentBuffer?.length&&(n.next({role:"assistant",cid:i?.id,content:this.content,complete:!0,createdAt:new Date}),o.unsubscribe(),clearInterval(this.contentPusher),n.complete()),this.contentBuffer?.length>=0&&(this.contentBuffer?.length>0&&(this.content+=this.contentBuffer.shift()),n.next({role:"assistant",cid:i?.id,content:this.content,createdAt:new Date}))}),e?.intTime))}}))})).pipe(bufferTime(100),concatMap((e=>e)),delay(200))}}function chunkToJson(e){let t;try{t=JSON.parse(e.replaceAll("data: ",""))}catch(e){}return t||{}}function RequestFmodeChatApi(e,t,n="POST"){return new Observable((o=>{let i=API_BASE+e,a=`Bearer ${Parse__default.User.current()?.getSessionToken()||localStorage.getItem("FMODE_AI_TOKEN")}`;return t.token=a,t&&(t=JSON.stringify(t)),fetch(i,{headers:{"Content-Type":"text/plain; charset=utf-8","Cache-Control":"no-cache"},body:t||null,method:n,credentials:"omit",mode:"cors"}).then((e=>{let t="";{let n=e.body?.getReader();const i=new TextDecoder;let a=new ReadableStream({start(e){!function read(){n.read().then((({done:t,value:n})=>{if(t)return e.close(),void o.complete();e.enqueue(n),read()}))}()}}).getReader();a.read().then((function processStream(e){let{done:n,value:r}=e;n||(!function processData(e){let n=(t+e).split("\n");if(n?.length>1){for(let e=0;e<n.length-1;e++){let t=n[e];o.next(t)}t=n[n.length-1]}}(i.decode(r)),a.read().then(processStream))}))}})).catch((e=>o.error(e))),()=>{}}))}function JsonToFormData(e){const t=new FormData;return function appendFormData(e,n=""){Array.isArray(e)?e.forEach(((e,t)=>{appendFormData(e,`${n}[${t}]`)})):"object"==typeof e&&null!==e?Object.keys(e).forEach((t=>{const o=n?`${n}.${t}`:t;appendFormData(e[t],o)})):t.append(n,e)}(e),t}const PromptTplTalkSSMLOutputCode="talk-ssml-output-tpl",PromptTplTalkTextSSMLCode="talk-text-ssml-tpl";function getMessageContentText(e){let t="";return"string"==typeof e&&(t=e),"object"==typeof e&&(t=e?.find((e=>e?.text))?.text||""),t}function getMessageImageUrl(e){return"object"==typeof e?e?.find((e=>e?.image_url))?.image_url?.url||"":null}class FmodeChat{async loadModelList(e){if(this.modelList?.length)return;let t=new Parse__default.Query("ChatModel");t.notEqualTo("isDeleted",!0),t.equalTo("isEnabled",!0),t.addAscending("index"),this.modelList=await t.find(),this.currentModel=e||this.modelList?.find((e=>"fmode-4.5-128k"==e.get("code")))}showAvatar(){this.avatarConfig=this.role?.get("avatarConfig"),this.avatarConfig&&(this.isAvatarShow=!0,this.avatarConfig?.image&&(this.avatarConfig.image.waiting=this.avatarConfig.image.waiting||this.role?.get("thumb")||this.role?.get("avatar"),this.avatarMode="image"),this.avatarConfig?.video&&(this.avatarConfig.video.waiting=this.avatarConfig.video.waiting,this.avatarMode="video"))}scrollToBottom(e){e=e||this.scrollComp,e?.nativeElement?.scrollHeight&&(e.nativeElement.scrollTop=e.nativeElement.scrollHeight)}constructor(e,t,n,o,i,a,r){this.ChatSession=Parse__default.Object.extend("ChatSession"),this.messageList=[{role:"system",content:"系统提示:AI仅供参考"}],this.latestAIResponse="",this.userInput="",this.userImage="",this.isDirect=!1,this.mode="page",this.hideShare=!1,this.hideModalSelect=!1,this.hideInputPreview=!1,this.isAvatarShow=!1,this.avatarMode="",this.isPromptModalOpen=!1,this.isPromptMessageAreaShow=!0,this.promptList=[],this.focusUserInput=()=>{},this.leftButtons=[{title:"灵感",icon:"color-wand-outline",onClick:()=>{this.isPromptModalOpen=!0},show:()=>this?.promptList?.length},{title:"角色",icon:"people-outline",onClick:()=>{this.navCtrl?.navigateRoot("/chat/pro/mask")},show:()=>!0},{title:"呼叫",icon:"call-outline",onClick:()=>{this.chatServ?.callRole(this.role)},show:()=>this?.role?.get("voiceConfig")}],this.isVoiceInputMode=!1,this.isTexting=!1,this.isTalkMode=!1,this.SSMLRoleVoice="zh-CN-XiaoxiaoNeural",this.playAnimation=e=>{console.log(e)},this.welcome=async()=>{let e=this.messageList?.filter((e=>"assistant"==e?.role));if(e?.length)return;let t=Parse__default.User.current(),n=await this.loadSelf("Person","userVerify"),o=await this.loadSelf("Profile","user"),i=t?.get("nickname")||o?.get("name")||t?.get("realname")||t?.get("name"),a=n?.get("name")||n?.get("userVefiry")?.get("realname")||n?.get("userVefiry")?.get("nickname");n?.get("userVerify")?.id==t?.id&&(a="您");let r=this.role.get("voiceConfig")?.welcome?.prompt;if(this.role.get("voiceConfig")?.welcome?.promptList?.length){let e=this.role.get("voiceConfig")?.welcome?.promptList;r=e[Math.floor(Math.random()*e.length)]}if(!r)return;let s=await PromptTemplate.fromTemplate(r,{templateFormat:"mustache"}).format({name:i,userName:i,personName:a,timeOfDay:this.getTimeOfDay()}),l=await this.getVoiceByContentText(s),c={role:"assistant",voice:l,content:s,complete:!0};this.voiceMap[l?.id],this.playChatVoice(this.voiceMap[l?.id]),this.messageList.push(c)},this.self={},this.voiceMap={},this.VoiceTTSMap={},this.chatServ=o,this.role=t,this.sessionId=e,this.navCtrl=i,this.ncloud=a,this.uploadServ=r,n?.id&&(this.chatSession=n,this.messageList=this.chatSession.get("messageList"),this.sessionId=n?.id),this.role?.id&&(this.voiceConfig=this.role?.get("voiceConfig"),this.voiceConfig?.autoTalk&&(this.isTalkMode=!0,this.isDirect=!0))}getTimeOfDay(){const e=(new Date).getHours();return e>=5&&e<12?"早上":e>=12&&e<14?"中午":e>=14&&e<18?"下午":"晚上"}async loadSelf(e,t){if(this.self[e])return this.self[e];let n=Parse__default.User.current(),o=new Parse__default.Query(e);return o.include(t),o.equalTo(t,n?.id),this.self[e]=await o.first(),this.self[e]}async loadTalkSystemPrompt(e){if(!this.isTalkMode)return;if(!e)return;"男"==e?.get("gender")?this.SSMLRoleVoice="zh-CN-YunyeNeural":this.SSMLRoleVoice="zh-CN-XiaoxiaoNeural",this.SSMLRoleVoice=e?.get("voiceConfig")?.voice||this.SSMLRoleVoice;let t=await getFormatTpl("talk-ssml-output-tpl",{SSMLRoleVoice:this.SSMLRoleVoice}),n=e.get("prompt")||"请你扮演飞码AI的人工智能专家。";n+=t;let o={role:"user",content:n,hidden:!0},i=this.messageList?.map((e=>e?.content)).join();if(i.indexOf(n)>-1)return;let a=this.messageList?.findIndex((e=>"system"==e?.role)),r=a+1;this.messageList.splice(r,0,o)}loadRolePrompt(){let e=this.role?.get("prompt"),t={role:"user",content:e,hidden:!0};if(!e)return;let n=this.messageList?.map((e=>e?.content)).join();if(n.indexOf(e)>-1)return;let o=this.messageList?.findIndex((e=>"system"==e?.role)),i=o+1;this.messageList.splice(i,0,t)}async sendMessage(e="FmodeAiTest测试问题",t,n,o,i){if(this.scrollToBottom&&this.scrollToBottom(),this.isPromptMessageAreaShow=!1,this.loadRolePrompt(),t){let n={role:"user",content:[{type:"image_url",image_url:{url:t}},{type:"text",text:e}],complete:!0,createdAt:new Date};i&&(n.voice={id:i?.id}),this.messageList.push({role:"user",content:[{type:"image_url",image_url:{url:t}},{type:"text",text:e}],complete:!0,createdAt:new Date})}else{let t={role:"user",content:e,complete:!0,createdAt:new Date};i&&(t.voice={id:i?.id,duration:i?.duration}),this.messageList.push(t)}let a=new FmodeChatCompletion(this.fixMessageList(this.messageList),{model:this.currentModel?.get("code")||"fmode-4.5-128k"});if(this.onUserSend){if(!await this.onUserSend(this,this.messageList[this.messageList?.length-1]))return}this.userInput="",this.userImage="";let r=this.isDirect||!1;this.isTalkMode&&(r=!0);let s=a.sendCompletion({isDirect:r,onComplete:n||null}).pipe(finalize((async()=>{if(this.isTalkMode){let e=this.messageList[a.indexOfList]?.content,t=await this.getVoiceByContentText(e,o);o?.onSSMLComplete&&o?.onSSMLComplete(t),this.messageList[a.indexOfList].voice=t,this.playChatVoice(this.voiceMap[t?.id])}this.messageList[a.indexOfList].complete=!0}))).subscribe((e=>{this.messageList[a.indexOfList]=e,this.latestAIResponse=this.getContentText(e?.content);let t=this.chatSession?.get("messageList")?.length;this.messageList?.length>t&&this.saveChatSession(),e?.complete&&(this.onMessage&&this.onMessage(this,this.messageList[this.messageList?.length-1]),this.saveChatSession(),s.unsubscribe()),this.scrollToBottom&&this.scrollToBottom()}))}getVoiceByContentText(e,t,n=!1){let o=this.getContentText(e),i=new(Parse__default.Object.extend("ChatVoice")),a="";return this.SSMLRoleVoice=this.role?.get("voiceConfig")?.voice||this.SSMLRoleVoice,new Promise((async(e,t)=>{let resolveChatVoice=async()=>{i.set("content",o),i.set("ssml",a),i.set("role","assistant");let t=localStorage.getItem("company");t&&i.set("company",{__type:"Pointer",className:"Company",objectId:t}),Parse__default.User.current()?.id&&i.set("user",Parse__default.User.current().toPointer()),this.chatSession?.id&&i.set("session",this.chatSession?.toPointer()),i=await i.save(),this.voiceMap[i?.id]=i,e({id:i?.id})};if(0==n&&(a=`<speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="zh-CN"><voice name="${this.SSMLRoleVoice}">${o}</voice></speak>`,resolveChatVoice()),1==n){let e=await getFormatTpl("talk-text-ssml-tpl",{content:o,SSMLRoleVoice:this.SSMLRoleVoice});new FmodeChatCompletion(this.fixMessageList([{role:"user",content:e}]),{model:this.currentModel?.get("code")||"fmode-4.5-128k"}).sendCompletion({isDirect:!0}).subscribe((async e=>{e?.complete&&(a=this.getContentText(e?.content),resolveChatVoice())}))}}))}getContentText(e){return"string"==typeof e?e:e?.[0]?.text||""}async initTTS(){let e=await this.ncloud.apig("voice/tts/token",{company:localStorage.getItem("company")});if(e?.token){return new FmodeTTS(e,this.uploadServ)}return null}stopPlayingVoice(){Object.values(this.VoiceTTSMap).forEach((e=>{e?.isPlaying&&e?.stop()}))}async playChatVoice(e,t){let n=await this.initTTS();if(n){try{this.playAnimation("talking"),n.speakAsync(e?.get("ssml"),e,{onStart:e=>{t?.onStart&&t?.onStart(e)},onLoaded:e=>{t?.onLoaded&&t?.onLoaded(e)},onStop:()=>{t?.onStop&&t?.onStop(),this.playAnimation("waiting")}})}catch(e){}return this.VoiceTTSMap[e.id]=n,n}return null}async saveChatSession(){if("new"==this.sessionId&&(this.chatSession=new this.ChatSession),this.chatSession.set("title",this.genTitle()),this.chatSession.set("role",this.role?.toPointer()),this.chatSession.set("messageList",this.messageList),this.chatSession.set("user",Parse__default.User.current()?.toPointer()),this.chatSession=await this.chatSession.save(),this.onChatSaved&&this.onChatSaved(this),this.sessionId=this.chatSession?.id,this.sessionId){let e=`${window.location.origin}/chat/pro/chat/${this.sessionId}`;window.location?.pathname?.indexOf("chat/session")>-1&&(e=`${window.location.origin}/chat/session/chat/${this.sessionId}`),"modal"==this.mode&&(e=window.location.href),e=this.getInviteUrl(e),window.history.replaceState(null,null,e+window.location.search);let t={sid:this.chatSession?.id,rid:this.role?.id,name:this.role?.get("name"),message:this.chatSession?.get("messageList")?.[this.chatSession?.get("messageList")?.length-1]?.content?.slice(0,20),latest:this.chatSession?.createdAt};this.chatServ&&!this.chatServ?.chatList?.length&&(this.chatServ.chatList=[]);let n=this.chatServ?.chatList?.find((e=>e?.sid==t?.sid));n>-1?this.chatServ.chatList[n]=t:this.chatServ?.chatList.unshift(t)}}getInviteUrl(e){let t=new URL(e),n=Parse__default.User?.current()?.id;return t.searchParams.set("invite",n),t.href}genTitle(){if(this.title)return this.title;let e=this.messageList.find((e=>"user"==e.role))?.content;return"string"==typeof e&&(this.title=e?.slice(0,15)||""),"object"==typeof e&&(this.title=e?.find((e=>e?.text))?.text||""),this.title}fixMessageList(e){return e.map((e=>({role:e.role,content:e.content})))}nowStr(){let e=new Date;return`${e.getFullYear()}/${e.getMonth()+1}/${e.getDate()} ${e.getHours()}:${e.getMinutes()}:${e.getSeconds()}`}}async function ncloudApi(e,t,n="POST",o){e=o+e;try{let o=JSON.stringify(t);"GET"==n&&(o=null);const i=await fetch(e,{method:n,headers:{"Content-Type":"application/json"},body:o,mode:"cors",credentials:"omit"}),a=await i.json();return!a||200!==a.code&&1!==a.code?null:a.data}catch(e){throw e}}async function novaql(e,t,n){const o=n+"/novaql/select";let i={sql:e};t&&t.length>0&&(i.params=JSON.stringify(t));try{const e=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i),mode:"cors",credentials:"omit"}),t=await e.json();if(t&&200===t.code)return t.data}catch(e){throw e}}async function apig(e,t,n="POST",o){localStorage.setItem("NOVA_APIG_SERVER","aHR0cHMlM0ElMkYlMkZzZXJ2ZXIuZm1vZGUuY24lMkZhcGklMkZhcGlnJTJG"),o||(o=localStorage.getItem("NOVA_APIG_SERVER"),o=decodeURIComponent(atob(o))),e=o+e;let i=Parse__default.User.current(),a={"Content-Type":"application/json",Authorization:`Bearer ${i?.getSessionToken()}`};try{let o=await fetch(e,{method:n,headers:a,body:t?JSON.stringify(t):null,mode:"cors",credentials:"omit"});if(!o.ok)throw new Error(`HTTP error! status: ${o.status}`);let i=await o.json();return!i||200!==i.code&&1!==i.code&&0!==i.code?null:i.data}catch(e){throw console.error("请求出错",e),e}}class NovaCloudService{constructor(e){this.http=e,this.serverURL="https://server.fmode.cn/api",localStorage.setItem("NOVA_APIG_SERVER","aHR0cHMlM0ElMkYlMkZzZXJ2ZXIuZm1vZGUuY24lMkZhcGklMkZhcGlnJTJG")}novaql(e,t){return novaql(e,t,this.serverURL)}apig(e,t,n="post"){return apig(e,t,n)}apigTest(e,t,n="post"){return apig(e,t,n,"https://test.fmode.cn/api/apig/")}api(e,t,n="post"){return ncloudApi(e,t,n,this.serverURL)}searchParse(e){return e=e||location.href,new URL(e).searchParams}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:NovaCloudService,deps:[{token:i1.HttpClient}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:NovaCloudService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:NovaCloudService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1.HttpClient}]});class CrossService{getMenuType(){return this.clientWidth=document.body.clientWidth,this.onResizeScreen(),this.navMenuType}constructor(e,t){this.platform=e,this.navCtrl=t,this.mobileWidth=915,this.clientWidth=document.body.clientWidth,this.clientWidth=document.body.clientWidth,this.updateWidth(),this.onResizeScreen()}async dismisModalTop(e,t){let n=await(e?.getTop());n&&(t?.preventDefault&&t?.preventDefault(),n.dismiss(),n.isOpen=!1)}updateWidth(){this.fixInterval=setInterval((()=>{if(this.clientWidth)return clearInterval(this.fixInterval),void delete this.fixInterval;console.log(document.body.clientWidth),this.clientWidth=document.body.clientWidth}),200)}onResizeScreen(e){this.clientWidth=document.body.clientWidth,this.clientWidth>=this.mobileWidth?(this.leftMenuMode="horizontal",this.navMenuType="pc"):(this.leftMenuMode="inline",this.navMenuType="mobile")}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CrossService,deps:[{token:i3.Platform},{token:i3.NavController}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CrossService,providedIn:"root"})}}function calcFileMd5(e){return new Promise(((t,n)=>{const o=new FileReader;o.onload=e=>{try{const o=e.target?.result;if(o){const e=new SparkMD5.ArrayBuffer;e.append(o);const n=e.end();t(n)}else n(new Error("Failed to load file"))}catch(e){n(e)}},o.onerror=e=>{n(e)},o.readAsArrayBuffer(e)}))}async function getFileMetadata(e){const t={name:e.name,size:e.size,type:e.type,lastModified:e.lastModified,metadata:{}};return t.metadata.lastModified=e.lastModified,e.type.startsWith("image/")?await extractImageMetadata(e,t.metadata):(e.type.startsWith("audio/")||e.type.startsWith("video/"))&&await extractMediaMetadata(e,t.metadata),t}async function extractImageMetadata(e,t){try{const n=new Image,o=URL.createObjectURL(e);await new Promise(((e,t)=>{n.onload=()=>e(),n.onerror=t,n.src=o})),t.width=n.naturalWidth,t.height=n.naturalHeight;try{const n=await e.arrayBuffer(),o=await parseExifData(n);o&&Object.assign(t,o)}catch(e){console.warn("无法解析EXIF数据:",e)}URL.revokeObjectURL(o)}catch(e){console.error("提取图片元数据失败:",e)}}async function extractMediaMetadata(e,t){try{const n=e.type.startsWith("audio/")?new Audio:document.createElement("video"),o=URL.createObjectURL(e);await new Promise(((e,t)=>{n.onloadedmetadata=()=>e(),n.onerror=t,n.src=o})),t.duration=n.duration,"videoWidth"in n&&(t.width=n.videoWidth),"videoHeight"in n&&(t.height=n.videoHeight),URL.revokeObjectURL(o)}catch(e){console.error("提取媒体元数据失败:",e)}}async function parseExifData(e){const t=new DataView(e);return 65496!==t.getUint16(0)?null:{colorDepth:24,orientation:t.getUint16(16,!1)||1}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CrossService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i3.Platform},{type:i3.NavController}]});class NovaUploadService{constructor(e,t){this.platform=e,this.diagnostic=t,this.maxSize=5242880,this.getUptoken(!0),this.requestPermission(),this.queryDomain()}async upload(e,t){let n=e.type,o=e.name?.split("."),i=o[o.length-1],a={id:"",name:"",type:"",size:0,key:"",url:""},r=await this.getFileMd5(e),s=await this.getAttachByMd5(r);if(s?.id)a.url=s?.get("url"),a.name=s?.get("name"),a.type=s?.get("mime"),a.size=s?.get("size"),a.metadata=s?.get("metadata"),t&&t({total:{loaded:a.size,size:a.size,percent:100}});else{let o=this.fileToBlob(e);a=n.indexOf("image")>-1?await this.saveQiniuImageFile(o,i,null,t):await this.saveQiniuMediaFile(e,o,null,t)}a?.url?.indexOf("undefined")>-1&&(a.url=(this.qiniuDomain||"https://file-cloud.fmode.cn/")+a.url.replace("undefined/",""));let l,c=(await getFileMetadata(e)).metadata;return a.metadata||(a.metadata={}),Object.keys(c).forEach((e=>{a.metadata[e]=c[e]})),console.log("metadata",c,a),a?.url&&(l=await this.saveAttachment(a,this.qiniuDomain,null,this.getCompanyId(),e)),l?.id&&(a.id=l?.id),a.attachment=l,a}async getAttachByMd5(e){if(!e)return null;let t=new Parse__default.Query("Attachment");return t.equalTo("md5",e),t.addDescending("createdAt"),await t.first()}isCapacitor(){return this.platform.is("capacitor")||this.platform.is("cordova")}async getFileMd5(e){let t;try{t=await calcFileMd5(e),console.log("md5File",t)}catch(e){console.error(e)}return t}async requestPermission(){this.isCapacitor()&&(await this.requestStoagePermission(),await this.requestCameraPermission())}async requestStoagePermission(){let e=await this.diagnostic.isExternalStorageAuthorized();if(console.log("permisson_STORAGE:",e),!e){await this.diagnostic.requestExternalStorageAuthorization()}}async requestCameraPermission(){let e=await this.diagnostic.isCameraAuthorized();if(console.log("permisson_Camera:",e),!e){await this.diagnostic.requestCameraAuthorization()}}async getUptoken(e=!1){if(console.log("getUptoken"),this.qiniuConf||e)try{console.log(this.getCompanyId());let e=await Parse__default.Cloud.run("qiniu_uptoken",{company:this.getCompanyId()});console.log(e),this.qiniuConf=e}catch(e){console.error(e)}}genFileKey(e,t){let n=new Date,o=new DatePipe("en");t||(t=this.getCompanyId());let i="storage/company/"+t+"/";return this.store?.id&&this.store?.id,i+""+(o.transform(n,"yMMdd")+"/"+String(e.id).substr(20,6)+o.transform(n,"hhmmssSSS")+/\.[^\.]+/.exec(e.name))}getCompanyId(){if(this.company)return this.company;return localStorage.getItem("company")}async queryDomain(){let e=new Parse__default.Query("Company"),t=await e.get(this.getCompanyId());t.get("configQiniu")&&t.get("configQiniu").domain?(console.log(t.get("configQiniu").domain),this.qiniuDomain=t.get("configQiniu").domain):this.qiniuDomain="https://file-cloud.fmode.cn"}async saveAttachment(e,t,n,o,i){e.md5=await this.getFileMd5(i);let a=e.url;a.startsWith("http")||(a=t+a),a=a.replace(/undefined\//,""),o||(o=localStorage.getItem("company"));let r,s=Parse__default.User.current();if(r?.id)return console.log("fast upload"),r;return r=new(Parse__default.Object.extend("Attachment")),r.set("size",e.size),r.set("url",a),r.set("name",e.name),r.set("mime",e.type),r.set("md5",e?.md5),r.set("metadata",e?.metadata),this.store?.id&&r.set("store",this.store.toPointer()),s?.id&&r.set("user",s.toPointer()),o&&r.set("company",{__type:"Pointer",className:"Company",objectId:localStorage.getItem("company")}),n&&r.set("category",{__type:"Pointer",className:"Category",objectId:n}),await r.save()}async captureVideo(e){if(this.qiniuConf=e,!this.isCapacitor())return;let t=await this.cameraCaptureVideoFile(),n=await this.getMediaFileDataString(t);return await this.saveQiniuMediaFile(t,n)}async cameraCaptureVideoFile(){let e=MediaCapture,t=await e.captureVideo({limit:1});return t?.length>0?t[0]:null}async getMediaFileDataString(e){new FilesystemWeb,e.fullPath.replaceAll("///","//");let t=await Filesystem.stat({path:e.fullPath}),n=Capacitor.convertFileSrc(t.uri),o=await fetch(n),i=await o.blob();if(console.log(i.size),console.log(JSON.stringify(t)),console.log(JSON.stringify(o)),console.log(JSON.stringify(Object.keys(o))),i)return i;throw"读取文件失败"}async takePicture(e){if(this.qiniuConf=e,!this.isCapacitor())return;await this.getUptoken();let t=await this.cameraTakePictureDataUrl();if(!t?.dataUrl)return;let n=await this.base64ToBlob(t?.dataUrl),o=await this.saveQiniuImageFile(n,t?.format);return console.log(JSON.stringify(o)),o}async cameraTakePictureDataUrl(){if(!this.isCapacitor())return;return await Camera.getPhoto({quality:90,allowEditing:!1,source:CameraSource.Camera,resultType:CameraResultType.DataUrl})}async saveQiniuImageFile(e,t,n,o){let i=this.maxSize;if(e.size>i)throw await console.log("照片过大,超出限制5MB"),"超出文件大小";let a=new DatePipe("en").transform(new Date,"yyyyMMddHHmmss"),r=`${a}.${t}`,s=e.type,l={fname:r,params:{},mimeType:e.type},c={useCdnDomain:!0,forceDirect:!0};console.log(this.qiniuConf);let p=this.genFileKey({id:a,name:r});return console.log("图片上传前"),console.log(p,e,t),new Promise(((t,n)=>{console.log("进入了上传"),qiniu.upload(e,p,this.qiniuConf?.uptoken,l,c).subscribe({next:e=>{console.log(e),o&&o(e)},error:async e=>{console.log(e)},complete:n=>{console.log("上传完成"),console.log(`${this.qiniuConf?.domain}${n.key}`),n.url=`${this.qiniuConf?.domain}${n.key}`,n.name=r,n.type=s,n.size=e.size,t(n)}})}))}async saveQiniuMediaFile(e,t,n,o){let i=e.name,a=e.type;if(e.size>(this.maxSize||104857600))throw console.log("视频过大,超出限制100MB"),"超出文件大小";let r=new DatePipe("en").transform(new Date,"yyyyMMddHHmmss"),s={fname:i,params:{},mimeType:a},l={useCdnDomain:!0,forceDirect:!0},c=this.genFileKey({id:r,name:i});return console.log("图片上传前"),console.log(e.name,t.size),console.log(t.size),console.log(t.size/1024/1024),new Promise(((n,i)=>{console.log("进入了上传"),qiniu.upload(t,c,this.qiniuConf?.uptoken,s,l).subscribe({next:e=>{console.log("主要用来展示进度"),o&&o(e),console.log(JSON.stringify(e))},error:async e=>{console.log("上传失败"),console.log(JSON.stringify(e))},complete:t=>{console.log("上传完成"),console.log(JSON.stringify(t)),e.key=t.key,console.log(e.type),e.url=`${this.qiniuConf?.domain}${t.key}`,console.log(e.url),n(e)}})}))}async base64ToBlobType(e,t){let n=await fetch(`data:${t};base64,${e}`);return await n.blob()}async base64ToBlob(e){let t=await fetch(e);return await t.blob()}fileToBlob(e){const t=e.slice(0,e.size,e.type);return new Blob([t],{type:e.type})}genMd5(e){return CryptoJS.MD5(e).toString()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:NovaUploadService,deps:[{token:i3.Platform},{token:i2.Diagnostic}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:NovaUploadService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:NovaUploadService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i3.Platform},{type:i2.Diagnostic}]});class ChatService{constructor(e,t,n,o,i,a,r){this.router=e,this.ncloud=t,this.platform=n,this.alertCtrl=o,this.navCtrl=i,this.cross=a,this.uploadServ=r,this.chatMap={},this.isCapacitor=!1,this.platformMap={pc:"电脑端",mobile:"移动端"},this.isCapacitor=this.platform.is("capacitor")}async doButtonAction(e){let t=this.cross.navMenuType,n=e?.platform?.map((e=>this.platformMap[e])).join("、");if(e?.platform?.length>0&&-1==e?.platform?.indexOf(t)){(await this.alertCtrl.create({header:"注意",subHeader:"终端不符",message:`请您使用${n}开启本功能。`,buttons:[{role:"ok",text:"知道了"}]})).present()}else e?.path&&this.navCtrl.navigateRoot(e?.path)}async initChatMap(e){if(this.chatMap[e])return this.chatMap[e];let t=new Parse__default.Query("ChatSession");t.include("user","role","role.model","story","story.person","person","person.userVerify");let n=await t.get(e),o=new FmodeChat(n?.id,n?.get("role"),n,this,this.navCtrl,this.ncloud,this.uploadServ);return this.chatMap[e]=o,this.chatMap[e]}async getChatSession(e){if(!Parse__default?.User?.current()?.id)return;let t=new Parse__default.Query("ChatSession");e&&(t=Parse__default.Query.fromJSON("ChatSession",e)),t.include("user","role","role.model","story","story.person","story.person.userVerify","person","person.userVerify"),t.addDescending("updatedAt"),t.equalTo("user",Parse__default.User.current().toPointer()),t.notEqualTo("isDeleted",!0),t.limit(30);let n=await t.find();this.chatList=n.map((e=>(this.chatMap[e?.id]=new FmodeChat(e?.id,e?.get("role"),e,this,this.navCtrl,this.ncloud,this.uploadServ),{session:e,sid:e?.id,isHidden:!1,rid:e?.get("role")?.id,name:e?.get("role")?.get("name"),thumb:e?.get("role")?.get("thumb"),title:e?.get("title")||e?.get("role")?.get("name"),message:e?.get("messageList")?.[e?.get("messageList")?.length-1]?.content?.slice(0,20),latest:e?.createdAt})))}async getChatSessionDistinct(){let e=await this.ncloud.novaql('SELECT t1."objectId" as sid , "AvatarRole"."objectId" as rid, * FROM (\n SELECT *,ROW_NUMBER() OVER (PARTITION BY "user", "role" ORDER BY "createdAt" DESC) AS rn\n FROM "ChatSession" WHERE "user"=$1\n ) as t1\n LEFT JOIN "AvatarRole" ON "AvatarRole"."objectId" = t1."role"\n WHERE t1.rn=1\n LIMIT $2\n ;',[Parse__default.User.current()?.id,10]),t=e?.map((e=>({sid:e?.sid,rid:e?.rid,name:e?.name,message:e?.messageList?.[e?.messageList?.length-1]?.content?.slice(0,20),latest:e?.createdAt})));return this.chatList=t,this.chatList}createChatPanel(e,t){let n=t?.id||"new";t=new FmodeChat(n,e,t,this,this.navCtrl,this.ncloud,this.uploadServ),this.chatMap[n]=t,this.router.navigate(["/chat/pro/chat/"+n])}async createNewRoleChat(e){let t=new Parse__default.Query("AvatarRole");t.include("model");let n=await t.get(e);return new FmodeChat("new",n,null,this,this.navCtrl,this.ncloud,this.uploadServ)}async restoreChatPanel(e){let t=new Parse__default.Query("AvatarRole"),n=new Parse__default.Query("ChatSession"),o=await t.get(e?.rid),i=await n.get(e?.sid),a=new FmodeChat(e?.sid,o,i,this,this.navCtrl,this.ncloud,this.uploadServ);this.chatMap[e?.sid]=a,this.router.navigate(["/chat/pro/chat/"+e?.sid])}async callRole(e){document.body.classList.add("dark"),this.router.navigate([`/avatar/role/${e.id}`,{type:"phone"}])}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatService,deps:[{token:i1$1.Router},{token:NovaCloudService},{token:i3.Platform},{token:i3.AlertController},{token:i3.NavController},{token:CrossService},{token:NovaUploadService}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatService,providedIn:"root"})}}async function drawDalle(e){e.size=e?.size||"1024x1024",e.style=e?.style||"natural",e.quality=e?.quality||null;let t={model:"dall-e-3",prompt:e.prompt,n:1,quality:e.quality,response_format:"url",size:e.size,style:e.style};if(e.prompt?.length>3e3)throw"prompt maximum < 4000 characters";let n,o=await apig("aigc/gpt/v1/images/generations",t);if(console.log(o),o?.id){let e=new Parse__default.Query("ImagineWork");e.get(o?.id),n=await e.first(),console.log(n)}return n}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1$1.Router},{type:NovaCloudService},{type:i3.Platform},{type:i3.AlertController},{type:i3.NavController},{type:CrossService},{type:NovaUploadService}]});class ImagineService{constructor(e,t,n){this.http=e,this.ncloud=t,this.uploadServ=n,this.taskDetailMap={},this.newWorkList=[],this.myWorkList=[]}async drawDalle(e){let t=await drawDalle(e);return t?.id&&this.newWorkList.unshift(t),t}priceDalle(e){let t=[{model:"dall-e-3",quality:null,size:"1024x1024",credit:6.4},{model:"dall-e-3",quality:null,size:"1024x1792",credit:12.8},{model:"dall-e-3",quality:null,size:"1792x1024",credit:12.8},{model:"dall-e-3",quality:"hd",size:"1024x1024",credit:12.8},{model:"dall-e-3",quality:"hd",size:"1024x1792",credit:19.2},{model:"dall-e-3",quality:"hd",size:"1792x1024",credit:19.2},{model:"dall-e-2",quality:null,size:"1024x1024",credit:3.2},{model:"dall-e-2",quality:null,size:"512x512",credit:2.88},{model:"dall-e-2",quality:null,size:"256x256",credit:2.56}].find((t=>t.model==e.model&&t.quality==e.quality&&t.size==e.size));return t?.credit||19.2}priceStableDiffusion(e){let t=e.width*e.height,n=763e-9*t*e.steps+2278e-8*t*(e?.upscale||0)+(e?.hrSteps||0)*t*(e?.hrScale||0)*(e?.hrScale||0)*763e-9+(e?.faceFix?2:0)+(e?.imgOptions?.removeBackground?2:0)+(e?.imgOptions?.redrawBackground?2:0)+(e?.imgOptions?.facePreservation?2:0)+(e?.imgOptions?.genderDetect?1:0)+2*(e?.controlnet?.units?.length||0);return n=.3*n*e.batchSize,n}b64DataToBase64Image(e){let t=atob(e),n=new Blob([t],{type:"image/webp"});new Promise((e=>{let t=new FileReader;t.onloadend=function(){let n=t.result;console.log(n),e(n)},t.readAsDataURL(n)}))}async draw(e){let t=await this.ncloud.apig("aigc/sdapi/v1/draw",e),n=t?.paintingSign;return n&&setTimeout((async()=>{let e=new Parse__default.Query("ImagineWork");e.equalTo("taskId",n);let t=await e.first();console.log(t),t?.id&&this.newWorkList.unshift(t)}),1e3),t}async taskDetail(e){let t=await this.ncloud.apig("aigc/sdapi/v1/task/detail",{taskId:e});return console.log(t),this.taskDetailMap[e]=t,t}getMyWorkQuery(){let e=Parse__default.User.current();if(!e?.id)return;let t=this.getWorkQuery();return t.include("model","module","user"),t.equalTo("user",e.toPointer()),t}getWorkQuery(){let e=new Date((new Date).getTime()-6e4),t=Parse__default.Query.fromJSON("ImagineWork",{where:{$or:[{createdAt:{$lte:e},progress:{$ne:0}},{createdAt:{$gt:e}}]}});return t.include("model","module","user"),t.notEqualTo("isDeleted",!0),t.notEqualTo("isFailed",!0),t.doesNotExist("respData.error"),t.doesNotExist("respData.data.taskLimitCount"),t.addDescending("createdAt"),t}getimg(){return new Promise(((e,t)=>{let n=document.createElement("input");n.type="file",n.click();let handleChange=async()=>{if(n.removeEventListener("change",handleChange),n.files&&n.files.length>0){let t=n.files[0],o=await this.uploadServ.upload(t,(e=>{console.log(e),e.total.percent.toFixed(2)}));e(o.url)}else t("未选择文件")};n.addEventListener("change",handleChange)}))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ImagineService,deps:[{token:i1.HttpClient},{token:NovaCloudService},{token:NovaUploadService}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ImagineService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ImagineService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1.HttpClient},{type:NovaCloudService},{type:NovaUploadService}]});class FmaiService{constructor(e,t){this.imagine=e,this.chat=t}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmaiService,deps:[{token:ImagineService},{token:ChatService}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmaiService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmaiService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:ImagineService},{type:ChatService}]});class ImagineWork{constructor(e){this.task=null,this.progress=0,this.images=[],this.id=e,this.fetchTask()}async fetchTask(){if(this.id){const e=new Parse__default.Query("ImagineWork");try{let t=await e.get(this.id);this.task=t,t.id&&(this.progress=this.task.get("progress"),this.images=this.task.get("images"),this.images?.length&&(this.progress=1))}catch(e){console.error("Error fetching task:",e)}}return this.task}draw(e){return new Observable((t=>{if(this.task)return t.next(this.task),void t.complete();drawDalle(e).then((e=>{this.id=e.id,this.fetchTask();const n=new Parse__default.Query("ImagineWork"),o=setInterval((()=>{n.get(this.id).then((e=>{this.progress+=.01,this.task=e,t.next(e),this.task?.get("images")?.length&&(this.progress=1,clearInterval(o),t.complete())})).catch((e=>{clearInterval(o),t.error(e)}))}),1e3)})).catch((e=>{t.error(e)}))}))}}let colorMap=["primary","secondary","tertiary","success","warning","danger","light","medium","dark"];const MASK_LIST=[{name:"执行李",type:"employee",title:"首席执行官",desc:"一位富有远见和领导才能的创业新秀。她具备战略思维和决策能力,能够为公司设定长期目标并领导团队实现这些目标。",color:colorMap[0],cover:"https://imgsource.huashi6.com/images/ai/2023/9/29/15_48766.jpg?e=1695974629&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:oPkQSsyQLLD08R_J4SMeO1f1RdM="},{name:"技术刘",type:"employee",title:"首席技术官",desc:"一位技术专家,拥有广泛的技术知识和经验。他善于解决复杂的技术问题,并能够领导开发团队实施创新的技术解决方案。",color:colorMap[1],cover:["https://imgsource.huashi6.com/images/ai/2023/9/29/9_619877.jpg?e=1695952672&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:LDuSg8_n5g4Rj_8F5PKrGzV4T54=","https://imgsource.huashi6.com/images/ai/2023/9/27/20_17767.jpg?e=1695819037&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:a9uOeeJMN2oopK-3WQZzldPXfH0="]},{name:"点子王",type:"employee",title:"首席运营官",desc:"一位富有创意和市场洞察力的市场营销专家。她擅长制定营销策略,了解目标受众,并能够利用各种渠道和工具推广公司的产品或服务。",color:colorMap[2],cover:"https://imgsource.huashi6.com/images/ai/2023/9/29/9_186291.jpg?e=1695952125&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:EhEUtwnC9hpu-SXXsBrp2Q-rcJk="},{title:"设计总监",name:"李欣",type:"employee",desc:"一位富有创造力和用户导向思维的设计师。她能够理解用户需求,并通过设计直观、易用且吸引人的用户界面来提供出色的用户体验。",color:colorMap[3],cover:"https://imgsource.huashi6.com/images/ai/2023/9/29/9_18099.jpg?e=1695952201&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:G_a60v52iTTqvJgeTSa_8zJUY2w="},{title:"运营经理",name:"刘洁",type:"employee",desc:"一位组织能力强、注重细节并擅长解决问题的运营专家。她能够协调各个部门的工作,并确保公司的运营流程高效运行。",color:colorMap[4],cover:"https://imgsource.huashi6.com/images/ai/2023/9/29/9_842519.jpg?e=1695952125&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:FM_kKZDzkcLQ1EX4266dXU46cRc="},{title:"销售经理",name:"张伟",type:"employee",desc:"一位富有销售天赋和人际交往能力的销售专家。他善于与客户建立良好的关系,并能够推动销售团队实现业绩目标。",color:colorMap[5],cover:"https://imgsource.huashi6.com/images/ai/2023/9/29/15_739110.jpg?e=1695974920&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:vg_sn-qn67MJS-7j2o7mWzOCUSk="},{title:"数据分析师",name:"杨晨",type:"employee",desc:"一位善于解读数据和提供商业洞察的数据分析专家。她能够收集、分析和解释数据,为公司的决策制定提供有力的支持。",color:colorMap[6],cover:"https://imgsource.huashi6.com/images/ai/2023/9/29/15_204321.jpg?e=1695974779&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:dC2sGmJekSPBTCycPF76BkQPBoo="},{title:"财务经理",name:"赵晓",type:"employee",desc:"一位精通财务管理和分析的专业人士。她能够制定财务战略、管理公司的财务流程,并提供准确的财务报告和预测。",color:colorMap[7],cover:"https://imgsource.huashi6.com/images/ai/2023/9/29/15_947878.jpg?e=1695974779&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:TFGn0_l2PqhUTe9G4A3it769hcU="},{title:"品牌专员",name:"王雅",type:"employee",desc:"一位富有创意和品牌意识的专业人士。她能够塑造和管理公司的品牌形象,制定品牌营销策略,并与内部和外部利益相关者建立良好的合作关系。",color:colorMap[8],cover:["https://imgsource.huashi6.com/images/ai/2023/9/29/15_129581.jpg?e=1695975151&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:YQrpiv1hBKRPIdaEbDDDkLFuPG8=","https://imgsource.huashi6.com/images/ai/2023/9/29/15_912136.jpg?e=1695975151&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:8SVMU1rdKD8eaJ1gH_qGQzcrMhM="]},{title:"全科",name:"孔博",type:"teacher",desc:"擅长全科教学的金牌教师,知识面广泛,博古通今,因材施教,耐心稳重。",color:colorMap[0],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/12_40958.jpg?e=1697604189&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:U7r1Td30lXdf9mE1TMVAnDhBP6c="]},{title:"语文",name:"王明",type:"teacher",desc:"激发学生对文学的热爱,引导他们成为优秀的作家和沟通者。",color:colorMap[1],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/11_698893.jpg?e=1697602689&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:hK_AuY7BA1pp33QVeUue5QjIg4o="]},{title:"数学",name:"万红",type:"teacher",desc:"以清晰的逻辑和耐心的指导,帮助学生掌握数学的基础知识和解题技巧。",color:colorMap[2],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/11_256253.jpg?e=1697603314&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:K2iqp_ZzHYzXNu_0VJlywyANHp8="]},{title:"英语",name:"张瑞",type:"teacher",desc:"激发学生对英语学习的兴趣,培养他们的听、说、读、写能力,让他们自信地运用英语。",color:colorMap[3],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/12_266171.jpg?e=1697603707&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:uhpxBbT-jlSt_KjAnj0SFsFAjWU="]},{title:"物理",name:"金晓",type:"teacher",desc:"通过实验和案例,帮助学生理解物理原理,培养他们的科学思维和实验技能。",color:colorMap[4],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/11_694925.jpg?e=1697603071&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:FznZxhkYUrZ-BzX05dvNt8acTUw="]},{title:"化学",name:"陈华",type:"teacher",desc:"激发学生对化学的好奇心,教授他们化学知识和实验技巧,培养他们的实验和分析能力。",color:colorMap[5],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/11_942234.jpg?e=1697603169&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:__2T8cxLl4J0AwMR9MJdDiooDF0="]},{title:"生物",name:"杨婷",type:"teacher",desc:"引导学生探索生命的奥秘,培养他们的科学观察和实验能力,让他们热爱生物科学。",color:colorMap[6],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/12_330738.jpg?e=1697603491&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:2K5-DHPnUQ-R9GGxtWKiEG68QlE="]},{title:"历史",name:"赵亮",type:"teacher",desc:"帮助学生了解历史事件和文化背景,培养他们的历史意识和批判思维。",color:colorMap[7],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/11_256302.jpg?e=1697602689&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:YP7ffC1YKO-Pb0C3ks4caT0QqZk="]},{title:"地理",name:"林丽",type:"teacher",desc:"引导学生探索地球的奥秘,培养他们的地理观察和分析能力,让他们热爱地理科学。",color:colorMap[8],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/12_555804.jpg?e=1697604054&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:xLN4QW0x9jx9lEB4EFHWvI_gEsI="]}];class UtilnowPipe{constructor(){this.enLocale={"秒钟前":" seconds ago","分钟前":" minutes ago","小时前":" hours ago","天前":" days ago"}}transform(e,t){let n=((new Date).getTime()-e.getTime())/1e3;if(n<=60)return this.handleArgs(n.toFixed(0),"秒钟前",t);let o=n/60;if(o<60)return this.handleArgs(o.toFixed(0),"分钟前",t);let i=o/60;if(i<24)return this.handleArgs(i.toFixed(0),"小时前",t);let a=i/24;return a<7?this.handleArgs(a.toFixed(0),"天前",t):`${e?.getFullYear()}-${e?.getMonth()+1}-${e?.getDate()}`}handleArgs(e,t,n){return"en"==n&&(t=this.enLocale[t]),"TranslateService"==n?.constructor?.name&&(console.log(t),"en"==n?.getDefaultLang()&&(t=this.enLocale[t])),"json"==n?{unit:t,value:e}:e+t}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:UtilnowPipe,deps:[],target:i0.ɵɵFactoryTarget.Pipe})}static{this.ɵpipe=i0.ɵɵngDeclarePipe({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:UtilnowPipe,isStandalone:!0,name:"utilnow"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:UtilnowPipe,decorators:[{type:Pipe,args:[{name:"utilnow",standalone:!0}]}]});class ChatContentPipe{transform(e,...t){let n=t?.[0]||"text";return"text"==n?getMessageContentText(e):"image_url"==n?getMessageImageUrl(e):e}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatContentPipe,deps:[],target:i0.ɵɵFactoryTarget.Pipe})}static{this.ɵpipe=i0.ɵɵngDeclarePipe({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:ChatContentPipe,isStandalone:!0,name:"chatContent"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatContentPipe,decorators:[{type:Pipe,args:[{name:"chatContent",pure:!0,standalone:!0}]}]});class HidexmlPipe{transform(e,...t){return e?this.hideXmlTags(e):""}hideXmlTags(e){return e.replace(/<[^>]*>/g,"")}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:HidexmlPipe,deps:[],target:i0.ɵɵFactoryTarget.Pipe})}static{this.ɵpipe=i0.ɵɵngDeclarePipe({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:HidexmlPipe,isStandalone:!0,name:"hidexml"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:HidexmlPipe,decorators:[{type:Pipe,args:[{name:"hidexml",standalone:!0}]}]});class MarkdownMathJax{constructor(e){this.options=e,this.adaptor=liteAdaptor(),RegisterHTMLHandler(this.adaptor)}text_to_mathjax(e,t){if(!e?.length)return"";if(!e?.replace)return"";t=t||this.options;let n=new SVG({fontCache:"local"});"chtml"==t?.output&&(n=new CHTML);const o=mathjax.document("",{skipHtmlTags:["script","noscript","style","textarea","pre","code","annotation","annotation-xml"],InputJax:new TeX({processEscapes:!0,packages:AllPackages}),OutputJax:n}),i={em:16,ex:8,containerWidth:1280};return[/\$\$\ (.+?)\ \$\$/g,/\$\$(.+?)\$\$/g,/\$\$\n(.+?)\n\$\$/g,/\$(.+?)\$/g,/\\\((.+?)\\\)/g,/\\\[(.+?)\\\]/g].forEach((t=>{e=e.replace(t,((e,n)=>{let a;console.log(t,e,n);try{a=o.convert(`${n}`,i)}catch(e){}if(a){return`<span class="mathjax raw" style="margin-left:10px;margin-right:10px;">${this.adaptor.innerHTML(a)}</span>`}return n}))})),e}}let md=new MarkdownIt({html:!0,xhtmlOut:!0,breaks:!1,linkify:!1,typographer:!1,quotes:"“”‘’",highlight:function(e,t){if(t&&hljs.getLanguage(t))try{return`<pre style="position:relative;padding:10px;" class="hljs lang-${t}"><code>${hljs.highlight(e,{language:t}).value}</code><small class="hljs-lang"><span class="sr-only">Language:</span>${t}</small></pre>`}catch(e){}return""}});md.use(abbr),md.use(footnote),md.use(deflist),md.use(mark),md.use(ins),md.use(sub),md.use(sup),md.use(ruby);const mditConfig={plantumlServer:"https://www.plantuml.com/plantuml"};function makePlantumlURL(e){const t=plantumlEncoder.encode(e);return`${mditConfig.plantumlServer}/svg/${t}`}md.renderer.rules.plantuml=(e,t,n,o,i)=>{const a=e[t];if("plantuml"!==a.type)return e[t].content;return`\n <img src="${makePlantumlURL(a.content)}" />\n <pre style="position:relative;padding:10px;" class="hljs lang-plantuml"><code>${a.content}</code><small class="hljs-lang"><span class="sr-only">Language:</span>plantuml</small></pre>\n `},md.core.ruler.push("plantuml",(e=>{const t=e.tokens;for(const e of t)"fence"===e.type&&"plantuml"===e.info&&(e.type="plantuml")}));const spaceregex=/\s*/,notinhtmltagregex=/(?![^<]*>|[^<>]*<\/)/;let coloregex=/\[color=([#|(|)|\s|,|\w]*?)\]/;coloregex=new RegExp(coloregex.source+notinhtmltagregex.source,"g");let nameregex=/\[name=(.*?)\]/,timeregex=/\[time=([:|,|+|-|(|)|\s|\w]*?)\]/;const nameandtimeregex=new RegExp(nameregex.source+spaceregex.source+timeregex.source+notinhtmltagregex.source,"g");function replaceExtraTags(e){return console.log("replaceExtraTags",e),e=(e=(e=(e=e.replace(coloregex,'<span class="color" data-color="$1"></span>')).replace(nameandtimeregex,'<small><i class="fa fa-user"></i> $1 <i class="fa fa-clock-o"></i> $2</small>')).replace(nameregex,'<small><i class="fa fa-user"></i> $1</small>')).replace(timeregex,'<small><i class="fa fa-clock-o"></i> $1</small>'),console.log("replaceExtraTags",e),e}function finishView(e){let t=$.parseHTML(`<html><body><div id="topmd">${e}</div></body></html>`)[0],n=$(t),o=n.find("blockquote.raw").removeClass("raw");o=n.find("blockquote");let i=$(o).find("p");i.each(((e,t)=>{let n=$(t).html();n=replaceExtraTags(n),t.innerHTML=n,$(t).html(n),i[e].innerHTML=n,$(i[e]).html(n)})),o.find(".color").each(((e,t)=>{let n=$(t).attr("data-color");$(t).closest("blockquote").css("border-left-color",n)}));let a="<style>\n .markdown-section {\n color: black;\n text-align: left;\n }\n .markdown-section pre .hljs-lang{\n text-transform: uppercase;\n font-weight: 700;\n font-size: .75rem;\n line-height: 1rem;\n padding-top: .25rem;\n padding-bottom: .25rem;\n padding-left: .5rem;\n padding-right: .5rem;\n background-color: rgba(0,0,0,.3);\n border-bottom-left-radius: .375rem;\n top:0;\n right:0;\n position:absolute;\n}\n\n }\n .markdown-section pre .hljs {\n position:relative!important;\n background: #272822!important;\n padding:10px!important;\n color: #ddd;\n text-shadow: none!important;\n }\n\n .markdown-section blockquote {\n margin: 0;\n margin-bottom: 0px;\n margin-bottom: .85em;\n padding: 0 15px;\n color: #858585;\n border-left: 4px solid #e5e5e5;\n border-left-color: rgb(229, 229, 229);\n }\n .markdown-section img {\n max-width:100%;\n }\n </style>"+(n.html()||e);return a=a.replaceAll('src="/uploads/','src="https://md.fmode.cn/uploads/'),a}nameregex=new RegExp(nameregex.source+notinhtmltagregex.source,"g"),timeregex=new RegExp(timeregex.source+notinhtmltagregex.source,"g");class MarkdownParse{constructor(){}parseToHTML(e){if(!e?.length)return"";if(!e?.replace)return"";let t=new MarkdownMathJax;e=e.split("```").map(((e,n)=>n%2==0?e=t.text_to_mathjax(e,{output:"svg"}):e)).join("```");let n=md.render(e);return n=finishView(n),n}info(...e){}}class MarkdownPreviewComponent{constructor(e,t){this.domSan=e,this.renderer=t,this.content="",this.render=!0}ngAfterViewInit(){this.renderMdToHTML()}renderMdToHTML(){if(!this.render)return;let e=(new MarkdownParse).parseToHTML(this.content);this.safeHTML=this.domSan.bypassSecurityTrustHtml(e);let t=this.renderer.createElement("div");t.innerHTML=e,this.renderer.appendChild(this.mdContent.nativeElement,t)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:MarkdownPreviewComponent,deps:[{token:i1$2.DomSanitizer},{token:i0.Renderer2}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:MarkdownPreviewComponent,selector:"fm-markdown-preview",inputs:{content:"content",render:"render"},viewQueries:[{propertyName:"mdContent",first:!0,predicate:["mdContent"],descendants:!0}],ngImport:i0,template:'<div class="message-body">\n <div *ngIf="render" #mdContent class="markdown-section">\n </div>\n <div *ngIf="!render" class="pre-section">\n {{content}}\n </div>\n</div>',styles:[":host{overflow-x:auto}.message-body div{text-align:left;overflow-x:auto}.message-body .pre-section{white-space:pre-wrap}.markdown-section blockquote{margin:0 0 .85em;padding:0 15px;color:#858585;border-left:4px solid #e5e5e5;border-left-color:#e5e5e5}\n"],dependencies:[{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:MarkdownPreviewComponent,decorators:[{type:Component,args:[{selector:"fm-markdown-preview",template:'<div class="message-body">\n <div *ngIf="render" #mdContent class="markdown-section">\n </div>\n <div *ngIf="!render" class="pre-section">\n {{content}}\n </div>\n</div>',styles:[":host{overflow-x:auto}.message-body div{text-align:left;overflow-x:auto}.message-body .pre-section{white-space:pre-wrap}.markdown-section blockquote{margin:0 0 .85em;padding:0 15px;color:#858585;border-left:4px solid #e5e5e5;border-left-color:#e5e5e5}\n"]}]}],ctorParameters:()=>[{type:i1$2.DomSanitizer},{type:i0.Renderer2}],propDecorators:{content:[{type:Input}],mdContent:[{type:ViewChild,args:["mdContent"]}],render:[{type:Input}]}});class MarkdownPreviewModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:MarkdownPreviewModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:MarkdownPreviewModule,declarations:[MarkdownPreviewComponent],imports:[CommonModule],exports:[MarkdownPreviewComponent]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:MarkdownPreviewModule,imports:[CommonModule]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:MarkdownPreviewModule,decorators:[{type:NgModule,args:[{declarations:[MarkdownPreviewComponent],imports:[CommonModule],exports:[MarkdownPreviewComponent]}]}]});class ClipboardService{constructor(e){this.toastCtrl=e}async copyToClipboard(e){try{return await Clipboard.write({string:e}),void this.copySuccess()}catch(t){try{if(navigator.clipboard&&window.isSecureContext)return await(navigator?.clipboard?.writeText(e)),void this.copySuccess();throw!1}catch(t){let n=document.createElement("textarea");n.value=e,n.style.position="fixed",n.style.left="-9999px",n.style.top="-9999px",document.body.appendChild(n),n.focus(),n.select();try{let e=document?.execCommand("copy");e?this.copySuccess():console.error("无法复制文本")}catch(e){console.error("无法复制文本: ",e)}document.body.removeChild(n)}}}async copySuccess(){(await this.toastCtrl.create({duration:1e3,message:"复制成功",color:"primary",icon:"information-circle",position:"top"})).present()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ClipboardService,deps:[{token:i3.ToastController}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ClipboardService,providedIn:"root"})}}function pcmtoWav(e,t,n,o){let i={chunkId:[82,73,70,70],chunkSize:0,format:[87,65,86,69],subChunk1Id:[102,109,116,32],subChunk1Size:16,audioFormat:1,numChannels:n||1,sampleRate:t||16e3,byteRate:0,blockAlign:0,bitsPerSample:o||16,subChunk2Id:[100,97,116,97],subChunk2Size:0};function u32ToArray(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]}function u16ToArray(e){return[255&e,e>>8&255]}let a=new Uint8Array(e);i.blockAlign=i.numChannels*i.bitsPerSample>>3,i.byteRate=i.blockAlign*i.sampleRate,i.subChunk2Size=a.length*(i.bitsPerSample>>3),i.chunkSize=36+i.subChunk2Size;let r=i.chunkId.concat(u32ToArray(i.chunkSize),i.format,i.subChunk1Id,u32ToArray(i.subChunk1Size),u16ToArray(i.audioFormat),u16ToArray(i.numChannels),u32ToArray(i.sampleRate),u32ToArray(i.byteRate),u16ToArray(i.blockAlign),u16ToArray(i.bitsPerSample),i.subChunk2Id,u32ToArray(i.subChunk2Size)),s=new Uint8Array(r),l=new Uint8Array(s.length+a.length);return l.set(s),l.set(a,s.length),new Blob([l],{type:"audio/wav"})}function resampleAudio(e,t,n){let o=e.length,i=Math.floor(o/t*n),a=[];for(let o=0;o<i;o++){let i=Math.floor(o*(t/n));a[o]=e[i]}return a}function convertFrameBufferToBase64(e){const t=new Uint8Array(2*e.length);for(let n=0;n<e.length;n++){const o=e[n];t[2*n]=255&o,t[2*n+1]=o>>8&255}return btoa(String.fromCharCode.apply(null,t))}function resampleBuffer(e,t,n){const o=t/n,i=Math.round(e.length/o),a=new Int16Array(i);for(let t=0;t<i;t++){const n=Math.floor(t*o);a[t]=e[n]}return a}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ClipboardService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i3.ToastController}]}),function(){"use strict";Recorder.prototype.enc_pcm={stable:!0,fast:!0,testmsg:"pcm为未封装的原始音频数据,pcm音频文件无法直接播放,可用Recorder.pcm2wav()转码成wav播放;支持位数8位、16位(填在比特率里面),采样率取值无限制"},Recorder.prototype.pcm=function(e,t,n){var o=this.set,i=e.length,a=8==o.bitRate?8:16,r=new ArrayBuffer(i*(a/8)),s=new DataView(r),l=0;if(8==a)for(var c=0;c<i;c++,l++){var p=128+(e[c]>>8);s.setInt8(l,p)}else for(c=0;c<i;c++,l+=2)s.setInt16(l,e[c],!0);t(new Blob([s.buffer],{type:"audio/pcm"}))},Recorder.pcm2wav=function(e,t,n){e.slice&&null!=e.type&&(e={blob:e});var o=e.sampleRate||16e3,i=e.bitRate||16;if(e.sampleRate&&e.bitRate||console.warn("pcm2wav必须提供sampleRate和bitRate"),Recorder.prototype.wav){var a=new FileReader;a.onloadend=function(){var e;let r=a.result;if(8==i){var s=new Uint8Array(r);e=new Int16Array(s.length);for(var l=0;l<s.length;l++)e[l]=s[l]-128<<8}else e=new Int16Array(r);Recorder({type:"wav",sampleRate:o,bitRate:i}).mock(e,o).stop((function(e,n){t(e,n)}),n)},a.readAsArrayBuffer(e.blob)}else n("pcm2wav必须先加载wav编码器wav.js")}}(),function(){"use strict";Recorder.prototype.enc_wav={stable:!0,fast:!0,testmsg:"支持位数8位、16位(填在比特率里面),采样率取值无限制;此编码器仅在pcm数据前加了一个44字节的wav头,编码出来的16位wav文件去掉开头的44字节即可得到pcm(注:其他wav编码器可能不是44字节)"},Recorder.prototype.wav=function(e,t,n){var o=this.set,i=e.length,a=o.sampleRate,r=8==o.bitRate?8:16,s=i*(r/8),l=new ArrayBuffer(44+s),c=new DataView(l),p=0,writeString=function(e){for(var t=0;t<e.length;t++,p++)c.setUint8(p,e.charCodeAt(t))},write16=function(e){c.setUint16(p,e,!0),p+=2},write32=function(e){c.setUint32(p,e,!0),p+=4};if(writeString("RIFF"),write32(36+s),writeString("WAVE"),writeString("fmt "),write32(16),write16(1),write16(1),write32(a),write32(a*(r/8)),write16(r/8),write16(r),writeString("data"),write32(s),8==r)for(var d=0;d<i;d++,p++){var m=128+(e[d]>>8);c.setInt8(p,m)}else for(d=0;d<i;d++,p+=2)c.setInt16(p,e[d],!0);t(new Blob([c.buffer],{type:"audio/wav"}))}}(),function(){var WaveView=function(e){return new fn(e)},e="WaveView",fn=function(t){var n=this,o={scale:2,speed:9,phase:21.8,fps:20,keep:!0,lineWidth:3,linear1:[0,"rgba(150,96,238,1)",.2,"rgba(170,79,249,1)",1,"rgba(53,199,253,1)"],linear2:[0,"rgba(209,130,255,0.6)",1,"rgba(53,199,255,0.6)"],linearBg:[0,"rgba(255,255,255,0.2)",1,"rgba(54,197,252,0.2)"]};for(var i in t)o[i]=t[i];n.set=t=o;var a=t.elem;a&&("string"==typeof a?a=document.querySelector(a):a.length&&(a=a[0])),a&&(t.width=a.offsetWidth,t.height=a.offsetHeight);var r=t.scale,s=t.width*r,l=t.height*r;if(!s||!l)throw new Error(e+"无宽高");var c=n.elem=document.createElement("div"),p=["","transform-origin:0 0;","transform:scale("+1/r+");"];c.innerHTML='<div style="width:'+t.width+"px;height:"+t.height+'px;overflow:hidden"><div style="width:'+s+"px;height:"+l+"px;"+p.join("-webkit-")+p.join("-ms-")+p.join("-moz-")+p.join("")+'"><canvas/></div></div>';var d=n.canvas=c.querySelector("canvas"),m=n.ctx=d.getContext("2d");d.width=s,d.height=l,n.linear1=n.genLinear(m,s,t.linear1),n.linear2=n.genLinear(m,s,t.linear2),n.linearBg=n.genLinear(m,l,t.linearBg,!0),a&&(a.innerHTML="",a.appendChild(c)),n._phase=0};fn.prototype=WaveView.prototype={genLinear:function(e,t,n,o){for(var i=e.createLinearGradient(0,0,o?0:t,o?t:0),a=0;a<n.length;)i.addColorStop(n[a++],n[a++]);return i},genPath:function(e,t,n){for(var o=[],i=this.set,a=i.scale,r=i.width*a,s=i.height*a/2,l=0;l<r;l+=a){var c=(1+Math.cos(Math.PI+l/r*2*Math.PI))/2*s*t*Math.sin(2*Math.PI*(l/r)*e+n)+s;o.push(c)}return o},input:function(e,t,n){var o=this;o.sampleRate=n,o.pcmData=e,o.pcmPos=0,o.inputTime=Date.now(),o.schedule()},schedule:function(){var e=this,t=e.set,n=Math.floor(1e3/t.fps);e.timer||(e.timer=setInterval((function(){e.schedule()}),n));var o=Date.now();if(!(o-(e.drawTime||0)<n)){e.drawTime=o;for(var i=e.sampleRate/t.fps,a=e.pcmData,r=e.pcmPos,s=Math.max(0,Math.min(i,a.length-r)),l=0,c=0;c<s;c++,r++)l+=Math.abs(a[r]);e.pcmPos=r,!s&&t.keep||e.draw(Recorder.PowerLevel(l,s)),!s&&o-e.inputTime>1300&&(clearInterval(e.timer),e.timer=0)}},draw:function(e){var t=this,n=t.set,o=t.ctx,i=n.scale,a=n.width*i,r=n.height*i,s=n.speed/n.fps,l=t._phase-=s,c=l+s*n.phase,p=e/100,d=t.genPath(2,p,l),m=t.genPath(1.8,p,c);o.clearRect(0,0,a,r),o.beginPath();for(var u=0,g=0;g<a;u++,g+=i)0==g?o.moveTo(g,d[u]):o.lineTo(g,d[u]);u--;for(g=a-1;g>=0;u--,g-=i)o.lineTo(g,m[u]);o.closePath(),o.fillStyle=t.linearBg,o.fill(),t.drawPath(m,t.linear2),t.drawPath(d,t.linear1)},drawPath:function(e,t){var n=this.set,o=this.ctx,i=n.scale,a=n.width*i;o.beginPath();for(var r=0,s=0;s<a;r++,s+=i)0==s?o.moveTo(s,e[r]):o.lineTo(s,e[r]);o.lineWidth=n.lineWidth*i,o.strokeStyle=t,o.stroke()}},Recorder[e]=WaveView}();const SpeechRecognition=window.SpeechRecognition||window.webkitSpeechRecognition,SpeechGrammarList=window.SpeechGrammarList||window.webkitSpeechGrammarList;class WebSpeech{constructor(e){this.platform=e}startRecognition(e="Nihao | Hello"){if(!SpeechRecognition)return;if(this.recognition&&this.recognition.stop(),console.log("startRecognition"),this.recognition=new SpeechRecognition,!this.recognition)return;this.recognition.continuous=!0;let t=`#JSGF V1.0; grammar words; public <word> = ${e} ;`;this.recognition=new SpeechRecognition;let n=new SpeechGrammarList;n.addFromString(t,1),this.recognition.grammars=n,this.recognition.start(),this.recognition.onresult=e=>{let t=e.results||[];console.log(t),console.log(t[0]?.[0]),t[0]?.[0]?.transcript?.indexOf("Nihao")>-1&&console.log("Nihao成功唤醒"),t[0]?.[0]?.transcript?.indexOf("Hello")>-1&&console.log("Hello成功唤醒"),this.startRecognition()},this.recognition.onend=e=>{console.log(e)},this.recognition.onerror=e=>{console.error(e)}}speak(e,t=1,n=1.2,o=.8){this.platform.is("capacitor")||this.speakWithEdge(e,1,1.2,.8)}speakWithEdge(e,t=1,n=1.2,o=.8){let i=new SpeechSynthesisUtterance(e),a=this.getVoiceByName("Yaoyao");console.log(a),a&&(i.voice=a),i.rate=n,i.pitch=t,i.volume=10,window.speechSynthesis.speak(i)}getVoiceByName(e){return window.speechSynthesis.getVoices().find((t=>t.name.indexOf(e)>-1))}}class FmodeVoiceService{constructor(e,t){this.platform=e,this.diagnostic=t,this.webSpeech=WebSpeech,this.isUserFinish=!1,this.recordWavBlob=null,this.recordPcmBlob=null,this.recordDuration=0,this.recordType="pcm",this.encodingType="raw",this.connStatus="",this.btnStatus="UNDEFINED",this.resultText="",this.resultTextTemp="",this.APPID="50f4a46c",this.API_SECRET="NzFlNmFhZDJjMDNkZGM3NzI0Mzg2OGNm",this.API_KEY="106ddc40dfd4b9ca6d7b47c70fada749",this.durationStr="00:00",this.duration=0,this.requestPermission()}toggleRecord(){console.log(this.btnStatus),"UNDEFINED"===this.btnStatus||"CLOSED"===this.btnStatus?this.startTalk():"CONNECTING"!==this.btnStatus&&"OPEN"!==this.btnStatus||this.finishTalk()}finishTalk(){this.isUserFinish=!0,this.onBeforeFinishTalk&&this.onBeforeFinishTalk(),this.recordStop()}async startTalk(e){this.resultText="",this.resultTextTemp="",this.onBeforeStartTalk&&this.onBeforeStartTalk(),event?.preventDefault(),await this.openWithPriviledge(),setTimeout((()=>{this.connectWebSocket()}),100),this.startCountdown(),this.onAfterStartTalk&&this.onAfterStartTalk()}cancelTalk(){this.onBeforeCancelTalk&&this.onBeforeCancelTalk(),this.recordStop(),this.iatWS?.close(),this.resultText=null,this.onAfterCancelTalk&&this.onAfterCancelTalk()}async recordStart(){this.createRecorder(),await this.openWithPriviledge(),this.recorder.start(),this.changeBtnStatus("OPEN"),this.onAfterRecordStart&&this.onAfterRecordStart()}recordStop(){return new Promise((e=>{clearInterval(this.countdownInterval),this.changeBtnStatus("CLOSED"),this.recorder?.stop((async(t,n)=>{try{this.iatWS.send(JSON.stringify({data:{status:2,format:"audio/L16;rate=16000",encoding:this.encodingType,audio:""}}))}catch(e){}let o=(window.URL||webkitURL).createObjectURL(t);console.log(t,o,"时长:"+n+"ms"),this.recordPcmBlob=t,this.recordWavBlob=await this.pcmBlobToWavBlob(t,44100),console.log("this.recordWavBlob",this.recordWavBlob),setTimeout((()=>{this.isUserFinish&&(this.onAfterFinishTalk&&this.onAfterFinishTalk(),this.isUserFinish=!1)}),2e3),this.recorder?.close(),this.recorder=null,console.log("localUrl",o),e(!0)}),(t=>{console.log("录音失败:"+t),this.recorder.close(),this.recorder=null,e(null)}))}))}playRecord(){this.playPCM(this.recordPcmBlob,44100)}async pcmBlobToWavBlob(e,t){return new Promise((n=>{let o=new FileReader;o.onload=function(e){let o=pcmtoWav(e.target.result,t,1,16);n(o)},o.readAsArrayBuffer(e)}))}async playPCM(e,t){let n=await this.pcmBlobToWavBlob(e,t),o=window.URL.createObjectURL(n),i=new Audio;i.src=o,i.play()}async playBuffers(){let e=await this.BuffersToBlob(this.buffers);this.playPCM(e,44100)}BuffersToBlob(e){let t=[];return e.forEach((e=>{e.forEach((e=>{t.push(e)}))})),new Blob([t],{type:"audio/pcm"})}splitAudioData(e){const t=1280,n=Math.ceil(e.length/t),o=[];for(let i=0;i<n;i++){const n=i*t,a=n+t,r=e.slice(n,a);o.push(r)}return o}BufferToBlob(e){return new Blob([e],{type:"audio/pcm"})}createRecorder(){this.recorder||(this.recorder=Recorder({type:this.recordType,sampleRate:44100,bitRate:16,onProcess:(e,t,n,o,i,a)=>{let r=e.length&&e[e.length-1];if(this.buffers=e,r=resampleBuffer(r,44100,16e3),this.iatWS.readyState===this.iatWS.OPEN){if(this.disableASR)return;this.iatWS.send(JSON.stringify({data:{status:1,format:"audio/L16;rate=16000",encoding:this.encodingType,audio:convertFrameBufferToBase64(r)}}))}this.waveClient?.input(e[e.length-1],t,o)}}))}async openWithPriviledge(){return console.log(this.btnStatus),await this.requestPermission(),this.createRecorder(),!!Recorder.IsOpen()||new Promise((e=>{this.recorder.open((()=>{let t=document.querySelector(".record-wave");t&&(console.log(t),Recorder.WaveView&&(this.waveClient=Recorder.WaveView({elem:".record-wave"}))),e(!0)}),((e,t)=>{console.log((t?"UserNotAllow,":"")+"无法录音:"+e)}))}))}getWebSocketUrl(){let e="wss://iat-api.xfyun.cn/v2/iat",t="iat-api.xfyun.cn",n=this.API_KEY,o=this.API_SECRET,i=(new Date).toUTCString(),a=`host: ${t}\ndate: ${i}\nGET /v2/iat HTTP/1.1`,r=CryptoJS.HmacSHA256(a,o),s=CryptoJS.enc.Base64.stringify(r);return e=`${e}?authorization=${btoa(`api_key="${n}", algorithm="hmac-sha256", headers="host date request-line", signature="${s}"`)}&date=${i}&host=${t}`,e}toBase64(e){for(var t="",n=new Uint8Array(e),o=n.byteLength,i=0;i<o;i++)t+=String.fromCharCode(n[i]);return window.btoa(t)}countTimer(){this.duration++;let e=String(parseInt(String(this.duration/60))).padStart(2,"0"),t=String((this.duration%60).toFixed(0)).padStart(2,"0"),n=e+":"+t;this.durationStr=n,this.connStatus=`录音中(${this.durationStr})`,console.log(this.duration,e,t),console.log(this.duration),console.log(n),this.onDurationStrChange&&this.onDurationStrChange(n)}startCountdown(){this.recordDuration=0,this.durationInterval&&clearInterval(this.durationInterval),this.countdownInterval=setInterval((()=>{this.recordDuration+=100}),100),this.now=new Date,this.duration=0,this.countdownInterval&&clearInterval(this.countdownInterval),this.countdownInterval=setInterval((()=>{this.countTimer()}),1e3)}changeBtnStatus(e){this.btnStatus=e,"CONNECTING"===e?this.connStatus="建立连接中":"OPEN"===e||("CLOSING"===e?this.connStatus="关闭连接中":"CLOSED"===e&&(this.connStatus="开始录音"))}renderResult(e){let t=JSON.parse(e);if(t.data&&t.data.result){let e=t.data.result,n="",o=e.ws;for(let e=0;e<o.length;e++)n+=o[e].cw[0].w,console.log(n);e.pgs?("apd"===e.pgs&&(this.resultText=this.resultTextTemp),this.resultTextTemp=this.resultText+n):this.resultText=this.resultText+n,this.resultTextTemp||this.resultText,console.log("diff temp",this.resultTextTemp),console.log("diff result",this.resultText),this.onInputChange&&this.onInputChange(this.getUserInput())}0===t.code&&2===t.data.status&&this.iatWS.close(),0!==t.code&&(this.iatWS.close(),console.error(t))}getUserInput(){return""+(this.resultTextTemp||this.resultText)}connectWebSocket(){console.log("connectWebSocket");const e=this.getWebSocketUrl();if("WebSocket"in window)this.iatWS=new WebSocket(e);else if(!("MozWebSocket"in window))return void alert("浏览器不支持WebSocket");console.log("connectWebSocket",this.btnStatus),this.changeBtnStatus("CONNECTING"),this.iatWS.onopen=e=>{this.recordStart();var t={common:{app_id:this.APPID},business:{language:"zh_cn",domain:"iat",accent:"mandarin",vad_eos:5e3,dwa:"wpgs"},data:{status:0,format:"audio/L16;rate=16000",encoding:this.encodingType}};this.iatWS.send(JSON.stringify(t))},this.iatWS.onmessage=e=>{console.log("onmessage"+this.resultText),this.renderResult(e.data)},this.iatWS.onerror=e=>{console.error("error",e),this.recordStop(),this.changeBtnStatus("CLOSED")},this.iatWS.onclose=async e=>{console.log("onclose"+this.resultText),this.reconnectWebsocket()}}async reconnectWebsocket(){this.isUserFinish||this.connectWebSocket()}isCapacitor(){return this.platform.is("capacitor")||this.platform.is("cordova")}async requestPermission(){if(this.isCapacitor())try{await this.requestStoagePermission(),await this.requestCameraPermission(),await this.requestMicPermission(),await this.requestRecordAudioPermission()}catch(e){console.error(e)}}async requestRecordAudioPermission(){let e=await this.diagnostic.requestRuntimePermissions([this.diagnostic.permission.RECORD_AUDIO]);console.log("record permission request:",e)}async requestMicPermission(){let e=await this.diagnostic.isMicrophoneAuthorized();if(console.log("permisson_MIC:",e),!e){await this.diagnostic.requestMicrophoneAuthorization()}}async requestStoagePermission(){let e=await this.diagnostic.isExternalStorageAuthorized();if(console.log("permisson_STORAGE:",e),!e){await this.diagnostic.requestExternalStorageAuthorization()}}async requestCameraPermission(){let e=await this.diagnostic.isCameraAuthorized();if(console.log("permisson_Camera:",e),!e){await this.diagnostic.requestCameraAuthorization()}}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeVoiceService,deps:[{token:i3.Platform},{token:i2.Diagnostic}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeVoiceService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeVoiceService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i3.Platform},{type:i2.Diagnostic}]});class RolePointsCloud{constructor(e,t,n){this.offsetPosition=new BABYLON.Vector3(0,1.25,0),this.animationGroup=new BABYLON.AnimationGroup("RoleAnimGroup"),this.AnimMap={idle:null},this.scene=e,this.engine=this.engine}async init(){this.Mesh=this.loadMesh(),this.loadIdleAnim()}playAnim(e){this.scene.beginDirectAnimation(this.Mesh,[this.AnimMap[e]],0,120,!0)}loadMesh(){let e=BABYLON.MeshBuilder.CreateSphere("sphere",{diameter:2},this.scene);return e.position.addInPlace(this.offsetPosition),e.visibility=1,e.material=new BABYLON.StandardMaterial("mat",this.scene),e.material.wireframe=!0,e.scaling=new BABYLON.Vector3(1,1,1),e}loadIdleAnim(){let e=new BABYLON.Animation("idle","scaling",30,BABYLON.Animation.ANIMATIONTYPE_VECTOR3,BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE),t=[];t.push({frame:0,value:new BABYLON.Vector3(1,1,1)}),t.push({frame:60,value:new BABYLON.Vector3(1.5,1.5,1.5)}),t.push({frame:120,value:new BABYLON.Vector3(1,1,1)}),e.setKeys(t),this.Mesh.animations.push(this.AnimMap.idle),this.AnimMap.idle=e,this.animationGroup.addTargetedAnimation(this.AnimMap.idle,this.Mesh)}}class CompAvatarParticleComponent{constructor(e){this.elementRef=e,this.isWebVR=!1,this.animMap={}}ngAfterViewInit(){if(this.canvas=this.renderCanvas.nativeElement,console.log(this.canvas),this.canvas){let e={};this.engine=new BABYLON.Engine(this.canvas,!0,e),console.log(this.engine),this.createScene(),this.engine.runRenderLoop((()=>{this.scene?.render(),this.engine?.resize()})),window.addEventListener("resize",(()=>{this.engine?.resize()}))}}async createScene(){this.scene=new BABYLON.Scene(this.engine),this.scene.clearColor=new BABYLON.Color4(0,0,0,1),this.mainCamera=this.createCamera(),console.log(this.mainCamera),this.currentRole=new RolePointsCloud(this.scene,this.engine,this.mainCamera),await this.currentRole.init(),this.currentRole.playAnim("idle"),this.currentRole.Mesh.visibility=0,await this.createCloudPoints();new BABYLON.HemisphericLight("light1",new BABYLON.Vector3(0,1,0),this.scene);this.engine?.resize()}createCamera(){let e=new(this.isWebVR?BABYLON.VRDeviceOrientationArcRotateCamera:BABYLON.ArcRotateCamera)("Camera",0,0,30,new BABYLON.Vector3(0,.5,0),this.scene);return e.setPosition(new BABYLON.Vector3(0,0,5)),e.beta=Math.PI/3,e.alpha=Math.PI/1.2,e.radius=15,e}async createCloudPoints(){this.pointsMesh=this.currentRole.Mesh,this.pointsCloud=new BABYLON.PointsCloudSystem("pcs",1,this.scene);let e=new BABYLON.Color3(.7,.8,1),t=new BABYLON.Color4(.7,.8,1),n=(new BABYLON.Color4(.2,.5,1),new BABYLON.Color4(0,0,.2,0),new BABYLON.Texture("/assets/avatar/particle/textures/flare.png",this.scene)),o=new BABYLON.PBRMaterial("material",this.scene);o.emissiveTexture=n,o.emissiveColor=e,this.pointsCloud.addVolumePoints(this.currentRole.Mesh,5e3,BABYLON.PointColor.Color,t),this.pointsCloud.buildMeshAsync().then((()=>{this.playAnimation("waiting")})),this.scene.registerAfterRender((()=>{this.pointsCloud.setParticles()})),this.engine.runRenderLoop((()=>{this.scene.render()}))}playAnimation(e){switch(e){case"waiting":this.cloudAnim();break;case"listening":this.cloudAnim({rotateSpeed:.01,breathing:!1});break;case"thinking":this.cloudAnim({rotateSpeed:.2,breathing:!1});break;case"talking":this.animMap.idle&&this.scene.beginDirectAnimation(this.pointsMesh,[this.animMap.talking],0,20,!0)}}cloudAnim(e={breathing:!0,rotateSpeed:.002}){this.animMap.idle&&this.scene.beginDirectAnimation(this.pointsMesh,[this.animMap.idle],0,120,!0);let t=new BABYLON.Color4(1,1,1,1),n=(new BABYLON.Texture("/assets/avatar/particle/textures/flare.png",this.scene),0);this.pointsCloud.updateParticle=o=>{let i=this.currentRole.Mesh.getBoundingInfo()?.boundingSphere?.radiusWorld,a=this.currentRole.Mesh.getBoundingInfo()?.boundingSphere?.centerWorld;o.idx;if(o.color=t,o.rotation.y+=e.rotateSpeed,o&&n<3&&(console.log(this.currentRole.Mesh.getBoundingInfo()),console.log(o),n++),o.initpos||(o.initpos=o.position),e.breathing){let e=o.initpos.subtract(a);o.position=new BABYLON.Vector3(e.x*i,e.y*i,e.z*i).add(this.currentRole.offsetPosition)}return o}}createSphere(){let e=BABYLON.MeshBuilder.CreateSphere("sphere",{diameter:2},this.scene);e.visibility=1,e.material=new BABYLON.StandardMaterial("mat",this.scene),e.material.wireframe=!0,e.scaling=new BABYLON.Vector3(1,1,1),this.pointsMesh=e;let t=new BABYLON.Animation("breathingAnimation","scaling",30,BABYLON.Animation.ANIMATIONTYPE_VECTOR3,BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE),n=[];n.push({frame:0,value:new BABYLON.Vector3(.3,.3,.3)}),n.push({frame:60,value:new BABYLON.Vector3(.5,.5,.5)}),n.push({frame:120,value:new BABYLON.Vector3(.3,.3,.3)}),t.setKeys(n),this.animMap.idle=t;let o=[{frame:0,value:BABYLON.Vector3.One()},{frame:10,value:new BABYLON.Vector3(1.2,.8,1.2)},{frame:20,value:BABYLON.Vector3.One()}],i=new BABYLON.Animation("talkAnimation","scaling",30,BABYLON.Animation.ANIMATIONTYPE_VECTOR3,BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);return i.setKeys(o),this.animMap.talk=i,this.scene.beginDirectAnimation(e,[this.animMap.idle],0,120,!0),e}async createParticle(){let e=this.createSphere(),t=new BABYLON.ParticleSystem("particles",2e3,this.scene);t.particleTexture=new BABYLON.Texture("/assets/avatar/particle/textures/flare.png",this.scene),t.emitter=e,t.minEmitBox=new BABYLON.Vector3(0,0,0),t.maxEmitBox=new BABYLON.Vector3(0,0,0),t.color1=new BABYLON.Color4(.7,.8,1,1),t.color2=new BABYLON.Color4(.2,.5,1,1),t.colorDead=new BABYLON.Color4(0,0,.2,0),t.minSize=.5,t.maxSize=.5,t.minLifeTime=.1,t.maxLifeTime=.1,t.minAngularSpeed=0,t.maxAngularSpeed=Math.PI,t.minInitialRotation=0,t.maxInitialRotation=Math.PI,t.minEmitPower=0,t.maxEmitPower=0,t.emitRate=1500,t.updateSpeed=.01,t.blendMode=BABYLON.ParticleSystem.BLENDMODE_ONEONE,t.direction1=new BABYLON.Vector3(0,0,0),t.direction2=new BABYLON.Vector3(0,0,0),t.start();let n=t.createSphereEmitter();n.radius=2,n.radiusRange=0,n.directionRandomizer=0,t.gravity=new BABYLON.Vector3(0,0,0),t.disposeOnStop=!0,t.updateFunction=n=>{for(let o=0;o<n.length;o++){let i=n[o],a=e.getBoundingInfo()?.boundingSphere?.radiusWorld;i.position=i.position.normalize().scale(a),i.age+=this.scene.getEngine().getDeltaTime()/1e3,i.age>=i.lifeTime&&(t.recycleParticle(i),o--)}},this.engine.runRenderLoop((()=>{this.scene.render(),t.worldOffset=e.position}))}setCameraToMeshCenter(e,t){t.computeWorldMatrix(!0);let n=t.getBoundingInfo(),o=n.minimum,i=n.maximum,a=i.x-o.x,r=i.y-o.y,s=i.z-o.z,l=n.boundingBox.center;console.log("宽度:"+a),console.log("高度:"+r),console.log("深度:"+s),console.log("中心点:"+l)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarParticleComponent,deps:[{token:i0.ElementRef}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompAvatarParticleComponent,isStandalone:!0,selector:"fm-avatar-role-particle",viewQueries:[{propertyName:"renderCanvas",first:!0,predicate:["renderCanvas"],descendants:!0}],ngImport:i0,template:'<canvas #renderCanvas class="render-canvas"></canvas>',styles:[".render-canvas{display:block;width:100%;height:100%;touch-action:none}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"ngmodule",type:FormsModule}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarParticleComponent,decorators:[{type:Component,args:[{selector:"fm-avatar-role-particle",standalone:!0,imports:[CommonModule,FormsModule],template:'<canvas #renderCanvas class="render-canvas"></canvas>',styles:[".render-canvas{display:block;width:100%;height:100%;touch-action:none}\n"]}]}],ctorParameters:()=>[{type:i0.ElementRef}],propDecorators:{renderCanvas:[{type:ViewChild,args:["renderCanvas"]}]}});class CompAvatarRoleImageComponent{constructor(){this.animClass="waiting",this.imageMap={}}playWave(){!this.wave&&Recorder.WaveView&&(this.wave=Recorder.WaveView({elem:".record-wave-avatar",keep:!1}));let e=function generatePowerLevel(){return 100*Math.random()}();this.waveInterval=setInterval((()=>{let t=function generateSampleRate(){const e=[44100,48e3,88200,96e3];return e[Math.floor(Math.random()*e.length)]}(),n=function generatePcmData(e){const t=[];for(let n=0;n<e;n++)t.push(Math.floor(65536*Math.random())-32768);return t}(1e3);this.wave.input(n,e,t)}),40)}stopWave(){clearInterval(this.waveInterval)}ngAfterViewInit(){}ngOnInit(){setTimeout((()=>{this.imageMap=this.fmodeChat.avatarConfig?.image,this.avatarImage.nativeElement.src=this.imageMap?.waiting,this.fmodeChat.playAnimation=this.playAnimation}),1500)}playAnimation(){let e=this;return t=>{let n=e.avatarImage.nativeElement;switch(e.animClass=t,e.stopWave(),t){case"thinking":case"waiting":n.style.animationPlayState="running";break;case"talking":n.style.animationPlayState="running",e.playWave();break;case"listening":n.style.animationPlayState="pause";break;default:n.style.animationPlayState="paused"}}}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarRoleImageComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompAvatarRoleImageComponent,isStandalone:!0,selector:"fm-avatar-role-image",inputs:{fmodeChat:"fmodeChat",role:"role"},viewQueries:[{propertyName:"avatarImage",first:!0,predicate:["avatarImage"],descendants:!0}],ngImport:i0,template:'<div class="page">\n <div class="avatar" [class]="animClass">\n <div class="avatar-photo">\n <img #avatarImage alt="">\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave-avatar">\n </div>\n </div>\n </div>\n</div>',styles:[".page{position:relative;width:100vw;height:100%;top:0;left:0;display:flex;justify-content:center;align-items:center;background-color:#000}.avatar{width:100%;display:flex;justify-content:center;align-items:center}.avatar .avatar-photo{position:relative;margin-top:-10vh;width:80%}.avatar .avatar-photo img{border-radius:10px}.avatar .record-wave-avatar{height:50px;width:100%;position:absolute;float:left;left:0;bottom:0}.thinking,.listening,.waiting,.talking{animation-duration:2s;animation-play-state:running;animation-iteration-count:infinite;animation-timing-function:ease-in-out}@keyframes waitingAnimation{0%{transform:scale(1)}50%{transform:scale(1.05)}to{transform:scale(1)}}@keyframes thinkingAnimation{0%{transform:rotate(0)}30%{transform:rotate(10deg)}60%{transform:rotate(-10deg)}to{transform:rotate(0)}}.thinking{animation-name:thinkingAnimation}.waiting{animation-name:waitingAnimation}.listening{animation-name:listeningAnimation}.talking{animation-name:talkingAnimation}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"ngmodule",type:FormsModule}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarRoleImageComponent,decorators:[{type:Component,args:[{selector:"fm-avatar-role-image",standalone:!0,imports:[CommonModule,FormsModule],template:'<div class="page">\n <div class="avatar" [class]="animClass">\n <div class="avatar-photo">\n <img #avatarImage alt="">\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave-avatar">\n </div>\n </div>\n </div>\n</div>',styles:[".page{position:relative;width:100vw;height:100%;top:0;left:0;display:flex;justify-content:center;align-items:center;background-color:#000}.avatar{width:100%;display:flex;justify-content:center;align-items:center}.avatar .avatar-photo{position:relative;margin-top:-10vh;width:80%}.avatar .avatar-photo img{border-radius:10px}.avatar .record-wave-avatar{height:50px;width:100%;position:absolute;float:left;left:0;bottom:0}.thinking,.listening,.waiting,.talking{animation-duration:2s;animation-play-state:running;animation-iteration-count:infinite;animation-timing-function:ease-in-out}@keyframes waitingAnimation{0%{transform:scale(1)}50%{transform:scale(1.05)}to{transform:scale(1)}}@keyframes thinkingAnimation{0%{transform:rotate(0)}30%{transform:rotate(10deg)}60%{transform:rotate(-10deg)}to{transform:rotate(0)}}.thinking{animation-name:thinkingAnimation}.waiting{animation-name:waitingAnimation}.listening{animation-name:listeningAnimation}.talking{animation-name:talkingAnimation}\n"]}]}],propDecorators:{avatarImage:[{type:ViewChild,args:["avatarImage"]}],fmodeChat:[{type:Input}],role:[{type:Input}]}});class ModalChatVoiceInputComponent{constructor(e,t,n,o,i,a){this.platform=e,this.router=t,this.voiceServ=n,this.toastCtrl=o,this.ncloud=i,this.chatServ=a,this.talkMode="click",this.talkTips="点击话筒开始讲话",this.errorText="",this.player=new Audio}ngOnInit(){"press"==this.talkMode&&(this.talkTips="轻触底部开始讲话"),setTimeout((()=>{this.initVoiceSevice(),this.initVoiceASR()}),500)}async initVoiceASR(){this.voiceServ.requestPermission().then((()=>{this.voiceServ.openWithPriviledge(),this.startASRAwake()}))}async startASRAwake(){await this.voiceServ.openWithPriviledge(),new this.voiceServ.webSpeech(this.platform).startRecognition("Nihao | Hello")}playMusic(e){this.player.src=`/assets/avatar/voice/${e}.mp3`,this.player.play()}initVoiceSevice(){this.fmodeChat.userInput=this.voiceServ.resultText,this.voiceServ.requestPermission().then((()=>{this.voiceServ.openWithPriviledge()})),this.voiceServ.onBeforeStartTalk=()=>{this.fmodeChat.playAnimation("listening"),this.playMusic("start-talk")},this.voiceServ.onBeforeCancelTalk=()=>{this.playMusic("interupt-talk"),this.fmodeChat.playAnimation("waiting")},this.voiceServ.onAfterCancelTalk=()=>{this.startASRAwake()},this.voiceServ.onBeforeFinishTalk=()=>{this.fmodeChat.playAnimation("thinking"),this.playMusic("stop-talk")},this.voiceServ.onAfterFinishTalk=()=>{console.log("onAfterFinishTalk"),this.fmodeChat.userInput=this.voiceServ?.resultText,this.sendMessage(),this.startASRAwake()}}async sendMessage(){if(!this.fmodeChat.userInput){return this.errorText="内容不能为空",void(await this.toastCtrl.create({message:this.errorText,position:"top",icon:"alert",color:"warning-circle",duration:1e3})).present()}this.fmodeChat?.sendMessage(this.voiceServ.resultText,null,(e=>{}),{onSSMLComplete:e=>{console.log(e)}}),this.fmodeChat.userInput="",this.fmodeChat.userImage=""}testTTS(e){console.log(e),e=e||"你好呀,我是飞马小智!很高兴为您介绍脑控科技的发展历程。我们成立于2019年",new this.voiceServ.webSpeech(this.platform).speak(e)}testXunfeiTTS(){}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalChatVoiceInputComponent,deps:[{token:i3.Platform},{token:i1$1.Router},{token:FmodeVoiceService},{token:i3.ToastController},{token:NovaCloudService},{token:ChatService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ModalChatVoiceInputComponent,isStandalone:!0,selector:"fm-modal-chat-voice-input",inputs:{fmodeChat:"fmodeChat",talkMode:"talkMode"},providers:[FmodeVoiceService],ngImport:i0,template:' \n <ng-container *ngIf="fmodeChat">\n\n \x3c!-- 用户输入 提示区域 --\x3e\n <div class="user-asr-input" style="text-align: center;" *ngIf="!fmodeChat?.userInput && voiceServ.btnStatus!=\'OPEN\'">{{talkTips}}</div>\n <div class="user-asr-input">{{fmodeChat?.userInput}}</div>\n \n \x3c!-- 测试按钮 --\x3e\n <div class="test-button-group" *ngIf="false">\n <button class="button-record" (click)="voiceServ.toggleRecord()">开始录制 {{voiceServ.connStatus}} {{voiceServ.btnStatus}}</button>\n <br>\n <button class="button-record" (click)="voiceServ.playRecord()">播放录制结果</button>\n <br>\n <button class="button-record" (click)="voiceServ.playBuffers()">播放Buffers结果</button>\n <button (click)="testTTS()">测试TTS纯WEB</button>\n <button (click)="startASR()">测试ASR</button> \n <button (click)="testXunfeiTTS()">测试合成</button> \n </div>\n\n \n \n \x3c!-- 交互按钮 --\x3e\n <ion-fab slot="fixed" horizontal="center" vertical="bottom">\n <ng-container *ngIf="talkMode==\'click\'">\n \x3c!-- 默认按钮:开始讲话 --\x3e\n <ion-fab-button color="primary" closeIcon="checkmark" (click)="voiceServ.toggleRecord()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n\n \x3c!-- 讲话中:取消发送 --\x3e\n <ion-fab-list side="end">\n <ion-fab-button [class]="\'loading\'" (click)="voiceServ.cancelTalk()">\n <ion-icon name="pause-outline"></ion-icon>\n </ion-fab-button>\n </ion-fab-list>\n </ng-container>\n \n <ng-container *ngIf="talkMode==\'press\'">\n <ion-fab-button color="primary" closeIcon="mic-outline" (touchstart)="voiceServ.toggleRecord()" (touchend)="voiceServ.cancelTalk()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n </ng-container>\n </ion-fab>\n\n\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave">\n </div>\n</ng-container>\n',styles:['ion-fab{margin-bottom:10vh}.fab-button-close-active:before{content:"";position:absolute;top:-5px;left:-5px;width:66px;height:66px;border-radius:50%;border:5px solid #fff;border-top-color:transparent;animation:spin 2s ease-in-out infinite;animation-fill-mode:both;animation-play-state:running}.record-wave{position:fixed;bottom:0;width:100vw;height:6vh}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:IonicModule},{kind:"component",type:i3.IonFab,selector:"ion-fab",inputs:["activated","edge","horizontal","vertical"]},{kind:"component",type:i3.IonFabButton,selector:"ion-fab-button",inputs:["activated","closeIcon","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","show","size","target","translucent","type"]},{kind:"component",type:i3.IonFabList,selector:"ion-fab-list",inputs:["activated","side"]},{kind:"component",type:i3.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"ngmodule",type:RouterModule}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalChatVoiceInputComponent,decorators:[{type:Component,args:[{selector:"fm-modal-chat-voice-input",standalone:!0,imports:[CommonModule,IonicModule,RouterModule],providers:[FmodeVoiceService],template:' \n <ng-container *ngIf="fmodeChat">\n\n \x3c!-- 用户输入 提示区域 --\x3e\n <div class="user-asr-input" style="text-align: center;" *ngIf="!fmodeChat?.userInput && voiceServ.btnStatus!=\'OPEN\'">{{talkTips}}</div>\n <div class="user-asr-input">{{fmodeChat?.userInput}}</div>\n \n \x3c!-- 测试按钮 --\x3e\n <div class="test-button-group" *ngIf="false">\n <button class="button-record" (click)="voiceServ.toggleRecord()">开始录制 {{voiceServ.connStatus}} {{voiceServ.btnStatus}}</button>\n <br>\n <button class="button-record" (click)="voiceServ.playRecord()">播放录制结果</button>\n <br>\n <button class="button-record" (click)="voiceServ.playBuffers()">播放Buffers结果</button>\n <button (click)="testTTS()">测试TTS纯WEB</button>\n <button (click)="startASR()">测试ASR</button> \n <button (click)="testXunfeiTTS()">测试合成</button> \n </div>\n\n \n \n \x3c!-- 交互按钮 --\x3e\n <ion-fab slot="fixed" horizontal="center" vertical="bottom">\n <ng-container *ngIf="talkMode==\'click\'">\n \x3c!-- 默认按钮:开始讲话 --\x3e\n <ion-fab-button color="primary" closeIcon="checkmark" (click)="voiceServ.toggleRecord()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n\n \x3c!-- 讲话中:取消发送 --\x3e\n <ion-fab-list side="end">\n <ion-fab-button [class]="\'loading\'" (click)="voiceServ.cancelTalk()">\n <ion-icon name="pause-outline"></ion-icon>\n </ion-fab-button>\n </ion-fab-list>\n </ng-container>\n \n <ng-container *ngIf="talkMode==\'press\'">\n <ion-fab-button color="primary" closeIcon="mic-outline" (touchstart)="voiceServ.toggleRecord()" (touchend)="voiceServ.cancelTalk()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n </ng-container>\n </ion-fab>\n\n\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave">\n </div>\n</ng-container>\n',styles:['ion-fab{margin-bottom:10vh}.fab-button-close-active:before{content:"";position:absolute;top:-5px;left:-5px;width:66px;height:66px;border-radius:50%;border:5px solid #fff;border-top-color:transparent;animation:spin 2s ease-in-out infinite;animation-fill-mode:both;animation-play-state:running}.record-wave{position:fixed;bottom:0;width:100vw;height:6vh}\n']}]}],ctorParameters:()=>[{type:i3.Platform},{type:i1$1.Router},{type:FmodeVoiceService},{type:i3.ToastController},{type:NovaCloudService},{type:ChatService}],propDecorators:{fmodeChat:[{type:Input}],talkMode:[{type:Input}]}});class CompAvatarTalkComponent{constructor(e,t,n,o,i,a,r){this.voiceServ=e,this.platform=t,this.router=n,this.navCtrl=o,this.route=i,this.chatServ=a,this.ncloud=r,this.route.paramMap.subscribe((e=>{this.roleId=e.get("roleId"),this.loadAvatarRole(this.roleId)})),document.body.classList.add("dark")}ngOnInit(){}ngOnDestroy(){document.body.classList.remove("dark"),this.voiceServ.resultText=null,this.fmodeChat&&(this.fmodeChat.latestAIResponse=null)}goBack(){document.body.classList.remove("dark");let e=this.avatarRole?.get("backUrl");try{if(e)return void this.navCtrl.navigateRoot(e);this.navCtrl.navigateRoot("/chat/pro/role/"+this.roleId)}catch(e){this.navCtrl.navigateRoot("/chat/pro/role/"+this.roleId)}}async loadAvatarRole(e){let t=new Parse.Query("AvatarRole");this.avatarRole=await t.get(e);let n=await this.chatServ.createNewRoleChat(this.roleId);n.isTalkMode=!0,this.fmodeChat=n,this.fmodeChat.showAvatar()}ngAfterViewInit(){this.listenDivChange()}listenDivChange(){new MutationObserver((()=>{this.scrollToBottom(this.aiRespComp)})).observe(this.aiRespComp.nativeElement,{childList:!0,subtree:!0,attributes:!0})}scrollToBottom(e){e?.nativeElement?.scrollHeight&&(e.nativeElement.scrollTop=e.nativeElement.scrollHeight)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarTalkComponent,deps:[{token:FmodeVoiceService},{token:i3.Platform},{token:i1$1.Router},{token:i3.NavController},{token:i1$1.ActivatedRoute},{token:ChatService},{token:NovaCloudService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompAvatarTalkComponent,isStandalone:!0,selector:"app-comp-avatar-talk",providers:[FmodeVoiceService,NovaCloudService,ChatService,Diagnostic,ModalController],viewQueries:[{propertyName:"avatarComp",first:!0,predicate:["avatar"],descendants:!0},{propertyName:"aiRespComp",first:!0,predicate:["aiRespComp"],descendants:!0}],ngImport:i0,template:'<ion-menu #menu contentId="main-content" side="end">\n <ion-header>\n <ion-toolbar>\n <ion-title>资料</ion-title>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n\n <ion-card style="margin: 0px;">\n <img [src]="avatarRole?.get(\'thumb\')" alt="">\n <ion-card-header>\n <ion-card-subtitle>{{avatarRole?.get(\'tags\')}}</ion-card-subtitle>\n <ion-card-title>{{avatarRole?.get("name")}}</ion-card-title>\n </ion-card-header>\n \n <ion-card-content>\n {{avatarRole?.get("desc")}}\n\n <ion-list [inset]="true" style="margin:0px;">\n \x3c!-- <ion-item>\n <ion-avatar *ngIf="avatarRole?.get(\'thumb\')" aria-hidden="true" slot="start">\n <img [src]="avatarRole?.get(\'thumb\')" />\n </ion-avatar>\n <ion-label>{{avatarRole?.get("name")}}</ion-label>\n </ion-item> --\x3e\n <ion-item lines="none" *ngIf="avatarRole?.get(\'age\')">\n <ion-note slot="start">年龄</ion-note>\n <ion-label>{{avatarRole?.get("age")}}</ion-label>\n </ion-item>\n <ion-item lines="none" *ngIf="avatarRole?.get(\'gender\')">\n <ion-note slot="start">性别</ion-note>\n <ion-label>{{avatarRole?.get("gender")}}</ion-label>\n </ion-item>\n <ion-item lines="none">\n <ion-note slot="start">称号</ion-note>\n <ion-label>{{avatarRole?.get("title")}}</ion-label>\n </ion-item>\n \n <ion-item lines="none">\n <ion-note slot="start">擅长</ion-note>\n <ion-label>{{avatarRole?.get("tags")?.join(\',\')}}</ion-label>\n </ion-item>\n\n </ion-list>\n </ion-card-content>\n </ion-card>\n \n \n \n </ion-content>\n</ion-menu>\n\n<div class="ion-page" id="main-content">\n <ion-header class="ion-no-border">\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="goBack()"> <ion-icon name="chevron-back-outline"></ion-icon> </ion-button>\n </ion-buttons>\n <ion-title>\n <ion-chip *ngIf="avatarRole?.get(\'title\')">{{avatarRole?.get("title")}}</ion-chip>\n </ion-title>\n <ion-buttons slot="end">\n \x3c!-- <ion-button (click)="playTTSTeting()">TTS测试</ion-button> --\x3e\n {{avatarRole?.get("name")}}\n <ion-button (click)="menu.toggle()"> <ion-icon name="ellipsis-horizontal-outline"></ion-icon> </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n\n \x3c!-- <ion-segment value="voice">\n <ion-segment-button (click)="chatServ.createChatPanel(avatarRole)" value="chat">\n <ion-label>聊天</ion-label>\n </ion-segment-button>\n <ion-segment-button routerLink="{{\'/avatar/role/\'+avatarRole?.id}}" value="voice">\n <ion-label>语音</ion-label>\n </ion-segment-button>\n </ion-segment> --\x3e\n\n \x3c!-- 数字形象:动画效果 --\x3e\n <fm-avatar-role-image *ngIf="avatarRole&&fmodeChat" [fmodeChat]="fmodeChat" [role]="avatarRole" #avatar class="avatar"></fm-avatar-role-image>\n \x3c!-- <fm-avatar-role-particle #avatar class="avatar"></fm-avatar-role-particle> --\x3e\n\n \x3c!-- AI回复的最新消息 --\x3e\n <div class="ai-resp-input" #aiRespComp>{{fmodeChat?.latestAIResponse | hidexml}}</div>\n\n <fm-modal-chat-voice-input *ngIf="fmodeChat" [fmodeChat]="fmodeChat"></fm-modal-chat-voice-input>\n\n</div>\n\n',styles:["ion-menu ion-note{color:#ccc;font-weight:700}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.avatar{display:block;width:100%;height:100%}.ai-resp-input{font-size:1rem;color:#fff;position:fixed;top:60px;max-height:15vh;overflow-y:scroll;padding:0 10px}.user-asr-input{font-size:1rem;color:#fff;position:fixed;bottom:6vh;padding:0 10px}.test-button-group{color:#00f;position:fixed;bottom:20vh}.test-button-group button{padding:10px;margin:10px}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:RouterModule},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:IonicModule},{kind:"component",type:i3.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:i3.IonButtons,selector:"ion-buttons",inputs:["collapse"]},{kind:"component",type:i3.IonCard,selector:"ion-card",inputs:["button","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonCardContent,selector:"ion-card-content",inputs:["mode"]},{kind:"component",type:i3.IonCardHeader,selector:"ion-card-header",inputs:["color","mode","translucent"]},{kind:"component",type:i3.IonCardSubtitle,selector:"ion-card-subtitle",inputs:["color","mode"]},{kind:"component",type:i3.IonCardTitle,selector:"ion-card-title",inputs:["color","mode"]},{kind:"component",type:i3.IonChip,selector:"ion-chip",inputs:["color","disabled","mode","outline"]},{kind:"component",type:i3.IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:i3.IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:i3.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:i3.IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:i3.IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:i3.IonMenu,selector:"ion-menu",inputs:["contentId","disabled","maxEdgeStart","menuId","side","swipeGesture","type"]},{kind:"component",type:i3.IonNote,selector:"ion-note",inputs:["color","mode"]},{kind:"component",type:i3.IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"component",type:i3.IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"component",type:CompAvatarRoleImageComponent,selector:"fm-avatar-role-image",inputs:["fmodeChat","role"]},{kind:"component",type:ModalChatVoiceInputComponent,selector:"fm-modal-chat-voice-input",inputs:["fmodeChat","talkMode"]},{kind:"pipe",type:HidexmlPipe,name:"hidexml"}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarTalkComponent,decorators:[{type:Component,args:[{selector:"app-comp-avatar-talk",standalone:!0,imports:[CommonModule,RouterModule,FormsModule,IonicModule,CompAvatarParticleComponent,CompAvatarRoleImageComponent,ModalChatVoiceInputComponent,HidexmlPipe],providers:[FmodeVoiceService,NovaCloudService,ChatService,Diagnostic,ModalController],template:'<ion-menu #menu contentId="main-content" side="end">\n <ion-header>\n <ion-toolbar>\n <ion-title>资料</ion-title>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n\n <ion-card style="margin: 0px;">\n <img [src]="avatarRole?.get(\'thumb\')" alt="">\n <ion-card-header>\n <ion-card-subtitle>{{avatarRole?.get(\'tags\')}}</ion-card-subtitle>\n <ion-card-title>{{avatarRole?.get("name")}}</ion-card-title>\n </ion-card-header>\n \n <ion-card-content>\n {{avatarRole?.get("desc")}}\n\n <ion-list [inset]="true" style="margin:0px;">\n \x3c!-- <ion-item>\n <ion-avatar *ngIf="avatarRole?.get(\'thumb\')" aria-hidden="true" slot="start">\n <img [src]="avatarRole?.get(\'thumb\')" />\n </ion-avatar>\n <ion-label>{{avatarRole?.get("name")}}</ion-label>\n </ion-item> --\x3e\n <ion-item lines="none" *ngIf="avatarRole?.get(\'age\')">\n <ion-note slot="start">年龄</ion-note>\n <ion-label>{{avatarRole?.get("age")}}</ion-label>\n </ion-item>\n <ion-item lines="none" *ngIf="avatarRole?.get(\'gender\')">\n <ion-note slot="start">性别</ion-note>\n <ion-label>{{avatarRole?.get("gender")}}</ion-label>\n </ion-item>\n <ion-item lines="none">\n <ion-note slot="start">称号</ion-note>\n <ion-label>{{avatarRole?.get("title")}}</ion-label>\n </ion-item>\n \n <ion-item lines="none">\n <ion-note slot="start">擅长</ion-note>\n <ion-label>{{avatarRole?.get("tags")?.join(\',\')}}</ion-label>\n </ion-item>\n\n </ion-list>\n </ion-card-content>\n </ion-card>\n \n \n \n </ion-content>\n</ion-menu>\n\n<div class="ion-page" id="main-content">\n <ion-header class="ion-no-border">\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="goBack()"> <ion-icon name="chevron-back-outline"></ion-icon> </ion-button>\n </ion-buttons>\n <ion-title>\n <ion-chip *ngIf="avatarRole?.get(\'title\')">{{avatarRole?.get("title")}}</ion-chip>\n </ion-title>\n <ion-buttons slot="end">\n \x3c!-- <ion-button (click)="playTTSTeting()">TTS测试</ion-button> --\x3e\n {{avatarRole?.get("name")}}\n <ion-button (click)="menu.toggle()"> <ion-icon name="ellipsis-horizontal-outline"></ion-icon> </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n\n \x3c!-- <ion-segment value="voice">\n <ion-segment-button (click)="chatServ.createChatPanel(avatarRole)" value="chat">\n <ion-label>聊天</ion-label>\n </ion-segment-button>\n <ion-segment-button routerLink="{{\'/avatar/role/\'+avatarRole?.id}}" value="voice">\n <ion-label>语音</ion-label>\n </ion-segment-button>\n </ion-segment> --\x3e\n\n \x3c!-- 数字形象:动画效果 --\x3e\n <fm-avatar-role-image *ngIf="avatarRole&&fmodeChat" [fmodeChat]="fmodeChat" [role]="avatarRole" #avatar class="avatar"></fm-avatar-role-image>\n \x3c!-- <fm-avatar-role-particle #avatar class="avatar"></fm-avatar-role-particle> --\x3e\n\n \x3c!-- AI回复的最新消息 --\x3e\n <div class="ai-resp-input" #aiRespComp>{{fmodeChat?.latestAIResponse | hidexml}}</div>\n\n <fm-modal-chat-voice-input *ngIf="fmodeChat" [fmodeChat]="fmodeChat"></fm-modal-chat-voice-input>\n\n</div>\n\n',styles:["ion-menu ion-note{color:#ccc;font-weight:700}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.avatar{display:block;width:100%;height:100%}.ai-resp-input{font-size:1rem;color:#fff;position:fixed;top:60px;max-height:15vh;overflow-y:scroll;padding:0 10px}.user-asr-input{font-size:1rem;color:#fff;position:fixed;bottom:6vh;padding:0 10px}.test-button-group{color:#00f;position:fixed;bottom:20vh}.test-button-group button{padding:10px;margin:10px}\n"]}]}],ctorParameters:()=>[{type:FmodeVoiceService},{type:i3.Platform},{type:i1$1.Router},{type:i3.NavController},{type:i1$1.ActivatedRoute},{type:ChatService},{type:NovaCloudService}],propDecorators:{avatarComp:[{type:ViewChild,args:["avatar"]}],aiRespComp:[{type:ViewChild,args:["aiRespComp"]}]}});const AvatarRoutes=[{path:"role/:roleId",component:CompAvatarTalkComponent,runGuardsAndResolvers:"always"}];class AvatarModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AvatarModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:AvatarModule,imports:[CommonModule,FormsModule,HttpClientModule,ReactiveFormsModule,i1$1.RouterModule,CompAvatarTalkComponent],exports:[CompAvatarTalkComponent]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AvatarModule,imports:[CommonModule,FormsModule,HttpClientModule,ReactiveFormsModule,RouterModule.forChild(AvatarRoutes),CompAvatarTalkComponent]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AvatarModule,decorators:[{type:NgModule,args:[{declarations:[],imports:[CommonModule,FormsModule,HttpClientModule,ReactiveFormsModule,RouterModule.forChild(AvatarRoutes),CompAvatarTalkComponent],exports:[CompAvatarTalkComponent]}]}]});class FmVideoComponent{constructor(){this.url="",this.video=document.createElement("video"),this.canvasStyle={},this.video.crossOrigin="anonymous"}ngOnChanges(e){e.url&&e.url.currentValue&&this.play(this.url)}play(e){try{this.video.muted=!0,this.video.loop=!0,this.video.controls=!1,this.video.src=e,this.video.playsInline=!0,this.video.load(),this.video.play().then((()=>{})).catch((()=>{setTimeout((()=>{this.play(e)}),200)}))}catch(t){return void setTimeout((()=>{this.play(e)}),500)}this.ctx||(this.ctx=this.canvasRef.nativeElement.getContext("2d"),this.video.addEventListener("loadeddata",(()=>{this.canvasRef.nativeElement.width=this.video.videoWidth,this.canvasRef.nativeElement.height=this.video.videoHeight,this.drawFrame()})))}drawFrame(){this.video.paused||this.video.ended||(this.ctx.drawImage(this.video,0,0,this.canvasRef.nativeElement.width,this.canvasRef.nativeElement.height),requestAnimationFrame((()=>this.drawFrame())))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmVideoComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmVideoComponent,isStandalone:!0,selector:"fm-video",inputs:{url:"url",canvasStyle:"canvasStyle"},viewQueries:[{propertyName:"canvasRef",first:!0,predicate:["videoCanvas"],descendants:!0,static:!0}],usesOnChanges:!0,ngImport:i0,template:'<canvas #videoCanvas [style]="canvasStyle"></canvas>',styles:[":host{display:flex;justify-content:center;align-items:center;overflow:hidden}canvas{max-height:100%;width:auto;height:auto;background:transparent}\n"],dependencies:[{kind:"ngmodule",type:CommonModule}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmVideoComponent,decorators:[{type:Component,args:[{selector:"fm-video",standalone:!0,imports:[CommonModule],template:'<canvas #videoCanvas [style]="canvasStyle"></canvas>',styles:[":host{display:flex;justify-content:center;align-items:center;overflow:hidden}canvas{max-height:100%;width:auto;height:auto;background:transparent}\n"]}]}],ctorParameters:()=>[],propDecorators:{url:[{type:Input}],canvasRef:[{type:ViewChild,args:["videoCanvas",{static:!0}]}],canvasStyle:[{type:Input}]}});class CompAvatarRoleVideoComponent{constructor(e){this.navCtrl=e,this.animClass="waiting",this.onClose=new EventEmitter,this.videoMap={}}close(){this.onClose.emit(!0),this.fmodeChat.isAvatarShow=!1}goBack(){this.navCtrl.back()}playWave(){!this.wave&&Recorder.WaveView&&(this.wave=Recorder.WaveView({elem:".record-wave-avatar",keep:!1}));let e=function generatePowerLevel(){return 100*Math.random()}();this.waveInterval=setInterval((()=>{let t=function generateSampleRate(){const e=[44100,48e3,88200,96e3];return e[Math.floor(Math.random()*e.length)]}(),n=function generatePcmData(e){const t=[];for(let n=0;n<e;n++)t.push(Math.floor(65536*Math.random())-32768);return t}(1e3);this.wave.input(n,e,t)}),40)}stopWave(){clearInterval(this.waveInterval)}ngAfterViewInit(){}ngOnInit(){setTimeout((()=>{this.videoMap=this.fmodeChat.avatarConfig?.video,this.playVideo(this.videoMap?.waiting),this.fmodeChat.playAnimation=this.playAnimation}),1500)}playAnimation(){let e=this;return t=>{e.animClass=t,e.stopWave(),e.playVideo(e.videoMap[t])}}playVideo(e){this.avatarVideo.play(e)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarRoleVideoComponent,deps:[{token:i2$2.NavController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompAvatarRoleVideoComponent,isStandalone:!0,selector:"fm-avatar-role-video",inputs:{fmodeChat:"fmodeChat",role:"role"},outputs:{onClose:"onClose"},viewQueries:[{propertyName:"avatarVideo",first:!0,predicate:FmVideoComponent,descendants:!0}],ngImport:i0,template:'<div class="page">\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="goBack()">\n <ion-icon name="chevron-back-outline"></ion-icon>\n </ion-button>\n </ion-buttons>\n <ion-buttons slot="end">\n <ion-button (click)="close()"> <ion-icon name="chevron-collapse-outline"></ion-icon> </ion-button>\n </ion-buttons>\n </ion-toolbar>\n <div class="avatar" [class]="animClass">\n <div class="avatar-photo">\n <fm-video #avatarVideo alt=""></fm-video>\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave-avatar">\n </div>\n </div>\n </div>\n</div>',styles:["ion-toolbar{position:fixed;top:0;left:0;width:100vw;--background:transparent}.page{position:relative;width:100vw;height:100%;top:0;left:0;display:flex;justify-content:center;align-items:center;background-color:#000}.avatar{height:100%;width:100%;display:flex;justify-content:center;align-items:center}.avatar .avatar-photo{position:relative;display:flex;justify-content:center;width:80%;max-height:100%}.avatar .avatar-photo fm-video{border-radius:50%;max-height:100%;max-width:100%}.avatar .record-wave-avatar{height:50px;width:100%;position:absolute;float:left;left:0;bottom:0}.thinking,.listening,.waiting,.talking{animation-duration:2s;animation-play-state:running;animation-iteration-count:infinite;animation-timing-function:ease-in-out}@keyframes waitingAnimation{0%{transform:scale(1)}50%{transform:scale(1.05)}to{transform:scale(1)}}@keyframes thinkingAnimation{0%{transform:rotate(0)}30%{transform:rotate(10deg)}60%{transform:rotate(-10deg)}to{transform:rotate(0)}}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"ngmodule",type:FormsModule},{kind:"component",type:FmVideoComponent,selector:"fm-video",inputs:["url","canvasStyle"]},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"component",type:IonButtons,selector:"ion-buttons",inputs:["collapse"]},{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"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarRoleVideoComponent,decorators:[{type:Component,args:[{selector:"fm-avatar-role-video",standalone:!0,imports:[CommonModule,FormsModule,FmVideoComponent,IonIcon,IonToolbar,IonButtons,IonButton],template:'<div class="page">\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="goBack()">\n <ion-icon name="chevron-back-outline"></ion-icon>\n </ion-button>\n </ion-buttons>\n <ion-buttons slot="end">\n <ion-button (click)="close()"> <ion-icon name="chevron-collapse-outline"></ion-icon> </ion-button>\n </ion-buttons>\n </ion-toolbar>\n <div class="avatar" [class]="animClass">\n <div class="avatar-photo">\n <fm-video #avatarVideo alt=""></fm-video>\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave-avatar">\n </div>\n </div>\n </div>\n</div>',styles:["ion-toolbar{position:fixed;top:0;left:0;width:100vw;--background:transparent}.page{position:relative;width:100vw;height:100%;top:0;left:0;display:flex;justify-content:center;align-items:center;background-color:#000}.avatar{height:100%;width:100%;display:flex;justify-content:center;align-items:center}.avatar .avatar-photo{position:relative;display:flex;justify-content:center;width:80%;max-height:100%}.avatar .avatar-photo fm-video{border-radius:50%;max-height:100%;max-width:100%}.avatar .record-wave-avatar{height:50px;width:100%;position:absolute;float:left;left:0;bottom:0}.thinking,.listening,.waiting,.talking{animation-duration:2s;animation-play-state:running;animation-iteration-count:infinite;animation-timing-function:ease-in-out}@keyframes waitingAnimation{0%{transform:scale(1)}50%{transform:scale(1.05)}to{transform:scale(1)}}@keyframes thinkingAnimation{0%{transform:rotate(0)}30%{transform:rotate(10deg)}60%{transform:rotate(-10deg)}to{transform:rotate(0)}}\n"]}]}],ctorParameters:()=>[{type:i2$2.NavController}],propDecorators:{avatarVideo:[{type:ViewChild,args:[FmVideoComponent]}],fmodeChat:[{type:Input}],role:[{type:Input}],onClose:[{type:Output}]}});class AgentPrompt{constructor(){}jsonCompletion(e,t){let n,o=new FmodeChatCompletion([{role:"user",content:e}]);return o.model=t||"fmode-4.0-cn-256k",o.sendCompletion({isDirect:!0,onComplete:e=>{console.log("finalMessage",e);e?.content;e.complete=!0}}).pipe(finalize((()=>{let e;try{n.json=this.extractAndParseJson(e)}catch(e){}n.complete=!0})))}extractAndParseJson(e){let t=e.indexOf("{");if(-1===t)return{};let n=0,o=t;for(let i=t;i<e.length;i++)if("{"===e[i]?n++:"}"===e[i]&&n--,0===n){o=i;break}if(0!==n)return{};const i=e.slice(t,o+1);try{return JSON.parse(i)}catch(e){return console.error("Failed to parse JSON:",e),{}}}extractMarkdownToMultiArray(e){let t=e.split("\n"),n=[],o=n,i=[n];for(let e of t){if(!e.trim())continue;if(e.startsWith("#")){let t=e.replace(/^#+\s*/,"");o.push([t]);continue}let t=e.search(/\S/)/2,n=e.trim().replace(/^-+\s*/,"");for(;t<i.length-1;)i.pop();for(;t>i.length-1;){let e=[];i[i.length-1].push(e),i.push(e)}o=i[i.length-1],o.push(n)}return n}async getFormatTpl(e,t){let n=await this.getPromptTpl(e);return await n.format(t)}async getPromptTpl(e){let t=new Parse__default.Query("PromptTemplate");t.equalTo("code",e);let n=await t.first();return PromptTemplate.fromTemplate(n?.get("template"),{templateFormat:"mustache"})}getTokens(e){return e=e||"",2*e?.length}}class AgentStory{constructor(e,t,n){this.Story=Parse__default.Object.extend("Story"),this.Document=Parse__default.Object.extend("Document"),this.docsList=[],this.story?.id||(this.story=e),this.story?.id||e?.id||(this.story=new this.Story),t?.id&&this.story?.set("person",t?.toPointer()),n?.id&&this.story?.set("book",n),this.story?.get("user")?.id||this.story?.set("user",Parse__default.User.current()?.toPointer())}async setAttachment(e){let t=new Parse__default.Query("Attachment"),n=await t.get(e?.id);return this.story?.set("attach",n),this.story?.set("type","document"),this.story=await(this.story?.save()),this.story?.set("attach",n),n}async loadSlipt(e){let t=await fetch("https://server.fmode.cn/api/aiagent/indexes/loader",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:e?.get("url"),md5:e?.get("md5")})}),n=await t.json(),o=n?.data;return console.log(o),console.log(o?.split),o?.split?.length&&(this.docsList=o?.split?.map((e=>{let t=e,n=new this.Document;return n.set({pageContent:t.pageContent,metadata:t.metadata}),n}))),this.docsList}}class AgentTaskStep{restart(){this.parentIndex&&this.parentComp?.startTask&&this.parentComp?.startTask(this.parentIndex),this.limitStart=!1}get progress(){return this._progress||this._simProgress}set progress(e){this._progress=e}constructor(e){this.shareData={},this.data={},this.buttons=[],this.restartButtonShow=!1,this.limitStart=!1,this.cancelAll=!1,this.progressHidden=!1,this._simProgress=0,this._progress=0,this.message="",this.error="",this.logList=[],this.title=e?.title,this.shareData=e?.shareData,this.progressHidden=e?.progressHidden||!1,this.handle=e?.handle}simulatorProgress(){return this.progressSub$?.unsubscribe(),this.restartButtonShow=!1,new Promise((e=>{let t=function progressHandlerIncreasingSpeed(e,t){return interval(t/(e-1)).pipe(take(e),map((e=>e+1)),concatMap((e=>{const t=100*Math.exp(e/30);return of(e).pipe(delay(t))})))}(80,1e4);this.progressSub$=t.subscribe({next:e=>{this.progress=e},complete:()=>{this.progressSub$?.unsubscribe(),e(!0)}})}))}}class TipsController{constructor(e){this.duration=5,this.container=null,this.currentIndex=0,this.intervalId=null,this.position="top",this.isVisible=!1,this.tipsList=e?.tipsList.length>0?e?.tipsList:this.getDefaultTips(),e?.random&&(this.tipsList=this.tipsList.sort((()=>Math.random()-.5))),this.position=e.position||"top"}getDefaultTips(){return["请耐心等待,精彩内容即将呈现...","生活就像一盒巧克力,你永远不知道下一颗是什么味道。","山重水复疑无路,柳暗花明又一村。","好的开始是成功的一半。","时间是最好的老师,但遗憾的是,它杀死了所有的学生。","不积跬步,无以至千里;不积小流,无以成江海。","代码如诗,简洁为美。"]}addTip(e){this.tipsList.push(e)}setTips(e){this.tipsList=e.length>0?e:this.getDefaultTips()}present(){if(this.isVisible)return;this.container=document.createElement("div"),this.container.id="tips-container",Object.assign(this.container.style,{position:"fixed",[this.position]:"20vh",left:"50%",transform:"translateX(-50%)",zIndex:"9999",backgroundColor:"rgba(255, 255, 255, 0.9)",color:"#333",padding:"12px 24px",borderRadius:"8px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.15)",maxWidth:"92vw",minWidth:"92vw",textAlign:"center",fontSize:"16px",lineHeight:"1.5",transition:"opacity 0.3s ease",border:"1px solid rgba(0, 0, 0, 0.1)",backdropFilter:"blur(4px)",animation:"fadeIn 0.5s ease"});const e=document.createElement("div");e.id="tip-content",e.textContent=this.tipsList[this.currentIndex],Object.assign(e.style,{margin:"0",whiteSpace:"pre-wrap",wordBreak:"break-word"});const t=document.createElement("div");t.id="tip-progress",Object.assign(t.style,{height:"3px",backgroundColor:"rgba(0, 150, 255, 0.5)",width:"100%",borderRadius:"3px",marginTop:"10px",overflow:"hidden"});const n=document.createElement("div");Object.assign(n.style,{height:"100%",width:"100%",backgroundColor:"#0096ff",animation:`progress ${this.duration}s linear forwards`}),t.appendChild(n),this.container.appendChild(e),this.container.appendChild(t),document.body.appendChild(this.container),this.addAnimationStyles(),this.startRotation(),this.isVisible=!0}dismiss(){this.isVisible&&this.container&&(this.container.style.opacity="0",setTimeout((()=>{this.container&&this.container.parentNode&&(document.body.removeChild(this.container),this.container=null),this.stopRotation(),this.isVisible=!1}),300))}startRotation(){this.stopRotation(),this.intervalId=window.setInterval((()=>{this.nextTip()}),1e3*this.duration)}stopRotation(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=null)}nextTip(){if(!this.container)return;this.currentIndex=(this.currentIndex+1)%this.tipsList.length;let e=this.container.querySelector("#tip-content"),t=this.container.querySelector("#tip-progress > div");e&&(e.style.opacity="0",setTimeout((()=>{e.textContent=this.tipsList[this.currentIndex],t&&(t.style.animation="none",t.offsetWidth,t.style.animation=`progress ${this.duration}s linear forwards`),e.style.opacity="1"}),50))}addAnimationStyles(){const e=document.createElement("style");e.textContent="\n @keyframes fadeIn {\n from { opacity: 0; transform: translateX(-50%) translateY(-10px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n }\n @keyframes progress {\n from { width: 100%; }\n to { width: 0%; }\n }\n ",document.head.appendChild(e)}}class FmAgentTaskComponent{constructor(e,t){this.dialogRef=e,this.data=t,this.enabledClose=!1,this.currentStepIndex=0,this.hasError=!1,console.log(this.data?.stepsList)}ngOnInit(){this.startTask()}async startTask(e){if(e&&(this.currentStepIndex=e),this.data.stepsList){for(;this.currentStepIndex<this.data.stepsList?.length;this.currentStepIndex++){let e=this.data.stepsList?.[this.currentStepIndex];if(console.log("this.currentStepIndex",this.currentStepIndex),e?.simulatorProgress(),e.parentComp=this,e.parentIndex=Number(this.currentStepIndex.toFixed(0)),e?.limitStart)break;if(e?.handle){let t=await(e?.handle());if(e.cancelAll){this.dialogRef.close();break}if(0==t)break;e.error||(e.progressSub$?.unsubscribe(),e.progress=1,this.stepper?.next())}}let e=!1;this.data?.stepsList.forEach(((t,n)=>{t?.error&&(e=!0,this.hasError=!0)})),e||(this.enabledClose=!0)}}onNoClick(){this.dialogRef.close()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmAgentTaskComponent,deps:[{token:i1$3.MatDialogRef},{token:MAT_DIALOG_DATA}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmAgentTaskComponent,isStandalone:!0,selector:"fm-agent-task",viewQueries:[{propertyName:"stepper",first:!0,predicate:MatStepper,descendants:!0}],ngImport:i0,template:'\n<h2 mat-dialog-title *ngIf="!enabledClose">AI生成中</h2>\n<h2 mat-dialog-title *ngIf="enabledClose">任务已完成</h2>\n<mat-dialog-content>\n \n <mat-stepper #stepper orientation="vertical">\n <mat-step *ngFor="let step of data?.stepsList; let index=index;">\n <ng-template matStepLabel>{{step?.title}}</ng-template>\n <ng-template matStepContent>\n <p *ngIf="step?.message">{{step?.message}}</p>\n <p *ngFor="let log of step?.logList">{{log}}</p>\n <button *ngIf="step?.error" mat-button color="warn">{{step?.error}}</button>\n <mat-progress-bar *ngIf="step?.progress!=1&&!step?.limitStart" [color]="step?.error?\'warn\':\'primary\'"\n [mode]="(step?.progress || 1)>=100?\'indeterminate\':\'buffer\'" [value]="step?.progress" [bufferValue]="(step?.progress || 0) + 10"></mat-progress-bar>\n\n\n\n \x3c!-- 自定义按钮区域 --\x3e\n <ng-container *ngFor="let button of step?.buttons">\n <button *ngIf="button.isShow&&button.isShow()" mat-raised-button [color]="button?.color||\'primary\'" (click)="button?.handle()">{{button?.name}}</button>\n </ng-container>\n\n <button mat-button color="warn" *ngIf="step?.restartButtonShow" (click)="startTask(index)">重试</button>\n \x3c!-- 非首项:上一步 --\x3e\n <button mat-button matStepperPrevious *ngIf="index!=0">上一步</button>\n \x3c!-- 非末项:下一步 --\x3e\n <button mat-button matStepperNext *ngIf="(index+1!=data?.stepsList?.length)&&!step?.error">下一步</button>\n </ng-template>\n </mat-step>\n\n </mat-stepper>\n \n \n</mat-dialog-content>\n<mat-dialog-actions [align]="\'end\'" style="display: flex;justify-content: center;">\n \x3c!-- <button mat-button (click)="onNoClick()">No Thanks</button> --\x3e\n <button style="font-size: 20px;" *ngIf="hasError" mat-button color="warn" [mat-dialog-close]="false" cdkFocusInitial>取消</button>\n <button style="font-size: 20px;" *ngIf="enabledClose" mat-button color="primary" [mat-dialog-close]="true" cdkFocusInitial>完成</button>\n</mat-dialog-actions>\n\n',styles:["h2{text-align:center;background-color:#6e23ce}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2$1.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:MatDialogModule},{kind:"directive",type:i1$3.MatDialogClose,selector:"[mat-dialog-close], [matDialogClose]",inputs:["aria-label","type","mat-dialog-close","matDialogClose"],exportAs:["matDialogClose"]},{kind:"directive",type:i1$3.MatDialogTitle,selector:"[mat-dialog-title], [matDialogTitle]",inputs:["id"],exportAs:["matDialogTitle"]},{kind:"directive",type:i1$3.MatDialogActions,selector:"[mat-dialog-actions], mat-dialog-actions, [matDialogActions]",inputs:["align"]},{kind:"directive",type:i1$3.MatDialogContent,selector:"[mat-dialog-content], mat-dialog-content, [matDialogContent]"},{kind:"ngmodule",type:MatFormFieldModule},{kind:"ngmodule",type:MatInputModule},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$1.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"ngmodule",type:MatStepperModule},{kind:"component",type:i4.MatStep,selector:"mat-step",inputs:["color"],exportAs:["matStep"]},{kind:"directive",type:i4.MatStepLabel,selector:"[matStepLabel]"},{kind:"component",type:i4.MatStepper,selector:"mat-stepper, mat-vertical-stepper, mat-horizontal-stepper, [matStepper]",inputs:["disableRipple","color","labelPosition","headerPosition","animationDuration"],outputs:["animationDone"],exportAs:["matStepper","matVerticalStepper","matHorizontalStepper"]},{kind:"directive",type:i4.MatStepperNext,selector:"button[matStepperNext]"},{kind:"directive",type:i4.MatStepperPrevious,selector:"button[matStepperPrevious]"},{kind:"directive",type:i4.MatStepContent,selector:"ng-template[matStepContent]"},{kind:"ngmodule",type:MatProgressBarModule},{kind:"component",type:i5.MatProgressBar,selector:"mat-progress-bar",inputs:["color","value","bufferValue","mode"],outputs:["animationEnd"],exportAs:["matProgressBar"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmAgentTaskComponent,decorators:[{type:Component,args:[{selector:"fm-agent-task",standalone:!0,imports:[CommonModule,FormsModule,MatDialogModule,MatFormFieldModule,MatInputModule,MatButtonModule,MatStepperModule,MatProgressBarModule],template:'\n<h2 mat-dialog-title *ngIf="!enabledClose">AI生成中</h2>\n<h2 mat-dialog-title *ngIf="enabledClose">任务已完成</h2>\n<mat-dialog-content>\n \n <mat-stepper #stepper orientation="vertical">\n <mat-step *ngFor="let step of data?.stepsList; let index=index;">\n <ng-template matStepLabel>{{step?.title}}</ng-template>\n <ng-template matStepContent>\n <p *ngIf="step?.message">{{step?.message}}</p>\n <p *ngFor="let log of step?.logList">{{log}}</p>\n <button *ngIf="step?.error" mat-button color="warn">{{step?.error}}</button>\n <mat-progress-bar *ngIf="step?.progress!=1&&!step?.limitStart" [color]="step?.error?\'warn\':\'primary\'"\n [mode]="(step?.progress || 1)>=100?\'indeterminate\':\'buffer\'" [value]="step?.progress" [bufferValue]="(step?.progress || 0) + 10"></mat-progress-bar>\n\n\n\n \x3c!-- 自定义按钮区域 --\x3e\n <ng-container *ngFor="let button of step?.buttons">\n <button *ngIf="button.isShow&&button.isShow()" mat-raised-button [color]="button?.color||\'primary\'" (click)="button?.handle()">{{button?.name}}</button>\n </ng-container>\n\n <button mat-button color="warn" *ngIf="step?.restartButtonShow" (click)="startTask(index)">重试</button>\n \x3c!-- 非首项:上一步 --\x3e\n <button mat-button matStepperPrevious *ngIf="index!=0">上一步</button>\n \x3c!-- 非末项:下一步 --\x3e\n <button mat-button matStepperNext *ngIf="(index+1!=data?.stepsList?.length)&&!step?.error">下一步</button>\n </ng-template>\n </mat-step>\n\n </mat-stepper>\n \n \n</mat-dialog-content>\n<mat-dialog-actions [align]="\'end\'" style="display: flex;justify-content: center;">\n \x3c!-- <button mat-button (click)="onNoClick()">No Thanks</button> --\x3e\n <button style="font-size: 20px;" *ngIf="hasError" mat-button color="warn" [mat-dialog-close]="false" cdkFocusInitial>取消</button>\n <button style="font-size: 20px;" *ngIf="enabledClose" mat-button color="primary" [mat-dialog-close]="true" cdkFocusInitial>完成</button>\n</mat-dialog-actions>\n\n',styles:["h2{text-align:center;background-color:#6e23ce}\n"]}]}],ctorParameters:()=>[{type:i1$3.MatDialogRef},{type:void 0,decorators:[{type:Inject,args:[MAT_DIALOG_DATA]}]}],propDecorators:{stepper:[{type:ViewChild,args:[MatStepper]}]}}),addIcons({chevronBackOutline:chevronBackOutline,ellipsisHorizontalOutline:ellipsisHorizontalOutline});class FmChatHeaderArea{constructor(e){this.navCtrl=e,this.isModalOpen=!1,this.goBack=()=>{this.navCtrl.back()}}async back(){if(this.chat?.onClose){if(!await(this.chat?.onClose(this.chat)))return}this.goBack()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatHeaderArea,deps:[{token:i2$2.NavController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmChatHeaderArea,isStandalone:!0,selector:"fm-chat-header-area",inputs:{chat:"chat",goBack:"goBack"},ngImport:i0,template:'<ion-toolbar *ngIf="chat?.isAvatarShow==false">\n <ion-buttons slot="start">\n <ion-button (click)="back()">\n <ion-icon name="chevron-back-outline"></ion-icon>\n </ion-button>\n </ion-buttons>\n <ion-title>\n <div class="title-avatar-area">\n <div class="avatar-img" (click)="chat.showAvatar()">\n <img *ngIf="chat?.role?.get(\'avatar\')||chat?.role?.get(\'thumb\')" [src]="chat?.role?.get(\'avatar\')||chat?.role?.get(\'thumb\')" />\n <ion-icon *ngIf="chat?.role?.get(\'avatarConfig\')" name="resize-outline"></ion-icon>\n </div>\n <span (click)="chat.showAvatar()">\n {{chat?.role?.get("name")}}\n </span>\n </div>\n </ion-title>\n\n <ion-buttons slot="end">\n <ion-button (click)="isModalOpen=true"> <ion-icon name="ellipsis-horizontal-outline"></ion-icon> </ion-button>\n </ion-buttons>\n</ion-toolbar>\n\n<div class="avatar-area" *ngIf="chat?.isAvatarShow==true">\n <fm-avatar-role-image *ngIf="chat?.avatarMode==\'image\'" [fmodeChat]="chat" [role]="avatarRole"></fm-avatar-role-image>\n <fm-avatar-role-video *ngIf="chat?.avatarMode==\'video\'" [fmodeChat]="chat" [role]="avatarRole"></fm-avatar-role-video>\n</div>\n\n\n<ion-modal [isOpen]="isModalOpen" (willDismiss)="isModalOpen=false">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="isModalOpen=false">返回</ion-button>\n </ion-buttons>\n <ion-title>简介</ion-title>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n\n <ion-card style="margin: 0px;">\n <img [src]="chat?.role?.get(\'thumb\')" alt="">\n <ion-card-header>\n <ion-card-subtitle>{{chat?.role?.get(\'tags\')}}</ion-card-subtitle>\n <ion-card-title>{{chat?.role?.get("name")}}</ion-card-title>\n </ion-card-header>\n \n <ion-card-content>\n {{chat?.role?.get("desc")}}\n \n <ion-list [inset]="true" style="margin:0px;">\n \x3c!-- <ion-item>\n <ion-avatar *ngIf="chat?.role?.get(\'thumb\')" aria-hidden="true" slot="start">\n <img [src]="chat?.role?.get(\'thumb\')" />\n </ion-avatar>\n <ion-label>{{chat?.role?.get("name")}}</ion-label>\n </ion-item> --\x3e\n <ion-item lines="none" *ngIf="chat?.role?.get(\'age\')">\n <ion-note slot="start">年龄</ion-note>\n <ion-label>{{chat?.role?.get("age")}}</ion-label>\n </ion-item>\n <ion-item lines="none" *ngIf="chat?.role?.get(\'gender\')">\n <ion-note slot="start">性别</ion-note>\n <ion-label>{{chat?.role?.get("gender")}}</ion-label>\n </ion-item>\n <ion-item lines="none">\n <ion-note slot="start">称号</ion-note>\n <ion-label>{{chat?.role?.get("title")}}</ion-label>\n </ion-item>\n \n <ion-item lines="none">\n <ion-note slot="start">擅长</ion-note>\n <ion-label>{{chat?.role?.get("tags")?.join(\',\')}}</ion-label>\n </ion-item>\n \n </ion-list>\n </ion-card-content>\n </ion-card>\n </ion-content>\n </ng-template>\n </ion-modal>',styles:[".title-avatar-area{width:100%;height:100%;display:flex;justify-content:center;align-items:center}.title-avatar-area .avatar-img img{width:32px;height:32px;border-radius:50%;margin-right:5px}.title-avatar-area .avatar-img ion-icon{background:#df76dfcc;border-radius:50%;padding:3px;position:absolute;color:#000;margin-left:-20px;font-size:10px;margin-top:18px}.avatar-area{height:100%}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"component",type:IonButtons,selector:"ion-buttons",inputs:["collapse"]},{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:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonModal,selector:"ion-modal"},{kind:"component",type:IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"component",type:IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:IonList,selector:"ion-list",inputs:["inset","lines","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:IonCard,selector:"ion-card",inputs:["button","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:IonNote,selector:"ion-note",inputs:["color","mode"]},{kind:"component",type:CompAvatarRoleImageComponent,selector:"fm-avatar-role-image",inputs:["fmodeChat","role"]},{kind:"component",type:CompAvatarRoleVideoComponent,selector:"fm-avatar-role-video",inputs:["fmodeChat","role"],outputs:["onClose"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatHeaderArea,decorators:[{type:Component,args:[{selector:"fm-chat-header-area",standalone:!0,imports:[CommonModule,IonToolbar,IonButtons,IonButton,IonIcon,IonModal,IonAvatar,IonTitle,IonHeader,IonList,IonItem,IonCard,IonLabel,IonNote,CompAvatarRoleImageComponent,CompAvatarRoleVideoComponent],template:'<ion-toolbar *ngIf="chat?.isAvatarShow==false">\n <ion-buttons slot="start">\n <ion-button (click)="back()">\n <ion-icon name="chevron-back-outline"></ion-icon>\n </ion-button>\n </ion-buttons>\n <ion-title>\n <div class="title-avatar-area">\n <div class="avatar-img" (click)="chat.showAvatar()">\n <img *ngIf="chat?.role?.get(\'avatar\')||chat?.role?.get(\'thumb\')" [src]="chat?.role?.get(\'avatar\')||chat?.role?.get(\'thumb\')" />\n <ion-icon *ngIf="chat?.role?.get(\'avatarConfig\')" name="resize-outline"></ion-icon>\n </div>\n <span (click)="chat.showAvatar()">\n {{chat?.role?.get("name")}}\n </span>\n </div>\n </ion-title>\n\n <ion-buttons slot="end">\n <ion-button (click)="isModalOpen=true"> <ion-icon name="ellipsis-horizontal-outline"></ion-icon> </ion-button>\n </ion-buttons>\n</ion-toolbar>\n\n<div class="avatar-area" *ngIf="chat?.isAvatarShow==true">\n <fm-avatar-role-image *ngIf="chat?.avatarMode==\'image\'" [fmodeChat]="chat" [role]="avatarRole"></fm-avatar-role-image>\n <fm-avatar-role-video *ngIf="chat?.avatarMode==\'video\'" [fmodeChat]="chat" [role]="avatarRole"></fm-avatar-role-video>\n</div>\n\n\n<ion-modal [isOpen]="isModalOpen" (willDismiss)="isModalOpen=false">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="isModalOpen=false">返回</ion-button>\n </ion-buttons>\n <ion-title>简介</ion-title>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n\n <ion-card style="margin: 0px;">\n <img [src]="chat?.role?.get(\'thumb\')" alt="">\n <ion-card-header>\n <ion-card-subtitle>{{chat?.role?.get(\'tags\')}}</ion-card-subtitle>\n <ion-card-title>{{chat?.role?.get("name")}}</ion-card-title>\n </ion-card-header>\n \n <ion-card-content>\n {{chat?.role?.get("desc")}}\n \n <ion-list [inset]="true" style="margin:0px;">\n \x3c!-- <ion-item>\n <ion-avatar *ngIf="chat?.role?.get(\'thumb\')" aria-hidden="true" slot="start">\n <img [src]="chat?.role?.get(\'thumb\')" />\n </ion-avatar>\n <ion-label>{{chat?.role?.get("name")}}</ion-label>\n </ion-item> --\x3e\n <ion-item lines="none" *ngIf="chat?.role?.get(\'age\')">\n <ion-note slot="start">年龄</ion-note>\n <ion-label>{{chat?.role?.get("age")}}</ion-label>\n </ion-item>\n <ion-item lines="none" *ngIf="chat?.role?.get(\'gender\')">\n <ion-note slot="start">性别</ion-note>\n <ion-label>{{chat?.role?.get("gender")}}</ion-label>\n </ion-item>\n <ion-item lines="none">\n <ion-note slot="start">称号</ion-note>\n <ion-label>{{chat?.role?.get("title")}}</ion-label>\n </ion-item>\n \n <ion-item lines="none">\n <ion-note slot="start">擅长</ion-note>\n <ion-label>{{chat?.role?.get("tags")?.join(\',\')}}</ion-label>\n </ion-item>\n \n </ion-list>\n </ion-card-content>\n </ion-card>\n </ion-content>\n </ng-template>\n </ion-modal>',styles:[".title-avatar-area{width:100%;height:100%;display:flex;justify-content:center;align-items:center}.title-avatar-area .avatar-img img{width:32px;height:32px;border-radius:50%;margin-right:5px}.title-avatar-area .avatar-img ion-icon{background:#df76dfcc;border-radius:50%;padding:3px;position:absolute;color:#000;margin-left:-20px;font-size:10px;margin-top:18px}.avatar-area{height:100%}\n"]}]}],ctorParameters:()=>[{type:i2$2.NavController}],propDecorators:{chat:[{type:Input}],goBack:[{type:Input}]}}),Parse__default.applicationId||(Parse__default.initialize("ncloudmaster"),Parse__default.serverURL=(Parse__default.serverURL?.split("parse")?.[0]||"https://server.fmode.cn/")+"parse");class AuthService{isGuardLock(e){let t=!0,n=Parse__default.User.current();return t=!n?.id&&this.guardMap[e],t}get loginTypeCount(){return Object.values(this.loginOptions)?.filter((e=>e))?.length}get logoUrl(){return localStorage.getItem("LOGO_URL")||this._logoUrl||"https://file.yuban.co/img/logo-feima.png"}set logoUrl(e){localStorage.setItem("LOGO_URL",e),this._logoUrl=this._logoUrl}getCompanyId(){let e=localStorage.getItem("company");return e=this.company||e,e}constructor(e,t,n,o){this.router=e,this.toastCtrl=t,this.novaCloud=n,this.http=o,this.guardMap={},this.modalType="fullscreen",this.isModalShow=!1,this.showBackHome=!0,this.activeButton="账号密码",this.loginOptions={userpwd:!0,mobilepwd:!0,mobilecode:!0,wechat:!0},this._logoUrl="https://file.yuban.co/img/logo-feima.png",this.wechatUrl="https://app.fmode.cn/logo/z0qr.jpg",this.isLoggedIn=!1,this.message={success:e=>{this.toast({color:"success",message:e})},create:(e,t)=>{"error"==e&&(e="danger"),this.toast({color:e,message:t})},info:e=>{this.toast({message:e})},error:e=>{this.toast({color:"danger",message:e})}},this.LoginPage="/pcuser/login",this.mobileUserMap={},this.enabledLocalCode=!1}async toast(e){e.position=e?.position||"top",e.duration=e?.duration||1500,e.color=e?.color||"primary",(await this.toastCtrl.create(e)).present()}init(e){this.company=e.company,this.guardType=e.guardType,this.modalType=e.modalType||this.modalType,this.saveParamsInvite()}checkLoginLock(){let e=Parse__default.User.current();return!!e?.id||(this.isModalShow=!0,this.isLoggedIn=!1,!1)}async checkLogin(e){await this.checkAndLoginWithToken(),this.guardMap[e]=!0;let t=Parse__default.User.current();return console.log("currentUser",t),t&&t.id?(this.setAccount(t),this.isLoggedIn=!0,!0):this.guardType&&"page"!=this.guardType?"modal"==this.guardType?(this.isModalShow=!0,this.isLoggedIn=!1,!0):void 0:(this.redirectUrl=e,this.router.navigate([this.LoginPage]),!1)}async checkAndLoginWithToken(){console.log("checkAndLoginWithToken");const e=new URLSearchParams(window.location.search),t=e.get("token");if(t){e.delete("token");let n=window.location.pathname+(e.toString()?"?"+e.toString():"")+window.location.hash;n=decodeURIComponent(n),console.log("newUrl",n),window.history.replaceState({},"",n),setTimeout((()=>{window.history.replaceState({},"",n)}),1e3);let o=Parse__default.User.current();if(!o?.id)try{o=await Parse__default.User.become(t)}catch(e){}}}async setAccount(e){if(this.account?.id)return;let t=Parse__default.Object.extend("Account"),n=e?.get("company")||{__type:"Pointer",className:"Company",objectId:this.getCompanyId()}||null,o=new Parse__default.Query("Account");o.equalTo("user",e.toPointer());let i=await o.first();return i?.id||(i=new t,i.set({user:e.toPointer(),company:n}),i=await i.save()),this.account=i,i}login(e,t){return new Promise(((n,o)=>{Parse__default.User.logIn(e,t).then((async e=>{if(this.bindInvite(e),this.setCurrentUserLocalStorage(e),"modal"==this.guardType)return await this.refreshPage(),void n(!0);let t=new Parse__default.Query("Company");t.select("rootPage"),t.equalTo("objectId",e?.get("company")?.id);let o=await t.first(),i=o?.get("rootPage");this.redirectUrl=this.redirectUrl||i||"/project/dashboard";let a=this.redirectUrl;a=decodeURIComponent(a),this.router.navigate([a])})).catch((e=>{console.error(e),o({message:"无此用户信息,请先在小程序登录"})}))}))}refreshPage(){return new Promise((e=>{let t=this.router.url;Parse__default.User.current()?.id&&(this.isModalShow=!1),this.router.navigateByUrl("/",{skipLocationChange:!0}).then((()=>{this.router.navigateByUrl(t).then((()=>{e(!0)}))}))}))}setCurrentUserLocalStorage(e){e.get("company")?.id&&localStorage.setItem("company",e.get("company")?.id)}logout(e,t){let n=localStorage.getItem("company"),o=localStorage.getItem("WECHAT_APP_ID"),i=localStorage.getItem("LOGO_URL"),a=localStorage.getItem("NOVA_APIG_SERVER");localStorage.clear(),localStorage.setItem("company",n),localStorage.setItem("WECHAT_APP_ID",o),localStorage.setItem("LOGO_URL",i),localStorage.setItem("NOVA_APIG_SERVER",a),Parse__default.User.logOut().then((e=>{})),this.router.navigate([t||"/pcuser/login"])}async loginMobilePassword(e,t,n){let o=await this.getMobileUser(e);o?this.login(o,t).then((async e=>{this.isModalShow=!1})).catch((e=>{console.log(e),n.create("error","错误的用户名或密码")})):n.create("error","用户不存在,请尝试其他登录方式")}signMobilePassword(e,t){return new Promise((async(n,o)=>{n(await this.signUpAndUpdate(e,t))}))}async getMobileUser(e){let t=this.getCompanyId(),n=t+e;if(this.mobileUserMap[n])return this.mobileUserMap[n];let o=await this.novaCloud.api("/auth/getusername",{company:t,mobile:e});return o?.username&&(this.mobileUserMap[n]=o?.username),this.mobileUserMap[n]}signUpAndUpdate(e,t){return t=t||e+"pwd666",new Promise((n=>{Parse__default.User.signUp(this.getCompanyId()+"-"+e,t,"").then((async t=>{t.id&&(console.log(t),t.set("company",{__type:"Pointer",className:"Company",objectId:this.getCompanyId()}),t.set("mobile",e),t.set("type","user"),this.bindInvite(t),t=await t.save(),n(t))})).catch((e=>{n(void 0)}))}))}async getMobileCodeToken(e,t){return new Promise(((n,o)=>{let i=Parse__default.serverURL?.split("parse")?.[0]||"https://server.fmode.cn/";this.http.get(i+`api/auth/mobile?company=${this.company}&mobile=${e}&code=${t}`).toPromise().then((e=>{n(e)})).catch((e=>{o(e)}))}))}async loginCode(e,t,n,o){if(t)try{let n=await this.getMobileCodeToken(e,t);if(200==n?.code){console.log(200,n);let e=await Parse__default.User.become(n.data.token);if(console.log(e,e?.id),e?.id){console.log(e,e?.id);try{await this.bindInvite(e)}catch(e){console.error("bind err b",e)}return!0}}}catch(n){if(console.log("error1",n),!(n?.error?.mess?.indexOf("用户不存在")>-1))return void this.toast({message:n?.error?.mess});{let n=await this.signUpAndUpdate(e);if(n?.id)return await this.loginCode(e,t)}}else this.toast({color:"primary",message:"请填写有效验证码"})}saveParamsInvite(){let e=this.novaCloud.searchParse();console.log("saveParamsInvite",e);let t=e?.get("invite");console.log(t),t&&localStorage.setItem("invite",t)}async bindInvite(e){if(!(e=e||Parse__default.User.current()))return;if(e?.get("invite")?.id)return;let t,n=localStorage.getItem("invite");if(n&&e?.id!=n)try{t=await this.novaCloud.api("/auth/invite",{current:e?.id,invite:n,type:"code"}),console.log("bind",t)}catch(e){console.error("bind err",e)}}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthService,deps:[{token:i1$1.Router},{token:i2$2.ToastController},{token:NovaCloudService},{token:i1.HttpClient}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1$1.Router},{type:i2$2.ToastController},{type:NovaCloudService},{type:i1.HttpClient}]});class AccountService{constructor(e,t,n){this.ncloud=e,this.authServ=t,this.http=n,this.company="",this.billing={credit:{usedDetail:{}}},this.wxAppId="",this.wxpayEnabled=!1,this.appid=localStorage.getItem("WECHAT_APP_ID")||"wxb4193c93ae9aa696",this.company=this.authServ.company||localStorage.getItem("company"),this.getBilling(),this.getProfile(),this.getUserOpenid()}async getProfile(){let e=Parse__default.User.current()?.id;if(!e)return;let t=new Parse__default.Query("Profile");t.equalTo("user",e),t.equalTo("company",this.company),t.notEqualTo("isDeleted",!0);let n=await t.first();n?.id&&(this.profile=n)}async getBilling(){let e;if(Parse__default.User.current()?.getSessionToken()){try{e=await this.ncloud.apig("aigc/account",null,"get")}catch(e){}return e?.credit&&(this.billing=e),e}}async getUserOpenid(){let e=-1!=navigator.userAgent.toLowerCase().indexOf("micromessenger"),t=this.getQueryStringByName("code"),n=localStorage.getItem("openid");if(!n){if(!Parse__default.User.current())return;let o=Parse__default.User.current().get("wechat");n=o?.[this.appid]?.openid,e&&(t?await this.getwechat(t):this.authWechat())}}authWechat(e="/account/billing"){if(!localStorage.getItem("openid")){let e=window.location.href;return e=encodeURIComponent(e),void(window.location.href="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+this.appid+"&redirect_uri="+e+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect")}}getQueryStringByName(e){let t=location.search.match(new RegExp("[?&]"+e+"=([^&]+)","i"));return null==t||t.length<1?"":t[1]}async getwechat(e,t="/account/billing"){return new Promise((async(n,o)=>{this.http.post("https://server.fmode.cn/api/wechat/get_wx",{company:this.company,code:e}).subscribe((async e=>{if(console.log(e),e&&200==e.code&&e.data.openid){let t=e.data.openid;localStorage.setItem("openid",t),localStorage.removeItem("code");let o={};o[this.appid]={openid:t},Parse__default.User.current().set("wechat",o),await Parse__default.User.current().save(),n(!0)}}),(async e=>{console.log("Error updating items",e),this.authWechat(t),o(!1)}))}))}getWXSignPackageInWechat(){let e={company:this.company,href:encodeURIComponent(location.href.split("?")[0])};this.http.post("https://server.fmode.cn/api/wechat/getconfig",e).subscribe((e=>{const t=e.data;this.wxAppId=t.appid,this.wxpayEnabled=!0,wx.config({debug:!1,appId:t.appid,timestamp:t.timestamp,nonceStr:t.nonceStr,signature:t.signature,jsApiList:["chooseWXPay","onMenuShareTimeline","onMenuShareAppMessage","onMenuShareQQ","onMenuShareQZone","updateAppMessageShareData","updateTimelineShareData"]});let n="https://ai.fmode.cn";location.pathname;Parse__default.User.current()?.id;let o=this.shareInfo||{title:"飞码AI",desc:"解放创意引领未来|国际前沿的AIGC平台",link:n,type:"link",imgUrl:"https://file-cloud.fmode.cn/E4KpGvTEto/20230822/3mkf41033623275.png",success:function(){console.log("分享成功")},error:function(){console.log("分享失败")},cancel:function(){console.log("取消分享")}};wx.ready((()=>{wx.updateAppMessageShareData(o),wx.updateTimelineShareData(o)})),wx.error((()=>{}))}))}async saveAccountLog(e,t,n,o){return new Promise(((i,a)=>{this.http.post("https://test.fmode.cn/api/apig/saveAccountLog",{company:n,uid:Parse__default.User.current().id,orderid:t,info:e}).subscribe((e=>{console.log(e),i(!0)}),(e=>{console.warn(e),o&&o.error("请求超时,请稍后再试"),a()}))}))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AccountService,deps:[{token:NovaCloudService},{token:AuthService},{token:i1.HttpClient}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AccountService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AccountService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:NovaCloudService},{type:AuthService},{type:i1.HttpClient}]}),addIcons({person:person});class CompUserAvatarComponent{constructor(e){this.novaAccount=e,this.type="icon",this.text="U"}ngOnInit(){this.type=this.getType()}ngOnChanges(){this.refresh()}async refresh(){await this.novaAccount.getProfile();let e=this.novaAccount.profile;e?.get("type")&&("student"==e?.get("type")?this.identity="https://file-cloud.fmode.cn/khgbeQmvYZ/20231123/k1k4iq103416124.png":this.identity="https://file-cloud.fmode.cn/E4KpGvTEto/20231116/q12c16094638625.png")}getType(){if(!this.user?.id)return"icon";if(this.user?.get("avatar"))return"avatar";let e=this.user?.get("nickname")||this.user?.get("realname");return e?(this.text=e?.slice(0,1),"text"):"icon"}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompUserAvatarComponent,deps:[{token:AccountService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompUserAvatarComponent,isStandalone:!0,selector:"app-comp-user-avatar",inputs:{user:"user"},usesOnChanges:!0,ngImport:i0,template:'<ng-container *ngIf="user?.id || type == \'icon\'">\n <div class="avatar-com">\n \x3c!-- Default Icon --\x3e\n <ion-avatar *ngIf="type == \'icon\'">\n <ion-icon name="person" color="dark"></ion-icon>\n </ion-avatar>\n \n \x3c!-- Avatar Image --\x3e\n <div class="avatar-com">\n <ion-avatar *ngIf="type == \'avatar\'">\n <img [src]="user?.get(\'avatar\')" />\n </ion-avatar>\n \n \x3c!-- Text Avatar --\x3e\n <ion-avatar *ngIf="type == \'text\'" class="text-avatar">\n {{text}}\n </ion-avatar>\n \n <img\n class="auth-icon"\n *ngIf="identity && type == \'avatar\'"\n [src]="identity"\n alt="已认证"\n />\n </div>\n </div>\n</ng-container>',styles:[".avatar-com{position:relative;width:32px;height:32px}.avatar-com ion-avatar{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background-color:var(--ion-color-light)}.avatar-com ion-avatar.text-avatar{background-color:#0199f9;color:#fff;font-weight:700}.avatar-com ion-avatar ion-icon{font-size:20px;color:#222d3a}.avatar-com .auth-icon{width:20px;height:20px;border-radius:50%;position:absolute;right:-6px;bottom:-2px;border:2px solid white}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:IonAvatar,selector:"ion-avatar"},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompUserAvatarComponent,decorators:[{type:Component,args:[{selector:"app-comp-user-avatar",standalone:!0,imports:[CommonModule,IonAvatar,IonIcon],template:'<ng-container *ngIf="user?.id || type == \'icon\'">\n <div class="avatar-com">\n \x3c!-- Default Icon --\x3e\n <ion-avatar *ngIf="type == \'icon\'">\n <ion-icon name="person" color="dark"></ion-icon>\n </ion-avatar>\n \n \x3c!-- Avatar Image --\x3e\n <div class="avatar-com">\n <ion-avatar *ngIf="type == \'avatar\'">\n <img [src]="user?.get(\'avatar\')" />\n </ion-avatar>\n \n \x3c!-- Text Avatar --\x3e\n <ion-avatar *ngIf="type == \'text\'" class="text-avatar">\n {{text}}\n </ion-avatar>\n \n <img\n class="auth-icon"\n *ngIf="identity && type == \'avatar\'"\n [src]="identity"\n alt="已认证"\n />\n </div>\n </div>\n</ng-container>',styles:[".avatar-com{position:relative;width:32px;height:32px}.avatar-com ion-avatar{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background-color:var(--ion-color-light)}.avatar-com ion-avatar.text-avatar{background-color:#0199f9;color:#fff;font-weight:700}.avatar-com ion-avatar ion-icon{font-size:20px;color:#222d3a}.avatar-com .auth-icon{width:20px;height:20px;border-radius:50%;position:absolute;right:-6px;bottom:-2px;border:2px solid white}\n"]}]}],ctorParameters:()=>[{type:AccountService}],propDecorators:{user:[{type:Input}]}});class DurationStrPipe{transform(e,...t){let n=String(parseInt(String(e/60))),o="";return e/60>1&&(o+=`${n}'`),o+=`${String((e%60).toFixed(0))}"`,o}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DurationStrPipe,deps:[],target:i0.ɵɵFactoryTarget.Pipe})}static{this.ɵpipe=i0.ɵɵngDeclarePipe({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:DurationStrPipe,isStandalone:!0,name:"durationStr"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DurationStrPipe,decorators:[{type:Pipe,args:[{name:"durationStr",standalone:!0}]}]}),addIcons({wifiOutline:wifiOutline,copyOutline:copyOutline});class FmChatMessageCard{constructor(e){this.copyServ=e,this.user=Parse__default.User.current()}async toggleVoicePlay(){if(this.message?.voice?.id&&this.chat.VoiceTTSMap[this.message?.voice?.id]&&(this.tts=this.chat.VoiceTTSMap[this.message?.voice?.id]),this.tts?.isPlaying)return void this.tts?.stop();let e,t=!1;if(this.message?.voice?.id){let t=new Parse__default.Query("ChatVoice");t.include("voiceFile"),e=await t.get(this.message?.voice?.id)}if(!e?.id){let n=await this.chat.getVoiceByContentText(this.message?.content);e=this.chat.voiceMap[n?.id],this.message.voice={id:e?.id,duration:e?.get("duration")},t=!0}this.message?.voice?.duration||(this.message.voice.duration=e?.get("duration"),t=!0),t&&this.saveSession(),await this.chat.playChatVoice(e,{onStart:t=>{e?.id,t?.id},onLoaded:e=>{this.message.voice.duration=1e3*e.duration,this.updateVoiceDuration(1e3*e.duration)},onStop:t=>{e?.id,t?.id}}),this.tts=this.chat.VoiceTTSMap[e?.id]}updateVoiceDuration(e){this.message?.voice?.duration||(this.message.voice.duration=e,this.saveSession())}saveSession(){(this.index>=2||void 0===this.index)&&this.chat?.saveChatSession()}async copy(){this.copyServ.copyToClipboard(getMessageContentText(this.message?.content))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatMessageCard,deps:[{token:ClipboardService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmChatMessageCard,isStandalone:!0,selector:"fm-chat-message-card",inputs:{index:"index",message:"message",role:"role",chat:"chat"},ngImport:i0,template:'<div class="message-card" [class.right]="message?.role==\'user\'" [class.center]="message?.role==\'system\'">\n \x3c!-- 用户及操作区 --\x3e\n <div class="item-row user" *ngIf="message?.role!=\'system\'"> \x3c!-- 系统消息不显示头像 --\x3e\n <div class="avatar-row">\n <div class="actions">\n \x3c!-- 刷新 --\x3e\n \x3c!-- <ion-button fill="outline" slot="start">\n <ion-icon name="refresh-outline"></ion-icon> \n </ion-button> --\x3e\n \x3c!-- 复制 --\x3e\n <ion-button size="small" fill="outline" slot="start" (click)="copy()">\n <ion-icon name="copy-outline"></ion-icon>\n </ion-button>\n \x3c!-- 编辑 --\x3e\n \x3c!-- <ion-button fill="outline" slot="start">\n <ion-icon name="create-outline"></ion-icon>\n </ion-button> --\x3e\n </div>\n \x3c!-- 音频消息区域 --\x3e\n <div *ngIf="((message?.role==\'assistant\' && chat?.role?.get(\'voiceConfig\')?.voice) || (message?.role==\'user\'&&message?.voice))" class="play-voice" (click)="toggleVoicePlay()">\n <div class="voice-button">\n <ion-icon name="wifi-outline"\n [style.transform]="message?.role==\'user\'?\'rotate(-90deg)\':\'rotate(90deg)\'"\n class="audio-icon" [class.play-voice-playing]="tts?.isPlaying"></ion-icon>\n </div>\n <div class="voice-info">\n <span *ngIf="message?.voice?.duration">\n {{((message?.voice?.duration||0)/1000) | durationStr}}\n </span>\n <span *ngIf="!message?.voice?.duration">\n \x3c!-- --\x3e\n </span>\n </div>\n </div>\n \x3c!-- 头像区域 --\x3e \n <img class="avatar" *ngIf="message?.role!=\'user\'" [src]="(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/100/h/100\'" >\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="item-row images" *ngIf="message?.content | chatContent:\'image_url\'">\n <img [src]="message?.content | chatContent:\'image_url\'" alt="">\n </div>\n \x3c!-- 聊天气泡 --\x3e\n <div class="item-row bubble" [style.fontSize]="role?.get(\'uiConfig\')?.message?.bubble?.fontSize || \'0.8rem\'">\n <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content | chatContent" [render]="false"></fm-markdown-preview>\n <fm-markdown-preview *ngIf="message?.complete" [content]="message?.content | chatContent"></fm-markdown-preview>\n </div>\n \x3c!-- 时间显示 --\x3e\n <div class="item-row loading" *ngIf="message?.role!=\'system\' && !message?.complete">\n 正在输入<ion-spinner name="dots"></ion-spinner>\n </div>\n\n <div class="item-row created" *ngIf="message?.createdAt">\n <span>{{message?.createdAt | date:"dd/MM/yy HH:mm"}}</span>\n </div>\n</div>',styles:['@charset "UTF-8";:host-context(body.dark) .message-card .actions .item-native{background:none!important}:host-context(body.dark) .message-card .bubble{color:#0e101d}:host-context(body.dark) .message-card .bubble .content-style{filter:invert(1)!important}:host-context(body.dark) .message-card .bubble fm-markdown-preview{filter:invert(1)!important}:host-context(body.dark) .message-card .play-voice{background-color:#0e101d}:host-context(body.dark) .message-card .play-voice .voice-info{color:#fff}:host-context(body.dark) .message-card .right .bubble{color:#921f8a!important;background:#921f8a!important}:host-context(body.dark) .message-card .right .play-voice{background:#921f8a!important}:host-context(body.dark) .message-card .created span{color:#fff}@media screen and (max-width: 800px){.message-card:focus .actions{opacity:1!important}}.message-card:hover .actions{opacity:1;transition:opacity .3s ease-in-out}.message-card{display:flex;flex-wrap:wrap;justify-content:start;align-items:flex-start}.message-card .avatar-row{width:300px;height:32px;display:flex;flex-direction:row-reverse;justify-content:start;align-items:center}.message-card .actions{display:flex;opacity:0;padding-left:10px;padding-right:10px}.message-card .item-row{display:flex;flex:100%;justify-content:start;margin-bottom:5px}.message-card .images img{max-width:300px}.message-card .bubble{display:flex;justify-content:center;max-width:100%;padding:.5rem .5rem 0rem;color:#333;flex:none;border-radius:0 1.5em 1.5em/0em 1.5em 1.5em;color:#fff;background-color:currentColor}.message-card .bubble .content-style{filter:grayscale(1) contrast(999) invert(1)}.message-card .loading{text-align:right;color:#101010}.message-card .created{display:flex}.message-card .created span{font-size:12px;opacity:.4;white-space:nowrap;transition:all .6s ease;color:var(--black);text-align:center;width:100%;box-sizing:border-box;padding-right:10px;pointer-events:none;z-index:1}.right{justify-content:end;align-items:flex-end}.right .avatar-row{flex-direction:row;justify-content:end;width:auto}.right .actions{position:relative;margin-left:0}.right .item-row{justify-content:end}.right .bubble{color:#bbdefb;border-top-left-radius:1.5em;border-top-right-radius:0}.right .play-voice{flex-direction:row-reverse;background-color:#bbdefb}.center{justify-content:center;align-items:center}.center .item-row{justify-content:center}.center .bubble{color:var(--gray-secondary);border-top-left-radius:1.5em;border-top-right-radius:1.5em;font-size:12px;font-weight:100;padding:5px 20px}.play-voice{min-width:100px;height:32px;display:flex;justify-content:space-around;align-items:center;background-color:#fff;border-radius:7px}.play-voice .voice-button{width:32px;height:32px;display:flex;justify-content:center;align-items:center}.play-voice .voice-button span{overflow:hidden;font-size:18px;color:#ff69b4}.play-voice .voice-info{height:32px;display:flex;padding:0 10px;justify-content:end;align-items:center;color:#333}.avatar{border-radius:50%;width:32px;height:32px;object-fit:cover}.audio-icon{color:#ff69b4;font-size:18px}.play-voice-playing{animation:play-voice-animation 1s infinite}@keyframes play-voice-animation{0%{width:0}to{width:32px}}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"pipe",type:i2$1.DatePipe,name:"date"},{kind:"component",type:CompUserAvatarComponent,selector:"app-comp-user-avatar",inputs:["user"]},{kind:"ngmodule",type:MarkdownPreviewModule},{kind:"component",type:MarkdownPreviewComponent,selector:"fm-markdown-preview",inputs:["content","render"]},{kind:"pipe",type:ChatContentPipe,name:"chatContent"},{kind:"pipe",type:DurationStrPipe,name:"durationStr"}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatMessageCard,decorators:[{type:Component,args:[{selector:"fm-chat-message-card",standalone:!0,imports:[CommonModule,IonItem,CompUserAvatarComponent,MarkdownPreviewModule,IonAvatar,ChatContentPipe,NzSanitizerPipe,DurationStrPipe],template:'<div class="message-card" [class.right]="message?.role==\'user\'" [class.center]="message?.role==\'system\'">\n \x3c!-- 用户及操作区 --\x3e\n <div class="item-row user" *ngIf="message?.role!=\'system\'"> \x3c!-- 系统消息不显示头像 --\x3e\n <div class="avatar-row">\n <div class="actions">\n \x3c!-- 刷新 --\x3e\n \x3c!-- <ion-button fill="outline" slot="start">\n <ion-icon name="refresh-outline"></ion-icon> \n </ion-button> --\x3e\n \x3c!-- 复制 --\x3e\n <ion-button size="small" fill="outline" slot="start" (click)="copy()">\n <ion-icon name="copy-outline"></ion-icon>\n </ion-button>\n \x3c!-- 编辑 --\x3e\n \x3c!-- <ion-button fill="outline" slot="start">\n <ion-icon name="create-outline"></ion-icon>\n </ion-button> --\x3e\n </div>\n \x3c!-- 音频消息区域 --\x3e\n <div *ngIf="((message?.role==\'assistant\' && chat?.role?.get(\'voiceConfig\')?.voice) || (message?.role==\'user\'&&message?.voice))" class="play-voice" (click)="toggleVoicePlay()">\n <div class="voice-button">\n <ion-icon name="wifi-outline"\n [style.transform]="message?.role==\'user\'?\'rotate(-90deg)\':\'rotate(90deg)\'"\n class="audio-icon" [class.play-voice-playing]="tts?.isPlaying"></ion-icon>\n </div>\n <div class="voice-info">\n <span *ngIf="message?.voice?.duration">\n {{((message?.voice?.duration||0)/1000) | durationStr}}\n </span>\n <span *ngIf="!message?.voice?.duration">\n \x3c!-- --\x3e\n </span>\n </div>\n </div>\n \x3c!-- 头像区域 --\x3e \n <img class="avatar" *ngIf="message?.role!=\'user\'" [src]="(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/100/h/100\'" >\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="item-row images" *ngIf="message?.content | chatContent:\'image_url\'">\n <img [src]="message?.content | chatContent:\'image_url\'" alt="">\n </div>\n \x3c!-- 聊天气泡 --\x3e\n <div class="item-row bubble" [style.fontSize]="role?.get(\'uiConfig\')?.message?.bubble?.fontSize || \'0.8rem\'">\n <fm-markdown-preview *ngIf="!message?.complete" class="content-style" [content]="message?.content | chatContent" [render]="false"></fm-markdown-preview>\n <fm-markdown-preview *ngIf="message?.complete" [content]="message?.content | chatContent"></fm-markdown-preview>\n </div>\n \x3c!-- 时间显示 --\x3e\n <div class="item-row loading" *ngIf="message?.role!=\'system\' && !message?.complete">\n 正在输入<ion-spinner name="dots"></ion-spinner>\n </div>\n\n <div class="item-row created" *ngIf="message?.createdAt">\n <span>{{message?.createdAt | date:"dd/MM/yy HH:mm"}}</span>\n </div>\n</div>',styles:['@charset "UTF-8";:host-context(body.dark) .message-card .actions .item-native{background:none!important}:host-context(body.dark) .message-card .bubble{color:#0e101d}:host-context(body.dark) .message-card .bubble .content-style{filter:invert(1)!important}:host-context(body.dark) .message-card .bubble fm-markdown-preview{filter:invert(1)!important}:host-context(body.dark) .message-card .play-voice{background-color:#0e101d}:host-context(body.dark) .message-card .play-voice .voice-info{color:#fff}:host-context(body.dark) .message-card .right .bubble{color:#921f8a!important;background:#921f8a!important}:host-context(body.dark) .message-card .right .play-voice{background:#921f8a!important}:host-context(body.dark) .message-card .created span{color:#fff}@media screen and (max-width: 800px){.message-card:focus .actions{opacity:1!important}}.message-card:hover .actions{opacity:1;transition:opacity .3s ease-in-out}.message-card{display:flex;flex-wrap:wrap;justify-content:start;align-items:flex-start}.message-card .avatar-row{width:300px;height:32px;display:flex;flex-direction:row-reverse;justify-content:start;align-items:center}.message-card .actions{display:flex;opacity:0;padding-left:10px;padding-right:10px}.message-card .item-row{display:flex;flex:100%;justify-content:start;margin-bottom:5px}.message-card .images img{max-width:300px}.message-card .bubble{display:flex;justify-content:center;max-width:100%;padding:.5rem .5rem 0rem;color:#333;flex:none;border-radius:0 1.5em 1.5em/0em 1.5em 1.5em;color:#fff;background-color:currentColor}.message-card .bubble .content-style{filter:grayscale(1) contrast(999) invert(1)}.message-card .loading{text-align:right;color:#101010}.message-card .created{display:flex}.message-card .created span{font-size:12px;opacity:.4;white-space:nowrap;transition:all .6s ease;color:var(--black);text-align:center;width:100%;box-sizing:border-box;padding-right:10px;pointer-events:none;z-index:1}.right{justify-content:end;align-items:flex-end}.right .avatar-row{flex-direction:row;justify-content:end;width:auto}.right .actions{position:relative;margin-left:0}.right .item-row{justify-content:end}.right .bubble{color:#bbdefb;border-top-left-radius:1.5em;border-top-right-radius:0}.right .play-voice{flex-direction:row-reverse;background-color:#bbdefb}.center{justify-content:center;align-items:center}.center .item-row{justify-content:center}.center .bubble{color:var(--gray-secondary);border-top-left-radius:1.5em;border-top-right-radius:1.5em;font-size:12px;font-weight:100;padding:5px 20px}.play-voice{min-width:100px;height:32px;display:flex;justify-content:space-around;align-items:center;background-color:#fff;border-radius:7px}.play-voice .voice-button{width:32px;height:32px;display:flex;justify-content:center;align-items:center}.play-voice .voice-button span{overflow:hidden;font-size:18px;color:#ff69b4}.play-voice .voice-info{height:32px;display:flex;padding:0 10px;justify-content:end;align-items:center;color:#333}.avatar{border-radius:50%;width:32px;height:32px;object-fit:cover}.audio-icon{color:#ff69b4;font-size:18px}.play-voice-playing{animation:play-voice-animation 1s infinite}@keyframes play-voice-animation{0%{width:0}to{width:32px}}\n']}]}],ctorParameters:()=>[{type:ClipboardService}],propDecorators:{index:[{type:Input}],message:[{type:Input}],role:[{type:Input}],chat:[{type:Input}]}}),addIcons({chevronForward:chevronForward});class CompRolePromptComponent{constructor(e){this.cross=e,this.role="",this.showModal=!1,this.cateIndex=0,this.isDarkMode=!1,this.company="E4KpGvTEto"}ngOnInit(){this.getChatPrompt(),document.body.classList.contains("dark")&&(this.isDarkMode=!0)}applyPrompt(e){this.chat.userInput=e,this.chat.isVoiceInputMode=!1,this.chat.focusUserInput(),"mobile"==this.cross?.navMenuType&&(this.chat.isPromptModalOpen=!1)}async getChatPrompt(){if(this.chat.promptList?.length)return;let e=new Parse.Query("ChatPrompt");e.notEqualTo("isDeleted",!0),e.equalTo("role",this.role),e.include("role");let t=await e.find();t?.length&&(this.chat.promptList=t,this.chat.promptList.forEach((e=>{let t=e.get("role").get("promptCates").filter((t=>t.name==e.get("cate")));e.img=t[0].img})),console.log(this.chat.promptList))}checkCate(e){this.cateIndex=e}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompRolePromptComponent,deps:[{token:CrossService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompRolePromptComponent,isStandalone:!0,selector:"app-comp-role-prompt",inputs:{chat:"chat",role:"role"},providers:[],ngImport:i0,template:'<ng-container *ngIf="chat?.messageList?.length<4 && chat?.isPromptMessageAreaShow && !chat?.userInput">\n \x3c!-- PC端样式 --\x3e\n <div class="prompt" *ngIf="cross?.navMenuType!=\'mobile\'">\n <ng-container *ngFor="let content of chat?.promptList">\n <div class="prompt_cate">\n <div class="cate_info">\n <div>\n <img [src]="content.img" alt="">\n </div>\n <div class="cate_name">\n {{content.get(\'cate\')}}\n </div>\n </div>\n <ng-container *ngFor="let message of content.get(\'messageList\')">\n <div class="message" (click)="applyPrompt(message)">\n {{message}}\n </div>\n </ng-container>\n </div>\n </ng-container>\n </div>\n \x3c!-- 手机端样式 --\x3e\n <ng-container *ngIf="cross?.navMenuType==\'mobile\'">\n <div class="prompt_mobile">\n <ng-container *ngFor="let content of chat?.promptList">\n <div class="prompt_cate">\n <div class="cate_info">\n <div>\n <img [src]="content.img" alt="">\n </div>\n <div class="cate_name">\n {{content.get(\'cate\')}}\n </div>\n </div>\n <ng-container *ngFor="let message of content.get(\'messageList\');let idx = index">\n <div *ngIf="idx<3" class="message" (click)="applyPrompt(message)">\n {{message}}\n </div>\n </ng-container>\n </div>\n </ng-container>\n </div>\n <div class="view_more" *ngIf="chat?.promptList?.length">\n <button (click)="chat.isPromptModalOpen=true" expand="block">查看更多<ion-icon name="chevron-forward"></ion-icon></button>\n </div>\n </ng-container>\n</ng-container>\n\n <ion-modal [isOpen]="chat.isPromptModalOpen" (willDismiss)="chat.isPromptModalOpen=false" [initialBreakpoint]="1" [breakpoints]="[0, 1]">\n <ng-template>\n <div class="block">\n <ion-label>话题灵感</ion-label>\n <div class="block_cate">\n \x3c!-- <ion-segment [(ngModel)]="cateIndex">\n <ng-container *ngFor="let prompt of chat?.promptList;let i = index">\n <ion-segment-button value="i">\n <ion-label>{{prompt?.get("cate")}}</ion-label>\n </ion-segment-button>\n </ng-container>\n </ion-segment> --\x3e\n <ng-container *ngFor="let prompt of chat?.promptList;let i = index">\n <ion-button [color]="i==cateIndex?\'secondary\':\'light\'" (click)="checkCate(i)">{{prompt?.get("cate")}}</ion-button>\n \x3c!-- <div [class]="i==cateIndex?\'active_cate\':\'\'" (click)="checkCate(i)">{{prompt?.get("cate")}}</div> --\x3e\n </ng-container>\n </div>\n <div class="message_mobile">\n <ng-container *ngFor="let message of chat?.promptList[cateIndex]?.get(\'messageList\')">\n <div class="message-box" [style.backgroundColor]="isDarkMode?\'rgba(255,255,255,0.2)\':\'white\'" [style.color]="isDarkMode?\'rgba(255,255,255,0.5)\':\'black\'" (click)="applyPrompt(message)">{{message}}</div>\n </ng-container>\n </div>\n </div>\n </ng-template>\n </ion-modal>',styles:[":host-context(body.dark) .prompt_cate .message{background:#fff3;border:1px solid #333;box-shadow:0 2px 8px #333;color:#ffffff80}:host-context(body.dark) .cate_info{color:#fff}:host-context(body.dark) ion-modal .block h4{color:#fff!important}:host-context(body.dark) ion-modal .block .message-box{color:#ccc!important;background-color:#333!important}:host-context(body.dark) .message-box{color:#ccc!important;background-color:#333!important}.prompt{color:#000;display:flex;justify-content:space-between;align-items:flex-start}.prompt .prompt_cate{flex:1;height:inherit;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-direction:column;display:flex;justify-content:center}.prompt .prompt_cate .cate_info{font-size:1.5em;font-weight:700}.prompt .prompt_cate .cate_info div img{width:58px;height:58px}.prompt .prompt_cate .cate_info .cate_name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.prompt .prompt_cate .message{padding:1em;margin:1em;background:#fff;border:1px solid #eef2f2;border-radius:12px;box-shadow:0 2px 8px #f5f6f8;cursor:pointer;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media screen and (max-width: 390.4px){.prompt .prompt_cate .message{width:100px;height:64px;padding:unset;margin:.8em;background:#fff;border:1px solid #eef2f2;border-radius:12px;box-shadow:0 2px 8px #f5f6f8;cursor:pointer;overflow:hidden;white-space:pre-wrap;text-overflow:ellipsis}}.prompt_mobile{color:#000;display:flex;justify-content:space-between;align-items:flex-start}.prompt_mobile .prompt_cate{flex:1;height:inherit}.prompt_mobile .prompt_cate .cate_info{display:flex;justify-content:center;align-items:center;font-size:1.2em}.prompt_mobile .prompt_cate .cate_info div img{width:48px;height:48px}.prompt_mobile .prompt_cate .cate_info .cate_name{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;overflow:hidden;text-overflow:ellipsis;margin-top:2vw}.prompt_mobile .prompt_cate .message{min-height:48px;padding:0 2vw;margin:4vw 1vw;background:#fff;border:1px solid #eef2f2;border-radius:12px;box-shadow:0 2px 8px #f5f6f8;cursor:pointer;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;text-overflow:ellipsis}.view_more{text-align:center;color:#999;margin:4vw 0}.view_more>button{background-color:transparent}.block{width:100%;height:80vh;padding:2vw}.block .block_cate{display:flex;justify-content:space-evenly}.block .message_mobile{overflow-y:auto;height:65vh;color:#000}.message-box{background-color:#fff;text-align:center;padding:8px 0;margin:8px 0;border-radius:4px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}ion-modal{--height: auto}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2$1.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"component",type:IonModal,selector:"ion-modal"},{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:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompRolePromptComponent,decorators:[{type:Component,args:[{selector:"app-comp-role-prompt",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,IonModal,IonButton,IonSegment,IonLabel,IonIcon],providers:[],template:'<ng-container *ngIf="chat?.messageList?.length<4 && chat?.isPromptMessageAreaShow && !chat?.userInput">\n \x3c!-- PC端样式 --\x3e\n <div class="prompt" *ngIf="cross?.navMenuType!=\'mobile\'">\n <ng-container *ngFor="let content of chat?.promptList">\n <div class="prompt_cate">\n <div class="cate_info">\n <div>\n <img [src]="content.img" alt="">\n </div>\n <div class="cate_name">\n {{content.get(\'cate\')}}\n </div>\n </div>\n <ng-container *ngFor="let message of content.get(\'messageList\')">\n <div class="message" (click)="applyPrompt(message)">\n {{message}}\n </div>\n </ng-container>\n </div>\n </ng-container>\n </div>\n \x3c!-- 手机端样式 --\x3e\n <ng-container *ngIf="cross?.navMenuType==\'mobile\'">\n <div class="prompt_mobile">\n <ng-container *ngFor="let content of chat?.promptList">\n <div class="prompt_cate">\n <div class="cate_info">\n <div>\n <img [src]="content.img" alt="">\n </div>\n <div class="cate_name">\n {{content.get(\'cate\')}}\n </div>\n </div>\n <ng-container *ngFor="let message of content.get(\'messageList\');let idx = index">\n <div *ngIf="idx<3" class="message" (click)="applyPrompt(message)">\n {{message}}\n </div>\n </ng-container>\n </div>\n </ng-container>\n </div>\n <div class="view_more" *ngIf="chat?.promptList?.length">\n <button (click)="chat.isPromptModalOpen=true" expand="block">查看更多<ion-icon name="chevron-forward"></ion-icon></button>\n </div>\n </ng-container>\n</ng-container>\n\n <ion-modal [isOpen]="chat.isPromptModalOpen" (willDismiss)="chat.isPromptModalOpen=false" [initialBreakpoint]="1" [breakpoints]="[0, 1]">\n <ng-template>\n <div class="block">\n <ion-label>话题灵感</ion-label>\n <div class="block_cate">\n \x3c!-- <ion-segment [(ngModel)]="cateIndex">\n <ng-container *ngFor="let prompt of chat?.promptList;let i = index">\n <ion-segment-button value="i">\n <ion-label>{{prompt?.get("cate")}}</ion-label>\n </ion-segment-button>\n </ng-container>\n </ion-segment> --\x3e\n <ng-container *ngFor="let prompt of chat?.promptList;let i = index">\n <ion-button [color]="i==cateIndex?\'secondary\':\'light\'" (click)="checkCate(i)">{{prompt?.get("cate")}}</ion-button>\n \x3c!-- <div [class]="i==cateIndex?\'active_cate\':\'\'" (click)="checkCate(i)">{{prompt?.get("cate")}}</div> --\x3e\n </ng-container>\n </div>\n <div class="message_mobile">\n <ng-container *ngFor="let message of chat?.promptList[cateIndex]?.get(\'messageList\')">\n <div class="message-box" [style.backgroundColor]="isDarkMode?\'rgba(255,255,255,0.2)\':\'white\'" [style.color]="isDarkMode?\'rgba(255,255,255,0.5)\':\'black\'" (click)="applyPrompt(message)">{{message}}</div>\n </ng-container>\n </div>\n </div>\n </ng-template>\n </ion-modal>',styles:[":host-context(body.dark) .prompt_cate .message{background:#fff3;border:1px solid #333;box-shadow:0 2px 8px #333;color:#ffffff80}:host-context(body.dark) .cate_info{color:#fff}:host-context(body.dark) ion-modal .block h4{color:#fff!important}:host-context(body.dark) ion-modal .block .message-box{color:#ccc!important;background-color:#333!important}:host-context(body.dark) .message-box{color:#ccc!important;background-color:#333!important}.prompt{color:#000;display:flex;justify-content:space-between;align-items:flex-start}.prompt .prompt_cate{flex:1;height:inherit;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-direction:column;display:flex;justify-content:center}.prompt .prompt_cate .cate_info{font-size:1.5em;font-weight:700}.prompt .prompt_cate .cate_info div img{width:58px;height:58px}.prompt .prompt_cate .cate_info .cate_name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.prompt .prompt_cate .message{padding:1em;margin:1em;background:#fff;border:1px solid #eef2f2;border-radius:12px;box-shadow:0 2px 8px #f5f6f8;cursor:pointer;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media screen and (max-width: 390.4px){.prompt .prompt_cate .message{width:100px;height:64px;padding:unset;margin:.8em;background:#fff;border:1px solid #eef2f2;border-radius:12px;box-shadow:0 2px 8px #f5f6f8;cursor:pointer;overflow:hidden;white-space:pre-wrap;text-overflow:ellipsis}}.prompt_mobile{color:#000;display:flex;justify-content:space-between;align-items:flex-start}.prompt_mobile .prompt_cate{flex:1;height:inherit}.prompt_mobile .prompt_cate .cate_info{display:flex;justify-content:center;align-items:center;font-size:1.2em}.prompt_mobile .prompt_cate .cate_info div img{width:48px;height:48px}.prompt_mobile .prompt_cate .cate_info .cate_name{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;overflow:hidden;text-overflow:ellipsis;margin-top:2vw}.prompt_mobile .prompt_cate .message{min-height:48px;padding:0 2vw;margin:4vw 1vw;background:#fff;border:1px solid #eef2f2;border-radius:12px;box-shadow:0 2px 8px #f5f6f8;cursor:pointer;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;text-overflow:ellipsis}.view_more{text-align:center;color:#999;margin:4vw 0}.view_more>button{background-color:transparent}.block{width:100%;height:80vh;padding:2vw}.block .block_cate{display:flex;justify-content:space-evenly}.block .message_mobile{overflow-y:auto;height:65vh;color:#000}.message-box{background-color:#fff;text-align:center;padding:8px 0;margin:8px 0;border-radius:4px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}ion-modal{--height: auto}\n"]}]}],ctorParameters:()=>[{type:CrossService}],propDecorators:{chat:[{type:Input}],role:[{type:Input}]}});class FmChatMesssageArea{get messageList(){return this.chatServ.chatMap[this.chatId]?.messageList}constructor(e){this.chatServ=e}ngDoCheck(){}ngAfterViewInit(){console.log("ng gogogo1"),console.log("ng gogogo2"),console.log(this.chat)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatMesssageArea,deps:[{token:ChatService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:FmChatMesssageArea,isStandalone:!0,selector:"fm-chat-message-area",inputs:{chatId:"chatId",chat:"chat"},ngImport:i0,template:'\n<div class="message-list">\n <app-comp-role-prompt [chat]="chat" [role]="chat?.role?.id"></app-comp-role-prompt>\n <ng-container *ngFor="let message of chat?.messageList;let index=index;">\n \x3c!-- 内容格式化区域 --\x3e\n <fm-chat-message-card [chat]="chat" *ngIf="!message?.hidden" [index]="index" [message]="message" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n\n @if(!chat?.hideInputPreview){\n \x3c!-- 预览无图消息 --\x3e\n <ng-container *ngIf="chat?.userInput&&!chat?.userImage">\n <fm-chat-message-card [chat]="chat" [message]="{role:\'user\',content:chat?.userInput}" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n \n \x3c!-- 预览有图消息 --\x3e\n <ng-container *ngIf="chat?.userImage">\n <fm-chat-message-card [chat]="chat" [message]="{role:\'user\',content:[{type:\'text\',text:chat?.userInput},{type:\'image_url\',image_url:{url:chat?.userImage}}]}" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n }\n</div>',styles:[".message-list{padding:5px 20px}:host-context(body.dark) .message-list{background-color:#000!important}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2$1.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:FmChatMessageCard,selector:"fm-chat-message-card",inputs:["index","message","role","chat"]},{kind:"component",type:CompRolePromptComponent,selector:"app-comp-role-prompt",inputs:["chat","role"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatMesssageArea,decorators:[{type:Component,args:[{selector:"fm-chat-message-area",standalone:!0,imports:[CommonModule,FmChatMessageCard,CompRolePromptComponent],template:'\n<div class="message-list">\n <app-comp-role-prompt [chat]="chat" [role]="chat?.role?.id"></app-comp-role-prompt>\n <ng-container *ngFor="let message of chat?.messageList;let index=index;">\n \x3c!-- 内容格式化区域 --\x3e\n <fm-chat-message-card [chat]="chat" *ngIf="!message?.hidden" [index]="index" [message]="message" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n\n @if(!chat?.hideInputPreview){\n \x3c!-- 预览无图消息 --\x3e\n <ng-container *ngIf="chat?.userInput&&!chat?.userImage">\n <fm-chat-message-card [chat]="chat" [message]="{role:\'user\',content:chat?.userInput}" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n \n \x3c!-- 预览有图消息 --\x3e\n <ng-container *ngIf="chat?.userImage">\n <fm-chat-message-card [chat]="chat" [message]="{role:\'user\',content:[{type:\'text\',text:chat?.userInput},{type:\'image_url\',image_url:{url:chat?.userImage}}]}" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n }\n</div>',styles:[".message-list{padding:5px 20px}:host-context(body.dark) .message-list{background-color:#000!important}\n"]}]}],ctorParameters:()=>[{type:ChatService}],propDecorators:{chatId:[{type:Input}],chat:[{type:Input}]}});class ModalAudioMessageComponent{constructor(e,t,n){this.voiceServ=e,this.toastCtrl=t,this.uploadServ=n,this.isRecording=!1,this.player=new Audio,this.durationStr="0:00"}ngOnInit(){this.chat.userInput="",this.initVoiceSevice(),this.voiceServ.startTalk()}playMusic(e){this.player||(this.player=new Audio),this.player.src=`/assets/avatar/voice/${e}.mp3`;try{this.player?.play()}catch(e){}}initVoiceSevice(){this.chat.userInput=this.voiceServ.resultText,this.voiceServ.requestPermission().then((()=>{this.voiceServ.openWithPriviledge()})),this.voiceServ.onBeforeStartTalk=()=>{this.chat.playAnimation("listening"),this.playMusic("start-talk")},this.voiceServ.onAfterRecordStart=()=>{this.isRecording=!0},this.voiceServ.onDurationStrChange=e=>{this.durationStr=e},this.voiceServ.onBeforeCancelTalk=()=>{this.playMusic("interupt-talk"),this.chat.playAnimation("waiting")},this.voiceServ.onAfterCancelTalk=()=>{},this.voiceServ.onBeforeFinishTalk=()=>{this.chat.playAnimation("thinking"),this.playMusic("stop-talk")},this.voiceServ.onAfterFinishTalk=async()=>{console.log("onAfterFinishTalk1",this.voiceServ?.resultText),console.log("onAfterFinishTalk2",this.voiceServ?.resultTextTemp),this.chat.userInput=""+(this.voiceServ?.resultTextTemp||this.voiceServ?.resultText),this.chat?.userInput&&await this.saveChatVoice(),this.sendMessage()}}async saveChatVoice(){let e=this.voiceServ.recordWavBlob,t=this.voiceServ.recordDuration;if(e){let n=Parse__default.Object.extend("ChatVoice");this.chatVoice=new n,this.chatVoice.set("content",this.chat.userInput),this.chatVoice.set("role","user"),this.chatVoice.set("duration",t);let o=localStorage.getItem("company");o&&this.chatVoice.set("company",{__type:"Pointer",className:"Company",objectId:o}),Parse__default.User.current()?.id&&this.chatVoice.set("user",Parse__default.User.current().toPointer());let i=this.chatVoice?.id||this.uploadServ?.genMd5(this.chatVoice?.get("content")||this.chatVoice?.get("ssml")),a=new Date,r=i+a.getFullYear()+(a.getMonth()+1)+a.getDate()+a.getHours()+a.getMinutes()+a.getSeconds()+".wav",s=new File([e],r,{type:"audio/wav"}),l=await this.uploadServ.upload(s,(e=>{console.log(e)})),c={__type:"Pointer",className:"Attachment",objectId:l?.id};c?.objectId&&(this.chatVoice.set("voiceFile",c),this.chatVoice=await this.chatVoice.save())}}async sendMessage(){if(this.chat.userInput)this.chat?.sendMessage(""+this.chat?.userInput,this.chat?.userImage,(e=>{}),{onSSMLComplete:e=>{console.log(e)}},{id:this.chatVoice?.id,duration:this.chatVoice?.get("duration")});else{(await this.toastCtrl.create({message:"内容不能为空",position:"top",icon:"alert",color:"warning-circle",duration:1e3})).present()}}cancel(){this.clear(),this.voiceServ.cancelTalk(),this.modal?.dismiss(null,"cancel")}send(){this.clear(),this.voiceServ.finishTalk(),this.modal?.dismiss(null,"send")}clear(){this.now=void 0,this.isRecording=!1}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalAudioMessageComponent,deps:[{token:FmodeVoiceService},{token:i2$2.ToastController},{token:NovaUploadService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ModalAudioMessageComponent,isStandalone:!0,selector:"fm-modal-audio-message",inputs:{chat:"chat",modal:"modal"},providers:[ModalController$1],ngImport:i0,template:'\x3c!-- <div style="background:#FFFFFF;color:#000000;width:100%">\n {{this.chat.userInput}}\n</div> --\x3e\n<div class="modal-area">\n\n \x3c!-- 加载WebSockets动画 --\x3e\n <ng-container *ngIf="!isRecording">\n <div class="row">\n <ion-spinner name="crescent" color="success" style="width:80px;height:80px;"></ion-spinner>\n </div>\n </ng-container>\n \x3c!-- 录音中动画 --\x3e\n <ng-container *ngIf="isRecording">\n <div class="actions row">\n \x3c!-- 取消 --\x3e\n <ion-button (click)="cancel()" size="large" shape="round" color="light">\n <ion-icon name="close-outline"></ion-icon>\n </ion-button>\n \x3c!-- 音频 --\x3e\n <div class="audio-input">\n <div class="timer row">\n {{durationStr || "00:00"}}\n </div>\n <div class="audio-wave row">\n <div class="audio">\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n </div>\n </div>\n </div>\n \x3c!-- 发送 --\x3e\n <ion-button (click)="send()" size="large" shape="round" color="success">\n <ion-icon name="send-outline"></ion-icon>\n </ion-button>\n </div>\n \n <div class="tips row">\n 请您讲话,AI会识别!\n </div>\n </ng-container>\n</div>',styles:[":host-context(body.dark) .modal-area{color:#fff}.modal-area{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;padding-top:15px}.modal-area .row{margin:10px}.modal-area .tips{padding-top:5px}.modal-area .timer{font-size:1.5rem;font-weight:700}.modal-area .actions{display:flex;justify-content:space-around;width:100%;height:86px}.audio-input{display:flex;flex-direction:column;justify-content:center;align-items:center}.audio{display:flex;justify-content:space-between;align-items:center;gap:8px;width:60px;height:40px}.audio .wave{height:40px;display:block;width:10px;height:6px;border-radius:8px;background:orange}.audio .wave{animation:audio-wave 2s ease-in-out infinite}.audio .wave:nth-child(1){animation-delay:.1s}.audio .wave:nth-child(2){animation-delay:.2s}.audio .wave:nth-child(3){animation-delay:.3s}.audio .wave:nth-child(4){animation-delay:.4s}.audio .wave:nth-child(5){animation-delay:.5s}@keyframes audio-wave{0%{height:6px;transform:translateY(0);background:#ff8e3a}25%{height:6px;transform:translateY(0);background:#9c73f8}50%{height:30px;transform:translateY(-5px) scaleY(1.5);background:#ed509e}75%{height:6px;transform:translateY(0);background:#9c73f8}to{height:6px;transform:translateY(0);background:#0fccce}}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{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:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonSpinner,selector:"ion-spinner",inputs:["color","duration","name","paused"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalAudioMessageComponent,decorators:[{type:Component,args:[{selector:"fm-modal-audio-message",standalone:!0,imports:[CommonModule,IonButton,IonIcon,IonSpinner],providers:[ModalController$1],template:'\x3c!-- <div style="background:#FFFFFF;color:#000000;width:100%">\n {{this.chat.userInput}}\n</div> --\x3e\n<div class="modal-area">\n\n \x3c!-- 加载WebSockets动画 --\x3e\n <ng-container *ngIf="!isRecording">\n <div class="row">\n <ion-spinner name="crescent" color="success" style="width:80px;height:80px;"></ion-spinner>\n </div>\n </ng-container>\n \x3c!-- 录音中动画 --\x3e\n <ng-container *ngIf="isRecording">\n <div class="actions row">\n \x3c!-- 取消 --\x3e\n <ion-button (click)="cancel()" size="large" shape="round" color="light">\n <ion-icon name="close-outline"></ion-icon>\n </ion-button>\n \x3c!-- 音频 --\x3e\n <div class="audio-input">\n <div class="timer row">\n {{durationStr || "00:00"}}\n </div>\n <div class="audio-wave row">\n <div class="audio">\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n </div>\n </div>\n </div>\n \x3c!-- 发送 --\x3e\n <ion-button (click)="send()" size="large" shape="round" color="success">\n <ion-icon name="send-outline"></ion-icon>\n </ion-button>\n </div>\n \n <div class="tips row">\n 请您讲话,AI会识别!\n </div>\n </ng-container>\n</div>',styles:[":host-context(body.dark) .modal-area{color:#fff}.modal-area{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;padding-top:15px}.modal-area .row{margin:10px}.modal-area .tips{padding-top:5px}.modal-area .timer{font-size:1.5rem;font-weight:700}.modal-area .actions{display:flex;justify-content:space-around;width:100%;height:86px}.audio-input{display:flex;flex-direction:column;justify-content:center;align-items:center}.audio{display:flex;justify-content:space-between;align-items:center;gap:8px;width:60px;height:40px}.audio .wave{height:40px;display:block;width:10px;height:6px;border-radius:8px;background:orange}.audio .wave{animation:audio-wave 2s ease-in-out infinite}.audio .wave:nth-child(1){animation-delay:.1s}.audio .wave:nth-child(2){animation-delay:.2s}.audio .wave:nth-child(3){animation-delay:.3s}.audio .wave:nth-child(4){animation-delay:.4s}.audio .wave:nth-child(5){animation-delay:.5s}@keyframes audio-wave{0%{height:6px;transform:translateY(0);background:#ff8e3a}25%{height:6px;transform:translateY(0);background:#9c73f8}50%{height:30px;transform:translateY(-5px) scaleY(1.5);background:#ed509e}75%{height:6px;transform:translateY(0);background:#9c73f8}to{height:6px;transform:translateY(0);background:#0fccce}}\n"]}]}],ctorParameters:()=>[{type:FmodeVoiceService},{type:i2$2.ToastController},{type:NovaUploadService}],propDecorators:{chat:[{type:Input}],modal:[{type:Input}]}}),addIcons({colorWandOutline:colorWandOutline,peopleOutline:peopleOutline,alertOutline:alertOutline,imageOutline:imageOutline,chevronBackOutline:chevronBackOutline,ellipsisHorizontalOutline:ellipsisHorizontalOutline,chevronDownOutline:chevronDownOutline,chatboxEllipsesOutline:chatboxEllipsesOutline,micOutline:micOutline,paperPlaneOutline:paperPlaneOutline,shareSocialOutline:shareSocialOutline,settingsOutline:settingsOutline});class FmChatModalInput{closeAudio(){this.audioComp?.cancel(),this.isAudioModal=!1}async startTalk(){let e,t=document.body.clientHeight||960;this.audioModalHeightPoint=Number((165/t).toFixed(2)),this.chat.stopPlayingVoice(),e=await this.modalCtrl.create({component:ModalAudioMessageComponent,componentProps:{chat:this.chat,modal:e,onBreakPointSet:()=>{e?.setCurrentBreakpoint(this.audioModalHeightPoint)}},breakpoints:[this.audioModalHeightPoint],initialBreakpoint:this.audioModalHeightPoint}),e.present()}constructor(e,t,n,o,i,a,r){this.toastCtrl=e,this.alertCtrl=t,this.modalCtrl=n,this.router=o,this.imagineServ=i,this.chatServ=a,this.account=r,this.errorText="",this.isAudioModal=!1,this.audioModalHeightPoint=.35,this.isShare=!1,this.user=Parse__default.User.current()}ngOnInit(){this.loadModel();let e=this;this.chat.focusUserInput=()=>{e.chat.isVoiceInputMode=!1,e.userInputComp.setFocus()}}async loadModel(){let e=this.chat?.role?.get("model");await this.chat.loadModelList(e)}async setMessageImage(){let e=await this.imagineServ.getimg();this.chat.userImage=e,console.log(this.chat?.userImage)}onInputFocus(){this.chat.isTexting=!0,this.chat.scrollToBottom&&this.chat.scrollToBottom()}onKeyDown(e){e.ctrlKey&&"Enter"===e.key&&(console.log("Ctrl+Enter 被按下"),this.sendMessage())}async sendMessage(){if(!await this.checkBalance())return!1;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(){let e=await this.account.getBilling();if(e?.credit?.balance>=10&&(this.chat.isDirect=!0),!this.chat?.currentModel?.get("payLimit"))return!0;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__default.User.current();let e=new Parse__default.Query("ChatShare");e.equalTo("user",Parse__default.User.current().id),e.equalTo("session",this.chat?.sessionId);await e.first()}async toggleChatShare(){let e=new Parse__default.Query("ChatShare");e.equalTo("user",Parse__default.User.current().id),e.equalTo("role",this.chat?.role.id),e.equalTo("session",this.chat?.sessionId),e.select("objectId");let t=await e.first();if(t?.id)t.set("messageList",this.chat?.messageList);else{t=new(Parse__default.Object.extend("ChatShare")),t.set("user",{__type:"Pointer",className:"_User",objectId:Parse__default.User.current()?.id}),t.set("session",{__type:"Pointer",className:"ChatSession",objectId:this.chat?.sessionId}),t.set("role",{__type:"Pointer",className:"AvatarRole",objectId:this.chat?.role.id}),t.set("company",{__type:"Pointer",className:"Company",objectId:"E4KpGvTEto"}),t.set("messageList",this.chat?.messageList)}await t.save(),this.getChatShare()}async chatShareSuccessMessage(){(await this.toastCtrl.create({duration:1e3,message:"分享成功",color:"primary",icon:"information-circle",position:"top"})).present()}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:i3.ToastController},{token:i3.AlertController},{token:i2$2.ModalController},{token:i1$1.Router},{token:ImagineService},{token:ChatService},{token:AccountService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.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},{propertyName:"userInputComp",first:!0,predicate:["userInput"],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 @if(!chat?.hideShare){\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 }\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 <ng-container *ngFor="let message of chat?.messageList;let index=index;">\n \x3c!-- 内容格式化区域 --\x3e\n <fm-chat-message-card [chat]="chat" *ngIf="!message?.hidden" [index]="index" [message]="message" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n\n <div *ngIf="false" 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 <img class="avatar" *ngIf="message?.role!=\'user\'" [src]="(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\'" >\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 \x3c!-- 图片 --\x3e\n <ion-button shape="round" *ngIf="chat?.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 @if(!chat?.hideModalSelect){\n <ion-button shape="round" fill="outline" slot="end" id="model-button">\n <ion-icon name="chevron-down-outline"></ion-icon>\n {{chat?.currentModel?.get&&chat?.currentModel?.get("name")||"Fmode-C1.0-128k"}}\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 chat.modelList">\n <ion-item (click)="chat.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\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)="startTalk()">\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\n #userInput\n *ngIf="chat" (keydown)="onKeyDown($event)"\n [errorText]="errorText"\n [(ngModel)]="chat.userInput"\n (ionFocus)="onInputFocus()"\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\x3c!-- <ion-modal #audioModal [isOpen]="isAudioModal" (willDismiss)="closeAudio()" [initialBreakpoint]="audioModalHeightPoint" [breakpoints]="[0, audioModalHeightPoint]">\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> --\x3e',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}.avatar{border-radius:50%;width:32px;height:32px;object-fit:cover}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:i2$1.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:i2$1.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"pipe",type:i2$1.DatePipe,name:"date"},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i6.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i6.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:"component",type:FmChatMessageCard,selector:"fm-chat-message-card",inputs:["index","message","role","chat"]}]})}}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,FmChatMessageCard,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 @if(!chat?.hideShare){\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 }\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 <ng-container *ngFor="let message of chat?.messageList;let index=index;">\n \x3c!-- 内容格式化区域 --\x3e\n <fm-chat-message-card [chat]="chat" *ngIf="!message?.hidden" [index]="index" [message]="message" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n\n <div *ngIf="false" 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 <img class="avatar" *ngIf="message?.role!=\'user\'" [src]="(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\'" >\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 \x3c!-- 图片 --\x3e\n <ion-button shape="round" *ngIf="chat?.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 @if(!chat?.hideModalSelect){\n <ion-button shape="round" fill="outline" slot="end" id="model-button">\n <ion-icon name="chevron-down-outline"></ion-icon>\n {{chat?.currentModel?.get&&chat?.currentModel?.get("name")||"Fmode-C1.0-128k"}}\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 chat.modelList">\n <ion-item (click)="chat.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\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)="startTalk()">\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\n #userInput\n *ngIf="chat" (keydown)="onKeyDown($event)"\n [errorText]="errorText"\n [(ngModel)]="chat.userInput"\n (ionFocus)="onInputFocus()"\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\x3c!-- <ion-modal #audioModal [isOpen]="isAudioModal" (willDismiss)="closeAudio()" [initialBreakpoint]="audioModalHeightPoint" [breakpoints]="[0, audioModalHeightPoint]">\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> --\x3e',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}.avatar{border-radius:50%;width:32px;height:32px;object-fit:cover}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:i3.ToastController},{type:i3.AlertController},{type:i2$2.ModalController},{type:i1$1.Router},{type:ImagineService},{type:ChatService},{type:AccountService}],propDecorators:{audioComp:[{type:ViewChild,args:[ModalAudioMessageComponent]}],userInputComp:[{type:ViewChild,args:["userInput"]}],chat:[{type:Input}],message:[{type:Input}],role:[{type:Input}]}});class ChatPanelComponent{constructor(e,t,n){this.route=e,this.router=t,this.chatServ=n,this.mode="page",this.isDirect=!1,this.showInputModal=!0,this.showMessageArea=!0,this.showHeaderArea=!0,this.hideShare=!1,this.hideModalSelect=!1,this.hideInputPreview=!1,window.location.pathname?.indexOf("chat/session")>-1&&document.body.classList.add("dark")}listenDivChange(){let e=new MutationObserver((()=>{this.fmodeChat.scrollComp=this.contentComp})),t={childList:!0,subtree:!0,attributes:!0};this.contentComp?.nativeElement&&e.observe(this.contentComp?.nativeElement,t)}ngAfterViewInit(){}ngOnInit(){"modal"==this.mode&&this.initChat(),"page"==this.mode&&combineLatest([this.route.params,this.route.queryParams]).subscribe((async e=>{this.initChat(e)}))}async initChat(e){console.log("ChatComp OnInit");let t=e?.[0];if(this.chatId=t?.chatId||this.chatId||null,this.chatId&&await this.chatServ.initChatMap(this.chatId),this.roleId=t?.roleId||this.roleId||"2DXJkRsjXK",this.roleId){let e=await this.chatServ.createNewRoleChat(this.roleId);this.fmodeChat=e}this.chatId&&(this.fmodeChat=this.chatServ.chatMap[this.chatId],this.fmodeChat||this.router.navigate(["/chat/pro/mask"],{queryParams:{type:"employee"}}),this.fmodeChat=this.chatServ.chatMap[this.chatId]),this.leftButtons&&(this.fmodeChat.leftButtons=this.leftButtons),window.location.pathname?.indexOf("chat/session")>-1?this.fmodeChat.isVoiceInputMode=!0:this.fmodeChat.isVoiceInputMode=!1,this.modelList&&(this.fmodeChat.modelList=this.modelList,this.fmodeChat.currentModel=this.modelList[0]),this.isDirect&&(this.fmodeChat.isDirect=this.isDirect),this.hideShare&&(this.fmodeChat.hideShare=this.hideShare),this.hideModalSelect&&(this.fmodeChat.hideModalSelect=this.hideModalSelect),this.hideInputPreview&&(this.fmodeChat.hideInputPreview=this.hideInputPreview),this.fmodeChat.mode=this.mode,this.fmodeChat.onChatSaved=this.onChatSaved,this.fmodeChat.onMessage=this.onMessage,this.fmodeChat.onUserSend=this.onUserSend,this.fmodeChat.onClose=this.onClose,this.onChatInit&&this.onChatInit(this.fmodeChat),setTimeout((()=>{this.fmodeChat.scrollComp=this.contentComp,this.listenDivChange()}),1e3),this.sayWelcome()}sayWelcome(){this.fmodeChat.voiceConfig?.welcome?.enabled&&this.fmodeChat.welcome()}loadMask(){}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatPanelComponent,deps:[{token:i1$1.ActivatedRoute},{token:i1$1.Router},{token:ChatService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ChatPanelComponent,isStandalone:!0,selector:"app-chat-panel",inputs:{goBack:"goBack",onChatSaved:"onChatSaved",onChatInit:"onChatInit",onMessage:"onMessage",onUserSend:"onUserSend",onClose:"onClose",mode:"mode",chatId:"chatId",maskId:"maskId",roleId:"roleId",leftButtons:"leftButtons",modelList:"modelList",isDirect:"isDirect",showInputModal:"showInputModal",showMessageArea:"showMessageArea",showHeaderArea:"showHeaderArea",hideShare:"hideShare",hideModalSelect:"hideModalSelect",hideInputPreview:"hideInputPreview"},viewQueries:[{propertyName:"headerArea",first:!0,predicate:FmChatHeaderArea,descendants:!0},{propertyName:"contentComp",first:!0,predicate:["contentComp"],descendants:!0}],ngImport:i0,template:'\n\x3c!-- <ion-header></ion-header> --\x3e\n\x3c!-- <ion-content class="ion-padding"> --\x3e\n <div class="chat-page" *ngIf="fmodeChat">\n <div class="header" [class.avatarHeader]="fmodeChat?.isAvatarShow">\n <ng-content select="[chat-header]"></ng-content>\n <fm-chat-header-area [goBack]="goBack" *ngIf="showHeaderArea" [chat]="fmodeChat"></fm-chat-header-area>\n </div>\n \n <div class="content" #contentComp>\n <ng-content select="[chat-content]"></ng-content>\n <fm-chat-message-area *ngIf="showMessageArea" [chat]="fmodeChat"></fm-chat-message-area>\n </div>\n \n <div class="footer">\n <ng-content select="[chat-footer]"></ng-content>\n <fm-chat-modal-input *ngIf="showInputModal" [chat]="fmodeChat"></fm-chat-modal-input>\n </div>\n </div>\n\n\x3c!-- </ion-content> --\x3e',styles:[".chat-page{display:flex;flex-direction:column;height:100%;background:#f3f3f3}.chat-page .content,.chat-page .header,.chat-page .footer{justify-content:center;align-items:center}.chat-page .content{flex-grow:1;flex:1;overflow-y:auto}.chat-page .avatarHeader{height:35vh!important;overflow:hidden}.chat-page .header{height:44px;margin-bottom:-1px}.chat-page .footer{height:auto;min-height:130px}:host-context(body.dark) .chat-page{background:#000}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:FmChatHeaderArea,selector:"fm-chat-header-area",inputs:["chat","goBack"]},{kind:"component",type:FmChatMesssageArea,selector:"fm-chat-message-area",inputs:["chatId","chat"]},{kind:"component",type:FmChatModalInput,selector:"fm-chat-modal-input",inputs:["chat","message","role"]}]})}}async function openChatPanelModal(e,t){let n=await e.create({component:ChatPanelComponent,componentProps:{roleId:t.roleId,chatId:t.chatId,leftButtons:t.leftButtons,modelList:t.modelList,isDirect:t.isDirect,hideModalSelect:t.hideModalSelect,hideShare:t.hideShare,hideInputPreview:t.hideInputPreview,mode:"modal",onChatInit:t?.onChatInit,onChatSaved:t?.onChatSaved,onMessage:t?.onMessage,onUserSend:t?.onUserSend,onClose:t?.onClose,goBack:()=>{e.dismiss()}},cssClass:"modal-chat-panel",backdropDismiss:!1,keyboardClose:!1});return await n.present(),n}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatPanelComponent,decorators:[{type:Component,args:[{selector:"app-chat-panel",standalone:!0,imports:[CommonModule,FmChatHeaderArea,FmChatMesssageArea,FmChatModalInput],template:'\n\x3c!-- <ion-header></ion-header> --\x3e\n\x3c!-- <ion-content class="ion-padding"> --\x3e\n <div class="chat-page" *ngIf="fmodeChat">\n <div class="header" [class.avatarHeader]="fmodeChat?.isAvatarShow">\n <ng-content select="[chat-header]"></ng-content>\n <fm-chat-header-area [goBack]="goBack" *ngIf="showHeaderArea" [chat]="fmodeChat"></fm-chat-header-area>\n </div>\n \n <div class="content" #contentComp>\n <ng-content select="[chat-content]"></ng-content>\n <fm-chat-message-area *ngIf="showMessageArea" [chat]="fmodeChat"></fm-chat-message-area>\n </div>\n \n <div class="footer">\n <ng-content select="[chat-footer]"></ng-content>\n <fm-chat-modal-input *ngIf="showInputModal" [chat]="fmodeChat"></fm-chat-modal-input>\n </div>\n </div>\n\n\x3c!-- </ion-content> --\x3e',styles:[".chat-page{display:flex;flex-direction:column;height:100%;background:#f3f3f3}.chat-page .content,.chat-page .header,.chat-page .footer{justify-content:center;align-items:center}.chat-page .content{flex-grow:1;flex:1;overflow-y:auto}.chat-page .avatarHeader{height:35vh!important;overflow:hidden}.chat-page .header{height:44px;margin-bottom:-1px}.chat-page .footer{height:auto;min-height:130px}:host-context(body.dark) .chat-page{background:#000}\n"]}]}],ctorParameters:()=>[{type:i1$1.ActivatedRoute},{type:i1$1.Router},{type:ChatService}],propDecorators:{headerArea:[{type:ViewChild,args:[FmChatHeaderArea]}],goBack:[{type:Input}],onChatSaved:[{type:Input}],onChatInit:[{type:Input}],onMessage:[{type:Input}],onUserSend:[{type:Input}],onClose:[{type:Input}],mode:[{type:Input}],chatId:[{type:Input}],maskId:[{type:Input}],roleId:[{type:Input}],leftButtons:[{type:Input}],modelList:[{type:Input}],isDirect:[{type:Input}],showInputModal:[{type:Input}],showMessageArea:[{type:Input}],showHeaderArea:[{type:Input}],hideShare:[{type:Input}],hideModalSelect:[{type:Input}],hideInputPreview:[{type:Input}],contentComp:[{type:ViewChild,args:["contentComp"]}]}});class ChatListComponent{constructor(e,t,n,o){this.chatServ=e,this.alertCtrl=t,this.navCtrl=n,this.modalCtrl=o,this.chatList=[],this.onItemClick=(e,t)=>{t.stopPropagation(),this.goSession(e)},this.avatar="https://ionicframework.com/docs/img/demos/avatar.svg",this.isPreventGo=!1,this.chatServ.getChatSession().then((()=>{}))}async goSession(e){if(!this.isPreventGo)if(e?.rid||e?.sid){if(document.body.clientWidth<700){let t={roleId:e?.rid,chatId:e?.sid};return console.log("openChatPanelModal"),void openChatPanelModal(this.modalCtrl,t)}this.chatServ.restoreChatPanel(e)}else{(await this.alertCtrl.create({header:"注意",subHeader:"请您选择右侧角色",message:"开始对话",buttons:[{role:"ok",text:"知道了",handler:()=>{}}]})).present(),this.navCtrl.navigateRoot("/chat/pro/mask")}}async presentEditTitle(e,t,n){n.stopPropagation(),this.isPreventGo=!0,setTimeout((()=>{this.isPreventGo=!1}),500),n.preventDefault();const o=await this.alertCtrl.create({header:"修改会话标题",subHeader:"",message:"",buttons:[{text:"取消",role:"cancel",handler:()=>{}},{text:"确定",role:"confirm",handler:n=>{t.title=n.title,e?.set("title",n.title),e?.save()}}],inputs:[{placeholder:"会话标题",name:"title",value:t?.title||""}]});await o.present()}async presentDeleteTItle(e,t,n){n.stopPropagation(),this.isPreventGo=!0,setTimeout((()=>{this.isPreventGo=!1}),500),n.preventDefault();const o=await this.alertCtrl.create({header:"确认删除?",subHeader:"",message:"",buttons:[{text:"取消",role:"cancel",handler:()=>{}},{text:"确定",role:"confirm",handler:()=>{t.isHidden=!0,e?.set("isDeleted",!0),e?.save()}}]});await o.present()}truncateString(e){return e&&e.length>10?e.slice(0,10)+"...":e}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatListComponent,deps:[{token:ChatService},{token:i2$2.AlertController},{token:i2$2.NavController},{token:i2$2.ModalController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ChatListComponent,isStandalone:!0,selector:"app-chat-list",inputs:{onItemClick:"onItemClick"},providers:[],ngImport:i0,template:'<ion-list>\n <ng-container *ngFor="let chat of (chatServ?.chatList || chatList)">\n <ion-item [button]="true" detail="false" *ngIf="!chat?.isHidden" (click)="onItemClick(chat,$event)">\n <div class="unread-indicator-wrapper" slot="start">\n <div class="unread-indicator"></div>\n </div>\n <ion-label>\n <div style="display: flex;justify-content: space-between; align-items: center;">\n <div style="display: flex; flex-direction: row;align-items: center;">\n <strong style="display: flex;align-items: center;">\n <ion-avatar style="margin-right: 10px;">\n <img [src]="chat?.thumb||avatar" />\n </ion-avatar>\n <p style="max-width: 7rem;white-space: nowrap;">{{truncateString(chat?.title)}}</p>\n </strong>\n\n <ion-icon (click)="presentEditTitle(chat?.session,chat,$event)" name="brush-sharp" style="color:#777777;margin-left: 1rem;"></ion-icon>\n <ion-icon (click)="presentDeleteTItle(chat?.session,chat,$event)" name="trash-sharp" style="color:#777777;margin-left: 0.5rem;"></ion-icon>\n \n </div>\n <div class="metadata-end-wrapper" slot="end">\n <ion-note color="medium">{{chat?.latest | date:"HH:mm"}}</ion-note>\n <ion-icon color="medium" name="chevron-forward"></ion-icon>\n </div>\n </div>\n <ion-text></ion-text><br />\n <ion-note color="medium" class="ion-text-wrap">\n {{chat?.message}}\n </ion-note>\n </ion-label>\n </ion-item>\n </ng-container>\n </ion-list>',styles:["ion-icon{color:#fff}ion-list{margin:3px}ion-list ion-item{--inner-padding-bottom:0px;--inner-padding-end:0px;--inner-padding-start:0px;--inner-padding-to:0px;--padding-bottom:0px;--padding-end:0px;--padding-start:0px;--padding-to:0px}ion-list ul{width:100%;list-style-type:none;padding:0;margin:0 0 10px;display:flex;flex-wrap:wrap;background-color:#fff;border-radius:10px}ion-list ul .active__{position:relative;padding:5px 15px;font-size:18px;font-weight:700;color:#535353;transition:.3s}ion-list ul .active{color:#2d8af7;background-color:#f2f4ff;border-radius:10px}ion-list ul li{flex:1 1 auto}ion-list ul li div{cursor:pointer;text-align:center}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2$1.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"pipe",type:i2$1.DatePipe,name:"date"},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:IonNote,selector:"ion-note",inputs:["color","mode"]},{kind:"component",type:IonAvatar,selector:"ion-avatar"},{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:IonText,selector:"ion-text",inputs:["color","mode"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatListComponent,decorators:[{type:Component,args:[{selector:"app-chat-list",imports:[CommonModule,IonIcon,IonList,IonLabel,IonNote,IonButton,IonAvatar,IonItem,IonText],providers:[],standalone:!0,template:'<ion-list>\n <ng-container *ngFor="let chat of (chatServ?.chatList || chatList)">\n <ion-item [button]="true" detail="false" *ngIf="!chat?.isHidden" (click)="onItemClick(chat,$event)">\n <div class="unread-indicator-wrapper" slot="start">\n <div class="unread-indicator"></div>\n </div>\n <ion-label>\n <div style="display: flex;justify-content: space-between; align-items: center;">\n <div style="display: flex; flex-direction: row;align-items: center;">\n <strong style="display: flex;align-items: center;">\n <ion-avatar style="margin-right: 10px;">\n <img [src]="chat?.thumb||avatar" />\n </ion-avatar>\n <p style="max-width: 7rem;white-space: nowrap;">{{truncateString(chat?.title)}}</p>\n </strong>\n\n <ion-icon (click)="presentEditTitle(chat?.session,chat,$event)" name="brush-sharp" style="color:#777777;margin-left: 1rem;"></ion-icon>\n <ion-icon (click)="presentDeleteTItle(chat?.session,chat,$event)" name="trash-sharp" style="color:#777777;margin-left: 0.5rem;"></ion-icon>\n \n </div>\n <div class="metadata-end-wrapper" slot="end">\n <ion-note color="medium">{{chat?.latest | date:"HH:mm"}}</ion-note>\n <ion-icon color="medium" name="chevron-forward"></ion-icon>\n </div>\n </div>\n <ion-text></ion-text><br />\n <ion-note color="medium" class="ion-text-wrap">\n {{chat?.message}}\n </ion-note>\n </ion-label>\n </ion-item>\n </ng-container>\n </ion-list>',styles:["ion-icon{color:#fff}ion-list{margin:3px}ion-list ion-item{--inner-padding-bottom:0px;--inner-padding-end:0px;--inner-padding-start:0px;--inner-padding-to:0px;--padding-bottom:0px;--padding-end:0px;--padding-start:0px;--padding-to:0px}ion-list ul{width:100%;list-style-type:none;padding:0;margin:0 0 10px;display:flex;flex-wrap:wrap;background-color:#fff;border-radius:10px}ion-list ul .active__{position:relative;padding:5px 15px;font-size:18px;font-weight:700;color:#535353;transition:.3s}ion-list ul .active{color:#2d8af7;background-color:#f2f4ff;border-radius:10px}ion-list ul li{flex:1 1 auto}ion-list ul li div{cursor:pointer;text-align:center}\n"]}]}],ctorParameters:()=>[{type:ChatService},{type:i2$2.AlertController},{type:i2$2.NavController},{type:i2$2.ModalController}],propDecorators:{onItemClick:[{type:Input}]}});class PageMapStartComponent{constructor(){this.placeList=[{name:"江财蛟桥校区",location:[115.855125,28.744335]},{name:"江财枫林校区",location:[115.835639,28.734119]},{name:"江财麦庐校区",location:[115.816717,28.728899]}],this.amap={securityJsCode:"32aa3f4ab0fa0061de03edd4eafdd50a",key:"473b52010df7d3a32db0a2f5db245c8e"},this.initaMapConfig()}async initaMapConfig(){let e=localStorage.getItem("company");if(e){let t=new Parse__default.Query("Company");t.select("config");let n=await t.get(e);n?.get("config")?.amap&&(this.amap=n.get("config").amap)}window._AMapSecurityConfig={securityJsCode:this.amap.securityJsCode}}ngAfterViewInit(){this.initMap()}async initMap(){await this.createMap(),this.goAndMarkPlace(this.placeList[1])}async createMap(){this.AMap=await AMapLoader.load({key:this.amap.key,version:"2.0"}),this.map=new this.AMap.Map("container")}async addMarks(){let e=new this.AMap.Marker({position:[115.835639,28.734119]});this.map.add(e)}goAndMarkPlace(e){this.map.setCenter(e.location),this.map.setZoom(18),console.log(this.placeList),e.marker||(e.marker=new this.AMap.Marker({position:e.location}),this.map.add(e.marker))}clearMark(e){e?.marker?.remove()}planRoute(e,t){let n;this.map.plugin(["AMap.Transfer"],(()=>{let o={map:this.map,city:"南昌市",panel:"panel",policy:this.AMap.TransferPolicy.LEAST_TIME};console.log(this.AMap),console.log(this.AMap.TransferPolicy),n=new this.AMap.Transfer(o),n.search(new this.AMap.LngLat(e.location[0],e.location[1]),new this.AMap.LngLat(t.location[0],t.location[1]),((e,t)=>{"complete"===e?(console.log("绘制公交路线完成:"),console.log(t)):console.error("公交路线数据查询失败"+t)}))}))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PageMapStartComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:PageMapStartComponent,selector:"app-page-map.start",ngImport:i0,template:'\x3c!-- 全屏地图 --\x3e\n<div id="container"></div>\n\n\x3c!-- 右侧地点 --\x3e\n<div class="place-list">\n <ng-container *ngFor="let place of placeList">\n <div class="place-item" (click)="goAndMarkPlace(place)">\n {{place.name}}\n <button (click)="clearMark(place)">清除标记</button>\n </div>\n </ng-container>\n\n <button (click)="planRoute(placeList[0],placeList[1])">从蛟桥到枫林</button>\n \n</div>',styles:["#container{width:100%;height:100%;position:fixed}.place-list{display:flex;flex-direction:column;position:fixed;justify-content:center;align-items:center;height:80%;width:200px}.place-list .place-item{background-color:#ffffff4d;height:100px;width:90%}\n"],dependencies:[{kind:"directive",type:i2$1.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PageMapStartComponent,decorators:[{type:Component,args:[{selector:"app-page-map.start",template:'\x3c!-- 全屏地图 --\x3e\n<div id="container"></div>\n\n\x3c!-- 右侧地点 --\x3e\n<div class="place-list">\n <ng-container *ngFor="let place of placeList">\n <div class="place-item" (click)="goAndMarkPlace(place)">\n {{place.name}}\n <button (click)="clearMark(place)">清除标记</button>\n </div>\n </ng-container>\n\n <button (click)="planRoute(placeList[0],placeList[1])">从蛟桥到枫林</button>\n \n</div>',styles:["#container{width:100%;height:100%;position:fixed}.place-list{display:flex;flex-direction:column;position:fixed;justify-content:center;align-items:center;height:80%;width:200px}.place-list .place-item{background-color:#ffffff4d;height:100px;width:90%}\n"]}]}],ctorParameters:()=>[]});class CompPoiPickerComponent{get name(){return this._name}set name(e){this._name=e,this.nameChange.emit(e)}get address(){return this._address}set address(e){this._address=e,this.addressChange.emit(e)}get location(){return this._location}set location(e){this._location=e,this.locationChange.emit(e)}constructor(){this.nameChange=new EventEmitter,this.addressChange=new EventEmitter,this.locationChange=new EventEmitter,this.amap={securityJsCode:"32aa3f4ab0fa0061de03edd4eafdd50a",key:"473b52010df7d3a32db0a2f5db245c8e"},this.isModalOpen=!1,this.initaMapConfig()}async initaMapConfig(){let e=localStorage.getItem("company");if(e){let t=new Parse__default.Query("Company");t.select("config");let n=await t.get(e);n?.get("config")?.amap&&(this.amap=n.get("config").amap)}window._AMapSecurityConfig={securityJsCode:this.amap.securityJsCode}}cancel(){this.isModalOpen=!1,this.modal.dismiss(null,"cancel")}confirm(){this.isModalOpen=!1,this.modal.dismiss(this.address,"confirm")}onWillDismiss(e){"confirm"===e.detail.role&&console.log("确认")}openModal(){this.isModalOpen=!0,setTimeout((()=>{this.initMap()}),800)}ngAfterViewInit(){}initMap(){this.createMap()}async createMap(){this.AMap=await AMapLoader.load({key:this.amap.key,version:"2.0"});let e=this.container.nativeElement;this.map=new this.AMap.Map(e),this.goCurrentCenter()}goCurrentCenter(){this.AMap.plugin(["AMap.Geolocation"],(()=>{let e=new this.AMap.Geolocation({enableHighAccuracy:!0,timeout:1e4,maximumAge:0,convert:!0,showButton:!0,buttonPosition:"RB",buttonOffset:new this.AMap.Pixel(10,10),showMarker:!1,showCircle:!1,panToLocation:!0,zoomToAccuracy:!1});this.map.addControl(e),e.getCurrentPosition((function(e,t){"complete"===e?(console.log("当前位置经度:"+t.position.getLng()),console.log("当前位置纬度:"+t.position.getLat())):console.log("定位失败:"+t.message)}))}))}searchByAddress(){let e=this.panel.nativeElement;this.AMap.plugin(["AMap.PlaceSearch"],(()=>{let t=new this.AMap.PlaceSearch({pageSize:3,pageIndex:1,map:this.map,panel:e,autoFitView:!0});t.on("selectChanged",(e=>{this.name=e.selected.data.name,this.address=e.selected.data.address,this.location=new Parse__default.GeoPoint({latitude:e.selected.data.location.lat,longitude:e.selected.data.location.lng}),this.createCenterMarker()})),t.search(this.address)}))}createCenterMarker(){this.centerMarker||(this.centerMarker=new this.AMap.Marker({position:this.map.getCenter(),offset:new this.AMap.Pixel(-15,-15)}),this.map.add(this.centerMarker),this.map.on("dragging",(()=>{this.centerMarker.setPosition(this.map.getCenter())})),this.map.on("dragend",(()=>{let e=this.centerMarker.getPosition();this.location=new Parse__default.GeoPoint({latitude:e.lat,longitude:e.lng})})))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPoiPickerComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompPoiPickerComponent,selector:"fm-map-poi-picker",inputs:{_name:["name","_name"],_address:["address","_address"],_location:["location","_location"]},outputs:{nameChange:"nameChange",addressChange:"addressChange",locationChange:"locationChange"},viewQueries:[{propertyName:"container",first:!0,predicate:["container"],descendants:!0},{propertyName:"panel",first:!0,predicate:["panel"],descendants:!0},{propertyName:"modal",first:!0,predicate:IonModal$1,descendants:!0}],ngImport:i0,template:'\x3c!-- 未选点 --\x3e\n<ion-button (click)="openModal()" expand="block">开始选点</ion-button>\n\n\x3c!-- 已选点 --\x3e\n\n<ion-modal [isOpen]="isModalOpen" (willDismiss)="onWillDismiss($event)">\n<ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="cancel()">Cancel</ion-button>\n </ion-buttons>\n <ion-title>地图选点<ng-container *ngIf="location">({{location.latitude}},{{location.longitude}})</ng-container></ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="confirm()" [strong]="true">Confirm</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding" style="height:100%">\n \x3c!-- 详细地址 --\x3e\n <ion-item>\n <ion-input\n label="请输入详细地址"\n labelPlacement="stacked"\n type="text"\n placeholder="精确到门牌号"\n [(ngModel)]="address"\n ></ion-input>\n <ion-button slot="end" (click)="searchByAddress()">搜索</ion-button>\n </ion-item>\n \n \x3c!-- 地图选点 --\x3e\n <div #container class="container"></div>\n <div #panel class="panel"></div>\n\n </ion-content>\n</ng-template>\n</ion-modal>\n\n',styles:[".container{width:100%;height:100%}.panel{position:absolute;background-color:#fff;max-height:50%;overflow-y:auto;top:12%;right:10px;width:45%}\n"],dependencies:[{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:i6.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i6.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"component",type:i3.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:i3.IonButtons,selector:"ion-buttons",inputs:["collapse"]},{kind:"component",type:i3.IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:i3.IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:i3.IonInput,selector:"ion-input",inputs:["autocapitalize","autocomplete","autocorrect","autofocus","clearInput","clearInputIcon","clearOnEdit","color","counter","counterFormatter","debounce","disabled","enterkeyhint","errorText","fill","helperText","inputmode","label","labelPlacement","max","maxlength","min","minlength","mode","multiple","name","pattern","placeholder","readonly","required","shape","spellcheck","step","type","value"]},{kind:"component",type:i3.IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"component",type:i3.IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"component",type:i3.IonModal,selector:"ion-modal"},{kind:"directive",type:i3.TextValueAccessor,selector:"ion-input:not([type=number]),ion-textarea,ion-searchbar"}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPoiPickerComponent,decorators:[{type:Component,args:[{selector:"fm-map-poi-picker",template:'\x3c!-- 未选点 --\x3e\n<ion-button (click)="openModal()" expand="block">开始选点</ion-button>\n\n\x3c!-- 已选点 --\x3e\n\n<ion-modal [isOpen]="isModalOpen" (willDismiss)="onWillDismiss($event)">\n<ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="cancel()">Cancel</ion-button>\n </ion-buttons>\n <ion-title>地图选点<ng-container *ngIf="location">({{location.latitude}},{{location.longitude}})</ng-container></ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="confirm()" [strong]="true">Confirm</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding" style="height:100%">\n \x3c!-- 详细地址 --\x3e\n <ion-item>\n <ion-input\n label="请输入详细地址"\n labelPlacement="stacked"\n type="text"\n placeholder="精确到门牌号"\n [(ngModel)]="address"\n ></ion-input>\n <ion-button slot="end" (click)="searchByAddress()">搜索</ion-button>\n </ion-item>\n \n \x3c!-- 地图选点 --\x3e\n <div #container class="container"></div>\n <div #panel class="panel"></div>\n\n </ion-content>\n</ng-template>\n</ion-modal>\n\n',styles:[".container{width:100%;height:100%}.panel{position:absolute;background-color:#fff;max-height:50%;overflow-y:auto;top:12%;right:10px;width:45%}\n"]}]}],ctorParameters:()=>[],propDecorators:{container:[{type:ViewChild,args:["container"]}],panel:[{type:ViewChild,args:["panel"]}],_name:[{type:Input,args:["name"]}],nameChange:[{type:Output}],_address:[{type:Input,args:["address"]}],addressChange:[{type:Output}],_location:[{type:Input,args:["location"]}],locationChange:[{type:Output}],modal:[{type:ViewChild,args:[IonModal$1]}]}});class CompPoiPickerModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPoiPickerModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:CompPoiPickerModule,declarations:[CompPoiPickerComponent],imports:[CommonModule,FormsModule,ReactiveFormsModule,i3.IonicModule],exports:[CompPoiPickerComponent]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPoiPickerModule,imports:[CommonModule,FormsModule,ReactiveFormsModule,IonicModule.forRoot({mode:"ios"})]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPoiPickerModule,decorators:[{type:NgModule,args:[{declarations:[CompPoiPickerComponent],imports:[CommonModule,FormsModule,ReactiveFormsModule,IonicModule.forRoot({mode:"ios"})],exports:[CompPoiPickerComponent]}]}]});class PagePlanRouteComponent{constructor(){this.placeList=[],this.currentTab="place",this.amap={securityJsCode:"32aa3f4ab0fa0061de03edd4eafdd50a",key:"473b52010df7d3a32db0a2f5db245c8e"},this.initaMapConfig(),this.addNewPlace(),this.currentTab="plan"}async initaMapConfig(){let e=localStorage.getItem("company");if(e){let t=new Parse__default.Query("Company");t.select("config");let n=await t.get(e);n?.get("config")?.amap&&(this.amap=n.get("config").amap)}window._AMapSecurityConfig={securityJsCode:this.amap.securityJsCode}}addNewPlace(){this.placeList?.length>=1?this.placeList.push({name:"秋水广场",address:"南昌市秋水广场",location:new Parse__default.GeoPoint({latitude:28.682634,longitude:115.86273})}):this.placeList.push({name:"八一广场",address:"南昌市八一广场",location:new Parse__default.GeoPoint({latitude:28.673856,longitude:115.904477})})}ngAfterViewInit(){}async initMap(){await this.createMap(),this.goAndMarkPlace(this.placeList[0])}async createMap(){this.AMap=await AMapLoader.load({key:this.amap.key,version:"2.0"}),this.map=new this.AMap.Map("container-plan")}goAndMarkPlace(e){this.map.setCenter([e.location.latitude,e.location.longitude]),this.map.setZoom(18),e.marker||(e.marker=new this.AMap.Marker({position:[e.location.latitude,e.location.longitude]}),this.map.add(e.marker))}clearMark(e){e?.marker?.remove()}planRoute(e,t){let n;this.map.plugin(["AMap.Transfer"],(()=>{let o={map:this.map,city:"南昌市",panel:"panel",policy:this.AMap.TransferPolicy.LEAST_TIME};n=new this.AMap.Transfer(o);let i=new this.AMap.LngLat(e.location.longitude,e.location.latitude),a=new this.AMap.LngLat(t.location.longitude,t.location.latitude);n.search(i,a,((e,t)=>{"complete"===e?(console.log("绘制公交路线完成:"),console.log(t)):console.error("公交路线数据查询失败"+t)}))}))}async createPlan(){await this.initMap(),this.planRoute(this.placeList[0],this.placeList[1])}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PagePlanRouteComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:PagePlanRouteComponent,selector:"app-page-plan-route",ngImport:i0,template:'<ion-segment value="place">\n <ion-segment-button (click)="currentTab=\'place\'" value="place">\n <ion-label>景点选择</ion-label>\n </ion-segment-button>\n <ion-segment-button (click)="currentTab=\'plan\'" value="plan">\n <ion-label>路线规划</ion-label>\n </ion-segment-button>\n </ion-segment>\n \n\n<ng-container *ngIf="currentTab==\'place\'">\n <h1>选择旅游计划景点</h1>\n\n <ng-container *ngFor="let place of placeList">\n <ion-card>\n <h2>{{place?.name}}</h2>\n <span *ngIf="place.address">详细地址:{{place.address}}</span>\n <span *ngIf="place.location">地图坐标:{{place.location.latitude}},{{place.location.longitude}}</span>\n <fm-map-poi-picker [(name)]="place.name" [(address)]="place.address" [(location)]="place.location"></fm-map-poi-picker>\n </ion-card>\n </ng-container>\n <ion-button (click)="addNewPlace()" expand="block">添加新景点</ion-button>\n</ng-container>\n\n<ng-container *ngIf="currentTab==\'plan\'">\n <ion-button (click)="createPlan()" expand="block">创建规划路线</ion-button>\n\n <div id="container-plan"></div>\n <div id="panel"></div>\n</ng-container>\n\n',styles:["#container-plan{width:100%;height:40%}#panel{width:100%;height:50%}\n"],dependencies:[{kind:"directive",type:i2$1.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:i3.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:i3.IonCard,selector:"ion-card",inputs:["button","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:i3.IonSegment,selector:"ion-segment",inputs:["color","disabled","mode","scrollable","selectOnFocus","swipeGesture","value"]},{kind:"component",type:i3.IonSegmentButton,selector:"ion-segment-button",inputs:["contentId","disabled","layout","mode","type","value"]},{kind:"directive",type:i3.SelectValueAccessor,selector:"ion-select, ion-radio-group, ion-segment, ion-datetime"},{kind:"component",type:CompPoiPickerComponent,selector:"fm-map-poi-picker",inputs:["name","address","location"],outputs:["nameChange","addressChange","locationChange"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PagePlanRouteComponent,decorators:[{type:Component,args:[{selector:"app-page-plan-route",template:'<ion-segment value="place">\n <ion-segment-button (click)="currentTab=\'place\'" value="place">\n <ion-label>景点选择</ion-label>\n </ion-segment-button>\n <ion-segment-button (click)="currentTab=\'plan\'" value="plan">\n <ion-label>路线规划</ion-label>\n </ion-segment-button>\n </ion-segment>\n \n\n<ng-container *ngIf="currentTab==\'place\'">\n <h1>选择旅游计划景点</h1>\n\n <ng-container *ngFor="let place of placeList">\n <ion-card>\n <h2>{{place?.name}}</h2>\n <span *ngIf="place.address">详细地址:{{place.address}}</span>\n <span *ngIf="place.location">地图坐标:{{place.location.latitude}},{{place.location.longitude}}</span>\n <fm-map-poi-picker [(name)]="place.name" [(address)]="place.address" [(location)]="place.location"></fm-map-poi-picker>\n </ion-card>\n </ng-container>\n <ion-button (click)="addNewPlace()" expand="block">添加新景点</ion-button>\n</ng-container>\n\n<ng-container *ngIf="currentTab==\'plan\'">\n <ion-button (click)="createPlan()" expand="block">创建规划路线</ion-button>\n\n <div id="container-plan"></div>\n <div id="panel"></div>\n</ng-container>\n\n',styles:["#container-plan{width:100%;height:40%}#panel{width:100%;height:50%}\n"]}]}],ctorParameters:()=>[]});class PageLocaScatterComponent{constructor(){this.amap={securityJsCode:"32aa3f4ab0fa0061de03edd4eafdd50a",key:"473b52010df7d3a32db0a2f5db245c8e"},this.initaMapConfig()}async initaMapConfig(){let e=localStorage.getItem("company");if(e){let t=new Parse__default.Query("Company");t.select("config");let n=await t.get(e);n?.get("config")?.amap&&(this.amap=n.get("config").amap)}window._AMapSecurityConfig={securityJsCode:this.amap.securityJsCode}}ngAfterViewInit(){this.initMap()}async initMap(){await this.createMap(),await this.createLoca()}async createLoca(){let e=window.loca=new Loca.Container({map:this.map}),t=new Loca.GeoJSONSource({url:"https://a.amap.com/Loca/static/loca-v2/demos/mock_data/sz_road.json"}),n=new Loca.ScatterLayer({zIndex:111,opacity:1,visible:!0,zooms:[2,22]});n.setSource(t),n.setStyle({color:"rgba(43,156,75,1)",unit:"meter",size:[150,150],borderWidth:0}),e.add(n);let o=new Loca.GeoJSONSource({url:"https://a.amap.com/Loca/static/loca-v2/demos/mock_data/sz_road_F.json"}),i=new Loca.ScatterLayer({loca:e,zIndex:113,opacity:1,visible:!0,zooms:[2,22]});i.setSource(o),i.setStyle({unit:"meter",size:[2600,2600],borderWidth:0,texture:"https://a.amap.com/Loca/static/loca-v2/demos/images/breath_red.png",duration:500,animate:!0});let a=new Loca.GeoJSONSource({url:"https://a.amap.com/Loca/static/loca-v2/demos/mock_data/sz_road_E.json"}),r=new Loca.ScatterLayer({loca:e,zIndex:112,opacity:1,visible:!0,zooms:[2,22]});r.setSource(a),r.setStyle({unit:"meter",size:[1e3,1e3],borderWidth:0,texture:"https://a.amap.com/Loca/static/loca-v2/demos/images/breath_yellow.png",duration:1e3,animate:!0}),e.animate.start();let s=new Loca.Dat;s.addLayer(n," 贴地"),s.addLayer(i,"红色"),s.addLayer(r,"黄色")}async createMap(){this.AMap=await AMapLoader.load({key:this.amap.key,version:"2.0",Loca:{version:"2.0.0"}}),this.map=new this.AMap.Map("container",{zoom:11.7,center:[113.97199630737305,22.5807295363949],pitch:40,showLabel:!1,mapStyle:"amap://styles/dark",viewMode:"3D"})}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PageLocaScatterComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:PageLocaScatterComponent,selector:"app-page-loca-scatter",ngImport:i0,template:'<div id="container"></div>',styles:["#container{width:100%;height:100%;position:fixed}\n"]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PageLocaScatterComponent,decorators:[{type:Component,args:[{selector:"app-page-loca-scatter",template:'<div id="container"></div>',styles:["#container{width:100%;height:100%;position:fixed}\n"]}]}],ctorParameters:()=>[]});const routes=[{path:"start",component:PageMapStartComponent},{path:"plan/route",component:PagePlanRouteComponent},{path:"loca/scatter",component:PageLocaScatterComponent}];class FmodeMapModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeMapModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:FmodeMapModule,declarations:[PageMapStartComponent,PagePlanRouteComponent,PageLocaScatterComponent],imports:[CommonModule,i1$1.RouterModule,i3.IonicModule,CompPoiPickerModule],exports:[CompPoiPickerModule]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeMapModule,imports:[CommonModule,RouterModule.forChild(routes),IonicModule.forRoot({mode:"ios"}),CompPoiPickerModule,CompPoiPickerModule]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeMapModule,decorators:[{type:NgModule,args:[{declarations:[PageMapStartComponent,PagePlanRouteComponent,PageLocaScatterComponent],imports:[CommonModule,RouterModule.forChild(routes),IonicModule.forRoot({mode:"ios"}),CompPoiPickerModule],exports:[CompPoiPickerModule]}]}]});class HwobsService{constructor(){this.Attachment=Parse__default.Object.extend("Attachment"),this.host="https://web3-test.obs.cn-south-1.myhuaweicloud.com/",this.bucketName="web3-test",this.obsClient=new ObsClient({access_key_id:"6UIET20WHUI5TLXWOVNA",secret_access_key:"YaoY8Kj3TeGZHEcBzplTMZiPGNL13Y3frEavC1kF",server:"https://obs.cn-south-1.myhuaweicloud.com"})}listDir(e){return new Promise(((t,n)=>{this.obsClient.listObjects({Bucket:this.bucketName,Prefix:e,Delimiter:"/"},((e,o)=>{if(e)console.error("Error--\x3e"+e),n(e);else{if(console.log("Status--\x3e"+o.CommonMsg.Status),console.log(o),o.CommonMsg.Status<300&&o.InterfaceResult)for(var i in o.InterfaceResult.Contents)console.log("Contents["+i+"]:"),console.log("Key--\x3e"+o.InterfaceResult.Contents[i].Key),console.log("Owner[ID]--\x3e"+o.InterfaceResult.Contents[i].Owner.ID);let e=o.InterfaceResult.CommonPrefixes,n=o.InterfaceResult.Contents;t({dirs:e,files:n})}}))}))}async uploadFile(e,t){let n=await this.checkFileExists(e);return n?.id?n:new Promise(((n,o)=>{this.obsClient.putObject({Bucket:this.bucketName,Key:t,SourceFile:e},(async(i,a)=>{if(i)console.error("Error--\x3e"+i),o(i);else{console.log("Status--\x3e"+a.CommonMsg.Status);let o=await this.saveAttachment(e,t);n(o)}}))}))}async checkFileExists(e){let t,n=await this.getFileHash(e),o=new Parse__default.Query("Attachment");o.equalTo("hash",n),o.equalTo("size",e.size);let i=await o.first();return i?.id||(i=new this.Attachment),t=i,t}async saveAttachment(e,t){let n=await this.getFileHash(e),o=await this.checkFileExists(e);return o.set("name",e.name),o.set("size",e.size),o.set("mime",e.type),o.set("url",this.host+t),o.set("hash",n),o=await o.save(),o}async getFileHash(e){return new Promise(((t,n)=>{const o=new FileReader;o.onload=async e=>{const n=e.target.result,o=await crypto.subtle.digest("SHA-256",n),i=Array.from(new Uint8Array(o)).map((e=>e.toString(16).padStart(2,"0"))).join("");t(i)},o.onerror=e=>{n(e.target.error)},o.readAsArrayBuffer(e)}))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:HwobsService,deps:[],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:HwobsService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:HwobsService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});class HwobsManagerComponent{openFile(e){console.log("Opening file:",e)}openDir(e,t="pre"){if(e)this.prefix=e.Prefix,this.listDir(e.Prefix);else if("pre"==t){let e=this.prefix.split("/");if(e.length>1){let t=e.splice(0,e.length-1).join("/");console.log(t),this.prefix=t,this.listDir(t)}}}showName(e){return e.replaceAll(this.prefix,"")}constructor(e){this.hwobs=e,this.dirs=[],this.files=[],this.prefix="storage/",this.listDir(this.prefix)}async listDir(e){let{dirs:t,files:n}=await this.hwobs.listDir(e);this.dirs=t,this.files=n}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:HwobsManagerComponent,deps:[{token:HwobsService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:HwobsManagerComponent,isStandalone:!0,selector:"fm-storage-hwobs-manager",ngImport:i0,template:'<ion-header>\n <ion-toolbar>\n <ion-title>\n File Manager\n </ion-title>\n </ion-toolbar>\n </ion-header>\n \n <ion-content>\n <ion-list>\n <ion-item (click)="openDir(null,\'pre\')">\n <ion-icon [name]="\'folder\'" slot="start"></ion-icon>\n <ion-label>../</ion-label>\n </ion-item>\n <ion-item *ngFor="let item of dirs" (click)="openDir(item)">\n <ion-icon [name]="\'folder\'" slot="start"></ion-icon>\n <ion-label>{{ showName(item.Prefix) }}</ion-label>\n </ion-item>\n <ion-item *ngFor="let item of files" (click)="openFile(item)">\n <ion-icon [name]="\'document\'" slot="start"></ion-icon>\n <ion-label>{{ showName(item.Key) }}</ion-label>\n </ion-item>\n </ion-list>\n </ion-content>',styles:["ion-list ion-item ion-icon{font-size:24px;margin-right:8px}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2$1.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"ngmodule",type:IonicModule},{kind:"component",type:i3.IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:i3.IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:i3.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:i3.IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:i3.IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:i3.IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"component",type:i3.IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:HwobsManagerComponent,decorators:[{type:Component,args:[{standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,IonicModule],selector:"fm-storage-hwobs-manager",template:'<ion-header>\n <ion-toolbar>\n <ion-title>\n File Manager\n </ion-title>\n </ion-toolbar>\n </ion-header>\n \n <ion-content>\n <ion-list>\n <ion-item (click)="openDir(null,\'pre\')">\n <ion-icon [name]="\'folder\'" slot="start"></ion-icon>\n <ion-label>../</ion-label>\n </ion-item>\n <ion-item *ngFor="let item of dirs" (click)="openDir(item)">\n <ion-icon [name]="\'folder\'" slot="start"></ion-icon>\n <ion-label>{{ showName(item.Prefix) }}</ion-label>\n </ion-item>\n <ion-item *ngFor="let item of files" (click)="openFile(item)">\n <ion-icon [name]="\'document\'" slot="start"></ion-icon>\n <ion-label>{{ showName(item.Key) }}</ion-label>\n </ion-item>\n </ion-list>\n </ion-content>',styles:["ion-list ion-item ion-icon{font-size:24px;margin-right:8px}\n"]}]}],ctorParameters:()=>[{type:HwobsService}]});class FmodeStorgeModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeStorgeModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:FmodeStorgeModule,imports:[CommonModule,i3.IonicModule,HwobsManagerComponent],exports:[HwobsManagerComponent]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeStorgeModule,providers:[Diagnostic,NovaUploadService],imports:[CommonModule,IonicModule.forRoot({mode:"ios"}),HwobsManagerComponent]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeStorgeModule,decorators:[{type:NgModule,args:[{declarations:[],imports:[CommonModule,IonicModule.forRoot({mode:"ios"}),HwobsManagerComponent],exports:[HwobsManagerComponent],providers:[Diagnostic,NovaUploadService]}]}]});class WechatJssdkService{constructor(e,t){this.http=e,this.authServ=t,this.isInit=!1,this.isWechat=!1,this.wechatAccountId=localStorage.getItem("WECHAT_APP_ID")||"wxb4193c93ae9aa696";let n=-1!==navigator.userAgent.toLowerCase().indexOf("micromessenger");this.isWechat=n,this.company=this.authServ.company||localStorage.getItem("company")}async setCurrentPageShareInfo(e={title:"飞码AI",desc:"解放创意引领未来|国际前沿的AIGC平台",link:location.href,type:"link",imgUrl:"https://file-cloud.fmode.cn/E4KpGvTEto/20230822/3mkf41033623275.png",success:()=>{console.log("分享成功")},error:()=>{console.log("分享失败")},cancel:()=>{console.log("取消分享")}}){const t=await this.getWXSignPackageInWechat();wx.config({debug:!1,appId:t.appid,timestamp:t.timestamp,nonceStr:t.nonceStr,signature:t.signature,jsApiList:["chooseWXPay","onMenuShareTimeline","onMenuShareAppMessage","onMenuShareQQ","onMenuShareQZone","updateAppMessageShareData","updateTimelineShareData"]}),"link"==e?.type&&(e.link=this.getInviteUrl(e.link)),wx.ready((()=>{wx.updateAppMessageShareData(e),wx.updateTimelineShareData(e)})),wx.error((()=>{}))}getInviteUrl(e){let t=new URL(e),n=Parse__default.User?.current()?.id;return n&&t.searchParams.set("invite",n),t.href}getWXSignPackageInWechat(){let e={company:this.company,href:encodeURIComponent(location.href)};return new Promise((t=>{this.http.post("https://server.fmode.cn/api/wechat/getconfig",e).subscribe((e=>{let n=e.data;t(n)}))}))}async initUserOpenid(){await this.init();let e=this.getQueryStringByName("code"),t=localStorage.getItem("openid");if(!t){if(!Parse__default.User.current())return;if(t=Parse__default?.User?.current()?.get("wechat")?.[this.wechatAccountId]?.openid,this.isWechat&&!t){let t=window.location.pathname;e?await this.getwechat(e,t):this.authWechat(t)}else this.openid=t}}authWechat(e="/account/billing"){if(!localStorage.getItem("openid")){let t="https://ai.fmode.cn"+e;return t=encodeURIComponent(t),void(window.location.href="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+this.wechatAccountId+"&redirect_uri="+t+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect")}}getQueryStringByName(e){let t=location.search.match(new RegExp("[?&]"+e+"=([^&]+)","i"));return null==t||t.length<1?"":t[1]}async getwechat(e,t="/account/billing"){return new Promise((async(n,o)=>{this.http.post("https://server.fmode.cn/api/wechat/get_wx",{company:this.company,code:e}).subscribe((async e=>{if(console.log(e),e&&200==e.code&&e.data.openid){let t=e.data.openid;localStorage.setItem("openid",t),localStorage.removeItem("code");let o={};o[this.wechatAccountId]={openid:t},Parse__default.User.current().set("wechat",o),await Parse__default.User.current().save(),n(!0)}}),(async e=>{console.log("Error updating items",e),this.authWechat(t),o(!1)}))}))}init(){return new Promise((e=>{this.isWechat||e(!1),this.isInit&&e(!0),wx&&e(!0),this.loadScript("https://res.wx.qq.com/open/js/jweixin-1.6.0.js",(()=>{this.isInit=!0,this.wx=wx,e(!0)}),(()=>{e(!1)}))}))}loadScript(e,t,n){var o=document.createElement("script");o.src=e,o.onload=()=>{t&&t()},o.onerror=()=>{n&&n()},document.body.appendChild(o)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:WechatJssdkService,deps:[{token:i1.HttpClient},{token:AuthService}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:WechatJssdkService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:WechatJssdkService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1.HttpClient},{type:AuthService}]});class LoginComponent{drawCode(e){this.canvas=document.getElementById("verifyCanvas");var t=this.canvas.getContext("2d");t.fillStyle="white",t.fillRect(0,0,this.canvas.width,this.canvas.height),t.fillStyle="cornflowerblue",t.font="25px Arial";for(var n=new Array,o=new Array,i=new Array,a=0;a<4;a++)n.push(n[a]),n[a]=this.nums[a],o[a]=20*a+10,i[a]=20*Math.random()+20,t.fillText(n[a],o[a],i[a]);e=n.join("").toUpperCase();for(a=0;a<3;a++)this.drawline(this.canvas,t);for(a=0;a<30;a++)this.drawDot(this.canvas,t);return this.convertCanvasToImage(this.canvas),e}drawline(e,t){t.moveTo(Math.floor(Math.random()*e.width),Math.floor(Math.random()*e.height)),t.lineTo(Math.floor(Math.random()*e.width),Math.floor(Math.random()*e.height)),t.lineWidth=.5,t.strokeStyle="rgba(50,50,50,0.3)",t.stroke()}drawDot(e,t){var n=Math.floor(Math.random()*e.width),o=Math.floor(Math.random()*e.height);t.moveTo(n,o),t.lineTo(n+1,o+1),t.lineWidth=.2,t.stroke()}convertCanvasToImage(e){return document.getElementById("verifyCanvas").style.display="none",this.image=document.getElementById("code_img"),this.image.src=e.toDataURL("image/png"),this.image}sendSMSCode(){if(!this.codeVerified)return void this.message.create("error","请先核对验证码");let e=this.validateSMSForm.value?.mobile;if(console.log(this.validateSMSForm.value),e){let t=localStorage.getItem("NOVA_APIG_SERVER");t=decodeURIComponent(atob(t));let n=t+"message";this.http.post(n,{company:this.companyId,mobile:e,action:"login"}).subscribe((e=>{this.countDownSMS(),this.message.info("已发送,请查收验证码")}),(e=>{this.message.error(e?.error?.mess||"系统繁忙中,请稍后重试")}))}else this.message.error("请正确输入手机号")}countDownSMS(){this.isSended=!0,this.isSending=!0,this.smsTimeCount=60;let e=setInterval((()=>{this.smsTimeCount--}),1e3);setTimeout((()=>{clearInterval(e),this.isSending=!1}),6e4)}submitFormMobileSMS(e){for(const e in this.validateSMSForm.controls)this.validateSMSForm.controls[e].markAsDirty(),this.validateSMSForm.controls[e].updateValueAndValidity();console.log(e),this.username=e.mobile,this.smsCode=e.smsCode,console.log("smslogin"),this.loginSMS()}submitFormMobilePassword(e){for(const e in this.validateForm.controls)this.validateForm.controls[e].markAsDirty(),this.validateForm.controls[e].updateValueAndValidity();this.username=e.mobile||e.username,this.password=e.password;let t=e.checkCode,n=this.code.toLowerCase(),o=t.toLowerCase();console.log(n,o),n!=o?(console.log(n,o),this.message.create("error","验证码错误")):this.loginMobilePassword()}submitFormUserPassword(e){for(const e in this.validateForm.controls)this.validateForm.controls[e].markAsDirty(),this.validateForm.controls[e].updateValueAndValidity();this.username=e.mobile||e.username,this.password=e.password;let t=e.checkCode,n=this.code.toLowerCase(),o=t.toLowerCase();console.log(n,o),n!=o?(console.log(n,o),this.message.create("error","验证码错误")):this.authServ.login(this.username,this.password).then((async e=>{})).catch((e=>{console.log(e),this.message.create("error","错误的用户名或密码")}))}async forgetFormFun(e){for(const e in this.forgetForm.controls)this.forgetForm.controls[e].markAsDirty(),this.forgetForm.controls[e].updateValueAndValidity();if(console.log(e.forgetusername,e.forgetPassword,e.forgetConfirmpassword),e.forgetPassword!=e.forgetConfirmpassword)return void this.message.create("error","两次密码不一致");if(!e.forgerphoneCode)return void this.message.create("error","请输入验证码");let t=(Parse__default.serverURL?.split("parse")?.[0]||"https://server.fmode.cn/")+"api/auth/reset_password";this.http.post(t,{company:this.companyId,mobile:e.forgetusername,code:e.forgerphoneCode,password:e.forgetConfirmpassword}).subscribe((e=>{200==e.code?(this.message.create("success",e.msg),this.type="login"):this.message.create("error","验证码错误")}),(e=>{console.log(e.error),this.message.create("error",e.error.mess)}))}async registSubmitForm(e){for(const e in this.registForm.controls)this.registForm.controls[e].markAsDirty(),this.registForm.controls[e].updateValueAndValidity();this.registName=e.registName,this.registIdcard=e.registIdcard,this.registPhone=e.registPhone,this.phoneCode=e.phoneCode,this.regpassword=e.regpassword,this.confirmPassword=e.confirmPassword;let t=await this.verifyCode(this.registPhone,this.phoneCode);t&&200!=t.code?this.message.create("error",t.mess):this.queryUser()}getSelectEducation(){this.loginMobilePassword(),this.iseducation=!1}loginSMS(){let e=(Parse__default.serverURL?.split("parse")?.[0]||"https://server.fmode.cn/")+`api/auth/mobile?company=${this.companyId}&mobile=${this.username}&code=${this.smsCode}`;this.http.get(e).subscribe((e=>{if(console.log(e),200==e.code){this.message.create("success","登录成功");let t=e.data.token;Parse__default.User.become(t).then((e=>{this.router.navigate([decodeURIComponent(this.rootPage)])}))}else this.message.create("error","验证码错误")}),(e=>{console.log(e.error),this.message.create("error",e.error.mess)}))}async loginMobilePassword(){let e=await this.getMobileUser(this.username);e?this.authServ.login(e,this.password).then((async e=>{})).catch((e=>{console.log(e),this.message.create("error","错误的用户名或密码")})):this.message.create("error","用户不存在,请尝试其他登录方式")}async queryUser(){let e=new Parse__default.Query("_User");e.contains("username",this.registPhone),e.equalTo("company",this.companyId);let t=await e.first();t?.id?this.message.info("该账户已激活,使用手机号密码直接登录"):Parse__default.User.signUp(this.companyId+"-"+this.registPhone,this.regpassword,"").then((async e=>{e.id&&(console.log(e),e.set("company",{__type:"Pointer",className:"Company",objectId:this.companyId}),e.set("mobile",this.registPhone),e.set("type","user"),e.save(),this.username=this.registPhone,this.password=this.regpassword)}))}async getMobileUser(e){if(this.mobileUserMap[e])return this.mobileUserMap[e];let t=await this.novaCloud.api("/auth/getusername",{company:this.companyId,mobile:e});return console.log(t),t?.username&&(this.mobileUserMap[e]=t?.username),this.mobileUserMap[e]}forget(){this.type="forget"}backLogin(){this.type="login"}handleCancel(){this.isVisible=!1}handleOk(){Parse__default.User.signUp(this.registPhone,this.regpassword,"").then((async e=>{e.id&&(console.log(e),e.set("company",{__type:"Pointer",className:"Company",objectId:this.companyId}),e.save(),this.username=this.registPhone,this.password=this.regpassword)}))}async getCode(){if(null==this.registPhone||""==this.registPhone.trim())return void this.message.info("请输入注册手机号");if(!this.registPhone.match(/^1[3456789]\d{9}$/))return void this.message.info("请输入正确的手机号");let e=new Parse__default.Query("User");e.equalTo("username",this.registPhone),e.equalTo("company",this.companyId);let t=await e.first();if(t&&t.id)return void this.message.info("该手机号已注册,请使用账号密码登录");let n=localStorage.getItem("NOVA_APIG_SERVER");n=decodeURIComponent(atob(n));let o=n+"message";this.http.post(o,{company:this.companyId,mobile:this.registPhone,action:"regist"}).subscribe((e=>{this.vCode=e.data.code,this.countDownFun()}),(e=>{this.message.info("系统繁忙中,请稍后重试"),console.log(e)}))}async getCode2(){if(null==this.forgetusername||""==this.forgetusername.trim())return void this.message.info("请输入账号");if(!this.forgetusername.match(/^1[3456789]\d{9}$/))return void this.message.info("请输入正确的手机号");console.log(this.forgetusername);let e=new Parse__default.Query("User");if(e.equalTo("username",this.companyId+"-"+this.forgetusername),e.equalTo("company",this.companyId),!await e.first())return void this.message.info("账号不存在");let t=localStorage.getItem("NOVA_APIG_SERVER");t=decodeURIComponent(atob(t));let n=t+"message";this.http.post(n,{company:this.companyId,mobile:this.forgetusername,action:"resetPassword"}).subscribe((e=>{console.log(e),this.vCode=e.data.code,this.countDownFun()}),(e=>{this.message.info("系统繁忙中,请稍后重试"),console.log(e)}))}async verifyCode(e,t){let n=localStorage.getItem("NOVA_APIG_SERVER");n=decodeURIComponent(atob(n));let o=n+"verifyCode";return new Promise((async(n,i)=>{this.http.post(o,{mobile:e,code:t}).subscribe((e=>{n(e)}),(e=>{console.log(e),n(e.error)}))}))}countDownFun(){if(this.isCountDown=!0,0==this.countDown)return;let e=setInterval((()=>{this.countDown=this.countDown-1,0==this.countDown&&(clearInterval(e),this.countDown=60,this.isCountDown=!1)}),1e3)}constructor(e,t,n,o,i,a,r,s){this.authServ=e,this.novaCloud=t,this.fb=n,this.toastCtrl=o,this.router=i,this.route=a,this.activatedRoute=r,this.http=s,this.nums=["C","6","Z","t"],this.str="",this.tabIndex=0,this.codeVerified=!1,this.passwordVisible=!1,this.passwordVisible2=!1,this.passwordVisible3=!1,this.iseducation=!1,this.redirectUrl=localStorage.getItem("redirectUrl"),this.isSended=!1,this.isSending=!1,this.smsTimeCount=60,this.loading=!0,this.Lesson=[],this.myDate=new Date,this.isVisible=!1,this.type="login",this.mobileUserMap={},this.isOkLoading=!1,this.countDown=60,this.isCountDown=!1,this.mobileLogin=!1,this.logo="https://www.fmode.cn/images/ewm1.png",this.qrcode="https://www.fmode.cn/images/logo_main.png",this.message=this.authServ.message,this.userNameAsyncValidator=e=>new Observable((t=>{let n=/^1[3456789]\d{9}$/,o=e.value;setTimeout((()=>null==o||""==o.trim()?(this.userErrorTip="请输入登录账号",t.next({error:!0,duplicated:!0}),void t.complete()):o.match(n)?(t.next(null),void t.complete()):(this.userErrorTip="请输入正确的登录账号",t.next({error:!0,duplicated:!0}),void t.complete())),1e3)})),this.smsAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;if(null==n||""==n.trim())return this.smsCodeErrorTip="请输入短信验证码",t.next({error:!0,duplicated:!0}),void t.complete();t.next(null),t.complete()}),1e3)})),this.passwordAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;return null==n||""==n.trim()?(this.passwordErrorTip="请输入密码",t.next({error:!0,duplicated:!0}),void t.complete()):n.length<6?(this.passwordErrorTip="密码长度不得小于6位",t.next({error:!0,duplicated:!0}),void t.complete()):(t.next(null),void t.complete())}),1e3)})),this.codeAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;return null==n||""==n.trim()?(this.codeVerified=!1,this.codeErrorTip="请输入验证码",t.next({error:!0,duplicated:!0}),void t.complete()):n.length<4?(this.codeVerified=!1,this.codeErrorTip="验证码长度不得小于4位",t.next({error:!0,duplicated:!0}),void t.complete()):this.code.toLowerCase()!=n.toLowerCase()?(this.codeVerified=!1,this.codeErrorTip="验证码输入错误",t.next({error:!0,duplicated:!0}),void t.complete()):(this.codeVerified=!0,t.next(null),void t.complete())}),1e3)})),this.registIdcardAsyncValidator=e=>new Observable((t=>{let n=e.value;setTimeout((()=>null==n||""==n.trim()||!1===/^\d{17}(\d|X|x)$/.test(n)?(this.registIdcardErrorTip="请输入正确的身份证号码",t.next({error:!0,duplicated:!0}),void t.complete()):(t.next(null),void t.complete())),1e3)})),this.forgetNameAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;if(null==n||""==n.trim())return this.registNameErrorTip="请输入账户账号或者手机号",t.next({error:!0,duplicated:!0}),void t.complete();this.forgetusername=n,t.next(null),t.complete()}),1e3)})),this.forgetPasswordAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;return null==n||""==n.trim()?(this.passwordErrorTip="请输入新密码",t.next({error:!0,duplicated:!0}),void t.complete()):n.length<6?(this.passwordErrorTip="密码长度不得小于6位",t.next({error:!0,duplicated:!0}),void t.complete()):(this.forgetPassword=n,t.next(null),void t.complete())}),1e3)})),this.forgetConfirmPasswordAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;return null==n||""==n.trim()?(this.forgetphoneCodesErrorTip="请确认新密码",t.next({error:!0,duplicated:!0}),void t.complete()):n.length<6?(this.forgetphoneCodesErrorTip="密码长度不得小于6位",t.next({error:!0,duplicated:!0}),void t.complete()):(this.forgetConfirmpassword=n,t.next(null),void t.complete())}),1e3)})),this.forgetCodeAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;if(null==n||""==n.trim())return this.phoneCodesErrorTip="请输入新密码",t.next({error:!0,duplicated:!0}),void t.complete();this.forgerphoneCode=n,t.next(null),t.complete()}),1e3)})),this.registNameAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;if(null==n||""==n.trim())return this.registNameErrorTip="请输入姓名",t.next({error:!0,duplicated:!0}),void t.complete();this.registName=n,t.next(null),t.complete()}),1e3)})),this.registPhoneAsyncValidator=e=>new Observable((t=>{let n=e.value;setTimeout((()=>null==n||""==n.trim()?(this.registIdcardErrorTip="请输入正确的身份证号码",t.next({error:!0,duplicated:!0}),void t.complete()):!1===/^1[3456789]\d{9}$/.test(n)?(this.phoneErrorTip="请输入正确的手机号",t.next({error:!0,duplicated:!0}),void t.complete()):(t.next(null),void t.complete())),1e3)})),this.registCodeAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;if(null==n||""==n.trim())return this.phoneCodesErrorTip="请输入验证码",t.next({error:!0,duplicated:!0}),void t.complete();t.next(null),t.complete()}),1e3)})),this.regpasswordAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;return null==n||""==n.trim()?(this.regpasswordErrorTip="请输入密码",t.next({error:!0,duplicated:!0}),void t.complete()):n.length<6?(this.regpasswordErrorTip="密码长度不得小于6位",t.next({error:!0,duplicated:!0}),void t.complete()):n.length>12?(this.regpasswordErrorTip="密码长度不得大于12位",t.next({error:!0,duplicated:!0}),void t.complete()):(this.regpassword=n,t.next(null),void t.complete())}),1e3)})),this.confirmPasswordAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;return null==n||""==n.trim()?(this.confirmPasswordErrorTip="请确认密码",t.next({error:!0,duplicated:!0}),void t.complete()):n!=this.regpassword?(this.confirmPasswordErrorTip="两次输入密码不一致,请重新输入",t.next({error:!0,duplicated:!0}),void t.complete()):(this.confirmPassword=n,t.next(null),void t.complete())}),1e3)})),this.code="",this.initLoginForm(),this.route.paramMap.subscribe((async e=>{console.log(e),this.appId=e.get("appId"),await this.initAppConfig()||(this.companyId=e.get("companyId"),this.companyId||(this.companyId=localStorage.getItem("company")||"Q0DryNYA8g"),await this.initCompanyConfig())}))}async initCompanyConfig(){if(!this.companyId)return;let e=new Parse__default.Query("Company");this.company=await e.get(this.companyId),this.logo=this.company?.get("logo")||this.logo,this.qrcode=this.company?.get("qrcode")||this.qrcode,this.mobileLogin=this.company?.get("jpush")?.appkey||!1,this.rootPage=this.company?.get("rootPage")}async initAppConfig(){if(!this.appId)return!1;let e=new Parse__default.Query("App");return e.include("company"),this.app=await e.get(this.appId),console.log(this.app),this.logo=this.app?.get("logo")||this.logo,this.qrcode=this.app?.get("qrcode")||this.qrcode,this.mobileLogin=this.app?.get("jpush")?.appkey||!1,this.companyId=this.app?.get("company").id,this.rootPage=this.app?.get("rootPage"),!0}initLoginForm(){this.validateForm=this.fb.group({mobile:["",[Validators.required],[this.userNameAsyncValidator]],password:["",[Validators.required],[this.passwordAsyncValidator]],checkCode:["",[Validators.required],[this.codeAsyncValidator]]}),this.validateUserForm=this.fb.group({username:["",[Validators.required],[]],password:["",[Validators.required],[this.passwordAsyncValidator]],checkCode:["",[Validators.required],[this.codeAsyncValidator]]}),this.validateSMSForm=this.fb.group({mobile:["",[Validators.required],[this.userNameAsyncValidator]],password:[""],smsCode:["",[Validators.required],[this.smsAsyncValidator]],checkCode:["",[Validators.required],[this.codeAsyncValidator]]}),this.registForm=this.fb.group({registName:["",[Validators.required],[this.registNameAsyncValidator]],registIdcard:["",[Validators.required],[this.registIdcardAsyncValidator]],registPhone:["",[Validators.required],[this.registPhoneAsyncValidator]],phoneCode:["",[Validators.required],[this.registCodeAsyncValidator]],regpassword:["",[Validators.required],[this.regpasswordAsyncValidator]],confirmPassword:["",[Validators.required],[this.confirmPasswordAsyncValidator]]}),this.forgetForm=this.fb.group({forgetusername:["",[Validators.required],[this.forgetNameAsyncValidator]],forgetPassword:["",[Validators.required],[this.forgetPasswordAsyncValidator]],forgetConfirmpassword:["",[Validators.required],[this.forgetConfirmPasswordAsyncValidator]],forgerphoneCode:["",[Validators.required],[this.registCodeAsyncValidator]]})}ngOnInit(){this.activatedRoute.paramMap.subscribe((e=>{e.get("p")?localStorage.setItem("pid",e.get("p")):localStorage.setItem("company",this.companyId)})),this.creatCode()}creatCode(){this.code="";let e=[0,1,2,3,4,5,6,7,8,9,"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];for(let t=0;t<4;t++){let t=Math.floor(52*Math.random());this.code+=e[t]}}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:LoginComponent,deps:[{token:AuthService},{token:NovaCloudService},{token:i6.FormBuilder},{token:i2$2.ToastController},{token:i1$1.Router},{token:i1$1.ActivatedRoute},{token:i1$1.ActivatedRoute},{token:i1.HttpClient}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:LoginComponent,selector:"app-pcuser-login",ngImport:i0,template:'<div class="student-login-layout">\n <div class="nav_center">\n <img [src]="logo" alt="" class="login_img">\n <div class="nav_login">\n <nz-tabset [nzSelectedIndex]="tabIndex" [nzTabPosition]="\'top\'">\n\n \x3c!-- 登录:手机号+密码登入 --\x3e\n <nz-tab nzTitle="手机密码" style="color: #000000;">\n <ng-container *ngIf="type == \'login\'">\n <form nz-form [formGroup]="validateForm" (ngSubmit)="submitFormMobilePassword(validateForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>手机号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="mobile" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="password" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item class="form-control-contain">\n <nz-form-label [nzSpan]="5" class="contain_yanzm" nzRequired >验证码 </nz-form-label>\n <nz-form-control [nzSpan]="6" nzErrorTip="{{codeErrorTip}}" class="contain_input_yanzm">\n <input style="font-size:14px" title="请输入验证码" nz-input type="text" formControlName="checkCode"\n placeholder="区分大小写" />\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="codeText">\n <div style=" height: 100%; margin: 0 4px; text-align: center; letter-spacing: 2px;">{{code}}</div>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div (click)="creatCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 换一个\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button nz-button nzType="primary" [nzSize]="\'large\'" [disabled]="!validateForm.valid">登录</button>\n </div>\n <div class="forget">\n <h6 (click)="forget()">忘记密码</h6>\n </div>\n </form>\n </ng-container>\n <ng-container *ngIf="type == \'forget\'">\n <form nz-form [formGroup]="forgetForm" (ngSubmit)="forgetFormFun(forgetForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>登录账号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="forgetusername" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>新 密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetPassword" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>确认密码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{forgetphoneCodesErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetConfirmpassword" placeholder="请再次输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item class="forget_contain">\n <nz-form-label [nzSpan]="5" nzRequired >验 证 码</nz-form-label>\n <nz-form-control [nzSpan]="8" nzHasFeedback nzErrorTip="{{phoneCodesErrorTip}}" class="codeInput">\n <input style="font-size: 18px;" nz-input type="text" formControlName="forgerphoneCode"\n placeholder="手机验证码" />\n </nz-form-control>\n <nz-form-control [nzSpan]="6" class="getCode">\n <div *ngIf="!isCountDown" (click)="getCode2()" class="get_code"\n style="background-color:#40a9ff;cursor: pointer; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n 获取验证码\n </div>\n <div *ngIf="isCountDown"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n {{countDown}}/秒\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button style="width: 348px;" nz-button nzType="primary" [nzSize]="\'large\'"\n [disabled]="!forgetForm.valid">重置密码</button>\n </div>\n <div class="forget">\n <h6 (click)="backLogin()">返回登录</h6>\n </div>\n </form>\n </ng-container>\n\n </nz-tab>\n\n \x3c!-- 登录:帐号+密码登入 --\x3e\n <nz-tab nzTitle="帐号密码" style="color: #000000;">\n <ng-container *ngIf="type == \'login\'">\n <form nz-form [formGroup]="validateUserForm" (ngSubmit)="submitFormUserPassword(validateUserForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>帐 号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="username" placeholder="请输入帐号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="password" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item class="form-control-contain">\n <nz-form-label [nzSpan]="5" class="contain_yanzm" nzRequired >验证码 </nz-form-label>\n <nz-form-control [nzSpan]="6" nzErrorTip="{{codeErrorTip}}" class="contain_input_yanzm">\n <input style="font-size:14px" title="请输入验证码" nz-input type="text" formControlName="checkCode"\n placeholder="区分大小写" />\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="codeText">\n <div style=" height: 100%; margin: 0 4px; text-align: center; letter-spacing: 2px;">{{code}}</div>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div (click)="creatCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 换一个\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button nz-button nzType="primary" [nzSize]="\'large\'" [disabled]="!validateUserForm.valid">登录</button>\n </div>\n </form>\n </ng-container>\n <ng-container *ngIf="type == \'forget\'">\n <form nz-form [formGroup]="forgetForm" (ngSubmit)="forgetFormFun(forgetForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>登录账号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="forgetusername" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>新 密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetPassword" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>确认密码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{forgetphoneCodesErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetConfirmpassword" placeholder="请再次输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item class="forget_contain">\n <nz-form-label [nzSpan]="5" nzRequired >验 证 码</nz-form-label>\n <nz-form-control [nzSpan]="8" nzHasFeedback nzErrorTip="{{phoneCodesErrorTip}}" class="codeInput">\n <input style="font-size: 18px;" nz-input type="text" formControlName="forgerphoneCode"\n placeholder="手机验证码" />\n </nz-form-control>\n <nz-form-control [nzSpan]="6" class="getCode">\n <div *ngIf="!isCountDown" (click)="getCode2()" class="get_code"\n style="background-color:#40a9ff;cursor: pointer; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n 获取验证码\n </div>\n <div *ngIf="isCountDown"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n {{countDown}}/秒\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button style="width: 348px;" nz-button nzType="primary" [nzSize]="\'large\'"\n [disabled]="!forgetForm.valid">重置密码</button>\n </div>\n <div class="forget">\n <h6 (click)="backLogin()">返回登录</h6>\n </div>\n </form>\n </ng-container>\n\n </nz-tab>\n \x3c!-- 登录:手机号+验证码登入 --\x3e\n <nz-tab nzTitle="短信验证" style="color: #000000;">\n <ng-container *ngIf="type == \'login\'">\n <form nz-form [formGroup]="validateSMSForm" (ngSubmit)="submitFormMobileSMS(validateSMSForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>手 机 号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="mobile" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item class="form-control-contain">\n <nz-form-label [nzSpan]="5" class="contain_yanzm" nzRequired >验证码</nz-form-label>\n <nz-form-control [nzSpan]="6" nzErrorTip="{{codeErrorTip}}" class="contain_input_yanzm">\n <input style="font-size:14px" title="请输入验证码" nz-input type="text" formControlName="checkCode"\n placeholder="区分大小写" />\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="codeText">\n <div style=" height: 100%; margin: 0 4px; text-align: center; letter-spacing: 2px;">{{code}}</div>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div (click)="creatCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 换一个\n </div>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>短信码</nz-form-label>\n <nz-form-control [nzSpan]="10" nzErrorTip="{{smsCodeErrorTip}}">\n <nz-input-group>\n <input nz-input [type]="\'text\'" [disabled]="!isSended || !codeVerified" formControlName="smsCode" placeholder="请输入短信验证码" />\n </nz-input-group>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div *ngIf="!isSending" (click)="sendSMSCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 获取验证码\n </div>\n <div *ngIf="isSending"\n style="background-color:#eff5f9; color: rgb(118, 117, 117); padding: 5px; text-align: center;">\n {{smsTimeCount}}\n </div>\n </nz-form-control>\n </nz-form-item>\n \n <div class="login_btn">\n <button nz-button nzType="primary" [nzSize]="\'large\'" [disabled]="!validateSMSForm.valid">登录</button>\n </div>\n </form>\n </ng-container>\n </nz-tab>\n\n \x3c!-- 注册:企业用户Profile开通 --\x3e\n <nz-tab *ngIf="mobileLogin" nzTitle="开通" style="color: #000000;" class="activation">\n <form nz-form [formGroup]="registForm" (ngSubmit)="registSubmitForm(registForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>开通证件</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzValidatingTip="验证中..."\n nzErrorTip="{{registIdcardErrorTip}}">\n <input title="请输入身份证号码" nz-input formControlName="registIdcard" placeholder="请输入身份证号码" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>开通姓名</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{registNameErrorTip}}">\n <input nz-input type="text" formControlName="registName" placeholder="请输入姓名" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>绑定手机号</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{phoneErrorTip}}">\n <input [(ngModel)]="registPhone" nz-input style="font-size: 18px;" type="text"\n formControlName="registPhone" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item class="verifyCode">\n <nz-form-label [nzSpan]="7" nzRequired>手机验证码</nz-form-label>\n <nz-form-control [nzSpan]="6" class="code_input" nzHasFeedback nzErrorTip="{{phoneCodesErrorTip}}">\n <input style="font-size: 18px;" nz-input type="text" formControlName="phoneCode" placeholder="手机验证码" />\n </nz-form-control>\n <nz-form-control [nzSpan]="6" class="codeContain">\n <div *ngIf="!isCountDown" (click)="getCode()"\n class="get_code"\n style="background-color:#40a9ff; cursor: pointer; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n 获验证码\n </div>\n <div *ngIf="isCountDown"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n {{countDown}}/秒\n </div>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>开通密码</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{regpasswordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate2">\n <input nz-input [type]="passwordVisible2 ? \'text\' : \'password\'" formControlName="regpassword"\n placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate2>\n <i nz-icon [nzType]="passwordVisible2 ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible2 = !passwordVisible2"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>确认密码</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{confirmPasswordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate3">\n <input nz-input [type]="passwordVisible3 ? \'text\' : \'password\'" formControlName="confirmPassword"\n placeholder="请确认密码" />\n </nz-input-group>\n <ng-template #suffixTemplate3>\n <i nz-icon [nzType]="passwordVisible3 ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible3 = !passwordVisible3"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button nz-button nzType="primary" [disabled]="!registForm.valid">申请开通</button>\n </div>\n </form>\n </nz-tab>\n </nz-tabset>\n <div class="nav_login_right">\n <p class="login_right_title">二维码</p>\n <img [src]="qrcode" alt="公众号二维码">\n <p>扫码进入微信端</p>\n \x3c!-- <p class="login_right_bottom">首次登录有惊喜</p> --\x3e\n </div>\n </div>\n\n <div class="loadWrap" style="display: flex;align-items: center;justify-content: center;width: 100%;height: 100%;"\n *ngIf="loading2">\n <nz-spin nzTip="加载中,请稍后...">\n <nz-alert nzType="info" nzMessage="课程加载中,请稍后..."></nz-alert>\n </nz-spin>\n </div>\n\n \x3c!-- 注销 --\x3e\n <nz-modal [(nzVisible)]="isVisible" nzTitle="手机号错误" (nzOnCancel)="handleCancel()" (nzOnOk)="handleOk()">\n <ng-container *nzModalContent>\n <p>手机号错误, 联系管理员核对信息</p>\n </ng-container>\n </nz-modal>\n </div>\n</div>\n',styles:[".student-login-layout{position:fixed;top:0;left:0;background:#fff;width:100%;height:100%;z-index:100;overflow:auto;background:url(https://cloud.fmode.cn/assets/bg-login.jpg) no-repeat;background-size:100% 100%}.student-login-layout .nav_center{width:800px;min-height:450px;margin:0 auto;top:50%;left:50%;transform:translate(-50%,-50%);background-size:inherit;position:absolute;padding:30px;text-align:center}.student-login-layout .nav_center .login_img{max-width:70%;max-height:100px}.student-login-layout .nav_center .nav_login{background:#ffffff1a}.student-login-layout .nav_center ::ng-deep .ant-tabs-tab-btn{font-size:22px}.student-login-layout .nav_center .ant-tabs-tab-btn{border-bottom:2px solid #1890ff}.student-login-layout .nav_center ::ng-deep .ant-tabs-nav{height:55px}.student-login-layout .nav_center ::ng-deep .ant-tabs-nav-list{width:100%;display:flex;justify-content:center;color:#000}.student-login-layout .nav_center ::ng-deep .ant-form-item-required{font-size:18px;font-weight:700}.student-login-layout .nav_center ::ng-deep .ng-invalid{font-size:18px}.student-login-layout .nav_center ::ng-deep .ng-valid{font-size:18px}.student-login-layout .nav_center ::ng-deep .ng-pending{font-size:18px}.student-login-layout .nav_center ::ng-deep .ant-form-item{display:flex;justify-content:center}.student-login-layout .nav_center ::ng-deep .ant-tabs-nav:before{border:none}.student-login-layout .nav_center .nav_login{display:flex;flex-direction:inherit;align-items:center;justify-content:center;width:100%;border-radius:2px;background-color:#fff;margin:0 auto;min-height:500px}.student-login-layout .nav_center .nav_login .login-form{max-width:300px}.student-login-layout .nav_center .nav_login [nz-form]{width:440px;max-width:500px}.student-login-layout .nav_center .nav_login .login_btn{width:400px;margin:0 auto;display:flex;justify-content:center}.student-login-layout .nav_center .nav_login .login_btn button{width:85%}.student-login-layout .nav_center .nav_login .forget{margin:10px 40px 0 auto;display:flex;justify-content:flex-end}.student-login-layout .nav_center .nav_login .forget h6{font-size:14px;color:#40a9ff}.student-login-layout .nav_center .nav_login .login-form-margin{margin-bottom:16px}.student-login-layout .nav_center .nav_login .login-form-forgot{float:right}.student-login-layout .nav_center .nav_login .login-form-button{width:100%}.student-login-layout .nav_center .nav_login .nav_login_right{height:100%;flex:2;border-left:2px dashed #e5e5e5;font-size:16px;display:flex;flex-direction:column;color:#626262;align-items:center;justify-content:center}.student-login-layout .nav_center .nav_login .nav_login_right .login_right_bottom{margin:40px 0 50px}.student-login-layout .nav_center .nav_login .nav_login_right img{width:160px}.student-login-layout .nav_center .iseducation{position:absolute;top:159px;background:#fff;width:90%;flex-direction:column;line-height:50px}.student-login-layout .nav_center .iseducation .login_btn{margin-top:30px}.student-login-layout .nav_center .iseducation .close_education{width:30px;height:30px;position:absolute;top:20px;right:10px;font-size:24px;background-color:#dddddddb;border-radius:15px;line-height:28px;cursor:pointer}.student-login-layout .nav_center .loadWrap{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}@media (min-width: 960px){.nav_center{width:90%}}@media (max-width: 760px){.student-login-layout .nav_center{width:100%}.student-login-layout .nav_center ::ng-deep .ant-form-item-explain{text-align:left!important}.student-login-layout .nav_center ::ng-deep .ng-invalid{font-size:13px!important}.student-login-layout .nav_center ::ng-deep .ant-tabs-tab-btn{font-size:18px}.student-login-layout .nav_center .login_btn{width:100%!important;margin:10px auto!important}.student-login-layout .nav_center .login_btn button{width:100%!important}.student-login-layout .nav_login [nz-form]{width:100%!important;max-width:auto;padding:0 30px;display:flex;justify-content:center;flex-direction:column}.student-login-layout .ant-form-item{margin-bottom:5px}.student-login-layout ::ng-deep .ant-form-item-required{font-size:12px!important;padding-bottom:0!important}.student-login-layout .ant-form-item-label{padding:0}.student-login-layout .form-control-contain{display:flex!important;justify-content:space-between!important;flex-wrap:wrap;margin-top:10px}.student-login-layout .form-control-contain .contain_yanzm{flex:0 0 30%}.student-login-layout .form-control-contain .contain_input_yanzm{flex:0 0 40%}.student-login-layout .form-control-contain .codeText{flex:0 0 30%}.student-login-layout .form-control-contain .switch{flex:0 0 100%}.verifyCode .code_input{flex:0 0 50%}.verifyCode .codeContain{margin-left:10px;flex:0 0 45%}.verifyCode .get_code{font-size:14px!important}.forget_contain .codeInput{flex:0 0 50%}.forget_contain .getCode{margin-left:10px;flex:0 0 45%}.get_code{font-size:14px!important}.iseducation{top:110px!important}.iseducation .close_education #login_btn{width:50%!important}}@media (max-width: 460px){.form-control-contain .switch{margin-top:10px!important}}\n"],dependencies:[{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:i6.ɵNgNoValidate,selector:"form:not([ngNoForm]):not([ngNativeValidate])"},{kind:"directive",type:i6.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:i6.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i6.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:i6.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:i6.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:i8.NzInputDirective,selector:"input[nz-input],textarea[nz-input]",inputs:["nzBorderless","nzSize","nzStepperless","nzStatus","disabled"],exportAs:["nzInput"]},{kind:"component",type:i8.NzInputGroupComponent,selector:"nz-input-group",inputs:["nzAddOnBeforeIcon","nzAddOnAfterIcon","nzPrefixIcon","nzSuffixIcon","nzAddOnBefore","nzAddOnAfter","nzPrefix","nzStatus","nzSuffix","nzSize","nzSearch","nzCompact"],exportAs:["nzInputGroup"]},{kind:"directive",type:i8.NzInputGroupWhitSuffixOrPrefixDirective,selector:"nz-input-group[nzSuffix], nz-input-group[nzPrefix]"},{kind:"component",type:i9.NzButtonComponent,selector:"button[nz-button], a[nz-button]",inputs:["nzBlock","nzGhost","nzSearch","nzLoading","nzDanger","disabled","tabIndex","nzType","nzShape","nzSize"],exportAs:["nzButton"]},{kind:"directive",type:i10.ɵNzTransitionPatchDirective,selector:"[nz-button], nz-button-group, [nz-icon], [nz-menu-item], [nz-submenu], nz-select-top-control, nz-select-placeholder, nz-input-group",inputs:["hidden"]},{kind:"directive",type:i11.NzWaveDirective,selector:'[nz-wave],button[nz-button]:not([nzType="link"]):not([nzType="text"])',inputs:["nzWaveExtraNode"],exportAs:["nzWave"]},{kind:"component",type:i12.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:i12.NzModalContentDirective,selector:"[nzModalContent]",exportAs:["nzModalContent"]},{kind:"component",type:i13.NzSpinComponent,selector:"nz-spin",inputs:["nzIndicator","nzSize","nzTip","nzDelay","nzSimple","nzSpinning"],exportAs:["nzSpin"]},{kind:"component",type:i14.NzTabSetComponent,selector:"nz-tabset",inputs:["nzSelectedIndex","nzTabPosition","nzTabBarExtraContent","nzCanDeactivate","nzAddIcon","nzTabBarStyle","nzType","nzSize","nzAnimated","nzTabBarGutter","nzHideAdd","nzCentered","nzHideAll","nzLinkRouter","nzLinkExact"],outputs:["nzSelectChange","nzSelectedIndexChange","nzTabListScroll","nzClose","nzAdd"],exportAs:["nzTabset"]},{kind:"component",type:i14.NzTabComponent,selector:"nz-tab",inputs:["nzTitle","nzClosable","nzCloseIcon","nzDisabled","nzForceRender"],outputs:["nzSelect","nzDeselect","nzClick","nzContextmenu"],exportAs:["nzTab"]},{kind:"directive",type:i15.NzColDirective,selector:"[nz-col],nz-col,nz-form-control,nz-form-label",inputs:["nzFlex","nzSpan","nzOrder","nzOffset","nzPush","nzPull","nzXs","nzSm","nzMd","nzLg","nzXl","nzXXl"],exportAs:["nzCol"]},{kind:"directive",type:i15.NzRowDirective,selector:"[nz-row],nz-row,nz-form-item",inputs:["nzAlign","nzJustify","nzGutter"],exportAs:["nzRow"]},{kind:"directive",type:i16.NzFormDirective,selector:"[nz-form]",inputs:["nzLayout","nzNoColon","nzAutoTips","nzDisableAutoTips","nzTooltipIcon","nzLabelAlign","nzLabelWrap"],exportAs:["nzForm"]},{kind:"component",type:i16.NzFormItemComponent,selector:"nz-form-item",exportAs:["nzFormItem"]},{kind:"component",type:i16.NzFormLabelComponent,selector:"nz-form-label",inputs:["nzFor","nzRequired","nzNoColon","nzTooltipTitle","nzTooltipIcon","nzLabelAlign","nzLabelWrap"],exportAs:["nzFormLabel"]},{kind:"component",type:i16.NzFormControlComponent,selector:"nz-form-control",inputs:["nzSuccessTip","nzWarningTip","nzErrorTip","nzValidatingTip","nzExtra","nzAutoTips","nzDisableAutoTips","nzHasFeedback","nzValidateStatus"],exportAs:["nzFormControl"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:LoginComponent,decorators:[{type:Component,args:[{selector:"app-pcuser-login",template:'<div class="student-login-layout">\n <div class="nav_center">\n <img [src]="logo" alt="" class="login_img">\n <div class="nav_login">\n <nz-tabset [nzSelectedIndex]="tabIndex" [nzTabPosition]="\'top\'">\n\n \x3c!-- 登录:手机号+密码登入 --\x3e\n <nz-tab nzTitle="手机密码" style="color: #000000;">\n <ng-container *ngIf="type == \'login\'">\n <form nz-form [formGroup]="validateForm" (ngSubmit)="submitFormMobilePassword(validateForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>手机号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="mobile" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="password" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item class="form-control-contain">\n <nz-form-label [nzSpan]="5" class="contain_yanzm" nzRequired >验证码 </nz-form-label>\n <nz-form-control [nzSpan]="6" nzErrorTip="{{codeErrorTip}}" class="contain_input_yanzm">\n <input style="font-size:14px" title="请输入验证码" nz-input type="text" formControlName="checkCode"\n placeholder="区分大小写" />\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="codeText">\n <div style=" height: 100%; margin: 0 4px; text-align: center; letter-spacing: 2px;">{{code}}</div>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div (click)="creatCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 换一个\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button nz-button nzType="primary" [nzSize]="\'large\'" [disabled]="!validateForm.valid">登录</button>\n </div>\n <div class="forget">\n <h6 (click)="forget()">忘记密码</h6>\n </div>\n </form>\n </ng-container>\n <ng-container *ngIf="type == \'forget\'">\n <form nz-form [formGroup]="forgetForm" (ngSubmit)="forgetFormFun(forgetForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>登录账号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="forgetusername" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>新 密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetPassword" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>确认密码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{forgetphoneCodesErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetConfirmpassword" placeholder="请再次输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item class="forget_contain">\n <nz-form-label [nzSpan]="5" nzRequired >验 证 码</nz-form-label>\n <nz-form-control [nzSpan]="8" nzHasFeedback nzErrorTip="{{phoneCodesErrorTip}}" class="codeInput">\n <input style="font-size: 18px;" nz-input type="text" formControlName="forgerphoneCode"\n placeholder="手机验证码" />\n </nz-form-control>\n <nz-form-control [nzSpan]="6" class="getCode">\n <div *ngIf="!isCountDown" (click)="getCode2()" class="get_code"\n style="background-color:#40a9ff;cursor: pointer; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n 获取验证码\n </div>\n <div *ngIf="isCountDown"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n {{countDown}}/秒\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button style="width: 348px;" nz-button nzType="primary" [nzSize]="\'large\'"\n [disabled]="!forgetForm.valid">重置密码</button>\n </div>\n <div class="forget">\n <h6 (click)="backLogin()">返回登录</h6>\n </div>\n </form>\n </ng-container>\n\n </nz-tab>\n\n \x3c!-- 登录:帐号+密码登入 --\x3e\n <nz-tab nzTitle="帐号密码" style="color: #000000;">\n <ng-container *ngIf="type == \'login\'">\n <form nz-form [formGroup]="validateUserForm" (ngSubmit)="submitFormUserPassword(validateUserForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>帐 号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="username" placeholder="请输入帐号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="password" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item class="form-control-contain">\n <nz-form-label [nzSpan]="5" class="contain_yanzm" nzRequired >验证码 </nz-form-label>\n <nz-form-control [nzSpan]="6" nzErrorTip="{{codeErrorTip}}" class="contain_input_yanzm">\n <input style="font-size:14px" title="请输入验证码" nz-input type="text" formControlName="checkCode"\n placeholder="区分大小写" />\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="codeText">\n <div style=" height: 100%; margin: 0 4px; text-align: center; letter-spacing: 2px;">{{code}}</div>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div (click)="creatCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 换一个\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button nz-button nzType="primary" [nzSize]="\'large\'" [disabled]="!validateUserForm.valid">登录</button>\n </div>\n </form>\n </ng-container>\n <ng-container *ngIf="type == \'forget\'">\n <form nz-form [formGroup]="forgetForm" (ngSubmit)="forgetFormFun(forgetForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>登录账号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="forgetusername" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>新 密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetPassword" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>确认密码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{forgetphoneCodesErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetConfirmpassword" placeholder="请再次输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item class="forget_contain">\n <nz-form-label [nzSpan]="5" nzRequired >验 证 码</nz-form-label>\n <nz-form-control [nzSpan]="8" nzHasFeedback nzErrorTip="{{phoneCodesErrorTip}}" class="codeInput">\n <input style="font-size: 18px;" nz-input type="text" formControlName="forgerphoneCode"\n placeholder="手机验证码" />\n </nz-form-control>\n <nz-form-control [nzSpan]="6" class="getCode">\n <div *ngIf="!isCountDown" (click)="getCode2()" class="get_code"\n style="background-color:#40a9ff;cursor: pointer; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n 获取验证码\n </div>\n <div *ngIf="isCountDown"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n {{countDown}}/秒\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button style="width: 348px;" nz-button nzType="primary" [nzSize]="\'large\'"\n [disabled]="!forgetForm.valid">重置密码</button>\n </div>\n <div class="forget">\n <h6 (click)="backLogin()">返回登录</h6>\n </div>\n </form>\n </ng-container>\n\n </nz-tab>\n \x3c!-- 登录:手机号+验证码登入 --\x3e\n <nz-tab nzTitle="短信验证" style="color: #000000;">\n <ng-container *ngIf="type == \'login\'">\n <form nz-form [formGroup]="validateSMSForm" (ngSubmit)="submitFormMobileSMS(validateSMSForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>手 机 号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="mobile" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item class="form-control-contain">\n <nz-form-label [nzSpan]="5" class="contain_yanzm" nzRequired >验证码</nz-form-label>\n <nz-form-control [nzSpan]="6" nzErrorTip="{{codeErrorTip}}" class="contain_input_yanzm">\n <input style="font-size:14px" title="请输入验证码" nz-input type="text" formControlName="checkCode"\n placeholder="区分大小写" />\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="codeText">\n <div style=" height: 100%; margin: 0 4px; text-align: center; letter-spacing: 2px;">{{code}}</div>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div (click)="creatCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 换一个\n </div>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>短信码</nz-form-label>\n <nz-form-control [nzSpan]="10" nzErrorTip="{{smsCodeErrorTip}}">\n <nz-input-group>\n <input nz-input [type]="\'text\'" [disabled]="!isSended || !codeVerified" formControlName="smsCode" placeholder="请输入短信验证码" />\n </nz-input-group>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div *ngIf="!isSending" (click)="sendSMSCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 获取验证码\n </div>\n <div *ngIf="isSending"\n style="background-color:#eff5f9; color: rgb(118, 117, 117); padding: 5px; text-align: center;">\n {{smsTimeCount}}\n </div>\n </nz-form-control>\n </nz-form-item>\n \n <div class="login_btn">\n <button nz-button nzType="primary" [nzSize]="\'large\'" [disabled]="!validateSMSForm.valid">登录</button>\n </div>\n </form>\n </ng-container>\n </nz-tab>\n\n \x3c!-- 注册:企业用户Profile开通 --\x3e\n <nz-tab *ngIf="mobileLogin" nzTitle="开通" style="color: #000000;" class="activation">\n <form nz-form [formGroup]="registForm" (ngSubmit)="registSubmitForm(registForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>开通证件</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzValidatingTip="验证中..."\n nzErrorTip="{{registIdcardErrorTip}}">\n <input title="请输入身份证号码" nz-input formControlName="registIdcard" placeholder="请输入身份证号码" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>开通姓名</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{registNameErrorTip}}">\n <input nz-input type="text" formControlName="registName" placeholder="请输入姓名" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>绑定手机号</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{phoneErrorTip}}">\n <input [(ngModel)]="registPhone" nz-input style="font-size: 18px;" type="text"\n formControlName="registPhone" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item class="verifyCode">\n <nz-form-label [nzSpan]="7" nzRequired>手机验证码</nz-form-label>\n <nz-form-control [nzSpan]="6" class="code_input" nzHasFeedback nzErrorTip="{{phoneCodesErrorTip}}">\n <input style="font-size: 18px;" nz-input type="text" formControlName="phoneCode" placeholder="手机验证码" />\n </nz-form-control>\n <nz-form-control [nzSpan]="6" class="codeContain">\n <div *ngIf="!isCountDown" (click)="getCode()"\n class="get_code"\n style="background-color:#40a9ff; cursor: pointer; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n 获验证码\n </div>\n <div *ngIf="isCountDown"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n {{countDown}}/秒\n </div>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>开通密码</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{regpasswordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate2">\n <input nz-input [type]="passwordVisible2 ? \'text\' : \'password\'" formControlName="regpassword"\n placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate2>\n <i nz-icon [nzType]="passwordVisible2 ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible2 = !passwordVisible2"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>确认密码</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{confirmPasswordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate3">\n <input nz-input [type]="passwordVisible3 ? \'text\' : \'password\'" formControlName="confirmPassword"\n placeholder="请确认密码" />\n </nz-input-group>\n <ng-template #suffixTemplate3>\n <i nz-icon [nzType]="passwordVisible3 ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible3 = !passwordVisible3"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button nz-button nzType="primary" [disabled]="!registForm.valid">申请开通</button>\n </div>\n </form>\n </nz-tab>\n </nz-tabset>\n <div class="nav_login_right">\n <p class="login_right_title">二维码</p>\n <img [src]="qrcode" alt="公众号二维码">\n <p>扫码进入微信端</p>\n \x3c!-- <p class="login_right_bottom">首次登录有惊喜</p> --\x3e\n </div>\n </div>\n\n <div class="loadWrap" style="display: flex;align-items: center;justify-content: center;width: 100%;height: 100%;"\n *ngIf="loading2">\n <nz-spin nzTip="加载中,请稍后...">\n <nz-alert nzType="info" nzMessage="课程加载中,请稍后..."></nz-alert>\n </nz-spin>\n </div>\n\n \x3c!-- 注销 --\x3e\n <nz-modal [(nzVisible)]="isVisible" nzTitle="手机号错误" (nzOnCancel)="handleCancel()" (nzOnOk)="handleOk()">\n <ng-container *nzModalContent>\n <p>手机号错误, 联系管理员核对信息</p>\n </ng-container>\n </nz-modal>\n </div>\n</div>\n',styles:[".student-login-layout{position:fixed;top:0;left:0;background:#fff;width:100%;height:100%;z-index:100;overflow:auto;background:url(https://cloud.fmode.cn/assets/bg-login.jpg) no-repeat;background-size:100% 100%}.student-login-layout .nav_center{width:800px;min-height:450px;margin:0 auto;top:50%;left:50%;transform:translate(-50%,-50%);background-size:inherit;position:absolute;padding:30px;text-align:center}.student-login-layout .nav_center .login_img{max-width:70%;max-height:100px}.student-login-layout .nav_center .nav_login{background:#ffffff1a}.student-login-layout .nav_center ::ng-deep .ant-tabs-tab-btn{font-size:22px}.student-login-layout .nav_center .ant-tabs-tab-btn{border-bottom:2px solid #1890ff}.student-login-layout .nav_center ::ng-deep .ant-tabs-nav{height:55px}.student-login-layout .nav_center ::ng-deep .ant-tabs-nav-list{width:100%;display:flex;justify-content:center;color:#000}.student-login-layout .nav_center ::ng-deep .ant-form-item-required{font-size:18px;font-weight:700}.student-login-layout .nav_center ::ng-deep .ng-invalid{font-size:18px}.student-login-layout .nav_center ::ng-deep .ng-valid{font-size:18px}.student-login-layout .nav_center ::ng-deep .ng-pending{font-size:18px}.student-login-layout .nav_center ::ng-deep .ant-form-item{display:flex;justify-content:center}.student-login-layout .nav_center ::ng-deep .ant-tabs-nav:before{border:none}.student-login-layout .nav_center .nav_login{display:flex;flex-direction:inherit;align-items:center;justify-content:center;width:100%;border-radius:2px;background-color:#fff;margin:0 auto;min-height:500px}.student-login-layout .nav_center .nav_login .login-form{max-width:300px}.student-login-layout .nav_center .nav_login [nz-form]{width:440px;max-width:500px}.student-login-layout .nav_center .nav_login .login_btn{width:400px;margin:0 auto;display:flex;justify-content:center}.student-login-layout .nav_center .nav_login .login_btn button{width:85%}.student-login-layout .nav_center .nav_login .forget{margin:10px 40px 0 auto;display:flex;justify-content:flex-end}.student-login-layout .nav_center .nav_login .forget h6{font-size:14px;color:#40a9ff}.student-login-layout .nav_center .nav_login .login-form-margin{margin-bottom:16px}.student-login-layout .nav_center .nav_login .login-form-forgot{float:right}.student-login-layout .nav_center .nav_login .login-form-button{width:100%}.student-login-layout .nav_center .nav_login .nav_login_right{height:100%;flex:2;border-left:2px dashed #e5e5e5;font-size:16px;display:flex;flex-direction:column;color:#626262;align-items:center;justify-content:center}.student-login-layout .nav_center .nav_login .nav_login_right .login_right_bottom{margin:40px 0 50px}.student-login-layout .nav_center .nav_login .nav_login_right img{width:160px}.student-login-layout .nav_center .iseducation{position:absolute;top:159px;background:#fff;width:90%;flex-direction:column;line-height:50px}.student-login-layout .nav_center .iseducation .login_btn{margin-top:30px}.student-login-layout .nav_center .iseducation .close_education{width:30px;height:30px;position:absolute;top:20px;right:10px;font-size:24px;background-color:#dddddddb;border-radius:15px;line-height:28px;cursor:pointer}.student-login-layout .nav_center .loadWrap{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}@media (min-width: 960px){.nav_center{width:90%}}@media (max-width: 760px){.student-login-layout .nav_center{width:100%}.student-login-layout .nav_center ::ng-deep .ant-form-item-explain{text-align:left!important}.student-login-layout .nav_center ::ng-deep .ng-invalid{font-size:13px!important}.student-login-layout .nav_center ::ng-deep .ant-tabs-tab-btn{font-size:18px}.student-login-layout .nav_center .login_btn{width:100%!important;margin:10px auto!important}.student-login-layout .nav_center .login_btn button{width:100%!important}.student-login-layout .nav_login [nz-form]{width:100%!important;max-width:auto;padding:0 30px;display:flex;justify-content:center;flex-direction:column}.student-login-layout .ant-form-item{margin-bottom:5px}.student-login-layout ::ng-deep .ant-form-item-required{font-size:12px!important;padding-bottom:0!important}.student-login-layout .ant-form-item-label{padding:0}.student-login-layout .form-control-contain{display:flex!important;justify-content:space-between!important;flex-wrap:wrap;margin-top:10px}.student-login-layout .form-control-contain .contain_yanzm{flex:0 0 30%}.student-login-layout .form-control-contain .contain_input_yanzm{flex:0 0 40%}.student-login-layout .form-control-contain .codeText{flex:0 0 30%}.student-login-layout .form-control-contain .switch{flex:0 0 100%}.verifyCode .code_input{flex:0 0 50%}.verifyCode .codeContain{margin-left:10px;flex:0 0 45%}.verifyCode .get_code{font-size:14px!important}.forget_contain .codeInput{flex:0 0 50%}.forget_contain .getCode{margin-left:10px;flex:0 0 45%}.get_code{font-size:14px!important}.iseducation{top:110px!important}.iseducation .close_education #login_btn{width:50%!important}}@media (max-width: 460px){.form-control-contain .switch{margin-top:10px!important}}\n"]}]}],ctorParameters:()=>[{type:AuthService},{type:NovaCloudService},{type:i6.FormBuilder},{type:i2$2.ToastController},{type:i1$1.Router},{type:i1$1.ActivatedRoute},{type:i1$1.ActivatedRoute},{type:i1.HttpClient}]});class ModalUserLoginComponent{constructor(e,t,n,o,i){this.authServ=e,this.router=t,this.route=n,this.http=o,this.toastCtrl=i,this.isUserRuleChecked=!1,this.loginInfo={mobile:"",code:""},this.localCodeNum="",this.msg=this.authServ.message,this.countdown=60,this.buttonText="获取验证码",this.isCountingdown=!1,this.drawCode=[]}ngOnInit(){this.close()}ngAfterViewInit(){this.setActiveButton(this.authServ.activeButton)}signMobilePassword(){this.mobile&&this.password?this.password==this.password2?this.authServ.signMobilePassword(this.mobile,this.password).then((e=>{e?.id&&this.setActiveButton("账号密码")})).catch((e=>{this.msg.error("注册失败,请更换手机号注册")})):this.msg.error("两次输入密码不同,请检查"):this.msg.error("请输入完整手机号和密码")}loginMobilePassword(){this.mobile&&this.password?this.authServ.loginMobilePassword(this.mobile,this.password,this.msg):this.msg.error("请输入完整手机号和密码")}close(){let e=this.authServ.isGuardLock(this.router.url);this.authServ.isModalShow=e}goHome(){let e=this.router.url;return e?.indexOf("yuban")&&this.router.navigateByUrl("/app/home"),e.indexOf("chat")>-1?(this.router.navigateByUrl("/chat/home"),void(this.authServ.isModalShow=!1)):e.indexOf("imagine")>-1?(this.router.navigateByUrl("/imagine/home"),void(this.authServ.isModalShow=!1)):(this.router.navigateByUrl("/"),void(this.authServ.isModalShow=!1))}handleEscapeKey(e){this.close()}setActiveButton(e){this.authServ.activeButton=e,console.log(this.authServ.activeButton),this.updateDrawCode()}smsAutoLogin(){6==this.loginInfo.code?.length&&this.login()}startCountdown(){if(!String(this.loginInfo.mobile).match(/^1[3456789]\d{9}$/))return void this.msg.error("请填写正确手机号");let e=this.drawCode.join("");if(this.authServ.enabledLocalCode&&this.localCodeNum.toLowerCase()!=e.toLowerCase())return void this.msg.error("校验码不正确");let t=Parse__default.serverURL?.split("parse")?.[0]||"https://server.fmode.cn/";this.isCountingdown=!0,this.http.post(t+"api/apig/message",{company:this.authServ.company,mobile:this.loginInfo.mobile}).subscribe((e=>{console.log(e),this.msg.success("发送成功"),this.time(),this.updateDrawCode(),this.focusSmsCodeInput()}))}focusSmsCodeInput(){this.smsCodeInput.nativeElement.focus()}time(){this.isCountingdown=!0,this.buttonText=`${this.countdown}秒`;let e=setInterval((()=>{this.countdown--,this.buttonText=`${this.countdown}秒`,(0===this.countdown||this.countdown<0)&&(clearInterval(e),this.buttonText="重新发送",this.isCountingdown=!1,this.countdown=0)}),1e3)}async login(){let e;if(!String(this.loginInfo.mobile).match(/^1[3456789]\d{9}$/))return void this.msg.error("请填写正确手机号");if(!this.loginInfo.code)return void this.msg.error("请输入短信验证码");this.loginInfo.code=this.loginInfo.code?.slice(0,6);try{e=await this.authServ.loginCode(this.loginInfo.mobile,this.loginInfo.code,this.msg)}catch(e){}let t=Parse__default.User.current();if((e||t?.id)&&(console.log(e,t?.id,"close"),this.close(),this.loginInfo={mobile:"",code:""},this.localCodeNum="",this.toast({color:"success",message:"登录成功"}),"modal"==this.authServ.guardType)){let e=new URLSearchParams(location.search);e.set("t",String((new Date).getTime()));let t="/"+(location.origin+location.pathname).replaceAll(document.baseURI,"")+`?${e.toString()}`;console.log(t),this.router.navigateByUrl(t)}}async toast(e){e.position=e?.position||"top",e.duration=e?.duration||1500,e.color=e?.color||"primary",(await this.toastCtrl.create(e)).present()}updateDrawCode(){if(!this.authServ.enabledLocalCode)return;let e=100,t=document.getElementById("canvas");t&&this.canvasDom.nativeElement.removeChild(t),this.canvasDom.nativeElement;let n=document.createElement("canvas");n.width=100,n.height=44,n.className="canvas",n.setAttribute("id","canvas"),n.addEventListener("click",(()=>{this.updateDrawCode()}));let o=n.getContext("2d");n.width=e,n.height=44;let i="A,B,C,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,W,X,Y,Z,1,2,3,4,5,6,7,8,9,0,q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m".split(","),a=i.length;for(let e=0;e<=3;e++){let t=Math.floor(Math.random()*a),n=30*Math.random()*Math.PI/180,r=i[t];this.drawCode[e]=r;let s=10+20*e,l=20+8*Math.random();o.font="bold 23px 微软雅黑",o.translate(s,l),o.rotate(n),o.fillStyle=this.randomColor(),o.fillText(r,0,0),o.rotate(-n),o.translate(-s,-l)}for(let t=0;t<=5;t++)o.strokeStyle=this.randomColor(),o.beginPath(),o.moveTo(Math.random()*e,44*Math.random()),o.lineTo(Math.random()*e,44*Math.random()),o.stroke();for(let t=0;t<=30;t++){o.strokeStyle=this.randomColor(),o.beginPath();let t=Math.random()*e,n=44*Math.random();o.moveTo(t,n),o.lineTo(t+1,n+1),o.stroke()}this.canvasDom.nativeElement.appendChild(n)}randomColor(){return"rgb("+Math.floor(256*Math.random())+","+Math.floor(256*Math.random())+","+Math.floor(256*Math.random())+")"}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalUserLoginComponent,deps:[{token:AuthService},{token:i1$1.Router},{token:i1$1.ActivatedRoute},{token:i1.HttpClient},{token:i2$2.ToastController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ModalUserLoginComponent,isStandalone:!0,selector:"fm-modal-user-login",host:{listeners:{"document:keydown.escape":"handleEscapeKey($event)"}},viewQueries:[{propertyName:"canvasDom",first:!0,predicate:["canvasDom"],descendants:!0},{propertyName:"smsCodeInput",first:!0,predicate:["smsCodeInput"],descendants:!0}],ngImport:i0,template:'\x3c!--登录弹出框设置--\x3e\n\x3c!--背景灰色蒙版--\x3e\n<div\n class="popup"\n [style.display]="authServ.isModalShow ? \'block\' : \'none\'"\n (click)="close()"\n>\n <div class="popup-content" [class.fullscreen]="authServ.modalType==\'fullscreen\'" [class.sheet]="authServ.modalType==\'sheet\'"\n (click)="$event.stopPropagation()">\n <div class="popup-box">\n \x3c!--弹框内设置position:absolute,规范排版,后续只需position:relative增减内容--\x3e\n <div class="popup-box-content">\n <div class="logo-img-login">\n <img\n [src]="authServ.logoUrl"\n alt="fmode"\n />\n </div>\n\n \x3c!--关闭图标按钮--\x3e\n <div class="close-icon-box">\n <div class="iconfont icon-shanchu2" (click)="close()"></div>\n </div>\n \x3c!--按钮切换登录方式--\x3e\n <div class="button-box" *ngIf="authServ?.loginTypeCount>1">\n <div class="button-group">\n <button *ngIf="authServ?.loginOptions?.userpwd"\n class="login-select-button"\n [class.active]="authServ.activeButton === \'账号密码\'"\n (click)="setActiveButton(\'账号密码\')"\n >\n 账号密码\n </button>\n <button *ngIf="authServ?.loginOptions?.mobilecode"\n class="login-select-button"\n [class.active]="authServ.activeButton === \'短信验证\'"\n (click)="setActiveButton(\'短信验证\')"\n >\n 短信验证\n </button>\n <button *ngIf="authServ?.loginOptions?.wechat"\n class="login-select-button"\n [class.active]="authServ.activeButton === \'微信扫码\'"\n (click)="setActiveButton(\'微信扫码\')"\n >\n 微信扫码\n </button>\n </div>\n </div>\n\n \x3c!--手机验证码--\x3e\n <form class="message-form" [class.active]="authServ.activeButton === \'短信验证\'" *ngIf="authServ?.loginOptions?.mobilecode">\n <div class="login-input-box">\n <div class="popup-input-frontnumber">+86</div>\n <input\n class="popup-input-itemone"\n type="text"\n required="required"\n [(ngModel)]="loginInfo.mobile"\n [ngModelOptions]="{ standalone: true }"\n maxlength="12"\n placeholder="请输入手机号"\n />\n </div>\n <div *ngIf="authServ?.enabledLocalCode"\n class="login-input-box local-code" #canvasDom>\n <input\n class="popup-input-itemtwo"\n type="text"\n required="required"\n [(ngModel)]="localCodeNum"\n [ngModelOptions]="{ standalone: true }"\n maxlength="4"\n placeholder="请输入校验码"\n />\n \x3c!-- <canvas\n #canvas\n width="100"\n height="44"\n (click)="updateDrawCode()"\n class="canvas"\n ></canvas> --\x3e\n </div>\n <div class="login-input-box">\n <input #smsCodeInput\n class="popup-input-itemtwo"\n type="text"\n required="required"\n placeholder="请输入短信验证码"\n [(ngModel)]="loginInfo.code"\n (change)="smsAutoLogin()"\n [ngModelOptions]="{ standalone: true }"\n maxlength="6"\n />\n <button\n class="checknumber-button"\n type="submit"\n [value]="buttonText"\n [disabled]="isCountingdown"\n (click)="startCountdown()"\n [class.active]="isCountingdown"\n >\n {{buttonText}}\n </button>\n </div>\n\n \x3c!-- 用户协议 --\x3e\n <div class="rule-box">\n <span>未注册的手机号,将自动创建帐号并登录。</span>\n </div>\n\n <div class="login-submit-box">\n <button class="login-submit-button" type="submit" (click)="login()">\n 登录\n </button>\n </div>\n </form>\n\n \x3c!--账号密码登录--\x3e\n <form class="mobile-form" [class.active]="authServ.activeButton === \'账号密码\'" *ngIf="authServ?.loginOptions?.userpwd">\n <div class="login-input-box">\n <input\n maxlength="12"\n [(ngModel)]="mobile"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="text"\n required="required"\n placeholder="请输入手机号"\n />\n </div>\n\n <div class="login-input-box">\n <input\n [(ngModel)]="password"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="password"\n required="required"\n placeholder="请输入密码"\n />\n </div>\n\n \x3c!-- 记住密码 --\x3e\n <div class="passwprd-box">\n <div class="remember-password-box">\n <input type="checkbox" id="remember-password" />\n 记住密码\n </div>\n\n \x3c!-- 忘记密码 --\x3e\n <div class="password-forget" (click)="setActiveButton(\'注册帐号\')">\n 注册帐号\n </div>\n </div>\n\n \x3c!-- 用户协议 --\x3e\n <div class="rule-box">\n <span>\n <input type="checkbox" [(ngModel)]="isUserRuleChecked" [ngModelOptions]="{ standalone: true }" style="margin-right:5px"/>\n <span (click)="isUserRuleChecked=true">同意</span></span>\n <span (click)="isUserRuleChecked=true">《用户协议及隐私条款》</span>\n </div>\n\n\n \x3c!-- 忘记密码 --\x3e\n \x3c!-- <div class="password-forget">忘记密码?</div>\n </div> --\x3e\n\n <div class="login-submit-box">\n <button\n class="login-submit-button"\n type="submit"\n (click)="loginMobilePassword()"\n >\n 登录\n </button>\n </div>\n </form>\n\n \x3c!-- 帐号密码注册 --\x3e\n <form class="mobile-form" [class.active]="authServ.activeButton === \'注册帐号\'">\n <div class="login-input-box">\n <input\n [(ngModel)]="mobile"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="text"\n required="required"\n placeholder="请输入手机号"\n />\n </div>\n\n <div class="login-input-box">\n <input\n [(ngModel)]="password"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="password"\n required="required"\n placeholder="请输入密码"\n />\n </div>\n\n <div class="login-input-box">\n <input\n [(ngModel)]="password2"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="password"\n required="required"\n placeholder="请再次输入密码"\n />\n </div>\n\n <div class="login-submit-box">\n <button\n class="login-submit-button"\n type="submit"\n (click)="signMobilePassword()"\n >\n 注册\n </button>\n </div>\n </form>\n\n \x3c!--微信扫码登陆--\x3e\n <form class="wechat-form" [class.active]="authServ.activeButton === \'微信扫码\'" *ngIf="authServ?.loginOptions?.wechat">\n <div class="wechat-login-box">\n <img\n class="login-erweima-img"\n [src]="authServ.wechatUrl"\n alt="微信扫码登陆二维码"\n />\n </div>\n <div class="wechat-explain">使用微信扫一扫,扫码登录 "飞码AI"</div>\n </form>\n\n \x3c!--返回首页--\x3e\n <div class="back-home-box" *ngIf="authServ.showBackHome">\n <button class="back-homepage-button" (click)="goHome()">\n 返回首页\n </button>\n </div>\n </div>\n </div>\n </div>\n</div>\n',styles:['@charset "UTF-8";:host{--fmode-background-primary: #FFF;--login-color-primary: var(--fmode-color-primary,#0199f9);--login-bgcolor-primary: var(--fmode-login-bgcolor-primary,dodgerblue);--login-bgcolor-secondary: var(--fmode-login-bgcolor-secondary,#00dbde);--login-bgcolor-third: var(--fmode-login-bgcolor-third,#f902ff)}:host-context(body.dark) .popup{--login-color-primary: #7974ff;--fmode-background-primary: #000000}:host-context(body.dark) .popup .remember-password-box{color:#fff}.popup{display:flex;position:fixed;left:0;top:0;width:100%;height:100%;background-color:#0006;z-index:1000}@media screen and (max-width: 800px){.popup-content.fullscreen .popup-box{position:fixed!important;left:0!important;top:0!important;height:100vh!important;width:100vw!important;border-radius:0!important}.popup-content.fullscreen .popup-box .popup-box-content{padding-top:35%;border-radius:50px!important}.popup{background:#00000080}.popup-content.sheet{background:transparent!important}.popup-content.sheet .popup-box{position:fixed!important;left:0!important;top:calc(100vh - 360px);height:400px;width:100vw!important;border-radius:50px!important}.popup-content.sheet .popup-box .popup-box-content{border-radius:50px!important}}.popup-content{margin:7% auto;display:flex;width:500px;height:600px;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .popup-box{width:500px;height:600px;position:relative;border-radius:50px 5px;background-color:var(--login-bgcolor-primary);overflow:hidden}.popup-content .popup-box .popup-box-content{position:absolute;border-radius:50px 5px;inset:4px;background-color:var(--fmode-background-primary);z-index:1}.popup-content .popup-box .popup-box-content .logo-img-login{margin-top:35px;position:relative;width:100%;display:flex;justify-content:center;z-index:2}.popup-content .popup-box .popup-box-content .logo-img-login img{height:auto;max-width:150px}.popup-content .popup-box .popup-box-content .close-icon-box{position:relative;top:20px;right:20px;float:right;font-size:20px;cursor:pointer;z-index:2}.popup-content .popup-box .popup-box-content .button-box{display:flex;justify-content:center;padding-top:32px;padding-right:59px;padding-left:59px;border-radius:10px;width:100%;height:72px}.popup-content .popup-box .popup-box-content .button-box .button-group{position:relative;display:flex;width:100%;line-height:40px;border-radius:10px;background-color:plum;z-index:2}.popup-content .popup-box .popup-box-content .button-box .login-select-button{flex:1;outline:none;border:none;border-radius:10px;font-size:16px;cursor:pointer;color:#fff;background-color:inherit;transition:background-color .3s}.popup-content .popup-box .popup-box-content .button-box .login-select-button:hover{flex:1;outline:none;border:none;border-radius:10px;font-size:16px;cursor:pointer;color:#000;background-color:inherit;transition:background-color .3s}.popup-content .popup-box .popup-box-content .button-box .login-select-button.active{background-color:var(--login-color-primary);border-radius:10px}.popup-content .popup-box .popup-box-content input{color:#000}.popup-content .popup-box .popup-box-content .message-form,.popup-content .popup-box .popup-box-content .mobile-form,.popup-content .popup-box .popup-box-content .wechat-form{display:none}.popup-content .popup-box .popup-box-content .message-form.active,.popup-content .popup-box .popup-box-content .mobile-form.active,.popup-content .popup-box .popup-box-content .wechat-form.active{display:block}.popup-content .popup-box:before{content:"";position:absolute;top:-50%;left:-50%;width:500px;height:600px;background:linear-gradient(0deg,transparent,var(--login-bgcolor-third),var(--login-bgcolor-third));transform-origin:bottom right;animation:animate 6s linear infinite}.popup-content .popup-box:after{content:"";position:absolute;top:-50%;left:-50%;width:500px;height:600px;background:linear-gradient(0deg,transparent,var(--login-bgcolor-secondary),var(--login-bgcolor-secondary));transform-origin:bottom right;animation:animate 6s linear infinite;animation-delay:-3s}@keyframes animate{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.popup-content .login-submit-box{position:relative}.popup-content .login-submit-button{margin-top:15px;padding:6px;width:100%;line-height:40px;border-radius:10px;border:0;position:relative;box-shadow:0 2px 10px #00000029,0 3px 6px #0000001a;text-decoration:none;font-size:18px;font-weight:700;letter-spacing:2px;text-align:center;color:#fff;background-color:var(--login-color-primary);transition:.3s ease all;cursor:pointer;z-index:1}.popup-content .login-submit-button:before{transition:.5s all ease;position:absolute;inset:0 50%;opacity:0;content:"";background-color:var(--fmode-background-primary);z-index:-1}.popup-content .login-submit-button:hover{color:var(--login-color-primary)}.popup-content .login-submit-button:hover:before{border-radius:10px;border:3px solid var(--login-color-primary);box-sizing:border-box;transition:.5s all ease;left:0;right:0;opacity:1}.popup-content .login-submit-button:active{transform:scale(.9)}.popup-content .message-form{padding:6px 55px;display:flex;position:relative;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .message-form .login-input-box{display:flex;align-items:center;padding-top:10px}.popup-content .message-form .login-input-box .popup-input-frontnumber{padding:6px 12px;position:relative;border-radius:10px 0 0 10px;line-height:40px;font-size:18px;color:#4d4d4d;background-color:#ededed}.popup-content .message-form .popup-input-itemone{padding:6px 12px;position:relative;line-height:40px;border-radius:0 10px 10px 0;border:0;width:93%;outline:none;box-shadow:none;font-size:18px;letter-spacing:.03em;background-color:#ededed;transition:.5s}.popup-content .message-form .popup-input-itemtwo{padding:6px 12px 6px 16px;position:relative;line-height:40px;border-radius:10px;border:0;width:55%;outline:none;box-shadow:none;font-size:18px;letter-spacing:.03em;background-color:#ededed;transition:.5s}.popup-content .message-form .checknumber-button{margin-left:46px;padding:6px;border-radius:10px;line-height:40px;font-size:18px;width:124px;border:none;outline:none;cursor:pointer;color:#fff;background:var(--login-color-primary)}.popup-content .message-form .checknumber-button:hover{margin-left:46px;padding:6px;border-radius:10px;line-height:40px;font-size:18px;width:124px;border:none;outline:none;cursor:pointer;background:#4bace9}.popup-content .message-form .checknumber-button.active{background:#c7c7c7}.popup-content .rule-box{display:flex;padding-top:4px;padding-left:15px;padding-right:10px;justify-content:space-between;font-size:15px}.popup-content .rule-box span,.popup-content .rule-box ion-checkbox{font-size:15px;color:var(--login-color-primary)}.popup-content .mobile-form{padding:6px 55px;display:flex;position:relative;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .mobile-form .login-input-box{padding-top:10px}.popup-content .mobile-form .login-input-box .popup-input-itemnomal{margin-top:20px;padding:6px 12px 6px 14px;position:relative;line-height:40px;border-radius:10px;border:0;width:100%;outline:none;box-shadow:none;font-size:18px;letter-spacing:.03em;background-color:#ededed;transition:.5s}.popup-content .mobile-form .passwprd-box{display:flex;padding-top:4px;justify-content:space-between}.popup-content .mobile-form .passwprd-box .remember-password-box{margin:10px 0 0 15px;font-size:15px}.popup-content .mobile-form .passwprd-box .password-forget{margin-top:10px;margin-right:15px;font-size:15px;color:gray;cursor:pointer}.popup-content .mobile-form .passwprd-box .password-forget:hover{margin-top:10px;margin-right:15px;font-size:15px;color:#000;cursor:pointer}.popup-content .wechat-form{padding:6px 55px;display:flex;position:relative;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .wechat-form .wechat-login-box{display:flex;justify-content:center}.popup-content .wechat-form .wechat-login-box .login-erweima-img{margin-top:30px;width:210px}.popup-content .wechat-form .wechat-explain{padding-top:20px;font-size:16px;text-align:center}.popup-content .back-home-box{display:flex;justify-content:center;padding:6px 55px}.popup-content .back-homepage-button{margin-top:15px;padding:6px;width:100%;line-height:40px;border-radius:10px;border:0;position:relative;box-shadow:0 2px 10px #00000029,0 3px 6px #0000001a;text-decoration:none;font-size:18px;font-weight:700;letter-spacing:2px;text-align:center;color:#fff;background-color:var(--login-color-primary);transition:.3s ease all;cursor:pointer;x:1}.popup-content .back-homepage-button:before{transition:.5s all ease;position:absolute;inset:0 50%;opacity:0;content:"";background-color:var(--fmode-background-primary);z-index:-1}.popup-content .back-homepage-button:hover{color:var(--login-color-primary)}.popup-content .back-homepage-button:hover:before{border-radius:10px;border:3px solid var(--login-color-primary);box-sizing:border-box;transition:.5s all ease;left:0;right:0;opacity:1}.popup-content .local-code{justify-content:space-between}.popup-content .local-code .canvas{border:1px solid #c2def5;border-radius:5px;width:100px;height:44px}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i6.ɵNgNoValidate,selector:"form:not([ngNoForm]):not([ngNativeValidate])"},{kind:"directive",type:i6.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:i6.CheckboxControlValueAccessor,selector:"input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]"},{kind:"directive",type:i6.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i6.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:i6.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:i6.MaxLengthValidator,selector:"[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]",inputs:["maxlength"]},{kind:"directive",type:i6.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:i6.NgForm,selector:"form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]",inputs:["ngFormOptions"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"ngmodule",type:ReactiveFormsModule}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalUserLoginComponent,decorators:[{type:Component,args:[{standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,IonCheckbox],selector:"fm-modal-user-login",template:'\x3c!--登录弹出框设置--\x3e\n\x3c!--背景灰色蒙版--\x3e\n<div\n class="popup"\n [style.display]="authServ.isModalShow ? \'block\' : \'none\'"\n (click)="close()"\n>\n <div class="popup-content" [class.fullscreen]="authServ.modalType==\'fullscreen\'" [class.sheet]="authServ.modalType==\'sheet\'"\n (click)="$event.stopPropagation()">\n <div class="popup-box">\n \x3c!--弹框内设置position:absolute,规范排版,后续只需position:relative增减内容--\x3e\n <div class="popup-box-content">\n <div class="logo-img-login">\n <img\n [src]="authServ.logoUrl"\n alt="fmode"\n />\n </div>\n\n \x3c!--关闭图标按钮--\x3e\n <div class="close-icon-box">\n <div class="iconfont icon-shanchu2" (click)="close()"></div>\n </div>\n \x3c!--按钮切换登录方式--\x3e\n <div class="button-box" *ngIf="authServ?.loginTypeCount>1">\n <div class="button-group">\n <button *ngIf="authServ?.loginOptions?.userpwd"\n class="login-select-button"\n [class.active]="authServ.activeButton === \'账号密码\'"\n (click)="setActiveButton(\'账号密码\')"\n >\n 账号密码\n </button>\n <button *ngIf="authServ?.loginOptions?.mobilecode"\n class="login-select-button"\n [class.active]="authServ.activeButton === \'短信验证\'"\n (click)="setActiveButton(\'短信验证\')"\n >\n 短信验证\n </button>\n <button *ngIf="authServ?.loginOptions?.wechat"\n class="login-select-button"\n [class.active]="authServ.activeButton === \'微信扫码\'"\n (click)="setActiveButton(\'微信扫码\')"\n >\n 微信扫码\n </button>\n </div>\n </div>\n\n \x3c!--手机验证码--\x3e\n <form class="message-form" [class.active]="authServ.activeButton === \'短信验证\'" *ngIf="authServ?.loginOptions?.mobilecode">\n <div class="login-input-box">\n <div class="popup-input-frontnumber">+86</div>\n <input\n class="popup-input-itemone"\n type="text"\n required="required"\n [(ngModel)]="loginInfo.mobile"\n [ngModelOptions]="{ standalone: true }"\n maxlength="12"\n placeholder="请输入手机号"\n />\n </div>\n <div *ngIf="authServ?.enabledLocalCode"\n class="login-input-box local-code" #canvasDom>\n <input\n class="popup-input-itemtwo"\n type="text"\n required="required"\n [(ngModel)]="localCodeNum"\n [ngModelOptions]="{ standalone: true }"\n maxlength="4"\n placeholder="请输入校验码"\n />\n \x3c!-- <canvas\n #canvas\n width="100"\n height="44"\n (click)="updateDrawCode()"\n class="canvas"\n ></canvas> --\x3e\n </div>\n <div class="login-input-box">\n <input #smsCodeInput\n class="popup-input-itemtwo"\n type="text"\n required="required"\n placeholder="请输入短信验证码"\n [(ngModel)]="loginInfo.code"\n (change)="smsAutoLogin()"\n [ngModelOptions]="{ standalone: true }"\n maxlength="6"\n />\n <button\n class="checknumber-button"\n type="submit"\n [value]="buttonText"\n [disabled]="isCountingdown"\n (click)="startCountdown()"\n [class.active]="isCountingdown"\n >\n {{buttonText}}\n </button>\n </div>\n\n \x3c!-- 用户协议 --\x3e\n <div class="rule-box">\n <span>未注册的手机号,将自动创建帐号并登录。</span>\n </div>\n\n <div class="login-submit-box">\n <button class="login-submit-button" type="submit" (click)="login()">\n 登录\n </button>\n </div>\n </form>\n\n \x3c!--账号密码登录--\x3e\n <form class="mobile-form" [class.active]="authServ.activeButton === \'账号密码\'" *ngIf="authServ?.loginOptions?.userpwd">\n <div class="login-input-box">\n <input\n maxlength="12"\n [(ngModel)]="mobile"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="text"\n required="required"\n placeholder="请输入手机号"\n />\n </div>\n\n <div class="login-input-box">\n <input\n [(ngModel)]="password"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="password"\n required="required"\n placeholder="请输入密码"\n />\n </div>\n\n \x3c!-- 记住密码 --\x3e\n <div class="passwprd-box">\n <div class="remember-password-box">\n <input type="checkbox" id="remember-password" />\n 记住密码\n </div>\n\n \x3c!-- 忘记密码 --\x3e\n <div class="password-forget" (click)="setActiveButton(\'注册帐号\')">\n 注册帐号\n </div>\n </div>\n\n \x3c!-- 用户协议 --\x3e\n <div class="rule-box">\n <span>\n <input type="checkbox" [(ngModel)]="isUserRuleChecked" [ngModelOptions]="{ standalone: true }" style="margin-right:5px"/>\n <span (click)="isUserRuleChecked=true">同意</span></span>\n <span (click)="isUserRuleChecked=true">《用户协议及隐私条款》</span>\n </div>\n\n\n \x3c!-- 忘记密码 --\x3e\n \x3c!-- <div class="password-forget">忘记密码?</div>\n </div> --\x3e\n\n <div class="login-submit-box">\n <button\n class="login-submit-button"\n type="submit"\n (click)="loginMobilePassword()"\n >\n 登录\n </button>\n </div>\n </form>\n\n \x3c!-- 帐号密码注册 --\x3e\n <form class="mobile-form" [class.active]="authServ.activeButton === \'注册帐号\'">\n <div class="login-input-box">\n <input\n [(ngModel)]="mobile"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="text"\n required="required"\n placeholder="请输入手机号"\n />\n </div>\n\n <div class="login-input-box">\n <input\n [(ngModel)]="password"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="password"\n required="required"\n placeholder="请输入密码"\n />\n </div>\n\n <div class="login-input-box">\n <input\n [(ngModel)]="password2"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="password"\n required="required"\n placeholder="请再次输入密码"\n />\n </div>\n\n <div class="login-submit-box">\n <button\n class="login-submit-button"\n type="submit"\n (click)="signMobilePassword()"\n >\n 注册\n </button>\n </div>\n </form>\n\n \x3c!--微信扫码登陆--\x3e\n <form class="wechat-form" [class.active]="authServ.activeButton === \'微信扫码\'" *ngIf="authServ?.loginOptions?.wechat">\n <div class="wechat-login-box">\n <img\n class="login-erweima-img"\n [src]="authServ.wechatUrl"\n alt="微信扫码登陆二维码"\n />\n </div>\n <div class="wechat-explain">使用微信扫一扫,扫码登录 "飞码AI"</div>\n </form>\n\n \x3c!--返回首页--\x3e\n <div class="back-home-box" *ngIf="authServ.showBackHome">\n <button class="back-homepage-button" (click)="goHome()">\n 返回首页\n </button>\n </div>\n </div>\n </div>\n </div>\n</div>\n',styles:['@charset "UTF-8";:host{--fmode-background-primary: #FFF;--login-color-primary: var(--fmode-color-primary,#0199f9);--login-bgcolor-primary: var(--fmode-login-bgcolor-primary,dodgerblue);--login-bgcolor-secondary: var(--fmode-login-bgcolor-secondary,#00dbde);--login-bgcolor-third: var(--fmode-login-bgcolor-third,#f902ff)}:host-context(body.dark) .popup{--login-color-primary: #7974ff;--fmode-background-primary: #000000}:host-context(body.dark) .popup .remember-password-box{color:#fff}.popup{display:flex;position:fixed;left:0;top:0;width:100%;height:100%;background-color:#0006;z-index:1000}@media screen and (max-width: 800px){.popup-content.fullscreen .popup-box{position:fixed!important;left:0!important;top:0!important;height:100vh!important;width:100vw!important;border-radius:0!important}.popup-content.fullscreen .popup-box .popup-box-content{padding-top:35%;border-radius:50px!important}.popup{background:#00000080}.popup-content.sheet{background:transparent!important}.popup-content.sheet .popup-box{position:fixed!important;left:0!important;top:calc(100vh - 360px);height:400px;width:100vw!important;border-radius:50px!important}.popup-content.sheet .popup-box .popup-box-content{border-radius:50px!important}}.popup-content{margin:7% auto;display:flex;width:500px;height:600px;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .popup-box{width:500px;height:600px;position:relative;border-radius:50px 5px;background-color:var(--login-bgcolor-primary);overflow:hidden}.popup-content .popup-box .popup-box-content{position:absolute;border-radius:50px 5px;inset:4px;background-color:var(--fmode-background-primary);z-index:1}.popup-content .popup-box .popup-box-content .logo-img-login{margin-top:35px;position:relative;width:100%;display:flex;justify-content:center;z-index:2}.popup-content .popup-box .popup-box-content .logo-img-login img{height:auto;max-width:150px}.popup-content .popup-box .popup-box-content .close-icon-box{position:relative;top:20px;right:20px;float:right;font-size:20px;cursor:pointer;z-index:2}.popup-content .popup-box .popup-box-content .button-box{display:flex;justify-content:center;padding-top:32px;padding-right:59px;padding-left:59px;border-radius:10px;width:100%;height:72px}.popup-content .popup-box .popup-box-content .button-box .button-group{position:relative;display:flex;width:100%;line-height:40px;border-radius:10px;background-color:plum;z-index:2}.popup-content .popup-box .popup-box-content .button-box .login-select-button{flex:1;outline:none;border:none;border-radius:10px;font-size:16px;cursor:pointer;color:#fff;background-color:inherit;transition:background-color .3s}.popup-content .popup-box .popup-box-content .button-box .login-select-button:hover{flex:1;outline:none;border:none;border-radius:10px;font-size:16px;cursor:pointer;color:#000;background-color:inherit;transition:background-color .3s}.popup-content .popup-box .popup-box-content .button-box .login-select-button.active{background-color:var(--login-color-primary);border-radius:10px}.popup-content .popup-box .popup-box-content input{color:#000}.popup-content .popup-box .popup-box-content .message-form,.popup-content .popup-box .popup-box-content .mobile-form,.popup-content .popup-box .popup-box-content .wechat-form{display:none}.popup-content .popup-box .popup-box-content .message-form.active,.popup-content .popup-box .popup-box-content .mobile-form.active,.popup-content .popup-box .popup-box-content .wechat-form.active{display:block}.popup-content .popup-box:before{content:"";position:absolute;top:-50%;left:-50%;width:500px;height:600px;background:linear-gradient(0deg,transparent,var(--login-bgcolor-third),var(--login-bgcolor-third));transform-origin:bottom right;animation:animate 6s linear infinite}.popup-content .popup-box:after{content:"";position:absolute;top:-50%;left:-50%;width:500px;height:600px;background:linear-gradient(0deg,transparent,var(--login-bgcolor-secondary),var(--login-bgcolor-secondary));transform-origin:bottom right;animation:animate 6s linear infinite;animation-delay:-3s}@keyframes animate{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.popup-content .login-submit-box{position:relative}.popup-content .login-submit-button{margin-top:15px;padding:6px;width:100%;line-height:40px;border-radius:10px;border:0;position:relative;box-shadow:0 2px 10px #00000029,0 3px 6px #0000001a;text-decoration:none;font-size:18px;font-weight:700;letter-spacing:2px;text-align:center;color:#fff;background-color:var(--login-color-primary);transition:.3s ease all;cursor:pointer;z-index:1}.popup-content .login-submit-button:before{transition:.5s all ease;position:absolute;inset:0 50%;opacity:0;content:"";background-color:var(--fmode-background-primary);z-index:-1}.popup-content .login-submit-button:hover{color:var(--login-color-primary)}.popup-content .login-submit-button:hover:before{border-radius:10px;border:3px solid var(--login-color-primary);box-sizing:border-box;transition:.5s all ease;left:0;right:0;opacity:1}.popup-content .login-submit-button:active{transform:scale(.9)}.popup-content .message-form{padding:6px 55px;display:flex;position:relative;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .message-form .login-input-box{display:flex;align-items:center;padding-top:10px}.popup-content .message-form .login-input-box .popup-input-frontnumber{padding:6px 12px;position:relative;border-radius:10px 0 0 10px;line-height:40px;font-size:18px;color:#4d4d4d;background-color:#ededed}.popup-content .message-form .popup-input-itemone{padding:6px 12px;position:relative;line-height:40px;border-radius:0 10px 10px 0;border:0;width:93%;outline:none;box-shadow:none;font-size:18px;letter-spacing:.03em;background-color:#ededed;transition:.5s}.popup-content .message-form .popup-input-itemtwo{padding:6px 12px 6px 16px;position:relative;line-height:40px;border-radius:10px;border:0;width:55%;outline:none;box-shadow:none;font-size:18px;letter-spacing:.03em;background-color:#ededed;transition:.5s}.popup-content .message-form .checknumber-button{margin-left:46px;padding:6px;border-radius:10px;line-height:40px;font-size:18px;width:124px;border:none;outline:none;cursor:pointer;color:#fff;background:var(--login-color-primary)}.popup-content .message-form .checknumber-button:hover{margin-left:46px;padding:6px;border-radius:10px;line-height:40px;font-size:18px;width:124px;border:none;outline:none;cursor:pointer;background:#4bace9}.popup-content .message-form .checknumber-button.active{background:#c7c7c7}.popup-content .rule-box{display:flex;padding-top:4px;padding-left:15px;padding-right:10px;justify-content:space-between;font-size:15px}.popup-content .rule-box span,.popup-content .rule-box ion-checkbox{font-size:15px;color:var(--login-color-primary)}.popup-content .mobile-form{padding:6px 55px;display:flex;position:relative;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .mobile-form .login-input-box{padding-top:10px}.popup-content .mobile-form .login-input-box .popup-input-itemnomal{margin-top:20px;padding:6px 12px 6px 14px;position:relative;line-height:40px;border-radius:10px;border:0;width:100%;outline:none;box-shadow:none;font-size:18px;letter-spacing:.03em;background-color:#ededed;transition:.5s}.popup-content .mobile-form .passwprd-box{display:flex;padding-top:4px;justify-content:space-between}.popup-content .mobile-form .passwprd-box .remember-password-box{margin:10px 0 0 15px;font-size:15px}.popup-content .mobile-form .passwprd-box .password-forget{margin-top:10px;margin-right:15px;font-size:15px;color:gray;cursor:pointer}.popup-content .mobile-form .passwprd-box .password-forget:hover{margin-top:10px;margin-right:15px;font-size:15px;color:#000;cursor:pointer}.popup-content .wechat-form{padding:6px 55px;display:flex;position:relative;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .wechat-form .wechat-login-box{display:flex;justify-content:center}.popup-content .wechat-form .wechat-login-box .login-erweima-img{margin-top:30px;width:210px}.popup-content .wechat-form .wechat-explain{padding-top:20px;font-size:16px;text-align:center}.popup-content .back-home-box{display:flex;justify-content:center;padding:6px 55px}.popup-content .back-homepage-button{margin-top:15px;padding:6px;width:100%;line-height:40px;border-radius:10px;border:0;position:relative;box-shadow:0 2px 10px #00000029,0 3px 6px #0000001a;text-decoration:none;font-size:18px;font-weight:700;letter-spacing:2px;text-align:center;color:#fff;background-color:var(--login-color-primary);transition:.3s ease all;cursor:pointer;x:1}.popup-content .back-homepage-button:before{transition:.5s all ease;position:absolute;inset:0 50%;opacity:0;content:"";background-color:var(--fmode-background-primary);z-index:-1}.popup-content .back-homepage-button:hover{color:var(--login-color-primary)}.popup-content .back-homepage-button:hover:before{border-radius:10px;border:3px solid var(--login-color-primary);box-sizing:border-box;transition:.5s all ease;left:0;right:0;opacity:1}.popup-content .local-code{justify-content:space-between}.popup-content .local-code .canvas{border:1px solid #c2def5;border-radius:5px;width:100px;height:44px}\n']}]}],ctorParameters:()=>[{type:AuthService},{type:i1$1.Router},{type:i1$1.ActivatedRoute},{type:i1.HttpClient},{type:i2$2.ToastController}],propDecorators:{canvasDom:[{type:ViewChild,args:["canvasDom"]}],smsCodeInput:[{type:ViewChild,args:["smsCodeInput"]}],handleEscapeKey:[{type:HostListener,args:["document:keydown.escape",["$event"]]}]}});class CaptchaComponent{constructor(){this.type="input",this.canvas_id="canvasCode",this.drawCode=[],this.vCode="",this.changeVal=new EventEmitter,this.onEnter=new EventEmitter,this.code=""}ngOnInit(){}ngAfterViewInit(){this.updateDrawCode()}updateDrawCode(){let e=100,t=document.getElementById(this.canvas_id);t&&this.canvasDom.nativeElement.removeChild(t);let n=document.getElementById(this.canvas_id+"_a");n&&this.canvasDom.nativeElement.removeChild(n),this.canvasDom.nativeElement;let o=document.createElement("canvas");o.className="canvas",o.setAttribute("id",this.canvas_id),o.addEventListener("click",(()=>{this.updateDrawCode()}));let i=o.getContext("2d");o.width=e,o.height=38;let a="A,B,C,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,W,X,Y,Z,1,2,3,4,5,6,7,8,9,0,q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m".split(","),r=a.length;for(let e=0;e<=3;e++){let t=Math.floor(Math.random()*r),n=30*Math.random()*Math.PI/180,o=a[t];this.drawCode[e]=o;let s=10+20*e,l=20+8*Math.random();i.font="bold 23px 微软雅黑",i.translate(s,l),i.rotate(n),i.fillStyle=this.randomColor(),i.fillText(o,0,0),i.rotate(-n),i.translate(-s,-l)}for(let t=0;t<=5;t++)i.strokeStyle=this.randomColor(),i.beginPath(),i.moveTo(Math.random()*e,38*Math.random()),i.lineTo(Math.random()*e,38*Math.random()),i.stroke();for(let t=0;t<=30;t++){i.strokeStyle=this.randomColor(),i.beginPath();let t=Math.random()*e,n=38*Math.random();i.moveTo(t,n),i.lineTo(t+1,n+1),i.stroke()}this.code=this.drawCode.join(""),this.changeVal.emit({code:this.code,vCode:this.vCode}),this.canvasDom.nativeElement.appendChild(o);let s=document.createElement("a");s.setAttribute("id",this.canvas_id+"_a"),s.innerText="看不清,换一张",s.addEventListener("click",(()=>{this.updateDrawCode()})),this.canvasDom.nativeElement.appendChild(s)}randomColor(){return"rgb("+Math.floor(256*Math.random())+","+Math.floor(256*Math.random())+","+Math.floor(256*Math.random())+")"}enter(e){13==e.keyCode&&(this.changeVal.emit({code:this.code,vCode:this.vCode}),this.onEnter.emit())}onChange(){this.changeVal.emit({code:this.code,vCode:this.vCode})}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CaptchaComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CaptchaComponent,isStandalone:!0,selector:"fm-captcha",inputs:{type:"type",canvas_id:"canvas_id",drawCode:"drawCode",vCode:"vCode"},outputs:{changeVal:"changeVal",onEnter:"onEnter"},viewQueries:[{propertyName:"canvasDom",first:!0,predicate:["canvasDom"],descendants:!0}],ngImport:i0,template:'<ng-container *ngIf="type == \'input\'; else elseTemplate">\n <div class="captcha">\n <input\n nz-input\n class="code-input"\n type="text"\n [(ngModel)]="vCode"\n maxlength="4"\n placeholder="验证码"\n [nzStatus]="vCode.length == 4 ? \'\' : \'error\'"\n (keydown)="enter($event)"\n (change)="onChange()"\n />\n <div class="code-card" #canvasDom></div>\n </div>\n</ng-container>\n<ng-template #elseTemplate>\n <div class="captcha">\n <div class="code-card" #canvasDom></div>\n </div>\n</ng-template>\n',styles:[".code-card{display:flex;align-items:center}.code-card .canvas{border:1px solid #c2def5;border-radius:5px;width:100px;height:38px}.code-input{width:90px;padding:4px;height:38px;border:1px solid #cdcdcd}.code-input:focus{outline:1px solid #40a9ff}.captcha{display:flex;align-items:center}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i6.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:i6.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i6.MaxLengthValidator,selector:"[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]",inputs:["maxlength"]},{kind:"directive",type:i6.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CaptchaComponent,decorators:[{type:Component,args:[{imports:[CommonModule,FormsModule],standalone:!0,selector:"fm-captcha",template:'<ng-container *ngIf="type == \'input\'; else elseTemplate">\n <div class="captcha">\n <input\n nz-input\n class="code-input"\n type="text"\n [(ngModel)]="vCode"\n maxlength="4"\n placeholder="验证码"\n [nzStatus]="vCode.length == 4 ? \'\' : \'error\'"\n (keydown)="enter($event)"\n (change)="onChange()"\n />\n <div class="code-card" #canvasDom></div>\n </div>\n</ng-container>\n<ng-template #elseTemplate>\n <div class="captcha">\n <div class="code-card" #canvasDom></div>\n </div>\n</ng-template>\n',styles:[".code-card{display:flex;align-items:center}.code-card .canvas{border:1px solid #c2def5;border-radius:5px;width:100px;height:38px}.code-input{width:90px;padding:4px;height:38px;border:1px solid #cdcdcd}.code-input:focus{outline:1px solid #40a9ff}.captcha{display:flex;align-items:center}\n"]}]}],ctorParameters:()=>[],propDecorators:{canvasDom:[{type:ViewChild,args:["canvasDom"]}],type:[{type:Input}],canvas_id:[{type:Input}],drawCode:[{type:Input}],vCode:[{type:Input}],changeVal:[{type:Output}],onEnter:[{type:Output}]}});class UserNamePipe{transform(e,...t){let n=e;if(n?.mobile||(n=e?.toJSON()),console.log(n),n?.nickname)return n?.nickname;let o=n?.name;if(o)return o.substr(0,1)+"*".repeat(o?.length-1);let i=n?.mobile;return i?i.substr(0,3)+"*".repeat(i?.length-6)+i.substr(i?.length-3):""}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:UserNamePipe,deps:[],target:i0.ɵɵFactoryTarget.Pipe})}static{this.ɵpipe=i0.ɵɵngDeclarePipe({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:UserNamePipe,name:"userName"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:UserNamePipe,decorators:[{type:Pipe,args:[{name:"userName"}]}]});const UserRoutes=[{path:"login",component:LoginComponent,runGuardsAndResolvers:"always"},{path:":companyId/login",component:LoginComponent,runGuardsAndResolvers:"always"},{path:"app/:appId/login",component:LoginComponent,runGuardsAndResolvers:"always"}];class UserModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:UserModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:UserModule,declarations:[LoginComponent,UserNamePipe],imports:[CommonModule,FormsModule,HttpClientModule,ReactiveFormsModule,i1$1.RouterModule,NzInputModule,NzButtonModule,NzModalModule,NzRadioModule,NzSpinModule,NzTabsModule,NzFormModule,NzMessageModule,ModalUserLoginComponent,CaptchaComponent],exports:[LoginComponent,ModalUserLoginComponent,UserNamePipe,CaptchaComponent]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:UserModule,imports:[CommonModule,FormsModule,HttpClientModule,ReactiveFormsModule,RouterModule.forChild(UserRoutes),NzInputModule,NzButtonModule,NzModalModule,NzRadioModule,NzSpinModule,NzTabsModule,NzFormModule,NzMessageModule,ModalUserLoginComponent,CaptchaComponent]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:UserModule,decorators:[{type:NgModule,args:[{declarations:[LoginComponent,UserNamePipe],imports:[CommonModule,FormsModule,HttpClientModule,ReactiveFormsModule,RouterModule.forChild(UserRoutes),NzInputModule,NzButtonModule,NzModalModule,NzRadioModule,NzSpinModule,NzTabsModule,NzFormModule,NzMessageModule,ModalUserLoginComponent,CaptchaComponent],exports:[LoginComponent,ModalUserLoginComponent,UserNamePipe,CaptchaComponent]}]}]});class StaffModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StaffModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:StaffModule,imports:[CommonModule]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StaffModule,imports:[CommonModule]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StaffModule,decorators:[{type:NgModule,args:[{declarations:[],imports:[CommonModule]}]}]});class StaffService{constructor(e){this.router=e,this.isPeiZhu=!1,this.checkIsPeiZhu()}async checkStaff(){if(this.staff?.id||(this.staff=await this.loadStaffByUser()),this.staff?.id)return!0;console.log(this.staff);let e=this.redirectURL;return e&&(e=encodeURIComponent(e)),e=e||"/store/home",this.router.navigate([e]),!1}async loadStaffByUser(e=!1){let t=Parse__default.User.current();if(!t?.id)return;let n=localStorage.getItem("staffid");e&&(n=null);let o,i=new Parse__default.Query("UserStaff");return i.include("job","shopStore"),n&&(i.equalTo("objectId",n),o=await i.first()),o?.id||(i.equalTo("user",t?.id),o=await i.first()),o?.id&&localStorage.setItem("staffid",o?.id),e&&(this.realStaff=o),o}async checkIsPeiZhu(){this.realStaff||(this.realStaff=await this.loadStaffByUser(!0)),"配件助理"!=this.realStaff?.get("job")?.get("title")?this.isPeiZhu=!1:this.isPeiZhu=!0}peizhuJob(e){return!this.isPeiZhu||!!(this.isPeiZhu&&e.jobs?.indexOf("配件助理")>-1)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StaffService,deps:[{token:i1$1.Router}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StaffService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StaffService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1$1.Router}]});class AuthStaffGuard{constructor(e){this.staffServ=e}canActivate(e,t){return this.staffServ.checkStaff()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthStaffGuard,deps:[{token:StaffService}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthStaffGuard,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthStaffGuard,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:StaffService}]});class AuthProfileService{get profileId(){return this._profileId?this._profileId:localStorage.getItem("Parse/ProfileId")}set profileId(e){this._profileId=e,localStorage.setItem("Parse/ProfileId",e)}get profilePointer(){return{__type:"Pointer",className:"Profile",objectId:this.companyId}}get companyId(){return this._companyId?this._companyId:localStorage.getItem("Parse/CompanyId")}set companyId(e){this._companyId=e,localStorage.setItem("Parse/CompanyId",e)}get companyPointer(){return{__type:"Pointer",className:"company",objectId:this.companyId}}get user(){return this._user||Parse__default.User.current()}set user(e){this._user=e}constructor(e){this.router=e,this.user=Parse__default.User.current()}async getProfile(){if(this.profile?.id)return this.profile;if(this.profileId){let e=new Parse__default.Query("Profile");return e.include("company"),this.profile=await e.get(this.profileId),this.profile}return this.profile}async bindProfile(e){this.profile=e,this.profileId=e.id,e?.get("company")?.id&&(this.companyId=e?.get("company")?.id),console.log(e,this.user),this.profile.set("user",this.user?.toPointer()),await this.profile.save(),console.log(localStorage.getItem("homePath")),console.log(e?.get("company")?.get("rootPage"));let t=localStorage.getItem("homePath")||e?.get("company")?.get("rootPage")||this.redirectUrl||"/";t=decodeURIComponent(t),this.router.navigate([t])}async checkProfile(e){let t=this.profile;if(t?.id)return this.setCurrentProfileLocalStorage(t),!0;if(this.profileId){let e=new Parse__default.Query("Profile");return e.include("company"),t=await e.get(this.profileId),t?.id&&(this.profile=t,this.setCurrentProfileLocalStorage(t)),!0}return this.redirectUrl=e,this.router.navigate(["/profile/bind"]),!1}async setCurrentProfileLocalStorage(e){let t=Parse__default.Query.fromJSON("Department",{where:{$or:[{leader:e.toPointer()}]}});(await t.find()).forEach((e=>{e?.id&&(this.isManager=!0,this.isLeader=!0)}))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthProfileService,deps:[{token:i1$1.Router}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthProfileService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthProfileService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1$1.Router}]});class AuthProfileGuard{constructor(e,t){this.authProfileServ=e,this.router=t}canActivate(e,t){let n=t.url;return this.authProfileServ.checkProfile(n)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthProfileGuard,deps:[{token:AuthProfileService},{token:i1$1.Router}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthProfileGuard,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthProfileGuard,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:AuthProfileService},{type:i1$1.Router}]});class ProfileConfirmModalComponent{constructor(e){this.modalController=e}dismiss(){this.modalController.dismiss()}confirm(){this.modalController.dismiss({confirmed:!0})}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ProfileConfirmModalComponent,deps:[{token:i3.ModalController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ProfileConfirmModalComponent,selector:"fm-profile-confirm-modal",inputs:{profile:"profile"},ngImport:i0,template:'\n <ion-header>\n <ion-toolbar>\n <ion-title>绑定身份</ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="dismiss()">取消</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n\n <ion-content class="ion-padding">\n <p>您确认绑定并切换至该身份吗?</p>\n <ion-item lines="none">\n <ion-label>\n <h3>姓名:{{ profile?.get("name") }}</h3>\n <p>帐套:{{ profile?.get("company")?.get("name") || profile?.get("company")?.get("title") }}</p>\n </ion-label>\n </ion-item>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar>\n <ion-button expand="block" (click)="confirm()">确认绑定</ion-button>\n </ion-toolbar>\n </ion-footer>\n ',isInline:!0,dependencies:[{kind:"component",type:i3.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:i3.IonButtons,selector:"ion-buttons",inputs:["collapse"]},{kind:"component",type:i3.IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:i3.IonFooter,selector:"ion-footer",inputs:["collapse","mode","translucent"]},{kind:"component",type:i3.IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:i3.IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:i3.IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"component",type:i3.IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ProfileConfirmModalComponent,decorators:[{type:Component,args:[{selector:"fm-profile-confirm-modal",template:'\n <ion-header>\n <ion-toolbar>\n <ion-title>绑定身份</ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="dismiss()">取消</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n\n <ion-content class="ion-padding">\n <p>您确认绑定并切换至该身份吗?</p>\n <ion-item lines="none">\n <ion-label>\n <h3>姓名:{{ profile?.get("name") }}</h3>\n <p>帐套:{{ profile?.get("company")?.get("name") || profile?.get("company")?.get("title") }}</p>\n </ion-label>\n </ion-item>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar>\n <ion-button expand="block" (click)="confirm()">确认绑定</ion-button>\n </ion-toolbar>\n </ion-footer>\n '}]}],ctorParameters:()=>[{type:i3.ModalController}],propDecorators:{profile:[{type:Input}]}});class ProfileBindComponent{onResize(){this.cross.onResizeScreen()}constructor(e,t,n,o,i,a){this.authProfile=e,this.router=t,this.alertController=n,this.toastController=o,this.cross=i,this.modalController=a,this.profileList=[],this.pdata={name:null,mobile:null},this.now=new Date,this.isLoading=!1,this.profile=this.authProfile.profile,this.currentProfile=localStorage.getItem("Parse/ProfileId"),this.user=Parse__default.User.current(),this.loadProfiles()}async loadProfiles(){this.isLoading=!0;try{let e=new Parse__default.Query("Profile");e.include("company"),e.notEqualTo("isDeleted",!0),this.profile?.id?(e.equalTo("mobile",this.profile.get("mobile")),e.equalTo("name",this.profile.get("name"))):e.equalTo("user",this.user.id),this.profileList=await e.find()}catch(e){console.error("Error loading profiles:",e),this.showToast("加载身份信息失败,请重试","danger")}finally{this.isLoading=!1}}async bindProfile(e){if(e?.id||(e=this.profileSearched),e?.id)try{await this.authProfile.bindProfile(e)}catch(e){console.error("Error binding profile:",e),this.showToast("绑定身份失败,请重试","danger")}}async searchProfile(){if(this.profileList=[],this.pdata.name&&this.pdata.mobile){this.isLoading=!0;try{let e=new Parse__default.Query("Profile");e.include("company"),e.equalTo("name",this.pdata.name),e.equalTo("mobile",this.pdata.mobile),this.profileList=await e.find(),this.profileList?.length<1&&this.showToast("该身份不存在,无法绑定!","warning")}catch(e){console.error("Error searching profile:",e),this.showToast("查询身份失败,请重试","danger")}finally{this.isLoading=!1}}else this.showToast("请填写完整信息以查询您的身份","warning")}async selectProfile(e){if(!e?.id)return;this.profileSearched=e;const t=await this.modalController.create({component:ProfileConfirmModalComponent,componentProps:{profile:e}});await t.present();const{data:n}=await t.onWillDismiss();n?.confirmed&&this.bindProfile(e)}goProfileManage(){this.router.navigate(["/common/manage/Profile",{rid:"x6xybaLWIC"}])}async onShowModal(){const e=await this.alertController.create({header:"团队成员管理",message:"您是企业管理员,可进入添加团队成员身份",buttons:[{text:"取消",role:"cancel"},{text:"前往管理",handler:()=>{this.goProfileManage()}}]});await e.present()}async showToast(e,t="success"){const n=await this.toastController.create({message:e,duration:2e3,color:t,position:"top"});await n.present()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ProfileBindComponent,deps:[{token:AuthProfileService},{token:i1$1.Router},{token:i3.AlertController},{token:i3.ToastController},{token:CrossService},{token:i3.ModalController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ProfileBindComponent,selector:"fm-profile-bind",host:{listeners:{"window:resize":"onResize($event)"}},ngImport:i0,template:'<ion-content>\n <ng-container *ngIf="cross?.navMenuType == \'mobile\'; else desktopTemplate">\n <div class="ion-padding tips-block">\n <img src="https://file-cloud.fmode.cn/CCuWCEM24z/20231213/45hm71034653179.png" alt="" />\n <div>请使用电脑浏览器打开</div>\n </div>\n </ng-container>\n\n <ng-template #desktopTemplate>\n <div class="profile-page ion-padding">\n <div class="title">企业项目管理系统</div>\n \n <div class="date-container">\n <div class="date">{{ now | date : "yyyy年MM月dd日" }}</div>\n <ion-button *ngIf="user?.get(\'type\') == \'admin\'" fill="clear" size="small" (click)="onShowModal()">\n <ion-icon slot="start" name="people"></ion-icon>\n 企业管理员\n </ion-button>\n </div>\n\n <ng-container *ngIf="profileList?.length > 0; else noProfileTemplate">\n <h2>\n 欢迎您:{{\n profile?.get("name") ||\n this.profileList[0]?.get("name") ||\n user?.get("nickname") ||\n user?.get("name") ||\n user?.get("username")\n }},请选择您的企业身份:\n </h2>\n </ng-container>\n \n <ng-template #noProfileTemplate>\n <h2>您还未绑定企业,请先联系管理员绑定!</h2>\n </ng-template>\n\n <ion-list *ngIf="profileList?.length > 0" lines="full">\n <ion-item \n *ngFor="let p of profileList" \n button \n detail="false"\n [color]="currentProfile == p.id ? \'primary\' : \'\'"\n (click)="selectProfile(p)">\n <ion-icon slot="start" name="person" color="primary"></ion-icon>\n <ion-label>\n <h2>{{ p.get("name") }}</h2>\n <p>企业:{{ p.get("company")?.get("name") || p.get("company")?.get("title") }}</p>\n </ion-label>\n <ion-icon *ngIf="currentProfile == p.id" slot="end" name="checkmark" color="primary"></ion-icon>\n </ion-item>\n </ion-list>\n\n <div class="ion-margin-top ion-text-center">\n <ion-text color="medium">\n <ion-icon name="information-circle-outline"></ion-icon>\n 若无帐套信息,请输入企业身份验证绑定\n </ion-text>\n </div>\n\n <div class="form-container ion-margin-top">\n <ion-item>\n <ion-icon slot="start" name="person-outline"></ion-icon>\n <ion-input \n type="text" \n [(ngModel)]="pdata.name" \n placeholder="请输入您的姓名"\n clearInput>\n </ion-input>\n </ion-item>\n\n <ion-item>\n <ion-icon slot="start" name="phone-portrait-outline"></ion-icon>\n <ion-input \n type="tel" \n [(ngModel)]="pdata.mobile" \n placeholder="请输入您手机号"\n clearInput>\n </ion-input>\n </ion-item>\n\n <ion-button \n expand="block" \n (click)="searchProfile()"\n [disabled]="!pdata.name || !pdata.mobile"\n class="ion-margin-top">\n 查询身份\n <ion-spinner *ngIf="isLoading" name="crescent"></ion-spinner>\n </ion-button>\n </div>\n </div>\n </ng-template>\n</ion-content>',styles:[".profile-page{max-width:500px;margin:0 auto;padding-top:20px}.profile-page .title{font-size:24px;font-weight:700;text-align:center;margin-bottom:30px;color:var(--ion-color-primary)}.profile-page .date-container{display:flex;justify-content:space-between;align-items:center;margin-bottom:30px}.profile-page .date-container .date{font-size:16px;color:var(--ion-color-medium)}.profile-page h2{font-size:18px;color:var(--ion-color-dark);margin-bottom:20px}.profile-page ion-list{background:transparent;border-radius:8px;margin-bottom:20px}.profile-page ion-list ion-item{--border-radius: 8px;--padding-start: 10px;--inner-padding-end: 10px;margin-bottom:10px}.profile-page ion-list ion-item ion-label h2{font-weight:500;margin-bottom:5px}.profile-page ion-list ion-item ion-label p{color:var(--ion-color-medium);font-size:14px}.profile-page .form-container ion-item{--background: var(--ion-color-light);--border-radius: 8px;margin-bottom:15px}.tips-block{display:flex;flex-direction:column;align-items:center;justify-content:center;height:80vh;text-align:center}.tips-block img{width:220px;margin-bottom:20px}.tips-block div{font-size:18px;color:var(--ion-color-medium)}\n"],dependencies:[{kind:"directive",type:i2$1.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2$1.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:i6.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i6.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"component",type:i3.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:i3.IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:i3.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:i3.IonInput,selector:"ion-input",inputs:["autocapitalize","autocomplete","autocorrect","autofocus","clearInput","clearInputIcon","clearOnEdit","color","counter","counterFormatter","debounce","disabled","enterkeyhint","errorText","fill","helperText","inputmode","label","labelPlacement","max","maxlength","min","minlength","mode","multiple","name","pattern","placeholder","readonly","required","shape","spellcheck","step","type","value"]},{kind:"component",type:i3.IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:i3.IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:i3.IonSpinner,selector:"ion-spinner",inputs:["color","duration","name","paused"]},{kind:"component",type:i3.IonText,selector:"ion-text",inputs:["color","mode"]},{kind:"directive",type:i3.TextValueAccessor,selector:"ion-input:not([type=number]),ion-textarea,ion-searchbar"},{kind:"pipe",type:i2$1.DatePipe,name:"date"}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ProfileBindComponent,decorators:[{type:Component,args:[{selector:"fm-profile-bind",template:'<ion-content>\n <ng-container *ngIf="cross?.navMenuType == \'mobile\'; else desktopTemplate">\n <div class="ion-padding tips-block">\n <img src="https://file-cloud.fmode.cn/CCuWCEM24z/20231213/45hm71034653179.png" alt="" />\n <div>请使用电脑浏览器打开</div>\n </div>\n </ng-container>\n\n <ng-template #desktopTemplate>\n <div class="profile-page ion-padding">\n <div class="title">企业项目管理系统</div>\n \n <div class="date-container">\n <div class="date">{{ now | date : "yyyy年MM月dd日" }}</div>\n <ion-button *ngIf="user?.get(\'type\') == \'admin\'" fill="clear" size="small" (click)="onShowModal()">\n <ion-icon slot="start" name="people"></ion-icon>\n 企业管理员\n </ion-button>\n </div>\n\n <ng-container *ngIf="profileList?.length > 0; else noProfileTemplate">\n <h2>\n 欢迎您:{{\n profile?.get("name") ||\n this.profileList[0]?.get("name") ||\n user?.get("nickname") ||\n user?.get("name") ||\n user?.get("username")\n }},请选择您的企业身份:\n </h2>\n </ng-container>\n \n <ng-template #noProfileTemplate>\n <h2>您还未绑定企业,请先联系管理员绑定!</h2>\n </ng-template>\n\n <ion-list *ngIf="profileList?.length > 0" lines="full">\n <ion-item \n *ngFor="let p of profileList" \n button \n detail="false"\n [color]="currentProfile == p.id ? \'primary\' : \'\'"\n (click)="selectProfile(p)">\n <ion-icon slot="start" name="person" color="primary"></ion-icon>\n <ion-label>\n <h2>{{ p.get("name") }}</h2>\n <p>企业:{{ p.get("company")?.get("name") || p.get("company")?.get("title") }}</p>\n </ion-label>\n <ion-icon *ngIf="currentProfile == p.id" slot="end" name="checkmark" color="primary"></ion-icon>\n </ion-item>\n </ion-list>\n\n <div class="ion-margin-top ion-text-center">\n <ion-text color="medium">\n <ion-icon name="information-circle-outline"></ion-icon>\n 若无帐套信息,请输入企业身份验证绑定\n </ion-text>\n </div>\n\n <div class="form-container ion-margin-top">\n <ion-item>\n <ion-icon slot="start" name="person-outline"></ion-icon>\n <ion-input \n type="text" \n [(ngModel)]="pdata.name" \n placeholder="请输入您的姓名"\n clearInput>\n </ion-input>\n </ion-item>\n\n <ion-item>\n <ion-icon slot="start" name="phone-portrait-outline"></ion-icon>\n <ion-input \n type="tel" \n [(ngModel)]="pdata.mobile" \n placeholder="请输入您手机号"\n clearInput>\n </ion-input>\n </ion-item>\n\n <ion-button \n expand="block" \n (click)="searchProfile()"\n [disabled]="!pdata.name || !pdata.mobile"\n class="ion-margin-top">\n 查询身份\n <ion-spinner *ngIf="isLoading" name="crescent"></ion-spinner>\n </ion-button>\n </div>\n </div>\n </ng-template>\n</ion-content>',styles:[".profile-page{max-width:500px;margin:0 auto;padding-top:20px}.profile-page .title{font-size:24px;font-weight:700;text-align:center;margin-bottom:30px;color:var(--ion-color-primary)}.profile-page .date-container{display:flex;justify-content:space-between;align-items:center;margin-bottom:30px}.profile-page .date-container .date{font-size:16px;color:var(--ion-color-medium)}.profile-page h2{font-size:18px;color:var(--ion-color-dark);margin-bottom:20px}.profile-page ion-list{background:transparent;border-radius:8px;margin-bottom:20px}.profile-page ion-list ion-item{--border-radius: 8px;--padding-start: 10px;--inner-padding-end: 10px;margin-bottom:10px}.profile-page ion-list ion-item ion-label h2{font-weight:500;margin-bottom:5px}.profile-page ion-list ion-item ion-label p{color:var(--ion-color-medium);font-size:14px}.profile-page .form-container ion-item{--background: var(--ion-color-light);--border-radius: 8px;margin-bottom:15px}.tips-block{display:flex;flex-direction:column;align-items:center;justify-content:center;height:80vh;text-align:center}.tips-block img{width:220px;margin-bottom:20px}.tips-block div{font-size:18px;color:var(--ion-color-medium)}\n"]}]}],ctorParameters:()=>[{type:AuthProfileService},{type:i1$1.Router},{type:i3.AlertController},{type:i3.ToastController},{type:CrossService},{type:i3.ModalController}],propDecorators:{onResize:[{type:HostListener,args:["window:resize",["$event"]]}]}});class AuthPcuserGuard{constructor(e,t){this.authService=e,this.router=t}canActivate(e,t){let n=t.url;return this.authService.redirectUrl=n,this.authService.checkLogin(n)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthPcuserGuard,deps:[{token:AuthService},{token:i1$1.Router}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthPcuserGuard,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthPcuserGuard,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:AuthService},{type:i1$1.Router}]});const ProfileRoutes=[{path:"bind",canActivate:[AuthPcuserGuard],component:ProfileBindComponent,runGuardsAndResolvers:"always"}];class ProfileModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ProfileModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:ProfileModule,declarations:[ProfileBindComponent,ProfileConfirmModalComponent],imports:[CommonModule,FormsModule,IonicModule,i1$1.RouterModule]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ProfileModule,providers:[CrossService,AuthProfileService],imports:[CommonModule,FormsModule,IonicModule,RouterModule.forChild(ProfileRoutes)]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ProfileModule,decorators:[{type:NgModule,args:[{declarations:[ProfileBindComponent,ProfileConfirmModalComponent],imports:[CommonModule,FormsModule,IonicModule,RouterModule.forChild(ProfileRoutes)],providers:[CrossService,AuthProfileService]}]}]});export{AccountService,AgentPrompt,AgentStory,AgentTaskStep,AudioPlayer,AuthPcuserGuard,AuthProfileGuard,AuthProfileService,AuthService,AuthStaffGuard,AvatarModule,AvatarRoutes,CaptchaComponent,ChatContentPipe,ChatListComponent,ChatPanelComponent,ChatService,ClipboardService,CompAvatarParticleComponent,CompAvatarRoleImageComponent,CompAvatarRoleVideoComponent,CompAvatarTalkComponent,CompPoiPickerComponent,CompPoiPickerModule,CompRolePromptComponent,CompUserAvatarComponent,CrossService,DurationStrPipe,FmAgentTaskComponent,FmChatHeaderArea,FmChatMessageCard,FmChatMesssageArea,FmChatModalInput,FmPushAudioOutputStreamCallback,FmVideoComponent,FmaiService,FmodeChat,FmodeChatCompletion,FmodeMapModule,FmodeStorgeModule,FmodeTTS,FmodeVoiceService,HidexmlPipe,HwobsManagerComponent,HwobsService,ImagineService,ImagineWork,LoginComponent,MASK_LIST,MarkdownMathJax,MarkdownParse,MarkdownPreviewComponent,MarkdownPreviewModule,ModalAudioMessageComponent,ModalChatVoiceInputComponent,ModalUserLoginComponent,NovaCloudService,NovaUploadService,ProfileBindComponent,ProfileModule,ProfileRoutes,StaffModule,StaffService,TipsController,UserModule,UserNamePipe,UserRoutes,UtilnowPipe,WebSpeech,WechatJssdkService,apig,drawDalle,getMessageContentText,getMessageImageUrl,ncloudApi,novaql,openChatPanelModal};
|
|
8
|
+
import{PromptTemplate}from"@langchain/core/prompts";import{Subject,Observable,bufferTime,concatMap,delay,finalize,interval,take,map,of,BehaviorSubject,combineLatest,from}from"rxjs";import*as Parse from"parse";import Parse__default from"parse";import{bufferWhen,takeUntil,filter}from"rxjs/operators";import{SpeechConfig,SpeechSynthesizer,AudioConfig,ResultReason}from"microsoft-cognitiveservices-speech-sdk";import{AudioOutputConfigImpl}from"microsoft-cognitiveservices-speech-sdk/distrib/lib/src/sdk/Audio/AudioConfig";import{PushAudioOutputStreamImpl}from"microsoft-cognitiveservices-speech-sdk/distrib/lib/src/sdk/Audio/AudioOutputStream";import pako from"pako";import{v4}from"uuid";import*as i0 from"@angular/core";import{Injectable,Pipe,Input,ViewChild,Component,NgModule,EventEmitter,Output,Inject,HostListener}from"@angular/core";import*as i1$1 from"@angular/router";import{RouterModule}from"@angular/router";import*as i1 from"@angular/common/http";import{HttpClientModule}from"@angular/common/http";import*as i3 from"@ionic/angular";import{IonicModule,ModalController,Platform,IonModal as IonModal$1}from"@ionic/angular";import*as i2 from"@angular/common";import{DatePipe,CommonModule,NgIf,DecimalPipe}from"@angular/common";import{Camera,CameraResultType,CameraSource}from"@capacitor/camera";import{Capacitor}from"@capacitor/core";import{Filesystem}from"@capacitor/filesystem";import{FilesystemWeb}from"@capacitor/filesystem/dist/esm/web.js";import*as qiniu from"qiniu-js";import*as i5 from"@awesome-cordova-plugins/diagnostic/ngx";import{Diagnostic}from"@awesome-cordova-plugins/diagnostic/ngx";import CryptoJS from"crypto-js";import{MediaCapture}from"@awesome-cordova-plugins/media-capture/ngx";import SparkMD5 from"spark-md5";import{mathjax}from"mathjax-full/js/mathjax";import{TeX}from"mathjax-full/js/input/tex";import{SVG}from"mathjax-full/js/output/svg";import{CHTML}from"mathjax-full/js/output/chtml";import{AllPackages}from"mathjax-full/js/input/tex/AllPackages";import{liteAdaptor}from"mathjax-full/js/adaptors/liteAdaptor";import{RegisterHTMLHandler}from"mathjax-full/js/handlers/html";import hljs from"highlight.js";import MarkdownIt from"markdown-it";import $ from"jquery";import abbr from"markdown-it-abbr";import footnote from"markdown-it-footnote";import deflist from"markdown-it-deflist";import mark from"markdown-it-mark";import ins from"markdown-it-ins";import sub from"markdown-it-sub";import sup from"markdown-it-sup";import ruby from"markdown-it-ruby";import plantumlEncoder from"plantuml-encoder";import*as i1$2 from"@angular/platform-browser";import{Clipboard}from"@capacitor/clipboard";import Recorder from"recorder-core";import"recorder-core/src/engine/pcm";import"recorder-core/src/engine/wav";import"recorder-core/src/extensions/waveview";import*as i3$3 from"@angular/forms";import{FormsModule,ReactiveFormsModule,FormControl,FormGroup,Validators}from"@angular/forms";import*as BABYLON from"@babylonjs/core";import"@babylonjs/loaders";import*as i1$3 from"@ionic/angular/standalone";import{IonIcon,IonToolbar,IonButtons,IonButton,IonModal,IonTitle,IonHeader,IonList,IonItem,IonCard,IonLabel,IonNote,IonAvatar,IonSegment,IonSpinner,ModalController as ModalController$1,IonTextarea,IonPopover,IonContent,IonInput,IonText,IonChip,IonImg,IonSegmentButton,IonSelect,IonSelectOption,IonDatetime,IonDatetimeButton,IonItemGroup,IonItemDivider,IonCardHeader,IonCardTitle,IonCardSubtitle,IonCardContent,IonSearchbar,IonFooter,IonCheckbox}from"@ionic/angular/standalone";import*as i3$2 from"@angular/material/button";import{MatButtonModule}from"@angular/material/button";import*as i3$1 from"@angular/material/dialog";import{MAT_DIALOG_DATA,MatDialogModule}from"@angular/material/dialog";import*as i11$1 from"@angular/material/form-field";import{MatFormFieldModule}from"@angular/material/form-field";import*as i4$4 from"@angular/material/input";import{MatInputModule}from"@angular/material/input";import*as i5$1 from"@angular/material/progress-bar";import{MatProgressBarModule}from"@angular/material/progress-bar";import*as i4 from"@angular/material/stepper";import{MatStepperModule,MatStepper}from"@angular/material/stepper";import{addIcons}from"ionicons";import*as icons from"ionicons/icons";import{ellipsisHorizontalOutline,chevronBackOutline,person,copyOutline,wifiOutline,chevronForward,settingsOutline,shareSocialOutline,paperPlaneOutline,micOutline,chatboxEllipsesOutline,chevronDownOutline,imageOutline,alertOutline,peopleOutline,colorWandOutline,helpCircleOutline,femaleOutline,maleOutline,alertCircleOutline,createOutline,cloudDoneOutline,folderOutline,receiptOutline,hardwareChipOutline,closeOutline}from"ionicons/icons";import*as i7 from"ng-zorro-antd/pipes";import{NzSanitizerPipe,NzPipesModule}from"ng-zorro-antd/pipes";import*as i2$1 from"@angular/material/card";import{MatCardModule}from"@angular/material/card";import*as i5$2 from"@angular/material/checkbox";import{MatCheckboxModule}from"@angular/material/checkbox";import*as i6 from"@angular/material/icon";import{MatIconModule}from"@angular/material/icon";import*as i11 from"@angular/material/button-toggle";import{MatButtonToggleModule}from"@angular/material/button-toggle";import{MatDividerModule}from"@angular/material/divider";import{MatToolbarModule}from"@angular/material/toolbar";import*as i10 from"@angular/material/chips";import{MatChipsModule,MatChipListbox}from"@angular/material/chips";import*as i2$2 from"ng-zorro-antd/message";import{NzMessageModule}from"ng-zorro-antd/message";import*as plupload from"plupload";import*as i3$4 from"ng-zorro-antd/button";import{NzButtonModule}from"ng-zorro-antd/button";import*as i4$1 from"ng-zorro-antd/core/transition-patch";import*as i5$3 from"ng-zorro-antd/core/wave";import*as i6$1 from"ng-zorro-antd/icon";import{NzIconModule}from"ng-zorro-antd/icon";import*as i8 from"ng-zorro-antd/input";import{NzInputModule}from"ng-zorro-antd/input";import*as i14$1 from"ng-zorro-antd/tabs";import{NzTabsModule}from"ng-zorro-antd/tabs";import*as i12 from"ng-zorro-antd/modal";import{NzModalModule}from"ng-zorro-antd/modal";import*as i14 from"ng-zorro-antd/grid";import{NzGridModule}from"ng-zorro-antd/grid";import*as i15 from"ng-zorro-antd/radio";import{NzRadioModule}from"ng-zorro-antd/radio";import*as i16 from"ng-zorro-antd/image";import{NzImageModule}from"ng-zorro-antd/image";import{NzDatePickerModule}from"ng-zorro-antd/date-picker";import*as i4$5 from"ng-zorro-antd/layout";import{NzLayoutModule}from"ng-zorro-antd/layout";import*as i7$1 from"ng-zorro-antd/upload";import{NzUploadModule}from"ng-zorro-antd/upload";import*as i4$2 from"@angular/material/tooltip";import{MatTooltipModule}from"@angular/material/tooltip";import Quill from"quill";import*as AMapLoader from"@amap/amap-jsapi-loader";import ObsClient from"esdk-obs-browserjs";import{NzToolTipModule}from"ng-zorro-antd/tooltip";import*as i6$2 from"ng-zorro-antd/divider";import{NzDividerModule}from"ng-zorro-antd/divider";import{NzDropDownModule}from"ng-zorro-antd/dropdown";import{NzEmptyModule}from"ng-zorro-antd/empty";import*as i5$4 from"ng-zorro-antd/avatar";import{NzAvatarModule}from"ng-zorro-antd/avatar";import{NzPopoverModule}from"ng-zorro-antd/popover";import*as i8$1 from"@angular/material/slide-toggle";import{MatSlideToggleModule}from"@angular/material/slide-toggle";import*as i4$3 from"@angular/material/radio";import{MatRadioModule}from"@angular/material/radio";import{NzCodeEditorModule}from"ng-zorro-antd/code-editor";import*as i7$2 from"@angular/material/expansion";import{MatExpansionModule,MatAccordion}from"@angular/material/expansion";import{Swiper}from"swiper";import*as i13 from"ng-zorro-antd/spin";import{NzSpinModule}from"ng-zorro-antd/spin";import*as i16$1 from"ng-zorro-antd/form";import{NzFormModule}from"ng-zorro-antd/form";class AudioPlayer{static{this.instance=null}constructor(){this.audio=new Audio}static getInstance(){return AudioPlayer.instance||(AudioPlayer.instance=new AudioPlayer),AudioPlayer.instance}setAudioEvent(e,t){this.audio[e]=t}get duration(){return this.audio.duration}get src(){return this.audio.src}stop(){this.audio.pause()}async play(e){return new Promise(((t,n)=>{this.audio.src!==e?(this.audio.src=e,this.audio.play().then((()=>{t()})).catch((()=>{n()}))):this.audio.paused?this.audio.play().then((()=>{t()})).catch((()=>{n()})):this.audio.pause()}))}}class FmPushAudioOutputStreamCallback{constructor(){this.audioDataSubject=new Subject,this.playedSubject=new Subject,this.isPlaying=!1,this.isClosed=!1,this.audioBufferQueue=[],this.maxBufferSize=10,this.writeCount=0,this.audioContext=new(window.AudioContext||window.webkitAudioContext),this.audioDataSubject.pipe(bufferWhen((()=>this.playedSubject)),takeUntil(this.audioDataSubject.pipe(filter((()=>this.isClosed))))).subscribe((e=>{this.playAudio(e)}))}async write(e){this.writeCount++,10==this.writeCount&&this.playedSubject.next(!0),this.audioDataSubject.next(e)}async playAudio(e){this.isPlaying=!0;const t=this.mergeArrayBuffers(e);let n;try{n=await this.audioContext.decodeAudioData(t)}catch(e){}if(n){const e=this.audioContext.createBufferSource();e.buffer=n,e.connect(this.audioContext.destination),e.start(),await new Promise((t=>{e.onended=t})),this.playedSubject.next(!0)}this.isPlaying=!1}mergeArrayBuffers(e){const t=e.reduce(((e,t)=>e+t.byteLength),0),n=new Uint8Array(t);let o=0;for(const t of e){const e=new Uint8Array(t);n.set(e,o),o+=e.length}return n.buffer}async stop(){this.isClosed=!0,this.audioDataSubject&&this.audioDataSubject.unsubscribe(),this.playedSubject&&this.playedSubject.unsubscribe(),this.audioContext&&this.audioContext.close()}async close(){console.log("close 数据加载完成"),this.isClosed=!0}}console.log("SpeechConfig",SpeechConfig);class FmodeTTSProviderMicrosoft{constructor(){}initialize(e){if(e.subscriptionKey)this.speechConfig=SpeechConfig.fromSubscription(e.subscriptionKey,e.region);else{if(!e.token)throw new Error("Either subscriptionKey or token must be provided");this.speechConfig=SpeechConfig.fromAuthorizationToken(e.token,e.region)}console.log("audio config",e,e.audioStream),this.audioConfig=new AudioOutputConfigImpl(new PushAudioOutputStreamImpl(e.audioStream)),this.synthesizer=new SpeechSynthesizer(this.speechConfig,this.audioConfig||AudioConfig.fromDefaultSpeakerOutput())}synthesize(e,t,n,o){if(!this.synthesizer)throw new Error("Synthesizer not initialized. Call initialize() first.");this.eventMap?.onSpeakBefore?.();const i=e?.indexOf("<")>-1?"speakSsmlAsync":"speakTextAsync";e=this.fixMarkdownChar(e),this.synthesizer[i](e,(e=>{e.reason===ResultReason.SynthesizingAudioStarted&&(o?.(),this.eventMap?.onStreamStarted?.()),e.reason===ResultReason.SynthesizingAudioCompleted?(this.eventMap?.onAudioCompleted?.(),t(e)):n(new Error(`Speech synthesis failed. Reason: ${e.errorDetails}`))}),(e=>{n(e)}))}stop(){this.synthesizer&&this.synthesizer.close()}dispose(){this.stop(),this.speechConfig=null,this.audioConfig=null,this.synthesizer=null}fixMarkdownChar(e){return e.replaceAll("*","")}}class PCMStreamer{constructor(e=24e3,t=1,n=16){this.bufferQueue=[],this.isPlaying=!1,this.currentSource=null,this.nextPlayTime=0,this.bufferedDuration=0,this.minBufferDuration=.5,this.targetBufferDuration=1,this.maxBufferDuration=1.5,this.mergeThreshold=.05,this.sampleRate=e,this.numChannels=t,this.bitsPerSample=n;const o=window.AudioContext||window.webkitAudioContext;this.audioContext=new o,document.addEventListener("click",(()=>{"suspended"===this.audioContext.state&&this.audioContext.resume()}),{once:!0})}write(e){if(0===e.byteLength)return;const t=this.calculateDuration(e);this.bufferedDuration+=t,this.bufferQueue.push(e),!this.isPlaying&&this.bufferedDuration>=this.minBufferDuration&&this.startPlayback()}startPlayback(){this.isPlaying||(this.isPlaying=!0,this.nextPlayTime=this.audioContext.currentTime,this.processBuffer())}processBuffer(){if("running"!==this.audioContext.state)return void this.audioContext.resume().then((()=>{setTimeout((()=>this.processBuffer()),50)}));if(this.bufferedDuration<this.minBufferDuration)return void(this.isPlaying=!1);const{mergedBuffer:e,totalDuration:t}=this.mergeBuffers();this.bufferedDuration-=t;const n=e.byteLength/(this.bitsPerSample/8)/this.numChannels,o=this.audioContext.createBuffer(this.numChannels,n,this.sampleRate);this.fillAudioBuffer(o,e);const i=this.audioContext.createBufferSource();i.buffer=o,i.connect(this.audioContext.destination);const a=this.audioContext.currentTime;this.nextPlayTime=Math.max(this.nextPlayTime,a),i.start(this.nextPlayTime),this.nextPlayTime+=o.duration,i.onended=()=>{this.currentSource=null,setTimeout((()=>this.processBuffer()),5)},this.currentSource=i}mergeBuffers(){let e=0,t=0;const n=[];for(;this.bufferQueue.length>0;){const o=this.bufferQueue[0],i=this.calculateDuration(o);if(t>0&&t+i>this.maxBufferDuration)break;if(n.push(this.bufferQueue.shift()),e+=o.byteLength,t+=i,t>=this.targetBufferDuration){if(this.bufferQueue.length>0&&this.calculateDuration(this.bufferQueue[0])<this.mergeThreshold)continue;break}}const o=new Uint8Array(e);let i=0;for(const e of n)o.set(new Uint8Array(e),i),i+=e.byteLength;return{mergedBuffer:o.buffer,totalDuration:t}}calculateDuration(e){const t=this.bitsPerSample/8;return e.byteLength/t/this.numChannels/this.sampleRate}fillAudioBuffer(e,t){const n=this.bitsPerSample/8,o=new DataView(t);for(let t=0;t<this.numChannels;t++){const i=e.getChannelData(t);let a=t*n;for(let e=0;e<i.length;e++){let t;if(16===this.bitsPerSample)t=o.getInt16(a,!0)/32768;else if(8===this.bitsPerSample)t=(o.getUint8(a)-128)/128;else{if(32!==this.bitsPerSample)throw new Error(`Unsupported bit depth: ${this.bitsPerSample}`);t=o.getInt32(a,!0)/2147483648}i[e]=t,a+=n*this.numChannels}}}stop(){this.currentSource&&(this.currentSource.stop(),this.currentSource=null),this.bufferQueue=[],this.isPlaying=!1,this.bufferedDuration=0,this.nextPlayTime=0}}class FmodeTTS{static{this.activeInstance=null}stop(){FmodeTTS.activeInstance===this&&(FmodeTTS.activeInstance=null),this.audioPlayer?.stop(),this.audioStream?.stop(),this.provider?.stop(),this.isPlaying=!1}constructor(e,t){if(this.isPlaying=!1,this.uploadServ=t,this.config=e,this.audioPlayer=AudioPlayer.getInstance(),this.audioStream=new FmPushAudioOutputStreamCallback,this.provider=e.provider||new FmodeTTSProviderMicrosoft,console.log("初始化provider",e,this.provider,this.provider.constructor),this.provider.constructor.toString().indexOf("Doubao")>-1){const t=new PCMStreamer(24e3,1,16);e.audioStream=t}else e.audioStream=this.audioStream;this.audioStream=e?.audioStream||this.audioStream,this.provider.initialize(e),this.provider.eventMap=this.eventMap}extractTextFromXML(e){if(!e||"string"!=typeof e)return"";const t=/>([^<]+)</g,n=[];let o;for(;null!==(o=t.exec(e));){const e=o[1]?.trim();e&&n.push(e)}return n.join(" ")}extractSSMLContent(e){if(!e||"string"!=typeof e)return e||"";const t=e.match(/<speak.*?<\/speak>/s);return t?.[0]||e}async speakAsync(e,t,n){if(FmodeTTS.activeInstance&&FmodeTTS.activeInstance!==this&&FmodeTTS.activeInstance.stop(),FmodeTTS.activeInstance=this,!t){const n=Parse__default.Object.extend("ChatVoice");(t=new n).set("ssml",e),t.set("content",this.extractTextFromXML(e));const o=localStorage.getItem("company");o&&t.set("company",{__type:"Pointer",className:"Company",objectId:o}),Parse__default.User.current()?.id&&t.set("user",Parse__default.User.current().toPointer())}if(!t?.get("voiceFile")){const n=[];t?.get("content")&&n.push({content:t?.get("content")}),e&&n.push({ssml:e});const o=Parse__default.Query.fromJSON("ChatVoice",{include:"voiceFile",where:{$or:n}});o.exists("voiceFile"),o.addDescending("updatedAt");const i=await o.first();t.set("voiceFile",i?.get("voiceFile"))}return console.log("Exists playAudioData",t?.get("voiceFile")),t?.get("voiceFile")?(this.playAudioData(t?.get("voiceFile")?.get("url"),t,n),t.save(),t):(e=this.extractSSMLContent(e),this.isPlaying=!0,new Promise(((o,i)=>{const a=Date.now();this.provider.synthesize(e,(async e=>{const i=Date.now(),r=e?.audioData;let s=Number(e?.audioDuration);"microsoft"==this.config.provider&&(s/=1e4),t.set("duration",s),console.log("eventMap?.onResult",n,s),n?.onResult?.({duration:s});const l=new Blob([r],{type:"audio/wav"});await this.uploadAndSaveVoice(l,t),console.log(`Audio synthesis finished. Duration: ${i-a} ms`),setTimeout((()=>{this.isPlaying=!1,n?.onStop?.()}),2e3),o(t)}),(e=>{this.isPlaying=!1,i(`Error occurred during synthesis: ${e}`)}),(()=>{n?.onStart?.()}))})))}async playAudioData(e,t,n){let o;if(e?.indexOf?.("http")>=-1)o=e;else{const n=new Blob([e],{type:"audio/wav"});o=URL.createObjectURL(n),await this.uploadAndSaveVoice(n,t)}n?.onStart?.(t),this.isPlaying=!0;const i=this.audioPlayer;i.setAudioEvent("onloadeddata",(()=>{const e=1e3*i.duration;t?.get("duration")||(t.set("duration",e),t.save()),n?.onLoaded?.(i)})),["onabort","onerror","onpause","onended","onclose"].forEach((e=>{i.setAudioEvent(e,(()=>{this.isPlaying=!1,n?.onStop?.()}))}));const playAudio=()=>{i.play(o).catch((()=>{setTimeout(playAudio,200)}))};playAudio()}async uploadAndSaveVoice(e,t){if(!this.uploadServ)return null;const n=t?.id||this.uploadServ.genMd5(t?.get("content")||t?.get("ssml")),o=new Date,i=`${n}${o.getFullYear()}${o.getMonth()+1}${o.getDate()}${o.getHours()}${o.getMinutes()}${o.getSeconds()}.wav`,a=new File([e],i,{type:"audio/wav"}),r=await this.uploadServ.upload(a);return r?.id&&(t.set("voiceFile",{__type:"Pointer",className:"Attachment",objectId:r.id}),await t.save()),r?.url||null}}class FmodeTTSProviderDoubao{constructor(){this.ws=null,this.audioChunks=[],this.isSynthesizing=!1,this.isStarted=!1}initialize(e){if(!e.appId||!e.accessToken)throw new Error("appId, accessToken are required for Doubao TTS");e.cluster=e.cluster||"volcano_tts",this.config=e,this.audioStream=e.audioStream}synthesize(e,t,n,o){this.isSynthesizing&&this.stop(),this.isSynthesizing=!0,this.audioChunks=[],this.eventMap?.onSpeakBefore?.();const i=e?.indexOf("<speak")>-1,a=i?this.extractTextFromSSML(e):e;let r=v4();const s=buildFullUrl("wss://openspeech.bytedance.com/api/v1/tts/ws_binary",{api_jwt:this.config.stsToken});this.ws=new WebSocket(s),this.ws.binaryType="arraybuffer",this.ws.onopen=()=>{this.eventMap?.onStreamStarted?.();const e={app:{appid:this.config.appId,token:this.config.accessToken,cluster:this.config.cluster},user:{uid:"user123"},audio:{voice_type:"zh_female_wenrouxiaoya_moon_bigtts",encoding:"pcm",rate:24e3,speed_ratio:1,volume_ratio:1,pitch_ratio:1,language:"cn"},request:{reqid:r,text:a,text_type:i?"ssml":"plain",operation:"submit"}},t=this.buildBinaryMessage(e);this.ws?.send(t)},this.ws.onmessage=async e=>{try{if(e.data instanceof ArrayBuffer){const i=new Uint8Array(e.data),a=this.parseResponse(i,o);if(a.error)return n(a.error),void this.stop();if(a.audio&&(this.audioChunks.push(a.audio),this.audioStream),a.isLast){this.eventMap?.onAudioCompleted?.();const{buffer:e,duration:n}=await this.mergePcmToWav(this.audioChunks);t({audioData:e,audioDuration:a.duration||n||0}),this.stop()}}else console.warn("Unexpected text message from TTS server:",e.data)}catch(e){n(`Error processing TTS response: ${e}`),this.stop()}},this.ws.onerror=e=>{n(`WebSocket error: ${JSON.stringify(e)}`),this.stop()},this.ws.onclose=()=>{this.isSynthesizing&&(n("WebSocket connection closed unexpectedly"),this.stop())}}buildBinaryMessage(e){const t=JSON.stringify(e),n=(new TextEncoder).encode(t),o=pako.gzip(n),i=new ArrayBuffer(8+o.length),a=new DataView(i);a.setUint8(0,17),a.setUint8(1,16),a.setUint8(2,17),a.setUint8(3,0),a.setUint32(4,o.length,!1);return new Uint8Array(i).set(o,8),i}parseResponse(e,t){const n=new DataView(e.buffer),o=(e[0],15&e[0]),i=e[1]>>4,a=15&e[1],r=(e[2],15&e[2]),s=(e[3],4*o);let l=e.slice(s);if(11==i){if(0===a)return{};{const e=n.getInt32(s,!1),o=(n.getInt32(s+4,!1),l.slice(8));return this.audioStream.write(o.buffer.slice(0)),this.isStarted||(t?.(),this.isStarted=!0),{audio:o.buffer,isLast:e<0}}}if(15===i){const e=n.getInt32(s,!1);n.getInt32(s+4,!1);let t=l.slice(8);return 1===r&&(t=pako.ungzip(t)),{error:`TTS error (code ${e}): ${(new TextDecoder).decode(t)}`}}if(12!==i)return{error:`Unknown message type: ${i}`};{n.getInt32(s,!1);let e=l.slice(4);1===r&&(e=pako.ungzip(e));try{return{duration:JSON.parse((new TextDecoder).decode(e)).duration||0}}catch(e){return console.warn("Failed to parse TTS metadata:",e),{}}}}stop(){this.isSynthesizing=!1,this.ws&&(this.ws.close(),this.ws=null),this.audioChunks=[]}dispose(){this.stop()}extractTextFromSSML(e){return e.replace(/<[^>]+>/g,"").trim()}async blobToArrayBuffer(e){return new Promise(((t,n)=>{const o=new FileReader;o.onload=()=>t(o.result),o.onerror=n,o.readAsArrayBuffer(e)}))}async mergePcmToWav(e){let t=0;e.forEach((e=>{t+=e.byteLength}));const n=1e3*t/48e3,o=new Uint8Array(t);let i=0;e.forEach((e=>{o.set(new Uint8Array(e),i),i+=e.byteLength}));const a=this.createWavHeader({sampleRate:24e3,numChannels:1,bitsPerSample:16,pcmDataSize:t}),r=new Uint8Array(a.byteLength+o.byteLength);return r.set(new Uint8Array(a),0),r.set(o,a.byteLength),{buffer:r.buffer,duration:n}}createWavHeader(e){const{sampleRate:t,numChannels:n,bitsPerSample:o,pcmDataSize:i}=e,a=t*n*o/8,r=n*o/8,s=new ArrayBuffer(44),l=new DataView(s);return this.writeString(l,0,"RIFF"),l.setUint32(4,36+i,!0),this.writeString(l,8,"WAVE"),this.writeString(l,12,"fmt "),l.setUint32(16,16,!0),l.setUint16(20,1,!0),l.setUint16(22,n,!0),l.setUint32(24,t,!0),l.setUint32(28,a,!0),l.setUint16(32,r,!0),l.setUint16(34,o,!0),this.writeString(l,36,"data"),l.setUint32(40,i,!0),s}writeString(e,t,n){for(let o=0;o<n.length;o++)e.setUint8(t+o,n.charCodeAt(o))}}function buildFullUrl(e,t){const n=[];for(const e in t)n.push(`${e}=${encodeURIComponent(t[e])}`);return`${e}?${n.join("&")}`}async function getFormatTpl(e,t){let n=await getPromptTpl(e);return await n.format(t)}async function getPromptTpl(e){let t=new Parse__default.Query("PromptTemplate");t.equalTo("code",e);let n=await t.first();return PromptTemplate.fromTemplate(n?.get("template"),{templateFormat:"mustache"})}const API_BASE="https://test.fmode.cn/api/apig/aigc/gpt";class FmodeChatCompletion{constructor(e,t){this.content="",this.contentBuffer=[],this.isCompleted=!1,this.indexOfList=Number(e.length),this.messages=e,this.model=t?.model||"fmode-4.5-128k"}sendCompletion(e={messages:[]}){e.intTime=e?.intTime||50,e.isDirect=e?.isDirect||!1,e?.isDirect&&(e.intTime=1);let t={messages:this.messages,stream:!0,model:this.model,temperature:e?.temperature||.5,presence_penalty:e?.presence_penalty||0,frequency_penalty:e?.frequency_penalty||0};return e?.max_tokens&&(t.max_tokens=e?.max_tokens),new Observable((n=>{let o=RequestFmodeChatApi("/v1/chat/completions",t).subscribe((t=>{let i,a=String(t);try{i=chunkToJson(a)}catch(e){}if(("data: [DONE]"==a||i?.created&&i?.choices?.[0]?.finish_reason)&&(this.isCompleted=!0,e?.isDirect&&this.isCompleted&&(n.next({role:"assistant",content:this.content,complete:!0,createdAt:new Date}),o.unsubscribe(),e?.onComplete&&e.onComplete({role:"assistant",content:this.content,complete:!0,createdAt:new Date}),n.complete())),a.indexOf("data: {")>-1){let t=i?.choices?.[0]?.delta?.content||"";this.contentBuffer.push(t),e?.isDirect&&(this.content+=t||"",this.isCompleted||n.next({role:"assistant",cid:i?.id,content:this.content,createdAt:new Date})),e?.isDirect||this.contentPusher||(this.contentPusher=setInterval((()=>{this.isCompleted&&0==this.contentBuffer?.length&&(n.next({role:"assistant",cid:i?.id,content:this.content,complete:!0,createdAt:new Date}),o.unsubscribe(),clearInterval(this.contentPusher),n.complete()),this.contentBuffer?.length>=0&&(this.contentBuffer?.length>0&&(this.content+=this.contentBuffer.shift()),n.next({role:"assistant",cid:i?.id,content:this.content,createdAt:new Date}))}),e?.intTime))}}))})).pipe(bufferTime(100),concatMap((e=>e)),delay(200))}}function chunkToJson(e){let t;try{t=JSON.parse(e.replaceAll("data: ",""))}catch(e){}return t||{}}function RequestFmodeChatApi(e,t,n="POST"){return new Observable((o=>{let i=API_BASE+e,a=`Bearer ${Parse__default.User.current()?.getSessionToken()||localStorage.getItem("FMODE_AI_TOKEN")}`;return t.token=a,t&&(t=JSON.stringify(t)),fetch(i,{headers:{"Content-Type":"text/plain; charset=utf-8","Cache-Control":"no-cache"},body:t||null,method:n,credentials:"omit",mode:"cors"}).then((e=>{let t="";{let n=e.body?.getReader();const i=new TextDecoder;let a=new ReadableStream({start(e){!function read(){n.read().then((({done:t,value:n})=>{if(t)return e.close(),void o.complete();e.enqueue(n),read()}))}()}}).getReader();a.read().then((function processStream(e){let{done:n,value:r}=e;n||(!function processData(e){let n=(t+e).split("\n");if(n?.length>1){for(let e=0;e<n.length-1;e++){let t=n[e];o.next(t)}t=n[n.length-1]}}(i.decode(r)),a.read().then(processStream))}))}})).catch((e=>o.error(e))),()=>{}}))}function JsonToFormData(e){const t=new FormData;return function appendFormData(e,n=""){Array.isArray(e)?e.forEach(((e,t)=>{appendFormData(e,`${n}[${t}]`)})):"object"==typeof e&&null!==e?Object.keys(e).forEach((t=>{const o=n?`${n}.${t}`:t;appendFormData(e[t],o)})):t.append(n,e)}(e),t}const PromptTplTalkSSMLOutputCode="talk-ssml-output-tpl",PromptTplTalkTextSSMLCode="talk-text-ssml-tpl";function getMessageContentText(e){let t="";return"string"==typeof e&&(t=e),"object"==typeof e&&(t=e?.find((e=>e?.text))?.text||""),t}function getMessageImageUrl(e){return"object"==typeof e?e?.find((e=>e?.image_url))?.image_url?.url||"":null}class FmodeChat{async loadModelList(e){if(this.modelList?.length)return;let t=new Parse__default.Query("ChatModel");t.notEqualTo("isDeleted",!0),t.equalTo("isEnabled",!0),t.addAscending("index"),this.modelList=await t.find(),this.currentModel=e||this.modelList?.find((e=>"fmode-4.5-128k"==e.get("code")))}showAvatar(){this.avatarConfig=this.role?.get("avatarConfig"),this.avatarConfig&&(this.isAvatarShow=!0,this.avatarConfig?.image&&(this.avatarConfig.image.waiting=this.avatarConfig.image.waiting||this.role?.get("thumb")||this.role?.get("avatar"),this.avatarMode="image"),this.avatarConfig?.video&&(this.avatarConfig.video.waiting=this.avatarConfig.video.waiting,this.avatarMode="video"))}scrollToBottom(e){e=e||this.scrollComp,e?.nativeElement?.scrollHeight&&(e.nativeElement.scrollTop=e.nativeElement.scrollHeight)}constructor(e,t,n,o,i,a,r){this.ChatSession=Parse__default.Object.extend("ChatSession"),this.messageList=[{role:"system",content:"系统提示:AI仅供参考"}],this.latestAIResponse="",this.userInput="",this.userImage="",this.isDirect=!1,this.mode="page",this.hideShare=!1,this.hideModalSelect=!1,this.hideInputPreview=!1,this.isAvatarShow=!1,this.avatarMode="",this.isPromptModalOpen=!1,this.isPromptMessageAreaShow=!0,this.promptList=[],this.focusUserInput=()=>{},this.leftButtons=[{title:"灵感",icon:"color-wand-outline",onClick:()=>{this.isPromptModalOpen=!0},show:()=>this?.promptList?.length},{title:"角色",icon:"people-outline",onClick:()=>{this.navCtrl?.navigateRoot("/chat/pro/mask")},show:()=>!0},{title:"呼叫",icon:"call-outline",onClick:()=>{this.chatServ?.callRole(this.role)},show:()=>this?.role?.get("voiceConfig")}],this.isVoiceInputMode=!1,this.isTexting=!1,this.isTalkMode=!1,this.SSMLRoleVoice="zh-CN-XiaoxiaoNeural",this.playAnimation=e=>{console.log(e)},this.welcome=async()=>{let e=this.messageList?.filter((e=>"assistant"==e?.role));if(e?.length)return;let t=Parse__default.User.current(),n=await this.loadSelf("Person","userVerify"),o=await this.loadSelf("Profile","user"),i=n?.get("name")||n?.get("userVefiry")?.get("realname")||n?.get("userVefiry")?.get("nickname"),a=t?.get("nickname")||o?.get("name")||t?.get("realname")||t?.get("name");n?.get("userVerify")?.id==t?.id&&(i="您"),a||(a=i);let r=this.role.get("voiceConfig")?.welcome?.prompt;if(this.role.get("voiceConfig")?.welcome?.promptList?.length){let e=this.role.get("voiceConfig")?.welcome?.promptList;r=e[Math.floor(Math.random()*e.length)]}if(!r)return;let s=await PromptTemplate.fromTemplate(r,{templateFormat:"mustache"}).format({name:a,userName:a,personName:i,timeOfDay:this.getTimeOfDay()}),l=await this.getVoiceByContentText(s),c={role:"assistant",voice:l,content:s,complete:!0};this.voiceMap[l?.id],this.playChatVoice(this.voiceMap[l?.id]),this.messageList.push(c)},this.self={},this.voiceMap={},this.VoiceTTSMap={},this.chatServ=o,this.role=t,this.sessionId=e,this.navCtrl=i,this.ncloud=a,this.uploadServ=r,n?.id&&(this.chatSession=n,this.messageList=this.chatSession.get("messageList"),this.sessionId=n?.id),this.role?.id&&(this.voiceConfig=this.role?.get("voiceConfig"),this.voiceConfig?.autoTalk&&(this.isTalkMode=this.isTalkMode||this.voiceConfig?.autoTalk,this.isDirect=!0))}getTimeOfDay(){const e=(new Date).getHours();return e>=5&&e<12?"早上":e>=12&&e<14?"中午":e>=14&&e<18?"下午":"晚上"}async loadSelf(e,t){if(this.self[e])return this.self[e];let n=Parse__default.User.current(),o=new Parse__default.Query(e);return o.include(t),o.equalTo(t,n?.id),this.self[e]=await o.first(),this.self[e]}async loadTalkSystemPrompt(e){if(!this.isTalkMode)return;if(!e)return;let t=e?.get("voiceConfig");"男"==e?.get("gender")?(this.SSMLRoleVoice="zh-CN-YunyeNeural","doubao"==t.provider&&(this.SSMLRoleVoice="zh_male_yangguangqingnian_emo_v2_mars_bigtts")):(this.SSMLRoleVoice="zh-CN-XiaoxiaoNeural","doubao"==t.provider&&(this.SSMLRoleVoice="zh_female_shuangkuaisisi_emo_v2_mars_bigtts")),this.SSMLRoleVoice=e?.get("voiceConfig")?.voice||this.SSMLRoleVoice;let n=await getFormatTpl("talk-ssml-output-tpl",{SSMLRoleVoice:this.SSMLRoleVoice}),o=e.get("prompt")||"请你扮演飞码AI的人工智能专家。";o+=n;let i={role:"user",content:o,hidden:!0},a=this.messageList?.map((e=>e?.content)).join();if(a.indexOf(o)>-1)return;let r=this.messageList?.findIndex((e=>"system"==e?.role)),s=r+1;this.messageList.splice(s,0,i)}loadRolePrompt(){let e=this.role?.get("prompt"),t={role:"user",content:e,hidden:!0};if(!e)return;let n=this.messageList?.map((e=>e?.content)).join();if(n.indexOf(e)>-1)return;let o=this.messageList?.findIndex((e=>"system"==e?.role)),i=o+1;this.messageList.splice(i,0,t)}async sendMessage(e="FmodeAiTest测试问题",t,n,o,i){if(this.scrollToBottom&&this.scrollToBottom(),this.isPromptMessageAreaShow=!1,this.loadRolePrompt(),t){let n={role:"user",content:[{type:"image_url",image_url:{url:t}},{type:"text",text:e}],complete:!0,createdAt:new Date};i&&(n.voice={id:i?.id}),this.messageList.push({role:"user",content:[{type:"image_url",image_url:{url:t}},{type:"text",text:e}],complete:!0,createdAt:new Date})}else{let t={role:"user",content:e,complete:!0,createdAt:new Date};i&&(t.voice={id:i?.id,duration:i?.duration}),this.messageList.push(t)}let a=new FmodeChatCompletion(this.fixMessageList(this.messageList),{model:this.currentModel?.get("code")||"fmode-4.5-128k"});if(this.onUserSend){if(!await this.onUserSend(this,this.messageList[this.messageList?.length-1]))return}this.userInput="",this.userImage="";let r=this.isDirect||!1;this.isTalkMode&&(r=!0);let s=a.sendCompletion({isDirect:r,onComplete:n||null}).pipe(finalize((async()=>{if(this.isTalkMode){let e=this.messageList[a.indexOfList]?.content,t=await this.getVoiceByContentText(e,o);o?.onSSMLComplete&&o?.onSSMLComplete(t),this.messageList[a.indexOfList].voice=t,this.playChatVoice(this.voiceMap[t?.id],{onResult:e=>{e?.duration&&(this.messageList[a.indexOfList].voice.duration=e?.duration)}})}this.messageList[a.indexOfList].complete=!0}))).subscribe((e=>{this.messageList[a.indexOfList]||o?.onMessageStart?.(e),this.messageList[a.indexOfList]=e,this.latestAIResponse=this.getContentText(e?.content);let t=this.chatSession?.get("messageList")?.length;this.messageList?.length>t&&this.saveChatSession(),e?.complete&&(this.onMessage&&this.onMessage(this,this.messageList[this.messageList?.length-1]),this.saveChatSession(),s.unsubscribe()),this.scrollToBottom&&this.scrollToBottom()}))}getVoiceByContentText(e,t,n=!1){let o=this.getContentText(e),i=new(Parse__default.Object.extend("ChatVoice")),a="",r=this.voiceConfig||this.role?.get("voiceConfig");return this.SSMLRoleVoice=r?.voice||this.SSMLRoleVoice,new Promise((async(e,t)=>{let resolveChatVoice=async()=>{i.set("content",o),i.set("ssml",a),i.set("role","assistant");let t=localStorage.getItem("company");t&&i.set("company",{__type:"Pointer",className:"Company",objectId:t}),Parse__default.User.current()?.id&&i.set("user",Parse__default.User.current().toPointer()),this.chatSession?.id&&i.set("session",this.chatSession?.toPointer()),i=await i.save(),this.voiceMap[i?.id]=i,e({id:i?.id})};if(0==n){let e=r?.provider||"microsoft",t=r?.rate,n=t?"</prosody>":"";a=`<speak provider="${e}">${t?`<prosody rate="${t}">`:""}<voice name="${this.SSMLRoleVoice}">${o}</voice>${n}</speak>`,resolveChatVoice()}if(1==n){let e=await getFormatTpl("talk-text-ssml-tpl",{content:o,SSMLRoleVoice:this.SSMLRoleVoice});new FmodeChatCompletion(this.fixMessageList([{role:"user",content:e}]),{model:this.currentModel?.get("code")||"fmode-4.5-128k"}).sendCompletion({isDirect:!0}).subscribe((async e=>{e?.complete&&(a=this.getContentText(e?.content),resolveChatVoice())}))}}))}getContentText(e){return"string"==typeof e?e:e?.[0]?.text||""}async initTTS(){this.voiceConfig=this.voiceConfig||this.role?.get("voiceConfig");let e=await this.ncloud.apig("voice/tts/token",{company:localStorage.getItem("company"),provider:this.voiceConfig?.provider||"microsoft"});if(e.provider=this.voiceConfig?.provider,e?.provider&&"microsoft"!=e?.provider||(e.provider=new FmodeTTSProviderMicrosoft),"doubao"==e?.provider&&(e.provider=new FmodeTTSProviderDoubao),console.log("initTTS",e),e?.token||e?.stsToken){return new FmodeTTS(e,this.uploadServ)}return null}stopPlayingVoice(){Object.values(this.VoiceTTSMap).forEach((e=>{e?.isPlaying&&e?.stop()}))}async playChatVoice(e,t){let n=await this.initTTS();if(console.log("playChatVoice",n),n){try{this.playAnimation("talking"),n.speakAsync(e?.get("ssml"),e,{onStart:e=>{t?.onStart&&t?.onStart(e)},onLoaded:e=>{t?.onLoaded&&t?.onLoaded(e)},onResult:e=>{t?.onResult&&t?.onResult(e)},onStop:()=>{t?.onStop&&t?.onStop(),this.playAnimation("waiting")}})}catch(e){}return this.VoiceTTSMap[e.id]=n,n}return null}async saveChatSession(){if("new"==this.sessionId&&(this.chatSession=new this.ChatSession),this.chatSession.set("title",this.genTitle()),this.chatSession.set("role",this.role?.toPointer()),this.chatSession.set("messageList",this.messageList),this.chatSession.set("user",Parse__default.User.current()?.toPointer()),this.chatSession=await this.chatSession.save(),this.onChatSaved&&this.onChatSaved(this),this.sessionId=this.chatSession?.id,this.sessionId){let e=`${window.location.origin}/chat/pro/chat/${this.sessionId}`;window.location?.pathname?.indexOf("chat/session")>-1&&(e=`${window.location.origin}/chat/session/chat/${this.sessionId}`),"modal"==this.mode&&(e=window.location.href),e=this.getInviteUrl(e),window.history.replaceState(null,null,e+window.location.search);let t={sid:this.chatSession?.id,rid:this.role?.id,name:this.role?.get("name"),message:this.chatSession?.get("messageList")?.[this.chatSession?.get("messageList")?.length-1]?.content?.slice(0,20),latest:this.chatSession?.createdAt};this.chatServ&&!this.chatServ?.chatList?.length&&(this.chatServ.chatList=[]);let n=this.chatServ?.chatList?.find((e=>e?.sid==t?.sid));n>-1?this.chatServ.chatList[n]=t:this.chatServ?.chatList.unshift(t)}}getInviteUrl(e){let t=new URL(e),n=Parse__default.User?.current()?.id;return t.searchParams.set("invite",n),t.href}genTitle(){if(this.title)return this.title;let e=this.messageList.find((e=>"user"==e.role))?.content;return"string"==typeof e&&(this.title=e?.slice(0,15)||""),"object"==typeof e&&(this.title=e?.find((e=>e?.text))?.text||""),this.title}fixMessageList(e){return e.map((e=>({role:e.role,content:e.content})))}nowStr(){let e=new Date;return`${e.getFullYear()}/${e.getMonth()+1}/${e.getDate()} ${e.getHours()}:${e.getMinutes()}:${e.getSeconds()}`}}class AgentPrompt{constructor(){}jsonCompletion(e,t,n){let o,i=new FmodeChatCompletion([{role:"user",content:e}]);i.model=t||"fmode-4.0-cn-256k";let a=Object.assign({},{isDirect:!0,onComplete:e=>{e.complete=!0}},n);return i.sendCompletion(a).pipe(finalize((()=>{let e;try{o.json=this.extractAndParseJson(e)}catch(e){}o.complete=!0})))}extractAndParseJson(e){let t=e.indexOf("{");if(-1===t)return{};let n=0,o=t;for(let i=t;i<e.length;i++)if("{"===e[i]?n++:"}"===e[i]&&n--,0===n){o=i;break}if(0!==n)return{};const i=e.slice(t,o+1);try{return JSON.parse(i)}catch(e){return console.error("Failed to parse JSON:",e),{}}}extractMarkdownToMultiArray(e){let t=e.split("\n"),n=[],o=n,i=[n];for(let e of t){if(!e.trim())continue;if(e.startsWith("#")){let t=e.replace(/^#+\s*/,"");o.push([t]);continue}let t=e.search(/\S/)/2,n=e.trim().replace(/^-+\s*/,"");for(;t<i.length-1;)i.pop();for(;t>i.length-1;){let e=[];i[i.length-1].push(e),i.push(e)}o=i[i.length-1],o.push(n)}return n}async getFormatTpl(e,t){let n=await this.getPromptTpl(e);return await n.format(t)}async getPromptTpl(e){let t=new Parse__default.Query("PromptTemplate");t.equalTo("code",e);let n=await t.first();return PromptTemplate.fromTemplate(n?.get("template"),{templateFormat:"mustache"})}getTokens(e){return e=e||"",2*e?.length}}class AgentStory{constructor(e,t,n){this.Story=Parse__default.Object.extend("Story"),this.Document=Parse__default.Object.extend("Document"),this.docsList=[],this.story?.id||(this.story=e),this.story?.id||e?.id||(this.story=new this.Story),t?.id&&this.story?.set("person",t?.toPointer()),n?.id&&this.story?.set("book",n),this.story?.get("user")?.id||this.story?.set("user",Parse__default.User.current()?.toPointer())}async setAttachment(e){let t=new Parse__default.Query("Attachment"),n=await t.get(e?.id);return this.story?.set("attach",n),this.story?.set("type","document"),this.story=await(this.story?.save()),this.story?.set("attach",n),n}async loadSlipt(e){let t=await fetch("https://server.fmode.cn/api/aiagent/indexes/loader",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:e?.get("url"),md5:e?.get("md5")})}),n=await t.json(),o=n?.data;return console.log(o),console.log(o?.split),o?.split?.length&&(this.docsList=o?.split?.map((e=>{let t=e,n=new this.Document;return n.set({pageContent:t.pageContent,metadata:t.metadata}),n}))),this.docsList}}class AgentTaskStep{restart(){this.parentIndex&&this.parentComp?.startTask&&this.parentComp?.startTask(this.parentIndex),this.limitStart=!1}get progress(){return this._progress||this._simProgress}set progress(e){this._progress=e}constructor(e){this.shareData={},this.data={},this.buttons=[],this.restartButtonShow=!1,this.limitStart=!1,this.cancelAll=!1,this.progressHidden=!1,this._simProgress=0,this._progress=0,this.message="",this.error="",this.logList=[],this.title=e?.title,this.shareData=e?.shareData,this.progressHidden=e?.progressHidden||!1,this.handle=e?.handle}simulatorProgress(){return this.progressSub$?.unsubscribe(),this.restartButtonShow=!1,new Promise((e=>{let t=function progressHandlerIncreasingSpeed(e,t){return interval(t/(e-1)).pipe(take(e),map((e=>e+1)),concatMap((e=>{const t=100*Math.exp(e/30);return of(e).pipe(delay(t))})))}(80,1e4);this.progressSub$=t.subscribe({next:e=>{this.progress=e},complete:()=>{this.progressSub$?.unsubscribe(),e(!0)}})}))}}class TipsController{constructor(e){this.duration=5,this.container=null,this.currentIndex=0,this.intervalId=null,this.position="top",this.isVisible=!1,this.tipsList=e?.tipsList.length>0?e?.tipsList:this.getDefaultTips(),e?.random&&(this.tipsList=this.tipsList.sort((()=>Math.random()-.5))),this.position=e.position||"top"}getDefaultTips(){return["请耐心等待,精彩内容即将呈现...","生活就像一盒巧克力,你永远不知道下一颗是什么味道。","山重水复疑无路,柳暗花明又一村。","好的开始是成功的一半。","时间是最好的老师,但遗憾的是,它杀死了所有的学生。","不积跬步,无以至千里;不积小流,无以成江海。","代码如诗,简洁为美。"]}addTip(e){this.tipsList.push(e)}setTips(e){this.tipsList=e.length>0?e:this.getDefaultTips()}present(){if(this.isVisible)return;this.container=document.createElement("div"),this.container.id="tips-container",Object.assign(this.container.style,{position:"fixed",[this.position]:"20vh",left:"50%",transform:"translateX(-50%)",zIndex:"9999",backgroundColor:"rgba(255, 255, 255, 0.9)",color:"#333",padding:"12px 24px",borderRadius:"8px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.15)",maxWidth:"92vw",minWidth:"92vw",textAlign:"center",fontSize:"16px",lineHeight:"1.5",transition:"opacity 0.3s ease",border:"1px solid rgba(0, 0, 0, 0.1)",backdropFilter:"blur(4px)",animation:"fadeIn 0.5s ease"});const e=document.createElement("div");e.id="tip-content",e.textContent=this.tipsList[this.currentIndex],Object.assign(e.style,{margin:"0",whiteSpace:"pre-wrap",wordBreak:"break-word"});const t=document.createElement("div");t.id="tip-progress",Object.assign(t.style,{height:"3px",backgroundColor:"rgba(0, 150, 255, 0.5)",width:"100%",borderRadius:"3px",marginTop:"10px",overflow:"hidden"});const n=document.createElement("div");Object.assign(n.style,{height:"100%",width:"100%",backgroundColor:"#0096ff",animation:`progress ${this.duration}s linear forwards`}),t.appendChild(n),this.container.appendChild(e),this.container.appendChild(t),document.body.appendChild(this.container),this.addAnimationStyles(),this.startRotation(),this.isVisible=!0}dismiss(){this.isVisible&&this.container&&(this.container.style.opacity="0",setTimeout((()=>{this.container&&this.container.parentNode&&(document.body.removeChild(this.container),this.container=null),this.stopRotation(),this.isVisible=!1}),300))}startRotation(){this.stopRotation(),this.intervalId=window.setInterval((()=>{this.nextTip()}),1e3*this.duration)}stopRotation(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=null)}nextTip(){if(!this.container)return;this.currentIndex=(this.currentIndex+1)%this.tipsList.length;let e=this.container.querySelector("#tip-content"),t=this.container.querySelector("#tip-progress > div");e&&(e.style.opacity="0",setTimeout((()=>{e.textContent=this.tipsList[this.currentIndex],t&&(t.style.animation="none",t.offsetWidth,t.style.animation=`progress ${this.duration}s linear forwards`),e.style.opacity="1"}),50))}addAnimationStyles(){const e=document.createElement("style");e.textContent="\n @keyframes fadeIn {\n from { opacity: 0; transform: translateX(-50%) translateY(-10px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n }\n @keyframes progress {\n from { width: 100%; }\n to { width: 0%; }\n }\n ",document.head.appendChild(e)}}async function ncloudApi(e,t,n="POST",o){e=o+e;try{let o=JSON.stringify(t);"GET"==n&&(o=null);const i=await fetch(e,{method:n,headers:{"Content-Type":"application/json"},body:o,mode:"cors",credentials:"omit"}),a=await i.json();return!a||200!==a.code&&1!==a.code?null:a.data}catch(e){throw e}}async function novaql(e,t,n){const o=n+"/novaql/select";let i={sql:e};t&&t.length>0&&(i.params=JSON.stringify(t));try{const e=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i),mode:"cors",credentials:"omit"}),t=await e.json();if(t&&200===t.code)return t.data}catch(e){throw e}}async function apig(e,t,n="POST",o){localStorage.setItem("NOVA_APIG_SERVER","aHR0cHMlM0ElMkYlMkZzZXJ2ZXIuZm1vZGUuY24lMkZhcGklMkZhcGlnJTJG"),o||(o=localStorage.getItem("NOVA_APIG_SERVER"),o=decodeURIComponent(atob(o))),e=o+e;let i=Parse__default.User.current(),a={"Content-Type":"application/json",Authorization:`Bearer ${i?.getSessionToken()}`};try{let o=await fetch(e,{method:n,headers:a,body:t?JSON.stringify(t):null,mode:"cors",credentials:"omit"});if(!o.ok)throw new Error(`HTTP error! status: ${o.status}`);let i=await o.json();return!i||200!==i.code&&1!==i.code&&0!==i.code?null:i.data}catch(e){throw console.error("请求出错",e),e}}class NovaCloudService{constructor(e){this.http=e,this.serverURL="https://server.fmode.cn/api",localStorage.setItem("NOVA_APIG_SERVER","aHR0cHMlM0ElMkYlMkZzZXJ2ZXIuZm1vZGUuY24lMkZhcGklMkZhcGlnJTJG")}novaql(e,t){return novaql(e,t,this.serverURL)}apig(e,t,n="post"){return apig(e,t,n)}apigTest(e,t,n="post"){return apig(e,t,n,"https://test.fmode.cn/api/apig/")}api(e,t,n="post"){return ncloudApi(e,t,n,this.serverURL)}searchParse(e){return e=e||location.href,new URL(e).searchParams}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:NovaCloudService,deps:[{token:i1.HttpClient}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:NovaCloudService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:NovaCloudService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1.HttpClient}]});class CrossService{getMenuType(){return this.clientWidth=document.body.clientWidth,this.onResizeScreen(),this.navMenuType}constructor(e,t){this.platform=e,this.navCtrl=t,this.mobileWidth=915,this.clientWidth=document.body.clientWidth,this.clientWidth=document.body.clientWidth,this.updateWidth(),this.onResizeScreen()}async dismisModalTop(e,t){let n=await(e?.getTop());n&&(t?.preventDefault&&t?.preventDefault(),n.dismiss(),n.isOpen=!1)}updateWidth(){this.fixInterval=setInterval((()=>{if(this.clientWidth)return clearInterval(this.fixInterval),void delete this.fixInterval;console.log(document.body.clientWidth),this.clientWidth=document.body.clientWidth}),200)}onResizeScreen(e){this.clientWidth=document.body.clientWidth,this.clientWidth>=this.mobileWidth?(this.leftMenuMode="horizontal",this.navMenuType="pc"):(this.leftMenuMode="inline",this.navMenuType="mobile")}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CrossService,deps:[{token:i3.Platform},{token:i3.NavController}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CrossService,providedIn:"root"})}}function calcFileMd5(e){return new Promise(((t,n)=>{const o=new FileReader;o.onload=e=>{try{const o=e.target?.result;if(o){const e=new SparkMD5.ArrayBuffer;e.append(o);const n=e.end();t(n)}else n(new Error("Failed to load file"))}catch(e){n(e)}},o.onerror=e=>{n(e)},o.readAsArrayBuffer(e)}))}async function getFileMetadata(e){const t={name:e.name,size:e.size,type:e.type,lastModified:e.lastModified,metadata:{}};return t.metadata.lastModified=e.lastModified,e.type.startsWith("image/")?await extractImageMetadata(e,t.metadata):(e.type.startsWith("audio/")||e.type.startsWith("video/"))&&await extractMediaMetadata(e,t.metadata),t}async function extractImageMetadata(e,t){try{const n=new Image,o=URL.createObjectURL(e);await new Promise(((e,t)=>{n.onload=()=>e(),n.onerror=t,n.src=o})),t.width=n.naturalWidth,t.height=n.naturalHeight;try{const n=await e.arrayBuffer(),o=await parseExifData(n);o&&Object.assign(t,o)}catch(e){console.warn("无法解析EXIF数据:",e)}URL.revokeObjectURL(o)}catch(e){console.error("提取图片元数据失败:",e)}}async function extractMediaMetadata(e,t){try{const n=e.type.startsWith("audio/")?new Audio:document.createElement("video"),o=URL.createObjectURL(e);await new Promise(((e,t)=>{n.onloadedmetadata=()=>e(),n.onerror=t,n.src=o})),t.duration=n.duration,"videoWidth"in n&&(t.width=n.videoWidth),"videoHeight"in n&&(t.height=n.videoHeight),URL.revokeObjectURL(o)}catch(e){console.error("提取媒体元数据失败:",e)}}async function parseExifData(e){const t=new DataView(e);return 65496!==t.getUint16(0)?null:{colorDepth:24,orientation:t.getUint16(16,!1)||1}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CrossService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i3.Platform},{type:i3.NavController}]});class NovaUploadService{constructor(e,t){this.platform=e,this.diagnostic=t,this.maxSize=5242880,this.getUptoken(!0),this.requestPermission(),this.queryDomain()}async upload(e,t){let n=e.type,o=e.name?.split("."),i=o[o.length-1],a={id:"",name:"",type:"",size:0,key:"",url:""},r=await this.getFileMd5(e),s=await this.getAttachByMd5(r);if(s?.id)a.url=s?.get("url"),a.name=s?.get("name"),a.type=s?.get("mime"),a.size=s?.get("size"),a.metadata=s?.get("metadata"),t&&t({total:{loaded:a.size,size:a.size,percent:100}});else{let o=this.fileToBlob(e);a=n.indexOf("image")>-1?await this.saveQiniuImageFile(o,i,null,t):await this.saveQiniuMediaFile(e,o,null,t)}a?.url?.indexOf("undefined")>-1&&(a.url=(this.qiniuDomain||"https://file-cloud.fmode.cn/")+a.url.replace("undefined/",""));let l,c=(await getFileMetadata(e)).metadata;return a.metadata||(a.metadata={}),Object.keys(c).forEach((e=>{a.metadata[e]=c[e]})),console.log("metadata",c,a),a?.url&&(l=await this.saveAttachment(a,this.qiniuDomain,null,this.getCompanyId(),e)),l?.id&&(a.id=l?.id),a.attachment=l,a}async getAttachByMd5(e){if(!e)return null;let t=new Parse__default.Query("Attachment");return t.equalTo("md5",e),t.addDescending("createdAt"),await t.first()}isCapacitor(){return this.platform.is("capacitor")||this.platform.is("cordova")}async getFileMd5(e){let t;try{t=await calcFileMd5(e),console.log("md5File",t)}catch(e){console.error(e)}return t}async requestPermission(){this.isCapacitor()&&(await this.requestStoagePermission(),await this.requestCameraPermission())}async requestStoagePermission(){let e=await this.diagnostic.isExternalStorageAuthorized();if(console.log("permisson_STORAGE:",e),!e){await this.diagnostic.requestExternalStorageAuthorization()}}async requestCameraPermission(){let e=await this.diagnostic.isCameraAuthorized();if(console.log("permisson_Camera:",e),!e){await this.diagnostic.requestCameraAuthorization()}}async getUptoken(e=!1){if(console.log("getUptoken"),this.qiniuConf||e)try{console.log(this.getCompanyId());let e=await Parse__default.Cloud.run("qiniu_uptoken",{company:this.getCompanyId()});console.log(e),this.qiniuConf=e}catch(e){console.error(e)}}genFileKey(e,t){let n=new Date,o=new DatePipe("en");t||(t=this.getCompanyId());let i="storage/company/"+t+"/";return this.store?.id&&this.store?.id,i+""+(o.transform(n,"yMMdd")+"/"+String(e.id).substr(20,6)+o.transform(n,"hhmmssSSS")+/\.[^\.]+/.exec(e.name))}getCompanyId(){if(this.company)return this.company;return localStorage.getItem("company")}async queryDomain(){let e=new Parse__default.Query("Company"),t=await e.get(this.getCompanyId());t.get("configQiniu")&&t.get("configQiniu").domain?(console.log(t.get("configQiniu").domain),this.qiniuDomain=t.get("configQiniu").domain):this.qiniuDomain="https://file-cloud.fmode.cn"}async saveAttachment(e,t,n,o,i){e.md5=await this.getFileMd5(i);let a=e.url;a.startsWith("http")||(a=t+a),a=a.replace(/undefined\//,""),o||(o=localStorage.getItem("company"));let r,s=Parse__default.User.current();if(r?.id)return console.log("fast upload"),r;return r=new(Parse__default.Object.extend("Attachment")),r.set("size",e.size),r.set("url",a),r.set("name",e.name),r.set("mime",e.type),r.set("md5",e?.md5),r.set("metadata",e?.metadata),this.store?.id&&r.set("store",this.store.toPointer()),s?.id&&r.set("user",s.toPointer()),o&&r.set("company",{__type:"Pointer",className:"Company",objectId:localStorage.getItem("company")}),n&&r.set("category",{__type:"Pointer",className:"Category",objectId:n}),await r.save()}async captureVideo(e){if(this.qiniuConf=e,!this.isCapacitor())return;let t=await this.cameraCaptureVideoFile(),n=await this.getMediaFileDataString(t);return await this.saveQiniuMediaFile(t,n)}async cameraCaptureVideoFile(){let e=MediaCapture,t=await e.captureVideo({limit:1});return t?.length>0?t[0]:null}async getMediaFileDataString(e){new FilesystemWeb,e.fullPath.replaceAll("///","//");let t=await Filesystem.stat({path:e.fullPath}),n=Capacitor.convertFileSrc(t.uri),o=await fetch(n),i=await o.blob();if(console.log(i.size),console.log(JSON.stringify(t)),console.log(JSON.stringify(o)),console.log(JSON.stringify(Object.keys(o))),i)return i;throw"读取文件失败"}async takePicture(e){if(this.qiniuConf=e,!this.isCapacitor())return;await this.getUptoken();let t=await this.cameraTakePictureDataUrl();if(!t?.dataUrl)return;let n=await this.base64ToBlob(t?.dataUrl),o=await this.saveQiniuImageFile(n,t?.format);return console.log(JSON.stringify(o)),o}async cameraTakePictureDataUrl(){if(!this.isCapacitor())return;return await Camera.getPhoto({quality:90,allowEditing:!1,source:CameraSource.Camera,resultType:CameraResultType.DataUrl})}async saveQiniuImageFile(e,t,n,o){let i=this.maxSize;if(e.size>i)throw await console.log("照片过大,超出限制5MB"),"超出文件大小";let a=new DatePipe("en").transform(new Date,"yyyyMMddHHmmss"),r=`${a}.${t}`,s=e.type,l={fname:r,params:{},mimeType:e.type},c={useCdnDomain:!0,forceDirect:!0};console.log(this.qiniuConf);let d=this.genFileKey({id:a,name:r});return console.log("图片上传前"),console.log(d,e,t),new Promise(((t,n)=>{console.log("进入了上传"),qiniu.upload(e,d,this.qiniuConf?.uptoken,l,c).subscribe({next:e=>{console.log(e),o&&o(e)},error:async e=>{console.log(e)},complete:n=>{console.log("上传完成"),console.log(`${this.qiniuConf?.domain}${n.key}`),n.url=`${this.qiniuConf?.domain}${n.key}`,n.name=r,n.type=s,n.size=e.size,t(n)}})}))}async saveQiniuMediaFile(e,t,n,o){let i=e.name,a=e.type;if(e.size>(this.maxSize||104857600))throw console.log("视频过大,超出限制100MB"),"超出文件大小";let r=new DatePipe("en").transform(new Date,"yyyyMMddHHmmss"),s={fname:i,params:{},mimeType:a},l={useCdnDomain:!0,forceDirect:!0},c=this.genFileKey({id:r,name:i});return console.log("图片上传前"),console.log(e.name,t.size),console.log(t.size),console.log(t.size/1024/1024),new Promise(((n,i)=>{console.log("进入了上传"),qiniu.upload(t,c,this.qiniuConf?.uptoken,s,l).subscribe({next:e=>{console.log("主要用来展示进度"),o&&o(e),console.log(JSON.stringify(e))},error:async e=>{console.log("上传失败"),console.log(JSON.stringify(e))},complete:t=>{console.log("上传完成"),console.log(JSON.stringify(t)),e.key=t.key,console.log(e.type),e.url=`${this.qiniuConf?.domain}${t.key}`,console.log(e.url),n(e)}})}))}async base64ToBlobType(e,t){let n=await fetch(`data:${t};base64,${e}`);return await n.blob()}async base64ToBlob(e){let t=await fetch(e);return await t.blob()}fileToBlob(e){const t=e.slice(0,e.size,e.type);return new Blob([t],{type:e.type})}genMd5(e){return CryptoJS.MD5(e).toString()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:NovaUploadService,deps:[{token:i3.Platform},{token:i5.Diagnostic}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:NovaUploadService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:NovaUploadService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i3.Platform},{type:i5.Diagnostic}]});class ChatService{constructor(e,t,n,o,i,a,r){this.router=e,this.ncloud=t,this.platform=n,this.alertCtrl=o,this.navCtrl=i,this.cross=a,this.uploadServ=r,this.chatMap={},this.isCapacitor=!1,this.platformMap={pc:"电脑端",mobile:"移动端"},this.isCapacitor=this.platform.is("capacitor")}async doButtonAction(e){let t=this.cross.navMenuType,n=e?.platform?.map((e=>this.platformMap[e])).join("、");if(e?.platform?.length>0&&-1==e?.platform?.indexOf(t)){(await this.alertCtrl.create({header:"注意",subHeader:"终端不符",message:`请您使用${n}开启本功能。`,buttons:[{role:"ok",text:"知道了"}]})).present()}else e?.path&&this.navCtrl.navigateRoot(e?.path)}async initChatMap(e){if(this.chatMap[e])return this.chatMap[e];let t=new Parse__default.Query("ChatSession");t.include("user","role","role.model","story","story.person","person","person.userVerify");let n=await t.get(e),o=new FmodeChat(n?.id,n?.get("role"),n,this,this.navCtrl,this.ncloud,this.uploadServ);return this.chatMap[e]=o,this.chatMap[e]}async getChatSession(e){if(!Parse__default?.User?.current()?.id)return;let t=new Parse__default.Query("ChatSession");e&&(t=Parse__default.Query.fromJSON("ChatSession",e)),t.include("user","role","role.model","story","story.person","story.person.userVerify","person","person.userVerify"),t.addDescending("updatedAt"),t.equalTo("user",Parse__default.User.current().toPointer()),t.notEqualTo("isDeleted",!0),t.limit(30);let n=await t.find();this.chatList=n.map((e=>(this.chatMap[e?.id]=new FmodeChat(e?.id,e?.get("role"),e,this,this.navCtrl,this.ncloud,this.uploadServ),{session:e,sid:e?.id,isHidden:!1,rid:e?.get("role")?.id,name:e?.get("role")?.get("name"),thumb:e?.get("role")?.get("thumb"),title:e?.get("title")||e?.get("role")?.get("name"),message:e?.get("messageList")?.[e?.get("messageList")?.length-1]?.content?.slice(0,20),latest:e?.createdAt})))}async getChatSessionDistinct(){let e=await this.ncloud.novaql('SELECT t1."objectId" as sid , "AvatarRole"."objectId" as rid, * FROM (\n SELECT *,ROW_NUMBER() OVER (PARTITION BY "user", "role" ORDER BY "createdAt" DESC) AS rn\n FROM "ChatSession" WHERE "user"=$1\n ) as t1\n LEFT JOIN "AvatarRole" ON "AvatarRole"."objectId" = t1."role"\n WHERE t1.rn=1\n LIMIT $2\n ;',[Parse__default.User.current()?.id,10]),t=e?.map((e=>({sid:e?.sid,rid:e?.rid,name:e?.name,message:e?.messageList?.[e?.messageList?.length-1]?.content?.slice(0,20),latest:e?.createdAt})));return this.chatList=t,this.chatList}createChatPanel(e,t){let n=t?.id||"new";t=new FmodeChat(n,e,t,this,this.navCtrl,this.ncloud,this.uploadServ),this.chatMap[n]=t,this.router.navigate(["/chat/pro/chat/"+n])}async createNewRoleChat(e){let t=new Parse__default.Query("AvatarRole");t.include("model");let n=await t.get(e);return new FmodeChat("new",n,null,this,this.navCtrl,this.ncloud,this.uploadServ)}async restoreChatPanel(e){let t=new Parse__default.Query("AvatarRole"),n=new Parse__default.Query("ChatSession"),o=await t.get(e?.rid),i=await n.get(e?.sid),a=new FmodeChat(e?.sid,o,i,this,this.navCtrl,this.ncloud,this.uploadServ);this.chatMap[e?.sid]=a,this.router.navigate(["/chat/pro/chat/"+e?.sid])}async callRole(e){document.body.classList.add("dark"),this.router.navigate([`/avatar/role/${e.id}`,{type:"phone"}])}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatService,deps:[{token:i1$1.Router},{token:NovaCloudService},{token:i3.Platform},{token:i3.AlertController},{token:i3.NavController},{token:CrossService},{token:NovaUploadService}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatService,providedIn:"root"})}}async function drawDalle(e){e.size=e?.size||"1024x1024",e.style=e?.style||"natural",e.quality=e?.quality||null;let t={model:"dall-e-3",prompt:e.prompt,n:1,quality:e.quality,response_format:"url",size:e.size,style:e.style};if(e.prompt?.length>3e3)throw"prompt maximum < 4000 characters";let n,o=await apig("aigc/gpt/v1/images/generations",t);if(console.log(o),o?.id){let e=new Parse__default.Query("ImagineWork");e.get(o?.id),n=await e.first(),console.log(n)}return n}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1$1.Router},{type:NovaCloudService},{type:i3.Platform},{type:i3.AlertController},{type:i3.NavController},{type:CrossService},{type:NovaUploadService}]});class ImagineService{constructor(e,t,n){this.http=e,this.ncloud=t,this.uploadServ=n,this.taskDetailMap={},this.newWorkList=[],this.myWorkList=[]}async drawDalle(e){let t=await drawDalle(e);return t?.id&&this.newWorkList.unshift(t),t}priceDalle(e){let t=[{model:"dall-e-3",quality:null,size:"1024x1024",credit:6.4},{model:"dall-e-3",quality:null,size:"1024x1792",credit:12.8},{model:"dall-e-3",quality:null,size:"1792x1024",credit:12.8},{model:"dall-e-3",quality:"hd",size:"1024x1024",credit:12.8},{model:"dall-e-3",quality:"hd",size:"1024x1792",credit:19.2},{model:"dall-e-3",quality:"hd",size:"1792x1024",credit:19.2},{model:"dall-e-2",quality:null,size:"1024x1024",credit:3.2},{model:"dall-e-2",quality:null,size:"512x512",credit:2.88},{model:"dall-e-2",quality:null,size:"256x256",credit:2.56}].find((t=>t.model==e.model&&t.quality==e.quality&&t.size==e.size));return t?.credit||19.2}priceStableDiffusion(e){let t=e.width*e.height,n=763e-9*t*e.steps+2278e-8*t*(e?.upscale||0)+(e?.hrSteps||0)*t*(e?.hrScale||0)*(e?.hrScale||0)*763e-9+(e?.faceFix?2:0)+(e?.imgOptions?.removeBackground?2:0)+(e?.imgOptions?.redrawBackground?2:0)+(e?.imgOptions?.facePreservation?2:0)+(e?.imgOptions?.genderDetect?1:0)+2*(e?.controlnet?.units?.length||0);return n=.3*n*e.batchSize,n}b64DataToBase64Image(e){let t=atob(e),n=new Blob([t],{type:"image/webp"});new Promise((e=>{let t=new FileReader;t.onloadend=function(){let n=t.result;console.log(n),e(n)},t.readAsDataURL(n)}))}async draw(e){let t=await this.ncloud.apig("aigc/sdapi/v1/draw",e),n=t?.paintingSign;return n&&setTimeout((async()=>{let e=new Parse__default.Query("ImagineWork");e.equalTo("taskId",n);let t=await e.first();console.log(t),t?.id&&this.newWorkList.unshift(t)}),1e3),t}async taskDetail(e){let t=await this.ncloud.apig("aigc/sdapi/v1/task/detail",{taskId:e});return console.log(t),this.taskDetailMap[e]=t,t}getMyWorkQuery(){let e=Parse__default.User.current();if(!e?.id)return;let t=this.getWorkQuery();return t.include("model","module","user"),t.equalTo("user",e.toPointer()),t}getWorkQuery(){let e=new Date((new Date).getTime()-6e4),t=Parse__default.Query.fromJSON("ImagineWork",{where:{$or:[{createdAt:{$lte:e},progress:{$ne:0}},{createdAt:{$gt:e}}]}});return t.include("model","module","user"),t.notEqualTo("isDeleted",!0),t.notEqualTo("isFailed",!0),t.doesNotExist("respData.error"),t.doesNotExist("respData.data.taskLimitCount"),t.addDescending("createdAt"),t}getimg(){return new Promise(((e,t)=>{let n=document.createElement("input");n.type="file",n.click();let handleChange=async()=>{if(n.removeEventListener("change",handleChange),n.files&&n.files.length>0){let t=n.files[0],o=await this.uploadServ.upload(t,(e=>{console.log(e),e.total.percent.toFixed(2)}));e(o.url)}else t("未选择文件")};n.addEventListener("change",handleChange)}))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ImagineService,deps:[{token:i1.HttpClient},{token:NovaCloudService},{token:NovaUploadService}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ImagineService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ImagineService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1.HttpClient},{type:NovaCloudService},{type:NovaUploadService}]});class FmaiService{constructor(e,t){this.imagine=e,this.chat=t}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmaiService,deps:[{token:ImagineService},{token:ChatService}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmaiService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmaiService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:ImagineService},{type:ChatService}]});class ImagineWork{constructor(e){this.task=null,this.progress=0,this.images=[],this.id=e,this.fetchTask()}async fetchTask(){if(this.id){const e=new Parse__default.Query("ImagineWork");try{let t=await e.get(this.id);this.task=t,t.id&&(this.progress=this.task.get("progress"),this.images=this.task.get("images"),this.images?.length&&(this.progress=1))}catch(e){console.error("Error fetching task:",e)}}return this.task}draw(e){return new Observable((t=>{if(this.task)return t.next(this.task),void t.complete();drawDalle(e).then((e=>{this.id=e.id,this.fetchTask();const n=new Parse__default.Query("ImagineWork"),o=setInterval((()=>{n.get(this.id).then((e=>{this.progress+=.01,this.task=e,t.next(e),this.task?.get("images")?.length&&(this.progress=1,clearInterval(o),t.complete())})).catch((e=>{clearInterval(o),t.error(e)}))}),1e3)})).catch((e=>{t.error(e)}))}))}}let colorMap=["primary","secondary","tertiary","success","warning","danger","light","medium","dark"];const MASK_LIST=[{name:"执行李",type:"employee",title:"首席执行官",desc:"一位富有远见和领导才能的创业新秀。她具备战略思维和决策能力,能够为公司设定长期目标并领导团队实现这些目标。",color:colorMap[0],cover:"https://imgsource.huashi6.com/images/ai/2023/9/29/15_48766.jpg?e=1695974629&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:oPkQSsyQLLD08R_J4SMeO1f1RdM="},{name:"技术刘",type:"employee",title:"首席技术官",desc:"一位技术专家,拥有广泛的技术知识和经验。他善于解决复杂的技术问题,并能够领导开发团队实施创新的技术解决方案。",color:colorMap[1],cover:["https://imgsource.huashi6.com/images/ai/2023/9/29/9_619877.jpg?e=1695952672&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:LDuSg8_n5g4Rj_8F5PKrGzV4T54=","https://imgsource.huashi6.com/images/ai/2023/9/27/20_17767.jpg?e=1695819037&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:a9uOeeJMN2oopK-3WQZzldPXfH0="]},{name:"点子王",type:"employee",title:"首席运营官",desc:"一位富有创意和市场洞察力的市场营销专家。她擅长制定营销策略,了解目标受众,并能够利用各种渠道和工具推广公司的产品或服务。",color:colorMap[2],cover:"https://imgsource.huashi6.com/images/ai/2023/9/29/9_186291.jpg?e=1695952125&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:EhEUtwnC9hpu-SXXsBrp2Q-rcJk="},{title:"设计总监",name:"李欣",type:"employee",desc:"一位富有创造力和用户导向思维的设计师。她能够理解用户需求,并通过设计直观、易用且吸引人的用户界面来提供出色的用户体验。",color:colorMap[3],cover:"https://imgsource.huashi6.com/images/ai/2023/9/29/9_18099.jpg?e=1695952201&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:G_a60v52iTTqvJgeTSa_8zJUY2w="},{title:"运营经理",name:"刘洁",type:"employee",desc:"一位组织能力强、注重细节并擅长解决问题的运营专家。她能够协调各个部门的工作,并确保公司的运营流程高效运行。",color:colorMap[4],cover:"https://imgsource.huashi6.com/images/ai/2023/9/29/9_842519.jpg?e=1695952125&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:FM_kKZDzkcLQ1EX4266dXU46cRc="},{title:"销售经理",name:"张伟",type:"employee",desc:"一位富有销售天赋和人际交往能力的销售专家。他善于与客户建立良好的关系,并能够推动销售团队实现业绩目标。",color:colorMap[5],cover:"https://imgsource.huashi6.com/images/ai/2023/9/29/15_739110.jpg?e=1695974920&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:vg_sn-qn67MJS-7j2o7mWzOCUSk="},{title:"数据分析师",name:"杨晨",type:"employee",desc:"一位善于解读数据和提供商业洞察的数据分析专家。她能够收集、分析和解释数据,为公司的决策制定提供有力的支持。",color:colorMap[6],cover:"https://imgsource.huashi6.com/images/ai/2023/9/29/15_204321.jpg?e=1695974779&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:dC2sGmJekSPBTCycPF76BkQPBoo="},{title:"财务经理",name:"赵晓",type:"employee",desc:"一位精通财务管理和分析的专业人士。她能够制定财务战略、管理公司的财务流程,并提供准确的财务报告和预测。",color:colorMap[7],cover:"https://imgsource.huashi6.com/images/ai/2023/9/29/15_947878.jpg?e=1695974779&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:TFGn0_l2PqhUTe9G4A3it769hcU="},{title:"品牌专员",name:"王雅",type:"employee",desc:"一位富有创意和品牌意识的专业人士。她能够塑造和管理公司的品牌形象,制定品牌营销策略,并与内部和外部利益相关者建立良好的合作关系。",color:colorMap[8],cover:["https://imgsource.huashi6.com/images/ai/2023/9/29/15_129581.jpg?e=1695975151&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:YQrpiv1hBKRPIdaEbDDDkLFuPG8=","https://imgsource.huashi6.com/images/ai/2023/9/29/15_912136.jpg?e=1695975151&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:8SVMU1rdKD8eaJ1gH_qGQzcrMhM="]},{title:"全科",name:"孔博",type:"teacher",desc:"擅长全科教学的金牌教师,知识面广泛,博古通今,因材施教,耐心稳重。",color:colorMap[0],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/12_40958.jpg?e=1697604189&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:U7r1Td30lXdf9mE1TMVAnDhBP6c="]},{title:"语文",name:"王明",type:"teacher",desc:"激发学生对文学的热爱,引导他们成为优秀的作家和沟通者。",color:colorMap[1],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/11_698893.jpg?e=1697602689&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:hK_AuY7BA1pp33QVeUue5QjIg4o="]},{title:"数学",name:"万红",type:"teacher",desc:"以清晰的逻辑和耐心的指导,帮助学生掌握数学的基础知识和解题技巧。",color:colorMap[2],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/11_256253.jpg?e=1697603314&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:K2iqp_ZzHYzXNu_0VJlywyANHp8="]},{title:"英语",name:"张瑞",type:"teacher",desc:"激发学生对英语学习的兴趣,培养他们的听、说、读、写能力,让他们自信地运用英语。",color:colorMap[3],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/12_266171.jpg?e=1697603707&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:uhpxBbT-jlSt_KjAnj0SFsFAjWU="]},{title:"物理",name:"金晓",type:"teacher",desc:"通过实验和案例,帮助学生理解物理原理,培养他们的科学思维和实验技能。",color:colorMap[4],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/11_694925.jpg?e=1697603071&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:FznZxhkYUrZ-BzX05dvNt8acTUw="]},{title:"化学",name:"陈华",type:"teacher",desc:"激发学生对化学的好奇心,教授他们化学知识和实验技巧,培养他们的实验和分析能力。",color:colorMap[5],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/11_942234.jpg?e=1697603169&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:__2T8cxLl4J0AwMR9MJdDiooDF0="]},{title:"生物",name:"杨婷",type:"teacher",desc:"引导学生探索生命的奥秘,培养他们的科学观察和实验能力,让他们热爱生物科学。",color:colorMap[6],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/12_330738.jpg?e=1697603491&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:2K5-DHPnUQ-R9GGxtWKiEG68QlE="]},{title:"历史",name:"赵亮",type:"teacher",desc:"帮助学生了解历史事件和文化背景,培养他们的历史意识和批判思维。",color:colorMap[7],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/11_256302.jpg?e=1697602689&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:YP7ffC1YKO-Pb0C3ks4caT0QqZk="]},{title:"地理",name:"林丽",type:"teacher",desc:"引导学生探索地球的奥秘,培养他们的地理观察和分析能力,让他们热爱地理科学。",color:colorMap[8],cover:["https://imgsource.huashi6.com/images/ai/2023/10/18/12_555804.jpg?e=1697604054&token=qFZErZx7WS1v5B4rgQE2KLMHlYHVNaCuXeaA9OLD:xLN4QW0x9jx9lEB4EFHWvI_gEsI="]}];class UtilnowPipe{constructor(){this.enLocale={"秒钟前":" seconds ago","分钟前":" minutes ago","小时前":" hours ago","天前":" days ago"}}transform(e,t){let n=((new Date).getTime()-e.getTime())/1e3;if(n<=60)return this.handleArgs(n.toFixed(0),"秒钟前",t);let o=n/60;if(o<60)return this.handleArgs(o.toFixed(0),"分钟前",t);let i=o/60;if(i<24)return this.handleArgs(i.toFixed(0),"小时前",t);let a=i/24;return a<7?this.handleArgs(a.toFixed(0),"天前",t):`${e?.getFullYear()}-${e?.getMonth()+1}-${e?.getDate()}`}handleArgs(e,t,n){return"en"==n&&(t=this.enLocale[t]),"TranslateService"==n?.constructor?.name&&(console.log(t),"en"==n?.getDefaultLang()&&(t=this.enLocale[t])),"json"==n?{unit:t,value:e}:e+t}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:UtilnowPipe,deps:[],target:i0.ɵɵFactoryTarget.Pipe})}static{this.ɵpipe=i0.ɵɵngDeclarePipe({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:UtilnowPipe,isStandalone:!0,name:"utilnow"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:UtilnowPipe,decorators:[{type:Pipe,args:[{name:"utilnow",standalone:!0}]}]});class ChatContentPipe{transform(e,...t){let n=t?.[0]||"text";return"text"==n?getMessageContentText(e):"image_url"==n?getMessageImageUrl(e):e}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatContentPipe,deps:[],target:i0.ɵɵFactoryTarget.Pipe})}static{this.ɵpipe=i0.ɵɵngDeclarePipe({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:ChatContentPipe,isStandalone:!0,name:"chatContent"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatContentPipe,decorators:[{type:Pipe,args:[{name:"chatContent",pure:!0,standalone:!0}]}]});class HidexmlPipe{transform(e,...t){return e?this.hideXmlTags(e):""}hideXmlTags(e){return e.replace(/<[^>]*>/g,"")}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:HidexmlPipe,deps:[],target:i0.ɵɵFactoryTarget.Pipe})}static{this.ɵpipe=i0.ɵɵngDeclarePipe({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:HidexmlPipe,isStandalone:!0,name:"hidexml"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:HidexmlPipe,decorators:[{type:Pipe,args:[{name:"hidexml",standalone:!0}]}]});class MarkdownMathJax{constructor(e){this.options=e,this.adaptor=liteAdaptor(),RegisterHTMLHandler(this.adaptor)}text_to_mathjax(e,t){if(!e?.length)return"";if(!e?.replace)return"";t=t||this.options;let n=new SVG({fontCache:"local"});"chtml"==t?.output&&(n=new CHTML);const o=mathjax.document("",{skipHtmlTags:["script","noscript","style","textarea","pre","code","annotation","annotation-xml"],InputJax:new TeX({processEscapes:!0,packages:AllPackages}),OutputJax:n}),i={em:16,ex:8,containerWidth:1280};return[/\$\$\ (.+?)\ \$\$/g,/\$\$(.+?)\$\$/g,/\$\$\n(.+?)\n\$\$/g,/\$(.+?)\$/g,/\\\((.+?)\\\)/g,/\\\[(.+?)\\\]/g].forEach((t=>{e=e.replace(t,((e,n)=>{let a;console.log(t,e,n);try{a=o.convert(`${n}`,i)}catch(e){}if(a){return`<span class="mathjax raw" style="margin-left:10px;margin-right:10px;">${this.adaptor.innerHTML(a)}</span>`}return n}))})),e}}let md=new MarkdownIt({html:!0,xhtmlOut:!0,breaks:!1,linkify:!1,typographer:!1,quotes:"“”‘’",highlight:function(e,t){if(t&&hljs.getLanguage(t))try{return`<pre style="position:relative;padding:10px;" class="hljs lang-${t}"><code>${hljs.highlight(e,{language:t}).value}</code><small class="hljs-lang"><span class="sr-only">Language:</span>${t}</small></pre>`}catch(e){}return""}});md.use(abbr),md.use(footnote),md.use(deflist),md.use(mark),md.use(ins),md.use(sub),md.use(sup),md.use(ruby);const mditConfig={plantumlServer:"https://www.plantuml.com/plantuml"};function makePlantumlURL(e){const t=plantumlEncoder.encode(e);return`${mditConfig.plantumlServer}/svg/${t}`}md.renderer.rules.plantuml=(e,t,n,o,i)=>{const a=e[t];if("plantuml"!==a.type)return e[t].content;return`\n <img src="${makePlantumlURL(a.content)}" />\n <pre style="position:relative;padding:10px;" class="hljs lang-plantuml"><code>${a.content}</code><small class="hljs-lang"><span class="sr-only">Language:</span>plantuml</small></pre>\n `},md.core.ruler.push("plantuml",(e=>{const t=e.tokens;for(const e of t)"fence"===e.type&&"plantuml"===e.info&&(e.type="plantuml")}));const spaceregex=/\s*/,notinhtmltagregex=/(?![^<]*>|[^<>]*<\/)/;let coloregex=/\[color=([#|(|)|\s|,|\w]*?)\]/;coloregex=new RegExp(coloregex.source+notinhtmltagregex.source,"g");let nameregex=/\[name=(.*?)\]/,timeregex=/\[time=([:|,|+|-|(|)|\s|\w]*?)\]/;const nameandtimeregex=new RegExp(nameregex.source+spaceregex.source+timeregex.source+notinhtmltagregex.source,"g");function replaceExtraTags(e){return console.log("replaceExtraTags",e),e=(e=(e=(e=e.replace(coloregex,'<span class="color" data-color="$1"></span>')).replace(nameandtimeregex,'<small><i class="fa fa-user"></i> $1 <i class="fa fa-clock-o"></i> $2</small>')).replace(nameregex,'<small><i class="fa fa-user"></i> $1</small>')).replace(timeregex,'<small><i class="fa fa-clock-o"></i> $1</small>'),console.log("replaceExtraTags",e),e}function finishView(e){let t=$.parseHTML(`<html><body><div id="topmd">${e}</div></body></html>`)[0],n=$(t),o=n.find("blockquote.raw").removeClass("raw");o=n.find("blockquote");let i=$(o).find("p");i.each(((e,t)=>{let n=$(t).html();n=replaceExtraTags(n),t.innerHTML=n,$(t).html(n),i[e].innerHTML=n,$(i[e]).html(n)})),o.find(".color").each(((e,t)=>{let n=$(t).attr("data-color");$(t).closest("blockquote").css("border-left-color",n)}));let a="<style>\n .markdown-section {\n color: black;\n text-align: left;\n }\n .markdown-section pre .hljs-lang{\n text-transform: uppercase;\n font-weight: 700;\n font-size: .75rem;\n line-height: 1rem;\n padding-top: .25rem;\n padding-bottom: .25rem;\n padding-left: .5rem;\n padding-right: .5rem;\n background-color: rgba(0,0,0,.3);\n border-bottom-left-radius: .375rem;\n top:0;\n right:0;\n position:absolute;\n}\n\n }\n .markdown-section pre .hljs {\n position:relative!important;\n background: #272822!important;\n padding:10px!important;\n color: #ddd;\n text-shadow: none!important;\n }\n\n .markdown-section blockquote {\n margin: 0;\n margin-bottom: 0px;\n margin-bottom: .85em;\n padding: 0 15px;\n color: #858585;\n border-left: 4px solid #e5e5e5;\n border-left-color: rgb(229, 229, 229);\n }\n .markdown-section img {\n max-width:100%;\n }\n </style>"+(n.html()||e);return a=a.replaceAll('src="/uploads/','src="https://md.fmode.cn/uploads/'),a}nameregex=new RegExp(nameregex.source+notinhtmltagregex.source,"g"),timeregex=new RegExp(timeregex.source+notinhtmltagregex.source,"g");class MarkdownParse{constructor(){}parseToHTML(e){if(!e?.length)return"";if(!e?.replace)return"";let t=new MarkdownMathJax;e=e.split("```").map(((e,n)=>n%2==0?e=t.text_to_mathjax(e,{output:"svg"}):e)).join("```");let n=md.render(e);return n=finishView(n),n}info(...e){}}class MarkdownPreviewComponent{constructor(e,t){this.domSan=e,this.renderer=t,this.content="",this.render=!0}ngAfterViewInit(){this.renderMdToHTML()}renderMdToHTML(){if(!this.render)return;let e=(new MarkdownParse).parseToHTML(this.content);this.safeHTML=this.domSan.bypassSecurityTrustHtml(e);let t=this.renderer.createElement("div");t.innerHTML=e,this.renderer.appendChild(this.mdContent.nativeElement,t)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:MarkdownPreviewComponent,deps:[{token:i1$2.DomSanitizer},{token:i0.Renderer2}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:MarkdownPreviewComponent,selector:"fm-markdown-preview",inputs:{content:"content",render:"render"},viewQueries:[{propertyName:"mdContent",first:!0,predicate:["mdContent"],descendants:!0}],ngImport:i0,template:'<div class="message-body">\n <div *ngIf="render" #mdContent class="markdown-section">\n </div>\n <div *ngIf="!render" class="pre-section">\n {{content}}\n </div>\n</div>',styles:[":host{overflow-x:auto}.message-body div{text-align:left;overflow-x:auto}.message-body .pre-section{white-space:pre-wrap}.markdown-section blockquote{margin:0 0 .85em;padding:0 15px;color:#858585;border-left:4px solid #e5e5e5;border-left-color:#e5e5e5}\n"],dependencies:[{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:MarkdownPreviewComponent,decorators:[{type:Component,args:[{selector:"fm-markdown-preview",template:'<div class="message-body">\n <div *ngIf="render" #mdContent class="markdown-section">\n </div>\n <div *ngIf="!render" class="pre-section">\n {{content}}\n </div>\n</div>',styles:[":host{overflow-x:auto}.message-body div{text-align:left;overflow-x:auto}.message-body .pre-section{white-space:pre-wrap}.markdown-section blockquote{margin:0 0 .85em;padding:0 15px;color:#858585;border-left:4px solid #e5e5e5;border-left-color:#e5e5e5}\n"]}]}],ctorParameters:()=>[{type:i1$2.DomSanitizer},{type:i0.Renderer2}],propDecorators:{content:[{type:Input}],mdContent:[{type:ViewChild,args:["mdContent"]}],render:[{type:Input}]}});class MarkdownPreviewModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:MarkdownPreviewModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:MarkdownPreviewModule,declarations:[MarkdownPreviewComponent],imports:[CommonModule],exports:[MarkdownPreviewComponent]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:MarkdownPreviewModule,imports:[CommonModule]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:MarkdownPreviewModule,decorators:[{type:NgModule,args:[{declarations:[MarkdownPreviewComponent],imports:[CommonModule],exports:[MarkdownPreviewComponent]}]}]});class ClipboardService{constructor(e){this.toastCtrl=e}async copyToClipboard(e){try{return await Clipboard.write({string:e}),void this.copySuccess()}catch(t){try{if(navigator.clipboard&&window.isSecureContext)return await(navigator?.clipboard?.writeText(e)),void this.copySuccess();throw!1}catch(t){let n=document.createElement("textarea");n.value=e,n.style.position="fixed",n.style.left="-9999px",n.style.top="-9999px",document.body.appendChild(n),n.focus(),n.select();try{let e=document?.execCommand("copy");e?this.copySuccess():console.error("无法复制文本")}catch(e){console.error("无法复制文本: ",e)}document.body.removeChild(n)}}}async copySuccess(){(await this.toastCtrl.create({duration:1e3,message:"复制成功",color:"primary",icon:"information-circle",position:"top"})).present()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ClipboardService,deps:[{token:i3.ToastController}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ClipboardService,providedIn:"root"})}}function pcmtoWav(e,t,n,o){let i={chunkId:[82,73,70,70],chunkSize:0,format:[87,65,86,69],subChunk1Id:[102,109,116,32],subChunk1Size:16,audioFormat:1,numChannels:n||1,sampleRate:t||16e3,byteRate:0,blockAlign:0,bitsPerSample:o||16,subChunk2Id:[100,97,116,97],subChunk2Size:0};function u32ToArray(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]}function u16ToArray(e){return[255&e,e>>8&255]}let a=new Uint8Array(e);i.blockAlign=i.numChannels*i.bitsPerSample>>3,i.byteRate=i.blockAlign*i.sampleRate,i.subChunk2Size=a.length*(i.bitsPerSample>>3),i.chunkSize=36+i.subChunk2Size;let r=i.chunkId.concat(u32ToArray(i.chunkSize),i.format,i.subChunk1Id,u32ToArray(i.subChunk1Size),u16ToArray(i.audioFormat),u16ToArray(i.numChannels),u32ToArray(i.sampleRate),u32ToArray(i.byteRate),u16ToArray(i.blockAlign),u16ToArray(i.bitsPerSample),i.subChunk2Id,u32ToArray(i.subChunk2Size)),s=new Uint8Array(r),l=new Uint8Array(s.length+a.length);return l.set(s),l.set(a,s.length),new Blob([l],{type:"audio/wav"})}function resampleAudio(e,t,n){let o=e.length,i=Math.floor(o/t*n),a=[];for(let o=0;o<i;o++){let i=Math.floor(o*(t/n));a[o]=e[i]}return a}function convertFrameBufferToBase64(e){const t=new Uint8Array(2*e.length);for(let n=0;n<e.length;n++){const o=e[n];t[2*n]=255&o,t[2*n+1]=o>>8&255}return btoa(String.fromCharCode.apply(null,t))}function resampleBuffer(e,t,n){const o=t/n,i=Math.round(e.length/o),a=new Int16Array(i);for(let t=0;t<i;t++){const n=Math.floor(t*o);a[t]=e[n]}return a}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ClipboardService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i3.ToastController}]});const SpeechRecognition=window.SpeechRecognition||window.webkitSpeechRecognition,SpeechGrammarList=window.SpeechGrammarList||window.webkitSpeechGrammarList;class WebSpeech{constructor(e){this.platform=e}startRecognition(e="Nihao | Hello"){if(!SpeechRecognition)return;if(this.recognition&&this.recognition.stop(),console.log("startRecognition"),this.recognition=new SpeechRecognition,!this.recognition)return;this.recognition.continuous=!0;let t=`#JSGF V1.0; grammar words; public <word> = ${e} ;`;this.recognition=new SpeechRecognition;let n=new SpeechGrammarList;n.addFromString(t,1),this.recognition.grammars=n,this.recognition.start(),this.recognition.onresult=e=>{let t=e.results||[];console.log(t),console.log(t[0]?.[0]),t[0]?.[0]?.transcript?.indexOf("Nihao")>-1&&console.log("Nihao成功唤醒"),t[0]?.[0]?.transcript?.indexOf("Hello")>-1&&console.log("Hello成功唤醒"),this.startRecognition()},this.recognition.onend=e=>{console.log(e)},this.recognition.onerror=e=>{console.error(e)}}speak(e,t=1,n=1.2,o=.8){this.platform.is("capacitor")||this.speakWithEdge(e,1,1.2,.8)}speakWithEdge(e,t=1,n=1.2,o=.8){let i=new SpeechSynthesisUtterance(e),a=this.getVoiceByName("Yaoyao");console.log(a),a&&(i.voice=a),i.rate=n,i.pitch=t,i.volume=10,window.speechSynthesis.speak(i)}getVoiceByName(e){return window.speechSynthesis.getVoices().find((t=>t.name.indexOf(e)>-1))}}function checkWorkletSupport(){try{return window.AudioWorkletNode&&window.AudioContext&&window.AudioContext.audioWorklet&&!/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)}catch(e){return!1}}Recorder.ConnectEnableWorklet=checkWorkletSupport();class FmodeVoiceService{constructor(e,t){this.platform=e,this.diagnostic=t,this.webSpeech=WebSpeech,this.isUserFinish=!1,this.recordWavBlob=null,this.recordPcmBlob=null,this.recordDuration=0,this.recordType="pcm",this.encodingType="raw",this.connStatus="",this.btnStatus="UNDEFINED",this.resultText="",this.resultTextTemp="",this.APPID="50f4a46c",this.API_SECRET="NzFlNmFhZDJjMDNkZGM3NzI0Mzg2OGNm",this.API_KEY="106ddc40dfd4b9ca6d7b47c70fada749",this.durationStr="00:00",this.duration=0,this.requestPermission()}toggleRecord(){console.log(this.btnStatus),"UNDEFINED"===this.btnStatus||"CLOSED"===this.btnStatus?this.startTalk():"CONNECTING"!==this.btnStatus&&"OPEN"!==this.btnStatus||this.finishTalk()}finishTalk(){this.isUserFinish=!0,this.onBeforeFinishTalk&&this.onBeforeFinishTalk(),this.recordStop()}async startTalk(e){this.resultText="",this.resultTextTemp="",this.onBeforeStartTalk&&this.onBeforeStartTalk(),event?.preventDefault(),await this.openWithPriviledge(),setTimeout((()=>{this.connectWebSocket()}),100),this.startCountdown(),this.onAfterStartTalk&&this.onAfterStartTalk()}cancelTalk(){this.onBeforeCancelTalk&&this.onBeforeCancelTalk(),this.recordStop(),this.iatWS?.close(),this.resultText=null,this.onAfterCancelTalk&&this.onAfterCancelTalk()}async recordStart(){this.createRecorder(),await this.openWithPriviledge(),this.recorder.start(),this.changeBtnStatus("OPEN"),this.onAfterRecordStart&&this.onAfterRecordStart()}recordStop(){return new Promise((e=>{clearInterval(this.countdownInterval),this.changeBtnStatus("CLOSED"),this.recorder?.stop((async(t,n)=>{try{this.iatWS.send(JSON.stringify({data:{status:2,format:"audio/L16;rate=16000",encoding:this.encodingType,audio:""}}))}catch(e){}let o=(window.URL||webkitURL).createObjectURL(t);console.log(t,o,"时长:"+n+"ms"),this.recordPcmBlob=t,this.recordWavBlob=await this.pcmBlobToWavBlob(t,44100),setTimeout((()=>{this.isUserFinish&&(this.onAfterFinishTalk&&this.onAfterFinishTalk(),this.isUserFinish=!1)}),2e3),this.recorder?.close(),this.recorder=null,e(!0)}),(t=>{console.log("录音失败:"+t),this.recorder.close(),this.recorder=null,e(null)}))}))}playRecord(){this.playPCM(this.recordPcmBlob,44100)}async pcmBlobToWavBlob(e,t){return new Promise((n=>{let o=new FileReader;o.onload=function(e){let o=pcmtoWav(e.target.result,t,1,16);n(o)},o.readAsArrayBuffer(e)}))}async playPCM(e,t){let n=await this.pcmBlobToWavBlob(e,t),o=window.URL.createObjectURL(n),i=new Audio;i.src=o,i.play()}async playBuffers(){let e=await this.BuffersToBlob(this.buffers);this.playPCM(e,44100)}BuffersToBlob(e){let t=[];return e.forEach((e=>{e.forEach((e=>{t.push(e)}))})),new Blob([t],{type:"audio/pcm"})}splitAudioData(e){const t=1280,n=Math.ceil(e.length/t),o=[];for(let i=0;i<n;i++){const n=i*t,a=n+t,r=e.slice(n,a);o.push(r)}return o}BufferToBlob(e){return new Blob([e],{type:"audio/pcm"})}createRecorder(){this.recorder||(this.recorder=Recorder({type:this.recordType,sampleRate:44100,bitRate:16,onProcess:(e,t,n,o,i,a)=>{let r=e.length&&e[e.length-1];if(this.buffers=e,r=resampleBuffer(r,44100,16e3),this.iatWS.readyState===this.iatWS.OPEN){if(this.disableASR)return;this.iatWS.send(JSON.stringify({data:{status:1,format:"audio/L16;rate=16000",encoding:this.encodingType,audio:convertFrameBufferToBase64(r)}}))}this.waveClient?.input(e[e.length-1],t,o)}}))}async openWithPriviledge(){return await this.requestPermission(),this.createRecorder(),!!Recorder.IsOpen()||new Promise((e=>{this.recorder.open((()=>{document.querySelector(".record-wave")&&Recorder.WaveView&&(this.waveClient=Recorder.WaveView({elem:".record-wave"})),e(!0)}),((e,t)=>{console.log((t?"UserNotAllow,":"")+"无法录音:"+e)}))}))}getWebSocketUrl(){let e="wss://iat-api.xfyun.cn/v2/iat",t="iat-api.xfyun.cn",n=this.API_KEY,o=this.API_SECRET,i=(new Date).toUTCString(),a=`host: ${t}\ndate: ${i}\nGET /v2/iat HTTP/1.1`,r=CryptoJS.HmacSHA256(a,o),s=CryptoJS.enc.Base64.stringify(r);return e=`${e}?authorization=${btoa(`api_key="${n}", algorithm="hmac-sha256", headers="host date request-line", signature="${s}"`)}&date=${i}&host=${t}`,e}toBase64(e){for(var t="",n=new Uint8Array(e),o=n.byteLength,i=0;i<o;i++)t+=String.fromCharCode(n[i]);return window.btoa(t)}countTimer(){this.duration++;let e=String(parseInt(String(this.duration/60))).padStart(2,"0")+":"+String((this.duration%60).toFixed(0)).padStart(2,"0");this.durationStr=e,this.connStatus=`录音中(${this.durationStr})`,this.onDurationStrChange&&this.onDurationStrChange(e)}startCountdown(){this.recordDuration=0,this.durationInterval&&clearInterval(this.durationInterval),this.countdownInterval=setInterval((()=>{this.recordDuration+=100}),100),this.now=new Date,this.duration=0,this.countdownInterval&&clearInterval(this.countdownInterval),this.countdownInterval=setInterval((()=>{this.countTimer()}),1e3)}changeBtnStatus(e){this.btnStatus=e,"CONNECTING"===e?this.connStatus="建立连接中":"OPEN"===e||("CLOSING"===e?this.connStatus="关闭连接中":"CLOSED"===e&&(this.connStatus="开始录音"))}renderResult(e){let t=JSON.parse(e);if(t.data&&t.data.result){let e=t.data.result,n="",o=e.ws;for(let e=0;e<o.length;e++)n+=o[e].cw[0].w;e.pgs?("apd"===e.pgs&&(this.resultText=this.resultTextTemp),this.resultTextTemp=this.resultText+n):this.resultText=this.resultText+n,this.resultTextTemp||this.resultText,this.onInputChange&&this.onInputChange(this.getUserInput())}0===t.code&&2===t.data.status&&this.iatWS.close(),0!==t.code&&(this.iatWS.close(),console.error(t))}getUserInput(){return""+(this.resultTextTemp||this.resultText)}connectWebSocket(){console.log("connectWebSocket");const e=this.getWebSocketUrl();if("WebSocket"in window)this.iatWS=new WebSocket(e);else if(!("MozWebSocket"in window))return void alert("浏览器不支持WebSocket");this.changeBtnStatus("CONNECTING"),this.iatWS.onopen=e=>{this.recordStart();var t={common:{app_id:this.APPID},business:{language:"zh_cn",domain:"iat",accent:"mandarin",vad_eos:5e3,dwa:"wpgs"},data:{status:0,format:"audio/L16;rate=16000",encoding:this.encodingType}};this.iatWS.send(JSON.stringify(t))},this.iatWS.onmessage=e=>{this.renderResult(e.data)},this.iatWS.onerror=e=>{console.error("error",e),this.recordStop(),this.changeBtnStatus("CLOSED")},this.iatWS.onclose=async e=>{this.reconnectWebsocket()}}async reconnectWebsocket(){this.isUserFinish||this.connectWebSocket()}isCapacitor(){return this.platform.is("capacitor")||this.platform.is("cordova")}async requestPermission(){if(this.isCapacitor())try{await this.requestStoagePermission(),await this.requestCameraPermission(),await this.requestMicPermission(),await this.requestRecordAudioPermission()}catch(e){console.error(e)}}async requestRecordAudioPermission(){let e=await this.diagnostic.requestRuntimePermissions([this.diagnostic.permission.RECORD_AUDIO]);console.log("record permission request:",e)}async requestMicPermission(){let e=await this.diagnostic.isMicrophoneAuthorized();if(console.log("permisson_MIC:",e),!e){await this.diagnostic.requestMicrophoneAuthorization()}}async requestStoagePermission(){let e=await this.diagnostic.isExternalStorageAuthorized();if(console.log("permisson_STORAGE:",e),!e){await this.diagnostic.requestExternalStorageAuthorization()}}async requestCameraPermission(){let e=await this.diagnostic.isCameraAuthorized();if(console.log("permisson_Camera:",e),!e){await this.diagnostic.requestCameraAuthorization()}}}class RolePointsCloud{constructor(e,t,n){this.offsetPosition=new BABYLON.Vector3(0,1.25,0),this.animationGroup=new BABYLON.AnimationGroup("RoleAnimGroup"),this.AnimMap={idle:null},this.scene=e,this.engine=this.engine}async init(){this.Mesh=this.loadMesh(),this.loadIdleAnim()}playAnim(e){this.scene.beginDirectAnimation(this.Mesh,[this.AnimMap[e]],0,120,!0)}loadMesh(){let e=BABYLON.MeshBuilder.CreateSphere("sphere",{diameter:2},this.scene);return e.position.addInPlace(this.offsetPosition),e.visibility=1,e.material=new BABYLON.StandardMaterial("mat",this.scene),e.material.wireframe=!0,e.scaling=new BABYLON.Vector3(1,1,1),e}loadIdleAnim(){let e=new BABYLON.Animation("idle","scaling",30,BABYLON.Animation.ANIMATIONTYPE_VECTOR3,BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE),t=[];t.push({frame:0,value:new BABYLON.Vector3(1,1,1)}),t.push({frame:60,value:new BABYLON.Vector3(1.5,1.5,1.5)}),t.push({frame:120,value:new BABYLON.Vector3(1,1,1)}),e.setKeys(t),this.Mesh.animations.push(this.AnimMap.idle),this.AnimMap.idle=e,this.animationGroup.addTargetedAnimation(this.AnimMap.idle,this.Mesh)}}class CompAvatarParticleComponent{constructor(e){this.elementRef=e,this.isWebVR=!1,this.animMap={}}ngAfterViewInit(){if(this.canvas=this.renderCanvas.nativeElement,console.log(this.canvas),this.canvas){let e={};this.engine=new BABYLON.Engine(this.canvas,!0,e),console.log(this.engine),this.createScene(),this.engine.runRenderLoop((()=>{this.scene?.render(),this.engine?.resize()})),window.addEventListener("resize",(()=>{this.engine?.resize()}))}}async createScene(){this.scene=new BABYLON.Scene(this.engine),this.scene.clearColor=new BABYLON.Color4(0,0,0,1),this.mainCamera=this.createCamera(),console.log(this.mainCamera),this.currentRole=new RolePointsCloud(this.scene,this.engine,this.mainCamera),await this.currentRole.init(),this.currentRole.playAnim("idle"),this.currentRole.Mesh.visibility=0,await this.createCloudPoints();new BABYLON.HemisphericLight("light1",new BABYLON.Vector3(0,1,0),this.scene);this.engine?.resize()}createCamera(){let e=new(this.isWebVR?BABYLON.VRDeviceOrientationArcRotateCamera:BABYLON.ArcRotateCamera)("Camera",0,0,30,new BABYLON.Vector3(0,.5,0),this.scene);return e.setPosition(new BABYLON.Vector3(0,0,5)),e.beta=Math.PI/3,e.alpha=Math.PI/1.2,e.radius=15,e}async createCloudPoints(){this.pointsMesh=this.currentRole.Mesh,this.pointsCloud=new BABYLON.PointsCloudSystem("pcs",1,this.scene);let e=new BABYLON.Color3(.7,.8,1),t=new BABYLON.Color4(.7,.8,1),n=(new BABYLON.Color4(.2,.5,1),new BABYLON.Color4(0,0,.2,0),new BABYLON.Texture("/assets/avatar/particle/textures/flare.png",this.scene)),o=new BABYLON.PBRMaterial("material",this.scene);o.emissiveTexture=n,o.emissiveColor=e,this.pointsCloud.addVolumePoints(this.currentRole.Mesh,5e3,BABYLON.PointColor.Color,t),this.pointsCloud.buildMeshAsync().then((()=>{this.playAnimation("waiting")})),this.scene.registerAfterRender((()=>{this.pointsCloud.setParticles()})),this.engine.runRenderLoop((()=>{this.scene.render()}))}playAnimation(e){switch(e){case"waiting":this.cloudAnim();break;case"listening":this.cloudAnim({rotateSpeed:.01,breathing:!1});break;case"thinking":this.cloudAnim({rotateSpeed:.2,breathing:!1});break;case"talking":this.animMap.idle&&this.scene.beginDirectAnimation(this.pointsMesh,[this.animMap.talking],0,20,!0)}}cloudAnim(e={breathing:!0,rotateSpeed:.002}){this.animMap.idle&&this.scene.beginDirectAnimation(this.pointsMesh,[this.animMap.idle],0,120,!0);let t=new BABYLON.Color4(1,1,1,1),n=(new BABYLON.Texture("/assets/avatar/particle/textures/flare.png",this.scene),0);this.pointsCloud.updateParticle=o=>{let i=this.currentRole.Mesh.getBoundingInfo()?.boundingSphere?.radiusWorld,a=this.currentRole.Mesh.getBoundingInfo()?.boundingSphere?.centerWorld;o.idx;if(o.color=t,o.rotation.y+=e.rotateSpeed,o&&n<3&&(console.log(this.currentRole.Mesh.getBoundingInfo()),console.log(o),n++),o.initpos||(o.initpos=o.position),e.breathing){let e=o.initpos.subtract(a);o.position=new BABYLON.Vector3(e.x*i,e.y*i,e.z*i).add(this.currentRole.offsetPosition)}return o}}createSphere(){let e=BABYLON.MeshBuilder.CreateSphere("sphere",{diameter:2},this.scene);e.visibility=1,e.material=new BABYLON.StandardMaterial("mat",this.scene),e.material.wireframe=!0,e.scaling=new BABYLON.Vector3(1,1,1),this.pointsMesh=e;let t=new BABYLON.Animation("breathingAnimation","scaling",30,BABYLON.Animation.ANIMATIONTYPE_VECTOR3,BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE),n=[];n.push({frame:0,value:new BABYLON.Vector3(.3,.3,.3)}),n.push({frame:60,value:new BABYLON.Vector3(.5,.5,.5)}),n.push({frame:120,value:new BABYLON.Vector3(.3,.3,.3)}),t.setKeys(n),this.animMap.idle=t;let o=[{frame:0,value:BABYLON.Vector3.One()},{frame:10,value:new BABYLON.Vector3(1.2,.8,1.2)},{frame:20,value:BABYLON.Vector3.One()}],i=new BABYLON.Animation("talkAnimation","scaling",30,BABYLON.Animation.ANIMATIONTYPE_VECTOR3,BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);return i.setKeys(o),this.animMap.talk=i,this.scene.beginDirectAnimation(e,[this.animMap.idle],0,120,!0),e}async createParticle(){let e=this.createSphere(),t=new BABYLON.ParticleSystem("particles",2e3,this.scene);t.particleTexture=new BABYLON.Texture("/assets/avatar/particle/textures/flare.png",this.scene),t.emitter=e,t.minEmitBox=new BABYLON.Vector3(0,0,0),t.maxEmitBox=new BABYLON.Vector3(0,0,0),t.color1=new BABYLON.Color4(.7,.8,1,1),t.color2=new BABYLON.Color4(.2,.5,1,1),t.colorDead=new BABYLON.Color4(0,0,.2,0),t.minSize=.5,t.maxSize=.5,t.minLifeTime=.1,t.maxLifeTime=.1,t.minAngularSpeed=0,t.maxAngularSpeed=Math.PI,t.minInitialRotation=0,t.maxInitialRotation=Math.PI,t.minEmitPower=0,t.maxEmitPower=0,t.emitRate=1500,t.updateSpeed=.01,t.blendMode=BABYLON.ParticleSystem.BLENDMODE_ONEONE,t.direction1=new BABYLON.Vector3(0,0,0),t.direction2=new BABYLON.Vector3(0,0,0),t.start();let n=t.createSphereEmitter();n.radius=2,n.radiusRange=0,n.directionRandomizer=0,t.gravity=new BABYLON.Vector3(0,0,0),t.disposeOnStop=!0,t.updateFunction=n=>{for(let o=0;o<n.length;o++){let i=n[o],a=e.getBoundingInfo()?.boundingSphere?.radiusWorld;i.position=i.position.normalize().scale(a),i.age+=this.scene.getEngine().getDeltaTime()/1e3,i.age>=i.lifeTime&&(t.recycleParticle(i),o--)}},this.engine.runRenderLoop((()=>{this.scene.render(),t.worldOffset=e.position}))}setCameraToMeshCenter(e,t){t.computeWorldMatrix(!0);let n=t.getBoundingInfo(),o=n.minimum,i=n.maximum,a=i.x-o.x,r=i.y-o.y,s=i.z-o.z,l=n.boundingBox.center;console.log("宽度:"+a),console.log("高度:"+r),console.log("深度:"+s),console.log("中心点:"+l)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarParticleComponent,deps:[{token:i0.ElementRef}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompAvatarParticleComponent,isStandalone:!0,selector:"fm-avatar-role-particle",viewQueries:[{propertyName:"renderCanvas",first:!0,predicate:["renderCanvas"],descendants:!0}],ngImport:i0,template:'<canvas #renderCanvas class="render-canvas"></canvas>',styles:[".render-canvas{display:block;width:100%;height:100%;touch-action:none}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"ngmodule",type:FormsModule}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarParticleComponent,decorators:[{type:Component,args:[{selector:"fm-avatar-role-particle",standalone:!0,imports:[CommonModule,FormsModule],template:'<canvas #renderCanvas class="render-canvas"></canvas>',styles:[".render-canvas{display:block;width:100%;height:100%;touch-action:none}\n"]}]}],ctorParameters:()=>[{type:i0.ElementRef}],propDecorators:{renderCanvas:[{type:ViewChild,args:["renderCanvas"]}]}}),function(){var WaveView=function(e){return new fn(e)},e="WaveView",fn=function(t){var n=this,o={scale:2,speed:9,phase:21.8,fps:20,keep:!0,lineWidth:3,linear1:[0,"rgba(150,96,238,1)",.2,"rgba(170,79,249,1)",1,"rgba(53,199,253,1)"],linear2:[0,"rgba(209,130,255,0.6)",1,"rgba(53,199,255,0.6)"],linearBg:[0,"rgba(255,255,255,0.2)",1,"rgba(54,197,252,0.2)"]};for(var i in t)o[i]=t[i];n.set=t=o;var a=t.elem;a&&("string"==typeof a?a=document.querySelector(a):a.length&&(a=a[0])),a&&(t.width=a.offsetWidth,t.height=a.offsetHeight);var r=t.scale,s=t.width*r,l=t.height*r;if(!s||!l)throw new Error(e+"无宽高");var c=n.elem=document.createElement("div"),d=["","transform-origin:0 0;","transform:scale("+1/r+");"];c.innerHTML='<div style="width:'+t.width+"px;height:"+t.height+'px;overflow:hidden"><div style="width:'+s+"px;height:"+l+"px;"+d.join("-webkit-")+d.join("-ms-")+d.join("-moz-")+d.join("")+'"><canvas/></div></div>';var p=n.canvas=c.querySelector("canvas"),m=n.ctx=p.getContext("2d");p.width=s,p.height=l,n.linear1=n.genLinear(m,s,t.linear1),n.linear2=n.genLinear(m,s,t.linear2),n.linearBg=n.genLinear(m,l,t.linearBg,!0),a&&(a.innerHTML="",a.appendChild(c)),n._phase=0};fn.prototype=WaveView.prototype={genLinear:function(e,t,n,o){for(var i=e.createLinearGradient(0,0,o?0:t,o?t:0),a=0;a<n.length;)i.addColorStop(n[a++],n[a++]);return i},genPath:function(e,t,n){for(var o=[],i=this.set,a=i.scale,r=i.width*a,s=i.height*a/2,l=0;l<r;l+=a){var c=(1+Math.cos(Math.PI+l/r*2*Math.PI))/2*s*t*Math.sin(2*Math.PI*(l/r)*e+n)+s;o.push(c)}return o},input:function(e,t,n){var o=this;o.sampleRate=n,o.pcmData=e,o.pcmPos=0,o.inputTime=Date.now(),o.schedule()},schedule:function(){var e=this,t=e.set,n=Math.floor(1e3/t.fps);e.timer||(e.timer=setInterval((function(){e.schedule()}),n));var o=Date.now();if(!(o-(e.drawTime||0)<n)){e.drawTime=o;for(var i=e.sampleRate/t.fps,a=e.pcmData,r=e.pcmPos,s=Math.max(0,Math.min(i,a.length-r)),l=0,c=0;c<s;c++,r++)l+=Math.abs(a[r]);e.pcmPos=r,!s&&t.keep||e.draw(Recorder.PowerLevel(l,s)),!s&&o-e.inputTime>1300&&(clearInterval(e.timer),e.timer=0)}},draw:function(e){var t=this,n=t.set,o=t.ctx,i=n.scale,a=n.width*i,r=n.height*i,s=n.speed/n.fps,l=t._phase-=s,c=l+s*n.phase,d=e/100,p=t.genPath(2,d,l),m=t.genPath(1.8,d,c);o.clearRect(0,0,a,r),o.beginPath();for(var g=0,u=0;u<a;g++,u+=i)0==u?o.moveTo(u,p[g]):o.lineTo(u,p[g]);g--;for(u=a-1;u>=0;g--,u-=i)o.lineTo(u,m[g]);o.closePath(),o.fillStyle=t.linearBg,o.fill(),t.drawPath(m,t.linear2),t.drawPath(p,t.linear1)},drawPath:function(e,t){var n=this.set,o=this.ctx,i=n.scale,a=n.width*i;o.beginPath();for(var r=0,s=0;s<a;r++,s+=i)0==s?o.moveTo(s,e[r]):o.lineTo(s,e[r]);o.lineWidth=n.lineWidth*i,o.strokeStyle=t,o.stroke()}},Recorder[e]=WaveView}();class CompAvatarRoleImageComponent{constructor(){this.animClass="waiting",this.imageMap={}}playWave(){!this.wave&&Recorder.WaveView&&(this.wave=Recorder.WaveView({elem:".record-wave-avatar",keep:!1}));let e=function generatePowerLevel(){return 100*Math.random()}();this.waveInterval=setInterval((()=>{let t=function generateSampleRate(){const e=[44100,48e3,88200,96e3];return e[Math.floor(Math.random()*e.length)]}(),n=function generatePcmData(e){const t=[];for(let n=0;n<e;n++)t.push(Math.floor(65536*Math.random())-32768);return t}(1e3);this.wave.input(n,e,t)}),40)}stopWave(){clearInterval(this.waveInterval)}ngAfterViewInit(){}ngOnInit(){setTimeout((()=>{this.imageMap=this.fmodeChat.avatarConfig?.image,this.avatarImage.nativeElement.src=this.imageMap?.waiting,this.fmodeChat.playAnimation=this.playAnimation}),1500)}playAnimation(){let e=this;return t=>{let n=e.avatarImage.nativeElement;switch(e.animClass=t,e.stopWave(),t){case"thinking":case"waiting":n.style.animationPlayState="running";break;case"talking":n.style.animationPlayState="running",e.playWave();break;case"listening":n.style.animationPlayState="pause";break;default:n.style.animationPlayState="paused"}}}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarRoleImageComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompAvatarRoleImageComponent,isStandalone:!0,selector:"fm-avatar-role-image",inputs:{fmodeChat:"fmodeChat",role:"role"},viewQueries:[{propertyName:"avatarImage",first:!0,predicate:["avatarImage"],descendants:!0}],ngImport:i0,template:'<div class="page">\n <div class="avatar" [class]="animClass">\n <div class="avatar-photo">\n <img #avatarImage alt="">\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave-avatar">\n </div>\n </div>\n </div>\n</div>',styles:[".page{position:relative;width:100vw;height:100%;top:0;left:0;display:flex;justify-content:center;align-items:center;background-color:#000}.avatar{width:100%;display:flex;justify-content:center;align-items:center}.avatar .avatar-photo{position:relative;margin-top:-10vh;width:80%}.avatar .avatar-photo img{border-radius:10px}.avatar .record-wave-avatar{height:50px;width:100%;position:absolute;float:left;left:0;bottom:0}.thinking,.listening,.waiting,.talking{animation-duration:2s;animation-play-state:running;animation-iteration-count:infinite;animation-timing-function:ease-in-out}@keyframes waitingAnimation{0%{transform:scale(1)}50%{transform:scale(1.05)}to{transform:scale(1)}}@keyframes thinkingAnimation{0%{transform:rotate(0)}30%{transform:rotate(10deg)}60%{transform:rotate(-10deg)}to{transform:rotate(0)}}.thinking{animation-name:thinkingAnimation}.waiting{animation-name:waitingAnimation}.listening{animation-name:listeningAnimation}.talking{animation-name:talkingAnimation}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"ngmodule",type:FormsModule}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarRoleImageComponent,decorators:[{type:Component,args:[{selector:"fm-avatar-role-image",standalone:!0,imports:[CommonModule,FormsModule],template:'<div class="page">\n <div class="avatar" [class]="animClass">\n <div class="avatar-photo">\n <img #avatarImage alt="">\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave-avatar">\n </div>\n </div>\n </div>\n</div>',styles:[".page{position:relative;width:100vw;height:100%;top:0;left:0;display:flex;justify-content:center;align-items:center;background-color:#000}.avatar{width:100%;display:flex;justify-content:center;align-items:center}.avatar .avatar-photo{position:relative;margin-top:-10vh;width:80%}.avatar .avatar-photo img{border-radius:10px}.avatar .record-wave-avatar{height:50px;width:100%;position:absolute;float:left;left:0;bottom:0}.thinking,.listening,.waiting,.talking{animation-duration:2s;animation-play-state:running;animation-iteration-count:infinite;animation-timing-function:ease-in-out}@keyframes waitingAnimation{0%{transform:scale(1)}50%{transform:scale(1.05)}to{transform:scale(1)}}@keyframes thinkingAnimation{0%{transform:rotate(0)}30%{transform:rotate(10deg)}60%{transform:rotate(-10deg)}to{transform:rotate(0)}}.thinking{animation-name:thinkingAnimation}.waiting{animation-name:waitingAnimation}.listening{animation-name:listeningAnimation}.talking{animation-name:talkingAnimation}\n"]}]}],propDecorators:{avatarImage:[{type:ViewChild,args:["avatarImage"]}],fmodeChat:[{type:Input}],role:[{type:Input}]}});class ModalChatVoiceInputComponent{constructor(e,t,n,o,i,a){this.platform=e,this.router=t,this.toastCtrl=n,this.ncloud=o,this.chatServ=i,this.diagnostic=a,this.talkMode="click",this.talkTips="点击话筒开始讲话",this.errorText="",this.player=new Audio,this.voiceServ=new FmodeVoiceService(this.platform,this.diagnostic)}ngOnInit(){"press"==this.talkMode&&(this.talkTips="轻触底部开始讲话"),setTimeout((()=>{this.initVoiceSevice(),this.initVoiceASR()}),500)}async initVoiceASR(){this.voiceServ.requestPermission().then((()=>{this.voiceServ.openWithPriviledge(),this.startASRAwake()}))}async startASRAwake(){await this.voiceServ.openWithPriviledge(),new this.voiceServ.webSpeech(this.platform).startRecognition("Nihao | Hello")}playMusic(e){this.player.src=`/assets/avatar/voice/${e}.mp3`,this.player.play()}initVoiceSevice(){this.fmodeChat.userInput=this.voiceServ.resultText,this.voiceServ.requestPermission().then((()=>{this.voiceServ.openWithPriviledge()})),this.voiceServ.onBeforeStartTalk=()=>{this.fmodeChat.playAnimation("listening"),this.playMusic("start-talk")},this.voiceServ.onBeforeCancelTalk=()=>{this.playMusic("interupt-talk"),this.fmodeChat.playAnimation("waiting")},this.voiceServ.onAfterCancelTalk=()=>{this.startASRAwake()},this.voiceServ.onBeforeFinishTalk=()=>{this.fmodeChat.playAnimation("thinking"),this.playMusic("stop-talk")},this.voiceServ.onAfterFinishTalk=()=>{console.log("onAfterFinishTalk"),this.fmodeChat.userInput=this.voiceServ?.resultText,this.sendMessage(),this.startASRAwake()}}async sendMessage(){if(!this.fmodeChat.userInput){return this.errorText="内容不能为空",void(await this.toastCtrl.create({message:this.errorText,position:"top",icon:"alert",color:"warning-circle",duration:1e3})).present()}this.fmodeChat?.sendMessage(this.voiceServ.resultText,null,(e=>{}),{onSSMLComplete:e=>{console.log(e)}}),this.fmodeChat.userInput="",this.fmodeChat.userImage=""}testTTS(e){console.log(e),e=e||"你好呀,我是飞马小智!很高兴为您介绍脑控科技的发展历程。我们成立于2019年",new this.voiceServ.webSpeech(this.platform).speak(e)}testXunfeiTTS(){}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalChatVoiceInputComponent,deps:[{token:i3.Platform},{token:i1$1.Router},{token:i3.ToastController},{token:NovaCloudService},{token:ChatService},{token:i5.Diagnostic}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ModalChatVoiceInputComponent,isStandalone:!0,selector:"fm-modal-chat-voice-input",inputs:{fmodeChat:"fmodeChat",talkMode:"talkMode"},providers:[],ngImport:i0,template:' \n <ng-container *ngIf="fmodeChat">\n\n \x3c!-- 用户输入 提示区域 --\x3e\n <div class="user-asr-input" style="text-align: center;" *ngIf="!fmodeChat?.userInput && voiceServ.btnStatus!=\'OPEN\'">{{talkTips}}</div>\n <div class="user-asr-input">{{fmodeChat?.userInput}}</div>\n \n \x3c!-- 测试按钮 --\x3e\n <div class="test-button-group" *ngIf="false">\n <button class="button-record" (click)="voiceServ.toggleRecord()">开始录制 {{voiceServ.connStatus}} {{voiceServ.btnStatus}}</button>\n <br>\n <button class="button-record" (click)="voiceServ.playRecord()">播放录制结果</button>\n <br>\n <button class="button-record" (click)="voiceServ.playBuffers()">播放Buffers结果</button>\n <button (click)="testTTS()">测试TTS纯WEB</button>\n <button (click)="startASR()">测试ASR</button> \n <button (click)="testXunfeiTTS()">测试合成</button> \n </div>\n\n \n \n \x3c!-- 交互按钮 --\x3e\n <ion-fab slot="fixed" horizontal="center" vertical="bottom">\n <ng-container *ngIf="talkMode==\'click\'">\n \x3c!-- 默认按钮:开始讲话 --\x3e\n <ion-fab-button color="primary" closeIcon="checkmark" (click)="voiceServ.toggleRecord()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n\n \x3c!-- 讲话中:取消发送 --\x3e\n <ion-fab-list side="end">\n <ion-fab-button [class]="\'loading\'" (click)="voiceServ.cancelTalk()">\n <ion-icon name="pause-outline"></ion-icon>\n </ion-fab-button>\n </ion-fab-list>\n </ng-container>\n \n <ng-container *ngIf="talkMode==\'press\'">\n <ion-fab-button color="primary" closeIcon="mic-outline" (touchstart)="voiceServ.toggleRecord()" (touchend)="voiceServ.cancelTalk()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n </ng-container>\n </ion-fab>\n\n\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave">\n </div>\n</ng-container>\n',styles:['ion-fab{margin-bottom:10vh}.fab-button-close-active:before{content:"";position:absolute;top:-5px;left:-5px;width:66px;height:66px;border-radius:50%;border:5px solid #fff;border-top-color:transparent;animation:spin 2s ease-in-out infinite;animation-fill-mode:both;animation-play-state:running}.record-wave{position:fixed;bottom:0;width:100vw;height:6vh}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:IonicModule},{kind:"component",type:i3.IonFab,selector:"ion-fab",inputs:["activated","edge","horizontal","vertical"]},{kind:"component",type:i3.IonFabButton,selector:"ion-fab-button",inputs:["activated","closeIcon","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","show","size","target","translucent","type"]},{kind:"component",type:i3.IonFabList,selector:"ion-fab-list",inputs:["activated","side"]},{kind:"component",type:i3.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"ngmodule",type:RouterModule}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalChatVoiceInputComponent,decorators:[{type:Component,args:[{selector:"fm-modal-chat-voice-input",standalone:!0,imports:[CommonModule,IonicModule,RouterModule],providers:[],template:' \n <ng-container *ngIf="fmodeChat">\n\n \x3c!-- 用户输入 提示区域 --\x3e\n <div class="user-asr-input" style="text-align: center;" *ngIf="!fmodeChat?.userInput && voiceServ.btnStatus!=\'OPEN\'">{{talkTips}}</div>\n <div class="user-asr-input">{{fmodeChat?.userInput}}</div>\n \n \x3c!-- 测试按钮 --\x3e\n <div class="test-button-group" *ngIf="false">\n <button class="button-record" (click)="voiceServ.toggleRecord()">开始录制 {{voiceServ.connStatus}} {{voiceServ.btnStatus}}</button>\n <br>\n <button class="button-record" (click)="voiceServ.playRecord()">播放录制结果</button>\n <br>\n <button class="button-record" (click)="voiceServ.playBuffers()">播放Buffers结果</button>\n <button (click)="testTTS()">测试TTS纯WEB</button>\n <button (click)="startASR()">测试ASR</button> \n <button (click)="testXunfeiTTS()">测试合成</button> \n </div>\n\n \n \n \x3c!-- 交互按钮 --\x3e\n <ion-fab slot="fixed" horizontal="center" vertical="bottom">\n <ng-container *ngIf="talkMode==\'click\'">\n \x3c!-- 默认按钮:开始讲话 --\x3e\n <ion-fab-button color="primary" closeIcon="checkmark" (click)="voiceServ.toggleRecord()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n\n \x3c!-- 讲话中:取消发送 --\x3e\n <ion-fab-list side="end">\n <ion-fab-button [class]="\'loading\'" (click)="voiceServ.cancelTalk()">\n <ion-icon name="pause-outline"></ion-icon>\n </ion-fab-button>\n </ion-fab-list>\n </ng-container>\n \n <ng-container *ngIf="talkMode==\'press\'">\n <ion-fab-button color="primary" closeIcon="mic-outline" (touchstart)="voiceServ.toggleRecord()" (touchend)="voiceServ.cancelTalk()">\n <ion-icon name="mic-outline"></ion-icon>\n </ion-fab-button>\n </ng-container>\n </ion-fab>\n\n\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave">\n </div>\n</ng-container>\n',styles:['ion-fab{margin-bottom:10vh}.fab-button-close-active:before{content:"";position:absolute;top:-5px;left:-5px;width:66px;height:66px;border-radius:50%;border:5px solid #fff;border-top-color:transparent;animation:spin 2s ease-in-out infinite;animation-fill-mode:both;animation-play-state:running}.record-wave{position:fixed;bottom:0;width:100vw;height:6vh}\n']}]}],ctorParameters:()=>[{type:i3.Platform},{type:i1$1.Router},{type:i3.ToastController},{type:NovaCloudService},{type:ChatService},{type:i5.Diagnostic}],propDecorators:{fmodeChat:[{type:Input}],talkMode:[{type:Input}]}});class CompAvatarTalkComponent{constructor(e,t,n,o,i,a,r){this.router=e,this.navCtrl=t,this.route=n,this.chatServ=o,this.ncloud=i,this.platform=a,this.diagnostic=r,this.voiceServ=new FmodeVoiceService(this.platform,this.diagnostic),this.route.paramMap.subscribe((e=>{this.roleId=e.get("roleId"),this.loadAvatarRole(this.roleId)})),document.body.classList.add("dark")}ngOnInit(){}ngOnDestroy(){document.body.classList.remove("dark"),this.voiceServ.resultText=null,this.fmodeChat&&(this.fmodeChat.latestAIResponse=null)}goBack(){document.body.classList.remove("dark");let e=this.avatarRole?.get("backUrl");try{if(e)return void this.navCtrl.navigateRoot(e);this.navCtrl.navigateRoot("/chat/pro/role/"+this.roleId)}catch(e){this.navCtrl.navigateRoot("/chat/pro/role/"+this.roleId)}}async loadAvatarRole(e){let t=new Parse.Query("AvatarRole");this.avatarRole=await t.get(e);let n=await this.chatServ.createNewRoleChat(this.roleId);n.isTalkMode=!0,this.fmodeChat=n,this.fmodeChat.showAvatar()}ngAfterViewInit(){this.listenDivChange()}listenDivChange(){new MutationObserver((()=>{this.scrollToBottom(this.aiRespComp)})).observe(this.aiRespComp.nativeElement,{childList:!0,subtree:!0,attributes:!0})}scrollToBottom(e){e?.nativeElement?.scrollHeight&&(e.nativeElement.scrollTop=e.nativeElement.scrollHeight)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarTalkComponent,deps:[{token:i1$1.Router},{token:i3.NavController},{token:i1$1.ActivatedRoute},{token:ChatService},{token:NovaCloudService},{token:i3.Platform},{token:i5.Diagnostic}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompAvatarTalkComponent,isStandalone:!0,selector:"app-comp-avatar-talk",providers:[NovaCloudService,ChatService,Diagnostic,ModalController],viewQueries:[{propertyName:"avatarComp",first:!0,predicate:["avatar"],descendants:!0},{propertyName:"aiRespComp",first:!0,predicate:["aiRespComp"],descendants:!0}],ngImport:i0,template:'<ion-menu #menu contentId="main-content" side="end">\n <ion-header>\n <ion-toolbar>\n <ion-title>资料</ion-title>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n\n <ion-card style="margin: 0px;">\n <img [src]="avatarRole?.get(\'thumb\')" alt="">\n <ion-card-header>\n <ion-card-subtitle>{{avatarRole?.get(\'tags\')}}</ion-card-subtitle>\n <ion-card-title>{{avatarRole?.get("name")}}</ion-card-title>\n </ion-card-header>\n \n <ion-card-content>\n {{avatarRole?.get("desc")}}\n\n <ion-list [inset]="true" style="margin:0px;">\n \x3c!-- <ion-item>\n <ion-avatar *ngIf="avatarRole?.get(\'thumb\')" aria-hidden="true" slot="start">\n <img [src]="avatarRole?.get(\'thumb\')" />\n </ion-avatar>\n <ion-label>{{avatarRole?.get("name")}}</ion-label>\n </ion-item> --\x3e\n <ion-item lines="none" *ngIf="avatarRole?.get(\'age\')">\n <ion-note slot="start">年龄</ion-note>\n <ion-label>{{avatarRole?.get("age")}}</ion-label>\n </ion-item>\n <ion-item lines="none" *ngIf="avatarRole?.get(\'gender\')">\n <ion-note slot="start">性别</ion-note>\n <ion-label>{{avatarRole?.get("gender")}}</ion-label>\n </ion-item>\n <ion-item lines="none">\n <ion-note slot="start">称号</ion-note>\n <ion-label>{{avatarRole?.get("title")}}</ion-label>\n </ion-item>\n \n <ion-item lines="none">\n <ion-note slot="start">擅长</ion-note>\n <ion-label>{{avatarRole?.get("tags")?.join(\',\')}}</ion-label>\n </ion-item>\n\n </ion-list>\n </ion-card-content>\n </ion-card>\n \n \n \n </ion-content>\n</ion-menu>\n\n<div class="ion-page" id="main-content">\n <ion-header class="ion-no-border">\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="goBack()"> <ion-icon name="chevron-back-outline"></ion-icon> </ion-button>\n </ion-buttons>\n <ion-title>\n <ion-chip *ngIf="avatarRole?.get(\'title\')">{{avatarRole?.get("title")}}</ion-chip>\n </ion-title>\n <ion-buttons slot="end">\n \x3c!-- <ion-button (click)="playTTSTeting()">TTS测试</ion-button> --\x3e\n {{avatarRole?.get("name")}}\n <ion-button (click)="menu.toggle()"> <ion-icon name="ellipsis-horizontal-outline"></ion-icon> </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n\n \x3c!-- <ion-segment value="voice">\n <ion-segment-button (click)="chatServ.createChatPanel(avatarRole)" value="chat">\n <ion-label>聊天</ion-label>\n </ion-segment-button>\n <ion-segment-button routerLink="{{\'/avatar/role/\'+avatarRole?.id}}" value="voice">\n <ion-label>语音</ion-label>\n </ion-segment-button>\n </ion-segment> --\x3e\n\n \x3c!-- 数字形象:动画效果 --\x3e\n <fm-avatar-role-image *ngIf="avatarRole&&fmodeChat" [fmodeChat]="fmodeChat" [role]="avatarRole" #avatar class="avatar"></fm-avatar-role-image>\n \x3c!-- <fm-avatar-role-particle #avatar class="avatar"></fm-avatar-role-particle> --\x3e\n\n \x3c!-- AI回复的最新消息 --\x3e\n <div class="ai-resp-input" #aiRespComp>{{fmodeChat?.latestAIResponse | hidexml}}</div>\n\n <fm-modal-chat-voice-input *ngIf="fmodeChat" [fmodeChat]="fmodeChat"></fm-modal-chat-voice-input>\n\n</div>\n\n',styles:["ion-menu ion-note{color:#ccc;font-weight:700}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.avatar{display:block;width:100%;height:100%}.ai-resp-input{font-size:1rem;color:#fff;position:fixed;top:60px;max-height:15vh;overflow-y:scroll;padding:0 10px}.user-asr-input{font-size:1rem;color:#fff;position:fixed;bottom:6vh;padding:0 10px}.test-button-group{color:#00f;position:fixed;bottom:20vh}.test-button-group button{padding:10px;margin:10px}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:RouterModule},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:IonicModule},{kind:"component",type:i3.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:i3.IonButtons,selector:"ion-buttons",inputs:["collapse"]},{kind:"component",type:i3.IonCard,selector:"ion-card",inputs:["button","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonCardContent,selector:"ion-card-content",inputs:["mode"]},{kind:"component",type:i3.IonCardHeader,selector:"ion-card-header",inputs:["color","mode","translucent"]},{kind:"component",type:i3.IonCardSubtitle,selector:"ion-card-subtitle",inputs:["color","mode"]},{kind:"component",type:i3.IonCardTitle,selector:"ion-card-title",inputs:["color","mode"]},{kind:"component",type:i3.IonChip,selector:"ion-chip",inputs:["color","disabled","mode","outline"]},{kind:"component",type:i3.IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:i3.IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:i3.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:i3.IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:i3.IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:i3.IonMenu,selector:"ion-menu",inputs:["contentId","disabled","maxEdgeStart","menuId","side","swipeGesture","type"]},{kind:"component",type:i3.IonNote,selector:"ion-note",inputs:["color","mode"]},{kind:"component",type:i3.IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"component",type:i3.IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"component",type:CompAvatarRoleImageComponent,selector:"fm-avatar-role-image",inputs:["fmodeChat","role"]},{kind:"component",type:ModalChatVoiceInputComponent,selector:"fm-modal-chat-voice-input",inputs:["fmodeChat","talkMode"]},{kind:"pipe",type:HidexmlPipe,name:"hidexml"}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarTalkComponent,decorators:[{type:Component,args:[{selector:"app-comp-avatar-talk",standalone:!0,imports:[CommonModule,RouterModule,FormsModule,IonicModule,CompAvatarParticleComponent,CompAvatarRoleImageComponent,ModalChatVoiceInputComponent,HidexmlPipe],providers:[NovaCloudService,ChatService,Diagnostic,ModalController],template:'<ion-menu #menu contentId="main-content" side="end">\n <ion-header>\n <ion-toolbar>\n <ion-title>资料</ion-title>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n\n <ion-card style="margin: 0px;">\n <img [src]="avatarRole?.get(\'thumb\')" alt="">\n <ion-card-header>\n <ion-card-subtitle>{{avatarRole?.get(\'tags\')}}</ion-card-subtitle>\n <ion-card-title>{{avatarRole?.get("name")}}</ion-card-title>\n </ion-card-header>\n \n <ion-card-content>\n {{avatarRole?.get("desc")}}\n\n <ion-list [inset]="true" style="margin:0px;">\n \x3c!-- <ion-item>\n <ion-avatar *ngIf="avatarRole?.get(\'thumb\')" aria-hidden="true" slot="start">\n <img [src]="avatarRole?.get(\'thumb\')" />\n </ion-avatar>\n <ion-label>{{avatarRole?.get("name")}}</ion-label>\n </ion-item> --\x3e\n <ion-item lines="none" *ngIf="avatarRole?.get(\'age\')">\n <ion-note slot="start">年龄</ion-note>\n <ion-label>{{avatarRole?.get("age")}}</ion-label>\n </ion-item>\n <ion-item lines="none" *ngIf="avatarRole?.get(\'gender\')">\n <ion-note slot="start">性别</ion-note>\n <ion-label>{{avatarRole?.get("gender")}}</ion-label>\n </ion-item>\n <ion-item lines="none">\n <ion-note slot="start">称号</ion-note>\n <ion-label>{{avatarRole?.get("title")}}</ion-label>\n </ion-item>\n \n <ion-item lines="none">\n <ion-note slot="start">擅长</ion-note>\n <ion-label>{{avatarRole?.get("tags")?.join(\',\')}}</ion-label>\n </ion-item>\n\n </ion-list>\n </ion-card-content>\n </ion-card>\n \n \n \n </ion-content>\n</ion-menu>\n\n<div class="ion-page" id="main-content">\n <ion-header class="ion-no-border">\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="goBack()"> <ion-icon name="chevron-back-outline"></ion-icon> </ion-button>\n </ion-buttons>\n <ion-title>\n <ion-chip *ngIf="avatarRole?.get(\'title\')">{{avatarRole?.get("title")}}</ion-chip>\n </ion-title>\n <ion-buttons slot="end">\n \x3c!-- <ion-button (click)="playTTSTeting()">TTS测试</ion-button> --\x3e\n {{avatarRole?.get("name")}}\n <ion-button (click)="menu.toggle()"> <ion-icon name="ellipsis-horizontal-outline"></ion-icon> </ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n\n \x3c!-- <ion-segment value="voice">\n <ion-segment-button (click)="chatServ.createChatPanel(avatarRole)" value="chat">\n <ion-label>聊天</ion-label>\n </ion-segment-button>\n <ion-segment-button routerLink="{{\'/avatar/role/\'+avatarRole?.id}}" value="voice">\n <ion-label>语音</ion-label>\n </ion-segment-button>\n </ion-segment> --\x3e\n\n \x3c!-- 数字形象:动画效果 --\x3e\n <fm-avatar-role-image *ngIf="avatarRole&&fmodeChat" [fmodeChat]="fmodeChat" [role]="avatarRole" #avatar class="avatar"></fm-avatar-role-image>\n \x3c!-- <fm-avatar-role-particle #avatar class="avatar"></fm-avatar-role-particle> --\x3e\n\n \x3c!-- AI回复的最新消息 --\x3e\n <div class="ai-resp-input" #aiRespComp>{{fmodeChat?.latestAIResponse | hidexml}}</div>\n\n <fm-modal-chat-voice-input *ngIf="fmodeChat" [fmodeChat]="fmodeChat"></fm-modal-chat-voice-input>\n\n</div>\n\n',styles:["ion-menu ion-note{color:#ccc;font-weight:700}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.avatar{display:block;width:100%;height:100%}.ai-resp-input{font-size:1rem;color:#fff;position:fixed;top:60px;max-height:15vh;overflow-y:scroll;padding:0 10px}.user-asr-input{font-size:1rem;color:#fff;position:fixed;bottom:6vh;padding:0 10px}.test-button-group{color:#00f;position:fixed;bottom:20vh}.test-button-group button{padding:10px;margin:10px}\n"]}]}],ctorParameters:()=>[{type:i1$1.Router},{type:i3.NavController},{type:i1$1.ActivatedRoute},{type:ChatService},{type:NovaCloudService},{type:i3.Platform},{type:i5.Diagnostic}],propDecorators:{avatarComp:[{type:ViewChild,args:["avatar"]}],aiRespComp:[{type:ViewChild,args:["aiRespComp"]}]}});const AvatarRoutes=[{path:"role/:roleId",component:CompAvatarTalkComponent,runGuardsAndResolvers:"always"}];class AvatarModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AvatarModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:AvatarModule,imports:[CommonModule,FormsModule,HttpClientModule,ReactiveFormsModule,i1$1.RouterModule,CompAvatarTalkComponent],exports:[CompAvatarTalkComponent]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AvatarModule,imports:[CommonModule,FormsModule,HttpClientModule,ReactiveFormsModule,RouterModule.forChild(AvatarRoutes),CompAvatarTalkComponent]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AvatarModule,decorators:[{type:NgModule,args:[{declarations:[],imports:[CommonModule,FormsModule,HttpClientModule,ReactiveFormsModule,RouterModule.forChild(AvatarRoutes),CompAvatarTalkComponent],exports:[CompAvatarTalkComponent]}]}]});class FmVideoComponent{constructor(){this.url="",this.video=document.createElement("video"),this.canvasStyle={},this.video.crossOrigin="anonymous"}ngOnChanges(e){e.url&&e.url.currentValue&&this.play(this.url)}play(e){try{this.video.muted=!0,this.video.loop=!0,this.video.controls=!1,this.video.src=e,this.video.playsInline=!0,this.video.load(),this.video.play().then((()=>{})).catch((()=>{setTimeout((()=>{this.play(e)}),200)}))}catch(t){return void setTimeout((()=>{this.play(e)}),500)}this.ctx||(this.ctx=this.canvasRef.nativeElement.getContext("2d"),this.video.addEventListener("loadeddata",(()=>{this.canvasRef.nativeElement.width=this.video.videoWidth,this.canvasRef.nativeElement.height=this.video.videoHeight,this.drawFrame()})))}drawFrame(){this.video.paused||this.video.ended||(this.ctx.drawImage(this.video,0,0,this.canvasRef.nativeElement.width,this.canvasRef.nativeElement.height),requestAnimationFrame((()=>this.drawFrame())))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmVideoComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmVideoComponent,isStandalone:!0,selector:"fm-video",inputs:{url:"url",canvasStyle:"canvasStyle"},viewQueries:[{propertyName:"canvasRef",first:!0,predicate:["videoCanvas"],descendants:!0,static:!0}],usesOnChanges:!0,ngImport:i0,template:'<canvas #videoCanvas [style]="canvasStyle"></canvas>',styles:[":host{display:flex;justify-content:center;align-items:center;overflow:hidden}canvas{max-height:100%;width:auto;height:auto;background:transparent}\n"],dependencies:[{kind:"ngmodule",type:CommonModule}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmVideoComponent,decorators:[{type:Component,args:[{selector:"fm-video",standalone:!0,imports:[CommonModule],template:'<canvas #videoCanvas [style]="canvasStyle"></canvas>',styles:[":host{display:flex;justify-content:center;align-items:center;overflow:hidden}canvas{max-height:100%;width:auto;height:auto;background:transparent}\n"]}]}],ctorParameters:()=>[],propDecorators:{url:[{type:Input}],canvasRef:[{type:ViewChild,args:["videoCanvas",{static:!0}]}],canvasStyle:[{type:Input}]}});class CompAvatarRoleVideoComponent{constructor(e){this.navCtrl=e,this.animClass="waiting",this.onClose=new EventEmitter,this.videoMap={}}close(){this.onClose.emit(!0),this.fmodeChat.isAvatarShow=!1}goBack(){this.navCtrl.back()}playWave(){!this.wave&&Recorder.WaveView&&(this.wave=Recorder.WaveView({elem:".record-wave-avatar",keep:!1}));let e=function generatePowerLevel(){return 100*Math.random()}();this.waveInterval=setInterval((()=>{let t=function generateSampleRate(){const e=[44100,48e3,88200,96e3];return e[Math.floor(Math.random()*e.length)]}(),n=function generatePcmData(e){const t=[];for(let n=0;n<e;n++)t.push(Math.floor(65536*Math.random())-32768);return t}(1e3);this.wave.input(n,e,t)}),40)}stopWave(){clearInterval(this.waveInterval)}ngAfterViewInit(){}ngOnInit(){setTimeout((()=>{this.videoMap=this.fmodeChat.avatarConfig?.video,this.playVideo(this.videoMap?.waiting),this.fmodeChat.playAnimation=this.playAnimation}),1500)}playAnimation(){let e=this;return t=>{e.animClass=t,e.stopWave(),e.playVideo(e.videoMap[t])}}playVideo(e){this.avatarVideo.play(e)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarRoleVideoComponent,deps:[{token:i1$3.NavController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompAvatarRoleVideoComponent,isStandalone:!0,selector:"fm-avatar-role-video",inputs:{fmodeChat:"fmodeChat",role:"role"},outputs:{onClose:"onClose"},viewQueries:[{propertyName:"avatarVideo",first:!0,predicate:FmVideoComponent,descendants:!0}],ngImport:i0,template:'<div class="page">\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="goBack()">\n <ion-icon name="chevron-back-outline"></ion-icon>\n </ion-button>\n </ion-buttons>\n <ion-buttons slot="end">\n <ion-button (click)="close()"> <ion-icon name="chevron-collapse-outline"></ion-icon> </ion-button>\n </ion-buttons>\n </ion-toolbar>\n <div class="avatar" [class]="animClass">\n <div class="avatar-photo">\n <fm-video #avatarVideo alt=""></fm-video>\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave-avatar">\n </div>\n </div>\n </div>\n</div>',styles:["ion-toolbar{position:fixed;top:0;left:0;width:100vw;--background:transparent}.page{position:relative;width:100vw;height:100%;top:0;left:0;display:flex;justify-content:center;align-items:center;background-color:#000}.avatar{height:100%;width:100%;display:flex;justify-content:center;align-items:center}.avatar .avatar-photo{position:relative;display:flex;justify-content:center;width:80%;max-height:100%}.avatar .avatar-photo fm-video{border-radius:50%;max-height:100%;max-width:100%}.avatar .record-wave-avatar{height:50px;width:100%;position:absolute;float:left;left:0;bottom:0}.thinking,.listening,.waiting,.talking{animation-duration:2s;animation-play-state:running;animation-iteration-count:infinite;animation-timing-function:ease-in-out}@keyframes waitingAnimation{0%{transform:scale(1)}50%{transform:scale(1.05)}to{transform:scale(1)}}@keyframes thinkingAnimation{0%{transform:rotate(0)}30%{transform:rotate(10deg)}60%{transform:rotate(-10deg)}to{transform:rotate(0)}}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"ngmodule",type:FormsModule},{kind:"component",type:FmVideoComponent,selector:"fm-video",inputs:["url","canvasStyle"]},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"component",type:IonButtons,selector:"ion-buttons",inputs:["collapse"]},{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"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompAvatarRoleVideoComponent,decorators:[{type:Component,args:[{selector:"fm-avatar-role-video",standalone:!0,imports:[CommonModule,FormsModule,FmVideoComponent,IonIcon,IonToolbar,IonButtons,IonButton],template:'<div class="page">\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="goBack()">\n <ion-icon name="chevron-back-outline"></ion-icon>\n </ion-button>\n </ion-buttons>\n <ion-buttons slot="end">\n <ion-button (click)="close()"> <ion-icon name="chevron-collapse-outline"></ion-icon> </ion-button>\n </ion-buttons>\n </ion-toolbar>\n <div class="avatar" [class]="animClass">\n <div class="avatar-photo">\n <fm-video #avatarVideo alt=""></fm-video>\n \x3c!-- 音频波动 --\x3e\n <div class="record-wave-avatar">\n </div>\n </div>\n </div>\n</div>',styles:["ion-toolbar{position:fixed;top:0;left:0;width:100vw;--background:transparent}.page{position:relative;width:100vw;height:100%;top:0;left:0;display:flex;justify-content:center;align-items:center;background-color:#000}.avatar{height:100%;width:100%;display:flex;justify-content:center;align-items:center}.avatar .avatar-photo{position:relative;display:flex;justify-content:center;width:80%;max-height:100%}.avatar .avatar-photo fm-video{border-radius:50%;max-height:100%;max-width:100%}.avatar .record-wave-avatar{height:50px;width:100%;position:absolute;float:left;left:0;bottom:0}.thinking,.listening,.waiting,.talking{animation-duration:2s;animation-play-state:running;animation-iteration-count:infinite;animation-timing-function:ease-in-out}@keyframes waitingAnimation{0%{transform:scale(1)}50%{transform:scale(1.05)}to{transform:scale(1)}}@keyframes thinkingAnimation{0%{transform:rotate(0)}30%{transform:rotate(10deg)}60%{transform:rotate(-10deg)}to{transform:rotate(0)}}\n"]}]}],ctorParameters:()=>[{type:i1$3.NavController}],propDecorators:{avatarVideo:[{type:ViewChild,args:[FmVideoComponent]}],fmodeChat:[{type:Input}],role:[{type:Input}],onClose:[{type:Output}]}});class FmAgentTaskComponent{constructor(e,t){this.dialogRef=e,this.data=t,this.enabledClose=!1,this.currentStepIndex=0,this.hasError=!1,console.log(this.data?.stepsList)}ngOnInit(){this.startTask()}async startTask(e){if(e&&(this.currentStepIndex=e),this.data.stepsList){for(;this.currentStepIndex<this.data.stepsList?.length;this.currentStepIndex++){let e=this.data.stepsList?.[this.currentStepIndex];if(console.log("this.currentStepIndex",this.currentStepIndex),e?.simulatorProgress(),e.parentComp=this,e.parentIndex=Number(this.currentStepIndex.toFixed(0)),e?.limitStart)break;if(e?.handle){let t=await(e?.handle());if(e.cancelAll){this.dialogRef.close();break}if(0==t)break;e.error||(e.progressSub$?.unsubscribe(),e.progress=1,this.stepper?.next())}}let e=!1;this.data?.stepsList.forEach(((t,n)=>{t?.error&&(e=!0,this.hasError=!0)})),e||(this.enabledClose=!0)}}onNoClick(){this.dialogRef.close()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmAgentTaskComponent,deps:[{token:i3$1.MatDialogRef},{token:MAT_DIALOG_DATA}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmAgentTaskComponent,isStandalone:!0,selector:"fm-agent-task",viewQueries:[{propertyName:"stepper",first:!0,predicate:MatStepper,descendants:!0}],ngImport:i0,template:'\n<h2 mat-dialog-title *ngIf="!enabledClose">AI生成中</h2>\n<h2 mat-dialog-title *ngIf="enabledClose">任务已完成</h2>\n<mat-dialog-content>\n \n <mat-stepper #stepper orientation="vertical">\n <mat-step *ngFor="let step of data?.stepsList; let index=index;">\n <ng-template matStepLabel>{{step?.title}}</ng-template>\n <ng-template matStepContent>\n <p *ngIf="step?.message">{{step?.message}}</p>\n <p *ngFor="let log of step?.logList">{{log}}</p>\n <button *ngIf="step?.error" mat-button color="warn">{{step?.error}}</button>\n <mat-progress-bar *ngIf="step?.progress!=1&&!step?.limitStart" [color]="step?.error?\'warn\':\'primary\'"\n [mode]="(step?.progress || 1)>=100?\'indeterminate\':\'buffer\'" [value]="step?.progress" [bufferValue]="(step?.progress || 0) + 10"></mat-progress-bar>\n\n\n\n \x3c!-- 自定义按钮区域 --\x3e\n <ng-container *ngFor="let button of step?.buttons">\n <button *ngIf="button.isShow&&button.isShow()" mat-raised-button [color]="button?.color||\'primary\'" (click)="button?.handle()">{{button?.name}}</button>\n </ng-container>\n\n <button mat-button color="warn" *ngIf="step?.restartButtonShow" (click)="startTask(index)">重试</button>\n \x3c!-- 非首项:上一步 --\x3e\n <button mat-button matStepperPrevious *ngIf="index!=0">上一步</button>\n \x3c!-- 非末项:下一步 --\x3e\n <button mat-button matStepperNext *ngIf="(index+1!=data?.stepsList?.length)&&!step?.error">下一步</button>\n </ng-template>\n </mat-step>\n\n </mat-stepper>\n \n \n</mat-dialog-content>\n<mat-dialog-actions [align]="\'end\'" style="display: flex;justify-content: center;">\n \x3c!-- <button mat-button (click)="onNoClick()">No Thanks</button> --\x3e\n <button style="font-size: 20px;" *ngIf="hasError" mat-button color="warn" [mat-dialog-close]="false" cdkFocusInitial>取消</button>\n <button style="font-size: 20px;" *ngIf="enabledClose" mat-button color="primary" [mat-dialog-close]="true" cdkFocusInitial>完成</button>\n</mat-dialog-actions>\n\n',styles:["h2{text-align:center;background-color:#6e23ce}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:MatDialogModule},{kind:"directive",type:i3$1.MatDialogClose,selector:"[mat-dialog-close], [matDialogClose]",inputs:["aria-label","type","mat-dialog-close","matDialogClose"],exportAs:["matDialogClose"]},{kind:"directive",type:i3$1.MatDialogTitle,selector:"[mat-dialog-title], [matDialogTitle]",inputs:["id"],exportAs:["matDialogTitle"]},{kind:"directive",type:i3$1.MatDialogActions,selector:"[mat-dialog-actions], mat-dialog-actions, [matDialogActions]",inputs:["align"]},{kind:"directive",type:i3$1.MatDialogContent,selector:"[mat-dialog-content], mat-dialog-content, [matDialogContent]"},{kind:"ngmodule",type:MatFormFieldModule},{kind:"ngmodule",type:MatInputModule},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"ngmodule",type:MatStepperModule},{kind:"component",type:i4.MatStep,selector:"mat-step",inputs:["color"],exportAs:["matStep"]},{kind:"directive",type:i4.MatStepLabel,selector:"[matStepLabel]"},{kind:"component",type:i4.MatStepper,selector:"mat-stepper, mat-vertical-stepper, mat-horizontal-stepper, [matStepper]",inputs:["disableRipple","color","labelPosition","headerPosition","animationDuration"],outputs:["animationDone"],exportAs:["matStepper","matVerticalStepper","matHorizontalStepper"]},{kind:"directive",type:i4.MatStepperNext,selector:"button[matStepperNext]"},{kind:"directive",type:i4.MatStepperPrevious,selector:"button[matStepperPrevious]"},{kind:"directive",type:i4.MatStepContent,selector:"ng-template[matStepContent]"},{kind:"ngmodule",type:MatProgressBarModule},{kind:"component",type:i5$1.MatProgressBar,selector:"mat-progress-bar",inputs:["color","value","bufferValue","mode"],outputs:["animationEnd"],exportAs:["matProgressBar"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmAgentTaskComponent,decorators:[{type:Component,args:[{selector:"fm-agent-task",standalone:!0,imports:[CommonModule,FormsModule,MatDialogModule,MatFormFieldModule,MatInputModule,MatButtonModule,MatStepperModule,MatProgressBarModule],template:'\n<h2 mat-dialog-title *ngIf="!enabledClose">AI生成中</h2>\n<h2 mat-dialog-title *ngIf="enabledClose">任务已完成</h2>\n<mat-dialog-content>\n \n <mat-stepper #stepper orientation="vertical">\n <mat-step *ngFor="let step of data?.stepsList; let index=index;">\n <ng-template matStepLabel>{{step?.title}}</ng-template>\n <ng-template matStepContent>\n <p *ngIf="step?.message">{{step?.message}}</p>\n <p *ngFor="let log of step?.logList">{{log}}</p>\n <button *ngIf="step?.error" mat-button color="warn">{{step?.error}}</button>\n <mat-progress-bar *ngIf="step?.progress!=1&&!step?.limitStart" [color]="step?.error?\'warn\':\'primary\'"\n [mode]="(step?.progress || 1)>=100?\'indeterminate\':\'buffer\'" [value]="step?.progress" [bufferValue]="(step?.progress || 0) + 10"></mat-progress-bar>\n\n\n\n \x3c!-- 自定义按钮区域 --\x3e\n <ng-container *ngFor="let button of step?.buttons">\n <button *ngIf="button.isShow&&button.isShow()" mat-raised-button [color]="button?.color||\'primary\'" (click)="button?.handle()">{{button?.name}}</button>\n </ng-container>\n\n <button mat-button color="warn" *ngIf="step?.restartButtonShow" (click)="startTask(index)">重试</button>\n \x3c!-- 非首项:上一步 --\x3e\n <button mat-button matStepperPrevious *ngIf="index!=0">上一步</button>\n \x3c!-- 非末项:下一步 --\x3e\n <button mat-button matStepperNext *ngIf="(index+1!=data?.stepsList?.length)&&!step?.error">下一步</button>\n </ng-template>\n </mat-step>\n\n </mat-stepper>\n \n \n</mat-dialog-content>\n<mat-dialog-actions [align]="\'end\'" style="display: flex;justify-content: center;">\n \x3c!-- <button mat-button (click)="onNoClick()">No Thanks</button> --\x3e\n <button style="font-size: 20px;" *ngIf="hasError" mat-button color="warn" [mat-dialog-close]="false" cdkFocusInitial>取消</button>\n <button style="font-size: 20px;" *ngIf="enabledClose" mat-button color="primary" [mat-dialog-close]="true" cdkFocusInitial>完成</button>\n</mat-dialog-actions>\n\n',styles:["h2{text-align:center;background-color:#6e23ce}\n"]}]}],ctorParameters:()=>[{type:i3$1.MatDialogRef},{type:void 0,decorators:[{type:Inject,args:[MAT_DIALOG_DATA]}]}],propDecorators:{stepper:[{type:ViewChild,args:[MatStepper]}]}}),addIcons({chevronBackOutline:chevronBackOutline,ellipsisHorizontalOutline:ellipsisHorizontalOutline});class FmChatHeaderArea{constructor(e){this.navCtrl=e,this.isModalOpen=!1,this.goBack=()=>{this.navCtrl.back()}}async back(){if(this.chat?.onClose){if(!await(this.chat?.onClose(this.chat)))return}this.goBack()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatHeaderArea,deps:[{token:i1$3.NavController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmChatHeaderArea,isStandalone:!0,selector:"fm-chat-header-area",inputs:{chat:"chat",goBack:"goBack"},ngImport:i0,template:'<ion-toolbar *ngIf="chat?.isAvatarShow==false">\n <ion-buttons slot="start">\n <ion-button (click)="back()">\n <ion-icon name="chevron-back-outline"></ion-icon>\n </ion-button>\n </ion-buttons>\n <ion-title>\n <div class="title-avatar-area">\n <div class="avatar-img" (click)="chat.showAvatar()">\n <img *ngIf="chat?.role?.get(\'avatar\')||chat?.role?.get(\'thumb\')" [src]="chat?.role?.get(\'avatar\')||chat?.role?.get(\'thumb\')" />\n <ion-icon *ngIf="chat?.role?.get(\'avatarConfig\')" name="resize-outline"></ion-icon>\n </div>\n <span (click)="chat.showAvatar()">\n {{chat?.role?.get("name")}}\n </span>\n </div>\n </ion-title>\n\n <ion-buttons slot="end">\n <ion-button (click)="isModalOpen=true"> <ion-icon name="ellipsis-horizontal-outline"></ion-icon> </ion-button>\n </ion-buttons>\n</ion-toolbar>\n\n<div class="avatar-area" *ngIf="chat?.isAvatarShow==true">\n <fm-avatar-role-image *ngIf="chat?.avatarMode==\'image\'" [fmodeChat]="chat" [role]="avatarRole"></fm-avatar-role-image>\n <fm-avatar-role-video *ngIf="chat?.avatarMode==\'video\'" [fmodeChat]="chat" [role]="avatarRole"></fm-avatar-role-video>\n</div>\n\n\n<ion-modal [isOpen]="isModalOpen" (willDismiss)="isModalOpen=false">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="isModalOpen=false">返回</ion-button>\n </ion-buttons>\n <ion-title>简介</ion-title>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n\n <ion-card style="margin: 0px;">\n <img style="width:100%" [src]="chat?.role?.get(\'thumb\')" alt="">\n <ion-card-header>\n <ion-card-subtitle>{{chat?.role?.get(\'tags\')}}</ion-card-subtitle>\n <ion-card-title>{{chat?.role?.get("name")}}</ion-card-title>\n </ion-card-header>\n \n <ion-card-content>\n {{chat?.role?.get("desc")}}\n \n <ion-list [inset]="true" style="margin:0px;">\n \x3c!-- <ion-item>\n <ion-avatar *ngIf="chat?.role?.get(\'thumb\')" aria-hidden="true" slot="start">\n <img [src]="chat?.role?.get(\'thumb\')" />\n </ion-avatar>\n <ion-label>{{chat?.role?.get("name")}}</ion-label>\n </ion-item> --\x3e\n <ion-item lines="none" *ngIf="chat?.role?.get(\'age\')">\n <ion-note slot="start">年龄</ion-note>\n <ion-label>{{chat?.role?.get("age")}}</ion-label>\n </ion-item>\n <ion-item lines="none" *ngIf="chat?.role?.get(\'gender\')">\n <ion-note slot="start">性别</ion-note>\n <ion-label>{{chat?.role?.get("gender")}}</ion-label>\n </ion-item>\n <ion-item lines="none">\n <ion-note slot="start">称号</ion-note>\n <ion-label>{{chat?.role?.get("title")}}</ion-label>\n </ion-item>\n \n <ion-item lines="none">\n <ion-note slot="start">擅长</ion-note>\n <ion-label>{{chat?.role?.get("tags")?.join(\',\')}}</ion-label>\n </ion-item>\n \n </ion-list>\n </ion-card-content>\n </ion-card>\n </ion-content>\n </ng-template>\n </ion-modal>',styles:[".title-avatar-area{width:100%;height:100%;display:flex;justify-content:center;align-items:center}.title-avatar-area .avatar-img img{width:32px;height:32px;border-radius:50%;margin-right:5px}.title-avatar-area .avatar-img ion-icon{background:#df76dfcc;border-radius:50%;padding:3px;position:absolute;color:#000;margin-left:-20px;font-size:10px;margin-top:18px}.avatar-area{height:100%}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"component",type:IonButtons,selector:"ion-buttons",inputs:["collapse"]},{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:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonModal,selector:"ion-modal"},{kind:"component",type:IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"component",type:IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:IonList,selector:"ion-list",inputs:["inset","lines","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:IonCard,selector:"ion-card",inputs:["button","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:IonNote,selector:"ion-note",inputs:["color","mode"]},{kind:"component",type:CompAvatarRoleImageComponent,selector:"fm-avatar-role-image",inputs:["fmodeChat","role"]},{kind:"component",type:CompAvatarRoleVideoComponent,selector:"fm-avatar-role-video",inputs:["fmodeChat","role"],outputs:["onClose"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatHeaderArea,decorators:[{type:Component,args:[{selector:"fm-chat-header-area",standalone:!0,imports:[CommonModule,IonToolbar,IonButtons,IonButton,IonIcon,IonModal,IonAvatar,IonTitle,IonHeader,IonList,IonItem,IonCard,IonLabel,IonNote,CompAvatarRoleImageComponent,CompAvatarRoleVideoComponent],template:'<ion-toolbar *ngIf="chat?.isAvatarShow==false">\n <ion-buttons slot="start">\n <ion-button (click)="back()">\n <ion-icon name="chevron-back-outline"></ion-icon>\n </ion-button>\n </ion-buttons>\n <ion-title>\n <div class="title-avatar-area">\n <div class="avatar-img" (click)="chat.showAvatar()">\n <img *ngIf="chat?.role?.get(\'avatar\')||chat?.role?.get(\'thumb\')" [src]="chat?.role?.get(\'avatar\')||chat?.role?.get(\'thumb\')" />\n <ion-icon *ngIf="chat?.role?.get(\'avatarConfig\')" name="resize-outline"></ion-icon>\n </div>\n <span (click)="chat.showAvatar()">\n {{chat?.role?.get("name")}}\n </span>\n </div>\n </ion-title>\n\n <ion-buttons slot="end">\n <ion-button (click)="isModalOpen=true"> <ion-icon name="ellipsis-horizontal-outline"></ion-icon> </ion-button>\n </ion-buttons>\n</ion-toolbar>\n\n<div class="avatar-area" *ngIf="chat?.isAvatarShow==true">\n <fm-avatar-role-image *ngIf="chat?.avatarMode==\'image\'" [fmodeChat]="chat" [role]="avatarRole"></fm-avatar-role-image>\n <fm-avatar-role-video *ngIf="chat?.avatarMode==\'video\'" [fmodeChat]="chat" [role]="avatarRole"></fm-avatar-role-video>\n</div>\n\n\n<ion-modal [isOpen]="isModalOpen" (willDismiss)="isModalOpen=false">\n <ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="isModalOpen=false">返回</ion-button>\n </ion-buttons>\n <ion-title>简介</ion-title>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding">\n\n <ion-card style="margin: 0px;">\n <img style="width:100%" [src]="chat?.role?.get(\'thumb\')" alt="">\n <ion-card-header>\n <ion-card-subtitle>{{chat?.role?.get(\'tags\')}}</ion-card-subtitle>\n <ion-card-title>{{chat?.role?.get("name")}}</ion-card-title>\n </ion-card-header>\n \n <ion-card-content>\n {{chat?.role?.get("desc")}}\n \n <ion-list [inset]="true" style="margin:0px;">\n \x3c!-- <ion-item>\n <ion-avatar *ngIf="chat?.role?.get(\'thumb\')" aria-hidden="true" slot="start">\n <img [src]="chat?.role?.get(\'thumb\')" />\n </ion-avatar>\n <ion-label>{{chat?.role?.get("name")}}</ion-label>\n </ion-item> --\x3e\n <ion-item lines="none" *ngIf="chat?.role?.get(\'age\')">\n <ion-note slot="start">年龄</ion-note>\n <ion-label>{{chat?.role?.get("age")}}</ion-label>\n </ion-item>\n <ion-item lines="none" *ngIf="chat?.role?.get(\'gender\')">\n <ion-note slot="start">性别</ion-note>\n <ion-label>{{chat?.role?.get("gender")}}</ion-label>\n </ion-item>\n <ion-item lines="none">\n <ion-note slot="start">称号</ion-note>\n <ion-label>{{chat?.role?.get("title")}}</ion-label>\n </ion-item>\n \n <ion-item lines="none">\n <ion-note slot="start">擅长</ion-note>\n <ion-label>{{chat?.role?.get("tags")?.join(\',\')}}</ion-label>\n </ion-item>\n \n </ion-list>\n </ion-card-content>\n </ion-card>\n </ion-content>\n </ng-template>\n </ion-modal>',styles:[".title-avatar-area{width:100%;height:100%;display:flex;justify-content:center;align-items:center}.title-avatar-area .avatar-img img{width:32px;height:32px;border-radius:50%;margin-right:5px}.title-avatar-area .avatar-img ion-icon{background:#df76dfcc;border-radius:50%;padding:3px;position:absolute;color:#000;margin-left:-20px;font-size:10px;margin-top:18px}.avatar-area{height:100%}\n"]}]}],ctorParameters:()=>[{type:i1$3.NavController}],propDecorators:{chat:[{type:Input}],goBack:[{type:Input}]}}),Parse__default.applicationId||(Parse__default.initialize("ncloudmaster"),Parse__default.serverURL=(Parse__default.serverURL?.split("parse")?.[0]||"https://server.fmode.cn/")+"parse");class AuthService{isGuardLock(e){let t=!0,n=Parse__default.User.current();return t=!n?.id&&this.guardMap[e],t}get loginTypeCount(){return Object.values(this.loginOptions)?.filter((e=>e))?.length}get logoUrl(){return localStorage.getItem("LOGO_URL")||this._logoUrl||"https://file.yuban.co/img/logo-feima.png"}set logoUrl(e){localStorage.setItem("LOGO_URL",e),this._logoUrl=this._logoUrl}getCompanyId(){let e=localStorage.getItem("company");return e=this.company||e,e}constructor(e,t,n,o){this.router=e,this.toastCtrl=t,this.novaCloud=n,this.http=o,this.guardMap={},this.modalType="fullscreen",this.isModalShow=!1,this.showBackHome=!0,this.activeButton="账号密码",this.loginOptions={userpwd:!0,mobilepwd:!0,mobilecode:!0,wechat:!0},this._logoUrl="https://file.yuban.co/img/logo-feima.png",this.wechatUrl="https://app.fmode.cn/logo/z0qr.jpg",this.isLoggedIn=!1,this.message={success:e=>{this.toast({color:"success",message:e})},create:(e,t)=>{"error"==e&&(e="danger"),this.toast({color:e,message:t})},info:e=>{this.toast({message:e})},error:e=>{this.toast({color:"danger",message:e})}},this.LoginPage="/pcuser/login",this.mobileUserMap={},this.enabledLocalCode=!1}async toast(e){e.position=e?.position||"top",e.duration=e?.duration||1500,e.color=e?.color||"primary",(await this.toastCtrl.create(e)).present()}init(e){this.company=e.company,this.guardType=e.guardType,this.modalType=e.modalType||this.modalType,this.saveParamsInvite()}checkLoginLock(){let e=Parse__default.User.current();return!!e?.id||(this.isModalShow=!0,this.isLoggedIn=!1,!1)}async checkLogin(e){await this.checkAndLoginWithToken(),this.guardMap[e]=!0;let t=Parse__default.User.current();return console.log("currentUser",t),t&&t.id?(this.setAccount(t),this.isLoggedIn=!0,!0):this.guardType&&"page"!=this.guardType?"modal"==this.guardType?(this.isModalShow=!0,this.isLoggedIn=!1,!0):void 0:(this.redirectUrl=e,this.router.navigate([this.LoginPage]),!1)}async checkAndLoginWithToken(){console.log("checkAndLoginWithToken");const e=new URLSearchParams(window.location.search),t=e.get("token");if(t){e.delete("token");let n=window.location.pathname+(e.toString()?"?"+e.toString():"")+window.location.hash;n=decodeURIComponent(n),console.log("newUrl",n),window.history.replaceState({},"",n),setTimeout((()=>{window.history.replaceState({},"",n)}),1e3);let o=Parse__default.User.current();if(!o?.id)try{o=await Parse__default.User.become(t)}catch(e){}}}async setAccount(e){if(this.account?.id)return;let t=Parse__default.Object.extend("Account"),n=e?.get("company")||{__type:"Pointer",className:"Company",objectId:this.getCompanyId()}||null,o=new Parse__default.Query("Account");o.equalTo("user",e.toPointer());let i=await o.first();return i?.id||(i=new t,i.set({user:e.toPointer(),company:n}),i=await i.save()),this.account=i,i}login(e,t){return new Promise(((n,o)=>{Parse__default.User.logIn(e,t).then((async e=>{if(this.bindInvite(e),this.setCurrentUserLocalStorage(e),"modal"==this.guardType)return await this.refreshPage(),void n(!0);let t=new Parse__default.Query("Company");t.select("rootPage"),t.equalTo("objectId",e?.get("company")?.id);let o=await t.first(),i=o?.get("rootPage");this.redirectUrl=this.redirectUrl||i||"/project/dashboard";let a=this.redirectUrl;a=decodeURIComponent(a),this.router.navigate([a])})).catch((e=>{console.error(e),o({message:"无此用户信息,请先在小程序登录"})}))}))}refreshPage(){return new Promise((e=>{let t=this.router.url;Parse__default.User.current()?.id&&(this.isModalShow=!1),this.router.navigateByUrl("/",{skipLocationChange:!0}).then((()=>{this.router.navigateByUrl(t).then((()=>{e(!0)}))}))}))}setCurrentUserLocalStorage(e){e.get("company")?.id&&localStorage.setItem("company",e.get("company")?.id)}logout(e,t){let n=localStorage.getItem("company"),o=localStorage.getItem("WECHAT_APP_ID"),i=localStorage.getItem("LOGO_URL"),a=localStorage.getItem("NOVA_APIG_SERVER");localStorage.clear(),localStorage.setItem("company",n),localStorage.setItem("WECHAT_APP_ID",o),localStorage.setItem("LOGO_URL",i),localStorage.setItem("NOVA_APIG_SERVER",a),Parse__default.User.logOut().then((e=>{})),this.router.navigate([t||"/pcuser/login"])}async loginMobilePassword(e,t,n){let o=await this.getMobileUser(e);o?this.login(o,t).then((async e=>{this.isModalShow=!1})).catch((e=>{console.log(e),n.create("error","错误的用户名或密码")})):n.create("error","用户不存在,请尝试其他登录方式")}signMobilePassword(e,t){return new Promise((async(n,o)=>{n(await this.signUpAndUpdate(e,t))}))}async getMobileUser(e){let t=this.getCompanyId(),n=t+e;if(this.mobileUserMap[n])return this.mobileUserMap[n];let o=await this.novaCloud.api("/auth/getusername",{company:t,mobile:e});return o?.username&&(this.mobileUserMap[n]=o?.username),this.mobileUserMap[n]}signUpAndUpdate(e,t){return t=t||e+"pwd666",new Promise((n=>{Parse__default.User.signUp(this.getCompanyId()+"-"+e,t,"").then((async t=>{t.id&&(console.log(t),t.set("company",{__type:"Pointer",className:"Company",objectId:this.getCompanyId()}),t.set("mobile",e),t.set("type","user"),this.bindInvite(t),t=await t.save(),n(t))})).catch((e=>{n(void 0)}))}))}async getMobileCodeToken(e,t){return new Promise(((n,o)=>{let i=Parse__default.serverURL?.split("parse")?.[0]||"https://server.fmode.cn/";this.http.get(i+`api/auth/mobile?company=${this.company}&mobile=${e}&code=${t}`).toPromise().then((e=>{n(e)})).catch((e=>{o(e)}))}))}async loginCode(e,t,n,o){if(t)try{let n=await this.getMobileCodeToken(e,t);if(200==n?.code){console.log(200,n);let e=await Parse__default.User.become(n.data.token);if(console.log(e,e?.id),e?.id){console.log(e,e?.id);try{await this.bindInvite(e)}catch(e){console.error("bind err b",e)}return!0}}}catch(n){if(console.log("error1",n),!(n?.error?.mess?.indexOf("用户不存在")>-1))return void this.toast({message:n?.error?.mess});{let n=await this.signUpAndUpdate(e);if(n?.id)return await this.loginCode(e,t)}}else this.toast({color:"primary",message:"请填写有效验证码"})}saveParamsInvite(){let e=this.novaCloud.searchParse();console.log("saveParamsInvite",e);let t=e?.get("invite");console.log(t),t&&localStorage.setItem("invite",t)}async bindInvite(e){if(!(e=e||Parse__default.User.current()))return;if(e?.get("invite")?.id)return;let t,n=localStorage.getItem("invite");if(n&&e?.id!=n)try{t=await this.novaCloud.api("/auth/invite",{current:e?.id,invite:n,type:"code"}),console.log("bind",t)}catch(e){console.error("bind err",e)}}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthService,deps:[{token:i1$1.Router},{token:i1$3.ToastController},{token:NovaCloudService},{token:i1.HttpClient}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1$1.Router},{type:i1$3.ToastController},{type:NovaCloudService},{type:i1.HttpClient}]});class AccountService{constructor(e,t,n){this.ncloud=e,this.authServ=t,this.http=n,this.company="",this.billing={credit:{usedDetail:{}}},this.wxAppId="",this.wxpayEnabled=!1,this.appid=localStorage.getItem("WECHAT_APP_ID")||"wxb4193c93ae9aa696",this.company=this.authServ.company||localStorage.getItem("company"),this.getBilling(),this.getProfile(),this.getUserOpenid()}async getProfile(){let e=Parse__default.User.current()?.id;if(!e)return;let t=new Parse__default.Query("Profile");t.equalTo("user",e),t.equalTo("company",this.company),t.notEqualTo("isDeleted",!0);let n=await t.first();n?.id&&(this.profile=n)}async getBilling(){let e;if(Parse__default.User.current()?.getSessionToken()){try{e=await this.ncloud.apig("aigc/account",null,"get")}catch(e){}return e?.credit&&(this.billing=e),e}}async getUserOpenid(){let e=-1!=navigator.userAgent.toLowerCase().indexOf("micromessenger"),t=this.getQueryStringByName("code"),n=localStorage.getItem("openid");if(!n){if(!Parse__default.User.current())return;let o=Parse__default.User.current().get("wechat");n=o?.[this.appid]?.openid,e&&(t?await this.getwechat(t):this.authWechat())}}authWechat(e="/account/billing"){if(!localStorage.getItem("openid")){let e=window.location.href;return e=encodeURIComponent(e),void(window.location.href="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+this.appid+"&redirect_uri="+e+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect")}}getQueryStringByName(e){let t=location.search.match(new RegExp("[?&]"+e+"=([^&]+)","i"));return null==t||t.length<1?"":t[1]}async getwechat(e,t="/account/billing"){return new Promise((async(n,o)=>{this.http.post("https://server.fmode.cn/api/wechat/get_wx",{company:this.company,code:e}).subscribe((async e=>{if(console.log(e),e&&200==e.code&&e.data.openid){let t=e.data.openid;localStorage.setItem("openid",t),localStorage.removeItem("code");let o={};o[this.appid]={openid:t},Parse__default.User.current().set("wechat",o),await Parse__default.User.current().save(),n(!0)}}),(async e=>{console.log("Error updating items",e),this.authWechat(t),o(!1)}))}))}getWXSignPackageInWechat(){let e={company:this.company,href:encodeURIComponent(location.href.split("?")[0])};this.http.post("https://server.fmode.cn/api/wechat/getconfig",e).subscribe((e=>{const t=e.data;this.wxAppId=t.appid,this.wxpayEnabled=!0,wx.config({debug:!1,appId:t.appid,timestamp:t.timestamp,nonceStr:t.nonceStr,signature:t.signature,jsApiList:["chooseWXPay","onMenuShareTimeline","onMenuShareAppMessage","onMenuShareQQ","onMenuShareQZone","updateAppMessageShareData","updateTimelineShareData"]});let n="https://ai.fmode.cn";location.pathname;Parse__default.User.current()?.id;let o=this.shareInfo||{title:"飞码AI",desc:"解放创意引领未来|国际前沿的AIGC平台",link:n,type:"link",imgUrl:"https://file-cloud.fmode.cn/E4KpGvTEto/20230822/3mkf41033623275.png",success:function(){console.log("分享成功")},error:function(){console.log("分享失败")},cancel:function(){console.log("取消分享")}};wx.ready((()=>{wx.updateAppMessageShareData(o),wx.updateTimelineShareData(o)})),wx.error((()=>{}))}))}async saveAccountLog(e,t,n,o){return new Promise(((i,a)=>{this.http.post("https://test.fmode.cn/api/apig/saveAccountLog",{company:n,uid:Parse__default.User.current().id,orderid:t,info:e}).subscribe((e=>{console.log(e),i(!0)}),(e=>{console.warn(e),o&&o.error("请求超时,请稍后再试"),a()}))}))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AccountService,deps:[{token:NovaCloudService},{token:AuthService},{token:i1.HttpClient}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AccountService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AccountService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:NovaCloudService},{type:AuthService},{type:i1.HttpClient}]}),addIcons({person:person});class CompUserAvatarComponent{constructor(e){this.novaAccount=e,this.type="icon",this.text="U"}ngOnInit(){this.type=this.getType()}ngOnChanges(){this.refresh()}async refresh(){await this.novaAccount.getProfile();let e=this.novaAccount.profile;e?.get("type")&&("student"==e?.get("type")?this.identity="https://file-cloud.fmode.cn/khgbeQmvYZ/20231123/k1k4iq103416124.png":this.identity="https://file-cloud.fmode.cn/E4KpGvTEto/20231116/q12c16094638625.png")}getType(){if(!this.user?.id)return"icon";if(this.user?.get("avatar"))return"avatar";let e=this.user?.get("nickname")||this.user?.get("realname");return e?(this.text=e?.slice(0,1),"text"):"icon"}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompUserAvatarComponent,deps:[{token:AccountService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompUserAvatarComponent,isStandalone:!0,selector:"app-comp-user-avatar",inputs:{user:"user"},usesOnChanges:!0,ngImport:i0,template:'<ng-container *ngIf="user?.id || type == \'icon\'">\n <div class="avatar-com">\n \x3c!-- Default Icon --\x3e\n <ion-avatar *ngIf="type == \'icon\'">\n <ion-icon name="person" color="dark"></ion-icon>\n </ion-avatar>\n \n \x3c!-- Avatar Image --\x3e\n <div class="avatar-com">\n <ion-avatar *ngIf="type == \'avatar\'">\n <img [src]="user?.get(\'avatar\')" />\n </ion-avatar>\n \n \x3c!-- Text Avatar --\x3e\n <ion-avatar *ngIf="type == \'text\'" class="text-avatar">\n {{text}}\n </ion-avatar>\n \n <img\n class="auth-icon"\n *ngIf="identity && type == \'avatar\'"\n [src]="identity"\n alt="已认证"\n />\n </div>\n </div>\n</ng-container>',styles:[".avatar-com{position:relative;width:32px;height:32px}.avatar-com ion-avatar{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background-color:var(--ion-color-light)}.avatar-com ion-avatar.text-avatar{background-color:#0199f9;color:#fff;font-weight:700}.avatar-com ion-avatar ion-icon{font-size:20px;color:#222d3a}.avatar-com .auth-icon{width:20px;height:20px;border-radius:50%;position:absolute;right:-6px;bottom:-2px;border:2px solid white}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:IonAvatar,selector:"ion-avatar"},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompUserAvatarComponent,decorators:[{type:Component,args:[{selector:"app-comp-user-avatar",standalone:!0,imports:[CommonModule,IonAvatar,IonIcon],template:'<ng-container *ngIf="user?.id || type == \'icon\'">\n <div class="avatar-com">\n \x3c!-- Default Icon --\x3e\n <ion-avatar *ngIf="type == \'icon\'">\n <ion-icon name="person" color="dark"></ion-icon>\n </ion-avatar>\n \n \x3c!-- Avatar Image --\x3e\n <div class="avatar-com">\n <ion-avatar *ngIf="type == \'avatar\'">\n <img [src]="user?.get(\'avatar\')" />\n </ion-avatar>\n \n \x3c!-- Text Avatar --\x3e\n <ion-avatar *ngIf="type == \'text\'" class="text-avatar">\n {{text}}\n </ion-avatar>\n \n <img\n class="auth-icon"\n *ngIf="identity && type == \'avatar\'"\n [src]="identity"\n alt="已认证"\n />\n </div>\n </div>\n</ng-container>',styles:[".avatar-com{position:relative;width:32px;height:32px}.avatar-com ion-avatar{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background-color:var(--ion-color-light)}.avatar-com ion-avatar.text-avatar{background-color:#0199f9;color:#fff;font-weight:700}.avatar-com ion-avatar ion-icon{font-size:20px;color:#222d3a}.avatar-com .auth-icon{width:20px;height:20px;border-radius:50%;position:absolute;right:-6px;bottom:-2px;border:2px solid white}\n"]}]}],ctorParameters:()=>[{type:AccountService}],propDecorators:{user:[{type:Input}]}});class DurationStrPipe{transform(e,...t){let n=String(parseInt(String(e/60))),o="";return e/60>1&&(o+=`${n}'`),o+=`${String((e%60).toFixed(0))}"`,o}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DurationStrPipe,deps:[],target:i0.ɵɵFactoryTarget.Pipe})}static{this.ɵpipe=i0.ɵɵngDeclarePipe({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:DurationStrPipe,isStandalone:!0,name:"durationStr"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DurationStrPipe,decorators:[{type:Pipe,args:[{name:"durationStr",standalone:!0}]}]}),addIcons({wifiOutline:wifiOutline,copyOutline:copyOutline});class FmChatMessageCard{ngOnChanges(){this.chat?.isTalkMode&&"assistant"===this.message?.role&&!this.message?.complete?(this.isLoadingText=!0,this.messageText$.next("正在加载中...")):(this.isLoadingText=!1,this.messageText$.next(getMessageContentText(this.message?.content)))}constructor(e){this.copyServ=e,this.messageText$=new BehaviorSubject(""),this.isLoadingText=!0,this.user=Parse__default.User.current()}async toggleVoicePlay(){if(this.message?.voice?.id&&this.chat.VoiceTTSMap[this.message?.voice?.id]&&(this.tts=this.chat.VoiceTTSMap[this.message?.voice?.id]),this.tts?.isPlaying)return void this.tts?.stop();this.chat?.isTalkMode&&"assistant"===this.message?.role&&(this.isLoadingText=!0,this.messageText$.next("正在加载中..."));let e,t=!1;if(this.message?.voice?.id){let t=new Parse__default.Query("ChatVoice");t.include("voiceFile"),e=await t.get(this.message?.voice?.id)}if(!e?.id){let n=await this.chat.getVoiceByContentText(this.message?.content);e=this.chat.voiceMap[n?.id],this.message.voice={id:e?.id,duration:e?.get("duration")},t=!0}this.message?.voice?.duration||(this.message.voice.duration=e?.get("duration"),t=!0),t&&this.saveSession(),await this.chat.playChatVoice(e,{onStart:t=>{this.chat?.isTalkMode&&"assistant"===this.message?.role&&setTimeout((()=>{this.isLoadingText=!1,this.messageText$.next(getMessageContentText(this.message?.content))}),600),e?.id,t?.id},onLoaded:e=>{this.message.voice.duration=1e3*e.duration,this.updateVoiceDuration(1e3*e.duration)},onResult:e=>{console.log("onResult",e),e?.duration&&(this.message.voice.duration=e?.duration)},onStop:t=>{e?.id,t?.id}}),this.tts=this.chat.VoiceTTSMap[e?.id]}updateVoiceDuration(e){this.message?.voice?.duration||(this.message.voice.duration=e,this.saveSession())}saveSession(){(this.index>=2||void 0===this.index)&&this.chat?.saveChatSession()}async copy(){this.copyServ.copyToClipboard(getMessageContentText(this.message?.content))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatMessageCard,deps:[{token:ClipboardService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmChatMessageCard,isStandalone:!0,selector:"fm-chat-message-card",inputs:{index:"index",message:"message",role:"role",chat:"chat"},usesOnChanges:!0,ngImport:i0,template:'<div class="message-card" [class.right]="message?.role==\'user\'" [class.center]="message?.role==\'system\'">\n \x3c!-- 用户及操作区 --\x3e\n <div class="item-row user" *ngIf="message?.role!=\'system\'"> \x3c!-- 系统消息不显示头像 --\x3e\n <div class="avatar-row">\n <div class="actions">\n \x3c!-- 刷新 --\x3e\n \x3c!-- <ion-button fill="outline" slot="start">\n <ion-icon name="refresh-outline"></ion-icon> \n </ion-button> --\x3e\n \x3c!-- 复制 --\x3e\n <ion-button size="small" fill="outline" slot="start" (click)="copy()">\n <ion-icon name="copy-outline"></ion-icon>\n </ion-button>\n \x3c!-- 编辑 --\x3e\n \x3c!-- <ion-button fill="outline" slot="start">\n <ion-icon name="create-outline"></ion-icon>\n </ion-button> --\x3e\n </div>\n \x3c!-- 更新音频消息区域 --\x3e\n <div *ngIf="((message?.role==\'assistant\' && chat?.role?.get(\'voiceConfig\')?.voice) || (message?.role==\'user\'&&message?.voice))" \n class="play-voice" \n (click)="!isLoadingText && toggleVoicePlay()"\n [class.loading-voice]="chat?.isTalkMode && isLoadingText">\n\n <div class="voice-button">\n \x3c!-- 加载时显示spinner,否则显示wifi图标 --\x3e\n <ion-spinner *ngIf="chat?.isTalkMode && isLoadingText" name="lines" class="loading-spinner"></ion-spinner>\n <ion-icon *ngIf="!(chat?.isTalkMode && isLoadingText)" name="wifi-outline"\n [style.transform]="message?.role==\'user\'?\'rotate(-90deg)\':\'rotate(90deg)\'"\n class="audio-icon" \n [class.play-voice-playing]="tts?.isPlaying"></ion-icon>\n </div>\n <div class="voice-info">\n <span *ngIf="message?.voice?.duration && !isLoadingText">\n {{((message?.voice?.duration||0)/1000) | durationStr}}\n </span>\n </div>\n </div>\n \x3c!-- 头像区域 --\x3e \n <img class="avatar" *ngIf="message?.role!=\'user\'" [src]="(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/100/h/100\'" >\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="item-row images" *ngIf="message?.content | chatContent:\'image_url\'">\n <img [src]="message?.content | chatContent:\'image_url\'" alt="">\n </div>\n \x3c!-- 聊天气泡 --\x3e\n \x3c!-- Replace the bubble section with this: --\x3e\n <div class="item-row bubble" [style.fontSize]="role?.get(\'uiConfig\')?.message?.bubble?.fontSize || \'0.8rem\'">\n \x3c!-- 说话模式:展示加载状态 Show loading state for talk mode when message is not complete --\x3e\n \n \x3c!-- Show normal content for non-talk mode or when loading is complete --\x3e\n <ng-container *ngIf="!chat?.isTalkMode || message?.role !== \'assistant\' || !isLoadingText">\n <fm-markdown-preview *ngIf="!message?.complete" class="content-style" \n [content]="message?.content | chatContent" [render]="false"></fm-markdown-preview>\n <fm-markdown-preview *ngIf="message?.complete" \n [content]="message?.content | chatContent"></fm-markdown-preview>\n </ng-container>\n </div>\n \x3c!-- 时间显示 --\x3e\n <div class="item-row loading" *ngIf="message?.role!=\'system\' && !message?.complete">\n 正在输入<ion-spinner name="dots"></ion-spinner>\n </div>\n\n <div class="item-row created" *ngIf="message?.createdAt">\n <span>{{message?.createdAt | date:"dd/MM/yy HH:mm"}}</span>\n </div>\n</div>',styles:['@charset "UTF-8";:host-context(body.dark) .message-card .actions .item-native{background:none!important}:host-context(body.dark) .message-card .bubble{color:#0e101d}:host-context(body.dark) .message-card .bubble .content-style{filter:invert(1)!important}:host-context(body.dark) .message-card .bubble fm-markdown-preview{filter:invert(1)!important}:host-context(body.dark) .message-card .play-voice{background-color:#0e101d}:host-context(body.dark) .message-card .play-voice .voice-info{color:#fff}:host-context(body.dark) .message-card .right .bubble{color:#921f8a!important;background:#921f8a!important}:host-context(body.dark) .message-card .right .play-voice{background:#921f8a!important}:host-context(body.dark) .message-card .created span{color:#fff}@media screen and (max-width: 800px){.message-card:focus .actions{opacity:1!important}}.message-card:hover .actions{opacity:1;transition:opacity .3s ease-in-out}.message-card{display:flex;flex-wrap:wrap;justify-content:start;align-items:flex-start}.message-card .avatar-row{width:300px;height:32px;display:flex;flex-direction:row-reverse;justify-content:start;align-items:center}.message-card .actions{display:flex;opacity:0;padding-left:10px;padding-right:10px}.message-card .item-row{display:flex;flex:100%;justify-content:start;margin-bottom:5px}.message-card .images img{max-width:300px}.message-card .bubble{display:flex;justify-content:center;max-width:100%;padding:.5rem .5rem 0rem;color:#333;flex:none;border-radius:0 1.5em 1.5em/0em 1.5em 1.5em;color:#fff;background-color:currentColor}.message-card .bubble.loading{color:var(--gray-secondary)}.message-card .bubble.loading .content-style{filter:none}.message-card .bubble .content-style{filter:grayscale(1) contrast(999) invert(1)}.message-card .loading{text-align:right;color:#101010}.message-card .created{display:flex}.message-card .created span{font-size:12px;opacity:.4;white-space:nowrap;transition:all .6s ease;color:var(--black);text-align:center;width:100%;box-sizing:border-box;padding-right:10px;pointer-events:none;z-index:1}.right{justify-content:end;align-items:flex-end}.right .avatar-row{flex-direction:row;justify-content:end;width:auto}.right .actions{position:relative;margin-left:0}.right .item-row{justify-content:end}.right .bubble{color:#bbdefb;border-top-left-radius:1.5em;border-top-right-radius:0}.right .play-voice{flex-direction:row-reverse;background-color:#bbdefb}.center{justify-content:center;align-items:center}.center .item-row{justify-content:center}.center .bubble{color:var(--gray-secondary);border-top-left-radius:1.5em;border-top-right-radius:1.5em;font-size:12px;font-weight:100;padding:5px 20px}.play-voice{min-width:100px;height:32px;display:flex;justify-content:space-around;align-items:center;background-color:#fff;border-radius:7px}.play-voice .voice-button{width:32px;height:32px;display:flex;justify-content:center;align-items:center}.play-voice .voice-button span{overflow:hidden;font-size:18px;color:#ff69b4}.play-voice .voice-info{height:32px;display:flex;padding:0 10px;justify-content:end;align-items:center;color:#333}.avatar{border-radius:50%;width:32px;height:32px;object-fit:cover}.audio-icon{color:#ff69b4;font-size:18px}.play-voice-playing{animation:play-voice-animation 1s infinite}@keyframes play-voice-animation{0%{width:0}to{width:32px}}.content-style.loading-text{color:#666;font-style:italic}.play-voice{transition:opacity .3s ease}.play-voice.loading-voice{opacity:.8;cursor:not-allowed}.play-voice.loading-voice .loading-spinner{width:18px;height:18px;color:var(--gray-secondary)}.play-voice.loading-voice .loading-text{font-size:.8em;color:var(--gray-secondary);margin-left:5px}.play-voice .voice-button{display:flex;align-items:center;justify-content:center;width:24px;height:24px}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"pipe",type:i2.DatePipe,name:"date"},{kind:"component",type:CompUserAvatarComponent,selector:"app-comp-user-avatar",inputs:["user"]},{kind:"ngmodule",type:MarkdownPreviewModule},{kind:"component",type:MarkdownPreviewComponent,selector:"fm-markdown-preview",inputs:["content","render"]},{kind:"pipe",type:ChatContentPipe,name:"chatContent"},{kind:"pipe",type:DurationStrPipe,name:"durationStr"}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatMessageCard,decorators:[{type:Component,args:[{selector:"fm-chat-message-card",standalone:!0,imports:[CommonModule,IonItem,CompUserAvatarComponent,MarkdownPreviewModule,IonAvatar,ChatContentPipe,NzSanitizerPipe,DurationStrPipe],template:'<div class="message-card" [class.right]="message?.role==\'user\'" [class.center]="message?.role==\'system\'">\n \x3c!-- 用户及操作区 --\x3e\n <div class="item-row user" *ngIf="message?.role!=\'system\'"> \x3c!-- 系统消息不显示头像 --\x3e\n <div class="avatar-row">\n <div class="actions">\n \x3c!-- 刷新 --\x3e\n \x3c!-- <ion-button fill="outline" slot="start">\n <ion-icon name="refresh-outline"></ion-icon> \n </ion-button> --\x3e\n \x3c!-- 复制 --\x3e\n <ion-button size="small" fill="outline" slot="start" (click)="copy()">\n <ion-icon name="copy-outline"></ion-icon>\n </ion-button>\n \x3c!-- 编辑 --\x3e\n \x3c!-- <ion-button fill="outline" slot="start">\n <ion-icon name="create-outline"></ion-icon>\n </ion-button> --\x3e\n </div>\n \x3c!-- 更新音频消息区域 --\x3e\n <div *ngIf="((message?.role==\'assistant\' && chat?.role?.get(\'voiceConfig\')?.voice) || (message?.role==\'user\'&&message?.voice))" \n class="play-voice" \n (click)="!isLoadingText && toggleVoicePlay()"\n [class.loading-voice]="chat?.isTalkMode && isLoadingText">\n\n <div class="voice-button">\n \x3c!-- 加载时显示spinner,否则显示wifi图标 --\x3e\n <ion-spinner *ngIf="chat?.isTalkMode && isLoadingText" name="lines" class="loading-spinner"></ion-spinner>\n <ion-icon *ngIf="!(chat?.isTalkMode && isLoadingText)" name="wifi-outline"\n [style.transform]="message?.role==\'user\'?\'rotate(-90deg)\':\'rotate(90deg)\'"\n class="audio-icon" \n [class.play-voice-playing]="tts?.isPlaying"></ion-icon>\n </div>\n <div class="voice-info">\n <span *ngIf="message?.voice?.duration && !isLoadingText">\n {{((message?.voice?.duration||0)/1000) | durationStr}}\n </span>\n </div>\n </div>\n \x3c!-- 头像区域 --\x3e \n <img class="avatar" *ngIf="message?.role!=\'user\'" [src]="(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/100/h/100\'" >\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="item-row images" *ngIf="message?.content | chatContent:\'image_url\'">\n <img [src]="message?.content | chatContent:\'image_url\'" alt="">\n </div>\n \x3c!-- 聊天气泡 --\x3e\n \x3c!-- Replace the bubble section with this: --\x3e\n <div class="item-row bubble" [style.fontSize]="role?.get(\'uiConfig\')?.message?.bubble?.fontSize || \'0.8rem\'">\n \x3c!-- 说话模式:展示加载状态 Show loading state for talk mode when message is not complete --\x3e\n \n \x3c!-- Show normal content for non-talk mode or when loading is complete --\x3e\n <ng-container *ngIf="!chat?.isTalkMode || message?.role !== \'assistant\' || !isLoadingText">\n <fm-markdown-preview *ngIf="!message?.complete" class="content-style" \n [content]="message?.content | chatContent" [render]="false"></fm-markdown-preview>\n <fm-markdown-preview *ngIf="message?.complete" \n [content]="message?.content | chatContent"></fm-markdown-preview>\n </ng-container>\n </div>\n \x3c!-- 时间显示 --\x3e\n <div class="item-row loading" *ngIf="message?.role!=\'system\' && !message?.complete">\n 正在输入<ion-spinner name="dots"></ion-spinner>\n </div>\n\n <div class="item-row created" *ngIf="message?.createdAt">\n <span>{{message?.createdAt | date:"dd/MM/yy HH:mm"}}</span>\n </div>\n</div>',styles:['@charset "UTF-8";:host-context(body.dark) .message-card .actions .item-native{background:none!important}:host-context(body.dark) .message-card .bubble{color:#0e101d}:host-context(body.dark) .message-card .bubble .content-style{filter:invert(1)!important}:host-context(body.dark) .message-card .bubble fm-markdown-preview{filter:invert(1)!important}:host-context(body.dark) .message-card .play-voice{background-color:#0e101d}:host-context(body.dark) .message-card .play-voice .voice-info{color:#fff}:host-context(body.dark) .message-card .right .bubble{color:#921f8a!important;background:#921f8a!important}:host-context(body.dark) .message-card .right .play-voice{background:#921f8a!important}:host-context(body.dark) .message-card .created span{color:#fff}@media screen and (max-width: 800px){.message-card:focus .actions{opacity:1!important}}.message-card:hover .actions{opacity:1;transition:opacity .3s ease-in-out}.message-card{display:flex;flex-wrap:wrap;justify-content:start;align-items:flex-start}.message-card .avatar-row{width:300px;height:32px;display:flex;flex-direction:row-reverse;justify-content:start;align-items:center}.message-card .actions{display:flex;opacity:0;padding-left:10px;padding-right:10px}.message-card .item-row{display:flex;flex:100%;justify-content:start;margin-bottom:5px}.message-card .images img{max-width:300px}.message-card .bubble{display:flex;justify-content:center;max-width:100%;padding:.5rem .5rem 0rem;color:#333;flex:none;border-radius:0 1.5em 1.5em/0em 1.5em 1.5em;color:#fff;background-color:currentColor}.message-card .bubble.loading{color:var(--gray-secondary)}.message-card .bubble.loading .content-style{filter:none}.message-card .bubble .content-style{filter:grayscale(1) contrast(999) invert(1)}.message-card .loading{text-align:right;color:#101010}.message-card .created{display:flex}.message-card .created span{font-size:12px;opacity:.4;white-space:nowrap;transition:all .6s ease;color:var(--black);text-align:center;width:100%;box-sizing:border-box;padding-right:10px;pointer-events:none;z-index:1}.right{justify-content:end;align-items:flex-end}.right .avatar-row{flex-direction:row;justify-content:end;width:auto}.right .actions{position:relative;margin-left:0}.right .item-row{justify-content:end}.right .bubble{color:#bbdefb;border-top-left-radius:1.5em;border-top-right-radius:0}.right .play-voice{flex-direction:row-reverse;background-color:#bbdefb}.center{justify-content:center;align-items:center}.center .item-row{justify-content:center}.center .bubble{color:var(--gray-secondary);border-top-left-radius:1.5em;border-top-right-radius:1.5em;font-size:12px;font-weight:100;padding:5px 20px}.play-voice{min-width:100px;height:32px;display:flex;justify-content:space-around;align-items:center;background-color:#fff;border-radius:7px}.play-voice .voice-button{width:32px;height:32px;display:flex;justify-content:center;align-items:center}.play-voice .voice-button span{overflow:hidden;font-size:18px;color:#ff69b4}.play-voice .voice-info{height:32px;display:flex;padding:0 10px;justify-content:end;align-items:center;color:#333}.avatar{border-radius:50%;width:32px;height:32px;object-fit:cover}.audio-icon{color:#ff69b4;font-size:18px}.play-voice-playing{animation:play-voice-animation 1s infinite}@keyframes play-voice-animation{0%{width:0}to{width:32px}}.content-style.loading-text{color:#666;font-style:italic}.play-voice{transition:opacity .3s ease}.play-voice.loading-voice{opacity:.8;cursor:not-allowed}.play-voice.loading-voice .loading-spinner{width:18px;height:18px;color:var(--gray-secondary)}.play-voice.loading-voice .loading-text{font-size:.8em;color:var(--gray-secondary);margin-left:5px}.play-voice .voice-button{display:flex;align-items:center;justify-content:center;width:24px;height:24px}\n']}]}],ctorParameters:()=>[{type:ClipboardService}],propDecorators:{index:[{type:Input}],message:[{type:Input}],role:[{type:Input}],chat:[{type:Input}]}}),addIcons({chevronForward:chevronForward});class CompRolePromptComponent{constructor(e){this.cross=e,this.role="",this.showModal=!1,this.cateIndex=0,this.isDarkMode=!1,this.company="E4KpGvTEto"}ngOnInit(){this.getChatPrompt(),document.body.classList.contains("dark")&&(this.isDarkMode=!0)}applyPrompt(e){this.chat.userInput=e,this.chat.isVoiceInputMode=!1,this.chat.focusUserInput(),"mobile"==this.cross?.navMenuType&&(this.chat.isPromptModalOpen=!1)}async getChatPrompt(){if(this.chat.promptList?.length)return;let e=new Parse.Query("ChatPrompt");e.notEqualTo("isDeleted",!0),e.equalTo("role",this.role),e.include("role");let t=await e.find();t?.length&&(this.chat.promptList=t,this.chat.promptList.forEach((e=>{let t=e.get("role").get("promptCates").filter((t=>t.name==e.get("cate")));e.img=t[0].img})),console.log(this.chat.promptList))}checkCate(e){this.cateIndex=e}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompRolePromptComponent,deps:[{token:CrossService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompRolePromptComponent,isStandalone:!0,selector:"app-comp-role-prompt",inputs:{chat:"chat",role:"role"},providers:[],ngImport:i0,template:'<ng-container *ngIf="chat?.messageList?.length<4 && chat?.isPromptMessageAreaShow && !chat?.userInput">\n \x3c!-- PC端样式 --\x3e\n <div class="prompt" *ngIf="cross?.navMenuType!=\'mobile\'">\n <ng-container *ngFor="let content of chat?.promptList">\n <div class="prompt_cate">\n <div class="cate_info">\n <div>\n <img [src]="content.img" alt="">\n </div>\n <div class="cate_name">\n {{content.get(\'cate\')}}\n </div>\n </div>\n <ng-container *ngFor="let message of content.get(\'messageList\')">\n <div class="message" (click)="applyPrompt(message)">\n {{message}}\n </div>\n </ng-container>\n </div>\n </ng-container>\n </div>\n \x3c!-- 手机端样式 --\x3e\n <ng-container *ngIf="cross?.navMenuType==\'mobile\'">\n <div class="prompt_mobile">\n <ng-container *ngFor="let content of chat?.promptList">\n <div class="prompt_cate">\n <div class="cate_info">\n <div>\n <img [src]="content.img" alt="">\n </div>\n <div class="cate_name">\n {{content.get(\'cate\')}}\n </div>\n </div>\n <ng-container *ngFor="let message of content.get(\'messageList\');let idx = index">\n <div *ngIf="idx<3" class="message" (click)="applyPrompt(message)">\n {{message}}\n </div>\n </ng-container>\n </div>\n </ng-container>\n </div>\n <div class="view_more" *ngIf="chat?.promptList?.length">\n <button (click)="chat.isPromptModalOpen=true" expand="block">查看更多<ion-icon name="chevron-forward"></ion-icon></button>\n </div>\n </ng-container>\n</ng-container>\n\n <ion-modal [isOpen]="chat.isPromptModalOpen" (willDismiss)="chat.isPromptModalOpen=false" [initialBreakpoint]="1" [breakpoints]="[0, 1]">\n <ng-template>\n <div class="block">\n <ion-label>话题灵感</ion-label>\n <div class="block_cate">\n \x3c!-- <ion-segment [(ngModel)]="cateIndex">\n <ng-container *ngFor="let prompt of chat?.promptList;let i = index">\n <ion-segment-button value="i">\n <ion-label>{{prompt?.get("cate")}}</ion-label>\n </ion-segment-button>\n </ng-container>\n </ion-segment> --\x3e\n <ng-container *ngFor="let prompt of chat?.promptList;let i = index">\n <ion-button [color]="i==cateIndex?\'secondary\':\'light\'" (click)="checkCate(i)">{{prompt?.get("cate")}}</ion-button>\n \x3c!-- <div [class]="i==cateIndex?\'active_cate\':\'\'" (click)="checkCate(i)">{{prompt?.get("cate")}}</div> --\x3e\n </ng-container>\n </div>\n <div class="message_mobile">\n <ng-container *ngFor="let message of chat?.promptList[cateIndex]?.get(\'messageList\')">\n <div class="message-box" [style.backgroundColor]="isDarkMode?\'rgba(255,255,255,0.2)\':\'white\'" [style.color]="isDarkMode?\'rgba(255,255,255,0.5)\':\'black\'" (click)="applyPrompt(message)">{{message}}</div>\n </ng-container>\n </div>\n </div>\n </ng-template>\n </ion-modal>',styles:[":host-context(body.dark) .prompt_cate .message{background:#fff3;border:1px solid #333;box-shadow:0 2px 8px #333;color:#ffffff80}:host-context(body.dark) .cate_info{color:#fff}:host-context(body.dark) ion-modal .block h4{color:#fff!important}:host-context(body.dark) ion-modal .block .message-box{color:#ccc!important;background-color:#333!important}:host-context(body.dark) .message-box{color:#ccc!important;background-color:#333!important}.prompt{color:#000;display:flex;justify-content:space-between;align-items:flex-start}.prompt .prompt_cate{flex:1;height:inherit;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-direction:column;display:flex;justify-content:center}.prompt .prompt_cate .cate_info{font-size:1.5em;font-weight:700}.prompt .prompt_cate .cate_info div img{width:58px;height:58px}.prompt .prompt_cate .cate_info .cate_name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.prompt .prompt_cate .message{padding:1em;margin:1em;background:#fff;border:1px solid #eef2f2;border-radius:12px;box-shadow:0 2px 8px #f5f6f8;cursor:pointer;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media screen and (max-width: 390.4px){.prompt .prompt_cate .message{width:100px;height:64px;padding:unset;margin:.8em;background:#fff;border:1px solid #eef2f2;border-radius:12px;box-shadow:0 2px 8px #f5f6f8;cursor:pointer;overflow:hidden;white-space:pre-wrap;text-overflow:ellipsis}}.prompt_mobile{color:#000;display:flex;justify-content:space-between;align-items:flex-start}.prompt_mobile .prompt_cate{flex:1;height:inherit}.prompt_mobile .prompt_cate .cate_info{display:flex;justify-content:center;align-items:center;font-size:1.2em}.prompt_mobile .prompt_cate .cate_info div img{width:48px;height:48px}.prompt_mobile .prompt_cate .cate_info .cate_name{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;overflow:hidden;text-overflow:ellipsis;margin-top:2vw}.prompt_mobile .prompt_cate .message{min-height:48px;padding:0 2vw;margin:4vw 1vw;background:#fff;border:1px solid #eef2f2;border-radius:12px;box-shadow:0 2px 8px #f5f6f8;cursor:pointer;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;text-overflow:ellipsis}.view_more{text-align:center;color:#999;margin:4vw 0}.view_more>button{background-color:transparent}.block{width:100%;height:80vh;padding:2vw}.block .block_cate{display:flex;justify-content:space-evenly}.block .message_mobile{overflow-y:auto;height:65vh;color:#000}.message-box{background-color:#fff;text-align:center;padding:8px 0;margin:8px 0;border-radius:4px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}ion-modal{--height: auto}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"component",type:IonModal,selector:"ion-modal"},{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:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompRolePromptComponent,decorators:[{type:Component,args:[{selector:"app-comp-role-prompt",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,IonModal,IonButton,IonSegment,IonLabel,IonIcon],providers:[],template:'<ng-container *ngIf="chat?.messageList?.length<4 && chat?.isPromptMessageAreaShow && !chat?.userInput">\n \x3c!-- PC端样式 --\x3e\n <div class="prompt" *ngIf="cross?.navMenuType!=\'mobile\'">\n <ng-container *ngFor="let content of chat?.promptList">\n <div class="prompt_cate">\n <div class="cate_info">\n <div>\n <img [src]="content.img" alt="">\n </div>\n <div class="cate_name">\n {{content.get(\'cate\')}}\n </div>\n </div>\n <ng-container *ngFor="let message of content.get(\'messageList\')">\n <div class="message" (click)="applyPrompt(message)">\n {{message}}\n </div>\n </ng-container>\n </div>\n </ng-container>\n </div>\n \x3c!-- 手机端样式 --\x3e\n <ng-container *ngIf="cross?.navMenuType==\'mobile\'">\n <div class="prompt_mobile">\n <ng-container *ngFor="let content of chat?.promptList">\n <div class="prompt_cate">\n <div class="cate_info">\n <div>\n <img [src]="content.img" alt="">\n </div>\n <div class="cate_name">\n {{content.get(\'cate\')}}\n </div>\n </div>\n <ng-container *ngFor="let message of content.get(\'messageList\');let idx = index">\n <div *ngIf="idx<3" class="message" (click)="applyPrompt(message)">\n {{message}}\n </div>\n </ng-container>\n </div>\n </ng-container>\n </div>\n <div class="view_more" *ngIf="chat?.promptList?.length">\n <button (click)="chat.isPromptModalOpen=true" expand="block">查看更多<ion-icon name="chevron-forward"></ion-icon></button>\n </div>\n </ng-container>\n</ng-container>\n\n <ion-modal [isOpen]="chat.isPromptModalOpen" (willDismiss)="chat.isPromptModalOpen=false" [initialBreakpoint]="1" [breakpoints]="[0, 1]">\n <ng-template>\n <div class="block">\n <ion-label>话题灵感</ion-label>\n <div class="block_cate">\n \x3c!-- <ion-segment [(ngModel)]="cateIndex">\n <ng-container *ngFor="let prompt of chat?.promptList;let i = index">\n <ion-segment-button value="i">\n <ion-label>{{prompt?.get("cate")}}</ion-label>\n </ion-segment-button>\n </ng-container>\n </ion-segment> --\x3e\n <ng-container *ngFor="let prompt of chat?.promptList;let i = index">\n <ion-button [color]="i==cateIndex?\'secondary\':\'light\'" (click)="checkCate(i)">{{prompt?.get("cate")}}</ion-button>\n \x3c!-- <div [class]="i==cateIndex?\'active_cate\':\'\'" (click)="checkCate(i)">{{prompt?.get("cate")}}</div> --\x3e\n </ng-container>\n </div>\n <div class="message_mobile">\n <ng-container *ngFor="let message of chat?.promptList[cateIndex]?.get(\'messageList\')">\n <div class="message-box" [style.backgroundColor]="isDarkMode?\'rgba(255,255,255,0.2)\':\'white\'" [style.color]="isDarkMode?\'rgba(255,255,255,0.5)\':\'black\'" (click)="applyPrompt(message)">{{message}}</div>\n </ng-container>\n </div>\n </div>\n </ng-template>\n </ion-modal>',styles:[":host-context(body.dark) .prompt_cate .message{background:#fff3;border:1px solid #333;box-shadow:0 2px 8px #333;color:#ffffff80}:host-context(body.dark) .cate_info{color:#fff}:host-context(body.dark) ion-modal .block h4{color:#fff!important}:host-context(body.dark) ion-modal .block .message-box{color:#ccc!important;background-color:#333!important}:host-context(body.dark) .message-box{color:#ccc!important;background-color:#333!important}.prompt{color:#000;display:flex;justify-content:space-between;align-items:flex-start}.prompt .prompt_cate{flex:1;height:inherit;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-direction:column;display:flex;justify-content:center}.prompt .prompt_cate .cate_info{font-size:1.5em;font-weight:700}.prompt .prompt_cate .cate_info div img{width:58px;height:58px}.prompt .prompt_cate .cate_info .cate_name{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.prompt .prompt_cate .message{padding:1em;margin:1em;background:#fff;border:1px solid #eef2f2;border-radius:12px;box-shadow:0 2px 8px #f5f6f8;cursor:pointer;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media screen and (max-width: 390.4px){.prompt .prompt_cate .message{width:100px;height:64px;padding:unset;margin:.8em;background:#fff;border:1px solid #eef2f2;border-radius:12px;box-shadow:0 2px 8px #f5f6f8;cursor:pointer;overflow:hidden;white-space:pre-wrap;text-overflow:ellipsis}}.prompt_mobile{color:#000;display:flex;justify-content:space-between;align-items:flex-start}.prompt_mobile .prompt_cate{flex:1;height:inherit}.prompt_mobile .prompt_cate .cate_info{display:flex;justify-content:center;align-items:center;font-size:1.2em}.prompt_mobile .prompt_cate .cate_info div img{width:48px;height:48px}.prompt_mobile .prompt_cate .cate_info .cate_name{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;overflow:hidden;text-overflow:ellipsis;margin-top:2vw}.prompt_mobile .prompt_cate .message{min-height:48px;padding:0 2vw;margin:4vw 1vw;background:#fff;border:1px solid #eef2f2;border-radius:12px;box-shadow:0 2px 8px #f5f6f8;cursor:pointer;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;text-overflow:ellipsis}.view_more{text-align:center;color:#999;margin:4vw 0}.view_more>button{background-color:transparent}.block{width:100%;height:80vh;padding:2vw}.block .block_cate{display:flex;justify-content:space-evenly}.block .message_mobile{overflow-y:auto;height:65vh;color:#000}.message-box{background-color:#fff;text-align:center;padding:8px 0;margin:8px 0;border-radius:4px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}ion-modal{--height: auto}\n"]}]}],ctorParameters:()=>[{type:CrossService}],propDecorators:{chat:[{type:Input}],role:[{type:Input}]}});class FmChatMesssageArea{get messageList(){return this.chatServ.chatMap[this.chatId]?.messageList}constructor(e){this.chatServ=e}ngDoCheck(){}ngAfterViewInit(){console.log("ng gogogo1"),console.log("ng gogogo2"),console.log(this.chat)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatMesssageArea,deps:[{token:ChatService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:FmChatMesssageArea,isStandalone:!0,selector:"fm-chat-message-area",inputs:{chatId:"chatId",chat:"chat"},ngImport:i0,template:'\n<div class="message-list">\n <app-comp-role-prompt [chat]="chat" [role]="chat?.role?.id"></app-comp-role-prompt>\n <ng-container *ngFor="let message of chat?.messageList;let index=index;">\n \x3c!-- 内容格式化区域 --\x3e\n <fm-chat-message-card [chat]="chat" *ngIf="!message?.hidden" [index]="index" [message]="message" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n\n @if(!chat?.hideInputPreview){\n \x3c!-- 预览无图消息 --\x3e\n <ng-container *ngIf="chat?.userInput&&!chat?.userImage">\n <fm-chat-message-card [chat]="chat" [message]="{role:\'user\',content:chat?.userInput}" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n \n \x3c!-- 预览有图消息 --\x3e\n <ng-container *ngIf="chat?.userImage">\n <fm-chat-message-card [chat]="chat" [message]="{role:\'user\',content:[{type:\'text\',text:chat?.userInput},{type:\'image_url\',image_url:{url:chat?.userImage}}]}" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n }\n</div>',styles:[".message-list{padding:5px 20px}:host-context(body.dark) .message-list{background-color:#000!important}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:FmChatMessageCard,selector:"fm-chat-message-card",inputs:["index","message","role","chat"]},{kind:"component",type:CompRolePromptComponent,selector:"app-comp-role-prompt",inputs:["chat","role"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmChatMesssageArea,decorators:[{type:Component,args:[{selector:"fm-chat-message-area",standalone:!0,imports:[CommonModule,FmChatMessageCard,CompRolePromptComponent],template:'\n<div class="message-list">\n <app-comp-role-prompt [chat]="chat" [role]="chat?.role?.id"></app-comp-role-prompt>\n <ng-container *ngFor="let message of chat?.messageList;let index=index;">\n \x3c!-- 内容格式化区域 --\x3e\n <fm-chat-message-card [chat]="chat" *ngIf="!message?.hidden" [index]="index" [message]="message" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n\n @if(!chat?.hideInputPreview){\n \x3c!-- 预览无图消息 --\x3e\n <ng-container *ngIf="chat?.userInput&&!chat?.userImage">\n <fm-chat-message-card [chat]="chat" [message]="{role:\'user\',content:chat?.userInput}" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n \n \x3c!-- 预览有图消息 --\x3e\n <ng-container *ngIf="chat?.userImage">\n <fm-chat-message-card [chat]="chat" [message]="{role:\'user\',content:[{type:\'text\',text:chat?.userInput},{type:\'image_url\',image_url:{url:chat?.userImage}}]}" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n }\n</div>',styles:[".message-list{padding:5px 20px}:host-context(body.dark) .message-list{background-color:#000!important}\n"]}]}],ctorParameters:()=>[{type:ChatService}],propDecorators:{chatId:[{type:Input}],chat:[{type:Input}]}});class ModalAudioMessageComponent{constructor(e,t,n,o){this.toastCtrl=e,this.uploadServ=t,this.platform=n,this.diagnostic=o,this.isRecording=!1,this.player=new Audio,this.durationStr="0:00",this.voiceServ=new FmodeVoiceService(this.platform,this.diagnostic)}ngOnInit(){this.chat.userInput="",this.initVoiceSevice(),this.voiceServ.startTalk()}playMusic(e){this.player||(this.player=new Audio),this.player.src=`/assets/avatar/voice/${e}.mp3`;try{this.player?.play()}catch(e){}}initVoiceSevice(){this.chat.userInput=this.voiceServ.resultText,this.voiceServ.requestPermission().then((()=>{this.voiceServ.openWithPriviledge()})),this.voiceServ.onBeforeStartTalk=()=>{this.chat.playAnimation("listening"),this.playMusic("start-talk")},this.voiceServ.onAfterRecordStart=()=>{this.isRecording=!0},this.voiceServ.onDurationStrChange=e=>{this.durationStr=e},this.voiceServ.onBeforeCancelTalk=()=>{this.playMusic("interupt-talk"),this.chat.playAnimation("waiting")},this.voiceServ.onAfterCancelTalk=()=>{},this.voiceServ.onBeforeFinishTalk=()=>{this.chat.playAnimation("thinking"),this.playMusic("stop-talk")},this.voiceServ.onAfterFinishTalk=async()=>{console.log("onAfterFinishTalk1",this.voiceServ?.resultText),console.log("onAfterFinishTalk2",this.voiceServ?.resultTextTemp),this.chat.userInput=""+(this.voiceServ?.resultTextTemp||this.voiceServ?.resultText),this.chat?.userInput&&await this.saveChatVoice(),this.sendMessage()}}async saveChatVoice(){let e=this.voiceServ.recordWavBlob,t=this.voiceServ.recordDuration;if(e){let n=Parse__default.Object.extend("ChatVoice");this.chatVoice=new n,this.chatVoice.set("content",this.chat.userInput),this.chatVoice.set("role","user"),this.chatVoice.set("duration",t);let o=localStorage.getItem("company");o&&this.chatVoice.set("company",{__type:"Pointer",className:"Company",objectId:o}),Parse__default.User.current()?.id&&this.chatVoice.set("user",Parse__default.User.current().toPointer());let i=this.chatVoice?.id||this.uploadServ?.genMd5(this.chatVoice?.get("content")||this.chatVoice?.get("ssml")),a=new Date,r=i+a.getFullYear()+(a.getMonth()+1)+a.getDate()+a.getHours()+a.getMinutes()+a.getSeconds()+".wav",s=new File([e],r,{type:"audio/wav"}),l=await this.uploadServ.upload(s,(e=>{console.log(e)})),c={__type:"Pointer",className:"Attachment",objectId:l?.id};c?.objectId&&(this.chatVoice.set("voiceFile",c),this.chatVoice=await this.chatVoice.save())}}async sendMessage(){if(this.chat.userInput)this.chat?.sendMessage(""+this.chat?.userInput,this.chat?.userImage,(e=>{}),{onSSMLComplete:e=>{console.log(e)}},{id:this.chatVoice?.id,duration:this.chatVoice?.get("duration")});else{(await this.toastCtrl.create({message:"内容不能为空",position:"top",icon:"alert",color:"warning-circle",duration:1e3})).present()}}cancel(){this.clear(),this.voiceServ.cancelTalk(),this.modal?.dismiss(null,"cancel")}send(){this.clear(),this.voiceServ.finishTalk(),this.modal?.dismiss(null,"send")}clear(){this.now=void 0,this.isRecording=!1}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalAudioMessageComponent,deps:[{token:i1$3.ToastController},{token:NovaUploadService},{token:i1$3.Platform},{token:i5.Diagnostic}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ModalAudioMessageComponent,isStandalone:!0,selector:"fm-modal-audio-message",inputs:{chat:"chat",modal:"modal"},providers:[ModalController$1],ngImport:i0,template:'\x3c!-- <div style="background:#FFFFFF;color:#000000;width:100%">\n {{this.chat.userInput}}\n</div> --\x3e\n<div class="modal-area">\n\n \x3c!-- 加载WebSockets动画 --\x3e\n <ng-container *ngIf="!isRecording">\n <div class="row">\n <ion-spinner name="crescent" color="success" style="width:80px;height:80px;"></ion-spinner>\n </div>\n </ng-container>\n \x3c!-- 录音中动画 --\x3e\n <ng-container *ngIf="isRecording">\n <div class="actions row">\n \x3c!-- 取消 --\x3e\n <ion-button (click)="cancel()" size="large" shape="round" color="light">\n <ion-icon name="close-outline"></ion-icon>\n </ion-button>\n \x3c!-- 音频 --\x3e\n <div class="audio-input">\n <div class="timer row">\n {{durationStr || "00:00"}}\n </div>\n <div class="audio-wave row">\n <div class="audio">\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n </div>\n </div>\n </div>\n \x3c!-- 发送 --\x3e\n <ion-button (click)="send()" size="large" shape="round" color="success">\n <ion-icon name="send-outline"></ion-icon>\n </ion-button>\n </div>\n \n <div class="tips row">\n 请您讲话,AI会识别!\n </div>\n </ng-container>\n</div>',styles:[":host-context(body.dark) .modal-area{color:#fff}.modal-area{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;padding-top:15px}.modal-area .row{margin:10px}.modal-area .tips{padding-top:5px}.modal-area .timer{font-size:1.5rem;font-weight:700}.modal-area .actions{display:flex;justify-content:space-around;width:100%;height:86px}.audio-input{display:flex;flex-direction:column;justify-content:center;align-items:center}.audio{display:flex;justify-content:space-between;align-items:center;gap:8px;width:60px;height:40px}.audio .wave{height:40px;display:block;width:10px;height:6px;border-radius:8px;background:orange}.audio .wave{animation:audio-wave 2s ease-in-out infinite}.audio .wave:nth-child(1){animation-delay:.1s}.audio .wave:nth-child(2){animation-delay:.2s}.audio .wave:nth-child(3){animation-delay:.3s}.audio .wave:nth-child(4){animation-delay:.4s}.audio .wave:nth-child(5){animation-delay:.5s}@keyframes audio-wave{0%{height:6px;transform:translateY(0);background:#ff8e3a}25%{height:6px;transform:translateY(0);background:#9c73f8}50%{height:30px;transform:translateY(-5px) scaleY(1.5);background:#ed509e}75%{height:6px;transform:translateY(0);background:#9c73f8}to{height:6px;transform:translateY(0);background:#0fccce}}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{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:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonSpinner,selector:"ion-spinner",inputs:["color","duration","name","paused"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalAudioMessageComponent,decorators:[{type:Component,args:[{selector:"fm-modal-audio-message",standalone:!0,imports:[CommonModule,IonButton,IonIcon,IonSpinner],providers:[ModalController$1],template:'\x3c!-- <div style="background:#FFFFFF;color:#000000;width:100%">\n {{this.chat.userInput}}\n</div> --\x3e\n<div class="modal-area">\n\n \x3c!-- 加载WebSockets动画 --\x3e\n <ng-container *ngIf="!isRecording">\n <div class="row">\n <ion-spinner name="crescent" color="success" style="width:80px;height:80px;"></ion-spinner>\n </div>\n </ng-container>\n \x3c!-- 录音中动画 --\x3e\n <ng-container *ngIf="isRecording">\n <div class="actions row">\n \x3c!-- 取消 --\x3e\n <ion-button (click)="cancel()" size="large" shape="round" color="light">\n <ion-icon name="close-outline"></ion-icon>\n </ion-button>\n \x3c!-- 音频 --\x3e\n <div class="audio-input">\n <div class="timer row">\n {{durationStr || "00:00"}}\n </div>\n <div class="audio-wave row">\n <div class="audio">\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n </div>\n </div>\n </div>\n \x3c!-- 发送 --\x3e\n <ion-button (click)="send()" size="large" shape="round" color="success">\n <ion-icon name="send-outline"></ion-icon>\n </ion-button>\n </div>\n \n <div class="tips row">\n 请您讲话,AI会识别!\n </div>\n </ng-container>\n</div>',styles:[":host-context(body.dark) .modal-area{color:#fff}.modal-area{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;padding-top:15px}.modal-area .row{margin:10px}.modal-area .tips{padding-top:5px}.modal-area .timer{font-size:1.5rem;font-weight:700}.modal-area .actions{display:flex;justify-content:space-around;width:100%;height:86px}.audio-input{display:flex;flex-direction:column;justify-content:center;align-items:center}.audio{display:flex;justify-content:space-between;align-items:center;gap:8px;width:60px;height:40px}.audio .wave{height:40px;display:block;width:10px;height:6px;border-radius:8px;background:orange}.audio .wave{animation:audio-wave 2s ease-in-out infinite}.audio .wave:nth-child(1){animation-delay:.1s}.audio .wave:nth-child(2){animation-delay:.2s}.audio .wave:nth-child(3){animation-delay:.3s}.audio .wave:nth-child(4){animation-delay:.4s}.audio .wave:nth-child(5){animation-delay:.5s}@keyframes audio-wave{0%{height:6px;transform:translateY(0);background:#ff8e3a}25%{height:6px;transform:translateY(0);background:#9c73f8}50%{height:30px;transform:translateY(-5px) scaleY(1.5);background:#ed509e}75%{height:6px;transform:translateY(0);background:#9c73f8}to{height:6px;transform:translateY(0);background:#0fccce}}\n"]}]}],ctorParameters:()=>[{type:i1$3.ToastController},{type:NovaUploadService},{type:i1$3.Platform},{type:i5.Diagnostic}],propDecorators:{chat:[{type:Input}],modal:[{type:Input}]}}),addIcons({colorWandOutline:colorWandOutline,peopleOutline:peopleOutline,alertOutline:alertOutline,imageOutline:imageOutline,chevronBackOutline:chevronBackOutline,ellipsisHorizontalOutline:ellipsisHorizontalOutline,chevronDownOutline:chevronDownOutline,chatboxEllipsesOutline:chatboxEllipsesOutline,micOutline:micOutline,paperPlaneOutline:paperPlaneOutline,shareSocialOutline:shareSocialOutline,settingsOutline:settingsOutline});class FmChatModalInput{closeAudio(){this.audioComp?.cancel(),this.isAudioModal=!1}async startTalk(){if(this.isSending)return!1;let e,t=document.body.clientHeight||960;this.audioModalHeightPoint=Number((165/t).toFixed(2)),this.chat.stopPlayingVoice(),e=await this.modalCtrl.create({component:ModalAudioMessageComponent,componentProps:{chat:this.chat,modal:e,onBreakPointSet:()=>{e?.setCurrentBreakpoint(this.audioModalHeightPoint)}},breakpoints:[this.audioModalHeightPoint],initialBreakpoint:this.audioModalHeightPoint}),e.present()}constructor(e,t,n,o,i,a,r){this.toastCtrl=e,this.alertCtrl=t,this.modalCtrl=n,this.router=o,this.imagineServ=i,this.chatServ=a,this.account=r,this.errorText="",this.isAudioModal=!1,this.audioModalHeightPoint=.35,this.isSending=!1,this.lastMessageTimestamp=0,this.replyTimeout=15e3,this.isShare=!1,this.user=Parse__default.User.current()}ngOnInit(){this.loadModel();let e=this;this.chat.focusUserInput=()=>{e.chat.isVoiceInputMode=!1,e.userInputComp.setFocus()}}async loadModel(){let e=this.chat?.role?.get("model");await this.chat.loadModelList(e)}async setMessageImage(){let e=await this.imagineServ.getimg();this.chat.userImage=e,console.log(this.chat?.userImage)}onInputFocus(){this.chat.isTexting=!0,this.chat.scrollToBottom&&this.chat.scrollToBottom()}onKeyDown(e){e.ctrlKey&&"Enter"===e.key&&(console.log("Ctrl+Enter 被按下"),this.sendMessage())}async sendMessage(){if(this.isSending)return!1;const e=Date.now();if(this.lastMessageTimestamp>0&&e-this.lastMessageTimestamp<this.replyTimeout){return this.errorText="请等待上一条消息的回复或稍后再试",(await this.toastCtrl.create({message:this.errorText,position:"top",icon:"alert",color:"warning",duration:1e3})).present(),!1}if(this.isSending=!0,this.lastMessageTimestamp=Date.now(),!await this.checkBalance())return this.isSending=!1,!1;if(!this.chat.userInput){return this.errorText="内容不能为空",(await this.toastCtrl.create({message:this.errorText,position:"top",icon:"alert",color:"warning-circle",duration:1e3})).present(),void(this.isSending=!1)}this.lastMessageTimeout&&clearTimeout(this.lastMessageTimeout),this.lastMessageTimeout=setTimeout((()=>{this.isSending=!1,this.lastMessageTimestamp=0}),this.replyTimeout),this.chat?.sendMessage(this.chat?.userInput,this.chat?.userImage,(e=>{}),{onMessageStart:e=>{clearTimeout(this.lastMessageTimeout),this.isSending=!1,this.lastMessageTimestamp=0},onSSMLComplete:e=>{console.log(e)}}),this.chat.userInput="",this.chat.userImage=""}async checkBalance(){let e=await this.account.getBilling();if(e?.credit?.balance>=10&&(this.chat.isDirect=!0),!this.chat?.currentModel?.get("payLimit"))return!0;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__default.User.current();let e=new Parse__default.Query("ChatShare");e.equalTo("user",Parse__default.User.current().id),e.equalTo("session",this.chat?.sessionId);await e.first()}async toggleChatShare(){let e=new Parse__default.Query("ChatShare");e.equalTo("user",Parse__default.User.current().id),e.equalTo("role",this.chat?.role.id),e.equalTo("session",this.chat?.sessionId),e.select("objectId");let t=await e.first();if(t?.id)t.set("messageList",this.chat?.messageList);else{t=new(Parse__default.Object.extend("ChatShare")),t.set("user",{__type:"Pointer",className:"_User",objectId:Parse__default.User.current()?.id}),t.set("session",{__type:"Pointer",className:"ChatSession",objectId:this.chat?.sessionId}),t.set("role",{__type:"Pointer",className:"AvatarRole",objectId:this.chat?.role.id}),t.set("company",{__type:"Pointer",className:"Company",objectId:"E4KpGvTEto"}),t.set("messageList",this.chat?.messageList)}await t.save(),this.getChatShare()}async chatShareSuccessMessage(){(await this.toastCtrl.create({duration:1e3,message:"分享成功",color:"primary",icon:"information-circle",position:"top"})).present()}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:i3.ToastController},{token:i3.AlertController},{token:i1$3.ModalController},{token:i1$1.Router},{token:ImagineService},{token:ChatService},{token:AccountService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.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},{propertyName:"userInputComp",first:!0,predicate:["userInput"],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 @if(!chat?.hideShare){\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 }\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 <ng-container *ngFor="let message of chat?.messageList;let index=index;">\n \x3c!-- 内容格式化区域 --\x3e\n <fm-chat-message-card [chat]="chat" *ngIf="!message?.hidden" [index]="index" [message]="message" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n\n <div *ngIf="false" 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 <img class="avatar" *ngIf="message?.role!=\'user\'" [src]="(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\'" >\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 \x3c!-- 图片 --\x3e\n <ion-button shape="round" *ngIf="chat?.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 @if(!chat?.hideModalSelect){\n <ion-button shape="round" fill="outline" slot="end" id="model-button">\n <ion-icon name="chevron-down-outline"></ion-icon>\n {{chat?.currentModel?.get&&chat?.currentModel?.get("name")||"Fmode-C1.0-128k"}}\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 chat.modelList">\n <ion-item (click)="chat.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\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)="startTalk()" [class.disabled]="isSending">\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\n #userInput\n *ngIf="chat" (keydown)="onKeyDown($event)"\n [errorText]="errorText"\n [(ngModel)]="chat.userInput"\n (ionFocus)="onInputFocus()"\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 [disabled]="isSending"\n 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\x3c!-- <ion-modal #audioModal [isOpen]="isAudioModal" (willDismiss)="closeAudio()" [initialBreakpoint]="audioModalHeightPoint" [breakpoints]="[0, audioModalHeightPoint]">\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> --\x3e',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}.disabled{opacity:.5;pointer-events:none}.avatar{border-radius:50%;width:32px;height:32px;object-fit:cover}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:i2.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"pipe",type:i2.DatePipe,name:"date"},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.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:"component",type:FmChatMessageCard,selector:"fm-chat-message-card",inputs:["index","message","role","chat"]}]})}}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,FmChatMessageCard,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 @if(!chat?.hideShare){\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 }\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 <ng-container *ngFor="let message of chat?.messageList;let index=index;">\n \x3c!-- 内容格式化区域 --\x3e\n <fm-chat-message-card [chat]="chat" *ngIf="!message?.hidden" [index]="index" [message]="message" [role]="chat?.role"></fm-chat-message-card>\n </ng-container>\n\n <div *ngIf="false" 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 <img class="avatar" *ngIf="message?.role!=\'user\'" [src]="(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\'" >\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 \x3c!-- 图片 --\x3e\n <ion-button shape="round" *ngIf="chat?.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 @if(!chat?.hideModalSelect){\n <ion-button shape="round" fill="outline" slot="end" id="model-button">\n <ion-icon name="chevron-down-outline"></ion-icon>\n {{chat?.currentModel?.get&&chat?.currentModel?.get("name")||"Fmode-C1.0-128k"}}\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 chat.modelList">\n <ion-item (click)="chat.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\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)="startTalk()" [class.disabled]="isSending">\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\n #userInput\n *ngIf="chat" (keydown)="onKeyDown($event)"\n [errorText]="errorText"\n [(ngModel)]="chat.userInput"\n (ionFocus)="onInputFocus()"\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 [disabled]="isSending"\n 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\x3c!-- <ion-modal #audioModal [isOpen]="isAudioModal" (willDismiss)="closeAudio()" [initialBreakpoint]="audioModalHeightPoint" [breakpoints]="[0, audioModalHeightPoint]">\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> --\x3e',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}.disabled{opacity:.5;pointer-events:none}.avatar{border-radius:50%;width:32px;height:32px;object-fit:cover}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:i3.ToastController},{type:i3.AlertController},{type:i1$3.ModalController},{type:i1$1.Router},{type:ImagineService},{type:ChatService},{type:AccountService}],propDecorators:{audioComp:[{type:ViewChild,args:[ModalAudioMessageComponent]}],userInputComp:[{type:ViewChild,args:["userInput"]}],chat:[{type:Input}],message:[{type:Input}],role:[{type:Input}]}});class ChatPanelComponent{constructor(e,t,n){this.route=e,this.router=t,this.chatServ=n,this.mode="page",this.isDirect=!1,this.showInputModal=!0,this.showMessageArea=!0,this.showHeaderArea=!0,this.hideShare=!1,this.hideModalSelect=!1,this.hideInputPreview=!1,window.location.pathname?.indexOf("chat/session")>-1&&document.body.classList.add("dark")}listenDivChange(){let e=new MutationObserver((()=>{this.fmodeChat.scrollComp=this.contentComp})),t={childList:!0,subtree:!0,attributes:!0};this.contentComp?.nativeElement&&e.observe(this.contentComp?.nativeElement,t)}ngAfterViewInit(){}ngOnInit(){"modal"==this.mode&&this.initChat(),"page"==this.mode&&combineLatest([this.route.params,this.route.queryParams]).subscribe((async e=>{this.initChat(e)}))}async initChat(e){console.log("ChatComp OnInit");let t=e?.[0];if(this.chatId=t?.chatId||this.chatId||null,this.chatId&&await this.chatServ.initChatMap(this.chatId),this.roleId=t?.roleId||this.roleId||"2DXJkRsjXK",this.roleId){let e=await this.chatServ.createNewRoleChat(this.roleId);this.fmodeChat=e}this.chatId&&(this.fmodeChat=this.chatServ.chatMap[this.chatId],this.fmodeChat||this.router.navigate(["/chat/pro/mask"],{queryParams:{type:"employee"}}),this.fmodeChat=this.chatServ.chatMap[this.chatId]),this.leftButtons&&(this.fmodeChat.leftButtons=this.leftButtons),window.location.pathname?.indexOf("chat/session")>-1?this.fmodeChat.isVoiceInputMode=!0:this.fmodeChat.isVoiceInputMode=!1,this.modelList&&(this.fmodeChat.modelList=this.modelList,this.fmodeChat.currentModel=this.modelList[0]),this.isDirect&&(this.fmodeChat.isDirect=this.isDirect),this.hideShare&&(this.fmodeChat.hideShare=this.hideShare),this.hideModalSelect&&(this.fmodeChat.hideModalSelect=this.hideModalSelect),this.hideInputPreview&&(this.fmodeChat.hideInputPreview=this.hideInputPreview),this.fmodeChat.mode=this.mode,this.fmodeChat.onChatSaved=this.onChatSaved,this.fmodeChat.onMessage=this.onMessage,this.fmodeChat.onUserSend=this.onUserSend,this.fmodeChat.onClose=this.onClose,this.onChatInit&&this.onChatInit(this.fmodeChat),setTimeout((()=>{this.fmodeChat.scrollComp=this.contentComp,this.listenDivChange()}),1e3),this.sayWelcome()}sayWelcome(){this.fmodeChat.voiceConfig?.welcome?.enabled&&this.fmodeChat.welcome()}loadMask(){}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatPanelComponent,deps:[{token:i1$1.ActivatedRoute},{token:i1$1.Router},{token:ChatService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ChatPanelComponent,isStandalone:!0,selector:"app-chat-panel",inputs:{goBack:"goBack",onChatSaved:"onChatSaved",onChatInit:"onChatInit",onMessage:"onMessage",onUserSend:"onUserSend",onClose:"onClose",mode:"mode",chatId:"chatId",maskId:"maskId",roleId:"roleId",leftButtons:"leftButtons",modelList:"modelList",isDirect:"isDirect",showInputModal:"showInputModal",showMessageArea:"showMessageArea",showHeaderArea:"showHeaderArea",hideShare:"hideShare",hideModalSelect:"hideModalSelect",hideInputPreview:"hideInputPreview"},providers:[ModalController$1],viewQueries:[{propertyName:"headerArea",first:!0,predicate:FmChatHeaderArea,descendants:!0},{propertyName:"contentComp",first:!0,predicate:["contentComp"],descendants:!0}],ngImport:i0,template:'\n\x3c!-- <ion-header></ion-header> --\x3e\n\x3c!-- <ion-content class="ion-padding"> --\x3e\n <div class="chat-page" *ngIf="fmodeChat">\n <div class="header" [class.avatarHeader]="fmodeChat?.isAvatarShow">\n <ng-content select="[chat-header]"></ng-content>\n <fm-chat-header-area [goBack]="goBack" *ngIf="showHeaderArea" [chat]="fmodeChat"></fm-chat-header-area>\n </div>\n \n <div class="content" #contentComp>\n <ng-content select="[chat-content]"></ng-content>\n <fm-chat-message-area *ngIf="showMessageArea" [chat]="fmodeChat"></fm-chat-message-area>\n </div>\n \n <div class="footer">\n <ng-content select="[chat-footer]"></ng-content>\n <fm-chat-modal-input *ngIf="showInputModal" [chat]="fmodeChat"></fm-chat-modal-input>\n </div>\n </div>\n\n\x3c!-- </ion-content> --\x3e',styles:[".chat-page{display:flex;flex-direction:column;height:100%;background:#f3f3f3}.chat-page .content,.chat-page .header,.chat-page .footer{justify-content:center;align-items:center}.chat-page .content{flex-grow:1;flex:1;overflow-y:auto}.chat-page .avatarHeader{height:35vh!important;overflow:hidden}.chat-page .header{height:44px;margin-bottom:-1px}.chat-page .footer{height:auto;min-height:130px}:host-context(body.dark) .chat-page{background:#000}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:FmChatHeaderArea,selector:"fm-chat-header-area",inputs:["chat","goBack"]},{kind:"component",type:FmChatMesssageArea,selector:"fm-chat-message-area",inputs:["chatId","chat"]},{kind:"component",type:FmChatModalInput,selector:"fm-chat-modal-input",inputs:["chat","message","role"]}]})}}async function openChatPanelModal(e,t){let n=await e.create({component:ChatPanelComponent,componentProps:{roleId:t.roleId,chatId:t.chatId,leftButtons:t.leftButtons,modelList:t.modelList,isDirect:t.isDirect,hideModalSelect:t.hideModalSelect,hideShare:t.hideShare,hideInputPreview:t.hideInputPreview,mode:"modal",onChatInit:t?.onChatInit,onChatSaved:t?.onChatSaved,onMessage:t?.onMessage,onUserSend:t?.onUserSend,onClose:t?.onClose,goBack:()=>{e.dismiss()}},cssClass:"modal-chat-panel",backdropDismiss:!1,keyboardClose:!1});return await n.present(),n}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatPanelComponent,decorators:[{type:Component,args:[{selector:"app-chat-panel",standalone:!0,providers:[ModalController$1],imports:[CommonModule,FmChatHeaderArea,FmChatMesssageArea,FmChatModalInput],template:'\n\x3c!-- <ion-header></ion-header> --\x3e\n\x3c!-- <ion-content class="ion-padding"> --\x3e\n <div class="chat-page" *ngIf="fmodeChat">\n <div class="header" [class.avatarHeader]="fmodeChat?.isAvatarShow">\n <ng-content select="[chat-header]"></ng-content>\n <fm-chat-header-area [goBack]="goBack" *ngIf="showHeaderArea" [chat]="fmodeChat"></fm-chat-header-area>\n </div>\n \n <div class="content" #contentComp>\n <ng-content select="[chat-content]"></ng-content>\n <fm-chat-message-area *ngIf="showMessageArea" [chat]="fmodeChat"></fm-chat-message-area>\n </div>\n \n <div class="footer">\n <ng-content select="[chat-footer]"></ng-content>\n <fm-chat-modal-input *ngIf="showInputModal" [chat]="fmodeChat"></fm-chat-modal-input>\n </div>\n </div>\n\n\x3c!-- </ion-content> --\x3e',styles:[".chat-page{display:flex;flex-direction:column;height:100%;background:#f3f3f3}.chat-page .content,.chat-page .header,.chat-page .footer{justify-content:center;align-items:center}.chat-page .content{flex-grow:1;flex:1;overflow-y:auto}.chat-page .avatarHeader{height:35vh!important;overflow:hidden}.chat-page .header{height:44px;margin-bottom:-1px}.chat-page .footer{height:auto;min-height:130px}:host-context(body.dark) .chat-page{background:#000}\n"]}]}],ctorParameters:()=>[{type:i1$1.ActivatedRoute},{type:i1$1.Router},{type:ChatService}],propDecorators:{headerArea:[{type:ViewChild,args:[FmChatHeaderArea]}],goBack:[{type:Input}],onChatSaved:[{type:Input}],onChatInit:[{type:Input}],onMessage:[{type:Input}],onUserSend:[{type:Input}],onClose:[{type:Input}],mode:[{type:Input}],chatId:[{type:Input}],maskId:[{type:Input}],roleId:[{type:Input}],leftButtons:[{type:Input}],modelList:[{type:Input}],isDirect:[{type:Input}],showInputModal:[{type:Input}],showMessageArea:[{type:Input}],showHeaderArea:[{type:Input}],hideShare:[{type:Input}],hideModalSelect:[{type:Input}],hideInputPreview:[{type:Input}],contentComp:[{type:ViewChild,args:["contentComp"]}]}});class ChatListComponent{constructor(e,t,n,o){this.chatServ=e,this.alertCtrl=t,this.navCtrl=n,this.modalCtrl=o,this.chatList=[],this.onItemClick=(e,t)=>{t.stopPropagation(),this.goSession(e)},this.avatar="https://ionicframework.com/docs/img/demos/avatar.svg",this.isPreventGo=!1,this.chatServ.getChatSession().then((()=>{}))}async goSession(e){if(!this.isPreventGo)if(e?.rid||e?.sid){if(document.body.clientWidth<700){let t={roleId:e?.rid,chatId:e?.sid};return console.log("openChatPanelModal"),void openChatPanelModal(this.modalCtrl,t)}this.chatServ.restoreChatPanel(e)}else{(await this.alertCtrl.create({header:"注意",subHeader:"请您选择右侧角色",message:"开始对话",buttons:[{role:"ok",text:"知道了",handler:()=>{}}]})).present(),this.navCtrl.navigateRoot("/chat/pro/mask")}}async presentEditTitle(e,t,n){n.stopPropagation(),this.isPreventGo=!0,setTimeout((()=>{this.isPreventGo=!1}),500),n.preventDefault();const o=await this.alertCtrl.create({header:"修改会话标题",subHeader:"",message:"",buttons:[{text:"取消",role:"cancel",handler:()=>{}},{text:"确定",role:"confirm",handler:n=>{t.title=n.title,e?.set("title",n.title),e?.save()}}],inputs:[{placeholder:"会话标题",name:"title",value:t?.title||""}]});await o.present()}async presentDeleteTItle(e,t,n){n.stopPropagation(),this.isPreventGo=!0,setTimeout((()=>{this.isPreventGo=!1}),500),n.preventDefault();const o=await this.alertCtrl.create({header:"确认删除?",subHeader:"",message:"",buttons:[{text:"取消",role:"cancel",handler:()=>{}},{text:"确定",role:"confirm",handler:()=>{t.isHidden=!0,e?.set("isDeleted",!0),e?.save()}}]});await o.present()}truncateString(e){return e&&e.length>10?e.slice(0,10)+"...":e}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatListComponent,deps:[{token:ChatService},{token:i1$3.AlertController},{token:i1$3.NavController},{token:i1$3.ModalController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ChatListComponent,isStandalone:!0,selector:"app-chat-list",inputs:{onItemClick:"onItemClick"},providers:[],ngImport:i0,template:'<ion-list>\n <ng-container *ngFor="let chat of (chatServ?.chatList || chatList)">\n <ion-item [button]="true" detail="false" *ngIf="!chat?.isHidden" (click)="onItemClick(chat,$event)">\n <div class="unread-indicator-wrapper" slot="start">\n <div class="unread-indicator"></div>\n </div>\n <ion-label>\n <div style="display: flex;justify-content: space-between; align-items: center;">\n <div style="display: flex; flex-direction: row;align-items: center;">\n <strong style="display: flex;align-items: center;">\n <ion-avatar style="margin-right: 10px;">\n <img [src]="chat?.thumb||avatar" />\n </ion-avatar>\n <p style="max-width: 7rem;white-space: nowrap;">{{truncateString(chat?.title)}}</p>\n </strong>\n\n <ion-icon (click)="presentEditTitle(chat?.session,chat,$event)" name="brush-sharp" style="color:#777777;margin-left: 1rem;"></ion-icon>\n <ion-icon (click)="presentDeleteTItle(chat?.session,chat,$event)" name="trash-sharp" style="color:#777777;margin-left: 0.5rem;"></ion-icon>\n \n </div>\n <div class="metadata-end-wrapper" slot="end">\n <ion-note color="medium">{{chat?.latest | date:"HH:mm"}}</ion-note>\n <ion-icon color="medium" name="chevron-forward"></ion-icon>\n </div>\n </div>\n <ion-text></ion-text><br />\n <ion-note color="medium" class="ion-text-wrap">\n {{chat?.message}}\n </ion-note>\n </ion-label>\n </ion-item>\n </ng-container>\n </ion-list>',styles:["ion-icon{color:#fff}ion-list{margin:3px}ion-list ion-item{--inner-padding-bottom:0px;--inner-padding-end:0px;--inner-padding-start:0px;--inner-padding-to:0px;--padding-bottom:0px;--padding-end:0px;--padding-start:0px;--padding-to:0px}ion-list ul{width:100%;list-style-type:none;padding:0;margin:0 0 10px;display:flex;flex-wrap:wrap;background-color:#fff;border-radius:10px}ion-list ul .active__{position:relative;padding:5px 15px;font-size:18px;font-weight:700;color:#535353;transition:.3s}ion-list ul .active{color:#2d8af7;background-color:#f2f4ff;border-radius:10px}ion-list ul li{flex:1 1 auto}ion-list ul li div{cursor:pointer;text-align:center}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"pipe",type:i2.DatePipe,name:"date"},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:IonNote,selector:"ion-note",inputs:["color","mode"]},{kind:"component",type:IonAvatar,selector:"ion-avatar"},{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:IonText,selector:"ion-text",inputs:["color","mode"]}]})}}function svgStringToBlobURL(e){const t=new Blob([e],{type:"image/svg+xml"});return URL.createObjectURL(t)}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatListComponent,decorators:[{type:Component,args:[{selector:"app-chat-list",imports:[CommonModule,IonIcon,IonList,IonLabel,IonNote,IonButton,IonAvatar,IonItem,IonText],providers:[],standalone:!0,template:'<ion-list>\n <ng-container *ngFor="let chat of (chatServ?.chatList || chatList)">\n <ion-item [button]="true" detail="false" *ngIf="!chat?.isHidden" (click)="onItemClick(chat,$event)">\n <div class="unread-indicator-wrapper" slot="start">\n <div class="unread-indicator"></div>\n </div>\n <ion-label>\n <div style="display: flex;justify-content: space-between; align-items: center;">\n <div style="display: flex; flex-direction: row;align-items: center;">\n <strong style="display: flex;align-items: center;">\n <ion-avatar style="margin-right: 10px;">\n <img [src]="chat?.thumb||avatar" />\n </ion-avatar>\n <p style="max-width: 7rem;white-space: nowrap;">{{truncateString(chat?.title)}}</p>\n </strong>\n\n <ion-icon (click)="presentEditTitle(chat?.session,chat,$event)" name="brush-sharp" style="color:#777777;margin-left: 1rem;"></ion-icon>\n <ion-icon (click)="presentDeleteTItle(chat?.session,chat,$event)" name="trash-sharp" style="color:#777777;margin-left: 0.5rem;"></ion-icon>\n \n </div>\n <div class="metadata-end-wrapper" slot="end">\n <ion-note color="medium">{{chat?.latest | date:"HH:mm"}}</ion-note>\n <ion-icon color="medium" name="chevron-forward"></ion-icon>\n </div>\n </div>\n <ion-text></ion-text><br />\n <ion-note color="medium" class="ion-text-wrap">\n {{chat?.message}}\n </ion-note>\n </ion-label>\n </ion-item>\n </ng-container>\n </ion-list>',styles:["ion-icon{color:#fff}ion-list{margin:3px}ion-list ion-item{--inner-padding-bottom:0px;--inner-padding-end:0px;--inner-padding-start:0px;--inner-padding-to:0px;--padding-bottom:0px;--padding-end:0px;--padding-start:0px;--padding-to:0px}ion-list ul{width:100%;list-style-type:none;padding:0;margin:0 0 10px;display:flex;flex-wrap:wrap;background-color:#fff;border-radius:10px}ion-list ul .active__{position:relative;padding:5px 15px;font-size:18px;font-weight:700;color:#535353;transition:.3s}ion-list ul .active{color:#2d8af7;background-color:#f2f4ff;border-radius:10px}ion-list ul li{flex:1 1 auto}ion-list ul li div{cursor:pointer;text-align:center}\n"]}]}],ctorParameters:()=>[{type:ChatService},{type:i1$3.AlertController},{type:i1$3.NavController},{type:i1$3.ModalController}],propDecorators:{onItemClick:[{type:Input}]}});const docxIcon=svgStringToBlobURL('<svg t="1726104361150" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5821" width="256" height="256"><path d="M950.272 843.776H527.36c-16.384 0-29.696-13.312-29.696-29.696V210.944c0-16.384 13.312-29.696 29.696-29.696h422.912c16.384 0 29.696 13.312 29.696 29.696v603.136c0 16.384-13.312 29.696-29.696 29.696z" fill="#E8E8E8" p-id="5822"></path><path d="M829.44 361.472H527.36c-16.384 0-29.696-13.312-29.696-29.696s13.312-29.696 29.696-29.696H829.44c16.384 0 29.696 13.312 29.696 29.696 0 15.36-13.312 29.696-29.696 29.696z m0 120.832H527.36c-16.384 0-29.696-13.312-29.696-29.696s13.312-29.696 29.696-29.696H829.44c16.384 0 29.696 13.312 29.696 29.696s-13.312 29.696-29.696 29.696z m0 119.808H527.36c-16.384 0-29.696-13.312-29.696-29.696s13.312-29.696 29.696-29.696H829.44c16.384 0 29.696 13.312 29.696 29.696s-13.312 29.696-29.696 29.696z m0 120.832H527.36c-16.384 0-29.696-13.312-29.696-29.696s13.312-29.696 29.696-29.696H829.44c16.384 0 29.696 13.312 29.696 29.696s-13.312 29.696-29.696 29.696z" fill="#B2B2B2" p-id="5823"></path><path d="M607.232 995.328l-563.2-107.52V135.168l563.2-107.52v967.68z" fill="#0D47A1" p-id="5824"></path><path d="M447.488 696.32h-71.68l-47.104-236.544c-3.072-13.312-4.096-27.648-4.096-40.96h-1.024c-1.024 16.384-3.072 30.72-5.12 40.96L269.312 696.32H194.56l-74.752-368.64h70.656l39.936 245.76c2.048 10.24 3.072 24.576 4.096 41.984h1.024c0-13.312 3.072-27.648 6.144-43.008l51.2-244.736h68.608l47.104 247.808c2.048 9.216 3.072 22.528 4.096 39.936h1.024c1.024-13.312 2.048-26.624 4.096-40.96l39.936-245.76H522.24L447.488 696.32z" fill="#FFFFFF" p-id="5825"></path></svg>'),pptxIcon=svgStringToBlobURL('<svg t="1726104498747" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5986" width="256" height="256"><path d="M968.704 135.168h-430.08v752.64h430.08c15.36 0 26.624-12.288 26.624-26.624V162.816c0-15.36-11.264-27.648-26.624-27.648z" fill="#FF8A65" p-id="5987"></path><path d="M512 646.144h376.832v53.248H512z m0 107.52h376.832v54.272H512z m161.792-483.328c-89.088 0-161.792 72.704-161.792 161.792C512 521.216 584.704 593.92 673.792 593.92s161.792-72.704 161.792-161.792H673.792V270.336z" fill="#FBE9E7" p-id="5988"></path><path d="M727.04 216.064v161.792h161.792c0-89.088-72.704-161.792-161.792-161.792z" fill="#FBE9E7" p-id="5989"></path><path d="M592.896 996.352L28.672 888.832V135.168L592.896 27.648z" fill="#E64A19" p-id="5990"></path><path d="M319.488 327.68H192.512v368.64h78.848V569.344h40.96c44.032 0 78.848-11.264 104.448-34.816 25.6-22.528 38.912-53.248 38.912-90.112C455.68 366.592 409.6 327.68 319.488 327.68z m-14.336 178.176h-33.792V391.168h33.792c43.008 0 64.512 18.432 64.512 56.32 0 39.936-21.504 58.368-64.512 58.368z" fill="#FFFFFF" p-id="5991"></path></svg>'),xlsxSvg=svgStringToBlobURL('<svg t="1726104542590" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6152" width="256" height="256"><path d="M968.704 135.168h-430.08v752.64h430.08c15.36 0 26.624-12.288 26.624-26.624V162.816c0-15.36-11.264-27.648-26.624-27.648z" fill="#4CAF50" p-id="6153"></path><path d="M727.04 270.336h188.416v80.896H727.04z m0 268.288h188.416v80.896H727.04z m0 134.144h188.416v80.896H727.04z m0-268.288h188.416v80.896H727.04zM538.624 270.336h134.144v80.896H538.624z m0 268.288h134.144v80.896H538.624z m0 134.144h134.144v80.896H538.624z m0-268.288h134.144v80.896H538.624z" fill="#FFFFFF" p-id="6154"></path><path d="M592.896 996.352L28.672 888.832V135.168L592.896 27.648z" fill="#2E7D32" p-id="6155"></path><path d="M379.904 696.32l-63.488-119.808c-2.048-4.096-5.12-12.288-7.168-24.576H307.2c-1.024 6.144-4.096 14.336-8.192 25.6L235.52 696.32h-99.328l117.76-184.32-107.52-184.32h101.376l53.248 110.592c4.096 9.216 8.192 19.456 11.264 30.72h1.024c2.048-7.168 6.144-17.408 11.264-31.744L381.952 327.68h92.16L364.544 509.952 478.208 696.32h-98.304z" fill="#FFFFFF" p-id="6156"></path></svg>'),pdfIcon=svgStringToBlobURL('<svg t="1726104655450" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1260" width="256" height="256"><path d="M205.5 64H665l232 232v639c0 13.807-11.193 25-25 25H205.5c-13.807 0-25-11.193-25-25V89c0-13.807 11.193-25 25-25z m449.145 25H205.5v846H872V306.355L654.645 89z" fill="#B7B7BD" p-id="1261"></path><path d="M665 64l-11 23.5v197c0 13.807 11.193 25 25 25h194.5L897 296 665 64z m14 49.355L850.145 284.5H679V113.355z" fill="#B7B7BD" p-id="1262"></path><path d="M255 571m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="1263"></path><path d="M255 707m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="1264"></path><path d="M255 639m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="1265"></path><path d="M255 774m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="1266"></path><path d="M255 842m10 0l556 0q10 0 10 10l0 0q0 10-10 10l-556 0q-10 0-10-10l0 0q0-10 10-10Z" fill="#B7B7BD" p-id="1267"></path><path d="M67 193m16 0l287 0q16 0 16 16l0 287q0 16-16 16l-287 0q-16 0-16-16l0-287q0-16 16-16Z" fill="#FF4867" p-id="1268"></path><path d="M314.229 459.289c-21.407 0-40.606-36.765-50.708-60.673-16.991-7.098-35.722-13.728-53.918-18.014-15.92 10.514-43.014 26.251-63.818 26.251-12.911 0-22.21-6.496-25.622-17.813-2.609-9.309-0.4-15.738 2.409-19.22 5.485-7.5 16.79-11.317 33.715-11.317 13.714 0 31.107 2.41 50.507 7.098 12.51-8.907 25.22-19.22 36.525-30.135-5.017-23.84-10.503-62.48 3.412-80.294 6.89-8.505 17.393-11.318 30.103-7.5 13.914 4.017 19.199 12.522 20.804 19.22 5.887 23.237-20.804 54.578-38.8 72.994 4.015 15.938 9.3 32.747 15.721 48.15 25.822 11.518 56.527 28.728 60.006 47.48 1.405 6.495-0.602 12.522-5.887 17.813-4.549 3.75-9.365 5.96-14.45 5.96z m-31.647-52.419c12.785 26.402 24.975 38.862 31.4 38.862 0.995 0 2.386-0.404 4.373-2.02 2.385-2.425 2.385-4.041 1.988-5.523-1.325-6.937-12.124-18.32-37.761-31.319z m-126.377-35.247c-16.73 0-21.33 4.093-22.73 6.003-0.399 0.614-1.599 2.455-0.399 7.23 1 4.092 3.8 8.458 12.464 8.458 10.865 0 26.595-6.207 44.857-17.325-13.063-2.933-24.594-4.366-34.192-4.366z m67.632-1.765c10.845 2.983 22.09 6.827 32.535 10.803-3.792-9.809-6.853-20.015-9.448-29.824-7.651 6.561-15.436 12.99-23.087 19.021zM265.9 259.556c-3.827 0-6.513 1.409-8.93 4.024-7.118 8.917-7.924 31.38-2.418 60.144 20.884-22.26 32.232-42.711 29.411-53.64-0.402-1.61-1.611-6.504-11.348-9.32-2.686-0.805-4.7-1.208-6.715-1.208z" fill="#FFFFFF" p-id="1269"></path></svg>'),videoIcon=svgStringToBlobURL('<svg t="1726104803743" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14491" width="256" height="256"><path d="M938.666667 938.666667a85.333333 85.333333 0 0 1-85.333334 85.333333H170.666667a85.333333 85.333333 0 0 1-85.333334-85.333333V85.333333a85.333333 85.333333 0 0 1 85.333334-85.333333h533.333333l234.666667 234.666667v704z" fill="#845EFF" p-id="14492"></path><path d="M704 0l234.666667 234.666667h-192a42.666667 42.666667 0 0 1-42.666667-42.666667V0z" fill="#000000" fill-opacity=".2" p-id="14493"></path><path d="M757.013333 437.76l-120.064 93.44v-66.56c0-30.378667-25.322667-55.04-56.576-55.04H291.242667C259.989333 409.6 234.666667 434.261333 234.666667 464.64v222.72c0 30.378667 25.322667 55.04 56.576 55.04h289.130666c31.253333 0 56.576-24.661333 56.576-55.04V632.746667l121.365334 86.357333c16.64 11.349333 39.552-0.256 39.552-20.053333V456.810667c0-20.48-24.384-31.914667-40.853334-19.072zM324.266667 537.6a38.4 38.4 0 1 1 0-76.8 38.4 38.4 0 0 1 0 76.8z" fill="#FFFFFF" p-id="14494"></path></svg>'),audioIcon=svgStringToBlobURL('<svg t="1726104860118" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3240" width="256" height="256"><path d="M113.777778 1024V0h540.444444l256 256v768z" fill="#FF5722" p-id="3241"></path><path d="M654.222222 256V0l256 256z" fill="#ECEFF1" p-id="3242"></path><path d="M654.222222 256l256 85.333333V256z" fill="#D84315" p-id="3243"></path><path d="M341.333333 711.111111a113.777778 85.333333 0 1 0 227.555556 0 113.777778 85.333333 0 1 0-227.555556 0Z" fill="#FBE9E7" p-id="3244"></path><path d="M512 398.222222h56.888889v312.888889h-56.888889z" fill="#FBE9E7" p-id="3245"></path><path d="M512 398.222222h170.666667v85.333334h-170.666667z" fill="#FBE9E7" p-id="3246"></path></svg>'),mdIcon=svgStringToBlobURL('<svg t="1726105093620" class="icon" viewBox="0 0 1843 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="23110" width="256" height="256"><path d="M1273.6 864H185.6c-19.2 0-32-12.8-32-32V256c0-19.2 12.8-32 32-32h1088c19.2 0 32 12.8 32 32v576c0 19.2-12.8 32-32 32z" fill="#4771C7" opacity=".3" p-id="23111"></path><path d="M921.6 1024H313.6c-19.2 0-32-12.8-32-32V32c0-19.2 12.8-32 32-32h832c19.2 0 32 12.8 32 32v736c0 140.8-115.2 256-256 256z" fill="#4771C7" p-id="23112"></path><path d="M547.2 704c-35.2 0-64-28.8-64-64V384c0-35.2 28.8-64 64-64s64 28.8 64 64v256c0 35.2-28.8 64-64 64z" fill="#FFFFFF" opacity=".6" p-id="23113"></path><path d="M912 704c-35.2 0-64-28.8-64-64V384c0-35.2 28.8-64 64-64s64 28.8 64 64v256c0 35.2-28.8 64-64 64zM774.4 611.2c-25.6 25.6-64 25.6-89.6 0L502.4 428.8c-25.6-25.6-25.6-64 0-89.6 25.6-25.6 64-25.6 89.6 0l182.4 182.4c25.6 22.4 25.6 64 0 89.6z" fill="#FFFFFF" p-id="23114"></path><path d="M684.8 611.2c25.6 25.6 64 25.6 89.6 0l182.4-182.4c25.6-25.6 25.6-64 0-89.6-25.6-25.6-64-25.6-89.6 0l-182.4 182.4c-25.6 22.4-25.6 64 0 89.6z" fill="#FFFFFF" p-id="23115"></path></svg>'),chatIcon=svgStringToBlobURL('<svg t="1726104960295" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12838" width="256" height="256"><path d="M387.157333 128C222.293333 125.568 85.333333 249.130667 85.333333 394.88c0 84.138667 38.826667 157.141333 113.877334 210.730667 0 0-27.52 92.629333-27.136 94.506666 0.426667 1.834667 6.4 5.504 8.448 4.266667 2.133333-1.152 99.498667-60.416 99.498666-60.416 74.624 26.154667 118.144 17.450667 120.618667 17.28a196.864 196.864 0 0 1-6.784-89.557333c29.098667-170.88 200.618667-224.042667 294.613333-214.997334-25.941333-123.392-138.666667-226.133333-301.312-228.608z m286.933334 249.173333c-145.365333 0-261.333333 97.792-261.333334 222.634667 0 125.098667 110.293333 228.650667 261.546667 229.504 30.421333 0.170667 75.733333-7.808 106.282667-20.864 0 0 73.088 45.226667 77.226666 44.885333a6.826667 6.826667 0 0 0 6.314667-6.485333c0.170667-2.816-23.296-73.386667-23.296-73.386667 62.72-50.133333 88.96-105.386667 88.96-175.786666 0-124.885333-118.4-220.544-255.701333-220.544zM272.64 268.288a39.552 39.552 0 0 0-39.168 39.936c0 22.058667 17.493333 39.936 39.168 39.936a39.552 39.552 0 0 0 39.125333-39.936 39.552 39.552 0 0 0-39.125333-39.936z m237.013333 0a39.552 39.552 0 0 0-39.168 39.936c0 22.058667 17.536 39.936 39.168 39.936a39.552 39.552 0 0 0 39.168-39.936 39.552 39.552 0 0 0-39.168-39.936z m68.778667 212.437333a35.029333 35.029333 0 0 0-34.602667 35.413334c0 19.541333 15.488 35.413333 34.602667 35.413333a35.029333 35.029333 0 0 0 34.645333-35.413333 35.029333 35.029333 0 0 0-34.645333-35.413334z m185.258667 0a35.029333 35.029333 0 0 0-34.645334 35.413334c0 19.541333 15.488 35.413333 34.645334 35.413333a35.029333 35.029333 0 0 0 34.645333-35.413333 35.029333 35.029333 0 0 0-34.645333-35.413334z" fill="#00C80C" p-id="12839"></path></svg>'),fileIcon=svgStringToBlobURL('<svg t="1726107262747" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="21360" width="256" height="256"><path d="M853.333333 960H170.666667V64h469.333333l213.333333 213.333333z" fill="#90CAF9" p-id="21361"></path><path d="M821.333333 298.666667H618.666667V96z" fill="#E1F5FE" p-id="21362"></path></svg>'),avatarIcon=svgStringToBlobURL('<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512" fill="none">\n<g clip-path="url(#clip0_1765_7055)">\n<path d="M0 0H512V512H0V0Z" fill="#222D3A"/>\n<path d="M330.085 110.955C311.299 90.672 285.059 79.5024 256.097 79.5024C226.981 79.5024 200.655 90.6044 181.955 110.762C163.053 131.141 153.843 158.838 156.005 188.746C160.292 247.751 205.192 295.75 256.097 295.75C307.003 295.75 351.826 247.76 356.18 188.765C358.371 159.128 349.103 131.489 330.085 110.955Z" fill="#B3BAC0"/>\n<path d="M53.9275 511.997H458.333C459 503 458.206 483.499 456.333 473.141C448.185 427.941 422.757 389.972 382.789 363.327C347.282 339.675 302.305 326.642 256.13 326.642C209.956 326.642 164.978 339.666 129.471 363.327C89.5038 389.982 64.0754 427.951 55.9275 473.15C54.0546 483.509 53.5001 504.5 53.9275 511.997Z" fill="#B3BAC0"/>\n</g>\n<defs>\n<clipPath id="clip0_1765_7055">\n<rect width="512" height="512" fill="white"/>\n</clipPath>\n</defs>\n</svg>');class FiletypePipe{constructor(){this.iconMap={pdf:pdfIcon,doc:docxIcon,xls:xlsxSvg,mp4:videoIcon,mp3:audioIcon,md:mdIcon,chat:chatIcon,file:fileIcon}}transform(e="",...t){let n=t[0]||"svg";e=e?.toLocaleLowerCase();let o=e.split(".")[e.split(".")?.length-1];return n?o.indexOf("pdf")>-1||o.indexOf("ppt")>-1?this.iconMap.pdf:o.indexOf("xls")>-1?this.iconMap.xls:o.indexOf("doc")>-1?this.iconMap.doc:o.indexOf("chat")>-1?this.iconMap.chat:o.indexOf("md")>-1||o.indexOf("mark")>-1?this.iconMap.md:["mp3","wav","pcm"].map((e=>o.indexOf(e)>-1)).filter((e=>e)).length>=1?this.iconMap.mp3:this.iconMap.file:null}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FiletypePipe,deps:[],target:i0.ɵɵFactoryTarget.Pipe})}static{this.ɵpipe=i0.ɵɵngDeclarePipe({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:FiletypePipe,isStandalone:!0,name:"filetype"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FiletypePipe,decorators:[{type:Pipe,args:[{name:"filetype",standalone:!0}]}]});class FmStoryCardComponent{get checked(){return this._checked}set checked(e){this.checkedChange.emit(e),this._checked=e}constructor(){this.isSelectMode=!1,this._checked=!1,this.checkedChange=new EventEmitter,this.onCheckStory=new EventEmitter,this.onPreviewStory=new EventEmitter,this.onDestoryStory=new EventEmitter,this.colorMap={chat:"#673ab7",diary:"#1179ff",document:"#00c80c"}}checkStory(e,t){this.checked=t,this.onCheckStory.emit({agentStory:e,event:t})}previewStory(e){this.onPreviewStory.emit(e)}destroyStory(e){this.onDestoryStory.emit(e)}ngOnInit(){this.agentStory=new AgentStory(this.story,this.story?.get("person"),this.story?.get("book"))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmStoryCardComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:FmStoryCardComponent,isStandalone:!0,selector:"fm-story-card",inputs:{story:"story",isSelectMode:"isSelectMode",_checked:["checked","_checked"]},outputs:{checkedChange:"checkedChange",onCheckStory:"onCheckStory",onPreviewStory:"onPreviewStory",onDestoryStory:"onDestoryStory"},ngImport:i0,template:'<mat-card class="story-card">\n <mat-card-header>\n \x3c!-- 新故事卡片标题 --\x3e\n <ng-container *ngIf="!agentStory?.story?.get(\'attach\') && !agentStory?.story?.get(\'chatSession\')"> \n <mat-card-subtitle>{{ 0 | nzBytes: 0 : \'B\' : \'MB\' }}</mat-card-subtitle>\n <mat-card-title>新故事</mat-card-title>\n </ng-container>\n \x3c!-- 附件故事卡片标题 + 对话故事卡片标题 --\x3e\n\n <mat-card-subtitle>\n <div class="filebar">\n \x3c!-- 文件信息 --\x3e\n <div class="file-info" style="display:flex;align-items:center;">\n \x3c!-- 图标+大小 --\x3e\n @if(agentStory?.story?.get(\'attach\')){\n <ion-icon [src]="agentStory?.story?.get(\'attach\')?.get(\'url\') | filetype"></ion-icon>\n <span class="size">{{agentStory?.story?.get("attach")?.get("size") | nzBytes }}</span>\n }\n @if(agentStory?.story?.get(\'chatSession\')?.id){\n <ion-icon [src]="\'.chat\'|filetype"></ion-icon>\n <span class="size">{{agentStory?.story?.get("chatSession")?.get("messageList")?.length }}条</span>\n }\n </div>\n \x3c!-- 标题 --\x3e\n <div class="title">\n @if(agentStory?.story?.get(\'attach\')){\n {{agentStory?.story?.get("attach")?.get("name")}}\n }\n @if(agentStory?.story?.get(\'chatSession\')?.id){\n {{agentStory?.story?.get("title")}}\n }\n </div>\n \x3c!-- 操作区域 --\x3e\n <div class="actions" style="display:flex;align-items:center;justify-content: flex-end;">\n \x3c!-- 预览 --\x3e\n <button mat-button (click)="previewStory(agentStory)" aria-label="预览">\n 预览\n </button>\n \x3c!-- 选择 --\x3e\n <mat-checkbox *ngIf="isSelectMode"\n [ngModel]="checked" (ngModelChange)="checkStory(agentStory,$event)"\n [labelPosition]="\'before\'">\n </mat-checkbox>\n </div>\n </div>\n </mat-card-subtitle>\n \x3c!-- <mat-card-title></mat-card-title> --\x3e\n </mat-card-header>\n <mat-card-content>\n {{agentStory?.story?.get("desc")}}\n \x3c!-- <p>This card has divider and indeterminate progress as footer</p>\n <p>----</p>\n <mat-divider></mat-divider> --\x3e\n <ng-container>\n <br/>\n <div style="width:100%;display:flex;flex:1;flex-wrap:wrap;overflow-x:auto;align-items: center;justify-content: space-between;">\n <div style="display:flex;flex-wrap:wrap;max-width: calc(100% - 50px);">\n @if(agentStory?.story?.get(\'keywords\')?.length){\n @for(item of agentStory?.story?.get(\'keywords\'); track item){\n <ion-chip style="white-space:nowrap;" color="light" [outline]="true">#{{item}}</ion-chip>\n }\n }\n\n </div>\n \x3c!-- 删除 --\x3e\n @if(!isSelectMode){\n <button style="min-width:30px;" mat-icon-button color="warn" (click)="destroyStory(agentStory)" aria-label="删除">\n <mat-icon>delete</mat-icon>\n </button>\n }\n\n </div>\n </ng-container>\n </mat-card-content>\n <mat-card-actions *ngIf="false">\n \x3c!-- <button mat-button color="primary" (click)="previewStory(agentStory)">预览</button> --\x3e\n \x3c!-- <button *ngIf="isSelectMode" mat-button [color]="checked?\'warn\':\'primary\'" (click)="checkStory(agentStory,!checked)">{{checked?\'取消\':\'选择\'}}</button> --\x3e\n \x3c!-- <button *ngIf="!isSelectMode" mat-button color="primary" (click)="previewStory(agentStory)">学习</button> --\x3e\n \x3c!-- <button *ngIf="!isSelectMode" mat-button color="warn" (click)="destroyStory(agentStory)">删除</button> --\x3e\n </mat-card-actions>\n <mat-card-footer>\n \x3c!-- [color]="colorMap[agentStory?.story?.get(\'type\') || \'document\']" --\x3e\n <mat-progress-bar [style.--mdc-linear-progress-active-indicator-color]="colorMap[agentStory?.story?.get(\'type\') || \'document\']" *ngIf="!agentStory?.story?.get(\'attach\')?.id && !agentStory?.story?.get(\'chatSession\')?.id" mode="buffer" [value]="10" [bufferValue]="20"></mat-progress-bar>\n <mat-progress-bar [style.--mdc-linear-progress-active-indicator-color]="colorMap[agentStory?.story?.get(\'type\') || \'document\']" *ngIf="agentStory?.story?.get(\'attach\')?.id || agentStory?.story?.get(\'chatSession\')?.id" mode="determinate" [value]="100" ></mat-progress-bar>\n </mat-card-footer>\n</mat-card>',styles:[":host-context(body.dark) .story-card .title{color:#fff}:host-context(body.dark) .story-card mat-card-content{color:#ccc}:host-context(body.dark) .story-card ion-chip{color:#ccc}:host-context(body.dark) .story-card .file-info,:host-context(body.dark) .story-card button{color:#ccc}.story-card{border-radius:10px}.story-card .filebar{display:flex;justify-content:space-between;align-items:center}.story-card .filebar .file-info{max-width:80px}.story-card .filebar .title{flex:1;font-weight:700;margin-left:5px;margin-right:5px;max-width:220px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;font-size:1.2rem;font-weight:400}.story-card .filebar mat-card-content{color:#333}.story-card .filebar ion-chip{color:#333}.story-card .filebar .actions{max-width:104px}.story-card .size{min-width:40px}.story-card ion-icon{font-size:28px;min-width:30px}.story-card ion-chip{font-size:12px;padding:0 5px}.story-card mat-card-header{flex-direction:column}.story-card mat-card-footer{padding-top:10px;border-radius:10px;overflow:hidden}\n"],dependencies:[{kind:"directive",type:NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"component",type:IonChip,selector:"ion-chip",inputs:["color","disabled","mode","outline"]},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"ngmodule",type:MatCardModule},{kind:"component",type:i2$1.MatCard,selector:"mat-card",inputs:["appearance"],exportAs:["matCard"]},{kind:"directive",type:i2$1.MatCardActions,selector:"mat-card-actions",inputs:["align"],exportAs:["matCardActions"]},{kind:"directive",type:i2$1.MatCardContent,selector:"mat-card-content"},{kind:"directive",type:i2$1.MatCardFooter,selector:"mat-card-footer"},{kind:"component",type:i2$1.MatCardHeader,selector:"mat-card-header"},{kind:"directive",type:i2$1.MatCardSubtitle,selector:"mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]"},{kind:"directive",type:i2$1.MatCardTitle,selector:"mat-card-title, [mat-card-title], [matCardTitle]"},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"component",type:i3$2.MatIconButton,selector:"button[mat-icon-button]",exportAs:["matButton"]},{kind:"ngmodule",type:MatProgressBarModule},{kind:"component",type:i5$1.MatProgressBar,selector:"mat-progress-bar",inputs:["color","value","bufferValue","mode"],outputs:["animationEnd"],exportAs:["matProgressBar"]},{kind:"ngmodule",type:MatCheckboxModule},{kind:"component",type:i5$2.MatCheckbox,selector:"mat-checkbox",inputs:["aria-label","aria-labelledby","aria-describedby","id","required","labelPosition","name","value","disableRipple","tabIndex","color","checked","disabled","indeterminate"],outputs:["change","indeterminateChange"],exportAs:["matCheckbox"]},{kind:"ngmodule",type:MatIconModule},{kind:"component",type:i6.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"ngmodule",type:NzPipesModule},{kind:"pipe",type:i7.NzBytesPipe,name:"nzBytes"},{kind:"pipe",type:FiletypePipe,name:"filetype"}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmStoryCardComponent,decorators:[{type:Component,args:[{selector:"fm-story-card",standalone:!0,imports:[NgIf,FormsModule,ReactiveFormsModule,IonChip,IonIcon,MatCardModule,MatButtonModule,MatProgressBarModule,MatCheckboxModule,MatIconModule,NzPipesModule,FiletypePipe],template:'<mat-card class="story-card">\n <mat-card-header>\n \x3c!-- 新故事卡片标题 --\x3e\n <ng-container *ngIf="!agentStory?.story?.get(\'attach\') && !agentStory?.story?.get(\'chatSession\')"> \n <mat-card-subtitle>{{ 0 | nzBytes: 0 : \'B\' : \'MB\' }}</mat-card-subtitle>\n <mat-card-title>新故事</mat-card-title>\n </ng-container>\n \x3c!-- 附件故事卡片标题 + 对话故事卡片标题 --\x3e\n\n <mat-card-subtitle>\n <div class="filebar">\n \x3c!-- 文件信息 --\x3e\n <div class="file-info" style="display:flex;align-items:center;">\n \x3c!-- 图标+大小 --\x3e\n @if(agentStory?.story?.get(\'attach\')){\n <ion-icon [src]="agentStory?.story?.get(\'attach\')?.get(\'url\') | filetype"></ion-icon>\n <span class="size">{{agentStory?.story?.get("attach")?.get("size") | nzBytes }}</span>\n }\n @if(agentStory?.story?.get(\'chatSession\')?.id){\n <ion-icon [src]="\'.chat\'|filetype"></ion-icon>\n <span class="size">{{agentStory?.story?.get("chatSession")?.get("messageList")?.length }}条</span>\n }\n </div>\n \x3c!-- 标题 --\x3e\n <div class="title">\n @if(agentStory?.story?.get(\'attach\')){\n {{agentStory?.story?.get("attach")?.get("name")}}\n }\n @if(agentStory?.story?.get(\'chatSession\')?.id){\n {{agentStory?.story?.get("title")}}\n }\n </div>\n \x3c!-- 操作区域 --\x3e\n <div class="actions" style="display:flex;align-items:center;justify-content: flex-end;">\n \x3c!-- 预览 --\x3e\n <button mat-button (click)="previewStory(agentStory)" aria-label="预览">\n 预览\n </button>\n \x3c!-- 选择 --\x3e\n <mat-checkbox *ngIf="isSelectMode"\n [ngModel]="checked" (ngModelChange)="checkStory(agentStory,$event)"\n [labelPosition]="\'before\'">\n </mat-checkbox>\n </div>\n </div>\n </mat-card-subtitle>\n \x3c!-- <mat-card-title></mat-card-title> --\x3e\n </mat-card-header>\n <mat-card-content>\n {{agentStory?.story?.get("desc")}}\n \x3c!-- <p>This card has divider and indeterminate progress as footer</p>\n <p>----</p>\n <mat-divider></mat-divider> --\x3e\n <ng-container>\n <br/>\n <div style="width:100%;display:flex;flex:1;flex-wrap:wrap;overflow-x:auto;align-items: center;justify-content: space-between;">\n <div style="display:flex;flex-wrap:wrap;max-width: calc(100% - 50px);">\n @if(agentStory?.story?.get(\'keywords\')?.length){\n @for(item of agentStory?.story?.get(\'keywords\'); track item){\n <ion-chip style="white-space:nowrap;" color="light" [outline]="true">#{{item}}</ion-chip>\n }\n }\n\n </div>\n \x3c!-- 删除 --\x3e\n @if(!isSelectMode){\n <button style="min-width:30px;" mat-icon-button color="warn" (click)="destroyStory(agentStory)" aria-label="删除">\n <mat-icon>delete</mat-icon>\n </button>\n }\n\n </div>\n </ng-container>\n </mat-card-content>\n <mat-card-actions *ngIf="false">\n \x3c!-- <button mat-button color="primary" (click)="previewStory(agentStory)">预览</button> --\x3e\n \x3c!-- <button *ngIf="isSelectMode" mat-button [color]="checked?\'warn\':\'primary\'" (click)="checkStory(agentStory,!checked)">{{checked?\'取消\':\'选择\'}}</button> --\x3e\n \x3c!-- <button *ngIf="!isSelectMode" mat-button color="primary" (click)="previewStory(agentStory)">学习</button> --\x3e\n \x3c!-- <button *ngIf="!isSelectMode" mat-button color="warn" (click)="destroyStory(agentStory)">删除</button> --\x3e\n </mat-card-actions>\n <mat-card-footer>\n \x3c!-- [color]="colorMap[agentStory?.story?.get(\'type\') || \'document\']" --\x3e\n <mat-progress-bar [style.--mdc-linear-progress-active-indicator-color]="colorMap[agentStory?.story?.get(\'type\') || \'document\']" *ngIf="!agentStory?.story?.get(\'attach\')?.id && !agentStory?.story?.get(\'chatSession\')?.id" mode="buffer" [value]="10" [bufferValue]="20"></mat-progress-bar>\n <mat-progress-bar [style.--mdc-linear-progress-active-indicator-color]="colorMap[agentStory?.story?.get(\'type\') || \'document\']" *ngIf="agentStory?.story?.get(\'attach\')?.id || agentStory?.story?.get(\'chatSession\')?.id" mode="determinate" [value]="100" ></mat-progress-bar>\n </mat-card-footer>\n</mat-card>',styles:[":host-context(body.dark) .story-card .title{color:#fff}:host-context(body.dark) .story-card mat-card-content{color:#ccc}:host-context(body.dark) .story-card ion-chip{color:#ccc}:host-context(body.dark) .story-card .file-info,:host-context(body.dark) .story-card button{color:#ccc}.story-card{border-radius:10px}.story-card .filebar{display:flex;justify-content:space-between;align-items:center}.story-card .filebar .file-info{max-width:80px}.story-card .filebar .title{flex:1;font-weight:700;margin-left:5px;margin-right:5px;max-width:220px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;font-size:1.2rem;font-weight:400}.story-card .filebar mat-card-content{color:#333}.story-card .filebar ion-chip{color:#333}.story-card .filebar .actions{max-width:104px}.story-card .size{min-width:40px}.story-card ion-icon{font-size:28px;min-width:30px}.story-card ion-chip{font-size:12px;padding:0 5px}.story-card mat-card-header{flex-direction:column}.story-card mat-card-footer{padding-top:10px;border-radius:10px;overflow:hidden}\n"]}]}],ctorParameters:()=>[],propDecorators:{story:[{type:Input}],isSelectMode:[{type:Input}],_checked:[{type:Input,args:["checked"]}],checkedChange:[{type:Output}],onCheckStory:[{type:Output}],onPreviewStory:[{type:Output}],onDestoryStory:[{type:Output}]}});class StoryService{constructor(){this.storyList=[]}newStory(e){let t;if(console.log("newStory"),this.storyList?.[0]&&!this.storyList?.[0]?.story?.id)return t=this.storyList?.[0],void console.log("新故事已创建");let n=new AgentStory(void 0,e?.person,e?.book);return console.log("new:",n),n&&(this.storyList?.unshift(n),t=n),n}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StoryService,deps:[],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StoryService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StoryService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});class FmOfficeViewerComponent{constructor(e,t){this.domSan=e,this.modalCtrl=t,this.officeHost="https://office.fmode.cn/browser/baa6eef/cool.html",this.wopiHost="https://server.fmode.cn/api/office",this.permission="readonly",this.showHeader=!1}back(){this.modalCtrl.dismiss()}ngOnInit(){this.genSafeUrl()}genSafeUrl(){if(this.fileId){let e=`${this.officeHost}?lang=zh-cn&permission=${this.permission}&WOPISrc=${this.wopiHost}/wopi/files/${this.fileId}`;this.safeUrl=this.domSan.bypassSecurityTrustResourceUrl(e),this.loadAttachment(this.fileId)}}async loadAttachment(e){let t=new Parse__default.Query("Attachment");this.attach=await t.get(e)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmOfficeViewerComponent,deps:[{token:i1$2.DomSanitizer},{token:i1$3.ModalController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:FmOfficeViewerComponent,isStandalone:!0,selector:"fm-office-viewer",inputs:{officeHost:"officeHost",wopiHost:"wopiHost",fileId:"fileId",permission:"permission",showHeader:"showHeader"},ngImport:i0,template:'@if(showHeader&&attach?.id){\n <div class="filebar">\n \x3c!-- 文件信息 --\x3e\n <div class="file-info" style="display:flex;align-items:center;">\n \x3c!-- 图标+大小 --\x3e\n <ion-icon [src]="attach?.get(\'url\') | filetype"></ion-icon>\n <span class="size">{{attach?.get("size") | nzBytes }}</span>\n </div>\n \x3c!-- 标题 --\x3e\n <div class="title">\n {{attach?.get("name") || \'未命名\'}}\n </div>\n \x3c!-- 操作区域 --\x3e\n <div class="actions" style="display:flex;align-items:center;justify-content: flex-end;">\n \x3c!-- 关闭 --\x3e\n <button mat-button (click)="back()" aria-label="预览">\n 关闭\n </button>\n </div>\n </div>\n}\n@if(safeUrl){\n <iframe [src]="safeUrl" frameborder="0" allow="clipboard-read *; clipboard-write *"></iframe> \n}',styles:["iframe{width:100%;height:100%}.filebar{display:flex;justify-content:space-between;align-items:center;padding:5px 15px}.filebar .file-info{max-width:80px}.filebar .title{flex:1;font-weight:700;margin-left:5px;margin-right:5px;max-width:220px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;padding:5px 15px;text-align:center}.filebar mat-card-content{color:#333}.filebar ion-icon{font-size:28px;min-width:30px}.filebar ion-chip{color:#333}.filebar .actions{max-width:104px}\n"],dependencies:[{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"ngmodule",type:NzPipesModule},{kind:"pipe",type:i7.NzBytesPipe,name:"nzBytes"},{kind:"pipe",type:FiletypePipe,name:"filetype"}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmOfficeViewerComponent,decorators:[{type:Component,args:[{selector:"fm-office-viewer",standalone:!0,imports:[IonIcon,MatButtonModule,NzPipesModule,FiletypePipe],template:'@if(showHeader&&attach?.id){\n <div class="filebar">\n \x3c!-- 文件信息 --\x3e\n <div class="file-info" style="display:flex;align-items:center;">\n \x3c!-- 图标+大小 --\x3e\n <ion-icon [src]="attach?.get(\'url\') | filetype"></ion-icon>\n <span class="size">{{attach?.get("size") | nzBytes }}</span>\n </div>\n \x3c!-- 标题 --\x3e\n <div class="title">\n {{attach?.get("name") || \'未命名\'}}\n </div>\n \x3c!-- 操作区域 --\x3e\n <div class="actions" style="display:flex;align-items:center;justify-content: flex-end;">\n \x3c!-- 关闭 --\x3e\n <button mat-button (click)="back()" aria-label="预览">\n 关闭\n </button>\n </div>\n </div>\n}\n@if(safeUrl){\n <iframe [src]="safeUrl" frameborder="0" allow="clipboard-read *; clipboard-write *"></iframe> \n}',styles:["iframe{width:100%;height:100%}.filebar{display:flex;justify-content:space-between;align-items:center;padding:5px 15px}.filebar .file-info{max-width:80px}.filebar .title{flex:1;font-weight:700;margin-left:5px;margin-right:5px;max-width:220px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;padding:5px 15px;text-align:center}.filebar mat-card-content{color:#333}.filebar ion-icon{font-size:28px;min-width:30px}.filebar ion-chip{color:#333}.filebar .actions{max-width:104px}\n"]}]}],ctorParameters:()=>[{type:i1$2.DomSanitizer},{type:i1$3.ModalController}],propDecorators:{officeHost:[{type:Input}],wopiHost:[{type:Input}],fileId:[{type:Input}],permission:[{type:Input}],showHeader:[{type:Input}]}});const agentPrompt$3=new AgentPrompt;class PersonService{constructor(e){this.dialog=e,this.personMap={},this.objectMap={},this.PromptTplPersonRelationCode="person-relation-tpl"}async loadPersonById(e){if(this.personMap[e])return this.personMap[e];let t=new Parse__default.Query("Person");t.include("userVerify");let n=await t.get(e);return n?.id&&(this.personMap[e]=n),n}async loadObjectById(e,t,n){if(this.objectMap[t])return this.objectMap[t];let o=new Parse__default.Query(e);o.include(...n);let i=await o.get(t);return i?.id&&(this.objectMap[t]=i),i}test(){return new Promise((e=>{}))}async loadSelfPerson(){let e=new Parse__default.Query("Person");return e.notEqualTo("isDeleted",!0),e.include("userVerify"),e.equalTo("userVerify",Parse__default.User.current()?.id),await e.first()}async queryOwnPerson(e){let t=Parse__default.User.current();if(!t?.id)return[];let n=new Parse__default.Query("Person");n.include("userVerify"),n.notEqualTo("isDeleted",!0),n.notEqualTo("userVerify",t?.id),n.equalTo("creator",t?.id),n.addDescending("updatedAt"),e?.roleTags.length>0&&n.containedIn("tags",e?.roleTags);let o=await n.find();return o.forEach((e=>this.personMap[e?.id]=e)),o}async queryAuthPerson(e){let t=Parse__default.User.current();if(!t?.id)return[];let n={};e?.roleTags?.length>0&&(n.person={$inQuery:{where:{tags:{$in:e?.roleTags}},className:"Person"}});let o=Parse__default.Query.fromJSON("PersonAuthor",{where:n});o.include("person","person.userVerify"),o.notEqualTo("isDeleted",!0),o.equalTo("isVerified",!0),o.equalTo("user",t?.id),o.addDescending("updatedAt");let i=await o.find();return i.forEach((e=>this.personMap[e?.id]=e.get("person"))),i}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PersonService,deps:[{token:i3$1.MatDialog}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PersonService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PersonService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i3$1.MatDialog}]}),addIcons({maleOutline:maleOutline,femaleOutline:femaleOutline,helpCircleOutline:helpCircleOutline});class CompPersonGenderIconComponent{constructor(){this.gender="unknown",this.genderIcon={male:"male-outline",female:"female-outline",unknown:"help-circle-outline"},this.genderColor={male:"#2196F3",female:"#E91E63",unknown:"#616161"}}ngOnInit(){if(this.person){let e=this.person?.get("gender")||this.person?.get("userVerify")?.get("gender")||this.person?.get("userVerify")?.get("sex");if("男"==e||"male"==e||!0===e)return void(this.gender="male");if("女"==e||"female"==e||!1===e)return void(this.gender="female");this.gender="unknown"}}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPersonGenderIconComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompPersonGenderIconComponent,isStandalone:!0,selector:"fm-comp-person-gender-icon",inputs:{person:"person"},ngImport:i0,template:'<ion-icon [name]="genderIcon[gender]" [style.color]="genderColor[gender]"></ion-icon>',styles:[""],dependencies:[{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPersonGenderIconComponent,decorators:[{type:Component,args:[{selector:"fm-comp-person-gender-icon",standalone:!0,imports:[NgIf,IonIcon],template:'<ion-icon [name]="genderIcon[gender]" [style.color]="genderColor[gender]"></ion-icon>'}]}],ctorParameters:()=>[],propDecorators:{person:[{type:Input}]}});class CompPersonItemComponent{constructor(){this.defaultAvatar="/assets/img/icon/avatar.svg"}ngOnInit(){}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPersonItemComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompPersonItemComponent,isStandalone:!0,selector:"fm-comp-person-item",inputs:{person:"person"},ngImport:i0,template:"<ion-item button *ngIf=\"person\">\n <ion-avatar>\n <ion-img [src]=\"person?.get('avatar') || person?.get('userVerify')?.get('avatar') ||defaultAvatar\"></ion-img>\n </ion-avatar>\n <ion-label>\n <h2>{{person?.get('name')}}<fm-comp-person-gender-icon [person]=\"person\"></fm-comp-person-gender-icon></h2>\n <p><span>{{person?.get(\"tags\")}}</span></p>\n </ion-label>\n</ion-item>",styles:["ion-label h2,ion-label p{color:#fff}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{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:IonAvatar,selector:"ion-avatar"},{kind:"component",type:IonImg,selector:"ion-img",inputs:["alt","src"]},{kind:"component",type:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:CompPersonGenderIconComponent,selector:"fm-comp-person-gender-icon",inputs:["person"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPersonItemComponent,decorators:[{type:Component,args:[{selector:"fm-comp-person-item",standalone:!0,imports:[CommonModule,IonItem,IonIcon,IonAvatar,IonImg,IonLabel,CompPersonGenderIconComponent],template:"<ion-item button *ngIf=\"person\">\n <ion-avatar>\n <ion-img [src]=\"person?.get('avatar') || person?.get('userVerify')?.get('avatar') ||defaultAvatar\"></ion-img>\n </ion-avatar>\n <ion-label>\n <h2>{{person?.get('name')}}<fm-comp-person-gender-icon [person]=\"person\"></fm-comp-person-gender-icon></h2>\n <p><span>{{person?.get(\"tags\")}}</span></p>\n </ion-label>\n</ion-item>",styles:["ion-label h2,ion-label p{color:#fff}\n"]}]}],ctorParameters:()=>[],propDecorators:{person:[{type:Input}]}});class EditUploadComponent{get file(){return this._file}set file(e){this._file=e,this.fileChange.emit(e)}addToFileList(e){this.fileList||(this.fileList=[]),this.fileList.find((t=>t==e))||this.fileList.push(e),this.fileListChange.emit(this.fileList)}get files(){return this._files}set files(e){this._files=e}async queryDomain(){let e=new Parse__default.Query("Company"),t=await e.get(this.getBelongId());t.get("configQiniu")&&t.get("configQiniu").domain?(console.log(t.get("configQiniu").domain),this.qiniuDomain=t.get("configQiniu").domain):this.qiniuDomain="https://file-cloud.fmode.cn"}constructor(e){this.uploadServ=e,this.dragdrop=!1,this.multi=!1,this.max_file_size=100,this.type="image",this.onFilesChange=new EventEmitter,this.avatarType="",this.inputType=null,this.fileChange=new EventEmitter,this.fileList=[],this.fileListChange=new EventEmitter,this.path="camera",this.isCapacitor=!1,this.zoneUrl="https://upload-z2.qiniup.com/",this.hashid=this.uuid(),this.mime_types=[{title:"",extensions:"jpg,gif,png,bmp,jpeg"}],this.imgShowing=!1,this.isCapacitor=this.uploadServ.isCapacitor(),this.local=window.location.pathname,this.listenToUploader()}ngOnInit(){this.queryDomain(),"more"==this.avatarType&&(this.multi=!0),console.log(this._files)}async takeFromCamera(){let e=await this.getUptoken();if("image"==this.type)try{let t=await this.uploadServ.takePicture(e);this.currentKey=t.key,await this.setFiles(t)}catch(e){console.error(e),console.error(JSON.stringify(e))}if("video"==this.type){let t=await this.uploadServ.captureVideo(e);this.currentKey=t.key,await this.setFiles(t)}}ngAfterViewInit(){null==this.files&&(this.files=[]),this.uploaderType(),this.upable()&&this.getUptoken().then((e=>{this.uptoken=e.uptoken,this.domain=e.domain,this.initUploader(e.uptoken,e.domain)}))}async getUptoken(){return this.qiniuConf?.uptoken||(this.qiniuConf=await Parse__default.Cloud.run("qiniu_uptoken",{company:this.getBelongId()}),this.zoneUrl=this.qiniuConf?.zoneUrl),this.qiniuConf}checkFileType(e){if(e&&"string"==typeof e){if(e.endsWith("png"))return"image";if(e.endsWith("jpg"))return"image";if(e.endsWith("jpeg"))return"image";if(e.endsWith("gif"))return"image"}if(e&&"string"==typeof e){if(e.endsWith("mp4"))return"video";if(e.endsWith("webm"))return"video";if(e.endsWith("ogg"))return"video"}return"file"}upable(){return""!=this.type}showFile(e){console.log(123),this.fileUrl=e,this.imgShowing=!0}closeShowModal(){this.imgShowing=!1}async setFiles(e){if((this._files&&0==this._files.length||this.multi)&&e&&e.url){let t=e.url;e.url.indexOf("undefined")>-1&&(t=(this.qiniuDomain?this.qiniuDomain:"https://file-cloud.fmode.cn/")+e.url.replace("undefined/","")),this.files=t,this.file=t,this.addToFileList(t),this.currentKey&&await this.uploadServ.saveAttachment(e,this.qiniuDomain,null,this.getBelongId()),this.dragdrop=!1}}deleteFile(e){let t=this._files?.length&&this._files?.findIndex&&this._files?.findIndex((t=>t==e));-1!=t&&this._files?.splice&&this._files?.splice(t,1);let n=this.fileList?.findIndex((t=>t==e));-1!=n&&(this.fileList.splice(n,1),this.fileListChange.emit(this.fileList)),this.file=void 0}listenToUploader(){console.log(123),document.addEventListener("uploader"+this.hashid+".onprogress",(e=>{console.log(123),this.setFiles(e.detail.file),this.setFiles(e.detail.file.percent)}),!1),document.addEventListener("uploader"+this.hashid+".fileuploaded",(e=>{this.setFiles(e.detail.file)}),!1)}uploaderType(){switch(console.log(this.type),this.type){case"image":this.mime_types=[{title:"Image files",extensions:"jpg,gif,png,webp,jpeg"}];break;case"attachment":this.mime_types=[{title:"Image files",extensions:"jpg,gif,png,webp,jpeg"},{title:"Attachment files",extensions:"pdf,doc,docx,xls,md,txt,json"},{title:"Zip files",extensions:"zip,7z,tar.gz,rar"}];break;case"video":this.mime_types=[{title:"Video files",extensions:"flv,mpg,mpeg,avi,wmv,mov,asf,rm,rmvb,mkv,m4v,mp4"}]}}getBelongId(){if(this.company)return this.company;return window.localStorage.getItem("company")}initUploader(e,t){let n=this,o=this.hashid;this.uploader=new plupload.Uploader({runtimes:"html5,html4",browse_button:"pickfiles_button_"+this.hashid,url:this.zoneUrl,multipart_params:{token:e},container:"dragdrop_container_"+this.hashid,filters:{max_file_size:this.max_file_size+"mb",prevent_duplicates:!0,mime_types:this.mime_types},max_retries:3,multi_selection:this.multi,drop_element:"dragdrop_container_"+this.hashid,chunk_size:"4mb",init:{BeforeUpload:function(t,o){"more"==n.avatarType?n.files.push(o):n.files=[];let i=n.uploadServ.genFileKey(o,n.getBelongId());n.currentKey=i,n.uploader.setOption({multipart_params:{token:e,key:i}})},UploadProgress:function(e,t){let n=new CustomEvent("uploader"+o+".onprogress",{detail:{up:e,file:t}});document.dispatchEvent(n)},FileUploaded:function(e,t,i){console.log("成功",e,t,i);let a=e.getOption("domain")+"/"+JSON.parse(i.response).key;t.url=a;let r=new CustomEvent("uploader"+o+".fileuploaded",{detail:{up:e,file:t,info:i}});document.dispatchEvent(r),console.log(n.files)},UploadComplete:function(){"more"!=n.avatarType&&(n.uploader.files=[])}}}),this.uploader.init(),this.uploader.bind("FilesAdded",(function(e,t){console.log(123),n.uploader.start()})),this.uploader.bind("FilesAdded",(function(e,t){}))}uuid(){let e=[],t="0123456789abcdef";for(let n=0;n<36;n++)e[n]=t.substr(Math.floor(16*Math.random()),1);return e[14]="4",e[19]=t.substr(3&e[19]|8,1),e[8]=e[13]=e[18]=e[23]="-",e.join("")}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:EditUploadComponent,deps:[{token:NovaUploadService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:EditUploadComponent,selector:"fm-edit-upload",inputs:{_files:["files","_files"],dragdrop:"dragdrop",multi:"multi",max_file_size:"max_file_size",type:"type",avatarType:"avatarType",company:"company",_file:["file","_file"],fileList:"fileList",path:"path"},outputs:{onFilesChange:"filesChange",fileChange:"fileChange",fileListChange:"fileListChange"},ngImport:i0,template:'\x3c!-- 预览图片:行内列表 --\x3e\n<ng-container *ngFor="let f of fileList">\n <div class="file-item" [ngSwitch]="checkFileType(f)">\n \x3c!-- 图片显示 --\x3e\n <div class="item" *ngSwitchCase="\'image\'">\n <img (click)="showFile(f)" style="width:100px;height:100px;" *ngIf="f" [src]="f+\'?imageView2/1/w/200/h/200\'"\n alt="" />\n <button (click)="deleteFile(f)" *ngIf="upable()" nzSize=\'small\' nz-button nzType="danger" nzShape="circle">\n <i style="width: 10px; height: 10px;" nz-icon nzType="close"></i>\n </button>\n </div>\n \x3c!-- 视频显示 --\x3e\n <div class="item" *ngSwitchCase="\'video\'">\n <video (click)="showFile(f)" style="width:100px;height:100px;" autoplay *ngIf="f" [src]="f"\n alt="">\n </video>\n <button (click)="deleteFile(f)" *ngIf="upable()" nzSize=\'small\' nz-button nzType="danger" nzShape="circle">\n <i style="width: 10px; height: 10px;" nz-icon nzType="close"></i>\n </button>\n </div>\n \x3c!-- 文件显示 --\x3e\n <div *ngSwitchDefault>\n <i style="width:100px;height:100px;" nz-icon [nzType]="\'file\'" [nzTheme]="\'twotone\'" style="font-size: 4.4em;"></i>\n </div>\n\n \x3c!-- 删除按钮 --\x3e\n \n </div>\n</ng-container>\n\n\x3c!-- 上传控件:相机/拍摄 (Capacitor端) --\x3e\n<div (click)="takeFromCamera()" [ngStyle]="{\'display\':isCapacitor && path == \'camera\' ?\'flex\':\'none\',\'width\':(fileList?.length==0 || multi)?\'100px\':\'0%\'}" class="divupload file-item">\n <div [ngStyle]="{\'width\':(fileList?.length==0 || multi)?\'100%\':\'0%\'}">\n <div class="plus" [class.capacitor]="isCapacitor">\n <span *ngIf="fileList?.length==0 || multi" nz-icon nzType="plus" nzTheme="outline"></span>\n </div>\n </div>\n</div>\n\x3c!-- 上传控件:点击/拖拽 (Web端) --\x3e\n\x3c!-- 通过样式切换显示,不可用ngIf会导致id绑定上传函数失效 --\x3e\n<div [ngStyle]="{\'display\':isCapacitor && path == \'camera\' ?\'none\':\'flex\',\'width\':(fileList?.length==0 || multi)?\'100px\':\'0%\'}" id="dragdrop_container_{{hashid}}" class="divupload file-item">\n <div [ngStyle]="{\'width\':(fileList?.length==0 || multi)?\'100%\':\'0%\'}" id="pickfiles_button_{{hashid}}">\n <div class="plus">\n <span *ngIf="fileList?.length==0 || multi" nz-icon nzType="plus" nzTheme="outline"></span>\n </div>\n </div>\n</div>\n\n\x3c!-- 预览区域:图片放大 --\x3e\n<div *ngIf="imgShowing" (click)="closeShowModal()"\nstyle="position:fixed;top:0px;left:0px;width:100%;height:100%;z-index:65535;\n background-color: rgba(0,0,0,0.6);text-align: center;">\n <div style="width:90%;margin-left:5%;margin-top:1%;color:#fff;\n font-size:30px;border:1px #FFF solid;border-radius: 5px;">退出预览</div>\n\n <img *ngIf="checkFileType(fileUrl)==\'image\'" style="height:90%;margin-left:5%;margin-top:1%;background:#fff;" [src]="fileUrl?fileUrl:\'assets/icon/nouser.png\'" alt="">\n <video *ngIf="fileUrl&&checkFileType(fileUrl)==\'video\'" autoplay style="max-height:90%;max-width: 80%;margin-left:5%;margin-top:1%;background:#fff;" [src]="fileUrl" alt=""></video>\n \n</div>',styles:[".file-item{float:left;height:100px;display:flex}.file-item .plus{width:100px;height:100px;display:flex;justify-content:center;align-items:center;align-content:center}.file-item .plus span{flex:100%;align-items:center;align-content:center}.file-item .capacitor{display:flex;justify-content:center}.file-item .capacitor span{position:relative;margin-left:-70px;margin-top:-70px}.file-item .item{position:relative}.file-item .item button{position:absolute;top:-11px;left:82px;display:flex;justify-content:center;align-items:center}.divupload{height:100px;width:100px;background-color:#ededed}.divupload div{height:100%}.divupload span{color:#909090;font-size:30px;position:absolute;left:35px;top:35px}.img{height:100px;width:100px;cursor:pointer}\n"],dependencies:[{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:i2.NgStyle,selector:"[ngStyle]",inputs:["ngStyle"]},{kind:"directive",type:i2.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:i2.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:i2.NgSwitchDefault,selector:"[ngSwitchDefault]"},{kind:"component",type:i3$4.NzButtonComponent,selector:"button[nz-button], a[nz-button]",inputs:["nzBlock","nzGhost","nzSearch","nzLoading","nzDanger","disabled","tabIndex","nzType","nzShape","nzSize"],exportAs:["nzButton"]},{kind:"directive",type:i4$1.ɵNzTransitionPatchDirective,selector:"[nz-button], nz-button-group, [nz-icon], [nz-menu-item], [nz-submenu], nz-select-top-control, nz-select-placeholder, nz-input-group",inputs:["hidden"]},{kind:"directive",type:i5$3.NzWaveDirective,selector:'[nz-wave],button[nz-button]:not([nzType="link"]):not([nzType="text"])',inputs:["nzWaveExtraNode"],exportAs:["nzWave"]},{kind:"directive",type:i6$1.NzIconDirective,selector:"[nz-icon]",inputs:["nzSpin","nzRotate","nzType","nzTheme","nzTwotoneColor","nzIconfont"],exportAs:["nzIcon"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:EditUploadComponent,decorators:[{type:Component,args:[{selector:"fm-edit-upload",template:'\x3c!-- 预览图片:行内列表 --\x3e\n<ng-container *ngFor="let f of fileList">\n <div class="file-item" [ngSwitch]="checkFileType(f)">\n \x3c!-- 图片显示 --\x3e\n <div class="item" *ngSwitchCase="\'image\'">\n <img (click)="showFile(f)" style="width:100px;height:100px;" *ngIf="f" [src]="f+\'?imageView2/1/w/200/h/200\'"\n alt="" />\n <button (click)="deleteFile(f)" *ngIf="upable()" nzSize=\'small\' nz-button nzType="danger" nzShape="circle">\n <i style="width: 10px; height: 10px;" nz-icon nzType="close"></i>\n </button>\n </div>\n \x3c!-- 视频显示 --\x3e\n <div class="item" *ngSwitchCase="\'video\'">\n <video (click)="showFile(f)" style="width:100px;height:100px;" autoplay *ngIf="f" [src]="f"\n alt="">\n </video>\n <button (click)="deleteFile(f)" *ngIf="upable()" nzSize=\'small\' nz-button nzType="danger" nzShape="circle">\n <i style="width: 10px; height: 10px;" nz-icon nzType="close"></i>\n </button>\n </div>\n \x3c!-- 文件显示 --\x3e\n <div *ngSwitchDefault>\n <i style="width:100px;height:100px;" nz-icon [nzType]="\'file\'" [nzTheme]="\'twotone\'" style="font-size: 4.4em;"></i>\n </div>\n\n \x3c!-- 删除按钮 --\x3e\n \n </div>\n</ng-container>\n\n\x3c!-- 上传控件:相机/拍摄 (Capacitor端) --\x3e\n<div (click)="takeFromCamera()" [ngStyle]="{\'display\':isCapacitor && path == \'camera\' ?\'flex\':\'none\',\'width\':(fileList?.length==0 || multi)?\'100px\':\'0%\'}" class="divupload file-item">\n <div [ngStyle]="{\'width\':(fileList?.length==0 || multi)?\'100%\':\'0%\'}">\n <div class="plus" [class.capacitor]="isCapacitor">\n <span *ngIf="fileList?.length==0 || multi" nz-icon nzType="plus" nzTheme="outline"></span>\n </div>\n </div>\n</div>\n\x3c!-- 上传控件:点击/拖拽 (Web端) --\x3e\n\x3c!-- 通过样式切换显示,不可用ngIf会导致id绑定上传函数失效 --\x3e\n<div [ngStyle]="{\'display\':isCapacitor && path == \'camera\' ?\'none\':\'flex\',\'width\':(fileList?.length==0 || multi)?\'100px\':\'0%\'}" id="dragdrop_container_{{hashid}}" class="divupload file-item">\n <div [ngStyle]="{\'width\':(fileList?.length==0 || multi)?\'100%\':\'0%\'}" id="pickfiles_button_{{hashid}}">\n <div class="plus">\n <span *ngIf="fileList?.length==0 || multi" nz-icon nzType="plus" nzTheme="outline"></span>\n </div>\n </div>\n</div>\n\n\x3c!-- 预览区域:图片放大 --\x3e\n<div *ngIf="imgShowing" (click)="closeShowModal()"\nstyle="position:fixed;top:0px;left:0px;width:100%;height:100%;z-index:65535;\n background-color: rgba(0,0,0,0.6);text-align: center;">\n <div style="width:90%;margin-left:5%;margin-top:1%;color:#fff;\n font-size:30px;border:1px #FFF solid;border-radius: 5px;">退出预览</div>\n\n <img *ngIf="checkFileType(fileUrl)==\'image\'" style="height:90%;margin-left:5%;margin-top:1%;background:#fff;" [src]="fileUrl?fileUrl:\'assets/icon/nouser.png\'" alt="">\n <video *ngIf="fileUrl&&checkFileType(fileUrl)==\'video\'" autoplay style="max-height:90%;max-width: 80%;margin-left:5%;margin-top:1%;background:#fff;" [src]="fileUrl" alt=""></video>\n \n</div>',styles:[".file-item{float:left;height:100px;display:flex}.file-item .plus{width:100px;height:100px;display:flex;justify-content:center;align-items:center;align-content:center}.file-item .plus span{flex:100%;align-items:center;align-content:center}.file-item .capacitor{display:flex;justify-content:center}.file-item .capacitor span{position:relative;margin-left:-70px;margin-top:-70px}.file-item .item{position:relative}.file-item .item button{position:absolute;top:-11px;left:82px;display:flex;justify-content:center;align-items:center}.divupload{height:100px;width:100px;background-color:#ededed}.divupload div{height:100%}.divupload span{color:#909090;font-size:30px;position:absolute;left:35px;top:35px}.img{height:100px;width:100px;cursor:pointer}\n"]}]}],ctorParameters:()=>[{type:NovaUploadService}],propDecorators:{_files:[{type:Input,args:["files"]}],dragdrop:[{type:Input}],multi:[{type:Input}],max_file_size:[{type:Input,args:["max_file_size"]}],type:[{type:Input}],onFilesChange:[{type:Output,args:["filesChange"]}],avatarType:[{type:Input,args:["avatarType"]}],company:[{type:Input}],_file:[{type:Input,args:["file"]}],fileChange:[{type:Output}],fileList:[{type:Input}],fileListChange:[{type:Output}],path:[{type:Input}]}});class EditUploadModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:EditUploadModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:EditUploadModule,declarations:[EditUploadComponent],imports:[CommonModule,FormsModule,NzButtonModule,NzIconModule],exports:[EditUploadComponent]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:EditUploadModule,providers:[DatePipe,Platform,Diagnostic,NovaUploadService],imports:[CommonModule,FormsModule,NzButtonModule,NzIconModule]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:EditUploadModule,decorators:[{type:NgModule,args:[{declarations:[EditUploadComponent],imports:[CommonModule,FormsModule,NzButtonModule,NzIconModule],exports:[EditUploadComponent],providers:[DatePipe,Platform,Diagnostic,NovaUploadService]}]}]});class SecretTextPipe{transform(e,...t){if(!e)return"";console.log(e,t);let n=t[0],o=1,i=0;"idcard"==n&&(o=3,i=2),"mobile"==n&&(o=3,i=4);let a=Array.from(e);return a=a.map(((e,t)=>t<o||t+1>a.length-i?e:"*")),a.join("")}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:SecretTextPipe,deps:[],target:i0.ɵɵFactoryTarget.Pipe})}static{this.ɵpipe=i0.ɵɵngDeclarePipe({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:SecretTextPipe,isStandalone:!0,name:"secretText"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:SecretTextPipe,decorators:[{type:Pipe,args:[{name:"secretText",standalone:!0}]}]});class ModalUserVerifyComponent{constructor(e,t,n,o,i,a){this.http=e,this.message=t,this.novaAccount=n,this.authServ=o,this.novaCloud=i,this.modalCtrl=a,this.isVisible=!1,this.isVisibleChange=new EventEmitter,this.verifyOptions={idcard:!1,student:!1,bankcard:!1,autoFinish:!0},this.verifyResult={},this.isLoading=!0,this.tab="idcard",this.company="",this.idcard="",this.idcardData={},this.name="",this.sex="",this.idcard_image_front="",this.idcard_image_back="",this.identity_auth=!1,this.studentDateil={studentID:"",mobile:"",school:"",schoolMajor:"",studentType:"毕业",education:"本科",workUnit:"",workid:"",diploma:"",degreeNumber:"",entrySchool:2023,college:""},this.eduImage="",this.bankMap={bank:"",bankcard:"",bankmobile:""},this.options=[],this.bankOptions=["招商银行","工商银行","农业银行","中国银行","建设银行","交通银行","邮政储蓄银行","农商银行","中信银行","光大银行","华夏银行","广发银行","平安银行","浦发银行","兴业银行","民生银行","恒丰银行","浙商银行","渤海银行"]}veifyFinishBack(){let e=!1;this.verifyOptions&&Object.keys(this.verifyOptions).forEach((t=>{"autoFinish"!=t&&this.verifyOptions?.[t]&&(this.verifyResult?.[t]||(e=!0))}));let t=Parse__default.User.current(),n=!1;t?.get("sex")!=this.profile?.get("sex")&&(t?.set("sex",this.profile?.get("sex")),n=!0),t?.get("realname")!=this.profile?.get("name")&&(t?.set("realname",this.profile?.get("name")),n=!0),n&&t?.save(),this.verifyOptions?.autoFinish&&(e||this.modalCtrl.dismiss({verifyResult:this.verifyResult,profile:this.profile,account:this.account},"confirm"))}async ngOnInit(){this.company=this.authServ.company||localStorage.getItem("company")||"",await this.novaAccount.getProfile(),this.getOptions(),this.getProfile(),await this.getAccount(),this.veifyFinishBack(),this.isLoading=!1,this.onBreakPointSet&&this.onBreakPointSet(.75)}getOptions(){let e=(new Date).getFullYear();for(let t=e-20;t<=e;t++)this.options.unshift(t)}async getProfile(){let e=this.novaAccount.profile;console.log(e),e?.id&&(this.profile=e,this.studentDateil={studentID:e?.get("studentID"),mobile:e?.get("mobile"),school:e?.get("school"),schoolMajor:e?.get("schoolMajor"),studentType:e?.get("studentType"),education:e?.get("education"),workUnit:e?.get("workUnit"),workid:e?.get("workid"),diploma:e?.get("diploma"),degreeNumber:e?.get("degreeNumber"),entrySchool:e?.get("entrySchool")?e.get("entrySchool").getFullYear():null,college:e?.get("college")},this.eduImage=e?.get("eduImage"),this.name=e?.get("name"),e?.get("isCheck")&&(this.idcard=e?.get("idcard"),this.sex=e?.get("sex"),this.idcard_image_front=e?.get("attachment")[0],this.idcard_image_back=e?.get("attachment")[1],this.verifyResult.idcard=!0))}async getAccount(){let e=Parse__default.User.current()?.id,t=new Parse__default.Query("Account");t.equalTo("user",e),t.equalTo("company",this.company),t.notEqualTo("isDeleted",!0),this.account=await t.first(),this.account?.id&&this.account?.get("bank")&&(this.bankMap=this.account.get("bank")?.[0]||{bank:"",bankcard:"",bankmobile:""},this.verifyResult.bankcard=!0)}onClose(){this.isVisibleChange.emit(!1)}async uploadChange(e,t){console.log(e,t);let n,o,i=e[0];switch(console.log(i),this[t]=i,t){case"idcard_image_front":n={company:this.company,image_url:i},o=await this.novaCloud.api("/apig/idcard/ocr",n),o&&o.cards[0]?.name&&o.cards[0]?.id_card_number?(this.name=o.cards[0].name,this.idcard=o.cards[0].id_card_number,this.sex=o.cards[0].gender,this.idcardData=o.cards[0]):this.message.create("error","未识别到身份信息,请确保身份证照片清晰不反光!");break;case"idcard_image_back":if(n={company:this.company,image_url:i},o=await this.novaCloud.api("/apig/idcard/ocr",n),o&&o.cards[0]?.side&&"back"==o.cards[0].side)return void(this.identity_auth=!0);this.message.create("error","未识别到身份信息,请确保身份证照片清晰不反光!")}}onDeleted(e){switch(this[e]="",e){case"idcard_image_front":this.name="",this.idcard="";break;case"idcard_image_back":this.identity_auth=!1}}authDisabled(){if(!this.verifyOptions?.idcard?.ocr)return!0;return!!(this.name&&this.idcard&&this.identity_auth)}authDisabledStudent(){return!0}async onSubmit(){if(!this.verifyOptions?.idcard?.ocr||this.name&&this.idcard&&this.identity_auth){let e={company:this.company,cardNo:this.idcard,realName:this.name},t=await this.novaCloud.api("/apig/idcard",e);if(console.log(t),t&&0===t?.error_code&&1==t?.result?.isok){let e=Parse__default.User.current()?.id,t=[];this.idcard_image_front&&t.push(this.idcard_image_front),this.idcard_image_back&&t.push(this.idcard_image_back);let n=new Parse__default.Query("Profile");n.equalTo("user",e),n.equalTo("company",this.company),n.notEqualTo("isDeleted",!0);let o=await n.first();if(!o?.id){o=new(Parse__default.Object.extend("Profile"))}o?.set("name",this.name),o?.set("idcard",this.idcard),o?.set("sex",this.sex),o?.set({city:this.idcardData?.city,area:[this.idcardData?.province,this.idcardData?.city,this.idcardData?.district],birthdate:this.idcardData?.birthday}),o?.set("company",{__type:"Pointer",className:"Company",objectId:this.company}),o?.set("user",{__type:"Pointer",className:"_User",objectId:e}),o?.set("attachment",t),o?.set("isCheck",!0),o?.get("type")||o?.set("type","user"),await(o?.save()),this.message.create("success","认证成功"),this.isVisibleChange.emit(!1),await this.novaAccount.getProfile(),this.profile=this.novaAccount.profile,this.verifyResult.idcard=!0}else this.message.create("error","认证失败:请检查身份信息是否正确。")}this.veifyFinishBack()}onChangeDate(e){console.log(e)}mobileStatus(e){return/^[1][3,4,5,6,7,8,9][0-9]{9}$/.test(e)?"":"error"}async onSubimtStudent(){let{studentID:e,mobile:t,school:n,schoolMajor:o,studentType:i,education:a,workUnit:r,workid:s,diploma:l,degreeNumber:c,entrySchool:d,college:p}=this.studentDateil;console.log(this.studentDateil);if(!(e&&t&&n&&this.name))return void this.message.create("error","认证失败:请检查信息填写是否完整。");if(!/^[1][3,4,5,7,8][0-9]{9}$/.test(t))return void this.message.create("error","认证失败:手机号格式错误。");let m=Parse__default.User.current()?.id,g=new Parse__default.Query("Profile");g.equalTo("user",m),g.equalTo("company",this.company),g.notEqualTo("isDeleted",!0);let u=await g.first();if(!u?.id){u=new(Parse__default.Object.extend("Profile"))}u?.set("name",this.name),u?.set("studentID",e),u?.set("mobile",t),u?.set("school",n),u?.set("college",p),u?.set("schoolMajor",o),u?.set("studentType",i),u?.set("education",a),u?.set("workUnit",String(r)),u?.set("workid",s),u?.set("eduImage",this.eduImage),u?.set("diploma",l),u?.set("degreeNumber",c),d&&"在校"!=i&&u?.set("entrySchool",new Date((new Date).setFullYear(d))),u?.set("company",{__type:"Pointer",className:"Company",objectId:this.company}),u?.set("user",{__type:"Pointer",className:"_User",objectId:m}),u?.get("type")||u?.set("type","student"),await(u?.save()),this.message.create("success","认证成功"),this.verifyResult.student=!0,this.isVisibleChange.emit(!1),await this.novaAccount.getProfile(),this.profile=this.novaAccount.profile,this.veifyFinishBack()}cardNoStatus(){return/^([1-9]{1})(\d{15}|\d{18})$/.test(this.bankMap.bankcard)?"":"error"}saveBankAuth(){return!(this.name&&this.idcard&&this.bankMap.bankcard&&this.bankMap.bankmobile)}async onSubimtBank(){if(!this.name||!this.idcard)return void this.message.create("error","请先完成实名或学生认证。");if(!this.bankMap.bankcard||!this.bankMap.bankmobile)return void this.message.create("error","请填写完整信息。");if(!/^([1-9]{1})(\d{15}|\d{18})$/.test(this.bankMap.bankcard))return void this.message.create("error","认证失败:请检查银行卡信息是否正确。");let e={company:this.company,bankcard:this.bankMap.bankcard.replace(/\s/g,""),name:this.name,idcard:this.idcard,mobile:this.bankMap.bankmobile},t=await this.novaCloud.api("/apig/bankcard",e);if(console.log(t),t&&200==t.code&&t?.success&&"一致"==t.data.msg){let e=t.data.bank_info,n=Parse__default.User.current()?.id,o=new Parse__default.Query("Account");o.equalTo("user",n),o.equalTo("company",this.company),o.notEqualTo("isDeleted",!0);let i=await o.first();if(!i?.id){i=new(Parse__default.Object.extend("Profile"))}i?.set("company",{__type:"Pointer",className:"Company",objectId:this.company}),i?.set("user",{__type:"Pointer",className:"_User",objectId:n}),i?.set("bank",[{bank:e.bank,bankcard:this.bankMap.bankcard,bankmobile:this.bankMap.bankmobile,city:e.city}]),await(i?.save());let a=new Parse__default.Query("Profile");a.equalTo("user",n),a.equalTo("company",this.company),a.notEqualTo("isDeleted",!0),a.select("objectId");let r=await a.first();if(!r?.id){r=new(Parse__default.Object.extend("Profile"))}r?.set("company",{__type:"Pointer",className:"Company",objectId:this.company}),r?.set("user",{__type:"Pointer",className:"_User",objectId:n}),r?.set("cardtype",e.bank),r?.set("cardnum",this.bankMap.bankcard),r?.set("nativePlace",e.city),await(r?.save()),this.message.create("success","认证成功"),this.verifyResult.bankcard=!0,this.isVisibleChange.emit(!1),this.veifyFinishBack()}else this.message.create("error","认证失败:请检查银行卡信息是否正确。")}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalUserVerifyComponent,deps:[{token:i1.HttpClient},{token:i2$2.NzMessageService},{token:AccountService},{token:AuthService},{token:NovaCloudService},{token:i1$3.ModalController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:ModalUserVerifyComponent,isStandalone:!0,selector:"app-user-verify",inputs:{isVisible:"isVisible",verifyOptions:"verifyOptions"},outputs:{isVisibleChange:"isVisibleChange"},ngImport:i0,template:'\n<ion-content *ngIf="isLoading">\n <div class="page" *ngIf="isLoading">\n <ion-spinner name="crescent" color="primary" style="width:80px;height:80px;"></ion-spinner>\n <ion-label color="primary">正在加载认证组件...</ion-label>\n </div>\n</ion-content>\n\n<ion-content class="ion-padding" *ngIf="!isLoading">\n <ion-segment [(ngModel)]="tab">\n <ion-segment-button *ngIf="verifyOptions?.idcard" value="idcard"><ion-icon name="card-outline"></ion-icon> 实名认证</ion-segment-button>\n <ion-segment-button *ngIf="verifyOptions?.student" value="student"><ion-icon name="school-outline"></ion-icon> 学生认证</ion-segment-button>\n <ion-segment-button *ngIf="verifyOptions?.bankcard" value="bankcard"><ion-icon name="wallet-outline"></ion-icon> 银行卡认证</ion-segment-button>\n </ion-segment>\n\n \x3c!-- <ng-container [ngTemplateOutlet]="rightAvatar"></ng-container> --\x3e\n <ng-container *ngIf="tab==\'idcard\'&&verifyOptions?.idcard">\n <ion-list>\n \x3c!-- 身份证OCR识别 --\x3e\n <ng-container *ngIf="verifyOptions?.idcard?.ocr">\n <ion-item>\n <ion-label><span class="required">*</span> 身份证正面</ion-label>\n <fm-edit-upload\n *ngIf="!idcard_image_front"\n [(file)]="idcard_image_front"\n [company]="company"\n (fileListChange)="uploadChange($event, \'idcard_image_front\')"\n ></fm-edit-upload>\n <ion-img *ngIf="idcard_image_front" [src]="idcard_image_front"></ion-img>\n </ion-item>\n <ion-item>\n <ion-label><span class="required">*</span> 身份证国徽面</ion-label>\n <fm-edit-upload\n *ngIf="!idcard_image_back"\n [(file)]="idcard_image_back"\n [company]="company"\n (fileListChange)="uploadChange($event, \'idcard_image_back\')"\n ></fm-edit-upload>\n <ion-img *ngIf="idcard_image_back" [src]="idcard_image_back"></ion-img>\n </ion-item>\n </ng-container>\n\n \x3c!-- 身份证手动输入 --\x3e\n <ng-container>\n <ion-item>\n @if (profile?.get(\'isCheck\')){\n <ion-input [ngModel]="name | secretText" label="姓名" [readonly]="true"></ion-input>\n }@else{\n <ion-input [(ngModel)]="name" label="姓名" [readonly]="verifyOptions?.idcard?.ocr" [placeholder]="verifyOptions?.idcard?.ocr?\'请上传身份证\':\'输入姓名\'"></ion-input>\n }\n </ion-item>\n\n <ion-item>\n @if (profile?.get(\'isCheck\')){\n <ion-input [ngModel]="idcard | secretText:\'idcard\'" label="身份证号" [readonly]="true"></ion-input>\n }@else{\n <ion-input [(ngModel)]="idcard" label="身份证号" [readonly]="verifyOptions?.idcard?.ocr" [placeholder]="verifyOptions?.idcard?.ocr?\'自动识别\':\'输入身份证号\'"></ion-input>\n }\n </ion-item>\n </ng-container>\n\n \x3c!-- 身份证认证状态 --\x3e\n <ion-button color="success" *ngIf="profile?.get(\'isCheck\'); else elseIdcard" expand="block">已实名</ion-button>\n <ng-template #elseIdcard>\n <ion-button color="primary" (click)="onSubmit()" [disabled]="!authDisabled()" expand="block">提交认证</ion-button>\n </ng-template>\n \n </ion-list>\n\n \x3c!-- <div class="tab-content">\n <div nz-row>\n <div nz-col nzSpan="12" class="li">\n <div class="label"><span>*</span> 身份证正面</div>\n <fm-edit-upload\n *ngIf="!idcard_image_front"\n [(file)]="idcard_image_front"\n [company]="company"\n (fileListChange)="uploadChange($event, \'idcard_image_front\')"\n ></fm-edit-upload>\n <div class="img-view" *ngIf="idcard_image_front">\n <span\n *ngIf="!profile?.get(\'isCheck\')"\n nz-icon\n nzType="close"\n nzTheme="outline"\n (click)="onDeleted(\'idcard_image_front\')"\n ></span>\n <img\n nz-image\n width="80px"\n height="80px"\n nzSrc="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"\n [nzSrc]="idcard_image_front"\n alt="身份证正面"\n />\n </div>\n </div>\n <div nz-col nzSpan="12" class="li">\n <div class="label"><span>*</span> 身份证国徽面</div>\n <fm-edit-upload\n *ngIf="!idcard_image_back"\n [(file)]="idcard_image_back"\n [company]="company"\n (fileListChange)="uploadChange($event, \'idcard_image_back\')"\n ></fm-edit-upload>\n <div class="img-view" *ngIf="idcard_image_back">\n <span\n *ngIf="!profile?.get(\'isCheck\')"\n nz-icon\n nzType="close"\n nzTheme="outline"\n (click)="onDeleted(\'idcard_image_back\')"\n ></span>\n <img\n nz-image\n width="80px"\n height="80px"\n nzSrc="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"\n [nzSrc]="idcard_image_back"\n alt="身份证国徽面"\n />\n </div>\n </div>\n </div>\n <div class="input-view">\n <nz-input-group nzAddOnBefore="姓名">\n <input\n type="text"\n nz-input\n [(ngModel)]="name"\n placeholder="请上传身份证"\n [disabled]="true"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="身份证号">\n <input\n type="text"\n nz-input\n [(ngModel)]="idcard"\n placeholder="请上传身份证"\n [disabled]="true"\n />\n </nz-input-group>\n </div>\n <div nz-row>\n <button\n nz-button\n *ngIf="profile && profile?.get(\'isCheck\'); else elseTemplate"\n nzType="primary"\n nzBlock\n [disabled]="true"\n >\n 已实名\n </button>\n <ng-template #elseTemplate>\n <button\n nz-button\n nzType="primary"\n nzBlock\n (click)="onSubmit()"\n [disabled]="!authDisabled()"\n >\n 确定\n </button>\n </ng-template>\n </div>\n </div> --\x3e\n\n </ng-container>\n\n <ng-container *ngIf="tab==\'student\'&&verifyOptions?.student">\n \n \n <div class="info">\n <div class="input-view">\n <nz-input-group nzAddOnBefore="姓名">\n <input\n type="text"\n nz-input\n [(ngModel)]="name"\n placeholder="请先完成实名认证"\n [disabled]="profile && profile?.get(\'isCheck\')"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="学信网账号">\n <input\n type="text"\n nz-input\n [(ngModel)]="studentDateil.studentID"\n placeholder="请填写学信网账号"\n [nzStatus]="studentDateil.studentID != \'\' ? \'\' : \'error\'"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="手机号">\n <input\n type="text"\n nz-input\n maxlength="11"\n [(ngModel)]="studentDateil.mobile"\n placeholder="请填写手机号"\n [nzStatus]="mobileStatus(studentDateil.mobile)"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="学校名称">\n <input\n type="text"\n nz-input\n [(ngModel)]="studentDateil.school"\n placeholder="请填写学校名称"\n [nzStatus]="studentDateil.school != \'\' ? \'\' : \'error\'"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="所属学院">\n <input\n type="text"\n nz-input\n [(ngModel)]="studentDateil.college"\n placeholder="请填写所属学院"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="专业名称">\n <input\n type="text"\n nz-input\n [(ngModel)]="studentDateil.schoolMajor"\n placeholder="请填写专业名称"\n />\n </nz-input-group>\n </div>\n <div class="info-row">\n <div class="info-row-lable">是否在校</div>\n <nz-radio-group [(ngModel)]="studentDateil.studentType">\n <label nz-radio nzValue="在校">是</label>\n <label nz-radio nzValue="毕业">否</label>\n </nz-radio-group>\n </div>\n <ng-container\n *ngIf="studentDateil.studentType == \'在校\'; else template1"\n >\n <div class="info-row">\n <div class="info-row-lable">阶段</div>\n <nz-radio-group [(ngModel)]="studentDateil.education">\n <label nz-radio nzValue="大专">大专</label>\n <label nz-radio nzValue="本科">本科</label>\n <label nz-radio nzValue="硕士">硕士</label>\n <label nz-radio nzValue="博士">博士</label>\n </nz-radio-group>\n </div>\n <div class="info-row">\n <div class="info-row-lable info-select">年级:</div>\n <ion-select\n interface="action-sheet"\n cancel-text="关闭"\n [(ngModel)]="studentDateil.workUnit"\n placeholder="点击选择"\n >\n <ng-container *ngFor="let item of options">\n <ion-select-option [value]="item"\n >{{ item }}级</ion-select-option\n >\n </ng-container>\n </ion-select>\n </div>\n <nz-input-group nzAddOnBefore="学生证号">\n <input\n type="text"\n nz-input\n [(ngModel)]="studentDateil.diploma"\n placeholder="请填写学生证号"\n />\n </nz-input-group>\n <div nz-row style="margin: 10px 0">\n <div nz-col nzSpan="12" class="li">\n <div class="label">\n <span style="color: red">*</span> 学生证照片\n </div>\n <fm-edit-upload\n *ngIf="!eduImage"\n [(file)]="eduImage"\n [company]="company"\n (fileListChange)="uploadChange($event, \'eduImage\')"\n ></fm-edit-upload>\n <div class="img-view" *ngIf="eduImage">\n <span\n *ngIf="!profile?.get(\'isCross\')"\n nz-icon\n nzType="close"\n nzTheme="outline"\n (click)="onDeleted(\'eduImage\')"\n ></span>\n <img\n nz-image\n width="100px"\n height="100px"\n nzSrc="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"\n [nzSrc]="eduImage"\n alt="学生证照片"\n />\n </div>\n </div>\n </div>\n </ng-container>\n <ng-template #template1>\n <div class="info-row">\n <div class="info-row-lable">最高学历</div>\n <nz-radio-group [(ngModel)]="studentDateil.education">\n <label nz-radio nzValue="大专">大专</label>\n <label nz-radio nzValue="学士">学士</label>\n <label nz-radio nzValue="硕士">硕士</label>\n <label nz-radio nzValue="博士">博士</label>\n </nz-radio-group>\n </div>\n <div class="info-row">\n <div class="info-row-lable info-select">毕业年份:</div>\n <ion-select\n interface="action-sheet"\n cancel-text="关闭"\n [(ngModel)]="studentDateil.entrySchool"\n placeholder="点击选择"\n >\n <ng-container *ngFor="let item of options">\n <ion-select-option [value]="item"\n >{{ item }}年</ion-select-option\n >\n </ng-container>\n </ion-select>\n </div>\n <nz-input-group nzAddOnBefore="毕业证号">\n <input\n type="text"\n nz-input\n [(ngModel)]="studentDateil.degreeNumber"\n placeholder="请填写毕业证号"\n />\n </nz-input-group>\n </ng-template>\n <div nz-row style="margin: 10px auto">\n <button\n nz-button\n nzType="primary"\n nzBlock\n (click)="onSubimtStudent()"\n [disabled]="false"\n >\n 确定\n </button>\n </div>\n </div>\n </ng-container>\n\n <ng-container *ngIf="tab==\'bankcard\'&&verifyOptions?.bankcard">\n \n \n <div class="info">\n <div class="input-view">\n <nz-input-group nzAddOnBefore="姓名">\n <input\n type="text"\n nz-input\n [(ngModel)]="name"\n placeholder="请先完成实名认证"\n [disabled]="true"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="身份证号">\n <input\n type="text"\n nz-input\n [(ngModel)]="idcard"\n placeholder="请先完成实名认证"\n [disabled]="true"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="银行卡账号">\n <input\n type="text"\n nz-input\n [(ngModel)]="bankMap.bankcard"\n placeholder="请填写银行卡账号"\n [nzStatus]="cardNoStatus()"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="银行卡预留手机号">\n <input\n type="text"\n nz-input\n [(ngModel)]="bankMap.bankmobile"\n maxlength="11"\n placeholder="请填写银行卡预留手机号"\n [nzStatus]="mobileStatus(bankMap.bankmobile)"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="开户行">\n <input\n type="text"\n nz-input\n [ngModel]="bankMap.bank"\n maxlength="11"\n placeholder="认证成功后自动识别"\n [disabled]="true"\n />\n </nz-input-group>\n \x3c!-- <div class="info-row">\n <div class="info-row-lable info-select">开户行:</div>\n <ion-select\n interface="action-sheet"\n cancel-text="关闭"\n [(ngModel)]="bankMap.bank"\n placeholder="点击选择"\n >\n <ng-container *ngFor="let item of bankOptions">\n <ion-select-option [value]="item"\n >{{ item }}</ion-select-option\n >\n </ng-container>\n </ion-select>\n </div> --\x3e\n </div>\n <div nz-row>\n <button\n nz-button\n nzType="primary"\n nzBlock\n (click)="onSubimtBank()"\n [disabled]="saveBankAuth()"\n >\n 确定\n </button>\n </div>\n </div>\n </ng-container>\n\n\n\n</ion-content>\n',styles:[".required{color:red}.page{display:flex;justify-content:center;align-items:center;flex-direction:column}.tab-content{width:80%;align-items:center;justify-content:center;margin:auto}.tab-content .li{display:flex;flex-direction:column;align-items:center}.tab-content .li .label{margin-bottom:10px}.tab-content .li .label span{color:red}.tab-content .li .img-view{position:relative}.tab-content .li .img-view span{position:absolute;right:-10px;top:0}.input-view{margin:10px auto}.info .info-row{display:flex;align-items:center;border:1px solid #d9d9d9;padding:6px 0}.info .info-row .info-row-lable{padding:0 10px;flex-shrink:0}.info .info-row .info-select{min-width:70px}.info .img-view{position:relative;width:100px}.info .img-view span{position:absolute;right:-10px;top:0}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i3$3.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.MaxLengthValidator,selector:"[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]",inputs:["maxlength"]},{kind:"directive",type:i3$3.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"ngmodule",type:NzInputModule},{kind:"directive",type:i8.NzInputDirective,selector:"input[nz-input],textarea[nz-input]",inputs:["nzBorderless","nzSize","nzStepperless","nzStatus","disabled"],exportAs:["nzInput"]},{kind:"component",type:i8.NzInputGroupComponent,selector:"nz-input-group",inputs:["nzAddOnBeforeIcon","nzAddOnAfterIcon","nzPrefixIcon","nzSuffixIcon","nzAddOnBefore","nzAddOnAfter","nzPrefix","nzStatus","nzSuffix","nzSize","nzSearch","nzCompact"],exportAs:["nzInputGroup"]},{kind:"ngmodule",type:NzIconModule},{kind:"directive",type:i6$1.NzIconDirective,selector:"[nz-icon]",inputs:["nzSpin","nzRotate","nzType","nzTheme","nzTwotoneColor","nzIconfont"],exportAs:["nzIcon"]},{kind:"ngmodule",type:NzTabsModule},{kind:"ngmodule",type:NzButtonModule},{kind:"component",type:i3$4.NzButtonComponent,selector:"button[nz-button], a[nz-button]",inputs:["nzBlock","nzGhost","nzSearch","nzLoading","nzDanger","disabled","tabIndex","nzType","nzShape","nzSize"],exportAs:["nzButton"]},{kind:"directive",type:i4$1.ɵNzTransitionPatchDirective,selector:"[nz-button], nz-button-group, [nz-icon], [nz-menu-item], [nz-submenu], nz-select-top-control, nz-select-placeholder, nz-input-group",inputs:["hidden"]},{kind:"directive",type:i5$3.NzWaveDirective,selector:'[nz-wave],button[nz-button]:not([nzType="link"]):not([nzType="text"])',inputs:["nzWaveExtraNode"],exportAs:["nzWave"]},{kind:"ngmodule",type:NzModalModule},{kind:"ngmodule",type:NzGridModule},{kind:"directive",type:i14.NzColDirective,selector:"[nz-col],nz-col,nz-form-control,nz-form-label",inputs:["nzFlex","nzSpan","nzOrder","nzOffset","nzPush","nzPull","nzXs","nzSm","nzMd","nzLg","nzXl","nzXXl"],exportAs:["nzCol"]},{kind:"directive",type:i14.NzRowDirective,selector:"[nz-row],nz-row,nz-form-item",inputs:["nzAlign","nzJustify","nzGutter"],exportAs:["nzRow"]},{kind:"ngmodule",type:NzRadioModule},{kind:"component",type:i15.NzRadioComponent,selector:"[nz-radio],[nz-radio-button]",inputs:["nzValue","nzDisabled","nzAutoFocus","nz-radio-button"],exportAs:["nzRadio"]},{kind:"component",type:i15.NzRadioGroupComponent,selector:"nz-radio-group",inputs:["nzDisabled","nzButtonStyle","nzSize","nzName"],exportAs:["nzRadioGroup"]},{kind:"ngmodule",type:NzImageModule},{kind:"directive",type:i16.NzImageDirective,selector:"img[nz-image]",inputs:["nzSrc","nzSrcset","nzDisablePreview","nzFallback","nzPlaceholder","nzScaleStep"],exportAs:["nzImage"]},{kind:"ngmodule",type:EditUploadModule},{kind:"component",type:EditUploadComponent,selector:"fm-edit-upload",inputs:["files","dragdrop","multi","max_file_size","type","avatarType","company","file","fileList","path"],outputs:["filesChange","fileChange","fileListChange"]},{kind:"component",type:IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:IonSegment,selector:"ion-segment",inputs:["color","disabled","mode","scrollable","selectOnFocus","swipeGesture","value"]},{kind:"component",type:IonSegmentButton,selector:"ion-segment-button",inputs:["contentId","disabled","layout","mode","type","value"]},{kind:"component",type:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonImg,selector:"ion-img",inputs:["alt","src"]},{kind:"component",type:IonSpinner,selector:"ion-spinner",inputs:["color","duration","name","paused"]},{kind:"component",type:IonList,selector:"ion-list",inputs:["inset","lines","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:IonInput,selector:"ion-input",inputs:["accept","autocapitalize","autocomplete","autocorrect","autofocus","clearInput","clearOnEdit","color","counter","counterFormatter","debounce","disabled","enterkeyhint","errorText","fill","helperText","inputmode","label","labelPlacement","max","maxlength","min","minlength","mode","multiple","name","pattern","placeholder","readonly","required","shape","size","spellcheck","step","type","value"]},{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:IonSelect,selector:"ion-select",inputs:["cancelText","color","compareWith","disabled","errorText","expandedIcon","fill","helperText","interface","interfaceOptions","justify","label","labelPlacement","mode","multiple","name","okText","placeholder","selectedText","shape","toggleIcon","value"]},{kind:"component",type:IonSelectOption,selector:"ion-select-option",inputs:["disabled","value"]},{kind:"pipe",type:SecretTextPipe,name:"secretText"}]})}}async function openUserVerifyModal(e,t,n){let o=n&&Object.keys(n)?.[0]||"idcard";null==n?.autoFinish&&n&&(n.autoFinish=!0);let i=await e.create({component:ModalUserVerifyComponent,componentProps:{verifyOptions:n,tab:o,onBreakPointSet:()=>{i?.setCurrentBreakpoint(.75)}},breakpoints:[.35,.75,1],initialBreakpoint:.35});i.present();let{data:a,role:r}=await i.onWillDismiss();if("confirm"==r)return a}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalUserVerifyComponent,decorators:[{type:Component,args:[{selector:"app-user-verify",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,NzInputModule,NzIconModule,NzTabsModule,NzButtonModule,NzModalModule,NzGridModule,NzRadioModule,NzImageModule,EditUploadModule,IonContent,IonSegment,IonSegmentButton,IonLabel,IonIcon,IonImg,IonSpinner,IonList,IonItem,IonInput,IonButton,IonDatetime,IonDatetimeButton,IonSelect,IonSelectOption,SecretTextPipe],template:'\n<ion-content *ngIf="isLoading">\n <div class="page" *ngIf="isLoading">\n <ion-spinner name="crescent" color="primary" style="width:80px;height:80px;"></ion-spinner>\n <ion-label color="primary">正在加载认证组件...</ion-label>\n </div>\n</ion-content>\n\n<ion-content class="ion-padding" *ngIf="!isLoading">\n <ion-segment [(ngModel)]="tab">\n <ion-segment-button *ngIf="verifyOptions?.idcard" value="idcard"><ion-icon name="card-outline"></ion-icon> 实名认证</ion-segment-button>\n <ion-segment-button *ngIf="verifyOptions?.student" value="student"><ion-icon name="school-outline"></ion-icon> 学生认证</ion-segment-button>\n <ion-segment-button *ngIf="verifyOptions?.bankcard" value="bankcard"><ion-icon name="wallet-outline"></ion-icon> 银行卡认证</ion-segment-button>\n </ion-segment>\n\n \x3c!-- <ng-container [ngTemplateOutlet]="rightAvatar"></ng-container> --\x3e\n <ng-container *ngIf="tab==\'idcard\'&&verifyOptions?.idcard">\n <ion-list>\n \x3c!-- 身份证OCR识别 --\x3e\n <ng-container *ngIf="verifyOptions?.idcard?.ocr">\n <ion-item>\n <ion-label><span class="required">*</span> 身份证正面</ion-label>\n <fm-edit-upload\n *ngIf="!idcard_image_front"\n [(file)]="idcard_image_front"\n [company]="company"\n (fileListChange)="uploadChange($event, \'idcard_image_front\')"\n ></fm-edit-upload>\n <ion-img *ngIf="idcard_image_front" [src]="idcard_image_front"></ion-img>\n </ion-item>\n <ion-item>\n <ion-label><span class="required">*</span> 身份证国徽面</ion-label>\n <fm-edit-upload\n *ngIf="!idcard_image_back"\n [(file)]="idcard_image_back"\n [company]="company"\n (fileListChange)="uploadChange($event, \'idcard_image_back\')"\n ></fm-edit-upload>\n <ion-img *ngIf="idcard_image_back" [src]="idcard_image_back"></ion-img>\n </ion-item>\n </ng-container>\n\n \x3c!-- 身份证手动输入 --\x3e\n <ng-container>\n <ion-item>\n @if (profile?.get(\'isCheck\')){\n <ion-input [ngModel]="name | secretText" label="姓名" [readonly]="true"></ion-input>\n }@else{\n <ion-input [(ngModel)]="name" label="姓名" [readonly]="verifyOptions?.idcard?.ocr" [placeholder]="verifyOptions?.idcard?.ocr?\'请上传身份证\':\'输入姓名\'"></ion-input>\n }\n </ion-item>\n\n <ion-item>\n @if (profile?.get(\'isCheck\')){\n <ion-input [ngModel]="idcard | secretText:\'idcard\'" label="身份证号" [readonly]="true"></ion-input>\n }@else{\n <ion-input [(ngModel)]="idcard" label="身份证号" [readonly]="verifyOptions?.idcard?.ocr" [placeholder]="verifyOptions?.idcard?.ocr?\'自动识别\':\'输入身份证号\'"></ion-input>\n }\n </ion-item>\n </ng-container>\n\n \x3c!-- 身份证认证状态 --\x3e\n <ion-button color="success" *ngIf="profile?.get(\'isCheck\'); else elseIdcard" expand="block">已实名</ion-button>\n <ng-template #elseIdcard>\n <ion-button color="primary" (click)="onSubmit()" [disabled]="!authDisabled()" expand="block">提交认证</ion-button>\n </ng-template>\n \n </ion-list>\n\n \x3c!-- <div class="tab-content">\n <div nz-row>\n <div nz-col nzSpan="12" class="li">\n <div class="label"><span>*</span> 身份证正面</div>\n <fm-edit-upload\n *ngIf="!idcard_image_front"\n [(file)]="idcard_image_front"\n [company]="company"\n (fileListChange)="uploadChange($event, \'idcard_image_front\')"\n ></fm-edit-upload>\n <div class="img-view" *ngIf="idcard_image_front">\n <span\n *ngIf="!profile?.get(\'isCheck\')"\n nz-icon\n nzType="close"\n nzTheme="outline"\n (click)="onDeleted(\'idcard_image_front\')"\n ></span>\n <img\n nz-image\n width="80px"\n height="80px"\n nzSrc="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"\n [nzSrc]="idcard_image_front"\n alt="身份证正面"\n />\n </div>\n </div>\n <div nz-col nzSpan="12" class="li">\n <div class="label"><span>*</span> 身份证国徽面</div>\n <fm-edit-upload\n *ngIf="!idcard_image_back"\n [(file)]="idcard_image_back"\n [company]="company"\n (fileListChange)="uploadChange($event, \'idcard_image_back\')"\n ></fm-edit-upload>\n <div class="img-view" *ngIf="idcard_image_back">\n <span\n *ngIf="!profile?.get(\'isCheck\')"\n nz-icon\n nzType="close"\n nzTheme="outline"\n (click)="onDeleted(\'idcard_image_back\')"\n ></span>\n <img\n nz-image\n width="80px"\n height="80px"\n nzSrc="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"\n [nzSrc]="idcard_image_back"\n alt="身份证国徽面"\n />\n </div>\n </div>\n </div>\n <div class="input-view">\n <nz-input-group nzAddOnBefore="姓名">\n <input\n type="text"\n nz-input\n [(ngModel)]="name"\n placeholder="请上传身份证"\n [disabled]="true"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="身份证号">\n <input\n type="text"\n nz-input\n [(ngModel)]="idcard"\n placeholder="请上传身份证"\n [disabled]="true"\n />\n </nz-input-group>\n </div>\n <div nz-row>\n <button\n nz-button\n *ngIf="profile && profile?.get(\'isCheck\'); else elseTemplate"\n nzType="primary"\n nzBlock\n [disabled]="true"\n >\n 已实名\n </button>\n <ng-template #elseTemplate>\n <button\n nz-button\n nzType="primary"\n nzBlock\n (click)="onSubmit()"\n [disabled]="!authDisabled()"\n >\n 确定\n </button>\n </ng-template>\n </div>\n </div> --\x3e\n\n </ng-container>\n\n <ng-container *ngIf="tab==\'student\'&&verifyOptions?.student">\n \n \n <div class="info">\n <div class="input-view">\n <nz-input-group nzAddOnBefore="姓名">\n <input\n type="text"\n nz-input\n [(ngModel)]="name"\n placeholder="请先完成实名认证"\n [disabled]="profile && profile?.get(\'isCheck\')"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="学信网账号">\n <input\n type="text"\n nz-input\n [(ngModel)]="studentDateil.studentID"\n placeholder="请填写学信网账号"\n [nzStatus]="studentDateil.studentID != \'\' ? \'\' : \'error\'"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="手机号">\n <input\n type="text"\n nz-input\n maxlength="11"\n [(ngModel)]="studentDateil.mobile"\n placeholder="请填写手机号"\n [nzStatus]="mobileStatus(studentDateil.mobile)"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="学校名称">\n <input\n type="text"\n nz-input\n [(ngModel)]="studentDateil.school"\n placeholder="请填写学校名称"\n [nzStatus]="studentDateil.school != \'\' ? \'\' : \'error\'"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="所属学院">\n <input\n type="text"\n nz-input\n [(ngModel)]="studentDateil.college"\n placeholder="请填写所属学院"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="专业名称">\n <input\n type="text"\n nz-input\n [(ngModel)]="studentDateil.schoolMajor"\n placeholder="请填写专业名称"\n />\n </nz-input-group>\n </div>\n <div class="info-row">\n <div class="info-row-lable">是否在校</div>\n <nz-radio-group [(ngModel)]="studentDateil.studentType">\n <label nz-radio nzValue="在校">是</label>\n <label nz-radio nzValue="毕业">否</label>\n </nz-radio-group>\n </div>\n <ng-container\n *ngIf="studentDateil.studentType == \'在校\'; else template1"\n >\n <div class="info-row">\n <div class="info-row-lable">阶段</div>\n <nz-radio-group [(ngModel)]="studentDateil.education">\n <label nz-radio nzValue="大专">大专</label>\n <label nz-radio nzValue="本科">本科</label>\n <label nz-radio nzValue="硕士">硕士</label>\n <label nz-radio nzValue="博士">博士</label>\n </nz-radio-group>\n </div>\n <div class="info-row">\n <div class="info-row-lable info-select">年级:</div>\n <ion-select\n interface="action-sheet"\n cancel-text="关闭"\n [(ngModel)]="studentDateil.workUnit"\n placeholder="点击选择"\n >\n <ng-container *ngFor="let item of options">\n <ion-select-option [value]="item"\n >{{ item }}级</ion-select-option\n >\n </ng-container>\n </ion-select>\n </div>\n <nz-input-group nzAddOnBefore="学生证号">\n <input\n type="text"\n nz-input\n [(ngModel)]="studentDateil.diploma"\n placeholder="请填写学生证号"\n />\n </nz-input-group>\n <div nz-row style="margin: 10px 0">\n <div nz-col nzSpan="12" class="li">\n <div class="label">\n <span style="color: red">*</span> 学生证照片\n </div>\n <fm-edit-upload\n *ngIf="!eduImage"\n [(file)]="eduImage"\n [company]="company"\n (fileListChange)="uploadChange($event, \'eduImage\')"\n ></fm-edit-upload>\n <div class="img-view" *ngIf="eduImage">\n <span\n *ngIf="!profile?.get(\'isCross\')"\n nz-icon\n nzType="close"\n nzTheme="outline"\n (click)="onDeleted(\'eduImage\')"\n ></span>\n <img\n nz-image\n width="100px"\n height="100px"\n nzSrc="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"\n [nzSrc]="eduImage"\n alt="学生证照片"\n />\n </div>\n </div>\n </div>\n </ng-container>\n <ng-template #template1>\n <div class="info-row">\n <div class="info-row-lable">最高学历</div>\n <nz-radio-group [(ngModel)]="studentDateil.education">\n <label nz-radio nzValue="大专">大专</label>\n <label nz-radio nzValue="学士">学士</label>\n <label nz-radio nzValue="硕士">硕士</label>\n <label nz-radio nzValue="博士">博士</label>\n </nz-radio-group>\n </div>\n <div class="info-row">\n <div class="info-row-lable info-select">毕业年份:</div>\n <ion-select\n interface="action-sheet"\n cancel-text="关闭"\n [(ngModel)]="studentDateil.entrySchool"\n placeholder="点击选择"\n >\n <ng-container *ngFor="let item of options">\n <ion-select-option [value]="item"\n >{{ item }}年</ion-select-option\n >\n </ng-container>\n </ion-select>\n </div>\n <nz-input-group nzAddOnBefore="毕业证号">\n <input\n type="text"\n nz-input\n [(ngModel)]="studentDateil.degreeNumber"\n placeholder="请填写毕业证号"\n />\n </nz-input-group>\n </ng-template>\n <div nz-row style="margin: 10px auto">\n <button\n nz-button\n nzType="primary"\n nzBlock\n (click)="onSubimtStudent()"\n [disabled]="false"\n >\n 确定\n </button>\n </div>\n </div>\n </ng-container>\n\n <ng-container *ngIf="tab==\'bankcard\'&&verifyOptions?.bankcard">\n \n \n <div class="info">\n <div class="input-view">\n <nz-input-group nzAddOnBefore="姓名">\n <input\n type="text"\n nz-input\n [(ngModel)]="name"\n placeholder="请先完成实名认证"\n [disabled]="true"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="身份证号">\n <input\n type="text"\n nz-input\n [(ngModel)]="idcard"\n placeholder="请先完成实名认证"\n [disabled]="true"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="银行卡账号">\n <input\n type="text"\n nz-input\n [(ngModel)]="bankMap.bankcard"\n placeholder="请填写银行卡账号"\n [nzStatus]="cardNoStatus()"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="银行卡预留手机号">\n <input\n type="text"\n nz-input\n [(ngModel)]="bankMap.bankmobile"\n maxlength="11"\n placeholder="请填写银行卡预留手机号"\n [nzStatus]="mobileStatus(bankMap.bankmobile)"\n />\n </nz-input-group>\n <nz-input-group nzAddOnBefore="开户行">\n <input\n type="text"\n nz-input\n [ngModel]="bankMap.bank"\n maxlength="11"\n placeholder="认证成功后自动识别"\n [disabled]="true"\n />\n </nz-input-group>\n \x3c!-- <div class="info-row">\n <div class="info-row-lable info-select">开户行:</div>\n <ion-select\n interface="action-sheet"\n cancel-text="关闭"\n [(ngModel)]="bankMap.bank"\n placeholder="点击选择"\n >\n <ng-container *ngFor="let item of bankOptions">\n <ion-select-option [value]="item"\n >{{ item }}</ion-select-option\n >\n </ng-container>\n </ion-select>\n </div> --\x3e\n </div>\n <div nz-row>\n <button\n nz-button\n nzType="primary"\n nzBlock\n (click)="onSubimtBank()"\n [disabled]="saveBankAuth()"\n >\n 确定\n </button>\n </div>\n </div>\n </ng-container>\n\n\n\n</ion-content>\n',styles:[".required{color:red}.page{display:flex;justify-content:center;align-items:center;flex-direction:column}.tab-content{width:80%;align-items:center;justify-content:center;margin:auto}.tab-content .li{display:flex;flex-direction:column;align-items:center}.tab-content .li .label{margin-bottom:10px}.tab-content .li .label span{color:red}.tab-content .li .img-view{position:relative}.tab-content .li .img-view span{position:absolute;right:-10px;top:0}.input-view{margin:10px auto}.info .info-row{display:flex;align-items:center;border:1px solid #d9d9d9;padding:6px 0}.info .info-row .info-row-lable{padding:0 10px;flex-shrink:0}.info .info-row .info-select{min-width:70px}.info .img-view{position:relative;width:100px}.info .img-view span{position:absolute;right:-10px;top:0}\n"]}]}],ctorParameters:()=>[{type:i1.HttpClient},{type:i2$2.NzMessageService},{type:AccountService},{type:AuthService},{type:NovaCloudService},{type:i1$3.ModalController}],propDecorators:{isVisible:[{type:Input}],isVisibleChange:[{type:Output}],verifyOptions:[{type:Input}]}});class PersonDetailComponent{cancel(){this.modalCtrl.dismiss(null)}async confirm(){await this.addPerson(),this.person?.id&&this.modalCtrl.dismiss(this.person,"confirm")}constructor(e,t,n,o){this.route=e,this.message=t,this.location=n,this.modalCtrl=o,this.radioValue="男",this.company="",this.avatar="",this.thumb="",this.gender={"男":"男","女":"女"},this.route.queryParamMap.subscribe((e=>{this.personId=e.get("personId"),console.log(this.personId)}))}ngOnInit(){this.person?.id||this.getPerson()}changeAvatar(){this.avatar="",console.log(this.avatar)}changeThumb(){this.thumb="",console.log(this.thumb)}onDateChange(e){const t=e.detail.value,n=new Date(t);this.date=n,console.log(this.date)}async getPerson(){if(!this.personId)return;let e=new Parse.Query("Person");e.equalTo("company","Svehl6FceL"),e.equalTo("objectId",this.personId),e.notEqualTo("isDeleted",!0),this.person=await e.first(),this.person?.id&&(this.name=this.person.get("name"),this.radioValue=this.person.get("gender"),this.birthday=this.person.get("birthday"),this.post=this.person.get("post"),this.mobile=this.person.get("mobile"),this.hobby=this.person.get("hobby"),this.avatar=this.person.get("avatar"),this.thumb=this.person.get("thumb"))}async addPerson(){if(this.currentUser=Parse.User.current(),!this.name)return this.message.error("姓名未填写");if(!this.radioValue)return this.message.error("性别未填写");if(!this.person){let e=Parse.Object.extend("Person");this.person=new e}if(this.person){this.person.set("name",this.name),this.person.set("gender",this.gender[this.radioValue]),this.person.set("birthday",this.date),this.person.set("post",this.post),this.person.set("mobile",String(this.mobile)),this.person.set("hobby",this.hobby),this.person.set("avatar",this.avatar),this.person.set("thumb",this.thumb),this.person.set("creator",{__type:"Pointer",className:"_User",objectId:this.currentUser?.id}),this.person.set("company",{__type:"Pointer",className:"Company",objectId:"Svehl6FceL"});try{this.person=await this.person.save(),this.person?.id&&this.message.success("保存成功")}catch(e){console.log(e),this.message.error("保存失败")}}}goBack(){this.location.back()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PersonDetailComponent,deps:[{token:i1$1.ActivatedRoute},{token:i2$2.NzMessageService},{token:i2.Location},{token:i1$3.ModalController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:PersonDetailComponent,isStandalone:!0,selector:"app-person-detail",providers:[],ngImport:i0,template:'<ion-header>\n <ion-toolbar>\n <ion-buttons slot="start" (click)="cancel()">\n <ion-button>取消</ion-button>\n </ion-buttons>\n <ion-title>基础信息</ion-title>\n <ion-buttons slot="end" (click)="confirm()">\n <ion-button>完成</ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n\n<div class="page">\n \x3c!-- <div class="top">完善人物基础信息</div> --\x3e\n <div class="box">\n <div class="item">\n <div class="title">姓名</div>\n <div class="input" style="padding: 3% 1% 1% 1%;">\n <input nz-input placeholder="请输入真实姓名" [(ngModel)]="name" nzBorderless style="width: 100%;background-color: #1e1f22;color: #fff;" />\n <div style="\n height: 1px;\n width: 95%;\n background-color: #353a4a;\n margin: 2% auto;"></div>\n </div>\n </div>\n <div class="item">\n <div class="title">性别</div>\n <div class="sex">\n <nz-radio-group [(ngModel)]="radioValue">\n <label nz-radio nzValue="男" style="color: #fff;">男</label>\n <label nz-radio nzValue="女" style="color: #fff;">女</label>\n </nz-radio-group>\n <div style="\n height: 1px;\n width: 100%;\n background-color: #353a4a;\n margin: 2% auto;"></div>\n </div>\n </div>\n <div class="item" style="padding: 3%;display: flex;">\n <div style="display: flex; flex-direction: row;width: 50%;text-align: center;">\n <div class="upload_avatar">\n <fm-edit-upload *ngIf="!avatar" [(file)]="avatar" [multi]="true" [company]="company"></fm-edit-upload>\n <img style="width: 130px;height:130px; object-fit: cover;" *ngIf="avatar" [src]="avatar" alt="" >\n <div>上传头像</div>\n </div>\n <div *ngIf="avatar" (click)="changeAvatar()" style="margin-left: 4px; font-size: 20px;margin-top: -20px; height: 25px; cursor: pointer;">x</div>\n </div>\n <div style="display: flex; flex-direction: row;width: 50%;text-align: center;">\n <div class="upload_avatar">\n <fm-edit-upload *ngIf="!thumb" [(file)]="thumb" [multi]="true" [company]="company"></fm-edit-upload>\n <img style="height: 130px; object-fit: cover;" *ngIf="thumb" [src]="thumb" alt="" >\n <div>上传封面</div>\n </div>\n <div *ngIf="thumb" (click)="changeThumb()" style="margin-left: 4px; font-size: 20px;margin-top: -20px; height: 25px; cursor: pointer;">x</div>\n </div>\n </div>\n <div class="item">\n <div class="title">生日</div>\n <div class="birthday">\n <ion-datetime-button datetime="datetime" [(ngModel)]="birthday"></ion-datetime-button>\n <ion-modal [keepContentsMounted]="true">\n <ng-template>\n <ion-datetime id="datetime" presentation="date"\n (ionChange)="onDateChange($event)"></ion-datetime>\n </ng-template>\n </ion-modal>\n <div style="\n height: 1px;\n width: 100%;\n background-color: #353a4a;\n margin: 2% auto;"></div>\n </div>\n </div>\n <div class="item">\n <div class="title">现任职位</div>\n <div class="input" style="padding: 3% 1% 1% 1%;">\n <input nz-input placeholder="请输入现任职位" [(ngModel)]="post" nzBorderless style="width: 100%;background-color: #1e1f22;color: #fff;" />\n <div style="\n height: 1px;\n width: 95%;\n background-color: #353a4a;\n margin: 2% auto;"></div>\n </div>\n </div>\n <div class="item">\n <div class="title">联系方式</div>\n <div class="input" style="padding: 3% 1% 1% 1%;">\n <input nz-input placeholder="请输入联系方式" [(ngModel)]="mobile" type="number" maxlength="11" nzBorderless style="width: 100%;background-color: #1e1f22;color: #fff;" />\n <div style="\n height: 1px;\n width: 95%;\n background-color: #353a4a;\n margin: 2% auto;"></div>\n </div>\n </div>\n <div class="item">\n <div class="title">兴趣爱好</div>\n <div class="input" style="padding: 3% 1% 1% 1%;">\n <input nz-input placeholder="请输入兴趣爱好" [(ngModel)]="hobby" nzBorderless style="width: 100%;background-color: #1e1f22;color: #fff;" />\n <div style="\n height: 1px;\n width: 95%;\n background-color: #353a4a;\n margin: 2% auto;"></div>\n </div>\n </div>\n\n <ion-button style="width: 90%;margin-left: 5%;" (click)="confirm()">完成</ion-button>\n </div>\n</div>\n</ion-content>\n',styles:[".page{width:100%;height:100%;padding:2%;background-color:#030810;color:#fff;overflow-y:scroll}.page .top{padding:3%;color:#ba6b16}.page .box{height:95%;padding:5% 0;background-color:#1e1f22;border-radius:20px}.page .box span{margin-left:3%}.page .box .item .title{margin-left:3%;margin-top:12px}.page .box .item .sex,.page .box .item .birthday{padding:3%}.page .box ion-button{--background: #6e23ce}ion-datetime-button{display:block}\n"],dependencies:[{kind:"component",type:IonDatetimeButton,selector:"ion-datetime-button",inputs:["color","datetime","disabled","mode"]},{kind:"component",type:IonModal,selector:"ion-modal"},{kind:"component",type:IonDatetime,selector:"ion-datetime",inputs:["cancelText","clearText","color","dayValues","disabled","doneText","firstDayOfWeek","formatOptions","highlightedDates","hourCycle","hourValues","isDateEnabled","locale","max","min","minuteValues","mode","monthValues","multiple","name","preferWheel","presentation","readonly","showClearButton","showDefaultButtons","showDefaultTimeLabel","showDefaultTitle","size","titleSelectedDatesFormatter","value","yearValues"]},{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:IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:IonButtons,selector:"ion-buttons",inputs:["collapse"]},{kind:"component",type:IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"component",type:IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"ngmodule",type:NzDatePickerModule},{kind:"ngmodule",type:NzInputModule},{kind:"directive",type:i8.NzInputDirective,selector:"input[nz-input],textarea[nz-input]",inputs:["nzBorderless","nzSize","nzStepperless","nzStatus","disabled"],exportAs:["nzInput"]},{kind:"ngmodule",type:NzRadioModule},{kind:"component",type:i15.NzRadioComponent,selector:"[nz-radio],[nz-radio-button]",inputs:["nzValue","nzDisabled","nzAutoFocus","nz-radio-button"],exportAs:["nzRadio"]},{kind:"component",type:i15.NzRadioGroupComponent,selector:"nz-radio-group",inputs:["nzDisabled","nzButtonStyle","nzSize","nzName"],exportAs:["nzRadioGroup"]},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"directive",type:i3$3.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:i3$3.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.MaxLengthValidator,selector:"[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]",inputs:["maxlength"]},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i3$3.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:EditUploadModule},{kind:"component",type:EditUploadComponent,selector:"fm-edit-upload",inputs:["files","dragdrop","multi","max_file_size","type","avatarType","company","file","fileList","path"],outputs:["filesChange","fileChange","fileListChange"]}]})}}async function openPersonDetailEditModal(e,t){let n=await e.create({component:PersonDetailComponent,componentProps:{person:t},breakpoints:[.5,1],initialBreakpoint:.5});n.present();let{data:o,role:i}=await n.onWillDismiss();if("confirm"==i){let e=o;return"PersonAuthor"==o?.className?o?.get("person"):e}return null}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PersonDetailComponent,decorators:[{type:Component,args:[{selector:"app-person-detail",standalone:!0,imports:[IonDatetimeButton,IonModal,IonDatetime,IonButton,IonHeader,IonButtons,IonToolbar,IonContent,IonTitle,NzDatePickerModule,NzInputModule,NzRadioModule,ReactiveFormsModule,FormsModule,CommonModule,EditUploadModule],providers:[],template:'<ion-header>\n <ion-toolbar>\n <ion-buttons slot="start" (click)="cancel()">\n <ion-button>取消</ion-button>\n </ion-buttons>\n <ion-title>基础信息</ion-title>\n <ion-buttons slot="end" (click)="confirm()">\n <ion-button>完成</ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n\n<div class="page">\n \x3c!-- <div class="top">完善人物基础信息</div> --\x3e\n <div class="box">\n <div class="item">\n <div class="title">姓名</div>\n <div class="input" style="padding: 3% 1% 1% 1%;">\n <input nz-input placeholder="请输入真实姓名" [(ngModel)]="name" nzBorderless style="width: 100%;background-color: #1e1f22;color: #fff;" />\n <div style="\n height: 1px;\n width: 95%;\n background-color: #353a4a;\n margin: 2% auto;"></div>\n </div>\n </div>\n <div class="item">\n <div class="title">性别</div>\n <div class="sex">\n <nz-radio-group [(ngModel)]="radioValue">\n <label nz-radio nzValue="男" style="color: #fff;">男</label>\n <label nz-radio nzValue="女" style="color: #fff;">女</label>\n </nz-radio-group>\n <div style="\n height: 1px;\n width: 100%;\n background-color: #353a4a;\n margin: 2% auto;"></div>\n </div>\n </div>\n <div class="item" style="padding: 3%;display: flex;">\n <div style="display: flex; flex-direction: row;width: 50%;text-align: center;">\n <div class="upload_avatar">\n <fm-edit-upload *ngIf="!avatar" [(file)]="avatar" [multi]="true" [company]="company"></fm-edit-upload>\n <img style="width: 130px;height:130px; object-fit: cover;" *ngIf="avatar" [src]="avatar" alt="" >\n <div>上传头像</div>\n </div>\n <div *ngIf="avatar" (click)="changeAvatar()" style="margin-left: 4px; font-size: 20px;margin-top: -20px; height: 25px; cursor: pointer;">x</div>\n </div>\n <div style="display: flex; flex-direction: row;width: 50%;text-align: center;">\n <div class="upload_avatar">\n <fm-edit-upload *ngIf="!thumb" [(file)]="thumb" [multi]="true" [company]="company"></fm-edit-upload>\n <img style="height: 130px; object-fit: cover;" *ngIf="thumb" [src]="thumb" alt="" >\n <div>上传封面</div>\n </div>\n <div *ngIf="thumb" (click)="changeThumb()" style="margin-left: 4px; font-size: 20px;margin-top: -20px; height: 25px; cursor: pointer;">x</div>\n </div>\n </div>\n <div class="item">\n <div class="title">生日</div>\n <div class="birthday">\n <ion-datetime-button datetime="datetime" [(ngModel)]="birthday"></ion-datetime-button>\n <ion-modal [keepContentsMounted]="true">\n <ng-template>\n <ion-datetime id="datetime" presentation="date"\n (ionChange)="onDateChange($event)"></ion-datetime>\n </ng-template>\n </ion-modal>\n <div style="\n height: 1px;\n width: 100%;\n background-color: #353a4a;\n margin: 2% auto;"></div>\n </div>\n </div>\n <div class="item">\n <div class="title">现任职位</div>\n <div class="input" style="padding: 3% 1% 1% 1%;">\n <input nz-input placeholder="请输入现任职位" [(ngModel)]="post" nzBorderless style="width: 100%;background-color: #1e1f22;color: #fff;" />\n <div style="\n height: 1px;\n width: 95%;\n background-color: #353a4a;\n margin: 2% auto;"></div>\n </div>\n </div>\n <div class="item">\n <div class="title">联系方式</div>\n <div class="input" style="padding: 3% 1% 1% 1%;">\n <input nz-input placeholder="请输入联系方式" [(ngModel)]="mobile" type="number" maxlength="11" nzBorderless style="width: 100%;background-color: #1e1f22;color: #fff;" />\n <div style="\n height: 1px;\n width: 95%;\n background-color: #353a4a;\n margin: 2% auto;"></div>\n </div>\n </div>\n <div class="item">\n <div class="title">兴趣爱好</div>\n <div class="input" style="padding: 3% 1% 1% 1%;">\n <input nz-input placeholder="请输入兴趣爱好" [(ngModel)]="hobby" nzBorderless style="width: 100%;background-color: #1e1f22;color: #fff;" />\n <div style="\n height: 1px;\n width: 95%;\n background-color: #353a4a;\n margin: 2% auto;"></div>\n </div>\n </div>\n\n <ion-button style="width: 90%;margin-left: 5%;" (click)="confirm()">完成</ion-button>\n </div>\n</div>\n</ion-content>\n',styles:[".page{width:100%;height:100%;padding:2%;background-color:#030810;color:#fff;overflow-y:scroll}.page .top{padding:3%;color:#ba6b16}.page .box{height:95%;padding:5% 0;background-color:#1e1f22;border-radius:20px}.page .box span{margin-left:3%}.page .box .item .title{margin-left:3%;margin-top:12px}.page .box .item .sex,.page .box .item .birthday{padding:3%}.page .box ion-button{--background: #6e23ce}ion-datetime-button{display:block}\n"]}]}],ctorParameters:()=>[{type:i1$1.ActivatedRoute},{type:i2$2.NzMessageService},{type:i2.Location},{type:i1$3.ModalController}]});class ModalPersonSelectComponent{constructor(e,t,n){this.modalCtrl=e,this.alertCtrl=t,this.personServ=n,this.defaultAvatar="/assets/img/icon/avatar.svg",this.ownPersonList=[],this.authPersonList=[],this.selfLoaded=!1}async createSelfPerson(e=!1){let t;if(e){let e=await openUserVerifyModal(this.modalCtrl,this.alertCtrl,{idcard:!0,autoFinish:!0});if(t=e?.profile,!t){return void(await this.alertCtrl.create({header:"认证失败",message:"请您重新认证。"})).present()}if(t?.id){let e=new(Parse__default.Object.extend("Person")),n=e?.get("birthdate"),o=n&&new Date(n)||void 0;e.set({name:t.get("name"),gender:t.get("sex"),birthday:o,area:t.get("area"),isVerified:!0,userVerify:Parse__default.User.current()}),this.selfPerson=await(e?.save())}}else{let e=new(Parse__default.Object.extend("Person")),t=Parse__default.User.current();e.set("userVerify",Parse__default.User.current()?.toPointer()),e=await openPersonDetailEditModal(this.modalCtrl,e),e.set("userVerify",Parse__default.User.current());let n=!1;e.get("name")&&(n=!0,t?.set("realname",e.get("name"))),e.get("avatar")&&(n=!0,t?.set("avatar",e.get("avatar"))),e.get("gender")&&(n=!0,t?.set("sex",e.get("gender"))),n&&t?.save(),e?.id&&(this.selfPerson=e)}}ngOnInit(){this.loadPerson()}async loadPerson(){this.personServ.loadSelfPerson().then((e=>{this.selfPerson=e,this.selfLoaded=!0})),this.personServ.queryOwnPerson().then((e=>{this.ownPersonList=e})),this.personServ.queryAuthPerson().then((e=>{this.authPersonList=e}))}selectPerson(e){if(e?.id)return this.modalCtrl.dismiss(e,"confirm")}cancel(){return this.modalCtrl.dismiss(null,"cancel")}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalPersonSelectComponent,deps:[{token:i1$3.ModalController},{token:i1$3.AlertController},{token:PersonService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:ModalPersonSelectComponent,isStandalone:!0,selector:"app-modal-person-select",ngImport:i0,template:'<ion-content class="ion-padding">\n <ion-list>\n @if(selfLoaded){\n\n <ion-item-group>\n <ion-item>\n <ion-item-divider>\n <ion-label>我自己</ion-label>\n </ion-item-divider>\n </ion-item>\n \x3c!-- 无自己角色,需要创建 --\x3e\n <ion-item button *ngIf="!selfPerson?.id" (click)="createSelfPerson()">\n <ion-avatar>\n <ion-img [src]="defaultAvatar"></ion-img>\n </ion-avatar>\n <ion-label>\n <h2>未创建</h2>\n <p>您点击认证自己的数字身份,可用于自传及名片应用...</p>\n </ion-label>\n </ion-item>\n \x3c!-- 自己的角色,点击进入 --\x3e\n <fm-comp-person-item *ngIf="selfPerson?.id" (click)="selectPerson(selfPerson)" [person]="selfPerson" (click)="selectPerson(selfPerson)"></fm-comp-person-item>\n \x3c!-- <ng-container *ngTemplateOutlet="personItem;context:{person:person}"></ng-container> --\x3e\n </ion-item-group>\n }\n\n <ion-item-group *ngIf="ownPersonList?.length">\n <ion-item>\n <ion-item-divider>\n <ion-label>我创建的</ion-label>\n </ion-item-divider>\n </ion-item>\n <ng-container *ngFor="let person of ownPersonList">\n <fm-comp-person-item [person]="person" (click)="selectPerson(person)"></fm-comp-person-item>\n </ng-container>\n \x3c!-- 创建角色,需要创建新角色 --\x3e\n <ion-item button *ngIf="!selfPerson?.id && false">\n <ion-avatar>\n <ion-img [src]="defaultAvatar"></ion-img>\n </ion-avatar>\n <ion-label>\n <h2>新增角色</h2>\n <p>点击新增人物,可撰写他人传记...</p>\n </ion-label>\n </ion-item>\n </ion-item-group>\n\n <ion-item-group *ngIf="authPersonList?.length">\n <ion-item>\n <ion-item-divider>\n <ion-label>授权我的</ion-label>\n </ion-item-divider>\n </ion-item>\n <ng-container *ngFor="let author of authPersonList">\n <fm-comp-person-item [person]="author?.get(\'person\')" (click)="selectPerson(author)"></fm-comp-person-item>\n </ng-container>\n </ion-item-group>\n \n \n </ion-list>\n</ion-content>\n',styles:["ion-label h2,ion-label p{color:#fff}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:IonAvatar,selector:"ion-avatar"},{kind:"component",type:IonImg,selector:"ion-img",inputs:["alt","src"]},{kind:"component",type:IonList,selector:"ion-list",inputs:["inset","lines","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:IonItemGroup,selector:"ion-item-group"},{kind:"component",type:IonItemDivider,selector:"ion-item-divider",inputs:["color","mode","sticky"]},{kind:"component",type:CompPersonItemComponent,selector:"fm-comp-person-item",inputs:["person"]}]})}}async function openPersonSelectModal(e){let t=await e.create({component:ModalPersonSelectComponent,breakpoints:[.3,.5,.75],initialBreakpoint:.3});t.present();let{data:n,role:o}=await t.onWillDismiss();if("confirm"==o){let e=n;return"PersonAuthor"==n?.className?n?.get("person"):e}return null}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalPersonSelectComponent,decorators:[{type:Component,args:[{selector:"app-modal-person-select",standalone:!0,imports:[CommonModule,IonModal,IonContent,IonLabel,IonAvatar,IonImg,IonList,IonItem,IonItemGroup,IonItemDivider,CompPersonItemComponent],template:'<ion-content class="ion-padding">\n <ion-list>\n @if(selfLoaded){\n\n <ion-item-group>\n <ion-item>\n <ion-item-divider>\n <ion-label>我自己</ion-label>\n </ion-item-divider>\n </ion-item>\n \x3c!-- 无自己角色,需要创建 --\x3e\n <ion-item button *ngIf="!selfPerson?.id" (click)="createSelfPerson()">\n <ion-avatar>\n <ion-img [src]="defaultAvatar"></ion-img>\n </ion-avatar>\n <ion-label>\n <h2>未创建</h2>\n <p>您点击认证自己的数字身份,可用于自传及名片应用...</p>\n </ion-label>\n </ion-item>\n \x3c!-- 自己的角色,点击进入 --\x3e\n <fm-comp-person-item *ngIf="selfPerson?.id" (click)="selectPerson(selfPerson)" [person]="selfPerson" (click)="selectPerson(selfPerson)"></fm-comp-person-item>\n \x3c!-- <ng-container *ngTemplateOutlet="personItem;context:{person:person}"></ng-container> --\x3e\n </ion-item-group>\n }\n\n <ion-item-group *ngIf="ownPersonList?.length">\n <ion-item>\n <ion-item-divider>\n <ion-label>我创建的</ion-label>\n </ion-item-divider>\n </ion-item>\n <ng-container *ngFor="let person of ownPersonList">\n <fm-comp-person-item [person]="person" (click)="selectPerson(person)"></fm-comp-person-item>\n </ng-container>\n \x3c!-- 创建角色,需要创建新角色 --\x3e\n <ion-item button *ngIf="!selfPerson?.id && false">\n <ion-avatar>\n <ion-img [src]="defaultAvatar"></ion-img>\n </ion-avatar>\n <ion-label>\n <h2>新增角色</h2>\n <p>点击新增人物,可撰写他人传记...</p>\n </ion-label>\n </ion-item>\n </ion-item-group>\n\n <ion-item-group *ngIf="authPersonList?.length">\n <ion-item>\n <ion-item-divider>\n <ion-label>授权我的</ion-label>\n </ion-item-divider>\n </ion-item>\n <ng-container *ngFor="let author of authPersonList">\n <fm-comp-person-item [person]="author?.get(\'person\')" (click)="selectPerson(author)"></fm-comp-person-item>\n </ng-container>\n </ion-item-group>\n \n \n </ion-list>\n</ion-content>\n',styles:["ion-label h2,ion-label p{color:#fff}\n"]}]}],ctorParameters:()=>[{type:i1$3.ModalController},{type:i1$3.AlertController},{type:PersonService}]});class CompPersonStoryComponent{countChange(e){this.selectCount=e,this.onCountChange.emit(e)}tokenChange(e){this.selectToken=e,this.onTokenChange.emit(e)}async confirmSelectedList(){let e=await(this.listComp?.getAllSelectDocument()),t=e?.documentList||[],n=e?.storyList||[];this.onConfirmSelect.emit({storyList:n,documentList:t})}constructor(e,t,n,o){this.route=e,this.loadingCtrl=t,this.dialog=n,this.router=o,this.storyList=[],this.isPreview=!1,this.currentTab="我的数据",this.height="100%",this.isSelectMode=!1,this.checkedMap={},this.selectCount=0,this.selectToken=0,this.onCancel=new EventEmitter,this.onCountChange=new EventEmitter,this.onTokenChange=new EventEmitter,this.onConfirmSelect=new EventEmitter,this.routingMode=!1,location.pathname?.indexOf("story")>-1&&(this.routingMode=!0)}async ngOnInit(){if(!this.person?.id||this.book?.id){let e=this.route.snapshot.params?.id||this.route?.parent?.snapshot?.params?.id;if(location?.pathname?.indexOf("editor/book")>-1){let t=new Parse__default.Query("Book");t.include("person"),this.book=await t.get(e),this.person=this.book.get("person")}if(location?.pathname?.indexOf("editor/person")>-1){let t=new Parse__default.Query("Person");this.person=await t.get(e)}}}async previewStory(e){let t=e;if(console.log("previewStory",e),document.body.clientWidth<1e3)return;if(this.routingMode){let e=location?.pathname?.split("story"),n=t?.story?.id||"";e=n?[e[0],"story","preview",n]?.filter((e=>e)):[e[0],"story"]?.filter((e=>e)),console.log(e),this.router.navigate(e)}this.currentStory=void 0;let n=t?.story?.get("attach")?.id?1e3:100;(await this.loadingCtrl.create({message:"故事渲染中...",duration:n})).present(),this.currentStory=t}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPersonStoryComponent,deps:[{token:i1$1.ActivatedRoute},{token:i3.LoadingController},{token:i3$1.MatDialog},{token:i1$1.Router}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:CompPersonStoryComponent,isStandalone:!0,selector:"comp-person-story",inputs:{person:"person",book:"book",article:"article",isSelectMode:"isSelectMode"},outputs:{onCancel:"onCancel",onCountChange:"onCountChange",onTokenChange:"onTokenChange",onConfirmSelect:"onConfirmSelect"},viewQueries:[{propertyName:"listComp",first:!0,predicate:FmStoryListComponent,descendants:!0}],ngImport:i0,template:'\n<div class="page" [style.height]="height">\n <div class="sider" style="padding:5px;" [class.collapsed]="isPreview">\n \x3c!-- [style.width]="(isSelectMode?290:400)+\'px\'" --\x3e\n <fm-story-list \n [isSelectMode]="isSelectMode"\n [person]="person"\n [book]="book"\n [article]="article"\n (onConfirmSelect)="confirmSelectedList()"\n (onCancel)="onCancel.emit(true)"\n (onPreviewStory)="previewStory($event)"\n (onCountChange)="countChange($event)" \n (onTokenChange)="tokenChange($event)"\n ></fm-story-list>\n </div>\n\n <div class="content on-pc">\n @if (routingMode){\n <router-outlet></router-outlet>\n }@else if(currentStory){\n\n <fm-story-loader #loader [isSelectMode]="isSelectMode" [story]="currentStory"></fm-story-loader>\n }\n </div>\n</div>\n\n',styles:["@media (max-width: 1024px){.on-pc{display:none}.sider{width:100%!important}}.page{width:100%;height:100%;display:flex;flex-direction:row;flex-wrap:nowrap}.page .sider{height:100%;width:400px}.page .content{flex:1;height:100%}nz-sider{background:var(--background-gray)}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"ngmodule",type:RouterModule},{kind:"directive",type:i1$1.RouterOutlet,selector:"router-outlet",inputs:["name"],outputs:["activate","deactivate","attach","detach"],exportAs:["outlet"]},{kind:"ngmodule",type:IonicModule},{kind:"ngmodule",type:NzLayoutModule},{kind:"ngmodule",type:NzIconModule},{kind:"ngmodule",type:NzPipesModule},{kind:"ngmodule",type:MatButtonToggleModule},{kind:"ngmodule",type:MatCheckboxModule},{kind:"ngmodule",type:MatDialogModule},{kind:"ngmodule",type:MatCardModule},{kind:"ngmodule",type:MatProgressBarModule},{kind:"ngmodule",type:MatDividerModule},{kind:"ngmodule",type:MatButtonModule},{kind:"ngmodule",type:MatIconModule},{kind:"component",type:FmStoryLoaderComponent,selector:"fm-story-loader",inputs:["isSelectMode","story"]},{kind:"component",type:FmStoryListComponent,selector:"fm-story-list",inputs:["id","article","person","book","isSelectMode"],outputs:["onCancel","onCountChange","onTokenChange","onPreviewStory","onConfirmSelect"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPersonStoryComponent,decorators:[{type:Component,args:[{selector:"comp-person-story",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,RouterModule,IonicModule,NzLayoutModule,NzIconModule,NzPipesModule,MatButtonToggleModule,MatCheckboxModule,MatDialogModule,MatCardModule,MatProgressBarModule,MatDividerModule,MatButtonModule,MatIconModule,FmStoryLoaderComponent,FmStoryCardComponent,FmStoryListComponent],template:'\n<div class="page" [style.height]="height">\n <div class="sider" style="padding:5px;" [class.collapsed]="isPreview">\n \x3c!-- [style.width]="(isSelectMode?290:400)+\'px\'" --\x3e\n <fm-story-list \n [isSelectMode]="isSelectMode"\n [person]="person"\n [book]="book"\n [article]="article"\n (onConfirmSelect)="confirmSelectedList()"\n (onCancel)="onCancel.emit(true)"\n (onPreviewStory)="previewStory($event)"\n (onCountChange)="countChange($event)" \n (onTokenChange)="tokenChange($event)"\n ></fm-story-list>\n </div>\n\n <div class="content on-pc">\n @if (routingMode){\n <router-outlet></router-outlet>\n }@else if(currentStory){\n\n <fm-story-loader #loader [isSelectMode]="isSelectMode" [story]="currentStory"></fm-story-loader>\n }\n </div>\n</div>\n\n',styles:["@media (max-width: 1024px){.on-pc{display:none}.sider{width:100%!important}}.page{width:100%;height:100%;display:flex;flex-direction:row;flex-wrap:nowrap}.page .sider{height:100%;width:400px}.page .content{flex:1;height:100%}nz-sider{background:var(--background-gray)}\n"]}]}],ctorParameters:()=>[{type:i1$1.ActivatedRoute},{type:i3.LoadingController},{type:i3$1.MatDialog},{type:i1$1.Router}],propDecorators:{listComp:[{type:ViewChild,args:[FmStoryListComponent]}],person:[{type:Input}],book:[{type:Input}],article:[{type:Input}],isSelectMode:[{type:Input}],onCancel:[{type:Output}],onCountChange:[{type:Output}],onTokenChange:[{type:Output}],onConfirmSelect:[{type:Output}]}});class DialogPersonStorySelect{confirmSelectedList(){this.storySelectComp?.confirmSelectedList()}constructor(e,t){this.dialogRef=e,this.data=t,this.isSelectMode=!0,this.selectCount=0,this.selectToken=0,this.limitToken=131072,this.person=t?.person,this.book=t?.book,this.article=t?.article,setTimeout((()=>{this.storySelectComp?.listComp?.loadStory()}),500)}onConfirm(e){console.log("onConfirm:",e),this.dialogRef.close(e)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DialogPersonStorySelect,deps:[{token:i3$1.MatDialogRef},{token:MAT_DIALOG_DATA}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:DialogPersonStorySelect,isStandalone:!0,selector:"person-story-select-dialog",viewQueries:[{propertyName:"storySelectComp",first:!0,predicate:CompPersonStoryComponent,descendants:!0}],ngImport:i0,template:'\n <comp-person-story \n (onCancel)="dialogRef.close(true)"\n (onConfirmSelect)="onConfirm($event)" (onCountChange)="selectCount=$event" (onTokenChange)="selectToken=$event"\n [article]="article" [person]="person" [book]="book" [isSelectMode]="isSelectMode"></comp-person-story>\n <mat-dialog-actions align="start" *ngIf="false">\n <button mat-button>已经选择:{{selectCount}}个 (约{{selectToken}}tokens)</button>\n <button mat-button color="primary" [mat-dialog-close]="false">取消</button>\n <button *ngIf=\'selectToken<=limitToken\' mat-raised-button color="primary" (click)="confirmSelectedList()" cdkFocusInitial>确认选择</button>\n <button *ngIf=\'selectToken>limitToken\' mat-raised-button color="warn" disabled>超出{{selectToken-limitToken}}tokens</button>\n </mat-dialog-actions>\n ',isInline:!0,styles:["comp-person-story{height:calc(100% - 50px);width:100%}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:MatDialogModule},{kind:"directive",type:i3$1.MatDialogClose,selector:"[mat-dialog-close], [matDialogClose]",inputs:["aria-label","type","mat-dialog-close","matDialogClose"],exportAs:["matDialogClose"]},{kind:"directive",type:i3$1.MatDialogActions,selector:"[mat-dialog-actions], mat-dialog-actions, [matDialogActions]",inputs:["align"]},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"component",type:CompPersonStoryComponent,selector:"comp-person-story",inputs:["person","book","article","isSelectMode"],outputs:["onCancel","onCountChange","onTokenChange","onConfirmSelect"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DialogPersonStorySelect,decorators:[{type:Component,args:[{selector:"person-story-select-dialog",template:'\n <comp-person-story \n (onCancel)="dialogRef.close(true)"\n (onConfirmSelect)="onConfirm($event)" (onCountChange)="selectCount=$event" (onTokenChange)="selectToken=$event"\n [article]="article" [person]="person" [book]="book" [isSelectMode]="isSelectMode"></comp-person-story>\n <mat-dialog-actions align="start" *ngIf="false">\n <button mat-button>已经选择:{{selectCount}}个 (约{{selectToken}}tokens)</button>\n <button mat-button color="primary" [mat-dialog-close]="false">取消</button>\n <button *ngIf=\'selectToken<=limitToken\' mat-raised-button color="primary" (click)="confirmSelectedList()" cdkFocusInitial>确认选择</button>\n <button *ngIf=\'selectToken>limitToken\' mat-raised-button color="warn" disabled>超出{{selectToken-limitToken}}tokens</button>\n </mat-dialog-actions>\n ',standalone:!0,imports:[CommonModule,MatDialogModule,MatButtonModule,CompPersonStoryComponent],styles:["comp-person-story{height:calc(100% - 50px);width:100%}\n"]}]}],ctorParameters:()=>[{type:i3$1.MatDialogRef},{type:void 0,decorators:[{type:Inject,args:[MAT_DIALOG_DATA]}]}],propDecorators:{storySelectComp:[{type:ViewChild,args:[CompPersonStoryComponent]}]}});class FmTextQuillComponent{constructor(e){this.cdRef=e,this.readOnly=!1,this.content="",this.theme="bubble",this.toolbar=[[{header:[1,2,3,4,!1]}],["bold","italic","underline"],[{list:"bullet"}],[{align:[]}],["code-block"]],this.onAIClick=new EventEmitter,this.contentChanged=!1,this.onContentChange=new EventEmitter,this.selectText="",this.optimizeText="",this.isOptimizing=!1,this.onSelectChange=new EventEmitter}ngOnInit(){setTimeout((()=>{this.initQuillEditor()}),100)}initQuillEditor(){this.oldContent=void 0;let e=this.editorComp?.nativeElement;this.quill=new Quill(e,{readOnly:this.readOnly,modules:{syntax:{hljs:hljs},toolbar:this.toolbar,history:{delay:2e3,maxStack:500,userOnly:!0}},theme:this.theme}),this.quill.on("selection-change",((e,t,n)=>{if(e)if(0==e.length);else{let t=this.quill?.getText(e.index,e.length);this.selectRange=e,this.selectText=t||"",this.onSelectChange.emit({name:"select",quill:this.quill,range:this.selectRange,text:this.selectText}),this.cdRef.detectChanges()}})),this.quill.root.innerHTML=this.content||"",this.oldContent||setTimeout((()=>{this.oldContent=this.quill?.root?.innerHTML}),2e3),this.quill.on("text-change",(()=>{this.content=this.quill?.root?.innerHTML||"",this.oldContent&&this.content&&(this.contentChanged=this.content!=this.oldContent,this.onContentChange.emit(this.content))}));let t=this.quill.getModule("toolbar"),n=document.createElement("span");n.className="ql-formats";let o=document.createElement("button");o.className="ql-ai-optimize",o.innerHTML="AI",o.onclick=()=>{this.onAIClick.emit({name:"AI",quill:this.quill,range:this.selectRange,text:this.selectText})},n.appendChild(o),t.container.appendChild(n);let i=document.createElement("style");i.innerText=".ql-bubble .ql-editor .ql-code-block-container .ql-ui{color:black!important;}",t.container.appendChild(i)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmTextQuillComponent,deps:[{token:i0.ChangeDetectorRef}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmTextQuillComponent,isStandalone:!0,selector:"fm-text-quill",inputs:{readOnly:"readOnly",content:"content",theme:"theme",toolbar:"toolbar"},outputs:{onAIClick:"onAIClick",onContentChange:"onContentChange",onSelectChange:"onSelectChange"},viewQueries:[{propertyName:"editorComp",first:!0,predicate:["editorComp"],descendants:!0}],ngImport:i0,template:'\x3c!-- 高亮区域 语言选择黑色字体 --\x3e\n<style>.ql-bubble .ql-editor .ql-code-block-container .ql-ui{color:black!important;}</style>\n<div class="editor-container" #editorComp id="editor"></div>',styles:[":host-context(body.dark) ::ng-deep .ql-snow .ql-stroke{stroke:#fff!important}:host-context(body.dark) ::ng-deep .ql-snow .ql-picker.ql-header .ql-picker-label:before,.ql-snow .ql-picker.ql-header .ql-picker-item:before{color:#fff}:host-context(body.dark) ::ng-deep .ql-snow h1,:host-context(body.dark) ::ng-deep .ql-snow h2,:host-context(body.dark) ::ng-deep .ql-snow h3,:host-context(body.dark) ::ng-deep .ql-snow h4,:host-context(body.dark) ::ng-deep .ql-snow h5,:host-context(body.dark) ::ng-deep .ql-snow h6{color:#fff}.editor-container{height:auto}.editor-container .ql-editor{padding:0!important}.ql-editor{padding:0 2px!important}::ng-deep .ql-container.ql-snow{border:none}::ng-deep .ql-toolbar.ql-snow{border:none;border-radius:10px}.ql-toolbar.ql-snow{border:none!important}\n",".ql-bubble .ql-editor .ql-code-block-container .ql-ui{color:black!important;}"]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmTextQuillComponent,decorators:[{type:Component,args:[{selector:"fm-text-quill",standalone:!0,imports:[],template:'\x3c!-- 高亮区域 语言选择黑色字体 --\x3e\n<style>.ql-bubble .ql-editor .ql-code-block-container .ql-ui{color:black!important;}</style>\n<div class="editor-container" #editorComp id="editor"></div>',styles:[":host-context(body.dark) ::ng-deep .ql-snow .ql-stroke{stroke:#fff!important}:host-context(body.dark) ::ng-deep .ql-snow .ql-picker.ql-header .ql-picker-label:before,.ql-snow .ql-picker.ql-header .ql-picker-item:before{color:#fff}:host-context(body.dark) ::ng-deep .ql-snow h1,:host-context(body.dark) ::ng-deep .ql-snow h2,:host-context(body.dark) ::ng-deep .ql-snow h3,:host-context(body.dark) ::ng-deep .ql-snow h4,:host-context(body.dark) ::ng-deep .ql-snow h5,:host-context(body.dark) ::ng-deep .ql-snow h6{color:#fff}.editor-container{height:auto}.editor-container .ql-editor{padding:0!important}.ql-editor{padding:0 2px!important}::ng-deep .ql-container.ql-snow{border:none}::ng-deep .ql-toolbar.ql-snow{border:none;border-radius:10px}.ql-toolbar.ql-snow{border:none!important}\n",".ql-bubble .ql-editor .ql-code-block-container .ql-ui{color:black!important;}"]}]}],ctorParameters:()=>[{type:i0.ChangeDetectorRef}],propDecorators:{editorComp:[{type:ViewChild,args:["editorComp"]}],readOnly:[{type:Input}],content:[{type:Input}],theme:[{type:Input}],toolbar:[{type:Input}],onAIClick:[{type:Output}],onContentChange:[{type:Output}],onSelectChange:[{type:Output}]}});class CompDiaryStoryComponent{constructor(e,t){this.modalCtrl=e,this.cdRef=t,this.showHeader=!1,this.readOnly=!1,this.contentChanged=!1,this.showInfo=!1,this.now=new Date,this.toolbar=[[{header:[1,2,3,4,!1]}],["bold","italic","underline"],[{list:"bullet"}],[{align:[]}]],this.selectText=""}back(){this.modalCtrl.dismiss()}ngOnInit(){this.story?.get("person")?.id&&this.story?.get("person")?.get("name")&&(this.person=this.story?.get("person"))}selectChange(e){this.selectRange=e?.range,this.selectText=e?.text,this.selectQuill=e?.quill,this.cdRef.detectChanges()}goOptimizeText(e){this.selectChange(e)}setContent(e,t){t?t.content=e:this.story?.set("content",e),this.contentChanged=!0}save(){this.contentChanged=!1,this.story?.save()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompDiaryStoryComponent,deps:[{token:i1$3.ModalController},{token:i0.ChangeDetectorRef}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:CompDiaryStoryComponent,isStandalone:!0,selector:"comp-diary-story",inputs:{story:"story",person:"person",showHeader:"showHeader",readOnly:"readOnly"},ngImport:i0,template:'@if(showHeader){\n <div class="filebar">\n \x3c!-- 文件信息 --\x3e\n <div class="file-info" style="display:flex;align-items:center;">\n \x3c!-- 图标+大小 --\x3e\n <ion-icon [src]="\'.chat\'|filetype"></ion-icon>\n <span class="size">{{story?.get("chatSession")?.get("messageList")?.length }}条</span>\n </div>\n \x3c!-- 标题 --\x3e\n <div class="title">\n {{story?.get("title")||\'未命名\'}}\n </div>\n \x3c!-- 操作区域 --\x3e\n <div class="actions" style="display:flex;align-items:center;justify-content: flex-end;">\n \x3c!-- 关闭 --\x3e\n <button mat-button (click)="back()" aria-label="预览">\n 关闭\n </button>\n </div>\n</div>\n}\n<ng-container *ngIf="story?.get(\'contentJson\')">\n <div [style.overflowY]="\'auto\'">\n\n @if(showInfo){\n\n @if(person?.id){\n <fm-comp-person-item [person]="person"></fm-comp-person-item>\n }\n \x3c!-- 采访主题 --\x3e\n \x3c!-- <ion-item>\n <ion-label>主题</ion-label>\n {{story?.get(\'contentJson\')?.title}}\n </ion-item> --\x3e\n <ion-item>\n <ion-label>日期</ion-label>\n {{(story?.get("recordDate") || now) | date:"yy/MM/dd HH:mm"}}\n </ion-item>\n <ion-item>\n <ion-label>标签</ion-label>\n <ion-chip *ngFor="let item of story?.get(\'contentJson\')?.keywords" color="success">{{item}}</ion-chip>\n </ion-item>\n <ion-item>\n <ion-textarea label="概述" [readonly]="true" [autoGrow]="true" [ngModel]="story?.get(\'contentJson\')?.desc"></ion-textarea>\n </ion-item>\n }\n\n <ion-list>\n <ion-item-group>\n <ion-item>\n <ion-label style="position: absolute;left: 0;width:50px;">主题</ion-label>\n <ion-label style="text-align:center;">{{story?.get(\'contentJson\')?.title}}</ion-label>\n <ion-button (click)="showInfo=!showInfo" style="position: absolute;right: 0;">{{showInfo?"折叠":"展开"}}</ion-button>\n <ion-button *ngIf="contentChanged" (click)="save()" style="position: absolute;right: 0;" [style.marginRight]="showInfo?\'50px\':\'0px\'">保存</ion-button>\n </ion-item>\n </ion-item-group>\n @if(story?.get(\'content\')){\n <fm-text-quill #textQuill [theme]="\'snow\'" [toolbar]="toolbar" [readOnly]="readOnly" [content]="story?.get(\'content\')" (onContentChange)="setContent($event)"\n (onAIClick)="goOptimizeText($event)" (onSelectChange)="selectChange($event)"\n ></fm-text-quill>\n }\n </ion-list>\n</div>\n\n</ng-container>',styles:[".filebar{display:flex;justify-content:space-between;align-items:center;padding:5px 15px}.filebar .file-info{max-width:80px}.filebar .title{flex:1;font-weight:700;margin-left:5px;margin-right:5px;max-width:220px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;text-align:center}.filebar mat-card-content{color:#333}.filebar ion-icon{font-size:28px;min-width:30px}.filebar ion-chip{color:#333}.filebar .actions{max-width:104px}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"pipe",type:i2.DatePipe,name:"date"},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"ngmodule",type:ReactiveFormsModule},{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:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:IonItemGroup,selector:"ion-item-group"},{kind:"component",type:IonChip,selector:"ion-chip",inputs:["color","disabled","mode","outline"]},{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: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:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"ngmodule",type:NzPipesModule},{kind:"pipe",type:FiletypePipe,name:"filetype"},{kind:"component",type:FmTextQuillComponent,selector:"fm-text-quill",inputs:["readOnly","content","theme","toolbar"],outputs:["onAIClick","onContentChange","onSelectChange"]},{kind:"component",type:CompPersonItemComponent,selector:"fm-comp-person-item",inputs:["person"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompDiaryStoryComponent,decorators:[{type:Component,args:[{selector:"comp-diary-story",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,IonItem,IonLabel,IonIcon,IonList,IonCard,IonCardHeader,IonCardTitle,IonCardSubtitle,IonCardContent,IonNote,IonItemGroup,IonItemDivider,IonChip,IonButton,IonTextarea,MatButtonModule,NzPipesModule,FiletypePipe,FmTextQuillComponent,CompPersonItemComponent],template:'@if(showHeader){\n <div class="filebar">\n \x3c!-- 文件信息 --\x3e\n <div class="file-info" style="display:flex;align-items:center;">\n \x3c!-- 图标+大小 --\x3e\n <ion-icon [src]="\'.chat\'|filetype"></ion-icon>\n <span class="size">{{story?.get("chatSession")?.get("messageList")?.length }}条</span>\n </div>\n \x3c!-- 标题 --\x3e\n <div class="title">\n {{story?.get("title")||\'未命名\'}}\n </div>\n \x3c!-- 操作区域 --\x3e\n <div class="actions" style="display:flex;align-items:center;justify-content: flex-end;">\n \x3c!-- 关闭 --\x3e\n <button mat-button (click)="back()" aria-label="预览">\n 关闭\n </button>\n </div>\n</div>\n}\n<ng-container *ngIf="story?.get(\'contentJson\')">\n <div [style.overflowY]="\'auto\'">\n\n @if(showInfo){\n\n @if(person?.id){\n <fm-comp-person-item [person]="person"></fm-comp-person-item>\n }\n \x3c!-- 采访主题 --\x3e\n \x3c!-- <ion-item>\n <ion-label>主题</ion-label>\n {{story?.get(\'contentJson\')?.title}}\n </ion-item> --\x3e\n <ion-item>\n <ion-label>日期</ion-label>\n {{(story?.get("recordDate") || now) | date:"yy/MM/dd HH:mm"}}\n </ion-item>\n <ion-item>\n <ion-label>标签</ion-label>\n <ion-chip *ngFor="let item of story?.get(\'contentJson\')?.keywords" color="success">{{item}}</ion-chip>\n </ion-item>\n <ion-item>\n <ion-textarea label="概述" [readonly]="true" [autoGrow]="true" [ngModel]="story?.get(\'contentJson\')?.desc"></ion-textarea>\n </ion-item>\n }\n\n <ion-list>\n <ion-item-group>\n <ion-item>\n <ion-label style="position: absolute;left: 0;width:50px;">主题</ion-label>\n <ion-label style="text-align:center;">{{story?.get(\'contentJson\')?.title}}</ion-label>\n <ion-button (click)="showInfo=!showInfo" style="position: absolute;right: 0;">{{showInfo?"折叠":"展开"}}</ion-button>\n <ion-button *ngIf="contentChanged" (click)="save()" style="position: absolute;right: 0;" [style.marginRight]="showInfo?\'50px\':\'0px\'">保存</ion-button>\n </ion-item>\n </ion-item-group>\n @if(story?.get(\'content\')){\n <fm-text-quill #textQuill [theme]="\'snow\'" [toolbar]="toolbar" [readOnly]="readOnly" [content]="story?.get(\'content\')" (onContentChange)="setContent($event)"\n (onAIClick)="goOptimizeText($event)" (onSelectChange)="selectChange($event)"\n ></fm-text-quill>\n }\n </ion-list>\n</div>\n\n</ng-container>',styles:[".filebar{display:flex;justify-content:space-between;align-items:center;padding:5px 15px}.filebar .file-info{max-width:80px}.filebar .title{flex:1;font-weight:700;margin-left:5px;margin-right:5px;max-width:220px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;text-align:center}.filebar mat-card-content{color:#333}.filebar ion-icon{font-size:28px;min-width:30px}.filebar ion-chip{color:#333}.filebar .actions{max-width:104px}\n"]}]}],ctorParameters:()=>[{type:i1$3.ModalController},{type:i0.ChangeDetectorRef}],propDecorators:{story:[{type:Input}],person:[{type:Input}],showHeader:[{type:Input}],readOnly:[{type:Input}]}});class CompChatStoryJsonComponent{constructor(e){this.modalCtrl=e,this.showHeader=!1}back(){this.modalCtrl.dismiss()}ngOnInit(){this.story?.get("person")?.id&&this.story?.get("person")?.get("name")&&(this.person=this.story?.get("person"))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompChatStoryJsonComponent,deps:[{token:i1$3.ModalController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:CompChatStoryJsonComponent,isStandalone:!0,selector:"comp-chat-story-json",inputs:{story:"story",person:"person",showHeader:"showHeader"},ngImport:i0,template:'@if(showHeader){\n <div class="filebar">\n \x3c!-- 文件信息 --\x3e\n <div class="file-info" style="display:flex;align-items:center;">\n \x3c!-- 图标+大小 --\x3e\n <ion-icon [src]="\'.chat\'|filetype"></ion-icon>\n <span class="size">{{story?.get("chatSession")?.get("messageList")?.length }}条</span>\n </div>\n \x3c!-- 标题 --\x3e\n <div class="title">\n {{story?.get("title")||\'未命名\'}}\n </div>\n \x3c!-- 操作区域 --\x3e\n <div class="actions" style="display:flex;align-items:center;justify-content: flex-end;">\n \x3c!-- 关闭 --\x3e\n <button mat-button (click)="back()" aria-label="预览">\n 关闭\n </button>\n </div>\n</div>\n}\n<ng-container *ngIf="story?.get(\'contentJson\')">\n <div [style.overflowY]="\'auto\'">\n\n \x3c!-- 采访主题 --\x3e\n <ion-item>\n <ion-label>主题</ion-label>\n {{story?.get(\'contentJson\')?.title}}\n </ion-item>\n <ion-item>\n <ion-label>标签</ion-label>\n <ion-chip *ngFor="let item of story?.get(\'contentJson\')?.keywords" color="success">{{item}}</ion-chip>\n </ion-item>\n <ion-item>\n <ion-textarea label="概述" [readonly]="true" [autoGrow]="true" [ngModel]="story?.get(\'contentJson\')?.desc"></ion-textarea>\n </ion-item>\n\n \x3c!-- 话题卡片 --\x3e\n <ion-list>\n <ion-card color="primary" *ngFor="let topic of story?.get(\'contentJson\')?.topics||[];let index = index;">\n <ion-card-header>\n <ion-card-title>话题{{index+1}}.{{ topic.title }}</ion-card-title>\n <ion-card-subtitle><ion-chip *ngFor="let item of topic.keywords" color="warning">{{item}}</ion-chip></ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <p>{{ topic.content }}</p>\n <ion-list>\n <ng-container *ngFor="let qa of topic.list">\n <ion-item >\n <ion-note slot="start" color="medium">\n 问\n </ion-note>\n <ion-label>\n {{ qa.q }}\n </ion-label>\n </ion-item>\n <ion-item >\n <ion-label>\n {{ qa.a }}\n </ion-label>\n <ion-note slot="end" color="medium">\n 答\n </ion-note>\n </ion-item>\n </ng-container>\n \n </ion-list>\n </ion-card-content>\n </ion-card>\n </ion-list>\n <ion-list>\n <ion-item-group *ngIf="person">\n <ion-item>\n <ion-label style="text-align:center;">延伸问题</ion-label>\n </ion-item>\n <ion-item *ngFor="let item of story?.get(\'contentJson\')?.questions||[];let index = index;">\n {{index+1}}{{item}}\n </ion-item>\n </ion-item-group>\n </ion-list>\n</div>\n\n</ng-container>',styles:[".filebar{display:flex;justify-content:space-between;align-items:center;padding:5px 15px}.filebar .file-info{max-width:80px}.filebar .title{flex:1;font-weight:700;margin-left:5px;margin-right:5px;max-width:220px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;text-align:center}.filebar mat-card-content{color:#333}.filebar ion-icon{font-size:28px;min-width:30px}.filebar ion-chip{color:#333}.filebar .actions{max-width:104px}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"ngmodule",type:ReactiveFormsModule},{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:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:IonCard,selector:"ion-card",inputs:["button","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:IonCardHeader,selector:"ion-card-header",inputs:["color","mode","translucent"]},{kind:"component",type:IonCardTitle,selector:"ion-card-title",inputs:["color","mode"]},{kind:"component",type:IonCardSubtitle,selector:"ion-card-subtitle",inputs:["color","mode"]},{kind:"component",type:IonCardContent,selector:"ion-card-content",inputs:["mode"]},{kind:"component",type:IonNote,selector:"ion-note",inputs:["color","mode"]},{kind:"component",type:IonItemGroup,selector:"ion-item-group"},{kind:"component",type:IonChip,selector:"ion-chip",inputs:["color","disabled","mode","outline"]},{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:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"ngmodule",type:NzPipesModule},{kind:"pipe",type:FiletypePipe,name:"filetype"}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompChatStoryJsonComponent,decorators:[{type:Component,args:[{selector:"comp-chat-story-json",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,IonItem,IonLabel,IonIcon,IonList,IonCard,IonCardHeader,IonCardTitle,IonCardSubtitle,IonCardContent,IonNote,IonItemGroup,IonItemDivider,IonChip,IonTextarea,MatButtonModule,NzPipesModule,FiletypePipe],template:'@if(showHeader){\n <div class="filebar">\n \x3c!-- 文件信息 --\x3e\n <div class="file-info" style="display:flex;align-items:center;">\n \x3c!-- 图标+大小 --\x3e\n <ion-icon [src]="\'.chat\'|filetype"></ion-icon>\n <span class="size">{{story?.get("chatSession")?.get("messageList")?.length }}条</span>\n </div>\n \x3c!-- 标题 --\x3e\n <div class="title">\n {{story?.get("title")||\'未命名\'}}\n </div>\n \x3c!-- 操作区域 --\x3e\n <div class="actions" style="display:flex;align-items:center;justify-content: flex-end;">\n \x3c!-- 关闭 --\x3e\n <button mat-button (click)="back()" aria-label="预览">\n 关闭\n </button>\n </div>\n</div>\n}\n<ng-container *ngIf="story?.get(\'contentJson\')">\n <div [style.overflowY]="\'auto\'">\n\n \x3c!-- 采访主题 --\x3e\n <ion-item>\n <ion-label>主题</ion-label>\n {{story?.get(\'contentJson\')?.title}}\n </ion-item>\n <ion-item>\n <ion-label>标签</ion-label>\n <ion-chip *ngFor="let item of story?.get(\'contentJson\')?.keywords" color="success">{{item}}</ion-chip>\n </ion-item>\n <ion-item>\n <ion-textarea label="概述" [readonly]="true" [autoGrow]="true" [ngModel]="story?.get(\'contentJson\')?.desc"></ion-textarea>\n </ion-item>\n\n \x3c!-- 话题卡片 --\x3e\n <ion-list>\n <ion-card color="primary" *ngFor="let topic of story?.get(\'contentJson\')?.topics||[];let index = index;">\n <ion-card-header>\n <ion-card-title>话题{{index+1}}.{{ topic.title }}</ion-card-title>\n <ion-card-subtitle><ion-chip *ngFor="let item of topic.keywords" color="warning">{{item}}</ion-chip></ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <p>{{ topic.content }}</p>\n <ion-list>\n <ng-container *ngFor="let qa of topic.list">\n <ion-item >\n <ion-note slot="start" color="medium">\n 问\n </ion-note>\n <ion-label>\n {{ qa.q }}\n </ion-label>\n </ion-item>\n <ion-item >\n <ion-label>\n {{ qa.a }}\n </ion-label>\n <ion-note slot="end" color="medium">\n 答\n </ion-note>\n </ion-item>\n </ng-container>\n \n </ion-list>\n </ion-card-content>\n </ion-card>\n </ion-list>\n <ion-list>\n <ion-item-group *ngIf="person">\n <ion-item>\n <ion-label style="text-align:center;">延伸问题</ion-label>\n </ion-item>\n <ion-item *ngFor="let item of story?.get(\'contentJson\')?.questions||[];let index = index;">\n {{index+1}}{{item}}\n </ion-item>\n </ion-item-group>\n </ion-list>\n</div>\n\n</ng-container>',styles:[".filebar{display:flex;justify-content:space-between;align-items:center;padding:5px 15px}.filebar .file-info{max-width:80px}.filebar .title{flex:1;font-weight:700;margin-left:5px;margin-right:5px;max-width:220px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;text-align:center}.filebar mat-card-content{color:#333}.filebar ion-icon{font-size:28px;min-width:30px}.filebar ion-chip{color:#333}.filebar .actions{max-width:104px}\n"]}]}],ctorParameters:()=>[{type:i1$3.ModalController}],propDecorators:{story:[{type:Input}],person:[{type:Input}],showHeader:[{type:Input}]}});const agentPrompt$2=new AgentPrompt,PromptTplSessionStoryCode="story-chat-session-tpl";addIcons({alertCircleOutline:alertCircleOutline});class ModalChatStoryComponent{constructor(e,t,n,o,i){this.alertCtrl=e,this.modalCtrl=t,this.personServ=n,this.navCtrl=o,this.route=i,this.title="",this.subtitle="",this.desc="",this.promptTpl=PromptTplSessionStoryCode,this.type="chat",this.now=new Date,this.isCreating=!1,this.Story=Parse__default.Object.extend("Story"),this.relationName="",this.defaultAvatar="/assets/img/icon/avatar.svg",this.summaryContent=""}ngOnInit(){this.loadPerson(),this.story?.id&&this.onBreakPointSet&&this.onBreakPointSet(.75)}async loadPerson(){let e=this.chatSession?.id||this.chatSession?.objectId;if(this.chatSession=await this.personServ.loadObjectById("ChatSession",e,["person","user","recorder","story"]),this.story=this.chatSession.get("story"),!this.person?.id){let e=(window.location.search?.replaceAll("?","")).split("&").find((e=>e.indexOf("pid=")>-1)),t=e?.split("=")?.[1];if(t){let e=new Parse__default.Query("Person");this.person=await e.get(t)}}this.person?.id||(this.person=this.story?.get("person")||this.story?.get("chatSession")?.get("person")),"Pointer"==this.person?.__type&&(this.person=await this.personServ.loadPersonById(this.person?.objectId)),this.relationName="朋友";let t=this.chatSession?.get("user")?.get("realname"),n=this.person?.get("name");n==t&&(this.relationName="本人")}async createStory(){let e=this.chatSession?.get("person")||this.person;e?.id||(e=await openPersonSelectModal(this.modalCtrl));let t=this.chatSession?.id||this.chatSession?.objectId;if(this.chatSession=await this.personServ.loadObjectById("ChatSession",t,["person","user","recorder"]),!this.chatSession?.id){return void(await this.alertCtrl.create({header:"当前会话未开始",message:"请聊一会儿再总结哦!"})).present()}this.isCreating=!0;let n=this.story||new this.Story;this.person&&n.set("person",this.person?.toPointer()),n.set("type",this.type),n.set("user",Parse__default.User.current());let o=await this.personServ.loadSelfPerson();n.set("chatSession",this.chatSession?.toPointer()),n.set("recorder",o),n.set("recordDate",this.chatSession?.createdAt);let i=this.chatSession.get("messageList"),a="",r=this.person?.get("name"),s=this.chatSession?.get("user")?.get("realname");i.forEach((e=>{if("system"==e?.role)return;let t="记者";"user"==e?.role&&(t=s);let n=getMessageContentText(e?.content);a+=`${t}:\n${n}\n`})),this.relationName="朋友",r==s&&(this.relationName="本人");let l=await agentPrompt$2.getFormatTpl(this.promptTpl,{personName:this.person?.get("name"),userName:s,relationName:this.relationName,messageRecord:a,createdAt:this.chatSession?.createdAt}),c=new FmodeChatCompletion([{role:"user",content:l}]);c.model="fmode-4.0-cn-256k";c.sendCompletion({isDirect:!0}).pipe(finalize((()=>{}))).subscribe((async e=>{if(this.summaryContent=e.content,e?.complete){let t=e?.content||"",i=agentPrompt$2.extractAndParseJson(t);n.set("title",i?.title),n.set("desc",i?.desc),n.set("keywords",i?.keywords),n.set("content",i?.content||""),delete i.content,n.set("contentJson",i),n=await n.save(),this.story=n;let a=this.person?.toPointer()||this.chatSession.get("person")?.toPointer&&this.chatSession.get("person")?.toPointer()||o?.toPointer();this.chatSession?.set("title",i?.title),this.chatSession?.set("story",n.toPointer()),a&&(console.log(a),this.chatSession?.set("person",a)),this.chatSession=await(this.chatSession?.save()),this.isCreating=!1,this.onCanDismiss&&this.onCanDismiss(!0),this.onBreakPointSet&&this.onBreakPointSet(.75)}}))}confirm(){this.modalCtrl.dismiss(null,"confirm"),window.location.pathname?.indexOf("chat/session")>-1&&this.navCtrl.back()}cancel(){this.modalCtrl.dismiss(null,"cancel"),window.location.pathname?.indexOf("chat/session")>-1&&this.navCtrl.back()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalChatStoryComponent,deps:[{token:i1$3.AlertController},{token:i1$3.ModalController},{token:PersonService},{token:i1$3.NavController},{token:i1$1.ActivatedRoute}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:ModalChatStoryComponent,isStandalone:!0,selector:"app-modal-chat-story",inputs:{title:"title",subtitle:"subtitle",desc:"desc",promptTpl:"promptTpl",type:"type",isCreating:"isCreating",story:"story"},ngImport:i0,template:'<ion-header *ngIf="story?.id&&story?.get(\'contentJson\')">\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="cancel()">返回</ion-button>\n </ion-buttons>\n <ion-title>{{title}}</ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="confirm()" [strong]="true">确认</ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class="ion-padding">\n\n \x3c!-- 提示:总结对话 --\x3e\n <ion-list *ngIf="!(story || chatSession?.get(\'story\'))?.get(\'contentJson\') && !isCreating">\n <ion-item>\n <ion-icon color="success" name="alert-circle-outline"></ion-icon>\n <ion-label>{{subtitle}}</ion-label>\n </ion-item>\n <ion-item>\n <ion-label>{{desc}}</ion-label>\n </ion-item>\n <div style="display:flex;justify-content: end;">\n <ion-button color="light" slot="end" (click)="cancel()">取消</ion-button>\n <ion-button style="margin-left:20px;" (click)="createStory()" color="success" slot="end">确认</ion-button>\n </div>\n </ion-list>\n\n\n \x3c!-- 加载:总结过程 --\x3e\n <div class="page" *ngIf="isCreating">\n <ion-spinner name="crescent" color="primary" style="width:80px;height:80px;"></ion-spinner>\n <ion-label color="primary">AI正在分析会话内容...</ion-label>\n <ion-label color="primary">{{(summaryContent?.length || 0)*1.5}} tokens</ion-label>\n \n </div>\n\n \x3c!-- 结果:总结后成果 --\x3e\n\n <ion-list *ngIf="(story || chatSession?.get(\'story\'))?.get(\'contentJson\')">\n @if(type=="diary"){\n <comp-diary-story [story]="story" [person]="person"></comp-diary-story>\n }\n @if(type==\'chat\'){\n <ion-item-group *ngIf="person?.id">\n <ion-item>\n <ion-label style="text-align:center;">话题人物</ion-label>\n </ion-item>\n \n <fm-comp-person-item [person]="person"></fm-comp-person-item>\n </ion-item-group>\n\n <ion-item-group>\n <ion-item>\n <ion-label style="text-align:center;">采访摘要</ion-label>\n </ion-item>\n </ion-item-group>\n\n <ion-item>\n <ion-label>采访日期</ion-label>\n {{(story?.get("recordDate") || now) | date:"yy/MM/dd HH:mm"}}\n </ion-item>\n <ion-item>\n <ion-label>被采访人</ion-label>\n {{story?.get("recorder")?.get("name")}} <ion-chip color="warning" *ngIf="relationName">{{relationName}}</ion-chip>\n </ion-item>\n <comp-chat-story-json [story]="story"></comp-chat-story-json>\n }\n \x3c!-- <ion-item>\n <fm-markdown-preview class="content" *ngIf="story?.get(\'content\')" [content]="story?.get(\'content\')"></fm-markdown-preview>\n </ion-item> --\x3e\n </ion-list>\n</ion-content>\n\n',styles:[".page{display:flex;justify-content:center;align-items:center;flex-direction:column}.content{filter:invert(1)!important}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"pipe",type:i2.DatePipe,name:"date"},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"component",type:IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"component",type:IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"component",type:IonButtons,selector:"ion-buttons",inputs:["collapse"]},{kind:"component",type:IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{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:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonList,selector:"ion-list",inputs:["inset","lines","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:IonItemGroup,selector:"ion-item-group"},{kind:"component",type:IonSpinner,selector:"ion-spinner",inputs:["color","duration","name","paused"]},{kind:"component",type:IonChip,selector:"ion-chip",inputs:["color","disabled","mode","outline"]},{kind:"component",type:CompPersonItemComponent,selector:"fm-comp-person-item",inputs:["person"]},{kind:"ngmodule",type:MarkdownPreviewModule},{kind:"component",type:CompDiaryStoryComponent,selector:"comp-diary-story",inputs:["story","person","showHeader","readOnly"]},{kind:"component",type:CompChatStoryJsonComponent,selector:"comp-chat-story-json",inputs:["story","person","showHeader"]}]})}}async function openChatStoryModal(e,t,n){let o=t?.get("story"),i=.4;o?.id&&o?.get("contentJson")&&(i=.75);let a={chatSession:t,story:o,onBreakPointSet:e=>{r.setCurrentBreakpoint(e)},onCanDismiss:e=>{r.canDismiss=e}};a.type=n?.type||"chat",a.title=n?.title||"采访总结",a.subtitle=n?.subtitle||"任务: 总结分析本次对话",a.desc=n?.desc||"总结后的对话信息,将进入人物知识库,可被检索和选择。但不可继续聊天!您是否确认总结本次对话内容?",a.promptTpl=n?.promptTpl||PromptTplSessionStoryCode;let r=await e.create({component:ModalChatStoryComponent,componentProps:a,breakpoints:[.3,.5,.75,1],initialBreakpoint:i});r.present();let{data:s,role:l}=await r.onWillDismiss();return"confirm"==l?s:null}async function previewStoryMobile(e,t){let n,o=await getStoryType(e);if(n=new AgentStory(e,e?.get("person"),e?.get("book")),console.log(o,n?.story),"document"==o){let e=n?.story?.get("attach")?.id;openStoryPreview(t?.modalCtrl,t?.alertCtrl,{previewComp:FmOfficeViewerComponent,props:{showHeader:!0,fileId:e}})}"chat"==o&&openChatStoryModal(t?.modalCtrl,e?.get("chatSession"),{type:"chat",title:"采访总结",subtitle:"任务: 总结分析本次对话",desc:"总结后的对话信息,将进入人物知识库,可被检索和选择。但不可继续聊天!您是否确认总结本次对话内容?",promptTpl:"story-chat-session-tpl"}),"diary"==o&&openChatStoryModal(t?.modalCtrl,e?.get("chatSession"),{type:"diary",title:"日记整理",subtitle:"任务:语音整理日记文本",desc:"总结生成后的日记将加入日记列表,可被检索和选择。但是不可继续对话!您是否确认生成本次日记?",promptTpl:"diary-chat-session-html-tpl"})}async function getStoryType(e){return"diary"==e?.get("type")?"diary":e?.get("attach")?.id?"document":e?.get("chatSession")?.id?"chat":""}async function getRoleById(e){return new Parse__default.Query("AvatarRole").get(e)}async function openStoryPreview(e,t,n){n.props=n?.props||{},n.props.onBreakPointSet=()=>{o?.setCurrentBreakpoint(.75)};let o=await e.create({component:n?.previewComp,componentProps:n?.props,breakpoints:[1],initialBreakpoint:1});o.present();let{data:i,role:a}=await o.onWillDismiss();if("confirm"==a)return i}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalChatStoryComponent,decorators:[{type:Component,args:[{selector:"app-modal-chat-story",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,IonHeader,IonTitle,IonToolbar,IonButtons,IonModal,IonContent,IonLabel,IonAvatar,IonImg,IonButton,IonIcon,IonList,IonItem,IonItemGroup,IonItemDivider,IonTextarea,IonSpinner,IonChip,CompPersonItemComponent,MarkdownPreviewModule,CompDiaryStoryComponent,CompChatStoryJsonComponent],template:'<ion-header *ngIf="story?.id&&story?.get(\'contentJson\')">\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="cancel()">返回</ion-button>\n </ion-buttons>\n <ion-title>{{title}}</ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="confirm()" [strong]="true">确认</ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class="ion-padding">\n\n \x3c!-- 提示:总结对话 --\x3e\n <ion-list *ngIf="!(story || chatSession?.get(\'story\'))?.get(\'contentJson\') && !isCreating">\n <ion-item>\n <ion-icon color="success" name="alert-circle-outline"></ion-icon>\n <ion-label>{{subtitle}}</ion-label>\n </ion-item>\n <ion-item>\n <ion-label>{{desc}}</ion-label>\n </ion-item>\n <div style="display:flex;justify-content: end;">\n <ion-button color="light" slot="end" (click)="cancel()">取消</ion-button>\n <ion-button style="margin-left:20px;" (click)="createStory()" color="success" slot="end">确认</ion-button>\n </div>\n </ion-list>\n\n\n \x3c!-- 加载:总结过程 --\x3e\n <div class="page" *ngIf="isCreating">\n <ion-spinner name="crescent" color="primary" style="width:80px;height:80px;"></ion-spinner>\n <ion-label color="primary">AI正在分析会话内容...</ion-label>\n <ion-label color="primary">{{(summaryContent?.length || 0)*1.5}} tokens</ion-label>\n \n </div>\n\n \x3c!-- 结果:总结后成果 --\x3e\n\n <ion-list *ngIf="(story || chatSession?.get(\'story\'))?.get(\'contentJson\')">\n @if(type=="diary"){\n <comp-diary-story [story]="story" [person]="person"></comp-diary-story>\n }\n @if(type==\'chat\'){\n <ion-item-group *ngIf="person?.id">\n <ion-item>\n <ion-label style="text-align:center;">话题人物</ion-label>\n </ion-item>\n \n <fm-comp-person-item [person]="person"></fm-comp-person-item>\n </ion-item-group>\n\n <ion-item-group>\n <ion-item>\n <ion-label style="text-align:center;">采访摘要</ion-label>\n </ion-item>\n </ion-item-group>\n\n <ion-item>\n <ion-label>采访日期</ion-label>\n {{(story?.get("recordDate") || now) | date:"yy/MM/dd HH:mm"}}\n </ion-item>\n <ion-item>\n <ion-label>被采访人</ion-label>\n {{story?.get("recorder")?.get("name")}} <ion-chip color="warning" *ngIf="relationName">{{relationName}}</ion-chip>\n </ion-item>\n <comp-chat-story-json [story]="story"></comp-chat-story-json>\n }\n \x3c!-- <ion-item>\n <fm-markdown-preview class="content" *ngIf="story?.get(\'content\')" [content]="story?.get(\'content\')"></fm-markdown-preview>\n </ion-item> --\x3e\n </ion-list>\n</ion-content>\n\n',styles:[".page{display:flex;justify-content:center;align-items:center;flex-direction:column}.content{filter:invert(1)!important}\n"]}]}],ctorParameters:()=>[{type:i1$3.AlertController},{type:i1$3.ModalController},{type:PersonService},{type:i1$3.NavController},{type:i1$1.ActivatedRoute}],propDecorators:{title:[{type:Input}],subtitle:[{type:Input}],desc:[{type:Input}],promptTpl:[{type:Input}],type:[{type:Input}],isCreating:[{type:Input}],story:[{type:Input}]}}),addIcons(icons);class FmStoryListComponent{changeStoryType(e){this.storyType=e,this.loadStory()}cancel(){this.onCancel.emit(!0)}checkStory(e){let t=e?.story,n=e?.event;console.log(e),console.log(t,n),t?.story?.id&&(this.checkedMap[t?.story?.id]=n),this.selectCount=Object.values(this.checkedMap)?.filter((e=>e))?.length||0,this.onCountChange.emit(this.selectCount),this.calcSelectTokens()}async calcSelectTokens(){let e=await this.getAllSelectDocument(),t=e?.documentList||[];this.selectToken=0;let n=e?.storyList?.filter((e=>e.get("chatSession")));return t.forEach((e=>{let t=e?.get("pageContent")||"";t=t?.replaceAll("\n\n","\n"),this.selectToken+=1.5*t.length})),n.forEach((e=>{let t=e?.get("contentJson");t=JSON.stringify(t),t=t?.replaceAll("\n\n","\n"),console.log(t),this.selectToken+=1.5*t.length})),this.onTokenChange.emit(this.selectToken),this.selectToken}async confirmSelectedList(){let e=await this.getAllSelectDocument(),t=e?.documentList||[],n=e?.storyList||[];this.onConfirmSelect.emit({storyList:n,documentList:t})}async getAllSelectDocument(){let e=[],t=[];this.storyServ.storyList?.forEach((e=>{e?.story?.id&&this.checkedMap[e?.story?.id||"new"]&&t.push(e?.story)}));let n=t?.map((e=>e?.get("attach")?.get("md5")));if(n=n?.filter((e=>e)),n?.length){let t=new Parse__default.Query("Document");t.equalTo("type","entire"),t.limit(200),console.log("md5List",n),t.containedIn("md5",n),e=await t.find()}return{documentList:e,storyList:t}}constructor(e,t,n,o,i,a,r,s,l,c,d){this.route=e,this.loadingCtrl=t,this.dialog=n,this.router=o,this.storyServ=i,this.chatServ=a,this.alertCtrl=r,this.modalCtrl=s,this.navCtrl=l,this.ncloud=c,this.nupload=d,this.defaultAvatar=avatarIcon,this.isPreview=!1,this.currentTab="我的",this.height="100%",this.isSelectMode=!1,this.checkedMap={},this.selectCount=0,this.selectToken=0,this.onCancel=new EventEmitter,this.onCountChange=new EventEmitter,this.onTokenChange=new EventEmitter,this.onPreviewStory=new EventEmitter,this.storyType="",this.onConfirmSelect=new EventEmitter}async ngOnInit(){if(!this.person?.id||this.book?.id){let e=this.route.snapshot.params?.id||this.route?.parent?.snapshot?.params?.id;if(location?.pathname?.indexOf("editor/book")>-1){let t=new Parse__default.Query("Book");t.include("person"),this.book=await t.get(e),this.person=this.book.get("person")}if(location?.pathname?.indexOf("editor/person")>-1){let t=new Parse__default.Query("Person");this.person=await t.get(e)}}await this.loadStory(),0==this.storyServ.storyList?.length&&this.newStory()}getArticleDocList(){let e={},t=this.article?.get("outlineJson"),n=t?.sections;return n?.forEach((t=>{let n=t?.docList;n?.forEach((t=>{e[t]||(e[t]=!0,this.checkedMap[t]=!0)}))})),console.log(Object.keys(e)),Object.keys(e)||[]}async loadStory(){this.storyServ.storyList=[];let e,t=[];if(this.article?.id&&(e=await this.getArticleDocList(),e?.length&&t.push({objectId:{$in:e}})),this.person?.id&&"主角数据"==this.currentTab){let e={__type:"Pointer",className:"Person",objectId:this.person.id};t.push({person:e})}if(this.book?.id&&"主角数据"==this.currentTab){let e={__type:"Pointer",className:"Book",objectId:this.book.id};t.push({book:e})}if(Parse__default.User.current()?.id&&t.push({user:Parse__default.User.current()?.toPointer()}),!t?.length)return;let n=Parse__default.Query.fromJSON("Story",{where:{$or:t}});n.include("attach","chatSession","person"),this.storyType&&n.equalTo("type",this.storyType),"主角数据"==this.currentTab&&n.equalTo("person",this.person?.id),"书籍数据"==this.currentTab&&n.equalTo("book",this.book?.id),n.notEqualTo("isDeleted",!0),n.addDescending("createdAt");let o=await n.find();this.storyServ.storyList=o.map((e=>new AgentStory(e,void 0,void 0))),this.currentStory=this.storyServ.storyList?.[0],this.selectCount=Object.values(this.checkedMap)?.filter((e=>e))?.length||0,this.onCountChange.emit(this.selectCount),this.calcSelectTokens()}newStory(){this.currentStory=this.storyServ.newStory({person:this.person,book:this.book}),this.currentStory&&this.previewStory(this.currentStory)}async previewStory(e){let t=e;if(this.onPreviewStory.emit(t),document.body.clientWidth<1e3)return void(t?.story&&previewStoryMobile(t?.story,{chatServ:this.chatServ,alertCtrl:this.alertCtrl,modalCtrl:this.modalCtrl,navCtrl:this.navCtrl,ncloud:this.ncloud,nupload:this.nupload}));this.currentStory=void 0;let n=t?.story?.get("attach")?.id?1e3:100;(await this.loadingCtrl.create({message:"故事渲染中...",duration:n})).present(),this.currentStory=t}async destroyStory(e,t){let n=e;this.dialog.open(DialogDeleteStoryDialog,{data:{}}).afterClosed().subscribe((async e=>{if(e)return n?.story?.id&&(n.story.set("isDeleted",!0),await n.story.save()),this.storyServ.storyList?.splice(t,1),void(this.storyServ.storyList?.[0]?this.previewStory(this.storyServ.storyList?.[0]):this.currentStory=void 0)}))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmStoryListComponent,deps:[{token:i1$1.ActivatedRoute},{token:i3.LoadingController},{token:i3$1.MatDialog},{token:i1$1.Router},{token:StoryService},{token:ChatService},{token:i1$3.AlertController},{token:i1$3.ModalController},{token:i1$3.NavController},{token:NovaCloudService},{token:NovaUploadService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:FmStoryListComponent,isStandalone:!0,selector:"fm-story-list",inputs:{id:"id",article:"article",person:"person",book:"book",isSelectMode:"isSelectMode"},outputs:{onCancel:"onCancel",onCountChange:"onCountChange",onTokenChange:"onTokenChange",onPreviewStory:"onPreviewStory",onConfirmSelect:"onConfirmSelect"},ngImport:i0,template:'\x3c!-- \n <ion-header>\n <ion-toolbar>\n <ion-title>知识库</ion-title>\n <ion-buttons slot="end">\n <ion-button *ngIf="!isSelectMode" (click)="newStory()" [strong]="true">新建</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content> --\x3e\n\n <div class="page">\n\n <div class="filter">\n \x3c!-- <button mat-icon-button class="example-icon" aria-label="Example icon-button with menu icon">\n <mat-icon>menu</mat-icon>\n </button> --\x3e\n\n \x3c!-- 知识库切换 --\x3e\n <ion-chip>\n <ion-avatar>\n <img alt="角色头像" [src]="defaultAvatar" />\n </ion-avatar>\n <ion-label>故事卡片</ion-label>\n <ion-icon name="swap-vertical-outline"></ion-icon>\n </ion-chip>\n\n <span class="example-spacer"></span>\n\n\n \x3c!-- 添加故事 --\x3e\n @if(false){\n <button mat-flat-button color="primary" (click)="newStory()" *ngIf="!isSelectMode">\n <span nz-icon nzType="plus" nzTheme="outline"></span> 上传\n </button>\n }\n\n \x3c!-- 选择状态 --\x3e\n <button mat-button color="primary" (click)="cancel()" *ngIf="isSelectMode" style="margin-left:5px;">\n <span nz-icon nzType="plus" nzTheme="outline"></span> 取消\n </button>\n <button mat-flat-button color="primary" (click)="confirmSelectedList()" *ngIf="isSelectMode">\n <span nz-icon nzType="plus" nzTheme="outline"></span> 确认选择\n </button>\n \x3c!-- <button mat-icon-button class="example-icon favorite-icon" aria-label="Example icon-button with heart icon">\n <mat-icon>favorite</mat-icon>\n </button> --\x3e\n <button id="trigger-button" mat-icon-button class="example-icon" aria-label="Example icon-button with share icon">\n <mat-icon>tune</mat-icon>\n </button>\n <ion-popover trigger="trigger-button" size="auto" side="bottom" alignment="end" style="--width: 34%;margin-left: 0%;">\n <ng-template>\n <ion-content class="ion-padding">\n <ion-item-group>\n <ion-item-divider>\n <ion-label>类型</ion-label>\n </ion-item-divider>\n <ion-item lines="none">\n <mat-chip-listbox [value]="storyType" aria-label="类型">\n <mat-chip-option (click)="changeStoryType(\'\')" value="">全部</mat-chip-option>\n <mat-chip-option (click)="changeStoryType(\'document\')" value="document">文档</mat-chip-option>\n <mat-chip-option (click)="changeStoryType(\'chat\')" value="chat">聊天</mat-chip-option>\n <mat-chip-option (click)="changeStoryType(\'diary\')" value="diary">日记</mat-chip-option>\n \x3c!-- <mat-chip-option color="accent" selected>Accent fish</mat-chip-option> --\x3e\n \x3c!-- <mat-chip-option color="warn">Warn fish</mat-chip-option> --\x3e\n </mat-chip-listbox>\n </ion-item>\n </ion-item-group>\n \n </ion-content>\n </ng-template>\n </ion-popover>\n </div>\n\n \x3c!-- 选择模式:选择数据 --\x3e\n @if(selectCount&&selectToken){\n <div class="select">\n <span>已选 {{selectCount||0}}个</span>\n <span style="margin-left:3px;">约{{selectToken||0}}tokens</span>\n </div>\n }\n \n <div class="list">\n\n\n \x3c!-- 切换筛选类型(角色故事、书籍故事、用户故事) --\x3e\n @if(person?.id || book?.id){\n <mat-button-toggle-group name="fontStyle">\n <mat-button-toggle (click)="currentTab=\'我的\';loadStory()" *ngIf="person?.id || book?.id" [checked]="currentTab==\'我的\'">\n <span nz-icon nzType="user" nzTheme="outline"></span> 我的\n </mat-button-toggle>\n <mat-button-toggle (click)="currentTab=\'主角\';loadStory()" *ngIf="person?.id" [checked]="currentTab==\'主角\'">\n <span nz-icon nzType="user" nzTheme="outline"></span> 主角\n </mat-button-toggle>\n <mat-button-toggle (click)="currentTab=\'书籍\';loadStory()" *ngIf="book?.id" [checked]="currentTab==\'书籍\'">\n <span nz-icon nzType="read" nzTheme="outline"></span> 书籍\n </mat-button-toggle>\n </mat-button-toggle-group>\n }\n \n \x3c!-- 故事卡片 --\x3e\n <ng-container *ngFor="let story of storyServ.storyList;let index=index;">\n <fm-story-card class="list-item" [story]="story?.story" [isSelectMode]="isSelectMode" \n [(checked)]="checkedMap[story?.story?.id||\'\']"\n (onCheckStory)="checkStory($event)" \n (onPreviewStory)="previewStory($event)"\n (onDestoryStory)="destroyStory($event,index)"\n ></fm-story-card>\n </ng-container>\n </div>\n \x3c!-- </ion-content> --\x3e\n</div>\n',styles:[".page{width:100%;height:100%;display:flex;flex-direction:column;background:var(--yuban-page-background)}.page .filter{height:48px;display:flex;align-items:center}.page .filter .example-spacer{flex:1 1 auto}.page .select{display:flex;justify-content:center;height:32px}.page .select span{background-color:none;color:#ccc}.page .select mat-chip{background-color:none!important}.page mat-button-toggle-group{display:flex;height:25px;align-items:center;margin-top:11px}.page mat-button-toggle-group mat-button-toggle{flex:50%}.page ion-popover{--min-width:300px}.page .list{flex:1;display:flex;flex-direction:column;overflow-y:auto;border-radius:5px;height:100%;padding:5px}.page .list button{width:100%;margin-bottom:5px}.page .list .list-item{margin-bottom:7px}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"ngmodule",type:MatToolbarModule},{kind:"ngmodule",type:MatChipsModule},{kind:"component",type:i10.MatChipListbox,selector:"mat-chip-listbox",inputs:["multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:i10.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["selectable","selected"],outputs:["selectionChange"]},{kind:"ngmodule",type:MatButtonToggleModule},{kind:"directive",type:i11.MatButtonToggleGroup,selector:"mat-button-toggle-group",inputs:["appearance","name","vertical","value","multiple","disabled","hideSingleSelectionIndicator","hideMultipleSelectionIndicator"],outputs:["valueChange","change"],exportAs:["matButtonToggleGroup"]},{kind:"component",type:i11.MatButtonToggle,selector:"mat-button-toggle",inputs:["aria-label","aria-labelledby","id","name","value","tabIndex","disableRipple","appearance","checked","disabled"],outputs:["change"],exportAs:["matButtonToggle"]},{kind:"ngmodule",type:MatCheckboxModule},{kind:"ngmodule",type:MatDialogModule},{kind:"ngmodule",type:MatCardModule},{kind:"ngmodule",type:MatProgressBarModule},{kind:"ngmodule",type:MatDividerModule},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"component",type:i3$2.MatIconButton,selector:"button[mat-icon-button]",exportAs:["matButton"]},{kind:"ngmodule",type:MatIconModule},{kind:"component",type:i6.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"component",type:IonPopover,selector:"ion-popover"},{kind:"component",type:IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{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:IonItemGroup,selector:"ion-item-group"},{kind:"component",type:IonItemDivider,selector:"ion-item-divider",inputs:["color","mode","sticky"]},{kind:"component",type:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:IonChip,selector:"ion-chip",inputs:["color","disabled","mode","outline"]},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonAvatar,selector:"ion-avatar"},{kind:"component",type:FmStoryCardComponent,selector:"fm-story-card",inputs:["story","isSelectMode","checked"],outputs:["checkedChange","onCheckStory","onPreviewStory","onDestoryStory"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmStoryListComponent,decorators:[{type:Component,args:[{selector:"fm-story-list",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,MatToolbarModule,MatChipsModule,MatButtonToggleModule,MatCheckboxModule,MatDialogModule,MatCardModule,MatProgressBarModule,MatDividerModule,MatButtonModule,MatIconModule,MatChipsModule,MatChipListbox,IonPopover,IonContent,IonItem,IonItemGroup,IonItemDivider,IonLabel,IonChip,IonIcon,IonAvatar,FmStoryCardComponent],template:'\x3c!-- \n <ion-header>\n <ion-toolbar>\n <ion-title>知识库</ion-title>\n <ion-buttons slot="end">\n <ion-button *ngIf="!isSelectMode" (click)="newStory()" [strong]="true">新建</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content> --\x3e\n\n <div class="page">\n\n <div class="filter">\n \x3c!-- <button mat-icon-button class="example-icon" aria-label="Example icon-button with menu icon">\n <mat-icon>menu</mat-icon>\n </button> --\x3e\n\n \x3c!-- 知识库切换 --\x3e\n <ion-chip>\n <ion-avatar>\n <img alt="角色头像" [src]="defaultAvatar" />\n </ion-avatar>\n <ion-label>故事卡片</ion-label>\n <ion-icon name="swap-vertical-outline"></ion-icon>\n </ion-chip>\n\n <span class="example-spacer"></span>\n\n\n \x3c!-- 添加故事 --\x3e\n @if(false){\n <button mat-flat-button color="primary" (click)="newStory()" *ngIf="!isSelectMode">\n <span nz-icon nzType="plus" nzTheme="outline"></span> 上传\n </button>\n }\n\n \x3c!-- 选择状态 --\x3e\n <button mat-button color="primary" (click)="cancel()" *ngIf="isSelectMode" style="margin-left:5px;">\n <span nz-icon nzType="plus" nzTheme="outline"></span> 取消\n </button>\n <button mat-flat-button color="primary" (click)="confirmSelectedList()" *ngIf="isSelectMode">\n <span nz-icon nzType="plus" nzTheme="outline"></span> 确认选择\n </button>\n \x3c!-- <button mat-icon-button class="example-icon favorite-icon" aria-label="Example icon-button with heart icon">\n <mat-icon>favorite</mat-icon>\n </button> --\x3e\n <button id="trigger-button" mat-icon-button class="example-icon" aria-label="Example icon-button with share icon">\n <mat-icon>tune</mat-icon>\n </button>\n <ion-popover trigger="trigger-button" size="auto" side="bottom" alignment="end" style="--width: 34%;margin-left: 0%;">\n <ng-template>\n <ion-content class="ion-padding">\n <ion-item-group>\n <ion-item-divider>\n <ion-label>类型</ion-label>\n </ion-item-divider>\n <ion-item lines="none">\n <mat-chip-listbox [value]="storyType" aria-label="类型">\n <mat-chip-option (click)="changeStoryType(\'\')" value="">全部</mat-chip-option>\n <mat-chip-option (click)="changeStoryType(\'document\')" value="document">文档</mat-chip-option>\n <mat-chip-option (click)="changeStoryType(\'chat\')" value="chat">聊天</mat-chip-option>\n <mat-chip-option (click)="changeStoryType(\'diary\')" value="diary">日记</mat-chip-option>\n \x3c!-- <mat-chip-option color="accent" selected>Accent fish</mat-chip-option> --\x3e\n \x3c!-- <mat-chip-option color="warn">Warn fish</mat-chip-option> --\x3e\n </mat-chip-listbox>\n </ion-item>\n </ion-item-group>\n \n </ion-content>\n </ng-template>\n </ion-popover>\n </div>\n\n \x3c!-- 选择模式:选择数据 --\x3e\n @if(selectCount&&selectToken){\n <div class="select">\n <span>已选 {{selectCount||0}}个</span>\n <span style="margin-left:3px;">约{{selectToken||0}}tokens</span>\n </div>\n }\n \n <div class="list">\n\n\n \x3c!-- 切换筛选类型(角色故事、书籍故事、用户故事) --\x3e\n @if(person?.id || book?.id){\n <mat-button-toggle-group name="fontStyle">\n <mat-button-toggle (click)="currentTab=\'我的\';loadStory()" *ngIf="person?.id || book?.id" [checked]="currentTab==\'我的\'">\n <span nz-icon nzType="user" nzTheme="outline"></span> 我的\n </mat-button-toggle>\n <mat-button-toggle (click)="currentTab=\'主角\';loadStory()" *ngIf="person?.id" [checked]="currentTab==\'主角\'">\n <span nz-icon nzType="user" nzTheme="outline"></span> 主角\n </mat-button-toggle>\n <mat-button-toggle (click)="currentTab=\'书籍\';loadStory()" *ngIf="book?.id" [checked]="currentTab==\'书籍\'">\n <span nz-icon nzType="read" nzTheme="outline"></span> 书籍\n </mat-button-toggle>\n </mat-button-toggle-group>\n }\n \n \x3c!-- 故事卡片 --\x3e\n <ng-container *ngFor="let story of storyServ.storyList;let index=index;">\n <fm-story-card class="list-item" [story]="story?.story" [isSelectMode]="isSelectMode" \n [(checked)]="checkedMap[story?.story?.id||\'\']"\n (onCheckStory)="checkStory($event)" \n (onPreviewStory)="previewStory($event)"\n (onDestoryStory)="destroyStory($event,index)"\n ></fm-story-card>\n </ng-container>\n </div>\n \x3c!-- </ion-content> --\x3e\n</div>\n',styles:[".page{width:100%;height:100%;display:flex;flex-direction:column;background:var(--yuban-page-background)}.page .filter{height:48px;display:flex;align-items:center}.page .filter .example-spacer{flex:1 1 auto}.page .select{display:flex;justify-content:center;height:32px}.page .select span{background-color:none;color:#ccc}.page .select mat-chip{background-color:none!important}.page mat-button-toggle-group{display:flex;height:25px;align-items:center;margin-top:11px}.page mat-button-toggle-group mat-button-toggle{flex:50%}.page ion-popover{--min-width:300px}.page .list{flex:1;display:flex;flex-direction:column;overflow-y:auto;border-radius:5px;height:100%;padding:5px}.page .list button{width:100%;margin-bottom:5px}.page .list .list-item{margin-bottom:7px}\n"]}]}],ctorParameters:()=>[{type:i1$1.ActivatedRoute},{type:i3.LoadingController},{type:i3$1.MatDialog},{type:i1$1.Router},{type:StoryService},{type:ChatService},{type:i1$3.AlertController},{type:i1$3.ModalController},{type:i1$3.NavController},{type:NovaCloudService},{type:NovaUploadService}],propDecorators:{id:[{type:Input}],article:[{type:Input}],person:[{type:Input}],book:[{type:Input}],isSelectMode:[{type:Input}],onCancel:[{type:Output}],onCountChange:[{type:Output}],onTokenChange:[{type:Output}],onPreviewStory:[{type:Output}],onConfirmSelect:[{type:Output}]}});class DialogDeleteStoryDialog{constructor(e,t){this.dialogRef=e,this.data=t}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DialogDeleteStoryDialog,deps:[{token:i3$1.MatDialogRef},{token:MAT_DIALOG_DATA}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:DialogDeleteStoryDialog,isStandalone:!0,selector:"delete-story-dialog",ngImport:i0,template:'<h1 mat-dialog-title>删除故事</h1>\n<div mat-dialog-content>\n 请问您要删除该故事及其所有线索吗?\n</div>\n<div mat-dialog-actions>\n <button mat-button mat-dialog-close cdkFocusInitial>取消</button>\n <button mat-button [mat-dialog-close]="true" color="warn">删除</button>\n</div>',dependencies:[{kind:"ngmodule",type:MatDialogModule},{kind:"directive",type:i3$1.MatDialogClose,selector:"[mat-dialog-close], [matDialogClose]",inputs:["aria-label","type","mat-dialog-close","matDialogClose"],exportAs:["matDialogClose"]},{kind:"directive",type:i3$1.MatDialogTitle,selector:"[mat-dialog-title], [matDialogTitle]",inputs:["id"],exportAs:["matDialogTitle"]},{kind:"directive",type:i3$1.MatDialogActions,selector:"[mat-dialog-actions], mat-dialog-actions, [matDialogActions]",inputs:["align"]},{kind:"directive",type:i3$1.MatDialogContent,selector:"[mat-dialog-content], mat-dialog-content, [matDialogContent]"},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DialogDeleteStoryDialog,decorators:[{type:Component,args:[{selector:"delete-story-dialog",standalone:!0,imports:[MatDialogModule,MatButtonModule],template:'<h1 mat-dialog-title>删除故事</h1>\n<div mat-dialog-content>\n 请问您要删除该故事及其所有线索吗?\n</div>\n<div mat-dialog-actions>\n <button mat-button mat-dialog-close cdkFocusInitial>取消</button>\n <button mat-button [mat-dialog-close]="true" color="warn">删除</button>\n</div>'}]}],ctorParameters:()=>[{type:i3$1.MatDialogRef},{type:void 0,decorators:[{type:Inject,args:[MAT_DIALOG_DATA]}]}]});class FmStorySplitterComponent{constructor(){this.docsList=[]}ngOnInit(){this.story?.story?.id||(this.story=new AgentStory),this.loadSplitter()}async loadSplitter(){let e=this.story?.story?.get("attach");e?.id&&(this.docsList=await(this.story?.loadSlipt(e))),console.log("docsList",this.docsList)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmStorySplitterComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmStorySplitterComponent,isStandalone:!0,selector:"fm-story-splitter",inputs:{story:"story"},ngImport:i0,template:'<div class="layout">\n <ng-container *ngFor="let doc of docsList;let idx=index">\n <mat-card>\n <mat-card-header>\n <mat-card-subtitle>#{{story?.story?.id | uppercase}}{{idx+1 | number: \'3.0\'}} 行{{doc?.get("metadata")?.loc?.lines?.from}}至行{{doc?.get("metadata")?.loc?.lines?.to}}</mat-card-subtitle>\n <mat-card-title>递归字符分割</mat-card-title>\n </mat-card-header>\n <mat-card-content>\n <p [matTooltip]="doc?.get(\'pageContent\')" matTooltipPosition="left">{{doc?.get("pageContent")}}</p>\n </mat-card-content>\n <mat-card-actions>\n <button mat-button>#块大小{{500}}</button>\n <button mat-button>#块层叠{{100}}</button>\n </mat-card-actions>\n \x3c!-- <mat-card-footer>\n <mat-progress-bar mode="indeterminate"></mat-progress-bar>\n </mat-card-footer> --\x3e\n </mat-card>\n </ng-container>\n</div>',styles:[".layout{display:flex;flex-direction:column;align-items:center;overflow-y:auto;height:100%;padding:7px}.layout mat-card{margin-bottom:7px;max-width:400px}.layout mat-card p{display:-webkit-box;overflow:hidden;word-break:break-all;-webkit-line-clamp:2;-webkit-box-orient:vertical}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"pipe",type:i2.UpperCasePipe,name:"uppercase"},{kind:"pipe",type:i2.DecimalPipe,name:"number"},{kind:"ngmodule",type:MatCardModule},{kind:"component",type:i2$1.MatCard,selector:"mat-card",inputs:["appearance"],exportAs:["matCard"]},{kind:"directive",type:i2$1.MatCardActions,selector:"mat-card-actions",inputs:["align"],exportAs:["matCardActions"]},{kind:"directive",type:i2$1.MatCardContent,selector:"mat-card-content"},{kind:"component",type:i2$1.MatCardHeader,selector:"mat-card-header"},{kind:"directive",type:i2$1.MatCardSubtitle,selector:"mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]"},{kind:"directive",type:i2$1.MatCardTitle,selector:"mat-card-title, [mat-card-title], [matCardTitle]"},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"ngmodule",type:MatTooltipModule},{kind:"directive",type:i4$2.MatTooltip,selector:"[matTooltip]",inputs:["matTooltipPosition","matTooltipPositionAtOrigin","matTooltipDisabled","matTooltipShowDelay","matTooltipHideDelay","matTooltipTouchGestures","matTooltip","matTooltipClass"],exportAs:["matTooltip"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmStorySplitterComponent,decorators:[{type:Component,args:[{selector:"fm-story-splitter",standalone:!0,imports:[CommonModule,DecimalPipe,MatCardModule,MatButtonModule,MatTooltipModule],template:'<div class="layout">\n <ng-container *ngFor="let doc of docsList;let idx=index">\n <mat-card>\n <mat-card-header>\n <mat-card-subtitle>#{{story?.story?.id | uppercase}}{{idx+1 | number: \'3.0\'}} 行{{doc?.get("metadata")?.loc?.lines?.from}}至行{{doc?.get("metadata")?.loc?.lines?.to}}</mat-card-subtitle>\n <mat-card-title>递归字符分割</mat-card-title>\n </mat-card-header>\n <mat-card-content>\n <p [matTooltip]="doc?.get(\'pageContent\')" matTooltipPosition="left">{{doc?.get("pageContent")}}</p>\n </mat-card-content>\n <mat-card-actions>\n <button mat-button>#块大小{{500}}</button>\n <button mat-button>#块层叠{{100}}</button>\n </mat-card-actions>\n \x3c!-- <mat-card-footer>\n <mat-progress-bar mode="indeterminate"></mat-progress-bar>\n </mat-card-footer> --\x3e\n </mat-card>\n </ng-container>\n</div>',styles:[".layout{display:flex;flex-direction:column;align-items:center;overflow-y:auto;height:100%;padding:7px}.layout mat-card{margin-bottom:7px;max-width:400px}.layout mat-card p{display:-webkit-box;overflow:hidden;word-break:break-all;-webkit-line-clamp:2;-webkit-box-orient:vertical}\n"]}]}],ctorParameters:()=>[],propDecorators:{story:[{type:Input}]}});class FmStoryLoaderComponent{constructor(e,t,n,o,i,a){this.nupload=e,this.chatServ=t,this.navCtrl=n,this.ncloud=o,this.cdRef=i,this.storyServ=a,this.isSelectMode=!1,this.fileType="",this.uploadToNovaRequest=e=>{console.log("fileReq",e),console.log(e?.file);let t=e.postFile;return from(this.nupload.upload(t,(t=>{e.file.percent=t?.total?.percent||0,100==t?.total?.percent&&(e.file.status="done",this.uploadedFile=e.file),console.log("progress",t)}))).subscribe({next:async t=>{console.log("response",t),t?.id&&(this.attachment=await(this.story?.setAttachment(t)),this.story?.story?.set("attach",this.attachment),this.cdRef.detectChanges(),console.log(this.story)),e.onSuccess?.(t,e.file,null)},error:t=>{e.onError?.(t,e.file)}})},this.fileType=["text/csv","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/pdf","application/vnd.openxmlformats-officedocument.presentationml.presentation"].join(",")}ngOnInit(){this.initStory()}initStory(e,t){this.attachment=void 0,this.chatSession=void 0,this.fmodeChat=void 0,e&&(this.story=e),setTimeout((()=>{t?.isNew&&(this.story=this.storyServ.storyList?.[0]),this.attachment=this.story?.story?.get("attach"),this.chatSession=this.story?.story?.get("chatSession"),this.loadChatSessionToFmodeChat(this.story)}),100)}async loadChatSessionToFmodeChat(e){let t=e?.story?.get("chatSession"),n=t?.id||t?.objectId;if(console.log("chatId",n),!t?.get("role")?.id){let e=new Parse__default.Query("ChatSession");e.equalTo("objectId",n),e.include("role"),t=await e.first(n)}if(n){let e=await getRoleById(t?.get("role")?.id),o=this.navCtrl;this.fmodeChat=new FmodeChat(n,e,t,this,o,this.ncloud,this.nupload),this.chatServ.chatMap[n]=this.fmodeChat}}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmStoryLoaderComponent,deps:[{token:NovaUploadService},{token:ChatService},{token:i3.NavController},{token:NovaCloudService},{token:i0.ChangeDetectorRef},{token:StoryService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:FmStoryLoaderComponent,isStandalone:!0,selector:"fm-story-loader",inputs:{isSelectMode:"isSelectMode",story:"story"},providers:[NovaUploadService,Diagnostic],ngImport:i0,template:'<div class="layout">\n <ng-container *ngIf="!attachment && !chatSession">\n <div class="col-uploader">\n <nz-upload\n nzType="drag"\n [nzAccept]="fileType"\n [nzMultiple]="false"\n [nzCustomRequest]="uploadToNovaRequest"\n >\n <p class="ant-upload-drag-icon">\n <span nz-icon nzType="inbox"></span>\n </p>\n <p class="ant-upload-text">拖拽文件到这里 或 点击上传文件</p>\n <p class="ant-upload-hint">\n 支持 .docx, .pptx, .pdf, .csv, .txt, .md 文件\n </p>\n </nz-upload>\n </div>\n </ng-container>\n\n \x3c!-- 附件加载器:显示附件预览效果 --\x3e\n <ng-container *ngIf="story?.story?.get(\'attach\')?.id">\n <div class="col-preview">\n <fm-office-viewer [fileId]="attachment?.id"></fm-office-viewer>\n </div>\n <div class="col-document" *ngIf="!isSelectMode">\n <fm-story-splitter [story]="story"></fm-story-splitter>\n </div>\n </ng-container>\n\n \x3c!-- 会话加载器:显示对话总结及聊天记录 --\x3e\n <ng-container *ngIf="fmodeChat">\n <div class="col-preview">\n <fm-chat-message-area *ngIf="fmodeChat" [chat]="fmodeChat"></fm-chat-message-area>\n </div>\n <div class="col-document" style="min-width:360px;">\n @if(story?.story?.get("type")=="chat"){\n <comp-chat-story-json [story]="story?.story"></comp-chat-story-json>\n }\n @if(story?.story?.get("type")=="diary"){\n <comp-diary-story [story]="story?.story"></comp-diary-story>\n }\n </div>\n </ng-container>\n</div>',styles:[".layout{display:flex;height:100%}.layout .col-uploader{height:100%;width:100%;display:flex;flex-direction:column;justify-content:center;align-items:center}.layout .col-uploader nz-upload{min-width:300px;max-width:500px;width:60%}.layout .col-preview{height:100%;flex:auto;overflow-y:auto}.layout .col-document{height:100%;overflow-y:auto}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:NzUploadModule},{kind:"component",type:i7$1.NzUploadComponent,selector:"nz-upload",inputs:["nzType","nzLimit","nzSize","nzFileType","nzAccept","nzAction","nzDirectory","nzOpenFileDialogOnClick","nzBeforeUpload","nzCustomRequest","nzData","nzFilter","nzFileList","nzDisabled","nzHeaders","nzListType","nzMultiple","nzName","nzShowUploadList","nzShowButton","nzWithCredentials","nzRemove","nzPreview","nzPreviewFile","nzPreviewIsImage","nzTransformFile","nzDownload","nzIconRender","nzFileListRender"],outputs:["nzChange","nzFileListChange"],exportAs:["nzUpload"]},{kind:"ngmodule",type:NzIconModule},{kind:"directive",type:i6$1.NzIconDirective,selector:"[nz-icon]",inputs:["nzSpin","nzRotate","nzType","nzTheme","nzTwotoneColor","nzIconfont"],exportAs:["nzIcon"]},{kind:"component",type:FmOfficeViewerComponent,selector:"fm-office-viewer",inputs:["officeHost","wopiHost","fileId","permission","showHeader"]},{kind:"component",type:FmStorySplitterComponent,selector:"fm-story-splitter",inputs:["story"]},{kind:"component",type:CompDiaryStoryComponent,selector:"comp-diary-story",inputs:["story","person","showHeader","readOnly"]},{kind:"component",type:CompChatStoryJsonComponent,selector:"comp-chat-story-json",inputs:["story","person","showHeader"]},{kind:"component",type:FmChatMesssageArea,selector:"fm-chat-message-area",inputs:["chatId","chat"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmStoryLoaderComponent,decorators:[{type:Component,args:[{selector:"fm-story-loader",standalone:!0,imports:[CommonModule,NzUploadModule,NzIconModule,FmOfficeViewerComponent,FmStorySplitterComponent,CompDiaryStoryComponent,CompChatStoryJsonComponent,FmChatMesssageArea],providers:[NovaUploadService,Diagnostic],template:'<div class="layout">\n <ng-container *ngIf="!attachment && !chatSession">\n <div class="col-uploader">\n <nz-upload\n nzType="drag"\n [nzAccept]="fileType"\n [nzMultiple]="false"\n [nzCustomRequest]="uploadToNovaRequest"\n >\n <p class="ant-upload-drag-icon">\n <span nz-icon nzType="inbox"></span>\n </p>\n <p class="ant-upload-text">拖拽文件到这里 或 点击上传文件</p>\n <p class="ant-upload-hint">\n 支持 .docx, .pptx, .pdf, .csv, .txt, .md 文件\n </p>\n </nz-upload>\n </div>\n </ng-container>\n\n \x3c!-- 附件加载器:显示附件预览效果 --\x3e\n <ng-container *ngIf="story?.story?.get(\'attach\')?.id">\n <div class="col-preview">\n <fm-office-viewer [fileId]="attachment?.id"></fm-office-viewer>\n </div>\n <div class="col-document" *ngIf="!isSelectMode">\n <fm-story-splitter [story]="story"></fm-story-splitter>\n </div>\n </ng-container>\n\n \x3c!-- 会话加载器:显示对话总结及聊天记录 --\x3e\n <ng-container *ngIf="fmodeChat">\n <div class="col-preview">\n <fm-chat-message-area *ngIf="fmodeChat" [chat]="fmodeChat"></fm-chat-message-area>\n </div>\n <div class="col-document" style="min-width:360px;">\n @if(story?.story?.get("type")=="chat"){\n <comp-chat-story-json [story]="story?.story"></comp-chat-story-json>\n }\n @if(story?.story?.get("type")=="diary"){\n <comp-diary-story [story]="story?.story"></comp-diary-story>\n }\n </div>\n </ng-container>\n</div>',styles:[".layout{display:flex;height:100%}.layout .col-uploader{height:100%;width:100%;display:flex;flex-direction:column;justify-content:center;align-items:center}.layout .col-uploader nz-upload{min-width:300px;max-width:500px;width:60%}.layout .col-preview{height:100%;flex:auto;overflow-y:auto}.layout .col-document{height:100%;overflow-y:auto}\n"]}]}],ctorParameters:()=>[{type:NovaUploadService},{type:ChatService},{type:i3.NavController},{type:NovaCloudService},{type:i0.ChangeDetectorRef},{type:StoryService}],propDecorators:{isSelectMode:[{type:Input}],story:[{type:Input}]}});class PageMapStartComponent{constructor(){this.placeList=[{name:"江财蛟桥校区",location:[115.855125,28.744335]},{name:"江财枫林校区",location:[115.835639,28.734119]},{name:"江财麦庐校区",location:[115.816717,28.728899]}],this.amap={securityJsCode:"32aa3f4ab0fa0061de03edd4eafdd50a",key:"473b52010df7d3a32db0a2f5db245c8e"},this.initaMapConfig()}async initaMapConfig(){let e=localStorage.getItem("company");if(e){let t=new Parse__default.Query("Company");t.select("config");let n=await t.get(e);n?.get("config")?.amap&&(this.amap=n.get("config").amap)}window._AMapSecurityConfig={securityJsCode:this.amap.securityJsCode}}ngAfterViewInit(){this.initMap()}async initMap(){await this.createMap(),this.goAndMarkPlace(this.placeList[1])}async createMap(){this.AMap=await AMapLoader.load({key:this.amap.key,version:"2.0"}),this.map=new this.AMap.Map("container")}async addMarks(){let e=new this.AMap.Marker({position:[115.835639,28.734119]});this.map.add(e)}goAndMarkPlace(e){this.map.setCenter(e.location),this.map.setZoom(18),console.log(this.placeList),e.marker||(e.marker=new this.AMap.Marker({position:e.location}),this.map.add(e.marker))}clearMark(e){e?.marker?.remove()}planRoute(e,t){let n;this.map.plugin(["AMap.Transfer"],(()=>{let o={map:this.map,city:"南昌市",panel:"panel",policy:this.AMap.TransferPolicy.LEAST_TIME};console.log(this.AMap),console.log(this.AMap.TransferPolicy),n=new this.AMap.Transfer(o),n.search(new this.AMap.LngLat(e.location[0],e.location[1]),new this.AMap.LngLat(t.location[0],t.location[1]),((e,t)=>{"complete"===e?(console.log("绘制公交路线完成:"),console.log(t)):console.error("公交路线数据查询失败"+t)}))}))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PageMapStartComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:PageMapStartComponent,selector:"app-page-map.start",ngImport:i0,template:'\x3c!-- 全屏地图 --\x3e\n<div id="container"></div>\n\n\x3c!-- 右侧地点 --\x3e\n<div class="place-list">\n <ng-container *ngFor="let place of placeList">\n <div class="place-item" (click)="goAndMarkPlace(place)">\n {{place.name}}\n <button (click)="clearMark(place)">清除标记</button>\n </div>\n </ng-container>\n\n <button (click)="planRoute(placeList[0],placeList[1])">从蛟桥到枫林</button>\n \n</div>',styles:["#container{width:100%;height:100%;position:fixed}.place-list{display:flex;flex-direction:column;position:fixed;justify-content:center;align-items:center;height:80%;width:200px}.place-list .place-item{background-color:#ffffff4d;height:100px;width:90%}\n"],dependencies:[{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PageMapStartComponent,decorators:[{type:Component,args:[{selector:"app-page-map.start",template:'\x3c!-- 全屏地图 --\x3e\n<div id="container"></div>\n\n\x3c!-- 右侧地点 --\x3e\n<div class="place-list">\n <ng-container *ngFor="let place of placeList">\n <div class="place-item" (click)="goAndMarkPlace(place)">\n {{place.name}}\n <button (click)="clearMark(place)">清除标记</button>\n </div>\n </ng-container>\n\n <button (click)="planRoute(placeList[0],placeList[1])">从蛟桥到枫林</button>\n \n</div>',styles:["#container{width:100%;height:100%;position:fixed}.place-list{display:flex;flex-direction:column;position:fixed;justify-content:center;align-items:center;height:80%;width:200px}.place-list .place-item{background-color:#ffffff4d;height:100px;width:90%}\n"]}]}],ctorParameters:()=>[]});class CompPoiPickerComponent{get name(){return this._name}set name(e){this._name=e,this.nameChange.emit(e)}get address(){return this._address}set address(e){this._address=e,this.addressChange.emit(e)}get location(){return this._location}set location(e){this._location=e,this.locationChange.emit(e)}constructor(){this.nameChange=new EventEmitter,this.addressChange=new EventEmitter,this.locationChange=new EventEmitter,this.amap={securityJsCode:"32aa3f4ab0fa0061de03edd4eafdd50a",key:"473b52010df7d3a32db0a2f5db245c8e"},this.isModalOpen=!1,this.initaMapConfig()}async initaMapConfig(){let e=localStorage.getItem("company");if(e){let t=new Parse__default.Query("Company");t.select("config");let n=await t.get(e);n?.get("config")?.amap&&(this.amap=n.get("config").amap)}window._AMapSecurityConfig={securityJsCode:this.amap.securityJsCode}}cancel(){this.isModalOpen=!1,this.modal.dismiss(null,"cancel")}confirm(){this.isModalOpen=!1,this.modal.dismiss(this.address,"confirm")}onWillDismiss(e){"confirm"===e.detail.role&&console.log("确认")}openModal(){this.isModalOpen=!0,setTimeout((()=>{this.initMap()}),800)}ngAfterViewInit(){}initMap(){this.createMap()}async createMap(){this.AMap=await AMapLoader.load({key:this.amap.key,version:"2.0"});let e=this.container.nativeElement;this.map=new this.AMap.Map(e),this.goCurrentCenter()}goCurrentCenter(){this.AMap.plugin(["AMap.Geolocation"],(()=>{let e=new this.AMap.Geolocation({enableHighAccuracy:!0,timeout:1e4,maximumAge:0,convert:!0,showButton:!0,buttonPosition:"RB",buttonOffset:new this.AMap.Pixel(10,10),showMarker:!1,showCircle:!1,panToLocation:!0,zoomToAccuracy:!1});this.map.addControl(e),e.getCurrentPosition((function(e,t){"complete"===e?(console.log("当前位置经度:"+t.position.getLng()),console.log("当前位置纬度:"+t.position.getLat())):console.log("定位失败:"+t.message)}))}))}searchByAddress(){let e=this.panel.nativeElement;this.AMap.plugin(["AMap.PlaceSearch"],(()=>{let t=new this.AMap.PlaceSearch({pageSize:3,pageIndex:1,map:this.map,panel:e,autoFitView:!0});t.on("selectChanged",(e=>{this.name=e.selected.data.name,this.address=e.selected.data.address,this.location=new Parse__default.GeoPoint({latitude:e.selected.data.location.lat,longitude:e.selected.data.location.lng}),this.createCenterMarker()})),t.search(this.address)}))}createCenterMarker(){this.centerMarker||(this.centerMarker=new this.AMap.Marker({position:this.map.getCenter(),offset:new this.AMap.Pixel(-15,-15)}),this.map.add(this.centerMarker),this.map.on("dragging",(()=>{this.centerMarker.setPosition(this.map.getCenter())})),this.map.on("dragend",(()=>{let e=this.centerMarker.getPosition();this.location=new Parse__default.GeoPoint({latitude:e.lat,longitude:e.lng})})))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPoiPickerComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompPoiPickerComponent,selector:"fm-map-poi-picker",inputs:{_name:["name","_name"],_address:["address","_address"],_location:["location","_location"]},outputs:{nameChange:"nameChange",addressChange:"addressChange",locationChange:"locationChange"},viewQueries:[{propertyName:"container",first:!0,predicate:["container"],descendants:!0},{propertyName:"panel",first:!0,predicate:["panel"],descendants:!0},{propertyName:"modal",first:!0,predicate:IonModal$1,descendants:!0}],ngImport:i0,template:'\x3c!-- 未选点 --\x3e\n<ion-button (click)="openModal()" expand="block">开始选点</ion-button>\n\n\x3c!-- 已选点 --\x3e\n\n<ion-modal [isOpen]="isModalOpen" (willDismiss)="onWillDismiss($event)">\n<ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="cancel()">Cancel</ion-button>\n </ion-buttons>\n <ion-title>地图选点<ng-container *ngIf="location">({{location.latitude}},{{location.longitude}})</ng-container></ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="confirm()" [strong]="true">Confirm</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding" style="height:100%">\n \x3c!-- 详细地址 --\x3e\n <ion-item>\n <ion-input\n label="请输入详细地址"\n labelPlacement="stacked"\n type="text"\n placeholder="精确到门牌号"\n [(ngModel)]="address"\n ></ion-input>\n <ion-button slot="end" (click)="searchByAddress()">搜索</ion-button>\n </ion-item>\n \n \x3c!-- 地图选点 --\x3e\n <div #container class="container"></div>\n <div #panel class="panel"></div>\n\n </ion-content>\n</ng-template>\n</ion-modal>\n\n',styles:[".container{width:100%;height:100%}.panel{position:absolute;background-color:#fff;max-height:50%;overflow-y:auto;top:12%;right:10px;width:45%}\n"],dependencies:[{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"component",type:i3.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:i3.IonButtons,selector:"ion-buttons",inputs:["collapse"]},{kind:"component",type:i3.IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:i3.IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:i3.IonInput,selector:"ion-input",inputs:["autocapitalize","autocomplete","autocorrect","autofocus","clearInput","clearInputIcon","clearOnEdit","color","counter","counterFormatter","debounce","disabled","enterkeyhint","errorText","fill","helperText","inputmode","label","labelPlacement","max","maxlength","min","minlength","mode","multiple","name","pattern","placeholder","readonly","required","shape","spellcheck","step","type","value"]},{kind:"component",type:i3.IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"component",type:i3.IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"component",type:i3.IonModal,selector:"ion-modal"},{kind:"directive",type:i3.TextValueAccessor,selector:"ion-input:not([type=number]),ion-textarea,ion-searchbar"}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPoiPickerComponent,decorators:[{type:Component,args:[{selector:"fm-map-poi-picker",template:'\x3c!-- 未选点 --\x3e\n<ion-button (click)="openModal()" expand="block">开始选点</ion-button>\n\n\x3c!-- 已选点 --\x3e\n\n<ion-modal [isOpen]="isModalOpen" (willDismiss)="onWillDismiss($event)">\n<ng-template>\n <ion-header>\n <ion-toolbar>\n <ion-buttons slot="start">\n <ion-button (click)="cancel()">Cancel</ion-button>\n </ion-buttons>\n <ion-title>地图选点<ng-container *ngIf="location">({{location.latitude}},{{location.longitude}})</ng-container></ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="confirm()" [strong]="true">Confirm</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n <ion-content class="ion-padding" style="height:100%">\n \x3c!-- 详细地址 --\x3e\n <ion-item>\n <ion-input\n label="请输入详细地址"\n labelPlacement="stacked"\n type="text"\n placeholder="精确到门牌号"\n [(ngModel)]="address"\n ></ion-input>\n <ion-button slot="end" (click)="searchByAddress()">搜索</ion-button>\n </ion-item>\n \n \x3c!-- 地图选点 --\x3e\n <div #container class="container"></div>\n <div #panel class="panel"></div>\n\n </ion-content>\n</ng-template>\n</ion-modal>\n\n',styles:[".container{width:100%;height:100%}.panel{position:absolute;background-color:#fff;max-height:50%;overflow-y:auto;top:12%;right:10px;width:45%}\n"]}]}],ctorParameters:()=>[],propDecorators:{container:[{type:ViewChild,args:["container"]}],panel:[{type:ViewChild,args:["panel"]}],_name:[{type:Input,args:["name"]}],nameChange:[{type:Output}],_address:[{type:Input,args:["address"]}],addressChange:[{type:Output}],_location:[{type:Input,args:["location"]}],locationChange:[{type:Output}],modal:[{type:ViewChild,args:[IonModal$1]}]}});class CompPoiPickerModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPoiPickerModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:CompPoiPickerModule,declarations:[CompPoiPickerComponent],imports:[CommonModule,FormsModule,ReactiveFormsModule,i3.IonicModule],exports:[CompPoiPickerComponent]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPoiPickerModule,imports:[CommonModule,FormsModule,ReactiveFormsModule,IonicModule.forRoot({mode:"ios"})]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompPoiPickerModule,decorators:[{type:NgModule,args:[{declarations:[CompPoiPickerComponent],imports:[CommonModule,FormsModule,ReactiveFormsModule,IonicModule.forRoot({mode:"ios"})],exports:[CompPoiPickerComponent]}]}]});class PagePlanRouteComponent{constructor(){this.placeList=[],this.currentTab="place",this.amap={securityJsCode:"32aa3f4ab0fa0061de03edd4eafdd50a",key:"473b52010df7d3a32db0a2f5db245c8e"},this.initaMapConfig(),this.addNewPlace(),this.currentTab="plan"}async initaMapConfig(){let e=localStorage.getItem("company");if(e){let t=new Parse__default.Query("Company");t.select("config");let n=await t.get(e);n?.get("config")?.amap&&(this.amap=n.get("config").amap)}window._AMapSecurityConfig={securityJsCode:this.amap.securityJsCode}}addNewPlace(){this.placeList?.length>=1?this.placeList.push({name:"秋水广场",address:"南昌市秋水广场",location:new Parse__default.GeoPoint({latitude:28.682634,longitude:115.86273})}):this.placeList.push({name:"八一广场",address:"南昌市八一广场",location:new Parse__default.GeoPoint({latitude:28.673856,longitude:115.904477})})}ngAfterViewInit(){}async initMap(){await this.createMap(),this.goAndMarkPlace(this.placeList[0])}async createMap(){this.AMap=await AMapLoader.load({key:this.amap.key,version:"2.0"}),this.map=new this.AMap.Map("container-plan")}goAndMarkPlace(e){this.map.setCenter([e.location.latitude,e.location.longitude]),this.map.setZoom(18),e.marker||(e.marker=new this.AMap.Marker({position:[e.location.latitude,e.location.longitude]}),this.map.add(e.marker))}clearMark(e){e?.marker?.remove()}planRoute(e,t){let n;this.map.plugin(["AMap.Transfer"],(()=>{let o={map:this.map,city:"南昌市",panel:"panel",policy:this.AMap.TransferPolicy.LEAST_TIME};n=new this.AMap.Transfer(o);let i=new this.AMap.LngLat(e.location.longitude,e.location.latitude),a=new this.AMap.LngLat(t.location.longitude,t.location.latitude);n.search(i,a,((e,t)=>{"complete"===e?(console.log("绘制公交路线完成:"),console.log(t)):console.error("公交路线数据查询失败"+t)}))}))}async createPlan(){await this.initMap(),this.planRoute(this.placeList[0],this.placeList[1])}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PagePlanRouteComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:PagePlanRouteComponent,selector:"app-page-plan-route",ngImport:i0,template:'<ion-segment value="place">\n <ion-segment-button (click)="currentTab=\'place\'" value="place">\n <ion-label>景点选择</ion-label>\n </ion-segment-button>\n <ion-segment-button (click)="currentTab=\'plan\'" value="plan">\n <ion-label>路线规划</ion-label>\n </ion-segment-button>\n </ion-segment>\n \n\n<ng-container *ngIf="currentTab==\'place\'">\n <h1>选择旅游计划景点</h1>\n\n <ng-container *ngFor="let place of placeList">\n <ion-card>\n <h2>{{place?.name}}</h2>\n <span *ngIf="place.address">详细地址:{{place.address}}</span>\n <span *ngIf="place.location">地图坐标:{{place.location.latitude}},{{place.location.longitude}}</span>\n <fm-map-poi-picker [(name)]="place.name" [(address)]="place.address" [(location)]="place.location"></fm-map-poi-picker>\n </ion-card>\n </ng-container>\n <ion-button (click)="addNewPlace()" expand="block">添加新景点</ion-button>\n</ng-container>\n\n<ng-container *ngIf="currentTab==\'plan\'">\n <ion-button (click)="createPlan()" expand="block">创建规划路线</ion-button>\n\n <div id="container-plan"></div>\n <div id="panel"></div>\n</ng-container>\n\n',styles:["#container-plan{width:100%;height:40%}#panel{width:100%;height:50%}\n"],dependencies:[{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:i3.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:i3.IonCard,selector:"ion-card",inputs:["button","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:i3.IonSegment,selector:"ion-segment",inputs:["color","disabled","mode","scrollable","selectOnFocus","swipeGesture","value"]},{kind:"component",type:i3.IonSegmentButton,selector:"ion-segment-button",inputs:["contentId","disabled","layout","mode","type","value"]},{kind:"directive",type:i3.SelectValueAccessor,selector:"ion-select, ion-radio-group, ion-segment, ion-datetime"},{kind:"component",type:CompPoiPickerComponent,selector:"fm-map-poi-picker",inputs:["name","address","location"],outputs:["nameChange","addressChange","locationChange"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PagePlanRouteComponent,decorators:[{type:Component,args:[{selector:"app-page-plan-route",template:'<ion-segment value="place">\n <ion-segment-button (click)="currentTab=\'place\'" value="place">\n <ion-label>景点选择</ion-label>\n </ion-segment-button>\n <ion-segment-button (click)="currentTab=\'plan\'" value="plan">\n <ion-label>路线规划</ion-label>\n </ion-segment-button>\n </ion-segment>\n \n\n<ng-container *ngIf="currentTab==\'place\'">\n <h1>选择旅游计划景点</h1>\n\n <ng-container *ngFor="let place of placeList">\n <ion-card>\n <h2>{{place?.name}}</h2>\n <span *ngIf="place.address">详细地址:{{place.address}}</span>\n <span *ngIf="place.location">地图坐标:{{place.location.latitude}},{{place.location.longitude}}</span>\n <fm-map-poi-picker [(name)]="place.name" [(address)]="place.address" [(location)]="place.location"></fm-map-poi-picker>\n </ion-card>\n </ng-container>\n <ion-button (click)="addNewPlace()" expand="block">添加新景点</ion-button>\n</ng-container>\n\n<ng-container *ngIf="currentTab==\'plan\'">\n <ion-button (click)="createPlan()" expand="block">创建规划路线</ion-button>\n\n <div id="container-plan"></div>\n <div id="panel"></div>\n</ng-container>\n\n',styles:["#container-plan{width:100%;height:40%}#panel{width:100%;height:50%}\n"]}]}],ctorParameters:()=>[]});class PageLocaScatterComponent{constructor(){this.amap={securityJsCode:"32aa3f4ab0fa0061de03edd4eafdd50a",key:"473b52010df7d3a32db0a2f5db245c8e"},this.initaMapConfig()}async initaMapConfig(){let e=localStorage.getItem("company");if(e){let t=new Parse__default.Query("Company");t.select("config");let n=await t.get(e);n?.get("config")?.amap&&(this.amap=n.get("config").amap)}window._AMapSecurityConfig={securityJsCode:this.amap.securityJsCode}}ngAfterViewInit(){this.initMap()}async initMap(){await this.createMap(),await this.createLoca()}async createLoca(){let e=window.loca=new Loca.Container({map:this.map}),t=new Loca.GeoJSONSource({url:"https://a.amap.com/Loca/static/loca-v2/demos/mock_data/sz_road.json"}),n=new Loca.ScatterLayer({zIndex:111,opacity:1,visible:!0,zooms:[2,22]});n.setSource(t),n.setStyle({color:"rgba(43,156,75,1)",unit:"meter",size:[150,150],borderWidth:0}),e.add(n);let o=new Loca.GeoJSONSource({url:"https://a.amap.com/Loca/static/loca-v2/demos/mock_data/sz_road_F.json"}),i=new Loca.ScatterLayer({loca:e,zIndex:113,opacity:1,visible:!0,zooms:[2,22]});i.setSource(o),i.setStyle({unit:"meter",size:[2600,2600],borderWidth:0,texture:"https://a.amap.com/Loca/static/loca-v2/demos/images/breath_red.png",duration:500,animate:!0});let a=new Loca.GeoJSONSource({url:"https://a.amap.com/Loca/static/loca-v2/demos/mock_data/sz_road_E.json"}),r=new Loca.ScatterLayer({loca:e,zIndex:112,opacity:1,visible:!0,zooms:[2,22]});r.setSource(a),r.setStyle({unit:"meter",size:[1e3,1e3],borderWidth:0,texture:"https://a.amap.com/Loca/static/loca-v2/demos/images/breath_yellow.png",duration:1e3,animate:!0}),e.animate.start();let s=new Loca.Dat;s.addLayer(n," 贴地"),s.addLayer(i,"红色"),s.addLayer(r,"黄色")}async createMap(){this.AMap=await AMapLoader.load({key:this.amap.key,version:"2.0",Loca:{version:"2.0.0"}}),this.map=new this.AMap.Map("container",{zoom:11.7,center:[113.97199630737305,22.5807295363949],pitch:40,showLabel:!1,mapStyle:"amap://styles/dark",viewMode:"3D"})}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PageLocaScatterComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:PageLocaScatterComponent,selector:"app-page-loca-scatter",ngImport:i0,template:'<div id="container"></div>',styles:["#container{width:100%;height:100%;position:fixed}\n"]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PageLocaScatterComponent,decorators:[{type:Component,args:[{selector:"app-page-loca-scatter",template:'<div id="container"></div>',styles:["#container{width:100%;height:100%;position:fixed}\n"]}]}],ctorParameters:()=>[]});const routes=[{path:"start",component:PageMapStartComponent},{path:"plan/route",component:PagePlanRouteComponent},{path:"loca/scatter",component:PageLocaScatterComponent}];class FmodeMapModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeMapModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:FmodeMapModule,declarations:[PageMapStartComponent,PagePlanRouteComponent,PageLocaScatterComponent],imports:[CommonModule,i1$1.RouterModule,i3.IonicModule,CompPoiPickerModule],exports:[CompPoiPickerModule]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeMapModule,imports:[CommonModule,RouterModule.forChild(routes),IonicModule.forRoot({mode:"ios"}),CompPoiPickerModule,CompPoiPickerModule]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeMapModule,decorators:[{type:NgModule,args:[{declarations:[PageMapStartComponent,PagePlanRouteComponent,PageLocaScatterComponent],imports:[CommonModule,RouterModule.forChild(routes),IonicModule.forRoot({mode:"ios"}),CompPoiPickerModule],exports:[CompPoiPickerModule]}]}]});class HwobsService{constructor(){this.Attachment=Parse__default.Object.extend("Attachment"),this.host="https://web3-test.obs.cn-south-1.myhuaweicloud.com/",this.bucketName="web3-test",this.obsClient=new ObsClient({access_key_id:"6UIET20WHUI5TLXWOVNA",secret_access_key:"YaoY8Kj3TeGZHEcBzplTMZiPGNL13Y3frEavC1kF",server:"https://obs.cn-south-1.myhuaweicloud.com"})}listDir(e){return new Promise(((t,n)=>{this.obsClient.listObjects({Bucket:this.bucketName,Prefix:e,Delimiter:"/"},((e,o)=>{if(e)console.error("Error--\x3e"+e),n(e);else{if(console.log("Status--\x3e"+o.CommonMsg.Status),console.log(o),o.CommonMsg.Status<300&&o.InterfaceResult)for(var i in o.InterfaceResult.Contents)console.log("Contents["+i+"]:"),console.log("Key--\x3e"+o.InterfaceResult.Contents[i].Key),console.log("Owner[ID]--\x3e"+o.InterfaceResult.Contents[i].Owner.ID);let e=o.InterfaceResult.CommonPrefixes,n=o.InterfaceResult.Contents;t({dirs:e,files:n})}}))}))}async uploadFile(e,t){let n=await this.checkFileExists(e);return n?.id?n:new Promise(((n,o)=>{this.obsClient.putObject({Bucket:this.bucketName,Key:t,SourceFile:e},(async(i,a)=>{if(i)console.error("Error--\x3e"+i),o(i);else{console.log("Status--\x3e"+a.CommonMsg.Status);let o=await this.saveAttachment(e,t);n(o)}}))}))}async checkFileExists(e){let t,n=await this.getFileHash(e),o=new Parse__default.Query("Attachment");o.equalTo("hash",n),o.equalTo("size",e.size);let i=await o.first();return i?.id||(i=new this.Attachment),t=i,t}async saveAttachment(e,t){let n=await this.getFileHash(e),o=await this.checkFileExists(e);return o.set("name",e.name),o.set("size",e.size),o.set("mime",e.type),o.set("url",this.host+t),o.set("hash",n),o=await o.save(),o}async getFileHash(e){return new Promise(((t,n)=>{const o=new FileReader;o.onload=async e=>{const n=e.target.result,o=await crypto.subtle.digest("SHA-256",n),i=Array.from(new Uint8Array(o)).map((e=>e.toString(16).padStart(2,"0"))).join("");t(i)},o.onerror=e=>{n(e.target.error)},o.readAsArrayBuffer(e)}))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:HwobsService,deps:[],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:HwobsService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:HwobsService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});class HwobsManagerComponent{openFile(e){console.log("Opening file:",e)}openDir(e,t="pre"){if(e)this.prefix=e.Prefix,this.listDir(e.Prefix);else if("pre"==t){let e=this.prefix.split("/");if(e.length>1){let t=e.splice(0,e.length-1).join("/");console.log(t),this.prefix=t,this.listDir(t)}}}showName(e){return e.replaceAll(this.prefix,"")}constructor(e){this.hwobs=e,this.dirs=[],this.files=[],this.prefix="storage/",this.listDir(this.prefix)}async listDir(e){let{dirs:t,files:n}=await this.hwobs.listDir(e);this.dirs=t,this.files=n}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:HwobsManagerComponent,deps:[{token:HwobsService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:HwobsManagerComponent,isStandalone:!0,selector:"fm-storage-hwobs-manager",ngImport:i0,template:'<ion-header>\n <ion-toolbar>\n <ion-title>\n File Manager\n </ion-title>\n </ion-toolbar>\n </ion-header>\n \n <ion-content>\n <ion-list>\n <ion-item (click)="openDir(null,\'pre\')">\n <ion-icon [name]="\'folder\'" slot="start"></ion-icon>\n <ion-label>../</ion-label>\n </ion-item>\n <ion-item *ngFor="let item of dirs" (click)="openDir(item)">\n <ion-icon [name]="\'folder\'" slot="start"></ion-icon>\n <ion-label>{{ showName(item.Prefix) }}</ion-label>\n </ion-item>\n <ion-item *ngFor="let item of files" (click)="openFile(item)">\n <ion-icon [name]="\'document\'" slot="start"></ion-icon>\n <ion-label>{{ showName(item.Key) }}</ion-label>\n </ion-item>\n </ion-list>\n </ion-content>',styles:["ion-list ion-item ion-icon{font-size:24px;margin-right:8px}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"ngmodule",type:IonicModule},{kind:"component",type:i3.IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:i3.IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:i3.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:i3.IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:i3.IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:i3.IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"component",type:i3.IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:HwobsManagerComponent,decorators:[{type:Component,args:[{standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,IonicModule],selector:"fm-storage-hwobs-manager",template:'<ion-header>\n <ion-toolbar>\n <ion-title>\n File Manager\n </ion-title>\n </ion-toolbar>\n </ion-header>\n \n <ion-content>\n <ion-list>\n <ion-item (click)="openDir(null,\'pre\')">\n <ion-icon [name]="\'folder\'" slot="start"></ion-icon>\n <ion-label>../</ion-label>\n </ion-item>\n <ion-item *ngFor="let item of dirs" (click)="openDir(item)">\n <ion-icon [name]="\'folder\'" slot="start"></ion-icon>\n <ion-label>{{ showName(item.Prefix) }}</ion-label>\n </ion-item>\n <ion-item *ngFor="let item of files" (click)="openFile(item)">\n <ion-icon [name]="\'document\'" slot="start"></ion-icon>\n <ion-label>{{ showName(item.Key) }}</ion-label>\n </ion-item>\n </ion-list>\n </ion-content>',styles:["ion-list ion-item ion-icon{font-size:24px;margin-right:8px}\n"]}]}],ctorParameters:()=>[{type:HwobsService}]});class FmodeStorgeModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeStorgeModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:FmodeStorgeModule,imports:[CommonModule,i3.IonicModule,HwobsManagerComponent],exports:[HwobsManagerComponent]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeStorgeModule,providers:[Diagnostic,NovaUploadService],imports:[CommonModule,IonicModule.forRoot({mode:"ios"}),HwobsManagerComponent]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmodeStorgeModule,decorators:[{type:NgModule,args:[{declarations:[],imports:[CommonModule,IonicModule.forRoot({mode:"ios"}),HwobsManagerComponent],exports:[HwobsManagerComponent],providers:[Diagnostic,NovaUploadService]}]}]});class WechatJssdkService{constructor(e,t){this.http=e,this.authServ=t,this.isInit=!1,this.isWechat=!1,this.wechatAccountId=localStorage.getItem("WECHAT_APP_ID")||"wxb4193c93ae9aa696";let n=-1!==navigator.userAgent.toLowerCase().indexOf("micromessenger");this.isWechat=n,this.company=this.authServ.company||localStorage.getItem("company")}async setCurrentPageShareInfo(e={title:"飞码AI",desc:"解放创意引领未来|国际前沿的AIGC平台",link:location.href,type:"link",imgUrl:"https://file-cloud.fmode.cn/E4KpGvTEto/20230822/3mkf41033623275.png",success:()=>{console.log("分享成功")},error:()=>{console.log("分享失败")},cancel:()=>{console.log("取消分享")}}){const t=await this.getWXSignPackageInWechat();wx.config({debug:!1,appId:t.appid,timestamp:t.timestamp,nonceStr:t.nonceStr,signature:t.signature,jsApiList:["chooseWXPay","onMenuShareTimeline","onMenuShareAppMessage","onMenuShareQQ","onMenuShareQZone","updateAppMessageShareData","updateTimelineShareData"]}),"link"==e?.type&&(e.link=this.getInviteUrl(e.link)),wx.ready((()=>{wx.updateAppMessageShareData(e),wx.updateTimelineShareData(e)})),wx.error((()=>{}))}getInviteUrl(e){let t=new URL(e),n=Parse__default.User?.current()?.id;return n&&t.searchParams.set("invite",n),t.href}getWXSignPackageInWechat(){let e={company:this.company,href:encodeURIComponent(location.href)};return new Promise((t=>{this.http.post("https://server.fmode.cn/api/wechat/getconfig",e).subscribe((e=>{let n=e.data;t(n)}))}))}async initUserOpenid(){await this.init();let e=this.getQueryStringByName("code"),t=localStorage.getItem("openid");if(!t){if(!Parse__default.User.current())return;if(t=Parse__default?.User?.current()?.get("wechat")?.[this.wechatAccountId]?.openid,this.isWechat&&!t){let t=window.location.pathname;e?await this.getwechat(e,t):this.authWechat(t)}else this.openid=t}}authWechat(e="/account/billing"){if(!localStorage.getItem("openid")){let t="https://ai.fmode.cn"+e;return t=encodeURIComponent(t),void(window.location.href="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+this.wechatAccountId+"&redirect_uri="+t+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect")}}getQueryStringByName(e){let t=location.search.match(new RegExp("[?&]"+e+"=([^&]+)","i"));return null==t||t.length<1?"":t[1]}async getwechat(e,t="/account/billing"){return new Promise((async(n,o)=>{this.http.post("https://server.fmode.cn/api/wechat/get_wx",{company:this.company,code:e}).subscribe((async e=>{if(console.log(e),e&&200==e.code&&e.data.openid){let t=e.data.openid;localStorage.setItem("openid",t),localStorage.removeItem("code");let o={};o[this.wechatAccountId]={openid:t},Parse__default.User.current().set("wechat",o),await Parse__default.User.current().save(),n(!0)}}),(async e=>{console.log("Error updating items",e),this.authWechat(t),o(!1)}))}))}init(){return new Promise((e=>{this.isWechat||e(!1),this.isInit&&e(!0),wx&&e(!0),this.loadScript("https://res.wx.qq.com/open/js/jweixin-1.6.0.js",(()=>{this.isInit=!0,this.wx=wx,e(!0)}),(()=>{e(!1)}))}))}loadScript(e,t,n){var o=document.createElement("script");o.src=e,o.onload=()=>{t&&t()},o.onerror=()=>{n&&n()},document.body.appendChild(o)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:WechatJssdkService,deps:[{token:i1.HttpClient},{token:AuthService}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:WechatJssdkService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:WechatJssdkService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1.HttpClient},{type:AuthService}]}),addIcons({chevronBackOutline:chevronBackOutline,folderOutline:folderOutline,cloudDoneOutline:cloudDoneOutline,createOutline:createOutline});class ArticleEditorTopbarComponent{goBack(){this.navCtrl.back()}navEvent(e){this.onNavEvent.emit(e)}onPublicChange(e){this.article?.set("isPublic",e?.checked),this.article?.save()}presentPopover(e){this.popover.event=e,this.isOpen=!0}constructor(e){this.navCtrl=e,this.contentChanged=!1,this.isSaving=!1,this.onNavEvent=new EventEmitter,this.showCard=!1,this.isOpen=!1,this.showPopover=!1}ngOnInit(){}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ArticleEditorTopbarComponent,deps:[{token:i3.NavController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ArticleEditorTopbarComponent,isStandalone:!0,selector:"fm-article-editor-topbar",inputs:{article:"article",contentChanged:"contentChanged",isSaving:"isSaving"},outputs:{onNavEvent:"onNavEvent"},viewQueries:[{propertyName:"popover",first:!0,predicate:["popover"],descendants:!0}],ngImport:i0,template:'<div class="nav">\n\n<div class="nav-left">\n <div (click)="goBack()">\n <ion-icon class="icon" name="chevron-back-outline"></ion-icon>\n <span>返回上级</span>\n </div>\n <div *ngIf="article?.get(\'chapter\')?.get(\'book\')?.id" (click)="navEvent(\'backmenu\')" style="width:100px;">\n <ion-icon class="icon" name="folder-outline"></ion-icon>\n <span *ngIf="!article?.get(\'chapter\')?.get(\'book\')?.id">返回首页</span>\n <span *ngIf="article?.get(\'chapter\')?.get(\'book\')?.id">打开目录</span>\n </div>\n <div (click)="navEvent(\'save\')">\n <ion-icon *ngIf="!isSaving" class="icon" name="cloud-done-outline"></ion-icon>\n <span *ngIf="isSaving" nz-icon [nzType]="\'sync\'" [nzSpin]="true"></span>\n <span [style.color]="contentChanged?\'red\':\'black\'">保存文章</span> <ion-badge *ngIf="contentChanged">新内容</ion-badge>\n </div>\n</div>\n\n<div class="nav-middle">\n <mat-chip-listbox aria-label="Dog selection">\n <mat-chip (click)="navEvent(\'options\')" [disabled]="!article?.get(\'writingOptions\')">\n \x3c!-- <img matChipAvatar src="https://material.angular.io/assets/img/examples/shiba1.jpg" alt="Photo of a Shiba Inu"/> --\x3e\n 设定\n </mat-chip>\n <mat-chip (click)="navEvent(\'outline\')" [disabled]="!article?.get(\'outlineJson\')">\n \x3c!-- <img matChipAvatar src="https://material.angular.io/assets/img/examples/shiba1.jpg" alt="Photo of a Shiba Inu"/> --\x3e\n 大纲\n </mat-chip>\n <mat-chip (click)="navEvent(\'preview\')" [disabled]="!article?.get(\'contentArray\')?.length">\n \x3c!-- <img matChipAvatar src="https://material.angular.io/assets/img/examples/shiba1.jpg" alt="Photo of a Shiba Inu"/> --\x3e\n 预览\n </mat-chip>\n </mat-chip-listbox>\n \x3c!-- <button>开始</button>\n <button>效率</button>\n <button>审阅</button> --\x3e\n\n</div>\n\n<div class="nav-right">\n\n <mat-slide-toggle [checked]="article?.get(\'isPublic\')" (change)="onPublicChange($event)">公开文章</mat-slide-toggle>\n \x3c!-- <button>登录/注册</button> --\x3e\n \x3c!-- <nz-avatar nzText="USER"></nz-avatar> --\x3e\n \x3c!-- <button class="bubble-card-trigger" (click)="showCard = !showCard">协作</button> --\x3e\n\n <div class="bubble-card" *ngIf="showCard">\n\n <div class="bubble-card-content">\n <div class="bubble-card-tab">\n <div class="invite">邀请协作</div>\n </div>\n <nz-divider></nz-divider>\n\n <div class="search-bar">\n <ion-searchbar class="search-input" style="font-size:14px" color="#ffffff"\n placeholder="输入 用户名 / 邮箱 / 手机号 添加协作权限" font-size="14px"></ion-searchbar>\n </div>\n \x3c!-- 协助者 --\x3e\n <div class="people-manage">\n\n <div class="people-top">协作者</div>\n <nz-divider></nz-divider>\n <div class="people-list">\n <div class="people">\n <div class="people-avatar">\n <nz-avatar nzText="USER"></nz-avatar>\n\n </div>\n <div class="people-name">\n <p>用户名</p>\n </div>\n <div class="people-source">\n <p>2191982744%qq.com</p>\n </div>\n <div class="permission-management">\n <ion-button color="light" (click)="presentPopover($event)">权限管理</ion-button>\n <ion-popover #popover [isOpen]="isOpen" (didDismiss)="isOpen = false">\n <ng-template>\n <ion-list>\n <ion-item>\n <ion-checkbox justify="start">只读</ion-checkbox>\n </ion-item>\n\n <ion-item>\n <ion-checkbox justify="end">可编辑</ion-checkbox>\n </ion-item>\n\n\n </ion-list>\n </ng-template>\n </ion-popover>\n </div>\n </div>\n\n\n\n\n </div>\n </div>\n\n \x3c!-- 协助者End --\x3e\n\n \x3c!-- 管理者 --\x3e\n <div class="people-manage">\n\n <div class="people-top">管理者</div>\n <nz-divider></nz-divider>\n <div class="people-list">\n <div class="people">\n <div class="people-avatar">\n <nz-avatar nzText="USER"></nz-avatar>\n\n </div>\n <div class="people-name">\n <p>用户名</p>\n </div>\n <div class="people-source">\n <p>2191982744%qq.com</p>\n </div>\n <div class="people-position">\n <p>管理员</p>\n </div>\n </div>\n\n\n\n\n </div>\n </div>\n \x3c!-- 管理者End --\x3e\n\n </div>\n </div>\n\n <button mat-button (click)="navEvent(\'toggle-aitool\')">\n <ion-icon style="font-size:20px;margin-bottom:-3px;" class="icon" name="create-outline"></ion-icon>\n <span>AI写作</span>\n </button>\n \x3c!-- <ion-button color="#fafafa" style="font-size: 13px; color:#252525;margin-top: 7px;" mode="ios"\n id="popover-button">分享</ion-button> --\x3e\n <ion-popover trigger="popover-button" [dismissOnSelect]="true">\n <ng-template>\n <ion-content>\n <ion-list>\n <ion-item [button]="true" [detail]="false">下载文档</ion-item>\n <ion-item [button]="true" [detail]="false">删除文档</ion-item>\n <ion-item [button]="true" id="nested-trigger">更多</ion-item>\n\n <ion-popover trigger="nested-trigger" [dismissOnSelect]="true" side="end">\n <ng-template>\n <ion-content>\n <ion-list>\n <ion-item [button]="true" [detail]="false">Nested option</ion-item>\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n</div>\n</div>\n',styles:["mat-button{display:felx;justify-content:center;align-items:center}.back-btn{margin-top:3px;width:100px;display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:center;align-items:center;background-color:transparent}.nav{background-color:#fafafa;display:flex;height:55px;width:100%;z-index:3;justify-content:space-between;align-items:center;box-shadow:0 4px 6px #00000026}.nav .nav-left{display:flex;justify-content:flex-start;align-items:flex-start;width:350px;padding-left:20px}.nav .nav-left div{display:flex;justify-content:center;align-items:center}.nav .nav-left div span{margin-left:5px;display:inline-block;color:#4b4b4b}.nav .nav-middle{display:flex;width:33%;align-items:center;justify-content:center}.nav .nav-middle button{padding:2%;width:33%;background-color:#fafafa;border:none;text-align:center}.nav .nav-right{display:flex;width:33%;height:50%;align-items:center;justify-content:flex-end}.nav .nav-right nz-avatar{cursor:pointer;margin-right:5%}.nav .nav-right ion-list{padding:20px}.nav .nav-right .bubble-card-trigger{position:relative}.nav .nav-right .bubble-card-content{width:35vw;height:55vh;background-color:#fff;position:absolute;right:1vw;top:5vh;z-index:999}.nav .nav-right .bubble-card-content .bubble-card-tab{height:6%;width:100%}.nav .nav-right .bubble-card-content .bubble-card-tab .invite{padding:3% 4%;margin-left:1.2%;font-size:18px;font-weight:700}.nav .nav-right .bubble-card-content .search-bar{width:92%;margin-left:4%;margin-bottom:2%;font-size:14px}.nav .nav-right .bubble-card-content .people-manage{width:100%;height:auto;padding:3% 4%;margin-left:1.2%;font-size:16px}.nav .nav-right .bubble-card-content .people-manage .people-top{height:15%}.nav .nav-right .bubble-card-content .people-manage .people-list .people{display:flex;align-items:center;height:10%;width:92%;cursor:pointer;transition:background-color .3s}.nav .nav-right .bubble-card-content .people-manage .people-list .people .people-avatar{width:10%;height:10%;margin:0% 3%}.nav .nav-right .bubble-card-content .people-manage .people-list .people .people-name{margin-right:4%;margin-top:5%;width:15%;height:1%}.nav .nav-right .bubble-card-content .people-manage .people-list .people .people-source{margin-top:5.5%;width:33%}.nav .nav-right .bubble-card-content .people-manage .people-list .people .people-source p{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nav .nav-right .bubble-card-content .people-manage .people-list .people .permission-management{margin-left:5%}.nav .nav-right .bubble-card-content .people-manage .people-list .people .people-position{margin-left:11%}.nav .nav-right .bubble-card-content .people-manage .people-list .people .people-position p{margin-top:revert}.nav .nav-right .bubble-card-content .people-manage .people-list .people:hover{background-color:#fafafa}.nav .nav-right .bubble-card-content nz-divider{margin:4% 0}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"ngmodule",type:MatChipsModule},{kind:"component",type:i10.MatChip,selector:"mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]",inputs:["role","id","aria-label","aria-description","value","color","removable","highlighted","disableRipple","disabled","tabIndex"],outputs:["removed","destroyed"],exportAs:["matChip"]},{kind:"component",type:i10.MatChipListbox,selector:"mat-chip-listbox",inputs:["multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"ngmodule",type:IonicModule},{kind:"component",type:i3.IonBadge,selector:"ion-badge",inputs:["color","mode"]},{kind:"component",type:i3.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:i3.IonCheckbox,selector:"ion-checkbox",inputs:["alignment","checked","color","disabled","errorText","helperText","indeterminate","justify","labelPlacement","mode","name","required","value"]},{kind:"component",type:i3.IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:i3.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:i3.IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:i3.IonSearchbar,selector:"ion-searchbar",inputs:["animated","autocapitalize","autocomplete","autocorrect","cancelButtonIcon","cancelButtonText","clearIcon","color","debounce","disabled","enterkeyhint","inputmode","maxlength","minlength","mode","name","placeholder","searchIcon","showCancelButton","showClearButton","spellcheck","type","value"]},{kind:"component",type:i3.IonPopover,selector:"ion-popover"},{kind:"directive",type:i3.BooleanValueAccessor,selector:"ion-checkbox,ion-toggle"},{kind:"directive",type:i3.TextValueAccessor,selector:"ion-input:not([type=number]),ion-textarea,ion-searchbar"},{kind:"ngmodule",type:NzAvatarModule},{kind:"component",type:i5$4.NzAvatarComponent,selector:"nz-avatar",inputs:["nzShape","nzSize","nzGap","nzText","nzSrc","nzSrcSet","nzAlt","nzIcon"],outputs:["nzError"],exportAs:["nzAvatar"]},{kind:"ngmodule",type:NzDividerModule},{kind:"component",type:i6$2.NzDividerComponent,selector:"nz-divider",inputs:["nzText","nzType","nzOrientation","nzDashed","nzPlain"],exportAs:["nzDivider"]},{kind:"ngmodule",type:NzIconModule},{kind:"directive",type:i6$1.NzIconDirective,selector:"[nz-icon]",inputs:["nzSpin","nzRotate","nzType","nzTheme","nzTwotoneColor","nzIconfont"],exportAs:["nzIcon"]},{kind:"ngmodule",type:MatSlideToggleModule},{kind:"component",type:i8$1.MatSlideToggle,selector:"mat-slide-toggle",inputs:["name","id","labelPosition","aria-label","aria-labelledby","aria-describedby","required","color","disabled","disableRipple","tabIndex","checked","hideIcon"],outputs:["change","toggleChange"],exportAs:["matSlideToggle"]}]})}}function TaskDocumentSelect(e){let t=new AgentTaskStep({title:"选择角色知识文档",shareData:e?.shareData});return t.handle=()=>new Promise((async(n,o)=>{let i=e?.dialog.open(DialogPersonStorySelect,{data:{article:e?.shareData?.article,person:e?.person,book:e?.book},height:"90vh",maxHeight:"90vh",width:"95vw",maxWidth:"95vw"});i?.afterClosed().subscribe((async o=>{console.log("已选择知识文档",o),o?.storyList||o?.documentList?(t.message=`已选择知识文档,共${o?.storyList?.length||0}条`,e.shareData.storyList=o?.storyList,e.shareData.documentList=o?.documentList,t.error="",t.progress=1,n(!0)):(t.error="未选择知识文档",t.restartButtonShow=!0,t.cancelAll=!0,n(!1))}))})),t}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ArticleEditorTopbarComponent,decorators:[{type:Component,args:[{selector:"fm-article-editor-topbar",standalone:!0,imports:[CommonModule,MatButtonModule,MatChipsModule,IonicModule,NzAvatarModule,NzDividerModule,NzIconModule,MatSlideToggleModule],template:'<div class="nav">\n\n<div class="nav-left">\n <div (click)="goBack()">\n <ion-icon class="icon" name="chevron-back-outline"></ion-icon>\n <span>返回上级</span>\n </div>\n <div *ngIf="article?.get(\'chapter\')?.get(\'book\')?.id" (click)="navEvent(\'backmenu\')" style="width:100px;">\n <ion-icon class="icon" name="folder-outline"></ion-icon>\n <span *ngIf="!article?.get(\'chapter\')?.get(\'book\')?.id">返回首页</span>\n <span *ngIf="article?.get(\'chapter\')?.get(\'book\')?.id">打开目录</span>\n </div>\n <div (click)="navEvent(\'save\')">\n <ion-icon *ngIf="!isSaving" class="icon" name="cloud-done-outline"></ion-icon>\n <span *ngIf="isSaving" nz-icon [nzType]="\'sync\'" [nzSpin]="true"></span>\n <span [style.color]="contentChanged?\'red\':\'black\'">保存文章</span> <ion-badge *ngIf="contentChanged">新内容</ion-badge>\n </div>\n</div>\n\n<div class="nav-middle">\n <mat-chip-listbox aria-label="Dog selection">\n <mat-chip (click)="navEvent(\'options\')" [disabled]="!article?.get(\'writingOptions\')">\n \x3c!-- <img matChipAvatar src="https://material.angular.io/assets/img/examples/shiba1.jpg" alt="Photo of a Shiba Inu"/> --\x3e\n 设定\n </mat-chip>\n <mat-chip (click)="navEvent(\'outline\')" [disabled]="!article?.get(\'outlineJson\')">\n \x3c!-- <img matChipAvatar src="https://material.angular.io/assets/img/examples/shiba1.jpg" alt="Photo of a Shiba Inu"/> --\x3e\n 大纲\n </mat-chip>\n <mat-chip (click)="navEvent(\'preview\')" [disabled]="!article?.get(\'contentArray\')?.length">\n \x3c!-- <img matChipAvatar src="https://material.angular.io/assets/img/examples/shiba1.jpg" alt="Photo of a Shiba Inu"/> --\x3e\n 预览\n </mat-chip>\n </mat-chip-listbox>\n \x3c!-- <button>开始</button>\n <button>效率</button>\n <button>审阅</button> --\x3e\n\n</div>\n\n<div class="nav-right">\n\n <mat-slide-toggle [checked]="article?.get(\'isPublic\')" (change)="onPublicChange($event)">公开文章</mat-slide-toggle>\n \x3c!-- <button>登录/注册</button> --\x3e\n \x3c!-- <nz-avatar nzText="USER"></nz-avatar> --\x3e\n \x3c!-- <button class="bubble-card-trigger" (click)="showCard = !showCard">协作</button> --\x3e\n\n <div class="bubble-card" *ngIf="showCard">\n\n <div class="bubble-card-content">\n <div class="bubble-card-tab">\n <div class="invite">邀请协作</div>\n </div>\n <nz-divider></nz-divider>\n\n <div class="search-bar">\n <ion-searchbar class="search-input" style="font-size:14px" color="#ffffff"\n placeholder="输入 用户名 / 邮箱 / 手机号 添加协作权限" font-size="14px"></ion-searchbar>\n </div>\n \x3c!-- 协助者 --\x3e\n <div class="people-manage">\n\n <div class="people-top">协作者</div>\n <nz-divider></nz-divider>\n <div class="people-list">\n <div class="people">\n <div class="people-avatar">\n <nz-avatar nzText="USER"></nz-avatar>\n\n </div>\n <div class="people-name">\n <p>用户名</p>\n </div>\n <div class="people-source">\n <p>2191982744%qq.com</p>\n </div>\n <div class="permission-management">\n <ion-button color="light" (click)="presentPopover($event)">权限管理</ion-button>\n <ion-popover #popover [isOpen]="isOpen" (didDismiss)="isOpen = false">\n <ng-template>\n <ion-list>\n <ion-item>\n <ion-checkbox justify="start">只读</ion-checkbox>\n </ion-item>\n\n <ion-item>\n <ion-checkbox justify="end">可编辑</ion-checkbox>\n </ion-item>\n\n\n </ion-list>\n </ng-template>\n </ion-popover>\n </div>\n </div>\n\n\n\n\n </div>\n </div>\n\n \x3c!-- 协助者End --\x3e\n\n \x3c!-- 管理者 --\x3e\n <div class="people-manage">\n\n <div class="people-top">管理者</div>\n <nz-divider></nz-divider>\n <div class="people-list">\n <div class="people">\n <div class="people-avatar">\n <nz-avatar nzText="USER"></nz-avatar>\n\n </div>\n <div class="people-name">\n <p>用户名</p>\n </div>\n <div class="people-source">\n <p>2191982744%qq.com</p>\n </div>\n <div class="people-position">\n <p>管理员</p>\n </div>\n </div>\n\n\n\n\n </div>\n </div>\n \x3c!-- 管理者End --\x3e\n\n </div>\n </div>\n\n <button mat-button (click)="navEvent(\'toggle-aitool\')">\n <ion-icon style="font-size:20px;margin-bottom:-3px;" class="icon" name="create-outline"></ion-icon>\n <span>AI写作</span>\n </button>\n \x3c!-- <ion-button color="#fafafa" style="font-size: 13px; color:#252525;margin-top: 7px;" mode="ios"\n id="popover-button">分享</ion-button> --\x3e\n <ion-popover trigger="popover-button" [dismissOnSelect]="true">\n <ng-template>\n <ion-content>\n <ion-list>\n <ion-item [button]="true" [detail]="false">下载文档</ion-item>\n <ion-item [button]="true" [detail]="false">删除文档</ion-item>\n <ion-item [button]="true" id="nested-trigger">更多</ion-item>\n\n <ion-popover trigger="nested-trigger" [dismissOnSelect]="true" side="end">\n <ng-template>\n <ion-content>\n <ion-list>\n <ion-item [button]="true" [detail]="false">Nested option</ion-item>\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n</div>\n</div>\n',styles:["mat-button{display:felx;justify-content:center;align-items:center}.back-btn{margin-top:3px;width:100px;display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:center;align-items:center;background-color:transparent}.nav{background-color:#fafafa;display:flex;height:55px;width:100%;z-index:3;justify-content:space-between;align-items:center;box-shadow:0 4px 6px #00000026}.nav .nav-left{display:flex;justify-content:flex-start;align-items:flex-start;width:350px;padding-left:20px}.nav .nav-left div{display:flex;justify-content:center;align-items:center}.nav .nav-left div span{margin-left:5px;display:inline-block;color:#4b4b4b}.nav .nav-middle{display:flex;width:33%;align-items:center;justify-content:center}.nav .nav-middle button{padding:2%;width:33%;background-color:#fafafa;border:none;text-align:center}.nav .nav-right{display:flex;width:33%;height:50%;align-items:center;justify-content:flex-end}.nav .nav-right nz-avatar{cursor:pointer;margin-right:5%}.nav .nav-right ion-list{padding:20px}.nav .nav-right .bubble-card-trigger{position:relative}.nav .nav-right .bubble-card-content{width:35vw;height:55vh;background-color:#fff;position:absolute;right:1vw;top:5vh;z-index:999}.nav .nav-right .bubble-card-content .bubble-card-tab{height:6%;width:100%}.nav .nav-right .bubble-card-content .bubble-card-tab .invite{padding:3% 4%;margin-left:1.2%;font-size:18px;font-weight:700}.nav .nav-right .bubble-card-content .search-bar{width:92%;margin-left:4%;margin-bottom:2%;font-size:14px}.nav .nav-right .bubble-card-content .people-manage{width:100%;height:auto;padding:3% 4%;margin-left:1.2%;font-size:16px}.nav .nav-right .bubble-card-content .people-manage .people-top{height:15%}.nav .nav-right .bubble-card-content .people-manage .people-list .people{display:flex;align-items:center;height:10%;width:92%;cursor:pointer;transition:background-color .3s}.nav .nav-right .bubble-card-content .people-manage .people-list .people .people-avatar{width:10%;height:10%;margin:0% 3%}.nav .nav-right .bubble-card-content .people-manage .people-list .people .people-name{margin-right:4%;margin-top:5%;width:15%;height:1%}.nav .nav-right .bubble-card-content .people-manage .people-list .people .people-source{margin-top:5.5%;width:33%}.nav .nav-right .bubble-card-content .people-manage .people-list .people .people-source p{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nav .nav-right .bubble-card-content .people-manage .people-list .people .permission-management{margin-left:5%}.nav .nav-right .bubble-card-content .people-manage .people-list .people .people-position{margin-left:11%}.nav .nav-right .bubble-card-content .people-manage .people-list .people .people-position p{margin-top:revert}.nav .nav-right .bubble-card-content .people-manage .people-list .people:hover{background-color:#fafafa}.nav .nav-right .bubble-card-content nz-divider{margin:4% 0}\n"]}]}],ctorParameters:()=>[{type:i3.NavController}],propDecorators:{popover:[{type:ViewChild,args:["popover"]}],article:[{type:Input}],contentChanged:[{type:Input}],isSaving:[{type:Input}],onNavEvent:[{type:Output}]}});class FmArticleWriteOptionsComponent{validatorMaxCount(e){return(e?.value||0)>4e3?{maxCount:"characters over 4000"}:null}genWordCountList(e){let t=e?.wordCountDocument||0;t<2500&&(this.wordCountList=[{label:"简练",value:.6*t},{label:"正常",value:1*t},{label:"发散",value:1.4*t}])}constructor(e,t){this.dialogRef=e,this.data=t,this.writingOptions={writingStyle:"记叙文",writingPerson:"第三人称"},this.writingStyleList=["记叙文","说明文","议论文","应用文"],this.writingPersonList=["第一人称","第三人称"],this.wordCountLimit=new FormControl("",[this.validatorMaxCount]),this.wordCountList=[{label:"简练",value:1500},{label:"正常",value:2500},{label:"发散",value:3500}],this.writingOptions=t?.writingOptions||this.writingOptions||{},this.genWordCountList(t?.writingOptions)}ngOnInit(){}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmArticleWriteOptionsComponent,deps:[{token:i3$1.MatDialogRef},{token:MAT_DIALOG_DATA}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmArticleWriteOptionsComponent,isStandalone:!0,selector:"app-fm-article-write-options",ngImport:i0,template:'\n<h2 mat-dialog-title>文章写作设定</h2>\n\n<mat-dialog-content>\n\n <div class="row">\n <h3>文章体裁</h3>\n <mat-radio-group [(ngModel)]="writingOptions.writingStyle">\n <mat-radio-button *ngFor="let style of writingStyleList" [value]="style">{{style}}</mat-radio-button>\n </mat-radio-group>\n </div>\n <div class="row">\n <h3>写作人称</h3>\n <mat-radio-group [(ngModel)]="writingOptions.writingPerson">\n <mat-radio-button *ngFor="let item of writingPersonList" [value]="item">{{item}}</mat-radio-button>\n </mat-radio-group>\n </div>\n \x3c!-- <div class="row">\n <h3>篇幅字数 <span *ngIf="writingOptions?.wordCountDocument">已选知识库总字数 {{writingOptions?.wordCountDocument}}</span></h3>\n <mat-radio-group [(ngModel)]="writingOptions.wordCount">\n <mat-radio-button *ngFor="let item of wordCountList" [value]="item.value">{{item.label}}({{item.value}}字)</mat-radio-button>\n </mat-radio-group><br/>\n <mat-form-field style="width:300px;" hintLabel="字数不超过">\n <mat-label>自定义字数</mat-label>\n <input #wordCountInput matInput placeholder="填写整数" [formControl]="wordCountLimit" step="1" min="100" max="4000" [(ngModel)]="writingOptions.wordCount">\n <mat-icon matSuffix>字</mat-icon>\n <mat-hint align="end">{{wordCountInput.value || 0}}/4000</mat-hint>\n <mat-error *ngIf="writingOptions.wordCount&&writingOptions.wordCount>4000">字数不可超过4000</mat-error>\n </mat-form-field>\n </div> --\x3e\n\n</mat-dialog-content>\n\n<mat-dialog-actions [align]="\'end\'" style="display: flex;justify-content: center;">\n \x3c!-- <button mat-button (click)="onNoClick()">No Thanks</button> --\x3e\n <button style="font-size: 20px;" mat-button color="warn" [mat-dialog-close]="false">取消</button>\n <button style="font-size: 20px;" mat-button color="primary" [mat-dialog-close]="writingOptions" cdkFocusInitial>完成</button>\n</mat-dialog-actions>\n\n',styles:[":host-context(body.dark) .row h3,:host-context(body.dark) .row span{color:#fff!important}.row h3 span{font-size:16px}h2{text-align:center;background-color:#6e23ce}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"ngmodule",type:MatDialogModule},{kind:"directive",type:i3$1.MatDialogClose,selector:"[mat-dialog-close], [matDialogClose]",inputs:["aria-label","type","mat-dialog-close","matDialogClose"],exportAs:["matDialogClose"]},{kind:"directive",type:i3$1.MatDialogTitle,selector:"[mat-dialog-title], [matDialogTitle]",inputs:["id"],exportAs:["matDialogTitle"]},{kind:"directive",type:i3$1.MatDialogActions,selector:"[mat-dialog-actions], mat-dialog-actions, [matDialogActions]",inputs:["align"]},{kind:"directive",type:i3$1.MatDialogContent,selector:"[mat-dialog-content], mat-dialog-content, [matDialogContent]"},{kind:"ngmodule",type:MatCheckboxModule},{kind:"ngmodule",type:MatRadioModule},{kind:"directive",type:i4$3.MatRadioGroup,selector:"mat-radio-group",inputs:["color","name","labelPosition","value","selected","disabled","required"],outputs:["change"],exportAs:["matRadioGroup"]},{kind:"component",type:i4$3.MatRadioButton,selector:"mat-radio-button",inputs:["id","name","aria-label","aria-labelledby","aria-describedby","disableRipple","tabIndex","checked","value","labelPosition","disabled","required","color"],outputs:["change"],exportAs:["matRadioButton"]},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"ngmodule",type:MatFormFieldModule},{kind:"ngmodule",type:MatInputModule}]})}}function TaskArticleWritingOptions(e){let t=new AgentTaskStep({title:"设定写作参数详情",shareData:e?.shareData});return t.handle=()=>new Promise((async(n,o)=>{let i=2500;e?.editOnly||e?.shareData.documentList.forEach((e=>{let t=e?.get("pageContent")||"";i+=t?.length}));let a={writingStyle:"文章体裁",wordCount:"篇幅字数"},r=e?.shareData?.writingOptions||{};r.wordCountDocument=i,console.log(e?.shareData);let s=e?.dialog.open(FmArticleWriteOptionsComponent,{data:{writingOptions:r,person:e?.person,book:e?.book},height:"75vh",maxHeight:"75vh",disableClose:!0});s?.afterClosed().subscribe((async o=>{o?(t.logList.push("已选择写作参数:"),Object.keys(o).forEach((e=>{a[e]&&t.logList.push(`${a[e]}: ${o[e]}`)})),e.shareData.writingOptions=o,console.log(e.shareData,o),e.shareData.article.set("writingOptions",o),e.shareData.article=await e.shareData.article.save(),t.error="",t.progress=1,n(!0)):(t.error="未选择参数,请重新选择",t.restartButtonShow=!0,n(!1))}))})),t}async function getRelationByDocList(e,t){if(!e?.length&&!t?.length)return[];let n=[];e?.length&&e?.forEach((e=>{e?.id&&n.push({docList:e?.toPointer()})}));let o=t?.map((e=>e?.get("person")));if(o=o?.filter((e=>e)),o?.forEach((e=>{e?.id&&(n.push({person:e?.toPointer()}),n.push({person1:e?.toPointer()}),n.push({person2:e?.toPointer()}))})),!n?.length)return;let i=Parse__default.Query.fromJSON("PersonRelation",{where:{$or:n}});i.notEqualTo("isDeleted",!0),i.include("person1","person2","relation");try{return await i.find()||[]}catch(e){}return[]}async function PromptInsertionRoleList(e,t){let n=await getRelationByDocList(e,t),o="";return n?.forEach((e=>{let t=e?.get("person1"),n=t?.get("name")||e?.get("person1Data")?.name,i=e?.get("person2"),a=i?.get("name")||e?.get("person2Data")?.name,r=e?.get("relation");i?.id&&(o+=`\n角色ID:${i?.id},名称:${a},是${n}的${r?.get("name")}`)})),o?o?"\n以下是相关角色id及名称:\n"+o:void 0:""}async function PromptInsertionDocumentList(e,t,n){let o="";if(e&&e?.forEach((e=>{let t=e?.get("pageContent");t=t?.replaceAll("\n\n","\n"),t&&(o+=`\`\`\`\n文档ID:${e?.id}\n文档内容:${t}\n\`\`\`\n`)})),t){t=t?.filter((e=>"chat"==e?.get("type")&&e?.get("chatSession")?.id||"diary"==e?.get("type")&&e?.get("content")));for(let e=0;e<t.length;e++){let i=t[e],a=await storyJsonToContent(i,n);a&&(o+=`\`\`\`\n文档ID:${i?.id}\n文档内容:${a}\n\`\`\`\n`)}}return"\n以下是知识文档id及内容:\n"+o}async function storyJsonToContent(e,t){let n,o=e?.get("contentJson"),i=e?.get("person")?.id||e?.get("person")?.objectId;if(i)try{n=await(t?.loadPersonById(i))}catch(e){}let a,r=n?.get&&n?.get("name"),s=e?.get("recorder")?.id||e?.get("recorder")?.objectId;if(s)try{a=await(t?.loadPersonById(s))}catch(e){}let l=a?.get&&a?.get("name")||e?.get("user")?.get&&e?.get("user")?.get("realname");if("diary"==e?.get("type")){if(o?.title){return`日记主题:${o?.title},作者:${r||l},描述:${o?.desc},关键字${o?.keywords?.join(",")},内容:${e?.get("content")}`}return""}if("chat"==e?.get("type")){let n,i="",a=e?.get("chatSession")?.get("messageList"),r=e?.get("chatSession")?.get("role")?.get("name")||"记者";try{n=await(t?.loadPersonById(e?.get("person")?.id||e?.get("person")?.objectId))}catch(e){}let s=n?.get("name")||n?.get("userVerify")?.get("name")||"当前人物",l=e?.get("user")?.get("realname")||e?.get("user")?.get("nickname")||"用户";return a?.length?(a?.forEach(((e,t)=>{if(e?.hidden)return;if("system"==e?.role)return;let n;"assistant"==e?.role&&(n=`${r}问:${e?.content}\n`),"user"==e?.role&&(n=`${l}答:${e?.content}\n`),i+=n||""})),`人物:${s},被采访人:${l},主题:${o?.title},描述:${o?.desc},关键字:${o?.keywords?.join(",")},对话记录:\n${i}`):""}return""}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmArticleWriteOptionsComponent,decorators:[{type:Component,args:[{selector:"app-fm-article-write-options",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,MatDialogModule,MatCheckboxModule,MatRadioModule,MatButtonModule,MatFormFieldModule,MatInputModule],template:'\n<h2 mat-dialog-title>文章写作设定</h2>\n\n<mat-dialog-content>\n\n <div class="row">\n <h3>文章体裁</h3>\n <mat-radio-group [(ngModel)]="writingOptions.writingStyle">\n <mat-radio-button *ngFor="let style of writingStyleList" [value]="style">{{style}}</mat-radio-button>\n </mat-radio-group>\n </div>\n <div class="row">\n <h3>写作人称</h3>\n <mat-radio-group [(ngModel)]="writingOptions.writingPerson">\n <mat-radio-button *ngFor="let item of writingPersonList" [value]="item">{{item}}</mat-radio-button>\n </mat-radio-group>\n </div>\n \x3c!-- <div class="row">\n <h3>篇幅字数 <span *ngIf="writingOptions?.wordCountDocument">已选知识库总字数 {{writingOptions?.wordCountDocument}}</span></h3>\n <mat-radio-group [(ngModel)]="writingOptions.wordCount">\n <mat-radio-button *ngFor="let item of wordCountList" [value]="item.value">{{item.label}}({{item.value}}字)</mat-radio-button>\n </mat-radio-group><br/>\n <mat-form-field style="width:300px;" hintLabel="字数不超过">\n <mat-label>自定义字数</mat-label>\n <input #wordCountInput matInput placeholder="填写整数" [formControl]="wordCountLimit" step="1" min="100" max="4000" [(ngModel)]="writingOptions.wordCount">\n <mat-icon matSuffix>字</mat-icon>\n <mat-hint align="end">{{wordCountInput.value || 0}}/4000</mat-hint>\n <mat-error *ngIf="writingOptions.wordCount&&writingOptions.wordCount>4000">字数不可超过4000</mat-error>\n </mat-form-field>\n </div> --\x3e\n\n</mat-dialog-content>\n\n<mat-dialog-actions [align]="\'end\'" style="display: flex;justify-content: center;">\n \x3c!-- <button mat-button (click)="onNoClick()">No Thanks</button> --\x3e\n <button style="font-size: 20px;" mat-button color="warn" [mat-dialog-close]="false">取消</button>\n <button style="font-size: 20px;" mat-button color="primary" [mat-dialog-close]="writingOptions" cdkFocusInitial>完成</button>\n</mat-dialog-actions>\n\n',styles:[":host-context(body.dark) .row h3,:host-context(body.dark) .row span{color:#fff!important}.row h3 span{font-size:16px}h2{text-align:center;background-color:#6e23ce}\n"]}]}],ctorParameters:()=>[{type:i3$1.MatDialogRef},{type:void 0,decorators:[{type:Inject,args:[MAT_DIALOG_DATA]}]}]});const agentPrompt$1=new AgentPrompt,PromptTplArticleOutlineCode="article-outline-json-tpl";function TaskArticleOutline(e){let t=e?.shareData?.writingOptions,n=new AgentTaskStep({title:"推理生成文章大纲",shareData:e?.shareData});return n.handle=()=>new Promise((o=>{n.progress=.01,setTimeout((async()=>{let i=await PromptInsertionRoleList(e?.shareData?.documentList,e?.shareData?.storyList),a=await PromptInsertionDocumentList(e?.shareData?.documentList,e?.shareData?.storyList,e.personServ),r=await agentPrompt$1.getFormatTpl(PromptTplArticleOutlineCode,{name:e?.person?.get("name"),writingStyle:t?.writingStyle||"不限",wordCount:t?.wordCount||2e3,roleList:"",docsRowList:""});a&&(r+=a),i&&(r+=i);let s=agentPrompt$1.getTokens(r);e.shareData.articleOutlinePrompt=r,e.shareData.articleOutlinePromptTokens=s,n.logList.push(`提示词tokens:${s}个`);let l=e?.shareData?.article.get("outlineJson");if(saveArticleOutline(e?.shareData?.article,l),l?.title)return n.logList.push(`已推理tokens:${JSON.stringify(l)?.length}个`),n.progress=1,void o(!0);agentPrompt$1.jsonCompletion(r).subscribe((async t=>{n.logList[0]=`已推理tokens:${t?.content?.length}个`,t?.complete&&(t.content&&(l=agentPrompt$1.extractAndParseJson(t?.content),saveArticleOutline(e?.shareData?.article,l),e.shareData.article.set("outlineJson",l),e.shareData.article=await e.shareData.article.save()),n.progress=1,o(!0))}))}),1500)})),n}function saveArticleOutline(e,t){t?.title&&e?.set("title",t?.title),t?.desc&&e?.set("desc",t?.desc),t?.keywords&&e?.set("keywords",t?.keywords)}function getOutlineJsonFromMarkdown(e,t){let n={},o=[];return function reduceArray(e){e.forEach((e=>{if("object"==typeof e&&reduceArray(e),"string"==typeof e){if(e?.indexOf("题目:")>-1){let t=e?.split(":")?.[1]?.trim();n.title=t}if(e?.indexOf("中心思想:")>-1){let t=e?.split(":")?.[1]?.trim();n.desc=t}if(e?.indexOf("关键字:")>-1){let t=e?.split(":")?.[1]?.trim(),o=t?.split(",");n.keywords=o?.map((e=>e.trim()))}if(e?.indexOf("文档ID:")>-1){let t=e?.split(":")?.[1]?.trim();t&&o.push({__type:"Pointer",className:"Document",objectId:t})}}}))}(agentPrompt$1.extractMarkdownToMultiArray(t)),n?.title&&e?.set("title",n?.title),n?.desc&&e?.set("desc",n?.desc),n?.keywords&&e?.set("keywords",n?.keywords),n?.docList?.length&&e?.set("docList",o),n}class OutlineCountPipe{transform(e,...t){return"string"==typeof e?e?.length:"object"==typeof e?JSON.stringify(e)?.length:0}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:OutlineCountPipe,deps:[],target:i0.ɵɵFactoryTarget.Pipe})}static{this.ɵpipe=i0.ɵɵngDeclarePipe({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:OutlineCountPipe,isStandalone:!0,name:"outlineCount"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:OutlineCountPipe,decorators:[{type:Pipe,args:[{name:"outlineCount",pure:!0,standalone:!0}]}]});class FmArticleOutlineLeftitemComponent{constructor(){this.readOnly=!1,this.width="200px"}ngOnInit(){}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmArticleOutlineLeftitemComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmArticleOutlineLeftitemComponent,isStandalone:!0,selector:"fm-article-outline-leftitem",inputs:{section:"section",index:"index",readOnly:"readOnly",width:"width"},ngImport:i0,template:'<div class="outline" [style.width]="width">\n <div class="row divide section-title" *ngIf="section?.title">\n <span>章{{(index||0)+1}}.</span>\n <input matInput [readonly]="readOnly" type="text" [(ngModel)]="section.title" placeholder="请填章节标题" nzBorderless />\n </div>\n <div class="row" *ngIf="section?.outline">\n <span>内容</span>\n <textarea nzAutosize matInput [readonly]="readOnly" type="text" [(ngModel)]="section.outline" placeholder="请填主要内容" nzBorderless></textarea>\n </div>\n <div class="row" *ngIf="section?.skill">\n <span>技巧</span>\n <textarea nzAutosize matInput [readonly]="readOnly" type="text" [(ngModel)]="section.skill" placeholder="请填写作技巧" nzBorderless></textarea>\n </div>\n <div class="row" *ngIf="section?.case">\n <span>事例</span>\n <textarea nzAutosize matInput [readonly]="readOnly" type="text" [(ngModel)]="section.case" placeholder="请填重点事例" nzBorderless></textarea>\n </div>\n</div>',styles:[":host-context(body.dark) .outline{color:#fff}:host-context(body.dark) .outline textarea,:host-context(body.dark) .outline input{background-color:#00000080;border-radius:5px}.outline{height:auto;display:flex;flex-direction:column}.outline mat-chip{margin:0 3px 0 0}.outline mat-chip .mat-mdc-standard-chip .mdc-evolution-chip__action--primary{padding-left:5px;padding-right:5px}.outline .row{width:100%;display:flex;justify-content:left;padding-left:5px}.outline .row span{padding-top:4px;width:50px}.outline .row input,.outline .row textarea{width:calc(100% - 60px)}.outline .divide{border-top:1px solid rgba(0,0,0,.06)}.outline .section-title{font-weight:600}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i3$3.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"ngmodule",type:NzInputModule},{kind:"directive",type:i8.NzAutosizeDirective,selector:"textarea[nzAutosize]",inputs:["nzAutosize"],exportAs:["nzAutosize"]},{kind:"ngmodule",type:MatInputModule},{kind:"directive",type:i4$4.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmArticleOutlineLeftitemComponent,decorators:[{type:Component,args:[{selector:"fm-article-outline-leftitem",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,NzInputModule,MatInputModule],template:'<div class="outline" [style.width]="width">\n <div class="row divide section-title" *ngIf="section?.title">\n <span>章{{(index||0)+1}}.</span>\n <input matInput [readonly]="readOnly" type="text" [(ngModel)]="section.title" placeholder="请填章节标题" nzBorderless />\n </div>\n <div class="row" *ngIf="section?.outline">\n <span>内容</span>\n <textarea nzAutosize matInput [readonly]="readOnly" type="text" [(ngModel)]="section.outline" placeholder="请填主要内容" nzBorderless></textarea>\n </div>\n <div class="row" *ngIf="section?.skill">\n <span>技巧</span>\n <textarea nzAutosize matInput [readonly]="readOnly" type="text" [(ngModel)]="section.skill" placeholder="请填写作技巧" nzBorderless></textarea>\n </div>\n <div class="row" *ngIf="section?.case">\n <span>事例</span>\n <textarea nzAutosize matInput [readonly]="readOnly" type="text" [(ngModel)]="section.case" placeholder="请填重点事例" nzBorderless></textarea>\n </div>\n</div>',styles:[":host-context(body.dark) .outline{color:#fff}:host-context(body.dark) .outline textarea,:host-context(body.dark) .outline input{background-color:#00000080;border-radius:5px}.outline{height:auto;display:flex;flex-direction:column}.outline mat-chip{margin:0 3px 0 0}.outline mat-chip .mat-mdc-standard-chip .mdc-evolution-chip__action--primary{padding-left:5px;padding-right:5px}.outline .row{width:100%;display:flex;justify-content:left;padding-left:5px}.outline .row span{padding-top:4px;width:50px}.outline .row input,.outline .row textarea{width:calc(100% - 60px)}.outline .divide{border-top:1px solid rgba(0,0,0,.06)}.outline .section-title{font-weight:600}\n"]}]}],ctorParameters:()=>[],propDecorators:{section:[{type:Input}],index:[{type:Input}],readOnly:[{type:Input}],width:[{type:Input}]}});class FmArticleOutlineComponent{constructor(){}ngOnInit(){this.outlineJson=this.article?.get("outlineJson")}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmArticleOutlineComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmArticleOutlineComponent,isStandalone:!0,selector:"fm-article-outline",inputs:{article:"article"},ngImport:i0,template:'<div class="page" *ngIf="article?.id">\n <div id="editor-outline" *ngIf="outlineJson">\n <div class="row title" *ngIf="outlineJson?.title">\n <span>标题</span>\n <input matInput type="text" [(ngModel)]="outlineJson.title" placeholder="请填写文章标题" nzBorderless />\n </div>\n <div class="row" *ngIf="outlineJson?.desc">\n <span>描述</span>\n <textarea nzAutosize matInput type="text" [(ngModel)]="outlineJson.desc" placeholder="请描述文章内容" nzBorderless></textarea>\n </div>\n\n\n <ng-container *ngIf="outlineJson.sections?.length">\n\n <ng-container *ngFor="let section of outlineJson.sections;let index=index">\n <div class="row">\n <fm-article-outline-leftitem style="width:100%;" [width]="\'100%\'" [section]="section" [index]="index"></fm-article-outline-leftitem>\n </div>\n \x3c!-- <div class="row divide title" *ngIf="section?.title">\n <span>章{{index+1}}.</span>\n <input nz-input type="text" [(ngModel)]="section.title" placeholder="请填章节标题" nzBorderless />\n </div>\n <div class="row" *ngIf="section?.outline">\n <span>内容</span>\n <textarea nzAutosize nz-input type="text" [(ngModel)]="section.outline" placeholder="请填主要内容" nzBorderless></textarea>\n </div>\n <div class="row" *ngIf="section?.skill">\n <span>技巧</span>\n <textarea nzAutosize nz-input type="text" [(ngModel)]="section.skill" placeholder="请填写作技巧" nzBorderless></textarea>\n </div>\n <div class="row" *ngIf="section?.case">\n <span>事例</span>\n <textarea nzAutosize nz-input type="text" [(ngModel)]="section.case" placeholder="请填重点事例" nzBorderless></textarea>\n </div> --\x3e\n </ng-container>\n </ng-container>\n\n \x3c!-- <nz-code-editor *ngIf="article?.get(\'outline\')?.length"\n style="height:calc( 90vh - 60px );width:75vw;display: block;"\n [ngModel]="article?.get(\'outline\')"\n (ngModelChange)="article?.set(\'outline\',$event)"\n [nzEditorOption]="{ language: \'markdown\' }"\n ></nz-code-editor> --\x3e\n </div>\n</div>',styles:[":host-context(body.dark) .row{color:#fff}:host-context(body.dark) .row textarea,:host-context(body.dark) .row input{background-color:#00000080;border-radius:5px}.page{width:100%;height:100%;padding-top:10px}.page #editor-outline{padding-top:10px;width:100%;height:100%;display:flex;flex-direction:column;justify-content:start;align-items:center}.page #editor-outline .row{width:95%;display:flex;justify-content:center}.page #editor-outline .row span{padding-top:4px;width:50px}.page #editor-outline .row input,.page #editor-outline .row textarea{width:calc(100% - 60px)}.page #editor-outline .divide{border-top:1px solid rgba(0,0,0,.06)}.page #editor-outline .title{font-weight:600}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i3$3.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"ngmodule",type:NzInputModule},{kind:"directive",type:i8.NzAutosizeDirective,selector:"textarea[nzAutosize]",inputs:["nzAutosize"],exportAs:["nzAutosize"]},{kind:"ngmodule",type:NzCodeEditorModule},{kind:"component",type:FmArticleOutlineLeftitemComponent,selector:"fm-article-outline-leftitem",inputs:["section","index","readOnly","width"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmArticleOutlineComponent,decorators:[{type:Component,args:[{selector:"fm-article-outline",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,NzInputModule,NzCodeEditorModule,FmArticleOutlineLeftitemComponent],template:'<div class="page" *ngIf="article?.id">\n <div id="editor-outline" *ngIf="outlineJson">\n <div class="row title" *ngIf="outlineJson?.title">\n <span>标题</span>\n <input matInput type="text" [(ngModel)]="outlineJson.title" placeholder="请填写文章标题" nzBorderless />\n </div>\n <div class="row" *ngIf="outlineJson?.desc">\n <span>描述</span>\n <textarea nzAutosize matInput type="text" [(ngModel)]="outlineJson.desc" placeholder="请描述文章内容" nzBorderless></textarea>\n </div>\n\n\n <ng-container *ngIf="outlineJson.sections?.length">\n\n <ng-container *ngFor="let section of outlineJson.sections;let index=index">\n <div class="row">\n <fm-article-outline-leftitem style="width:100%;" [width]="\'100%\'" [section]="section" [index]="index"></fm-article-outline-leftitem>\n </div>\n \x3c!-- <div class="row divide title" *ngIf="section?.title">\n <span>章{{index+1}}.</span>\n <input nz-input type="text" [(ngModel)]="section.title" placeholder="请填章节标题" nzBorderless />\n </div>\n <div class="row" *ngIf="section?.outline">\n <span>内容</span>\n <textarea nzAutosize nz-input type="text" [(ngModel)]="section.outline" placeholder="请填主要内容" nzBorderless></textarea>\n </div>\n <div class="row" *ngIf="section?.skill">\n <span>技巧</span>\n <textarea nzAutosize nz-input type="text" [(ngModel)]="section.skill" placeholder="请填写作技巧" nzBorderless></textarea>\n </div>\n <div class="row" *ngIf="section?.case">\n <span>事例</span>\n <textarea nzAutosize nz-input type="text" [(ngModel)]="section.case" placeholder="请填重点事例" nzBorderless></textarea>\n </div> --\x3e\n </ng-container>\n </ng-container>\n\n \x3c!-- <nz-code-editor *ngIf="article?.get(\'outline\')?.length"\n style="height:calc( 90vh - 60px );width:75vw;display: block;"\n [ngModel]="article?.get(\'outline\')"\n (ngModelChange)="article?.set(\'outline\',$event)"\n [nzEditorOption]="{ language: \'markdown\' }"\n ></nz-code-editor> --\x3e\n </div>\n</div>',styles:[":host-context(body.dark) .row{color:#fff}:host-context(body.dark) .row textarea,:host-context(body.dark) .row input{background-color:#00000080;border-radius:5px}.page{width:100%;height:100%;padding-top:10px}.page #editor-outline{padding-top:10px;width:100%;height:100%;display:flex;flex-direction:column;justify-content:start;align-items:center}.page #editor-outline .row{width:95%;display:flex;justify-content:center}.page #editor-outline .row span{padding-top:4px;width:50px}.page #editor-outline .row input,.page #editor-outline .row textarea{width:calc(100% - 60px)}.page #editor-outline .divide{border-top:1px solid rgba(0,0,0,.06)}.page #editor-outline .title{font-weight:600}\n"]}]}],ctorParameters:()=>[],propDecorators:{article:[{type:Input}]}});class DialogArticleOutline{confirmOutline(){this.dialogRef.close(this.article?.get("outlineJson"))}constructor(e,t){this.dialogRef=e,this.data=t,this.isSelectMode=!0,this.selectCount=0,this.outline="",this.writingOptions={},this.article=t?.article,this.person=t?.person,this.book=t?.book}onConfirm(){this.dialogRef.close(this.article?.get("outlineJson"))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DialogArticleOutline,deps:[{token:i3$1.MatDialogRef},{token:MAT_DIALOG_DATA}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:DialogArticleOutline,isStandalone:!0,selector:"article-outline-dialog",viewQueries:[{propertyName:"storySelectComp",first:!0,predicate:FmArticleOutlineComponent,descendants:!0}],ngImport:i0,template:'\n <fm-article-outline [article]="article"></fm-article-outline>\n <mat-dialog-actions align="start" style="display: flex;justify-content: center;">\n <button mat-button>大纲篇幅:{{article?.get(\'outlineJson\')|outlineCount}}字</button>\n <button mat-button style="color:red;">请您检查或修改大纲,确认后点击生成</button>\n <button mat-button color="primary" [mat-dialog-close]="true">取消</button>\n <button mat-raised-button color="primary" (click)="onConfirm()" cdkFocusInitial>生成文章</button>\n </mat-dialog-actions>\n ',isInline:!0,styles:["fm-article-outline{height:calc(100% - 60px);width:100%;overflow-y:auto}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"ngmodule",type:MatDialogModule},{kind:"directive",type:i3$1.MatDialogClose,selector:"[mat-dialog-close], [matDialogClose]",inputs:["aria-label","type","mat-dialog-close","matDialogClose"],exportAs:["matDialogClose"]},{kind:"directive",type:i3$1.MatDialogActions,selector:"[mat-dialog-actions], mat-dialog-actions, [matDialogActions]",inputs:["align"]},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"ngmodule",type:MatInputModule},{kind:"component",type:FmArticleOutlineComponent,selector:"fm-article-outline",inputs:["article"]},{kind:"pipe",type:OutlineCountPipe,name:"outlineCount"}]})}}function TaskArticleOutlineEdit(e){let t=new AgentTaskStep({title:"编辑修订写作大纲",shareData:e?.shareData});return t.handle=()=>new Promise((async(n,o)=>{let i=e?.dialog.open(DialogArticleOutline,{data:{article:e?.shareData?.article,person:e?.person,book:e?.book},height:"90vh",maxHeight:"90vh",width:"80vw",maxWidth:"80vw"});i?.afterClosed().subscribe((async o=>{o?("string"==typeof o&&(e?.shareData?.article?.set("outline",o),await(e?.shareData?.article?.save())),"object"==typeof o&&(e?.shareData?.article?.set("outlineJson",o),await(e?.shareData?.article?.save())),t.logList.push("已确认写作大纲"),t.error="",t.progress=1,n(!0)):(t.error="未保存大纲,请重试",t.restartButtonShow=!0,n(!1))}))})),t}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DialogArticleOutline,decorators:[{type:Component,args:[{selector:"article-outline-dialog",template:'\n <fm-article-outline [article]="article"></fm-article-outline>\n <mat-dialog-actions align="start" style="display: flex;justify-content: center;">\n <button mat-button>大纲篇幅:{{article?.get(\'outlineJson\')|outlineCount}}字</button>\n <button mat-button style="color:red;">请您检查或修改大纲,确认后点击生成</button>\n <button mat-button color="primary" [mat-dialog-close]="true">取消</button>\n <button mat-raised-button color="primary" (click)="onConfirm()" cdkFocusInitial>生成文章</button>\n </mat-dialog-actions>\n ',standalone:!0,imports:[CommonModule,MatDialogModule,MatButtonModule,MatInputModule,FmArticleOutlineComponent,OutlineCountPipe],styles:["fm-article-outline{height:calc(100% - 60px);width:100%;overflow-y:auto}\n"]}]}],ctorParameters:()=>[{type:i3$1.MatDialogRef},{type:void 0,decorators:[{type:Inject,args:[MAT_DIALOG_DATA]}]}],propDecorators:{storySelectComp:[{type:ViewChild,args:[FmArticleOutlineComponent]}]}});const agentPrompt=new AgentPrompt;var PromptTplArticleSectionCode="article-section-create-tpl";class DraftService{constructor(e){this.personServ=e,this.DraftListMap={},this.DraftCountMap={},this.total=0,this.aiCount=0,this.draftCount=0}async loadArticleDraft(e){if(!e?.id)return;let t=new Parse__default.Query("ArticleDraft");t.equalTo("article",e?.id),t.addDescending("updatedAt"),t.notEqualTo("isDeleted",!0),this.DraftListMap[e?.id]=await t.find(),this.DraftCountMap[e.id]||(this.DraftCountMap[e.id]={}),this.DraftCountMap[e.id].total=this.DraftListMap[e?.id]?.length,this.DraftCountMap[e.id].aiCount=this.DraftListMap[e?.id].filter((e=>"ai"==e?.get("type")))?.length,this.DraftCountMap[e.id].draftCount=this.total-this.aiCount}async newSectionCreate(e){let t=e?.draft?.get("outlineJson"),n=t?.sections?.[e?.sectionIndex],o=e.writingOptions;if(o.title=n?.title,o.outline="",o.skill="",o.case="",o.count="",o.writtingPerson=o.writtingPerson||"第三人称",o.personName=e?.person?.get("name")||"",o.personGender=e?.person?.get("gender")||"",n?.outline&&(o.outline=`,主要内容:${n?.outline}.`),n?.skill&&(o.skill=`,写作技巧:${n?.skill}.`),n?.case&&(o.case=`,细节案例:${n?.case}.`),n?.count&&(o.count=`,总字数达${n?.count||2e3}以上.`),e?.contentArray?.length){let n=t?.sections||[],i=n.map(((t,n)=>`# ${t.title}\n${e?.contentArray?.[n]?.content||"待完成"}\n`))?.join("\n");o.createdContent="\n已编写内容:\n"+i+"\n"}let i,a,r=await agentPrompt.getFormatTpl(PromptTplArticleSectionCode,o),s=[];if(n?.docList?.length>0){let t=new Parse__default.Query("Document");t.notEqualTo("isDeleted",!0),t.containedIn("objectId",n?.docList);let o=await(t?.find());o?.length>0&&(e.documentList=o);let i=new Parse__default.Query("Story");i.include("chatSession","person","recorder","user"),i.notEqualTo("isDeleted",!0),i.containedIn("objectId",n?.docList),s=await(i?.find())}if(e.documentList?.length||s?.length){try{i=await PromptInsertionRoleList(e.documentList,s)}catch(e){console.error("PromptInsertionRoleList",e)}try{a=await PromptInsertionDocumentList(e.documentList,s,this.personServ)}catch(e){console.error("PromptInsertionDocumentList",e)}}a&&(r=a+r),i&&(r=i+r);let l=new FmodeChatCompletion([{role:"user",content:r}]);l.model="fmode-4.0-cn-256k",e.draft?.set("model",l?.model);let c=l.sendCompletion({isDirect:!0}).pipe(finalize((()=>{undefined.complete=!0}))).subscribe((async t=>{if(e?.contentArray?.[e?.sectionIndex]||(e.contentArray[e.sectionIndex]={type:"markdown",content:""}),"string"==typeof t?.content&&(t.content=t.content?.replaceAll(`## ${n?.title}`,""),t.content=t.content?.replaceAll(`# ${n?.title}`,""),t.content=t.content?.replaceAll(`${n?.title}`,"")),e.contentArray[e?.sectionIndex].content=`# ${n?.title}\n${t.content}`,t?.complete){e?.afterComplete&&e?.afterComplete(e?.draft);try{e?.cdRef?.detectChanges(),c?.closed||c?.unsubscribe&&c?.unsubscribe()}catch(e){console.error("unsubscribe",e)}}e?.cdRef?.detectChanges()}));return c}testCreateLongArticle(e,t,n,o,i){let a="";return from(["大连宇科创新科技有限公司作为国内领先的氢能测试装备和解决方案提供商,其在氢能领域的技术创新和未来发展方向备受瞩目。公司通过团队核心成员丰富的燃料电池及系统研发经验,采用创新加湿技术、流体控制模式和独创算法等,打造了高精度、高稳定性、功能完善的氢能测试设备,为客户提供极具竞争力、安全可信赖的产品、解决方案与服务。","在技术创新方面,大连宇科创新科技有限公司不断提升研发水准,致力于为燃料电池领域科技发展做出积极贡献。公司拥有国家级高新技术企业认证,通过ISO9001质量体系认证、ISO14001环境管理体系认证、ISO45001职业健康安全管理体系认证等多项资质,展现了其在技术水平和产品质量方面的领先地位。","在未来发展方向上,大连宇科创新科技有限公司将继续坚持以自主研发和自主品牌为发展核心,不断推动技术创新,增强企业核心竞争力。公司与中科院大连化学物理研究所、大连海事大学等高校建立合作关系,共同推进企业与高校的全面技术术合作,形成专业、产业相互促进,共同发展的局面。","在市场前景方面,大连宇科创新科技有限公司已经与中国科学院、清华大学、国家电投集团等知名机构建立了合作关系,市场反馈良好。公司在行业机构测评中取得了多个荣誉,技术水平已达到国内领先水平。随着氢能装备产业的快速发展,公司有望在未来取得更大的市场份额,成为行业的领头羊。","综上所述,大连宇科创新科技有限公司在氢能测试装备领域具有较强的技术创新性和市场竞争力,未来发展潜力巨大。建议公司继续加大研发投入,拓展合作伙伴关系,不断提升产品质量和服务水平,以应对市场竞争,实现更好的发展。 ","综上所述,大连宇科创新科技有限公司在氢能测试装备领域取得了令人瞩目的成就,不仅在技术创新方面具有国内领先地位,还在服务质量和市场影响力上展现出强大实力。其通过不断提升研发水准和加强核心竞争力,为燃料电池领域的科技发展做出了积极贡献。","展望未来,大连宇科创新科技有限公司将继续坚持自主研发和品牌建设,不断拓展业务领域,加大创新力度,助推我国氢能装备产业的快速发展。公司的发展潜力和价值不可估量,对氢能技术的推动和应用具有重要意义。","因此,鼓励广大读者关注和支持氢能技术的发展,共同见证大连宇科创新科技有限公司在未来的辉煌成就,为构建清洁能源时代贡献自己的力量。让我们携手并肩,共同开创氢能技术的美好未来! "]).subscribe((r=>{a+=r,t[n]||(t[n]={type:"markdown",content:""}),t[n].content=a,r?.indexOf("因此,鼓励")>-1&&o&&o(e),i?.detectChanges()}))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DraftService,deps:[{token:PersonService}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DraftService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DraftService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:PersonService}]}),addIcons({hardwareChipOutline:hardwareChipOutline,receiptOutline:receiptOutline,chevronForward:chevronForward});class FmArticleDraftComponent{constructor(e,t){this.draftServ=e,this.cdRef=t,this.isSelectMode=!1,this.onDraftConfirm=new EventEmitter,this.currentHTML="",this.ArticleDraft=Parse__default.Object.extend("ArticleDraft"),this.isCreating=!1,this.isCreatingMap={},this.isCompleteMap={},this.create$Map={},this.contentArray=[]}getAcc(){console.log(this.expandComp)}ngOnInit(){for(let e=0;e<20;e++)this.isCompleteMap[e]=!0;this.expandComp?.openAll(),this.article?.id&&this.draftServ?.loadArticleDraft(this.article)}confirmDraft(){let e=new MarkdownParse,t=this.contentArray?.map((t=>(t.type="richtext",t.content=e.parseToHTML(t.content),t)));this.onDraftConfirm.emit(t)}previewDraft(e){this.currentDraft=void 0,setTimeout((()=>{this.currentDraft=e,this.contentArray=e?.get("contentArray")}),100)}async createNewDraft(e,t,n,o,i){this.isCompleteMap={},this.expandComp?.closeAll();let a=new this.ArticleDraft;a.set({type:"ai",title:e?.title||this.article?.get("title"),desc:e?.desc||this.article?.get("desc"),keywords:e?.keywords||this.article?.get("keywords"),article:this.article?.toPointer(),docList:o,content:"",outlineJson:e,contentArray:[],author:Parse__default.User.current()?.toPointer()}),this.article&&(this.draftServ.DraftListMap[this.article.id]||(this.draftServ.DraftListMap[this.article.id]=[]),this.draftServ.DraftListMap[this.article.id].unshift(a)),this.currentDraft=a,this.createAllSections(i,t,n)}async createAllSections(e,t,n){let o=this;if(this.isCreating=!0,this.currentDraft){let i=this.currentDraft?.get("outlineJson")?.sections||[];for(let a=0;a<i.length;a++){this.isCreatingMap[a]=!0;let i="逐个";"逐个"==i&&await new Promise((async i=>{this.create$Map[a]=await(this.draftServ?.newSectionCreate({person:n,writingOptions:t,contentArray:this.contentArray,outlineJson:this.currentDraft?.get("outlineJson"),draft:this.currentDraft,sectionIndex:a,documentList:e,afterComplete:e=>{o.stopCreating(a),i(!0)},cdRef:this.cdRef}))})),"并发"==i&&(this.create$Map[a]=await(this.draftServ?.newSectionCreate({person:n,writingOptions:t,contentArray:this.contentArray,outlineJson:this.currentDraft?.get("outlineJson"),draft:this.currentDraft,sectionIndex:a,documentList:e,afterComplete:e=>{o.stopCreating(a)},cdRef:this.cdRef})))}}}stopCreatingAll(){Object.values(this.isCreatingMap).forEach((e=>{try{e&&e?.unsubscribe()}catch(e){}}))}stopCreating(e){this.isCreatingMap[e]=!1,this.isCompleteMap[e]=!0,0==Object.values(this.isCreatingMap)?.filter((e=>1==e))?.length&&(this.isCreating=!1,this.contentArray?.length>0&&(this.currentDraft?.set("contentArray",this.contentArray),this.currentDraft?.save())),this.checkAllComplete(e)}checkAllComplete(e){let t=this.contentArray?.length,n=e+1;this.expandComp?.closeAll(),this.expandComp?._keyManager?._items?._results?.[n]?.panel?.open();for(let e=0;e<t;e++){if(!this.isCompleteMap[e])return!1}return!0}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmArticleDraftComponent,deps:[{token:DraftService},{token:i0.ChangeDetectorRef}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:FmArticleDraftComponent,isStandalone:!0,selector:"fm-article-draft",inputs:{article:"article"},outputs:{onDraftConfirm:"onDraftConfirm"},viewQueries:[{propertyName:"expandComp",first:!0,predicate:MatAccordion,descendants:!0}],ngImport:i0,template:'\n\n\n<nz-layout style="height:100%;">\n <nz-sider [nzWidth]="isSelectMode?290:350">\n\n <div class="list">\n \x3c!-- 添加草稿 --\x3e\n \x3c!-- <button mat-flat-button color="primary" *ngIf="!isSelectMode">\n <span nz-icon nzType="plus" nzTheme="outline"></span> 新的草稿\n </button> --\x3e\n \x3c!-- 草稿卡片 --\x3e\n \n <ion-list [inset]="true">\n\n <ion-item [button]="true">\n <ion-icon color="tertiary" slot="start" name="hardware-chip-outline" size="large"></ion-icon>\n <ion-label>AI创作稿件</ion-label>\n <ion-note slot="end">{{draftServ.DraftCountMap?.[article?.id||\'\']?.aiCount}}</ion-note>\n </ion-item>\n\n <ion-item [button]="true">\n <ion-icon color="warning" slot="start" name="receipt-outline" size="large"></ion-icon>\n <ion-label>历 史 稿 件</ion-label>\n <ion-note slot="end">{{draftServ.DraftCountMap?.[article?.id||\'\']?.draftCount}}</ion-note>\n </ion-item>\n </ion-list>\n\n <ion-list [inset]="true" *ngIf="article?.id">\n\n \x3c!-- 草稿文章卡片 --\x3e\n <ng-container *ngFor="let draft of (draftServ.DraftListMap?.[article?.id||\'\']||[])">\n <ion-item (click)="previewDraft(draft)" [button]="true" detail="false">\n <div class="unread-indicator-wrapper" slot="start">\n <div class="unread-indicator"></div>\n </div>\n <ion-label>\n \x3c!-- 标题 --\x3e\n <strong>{{draft?.get("title")}}</strong>\n \x3c!-- <ion-text>Never Gonna Give You Up</ion-text> --\x3e\n \x3c!-- 关键字 --\x3e\n <br />\n <ion-note color="medium" class="ion-text-wrap">\n <span *ngFor="let key of draft?.get(\'keywords\')" style="margin-right:3px;">{{key}}</span>\n </ion-note>\n \x3c!-- 所用模型 --\x3e\n <ng-container *ngIf="draft?.get(\'model\')">\n <br />\n <ion-note color="medium">#{{draft?.get(\'model\')}} <span>约{{draft?.get("contentArray") | outlineCount}}字</span></ion-note>\n </ng-container>\n \x3c!-- 生成时间 --\x3e\n <br />\n <ion-note color="medium" *ngIf="draft?.id">{{draft.updatedAt | utilnow}}</ion-note>\n <ion-note color="medium" *ngIf="!draft?.id">--</ion-note>\n </ion-label>\n <div class="metadata-end-wrapper" slot="end">\n <ion-icon color="medium" name="chevron-forward"></ion-icon>\n </div>\n </ion-item>\n\n <button (click)="stopCreatingAll()" *ngIf="!draft?.id&&isCreating&&create$" mat-flat-button color="warn">\n <span nz-icon [nzType]="\'sync\'" [nzSpin]="true"></span>\n 停止生成\n </button>\n </ng-container>\n\n </ion-list>\n\n </div>\n\n </nz-sider>\n\n \x3c!-- PC端:草稿显示区域 --\x3e\n <nz-layout class="draft-area" [class.is-hidden]="!currentDraft">\n <nz-content style="height:100%;">\n \x3c!-- <fm-story-loader *ngIf="currentStory?.story" [isSelectMode]="isSelectMode" [story]="currentStory"></fm-story-loader> --\x3e\n <div class="preview" *ngIf="currentDraft">\n <div class="title">\n <div class="text">\n <span style="font-weight: bold;" (click)="getAcc()">{{currentDraft?.get(\'title\')}}@if(currentDraft?.get(\'contentArray\')?.length){ 约{{currentDraft?.get("contentArray") | outlineCount}}字}</span>\n \x3c!-- <span style="font-size:16px;" *ngIf="currentDraft?.get(\'contentArray\')?.length">约{{currentDraft?.get("contentArray") | outlineCount}}字</span> --\x3e\n </div>\n <button mat-raised-button (click)="currentDraft=undefined">取消</button>\n <button mat-raised-button color="primary" (click)="confirmDraft()">选择</button>\n </div>\n\n <div class="section-area">\n\n <mat-accordion #expandComp class="example-headers-align" multi>\n\n <ng-container *ngFor="let section of (currentDraft?.get(\'outlineJson\')?.sections || []);let index=index">\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title style="min-width: 120px;text-overflow: ellipsis;overflow: hidden;white-space: nowrap;">\n {{index}}.{{section?.title}}\n </mat-panel-title>\n <mat-panel-description>\n @if(isCompleteMap[index]){\n <span style="min-width: 50px;">已完成</span>\n }@else{\n <span style="min-width: 50px;">生成中</span>\n }\n <mat-progress-bar [mode]="isCompleteMap[index]?\'determinate\':\'indeterminate\'" value="100"></mat-progress-bar>\n \x3c!-- <mat-icon>account_circle</mat-icon> --\x3e\n </mat-panel-description>\n </mat-expansion-panel-header>\n \n <div class="row section-tips" *ngIf="section?.outline">\n \x3c!-- <div class="name"></div> --\x3e\n <div class="content"><span style="font-weight: bold;">主要内容: </span>{{section?.outline}}</div>\n </div>\n <div class="row section-tips" *ngIf="section?.skill">\n \x3c!-- <div class="name"></div> --\x3e\n <div class="content"><span style="font-weight: bold;">写作技巧: </span>{{section?.skill}}</div>\n </div>\n <div class="row section-tips" *ngIf="section?.case">\n \x3c!-- <div class="name"></div> --\x3e\n <div class="content"><span style="font-weight: bold;">重点事例: </span>{{section?.case}}</div>\n </div>\n\n \x3c!-- 生成中/已生成 --\x3e\n <fm-markdown-preview class="content" *ngIf="isCreatingMap[index]&&contentArray?.[index]" [content]="contentArray?.[index]?.content" [render]="false"></fm-markdown-preview>\n <fm-markdown-preview class="content" *ngIf="!isCreatingMap[index]&&contentArray?.[index]" [content]="contentArray?.[index]?.content"></fm-markdown-preview>\n </mat-expansion-panel>\n \x3c!-- <div class="section" *ngFor="let section of (currentDraft?.get(\'outlineJson\')?.sections || []);let index=index"> --\x3e\n\n \x3c!-- <div class="outline">\n <div class="row divide section-title" *ngIf="section?.title">\n <span>章{{index+1}}.</span>\n <input nz-input type="text" [(ngModel)]="section.title" placeholder="请填章节标题" nzBorderless />\n </div>\n <div class="row" *ngIf="section?.outline">\n <span>内容</span>\n <textarea nzAutosize nz-input type="text" [(ngModel)]="section.outline" placeholder="请填主要内容" nzBorderless></textarea>\n </div>\n <div class="row" *ngIf="section?.skill">\n <span>技巧</span>\n <textarea nzAutosize nz-input type="text" [(ngModel)]="section.skill" placeholder="请填写作技巧" nzBorderless></textarea>\n </div>\n <div class="row" *ngIf="section?.case">\n <span>事例</span>\n <textarea nzAutosize nz-input type="text" [(ngModel)]="section.case" placeholder="请填重点事例" nzBorderless></textarea>\n </div>\n </div> --\x3e\n\n \x3c!-- <div class="content" [innerHTML]="currentDraft.get(\'content\') | nzSanitizer: \'html\'"></div> --\x3e\n \x3c!-- </div> --\x3e\n </ng-container>\n\n </mat-accordion>\n\n </div>\n </div>\n </nz-content>\n </nz-layout>\n</nz-layout>\n\n\n\n\n',styles:["@media (max-width: 1024px){:host{--mat-expansion-container-background-color:#ded9c4}.draft-area{position:fixed;height:90vh;width:90vw!important;display:flex;top:5vh;left:5vw;z-index:100}.is-hidden{display:none}nz-sider{padding:0}nz-sider,.list,nz-layout{background:var(--dark-page-background)!important}.title{height:auto!important}.title .text{flex-direction:column;align-items:flex-start}.title .text span{font-size:14px!important}}.section-tips{border-left:solid 2px rgba(0,0,0,.5);padding-left:7px}mat-card-header{flex-direction:column}nz-sider{background:var(--background-gray)}nz-sider mat-button-toggle-group{display:flex;width:100%}nz-sider mat-button-toggle-group mat-button-toggle{flex:50%}nz-sider .list{overflow-y:auto;background:#fff;border-radius:5px;height:100%;padding:7px}nz-sider .list button{width:100%;margin-bottom:5px}.preview{width:100%;height:100%;padding:5px;display:flex;flex-direction:column}.preview .title{display:flex;justify-content:space-between;align-items:center;width:100%;height:48px;font-size:24px;font-weight:700}.preview .title .text{display:flex;justify-content:center}.preview .section-area{width:100%;flex:1;overflow-y:auto;display:flex;flex-wrap:wrap}.preview .section-area .row{width:100%;display:flex}.preview .section-area .row .title{width:50px}.preview .section-area .row .content{flex:1}.preview .section-area .section{width:100%;display:flex;flex-direction:row}.preview .section-area .section .content{flex:1;overflow-y:auto;min-height:20px}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"ngmodule",type:IonicModule},{kind:"component",type:i3.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:i3.IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:i3.IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:i3.IonNote,selector:"ion-note",inputs:["color","mode"]},{kind:"ngmodule",type:NzLayoutModule},{kind:"component",type:i4$5.NzLayoutComponent,selector:"nz-layout",exportAs:["nzLayout"]},{kind:"component",type:i4$5.NzContentComponent,selector:"nz-content",exportAs:["nzContent"]},{kind:"component",type:i4$5.NzSiderComponent,selector:"nz-sider",inputs:["nzWidth","nzTheme","nzCollapsedWidth","nzBreakpoint","nzZeroTrigger","nzTrigger","nzReverseArrow","nzCollapsible","nzCollapsed"],outputs:["nzCollapsedChange"],exportAs:["nzSider"]},{kind:"ngmodule",type:NzPipesModule},{kind:"ngmodule",type:NzIconModule},{kind:"directive",type:i6$1.NzIconDirective,selector:"[nz-icon]",inputs:["nzSpin","nzRotate","nzType","nzTheme","nzTwotoneColor","nzIconfont"],exportAs:["nzIcon"]},{kind:"ngmodule",type:NzInputModule},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"ngmodule",type:MatExpansionModule},{kind:"directive",type:i7$2.MatAccordion,selector:"mat-accordion",inputs:["hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:i7$2.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["hideToggle","togglePosition"],outputs:["afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:i7$2.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["expandedHeight","collapsedHeight","tabIndex"]},{kind:"directive",type:i7$2.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:i7$2.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"ngmodule",type:MatIconModule},{kind:"ngmodule",type:MatProgressBarModule},{kind:"component",type:i5$1.MatProgressBar,selector:"mat-progress-bar",inputs:["color","value","bufferValue","mode"],outputs:["animationEnd"],exportAs:["matProgressBar"]},{kind:"pipe",type:UtilnowPipe,name:"utilnow"},{kind:"ngmodule",type:MarkdownPreviewModule},{kind:"component",type:MarkdownPreviewComponent,selector:"fm-markdown-preview",inputs:["content","render"]},{kind:"pipe",type:OutlineCountPipe,name:"outlineCount"}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmArticleDraftComponent,decorators:[{type:Component,args:[{selector:"fm-article-draft",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,IonicModule,NzLayoutModule,NzPipesModule,NzIconModule,NzInputModule,MatButtonModule,MatExpansionModule,MatIconModule,MatProgressBarModule,UtilnowPipe,MarkdownPreviewModule,OutlineCountPipe,FmArticleOutlineLeftitemComponent],template:'\n\n\n<nz-layout style="height:100%;">\n <nz-sider [nzWidth]="isSelectMode?290:350">\n\n <div class="list">\n \x3c!-- 添加草稿 --\x3e\n \x3c!-- <button mat-flat-button color="primary" *ngIf="!isSelectMode">\n <span nz-icon nzType="plus" nzTheme="outline"></span> 新的草稿\n </button> --\x3e\n \x3c!-- 草稿卡片 --\x3e\n \n <ion-list [inset]="true">\n\n <ion-item [button]="true">\n <ion-icon color="tertiary" slot="start" name="hardware-chip-outline" size="large"></ion-icon>\n <ion-label>AI创作稿件</ion-label>\n <ion-note slot="end">{{draftServ.DraftCountMap?.[article?.id||\'\']?.aiCount}}</ion-note>\n </ion-item>\n\n <ion-item [button]="true">\n <ion-icon color="warning" slot="start" name="receipt-outline" size="large"></ion-icon>\n <ion-label>历 史 稿 件</ion-label>\n <ion-note slot="end">{{draftServ.DraftCountMap?.[article?.id||\'\']?.draftCount}}</ion-note>\n </ion-item>\n </ion-list>\n\n <ion-list [inset]="true" *ngIf="article?.id">\n\n \x3c!-- 草稿文章卡片 --\x3e\n <ng-container *ngFor="let draft of (draftServ.DraftListMap?.[article?.id||\'\']||[])">\n <ion-item (click)="previewDraft(draft)" [button]="true" detail="false">\n <div class="unread-indicator-wrapper" slot="start">\n <div class="unread-indicator"></div>\n </div>\n <ion-label>\n \x3c!-- 标题 --\x3e\n <strong>{{draft?.get("title")}}</strong>\n \x3c!-- <ion-text>Never Gonna Give You Up</ion-text> --\x3e\n \x3c!-- 关键字 --\x3e\n <br />\n <ion-note color="medium" class="ion-text-wrap">\n <span *ngFor="let key of draft?.get(\'keywords\')" style="margin-right:3px;">{{key}}</span>\n </ion-note>\n \x3c!-- 所用模型 --\x3e\n <ng-container *ngIf="draft?.get(\'model\')">\n <br />\n <ion-note color="medium">#{{draft?.get(\'model\')}} <span>约{{draft?.get("contentArray") | outlineCount}}字</span></ion-note>\n </ng-container>\n \x3c!-- 生成时间 --\x3e\n <br />\n <ion-note color="medium" *ngIf="draft?.id">{{draft.updatedAt | utilnow}}</ion-note>\n <ion-note color="medium" *ngIf="!draft?.id">--</ion-note>\n </ion-label>\n <div class="metadata-end-wrapper" slot="end">\n <ion-icon color="medium" name="chevron-forward"></ion-icon>\n </div>\n </ion-item>\n\n <button (click)="stopCreatingAll()" *ngIf="!draft?.id&&isCreating&&create$" mat-flat-button color="warn">\n <span nz-icon [nzType]="\'sync\'" [nzSpin]="true"></span>\n 停止生成\n </button>\n </ng-container>\n\n </ion-list>\n\n </div>\n\n </nz-sider>\n\n \x3c!-- PC端:草稿显示区域 --\x3e\n <nz-layout class="draft-area" [class.is-hidden]="!currentDraft">\n <nz-content style="height:100%;">\n \x3c!-- <fm-story-loader *ngIf="currentStory?.story" [isSelectMode]="isSelectMode" [story]="currentStory"></fm-story-loader> --\x3e\n <div class="preview" *ngIf="currentDraft">\n <div class="title">\n <div class="text">\n <span style="font-weight: bold;" (click)="getAcc()">{{currentDraft?.get(\'title\')}}@if(currentDraft?.get(\'contentArray\')?.length){ 约{{currentDraft?.get("contentArray") | outlineCount}}字}</span>\n \x3c!-- <span style="font-size:16px;" *ngIf="currentDraft?.get(\'contentArray\')?.length">约{{currentDraft?.get("contentArray") | outlineCount}}字</span> --\x3e\n </div>\n <button mat-raised-button (click)="currentDraft=undefined">取消</button>\n <button mat-raised-button color="primary" (click)="confirmDraft()">选择</button>\n </div>\n\n <div class="section-area">\n\n <mat-accordion #expandComp class="example-headers-align" multi>\n\n <ng-container *ngFor="let section of (currentDraft?.get(\'outlineJson\')?.sections || []);let index=index">\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title style="min-width: 120px;text-overflow: ellipsis;overflow: hidden;white-space: nowrap;">\n {{index}}.{{section?.title}}\n </mat-panel-title>\n <mat-panel-description>\n @if(isCompleteMap[index]){\n <span style="min-width: 50px;">已完成</span>\n }@else{\n <span style="min-width: 50px;">生成中</span>\n }\n <mat-progress-bar [mode]="isCompleteMap[index]?\'determinate\':\'indeterminate\'" value="100"></mat-progress-bar>\n \x3c!-- <mat-icon>account_circle</mat-icon> --\x3e\n </mat-panel-description>\n </mat-expansion-panel-header>\n \n <div class="row section-tips" *ngIf="section?.outline">\n \x3c!-- <div class="name"></div> --\x3e\n <div class="content"><span style="font-weight: bold;">主要内容: </span>{{section?.outline}}</div>\n </div>\n <div class="row section-tips" *ngIf="section?.skill">\n \x3c!-- <div class="name"></div> --\x3e\n <div class="content"><span style="font-weight: bold;">写作技巧: </span>{{section?.skill}}</div>\n </div>\n <div class="row section-tips" *ngIf="section?.case">\n \x3c!-- <div class="name"></div> --\x3e\n <div class="content"><span style="font-weight: bold;">重点事例: </span>{{section?.case}}</div>\n </div>\n\n \x3c!-- 生成中/已生成 --\x3e\n <fm-markdown-preview class="content" *ngIf="isCreatingMap[index]&&contentArray?.[index]" [content]="contentArray?.[index]?.content" [render]="false"></fm-markdown-preview>\n <fm-markdown-preview class="content" *ngIf="!isCreatingMap[index]&&contentArray?.[index]" [content]="contentArray?.[index]?.content"></fm-markdown-preview>\n </mat-expansion-panel>\n \x3c!-- <div class="section" *ngFor="let section of (currentDraft?.get(\'outlineJson\')?.sections || []);let index=index"> --\x3e\n\n \x3c!-- <div class="outline">\n <div class="row divide section-title" *ngIf="section?.title">\n <span>章{{index+1}}.</span>\n <input nz-input type="text" [(ngModel)]="section.title" placeholder="请填章节标题" nzBorderless />\n </div>\n <div class="row" *ngIf="section?.outline">\n <span>内容</span>\n <textarea nzAutosize nz-input type="text" [(ngModel)]="section.outline" placeholder="请填主要内容" nzBorderless></textarea>\n </div>\n <div class="row" *ngIf="section?.skill">\n <span>技巧</span>\n <textarea nzAutosize nz-input type="text" [(ngModel)]="section.skill" placeholder="请填写作技巧" nzBorderless></textarea>\n </div>\n <div class="row" *ngIf="section?.case">\n <span>事例</span>\n <textarea nzAutosize nz-input type="text" [(ngModel)]="section.case" placeholder="请填重点事例" nzBorderless></textarea>\n </div>\n </div> --\x3e\n\n \x3c!-- <div class="content" [innerHTML]="currentDraft.get(\'content\') | nzSanitizer: \'html\'"></div> --\x3e\n \x3c!-- </div> --\x3e\n </ng-container>\n\n </mat-accordion>\n\n </div>\n </div>\n </nz-content>\n </nz-layout>\n</nz-layout>\n\n\n\n\n',styles:["@media (max-width: 1024px){:host{--mat-expansion-container-background-color:#ded9c4}.draft-area{position:fixed;height:90vh;width:90vw!important;display:flex;top:5vh;left:5vw;z-index:100}.is-hidden{display:none}nz-sider{padding:0}nz-sider,.list,nz-layout{background:var(--dark-page-background)!important}.title{height:auto!important}.title .text{flex-direction:column;align-items:flex-start}.title .text span{font-size:14px!important}}.section-tips{border-left:solid 2px rgba(0,0,0,.5);padding-left:7px}mat-card-header{flex-direction:column}nz-sider{background:var(--background-gray)}nz-sider mat-button-toggle-group{display:flex;width:100%}nz-sider mat-button-toggle-group mat-button-toggle{flex:50%}nz-sider .list{overflow-y:auto;background:#fff;border-radius:5px;height:100%;padding:7px}nz-sider .list button{width:100%;margin-bottom:5px}.preview{width:100%;height:100%;padding:5px;display:flex;flex-direction:column}.preview .title{display:flex;justify-content:space-between;align-items:center;width:100%;height:48px;font-size:24px;font-weight:700}.preview .title .text{display:flex;justify-content:center}.preview .section-area{width:100%;flex:1;overflow-y:auto;display:flex;flex-wrap:wrap}.preview .section-area .row{width:100%;display:flex}.preview .section-area .row .title{width:50px}.preview .section-area .row .content{flex:1}.preview .section-area .section{width:100%;display:flex;flex-direction:row}.preview .section-area .section .content{flex:1;overflow-y:auto;min-height:20px}\n"]}]}],ctorParameters:()=>[{type:DraftService},{type:i0.ChangeDetectorRef}],propDecorators:{expandComp:[{type:ViewChild,args:[MatAccordion]}],article:[{type:Input}],onDraftConfirm:[{type:Output}]}});class DialogArticleDraft{constructor(e,t){this.dialogRef=e,this.data=t,this.isSelectMode=!0,this.selectCount=0,this.writingOptions={},this.createNewDraft=!1,this.article=t?.article,this.person=t?.person,this.book=t?.book,this.outlineJson=t?.outlineJson,this.documentList=t?.documentList,this.docList=t?.docList,this.writingOptions=t?.writingOptions,this.createNewDraft=t?.createNewDraft||!1}ngOnInit(){this.createNewDraft&&setTimeout((()=>{this.draftComp&&(this.draftComp.article=this.article,this.draftComp?.createNewDraft(this.outlineJson,this.writingOptions,this.person,this.docList,this.documentList))}),200)}onConfirm(){this.dialogRef.close({draft:this.draftComp?.currentDraft,contentArray:this.draftComp?.contentArray})}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DialogArticleDraft,deps:[{token:i3$1.MatDialogRef},{token:MAT_DIALOG_DATA}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:DialogArticleDraft,isStandalone:!0,selector:"article-draft-dialog",viewQueries:[{propertyName:"draftComp",first:!0,predicate:FmArticleDraftComponent,descendants:!0}],ngImport:i0,template:'\n <fm-article-draft [article]="article" (onDraftConfirm)="onConfirm()"></fm-article-draft>\n <mat-dialog-actions align="start">\n <button mat-button color="primary" [mat-dialog-close]="true">取消</button>\n <button mat-raised-button color="primary" [mat-dialog-close]="true" cdkFocusInitial>完成</button>\n </mat-dialog-actions>\n ',isInline:!0,styles:["fm-article-draft{height:calc(100% - 60px);width:100%}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"ngmodule",type:MatDialogModule},{kind:"directive",type:i3$1.MatDialogClose,selector:"[mat-dialog-close], [matDialogClose]",inputs:["aria-label","type","mat-dialog-close","matDialogClose"],exportAs:["matDialogClose"]},{kind:"directive",type:i3$1.MatDialogActions,selector:"[mat-dialog-actions], mat-dialog-actions, [matDialogActions]",inputs:["align"]},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"component",type:FmArticleDraftComponent,selector:"fm-article-draft",inputs:["article"],outputs:["onDraftConfirm"]}]})}}function TaskArticleDraft(e){let t=new AgentTaskStep({title:"整篇文章草稿创作",shareData:e?.shareData});return t.handle=()=>new Promise((async(n,o)=>{let i=e?.dialog.open(DialogArticleDraft,{data:{article:e?.shareData?.article,person:e?.person,book:e?.book,createNewDraft:e?.shareData?.createNewDraft,outlineJson:e?.shareData?.articleOutline||e?.shareData?.article?.get("outlineJson"),writingOptions:e?.shareData?.writingOptions||e?.shareData?.article?.get("writingOptions"),docList:e?.shareData?.docList||e?.shareData?.article?.get("docList")||e?.shareData?.documentList?.map((e=>e.toPointer())),documentList:e?.shareData?.documentList},height:"90vh",maxHeight:"90vh",width:"90vw",maxWidth:"90vw"});i?.afterClosed().subscribe((async o=>{if(o){let i=localStorage.getItem("company");i&&(e?.shareData?.article?.set("company",{__type:"Pointer",className:"Company",objectId:i}),await(e?.shareData?.article?.save())),o?.html&&(e?.shareData?.article?.set("content",o?.html),await(e?.shareData?.article?.save())),o?.contentArray&&(e?.shareData?.article?.set("contentArray",o?.contentArray),await(e?.shareData?.article?.save())),t.logList.push("已确认写作大纲"),t.error="",t.progress=1,n(!0)}else t.error="未保存大纲,请重试",t.restartButtonShow=!0,n(!1)}))})),t}async function taskArticleGeneration(e,t){if(t?.shareData&&(t.shareData.createNewDraft=!0,t?.dialog)){if(!t?.person&&(t.person=await openPersonSelectModal(t?.modalCtrl),!t?.person))return;doArticleTask([TaskDocumentSelect({person:t?.book?.get("person"),book:t?.book,shareData:t.shareData,dialog:t?.dialog}),TaskArticleWritingOptions({shareData:t.shareData,dialog:t?.dialog}),TaskArticleOutline({person:t?.book?.get("person"),book:t?.book,shareData:t.shareData,dialog:t?.dialog,personServ:t?.personServ}),TaskArticleOutlineEdit({person:t?.book?.get("person"),book:t?.book,shareData:t.shareData,dialog:t?.dialog}),TaskArticleDraft({person:t?.person,isSelectedMode:!0,shareData:t.shareData,dialog:t?.dialog,modalCtrl:t?.modalCtrl})],t,(()=>{}))}}function doArticleTask(e,t,n){if(!t)return;console.log(t.shareData),t.shareData.article=t?.article||t.shareData.article,t.person?.id&&t.shareData?.article.set("person",t.person?.toPointer());let o=t?.article?.get("writingOptions");o&&(t.shareData.writingOptions=o);let i=e,a=t?.dialog.open(FmAgentTaskComponent,{data:{shareData:t?.shareData,stepsList:i},disableClose:!0});a.afterClosed().subscribe((e=>{t?.shareData?.article?.get("outlineJson")||e||(t?.shareData?.article?.set("isDeleted",!0),t?.shareData?.article?.destroy()),n&&n()}))}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DialogArticleDraft,decorators:[{type:Component,args:[{selector:"article-draft-dialog",template:'\n <fm-article-draft [article]="article" (onDraftConfirm)="onConfirm()"></fm-article-draft>\n <mat-dialog-actions align="start">\n <button mat-button color="primary" [mat-dialog-close]="true">取消</button>\n <button mat-raised-button color="primary" [mat-dialog-close]="true" cdkFocusInitial>完成</button>\n </mat-dialog-actions>\n ',standalone:!0,imports:[CommonModule,MatDialogModule,MatButtonModule,FmArticleDraftComponent],styles:["fm-article-draft{height:calc(100% - 60px);width:100%}\n"]}]}],ctorParameters:()=>[{type:i3$1.MatDialogRef},{type:void 0,decorators:[{type:Inject,args:[MAT_DIALOG_DATA]}]}],propDecorators:{draftComp:[{type:ViewChild,args:[FmArticleDraftComponent]}]}});class ArticleService{constructor(e,t,n,o,i,a){this.router=e,this.wxjssdk=t,this.clipboard=n,this.dialog=o,this.modalCtrl=i,this.personServ=a,this.Article=Parse__default.Object.extend("Article"),this.articleList=[],this.limit=20,this.skip=0,this.likeMap={},this.ArticleLike=Parse__default.Object.extend("ArticleLike"),this.collectMap={}}async loadArticle(e){if(e.currentTab=e.currentTab||"article",e.isNew=e.isNew||!1,!Parse__default.User.current()?.id)return[];e?.isNew?(this.articleList=[],this.skip=0):this.skip+=this.articleList?.length;let t=new Parse__default.Query("Article");t.include("chapter.book.person","author.user"),t.addDescending("createdAt"),t.skip(this.skip),t.notEqualTo("isDeleted",!0),"mine"==e?.currentTab?t.equalTo("author",Parse__default.User?.current()?.id):t.equalTo("isPublic",!0);let n=await t.find();return this.loadArtcleAnalysis(n),this.articleList?.length?this.articleList=this.articleList.concat(n):this.articleList=n,this.articleList}async createArticle(e){let t=new this.Article;t.set("title",this.newTitle());let n=localStorage.getItem("company");return n&&t?.set("company",{__type:"Pointer",className:"Company",objectId:n}),t?.get("author")?.id||t?.set("author",Parse__default.User.current()?.toPointer()),t=await(t?.save()),e?.noRedirect||this.router.navigate(["editor","article",t?.id]),t}async newArticleByStory(){let e={createNewDraft:!0},t=await this.createArticle({noRedirect:!0});taskArticleGeneration((()=>{}),{dialog:this.dialog,modalCtrl:this.modalCtrl,shareData:e,article:t,personServ:this.personServ})}newTitle(){let e=new Date;return`${e.getFullYear()}-${e.getMonth()+1}-${e.getDate()}-新创作`}async shareArticle(e){if(!e?.id)return;this.getArticleBanner(e);let t="https://www.yuban.co/app/article/"+e?.id+"?invite="+Parse__default.User.current()?.id;if(this.wxjssdk.isWechat)this.initWxShareInfo(e);else{let n=`${e?.get("title")} ${t} POWERED BY 自传语伴`;this.clipboard.copyToClipboard(n)}}initWxShareInfo(e){let t=this.getArticleBanner(e),n=Parse__default.User.current()?.get("avatar"),o="https://www.yuban.co/app/article/"+e?.id+"?invite="+Parse__default.User.current()?.id;if(this.wxjssdk.isWechat){let i={title:e?.get("title"),desc:e?.get("desc"),link:o,type:"link",imgUrl:t[0]||n||"https://file.yuban.co/img/icon.png",success:()=>{console.log("分享成功")},error:()=>{console.log("分享失败")},cancel:()=>{console.log("取消分享")}};this.wxjssdk.setCurrentPageShareInfo(i)}}getArticleBanner(e){let t=[],n=e?.get("image");return n&&t.push(n),t=t.concat(e?.get("cover")||[]),console.log("bannerList",t),t}async loadArtcleAnalysis(e){let t=Parse__default.User.current()?.id;if(!t)return;let n=new Parse__default.Query("ArticleLike");n.select("article","type"),n.equalTo("user",t),n.notEqualTo("isDeleted",!0),n.containedIn("article",e?.map((e=>e?.id))),(await n.find()).forEach((e=>{let t=e?.get("article")?.id||e?.get("article")?.objectId;"collect"==e?.get("type")&&(this.collectMap[t]=!0),"like"==e?.get("type")&&(this.likeMap[t]=!0)}))}viewArticle(e){e?.id&&(e.increment("viewCount"),e.save())}async likeArticle(e,t="like"){if(e?.id&&Parse__default.User.current()?.id){let n=new Parse__default.Query("ArticleLike");n.equalTo("user",Parse__default.User.current()),n.equalTo("type",t),n.equalTo("article",e?.id);let o=await n.first();o?.id||(o=new this.ArticleLike),o?.set("type",t),o?.set("user",Parse__default.User.current()),o?.set("article",e.toPointer()),null==o?.get("isDeleted")?o?.set("isDeleted",!1):o?.set("isDeleted",!o.get("isDeleted")),localStorage.getItem("company")&&o?.set("company",{__type:"Pointer",className:"Company",objectId:localStorage.getItem("company")}),o=await(o?.save()),"like"==t&&(this.likeMap[e?.id]=!o?.get("isDeleted")),"collect"==t&&(this.collectMap[e?.id]=!o?.get("isDeleted"));let i=new Parse__default.Query("ArticleLike");i.notEqualTo("isDeleted",!0),i.equalTo("type",t),i.equalTo("article",e?.id),"like"==t&&e.set("likeCount",await i.count()||0),"collect"==t&&e.set("collectCount",await i.count()||0),e=await e.save()}}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ArticleService,deps:[{token:i1$1.Router},{token:WechatJssdkService},{token:ClipboardService},{token:i3$1.MatDialog},{token:i1$3.ModalController},{token:PersonService}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ArticleService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ArticleService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1$1.Router},{type:WechatJssdkService},{type:ClipboardService},{type:i3$1.MatDialog},{type:i1$3.ModalController},{type:PersonService}]});class FmArticleAitoolComponent{async clickTab(e){this.clicktab=e}async dashboardTab(e){this.dashboardtab=e}close(){this.modalCtrl.dismiss()}constructor(e,t,n,o,i,a,r){this.alertCtrl=e,this.modalCtrl=t,this.dialog=n,this.nupload=o,this.cdRef=i,this.clipboard=a,this.personServ=r,this.aitab="AI写作",this.clicktab="语法错误",this.dashboardtab="全部",this.cards=[{title:"全文创作",handle:()=>{this.taskArticleGeneration()},content:"按步骤快速创作一篇完整的文章",imageurl:"../../../assets/images/write.png"},{title:"润色改写",handle:()=>{this.linkEditor()},content:"根据选段,调整语言,逻辑顺畅表达清晰",imageurl:"../../../assets/images/句子续写.png"},{title:"智能摘要(未开放)",handle:()=>{this.linkEditor()},content:"快速生成文章摘要",imageurl:"../../../assets/images/智能摘要.png"},{title:"句子续写(未开放)",handle:()=>{this.linkEditor()},content:"根据上文,续写多个句子",imageurl:"../../../assets/images/句子续写.png"},{title:"段落评论(未开放)",handle:()=>{this.linkEditor()},content:"根据段落特点,进行有针对性的评论",imageurl:"../../../assets/images/产品评论.png"},{title:"模板建议(未开放)",handle:()=>{this.linkEditor()},content:"欢迎与我们反馈您的需求",imageurl:"../../../assets/images/模板建议.png"}],this.content="",this.contentChanged=!1,this.selectText="",this.optimizeText="",this.isOptimizing=!1,this.tempFormGroup=new FormGroup({})}ngOnInit(){}async linkEditor(){(await this.alertCtrl.create({header:"编辑文章",subHeader:"请登录PC编辑端",message:"https://www.yuban.co/editor"})).present()}async taskArticleGeneration(e){let t={createNewDraft:!0};this.modalCtrl.dismiss(),taskArticleGeneration((()=>{}),{modalCtrl:this.modalCtrl,article:this.article,shareData:t,dialog:this.dialog,personServ:this.personServ})}cancelOptimize(){this.isOptimizing=!1,this.optimize$?.unsubscribe()}optimizeContent(){if(!this.selectText)return;this.isOptimizing=!0;let e=[{role:"user",content:`有段文字要润色,目的是提高其专业性和清晰度。请您调整语言,确保逻辑流畅,并使用行业相关术语。同时,请检查并修正任何语法错误。直接返回润色后内容。这是原文:${this.selectText}`}],t=new FmodeChatCompletion(e);t.model="fmode-4.0-cn-256k",this.optimize$=t.sendCompletion().pipe(finalize((()=>{undefined.complete=!0}))).subscribe((e=>{this.optimizeText=e.content,e?.complete&&(this.isOptimizing=!1,this.optimize$?.unsubscribe(),this.cdRef.detectChanges())}))}copyOptimize(){this.clipboard.copyToClipboard(this.optimizeText)}applyOptimize(){this.selectRange&&(this.selectQuill?.deleteText(this.selectRange?.index,this.selectRange.length),this.selectQuill?.insertText(this.selectRange?.index,this.optimizeText),this.selectRange=void 0)}async presentAlert(e){const t=await this.alertCtrl.create({header:"提示",subHeader:e?.message,buttons:["好的"]});await t.present()}uploadImage(){let e=this,t=document.createElement("input");t.type="file",t.accept="image/*",t.multiple=!1,t.addEventListener("change",(async()=>{let n=t?.files?.[0];if(n){let t=await e.nupload.upload(n);t?.url&&(this.article?.set("image",t?.url),this.article?.save())}})),t.click()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmArticleAitoolComponent,deps:[{token:i1$3.AlertController},{token:i1$3.ModalController},{token:i3$1.MatDialog},{token:NovaUploadService},{token:i0.ChangeDetectorRef},{token:ClipboardService},{token:PersonService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmArticleAitoolComponent,isStandalone:!0,selector:"app-fm-article-aitool",inputs:{article:"article"},ngImport:i0,template:'<ion-content>\n\n <div class="header">\n <ion-segment [(ngModel)]="aitab" [disabled]="true" (click)="linkEditor()">\n <ion-segment-button value="AI写作">\n <ion-label>AI写作</ion-label>\n </ion-segment-button>\n <ion-segment-button value="AI润色">\n <ion-label>AI润色</ion-label>\n </ion-segment-button>\n <ion-segment-button value="AI校阅">\n <ion-label>AI校阅</ion-label>\n </ion-segment-button>\n <ion-segment-button value="AI配图">\n <ion-label>AI配图</ion-label>\n </ion-segment-button>\n </ion-segment>\n <ion-icon name="close-outline" (click)="$event.stopPropagation();close()"></ion-icon>\n </div>\n\n \x3c!-- 工具面板 --\x3e\n <div class="ai-panel">\n\n <div *ngIf="aitab==\'AI写作\'" class="ai-write">\n \x3c!-- 搜索 --\x3e\n <div class="search-bar">\n <ion-searchbar color="light" placeholder="搜索模板"></ion-searchbar>\n </div>\n\n <div class="ai-tool-grid">\n <ng-container *ngFor="let card of cards">\n <ion-card class="card" (click)="card?.handle()">\n <ion-card-header>\n <ion-card-title class="card-image">\n <img src="{{card.imageurl}}" width="25" height="25" alt="write">\n </ion-card-title>\n <ion-card-subtitle>{{card.title}}</ion-card-subtitle>\n </ion-card-header>\n\n <ion-card-content>\n {{card.content}}\n </ion-card-content>\n </ion-card>\n </ng-container>\n </div>\n\n </div>\n <div *ngIf="aitab==\'AI润色\'" class="ai-polish" [formGroup]="tempFormGroup">\n <div class="ai-polish-input">\n <mat-form-field style="width:95%;">\n <mat-label>输入或选中左侧文本开始润色</mat-label>\n <textarea matInput [(ngModel)]="selectText" [ngModelOptions]="{standalone: true}" rows="10"></textarea>\n </mat-form-field>\n\n \x3c!-- <textarea [(ngModel)]="selectText" rows="10" formControlName="comment" nz-input placeholder="输入或选中左侧文本开始润色"></textarea> --\x3e\n </div>\n <div class="ai-polish-button">\n <button *ngIf="!isOptimizing" mat-raised-button color="primary" (click)="optimizeContent()">开始润色</button>\n <button *ngIf="isOptimizing" mat-raised-button color="warn" (click)="cancelOptimize()">停止润色</button>\n \x3c!-- <ion-button id="start" [disabled]="false" (click)="enableButton()">开始润色</ion-button> --\x3e\n </div>\n <div class="ai-polish-input">\n <mat-form-field style="width:95%;">\n <mat-label>生成内容</mat-label>\n <textarea matInput [(ngModel)]="optimizeText" [ngModelOptions]="{standalone: true}" rows="10"></textarea>\n </mat-form-field>\n </div>\n <div class="ai-polish-button">\n <button *ngIf="selectRange?.length" mat-raised-button (click)="applyOptimize()"><mat-icon fontIcon="flip"></mat-icon>替换</button>\n <button mat-raised-button (click)="copyOptimize()"><mat-icon fontIcon="content_copy"></mat-icon>复制</button>\n \x3c!-- <ion-button id="start" [disabled]="false" (click)="enableButton()">开始润色</ion-button> --\x3e\n </div>\n \x3c!-- <div class="copy">\n <ion-icon name="copy-outline" style="color:#4e80f4" (click)="Copy(polishContent)"></ion-icon>\n </div> --\x3e\n </div>\n <div *ngIf="aitab==\'校阅\'" class="ai-proofread">\n\n <div class="showItems-container">\n <div class="showItems">\n\n <div class="showItem" (click)="clickTab(\'内容建议\')" [ngClass]="{ \'active1\': clicktab == \'内容建议\' }">\n <div style="line-height: 12px;">\n <svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M11 10H5M7 14H5M13 6H5M17 9.5V5.8C17 4.11984 17 3.27976 16.673 2.63803C16.3854 2.07354 15.9265 1.6146 15.362 1.32698C14.7202 1 13.8802 1 12.2 1H5.8C4.11984 1 3.27976 1 2.63803 1.32698C2.07354 1.6146 1.6146 2.07354 1.32698 2.63803C1 3.27976 1 4.11984 1 5.8V16.2C1 17.8802 1 18.7202 1.32698 19.362C1.6146 19.9265 2.07354 20.3854 2.63803 20.673C3.27976 21 4.11984 21 5.8 21H8.5M19 21L17.5 19.5M18.5 17C18.5 18.933 16.933 20.5 15 20.5C13.067 20.5 11.5 18.933 11.5 17C11.5 15.067 13.067 13.5 15 13.5C16.933 13.5 18.5 15.067 18.5 17Z"\n stroke="#1570EF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <span>内容建议</span>\n\n\n </div>\n\n <div class="showItem" (click)="clickTab(\'事实验证\')" [ngClass]="{\'active1\': clicktab==\'事实验证\'}">\n <div style="line-height: 12px;">\n <svg width="18" height="22" viewBox="0 0 18 22" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M11 1.26953V5.40007C11 5.96012 11 6.24015 11.109 6.45406C11.2049 6.64222 11.3578 6.7952 11.546 6.89108C11.7599 7.00007 12.0399 7.00007 12.6 7.00007H16.7305M6 15L8 17L12.5 12.5M11 1H5.8C4.11984 1 3.27976 1 2.63803 1.32698C2.07354 1.6146 1.6146 2.07354 1.32698 2.63803C1 3.27976 1 4.11984 1 5.8V16.2C1 17.8802 1 18.7202 1.32698 19.362C1.6146 19.9265 2.07354 20.3854 2.63803 20.673C3.27976 21 4.11984 21 5.8 21H12.2C13.8802 21 14.7202 21 15.362 20.673C15.9265 20.3854 16.3854 19.9265 16.673 19.362C17 18.7202 17 17.8802 17 16.2V7L11 1Z"\n stroke="#D92D20" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <span>事实验证</span>\n </div>\n\n <div class="showItem" (click)="clickTab(\'全文总结\')" [ngClass]="{\'active1\': clicktab==\'全文总结\'}">\n <div style="line-height: 12px;"> <svg width="20" height="22" viewBox="0 0 16 20" fill="none"\n xmlns="http://www.w3.org/2000/svg">\n <path\n d="M14.1668 5.83329V5.66663C14.1668 4.26649 14.1668 3.56643 13.8943 3.03165C13.6547 2.56124 13.2722 2.17879 12.8018 1.93911C12.267 1.66663 11.567 1.66663 10.1668 1.66663H4.8335C3.43336 1.66663 2.7333 1.66663 2.19852 1.93911C1.72811 2.17879 1.34566 2.56124 1.10598 3.03165C0.833496 3.56643 0.833496 4.26649 0.833496 5.66663V14.3333C0.833496 15.7334 0.833496 16.4335 1.10598 16.9683C1.34566 17.4387 1.72811 17.8211 2.19852 18.0608C2.7333 18.3333 3.43336 18.3333 4.8335 18.3333H7.91683M7.91683 9.16663H4.16683M7.0835 12.5H4.16683M10.8335 5.83329H4.16683M12.5002 15V10.4166C12.5002 9.72627 13.0598 9.16663 13.7502 9.16663C14.4405 9.16663 15.0002 9.72627 15.0002 10.4166V15C15.0002 16.3807 13.8809 17.5 12.5002 17.5C11.1195 17.5 10.0002 16.3807 10.0002 15V11.6666"\n stroke="#F79009" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <span>全文总结</span>\n </div>\n\n </div>\n </div>\n\n <div class="showItem-content">\n <div *ngIf="clicktab==\'语法错误\'" class="grammar-panel">\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n\n </div>\n <div *ngIf="clicktab==\'内容建议\'" class="suggest-panel">\n\n <div class="content-suggest">\n <div style="line-height: 12px;">\n <svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M11 10H5M7 14H5M13 6H5M17 9.5V5.8C17 4.11984 17 3.27976 16.673 2.63803C16.3854 2.07354 15.9265 1.6146 15.362 1.32698C14.7202 1 13.8802 1 12.2 1H5.8C4.11984 1 3.27976 1 2.63803 1.32698C2.07354 1.6146 1.6146 2.07354 1.32698 2.63803C1 3.27976 1 4.11984 1 5.8V16.2C1 17.8802 1 18.7202 1.32698 19.362C1.6146 19.9265 2.07354 20.3854 2.63803 20.673C3.27976 21 4.11984 21 5.8 21H8.5M19 21L17.5 19.5M18.5 17C18.5 18.933 16.933 20.5 15 20.5C13.067 20.5 11.5 18.933 11.5 17C11.5 15.067 13.067 13.5 15 13.5C16.933 13.5 18.5 15.067 18.5 17Z"\n stroke="#1570EF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <div class="content-suggest-title">内容建议</div>\n </div>\n\n <div class="content">\n <div class="content-title"> 这篇文章介绍的是七个关于中国企业家的管理之道的自传小说章节标题,旨在展示企业家们的个人经历、管理理念和人生哲学。\n </div>\n <div class="content-title">改进建议:</div>\n <ol>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n </ol>\n\n\n </div>\n </div>\n <div *ngIf="clicktab==\'事实验证\'" class="verify-panel">\n <div class="dashboard">\n <div class="item" (click)="dashboardTab(\'全部\')" [ngClass]="{\'itemChoose\': dashboardtab==\'全部\'}">\n <div class="icon">\n <div class="statusIcon" style="border: 1px solid black; box-sizing: border-box;"></div>\n </div>\n <div class="text">全部</div>\n <div class="number">28</div>\n </div>\n\n <div class="item" (click)="dashboardTab(\'通过\')" [ngClass]="{\'itemChoose\': dashboardtab==\'通过\'}">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n <div class="number">9</div>\n </div>\n\n <div class="item" (click)="dashboardTab(\'不通过\')" [ngClass]="{\'itemChoose\': dashboardtab==\'不通过\'}">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(217, 45, 32);"><svg\n xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">\n <path d="M7 17L17 7" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n <path d="M7 7L17 17" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </svg></div>\n </div>\n <div class="text" style="color: rgb(217, 45, 32);">不通过</div>\n <div class="number">1</div>\n </div>\n <div class="item" (click)="dashboardTab(\'无法判断\')" [ngClass]="{\'itemChoose\': dashboardtab==\'无法判断\'}">\n <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="3 3 18 18"\n fill="none">\n <path\n d="M7.8824 8.679C7.88035 8.72744 7.88822 8.77579 7.90555 8.82107C7.92287 8.86636 7.94927 8.90762 7.98313 8.94232C8.01699 8.97703 8.05759 9.00444 8.10244 9.02287C8.14728 9.0413 8.19542 9.05036 8.2439 9.0495H9.4814C9.6884 9.0495 9.8534 8.88 9.8804 8.6745C10.0154 7.6905 10.6904 6.9735 11.8934 6.9735C12.9224 6.9735 13.8644 7.488 13.8644 8.7255C13.8644 9.678 13.3034 10.116 12.4169 10.782C11.4074 11.5155 10.6079 12.372 10.6649 13.7625L10.6694 14.088C10.671 14.1864 10.7112 14.2803 10.7813 14.3493C10.8515 14.4183 10.946 14.457 11.0444 14.457H12.2609C12.3604 14.457 12.4557 14.4175 12.5261 14.3472C12.5964 14.2768 12.6359 14.1815 12.6359 14.082V13.9245C12.6359 12.8475 13.0454 12.534 14.1509 11.6955C15.0644 11.001 16.0169 10.23 16.0169 8.6115C16.0169 6.345 14.1029 5.25 12.0074 5.25C10.1069 5.25 8.0249 6.135 7.8824 8.679ZM10.2179 17.3235C10.2179 18.123 10.8554 18.714 11.7329 18.714C12.6464 18.714 13.2749 18.123 13.2749 17.3235C13.2749 16.4955 12.6449 15.9135 11.7314 15.9135C10.8554 15.9135 10.2179 16.4955 10.2179 17.3235Z"\n fill="#475467"></path>\n </svg></div>\n <div class="text">无法判断</div>\n <div class="number">18</div>\n </div>\n </div>\n\n <div class="verify-card-list">\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n </div>\n </div>\n <div *ngIf="clicktab==\'全文总结\'" class="summary-panel">\n\n <div class="text-summary">\n <div style="line-height: 12px;">\n <svg width="20" height="22" viewBox="0 0 16 20" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M14.1668 5.83329V5.66663C14.1668 4.26649 14.1668 3.56643 13.8943 3.03165C13.6547 2.56124 13.2722 2.17879 12.8018 1.93911C12.267 1.66663 11.567 1.66663 10.1668 1.66663H4.8335C3.43336 1.66663 2.7333 1.66663 2.19852 1.93911C1.72811 2.17879 1.34566 2.56124 1.10598 3.03165C0.833496 3.56643 0.833496 4.26649 0.833496 5.66663V14.3333C0.833496 15.7334 0.833496 16.4335 1.10598 16.9683C1.34566 17.4387 1.72811 17.8211 2.19852 18.0608C2.7333 18.3333 3.43336 18.3333 4.8335 18.3333H7.91683M7.91683 9.16663H4.16683M7.0835 12.5H4.16683M10.8335 5.83329H4.16683M12.5002 15V10.4166C12.5002 9.72627 13.0598 9.16663 13.7502 9.16663C14.4405 9.16663 15.0002 9.72627 15.0002 10.4166V15C15.0002 16.3807 13.8809 17.5 12.5002 17.5C11.1195 17.5 10.0002 16.3807 10.0002 15V11.6666"\n stroke="#F79009" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <div class="text-summary-title">全文总结</div>\n </div>\n\n <div class="text">\n <div class="text-title">概括:</div>\n\n <p>\n 这本自传小说由企业家曹国熊撰写,讲述了他如何从贫穷孩子成长为成功企业家的经历和管理智慧,同时通过不同章节探讨了企业家的成长、团队合作、创新驱动、领导力培养、面对危机和可持续发展等主题。\n </p>\n <div class="text-title">要点:</div>\n <ul>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n </ul>\n\n\n\n\n\n\n </div>\n </div>\n </div>\n\n\n\n </div>\n <div *ngIf="aitab==\'AI配图\'" class="ai-img">\n <mat-accordion multi>\n <mat-expansion-panel expanded="true">\n <mat-expansion-panel-header>\n <mat-panel-title>文章封面</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="image" (click)="uploadImage()">\n <img [src]="article?.get(\'image\') || \'/assets/img/icon/addphoto.png\'" alt="">\n </div>\n </mat-expansion-panel>\n\n <mat-expansion-panel expanded="false">\n <mat-expansion-panel-header>\n <mat-panel-title>段落插图</mat-panel-title>\n </mat-expansion-panel-header>\n \n <div class="ai-img-search">\n\n <div class="ai-img-search-input">\n <input type="text" nz-input placeholder="请输入图片描述" />\n </div>\n\n <div class="ai-img-search-button">\n <ion-button>\n <ion-icon name="search-outline"></ion-icon>\n 查找\n </ion-button>\n </div>\n\n </div>\n\n <div class="img-tip">\n <img class="bg-img" src="../../../assets/images/火箭2.png">\n </div>\n <div class="ai-img-tip">\n <h1>输入描述,自动配图</h1>\n\n </div>\n\n <div class="ai-img-tip-list">\n <div class="pce-inner-tip-point"></div>\n <span>\n 根据您对图片的描述,智能匹配相关图片\n </span>\n </div>\n </mat-expansion-panel>\n </mat-accordion>\n\n\n </div>\n\n\n </div>\n\n</ion-content>\n',styles:['@charset "UTF-8";@media (max-width: 1024px){.ai-tool-grid ion-card{max-width:90%}.ai-tool-grid .card{width:100%;max-width:none}}.header{display:flex}.header ion-icon{font-size:30px}.ai-panel{height:100%;width:100%;padding:15px}.ai-panel .ai-tool-grid{display:flex;flex-wrap:wrap}.ai-panel div::-webkit-scrollbar{display:none}.ai-panel .ai-write{width:100%}.ai-panel .ai-write .search-bar{height:40px;width:100%}.ai-panel .ai-write ion-col{background-color:#fafafa;border:solid 2px #fafafa;text-align:center;padding:0;margin-left:3%}.ai-panel .ai-write .card{max-height:150px;height:15vh;cursor:pointer}.ai-panel .ai-write .card .card-image{margin-right:80%}.ai-panel .ai-write .card ion-card-header{padding:6%}.ai-panel .ai-write .card ion-card-subtitle{font-weight:600;text-align:left}.ai-panel .ai-write .card ion-card-content{text-align:left;white-space:pre-line;font-size:12px;margin-left:6%;padding:0}.ai-panel .ai-write .card-image{background:#fff;box-shadow:0 1px 4px #0000000a,0 4px 10px #00000014;width:30px;height:30px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex:none}.ai-panel .ai-polish{margin-top:10px;background-color:#fafafa}.ai-panel .ai-polish textarea.ant-input{max-width:93%;height:auto;min-height:32px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ai-panel .ai-polish ::-webkit-scrollbar{width:4px;border-radius:3px}.ai-panel .ai-polish ::-webkit-scrollbar-thumb{background-color:#dddee0;border-radius:2px}.ai-panel .ai-polish .ai-polish-button{text-align:right;margin-right:21px}.ai-panel .ai-polish .ai-polish-button button{margin-left:15px}.ai-panel .ai-polish .copy{text-align:right;margin-right:7%;cursor:pointer}.ai-panel .ai-proofread{height:73vh;margin-top:2%;position:sticky;top:0}.ai-panel .ai-proofread .showItems-container{width:100%;z-index:2}.ai-panel .ai-proofread .showItems-container .showItems{display:flex;justify-content:space-around;position:sticky;top:0;padding-left:15px;padding-right:15px}.ai-panel .ai-proofread .showItems-container .showItems .showItem{display:flex;flex-shrink:0;cursor:pointer;gap:8px;padding:12px 15px;background:#fff;border:1px solid #f9fafb;box-shadow:0 1px 2px #1018280d;font-size:16px;font-weight:400}.ai-panel .ai-proofread .showItems-container .showItems .active1{color:#333;font-weight:700}.ai-panel .ai-proofread .showItem-content .grammar-panel{margin-top:10%;margin-left:2.3%;height:61vh;overflow-y:scroll}.ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error{display:flex;text-align:center;margin-bottom:5%;width:90%;height:6vh;margin-left:4%;background:#fff;border:1px solid #f9fafb;box-shadow:0 1px 2px #1018280d;line-height:6vh}.ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .alert-point{color:#ff7a7a;margin-left:6%;margin-right:5%;font-size:20px}.ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .alert-point-gray{color:#8189a9;font-size:10px;margin-right:1%}.ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .error-content{margin-right:4%}.ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .right-content{margin-left:4%}.ai-panel .ai-proofread .showItem-content .suggest-panel{position:sticky;top:0;margin-top:4%;margin-left:6.8%;width:91%;background-color:#fff}.ai-panel .ai-proofread .showItem-content .suggest-panel .content-suggest{display:flex;cursor:pointer;padding:5% 3%;height:6%;width:100%}.ai-panel .ai-proofread .showItem-content .suggest-panel .content-suggest .content-suggest-title{margin-left:3%;font-size:16px;font-weight:400}.ai-panel .ai-proofread .showItem-content .suggest-panel .content{width:98%;height:55vh;overflow-y:scroll}.ai-panel .ai-proofread .showItem-content .suggest-panel .content .content-title{margin:3% 4%}.ai-panel .ai-proofread .showItem-content .suggest-panel .content ol{margin:3% 4%;counter-reset:section}.ai-panel .ai-proofread .showItem-content .suggest-panel .content li:before{counter-increment:section;content:"Section " counter(section) ". "}.ai-panel .ai-proofread .showItem-content .verify-panel{margin-top:2%;margin-left:6.8%;width:95%;margin-bottom:2%}.ai-panel .ai-proofread .showItem-content .verify-panel .icon{width:16px;height:16px;display:inline-block;margin-top:3px}.ai-panel .ai-proofread .showItem-content .verify-panel .dashboard{display:flex;margin-left:-1%;margin-top:3%;height:5%}.ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .itemChoose{background-color:#eaecf0}.ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .item{display:flex;height:76%;width:23%;padding:6px 8px;cursor:pointer}.ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .item .text{font-weight:bolder;margin-right:4%}.ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .item .number{font-weight:bolder;margin-right:1%}.ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .statusIcon{border-radius:50%;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:18px;height:18px}.ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list{height:61vh;overflow-y:scroll}.ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .card{box-shadow:0 1px 2px #1018280f,0 1px 3px #1018281a;width:95%;height:auto;margin-top:3%;padding:2% 3%;background-color:#fff}.ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .card .item{display:flex}.ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .card .card-content{margin-top:3%;margin-bottom:3%}.ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .statusIcon{border-radius:50%;width:18px;height:18px}.ai-panel .ai-proofread .showItem-content .summary-panel{margin-top:2%;margin-left:6.8%;width:91%;background-color:#fff}.ai-panel .ai-proofread .showItem-content .summary-panel .text-summary{display:flex;cursor:pointer;padding:5% 3%;height:6%;width:100%}.ai-panel .ai-proofread .showItem-content .summary-panel .text-summary .text-summary-title{margin-left:3%;font-size:16px;font-weight:400}.ai-panel .ai-proofread .showItem-content .summary-panel .text{width:100%;height:57vh;overflow-y:scroll}.ai-panel .ai-proofread .showItem-content .summary-panel .text .text-title{margin:3% 4%;font-weight:700}.ai-panel .ai-proofread .showItem-content .summary-panel .text p{margin:3% 4%}.ai-panel .ai-img{width:480px}.ai-panel .ai-img .ai-img-search{display:flex;height:4%;width:100%;margin-left:4%;margin-top:5%}.ai-panel .ai-img .ai-img-search .ai-img-search-input{width:65%}.ai-panel .ai-img .ai-img-search .ai-img-search-input input{height:100%}.ai-panel .ai-img .ai-img-search .ai-img-search-button{margin-left:5%;margin-top:-.8%}.ai-panel .ai-img .img-tip{display:flex;text-align:center;justify-content:center;margin-top:20%;width:95%}.ai-panel .ai-img .img-tip .bg-img{width:65%}.ai-panel .ai-img .ai-img-tip{display:flex;justify-content:center;text-align:center;margin-top:2%;margin-right:5%}.ai-panel .ai-img .ai-img-tip h1{font-weight:600}.ai-panel .ai-img .ai-img-tip-list{display:flex;justify-content:center;text-align:center;margin-top:2%;margin-right:5%}.ai-panel .ai-img .ai-img-tip-list .pce-inner-tip-point{display:inline-block;margin-top:2%;margin-right:1%;height:8px;width:8px;border-radius:50%;background-color:#4b4b4b}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i3$3.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:i3$3.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"directive",type:i3$3.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"component",type:IonSearchbar,selector:"ion-searchbar",inputs:["animated","autocomplete","autocorrect","cancelButtonIcon","cancelButtonText","clearIcon","color","debounce","disabled","enterkeyhint","inputmode","mode","name","placeholder","searchIcon","showCancelButton","showClearButton","spellcheck","type","value"]},{kind:"component",type:IonCard,selector:"ion-card",inputs:["button","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:IonCardTitle,selector:"ion-card-title",inputs:["color","mode"]},{kind:"component",type:IonCardSubtitle,selector:"ion-card-subtitle",inputs:["color","mode"]},{kind:"component",type:IonCardHeader,selector:"ion-card-header",inputs:["color","mode","translucent"]},{kind:"component",type:IonCardContent,selector:"ion-card-content",inputs:["mode"]},{kind:"component",type:IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{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:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:IonSegment,selector:"ion-segment",inputs:["color","disabled","mode","scrollable","selectOnFocus","swipeGesture","value"]},{kind:"component",type:IonSegmentButton,selector:"ion-segment-button",inputs:["contentId","disabled","layout","mode","type","value"]},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"ngmodule",type:MatExpansionModule},{kind:"directive",type:i7$2.MatAccordion,selector:"mat-accordion",inputs:["hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:i7$2.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["hideToggle","togglePosition"],outputs:["afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:i7$2.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["expandedHeight","collapsedHeight","tabIndex"]},{kind:"directive",type:i7$2.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"ngmodule",type:MatIconModule},{kind:"component",type:i6.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"ngmodule",type:MatFormFieldModule},{kind:"component",type:i11$1.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:i11$1.MatLabel,selector:"mat-label"}]})}}async function openArticleAITool(e){let t=await e.modalCtrl.create({component:FmArticleAitoolComponent,componentProps:{article:e?.article,onBreakPointSet:()=>{}},breakpoints:[1],initialBreakpoint:1});t.present();let{data:n,role:o}=await t.onWillDismiss();if("confirm"==o)return n}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmArticleAitoolComponent,decorators:[{type:Component,args:[{selector:"app-fm-article-aitool",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,IonSearchbar,IonCard,IonCardTitle,IonCardSubtitle,IonCardHeader,IonCardContent,IonContent,IonButton,IonIcon,IonLabel,IonSegment,IonSegmentButton,MatButtonModule,MatExpansionModule,MatIconModule,MatFormFieldModule],template:'<ion-content>\n\n <div class="header">\n <ion-segment [(ngModel)]="aitab" [disabled]="true" (click)="linkEditor()">\n <ion-segment-button value="AI写作">\n <ion-label>AI写作</ion-label>\n </ion-segment-button>\n <ion-segment-button value="AI润色">\n <ion-label>AI润色</ion-label>\n </ion-segment-button>\n <ion-segment-button value="AI校阅">\n <ion-label>AI校阅</ion-label>\n </ion-segment-button>\n <ion-segment-button value="AI配图">\n <ion-label>AI配图</ion-label>\n </ion-segment-button>\n </ion-segment>\n <ion-icon name="close-outline" (click)="$event.stopPropagation();close()"></ion-icon>\n </div>\n\n \x3c!-- 工具面板 --\x3e\n <div class="ai-panel">\n\n <div *ngIf="aitab==\'AI写作\'" class="ai-write">\n \x3c!-- 搜索 --\x3e\n <div class="search-bar">\n <ion-searchbar color="light" placeholder="搜索模板"></ion-searchbar>\n </div>\n\n <div class="ai-tool-grid">\n <ng-container *ngFor="let card of cards">\n <ion-card class="card" (click)="card?.handle()">\n <ion-card-header>\n <ion-card-title class="card-image">\n <img src="{{card.imageurl}}" width="25" height="25" alt="write">\n </ion-card-title>\n <ion-card-subtitle>{{card.title}}</ion-card-subtitle>\n </ion-card-header>\n\n <ion-card-content>\n {{card.content}}\n </ion-card-content>\n </ion-card>\n </ng-container>\n </div>\n\n </div>\n <div *ngIf="aitab==\'AI润色\'" class="ai-polish" [formGroup]="tempFormGroup">\n <div class="ai-polish-input">\n <mat-form-field style="width:95%;">\n <mat-label>输入或选中左侧文本开始润色</mat-label>\n <textarea matInput [(ngModel)]="selectText" [ngModelOptions]="{standalone: true}" rows="10"></textarea>\n </mat-form-field>\n\n \x3c!-- <textarea [(ngModel)]="selectText" rows="10" formControlName="comment" nz-input placeholder="输入或选中左侧文本开始润色"></textarea> --\x3e\n </div>\n <div class="ai-polish-button">\n <button *ngIf="!isOptimizing" mat-raised-button color="primary" (click)="optimizeContent()">开始润色</button>\n <button *ngIf="isOptimizing" mat-raised-button color="warn" (click)="cancelOptimize()">停止润色</button>\n \x3c!-- <ion-button id="start" [disabled]="false" (click)="enableButton()">开始润色</ion-button> --\x3e\n </div>\n <div class="ai-polish-input">\n <mat-form-field style="width:95%;">\n <mat-label>生成内容</mat-label>\n <textarea matInput [(ngModel)]="optimizeText" [ngModelOptions]="{standalone: true}" rows="10"></textarea>\n </mat-form-field>\n </div>\n <div class="ai-polish-button">\n <button *ngIf="selectRange?.length" mat-raised-button (click)="applyOptimize()"><mat-icon fontIcon="flip"></mat-icon>替换</button>\n <button mat-raised-button (click)="copyOptimize()"><mat-icon fontIcon="content_copy"></mat-icon>复制</button>\n \x3c!-- <ion-button id="start" [disabled]="false" (click)="enableButton()">开始润色</ion-button> --\x3e\n </div>\n \x3c!-- <div class="copy">\n <ion-icon name="copy-outline" style="color:#4e80f4" (click)="Copy(polishContent)"></ion-icon>\n </div> --\x3e\n </div>\n <div *ngIf="aitab==\'校阅\'" class="ai-proofread">\n\n <div class="showItems-container">\n <div class="showItems">\n\n <div class="showItem" (click)="clickTab(\'内容建议\')" [ngClass]="{ \'active1\': clicktab == \'内容建议\' }">\n <div style="line-height: 12px;">\n <svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M11 10H5M7 14H5M13 6H5M17 9.5V5.8C17 4.11984 17 3.27976 16.673 2.63803C16.3854 2.07354 15.9265 1.6146 15.362 1.32698C14.7202 1 13.8802 1 12.2 1H5.8C4.11984 1 3.27976 1 2.63803 1.32698C2.07354 1.6146 1.6146 2.07354 1.32698 2.63803C1 3.27976 1 4.11984 1 5.8V16.2C1 17.8802 1 18.7202 1.32698 19.362C1.6146 19.9265 2.07354 20.3854 2.63803 20.673C3.27976 21 4.11984 21 5.8 21H8.5M19 21L17.5 19.5M18.5 17C18.5 18.933 16.933 20.5 15 20.5C13.067 20.5 11.5 18.933 11.5 17C11.5 15.067 13.067 13.5 15 13.5C16.933 13.5 18.5 15.067 18.5 17Z"\n stroke="#1570EF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <span>内容建议</span>\n\n\n </div>\n\n <div class="showItem" (click)="clickTab(\'事实验证\')" [ngClass]="{\'active1\': clicktab==\'事实验证\'}">\n <div style="line-height: 12px;">\n <svg width="18" height="22" viewBox="0 0 18 22" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M11 1.26953V5.40007C11 5.96012 11 6.24015 11.109 6.45406C11.2049 6.64222 11.3578 6.7952 11.546 6.89108C11.7599 7.00007 12.0399 7.00007 12.6 7.00007H16.7305M6 15L8 17L12.5 12.5M11 1H5.8C4.11984 1 3.27976 1 2.63803 1.32698C2.07354 1.6146 1.6146 2.07354 1.32698 2.63803C1 3.27976 1 4.11984 1 5.8V16.2C1 17.8802 1 18.7202 1.32698 19.362C1.6146 19.9265 2.07354 20.3854 2.63803 20.673C3.27976 21 4.11984 21 5.8 21H12.2C13.8802 21 14.7202 21 15.362 20.673C15.9265 20.3854 16.3854 19.9265 16.673 19.362C17 18.7202 17 17.8802 17 16.2V7L11 1Z"\n stroke="#D92D20" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <span>事实验证</span>\n </div>\n\n <div class="showItem" (click)="clickTab(\'全文总结\')" [ngClass]="{\'active1\': clicktab==\'全文总结\'}">\n <div style="line-height: 12px;"> <svg width="20" height="22" viewBox="0 0 16 20" fill="none"\n xmlns="http://www.w3.org/2000/svg">\n <path\n d="M14.1668 5.83329V5.66663C14.1668 4.26649 14.1668 3.56643 13.8943 3.03165C13.6547 2.56124 13.2722 2.17879 12.8018 1.93911C12.267 1.66663 11.567 1.66663 10.1668 1.66663H4.8335C3.43336 1.66663 2.7333 1.66663 2.19852 1.93911C1.72811 2.17879 1.34566 2.56124 1.10598 3.03165C0.833496 3.56643 0.833496 4.26649 0.833496 5.66663V14.3333C0.833496 15.7334 0.833496 16.4335 1.10598 16.9683C1.34566 17.4387 1.72811 17.8211 2.19852 18.0608C2.7333 18.3333 3.43336 18.3333 4.8335 18.3333H7.91683M7.91683 9.16663H4.16683M7.0835 12.5H4.16683M10.8335 5.83329H4.16683M12.5002 15V10.4166C12.5002 9.72627 13.0598 9.16663 13.7502 9.16663C14.4405 9.16663 15.0002 9.72627 15.0002 10.4166V15C15.0002 16.3807 13.8809 17.5 12.5002 17.5C11.1195 17.5 10.0002 16.3807 10.0002 15V11.6666"\n stroke="#F79009" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <span>全文总结</span>\n </div>\n\n </div>\n </div>\n\n <div class="showItem-content">\n <div *ngIf="clicktab==\'语法错误\'" class="grammar-panel">\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n\n </div>\n <div *ngIf="clicktab==\'内容建议\'" class="suggest-panel">\n\n <div class="content-suggest">\n <div style="line-height: 12px;">\n <svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M11 10H5M7 14H5M13 6H5M17 9.5V5.8C17 4.11984 17 3.27976 16.673 2.63803C16.3854 2.07354 15.9265 1.6146 15.362 1.32698C14.7202 1 13.8802 1 12.2 1H5.8C4.11984 1 3.27976 1 2.63803 1.32698C2.07354 1.6146 1.6146 2.07354 1.32698 2.63803C1 3.27976 1 4.11984 1 5.8V16.2C1 17.8802 1 18.7202 1.32698 19.362C1.6146 19.9265 2.07354 20.3854 2.63803 20.673C3.27976 21 4.11984 21 5.8 21H8.5M19 21L17.5 19.5M18.5 17C18.5 18.933 16.933 20.5 15 20.5C13.067 20.5 11.5 18.933 11.5 17C11.5 15.067 13.067 13.5 15 13.5C16.933 13.5 18.5 15.067 18.5 17Z"\n stroke="#1570EF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <div class="content-suggest-title">内容建议</div>\n </div>\n\n <div class="content">\n <div class="content-title"> 这篇文章介绍的是七个关于中国企业家的管理之道的自传小说章节标题,旨在展示企业家们的个人经历、管理理念和人生哲学。\n </div>\n <div class="content-title">改进建议:</div>\n <ol>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n </ol>\n\n\n </div>\n </div>\n <div *ngIf="clicktab==\'事实验证\'" class="verify-panel">\n <div class="dashboard">\n <div class="item" (click)="dashboardTab(\'全部\')" [ngClass]="{\'itemChoose\': dashboardtab==\'全部\'}">\n <div class="icon">\n <div class="statusIcon" style="border: 1px solid black; box-sizing: border-box;"></div>\n </div>\n <div class="text">全部</div>\n <div class="number">28</div>\n </div>\n\n <div class="item" (click)="dashboardTab(\'通过\')" [ngClass]="{\'itemChoose\': dashboardtab==\'通过\'}">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n <div class="number">9</div>\n </div>\n\n <div class="item" (click)="dashboardTab(\'不通过\')" [ngClass]="{\'itemChoose\': dashboardtab==\'不通过\'}">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(217, 45, 32);"><svg\n xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">\n <path d="M7 17L17 7" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n <path d="M7 7L17 17" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </svg></div>\n </div>\n <div class="text" style="color: rgb(217, 45, 32);">不通过</div>\n <div class="number">1</div>\n </div>\n <div class="item" (click)="dashboardTab(\'无法判断\')" [ngClass]="{\'itemChoose\': dashboardtab==\'无法判断\'}">\n <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="3 3 18 18"\n fill="none">\n <path\n d="M7.8824 8.679C7.88035 8.72744 7.88822 8.77579 7.90555 8.82107C7.92287 8.86636 7.94927 8.90762 7.98313 8.94232C8.01699 8.97703 8.05759 9.00444 8.10244 9.02287C8.14728 9.0413 8.19542 9.05036 8.2439 9.0495H9.4814C9.6884 9.0495 9.8534 8.88 9.8804 8.6745C10.0154 7.6905 10.6904 6.9735 11.8934 6.9735C12.9224 6.9735 13.8644 7.488 13.8644 8.7255C13.8644 9.678 13.3034 10.116 12.4169 10.782C11.4074 11.5155 10.6079 12.372 10.6649 13.7625L10.6694 14.088C10.671 14.1864 10.7112 14.2803 10.7813 14.3493C10.8515 14.4183 10.946 14.457 11.0444 14.457H12.2609C12.3604 14.457 12.4557 14.4175 12.5261 14.3472C12.5964 14.2768 12.6359 14.1815 12.6359 14.082V13.9245C12.6359 12.8475 13.0454 12.534 14.1509 11.6955C15.0644 11.001 16.0169 10.23 16.0169 8.6115C16.0169 6.345 14.1029 5.25 12.0074 5.25C10.1069 5.25 8.0249 6.135 7.8824 8.679ZM10.2179 17.3235C10.2179 18.123 10.8554 18.714 11.7329 18.714C12.6464 18.714 13.2749 18.123 13.2749 17.3235C13.2749 16.4955 12.6449 15.9135 11.7314 15.9135C10.8554 15.9135 10.2179 16.4955 10.2179 17.3235Z"\n fill="#475467"></path>\n </svg></div>\n <div class="text">无法判断</div>\n <div class="number">18</div>\n </div>\n </div>\n\n <div class="verify-card-list">\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n </div>\n </div>\n <div *ngIf="clicktab==\'全文总结\'" class="summary-panel">\n\n <div class="text-summary">\n <div style="line-height: 12px;">\n <svg width="20" height="22" viewBox="0 0 16 20" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M14.1668 5.83329V5.66663C14.1668 4.26649 14.1668 3.56643 13.8943 3.03165C13.6547 2.56124 13.2722 2.17879 12.8018 1.93911C12.267 1.66663 11.567 1.66663 10.1668 1.66663H4.8335C3.43336 1.66663 2.7333 1.66663 2.19852 1.93911C1.72811 2.17879 1.34566 2.56124 1.10598 3.03165C0.833496 3.56643 0.833496 4.26649 0.833496 5.66663V14.3333C0.833496 15.7334 0.833496 16.4335 1.10598 16.9683C1.34566 17.4387 1.72811 17.8211 2.19852 18.0608C2.7333 18.3333 3.43336 18.3333 4.8335 18.3333H7.91683M7.91683 9.16663H4.16683M7.0835 12.5H4.16683M10.8335 5.83329H4.16683M12.5002 15V10.4166C12.5002 9.72627 13.0598 9.16663 13.7502 9.16663C14.4405 9.16663 15.0002 9.72627 15.0002 10.4166V15C15.0002 16.3807 13.8809 17.5 12.5002 17.5C11.1195 17.5 10.0002 16.3807 10.0002 15V11.6666"\n stroke="#F79009" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <div class="text-summary-title">全文总结</div>\n </div>\n\n <div class="text">\n <div class="text-title">概括:</div>\n\n <p>\n 这本自传小说由企业家曹国熊撰写,讲述了他如何从贫穷孩子成长为成功企业家的经历和管理智慧,同时通过不同章节探讨了企业家的成长、团队合作、创新驱动、领导力培养、面对危机和可持续发展等主题。\n </p>\n <div class="text-title">要点:</div>\n <ul>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n </ul>\n\n\n\n\n\n\n </div>\n </div>\n </div>\n\n\n\n </div>\n <div *ngIf="aitab==\'AI配图\'" class="ai-img">\n <mat-accordion multi>\n <mat-expansion-panel expanded="true">\n <mat-expansion-panel-header>\n <mat-panel-title>文章封面</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="image" (click)="uploadImage()">\n <img [src]="article?.get(\'image\') || \'/assets/img/icon/addphoto.png\'" alt="">\n </div>\n </mat-expansion-panel>\n\n <mat-expansion-panel expanded="false">\n <mat-expansion-panel-header>\n <mat-panel-title>段落插图</mat-panel-title>\n </mat-expansion-panel-header>\n \n <div class="ai-img-search">\n\n <div class="ai-img-search-input">\n <input type="text" nz-input placeholder="请输入图片描述" />\n </div>\n\n <div class="ai-img-search-button">\n <ion-button>\n <ion-icon name="search-outline"></ion-icon>\n 查找\n </ion-button>\n </div>\n\n </div>\n\n <div class="img-tip">\n <img class="bg-img" src="../../../assets/images/火箭2.png">\n </div>\n <div class="ai-img-tip">\n <h1>输入描述,自动配图</h1>\n\n </div>\n\n <div class="ai-img-tip-list">\n <div class="pce-inner-tip-point"></div>\n <span>\n 根据您对图片的描述,智能匹配相关图片\n </span>\n </div>\n </mat-expansion-panel>\n </mat-accordion>\n\n\n </div>\n\n\n </div>\n\n</ion-content>\n',styles:['@charset "UTF-8";@media (max-width: 1024px){.ai-tool-grid ion-card{max-width:90%}.ai-tool-grid .card{width:100%;max-width:none}}.header{display:flex}.header ion-icon{font-size:30px}.ai-panel{height:100%;width:100%;padding:15px}.ai-panel .ai-tool-grid{display:flex;flex-wrap:wrap}.ai-panel div::-webkit-scrollbar{display:none}.ai-panel .ai-write{width:100%}.ai-panel .ai-write .search-bar{height:40px;width:100%}.ai-panel .ai-write ion-col{background-color:#fafafa;border:solid 2px #fafafa;text-align:center;padding:0;margin-left:3%}.ai-panel .ai-write .card{max-height:150px;height:15vh;cursor:pointer}.ai-panel .ai-write .card .card-image{margin-right:80%}.ai-panel .ai-write .card ion-card-header{padding:6%}.ai-panel .ai-write .card ion-card-subtitle{font-weight:600;text-align:left}.ai-panel .ai-write .card ion-card-content{text-align:left;white-space:pre-line;font-size:12px;margin-left:6%;padding:0}.ai-panel .ai-write .card-image{background:#fff;box-shadow:0 1px 4px #0000000a,0 4px 10px #00000014;width:30px;height:30px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex:none}.ai-panel .ai-polish{margin-top:10px;background-color:#fafafa}.ai-panel .ai-polish textarea.ant-input{max-width:93%;height:auto;min-height:32px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.ai-panel .ai-polish ::-webkit-scrollbar{width:4px;border-radius:3px}.ai-panel .ai-polish ::-webkit-scrollbar-thumb{background-color:#dddee0;border-radius:2px}.ai-panel .ai-polish .ai-polish-button{text-align:right;margin-right:21px}.ai-panel .ai-polish .ai-polish-button button{margin-left:15px}.ai-panel .ai-polish .copy{text-align:right;margin-right:7%;cursor:pointer}.ai-panel .ai-proofread{height:73vh;margin-top:2%;position:sticky;top:0}.ai-panel .ai-proofread .showItems-container{width:100%;z-index:2}.ai-panel .ai-proofread .showItems-container .showItems{display:flex;justify-content:space-around;position:sticky;top:0;padding-left:15px;padding-right:15px}.ai-panel .ai-proofread .showItems-container .showItems .showItem{display:flex;flex-shrink:0;cursor:pointer;gap:8px;padding:12px 15px;background:#fff;border:1px solid #f9fafb;box-shadow:0 1px 2px #1018280d;font-size:16px;font-weight:400}.ai-panel .ai-proofread .showItems-container .showItems .active1{color:#333;font-weight:700}.ai-panel .ai-proofread .showItem-content .grammar-panel{margin-top:10%;margin-left:2.3%;height:61vh;overflow-y:scroll}.ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error{display:flex;text-align:center;margin-bottom:5%;width:90%;height:6vh;margin-left:4%;background:#fff;border:1px solid #f9fafb;box-shadow:0 1px 2px #1018280d;line-height:6vh}.ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .alert-point{color:#ff7a7a;margin-left:6%;margin-right:5%;font-size:20px}.ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .alert-point-gray{color:#8189a9;font-size:10px;margin-right:1%}.ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .error-content{margin-right:4%}.ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .right-content{margin-left:4%}.ai-panel .ai-proofread .showItem-content .suggest-panel{position:sticky;top:0;margin-top:4%;margin-left:6.8%;width:91%;background-color:#fff}.ai-panel .ai-proofread .showItem-content .suggest-panel .content-suggest{display:flex;cursor:pointer;padding:5% 3%;height:6%;width:100%}.ai-panel .ai-proofread .showItem-content .suggest-panel .content-suggest .content-suggest-title{margin-left:3%;font-size:16px;font-weight:400}.ai-panel .ai-proofread .showItem-content .suggest-panel .content{width:98%;height:55vh;overflow-y:scroll}.ai-panel .ai-proofread .showItem-content .suggest-panel .content .content-title{margin:3% 4%}.ai-panel .ai-proofread .showItem-content .suggest-panel .content ol{margin:3% 4%;counter-reset:section}.ai-panel .ai-proofread .showItem-content .suggest-panel .content li:before{counter-increment:section;content:"Section " counter(section) ". "}.ai-panel .ai-proofread .showItem-content .verify-panel{margin-top:2%;margin-left:6.8%;width:95%;margin-bottom:2%}.ai-panel .ai-proofread .showItem-content .verify-panel .icon{width:16px;height:16px;display:inline-block;margin-top:3px}.ai-panel .ai-proofread .showItem-content .verify-panel .dashboard{display:flex;margin-left:-1%;margin-top:3%;height:5%}.ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .itemChoose{background-color:#eaecf0}.ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .item{display:flex;height:76%;width:23%;padding:6px 8px;cursor:pointer}.ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .item .text{font-weight:bolder;margin-right:4%}.ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .item .number{font-weight:bolder;margin-right:1%}.ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .statusIcon{border-radius:50%;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:18px;height:18px}.ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list{height:61vh;overflow-y:scroll}.ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .card{box-shadow:0 1px 2px #1018280f,0 1px 3px #1018281a;width:95%;height:auto;margin-top:3%;padding:2% 3%;background-color:#fff}.ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .card .item{display:flex}.ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .card .card-content{margin-top:3%;margin-bottom:3%}.ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .statusIcon{border-radius:50%;width:18px;height:18px}.ai-panel .ai-proofread .showItem-content .summary-panel{margin-top:2%;margin-left:6.8%;width:91%;background-color:#fff}.ai-panel .ai-proofread .showItem-content .summary-panel .text-summary{display:flex;cursor:pointer;padding:5% 3%;height:6%;width:100%}.ai-panel .ai-proofread .showItem-content .summary-panel .text-summary .text-summary-title{margin-left:3%;font-size:16px;font-weight:400}.ai-panel .ai-proofread .showItem-content .summary-panel .text{width:100%;height:57vh;overflow-y:scroll}.ai-panel .ai-proofread .showItem-content .summary-panel .text .text-title{margin:3% 4%;font-weight:700}.ai-panel .ai-proofread .showItem-content .summary-panel .text p{margin:3% 4%}.ai-panel .ai-img{width:480px}.ai-panel .ai-img .ai-img-search{display:flex;height:4%;width:100%;margin-left:4%;margin-top:5%}.ai-panel .ai-img .ai-img-search .ai-img-search-input{width:65%}.ai-panel .ai-img .ai-img-search .ai-img-search-input input{height:100%}.ai-panel .ai-img .ai-img-search .ai-img-search-button{margin-left:5%;margin-top:-.8%}.ai-panel .ai-img .img-tip{display:flex;text-align:center;justify-content:center;margin-top:20%;width:95%}.ai-panel .ai-img .img-tip .bg-img{width:65%}.ai-panel .ai-img .ai-img-tip{display:flex;justify-content:center;text-align:center;margin-top:2%;margin-right:5%}.ai-panel .ai-img .ai-img-tip h1{font-weight:600}.ai-panel .ai-img .ai-img-tip-list{display:flex;justify-content:center;text-align:center;margin-top:2%;margin-right:5%}.ai-panel .ai-img .ai-img-tip-list .pce-inner-tip-point{display:inline-block;margin-top:2%;margin-right:1%;height:8px;width:8px;border-radius:50%;background-color:#4b4b4b}\n']}]}],ctorParameters:()=>[{type:i1$3.AlertController},{type:i1$3.ModalController},{type:i3$1.MatDialog},{type:NovaUploadService},{type:i0.ChangeDetectorRef},{type:ClipboardService},{type:PersonService}],propDecorators:{article:[{type:Input}]}});class CompUploadBookBannersComponent{constructor(e){this.modalCtrl=e}ngOnInit(){this.getArticle()}changeBanner(){this.banner="",console.log(this.banner)}async getArticle(){let e=new Parse__default.Query("Article");e.equalTo("objectId",this.articleId),e.notEqualTo("isDeleted",!0),e.include("author"),this.article=await e.first(),console.log("article",this.article)}async saveSelection(){if(!this.banner)return void console.log("没有上传封面图");console.log("this.bookId",this.articleId);let e=new Parse__default.Query("Article");e.equalTo("objectId",this.articleId);try{let t=await e.first();t?(t.set("image",this.banner),await t.save(),console.log("封面图保存成功"),await this.modalCtrl.dismiss({success:!0,banner:this.banner},"confirm")):console.log("未找到相关章节")}catch(e){console.error("保存失败",e),alert("保存失败")}}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompUploadBookBannersComponent,deps:[{token:i1$3.ModalController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CompUploadBookBannersComponent,isStandalone:!0,selector:"app-comp-upload-book-banners",inputs:{articleId:"articleId"},ngImport:i0,template:'<div class="background">\n <div class="fixed-navbar">\n <div class="left">\n </div>\n <div class="center">\n 封面上传\n </div>\n <div class="right" (click)="saveSelection()">保存</div>\n </div>\n <div class="content">\n <div style="display: flex; flex-direction: row;width: 50%;text-align: center;margin-top: 20px;margin-left: 13%;">\n <div class="upload_avatar">\n <fm-edit-upload *ngIf="!banner" [(file)]="banner" [multi]="true"></fm-edit-upload>\n <img style="width: 110px;height: 110px;object-fit: cover;" *ngIf="banner"\n [src]="banner" alt="">\n </div>\n <div *ngIf="banner" (click)="changeBanner()" style="margin-left: -12px;\n font-size: 11px;\n margin-top: -12px;\n height: 24px;\n cursor: pointer;\n width: 24px;\n border-radius: 50%;\n background-color: #ccc;\n color: #fff;\n display: flex;\n align-items: center;\n justify-content: center;">\n <span nz-icon nzType="close" nzTheme="outline"></span>\n </div>\n </div>\n </div>\n</div>\n',styles:[".background{background:linear-gradient(#040a15,#0e254b);width:100%;height:100%;margin:0;padding:0;overflow-y:auto;overflow-x:hidden}.background .fixed-navbar{height:8vh;position:sticky;top:0;display:flex;flex-direction:row;justify-content:space-between;align-items:center;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);z-index:999}.background .fixed-navbar .left{flex:1;display:flex;justify-content:flex-start;align-items:center;color:#fff}.background .fixed-navbar .center{color:#fff;font-size:1.3rem;font-weight:700}.background .fixed-navbar .right{display:flex;justify-content:flex-end;margin-right:20px;font-size:1rem;flex:1}.background .content{padding:8% 5%}\n"],dependencies:[{kind:"ngmodule",type:EditUploadModule},{kind:"component",type:EditUploadComponent,selector:"fm-edit-upload",inputs:["files","dragdrop","multi","max_file_size","type","avatarType","company","file","fileList","path"],outputs:["filesChange","fileChange","fileListChange"]},{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompUploadBookBannersComponent,decorators:[{type:Component,args:[{selector:"app-comp-upload-book-banners",standalone:!0,imports:[EditUploadModule,CommonModule,FormsModule],template:'<div class="background">\n <div class="fixed-navbar">\n <div class="left">\n </div>\n <div class="center">\n 封面上传\n </div>\n <div class="right" (click)="saveSelection()">保存</div>\n </div>\n <div class="content">\n <div style="display: flex; flex-direction: row;width: 50%;text-align: center;margin-top: 20px;margin-left: 13%;">\n <div class="upload_avatar">\n <fm-edit-upload *ngIf="!banner" [(file)]="banner" [multi]="true"></fm-edit-upload>\n <img style="width: 110px;height: 110px;object-fit: cover;" *ngIf="banner"\n [src]="banner" alt="">\n </div>\n <div *ngIf="banner" (click)="changeBanner()" style="margin-left: -12px;\n font-size: 11px;\n margin-top: -12px;\n height: 24px;\n cursor: pointer;\n width: 24px;\n border-radius: 50%;\n background-color: #ccc;\n color: #fff;\n display: flex;\n align-items: center;\n justify-content: center;">\n <span nz-icon nzType="close" nzTheme="outline"></span>\n </div>\n </div>\n </div>\n</div>\n',styles:[".background{background:linear-gradient(#040a15,#0e254b);width:100%;height:100%;margin:0;padding:0;overflow-y:auto;overflow-x:hidden}.background .fixed-navbar{height:8vh;position:sticky;top:0;display:flex;flex-direction:row;justify-content:space-between;align-items:center;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);z-index:999}.background .fixed-navbar .left{flex:1;display:flex;justify-content:flex-start;align-items:center;color:#fff}.background .fixed-navbar .center{color:#fff;font-size:1.3rem;font-weight:700}.background .fixed-navbar .right{display:flex;justify-content:flex-end;margin-right:20px;font-size:1rem;flex:1}.background .content{padding:8% 5%}\n"]}]}],ctorParameters:()=>[{type:i1$3.ModalController}],propDecorators:{articleId:[{type:Input}]}});class FmArticlePreviewComponent{constructor(e,t,n,o,i,a,r,s,l){this.route=e,this.router=t,this.dialog=n,this.navCtrl=o,this.modalCtrl=i,this.animationCtrl=a,this.articleServ=r,this.alertCtrl=s,this.draftServ=l,this.isDisplayEdit=!0,this.isDisplayPublic=!0,this.isDisplayUploadImage=!1,this.isAuthor=!1,this.previewStyle="<style>\n .content-block h1,.content-block h2,.content-block h3,.content-block h4,.content-block h5,.content-block h6{\n color:white !important;\n }\n </style>",this.bannerList=[],this.isShare=!1}ngOnInit(){this.route.params.subscribe((async e=>{console.log(e);let t=e?.id;console.log(111,t),this.article?.id||await this.loadArticle(t),this.initArticleBanner(),this.article?.id&&(this.articleServ.initWxShareInfo(this.article),(this.article?.get("author")?.id||this.article?.get("author")?.objectId)==Parse__default.User.current()?.id&&(this.isAuthor=!0),this.draftServ?.loadArticleDraft(this.article),this.articleServ.viewArticle(this.article))}))}handleNavEvent(e,t){let n={article:null};t={shareData:n,dialog:this.dialog,article:this.article},console.log(e,n),"options"==e&&doArticleTask([TaskArticleWritingOptions({shareData:n,dialog:this.dialog,editOnly:!0})],t),"outline"==e&&doArticleTask([TaskArticleOutlineEdit({shareData:n,dialog:this.dialog})],t),"draft"==e&&doArticleTask([TaskArticleDraft({isSelectedMode:!0,shareData:n,dialog:this.dialog,modalCtrl:this.modalCtrl})],t,(()=>{}))}async loadArticle(e){let t=new Parse__default.Query("Article");this.article=await t.get(e),console.log(this.article)}shareArticle(){this.articleServ.shareArticle(this.article)}async editArticle(){document.body.clientWidth>1e3?this.navCtrl.navigateForward("/editor/article/"+this.article?.id):this.article&&openArticleAITool({modalCtrl:this.modalCtrl,alertCtrl:this.alertCtrl,animationCtrl:this.animationCtrl,article:this.article})}initArticleBanner(){this.bannerList=this.articleServ.getArticleBanner(this.article),this.bannerList?.length&&this.initSwiperTimeEvent()}back(){if(location?.pathname?.indexOf("chapter")>-1){let e=location.pathname.split("/chapter")[0];this.navCtrl.navigateRoot(e)}else location?.pathname?.indexOf("article")>-1?this.navCtrl.navigateRoot("/app/book"):this.modalCtrl?.dismiss()}onPublicChange(e){this.article?.set("isPublic",e?.checked),this.article?.save()}async delete(){const e=await this.alertCtrl.create({header:"删除文章",subHeader:"您确认删除文章及其数据吗?",buttons:[{text:"取消",role:"cancel",handler:()=>{}},{text:"删除",role:"confirm",handler:()=>{this.article?.set("isDeleted",!0),this.article?.save(),this.modalCtrl.dismiss()}}]});await e.present()}onScroll(e){}initSwiperTimeEvent(){this.pageSwiper=new Swiper(".swiper",{mousewheel:!0,effect:"fade",loop:!0,pagination:{el:".swiper-pagination",clickable:!0}})}openOverlay(){this.isShare=!0}closeOverlay(){this.isShare=!1}openUploadBanner(){let e=this.article?.id;openUploadBannerModal(this.modalCtrl,e).then((e=>{e&&this.bannerList.push(e)}))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmArticlePreviewComponent,deps:[{token:i1$1.ActivatedRoute},{token:i1$1.Router},{token:i3$1.MatDialog},{token:i1$3.NavController},{token:i1$3.ModalController},{token:i1$3.AnimationController},{token:ArticleService},{token:i1$3.AlertController},{token:DraftService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:FmArticlePreviewComponent,isStandalone:!0,selector:"fm-article-preview",inputs:{article:"article",isDisplayEdit:"isDisplayEdit",isDisplayPublic:"isDisplayPublic",isDisplayUploadImage:"isDisplayUploadImage"},ngImport:i0,template:'<ion-header [translucent]="true" collapse="fade" class="ion-no-border">\n <ion-toolbar>\n \x3c!-- 返回 --\x3e\n <ion-buttons slot="secondary">\n <ion-button (click)="back()">\n <ion-icon slot="icon-only" name="arrow-back-circle"></ion-icon>\n </ion-button>\n @if(isAuthor){\n @if(isDisplayPublic===true){\n <div style="display:flex;justify-content: center;align-items: center;margin-left: 20px;">\n <mat-slide-toggle [checked]="article?.get(\'isPublic\')" (change)="onPublicChange($event)"></mat-slide-toggle>\n <span class="toggle-text">公开</span>\n </div>\n }\n }\n </ion-buttons>\n <ion-title style="font-size: 1.3rem;font-weight: bold;">文章预览</ion-title>\n <ion-buttons slot="primary">\n \x3c!-- 编辑 --\x3e\n @if(isAuthor){\n \x3c!-- <div style="display:flex;justify-content: center;align-items: center;">\n <mat-slide-toggle [checked]="article?.get(\'isPublic\')" (change)="onPublicChange($event)"></mat-slide-toggle>\n <span class="toggle-text">公开</span>\n </div> --\x3e\n @if(isDisplayEdit===true){\n <ion-button (click)="editArticle()" style="display: none;">\n <ion-icon slot="icon-only" name="create"></ion-icon>\n </ion-button>\n }\n }\n \x3c!-- 上传轮播图 --\x3e\n @if(isAuthor){\n \x3c!-- <div style="display:flex;justify-content: center;align-items: center;">\n <mat-slide-toggle [checked]="article?.get(\'isPublic\')" (change)="onPublicChange($event)"></mat-slide-toggle>\n <span class="toggle-text">公开</span>\n </div> --\x3e\n \x3c!-- @if(isDisplayUploadImage===true){ --\x3e\n <ion-button (click)="openUploadBanner()">\n \x3c!-- <ion-icon slot="icon-only" name="create"></ion-icon> --\x3e\n <div>上传封面</div>\n </ion-button>\n \x3c!-- } --\x3e\n }\n \x3c!-- 分享 --\x3e\n \x3c!-- (click)="shareArticle()" --\x3e\n <ion-button (click)="openOverlay()">\n <ion-icon slot="icon-only" name="share"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<div class="sharetOverlay" (click)="closeOverlay()" *ngIf="isShare">\n\n <div class="overlay-content">\n <img src="https://static.ws.126.net/163/frontend/backflow-ssr/article/share-cover.98543a0088a4.png" alt="">\n <ion-icon style="color: white;" name="ellipsis-horizontal"></ion-icon>\n\n </div>\n</div>\n<ion-content>\n <div class="page">\n <div style="background-color: #1e1f22;">\n \x3c!-- <div class="btn">\n <button mat-raised-button color="primary">\n <span nz-icon nzType="close" nzTheme="outline"></span>\n </button>\n </div> --\x3e\n \n \x3c!-- 轮播图 --\x3e\n <div class="swiper" (wheel)="onScroll($event)" *ngIf="bannerList?.length">\n <div class="swiper-wrapper">\n <div class="swiper-slide bg-purple-blue" *ngFor="let imgUrl of bannerList">\n <img [src]="imgUrl" alt="" srcset="">\n </div>\n </div>\n </div>\n \n \x3c!-- 标题、关键字 --\x3e\n <div class="article-header">\n <h1 style="color: #5a55d1 !important;">{{article?.get(\'title\')}}</h1>\n </div>\n <div class="chip-list">关键字:\n \x3c!-- <mat-chip *ngFor="let keyword of article?.get(\'keywords\')">{{keyword}}</mat-chip> --\x3e\n <span class="cueWord" *ngFor="let keyword of article?.get(\'keywords\')">\n #{{keyword}}\n </span>\n </div>\n\n @if(isAuthor){\n <div class="article-info">\n <ng-container *ngIf="article?.get(\'writingOptions\')">\n <div (click)="handleNavEvent(\'options\')">设 定:\n \x3c!-- <mat-chip (click)="handleNavEvent(\'outline\')" [disabled]="!article?.get(\'outlineJson\')">\n 大纲\n </mat-chip> --\x3e\n \x3c!-- <mat-chip *ngIf="article?.get(\'writingOptions\')?.writingStyle">{{article?.get(\'writingOptions\')?.writingStyle}}</mat-chip>\n <mat-chip *ngIf="article?.get(\'writingOptions\')?.wordCount">约{{article?.get(\'writingOptions\')?.wordCount}}字</mat-chip> --\x3e\n <span class="cueWord" *ngIf="article?.get(\'writingOptions\')?.writingStyle">{{article?.get(\'writingOptions\')?.writingStyle}}</span>\n <span class="cueWord" *ngIf="article?.get(\'writingOptions\')?.wordCount">约{{article?.get(\'writingOptions\')?.wordCount}}字</span>\n </div>\n </ng-container>\n <ng-container *ngIf="article?.get(\'outlineJson\')">\n <div (click)="handleNavEvent(\'outline\')">提 纲:\n \x3c!-- <mat-chip>{{article?.get(\'outlineJson\') | outlineCount}}字</mat-chip> --\x3e\n <span class="cueWord">{{article?.get(\'outlineJson\') | outlineCount}}字</span>\n </div>\n </ng-container>\n <div *ngIf="article?.id" (click)="handleNavEvent(\'draft\')">稿件箱:\n \x3c!-- <mat-chip>{{draftServ.DraftCountMap?.[article?.id||\'\']?.total || 0}}篇</mat-chip> --\x3e\n <span class="cueWord">{{draftServ.DraftCountMap?.[article?.id||\'\']?.total || 0}}篇</span>\n </div>\n </div>\n }\n \n \x3c!-- 文章内容 --\x3e\n <div class="content">\n <ng-container *ngFor="let item of article?.get(\'contentArray\');let index=index;" >\n \x3c!-- 章节信息 --\x3e\n \x3c!-- <h2 style="margin:5px 0px;" *ngIf="article?.get(\'outlineJson\')?.sections?.[index]?.title">{{article?.get(\'outlineJson\')?.sections?.[index]?.title}}</h2> --\x3e\n <div class="content-block" [innerHTML]="(previewStyle+item?.content)| nzSanitizer: \'html\'"></div>\n </ng-container>\n <div style="height:100px;width:100%;"></div>\n </div>\n </div>\n\n </div>\n\n</ion-content>\n\n<ion-footer class="ion-no-border">\n <ion-toolbar>\n @if(article?.get("author")){\n <ion-buttons slot="start">\n <ion-button>\n <div class="author">\n @if(article?.get("author")?.get("nickname")){ \n <app-comp-user-avatar [user]="article?.get(\'author\')"></app-comp-user-avatar>\n }\n <span>\n {{article?.get("author")?.get("nickname") || (article?.get("author")?.get("realname")| secretText)}}\n </span>\n </div>\n </ion-button>\n </ion-buttons>\n }\n @if(article?.id){\n <ion-buttons slot="end">\n @if(isAuthor){\n <ion-button (click)="delete()" color="medium" size="small">\n <ion-icon slot="icon-only" name="trash"></ion-icon>\n </ion-button>\n }\n <ion-button color="medium" size="small">\n <span class="count">{{article?.get("viewCount")||""}}</span>\n <ion-icon slot="icon-only" name="eye-outline"></ion-icon>\n </ion-button>\n <ion-button [color]="articleServ?.likeMap[article?.id||\'666\']?\'danger\':\'medium\'" size="small" (click)="articleServ.likeArticle(article)">\n <span class="count">{{article?.get("likeCount")||""}}</span>\n <ion-icon slot="icon-only" [name]="\'heart\'+(articleServ?.likeMap[article?.id||\'666\']?\'\':\'-outline\')"></ion-icon>\n </ion-button>\n <ion-button [color]="articleServ?.collectMap[article?.id||\'666\']?\'warn\':\'medium\'" size="small" (click)="articleServ.likeArticle(article,\'collect\')">\n <span class="count">{{article?.get("collectCount")||""}}</span>\n <ion-icon slot="icon-only" [name]="\'star\'+(articleServ?.collectMap[article?.id||\'666\']?\'\':\'-outline\')"></ion-icon>\n </ion-button>\n \x3c!-- <ion-button color="medium" size="small">\n <span class="count">{{article?.get("commentCount")||""}}</span>\n <ion-icon slot="icon-only" name="chatbubble-outline"></ion-icon>\n </ion-button> --\x3e\n </ion-buttons>\n }\n\n </ion-toolbar>\n</ion-footer>',styles:[":host-context(body.dark) .page{background:var(--background-black);background-color:#1e1f22;color:#ddd!important}:host-context(body.dark) .page h1,:host-context(body.dark) .page h2,:host-context(body.dark) .page h3,:host-context(body.dark) .page h4,:host-context(body.dark) .page h5,:host-context(body.dark) .page h6{color:#ddd!important}:host-context(body.dark) .page .content-block{color:#ddd!important;font-size:1.1rem}:host-context(body.dark) .page .content-block h1,:host-context(body.dark) .page .content-block h2,:host-context(body.dark) .page .content-block h3,:host-context(body.dark) .page .content-block h4,:host-context(body.dark) .page .content-block h5,:host-context(body.dark) .page .content-block h6{color:#ddd!important}:host-context(body.dark) .page .toggle-text{color:#ddd!important}.page{-webkit-user-select:none;user-select:none;width:100%;height:100%;display:flex;flex-direction:column;padding:10px;position:relative}.page .btn{z-index:999;position:fixed;top:0;right:0}.page .btn>button{width:80px}.page .article-info{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;padding:0% 3%}.page .article-info div{margin-bottom:3px;display:flex;font-size:1.1rem}.page .article-info div mat-chip{margin-right:3px}.page .article-info div .cueWord{display:flex;flex-wrap:wrap;margin-right:10px}.page .article-header{display:flex;flex-direction:column;justify-content:center;align-items:center}.page .article-header h1{color:#5a55d1!important}.page .chip-list{display:flex;justify-content:flex-start;margin-top:30px;padding:0% 3%;font-size:1.1rem;flex-wrap:wrap}.page .chip-list>mat-chip{margin:0}.page .chip-list .cueWord{display:flex;flex-wrap:wrap;margin-right:10px}.page .content{padding:12px;width:100%}.swiper{width:100%}.swiper .swiper-slide{display:flex;flex-wrap:wrap;justify-content:center;align-items:center}.swiper .swiper-slide img{object-fit:cover}.count{margin-top:-17px}.author{display:flex;align-items:center;text-align:left}.author span{margin-left:7px}.sharetOverlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;display:flex;justify-content:center;align-items:center;z-index:999}.sharetOverlay .overlay-content{position:absolute;top:0;width:100%;padding:20px;box-shadow:0 2px 10px #0000001a}.sharetOverlay .overlay-content ion-icon{position:absolute;top:0;right:11px;font-size:2em;color:#000}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:MatToolbarModule},{kind:"ngmodule",type:MatCardModule},{kind:"ngmodule",type:MatChipsModule},{kind:"ngmodule",type:MatButtonModule},{kind:"ngmodule",type:MatSlideToggleModule},{kind:"component",type:i8$1.MatSlideToggle,selector:"mat-slide-toggle",inputs:["name","id","labelPosition","aria-label","aria-labelledby","aria-describedby","required","color","disabled","disableRipple","tabIndex","checked","hideIcon"],outputs:["change","toggleChange"],exportAs:["matSlideToggle"]},{kind:"ngmodule",type:NzPipesModule},{kind:"pipe",type:i7.NzSanitizerPipe,name:"nzSanitizer"},{kind:"ngmodule",type:NzIconModule},{kind:"component",type:IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]},{kind:"component",type:IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"component",type:IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:IonButtons,selector:"ion-buttons",inputs:["collapse"]},{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:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonFooter,selector:"ion-footer",inputs:["collapse","mode","translucent"]},{kind:"pipe",type:OutlineCountPipe,name:"outlineCount"},{kind:"pipe",type:SecretTextPipe,name:"secretText"},{kind:"component",type:CompUserAvatarComponent,selector:"app-comp-user-avatar",inputs:["user"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmArticlePreviewComponent,decorators:[{type:Component,args:[{selector:"fm-article-preview",standalone:!0,imports:[CommonModule,MatToolbarModule,MatCardModule,MatChipsModule,MatButtonModule,MatSlideToggleModule,MatChipsModule,NzPipesModule,NzIconModule,IonContent,IonToolbar,IonTitle,IonHeader,IonButtons,IonButton,IonIcon,IonFooter,IonToolbar,OutlineCountPipe,SecretTextPipe,CompUserAvatarComponent],template:'<ion-header [translucent]="true" collapse="fade" class="ion-no-border">\n <ion-toolbar>\n \x3c!-- 返回 --\x3e\n <ion-buttons slot="secondary">\n <ion-button (click)="back()">\n <ion-icon slot="icon-only" name="arrow-back-circle"></ion-icon>\n </ion-button>\n @if(isAuthor){\n @if(isDisplayPublic===true){\n <div style="display:flex;justify-content: center;align-items: center;margin-left: 20px;">\n <mat-slide-toggle [checked]="article?.get(\'isPublic\')" (change)="onPublicChange($event)"></mat-slide-toggle>\n <span class="toggle-text">公开</span>\n </div>\n }\n }\n </ion-buttons>\n <ion-title style="font-size: 1.3rem;font-weight: bold;">文章预览</ion-title>\n <ion-buttons slot="primary">\n \x3c!-- 编辑 --\x3e\n @if(isAuthor){\n \x3c!-- <div style="display:flex;justify-content: center;align-items: center;">\n <mat-slide-toggle [checked]="article?.get(\'isPublic\')" (change)="onPublicChange($event)"></mat-slide-toggle>\n <span class="toggle-text">公开</span>\n </div> --\x3e\n @if(isDisplayEdit===true){\n <ion-button (click)="editArticle()" style="display: none;">\n <ion-icon slot="icon-only" name="create"></ion-icon>\n </ion-button>\n }\n }\n \x3c!-- 上传轮播图 --\x3e\n @if(isAuthor){\n \x3c!-- <div style="display:flex;justify-content: center;align-items: center;">\n <mat-slide-toggle [checked]="article?.get(\'isPublic\')" (change)="onPublicChange($event)"></mat-slide-toggle>\n <span class="toggle-text">公开</span>\n </div> --\x3e\n \x3c!-- @if(isDisplayUploadImage===true){ --\x3e\n <ion-button (click)="openUploadBanner()">\n \x3c!-- <ion-icon slot="icon-only" name="create"></ion-icon> --\x3e\n <div>上传封面</div>\n </ion-button>\n \x3c!-- } --\x3e\n }\n \x3c!-- 分享 --\x3e\n \x3c!-- (click)="shareArticle()" --\x3e\n <ion-button (click)="openOverlay()">\n <ion-icon slot="icon-only" name="share"></ion-icon>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<div class="sharetOverlay" (click)="closeOverlay()" *ngIf="isShare">\n\n <div class="overlay-content">\n <img src="https://static.ws.126.net/163/frontend/backflow-ssr/article/share-cover.98543a0088a4.png" alt="">\n <ion-icon style="color: white;" name="ellipsis-horizontal"></ion-icon>\n\n </div>\n</div>\n<ion-content>\n <div class="page">\n <div style="background-color: #1e1f22;">\n \x3c!-- <div class="btn">\n <button mat-raised-button color="primary">\n <span nz-icon nzType="close" nzTheme="outline"></span>\n </button>\n </div> --\x3e\n \n \x3c!-- 轮播图 --\x3e\n <div class="swiper" (wheel)="onScroll($event)" *ngIf="bannerList?.length">\n <div class="swiper-wrapper">\n <div class="swiper-slide bg-purple-blue" *ngFor="let imgUrl of bannerList">\n <img [src]="imgUrl" alt="" srcset="">\n </div>\n </div>\n </div>\n \n \x3c!-- 标题、关键字 --\x3e\n <div class="article-header">\n <h1 style="color: #5a55d1 !important;">{{article?.get(\'title\')}}</h1>\n </div>\n <div class="chip-list">关键字:\n \x3c!-- <mat-chip *ngFor="let keyword of article?.get(\'keywords\')">{{keyword}}</mat-chip> --\x3e\n <span class="cueWord" *ngFor="let keyword of article?.get(\'keywords\')">\n #{{keyword}}\n </span>\n </div>\n\n @if(isAuthor){\n <div class="article-info">\n <ng-container *ngIf="article?.get(\'writingOptions\')">\n <div (click)="handleNavEvent(\'options\')">设 定:\n \x3c!-- <mat-chip (click)="handleNavEvent(\'outline\')" [disabled]="!article?.get(\'outlineJson\')">\n 大纲\n </mat-chip> --\x3e\n \x3c!-- <mat-chip *ngIf="article?.get(\'writingOptions\')?.writingStyle">{{article?.get(\'writingOptions\')?.writingStyle}}</mat-chip>\n <mat-chip *ngIf="article?.get(\'writingOptions\')?.wordCount">约{{article?.get(\'writingOptions\')?.wordCount}}字</mat-chip> --\x3e\n <span class="cueWord" *ngIf="article?.get(\'writingOptions\')?.writingStyle">{{article?.get(\'writingOptions\')?.writingStyle}}</span>\n <span class="cueWord" *ngIf="article?.get(\'writingOptions\')?.wordCount">约{{article?.get(\'writingOptions\')?.wordCount}}字</span>\n </div>\n </ng-container>\n <ng-container *ngIf="article?.get(\'outlineJson\')">\n <div (click)="handleNavEvent(\'outline\')">提 纲:\n \x3c!-- <mat-chip>{{article?.get(\'outlineJson\') | outlineCount}}字</mat-chip> --\x3e\n <span class="cueWord">{{article?.get(\'outlineJson\') | outlineCount}}字</span>\n </div>\n </ng-container>\n <div *ngIf="article?.id" (click)="handleNavEvent(\'draft\')">稿件箱:\n \x3c!-- <mat-chip>{{draftServ.DraftCountMap?.[article?.id||\'\']?.total || 0}}篇</mat-chip> --\x3e\n <span class="cueWord">{{draftServ.DraftCountMap?.[article?.id||\'\']?.total || 0}}篇</span>\n </div>\n </div>\n }\n \n \x3c!-- 文章内容 --\x3e\n <div class="content">\n <ng-container *ngFor="let item of article?.get(\'contentArray\');let index=index;" >\n \x3c!-- 章节信息 --\x3e\n \x3c!-- <h2 style="margin:5px 0px;" *ngIf="article?.get(\'outlineJson\')?.sections?.[index]?.title">{{article?.get(\'outlineJson\')?.sections?.[index]?.title}}</h2> --\x3e\n <div class="content-block" [innerHTML]="(previewStyle+item?.content)| nzSanitizer: \'html\'"></div>\n </ng-container>\n <div style="height:100px;width:100%;"></div>\n </div>\n </div>\n\n </div>\n\n</ion-content>\n\n<ion-footer class="ion-no-border">\n <ion-toolbar>\n @if(article?.get("author")){\n <ion-buttons slot="start">\n <ion-button>\n <div class="author">\n @if(article?.get("author")?.get("nickname")){ \n <app-comp-user-avatar [user]="article?.get(\'author\')"></app-comp-user-avatar>\n }\n <span>\n {{article?.get("author")?.get("nickname") || (article?.get("author")?.get("realname")| secretText)}}\n </span>\n </div>\n </ion-button>\n </ion-buttons>\n }\n @if(article?.id){\n <ion-buttons slot="end">\n @if(isAuthor){\n <ion-button (click)="delete()" color="medium" size="small">\n <ion-icon slot="icon-only" name="trash"></ion-icon>\n </ion-button>\n }\n <ion-button color="medium" size="small">\n <span class="count">{{article?.get("viewCount")||""}}</span>\n <ion-icon slot="icon-only" name="eye-outline"></ion-icon>\n </ion-button>\n <ion-button [color]="articleServ?.likeMap[article?.id||\'666\']?\'danger\':\'medium\'" size="small" (click)="articleServ.likeArticle(article)">\n <span class="count">{{article?.get("likeCount")||""}}</span>\n <ion-icon slot="icon-only" [name]="\'heart\'+(articleServ?.likeMap[article?.id||\'666\']?\'\':\'-outline\')"></ion-icon>\n </ion-button>\n <ion-button [color]="articleServ?.collectMap[article?.id||\'666\']?\'warn\':\'medium\'" size="small" (click)="articleServ.likeArticle(article,\'collect\')">\n <span class="count">{{article?.get("collectCount")||""}}</span>\n <ion-icon slot="icon-only" [name]="\'star\'+(articleServ?.collectMap[article?.id||\'666\']?\'\':\'-outline\')"></ion-icon>\n </ion-button>\n \x3c!-- <ion-button color="medium" size="small">\n <span class="count">{{article?.get("commentCount")||""}}</span>\n <ion-icon slot="icon-only" name="chatbubble-outline"></ion-icon>\n </ion-button> --\x3e\n </ion-buttons>\n }\n\n </ion-toolbar>\n</ion-footer>',styles:[":host-context(body.dark) .page{background:var(--background-black);background-color:#1e1f22;color:#ddd!important}:host-context(body.dark) .page h1,:host-context(body.dark) .page h2,:host-context(body.dark) .page h3,:host-context(body.dark) .page h4,:host-context(body.dark) .page h5,:host-context(body.dark) .page h6{color:#ddd!important}:host-context(body.dark) .page .content-block{color:#ddd!important;font-size:1.1rem}:host-context(body.dark) .page .content-block h1,:host-context(body.dark) .page .content-block h2,:host-context(body.dark) .page .content-block h3,:host-context(body.dark) .page .content-block h4,:host-context(body.dark) .page .content-block h5,:host-context(body.dark) .page .content-block h6{color:#ddd!important}:host-context(body.dark) .page .toggle-text{color:#ddd!important}.page{-webkit-user-select:none;user-select:none;width:100%;height:100%;display:flex;flex-direction:column;padding:10px;position:relative}.page .btn{z-index:999;position:fixed;top:0;right:0}.page .btn>button{width:80px}.page .article-info{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;padding:0% 3%}.page .article-info div{margin-bottom:3px;display:flex;font-size:1.1rem}.page .article-info div mat-chip{margin-right:3px}.page .article-info div .cueWord{display:flex;flex-wrap:wrap;margin-right:10px}.page .article-header{display:flex;flex-direction:column;justify-content:center;align-items:center}.page .article-header h1{color:#5a55d1!important}.page .chip-list{display:flex;justify-content:flex-start;margin-top:30px;padding:0% 3%;font-size:1.1rem;flex-wrap:wrap}.page .chip-list>mat-chip{margin:0}.page .chip-list .cueWord{display:flex;flex-wrap:wrap;margin-right:10px}.page .content{padding:12px;width:100%}.swiper{width:100%}.swiper .swiper-slide{display:flex;flex-wrap:wrap;justify-content:center;align-items:center}.swiper .swiper-slide img{object-fit:cover}.count{margin-top:-17px}.author{display:flex;align-items:center;text-align:left}.author span{margin-left:7px}.sharetOverlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;display:flex;justify-content:center;align-items:center;z-index:999}.sharetOverlay .overlay-content{position:absolute;top:0;width:100%;padding:20px;box-shadow:0 2px 10px #0000001a}.sharetOverlay .overlay-content ion-icon{position:absolute;top:0;right:11px;font-size:2em;color:#000}\n"]}]}],ctorParameters:()=>[{type:i1$1.ActivatedRoute},{type:i1$1.Router},{type:i3$1.MatDialog},{type:i1$3.NavController},{type:i1$3.ModalController},{type:i1$3.AnimationController},{type:ArticleService},{type:i1$3.AlertController},{type:DraftService}],propDecorators:{article:[{type:Input}],isDisplayEdit:[{type:Input}],isDisplayPublic:[{type:Input}],isDisplayUploadImage:[{type:Input}]}});class DialogArticlePreview{constructor(e,t){this.dialogRef=e,this.data=t}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DialogArticlePreview,deps:[{token:i3$1.MatDialogRef},{token:MAT_DIALOG_DATA}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:DialogArticlePreview,isStandalone:!0,selector:"article-preview-dialog",ngImport:i0,template:'<fm-article-preview [article]="data?.article"></fm-article-preview>',isInline:!0,styles:[""],dependencies:[{kind:"ngmodule",type:MatDialogModule},{kind:"component",type:FmArticlePreviewComponent,selector:"fm-article-preview",inputs:["article","isDisplayEdit","isDisplayPublic","isDisplayUploadImage"]}]})}}async function openUploadBannerModal(e,t){const n=await e.create({component:CompUploadBookBannersComponent,componentProps:{articleId:t},breakpoints:[.5,.8,1],initialBreakpoint:.8});await n.present();const{data:o,role:i}=await n.onWillDismiss();return"confirm"===i&&o?.success?(console.log("新章节:",o.banner),o.banner):null}async function TaskArticlePreview(e){if(e?.modal){(await(e?.modal.create({component:FmArticlePreviewComponent,cssClass:"preview-article-modal",componentProps:{article:e?.article,onBreakPointSet:()=>{}},breakpoints:[1],initialBreakpoint:1}))).present()}e?.dialog}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:DialogArticlePreview,decorators:[{type:Component,args:[{selector:"article-preview-dialog",template:'<fm-article-preview [article]="data?.article"></fm-article-preview>',standalone:!0,imports:[MatDialogModule,FmArticlePreviewComponent]}]}],ctorParameters:()=>[{type:i3$1.MatDialogRef},{type:void 0,decorators:[{type:Inject,args:[MAT_DIALOG_DATA]}]}]}),addIcons({closeOutline:closeOutline,copyOutline:copyOutline,cloudDoneOutline:cloudDoneOutline,createOutline:createOutline});class FmArticleEditorComponent{async ngOnInit(){this.article?.id&&this.draftServ?.loadArticleDraft(this.article)}setContent(e,t){t?t.content=e:this.article?.set("content",e),this.contentChanged=!0}selectChange(e){this.selectRange=e?.range,this.selectText=e?.text,this.selectQuill=e?.quill,this.cdRef.detectChanges()}goOptimizeText(e){this.selectChange(e),this.aitab="AI润色",this.optimizeContent()}cancelOptimize(){this.isOptimizing=!1,this.optimize$?.unsubscribe()}optimizeContent(){if(!this.selectText)return;this.isOptimizing=!0;let e=[{role:"user",content:`有段文字要润色,目的是提高其专业性和清晰度。请您调整语言,确保逻辑流畅,并使用行业相关术语。同时,请检查并修正任何语法错误。直接返回润色后内容。这是原文:${this.selectText}`}],t=new FmodeChatCompletion(e);t.model="fmode-4.0-cn-256k",this.optimize$=t.sendCompletion().pipe(finalize((()=>{undefined.complete=!0}))).subscribe((e=>{this.optimizeText=e.content,e?.complete&&(this.isOptimizing=!1,this.optimize$?.unsubscribe(),this.cdRef.detectChanges())}))}copyOptimize(){this.clipboard.copyToClipboard(this.optimizeText)}applyOptimize(){this.selectRange&&(this.selectQuill?.deleteText(this.selectRange?.index,this.selectRange.length),this.selectQuill?.insertText(this.selectRange?.index,this.optimizeText),this.selectRange=void 0)}handleNavEvent(e,t){if("preview"==e&&this.article?.id&&TaskArticlePreview({modal:this.modalCtrl,dialog:this.dialog,article:this.article}),"backmenu"==e&&(this.article?.get("chapter")?.get("book")?.id||this.router.navigateByUrl("/editor/my/home"),this.onClose.emit(!0)),"toggle-aitool"==e&&(this.isDivHidden=!this.isDivHidden),"save"==e&&this.saveArticleContent(),"options"==e){if(this.readOnly)return;let e={};this.doArticleTask([TaskArticleWritingOptions({shareData:e,dialog:this.dialog,editOnly:!0})],e)}if("outline"==e){if(this.readOnly)return;let e={};this.doArticleTask([TaskArticleOutlineEdit({shareData:e,dialog:this.dialog})],e)}if("draft"==e){let e={};if(this.readOnly)return;this.doArticleTask([TaskArticleDraft({isSelectedMode:!0,shareData:e,dialog:this.dialog,modalCtrl:this.modalCtrl})],e,(()=>{}))}}async saveArticleContent(){this.isSaving=!0,this.article?.get("author")?.id||this.article?.set("author",Parse__default.User.current()?.toPointer()),await(this.article?.save()),this.contentChanged=!1,this.isSaving=!1}close(){this.onClose.emit(!0)}async presentAlert(e){const t=await this.alertController.create({header:"提示",subHeader:e?.message,buttons:["好的"]});await t.present()}async aiTab(e){this.aitab=e}async clickTab(e){this.clicktab=e}async dashboardTab(e){this.dashboardtab=e}showContent(e){this.selectedContent=e}constructor(e,t,n,o,i,a,r,s,l){this.modalCtrl=e,this.alertController=t,this.dialog=n,this.cdRef=o,this.clipboard=i,this.draftServ=a,this.router=r,this.nupload=s,this.personServ=l,this.onClose=new EventEmitter,this.readOnly=!1,this.title="此处是标题",this.content="",this.contentChanged=!1,this.selectText="",this.optimizeText="",this.isOptimizing=!1,this.isSaving=!1,this.isDivHidden=!1,this.aitab="AI写作",this.clicktab="语法错误",this.dashboardtab="全部",this.cards=[{title:"全文创作",handle:()=>{this.taskArticleGeneration()},content:"按步骤快速创作一篇完整的文章",imageurl:"../../../assets/images/write.png"},{title:"润色改写",handle:()=>{this.aitab="AI润色"},content:"根据选段,调整语言,逻辑顺畅表达清晰",imageurl:"../../../assets/images/句子续写.png"},{title:"智能摘要(未开放)",handle:()=>{this.presentAlert({message:"暂未开放,敬请期待"})},content:"快速生成文章摘要",imageurl:"../../../assets/images/智能摘要.png"},{title:"句子续写(未开放)",handle:()=>{this.presentAlert({message:"暂未开放,敬请期待"})},content:"根据上文,续写多个句子",imageurl:"../../../assets/images/句子续写.png"},{title:"段落评论(未开放)",handle:()=>{this.presentAlert({message:"暂未开放,敬请期待"})},content:"根据段落特点,进行有针对性的评论",imageurl:"../../../assets/images/产品评论.png"},{title:"模板建议(未开放)",handle:()=>{this.presentAlert({message:"暂未开放,敬请期待"})},content:"欢迎与我们反馈您的需求",imageurl:"../../../assets/images/模板建议.png"}],this.tempFormGroup=new FormGroup({}),this.selectedContent="图片"}enableButton(){document.getElementById("start").disabled=!0}async taskArticleGeneration(e){let t={createNewDraft:!0};taskArticleGeneration((()=>{}),{modalCtrl:this.modalCtrl,article:this.article,person:this.book?.get("person"),book:this.book,shareData:t,dialog:this.dialog,personServ:this.personServ})}doArticleTask(e,t,n){t.article=this.article;let o=this.article?.get("writingOptions");o&&(t.writingOptions=o);let i=e;this.dialog.open(FmAgentTaskComponent,{data:{shareData:t,stepsList:i},disableClose:!0}).afterClosed().subscribe((e=>{n&&n()}))}uploadImage(){let e=this,t=document.createElement("input");t.type="file",t.accept="image/*",t.multiple=!1,t.addEventListener("change",(async()=>{let n=t?.files?.[0];if(n){let t=await e.nupload.upload(n);t?.url&&(this.article?.set("image",t?.url),this.article?.save())}})),t.click()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmArticleEditorComponent,deps:[{token:i1$3.ModalController},{token:i1$3.AlertController},{token:i3$1.MatDialog},{token:i0.ChangeDetectorRef},{token:ClipboardService},{token:DraftService},{token:i1$1.Router},{token:NovaUploadService},{token:PersonService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:FmArticleEditorComponent,isStandalone:!0,selector:"fm-article-editor",inputs:{article:"article",book:"book",readOnly:"readOnly"},outputs:{onClose:"onClose"},providers:[DraftService,NovaUploadService,Diagnostic],viewQueries:[{propertyName:"editorComp",first:!0,predicate:["editorComp"],descendants:!0}],ngImport:i0,template:'<div class="page">\n\n \x3c!-- 导航栏 --\x3e\n <div class="nav" *ngIf="!readOnly">\n <fm-article-editor-topbar #topbar [article]="article" [isSaving]="isSaving" [contentChanged]="contentChanged" (onNavEvent)="handleNavEvent($event)"></fm-article-editor-topbar>\n </div>\n\n <div class="page-container">\n \x3c!-- (scroll)="onScroll($event)" --\x3e\n\n \x3c!-- 编辑文本 --\x3e\n \x3c!-- --\x3e\n <div class="editor-text" [ngClass]="{\'center\':isDivHidden}">\n <div class="editor-main">\n\n <div role="toolbar" class="ql-toolbar ql-snow" *ngIf="false">\n <span class="ql-formats"><span class="ql-header ql-picker"><span class="ql-picker-label" tabindex="0" role="button" aria-expanded="false" aria-controls="ql-picker-options-0"><svg viewBox="0 0 18 18"><polygon class="ql-stroke" points="7 11 9 13 11 11 7 11"></polygon><polygon class="ql-stroke" points="7 7 9 5 11 7 7 7"></polygon></svg></span><span class="ql-picker-options" aria-hidden="true" tabindex="-1" id="ql-picker-options-0"><span tabindex="0" role="button" class="ql-picker-item" data-value="1"></span><span tabindex="0" role="button" class="ql-picker-item" data-value="2"></span><span tabindex="0" role="button" class="ql-picker-item" data-value="3"></span><span tabindex="0" role="button" class="ql-picker-item" data-value="4"></span><span tabindex="0" role="button" class="ql-picker-item"></span></span></span><select class="ql-header" style="display: none;"><option value="1"></option><option value="2"></option><option value="3"></option><option value="4"></option><option selected="selected"></option></select></span>\n <span class="ql-formats"><button type="button" class="ql-bold" aria-pressed="false" aria-label="bold"><svg viewBox="0 0 18 18"><path class="ql-stroke" d="M5,4H9.5A2.5,2.5,0,0,1,12,6.5v0A2.5,2.5,0,0,1,9.5,9H5A0,0,0,0,1,5,9V4A0,0,0,0,1,5,4Z"></path><path class="ql-stroke" d="M5,9h5.5A2.5,2.5,0,0,1,13,11.5v0A2.5,2.5,0,0,1,10.5,14H5a0,0,0,0,1,0,0V9A0,0,0,0,1,5,9Z"></path></svg></button><button type="button" class="ql-italic" aria-pressed="false" aria-label="italic"><svg viewBox="0 0 18 18"><line class="ql-stroke" x1="7" x2="13" y1="4" y2="4"></line><line class="ql-stroke" x1="5" x2="11" y1="14" y2="14"></line><line class="ql-stroke" x1="8" x2="10" y1="14" y2="4"></line></svg></button><button type="button" class="ql-underline" aria-pressed="false" aria-label="underline"><svg viewBox="0 0 18 18"><path class="ql-stroke" d="M5,3V9a4.012,4.012,0,0,0,4,4H9a4.012,4.012,0,0,0,4-4V3"></path><rect class="ql-fill" height="1" rx="0.5" ry="0.5" width="12" x="3" y="15"></rect></svg></button></span>\n <span class="ql-formats"><button type="button" class="ql-list" aria-pressed="false" value="bullet" aria-label="list: bullet"><svg viewBox="0 0 18 18"><line class="ql-stroke" x1="6" x2="15" y1="4" y2="4"></line><line class="ql-stroke" x1="6" x2="15" y1="9" y2="9"></line><line class="ql-stroke" x1="6" x2="15" y1="14" y2="14"></line><line class="ql-stroke" x1="3" x2="3" y1="4" y2="4"></line><line class="ql-stroke" x1="3" x2="3" y1="9" y2="9"></line><line class="ql-stroke" x1="3" x2="3" y1="14" y2="14"></line></svg></button></span>\n <span class="ql-formats"><span class="ql-align ql-picker ql-icon-picker"><span class="ql-picker-label" tabindex="0" role="button" aria-expanded="false" aria-controls="ql-picker-options-1"><svg viewBox="0 0 18 18"><line class="ql-stroke" x1="3" x2="15" y1="9" y2="9"></line><line class="ql-stroke" x1="3" x2="13" y1="14" y2="14"></line><line class="ql-stroke" x1="3" x2="9" y1="4" y2="4"></line></svg></span><span class="ql-picker-options" aria-hidden="true" tabindex="-1" id="ql-picker-options-1"><span tabindex="0" role="button" class="ql-picker-item"><svg viewBox="0 0 18 18"><line class="ql-stroke" x1="3" x2="15" y1="9" y2="9"></line><line class="ql-stroke" x1="3" x2="13" y1="14" y2="14"></line><line class="ql-stroke" x1="3" x2="9" y1="4" y2="4"></line></svg></span><span tabindex="0" role="button" class="ql-picker-item" data-value="center"><svg viewBox="0 0 18 18"><line class="ql-stroke" x1="15" x2="3" y1="9" y2="9"></line><line class="ql-stroke" x1="14" x2="4" y1="14" y2="14"></line><line class="ql-stroke" x1="12" x2="6" y1="4" y2="4"></line></svg></span><span tabindex="0" role="button" class="ql-picker-item" data-value="right"><svg viewBox="0 0 18 18"><line class="ql-stroke" x1="15" x2="3" y1="9" y2="9"></line><line class="ql-stroke" x1="15" x2="5" y1="14" y2="14"></line><line class="ql-stroke" x1="15" x2="9" y1="4" y2="4"></line></svg></span><span tabindex="0" role="button" class="ql-picker-item" data-value="justify"><svg viewBox="0 0 18 18"><line class="ql-stroke" x1="15" x2="3" y1="9" y2="9"></line><line class="ql-stroke" x1="15" x2="3" y1="14" y2="14"></line><line class="ql-stroke" x1="15" x2="3" y1="4" y2="4"></line></svg></span></span></span><select class="ql-align" style="display: none;"><option selected="selected"></option><option value="center"></option><option value="right"></option><option value="justify"></option></select></span>\n <span class="ql-formats"><button type="button" class="ql-code-block" aria-pressed="false" aria-label="code-block"><svg viewBox="0 0 18 18"><polyline class="ql-even ql-stroke" points="5 7 3 9 5 11"></polyline><polyline class="ql-even ql-stroke" points="13 7 15 9 13 11"></polyline><line class="ql-stroke" x1="10" x2="8" y1="5" y2="13"></line></svg></button></span>\n <span class="ql-formats"><button class="ql-ai-optimize">AI</button></span>\n </div>\n\n <div class="text-header">\n <input [ngModel]="article?.get(\'title\')" (ngModelChange)="article?.set(\'title\',$event)" type="text" />\n \x3c!-- <quill-editor [(ngModel)]="title" [modules]="{toolbar: true}"></quill-editor> --\x3e\n </div>\n <div class="article-info">\n <ng-container *ngIf="article?.get(\'keywords\')?.length">\n <div>关键字:<mat-chip *ngFor="let key of article?.get(\'keywords\')">{{key}}</mat-chip></div>\n </ng-container>\n <ng-container *ngIf="article?.get(\'writingOptions\')">\n <div (click)="handleNavEvent(\'options\')">设 定:\n <mat-chip *ngIf="article?.get(\'writingOptions\')?.writingStyle">{{article?.get(\'writingOptions\')?.writingStyle}}</mat-chip>\n <mat-chip *ngIf="article?.get(\'writingOptions\')?.wordCount">约{{article?.get(\'writingOptions\')?.wordCount}}字</mat-chip></div>\n </ng-container>\n <ng-container *ngIf="article?.get(\'outlineJson\')?.length">\n <div (click)="handleNavEvent(\'outline\')">提 纲:<mat-chip>{{article?.get(\'outlineJson\') | outlineCount}}字</mat-chip></div>\n </ng-container>\n <div *ngIf="article?.id" (click)="handleNavEvent(\'draft\')">稿件箱:<mat-chip>{{draftServ.DraftCountMap?.[article?.id||\'\']?.total || 0}}篇</mat-chip></div>\n </div>\n\n <div class="article-content">\n \x3c!-- 文本编辑区域:仅content正文 --\x3e\n <ng-container *ngIf="!article?.get(\'contentArray\')?.length">\n <fm-text-quill #textQuill [readOnly]="readOnly" [content]="article?.get(\'content\')" (onContentChange)="setContent($event)"\n (onAIClick)="goOptimizeText($event)" (onSelectChange)="selectChange($event)"\n ></fm-text-quill>\n </ng-container>\n \x3c!-- 文本编辑区域:含大纲正文 --\x3e\n <ng-container *ngIf="article?.get(\'contentArray\')?.length">\n <ng-container *ngFor="let item of article?.get(\'contentArray\');let index=index;">\n \x3c!-- 章节信息 --\x3e\n \x3c!-- <h2 style="margin:0px;padding-left:12px;" *ngIf="article?.get(\'outlineJson\')?.sections?.[index]?.title">{{article?.get(\'outlineJson\')?.sections?.[index]?.title}}</h2> --\x3e\n <fm-text-quill #textQuill [readOnly]="readOnly" [content]="item?.content" (onContentChange)="setContent($event,item)"\n (onAIClick)="goOptimizeText($event)" (onSelectChange)="selectChange($event)"\n ></fm-text-quill>\n </ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n\n\n\n \x3c!-- AI工具 --\x3e\n <div *ngIf="!readOnly && !isDivHidden" class="page-right">\n <div class="nav-ai">\n \x3c!-- AI功能按钮 --\x3e\n \x3c!-- <div class="ai-btn">\n <button (click)="showContent(\'AI-写作\')">AI写作</button>\n <button (click)="showContent(\'AI-润色\')">AI润色</button>\n <button (click)="showContent(\'校阅\')">校阅</button>\n <button (click)="showContent(\'图片\')">图片</button>\n <button (click)="showContent(\'评论\')">评论</button>\n </div> --\x3e\n\n <ul class="ai-btn">\n <li class="active0" (click)="aiTab(\'AI写作\')" [ngClass]="{ \'active1\': aitab == \'AI写作\' }">\n <div>AI写作</div>\n </li>\n <li class="active0" (click)="aiTab(\'AI润色\')" [ngClass]="{ \'active1\': aitab == \'AI润色\' }">\n <div>AI润色</div>\n </li>\n \x3c!-- <li class="active0" (click)="aiTab(\'校阅\')" [ngClass]="{ \'active1\': aitab == \'校阅\' }">\n <div>校阅</div>\n </li> --\x3e\n <li class="active0" (click)="aiTab(\'AI配图\')" [ngClass]="{ \'active1\': aitab == \'AI配图\' }">\n <div>AI配图</div>\n </li>\n\n </ul>\n \x3c!-- AI功能退出按钮 --\x3e\n <div>\n <ion-icon class="icon" name="close-outline" (click)="this.isDivHidden = !this.isDivHidden;"></ion-icon>\n </div>\n\n </div>\n\n\n \x3c!-- 工具面板 --\x3e\n <div class="ai-panel">\n\n <div *ngIf="aitab==\'AI写作\'" class="ai-write">\n \x3c!-- 搜索 --\x3e\n <div class="search-bar">\n <ion-searchbar color="light" placeholder="搜索模板"></ion-searchbar>\n </div>\n\n <div class="ai-tool-grid">\n <ng-container *ngFor="let card of cards">\n <ion-card class="card" style="margin-left: 5%;max-width:215px;" (click)="card?.handle()">\n <ion-card-header>\n <ion-card-title class="card-image">\n <img src="{{card.imageurl}}" width="25" height="25" alt="write">\n </ion-card-title>\n <ion-card-subtitle>{{card.title}}</ion-card-subtitle>\n </ion-card-header>\n\n <ion-card-content>\n {{card.content}}\n </ion-card-content>\n </ion-card>\n </ng-container>\n </div>\n\n </div>\n <div *ngIf="aitab==\'AI润色\'" class="ai-polish" [formGroup]="tempFormGroup">\n <div class="ai-polish-input">\n <mat-form-field style="width:95%;">\n <mat-label>输入或选中左侧文本开始润色</mat-label>\n <textarea matInput [(ngModel)]="selectText" [ngModelOptions]="{standalone: true}" rows="10"></textarea>\n </mat-form-field>\n\n \x3c!-- <textarea [(ngModel)]="selectText" rows="10" formControlName="comment" nz-input placeholder="输入或选中左侧文本开始润色"></textarea> --\x3e\n </div>\n <div class="ai-polish-button">\n <button *ngIf="!isOptimizing" mat-raised-button color="primary" (click)="optimizeContent()">开始润色</button>\n <button *ngIf="isOptimizing" mat-raised-button color="warn" (click)="cancelOptimize()">停止润色</button>\n \x3c!-- <ion-button id="start" [disabled]="false" (click)="enableButton()">开始润色</ion-button> --\x3e\n </div>\n <div class="ai-polish-input">\n <mat-form-field style="width:95%;">\n <mat-label>生成内容</mat-label>\n <textarea matInput [(ngModel)]="optimizeText" [ngModelOptions]="{standalone: true}" rows="10"></textarea>\n </mat-form-field>\n </div>\n <div class="ai-polish-button">\n <button *ngIf="selectRange?.length" mat-raised-button (click)="applyOptimize()"><mat-icon fontIcon="flip"></mat-icon>替换</button>\n <button mat-raised-button (click)="copyOptimize()"><mat-icon fontIcon="content_copy"></mat-icon>复制</button>\n \x3c!-- <ion-button id="start" [disabled]="false" (click)="enableButton()">开始润色</ion-button> --\x3e\n </div>\n \x3c!-- <div class="copy">\n <ion-icon name="copy-outline" style="color:#4e80f4" (click)="Copy(polishContent)"></ion-icon>\n </div> --\x3e\n </div>\n <div *ngIf="aitab==\'校阅\'" class="ai-proofread">\n\n <div class="showItems-container">\n <div class="showItems">\n\n <div class="showItem" (click)="clickTab(\'内容建议\')" [ngClass]="{ \'active1\': clicktab == \'内容建议\' }">\n <div style="line-height: 12px;">\n <svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M11 10H5M7 14H5M13 6H5M17 9.5V5.8C17 4.11984 17 3.27976 16.673 2.63803C16.3854 2.07354 15.9265 1.6146 15.362 1.32698C14.7202 1 13.8802 1 12.2 1H5.8C4.11984 1 3.27976 1 2.63803 1.32698C2.07354 1.6146 1.6146 2.07354 1.32698 2.63803C1 3.27976 1 4.11984 1 5.8V16.2C1 17.8802 1 18.7202 1.32698 19.362C1.6146 19.9265 2.07354 20.3854 2.63803 20.673C3.27976 21 4.11984 21 5.8 21H8.5M19 21L17.5 19.5M18.5 17C18.5 18.933 16.933 20.5 15 20.5C13.067 20.5 11.5 18.933 11.5 17C11.5 15.067 13.067 13.5 15 13.5C16.933 13.5 18.5 15.067 18.5 17Z"\n stroke="#1570EF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <span>内容建议</span>\n\n\n </div>\n\n <div class="showItem" (click)="clickTab(\'事实验证\')" [ngClass]="{\'active1\': clicktab==\'事实验证\'}">\n <div style="line-height: 12px;">\n <svg width="18" height="22" viewBox="0 0 18 22" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M11 1.26953V5.40007C11 5.96012 11 6.24015 11.109 6.45406C11.2049 6.64222 11.3578 6.7952 11.546 6.89108C11.7599 7.00007 12.0399 7.00007 12.6 7.00007H16.7305M6 15L8 17L12.5 12.5M11 1H5.8C4.11984 1 3.27976 1 2.63803 1.32698C2.07354 1.6146 1.6146 2.07354 1.32698 2.63803C1 3.27976 1 4.11984 1 5.8V16.2C1 17.8802 1 18.7202 1.32698 19.362C1.6146 19.9265 2.07354 20.3854 2.63803 20.673C3.27976 21 4.11984 21 5.8 21H12.2C13.8802 21 14.7202 21 15.362 20.673C15.9265 20.3854 16.3854 19.9265 16.673 19.362C17 18.7202 17 17.8802 17 16.2V7L11 1Z"\n stroke="#D92D20" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <span>事实验证</span>\n </div>\n\n <div class="showItem" (click)="clickTab(\'全文总结\')" [ngClass]="{\'active1\': clicktab==\'全文总结\'}">\n <div style="line-height: 12px;"> <svg width="20" height="22" viewBox="0 0 16 20" fill="none"\n xmlns="http://www.w3.org/2000/svg">\n <path\n d="M14.1668 5.83329V5.66663C14.1668 4.26649 14.1668 3.56643 13.8943 3.03165C13.6547 2.56124 13.2722 2.17879 12.8018 1.93911C12.267 1.66663 11.567 1.66663 10.1668 1.66663H4.8335C3.43336 1.66663 2.7333 1.66663 2.19852 1.93911C1.72811 2.17879 1.34566 2.56124 1.10598 3.03165C0.833496 3.56643 0.833496 4.26649 0.833496 5.66663V14.3333C0.833496 15.7334 0.833496 16.4335 1.10598 16.9683C1.34566 17.4387 1.72811 17.8211 2.19852 18.0608C2.7333 18.3333 3.43336 18.3333 4.8335 18.3333H7.91683M7.91683 9.16663H4.16683M7.0835 12.5H4.16683M10.8335 5.83329H4.16683M12.5002 15V10.4166C12.5002 9.72627 13.0598 9.16663 13.7502 9.16663C14.4405 9.16663 15.0002 9.72627 15.0002 10.4166V15C15.0002 16.3807 13.8809 17.5 12.5002 17.5C11.1195 17.5 10.0002 16.3807 10.0002 15V11.6666"\n stroke="#F79009" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <span>全文总结</span>\n </div>\n\n </div>\n </div>\n\n <div class="showItem-content">\n <div *ngIf="clicktab==\'语法错误\'" class="grammar-panel">\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n\n </div>\n <div *ngIf="clicktab==\'内容建议\'" class="suggest-panel">\n\n <div class="content-suggest">\n <div style="line-height: 12px;">\n <svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M11 10H5M7 14H5M13 6H5M17 9.5V5.8C17 4.11984 17 3.27976 16.673 2.63803C16.3854 2.07354 15.9265 1.6146 15.362 1.32698C14.7202 1 13.8802 1 12.2 1H5.8C4.11984 1 3.27976 1 2.63803 1.32698C2.07354 1.6146 1.6146 2.07354 1.32698 2.63803C1 3.27976 1 4.11984 1 5.8V16.2C1 17.8802 1 18.7202 1.32698 19.362C1.6146 19.9265 2.07354 20.3854 2.63803 20.673C3.27976 21 4.11984 21 5.8 21H8.5M19 21L17.5 19.5M18.5 17C18.5 18.933 16.933 20.5 15 20.5C13.067 20.5 11.5 18.933 11.5 17C11.5 15.067 13.067 13.5 15 13.5C16.933 13.5 18.5 15.067 18.5 17Z"\n stroke="#1570EF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <div class="content-suggest-title">内容建议</div>\n </div>\n\n <div class="content">\n <div class="content-title"> 这篇文章介绍的是七个关于中国企业家的管理之道的自传小说章节标题,旨在展示企业家们的个人经历、管理理念和人生哲学。\n </div>\n <div class="content-title">改进建议:</div>\n <ol>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n </ol>\n\n\n </div>\n </div>\n <div *ngIf="clicktab==\'事实验证\'" class="verify-panel">\n <div class="dashboard">\n <div class="item" (click)="dashboardTab(\'全部\')" [ngClass]="{\'itemChoose\': dashboardtab==\'全部\'}">\n <div class="icon">\n <div class="statusIcon" style="border: 1px solid black; box-sizing: border-box;"></div>\n </div>\n <div class="text">全部</div>\n <div class="number">28</div>\n </div>\n\n <div class="item" (click)="dashboardTab(\'通过\')" [ngClass]="{\'itemChoose\': dashboardtab==\'通过\'}">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n <div class="number">9</div>\n </div>\n\n <div class="item" (click)="dashboardTab(\'不通过\')" [ngClass]="{\'itemChoose\': dashboardtab==\'不通过\'}">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(217, 45, 32);"><svg\n xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">\n <path d="M7 17L17 7" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n <path d="M7 7L17 17" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </svg></div>\n </div>\n <div class="text" style="color: rgb(217, 45, 32);">不通过</div>\n <div class="number">1</div>\n </div>\n <div class="item" (click)="dashboardTab(\'无法判断\')" [ngClass]="{\'itemChoose\': dashboardtab==\'无法判断\'}">\n <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="3 3 18 18"\n fill="none">\n <path\n d="M7.8824 8.679C7.88035 8.72744 7.88822 8.77579 7.90555 8.82107C7.92287 8.86636 7.94927 8.90762 7.98313 8.94232C8.01699 8.97703 8.05759 9.00444 8.10244 9.02287C8.14728 9.0413 8.19542 9.05036 8.2439 9.0495H9.4814C9.6884 9.0495 9.8534 8.88 9.8804 8.6745C10.0154 7.6905 10.6904 6.9735 11.8934 6.9735C12.9224 6.9735 13.8644 7.488 13.8644 8.7255C13.8644 9.678 13.3034 10.116 12.4169 10.782C11.4074 11.5155 10.6079 12.372 10.6649 13.7625L10.6694 14.088C10.671 14.1864 10.7112 14.2803 10.7813 14.3493C10.8515 14.4183 10.946 14.457 11.0444 14.457H12.2609C12.3604 14.457 12.4557 14.4175 12.5261 14.3472C12.5964 14.2768 12.6359 14.1815 12.6359 14.082V13.9245C12.6359 12.8475 13.0454 12.534 14.1509 11.6955C15.0644 11.001 16.0169 10.23 16.0169 8.6115C16.0169 6.345 14.1029 5.25 12.0074 5.25C10.1069 5.25 8.0249 6.135 7.8824 8.679ZM10.2179 17.3235C10.2179 18.123 10.8554 18.714 11.7329 18.714C12.6464 18.714 13.2749 18.123 13.2749 17.3235C13.2749 16.4955 12.6449 15.9135 11.7314 15.9135C10.8554 15.9135 10.2179 16.4955 10.2179 17.3235Z"\n fill="#475467"></path>\n </svg></div>\n <div class="text">无法判断</div>\n <div class="number">18</div>\n </div>\n </div>\n\n <div class="verify-card-list">\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n </div>\n </div>\n <div *ngIf="clicktab==\'全文总结\'" class="summary-panel">\n\n <div class="text-summary">\n <div style="line-height: 12px;">\n <svg width="20" height="22" viewBox="0 0 16 20" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M14.1668 5.83329V5.66663C14.1668 4.26649 14.1668 3.56643 13.8943 3.03165C13.6547 2.56124 13.2722 2.17879 12.8018 1.93911C12.267 1.66663 11.567 1.66663 10.1668 1.66663H4.8335C3.43336 1.66663 2.7333 1.66663 2.19852 1.93911C1.72811 2.17879 1.34566 2.56124 1.10598 3.03165C0.833496 3.56643 0.833496 4.26649 0.833496 5.66663V14.3333C0.833496 15.7334 0.833496 16.4335 1.10598 16.9683C1.34566 17.4387 1.72811 17.8211 2.19852 18.0608C2.7333 18.3333 3.43336 18.3333 4.8335 18.3333H7.91683M7.91683 9.16663H4.16683M7.0835 12.5H4.16683M10.8335 5.83329H4.16683M12.5002 15V10.4166C12.5002 9.72627 13.0598 9.16663 13.7502 9.16663C14.4405 9.16663 15.0002 9.72627 15.0002 10.4166V15C15.0002 16.3807 13.8809 17.5 12.5002 17.5C11.1195 17.5 10.0002 16.3807 10.0002 15V11.6666"\n stroke="#F79009" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <div class="text-summary-title">全文总结</div>\n </div>\n\n <div class="text">\n <div class="text-title">概括:</div>\n\n <p>\n 这本自传小说由企业家曹国熊撰写,讲述了他如何从贫穷孩子成长为成功企业家的经历和管理智慧,同时通过不同章节探讨了企业家的成长、团队合作、创新驱动、领导力培养、面对危机和可持续发展等主题。\n </p>\n <div class="text-title">要点:</div>\n <ul>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n </ul>\n\n\n\n\n\n\n </div>\n </div>\n </div>\n\n\n\n </div>\n <div *ngIf="aitab==\'AI配图\'" class="ai-img">\n <mat-accordion multi>\n <mat-expansion-panel expanded="true">\n <mat-expansion-panel-header>\n <mat-panel-title>文章封面</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="image" (click)="uploadImage()">\n <img [src]="article?.get(\'image\') || \'/assets/img/icon/addphoto.png\'" alt="">\n </div>\n </mat-expansion-panel>\n\n <mat-expansion-panel expanded="false">\n <mat-expansion-panel-header>\n <mat-panel-title>段落插图</mat-panel-title>\n </mat-expansion-panel-header>\n \n <div class="ai-img-search">\n\n <div class="ai-img-search-input">\n <input type="text" nz-input placeholder="请输入图片描述" />\n </div>\n\n <div class="ai-img-search-button">\n <ion-button>\n <ion-icon name="search-outline"></ion-icon>\n 查找\n </ion-button>\n </div>\n\n </div>\n\n <div class="img-tip">\n <img class="bg-img" src="../../../assets/images/火箭2.png">\n </div>\n <div class="ai-img-tip">\n <h1>输入描述,自动配图</h1>\n\n </div>\n\n <div class="ai-img-tip-list">\n <div class="pce-inner-tip-point"></div>\n <span>\n 根据您对图片的描述,智能匹配相关图片\n </span>\n </div>\n </mat-expansion-panel>\n </mat-accordion>\n\n\n </div>\n\n\n </div>\n </div>\n\n\n\n\n </div>\n</div>',styles:['@charset "UTF-8";.image{width:100%;height:240px;overflow:hidden;display:flex;justify-content:center;align-items:center}.image img{height:100%;object-fit:contain;height:auto;transition:transform .2s}.image:hover img{transform:scale(1.2)}.page{background-color:#fafafa;height:100%;width:100%;display:flex;flex-direction:column;overflow:hidden}.page .nav{position:sticky;top:0;z-index:3}.page .icon{width:20px;height:20px;margin:0 10px 0 5%}.page .page-container{display:flex;height:calc(100vh - 120px)}.page .page-container .center{margin:5vh auto!important}.page .page-container .editor-text{display:flex;justify-content:center;flex:1;right:0;height:auto;min-height:75vh;min-width:35%;box-shadow:#00000026 1px 2px 8px;background-color:#fff;overflow:visible}.page .page-container .editor-text .editor-main{width:100%;height:100%;display:flex;flex-direction:column;overflow:hidden}.page .page-container .editor-text .editor-main .text-header{display:flex;justify-content:center;padding-top:10px}.page .page-container .editor-text .editor-main .text-header input,.page .page-container .editor-text .editor-main .text-header input:focus{width:100%;text-align:center;border:none;font-size:22px;font-weight:700;box-shadow:none;outline:none}.page .page-container .editor-text .editor-main .article-info{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center}.page .page-container .editor-text .editor-main .article-info div{padding-left:5px;padding-right:5px;margin-bottom:3px}.page .page-container .editor-text .editor-main .article-info div mat-chip{margin-right:3px}.page .page-container .editor-text .editor-main .article-content{flex:1;min-height:50vh;overflow-y:auto}.page .page-container .page-right{height:calc(80vh - 10px);margin-top:6px;margin-left:3px;min-width:480px;background-color:#fafafa;opacity:1;transition:opacity 2s ease-in-out;overflow-y:hidden;overflow-x:hidden}.page .page-container .page-right .nav-ai{background-color:#fafafa;display:flex;width:100%;justify-content:space-between;z-index:3;position:sticky;top:0}.page .page-container .page-right .nav-ai ul{width:100%;list-style-type:none;padding:0;margin:0;display:flex;flex-wrap:wrap;justify-content:space-around}.page .page-container .page-right .nav-ai ul .active0{position:relative;padding:5px 15px;margin:0 5px 10px;font-size:18px;font-weight:700;color:#8e8e8e;border-radius:5px;transition:.3s}.page .page-container .page-right .nav-ai ul .active1{color:#333}.page .page-container .page-right .nav-ai ul .active1 div:after{content:"";position:absolute;left:0;bottom:0;width:100%;border-bottom:4px solid #8e8e8e;border-radius:10px;margin-bottom:-6px}.page .page-container .page-right .nav-ai ul li div{cursor:pointer;text-align:center;position:relative}.page .page-container .page-right .nav-ai .icon{cursor:pointer;margin-top:20%;width:25px;height:25px;align-content:center}.page .page-container .page-right .ai-panel{right:2%;background-color:#fafafa;width:95%;z-index:1}.page .page-container .page-right .ai-panel .ai-tool-grid{display:flex;flex-wrap:wrap}.page .page-container .page-right .ai-panel .ai-tool-grid ion-card{max-width:33%}.page .page-container .page-right .ai-panel div::-webkit-scrollbar{display:none}.page .page-container .page-right .ai-panel .ai-write{width:515px}.page .page-container .page-right .ai-panel .ai-write .search-bar{height:40px;width:100%;margin-left:15px}.page .page-container .page-right .ai-panel .ai-write ion-col{background-color:#fafafa;border:solid 2px #fafafa;text-align:center;padding:0;margin-left:3%}.page .page-container .page-right .ai-panel .ai-write .card{max-height:150px;max-width:220px;height:15vh;width:16vw;cursor:pointer}.page .page-container .page-right .ai-panel .ai-write .card .card-image{margin-right:80%}.page .page-container .page-right .ai-panel .ai-write .card ion-card-header{padding:6%}.page .page-container .page-right .ai-panel .ai-write .card ion-card-subtitle{font-weight:600;text-align:left}.page .page-container .page-right .ai-panel .ai-write .card ion-card-content{text-align:left;white-space:pre-line;font-size:12px;margin-left:6%;padding:0}.page .page-container .page-right .ai-panel .ai-write .card-image{background:#fff;box-shadow:0 1px 4px #0000000a,0 4px 10px #00000014;width:30px;height:30px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex:none}.page .page-container .page-right .ai-panel .ai-polish{margin-top:10px;background-color:#fafafa}.page .page-container .page-right .ai-panel .ai-polish textarea.ant-input{max-width:93%;height:auto;min-height:32px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.page .page-container .page-right .ai-panel .ai-polish ::-webkit-scrollbar{width:4px;border-radius:3px}.page .page-container .page-right .ai-panel .ai-polish ::-webkit-scrollbar-thumb{background-color:#dddee0;border-radius:2px}.page .page-container .page-right .ai-panel .ai-polish .ai-polish-button{text-align:right;margin-right:21px}.page .page-container .page-right .ai-panel .ai-polish .ai-polish-button button{margin-left:15px}.page .page-container .page-right .ai-panel .ai-polish .copy{text-align:right;margin-right:7%;cursor:pointer}.page .page-container .page-right .ai-panel .ai-proofread{height:73vh;margin-top:2%;position:sticky;top:0}.page .page-container .page-right .ai-panel .ai-proofread .showItems-container{width:100%;z-index:2}.page .page-container .page-right .ai-panel .ai-proofread .showItems-container .showItems{display:flex;justify-content:space-around;position:sticky;top:0;padding-left:15px;padding-right:15px}.page .page-container .page-right .ai-panel .ai-proofread .showItems-container .showItems .showItem{display:flex;flex-shrink:0;cursor:pointer;gap:8px;padding:12px 15px;background:#fff;border:1px solid #f9fafb;box-shadow:0 1px 2px #1018280d;font-size:16px;font-weight:400}.page .page-container .page-right .ai-panel .ai-proofread .showItems-container .showItems .active1{color:#333;font-weight:700}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .grammar-panel{margin-top:10%;margin-left:2.3%;height:61vh;overflow-y:scroll}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error{display:flex;text-align:center;margin-bottom:5%;width:90%;height:6vh;margin-left:4%;background:#fff;border:1px solid #f9fafb;box-shadow:0 1px 2px #1018280d;line-height:6vh}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .alert-point{color:#ff7a7a;margin-left:6%;margin-right:5%;font-size:20px}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .alert-point-gray{color:#8189a9;font-size:10px;margin-right:1%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .error-content{margin-right:4%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .right-content{margin-left:4%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .suggest-panel{position:sticky;top:0;margin-top:4%;margin-left:6.8%;width:91%;background-color:#fff}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .suggest-panel .content-suggest{display:flex;cursor:pointer;padding:5% 3%;height:6%;width:100%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .suggest-panel .content-suggest .content-suggest-title{margin-left:3%;font-size:16px;font-weight:400}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .suggest-panel .content{width:98%;height:55vh;overflow-y:scroll}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .suggest-panel .content .content-title{margin:3% 4%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .suggest-panel .content ol{margin:3% 4%;counter-reset:section}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .suggest-panel .content li:before{counter-increment:section;content:"Section " counter(section) ". "}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel{margin-top:2%;margin-left:6.8%;width:95%;margin-bottom:2%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .icon{width:16px;height:16px;display:inline-block;margin-top:3px}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .dashboard{display:flex;margin-left:-1%;margin-top:3%;height:5%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .itemChoose{background-color:#eaecf0}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .item{display:flex;height:76%;width:23%;padding:6px 8px;cursor:pointer}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .item .text{font-weight:bolder;margin-right:4%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .item .number{font-weight:bolder;margin-right:1%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .statusIcon{border-radius:50%;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:18px;height:18px}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list{height:61vh;overflow-y:scroll}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .card{box-shadow:0 1px 2px #1018280f,0 1px 3px #1018281a;width:95%;height:auto;margin-top:3%;padding:2% 3%;background-color:#fff}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .card .item{display:flex}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .card .card-content{margin-top:3%;margin-bottom:3%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .statusIcon{border-radius:50%;width:18px;height:18px}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .summary-panel{margin-top:2%;margin-left:6.8%;width:91%;background-color:#fff}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .summary-panel .text-summary{display:flex;cursor:pointer;padding:5% 3%;height:6%;width:100%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .summary-panel .text-summary .text-summary-title{margin-left:3%;font-size:16px;font-weight:400}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .summary-panel .text{width:100%;height:57vh;overflow-y:scroll}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .summary-panel .text .text-title{margin:3% 4%;font-weight:700}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .summary-panel .text p{margin:3% 4%}.page .page-container .page-right .ai-panel .ai-img{width:480px}.page .page-container .page-right .ai-panel .ai-img .ai-img-search{display:flex;height:4%;width:100%;margin-left:4%;margin-top:5%}.page .page-container .page-right .ai-panel .ai-img .ai-img-search .ai-img-search-input{width:65%}.page .page-container .page-right .ai-panel .ai-img .ai-img-search .ai-img-search-input input{height:100%}.page .page-container .page-right .ai-panel .ai-img .ai-img-search .ai-img-search-button{margin-left:5%;margin-top:-.8%}.page .page-container .page-right .ai-panel .ai-img .img-tip{display:flex;text-align:center;justify-content:center;margin-top:20%;width:95%}.page .page-container .page-right .ai-panel .ai-img .img-tip .bg-img{width:65%}.page .page-container .page-right .ai-panel .ai-img .ai-img-tip{display:flex;justify-content:center;text-align:center;margin-top:2%;margin-right:5%}.page .page-container .page-right .ai-panel .ai-img .ai-img-tip h1{font-weight:600}.page .page-container .page-right .ai-panel .ai-img .ai-img-tip-list{display:flex;justify-content:center;text-align:center;margin-top:2%;margin-right:5%}.page .page-container .page-right .ai-panel .ai-img .ai-img-tip-list .pce-inner-tip-point{display:inline-block;margin-top:2%;margin-right:1%;height:8px;width:8px;border-radius:50%;background-color:#4b4b4b}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i3$3.NgSelectOption,selector:"option",inputs:["ngValue","value"]},{kind:"directive",type:i3$3.ɵNgSelectMultipleOption,selector:"option",inputs:["ngValue","value"]},{kind:"directive",type:i3$3.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:i3$3.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"ngmodule",type:ReactiveFormsModule},{kind:"directive",type:i3$3.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"ngmodule",type:IonicModule},{kind:"component",type:i3.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:i3.IonCard,selector:"ion-card",inputs:["button","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonCardContent,selector:"ion-card-content",inputs:["mode"]},{kind:"component",type:i3.IonCardHeader,selector:"ion-card-header",inputs:["color","mode","translucent"]},{kind:"component",type:i3.IonCardSubtitle,selector:"ion-card-subtitle",inputs:["color","mode"]},{kind:"component",type:i3.IonCardTitle,selector:"ion-card-title",inputs:["color","mode"]},{kind:"component",type:i3.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:i3.IonSearchbar,selector:"ion-searchbar",inputs:["animated","autocapitalize","autocomplete","autocorrect","cancelButtonIcon","cancelButtonText","clearIcon","color","debounce","disabled","enterkeyhint","inputmode","maxlength","minlength","mode","name","placeholder","searchIcon","showCancelButton","showClearButton","spellcheck","type","value"]},{kind:"directive",type:i3.TextValueAccessor,selector:"ion-input:not([type=number]),ion-textarea,ion-searchbar"},{kind:"ngmodule",type:NzInputModule},{kind:"directive",type:i8.NzInputDirective,selector:"input[nz-input],textarea[nz-input]",inputs:["nzBorderless","nzSize","nzStepperless","nzStatus","disabled"],exportAs:["nzInput"]},{kind:"ngmodule",type:NzDropDownModule},{kind:"ngmodule",type:NzDividerModule},{kind:"ngmodule",type:NzEmptyModule},{kind:"ngmodule",type:NzAvatarModule},{kind:"ngmodule",type:NzPopoverModule},{kind:"ngmodule",type:NzToolTipModule},{kind:"ngmodule",type:NzPipesModule},{kind:"ngmodule",type:MatDialogModule},{kind:"ngmodule",type:MatFormFieldModule},{kind:"component",type:i11$1.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:i11$1.MatLabel,selector:"mat-label"},{kind:"ngmodule",type:MatInputModule},{kind:"directive",type:i4$4.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"ngmodule",type:MatButtonModule},{kind:"component",type:i3$2.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",exportAs:["matButton"]},{kind:"ngmodule",type:MatIconModule},{kind:"component",type:i6.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"ngmodule",type:MatChipsModule},{kind:"component",type:i10.MatChip,selector:"mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]",inputs:["role","id","aria-label","aria-description","value","color","removable","highlighted","disableRipple","disabled","tabIndex"],outputs:["removed","destroyed"],exportAs:["matChip"]},{kind:"ngmodule",type:MatExpansionModule},{kind:"directive",type:i7$2.MatAccordion,selector:"mat-accordion",inputs:["hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:i7$2.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["hideToggle","togglePosition"],outputs:["afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:i7$2.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["expandedHeight","collapsedHeight","tabIndex"]},{kind:"directive",type:i7$2.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"component",type:ArticleEditorTopbarComponent,selector:"fm-article-editor-topbar",inputs:["article","contentChanged","isSaving"],outputs:["onNavEvent"]},{kind:"component",type:FmTextQuillComponent,selector:"fm-text-quill",inputs:["readOnly","content","theme","toolbar"],outputs:["onAIClick","onContentChange","onSelectChange"]},{kind:"pipe",type:OutlineCountPipe,name:"outlineCount"}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FmArticleEditorComponent,decorators:[{type:Component,args:[{selector:"fm-article-editor",standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,IonicModule,NzInputModule,NzDropDownModule,NzDividerModule,NzEmptyModule,NzAvatarModule,NzPopoverModule,NzToolTipModule,NzPipesModule,MatDialogModule,MatFormFieldModule,MatInputModule,MatButtonModule,MatIconModule,MatChipsModule,MatExpansionModule,ArticleEditorTopbarComponent,FmTextQuillComponent,OutlineCountPipe,FmArticleOutlineLeftitemComponent],providers:[DraftService,NovaUploadService,Diagnostic],template:'<div class="page">\n\n \x3c!-- 导航栏 --\x3e\n <div class="nav" *ngIf="!readOnly">\n <fm-article-editor-topbar #topbar [article]="article" [isSaving]="isSaving" [contentChanged]="contentChanged" (onNavEvent)="handleNavEvent($event)"></fm-article-editor-topbar>\n </div>\n\n <div class="page-container">\n \x3c!-- (scroll)="onScroll($event)" --\x3e\n\n \x3c!-- 编辑文本 --\x3e\n \x3c!-- --\x3e\n <div class="editor-text" [ngClass]="{\'center\':isDivHidden}">\n <div class="editor-main">\n\n <div role="toolbar" class="ql-toolbar ql-snow" *ngIf="false">\n <span class="ql-formats"><span class="ql-header ql-picker"><span class="ql-picker-label" tabindex="0" role="button" aria-expanded="false" aria-controls="ql-picker-options-0"><svg viewBox="0 0 18 18"><polygon class="ql-stroke" points="7 11 9 13 11 11 7 11"></polygon><polygon class="ql-stroke" points="7 7 9 5 11 7 7 7"></polygon></svg></span><span class="ql-picker-options" aria-hidden="true" tabindex="-1" id="ql-picker-options-0"><span tabindex="0" role="button" class="ql-picker-item" data-value="1"></span><span tabindex="0" role="button" class="ql-picker-item" data-value="2"></span><span tabindex="0" role="button" class="ql-picker-item" data-value="3"></span><span tabindex="0" role="button" class="ql-picker-item" data-value="4"></span><span tabindex="0" role="button" class="ql-picker-item"></span></span></span><select class="ql-header" style="display: none;"><option value="1"></option><option value="2"></option><option value="3"></option><option value="4"></option><option selected="selected"></option></select></span>\n <span class="ql-formats"><button type="button" class="ql-bold" aria-pressed="false" aria-label="bold"><svg viewBox="0 0 18 18"><path class="ql-stroke" d="M5,4H9.5A2.5,2.5,0,0,1,12,6.5v0A2.5,2.5,0,0,1,9.5,9H5A0,0,0,0,1,5,9V4A0,0,0,0,1,5,4Z"></path><path class="ql-stroke" d="M5,9h5.5A2.5,2.5,0,0,1,13,11.5v0A2.5,2.5,0,0,1,10.5,14H5a0,0,0,0,1,0,0V9A0,0,0,0,1,5,9Z"></path></svg></button><button type="button" class="ql-italic" aria-pressed="false" aria-label="italic"><svg viewBox="0 0 18 18"><line class="ql-stroke" x1="7" x2="13" y1="4" y2="4"></line><line class="ql-stroke" x1="5" x2="11" y1="14" y2="14"></line><line class="ql-stroke" x1="8" x2="10" y1="14" y2="4"></line></svg></button><button type="button" class="ql-underline" aria-pressed="false" aria-label="underline"><svg viewBox="0 0 18 18"><path class="ql-stroke" d="M5,3V9a4.012,4.012,0,0,0,4,4H9a4.012,4.012,0,0,0,4-4V3"></path><rect class="ql-fill" height="1" rx="0.5" ry="0.5" width="12" x="3" y="15"></rect></svg></button></span>\n <span class="ql-formats"><button type="button" class="ql-list" aria-pressed="false" value="bullet" aria-label="list: bullet"><svg viewBox="0 0 18 18"><line class="ql-stroke" x1="6" x2="15" y1="4" y2="4"></line><line class="ql-stroke" x1="6" x2="15" y1="9" y2="9"></line><line class="ql-stroke" x1="6" x2="15" y1="14" y2="14"></line><line class="ql-stroke" x1="3" x2="3" y1="4" y2="4"></line><line class="ql-stroke" x1="3" x2="3" y1="9" y2="9"></line><line class="ql-stroke" x1="3" x2="3" y1="14" y2="14"></line></svg></button></span>\n <span class="ql-formats"><span class="ql-align ql-picker ql-icon-picker"><span class="ql-picker-label" tabindex="0" role="button" aria-expanded="false" aria-controls="ql-picker-options-1"><svg viewBox="0 0 18 18"><line class="ql-stroke" x1="3" x2="15" y1="9" y2="9"></line><line class="ql-stroke" x1="3" x2="13" y1="14" y2="14"></line><line class="ql-stroke" x1="3" x2="9" y1="4" y2="4"></line></svg></span><span class="ql-picker-options" aria-hidden="true" tabindex="-1" id="ql-picker-options-1"><span tabindex="0" role="button" class="ql-picker-item"><svg viewBox="0 0 18 18"><line class="ql-stroke" x1="3" x2="15" y1="9" y2="9"></line><line class="ql-stroke" x1="3" x2="13" y1="14" y2="14"></line><line class="ql-stroke" x1="3" x2="9" y1="4" y2="4"></line></svg></span><span tabindex="0" role="button" class="ql-picker-item" data-value="center"><svg viewBox="0 0 18 18"><line class="ql-stroke" x1="15" x2="3" y1="9" y2="9"></line><line class="ql-stroke" x1="14" x2="4" y1="14" y2="14"></line><line class="ql-stroke" x1="12" x2="6" y1="4" y2="4"></line></svg></span><span tabindex="0" role="button" class="ql-picker-item" data-value="right"><svg viewBox="0 0 18 18"><line class="ql-stroke" x1="15" x2="3" y1="9" y2="9"></line><line class="ql-stroke" x1="15" x2="5" y1="14" y2="14"></line><line class="ql-stroke" x1="15" x2="9" y1="4" y2="4"></line></svg></span><span tabindex="0" role="button" class="ql-picker-item" data-value="justify"><svg viewBox="0 0 18 18"><line class="ql-stroke" x1="15" x2="3" y1="9" y2="9"></line><line class="ql-stroke" x1="15" x2="3" y1="14" y2="14"></line><line class="ql-stroke" x1="15" x2="3" y1="4" y2="4"></line></svg></span></span></span><select class="ql-align" style="display: none;"><option selected="selected"></option><option value="center"></option><option value="right"></option><option value="justify"></option></select></span>\n <span class="ql-formats"><button type="button" class="ql-code-block" aria-pressed="false" aria-label="code-block"><svg viewBox="0 0 18 18"><polyline class="ql-even ql-stroke" points="5 7 3 9 5 11"></polyline><polyline class="ql-even ql-stroke" points="13 7 15 9 13 11"></polyline><line class="ql-stroke" x1="10" x2="8" y1="5" y2="13"></line></svg></button></span>\n <span class="ql-formats"><button class="ql-ai-optimize">AI</button></span>\n </div>\n\n <div class="text-header">\n <input [ngModel]="article?.get(\'title\')" (ngModelChange)="article?.set(\'title\',$event)" type="text" />\n \x3c!-- <quill-editor [(ngModel)]="title" [modules]="{toolbar: true}"></quill-editor> --\x3e\n </div>\n <div class="article-info">\n <ng-container *ngIf="article?.get(\'keywords\')?.length">\n <div>关键字:<mat-chip *ngFor="let key of article?.get(\'keywords\')">{{key}}</mat-chip></div>\n </ng-container>\n <ng-container *ngIf="article?.get(\'writingOptions\')">\n <div (click)="handleNavEvent(\'options\')">设 定:\n <mat-chip *ngIf="article?.get(\'writingOptions\')?.writingStyle">{{article?.get(\'writingOptions\')?.writingStyle}}</mat-chip>\n <mat-chip *ngIf="article?.get(\'writingOptions\')?.wordCount">约{{article?.get(\'writingOptions\')?.wordCount}}字</mat-chip></div>\n </ng-container>\n <ng-container *ngIf="article?.get(\'outlineJson\')?.length">\n <div (click)="handleNavEvent(\'outline\')">提 纲:<mat-chip>{{article?.get(\'outlineJson\') | outlineCount}}字</mat-chip></div>\n </ng-container>\n <div *ngIf="article?.id" (click)="handleNavEvent(\'draft\')">稿件箱:<mat-chip>{{draftServ.DraftCountMap?.[article?.id||\'\']?.total || 0}}篇</mat-chip></div>\n </div>\n\n <div class="article-content">\n \x3c!-- 文本编辑区域:仅content正文 --\x3e\n <ng-container *ngIf="!article?.get(\'contentArray\')?.length">\n <fm-text-quill #textQuill [readOnly]="readOnly" [content]="article?.get(\'content\')" (onContentChange)="setContent($event)"\n (onAIClick)="goOptimizeText($event)" (onSelectChange)="selectChange($event)"\n ></fm-text-quill>\n </ng-container>\n \x3c!-- 文本编辑区域:含大纲正文 --\x3e\n <ng-container *ngIf="article?.get(\'contentArray\')?.length">\n <ng-container *ngFor="let item of article?.get(\'contentArray\');let index=index;">\n \x3c!-- 章节信息 --\x3e\n \x3c!-- <h2 style="margin:0px;padding-left:12px;" *ngIf="article?.get(\'outlineJson\')?.sections?.[index]?.title">{{article?.get(\'outlineJson\')?.sections?.[index]?.title}}</h2> --\x3e\n <fm-text-quill #textQuill [readOnly]="readOnly" [content]="item?.content" (onContentChange)="setContent($event,item)"\n (onAIClick)="goOptimizeText($event)" (onSelectChange)="selectChange($event)"\n ></fm-text-quill>\n </ng-container>\n </ng-container>\n </div>\n </div>\n </div>\n\n\n\n \x3c!-- AI工具 --\x3e\n <div *ngIf="!readOnly && !isDivHidden" class="page-right">\n <div class="nav-ai">\n \x3c!-- AI功能按钮 --\x3e\n \x3c!-- <div class="ai-btn">\n <button (click)="showContent(\'AI-写作\')">AI写作</button>\n <button (click)="showContent(\'AI-润色\')">AI润色</button>\n <button (click)="showContent(\'校阅\')">校阅</button>\n <button (click)="showContent(\'图片\')">图片</button>\n <button (click)="showContent(\'评论\')">评论</button>\n </div> --\x3e\n\n <ul class="ai-btn">\n <li class="active0" (click)="aiTab(\'AI写作\')" [ngClass]="{ \'active1\': aitab == \'AI写作\' }">\n <div>AI写作</div>\n </li>\n <li class="active0" (click)="aiTab(\'AI润色\')" [ngClass]="{ \'active1\': aitab == \'AI润色\' }">\n <div>AI润色</div>\n </li>\n \x3c!-- <li class="active0" (click)="aiTab(\'校阅\')" [ngClass]="{ \'active1\': aitab == \'校阅\' }">\n <div>校阅</div>\n </li> --\x3e\n <li class="active0" (click)="aiTab(\'AI配图\')" [ngClass]="{ \'active1\': aitab == \'AI配图\' }">\n <div>AI配图</div>\n </li>\n\n </ul>\n \x3c!-- AI功能退出按钮 --\x3e\n <div>\n <ion-icon class="icon" name="close-outline" (click)="this.isDivHidden = !this.isDivHidden;"></ion-icon>\n </div>\n\n </div>\n\n\n \x3c!-- 工具面板 --\x3e\n <div class="ai-panel">\n\n <div *ngIf="aitab==\'AI写作\'" class="ai-write">\n \x3c!-- 搜索 --\x3e\n <div class="search-bar">\n <ion-searchbar color="light" placeholder="搜索模板"></ion-searchbar>\n </div>\n\n <div class="ai-tool-grid">\n <ng-container *ngFor="let card of cards">\n <ion-card class="card" style="margin-left: 5%;max-width:215px;" (click)="card?.handle()">\n <ion-card-header>\n <ion-card-title class="card-image">\n <img src="{{card.imageurl}}" width="25" height="25" alt="write">\n </ion-card-title>\n <ion-card-subtitle>{{card.title}}</ion-card-subtitle>\n </ion-card-header>\n\n <ion-card-content>\n {{card.content}}\n </ion-card-content>\n </ion-card>\n </ng-container>\n </div>\n\n </div>\n <div *ngIf="aitab==\'AI润色\'" class="ai-polish" [formGroup]="tempFormGroup">\n <div class="ai-polish-input">\n <mat-form-field style="width:95%;">\n <mat-label>输入或选中左侧文本开始润色</mat-label>\n <textarea matInput [(ngModel)]="selectText" [ngModelOptions]="{standalone: true}" rows="10"></textarea>\n </mat-form-field>\n\n \x3c!-- <textarea [(ngModel)]="selectText" rows="10" formControlName="comment" nz-input placeholder="输入或选中左侧文本开始润色"></textarea> --\x3e\n </div>\n <div class="ai-polish-button">\n <button *ngIf="!isOptimizing" mat-raised-button color="primary" (click)="optimizeContent()">开始润色</button>\n <button *ngIf="isOptimizing" mat-raised-button color="warn" (click)="cancelOptimize()">停止润色</button>\n \x3c!-- <ion-button id="start" [disabled]="false" (click)="enableButton()">开始润色</ion-button> --\x3e\n </div>\n <div class="ai-polish-input">\n <mat-form-field style="width:95%;">\n <mat-label>生成内容</mat-label>\n <textarea matInput [(ngModel)]="optimizeText" [ngModelOptions]="{standalone: true}" rows="10"></textarea>\n </mat-form-field>\n </div>\n <div class="ai-polish-button">\n <button *ngIf="selectRange?.length" mat-raised-button (click)="applyOptimize()"><mat-icon fontIcon="flip"></mat-icon>替换</button>\n <button mat-raised-button (click)="copyOptimize()"><mat-icon fontIcon="content_copy"></mat-icon>复制</button>\n \x3c!-- <ion-button id="start" [disabled]="false" (click)="enableButton()">开始润色</ion-button> --\x3e\n </div>\n \x3c!-- <div class="copy">\n <ion-icon name="copy-outline" style="color:#4e80f4" (click)="Copy(polishContent)"></ion-icon>\n </div> --\x3e\n </div>\n <div *ngIf="aitab==\'校阅\'" class="ai-proofread">\n\n <div class="showItems-container">\n <div class="showItems">\n\n <div class="showItem" (click)="clickTab(\'内容建议\')" [ngClass]="{ \'active1\': clicktab == \'内容建议\' }">\n <div style="line-height: 12px;">\n <svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M11 10H5M7 14H5M13 6H5M17 9.5V5.8C17 4.11984 17 3.27976 16.673 2.63803C16.3854 2.07354 15.9265 1.6146 15.362 1.32698C14.7202 1 13.8802 1 12.2 1H5.8C4.11984 1 3.27976 1 2.63803 1.32698C2.07354 1.6146 1.6146 2.07354 1.32698 2.63803C1 3.27976 1 4.11984 1 5.8V16.2C1 17.8802 1 18.7202 1.32698 19.362C1.6146 19.9265 2.07354 20.3854 2.63803 20.673C3.27976 21 4.11984 21 5.8 21H8.5M19 21L17.5 19.5M18.5 17C18.5 18.933 16.933 20.5 15 20.5C13.067 20.5 11.5 18.933 11.5 17C11.5 15.067 13.067 13.5 15 13.5C16.933 13.5 18.5 15.067 18.5 17Z"\n stroke="#1570EF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <span>内容建议</span>\n\n\n </div>\n\n <div class="showItem" (click)="clickTab(\'事实验证\')" [ngClass]="{\'active1\': clicktab==\'事实验证\'}">\n <div style="line-height: 12px;">\n <svg width="18" height="22" viewBox="0 0 18 22" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M11 1.26953V5.40007C11 5.96012 11 6.24015 11.109 6.45406C11.2049 6.64222 11.3578 6.7952 11.546 6.89108C11.7599 7.00007 12.0399 7.00007 12.6 7.00007H16.7305M6 15L8 17L12.5 12.5M11 1H5.8C4.11984 1 3.27976 1 2.63803 1.32698C2.07354 1.6146 1.6146 2.07354 1.32698 2.63803C1 3.27976 1 4.11984 1 5.8V16.2C1 17.8802 1 18.7202 1.32698 19.362C1.6146 19.9265 2.07354 20.3854 2.63803 20.673C3.27976 21 4.11984 21 5.8 21H12.2C13.8802 21 14.7202 21 15.362 20.673C15.9265 20.3854 16.3854 19.9265 16.673 19.362C17 18.7202 17 17.8802 17 16.2V7L11 1Z"\n stroke="#D92D20" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <span>事实验证</span>\n </div>\n\n <div class="showItem" (click)="clickTab(\'全文总结\')" [ngClass]="{\'active1\': clicktab==\'全文总结\'}">\n <div style="line-height: 12px;"> <svg width="20" height="22" viewBox="0 0 16 20" fill="none"\n xmlns="http://www.w3.org/2000/svg">\n <path\n d="M14.1668 5.83329V5.66663C14.1668 4.26649 14.1668 3.56643 13.8943 3.03165C13.6547 2.56124 13.2722 2.17879 12.8018 1.93911C12.267 1.66663 11.567 1.66663 10.1668 1.66663H4.8335C3.43336 1.66663 2.7333 1.66663 2.19852 1.93911C1.72811 2.17879 1.34566 2.56124 1.10598 3.03165C0.833496 3.56643 0.833496 4.26649 0.833496 5.66663V14.3333C0.833496 15.7334 0.833496 16.4335 1.10598 16.9683C1.34566 17.4387 1.72811 17.8211 2.19852 18.0608C2.7333 18.3333 3.43336 18.3333 4.8335 18.3333H7.91683M7.91683 9.16663H4.16683M7.0835 12.5H4.16683M10.8335 5.83329H4.16683M12.5002 15V10.4166C12.5002 9.72627 13.0598 9.16663 13.7502 9.16663C14.4405 9.16663 15.0002 9.72627 15.0002 10.4166V15C15.0002 16.3807 13.8809 17.5 12.5002 17.5C11.1195 17.5 10.0002 16.3807 10.0002 15V11.6666"\n stroke="#F79009" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <span>全文总结</span>\n </div>\n\n </div>\n </div>\n\n <div class="showItem-content">\n <div *ngIf="clicktab==\'语法错误\'" class="grammar-panel">\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n <div class="grammar-error">\n\n <span class="alert-point">\n •\n </span>\n <div class="error-content">\n <span>古老</span>\n </div>\n <span class="alert-point-gray">\n •\n </span>\n\n <span style="color:#8189a9">\n 建议替换为\n </span>\n\n <div class="right-content">\n <span>古老</span>\n </div>\n\n </div>\n\n </div>\n <div *ngIf="clicktab==\'内容建议\'" class="suggest-panel">\n\n <div class="content-suggest">\n <div style="line-height: 12px;">\n <svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M11 10H5M7 14H5M13 6H5M17 9.5V5.8C17 4.11984 17 3.27976 16.673 2.63803C16.3854 2.07354 15.9265 1.6146 15.362 1.32698C14.7202 1 13.8802 1 12.2 1H5.8C4.11984 1 3.27976 1 2.63803 1.32698C2.07354 1.6146 1.6146 2.07354 1.32698 2.63803C1 3.27976 1 4.11984 1 5.8V16.2C1 17.8802 1 18.7202 1.32698 19.362C1.6146 19.9265 2.07354 20.3854 2.63803 20.673C3.27976 21 4.11984 21 5.8 21H8.5M19 21L17.5 19.5M18.5 17C18.5 18.933 16.933 20.5 15 20.5C13.067 20.5 11.5 18.933 11.5 17C11.5 15.067 13.067 13.5 15 13.5C16.933 13.5 18.5 15.067 18.5 17Z"\n stroke="#1570EF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <div class="content-suggest-title">内容建议</div>\n </div>\n\n <div class="content">\n <div class="content-title"> 这篇文章介绍的是七个关于中国企业家的管理之道的自传小说章节标题,旨在展示企业家们的个人经历、管理理念和人生哲学。\n </div>\n <div class="content-title">改进建议:</div>\n <ol>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n <li> 标题一致性:文章中的章节标题应保持一致的格式,例如“啊手动阀士大夫”和“爱喝水的人,一定是有品味的”与其他章节的格式不一致,建议统一格式以增强文章的专业性。</li>\n <li> 语言风格:文章中出现了一些非正式或口语化的表达,如“嫩给够穿越时空的力量”和“包韩了对生命意义的深刻反思”,建议使用更正式的语言以符合专业文章的标准。</li>\n <li> 信息重复:在介绍《时光的裂缝》的部分,有关时间旅行的描述被多次提及,建议合并相似内容以避免重复。\n </li>\n </ol>\n\n\n </div>\n </div>\n <div *ngIf="clicktab==\'事实验证\'" class="verify-panel">\n <div class="dashboard">\n <div class="item" (click)="dashboardTab(\'全部\')" [ngClass]="{\'itemChoose\': dashboardtab==\'全部\'}">\n <div class="icon">\n <div class="statusIcon" style="border: 1px solid black; box-sizing: border-box;"></div>\n </div>\n <div class="text">全部</div>\n <div class="number">28</div>\n </div>\n\n <div class="item" (click)="dashboardTab(\'通过\')" [ngClass]="{\'itemChoose\': dashboardtab==\'通过\'}">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n <div class="number">9</div>\n </div>\n\n <div class="item" (click)="dashboardTab(\'不通过\')" [ngClass]="{\'itemChoose\': dashboardtab==\'不通过\'}">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(217, 45, 32);"><svg\n xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">\n <path d="M7 17L17 7" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n <path d="M7 7L17 17" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </svg></div>\n </div>\n <div class="text" style="color: rgb(217, 45, 32);">不通过</div>\n <div class="number">1</div>\n </div>\n <div class="item" (click)="dashboardTab(\'无法判断\')" [ngClass]="{\'itemChoose\': dashboardtab==\'无法判断\'}">\n <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="3 3 18 18"\n fill="none">\n <path\n d="M7.8824 8.679C7.88035 8.72744 7.88822 8.77579 7.90555 8.82107C7.92287 8.86636 7.94927 8.90762 7.98313 8.94232C8.01699 8.97703 8.05759 9.00444 8.10244 9.02287C8.14728 9.0413 8.19542 9.05036 8.2439 9.0495H9.4814C9.6884 9.0495 9.8534 8.88 9.8804 8.6745C10.0154 7.6905 10.6904 6.9735 11.8934 6.9735C12.9224 6.9735 13.8644 7.488 13.8644 8.7255C13.8644 9.678 13.3034 10.116 12.4169 10.782C11.4074 11.5155 10.6079 12.372 10.6649 13.7625L10.6694 14.088C10.671 14.1864 10.7112 14.2803 10.7813 14.3493C10.8515 14.4183 10.946 14.457 11.0444 14.457H12.2609C12.3604 14.457 12.4557 14.4175 12.5261 14.3472C12.5964 14.2768 12.6359 14.1815 12.6359 14.082V13.9245C12.6359 12.8475 13.0454 12.534 14.1509 11.6955C15.0644 11.001 16.0169 10.23 16.0169 8.6115C16.0169 6.345 14.1029 5.25 12.0074 5.25C10.1069 5.25 8.0249 6.135 7.8824 8.679ZM10.2179 17.3235C10.2179 18.123 10.8554 18.714 11.7329 18.714C12.6464 18.714 13.2749 18.123 13.2749 17.3235C13.2749 16.4955 12.6449 15.9135 11.7314 15.9135C10.8554 15.9135 10.2179 16.4955 10.2179 17.3235Z"\n fill="#475467"></path>\n </svg></div>\n <div class="text">无法判断</div>\n <div class="number">18</div>\n </div>\n </div>\n\n <div class="verify-card-list">\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n <div class="card">\n <div class="item">\n <div class="icon">\n <div class="statusIcon" style="background-color: rgb(18, 183, 106);">\n <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 25" fill="none">\n <g clip-path="url(#clip0_9987_2125)">\n <path d="M20 7.5L10 17.5L5 12.5" stroke="#ffffff" stroke-width="3" stroke-linecap="round"\n stroke-linejoin="round"></path>\n </g>\n <defs>\n <clipPath id="clip0_9987_2125">\n <rect width="24" height="24" fill="white" transform="translate(0 0.5)">\n </rect>\n </clipPath>\n </defs>\n </svg>\n </div>\n </div>\n <div class="text" style="color: rgb(18, 183, 106);">通过</div>\n\n </div>\n <div class="card-content">\n 本书分为四个部分:第二部分讲述中国经济体制改革过程中,他是如何在“摸着石头过河”的过程中不断探索、不断创新。\n </div>\n </div>\n\n </div>\n </div>\n <div *ngIf="clicktab==\'全文总结\'" class="summary-panel">\n\n <div class="text-summary">\n <div style="line-height: 12px;">\n <svg width="20" height="22" viewBox="0 0 16 20" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path\n d="M14.1668 5.83329V5.66663C14.1668 4.26649 14.1668 3.56643 13.8943 3.03165C13.6547 2.56124 13.2722 2.17879 12.8018 1.93911C12.267 1.66663 11.567 1.66663 10.1668 1.66663H4.8335C3.43336 1.66663 2.7333 1.66663 2.19852 1.93911C1.72811 2.17879 1.34566 2.56124 1.10598 3.03165C0.833496 3.56643 0.833496 4.26649 0.833496 5.66663V14.3333C0.833496 15.7334 0.833496 16.4335 1.10598 16.9683C1.34566 17.4387 1.72811 17.8211 2.19852 18.0608C2.7333 18.3333 3.43336 18.3333 4.8335 18.3333H7.91683M7.91683 9.16663H4.16683M7.0835 12.5H4.16683M10.8335 5.83329H4.16683M12.5002 15V10.4166C12.5002 9.72627 13.0598 9.16663 13.7502 9.16663C14.4405 9.16663 15.0002 9.72627 15.0002 10.4166V15C15.0002 16.3807 13.8809 17.5 12.5002 17.5C11.1195 17.5 10.0002 16.3807 10.0002 15V11.6666"\n stroke="#F79009" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"></path>\n </svg>\n </div>\n <div class="text-summary-title">全文总结</div>\n </div>\n\n <div class="text">\n <div class="text-title">概括:</div>\n\n <p>\n 这本自传小说由企业家曹国熊撰写,讲述了他如何从贫穷孩子成长为成功企业家的经历和管理智慧,同时通过不同章节探讨了企业家的成长、团队合作、创新驱动、领导力培养、面对危机和可持续发展等主题。\n </p>\n <div class="text-title">要点:</div>\n <ul>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 章节《从小梦想到大事业》回顾了作者从少年时代怀揣创业梦想,克服困难和挑战的过程。</li>\n <li> 《时光的裂缝》是一部结合悬疑、奇幻和哲思的小说,通过杰克的视角探索人性、选择和成长。</li>\n <li> 书中还涉及了如何培养企业家的道德操守和社会责任感、团队合作的重要性、科技创新的推动、领导力的培养以及如何面对和化解危机。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n <li>曹国熊是中国的企业家、作家,他的自传记录了从贫穷到成功的历程。</li>\n <li> 最后一章《绿色转型的先锋》探讨了作者作为企业家在社会责任方面的努力,包括推动企业绿色转型和可持续发展。</li>\n </ul>\n\n\n\n\n\n\n </div>\n </div>\n </div>\n\n\n\n </div>\n <div *ngIf="aitab==\'AI配图\'" class="ai-img">\n <mat-accordion multi>\n <mat-expansion-panel expanded="true">\n <mat-expansion-panel-header>\n <mat-panel-title>文章封面</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="image" (click)="uploadImage()">\n <img [src]="article?.get(\'image\') || \'/assets/img/icon/addphoto.png\'" alt="">\n </div>\n </mat-expansion-panel>\n\n <mat-expansion-panel expanded="false">\n <mat-expansion-panel-header>\n <mat-panel-title>段落插图</mat-panel-title>\n </mat-expansion-panel-header>\n \n <div class="ai-img-search">\n\n <div class="ai-img-search-input">\n <input type="text" nz-input placeholder="请输入图片描述" />\n </div>\n\n <div class="ai-img-search-button">\n <ion-button>\n <ion-icon name="search-outline"></ion-icon>\n 查找\n </ion-button>\n </div>\n\n </div>\n\n <div class="img-tip">\n <img class="bg-img" src="../../../assets/images/火箭2.png">\n </div>\n <div class="ai-img-tip">\n <h1>输入描述,自动配图</h1>\n\n </div>\n\n <div class="ai-img-tip-list">\n <div class="pce-inner-tip-point"></div>\n <span>\n 根据您对图片的描述,智能匹配相关图片\n </span>\n </div>\n </mat-expansion-panel>\n </mat-accordion>\n\n\n </div>\n\n\n </div>\n </div>\n\n\n\n\n </div>\n</div>',styles:['@charset "UTF-8";.image{width:100%;height:240px;overflow:hidden;display:flex;justify-content:center;align-items:center}.image img{height:100%;object-fit:contain;height:auto;transition:transform .2s}.image:hover img{transform:scale(1.2)}.page{background-color:#fafafa;height:100%;width:100%;display:flex;flex-direction:column;overflow:hidden}.page .nav{position:sticky;top:0;z-index:3}.page .icon{width:20px;height:20px;margin:0 10px 0 5%}.page .page-container{display:flex;height:calc(100vh - 120px)}.page .page-container .center{margin:5vh auto!important}.page .page-container .editor-text{display:flex;justify-content:center;flex:1;right:0;height:auto;min-height:75vh;min-width:35%;box-shadow:#00000026 1px 2px 8px;background-color:#fff;overflow:visible}.page .page-container .editor-text .editor-main{width:100%;height:100%;display:flex;flex-direction:column;overflow:hidden}.page .page-container .editor-text .editor-main .text-header{display:flex;justify-content:center;padding-top:10px}.page .page-container .editor-text .editor-main .text-header input,.page .page-container .editor-text .editor-main .text-header input:focus{width:100%;text-align:center;border:none;font-size:22px;font-weight:700;box-shadow:none;outline:none}.page .page-container .editor-text .editor-main .article-info{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center}.page .page-container .editor-text .editor-main .article-info div{padding-left:5px;padding-right:5px;margin-bottom:3px}.page .page-container .editor-text .editor-main .article-info div mat-chip{margin-right:3px}.page .page-container .editor-text .editor-main .article-content{flex:1;min-height:50vh;overflow-y:auto}.page .page-container .page-right{height:calc(80vh - 10px);margin-top:6px;margin-left:3px;min-width:480px;background-color:#fafafa;opacity:1;transition:opacity 2s ease-in-out;overflow-y:hidden;overflow-x:hidden}.page .page-container .page-right .nav-ai{background-color:#fafafa;display:flex;width:100%;justify-content:space-between;z-index:3;position:sticky;top:0}.page .page-container .page-right .nav-ai ul{width:100%;list-style-type:none;padding:0;margin:0;display:flex;flex-wrap:wrap;justify-content:space-around}.page .page-container .page-right .nav-ai ul .active0{position:relative;padding:5px 15px;margin:0 5px 10px;font-size:18px;font-weight:700;color:#8e8e8e;border-radius:5px;transition:.3s}.page .page-container .page-right .nav-ai ul .active1{color:#333}.page .page-container .page-right .nav-ai ul .active1 div:after{content:"";position:absolute;left:0;bottom:0;width:100%;border-bottom:4px solid #8e8e8e;border-radius:10px;margin-bottom:-6px}.page .page-container .page-right .nav-ai ul li div{cursor:pointer;text-align:center;position:relative}.page .page-container .page-right .nav-ai .icon{cursor:pointer;margin-top:20%;width:25px;height:25px;align-content:center}.page .page-container .page-right .ai-panel{right:2%;background-color:#fafafa;width:95%;z-index:1}.page .page-container .page-right .ai-panel .ai-tool-grid{display:flex;flex-wrap:wrap}.page .page-container .page-right .ai-panel .ai-tool-grid ion-card{max-width:33%}.page .page-container .page-right .ai-panel div::-webkit-scrollbar{display:none}.page .page-container .page-right .ai-panel .ai-write{width:515px}.page .page-container .page-right .ai-panel .ai-write .search-bar{height:40px;width:100%;margin-left:15px}.page .page-container .page-right .ai-panel .ai-write ion-col{background-color:#fafafa;border:solid 2px #fafafa;text-align:center;padding:0;margin-left:3%}.page .page-container .page-right .ai-panel .ai-write .card{max-height:150px;max-width:220px;height:15vh;width:16vw;cursor:pointer}.page .page-container .page-right .ai-panel .ai-write .card .card-image{margin-right:80%}.page .page-container .page-right .ai-panel .ai-write .card ion-card-header{padding:6%}.page .page-container .page-right .ai-panel .ai-write .card ion-card-subtitle{font-weight:600;text-align:left}.page .page-container .page-right .ai-panel .ai-write .card ion-card-content{text-align:left;white-space:pre-line;font-size:12px;margin-left:6%;padding:0}.page .page-container .page-right .ai-panel .ai-write .card-image{background:#fff;box-shadow:0 1px 4px #0000000a,0 4px 10px #00000014;width:30px;height:30px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex:none}.page .page-container .page-right .ai-panel .ai-polish{margin-top:10px;background-color:#fafafa}.page .page-container .page-right .ai-panel .ai-polish textarea.ant-input{max-width:93%;height:auto;min-height:32px;line-height:1.5715;vertical-align:bottom;transition:all .3s,height 0s}.page .page-container .page-right .ai-panel .ai-polish ::-webkit-scrollbar{width:4px;border-radius:3px}.page .page-container .page-right .ai-panel .ai-polish ::-webkit-scrollbar-thumb{background-color:#dddee0;border-radius:2px}.page .page-container .page-right .ai-panel .ai-polish .ai-polish-button{text-align:right;margin-right:21px}.page .page-container .page-right .ai-panel .ai-polish .ai-polish-button button{margin-left:15px}.page .page-container .page-right .ai-panel .ai-polish .copy{text-align:right;margin-right:7%;cursor:pointer}.page .page-container .page-right .ai-panel .ai-proofread{height:73vh;margin-top:2%;position:sticky;top:0}.page .page-container .page-right .ai-panel .ai-proofread .showItems-container{width:100%;z-index:2}.page .page-container .page-right .ai-panel .ai-proofread .showItems-container .showItems{display:flex;justify-content:space-around;position:sticky;top:0;padding-left:15px;padding-right:15px}.page .page-container .page-right .ai-panel .ai-proofread .showItems-container .showItems .showItem{display:flex;flex-shrink:0;cursor:pointer;gap:8px;padding:12px 15px;background:#fff;border:1px solid #f9fafb;box-shadow:0 1px 2px #1018280d;font-size:16px;font-weight:400}.page .page-container .page-right .ai-panel .ai-proofread .showItems-container .showItems .active1{color:#333;font-weight:700}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .grammar-panel{margin-top:10%;margin-left:2.3%;height:61vh;overflow-y:scroll}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error{display:flex;text-align:center;margin-bottom:5%;width:90%;height:6vh;margin-left:4%;background:#fff;border:1px solid #f9fafb;box-shadow:0 1px 2px #1018280d;line-height:6vh}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .alert-point{color:#ff7a7a;margin-left:6%;margin-right:5%;font-size:20px}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .alert-point-gray{color:#8189a9;font-size:10px;margin-right:1%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .error-content{margin-right:4%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .grammar-panel .grammar-error .right-content{margin-left:4%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .suggest-panel{position:sticky;top:0;margin-top:4%;margin-left:6.8%;width:91%;background-color:#fff}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .suggest-panel .content-suggest{display:flex;cursor:pointer;padding:5% 3%;height:6%;width:100%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .suggest-panel .content-suggest .content-suggest-title{margin-left:3%;font-size:16px;font-weight:400}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .suggest-panel .content{width:98%;height:55vh;overflow-y:scroll}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .suggest-panel .content .content-title{margin:3% 4%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .suggest-panel .content ol{margin:3% 4%;counter-reset:section}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .suggest-panel .content li:before{counter-increment:section;content:"Section " counter(section) ". "}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel{margin-top:2%;margin-left:6.8%;width:95%;margin-bottom:2%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .icon{width:16px;height:16px;display:inline-block;margin-top:3px}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .dashboard{display:flex;margin-left:-1%;margin-top:3%;height:5%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .itemChoose{background-color:#eaecf0}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .item{display:flex;height:76%;width:23%;padding:6px 8px;cursor:pointer}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .item .text{font-weight:bolder;margin-right:4%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .item .number{font-weight:bolder;margin-right:1%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .dashboard .statusIcon{border-radius:50%;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:18px;height:18px}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list{height:61vh;overflow-y:scroll}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .card{box-shadow:0 1px 2px #1018280f,0 1px 3px #1018281a;width:95%;height:auto;margin-top:3%;padding:2% 3%;background-color:#fff}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .card .item{display:flex}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .card .card-content{margin-top:3%;margin-bottom:3%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .verify-panel .verify-card-list .statusIcon{border-radius:50%;width:18px;height:18px}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .summary-panel{margin-top:2%;margin-left:6.8%;width:91%;background-color:#fff}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .summary-panel .text-summary{display:flex;cursor:pointer;padding:5% 3%;height:6%;width:100%}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .summary-panel .text-summary .text-summary-title{margin-left:3%;font-size:16px;font-weight:400}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .summary-panel .text{width:100%;height:57vh;overflow-y:scroll}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .summary-panel .text .text-title{margin:3% 4%;font-weight:700}.page .page-container .page-right .ai-panel .ai-proofread .showItem-content .summary-panel .text p{margin:3% 4%}.page .page-container .page-right .ai-panel .ai-img{width:480px}.page .page-container .page-right .ai-panel .ai-img .ai-img-search{display:flex;height:4%;width:100%;margin-left:4%;margin-top:5%}.page .page-container .page-right .ai-panel .ai-img .ai-img-search .ai-img-search-input{width:65%}.page .page-container .page-right .ai-panel .ai-img .ai-img-search .ai-img-search-input input{height:100%}.page .page-container .page-right .ai-panel .ai-img .ai-img-search .ai-img-search-button{margin-left:5%;margin-top:-.8%}.page .page-container .page-right .ai-panel .ai-img .img-tip{display:flex;text-align:center;justify-content:center;margin-top:20%;width:95%}.page .page-container .page-right .ai-panel .ai-img .img-tip .bg-img{width:65%}.page .page-container .page-right .ai-panel .ai-img .ai-img-tip{display:flex;justify-content:center;text-align:center;margin-top:2%;margin-right:5%}.page .page-container .page-right .ai-panel .ai-img .ai-img-tip h1{font-weight:600}.page .page-container .page-right .ai-panel .ai-img .ai-img-tip-list{display:flex;justify-content:center;text-align:center;margin-top:2%;margin-right:5%}.page .page-container .page-right .ai-panel .ai-img .ai-img-tip-list .pce-inner-tip-point{display:inline-block;margin-top:2%;margin-right:1%;height:8px;width:8px;border-radius:50%;background-color:#4b4b4b}\n']}]}],ctorParameters:()=>[{type:i1$3.ModalController},{type:i1$3.AlertController},{type:i3$1.MatDialog},{type:i0.ChangeDetectorRef},{type:ClipboardService},{type:DraftService},{type:i1$1.Router},{type:NovaUploadService},{type:PersonService}],propDecorators:{editorComp:[{type:ViewChild,args:["editorComp"]}],article:[{type:Input}],onClose:[{type:Output}],book:[{type:Input}],readOnly:[{type:Input}]}});class LoginComponent{drawCode(e){this.canvas=document.getElementById("verifyCanvas");var t=this.canvas.getContext("2d");t.fillStyle="white",t.fillRect(0,0,this.canvas.width,this.canvas.height),t.fillStyle="cornflowerblue",t.font="25px Arial";for(var n=new Array,o=new Array,i=new Array,a=0;a<4;a++)n.push(n[a]),n[a]=this.nums[a],o[a]=20*a+10,i[a]=20*Math.random()+20,t.fillText(n[a],o[a],i[a]);e=n.join("").toUpperCase();for(a=0;a<3;a++)this.drawline(this.canvas,t);for(a=0;a<30;a++)this.drawDot(this.canvas,t);return this.convertCanvasToImage(this.canvas),e}drawline(e,t){t.moveTo(Math.floor(Math.random()*e.width),Math.floor(Math.random()*e.height)),t.lineTo(Math.floor(Math.random()*e.width),Math.floor(Math.random()*e.height)),t.lineWidth=.5,t.strokeStyle="rgba(50,50,50,0.3)",t.stroke()}drawDot(e,t){var n=Math.floor(Math.random()*e.width),o=Math.floor(Math.random()*e.height);t.moveTo(n,o),t.lineTo(n+1,o+1),t.lineWidth=.2,t.stroke()}convertCanvasToImage(e){return document.getElementById("verifyCanvas").style.display="none",this.image=document.getElementById("code_img"),this.image.src=e.toDataURL("image/png"),this.image}sendSMSCode(){if(!this.codeVerified)return void this.message.create("error","请先核对验证码");let e=this.validateSMSForm.value?.mobile;if(console.log(this.validateSMSForm.value),e){let t=localStorage.getItem("NOVA_APIG_SERVER");t=decodeURIComponent(atob(t));let n=t+"message";this.http.post(n,{company:this.companyId,mobile:e,action:"login"}).subscribe((e=>{this.countDownSMS(),this.message.info("已发送,请查收验证码")}),(e=>{this.message.error(e?.error?.mess||"系统繁忙中,请稍后重试")}))}else this.message.error("请正确输入手机号")}countDownSMS(){this.isSended=!0,this.isSending=!0,this.smsTimeCount=60;let e=setInterval((()=>{this.smsTimeCount--}),1e3);setTimeout((()=>{clearInterval(e),this.isSending=!1}),6e4)}submitFormMobileSMS(e){for(const e in this.validateSMSForm.controls)this.validateSMSForm.controls[e].markAsDirty(),this.validateSMSForm.controls[e].updateValueAndValidity();console.log(e),this.username=e.mobile,this.smsCode=e.smsCode,console.log("smslogin"),this.loginSMS()}submitFormMobilePassword(e){for(const e in this.validateForm.controls)this.validateForm.controls[e].markAsDirty(),this.validateForm.controls[e].updateValueAndValidity();this.username=e.mobile||e.username,this.password=e.password;let t=e.checkCode,n=this.code.toLowerCase(),o=t.toLowerCase();console.log(n,o),n!=o?(console.log(n,o),this.message.create("error","验证码错误")):this.loginMobilePassword()}submitFormUserPassword(e){for(const e in this.validateForm.controls)this.validateForm.controls[e].markAsDirty(),this.validateForm.controls[e].updateValueAndValidity();this.username=e.mobile||e.username,this.password=e.password;let t=e.checkCode,n=this.code.toLowerCase(),o=t.toLowerCase();console.log(n,o),n!=o?(console.log(n,o),this.message.create("error","验证码错误")):this.authServ.login(this.username,this.password).then((async e=>{})).catch((e=>{console.log(e),this.message.create("error","错误的用户名或密码")}))}async forgetFormFun(e){for(const e in this.forgetForm.controls)this.forgetForm.controls[e].markAsDirty(),this.forgetForm.controls[e].updateValueAndValidity();if(console.log(e.forgetusername,e.forgetPassword,e.forgetConfirmpassword),e.forgetPassword!=e.forgetConfirmpassword)return void this.message.create("error","两次密码不一致");if(!e.forgerphoneCode)return void this.message.create("error","请输入验证码");let t=(Parse__default.serverURL?.split("parse")?.[0]||"https://server.fmode.cn/")+"api/auth/reset_password";this.http.post(t,{company:this.companyId,mobile:e.forgetusername,code:e.forgerphoneCode,password:e.forgetConfirmpassword}).subscribe((e=>{200==e.code?(this.message.create("success",e.msg),this.type="login"):this.message.create("error","验证码错误")}),(e=>{console.log(e.error),this.message.create("error",e.error.mess)}))}async registSubmitForm(e){for(const e in this.registForm.controls)this.registForm.controls[e].markAsDirty(),this.registForm.controls[e].updateValueAndValidity();this.registName=e.registName,this.registIdcard=e.registIdcard,this.registPhone=e.registPhone,this.phoneCode=e.phoneCode,this.regpassword=e.regpassword,this.confirmPassword=e.confirmPassword;let t=await this.verifyCode(this.registPhone,this.phoneCode);t&&200!=t.code?this.message.create("error",t.mess):this.queryUser()}getSelectEducation(){this.loginMobilePassword(),this.iseducation=!1}loginSMS(){let e=(Parse__default.serverURL?.split("parse")?.[0]||"https://server.fmode.cn/")+`api/auth/mobile?company=${this.companyId}&mobile=${this.username}&code=${this.smsCode}`;this.http.get(e).subscribe((e=>{if(console.log(e),200==e.code){this.message.create("success","登录成功");let t=e.data.token;Parse__default.User.become(t).then((e=>{this.router.navigate([decodeURIComponent(this.rootPage)])}))}else this.message.create("error","验证码错误")}),(e=>{console.log(e.error),this.message.create("error",e.error.mess)}))}async loginMobilePassword(){let e=await this.getMobileUser(this.username);e?this.authServ.login(e,this.password).then((async e=>{})).catch((e=>{console.log(e),this.message.create("error","错误的用户名或密码")})):this.message.create("error","用户不存在,请尝试其他登录方式")}async queryUser(){let e=new Parse__default.Query("_User");e.contains("username",this.registPhone),e.equalTo("company",this.companyId);let t=await e.first();t?.id?this.message.info("该账户已激活,使用手机号密码直接登录"):Parse__default.User.signUp(this.companyId+"-"+this.registPhone,this.regpassword,"").then((async e=>{e.id&&(console.log(e),e.set("company",{__type:"Pointer",className:"Company",objectId:this.companyId}),e.set("mobile",this.registPhone),e.set("type","user"),e.save(),this.username=this.registPhone,this.password=this.regpassword)}))}async getMobileUser(e){if(this.mobileUserMap[e])return this.mobileUserMap[e];let t=await this.novaCloud.api("/auth/getusername",{company:this.companyId,mobile:e});return console.log(t),t?.username&&(this.mobileUserMap[e]=t?.username),this.mobileUserMap[e]}forget(){this.type="forget"}backLogin(){this.type="login"}handleCancel(){this.isVisible=!1}handleOk(){Parse__default.User.signUp(this.registPhone,this.regpassword,"").then((async e=>{e.id&&(console.log(e),e.set("company",{__type:"Pointer",className:"Company",objectId:this.companyId}),e.save(),this.username=this.registPhone,this.password=this.regpassword)}))}async getCode(){if(null==this.registPhone||""==this.registPhone.trim())return void this.message.info("请输入注册手机号");if(!this.registPhone.match(/^1[3456789]\d{9}$/))return void this.message.info("请输入正确的手机号");let e=new Parse__default.Query("User");e.equalTo("username",this.registPhone),e.equalTo("company",this.companyId);let t=await e.first();if(t&&t.id)return void this.message.info("该手机号已注册,请使用账号密码登录");let n=localStorage.getItem("NOVA_APIG_SERVER");n=decodeURIComponent(atob(n));let o=n+"message";this.http.post(o,{company:this.companyId,mobile:this.registPhone,action:"regist"}).subscribe((e=>{this.vCode=e.data.code,this.countDownFun()}),(e=>{this.message.info("系统繁忙中,请稍后重试"),console.log(e)}))}async getCode2(){if(null==this.forgetusername||""==this.forgetusername.trim())return void this.message.info("请输入账号");if(!this.forgetusername.match(/^1[3456789]\d{9}$/))return void this.message.info("请输入正确的手机号");console.log(this.forgetusername);let e=new Parse__default.Query("User");if(e.equalTo("username",this.companyId+"-"+this.forgetusername),e.equalTo("company",this.companyId),!await e.first())return void this.message.info("账号不存在");let t=localStorage.getItem("NOVA_APIG_SERVER");t=decodeURIComponent(atob(t));let n=t+"message";this.http.post(n,{company:this.companyId,mobile:this.forgetusername,action:"resetPassword"}).subscribe((e=>{console.log(e),this.vCode=e.data.code,this.countDownFun()}),(e=>{this.message.info("系统繁忙中,请稍后重试"),console.log(e)}))}async verifyCode(e,t){let n=localStorage.getItem("NOVA_APIG_SERVER");n=decodeURIComponent(atob(n));let o=n+"verifyCode";return new Promise((async(n,i)=>{this.http.post(o,{mobile:e,code:t}).subscribe((e=>{n(e)}),(e=>{console.log(e),n(e.error)}))}))}countDownFun(){if(this.isCountDown=!0,0==this.countDown)return;let e=setInterval((()=>{this.countDown=this.countDown-1,0==this.countDown&&(clearInterval(e),this.countDown=60,this.isCountDown=!1)}),1e3)}constructor(e,t,n,o,i,a,r,s){this.authServ=e,this.novaCloud=t,this.fb=n,this.toastCtrl=o,this.router=i,this.route=a,this.activatedRoute=r,this.http=s,this.nums=["C","6","Z","t"],this.str="",this.tabIndex=0,this.codeVerified=!1,this.passwordVisible=!1,this.passwordVisible2=!1,this.passwordVisible3=!1,this.iseducation=!1,this.redirectUrl=localStorage.getItem("redirectUrl"),this.isSended=!1,this.isSending=!1,this.smsTimeCount=60,this.loading=!0,this.Lesson=[],this.myDate=new Date,this.isVisible=!1,this.type="login",this.mobileUserMap={},this.isOkLoading=!1,this.countDown=60,this.isCountDown=!1,this.mobileLogin=!1,this.logo="https://www.fmode.cn/images/ewm1.png",this.qrcode="https://www.fmode.cn/images/logo_main.png",this.message=this.authServ.message,this.userNameAsyncValidator=e=>new Observable((t=>{let n=/^1[3456789]\d{9}$/,o=e.value;setTimeout((()=>null==o||""==o.trim()?(this.userErrorTip="请输入登录账号",t.next({error:!0,duplicated:!0}),void t.complete()):o.match(n)?(t.next(null),void t.complete()):(this.userErrorTip="请输入正确的登录账号",t.next({error:!0,duplicated:!0}),void t.complete())),1e3)})),this.smsAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;if(null==n||""==n.trim())return this.smsCodeErrorTip="请输入短信验证码",t.next({error:!0,duplicated:!0}),void t.complete();t.next(null),t.complete()}),1e3)})),this.passwordAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;return null==n||""==n.trim()?(this.passwordErrorTip="请输入密码",t.next({error:!0,duplicated:!0}),void t.complete()):n.length<6?(this.passwordErrorTip="密码长度不得小于6位",t.next({error:!0,duplicated:!0}),void t.complete()):(t.next(null),void t.complete())}),1e3)})),this.codeAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;return null==n||""==n.trim()?(this.codeVerified=!1,this.codeErrorTip="请输入验证码",t.next({error:!0,duplicated:!0}),void t.complete()):n.length<4?(this.codeVerified=!1,this.codeErrorTip="验证码长度不得小于4位",t.next({error:!0,duplicated:!0}),void t.complete()):this.code.toLowerCase()!=n.toLowerCase()?(this.codeVerified=!1,this.codeErrorTip="验证码输入错误",t.next({error:!0,duplicated:!0}),void t.complete()):(this.codeVerified=!0,t.next(null),void t.complete())}),1e3)})),this.registIdcardAsyncValidator=e=>new Observable((t=>{let n=e.value;setTimeout((()=>null==n||""==n.trim()||!1===/^\d{17}(\d|X|x)$/.test(n)?(this.registIdcardErrorTip="请输入正确的身份证号码",t.next({error:!0,duplicated:!0}),void t.complete()):(t.next(null),void t.complete())),1e3)})),this.forgetNameAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;if(null==n||""==n.trim())return this.registNameErrorTip="请输入账户账号或者手机号",t.next({error:!0,duplicated:!0}),void t.complete();this.forgetusername=n,t.next(null),t.complete()}),1e3)})),this.forgetPasswordAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;return null==n||""==n.trim()?(this.passwordErrorTip="请输入新密码",t.next({error:!0,duplicated:!0}),void t.complete()):n.length<6?(this.passwordErrorTip="密码长度不得小于6位",t.next({error:!0,duplicated:!0}),void t.complete()):(this.forgetPassword=n,t.next(null),void t.complete())}),1e3)})),this.forgetConfirmPasswordAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;return null==n||""==n.trim()?(this.forgetphoneCodesErrorTip="请确认新密码",t.next({error:!0,duplicated:!0}),void t.complete()):n.length<6?(this.forgetphoneCodesErrorTip="密码长度不得小于6位",t.next({error:!0,duplicated:!0}),void t.complete()):(this.forgetConfirmpassword=n,t.next(null),void t.complete())}),1e3)})),this.forgetCodeAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;if(null==n||""==n.trim())return this.phoneCodesErrorTip="请输入新密码",t.next({error:!0,duplicated:!0}),void t.complete();this.forgerphoneCode=n,t.next(null),t.complete()}),1e3)})),this.registNameAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;if(null==n||""==n.trim())return this.registNameErrorTip="请输入姓名",t.next({error:!0,duplicated:!0}),void t.complete();this.registName=n,t.next(null),t.complete()}),1e3)})),this.registPhoneAsyncValidator=e=>new Observable((t=>{let n=e.value;setTimeout((()=>null==n||""==n.trim()?(this.registIdcardErrorTip="请输入正确的身份证号码",t.next({error:!0,duplicated:!0}),void t.complete()):!1===/^1[3456789]\d{9}$/.test(n)?(this.phoneErrorTip="请输入正确的手机号",t.next({error:!0,duplicated:!0}),void t.complete()):(t.next(null),void t.complete())),1e3)})),this.registCodeAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;if(null==n||""==n.trim())return this.phoneCodesErrorTip="请输入验证码",t.next({error:!0,duplicated:!0}),void t.complete();t.next(null),t.complete()}),1e3)})),this.regpasswordAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;return null==n||""==n.trim()?(this.regpasswordErrorTip="请输入密码",t.next({error:!0,duplicated:!0}),void t.complete()):n.length<6?(this.regpasswordErrorTip="密码长度不得小于6位",t.next({error:!0,duplicated:!0}),void t.complete()):n.length>12?(this.regpasswordErrorTip="密码长度不得大于12位",t.next({error:!0,duplicated:!0}),void t.complete()):(this.regpassword=n,t.next(null),void t.complete())}),1e3)})),this.confirmPasswordAsyncValidator=e=>new Observable((t=>{setTimeout((()=>{let n=e.value;return null==n||""==n.trim()?(this.confirmPasswordErrorTip="请确认密码",t.next({error:!0,duplicated:!0}),void t.complete()):n!=this.regpassword?(this.confirmPasswordErrorTip="两次输入密码不一致,请重新输入",t.next({error:!0,duplicated:!0}),void t.complete()):(this.confirmPassword=n,t.next(null),void t.complete())}),1e3)})),this.code="",this.initLoginForm(),this.route.paramMap.subscribe((async e=>{console.log(e),this.appId=e.get("appId"),await this.initAppConfig()||(this.companyId=e.get("companyId"),this.companyId||(this.companyId=localStorage.getItem("company")||"Q0DryNYA8g"),await this.initCompanyConfig())}))}async initCompanyConfig(){if(!this.companyId)return;let e=new Parse__default.Query("Company");this.company=await e.get(this.companyId),this.logo=this.company?.get("logo")||this.logo,this.qrcode=this.company?.get("qrcode")||this.qrcode,this.mobileLogin=this.company?.get("jpush")?.appkey||!1,this.rootPage=this.company?.get("rootPage")}async initAppConfig(){if(!this.appId)return!1;let e=new Parse__default.Query("App");return e.include("company"),this.app=await e.get(this.appId),console.log(this.app),this.logo=this.app?.get("logo")||this.logo,this.qrcode=this.app?.get("qrcode")||this.qrcode,this.mobileLogin=this.app?.get("jpush")?.appkey||!1,this.companyId=this.app?.get("company").id,this.rootPage=this.app?.get("rootPage"),!0}initLoginForm(){this.validateForm=this.fb.group({mobile:["",[Validators.required],[this.userNameAsyncValidator]],password:["",[Validators.required],[this.passwordAsyncValidator]],checkCode:["",[Validators.required],[this.codeAsyncValidator]]}),this.validateUserForm=this.fb.group({username:["",[Validators.required],[]],password:["",[Validators.required],[this.passwordAsyncValidator]],checkCode:["",[Validators.required],[this.codeAsyncValidator]]}),this.validateSMSForm=this.fb.group({mobile:["",[Validators.required],[this.userNameAsyncValidator]],password:[""],smsCode:["",[Validators.required],[this.smsAsyncValidator]],checkCode:["",[Validators.required],[this.codeAsyncValidator]]}),this.registForm=this.fb.group({registName:["",[Validators.required],[this.registNameAsyncValidator]],registIdcard:["",[Validators.required],[this.registIdcardAsyncValidator]],registPhone:["",[Validators.required],[this.registPhoneAsyncValidator]],phoneCode:["",[Validators.required],[this.registCodeAsyncValidator]],regpassword:["",[Validators.required],[this.regpasswordAsyncValidator]],confirmPassword:["",[Validators.required],[this.confirmPasswordAsyncValidator]]}),this.forgetForm=this.fb.group({forgetusername:["",[Validators.required],[this.forgetNameAsyncValidator]],forgetPassword:["",[Validators.required],[this.forgetPasswordAsyncValidator]],forgetConfirmpassword:["",[Validators.required],[this.forgetConfirmPasswordAsyncValidator]],forgerphoneCode:["",[Validators.required],[this.registCodeAsyncValidator]]})}ngOnInit(){this.activatedRoute.paramMap.subscribe((e=>{e.get("p")?localStorage.setItem("pid",e.get("p")):localStorage.setItem("company",this.companyId)})),this.creatCode()}creatCode(){this.code="";let e=[0,1,2,3,4,5,6,7,8,9,"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];for(let t=0;t<4;t++){let t=Math.floor(52*Math.random());this.code+=e[t]}}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:LoginComponent,deps:[{token:AuthService},{token:NovaCloudService},{token:i3$3.FormBuilder},{token:i1$3.ToastController},{token:i1$1.Router},{token:i1$1.ActivatedRoute},{token:i1$1.ActivatedRoute},{token:i1.HttpClient}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:LoginComponent,selector:"app-pcuser-login",ngImport:i0,template:'<div class="student-login-layout">\n <div class="nav_center">\n <img [src]="logo" alt="" class="login_img">\n <div class="nav_login">\n <nz-tabset [nzSelectedIndex]="tabIndex" [nzTabPosition]="\'top\'">\n\n \x3c!-- 登录:手机号+密码登入 --\x3e\n <nz-tab nzTitle="手机密码" style="color: #000000;">\n <ng-container *ngIf="type == \'login\'">\n <form nz-form [formGroup]="validateForm" (ngSubmit)="submitFormMobilePassword(validateForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>手机号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="mobile" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="password" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item class="form-control-contain">\n <nz-form-label [nzSpan]="5" class="contain_yanzm" nzRequired >验证码 </nz-form-label>\n <nz-form-control [nzSpan]="6" nzErrorTip="{{codeErrorTip}}" class="contain_input_yanzm">\n <input style="font-size:14px" title="请输入验证码" nz-input type="text" formControlName="checkCode"\n placeholder="区分大小写" />\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="codeText">\n <div style=" height: 100%; margin: 0 4px; text-align: center; letter-spacing: 2px;">{{code}}</div>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div (click)="creatCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 换一个\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button nz-button nzType="primary" [nzSize]="\'large\'" [disabled]="!validateForm.valid">登录</button>\n </div>\n <div class="forget">\n <h6 (click)="forget()">忘记密码</h6>\n </div>\n </form>\n </ng-container>\n <ng-container *ngIf="type == \'forget\'">\n <form nz-form [formGroup]="forgetForm" (ngSubmit)="forgetFormFun(forgetForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>登录账号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="forgetusername" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>新 密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetPassword" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>确认密码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{forgetphoneCodesErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetConfirmpassword" placeholder="请再次输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item class="forget_contain">\n <nz-form-label [nzSpan]="5" nzRequired >验 证 码</nz-form-label>\n <nz-form-control [nzSpan]="8" nzHasFeedback nzErrorTip="{{phoneCodesErrorTip}}" class="codeInput">\n <input style="font-size: 18px;" nz-input type="text" formControlName="forgerphoneCode"\n placeholder="手机验证码" />\n </nz-form-control>\n <nz-form-control [nzSpan]="6" class="getCode">\n <div *ngIf="!isCountDown" (click)="getCode2()" class="get_code"\n style="background-color:#40a9ff;cursor: pointer; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n 获取验证码\n </div>\n <div *ngIf="isCountDown"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n {{countDown}}/秒\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button style="width: 348px;" nz-button nzType="primary" [nzSize]="\'large\'"\n [disabled]="!forgetForm.valid">重置密码</button>\n </div>\n <div class="forget">\n <h6 (click)="backLogin()">返回登录</h6>\n </div>\n </form>\n </ng-container>\n\n </nz-tab>\n\n \x3c!-- 登录:帐号+密码登入 --\x3e\n <nz-tab nzTitle="帐号密码" style="color: #000000;">\n <ng-container *ngIf="type == \'login\'">\n <form nz-form [formGroup]="validateUserForm" (ngSubmit)="submitFormUserPassword(validateUserForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>帐 号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="username" placeholder="请输入帐号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="password" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item class="form-control-contain">\n <nz-form-label [nzSpan]="5" class="contain_yanzm" nzRequired >验证码 </nz-form-label>\n <nz-form-control [nzSpan]="6" nzErrorTip="{{codeErrorTip}}" class="contain_input_yanzm">\n <input style="font-size:14px" title="请输入验证码" nz-input type="text" formControlName="checkCode"\n placeholder="区分大小写" />\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="codeText">\n <div style=" height: 100%; margin: 0 4px; text-align: center; letter-spacing: 2px;">{{code}}</div>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div (click)="creatCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 换一个\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button nz-button nzType="primary" [nzSize]="\'large\'" [disabled]="!validateUserForm.valid">登录</button>\n </div>\n </form>\n </ng-container>\n <ng-container *ngIf="type == \'forget\'">\n <form nz-form [formGroup]="forgetForm" (ngSubmit)="forgetFormFun(forgetForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>登录账号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="forgetusername" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>新 密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetPassword" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>确认密码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{forgetphoneCodesErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetConfirmpassword" placeholder="请再次输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item class="forget_contain">\n <nz-form-label [nzSpan]="5" nzRequired >验 证 码</nz-form-label>\n <nz-form-control [nzSpan]="8" nzHasFeedback nzErrorTip="{{phoneCodesErrorTip}}" class="codeInput">\n <input style="font-size: 18px;" nz-input type="text" formControlName="forgerphoneCode"\n placeholder="手机验证码" />\n </nz-form-control>\n <nz-form-control [nzSpan]="6" class="getCode">\n <div *ngIf="!isCountDown" (click)="getCode2()" class="get_code"\n style="background-color:#40a9ff;cursor: pointer; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n 获取验证码\n </div>\n <div *ngIf="isCountDown"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n {{countDown}}/秒\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button style="width: 348px;" nz-button nzType="primary" [nzSize]="\'large\'"\n [disabled]="!forgetForm.valid">重置密码</button>\n </div>\n <div class="forget">\n <h6 (click)="backLogin()">返回登录</h6>\n </div>\n </form>\n </ng-container>\n\n </nz-tab>\n \x3c!-- 登录:手机号+验证码登入 --\x3e\n <nz-tab nzTitle="短信验证" style="color: #000000;">\n <ng-container *ngIf="type == \'login\'">\n <form nz-form [formGroup]="validateSMSForm" (ngSubmit)="submitFormMobileSMS(validateSMSForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>手 机 号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="mobile" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item class="form-control-contain">\n <nz-form-label [nzSpan]="5" class="contain_yanzm" nzRequired >验证码</nz-form-label>\n <nz-form-control [nzSpan]="6" nzErrorTip="{{codeErrorTip}}" class="contain_input_yanzm">\n <input style="font-size:14px" title="请输入验证码" nz-input type="text" formControlName="checkCode"\n placeholder="区分大小写" />\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="codeText">\n <div style=" height: 100%; margin: 0 4px; text-align: center; letter-spacing: 2px;">{{code}}</div>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div (click)="creatCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 换一个\n </div>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>短信码</nz-form-label>\n <nz-form-control [nzSpan]="10" nzErrorTip="{{smsCodeErrorTip}}">\n <nz-input-group>\n <input nz-input [type]="\'text\'" [disabled]="!isSended || !codeVerified" formControlName="smsCode" placeholder="请输入短信验证码" />\n </nz-input-group>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div *ngIf="!isSending" (click)="sendSMSCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 获取验证码\n </div>\n <div *ngIf="isSending"\n style="background-color:#eff5f9; color: rgb(118, 117, 117); padding: 5px; text-align: center;">\n {{smsTimeCount}}\n </div>\n </nz-form-control>\n </nz-form-item>\n \n <div class="login_btn">\n <button nz-button nzType="primary" [nzSize]="\'large\'" [disabled]="!validateSMSForm.valid">登录</button>\n </div>\n </form>\n </ng-container>\n </nz-tab>\n\n \x3c!-- 注册:企业用户Profile开通 --\x3e\n <nz-tab *ngIf="mobileLogin" nzTitle="开通" style="color: #000000;" class="activation">\n <form nz-form [formGroup]="registForm" (ngSubmit)="registSubmitForm(registForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>开通证件</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzValidatingTip="验证中..."\n nzErrorTip="{{registIdcardErrorTip}}">\n <input title="请输入身份证号码" nz-input formControlName="registIdcard" placeholder="请输入身份证号码" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>开通姓名</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{registNameErrorTip}}">\n <input nz-input type="text" formControlName="registName" placeholder="请输入姓名" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>绑定手机号</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{phoneErrorTip}}">\n <input [(ngModel)]="registPhone" nz-input style="font-size: 18px;" type="text"\n formControlName="registPhone" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item class="verifyCode">\n <nz-form-label [nzSpan]="7" nzRequired>手机验证码</nz-form-label>\n <nz-form-control [nzSpan]="6" class="code_input" nzHasFeedback nzErrorTip="{{phoneCodesErrorTip}}">\n <input style="font-size: 18px;" nz-input type="text" formControlName="phoneCode" placeholder="手机验证码" />\n </nz-form-control>\n <nz-form-control [nzSpan]="6" class="codeContain">\n <div *ngIf="!isCountDown" (click)="getCode()"\n class="get_code"\n style="background-color:#40a9ff; cursor: pointer; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n 获验证码\n </div>\n <div *ngIf="isCountDown"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n {{countDown}}/秒\n </div>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>开通密码</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{regpasswordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate2">\n <input nz-input [type]="passwordVisible2 ? \'text\' : \'password\'" formControlName="regpassword"\n placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate2>\n <i nz-icon [nzType]="passwordVisible2 ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible2 = !passwordVisible2"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>确认密码</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{confirmPasswordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate3">\n <input nz-input [type]="passwordVisible3 ? \'text\' : \'password\'" formControlName="confirmPassword"\n placeholder="请确认密码" />\n </nz-input-group>\n <ng-template #suffixTemplate3>\n <i nz-icon [nzType]="passwordVisible3 ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible3 = !passwordVisible3"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button nz-button nzType="primary" [disabled]="!registForm.valid">申请开通</button>\n </div>\n </form>\n </nz-tab>\n </nz-tabset>\n <div class="nav_login_right">\n <p class="login_right_title">二维码</p>\n <img [src]="qrcode" alt="公众号二维码">\n <p>扫码进入微信端</p>\n \x3c!-- <p class="login_right_bottom">首次登录有惊喜</p> --\x3e\n </div>\n </div>\n\n <div class="loadWrap" style="display: flex;align-items: center;justify-content: center;width: 100%;height: 100%;"\n *ngIf="loading2">\n <nz-spin nzTip="加载中,请稍后...">\n <nz-alert nzType="info" nzMessage="课程加载中,请稍后..."></nz-alert>\n </nz-spin>\n </div>\n\n \x3c!-- 注销 --\x3e\n <nz-modal [(nzVisible)]="isVisible" nzTitle="手机号错误" (nzOnCancel)="handleCancel()" (nzOnOk)="handleOk()">\n <ng-container *nzModalContent>\n <p>手机号错误, 联系管理员核对信息</p>\n </ng-container>\n </nz-modal>\n </div>\n</div>\n',styles:[".student-login-layout{position:fixed;top:0;left:0;background:#fff;width:100%;height:100%;z-index:100;overflow:auto;background:url(https://cloud.fmode.cn/assets/bg-login.jpg) no-repeat;background-size:100% 100%}.student-login-layout .nav_center{width:800px;min-height:450px;margin:0 auto;top:50%;left:50%;transform:translate(-50%,-50%);background-size:inherit;position:absolute;padding:30px;text-align:center}.student-login-layout .nav_center .login_img{max-width:70%;max-height:100px}.student-login-layout .nav_center .nav_login{background:#ffffff1a}.student-login-layout .nav_center ::ng-deep .ant-tabs-tab-btn{font-size:22px}.student-login-layout .nav_center .ant-tabs-tab-btn{border-bottom:2px solid #1890ff}.student-login-layout .nav_center ::ng-deep .ant-tabs-nav{height:55px}.student-login-layout .nav_center ::ng-deep .ant-tabs-nav-list{width:100%;display:flex;justify-content:center;color:#000}.student-login-layout .nav_center ::ng-deep .ant-form-item-required{font-size:18px;font-weight:700}.student-login-layout .nav_center ::ng-deep .ng-invalid{font-size:18px}.student-login-layout .nav_center ::ng-deep .ng-valid{font-size:18px}.student-login-layout .nav_center ::ng-deep .ng-pending{font-size:18px}.student-login-layout .nav_center ::ng-deep .ant-form-item{display:flex;justify-content:center}.student-login-layout .nav_center ::ng-deep .ant-tabs-nav:before{border:none}.student-login-layout .nav_center .nav_login{display:flex;flex-direction:inherit;align-items:center;justify-content:center;width:100%;border-radius:2px;background-color:#fff;margin:0 auto;min-height:500px}.student-login-layout .nav_center .nav_login .login-form{max-width:300px}.student-login-layout .nav_center .nav_login [nz-form]{width:440px;max-width:500px}.student-login-layout .nav_center .nav_login .login_btn{width:400px;margin:0 auto;display:flex;justify-content:center}.student-login-layout .nav_center .nav_login .login_btn button{width:85%}.student-login-layout .nav_center .nav_login .forget{margin:10px 40px 0 auto;display:flex;justify-content:flex-end}.student-login-layout .nav_center .nav_login .forget h6{font-size:14px;color:#40a9ff}.student-login-layout .nav_center .nav_login .login-form-margin{margin-bottom:16px}.student-login-layout .nav_center .nav_login .login-form-forgot{float:right}.student-login-layout .nav_center .nav_login .login-form-button{width:100%}.student-login-layout .nav_center .nav_login .nav_login_right{height:100%;flex:2;border-left:2px dashed #e5e5e5;font-size:16px;display:flex;flex-direction:column;color:#626262;align-items:center;justify-content:center}.student-login-layout .nav_center .nav_login .nav_login_right .login_right_bottom{margin:40px 0 50px}.student-login-layout .nav_center .nav_login .nav_login_right img{width:160px}.student-login-layout .nav_center .iseducation{position:absolute;top:159px;background:#fff;width:90%;flex-direction:column;line-height:50px}.student-login-layout .nav_center .iseducation .login_btn{margin-top:30px}.student-login-layout .nav_center .iseducation .close_education{width:30px;height:30px;position:absolute;top:20px;right:10px;font-size:24px;background-color:#dddddddb;border-radius:15px;line-height:28px;cursor:pointer}.student-login-layout .nav_center .loadWrap{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}@media (min-width: 960px){.nav_center{width:90%}}@media (max-width: 760px){.student-login-layout .nav_center{width:100%}.student-login-layout .nav_center ::ng-deep .ant-form-item-explain{text-align:left!important}.student-login-layout .nav_center ::ng-deep .ng-invalid{font-size:13px!important}.student-login-layout .nav_center ::ng-deep .ant-tabs-tab-btn{font-size:18px}.student-login-layout .nav_center .login_btn{width:100%!important;margin:10px auto!important}.student-login-layout .nav_center .login_btn button{width:100%!important}.student-login-layout .nav_login [nz-form]{width:100%!important;max-width:auto;padding:0 30px;display:flex;justify-content:center;flex-direction:column}.student-login-layout .ant-form-item{margin-bottom:5px}.student-login-layout ::ng-deep .ant-form-item-required{font-size:12px!important;padding-bottom:0!important}.student-login-layout .ant-form-item-label{padding:0}.student-login-layout .form-control-contain{display:flex!important;justify-content:space-between!important;flex-wrap:wrap;margin-top:10px}.student-login-layout .form-control-contain .contain_yanzm{flex:0 0 30%}.student-login-layout .form-control-contain .contain_input_yanzm{flex:0 0 40%}.student-login-layout .form-control-contain .codeText{flex:0 0 30%}.student-login-layout .form-control-contain .switch{flex:0 0 100%}.verifyCode .code_input{flex:0 0 50%}.verifyCode .codeContain{margin-left:10px;flex:0 0 45%}.verifyCode .get_code{font-size:14px!important}.forget_contain .codeInput{flex:0 0 50%}.forget_contain .getCode{margin-left:10px;flex:0 0 45%}.get_code{font-size:14px!important}.iseducation{top:110px!important}.iseducation .close_education #login_btn{width:50%!important}}@media (max-width: 460px){.form-control-contain .switch{margin-top:10px!important}}\n"],dependencies:[{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:i3$3.ɵNgNoValidate,selector:"form:not([ngNoForm]):not([ngNativeValidate])"},{kind:"directive",type:i3$3.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:i3$3.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:i3$3.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:i8.NzInputDirective,selector:"input[nz-input],textarea[nz-input]",inputs:["nzBorderless","nzSize","nzStepperless","nzStatus","disabled"],exportAs:["nzInput"]},{kind:"component",type:i8.NzInputGroupComponent,selector:"nz-input-group",inputs:["nzAddOnBeforeIcon","nzAddOnAfterIcon","nzPrefixIcon","nzSuffixIcon","nzAddOnBefore","nzAddOnAfter","nzPrefix","nzStatus","nzSuffix","nzSize","nzSearch","nzCompact"],exportAs:["nzInputGroup"]},{kind:"directive",type:i8.NzInputGroupWhitSuffixOrPrefixDirective,selector:"nz-input-group[nzSuffix], nz-input-group[nzPrefix]"},{kind:"component",type:i3$4.NzButtonComponent,selector:"button[nz-button], a[nz-button]",inputs:["nzBlock","nzGhost","nzSearch","nzLoading","nzDanger","disabled","tabIndex","nzType","nzShape","nzSize"],exportAs:["nzButton"]},{kind:"directive",type:i4$1.ɵNzTransitionPatchDirective,selector:"[nz-button], nz-button-group, [nz-icon], [nz-menu-item], [nz-submenu], nz-select-top-control, nz-select-placeholder, nz-input-group",inputs:["hidden"]},{kind:"directive",type:i5$3.NzWaveDirective,selector:'[nz-wave],button[nz-button]:not([nzType="link"]):not([nzType="text"])',inputs:["nzWaveExtraNode"],exportAs:["nzWave"]},{kind:"component",type:i12.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:i12.NzModalContentDirective,selector:"[nzModalContent]",exportAs:["nzModalContent"]},{kind:"component",type:i13.NzSpinComponent,selector:"nz-spin",inputs:["nzIndicator","nzSize","nzTip","nzDelay","nzSimple","nzSpinning"],exportAs:["nzSpin"]},{kind:"component",type:i14$1.NzTabSetComponent,selector:"nz-tabset",inputs:["nzSelectedIndex","nzTabPosition","nzTabBarExtraContent","nzCanDeactivate","nzAddIcon","nzTabBarStyle","nzType","nzSize","nzAnimated","nzTabBarGutter","nzHideAdd","nzCentered","nzHideAll","nzLinkRouter","nzLinkExact"],outputs:["nzSelectChange","nzSelectedIndexChange","nzTabListScroll","nzClose","nzAdd"],exportAs:["nzTabset"]},{kind:"component",type:i14$1.NzTabComponent,selector:"nz-tab",inputs:["nzTitle","nzClosable","nzCloseIcon","nzDisabled","nzForceRender"],outputs:["nzSelect","nzDeselect","nzClick","nzContextmenu"],exportAs:["nzTab"]},{kind:"directive",type:i14.NzColDirective,selector:"[nz-col],nz-col,nz-form-control,nz-form-label",inputs:["nzFlex","nzSpan","nzOrder","nzOffset","nzPush","nzPull","nzXs","nzSm","nzMd","nzLg","nzXl","nzXXl"],exportAs:["nzCol"]},{kind:"directive",type:i14.NzRowDirective,selector:"[nz-row],nz-row,nz-form-item",inputs:["nzAlign","nzJustify","nzGutter"],exportAs:["nzRow"]},{kind:"directive",type:i16$1.NzFormDirective,selector:"[nz-form]",inputs:["nzLayout","nzNoColon","nzAutoTips","nzDisableAutoTips","nzTooltipIcon","nzLabelAlign","nzLabelWrap"],exportAs:["nzForm"]},{kind:"component",type:i16$1.NzFormItemComponent,selector:"nz-form-item",exportAs:["nzFormItem"]},{kind:"component",type:i16$1.NzFormLabelComponent,selector:"nz-form-label",inputs:["nzFor","nzRequired","nzNoColon","nzTooltipTitle","nzTooltipIcon","nzLabelAlign","nzLabelWrap"],exportAs:["nzFormLabel"]},{kind:"component",type:i16$1.NzFormControlComponent,selector:"nz-form-control",inputs:["nzSuccessTip","nzWarningTip","nzErrorTip","nzValidatingTip","nzExtra","nzAutoTips","nzDisableAutoTips","nzHasFeedback","nzValidateStatus"],exportAs:["nzFormControl"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:LoginComponent,decorators:[{type:Component,args:[{selector:"app-pcuser-login",template:'<div class="student-login-layout">\n <div class="nav_center">\n <img [src]="logo" alt="" class="login_img">\n <div class="nav_login">\n <nz-tabset [nzSelectedIndex]="tabIndex" [nzTabPosition]="\'top\'">\n\n \x3c!-- 登录:手机号+密码登入 --\x3e\n <nz-tab nzTitle="手机密码" style="color: #000000;">\n <ng-container *ngIf="type == \'login\'">\n <form nz-form [formGroup]="validateForm" (ngSubmit)="submitFormMobilePassword(validateForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>手机号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="mobile" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="password" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item class="form-control-contain">\n <nz-form-label [nzSpan]="5" class="contain_yanzm" nzRequired >验证码 </nz-form-label>\n <nz-form-control [nzSpan]="6" nzErrorTip="{{codeErrorTip}}" class="contain_input_yanzm">\n <input style="font-size:14px" title="请输入验证码" nz-input type="text" formControlName="checkCode"\n placeholder="区分大小写" />\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="codeText">\n <div style=" height: 100%; margin: 0 4px; text-align: center; letter-spacing: 2px;">{{code}}</div>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div (click)="creatCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 换一个\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button nz-button nzType="primary" [nzSize]="\'large\'" [disabled]="!validateForm.valid">登录</button>\n </div>\n <div class="forget">\n <h6 (click)="forget()">忘记密码</h6>\n </div>\n </form>\n </ng-container>\n <ng-container *ngIf="type == \'forget\'">\n <form nz-form [formGroup]="forgetForm" (ngSubmit)="forgetFormFun(forgetForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>登录账号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="forgetusername" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>新 密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetPassword" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>确认密码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{forgetphoneCodesErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetConfirmpassword" placeholder="请再次输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item class="forget_contain">\n <nz-form-label [nzSpan]="5" nzRequired >验 证 码</nz-form-label>\n <nz-form-control [nzSpan]="8" nzHasFeedback nzErrorTip="{{phoneCodesErrorTip}}" class="codeInput">\n <input style="font-size: 18px;" nz-input type="text" formControlName="forgerphoneCode"\n placeholder="手机验证码" />\n </nz-form-control>\n <nz-form-control [nzSpan]="6" class="getCode">\n <div *ngIf="!isCountDown" (click)="getCode2()" class="get_code"\n style="background-color:#40a9ff;cursor: pointer; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n 获取验证码\n </div>\n <div *ngIf="isCountDown"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n {{countDown}}/秒\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button style="width: 348px;" nz-button nzType="primary" [nzSize]="\'large\'"\n [disabled]="!forgetForm.valid">重置密码</button>\n </div>\n <div class="forget">\n <h6 (click)="backLogin()">返回登录</h6>\n </div>\n </form>\n </ng-container>\n\n </nz-tab>\n\n \x3c!-- 登录:帐号+密码登入 --\x3e\n <nz-tab nzTitle="帐号密码" style="color: #000000;">\n <ng-container *ngIf="type == \'login\'">\n <form nz-form [formGroup]="validateUserForm" (ngSubmit)="submitFormUserPassword(validateUserForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>帐 号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="username" placeholder="请输入帐号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="password" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item class="form-control-contain">\n <nz-form-label [nzSpan]="5" class="contain_yanzm" nzRequired >验证码 </nz-form-label>\n <nz-form-control [nzSpan]="6" nzErrorTip="{{codeErrorTip}}" class="contain_input_yanzm">\n <input style="font-size:14px" title="请输入验证码" nz-input type="text" formControlName="checkCode"\n placeholder="区分大小写" />\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="codeText">\n <div style=" height: 100%; margin: 0 4px; text-align: center; letter-spacing: 2px;">{{code}}</div>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div (click)="creatCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 换一个\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button nz-button nzType="primary" [nzSize]="\'large\'" [disabled]="!validateUserForm.valid">登录</button>\n </div>\n </form>\n </ng-container>\n <ng-container *ngIf="type == \'forget\'">\n <form nz-form [formGroup]="forgetForm" (ngSubmit)="forgetFormFun(forgetForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>登录账号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="forgetusername" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>新 密 码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{passwordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetPassword" placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>确认密码</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{forgetphoneCodesErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate">\n <input nz-input [type]="passwordVisible ? \'text\' : \'password\'" formControlName="forgetConfirmpassword" placeholder="请再次输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate>\n <i nz-icon [nzType]="passwordVisible ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible = !passwordVisible"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item class="forget_contain">\n <nz-form-label [nzSpan]="5" nzRequired >验 证 码</nz-form-label>\n <nz-form-control [nzSpan]="8" nzHasFeedback nzErrorTip="{{phoneCodesErrorTip}}" class="codeInput">\n <input style="font-size: 18px;" nz-input type="text" formControlName="forgerphoneCode"\n placeholder="手机验证码" />\n </nz-form-control>\n <nz-form-control [nzSpan]="6" class="getCode">\n <div *ngIf="!isCountDown" (click)="getCode2()" class="get_code"\n style="background-color:#40a9ff;cursor: pointer; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n 获取验证码\n </div>\n <div *ngIf="isCountDown"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n {{countDown}}/秒\n </div>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button style="width: 348px;" nz-button nzType="primary" [nzSize]="\'large\'"\n [disabled]="!forgetForm.valid">重置密码</button>\n </div>\n <div class="forget">\n <h6 (click)="backLogin()">返回登录</h6>\n </div>\n </form>\n </ng-container>\n\n </nz-tab>\n \x3c!-- 登录:手机号+验证码登入 --\x3e\n <nz-tab nzTitle="短信验证" style="color: #000000;">\n <ng-container *ngIf="type == \'login\'">\n <form nz-form [formGroup]="validateSMSForm" (ngSubmit)="submitFormMobileSMS(validateSMSForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>手 机 号</nz-form-label>\n <nz-form-control [nzSpan]="14" nzErrorTip="{{userErrorTip}}">\n <input nz-input formControlName="mobile" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item class="form-control-contain">\n <nz-form-label [nzSpan]="5" class="contain_yanzm" nzRequired >验证码</nz-form-label>\n <nz-form-control [nzSpan]="6" nzErrorTip="{{codeErrorTip}}" class="contain_input_yanzm">\n <input style="font-size:14px" title="请输入验证码" nz-input type="text" formControlName="checkCode"\n placeholder="区分大小写" />\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="codeText">\n <div style=" height: 100%; margin: 0 4px; text-align: center; letter-spacing: 2px;">{{code}}</div>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div (click)="creatCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 换一个\n </div>\n </nz-form-control>\n </nz-form-item>\n\n <nz-form-item>\n <nz-form-label [nzSpan]="5" nzRequired>短信码</nz-form-label>\n <nz-form-control [nzSpan]="10" nzErrorTip="{{smsCodeErrorTip}}">\n <nz-input-group>\n <input nz-input [type]="\'text\'" [disabled]="!isSended || !codeVerified" formControlName="smsCode" placeholder="请输入短信验证码" />\n </nz-input-group>\n </nz-form-control>\n <nz-form-control [nzSpan]="4" class="switch">\n <div *ngIf="!isSending" (click)="sendSMSCode()"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center;">\n 获取验证码\n </div>\n <div *ngIf="isSending"\n style="background-color:#eff5f9; color: rgb(118, 117, 117); padding: 5px; text-align: center;">\n {{smsTimeCount}}\n </div>\n </nz-form-control>\n </nz-form-item>\n \n <div class="login_btn">\n <button nz-button nzType="primary" [nzSize]="\'large\'" [disabled]="!validateSMSForm.valid">登录</button>\n </div>\n </form>\n </ng-container>\n </nz-tab>\n\n \x3c!-- 注册:企业用户Profile开通 --\x3e\n <nz-tab *ngIf="mobileLogin" nzTitle="开通" style="color: #000000;" class="activation">\n <form nz-form [formGroup]="registForm" (ngSubmit)="registSubmitForm(registForm.value)">\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>开通证件</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzValidatingTip="验证中..."\n nzErrorTip="{{registIdcardErrorTip}}">\n <input title="请输入身份证号码" nz-input formControlName="registIdcard" placeholder="请输入身份证号码" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>开通姓名</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{registNameErrorTip}}">\n <input nz-input type="text" formControlName="registName" placeholder="请输入姓名" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>绑定手机号</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{phoneErrorTip}}">\n <input [(ngModel)]="registPhone" nz-input style="font-size: 18px;" type="text"\n formControlName="registPhone" placeholder="请输入手机号" />\n </nz-form-control>\n </nz-form-item>\n <nz-form-item class="verifyCode">\n <nz-form-label [nzSpan]="7" nzRequired>手机验证码</nz-form-label>\n <nz-form-control [nzSpan]="6" class="code_input" nzHasFeedback nzErrorTip="{{phoneCodesErrorTip}}">\n <input style="font-size: 18px;" nz-input type="text" formControlName="phoneCode" placeholder="手机验证码" />\n </nz-form-control>\n <nz-form-control [nzSpan]="6" class="codeContain">\n <div *ngIf="!isCountDown" (click)="getCode()"\n class="get_code"\n style="background-color:#40a9ff; cursor: pointer; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n 获验证码\n </div>\n <div *ngIf="isCountDown"\n style="background-color:#40a9ff; color: #fff; padding: 5px; text-align: center; font-size: 18px;">\n {{countDown}}/秒\n </div>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>开通密码</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{regpasswordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate2">\n <input nz-input [type]="passwordVisible2 ? \'text\' : \'password\'" formControlName="regpassword"\n placeholder="请输入密码" />\n </nz-input-group>\n <ng-template #suffixTemplate2>\n <i nz-icon [nzType]="passwordVisible2 ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible2 = !passwordVisible2"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-label [nzSpan]="7" nzRequired>确认密码</nz-form-label>\n <nz-form-control [nzSpan]="12" nzHasFeedback nzErrorTip="{{confirmPasswordErrorTip}}">\n <nz-input-group [nzSuffix]="suffixTemplate3">\n <input nz-input [type]="passwordVisible3 ? \'text\' : \'password\'" formControlName="confirmPassword"\n placeholder="请确认密码" />\n </nz-input-group>\n <ng-template #suffixTemplate3>\n <i nz-icon [nzType]="passwordVisible3 ? \'eye-invisible\' : \'eye\'"\n (click)="passwordVisible3 = !passwordVisible3"></i>\n </ng-template>\n </nz-form-control>\n </nz-form-item>\n <div class="login_btn">\n <button nz-button nzType="primary" [disabled]="!registForm.valid">申请开通</button>\n </div>\n </form>\n </nz-tab>\n </nz-tabset>\n <div class="nav_login_right">\n <p class="login_right_title">二维码</p>\n <img [src]="qrcode" alt="公众号二维码">\n <p>扫码进入微信端</p>\n \x3c!-- <p class="login_right_bottom">首次登录有惊喜</p> --\x3e\n </div>\n </div>\n\n <div class="loadWrap" style="display: flex;align-items: center;justify-content: center;width: 100%;height: 100%;"\n *ngIf="loading2">\n <nz-spin nzTip="加载中,请稍后...">\n <nz-alert nzType="info" nzMessage="课程加载中,请稍后..."></nz-alert>\n </nz-spin>\n </div>\n\n \x3c!-- 注销 --\x3e\n <nz-modal [(nzVisible)]="isVisible" nzTitle="手机号错误" (nzOnCancel)="handleCancel()" (nzOnOk)="handleOk()">\n <ng-container *nzModalContent>\n <p>手机号错误, 联系管理员核对信息</p>\n </ng-container>\n </nz-modal>\n </div>\n</div>\n',styles:[".student-login-layout{position:fixed;top:0;left:0;background:#fff;width:100%;height:100%;z-index:100;overflow:auto;background:url(https://cloud.fmode.cn/assets/bg-login.jpg) no-repeat;background-size:100% 100%}.student-login-layout .nav_center{width:800px;min-height:450px;margin:0 auto;top:50%;left:50%;transform:translate(-50%,-50%);background-size:inherit;position:absolute;padding:30px;text-align:center}.student-login-layout .nav_center .login_img{max-width:70%;max-height:100px}.student-login-layout .nav_center .nav_login{background:#ffffff1a}.student-login-layout .nav_center ::ng-deep .ant-tabs-tab-btn{font-size:22px}.student-login-layout .nav_center .ant-tabs-tab-btn{border-bottom:2px solid #1890ff}.student-login-layout .nav_center ::ng-deep .ant-tabs-nav{height:55px}.student-login-layout .nav_center ::ng-deep .ant-tabs-nav-list{width:100%;display:flex;justify-content:center;color:#000}.student-login-layout .nav_center ::ng-deep .ant-form-item-required{font-size:18px;font-weight:700}.student-login-layout .nav_center ::ng-deep .ng-invalid{font-size:18px}.student-login-layout .nav_center ::ng-deep .ng-valid{font-size:18px}.student-login-layout .nav_center ::ng-deep .ng-pending{font-size:18px}.student-login-layout .nav_center ::ng-deep .ant-form-item{display:flex;justify-content:center}.student-login-layout .nav_center ::ng-deep .ant-tabs-nav:before{border:none}.student-login-layout .nav_center .nav_login{display:flex;flex-direction:inherit;align-items:center;justify-content:center;width:100%;border-radius:2px;background-color:#fff;margin:0 auto;min-height:500px}.student-login-layout .nav_center .nav_login .login-form{max-width:300px}.student-login-layout .nav_center .nav_login [nz-form]{width:440px;max-width:500px}.student-login-layout .nav_center .nav_login .login_btn{width:400px;margin:0 auto;display:flex;justify-content:center}.student-login-layout .nav_center .nav_login .login_btn button{width:85%}.student-login-layout .nav_center .nav_login .forget{margin:10px 40px 0 auto;display:flex;justify-content:flex-end}.student-login-layout .nav_center .nav_login .forget h6{font-size:14px;color:#40a9ff}.student-login-layout .nav_center .nav_login .login-form-margin{margin-bottom:16px}.student-login-layout .nav_center .nav_login .login-form-forgot{float:right}.student-login-layout .nav_center .nav_login .login-form-button{width:100%}.student-login-layout .nav_center .nav_login .nav_login_right{height:100%;flex:2;border-left:2px dashed #e5e5e5;font-size:16px;display:flex;flex-direction:column;color:#626262;align-items:center;justify-content:center}.student-login-layout .nav_center .nav_login .nav_login_right .login_right_bottom{margin:40px 0 50px}.student-login-layout .nav_center .nav_login .nav_login_right img{width:160px}.student-login-layout .nav_center .iseducation{position:absolute;top:159px;background:#fff;width:90%;flex-direction:column;line-height:50px}.student-login-layout .nav_center .iseducation .login_btn{margin-top:30px}.student-login-layout .nav_center .iseducation .close_education{width:30px;height:30px;position:absolute;top:20px;right:10px;font-size:24px;background-color:#dddddddb;border-radius:15px;line-height:28px;cursor:pointer}.student-login-layout .nav_center .loadWrap{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}@media (min-width: 960px){.nav_center{width:90%}}@media (max-width: 760px){.student-login-layout .nav_center{width:100%}.student-login-layout .nav_center ::ng-deep .ant-form-item-explain{text-align:left!important}.student-login-layout .nav_center ::ng-deep .ng-invalid{font-size:13px!important}.student-login-layout .nav_center ::ng-deep .ant-tabs-tab-btn{font-size:18px}.student-login-layout .nav_center .login_btn{width:100%!important;margin:10px auto!important}.student-login-layout .nav_center .login_btn button{width:100%!important}.student-login-layout .nav_login [nz-form]{width:100%!important;max-width:auto;padding:0 30px;display:flex;justify-content:center;flex-direction:column}.student-login-layout .ant-form-item{margin-bottom:5px}.student-login-layout ::ng-deep .ant-form-item-required{font-size:12px!important;padding-bottom:0!important}.student-login-layout .ant-form-item-label{padding:0}.student-login-layout .form-control-contain{display:flex!important;justify-content:space-between!important;flex-wrap:wrap;margin-top:10px}.student-login-layout .form-control-contain .contain_yanzm{flex:0 0 30%}.student-login-layout .form-control-contain .contain_input_yanzm{flex:0 0 40%}.student-login-layout .form-control-contain .codeText{flex:0 0 30%}.student-login-layout .form-control-contain .switch{flex:0 0 100%}.verifyCode .code_input{flex:0 0 50%}.verifyCode .codeContain{margin-left:10px;flex:0 0 45%}.verifyCode .get_code{font-size:14px!important}.forget_contain .codeInput{flex:0 0 50%}.forget_contain .getCode{margin-left:10px;flex:0 0 45%}.get_code{font-size:14px!important}.iseducation{top:110px!important}.iseducation .close_education #login_btn{width:50%!important}}@media (max-width: 460px){.form-control-contain .switch{margin-top:10px!important}}\n"]}]}],ctorParameters:()=>[{type:AuthService},{type:NovaCloudService},{type:i3$3.FormBuilder},{type:i1$3.ToastController},{type:i1$1.Router},{type:i1$1.ActivatedRoute},{type:i1$1.ActivatedRoute},{type:i1.HttpClient}]});class ModalUserLoginComponent{constructor(e,t,n,o,i){this.authServ=e,this.router=t,this.route=n,this.http=o,this.toastCtrl=i,this.isUserRuleChecked=!1,this.loginInfo={mobile:"",code:""},this.localCodeNum="",this.msg=this.authServ.message,this.countdown=60,this.buttonText="获取验证码",this.isCountingdown=!1,this.drawCode=[]}ngOnInit(){this.close()}ngAfterViewInit(){this.setActiveButton(this.authServ.activeButton)}signMobilePassword(){this.mobile&&this.password?this.password==this.password2?this.authServ.signMobilePassword(this.mobile,this.password).then((e=>{e?.id&&this.setActiveButton("账号密码")})).catch((e=>{this.msg.error("注册失败,请更换手机号注册")})):this.msg.error("两次输入密码不同,请检查"):this.msg.error("请输入完整手机号和密码")}loginMobilePassword(){this.mobile&&this.password?this.authServ.loginMobilePassword(this.mobile,this.password,this.msg):this.msg.error("请输入完整手机号和密码")}close(){let e=this.authServ.isGuardLock(this.router.url);this.authServ.isModalShow=e}goHome(){let e=this.router.url;return e?.indexOf("yuban")&&this.router.navigateByUrl("/app/home"),e.indexOf("chat")>-1?(this.router.navigateByUrl("/chat/home"),void(this.authServ.isModalShow=!1)):e.indexOf("imagine")>-1?(this.router.navigateByUrl("/imagine/home"),void(this.authServ.isModalShow=!1)):(this.router.navigateByUrl("/"),void(this.authServ.isModalShow=!1))}handleEscapeKey(e){this.close()}setActiveButton(e){this.authServ.activeButton=e,console.log(this.authServ.activeButton),this.updateDrawCode()}smsAutoLogin(){6==this.loginInfo.code?.length&&this.login()}startCountdown(){if(!String(this.loginInfo.mobile).match(/^1[3456789]\d{9}$/))return void this.msg.error("请填写正确手机号");let e=this.drawCode.join("");if(this.authServ.enabledLocalCode&&this.localCodeNum.toLowerCase()!=e.toLowerCase())return void this.msg.error("校验码不正确");let t=Parse__default.serverURL?.split("parse")?.[0]||"https://server.fmode.cn/";this.isCountingdown=!0,this.http.post(t+"api/apig/message",{company:this.authServ.company,mobile:this.loginInfo.mobile}).subscribe((e=>{console.log(e),this.msg.success("发送成功"),this.time(),this.updateDrawCode(),this.focusSmsCodeInput()}))}focusSmsCodeInput(){this.smsCodeInput.nativeElement.focus()}time(){this.isCountingdown=!0,this.buttonText=`${this.countdown}秒`;let e=setInterval((()=>{this.countdown--,this.buttonText=`${this.countdown}秒`,(0===this.countdown||this.countdown<0)&&(clearInterval(e),this.buttonText="重新发送",this.isCountingdown=!1,this.countdown=0)}),1e3)}async login(){let e;if(!String(this.loginInfo.mobile).match(/^1[3456789]\d{9}$/))return void this.msg.error("请填写正确手机号");if(!this.loginInfo.code)return void this.msg.error("请输入短信验证码");this.loginInfo.code=this.loginInfo.code?.slice(0,6);try{e=await this.authServ.loginCode(this.loginInfo.mobile,this.loginInfo.code,this.msg)}catch(e){}let t=Parse__default.User.current();if((e||t?.id)&&(console.log(e,t?.id,"close"),this.close(),this.loginInfo={mobile:"",code:""},this.localCodeNum="",this.toast({color:"success",message:"登录成功"}),"modal"==this.authServ.guardType)){let e=new URLSearchParams(location.search);e.set("t",String((new Date).getTime()));let t="/"+(location.origin+location.pathname).replaceAll(document.baseURI,"")+`?${e.toString()}`;console.log(t),this.router.navigateByUrl(t)}}async toast(e){e.position=e?.position||"top",e.duration=e?.duration||1500,e.color=e?.color||"primary",(await this.toastCtrl.create(e)).present()}updateDrawCode(){if(!this.authServ.enabledLocalCode)return;let e=100,t=document.getElementById("canvas");t&&this.canvasDom.nativeElement.removeChild(t),this.canvasDom.nativeElement;let n=document.createElement("canvas");n.width=100,n.height=44,n.className="canvas",n.setAttribute("id","canvas"),n.addEventListener("click",(()=>{this.updateDrawCode()}));let o=n.getContext("2d");n.width=e,n.height=44;let i="A,B,C,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,W,X,Y,Z,1,2,3,4,5,6,7,8,9,0,q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m".split(","),a=i.length;for(let e=0;e<=3;e++){let t=Math.floor(Math.random()*a),n=30*Math.random()*Math.PI/180,r=i[t];this.drawCode[e]=r;let s=10+20*e,l=20+8*Math.random();o.font="bold 23px 微软雅黑",o.translate(s,l),o.rotate(n),o.fillStyle=this.randomColor(),o.fillText(r,0,0),o.rotate(-n),o.translate(-s,-l)}for(let t=0;t<=5;t++)o.strokeStyle=this.randomColor(),o.beginPath(),o.moveTo(Math.random()*e,44*Math.random()),o.lineTo(Math.random()*e,44*Math.random()),o.stroke();for(let t=0;t<=30;t++){o.strokeStyle=this.randomColor(),o.beginPath();let t=Math.random()*e,n=44*Math.random();o.moveTo(t,n),o.lineTo(t+1,n+1),o.stroke()}this.canvasDom.nativeElement.appendChild(n)}randomColor(){return"rgb("+Math.floor(256*Math.random())+","+Math.floor(256*Math.random())+","+Math.floor(256*Math.random())+")"}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalUserLoginComponent,deps:[{token:AuthService},{token:i1$1.Router},{token:i1$1.ActivatedRoute},{token:i1.HttpClient},{token:i1$3.ToastController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ModalUserLoginComponent,isStandalone:!0,selector:"fm-modal-user-login",host:{listeners:{"document:keydown.escape":"handleEscapeKey($event)"}},viewQueries:[{propertyName:"canvasDom",first:!0,predicate:["canvasDom"],descendants:!0},{propertyName:"smsCodeInput",first:!0,predicate:["smsCodeInput"],descendants:!0}],ngImport:i0,template:'\x3c!--登录弹出框设置--\x3e\n\x3c!--背景灰色蒙版--\x3e\n<div\n class="popup"\n [style.display]="authServ.isModalShow ? \'block\' : \'none\'"\n (click)="close()"\n>\n <div class="popup-content" [class.fullscreen]="authServ.modalType==\'fullscreen\'" [class.sheet]="authServ.modalType==\'sheet\'"\n (click)="$event.stopPropagation()">\n <div class="popup-box">\n \x3c!--弹框内设置position:absolute,规范排版,后续只需position:relative增减内容--\x3e\n <div class="popup-box-content">\n <div class="logo-img-login">\n <img\n [src]="authServ.logoUrl"\n alt="fmode"\n />\n </div>\n\n \x3c!--关闭图标按钮--\x3e\n <div class="close-icon-box">\n <div class="iconfont icon-shanchu2" (click)="close()"></div>\n </div>\n \x3c!--按钮切换登录方式--\x3e\n <div class="button-box" *ngIf="authServ?.loginTypeCount>1">\n <div class="button-group">\n <button *ngIf="authServ?.loginOptions?.userpwd"\n class="login-select-button"\n [class.active]="authServ.activeButton === \'账号密码\'"\n (click)="setActiveButton(\'账号密码\')"\n >\n 账号密码\n </button>\n <button *ngIf="authServ?.loginOptions?.mobilecode"\n class="login-select-button"\n [class.active]="authServ.activeButton === \'短信验证\'"\n (click)="setActiveButton(\'短信验证\')"\n >\n 短信验证\n </button>\n <button *ngIf="authServ?.loginOptions?.wechat"\n class="login-select-button"\n [class.active]="authServ.activeButton === \'微信扫码\'"\n (click)="setActiveButton(\'微信扫码\')"\n >\n 微信扫码\n </button>\n </div>\n </div>\n\n \x3c!--手机验证码--\x3e\n <form class="message-form" [class.active]="authServ.activeButton === \'短信验证\'" *ngIf="authServ?.loginOptions?.mobilecode">\n <div class="login-input-box">\n <div class="popup-input-frontnumber">+86</div>\n <input\n class="popup-input-itemone"\n type="text"\n required="required"\n [(ngModel)]="loginInfo.mobile"\n [ngModelOptions]="{ standalone: true }"\n maxlength="12"\n placeholder="请输入手机号"\n />\n </div>\n <div *ngIf="authServ?.enabledLocalCode"\n class="login-input-box local-code" #canvasDom>\n <input\n class="popup-input-itemtwo"\n type="text"\n required="required"\n [(ngModel)]="localCodeNum"\n [ngModelOptions]="{ standalone: true }"\n maxlength="4"\n placeholder="请输入校验码"\n />\n \x3c!-- <canvas\n #canvas\n width="100"\n height="44"\n (click)="updateDrawCode()"\n class="canvas"\n ></canvas> --\x3e\n </div>\n <div class="login-input-box">\n <input #smsCodeInput\n class="popup-input-itemtwo"\n type="text"\n required="required"\n placeholder="请输入短信验证码"\n [(ngModel)]="loginInfo.code"\n (change)="smsAutoLogin()"\n [ngModelOptions]="{ standalone: true }"\n maxlength="6"\n />\n <button\n class="checknumber-button"\n type="submit"\n [value]="buttonText"\n [disabled]="isCountingdown"\n (click)="startCountdown()"\n [class.active]="isCountingdown"\n >\n {{buttonText}}\n </button>\n </div>\n\n \x3c!-- 用户协议 --\x3e\n <div class="rule-box">\n <span>未注册的手机号,将自动创建帐号并登录。</span>\n </div>\n\n <div class="login-submit-box">\n <button class="login-submit-button" type="submit" (click)="login()">\n 登录\n </button>\n </div>\n </form>\n\n \x3c!--账号密码登录--\x3e\n <form class="mobile-form" [class.active]="authServ.activeButton === \'账号密码\'" *ngIf="authServ?.loginOptions?.userpwd">\n <div class="login-input-box">\n <input\n maxlength="12"\n [(ngModel)]="mobile"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="text"\n required="required"\n placeholder="请输入手机号"\n />\n </div>\n\n <div class="login-input-box">\n <input\n [(ngModel)]="password"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="password"\n required="required"\n placeholder="请输入密码"\n />\n </div>\n\n \x3c!-- 记住密码 --\x3e\n <div class="passwprd-box">\n <div class="remember-password-box">\n <input type="checkbox" id="remember-password" />\n 记住密码\n </div>\n\n \x3c!-- 忘记密码 --\x3e\n <div class="password-forget" (click)="setActiveButton(\'注册帐号\')">\n 注册帐号\n </div>\n </div>\n\n \x3c!-- 用户协议 --\x3e\n <div class="rule-box">\n <span>\n <input type="checkbox" [(ngModel)]="isUserRuleChecked" [ngModelOptions]="{ standalone: true }" style="margin-right:5px"/>\n <span (click)="isUserRuleChecked=true">同意</span></span>\n <span (click)="isUserRuleChecked=true">《用户协议及隐私条款》</span>\n </div>\n\n\n \x3c!-- 忘记密码 --\x3e\n \x3c!-- <div class="password-forget">忘记密码?</div>\n </div> --\x3e\n\n <div class="login-submit-box">\n <button\n class="login-submit-button"\n type="submit"\n (click)="loginMobilePassword()"\n >\n 登录\n </button>\n </div>\n </form>\n\n \x3c!-- 帐号密码注册 --\x3e\n <form class="mobile-form" [class.active]="authServ.activeButton === \'注册帐号\'">\n <div class="login-input-box">\n <input\n [(ngModel)]="mobile"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="text"\n required="required"\n placeholder="请输入手机号"\n />\n </div>\n\n <div class="login-input-box">\n <input\n [(ngModel)]="password"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="password"\n required="required"\n placeholder="请输入密码"\n />\n </div>\n\n <div class="login-input-box">\n <input\n [(ngModel)]="password2"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="password"\n required="required"\n placeholder="请再次输入密码"\n />\n </div>\n\n <div class="login-submit-box">\n <button\n class="login-submit-button"\n type="submit"\n (click)="signMobilePassword()"\n >\n 注册\n </button>\n </div>\n </form>\n\n \x3c!--微信扫码登陆--\x3e\n <form class="wechat-form" [class.active]="authServ.activeButton === \'微信扫码\'" *ngIf="authServ?.loginOptions?.wechat">\n <div class="wechat-login-box">\n <img\n class="login-erweima-img"\n [src]="authServ.wechatUrl"\n alt="微信扫码登陆二维码"\n />\n </div>\n <div class="wechat-explain">使用微信扫一扫,扫码登录 "飞码AI"</div>\n </form>\n\n \x3c!--返回首页--\x3e\n <div class="back-home-box" *ngIf="authServ.showBackHome">\n <button class="back-homepage-button" (click)="goHome()">\n 返回首页\n </button>\n </div>\n </div>\n </div>\n </div>\n</div>\n',styles:['@charset "UTF-8";:host{--fmode-background-primary: #FFF;--login-color-primary: var(--fmode-color-primary,#0199f9);--login-bgcolor-primary: var(--fmode-login-bgcolor-primary,dodgerblue);--login-bgcolor-secondary: var(--fmode-login-bgcolor-secondary,#00dbde);--login-bgcolor-third: var(--fmode-login-bgcolor-third,#f902ff)}:host-context(body.dark) .popup{--login-color-primary: #7974ff;--fmode-background-primary: #000000}:host-context(body.dark) .popup .remember-password-box{color:#fff}.popup{display:flex;position:fixed;left:0;top:0;width:100%;height:100%;background-color:#0006;z-index:1000}@media screen and (max-width: 800px){.popup-content.fullscreen .popup-box{position:fixed!important;left:0!important;top:0!important;height:100vh!important;width:100vw!important;border-radius:0!important}.popup-content.fullscreen .popup-box .popup-box-content{padding-top:35%;border-radius:50px!important}.popup{background:#00000080}.popup-content.sheet{background:transparent!important}.popup-content.sheet .popup-box{position:fixed!important;left:0!important;top:calc(100vh - 360px);height:400px;width:100vw!important;border-radius:50px!important}.popup-content.sheet .popup-box .popup-box-content{border-radius:50px!important}}.popup-content{margin:7% auto;display:flex;width:500px;height:600px;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .popup-box{width:500px;height:600px;position:relative;border-radius:50px 5px;background-color:var(--login-bgcolor-primary);overflow:hidden}.popup-content .popup-box .popup-box-content{position:absolute;border-radius:50px 5px;inset:4px;background-color:var(--fmode-background-primary);z-index:1}.popup-content .popup-box .popup-box-content .logo-img-login{margin-top:35px;position:relative;width:100%;display:flex;justify-content:center;z-index:2}.popup-content .popup-box .popup-box-content .logo-img-login img{height:auto;max-width:150px}.popup-content .popup-box .popup-box-content .close-icon-box{position:relative;top:20px;right:20px;float:right;font-size:20px;cursor:pointer;z-index:2}.popup-content .popup-box .popup-box-content .button-box{display:flex;justify-content:center;padding-top:32px;padding-right:59px;padding-left:59px;border-radius:10px;width:100%;height:72px}.popup-content .popup-box .popup-box-content .button-box .button-group{position:relative;display:flex;width:100%;line-height:40px;border-radius:10px;background-color:plum;z-index:2}.popup-content .popup-box .popup-box-content .button-box .login-select-button{flex:1;outline:none;border:none;border-radius:10px;font-size:16px;cursor:pointer;color:#fff;background-color:inherit;transition:background-color .3s}.popup-content .popup-box .popup-box-content .button-box .login-select-button:hover{flex:1;outline:none;border:none;border-radius:10px;font-size:16px;cursor:pointer;color:#000;background-color:inherit;transition:background-color .3s}.popup-content .popup-box .popup-box-content .button-box .login-select-button.active{background-color:var(--login-color-primary);border-radius:10px}.popup-content .popup-box .popup-box-content input{color:#000}.popup-content .popup-box .popup-box-content .message-form,.popup-content .popup-box .popup-box-content .mobile-form,.popup-content .popup-box .popup-box-content .wechat-form{display:none}.popup-content .popup-box .popup-box-content .message-form.active,.popup-content .popup-box .popup-box-content .mobile-form.active,.popup-content .popup-box .popup-box-content .wechat-form.active{display:block}.popup-content .popup-box:before{content:"";position:absolute;top:-50%;left:-50%;width:500px;height:600px;background:linear-gradient(0deg,transparent,var(--login-bgcolor-third),var(--login-bgcolor-third));transform-origin:bottom right;animation:animate 6s linear infinite}.popup-content .popup-box:after{content:"";position:absolute;top:-50%;left:-50%;width:500px;height:600px;background:linear-gradient(0deg,transparent,var(--login-bgcolor-secondary),var(--login-bgcolor-secondary));transform-origin:bottom right;animation:animate 6s linear infinite;animation-delay:-3s}@keyframes animate{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.popup-content .login-submit-box{position:relative}.popup-content .login-submit-button{margin-top:15px;padding:6px;width:100%;line-height:40px;border-radius:10px;border:0;position:relative;box-shadow:0 2px 10px #00000029,0 3px 6px #0000001a;text-decoration:none;font-size:18px;font-weight:700;letter-spacing:2px;text-align:center;color:#fff;background-color:var(--login-color-primary);transition:.3s ease all;cursor:pointer;z-index:1}.popup-content .login-submit-button:before{transition:.5s all ease;position:absolute;inset:0 50%;opacity:0;content:"";background-color:var(--fmode-background-primary);z-index:-1}.popup-content .login-submit-button:hover{color:var(--login-color-primary)}.popup-content .login-submit-button:hover:before{border-radius:10px;border:3px solid var(--login-color-primary);box-sizing:border-box;transition:.5s all ease;left:0;right:0;opacity:1}.popup-content .login-submit-button:active{transform:scale(.9)}.popup-content .message-form{padding:6px 55px;display:flex;position:relative;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .message-form .login-input-box{display:flex;align-items:center;padding-top:10px}.popup-content .message-form .login-input-box .popup-input-frontnumber{padding:6px 12px;position:relative;border-radius:10px 0 0 10px;line-height:40px;font-size:18px;color:#4d4d4d;background-color:#ededed}.popup-content .message-form .popup-input-itemone{padding:6px 12px;position:relative;line-height:40px;border-radius:0 10px 10px 0;border:0;width:93%;outline:none;box-shadow:none;font-size:18px;letter-spacing:.03em;background-color:#ededed;transition:.5s}.popup-content .message-form .popup-input-itemtwo{padding:6px 12px 6px 16px;position:relative;line-height:40px;border-radius:10px;border:0;width:55%;outline:none;box-shadow:none;font-size:18px;letter-spacing:.03em;background-color:#ededed;transition:.5s}.popup-content .message-form .checknumber-button{margin-left:46px;padding:6px;border-radius:10px;line-height:40px;font-size:18px;width:124px;border:none;outline:none;cursor:pointer;color:#fff;background:var(--login-color-primary)}.popup-content .message-form .checknumber-button:hover{margin-left:46px;padding:6px;border-radius:10px;line-height:40px;font-size:18px;width:124px;border:none;outline:none;cursor:pointer;background:#4bace9}.popup-content .message-form .checknumber-button.active{background:#c7c7c7}.popup-content .rule-box{display:flex;padding-top:4px;padding-left:15px;padding-right:10px;justify-content:space-between;font-size:15px}.popup-content .rule-box span,.popup-content .rule-box ion-checkbox{font-size:15px;color:var(--login-color-primary)}.popup-content .mobile-form{padding:6px 55px;display:flex;position:relative;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .mobile-form .login-input-box{padding-top:10px}.popup-content .mobile-form .login-input-box .popup-input-itemnomal{margin-top:20px;padding:6px 12px 6px 14px;position:relative;line-height:40px;border-radius:10px;border:0;width:100%;outline:none;box-shadow:none;font-size:18px;letter-spacing:.03em;background-color:#ededed;transition:.5s}.popup-content .mobile-form .passwprd-box{display:flex;padding-top:4px;justify-content:space-between}.popup-content .mobile-form .passwprd-box .remember-password-box{margin:10px 0 0 15px;font-size:15px}.popup-content .mobile-form .passwprd-box .password-forget{margin-top:10px;margin-right:15px;font-size:15px;color:gray;cursor:pointer}.popup-content .mobile-form .passwprd-box .password-forget:hover{margin-top:10px;margin-right:15px;font-size:15px;color:#000;cursor:pointer}.popup-content .wechat-form{padding:6px 55px;display:flex;position:relative;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .wechat-form .wechat-login-box{display:flex;justify-content:center}.popup-content .wechat-form .wechat-login-box .login-erweima-img{margin-top:30px;width:210px}.popup-content .wechat-form .wechat-explain{padding-top:20px;font-size:16px;text-align:center}.popup-content .back-home-box{display:flex;justify-content:center;padding:6px 55px}.popup-content .back-homepage-button{margin-top:15px;padding:6px;width:100%;line-height:40px;border-radius:10px;border:0;position:relative;box-shadow:0 2px 10px #00000029,0 3px 6px #0000001a;text-decoration:none;font-size:18px;font-weight:700;letter-spacing:2px;text-align:center;color:#fff;background-color:var(--login-color-primary);transition:.3s ease all;cursor:pointer;x:1}.popup-content .back-homepage-button:before{transition:.5s all ease;position:absolute;inset:0 50%;opacity:0;content:"";background-color:var(--fmode-background-primary);z-index:-1}.popup-content .back-homepage-button:hover{color:var(--login-color-primary)}.popup-content .back-homepage-button:hover:before{border-radius:10px;border:3px solid var(--login-color-primary);box-sizing:border-box;transition:.5s all ease;left:0;right:0;opacity:1}.popup-content .local-code{justify-content:space-between}.popup-content .local-code .canvas{border:1px solid #c2def5;border-radius:5px;width:100px;height:44px}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i3$3.ɵNgNoValidate,selector:"form:not([ngNoForm]):not([ngNativeValidate])"},{kind:"directive",type:i3$3.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:i3$3.CheckboxControlValueAccessor,selector:"input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]"},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:i3$3.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:i3$3.MaxLengthValidator,selector:"[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]",inputs:["maxlength"]},{kind:"directive",type:i3$3.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:i3$3.NgForm,selector:"form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]",inputs:["ngFormOptions"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"ngmodule",type:ReactiveFormsModule}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalUserLoginComponent,decorators:[{type:Component,args:[{standalone:!0,imports:[CommonModule,FormsModule,ReactiveFormsModule,IonCheckbox],selector:"fm-modal-user-login",template:'\x3c!--登录弹出框设置--\x3e\n\x3c!--背景灰色蒙版--\x3e\n<div\n class="popup"\n [style.display]="authServ.isModalShow ? \'block\' : \'none\'"\n (click)="close()"\n>\n <div class="popup-content" [class.fullscreen]="authServ.modalType==\'fullscreen\'" [class.sheet]="authServ.modalType==\'sheet\'"\n (click)="$event.stopPropagation()">\n <div class="popup-box">\n \x3c!--弹框内设置position:absolute,规范排版,后续只需position:relative增减内容--\x3e\n <div class="popup-box-content">\n <div class="logo-img-login">\n <img\n [src]="authServ.logoUrl"\n alt="fmode"\n />\n </div>\n\n \x3c!--关闭图标按钮--\x3e\n <div class="close-icon-box">\n <div class="iconfont icon-shanchu2" (click)="close()"></div>\n </div>\n \x3c!--按钮切换登录方式--\x3e\n <div class="button-box" *ngIf="authServ?.loginTypeCount>1">\n <div class="button-group">\n <button *ngIf="authServ?.loginOptions?.userpwd"\n class="login-select-button"\n [class.active]="authServ.activeButton === \'账号密码\'"\n (click)="setActiveButton(\'账号密码\')"\n >\n 账号密码\n </button>\n <button *ngIf="authServ?.loginOptions?.mobilecode"\n class="login-select-button"\n [class.active]="authServ.activeButton === \'短信验证\'"\n (click)="setActiveButton(\'短信验证\')"\n >\n 短信验证\n </button>\n <button *ngIf="authServ?.loginOptions?.wechat"\n class="login-select-button"\n [class.active]="authServ.activeButton === \'微信扫码\'"\n (click)="setActiveButton(\'微信扫码\')"\n >\n 微信扫码\n </button>\n </div>\n </div>\n\n \x3c!--手机验证码--\x3e\n <form class="message-form" [class.active]="authServ.activeButton === \'短信验证\'" *ngIf="authServ?.loginOptions?.mobilecode">\n <div class="login-input-box">\n <div class="popup-input-frontnumber">+86</div>\n <input\n class="popup-input-itemone"\n type="text"\n required="required"\n [(ngModel)]="loginInfo.mobile"\n [ngModelOptions]="{ standalone: true }"\n maxlength="12"\n placeholder="请输入手机号"\n />\n </div>\n <div *ngIf="authServ?.enabledLocalCode"\n class="login-input-box local-code" #canvasDom>\n <input\n class="popup-input-itemtwo"\n type="text"\n required="required"\n [(ngModel)]="localCodeNum"\n [ngModelOptions]="{ standalone: true }"\n maxlength="4"\n placeholder="请输入校验码"\n />\n \x3c!-- <canvas\n #canvas\n width="100"\n height="44"\n (click)="updateDrawCode()"\n class="canvas"\n ></canvas> --\x3e\n </div>\n <div class="login-input-box">\n <input #smsCodeInput\n class="popup-input-itemtwo"\n type="text"\n required="required"\n placeholder="请输入短信验证码"\n [(ngModel)]="loginInfo.code"\n (change)="smsAutoLogin()"\n [ngModelOptions]="{ standalone: true }"\n maxlength="6"\n />\n <button\n class="checknumber-button"\n type="submit"\n [value]="buttonText"\n [disabled]="isCountingdown"\n (click)="startCountdown()"\n [class.active]="isCountingdown"\n >\n {{buttonText}}\n </button>\n </div>\n\n \x3c!-- 用户协议 --\x3e\n <div class="rule-box">\n <span>未注册的手机号,将自动创建帐号并登录。</span>\n </div>\n\n <div class="login-submit-box">\n <button class="login-submit-button" type="submit" (click)="login()">\n 登录\n </button>\n </div>\n </form>\n\n \x3c!--账号密码登录--\x3e\n <form class="mobile-form" [class.active]="authServ.activeButton === \'账号密码\'" *ngIf="authServ?.loginOptions?.userpwd">\n <div class="login-input-box">\n <input\n maxlength="12"\n [(ngModel)]="mobile"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="text"\n required="required"\n placeholder="请输入手机号"\n />\n </div>\n\n <div class="login-input-box">\n <input\n [(ngModel)]="password"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="password"\n required="required"\n placeholder="请输入密码"\n />\n </div>\n\n \x3c!-- 记住密码 --\x3e\n <div class="passwprd-box">\n <div class="remember-password-box">\n <input type="checkbox" id="remember-password" />\n 记住密码\n </div>\n\n \x3c!-- 忘记密码 --\x3e\n <div class="password-forget" (click)="setActiveButton(\'注册帐号\')">\n 注册帐号\n </div>\n </div>\n\n \x3c!-- 用户协议 --\x3e\n <div class="rule-box">\n <span>\n <input type="checkbox" [(ngModel)]="isUserRuleChecked" [ngModelOptions]="{ standalone: true }" style="margin-right:5px"/>\n <span (click)="isUserRuleChecked=true">同意</span></span>\n <span (click)="isUserRuleChecked=true">《用户协议及隐私条款》</span>\n </div>\n\n\n \x3c!-- 忘记密码 --\x3e\n \x3c!-- <div class="password-forget">忘记密码?</div>\n </div> --\x3e\n\n <div class="login-submit-box">\n <button\n class="login-submit-button"\n type="submit"\n (click)="loginMobilePassword()"\n >\n 登录\n </button>\n </div>\n </form>\n\n \x3c!-- 帐号密码注册 --\x3e\n <form class="mobile-form" [class.active]="authServ.activeButton === \'注册帐号\'">\n <div class="login-input-box">\n <input\n [(ngModel)]="mobile"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="text"\n required="required"\n placeholder="请输入手机号"\n />\n </div>\n\n <div class="login-input-box">\n <input\n [(ngModel)]="password"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="password"\n required="required"\n placeholder="请输入密码"\n />\n </div>\n\n <div class="login-input-box">\n <input\n [(ngModel)]="password2"\n [ngModelOptions]="{ standalone: true }"\n class="popup-input-itemnomal"\n type="password"\n required="required"\n placeholder="请再次输入密码"\n />\n </div>\n\n <div class="login-submit-box">\n <button\n class="login-submit-button"\n type="submit"\n (click)="signMobilePassword()"\n >\n 注册\n </button>\n </div>\n </form>\n\n \x3c!--微信扫码登陆--\x3e\n <form class="wechat-form" [class.active]="authServ.activeButton === \'微信扫码\'" *ngIf="authServ?.loginOptions?.wechat">\n <div class="wechat-login-box">\n <img\n class="login-erweima-img"\n [src]="authServ.wechatUrl"\n alt="微信扫码登陆二维码"\n />\n </div>\n <div class="wechat-explain">使用微信扫一扫,扫码登录 "飞码AI"</div>\n </form>\n\n \x3c!--返回首页--\x3e\n <div class="back-home-box" *ngIf="authServ.showBackHome">\n <button class="back-homepage-button" (click)="goHome()">\n 返回首页\n </button>\n </div>\n </div>\n </div>\n </div>\n</div>\n',styles:['@charset "UTF-8";:host{--fmode-background-primary: #FFF;--login-color-primary: var(--fmode-color-primary,#0199f9);--login-bgcolor-primary: var(--fmode-login-bgcolor-primary,dodgerblue);--login-bgcolor-secondary: var(--fmode-login-bgcolor-secondary,#00dbde);--login-bgcolor-third: var(--fmode-login-bgcolor-third,#f902ff)}:host-context(body.dark) .popup{--login-color-primary: #7974ff;--fmode-background-primary: #000000}:host-context(body.dark) .popup .remember-password-box{color:#fff}.popup{display:flex;position:fixed;left:0;top:0;width:100%;height:100%;background-color:#0006;z-index:1000}@media screen and (max-width: 800px){.popup-content.fullscreen .popup-box{position:fixed!important;left:0!important;top:0!important;height:100vh!important;width:100vw!important;border-radius:0!important}.popup-content.fullscreen .popup-box .popup-box-content{padding-top:35%;border-radius:50px!important}.popup{background:#00000080}.popup-content.sheet{background:transparent!important}.popup-content.sheet .popup-box{position:fixed!important;left:0!important;top:calc(100vh - 360px);height:400px;width:100vw!important;border-radius:50px!important}.popup-content.sheet .popup-box .popup-box-content{border-radius:50px!important}}.popup-content{margin:7% auto;display:flex;width:500px;height:600px;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .popup-box{width:500px;height:600px;position:relative;border-radius:50px 5px;background-color:var(--login-bgcolor-primary);overflow:hidden}.popup-content .popup-box .popup-box-content{position:absolute;border-radius:50px 5px;inset:4px;background-color:var(--fmode-background-primary);z-index:1}.popup-content .popup-box .popup-box-content .logo-img-login{margin-top:35px;position:relative;width:100%;display:flex;justify-content:center;z-index:2}.popup-content .popup-box .popup-box-content .logo-img-login img{height:auto;max-width:150px}.popup-content .popup-box .popup-box-content .close-icon-box{position:relative;top:20px;right:20px;float:right;font-size:20px;cursor:pointer;z-index:2}.popup-content .popup-box .popup-box-content .button-box{display:flex;justify-content:center;padding-top:32px;padding-right:59px;padding-left:59px;border-radius:10px;width:100%;height:72px}.popup-content .popup-box .popup-box-content .button-box .button-group{position:relative;display:flex;width:100%;line-height:40px;border-radius:10px;background-color:plum;z-index:2}.popup-content .popup-box .popup-box-content .button-box .login-select-button{flex:1;outline:none;border:none;border-radius:10px;font-size:16px;cursor:pointer;color:#fff;background-color:inherit;transition:background-color .3s}.popup-content .popup-box .popup-box-content .button-box .login-select-button:hover{flex:1;outline:none;border:none;border-radius:10px;font-size:16px;cursor:pointer;color:#000;background-color:inherit;transition:background-color .3s}.popup-content .popup-box .popup-box-content .button-box .login-select-button.active{background-color:var(--login-color-primary);border-radius:10px}.popup-content .popup-box .popup-box-content input{color:#000}.popup-content .popup-box .popup-box-content .message-form,.popup-content .popup-box .popup-box-content .mobile-form,.popup-content .popup-box .popup-box-content .wechat-form{display:none}.popup-content .popup-box .popup-box-content .message-form.active,.popup-content .popup-box .popup-box-content .mobile-form.active,.popup-content .popup-box .popup-box-content .wechat-form.active{display:block}.popup-content .popup-box:before{content:"";position:absolute;top:-50%;left:-50%;width:500px;height:600px;background:linear-gradient(0deg,transparent,var(--login-bgcolor-third),var(--login-bgcolor-third));transform-origin:bottom right;animation:animate 6s linear infinite}.popup-content .popup-box:after{content:"";position:absolute;top:-50%;left:-50%;width:500px;height:600px;background:linear-gradient(0deg,transparent,var(--login-bgcolor-secondary),var(--login-bgcolor-secondary));transform-origin:bottom right;animation:animate 6s linear infinite;animation-delay:-3s}@keyframes animate{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.popup-content .login-submit-box{position:relative}.popup-content .login-submit-button{margin-top:15px;padding:6px;width:100%;line-height:40px;border-radius:10px;border:0;position:relative;box-shadow:0 2px 10px #00000029,0 3px 6px #0000001a;text-decoration:none;font-size:18px;font-weight:700;letter-spacing:2px;text-align:center;color:#fff;background-color:var(--login-color-primary);transition:.3s ease all;cursor:pointer;z-index:1}.popup-content .login-submit-button:before{transition:.5s all ease;position:absolute;inset:0 50%;opacity:0;content:"";background-color:var(--fmode-background-primary);z-index:-1}.popup-content .login-submit-button:hover{color:var(--login-color-primary)}.popup-content .login-submit-button:hover:before{border-radius:10px;border:3px solid var(--login-color-primary);box-sizing:border-box;transition:.5s all ease;left:0;right:0;opacity:1}.popup-content .login-submit-button:active{transform:scale(.9)}.popup-content .message-form{padding:6px 55px;display:flex;position:relative;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .message-form .login-input-box{display:flex;align-items:center;padding-top:10px}.popup-content .message-form .login-input-box .popup-input-frontnumber{padding:6px 12px;position:relative;border-radius:10px 0 0 10px;line-height:40px;font-size:18px;color:#4d4d4d;background-color:#ededed}.popup-content .message-form .popup-input-itemone{padding:6px 12px;position:relative;line-height:40px;border-radius:0 10px 10px 0;border:0;width:93%;outline:none;box-shadow:none;font-size:18px;letter-spacing:.03em;background-color:#ededed;transition:.5s}.popup-content .message-form .popup-input-itemtwo{padding:6px 12px 6px 16px;position:relative;line-height:40px;border-radius:10px;border:0;width:55%;outline:none;box-shadow:none;font-size:18px;letter-spacing:.03em;background-color:#ededed;transition:.5s}.popup-content .message-form .checknumber-button{margin-left:46px;padding:6px;border-radius:10px;line-height:40px;font-size:18px;width:124px;border:none;outline:none;cursor:pointer;color:#fff;background:var(--login-color-primary)}.popup-content .message-form .checknumber-button:hover{margin-left:46px;padding:6px;border-radius:10px;line-height:40px;font-size:18px;width:124px;border:none;outline:none;cursor:pointer;background:#4bace9}.popup-content .message-form .checknumber-button.active{background:#c7c7c7}.popup-content .rule-box{display:flex;padding-top:4px;padding-left:15px;padding-right:10px;justify-content:space-between;font-size:15px}.popup-content .rule-box span,.popup-content .rule-box ion-checkbox{font-size:15px;color:var(--login-color-primary)}.popup-content .mobile-form{padding:6px 55px;display:flex;position:relative;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .mobile-form .login-input-box{padding-top:10px}.popup-content .mobile-form .login-input-box .popup-input-itemnomal{margin-top:20px;padding:6px 12px 6px 14px;position:relative;line-height:40px;border-radius:10px;border:0;width:100%;outline:none;box-shadow:none;font-size:18px;letter-spacing:.03em;background-color:#ededed;transition:.5s}.popup-content .mobile-form .passwprd-box{display:flex;padding-top:4px;justify-content:space-between}.popup-content .mobile-form .passwprd-box .remember-password-box{margin:10px 0 0 15px;font-size:15px}.popup-content .mobile-form .passwprd-box .password-forget{margin-top:10px;margin-right:15px;font-size:15px;color:gray;cursor:pointer}.popup-content .mobile-form .passwprd-box .password-forget:hover{margin-top:10px;margin-right:15px;font-size:15px;color:#000;cursor:pointer}.popup-content .wechat-form{padding:6px 55px;display:flex;position:relative;border-radius:50px 5px;background-color:var(--fmode-background-primary)}.popup-content .wechat-form .wechat-login-box{display:flex;justify-content:center}.popup-content .wechat-form .wechat-login-box .login-erweima-img{margin-top:30px;width:210px}.popup-content .wechat-form .wechat-explain{padding-top:20px;font-size:16px;text-align:center}.popup-content .back-home-box{display:flex;justify-content:center;padding:6px 55px}.popup-content .back-homepage-button{margin-top:15px;padding:6px;width:100%;line-height:40px;border-radius:10px;border:0;position:relative;box-shadow:0 2px 10px #00000029,0 3px 6px #0000001a;text-decoration:none;font-size:18px;font-weight:700;letter-spacing:2px;text-align:center;color:#fff;background-color:var(--login-color-primary);transition:.3s ease all;cursor:pointer;x:1}.popup-content .back-homepage-button:before{transition:.5s all ease;position:absolute;inset:0 50%;opacity:0;content:"";background-color:var(--fmode-background-primary);z-index:-1}.popup-content .back-homepage-button:hover{color:var(--login-color-primary)}.popup-content .back-homepage-button:hover:before{border-radius:10px;border:3px solid var(--login-color-primary);box-sizing:border-box;transition:.5s all ease;left:0;right:0;opacity:1}.popup-content .local-code{justify-content:space-between}.popup-content .local-code .canvas{border:1px solid #c2def5;border-radius:5px;width:100px;height:44px}\n']}]}],ctorParameters:()=>[{type:AuthService},{type:i1$1.Router},{type:i1$1.ActivatedRoute},{type:i1.HttpClient},{type:i1$3.ToastController}],propDecorators:{canvasDom:[{type:ViewChild,args:["canvasDom"]}],smsCodeInput:[{type:ViewChild,args:["smsCodeInput"]}],handleEscapeKey:[{type:HostListener,args:["document:keydown.escape",["$event"]]}]}});class CaptchaComponent{constructor(){this.type="input",this.canvas_id="canvasCode",this.drawCode=[],this.vCode="",this.changeVal=new EventEmitter,this.onEnter=new EventEmitter,this.code=""}ngOnInit(){}ngAfterViewInit(){this.updateDrawCode()}updateDrawCode(){let e=100,t=document.getElementById(this.canvas_id);t&&this.canvasDom.nativeElement.removeChild(t);let n=document.getElementById(this.canvas_id+"_a");n&&this.canvasDom.nativeElement.removeChild(n),this.canvasDom.nativeElement;let o=document.createElement("canvas");o.className="canvas",o.setAttribute("id",this.canvas_id),o.addEventListener("click",(()=>{this.updateDrawCode()}));let i=o.getContext("2d");o.width=e,o.height=38;let a="A,B,C,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,W,X,Y,Z,1,2,3,4,5,6,7,8,9,0,q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m".split(","),r=a.length;for(let e=0;e<=3;e++){let t=Math.floor(Math.random()*r),n=30*Math.random()*Math.PI/180,o=a[t];this.drawCode[e]=o;let s=10+20*e,l=20+8*Math.random();i.font="bold 23px 微软雅黑",i.translate(s,l),i.rotate(n),i.fillStyle=this.randomColor(),i.fillText(o,0,0),i.rotate(-n),i.translate(-s,-l)}for(let t=0;t<=5;t++)i.strokeStyle=this.randomColor(),i.beginPath(),i.moveTo(Math.random()*e,38*Math.random()),i.lineTo(Math.random()*e,38*Math.random()),i.stroke();for(let t=0;t<=30;t++){i.strokeStyle=this.randomColor(),i.beginPath();let t=Math.random()*e,n=38*Math.random();i.moveTo(t,n),i.lineTo(t+1,n+1),i.stroke()}this.code=this.drawCode.join(""),this.changeVal.emit({code:this.code,vCode:this.vCode}),this.canvasDom.nativeElement.appendChild(o);let s=document.createElement("a");s.setAttribute("id",this.canvas_id+"_a"),s.innerText="看不清,换一张",s.addEventListener("click",(()=>{this.updateDrawCode()})),this.canvasDom.nativeElement.appendChild(s)}randomColor(){return"rgb("+Math.floor(256*Math.random())+","+Math.floor(256*Math.random())+","+Math.floor(256*Math.random())+")"}enter(e){13==e.keyCode&&(this.changeVal.emit({code:this.code,vCode:this.vCode}),this.onEnter.emit())}onChange(){this.changeVal.emit({code:this.code,vCode:this.vCode})}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CaptchaComponent,deps:[],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CaptchaComponent,isStandalone:!0,selector:"fm-captcha",inputs:{type:"type",canvas_id:"canvas_id",drawCode:"drawCode",vCode:"vCode"},outputs:{changeVal:"changeVal",onEnter:"onEnter"},viewQueries:[{propertyName:"canvasDom",first:!0,predicate:["canvasDom"],descendants:!0}],ngImport:i0,template:'<ng-container *ngIf="type == \'input\'; else elseTemplate">\n <div class="captcha">\n <input\n nz-input\n class="code-input"\n type="text"\n [(ngModel)]="vCode"\n maxlength="4"\n placeholder="验证码"\n [nzStatus]="vCode.length == 4 ? \'\' : \'error\'"\n (keydown)="enter($event)"\n (change)="onChange()"\n />\n <div class="code-card" #canvasDom></div>\n </div>\n</ng-container>\n<ng-template #elseTemplate>\n <div class="captcha">\n <div class="code-card" #canvasDom></div>\n </div>\n</ng-template>\n',styles:[".code-card{display:flex;align-items:center}.code-card .canvas{border:1px solid #c2def5;border-radius:5px;width:100px;height:38px}.code-input{width:90px;padding:4px;height:38px;border:1px solid #cdcdcd}.code-input:focus{outline:1px solid #40a9ff}.captcha{display:flex;align-items:center}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"ngmodule",type:FormsModule},{kind:"directive",type:i3$3.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.MaxLengthValidator,selector:"[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]",inputs:["maxlength"]},{kind:"directive",type:i3$3.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CaptchaComponent,decorators:[{type:Component,args:[{imports:[CommonModule,FormsModule],standalone:!0,selector:"fm-captcha",template:'<ng-container *ngIf="type == \'input\'; else elseTemplate">\n <div class="captcha">\n <input\n nz-input\n class="code-input"\n type="text"\n [(ngModel)]="vCode"\n maxlength="4"\n placeholder="验证码"\n [nzStatus]="vCode.length == 4 ? \'\' : \'error\'"\n (keydown)="enter($event)"\n (change)="onChange()"\n />\n <div class="code-card" #canvasDom></div>\n </div>\n</ng-container>\n<ng-template #elseTemplate>\n <div class="captcha">\n <div class="code-card" #canvasDom></div>\n </div>\n</ng-template>\n',styles:[".code-card{display:flex;align-items:center}.code-card .canvas{border:1px solid #c2def5;border-radius:5px;width:100px;height:38px}.code-input{width:90px;padding:4px;height:38px;border:1px solid #cdcdcd}.code-input:focus{outline:1px solid #40a9ff}.captcha{display:flex;align-items:center}\n"]}]}],ctorParameters:()=>[],propDecorators:{canvasDom:[{type:ViewChild,args:["canvasDom"]}],type:[{type:Input}],canvas_id:[{type:Input}],drawCode:[{type:Input}],vCode:[{type:Input}],changeVal:[{type:Output}],onEnter:[{type:Output}]}});class UserNamePipe{transform(e,...t){let n=e;if(n?.mobile||(n=e?.toJSON()),console.log(n),n?.nickname)return n?.nickname;let o=n?.name;if(o)return o.substr(0,1)+"*".repeat(o?.length-1);let i=n?.mobile;return i?i.substr(0,3)+"*".repeat(i?.length-6)+i.substr(i?.length-3):""}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:UserNamePipe,deps:[],target:i0.ɵɵFactoryTarget.Pipe})}static{this.ɵpipe=i0.ɵɵngDeclarePipe({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:UserNamePipe,name:"userName"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:UserNamePipe,decorators:[{type:Pipe,args:[{name:"userName"}]}]});const UserRoutes=[{path:"login",component:LoginComponent,runGuardsAndResolvers:"always"},{path:":companyId/login",component:LoginComponent,runGuardsAndResolvers:"always"},{path:"app/:appId/login",component:LoginComponent,runGuardsAndResolvers:"always"}];class UserModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:UserModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:UserModule,declarations:[LoginComponent,UserNamePipe],imports:[CommonModule,FormsModule,HttpClientModule,ReactiveFormsModule,i1$1.RouterModule,NzInputModule,NzButtonModule,NzModalModule,NzRadioModule,NzSpinModule,NzTabsModule,NzFormModule,NzMessageModule,ModalUserLoginComponent,CaptchaComponent],exports:[LoginComponent,ModalUserLoginComponent,UserNamePipe,CaptchaComponent]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:UserModule,imports:[CommonModule,FormsModule,HttpClientModule,ReactiveFormsModule,RouterModule.forChild(UserRoutes),NzInputModule,NzButtonModule,NzModalModule,NzRadioModule,NzSpinModule,NzTabsModule,NzFormModule,NzMessageModule,ModalUserLoginComponent,CaptchaComponent]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:UserModule,decorators:[{type:NgModule,args:[{declarations:[LoginComponent,UserNamePipe],imports:[CommonModule,FormsModule,HttpClientModule,ReactiveFormsModule,RouterModule.forChild(UserRoutes),NzInputModule,NzButtonModule,NzModalModule,NzRadioModule,NzSpinModule,NzTabsModule,NzFormModule,NzMessageModule,ModalUserLoginComponent,CaptchaComponent],exports:[LoginComponent,ModalUserLoginComponent,UserNamePipe,CaptchaComponent]}]}]});class StaffModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StaffModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:StaffModule,imports:[CommonModule]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StaffModule,imports:[CommonModule]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StaffModule,decorators:[{type:NgModule,args:[{declarations:[],imports:[CommonModule]}]}]});class StaffService{constructor(e){this.router=e,this.isPeiZhu=!1,this.checkIsPeiZhu()}async checkStaff(){if(this.staff?.id||(this.staff=await this.loadStaffByUser()),this.staff?.id)return!0;console.log(this.staff);let e=this.redirectURL;return e&&(e=encodeURIComponent(e)),e=e||"/store/home",this.router.navigate([e]),!1}async loadStaffByUser(e=!1){let t=Parse__default.User.current();if(!t?.id)return;let n=localStorage.getItem("staffid");e&&(n=null);let o,i=new Parse__default.Query("UserStaff");return i.include("job","shopStore"),n&&(i.equalTo("objectId",n),o=await i.first()),o?.id||(i.equalTo("user",t?.id),o=await i.first()),o?.id&&localStorage.setItem("staffid",o?.id),e&&(this.realStaff=o),o}async checkIsPeiZhu(){this.realStaff||(this.realStaff=await this.loadStaffByUser(!0)),"配件助理"!=this.realStaff?.get("job")?.get("title")?this.isPeiZhu=!1:this.isPeiZhu=!0}peizhuJob(e){return!this.isPeiZhu||!!(this.isPeiZhu&&e.jobs?.indexOf("配件助理")>-1)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StaffService,deps:[{token:i1$1.Router}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StaffService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:StaffService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1$1.Router}]});class AuthStaffGuard{constructor(e){this.staffServ=e}canActivate(e,t){return this.staffServ.checkStaff()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthStaffGuard,deps:[{token:StaffService}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthStaffGuard,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthStaffGuard,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:StaffService}]});class AuthProfileService{get profileId(){return this._profileId?this._profileId:localStorage.getItem("Parse/ProfileId")}set profileId(e){this._profileId=e,localStorage.setItem("Parse/ProfileId",e)}get profilePointer(){return{__type:"Pointer",className:"Profile",objectId:this.companyId}}get companyId(){return this._companyId?this._companyId:localStorage.getItem("Parse/CompanyId")}set companyId(e){this._companyId=e,localStorage.setItem("Parse/CompanyId",e)}get companyPointer(){return{__type:"Pointer",className:"company",objectId:this.companyId}}get user(){return this._user||Parse__default.User.current()}set user(e){this._user=e}constructor(e){this.router=e,this.user=Parse__default.User.current()}async getProfile(){if(this.profile?.id)return this.profile;if(this.profileId){let e=new Parse__default.Query("Profile");return e.include("company"),this.profile=await e.get(this.profileId),this.profile}return this.profile}async bindProfile(e){this.profile=e,this.profileId=e.id,e?.get("company")?.id&&(this.companyId=e?.get("company")?.id),console.log(e,this.user),this.profile.set("user",this.user?.toPointer()),await this.profile.save(),console.log(localStorage.getItem("homePath")),console.log(e?.get("company")?.get("rootPage"));let t=localStorage.getItem("homePath")||e?.get("company")?.get("rootPage")||this.redirectUrl||"/";t=decodeURIComponent(t),this.router.navigate([t])}async checkProfile(e){let t=this.profile;if(t?.id)return this.setCurrentProfileLocalStorage(t),!0;if(this.profileId){let e=new Parse__default.Query("Profile");return e.include("company"),t=await e.get(this.profileId),t?.id&&(this.profile=t,this.setCurrentProfileLocalStorage(t)),!0}return this.redirectUrl=e,this.router.navigate(["/profile/bind"]),!1}async setCurrentProfileLocalStorage(e){let t=Parse__default.Query.fromJSON("Department",{where:{$or:[{leader:e.toPointer()}]}});(await t.find()).forEach((e=>{e?.id&&(this.isManager=!0,this.isLeader=!0)}))}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthProfileService,deps:[{token:i1$1.Router}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthProfileService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthProfileService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i1$1.Router}]});class AuthProfileGuard{constructor(e,t){this.authProfileServ=e,this.router=t}canActivate(e,t){let n=t.url;return this.authProfileServ.checkProfile(n)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthProfileGuard,deps:[{token:AuthProfileService},{token:i1$1.Router}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthProfileGuard,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthProfileGuard,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:AuthProfileService},{type:i1$1.Router}]});class ProfileConfirmModalComponent{constructor(e){this.modalController=e}dismiss(){this.modalController.dismiss()}confirm(){this.modalController.dismiss({confirmed:!0})}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ProfileConfirmModalComponent,deps:[{token:i3.ModalController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ProfileConfirmModalComponent,selector:"fm-profile-confirm-modal",inputs:{profile:"profile"},ngImport:i0,template:'\n <ion-header>\n <ion-toolbar>\n <ion-title>绑定身份</ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="dismiss()">取消</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n\n <ion-content class="ion-padding">\n <p>您确认绑定并切换至该身份吗?</p>\n <ion-item lines="none">\n <ion-label>\n <h3>姓名:{{ profile?.get("name") }}</h3>\n <p>帐套:{{ profile?.get("company")?.get("name") || profile?.get("company")?.get("title") }}</p>\n </ion-label>\n </ion-item>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar>\n <ion-button expand="block" (click)="confirm()">确认绑定</ion-button>\n </ion-toolbar>\n </ion-footer>\n ',isInline:!0,dependencies:[{kind:"component",type:i3.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:i3.IonButtons,selector:"ion-buttons",inputs:["collapse"]},{kind:"component",type:i3.IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:i3.IonFooter,selector:"ion-footer",inputs:["collapse","mode","translucent"]},{kind:"component",type:i3.IonHeader,selector:"ion-header",inputs:["collapse","mode","translucent"]},{kind:"component",type:i3.IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:i3.IonTitle,selector:"ion-title",inputs:["color","size"]},{kind:"component",type:i3.IonToolbar,selector:"ion-toolbar",inputs:["color","mode"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ProfileConfirmModalComponent,decorators:[{type:Component,args:[{selector:"fm-profile-confirm-modal",template:'\n <ion-header>\n <ion-toolbar>\n <ion-title>绑定身份</ion-title>\n <ion-buttons slot="end">\n <ion-button (click)="dismiss()">取消</ion-button>\n </ion-buttons>\n </ion-toolbar>\n </ion-header>\n\n <ion-content class="ion-padding">\n <p>您确认绑定并切换至该身份吗?</p>\n <ion-item lines="none">\n <ion-label>\n <h3>姓名:{{ profile?.get("name") }}</h3>\n <p>帐套:{{ profile?.get("company")?.get("name") || profile?.get("company")?.get("title") }}</p>\n </ion-label>\n </ion-item>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar>\n <ion-button expand="block" (click)="confirm()">确认绑定</ion-button>\n </ion-toolbar>\n </ion-footer>\n '}]}],ctorParameters:()=>[{type:i3.ModalController}],propDecorators:{profile:[{type:Input}]}});class ProfileBindComponent{onResize(){this.cross.onResizeScreen()}constructor(e,t,n,o,i,a){this.authProfile=e,this.router=t,this.alertController=n,this.toastController=o,this.cross=i,this.modalController=a,this.profileList=[],this.pdata={name:null,mobile:null},this.now=new Date,this.isLoading=!1,this.profile=this.authProfile.profile,this.currentProfile=localStorage.getItem("Parse/ProfileId"),this.user=Parse__default.User.current(),this.loadProfiles()}async loadProfiles(){this.isLoading=!0;try{let e=new Parse__default.Query("Profile");e.include("company"),e.notEqualTo("isDeleted",!0),this.profile?.id?(e.equalTo("mobile",this.profile.get("mobile")),e.equalTo("name",this.profile.get("name"))):e.equalTo("user",this.user.id),this.profileList=await e.find()}catch(e){console.error("Error loading profiles:",e),this.showToast("加载身份信息失败,请重试","danger")}finally{this.isLoading=!1}}async bindProfile(e){if(e?.id||(e=this.profileSearched),e?.id)try{await this.authProfile.bindProfile(e)}catch(e){console.error("Error binding profile:",e),this.showToast("绑定身份失败,请重试","danger")}}async searchProfile(){if(this.profileList=[],this.pdata.name&&this.pdata.mobile){this.isLoading=!0;try{let e=new Parse__default.Query("Profile");e.include("company"),e.equalTo("name",this.pdata.name),e.equalTo("mobile",this.pdata.mobile),this.profileList=await e.find(),this.profileList?.length<1&&this.showToast("该身份不存在,无法绑定!","warning")}catch(e){console.error("Error searching profile:",e),this.showToast("查询身份失败,请重试","danger")}finally{this.isLoading=!1}}else this.showToast("请填写完整信息以查询您的身份","warning")}async selectProfile(e){if(!e?.id)return;this.profileSearched=e;const t=await this.modalController.create({component:ProfileConfirmModalComponent,componentProps:{profile:e}});await t.present();const{data:n}=await t.onWillDismiss();n?.confirmed&&this.bindProfile(e)}goProfileManage(){this.router.navigate(["/common/manage/Profile",{rid:"x6xybaLWIC"}])}async onShowModal(){const e=await this.alertController.create({header:"团队成员管理",message:"您是企业管理员,可进入添加团队成员身份",buttons:[{text:"取消",role:"cancel"},{text:"前往管理",handler:()=>{this.goProfileManage()}}]});await e.present()}async showToast(e,t="success"){const n=await this.toastController.create({message:e,duration:2e3,color:t,position:"top"});await n.present()}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ProfileBindComponent,deps:[{token:AuthProfileService},{token:i1$1.Router},{token:i3.AlertController},{token:i3.ToastController},{token:CrossService},{token:i3.ModalController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ProfileBindComponent,selector:"fm-profile-bind",host:{listeners:{"window:resize":"onResize($event)"}},ngImport:i0,template:'<ion-content>\n <ng-container *ngIf="cross?.navMenuType == \'mobile\'; else desktopTemplate">\n <div class="ion-padding tips-block">\n <img src="https://file-cloud.fmode.cn/CCuWCEM24z/20231213/45hm71034653179.png" alt="" />\n <div>请使用电脑浏览器打开</div>\n </div>\n </ng-container>\n\n <ng-template #desktopTemplate>\n <div class="profile-page ion-padding">\n <div class="title">企业项目管理系统</div>\n \n <div class="date-container">\n <div class="date">{{ now | date : "yyyy年MM月dd日" }}</div>\n <ion-button *ngIf="user?.get(\'type\') == \'admin\'" fill="clear" size="small" (click)="onShowModal()">\n <ion-icon slot="start" name="people"></ion-icon>\n 企业管理员\n </ion-button>\n </div>\n\n <ng-container *ngIf="profileList?.length > 0; else noProfileTemplate">\n <h2>\n 欢迎您:{{\n profile?.get("name") ||\n this.profileList[0]?.get("name") ||\n user?.get("nickname") ||\n user?.get("name") ||\n user?.get("username")\n }},请选择您的企业身份:\n </h2>\n </ng-container>\n \n <ng-template #noProfileTemplate>\n <h2>您还未绑定企业,请先联系管理员绑定!</h2>\n </ng-template>\n\n <ion-list *ngIf="profileList?.length > 0" lines="full">\n <ion-item \n *ngFor="let p of profileList" \n button \n detail="false"\n [color]="currentProfile == p.id ? \'primary\' : \'\'"\n (click)="selectProfile(p)">\n <ion-icon slot="start" name="person" color="primary"></ion-icon>\n <ion-label>\n <h2>{{ p.get("name") }}</h2>\n <p>企业:{{ p.get("company")?.get("name") || p.get("company")?.get("title") }}</p>\n </ion-label>\n <ion-icon *ngIf="currentProfile == p.id" slot="end" name="checkmark" color="primary"></ion-icon>\n </ion-item>\n </ion-list>\n\n <div class="ion-margin-top ion-text-center">\n <ion-text color="medium">\n <ion-icon name="information-circle-outline"></ion-icon>\n 若无帐套信息,请输入企业身份验证绑定\n </ion-text>\n </div>\n\n <div class="form-container ion-margin-top">\n <ion-item>\n <ion-icon slot="start" name="person-outline"></ion-icon>\n <ion-input \n type="text" \n [(ngModel)]="pdata.name" \n placeholder="请输入您的姓名"\n clearInput>\n </ion-input>\n </ion-item>\n\n <ion-item>\n <ion-icon slot="start" name="phone-portrait-outline"></ion-icon>\n <ion-input \n type="tel" \n [(ngModel)]="pdata.mobile" \n placeholder="请输入您手机号"\n clearInput>\n </ion-input>\n </ion-item>\n\n <ion-button \n expand="block" \n (click)="searchProfile()"\n [disabled]="!pdata.name || !pdata.mobile"\n class="ion-margin-top">\n 查询身份\n <ion-spinner *ngIf="isLoading" name="crescent"></ion-spinner>\n </ion-button>\n </div>\n </div>\n </ng-template>\n</ion-content>',styles:[".profile-page{max-width:500px;margin:0 auto;padding-top:20px}.profile-page .title{font-size:24px;font-weight:700;text-align:center;margin-bottom:30px;color:var(--ion-color-primary)}.profile-page .date-container{display:flex;justify-content:space-between;align-items:center;margin-bottom:30px}.profile-page .date-container .date{font-size:16px;color:var(--ion-color-medium)}.profile-page h2{font-size:18px;color:var(--ion-color-dark);margin-bottom:20px}.profile-page ion-list{background:transparent;border-radius:8px;margin-bottom:20px}.profile-page ion-list ion-item{--border-radius: 8px;--padding-start: 10px;--inner-padding-end: 10px;margin-bottom:10px}.profile-page ion-list ion-item ion-label h2{font-weight:500;margin-bottom:5px}.profile-page ion-list ion-item ion-label p{color:var(--ion-color-medium);font-size:14px}.profile-page .form-container ion-item{--background: var(--ion-color-light);--border-radius: 8px;margin-bottom:15px}.tips-block{display:flex;flex-direction:column;align-items:center;justify-content:center;height:80vh;text-align:center}.tips-block img{width:220px;margin-bottom:20px}.tips-block div{font-size:18px;color:var(--ion-color-medium)}\n"],dependencies:[{kind:"directive",type:i2.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:i2.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:i3$3.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:i3$3.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"component",type:i3.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:i3.IonContent,selector:"ion-content",inputs:["color","fixedSlotPlacement","forceOverscroll","fullscreen","scrollEvents","scrollX","scrollY"]},{kind:"component",type:i3.IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:i3.IonInput,selector:"ion-input",inputs:["autocapitalize","autocomplete","autocorrect","autofocus","clearInput","clearInputIcon","clearOnEdit","color","counter","counterFormatter","debounce","disabled","enterkeyhint","errorText","fill","helperText","inputmode","label","labelPlacement","max","maxlength","min","minlength","mode","multiple","name","pattern","placeholder","readonly","required","shape","spellcheck","step","type","value"]},{kind:"component",type:i3.IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:i3.IonLabel,selector:"ion-label",inputs:["color","mode","position"]},{kind:"component",type:i3.IonList,selector:"ion-list",inputs:["inset","lines","mode"]},{kind:"component",type:i3.IonSpinner,selector:"ion-spinner",inputs:["color","duration","name","paused"]},{kind:"component",type:i3.IonText,selector:"ion-text",inputs:["color","mode"]},{kind:"directive",type:i3.TextValueAccessor,selector:"ion-input:not([type=number]),ion-textarea,ion-searchbar"},{kind:"pipe",type:i2.DatePipe,name:"date"}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ProfileBindComponent,decorators:[{type:Component,args:[{selector:"fm-profile-bind",template:'<ion-content>\n <ng-container *ngIf="cross?.navMenuType == \'mobile\'; else desktopTemplate">\n <div class="ion-padding tips-block">\n <img src="https://file-cloud.fmode.cn/CCuWCEM24z/20231213/45hm71034653179.png" alt="" />\n <div>请使用电脑浏览器打开</div>\n </div>\n </ng-container>\n\n <ng-template #desktopTemplate>\n <div class="profile-page ion-padding">\n <div class="title">企业项目管理系统</div>\n \n <div class="date-container">\n <div class="date">{{ now | date : "yyyy年MM月dd日" }}</div>\n <ion-button *ngIf="user?.get(\'type\') == \'admin\'" fill="clear" size="small" (click)="onShowModal()">\n <ion-icon slot="start" name="people"></ion-icon>\n 企业管理员\n </ion-button>\n </div>\n\n <ng-container *ngIf="profileList?.length > 0; else noProfileTemplate">\n <h2>\n 欢迎您:{{\n profile?.get("name") ||\n this.profileList[0]?.get("name") ||\n user?.get("nickname") ||\n user?.get("name") ||\n user?.get("username")\n }},请选择您的企业身份:\n </h2>\n </ng-container>\n \n <ng-template #noProfileTemplate>\n <h2>您还未绑定企业,请先联系管理员绑定!</h2>\n </ng-template>\n\n <ion-list *ngIf="profileList?.length > 0" lines="full">\n <ion-item \n *ngFor="let p of profileList" \n button \n detail="false"\n [color]="currentProfile == p.id ? \'primary\' : \'\'"\n (click)="selectProfile(p)">\n <ion-icon slot="start" name="person" color="primary"></ion-icon>\n <ion-label>\n <h2>{{ p.get("name") }}</h2>\n <p>企业:{{ p.get("company")?.get("name") || p.get("company")?.get("title") }}</p>\n </ion-label>\n <ion-icon *ngIf="currentProfile == p.id" slot="end" name="checkmark" color="primary"></ion-icon>\n </ion-item>\n </ion-list>\n\n <div class="ion-margin-top ion-text-center">\n <ion-text color="medium">\n <ion-icon name="information-circle-outline"></ion-icon>\n 若无帐套信息,请输入企业身份验证绑定\n </ion-text>\n </div>\n\n <div class="form-container ion-margin-top">\n <ion-item>\n <ion-icon slot="start" name="person-outline"></ion-icon>\n <ion-input \n type="text" \n [(ngModel)]="pdata.name" \n placeholder="请输入您的姓名"\n clearInput>\n </ion-input>\n </ion-item>\n\n <ion-item>\n <ion-icon slot="start" name="phone-portrait-outline"></ion-icon>\n <ion-input \n type="tel" \n [(ngModel)]="pdata.mobile" \n placeholder="请输入您手机号"\n clearInput>\n </ion-input>\n </ion-item>\n\n <ion-button \n expand="block" \n (click)="searchProfile()"\n [disabled]="!pdata.name || !pdata.mobile"\n class="ion-margin-top">\n 查询身份\n <ion-spinner *ngIf="isLoading" name="crescent"></ion-spinner>\n </ion-button>\n </div>\n </div>\n </ng-template>\n</ion-content>',styles:[".profile-page{max-width:500px;margin:0 auto;padding-top:20px}.profile-page .title{font-size:24px;font-weight:700;text-align:center;margin-bottom:30px;color:var(--ion-color-primary)}.profile-page .date-container{display:flex;justify-content:space-between;align-items:center;margin-bottom:30px}.profile-page .date-container .date{font-size:16px;color:var(--ion-color-medium)}.profile-page h2{font-size:18px;color:var(--ion-color-dark);margin-bottom:20px}.profile-page ion-list{background:transparent;border-radius:8px;margin-bottom:20px}.profile-page ion-list ion-item{--border-radius: 8px;--padding-start: 10px;--inner-padding-end: 10px;margin-bottom:10px}.profile-page ion-list ion-item ion-label h2{font-weight:500;margin-bottom:5px}.profile-page ion-list ion-item ion-label p{color:var(--ion-color-medium);font-size:14px}.profile-page .form-container ion-item{--background: var(--ion-color-light);--border-radius: 8px;margin-bottom:15px}.tips-block{display:flex;flex-direction:column;align-items:center;justify-content:center;height:80vh;text-align:center}.tips-block img{width:220px;margin-bottom:20px}.tips-block div{font-size:18px;color:var(--ion-color-medium)}\n"]}]}],ctorParameters:()=>[{type:AuthProfileService},{type:i1$1.Router},{type:i3.AlertController},{type:i3.ToastController},{type:CrossService},{type:i3.ModalController}],propDecorators:{onResize:[{type:HostListener,args:["window:resize",["$event"]]}]}});class AuthPcuserGuard{constructor(e,t){this.authService=e,this.router=t}canActivate(e,t){let n=t.url;return this.authService.redirectUrl=n,this.authService.checkLogin(n)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthPcuserGuard,deps:[{token:AuthService},{token:i1$1.Router}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthPcuserGuard,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:AuthPcuserGuard,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:AuthService},{type:i1$1.Router}]});const ProfileRoutes=[{path:"bind",canActivate:[AuthPcuserGuard],component:ProfileBindComponent,runGuardsAndResolvers:"always"}];class ProfileModule{static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ProfileModule,deps:[],target:i0.ɵɵFactoryTarget.NgModule})}static{this.ɵmod=i0.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"17.3.12",ngImport:i0,type:ProfileModule,declarations:[ProfileBindComponent,ProfileConfirmModalComponent],imports:[CommonModule,FormsModule,IonicModule,i1$1.RouterModule]})}static{this.ɵinj=i0.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ProfileModule,providers:[CrossService,AuthProfileService],imports:[CommonModule,FormsModule,IonicModule,RouterModule.forChild(ProfileRoutes)]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ProfileModule,decorators:[{type:NgModule,args:[{declarations:[ProfileBindComponent,ProfileConfirmModalComponent],imports:[CommonModule,FormsModule,IonicModule,RouterModule.forChild(ProfileRoutes)],providers:[CrossService,AuthProfileService]}]}]});export{AccountService,AgentPrompt,AgentStory,AgentTaskStep,ArticleService,AudioPlayer,AuthPcuserGuard,AuthProfileGuard,AuthProfileService,AuthService,AuthStaffGuard,AvatarModule,AvatarRoutes,CaptchaComponent,ChatContentPipe,ChatListComponent,ChatPanelComponent,ChatService,ClipboardService,CompAvatarParticleComponent,CompAvatarRoleImageComponent,CompAvatarRoleVideoComponent,CompAvatarTalkComponent,CompPersonItemComponent,CompPersonStoryComponent,CompPoiPickerComponent,CompPoiPickerModule,CompRolePromptComponent,CompUserAvatarComponent,CrossService,DialogDeleteStoryDialog,DialogPersonStorySelect,DurationStrPipe,FiletypePipe,FmAgentTaskComponent,FmArticleEditorComponent,FmChatHeaderArea,FmChatMessageCard,FmChatMesssageArea,FmChatModalInput,FmPushAudioOutputStreamCallback,FmStoryCardComponent,FmStoryListComponent,FmStoryLoaderComponent,FmStorySplitterComponent,FmTextQuillComponent,FmVideoComponent,FmaiService,FmodeChat,FmodeChatCompletion,FmodeMapModule,FmodeStorgeModule,FmodeTTS,FmodeTTSProviderDoubao,FmodeTTSProviderMicrosoft,FmodeVoiceService,HidexmlPipe,HwobsManagerComponent,HwobsService,ImagineService,ImagineWork,LoginComponent,MASK_LIST,MarkdownMathJax,MarkdownParse,MarkdownPreviewComponent,MarkdownPreviewModule,ModalAudioMessageComponent,ModalChatVoiceInputComponent,ModalPersonSelectComponent,ModalUserLoginComponent,NovaCloudService,NovaUploadService,PCMStreamer,PersonService,ProfileBindComponent,ProfileModule,ProfileRoutes,StaffModule,StaffService,StoryService,TipsController,UserModule,UserNamePipe,UserRoutes,UtilnowPipe,WebSpeech,WechatJssdkService,apig,buildFullUrl,drawDalle,getMessageContentText,getMessageImageUrl,ncloudApi,novaql,openChatPanelModal,openPersonSelectModal};
|
|
9
9
|
var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9mZXNtMjAyMi9mbW9kZS1uZy5tanM=`
|
|
10
10
|
|