fmode-ng 0.0.231 → 0.0.233

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/esm2022/lib/aigc/chat/chat-modal-input/modal-input.component.mjs +1 -1
  2. package/esm2022/lib/core/agent/chat/fmode-chat.mjs +1 -1
  3. package/esm2022/lib/core/agent/chat/message/index.mjs +10 -0
  4. package/esm2022/lib/core/agent/chat/message/message-manager.mjs +10 -0
  5. package/esm2022/lib/core/agent/chat/message/message.mjs +10 -0
  6. package/esm2022/lib/core/ecom/index.mjs +10 -0
  7. package/esm2022/lib/core/ecom/shopee/index.mjs +10 -0
  8. package/esm2022/lib/core/ecom/shopee/src/client.mjs +10 -0
  9. package/esm2022/lib/core/ecom/shopee/src/index.mjs +10 -0
  10. package/esm2022/lib/core/ecom/shopee/src/merchant.mjs +10 -0
  11. package/esm2022/lib/core/ecom/shopee/src/public.mjs +10 -0
  12. package/esm2022/lib/core/ecom/shopee/src/shop.mjs +10 -0
  13. package/esm2022/lib/core/ecom/shopee/src/types.mjs +10 -0
  14. package/esm2022/lib/core/index.mjs +1 -1
  15. package/esm2022/lib/core/parse/fmode.cloud.mjs +1 -1
  16. package/esm2022/lib/core/parse/fmode.parse.mjs +1 -1
  17. package/esm2022/lib/user/account/account.service.mjs +1 -1
  18. package/fesm2022/fmode-ng.mjs +1 -1
  19. package/fesm2022/fmode-ng.mjs.map +1 -1
  20. package/lib/core/agent/chat/fmode-chat.d.ts +35 -1
  21. package/lib/core/agent/chat/interface.d.ts +2 -0
  22. package/lib/core/agent/chat/message/index.d.ts +2 -0
  23. package/lib/core/agent/chat/message/message-manager.d.ts +86 -0
  24. package/lib/core/agent/chat/message/message.d.ts +175 -0
  25. package/lib/core/ecom/index.d.ts +1 -0
  26. package/lib/core/ecom/shopee/index.d.ts +1 -0
  27. package/lib/core/ecom/shopee/src/client.d.ts +51 -0
  28. package/lib/core/ecom/shopee/src/index.d.ts +37 -0
  29. package/lib/core/ecom/shopee/src/merchant.d.ts +214 -0
  30. package/lib/core/ecom/shopee/src/public.d.ts +204 -0
  31. package/lib/core/ecom/shopee/src/shop.d.ts +177 -0
  32. package/lib/core/ecom/shopee/src/types.d.ts +102 -0
  33. package/lib/core/index.d.ts +1 -0
  34. package/lib/core/parse/fmode.cloud.d.ts +5 -4
  35. package/lib/user/account/account.service.d.ts +5 -0
  36. package/package.json +2 -1
@@ -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{PromptTemplate}from"@langchain/core/prompts";import{Subject,Observable,bufferTime,concatMap,delay,finalize,interval,take,map,of,BehaviorSubject,combineLatest}from"rxjs";import{bufferWhen,takeUntil,filter,catchError}from"rxjs/operators";import pako from"pako";import{v4}from"uuid";import Recorder from"recorder-core";import"recorder-core/src/engine/pcm";import"recorder-core/src/engine/wav";import"recorder-core/src/extensions/waveview";import CryptoJS from"crypto-js";import*as ww from"@wecom/jssdk";import*as dd from"dingtalk-jsapi";import*as qiniu from"qiniu-js";import*as SparkMD5 from"spark-md5";import ObsClient from"esdk-obs-browserjs";import*as i0 from"@angular/core";import{Injectable,Pipe,Input,ViewChild,Component,NgModule,EventEmitter,Output,Inject,forwardRef,ChangeDetectionStrategy,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,IonModal as IonModal$1}from"@ionic/angular";import*as i2 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 i5 from"@awesome-cordova-plugins/diagnostic/ngx";import{Diagnostic}from"@awesome-cordova-plugins/diagnostic/ngx";import{MediaCapture}from"@awesome-cordova-plugins/media-capture/ngx";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*as i6 from"@angular/forms";import{FormsModule,ReactiveFormsModule,NG_VALUE_ACCESSOR,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,IonCheckbox,IonCardContent,IonCardHeader,IonCardTitle,IonCardSubtitle,IonSegmentButton}from"@ionic/angular/standalone";import*as i3$1 from"@angular/material/button";import{MatButtonModule}from"@angular/material/button";import*as i1$4 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$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{resizeOutline,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 Quill from"quill";import{basicSetup,EditorView}from"codemirror";import{Compartment}from"@codemirror/state";import*as i6$1 from"ng-qrcode";import{QrCodeModule}from"ng-qrcode";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";class FmodeACL{static{this._instance=null}static bindInstance(e){this._instance=e}constructor(e){this.permissions={},e&&(this.permissions={...e})}setPublicReadAccess(e){return this.permissions["*"]=this.permissions["*"]||{read:!1,write:!1},this.permissions["*"].read=e,this}setPublicWriteAccess(e){return this.permissions["*"]=this.permissions["*"]||{read:!1,write:!1},this.permissions["*"].write=e,this}setReadAccess(e,t){const n="string"==typeof e?e:e.id;if(!n)throw new Error("Invalid user ID");return this.permissions[n]=this.permissions[n]||{read:!1,write:!1},this.permissions[n].read=t,this}setWriteAccess(e,t){const n="string"==typeof e?e:e.id;if(!n)throw new Error("Invalid user ID");return this.permissions[n]=this.permissions[n]||{read:!1,write:!1},this.permissions[n].write=t,this}getPublicReadAccess(){return!!this.permissions["*"]?.read}getPublicWriteAccess(){return!!this.permissions["*"]?.write}getReadAccess(e){const t="string"==typeof e?e:e.id;return!!this.permissions[t]?.read}getWriteAccess(e){const t="string"==typeof e?e:e.id;return!!this.permissions[t]?.write}toJSON(){return{...this.permissions}}}class FmodeQuery{static{this._instance=null}static bindInstance(e){this._instance=e}static get instance(){if(!this._instance)throw new Error("FmodeParse not initialized");return this._instance}get currentInstance(){return this._parseInstance||FmodeQuery.instance}static convertIncludedObjects(e){if(!e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map((e=>this.convertIncludedObjects(e)));if(e.objectId&&(e.createdAt||e.updatedAt)){const t=e.className||"Object",n=new FmodeObject(t);n.id=e.objectId,e.createdAt&&(n.createdAt="string"==typeof e.createdAt?new Date(e.createdAt):e.createdAt),e.updatedAt&&(n.updatedAt="string"==typeof e.updatedAt?new Date(e.updatedAt):e.updatedAt),e.ACL&&(n.ACL=e.ACL);const o={};for(const[t,n]of Object.entries(e))["__type","className","objectId","createdAt","updatedAt","ACL"].includes(t)||(o[t]=this.convertIncludedObjects(n));return n.set(o),n}if("Object"===e.__type&&e.className&&e.objectId){const t=new FmodeObject(e.className);t.id=e.objectId,e.createdAt&&(t.createdAt=new Date(e.createdAt)),e.updatedAt&&(t.updatedAt=new Date(e.updatedAt)),e.ACL&&(t.ACL=e.ACL);const n={};for(const[t,o]of Object.entries(e))["__type","className","objectId","createdAt","updatedAt","ACL"].includes(t)||(n[t]=this.convertIncludedObjects(o));return t.set(n),t}if("Pointer"===e.__type&&e.className&&e.objectId)return e;const t={};for(const[n,o]of Object.entries(e))t[n]=this.convertIncludedObjects(o);return t}constructor(e){this.where={},this._include=[],this._exclude=[],this._select=[],this._count=!1,this.className="string"==typeof e?e:e.prototype.constructor.name}equalTo(e,t){return t=this.fixPointer(t),this.where[e]=t,this}fixPointer(e){return e?.className&&e?.data?{__type:"Pointer",className:e?.className,objectId:e?.data?.id||e?.id}:e}notEqualTo(e,t){return t=this.fixPointer(t),this.where[e]={$ne:t},this}lessThan(e,t){return this.where[e]={$lt:t},this}lessThanOrEqualTo(e,t){return this.where[e]={$lte:t},this}greaterThan(e,t){return this.where[e]={$gt:t},this}greaterThanOrEqualTo(e,t){return this.where[e]={$gte:t},this}containedIn(e,t){return this.where[e]={$in:t},this}notContainedIn(e,t){return this.where[e]={$nin:t},this}exists(e){return this.where[e]={$exists:!0},this}doesNotExist(e){return this.where[e]={$exists:!1},this}containsAll(e,t){return this.where[e]={$all:t},this}contains(e,t){return this.where[e]={$regex:t,$options:"i"},this}startsWith(e,t){return this.where[e]={$regex:`^${t}`,$options:"i"},this}endsWith(e,t){return this.where[e]={$regex:`${t}$`,$options:"i"},this}matches(e,t,n){return this.where[e]={$regex:t.source,$options:n},this}matchesQuery(e,t){return this.where[e]={$inQuery:{className:t.className,where:t.where}},this}doesNotMatchQuery(e,t){return this.where[e]={$notInQuery:{className:t.className,where:t.where}},this}matchesKeyInQuery(e,t,n){return this.where[e]={$select:{key:t,query:{className:n.className,where:n.where}}},this}doesNotMatchKeyInQuery(e,t,n){return this.where[e]={$dontSelect:{key:t,query:{className:n.className,where:n.where}}},this}near(e,t){return this.where[e]={$nearSphere:t},this}withinRadians(e,t,n){return this.where[e]={$nearSphere:t,$maxDistance:n},this}withinMiles(e,t,n){return this.withinRadians(e,t,n/3959)}withinKilometers(e,t,n){return this.withinRadians(e,t,n/6371)}withinGeoBox(e,t,n){return this.where[e]={$within:{$box:[t,n]}},this}polygonContains(e,t){return this.where[e]={$geoWithin:{$polygon:t}},this}containedBy(e,t){return this.where[e]={$containedBy:t},this}fullText(e,t,n){return this.where[e]={$text:{$search:t,$caseSensitive:n?.caseSensitive,$diacriticSensitive:n?.diacriticSensitive}},this}containsAllStartingWith(e,t){return this.where[e]={$all:t.map((e=>({$regex:`^${e}`})))},this}sizeEqualTo(e,t){return this.where[e]={$size:t},this}relatedTo(e,t){if(!e.id)throw new Error("Parent object must have an ID");return this.where.$relatedTo={object:e.toPointer(),key:t},this}relatedToObject(e,t){if(!e.id)throw new Error("Parent object must have an ID");return this.where.$relatedTo={object:e.toPointer(),key:t},this}relatedToQuery(e,t,n){return this.where.$relatedTo={key:t,query:{className:e,where:n.where}},this}matchesPointer(e,t){if(!t.id)throw new Error("Object must have an ID");return this.where[e]=t.toPointer(),this}matchesAnyPointer(e,t){const n=t.map((e=>{if(!e.id)throw new Error("All objects must have IDs");return e.toPointer()}));return this.where[e]={$in:n},this}static async findRelation(e,t,n){if(!e.id)throw new Error("Parent object must have an ID");return new FmodeQuery(e.className).relatedTo(e,t).find(n)}static async countRelation(e,t,n){if(!e.id)throw new Error("Parent object must have an ID");return new FmodeQuery(e.className).relatedTo(e,t).count(n)}static async addToRelation(e,t,n,o){if(!e.id)throw new Error("Parent object must have an ID");if(n.some((e=>!e.id)))throw new Error("All objects to add must have IDs");const i=n.map((e=>e.toPointer())),a=e._parseInstance||FmodeQuery.instance,r=`${a.serverURL}/classes/${e.className}/${e.id}`,s={"Content-Type":"application/json","X-Parse-Application-Id":a.appId};if(o?.useMasterKey&&a.config.masterKey)s["X-Parse-Master-Key"]=a.config.masterKey;else{const e=a.sessionToken;e&&(s["X-Parse-Session-Token"]=e)}const l=await fetch(r,{method:"PUT",headers:s,body:JSON.stringify({[t]:{__op:"AddRelation",objects:i}})});if(!l.ok){const e=await l.json();throw new Error(e.error||"Failed to add to relation")}}static async removeFromRelation(e,t,n,o){if(!e.id)throw new Error("Parent object must have an ID");if(n.some((e=>!e.id)))throw new Error("All objects to remove must have IDs");const i=n.map((e=>e.toPointer())),a=e._parseInstance||FmodeQuery.instance,r=`${a.serverURL}/classes/${e.className}/${e.id}`,s={"Content-Type":"application/json","X-Parse-Application-Id":a.appId};if(o?.useMasterKey&&a.config.masterKey)s["X-Parse-Master-Key"]=a.config.masterKey;else{const e=a.sessionToken;e&&(s["X-Parse-Session-Token"]=e)}const l=await fetch(r,{method:"PUT",headers:s,body:JSON.stringify({[t]:{__op:"RemoveRelation",objects:i}})});if(!l.ok){const e=await l.json();throw new Error(e.error||"Failed to remove from relation")}}exclude(...e){let t={};return this._exclude.concat(e).forEach((e=>{t[e]=!0})),this._exclude=Object.keys(t),this}include(...e){let t={};return this._include.concat(e).forEach((e=>{t[e]=!0})),this._include=Object.keys(t),this}select(...e){return this._select=e,this}limit(e){return this._limit=e,this}skip(e){return this._skip=e,this}ascending(...e){return this._order=e.map((e=>e.startsWith("-")?e.substring(1):e)),this}descending(...e){return this._order=e.map((e=>e.startsWith("-")?e.substring(1):`-${e}`)),this}addAscending(...e){return this._order||(this._order=[]),this._order.push(...e),this}addDescending(...e){return this._order||(this._order=[]),this._order.push(...e.map((e=>`-${e}`))),this}readPreference(e){return this._readPreference=e,this}includeReadPreference(e){return this._includeReadPreference=e,this}excludeReadPreference(e){return this._excludeReadPreference=e,this}subqueryReadPreference(e){return this._subqueryReadPreference=e,this}hint(e){return this.hint=e,this}maxTimeMS(e){return this._maxTimeMS=e,this}explain(e=!0){return this._explain=e,this}withCount(e=!0){return this._count=e,this}async find(e){const t=this.currentInstance,n=new URL(`${t.serverURL}/classes/${this.className}`),o=this._buildQueryParams();Object.entries(o).forEach((([e,t])=>{void 0!==t&&n.searchParams.set(e,"string"==typeof t?t:JSON.stringify(t))}));const i={"X-Parse-Application-Id":t.appId};if(e?.useMasterKey&&t.config.masterKey)i["X-Parse-Master-Key"]=t.config.masterKey;else{const e=this._sessionToken||t.sessionToken;e&&(i["X-Parse-Session-Token"]=e)}const a=await fetch(n.toString(),{headers:i}),r=await a.json();if(209==r.code&&t.User.logOut(),r.error)throw console.error(a),new Error(r.error);return r.results.map((e=>{const t=new FmodeObject(this.className);t._parseInstance=this._parseInstance,t.id=e.objectId,e.createdAt&&(t.createdAt=new Date(e.createdAt)),e.updatedAt&&(t.updatedAt=new Date(e.updatedAt||e.createdAt)),e.ACL&&(t.ACL=e.ACL);const n={};for(const[t,o]of Object.entries(e))["__type","className","objectId","createdAt","updatedAt","ACL"].includes(t)||(this._include.includes(t)&&o&&"object"==typeof o&&o.objectId,n[t]=FmodeQuery.convertIncludedObjects(o));return t.set(n),t}))}async first(e){this.limit(1);return(await this.find(e))[0]||null}async get(e,t){const n=this.currentInstance,o=new URL(`${n.serverURL}/classes/${this.className}/${e}`);this._include.length>0&&o.searchParams.set("include",this._include.join(","));const i={"X-Parse-Application-Id":n.appId};if(t?.useMasterKey&&n.config.masterKey)i["X-Parse-Master-Key"]=n.config.masterKey;else{const e=this._sessionToken||n.sessionToken;e&&(i["X-Parse-Session-Token"]=e)}const a=await fetch(o.toString(),{headers:i}),r=await a.json();if(r.error)throw new Error(r.error);const s=new FmodeObject(this.className);s._parseInstance=this._parseInstance,s.id=r.objectId,r.createdAt&&(s.createdAt=new Date(r.createdAt)),r.updatedAt&&(s.updatedAt=new Date(r.updatedAt||r.createdAt)),r.ACL&&(s.ACL=r.ACL);const l={};for(const[e,t]of Object.entries(r))["__type","className","objectId","createdAt","updatedAt","ACL"].includes(e)||(this._include.includes(e)&&t&&"object"==typeof t&&t.objectId,l[e]=FmodeQuery.convertIncludedObjects(t));return s.set(l),s}async count(e){this.withCount();const t=this.currentInstance,n=new URL(`${t.serverURL}/classes/${this.className}`);n.searchParams.set("count","1"),n.searchParams.set("limit","0"),Object.keys(this.where).length>0&&n.searchParams.set("where",JSON.stringify(this.where));const o={"X-Parse-Application-Id":t.appId};if(e?.useMasterKey&&t.config.masterKey)o["X-Parse-Master-Key"]=t.config.masterKey;else{const e=this._sessionToken||t.sessionToken;e&&(o["X-Parse-Session-Token"]=e)}console.log(o,n?.href);const i=await fetch(n.toString(),{headers:o}),a=await i.json();if(a.error)throw new Error(a.error);return a.count||0}toJSON(){const e={className:this.className};return Object.keys(this.where).length>0&&(e.where=this.where),this._include.length>0&&(e.include=this._include.join(",")),this._exclude.length>0&&(e.exclude=this._exclude.join(",")),this._select.length>0&&(e.keys=this._select.join(",")),void 0!==this._limit&&(e.limit=this._limit),void 0!==this._skip&&(e.skip=this._skip),this._order&&this._order.length>0&&(e.order=this._order.join(",")),this._count&&(e.count=1),this._explain&&(e.explain=!0),this._hint&&(e.hint=this._hint),this._maxTimeMS&&(e.maxTimeMS=this._maxTimeMS),this._readPreference&&(e.readPreference=this._readPreference),this._includeReadPreference&&(e.includeReadPreference=this._includeReadPreference),this._excludeReadPreference&&(e.excludeReadPreference=this._excludeReadPreference),this._subqueryReadPreference&&(e.subqueryReadPreference=this._subqueryReadPreference),e}static fromJSON(e,t){const n=new FmodeQuery(e=e||t?.className);if(t.where&&(n.where=t.where),t.include){const e="string"==typeof t.include?t.include.split(","):t.include;n._include=e}if(t.exclude){const e="string"==typeof t.exclude?t.exclude.split(","):t.exclude;n._exclude=e}if(t.keys){const e="string"==typeof t.keys?t.keys.split(","):t.keys;n._select=e}if(void 0!==t.limit&&(n._limit=t.limit),void 0!==t.skip&&(n._skip=t.skip),t.order){const e="string"==typeof t.order?t.order.split(","):t.order;n._order=e}return t.count&&(n._count=!!t.count),t.explain&&(n._explain=!!t.explain),t.hint&&(n._hint=t.hint),t.maxTimeMS&&(n._maxTimeMS=t.maxTimeMS),t.readPreference&&(n._readPreference=t.readPreference),t.includeReadPreference&&(n._includeReadPreference=t.includeReadPreference),t.excludeReadPreference&&(n._excludeReadPreference=t.excludeReadPreference),t.subqueryReadPreference&&(n._subqueryReadPreference=t.subqueryReadPreference),n}_buildQueryParams(){const e={};return Object.keys(this.where).length>0&&(e.where=this.where),this._include.length>0&&(e.include=this._include.join(",")),this._exclude.length>0&&(e.excludeKeys=this._exclude.join(",")),this._select.length>0&&(e.keys=this._select.join(",")),void 0!==this._limit&&(e.limit=this._limit),void 0!==this._skip&&(e.skip=this._skip),this._order&&(e.order=this._order.join(",")),this._count&&(e.count=1),this._explain&&(e.explain=!0),this._hint&&(e.hint=this._hint),this._maxTimeMS&&(e.maxTimeMS=this._maxTimeMS),e}subscribe(){const e=new EventTarget,t=setInterval((async()=>{try{const t=await this.find();e.dispatchEvent(new CustomEvent("update",{detail:t}))}catch(t){e.dispatchEvent(new CustomEvent("error",{detail:t}))}}),5e3);return e.unsubscribe=()=>{clearInterval(t)},e}static or(...e){if(0===e.length)throw new Error("At least one query required");const t=e[0].className;if(e.some((e=>e.className!==t)))throw new Error("All queries must be for the same class");const n=new FmodeQuery(t);return n.where={$or:e.map((e=>e.where))},n}static and(...e){if(0===e.length)throw new Error("At least one query required");const t=e[0].className;if(e.some((e=>e.className!==t)))throw new Error("All queries must be for the same class");const n=new FmodeQuery(t);return n.where={$and:e.map((e=>e.where))},n}or(...e){return FmodeQuery.or(this,...e)}and(...e){return FmodeQuery.and(this,...e)}}class FmodeRelation{static{this._instance=null}static bindInstance(e){this._instance=e}constructor(e,t){this.__type="Relation",this.parent=e,this.key=t,this.className=e.className}add(e){if(!this.parent.id)throw new Error("Cannot add relation to unsaved object");if(Array.isArray(e)){e.map((e=>{if("function"!=typeof e.toPointer)throw new Error("Object does not have toPointer method");return e.toPointer()}))}else{if("function"!=typeof e.toPointer)throw new Error("Object does not have toPointer method");e.toPointer()}}remove(e){if(!this.parent.id)throw new Error("Cannot remove relation from unsaved object");e.map((e=>e.toPointer()))}query(){return new FmodeQuery(this.className).relatedTo(this.parent,this.key)}toJSON(){return{__type:"Relation",className:this.className}}}class FmodeObject{static{this._instance=null}static bindInstance(e){this._instance=e}constructor(e){this.data={},this.className=e,this._parseInstance=FmodeObject._instance}static extend(e){const t=class extends FmodeObject{constructor(){super(e)}};return t.extend=FmodeObject.extend,t.create=FmodeObject.create,t.fetchAll=FmodeObject.fetchAll,t.fromFile=FmodeObject.fromFile,t.bindInstance=FmodeObject.bindInstance,t._instance=FmodeObject._instance,t}toPointer(){return{__type:"Pointer",className:this.className,objectId:this.id}}toJSON(){const e={__type:"Object",className:this.className,...this.data};this.id&&(e.objectId=this.id),Object.keys(e).forEach((t=>{e[t]?.getTime?.()&&(e[t]={__type:"Date",iso:e[t].toISOString()})}));try{this.createdAt&&("string"==typeof this.createdAt&&(this.createdAt=new Date(this.createdAt)),e.createdAt={__type:"Date",iso:this.createdAt.toISOString()}),this.updatedAt&&("string"==typeof this.updatedAt&&(this.updatedAt=new Date(this.updatedAt)),console.log(this.updatedAt),e.updatedAt={__type:"Date",iso:this.updatedAt.toISOString()})}catch(e){}return this.ACL&&(e.ACL=this.ACL),e}get(e){return"Date"==this.data[e]?.__type?new Date(this.data[e]?.iso):this.data[e]}isoStrToDate(e){if(e?.indexOf?.("T")>-1&&e?.indexOf?.("Z")>-1&&24==e?.length)try{return new Date(e)}catch(e){}return e}set(e,t){return"object"==typeof e?(Object.keys(e).forEach((t=>{e[t]?.indexOf?.("T")>-1&&e[t]?.indexOf?.("Z")>-1&&(e[t]=this.isoStrToDate(e[t]))})),Object.assign(this.data,e)):(t&&(t=this.isoStrToDate(t)),this.data[e]=t),this}unset(e){return delete this.data[e],this}increment(e,t=1){const n=this.get(e)||0;return this.set(e,n+t),this}add(e,t){const n=this.get(e)||[];return this.set(e,[...n,...t]),this}addUnique(e,t){const n=new Set(this.get(e)||new Set);return t.forEach((e=>n.add(e))),this.set(e,Array.from(n)),this}remove(e,t){const n=this.get(e)||[],o=new Set(t);return this.set(e,n.filter((e=>!o.has(e)))),this}async save(e){const t=this._parseInstance||FmodeObject._instance;if(!t)throw new Error("Not initialized");const n=this.id?"PUT":"POST";let o=`${t.serverURL}/classes/${this.className}`;this.id&&(o+=`/${this.id}`);const i={"Content-Type":"application/json","X-Parse-Application-Id":t.appId};if(e?.useMasterKey&&t.config.masterKey)i["X-Parse-Master-Key"]=t.config.masterKey;else{const e=t.sessionToken;e&&(i["X-Parse-Session-Token"]=e)}const a=this.toJSON();delete a.createdAt,delete a.updatedAt,delete a.__type,delete a.className;for(const e in a)this.get(e)?.toPointer&&(a[e]=this.get(e).toPointer());let r,s;console.log(o,a);try{s=await fetch(o,{method:n,headers:i,body:JSON.stringify(a)}),console.log(JSON.stringify(a)),r=await s.json()}catch(e){alert(e)}if(console.log(r),r.error)throw new Error(r.error);return this.id=r.objectId||this.id,this.createdAt=new Date(r.createdAt||this.createdAt),this.updatedAt=new Date(r.updatedAt||this.updatedAt),this}async destroy(e){if(!this.id)throw new Error("Cannot destroy unsaved object");const t=this._parseInstance||FmodeObject._instance;if(!t)throw new Error("Not initialized");const n={"X-Parse-Application-Id":t.appId};if(e?.useMasterKey&&t.config.masterKey)n["X-Parse-Master-Key"]=t.config.masterKey;else{const e=t.sessionToken;e&&(n["X-Parse-Session-Token"]=e)}const o=`${t.serverURL}/classes/${this.className}/${this.id}`,i=await fetch(o,{method:"DELETE",headers:n});if(!i.ok){const e=await i.json();throw new Error(e.error||"Failed to delete object")}}static async create(e,t,n){const o=new this(e);return o.set(t),o.save(n)}static async fetchAll(e,t){if(!FmodeObject._instance)throw new Error("Not initialized");if(0===e.length)return[];const n={"Content-Type":"application/json","X-Parse-Application-Id":FmodeObject._instance.appId};if(t?.useMasterKey&&FmodeObject._instance.config.masterKey)n["X-Parse-Master-Key"]=FmodeObject._instance.config.masterKey;else{const e=FmodeObject._instance.sessionToken;e&&(n["X-Parse-Session-Token"]=e)}const o=`${FmodeObject._instance.serverURL}/batch`,i=e.map((e=>({method:"GET",path:`/classes/${e.className}/${e.id}`}))),a=await fetch(o,{method:"POST",headers:n,body:JSON.stringify({requests:i})}),r=await a.json();if(r.error)throw new Error(r.error);return r.map(((t,n)=>{const o=e[n];return o.set(t.success),o}))}relation(e){return new FmodeRelation(this,e)}static async fromFile(e,t,n){if(!FmodeObject._instance)throw new Error("Not initialized");const o=new FormData;o.append("file",t,e);const i={"X-Parse-Application-Id":FmodeObject._instance.appId},a=FmodeObject._instance.sessionToken;a&&(i["X-Parse-Session-Token"]=a);const r=`${FmodeObject._instance.serverURL}/files/${e}`,s=await fetch(r,{method:"POST",headers:i,body:o}),l=await s.json();if(l.error)throw new Error(l.error);return{__type:"File",name:l.name,url:l.url}}}class FmodeFile{static{this._instance=null}static bindInstance(e){this._instance=e}constructor(e,t){this.__type="File",this.name=e,this.data="object"==typeof t&&"base64"in t?this._base64ToArrayBuffer(t.base64):t,this.url=""}_base64ToArrayBuffer(e){const t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n.buffer}static async save(e,t,n){if(!FmodeObject._instance)throw new Error("Not initialized");const o=new FormData;if(t instanceof Blob||t instanceof File)o.append("file",t,e);else if(t instanceof ArrayBuffer){const i=new Blob([new Uint8Array(t)],{type:n?.type});o.append("file",i,e)}else{const i=new Blob([t],{type:n?.type||"text/plain"});o.append("file",i,e)}const i={"X-Parse-Application-Id":FmodeObject._instance.appId};n?.useMasterKey&&FmodeObject._instance.config.masterKey&&(i["X-Parse-Master-Key"]=FmodeObject._instance.config.masterKey);const a=`${FmodeObject._instance.serverURL}/files/${e}`,r=await fetch(a,{method:"POST",headers:i,body:o}),s=await r.json();if(s.error)throw new Error(s.error);return new FmodeFile(s.name,s.url)}toJSON(){return{__type:"File",name:this.name,url:this.url}}}class FmodeGeoPoint{static{this._instance=null}static bindInstance(e){this._instance=e}constructor(e,t){let n,o;if(this.__type="GeoPoint","object"==typeof e&&null!==e)n=e.latitude,o=e.longitude;else{if("number"!=typeof e||"number"!=typeof t)throw new Error("Invalid GeoPoint parameters. Use either GeoPoint(lat, lon) or GeoPoint({latitude, longitude})");n=e,o=t}if(n<-90||n>90)throw new Error("Latitude must be between -90 and 90");if(o<-180||o>180)throw new Error("Longitude must be between -180 and 180");this.latitude=n,this.longitude=o}static current(e){return new Promise(((t,n)=>{navigator.geolocation.getCurrentPosition((e=>{t(new FmodeGeoPoint(e.coords.latitude,e.coords.longitude))}),(e=>n(e)),e)}))}kilometersTo(e){return this._calculateDistance(e,"kilometers")}milesTo(e){return this._calculateDistance(e,"miles")}radiansTo(e){return this._calculateDistance(e,"radians")}_calculateDistance(e,t){const n={kilometers:6371,miles:3959,radians:1}[t],o=(e.latitude-this.latitude)*Math.PI/180,i=(e.longitude-this.longitude)*Math.PI/180,a=Math.sin(o/2)*Math.sin(o/2)+Math.cos(this.latitude*Math.PI/180)*Math.cos(e.latitude*Math.PI/180)*Math.sin(i/2)*Math.sin(i/2);return n*(2*Math.atan2(Math.sqrt(a),Math.sqrt(1-a)))}toJSON(){return{__type:"GeoPoint",latitude:this.latitude,longitude:this.longitude}}}class FmodeUser extends FmodeObject{static{this._instance=null}static{this.instanceKey=()=>{if(!this._instance)throw new Error("FmodeParse not initialized before using User");return"Parse/"+this._instance.appId+"/currentUser"}}static bindInstance(e){this._instance=e}static get instance(){if(!this._instance)throw new Error("FmodeParse not initialized");return this._instance}get username(){return this.get("username")}set username(e){this.set("username",e)}get email(){return this.get("email")}set email(e){this.set("email",e)}get password(){return this.get("password")}set password(e){this.set("password",e)}constructor(e){super("_User"),e&&(this.id=e?.objectId,this.createdAt=new Date(e?.createdAt),this.updatedAt=new Date(e?.updatedAt),e.sessionToken&&(this.sessionToken=e.sessionToken,delete e.sessionToken),this.set(e))}static async logIn(e,t){const n=`${this.instance.serverURL}/login`,o=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json","X-Parse-Application-Id":this.instance.appId},body:JSON.stringify({username:e,password:t})}),i=await o.json();if(i.error)throw i;const a=new this({...i,username:e,password:t});return a._saveToCache(),a}static async become(e){const t=`${this.instance.serverURL}/users/me`;let n={"X-Parse-Session-Token":e,"X-Parse-Application-Id":this.instance.appId};const o=await fetch(t,{headers:n}),i=await o.json();if(i.error)throw i.error;const a=new this({...i,sessionToken:e});return a._saveToCache(),a}static async signUp(e,t,n={}){return new this({...n,username:e,password:t}).signUp()}static async logOut(){if(this.current())try{await fetch(`${this.instance.serverURL}/logout`,{method:"POST",headers:{"X-Parse-Session-Token":this.current().sessionToken,"X-Parse-Application-Id":this.instance.appId}})}finally{this._clearCurrentUser()}}static async requestPasswordReset(e){const t=`${this.instance.serverURL}/requestPasswordReset`,n=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json","X-Parse-Application-Id":this.instance.appId},body:JSON.stringify({email:e})}),o=await n.json();if(o.error)throw o}static{this._currentUser=null}static current(){if(this._currentUser)return this._currentUser;try{const e=localStorage.getItem(this.instanceKey());if(!e)return null;const t=JSON.parse(e);if(!t.sessionToken)return null;const n=new this(t);return this._currentUser=n,n.sessionToken&&this._instance&&(this._instance.sessionToken=n.sessionToken),n}catch(e){return console.warn("Failed to restore user from cache",e),null}}static _clearCurrentUser(){this._currentUser=null,this._instance&&(this._instance.sessionToken=void 0),localStorage.removeItem(this.instanceKey())}async signUp(e){if(e&&this.set(e),!this.username)throw new Error("Username is required");if(!this.password)throw new Error("Password is required");const t=this._parseInstance||FmodeUser.instance;let n=this.toJSON();delete n.__type,delete n.className;const o=`${t.serverURL}/users`,i=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json","X-Parse-Application-Id":t.appId},body:JSON.stringify(n)}),a=await i.json();if(a.error)throw a;return this.id=a.objectId,this.createdAt=new Date(a.createdAt),this.sessionToken=a.sessionToken,this._saveToCache(),this}async save(){const e=this._parseInstance||FmodeUser.instance,t=`${e.serverURL}/users/${this.id||this.data.objectId}`,n={"Content-Type":"application/json","X-Parse-Application-Id":e.appId,"X-Parse-Session-Token":this.sessionToken},o=this.toJSON();delete o.__type,delete o.objectId,delete o.className,delete o.sessionToken,delete o.username,delete o.createdAt,delete o.updatedAt;const i=await fetch(t,{method:"PUT",headers:n,body:JSON.stringify(o)}),a=await i.json();if(a.error)throw 209===a.code&&FmodeUser._clearCurrentUser(),new Error(a.error);return this.set("updatedAt",new Date(a.updatedAt)),this._saveToCache(),this}_saveToCache(){if(!this.sessionToken)return;FmodeUser._currentUser=this;const e=this._parseInstance||FmodeUser._instance;e&&(e.sessionToken=this.sessionToken),localStorage.setItem(FmodeUser.instanceKey(),JSON.stringify(this.toJSONForCache()))}toJSONForCache(){return{...super.toJSON(),sessionToken:this.sessionToken}}getSessionToken(){return this.sessionToken}async destroy(e){if(!this.id)throw new Error("Cannot destroy unsaved user");const t=this._parseInstance||FmodeUser.instance,n=`${t.serverURL}/users/${this.id}`,o={"X-Parse-Session-Token":this.sessionToken,"X-Parse-Application-Id":t.appId};e?.useMasterKey&&t.config.masterKey&&(o["X-Parse-Master-Key"]=t.config.masterKey);const i=await fetch(n,{method:"DELETE",headers:o});if(!i.ok){const e=await i.json();throw new Error(e.error||"Failed to delete user")}FmodeUser._clearCurrentUser()}}class FmodeCloud{static{this._instance=null}constructor(){this._config=null,this._cloudFunctions=new Map}static getInstance(){return this._instance||(this._instance=new FmodeCloud),this._instance}bindInstance(e){this._config=e}define(e,t){this._cloudFunctions.set(e,t)}async run(e,t={},n={}){if(!this._config)throw new Error("FmodeCloud not initialized. Call bindInstance first.");const o=`${this._config.serverURL}/functions/${e}`,i={...t,_ApplicationId:this._config.appId,_InstallationId:n.installationId||this.generateInstallationId()},a=this._config.sessionToken;a&&(i._SessionToken=a);try{const e=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json","X-Parse-Application-Id":this._config.appId,...this._config.javascriptKey&&{"X-Parse-JavaScript-Key":this._config.javascriptKey},...this._config.masterKey&&{"X-Parse-Master-Key":this._config.masterKey},...a&&{"X-Parse-Session-Token":a}},body:JSON.stringify(i)});if(!e.ok)throw new Error(`HTTP error! status: ${e.status}`);const t=await e.json();if(t.error)throw new Error(t.error.message||"Cloud function error");return t.result}catch(t){throw console.error(`Cloud function ${e} failed:`,t),t}}async afterDelete(e,t){this.define(`afterDelete_${e}`,t)}async afterSave(e,t){this.define(`afterSave_${e}`,t)}async beforeDelete(e,t){this.define(`beforeDelete_${e}`,t)}async beforeSave(e,t){this.define(`beforeSave_${e}`,t)}async beforeFind(e,t){this.define(`beforeFind_${e}`,t)}async afterFind(e,t){this.define(`afterFind_${e}`,t)}async job(e,t){this.define(`job_${e}`,t)}generateInstallationId(){return"undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(function(e){const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)}))}}const Cloud=FmodeCloud.getInstance();class FmodeParse{static{this._instances={}}static{this._defaultInstance=null}constructor(e){this.config=e,this.Object=this.createObjectFactory(),this.Query=this.createQueryFactory(),this.User=this.createUserFactory(),this.GeoPoint=FmodeGeoPoint,this.File=FmodeFile,this.ACL=FmodeACL,this.Relation=FmodeRelation,this.Cloud=FmodeCloud.getInstance(),FmodeObject._instance||FmodeObject.bindInstance(this),FmodeQuery._instance||FmodeQuery.bindInstance(this),FmodeUser._instance||FmodeUser.bindInstance(this),FmodeGeoPoint._instance||FmodeGeoPoint.bindInstance(this),FmodeRelation._instance||FmodeRelation.bindInstance(this),FmodeFile._instance||FmodeFile.bindInstance(this),FmodeACL._instance||FmodeACL.bindInstance(this),this.Cloud.bindInstance(this.config)}createObjectFactory(){const e=this;return class Object extends FmodeObject{constructor(t){super(t),this._parseInstance=e}static extend(e){const t=class extends Object{constructor(){super(e)}};return t.extend=Object.extend,t.create=Object.create,t.fetchAll=Object.fetchAll,t.fromFile=Object.fromFile,t}static async create(e,t,n){const o=new this(e);return o.set(t),o.save(n)}static async fetchAll(t,n){if(!e)throw new Error("Not initialized");if(0===t.length)return[];const o={"Content-Type":"application/json","X-Parse-Application-Id":e.appId};if(n?.useMasterKey&&e.config.masterKey)o["X-Parse-Master-Key"]=e.config.masterKey;else{const t=e.sessionToken;t&&(o["X-Parse-Session-Token"]=t)}const i=`${e.serverURL}/batch`,a=t.map((e=>({method:"GET",path:`/classes/${e.className}/${e.id}`}))),r=await fetch(i,{method:"POST",headers:o,body:JSON.stringify({requests:a})}),s=await r.json();if(s.error)throw new Error(s.error);return s.map(((e,n)=>{const o=t[n];return o.set(e.success),o}))}static async fromFile(t,n,o){if(!e)throw new Error("Not initialized");const i=new FormData;i.append("file",n,t);const a={"X-Parse-Application-Id":e.appId},r=e.sessionToken;r&&(a["X-Parse-Session-Token"]=r);const s=`${e.serverURL}/files/${t}`,l=await fetch(s,{method:"POST",headers:a,body:i}),c=await l.json();if(c.error)throw new Error(c.error);return{__type:"File",name:c.name,url:c.url}}}}createQueryFactory(){const e=this;return class Query extends FmodeQuery{constructor(t){super(t),this._parseInstance=e}static get instance(){return e}static bindInstance(e){}}}createUserFactory(){const e=this;return class User extends FmodeUser{constructor(t){super(t),this._parseInstance=e}static get instance(){return e}static{this.instanceKey=()=>"Parse/"+e.appId+"/currentUser"}static bindInstance(e){}static async logIn(t,n){const o=`${e.serverURL}/login`,i=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json","X-Parse-Application-Id":e.appId},body:JSON.stringify({username:t,password:n})}),a=await i.json();if(a.error)throw a;const r=new this({...a,username:t,password:n});return r._saveToCache(),r}static async become(t){const n=`${e.serverURL}/users/me`;let o={"X-Parse-Session-Token":t,"X-Parse-Application-Id":e.appId};const i=await fetch(n,{headers:o}),a=await i.json();if(a.error)throw a.error;const r=new this({...a,sessionToken:t});return r._saveToCache(),r}static async signUp(e,t,n={}){return new this({...n,username:e,password:t}).signUp()}static async logOut(){if(this.current())try{await fetch(`${e.serverURL}/logout`,{method:"POST",headers:{"X-Parse-Session-Token":this.current().sessionToken,"X-Parse-Application-Id":e.appId}})}finally{this._clearCurrentUser()}}static async requestPasswordReset(t){const n=`${e.serverURL}/requestPasswordReset`,o=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json","X-Parse-Application-Id":e.appId},body:JSON.stringify({email:t})}),i=await o.json();if(i.error)throw i}static{this._currentUser=null}static current(){if(this._currentUser)return this._currentUser;try{const t=localStorage.getItem(this.instanceKey());if(!t)return null;const n=JSON.parse(t);if(!n.sessionToken)return null;const o=new this(n);return this._currentUser=o,o.sessionToken&&e&&(e.sessionToken=o.sessionToken),o}catch(e){return console.warn("Failed to restore user from cache",e),null}}static _clearCurrentUser(){this._currentUser=null,e&&(e.sessionToken=void 0),localStorage.removeItem(this.instanceKey())}_saveToCache(){if(!this.sessionToken)return;this.constructor._currentUser=this;const e=this._parseInstance||this.constructor.instance;e&&(e.sessionToken=this.sessionToken),localStorage.setItem(this.constructor.instanceKey(),JSON.stringify(this.toJSONForCache()))}}}static initialize(e){let t;if("string"==typeof e){let n="http://dev.fmode.cn:1337/parse";"undefined"!=typeof location&&"https:"===location.protocol&&(n="https://dev.fmode.cn/parse"),t=new FmodeParse({appId:e,serverURL:n}),this._defaultInstance=t,this._instances.default=t}else t=new FmodeParse(e),e.config&&(this._instances[e.config]=t),e.config&&"default"!==e.config||(this._defaultInstance=t);return t}static with(e){if(!this._instances.nova){let e=new FmodeParse({appId:"ncloudmaster",serverURL:"https://server.fmode.cn/parse"});this._instances.nova=e}if(!this._instances.dev){let e=new FmodeParse({appId:"dev",serverURL:"https://dev.fmode.cn/parse"});this._instances.dev=e}return"dev"!=e||this._defaultInstance||(this._defaultInstance=this._instances.dev),"default"!=e||this._instances.default||(this._instances.default=this._instances.dev,this._defaultInstance=this._instances.dev),this._instances[e]||this._defaultInstance}static getAllInstances(){return{...this._instances}}static getInstanceConfigs(){const e={};return Object.entries(this._instances).forEach((([t,n])=>{e[t]=n.config})),e}get serverURL(){return this.config.serverURL}set serverURL(e){this.config.serverURL=e}get appId(){return this.config.appId}get sessionToken(){if(this.config.sessionToken)return this.config.sessionToken;const e=this.User.current();return e?.sessionToken}set sessionToken(e){this.config.sessionToken=e}}!function(e){e.Object=FmodeObject,e.Query=FmodeQuery,e.User=FmodeUser,e.File=FmodeFile,e.Relation=FmodeRelation,e.ACL=FmodeACL,e.GeoPoint=FmodeGeoPoint,e.Cloud=FmodeCloud.getInstance()}(FmodeParse||(FmodeParse={}));const defaultExport=new Proxy(FmodeParse,{apply:(e,t,n)=>FmodeParse.initialize.apply(e,n),get:(e,t)=>t in e?e[t]:t in FmodeParse?FmodeParse[t]:FmodeParse.with("default")[t]});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}}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}}const Parse$H=defaultExport.with("nova");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,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.voiceConfig=e?.voiceConfig,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$H.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$H.User.current()?.id&&t.set("user",Parse$H.User.current().toPointer())}if(!t?.get("voiceFile")){const n=[];e&&n.push({ssml:e});const o=Parse$H.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")?(n?.onStart?.(t),this.playAudioData(t?.get("voiceFile")?.get("url"),t,n,!0),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?.()}),500),o(t)}),(e=>{this.isPlaying=!1,i(`Error occurred during synthesis: ${e}`)}),(()=>{n?.onStart?.()}))})))}async playAudioData(e,t,n,o=!1){let i;if(e?.indexOf?.("http")>=-1)i=e;else{const n=new Blob([e],{type:"audio/wav"});i=URL.createObjectURL(n),await this.uploadAndSaveVoice(n,t)}o||n?.onStart?.(t),this.isPlaying=!0;const a=this.audioPlayer;a.setAudioEvent("onloadeddata",(()=>{const e=1e3*a.duration;t?.get("duration")||(t.set("duration",e),t.save()),n?.onLoaded?.(a)})),["onended"].forEach((e=>{a.setAudioEvent(e,(()=>{this.isPlaying=!1,n?.onStop?.()}))}));const playAudio=()=>{a.play(i).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:this.voiceConfig?.voice||"zh_female_shuangkuaisisi_emo_v2_mars_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("&")}`}const Parse$G=defaultExport.with("nova");async function getFormatTpl(e,t){let n=await getPromptTpl(e);return await n.format(t)}async function getPromptTpl(e){let t=new Parse$G.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",Parse$F=defaultExport.with("nova");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-1.6-cn",this.max_tokens=t?.max_tokens||32768}sendCompletion(e={messages:[]}){e.intTime=e?.intTime||50,e.isDirect=e?.isDirect||!1,e?.isDirect&&(e.intTime=1);const 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 this.model.indexOf("1.6")>-1&&(t.thinking=t.thinking||{type:"disabled"}),e?.max_tokens&&(t.max_tokens=e?.max_tokens||this.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 ${localStorage.getItem("FMODE_AI_TOKEN")||Parse$F.User.current()?.getSessionToken()}`;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="";{const n=e.body?.getReader();if(!n)return void o.error(new Error("Response body reader is null"));const i=new TextDecoder;let a=new ReadableStream({start(e){!function read(){try{e&&n.read().then((({done:t,value:n})=>{if(t)return e?.close(),void o.complete();e?.enqueue(n),read()})).catch((e=>{}))}catch(e){console.log("err2",e)}}()}}).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}async function completionJSON(e,t,n,o=1,i){i=i||{};let a=0;const attemptCompletion=async()=>{const o=`请严格按照以下要求生成JSON数据:\n- 数据结构要求:${t}\n- 返回一个完整的JSON对象,请确保JSON格式完整,不要遗漏任何标点符号\n- 注意返回的JSON格式每个KEY都有""包裹和Value之间都有:\n- 注意""字符串内再出现"符号需要用\\"转义\n`;let r;if(Array.isArray(e))r=e;else if(i.vision&&i.images&&i.images.length>0){r=[{role:"user",content:[...i.images.map((e=>({type:"image_url",image_url:{url:e}}))),{type:"text",text:e+o}]}]}else r=[{role:"user",content:e+o}];i.response_format={type:"json_object"};const s=new FmodeChatCompletion(r,i);let l="";return new Promise(((e,t)=>{const o=s.sendCompletion({isDirect:!0,max_tokens:32768}).subscribe({next:i=>{if("string"==typeof i?.content&&(l=i.content,n&&n(l)),i.complete){try{const t=extractJSON(l);if(!t)throw new Error("未能从响应中提取有效的JSON对象");e(t)}catch(e){console.error(`JSON解析失败 (第${a+1}次尝试):`,e),t(new Error(`生成的响应不符合JSON格式: ${e.message}`))}o.unsubscribe()}},error:e=>{console.error("Completion请求失败:",e),o.unsubscribe(),t(e)}})}))};for(;a<=o;)try{const e=await attemptCompletion();return a>0&&console.log(`JSON生成成功,重试了 ${a} 次`),e}catch(e){if(a++,!(a<=o))throw console.error(`JSON生成失败,已重试 ${o} 次,最终错误:`,e),new Error(`经过 ${o} 次重试后仍无法生成有效JSON: ${e.message}`);console.warn(`第 ${a} 次尝试失败,正在重试... 错误信息:`,e.message),await new Promise((e=>setTimeout(e,1e3)))}}function extractJSON(e){try{return JSON.parse(e.trim())}catch(e){}let t=0,n=-1,o=null;for(let i=0;i<e.length;i++)if("{"===e[i])0===t&&(n=i),t++;else if("}"===e[i]&&(t--,0===t&&-1!==n))try{const t=e.slice(n,i+1);o=JSON.parse(t);break}catch(e){n=-1}return o||(o=tryFixAndParseJSON(e)),o}function tryFixAndParseJSON(e){const t=e.match(/\{[\s\S]*\}/);if(!t)return null;let n=t[0];const o=[e=>e.replace(/,(\s*[}\]])/g,"$1"),e=>e.replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g,'$1"$2":'),e=>e.replace(/'/g,'"'),e=>e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"")];for(const e of o)try{const t=e(n);return JSON.parse(t)}catch(e){}return null}const Parse$E=defaultExport.with("nova"),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$E.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-1.6-cn"==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$E.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$E.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$E.User.current(),o=new Parse$E.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-1.6-cn"});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$E.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$E.User.current()?.id&&i.set("user",Parse$E.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>`,"doubao"==e&&(a=o),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-1.6-cn"}).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||e?.provider,"doubao"==e?.provider&&(e.provider=new FmodeTTSProviderDoubao),e.voiceConfig=this.voiceConfig,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{n.voiceConfig=this.voiceConfig,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$E.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$E.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()}`}}const Parse$D=defaultExport.with("nova");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$D.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}}const Parse$C=defaultExport.with("nova");class AgentStory{constructor(e,t,n){this.Story=Parse$C.Object.extend("Story"),this.Document=Parse$C.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$C.User.current()?.toPointer())}async setAttachment(e){let t=new Parse$C.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 FmodeLoadingController{async create(e){return new FmodeLoadingInstance(e)}}class FmodeLoadingInstance{constructor(e){this._message="加载中...",this._progress=0,this._taskIndex=0,this._taskTotal=1,this.position="bottom",this.container=null,this.progressTimer=null,this._message=e.message??this._message,this._progress=e.progress??this._progress,this._taskIndex=e.taskIndex??this._taskIndex,this._taskTotal=e.taskTotal??this._taskTotal,this.position=e.position??this.position,this.handle=e.handle,this.initDom()}set message(e){this._message=e,this.updateUI()}get message(){return this._message}set progress(e){this._progress=e,this.updateUI()}get progress(){return this._progress}set taskIndex(e){this._taskIndex=e,this.updateUI()}get taskIndex(){return this._taskIndex}set taskTotal(e){this._taskTotal=e,this.updateUI()}get taskTotal(){return this._taskTotal}initDom(){this.container=document.createElement("div"),this.container.className="fmode-loading fmode-loading-"+this.position,this.setPositionStyle(),this.container.innerHTML=`\n <div class="fmode-loader-circle">\n <svg viewBox="0 0 100 100">\n <circle class="bg" cx="50" cy="50" r="45" />\n <circle class="progress" cx="50" cy="50" r="45" />\n </svg>\n <div class="fmode-progress-text">${Math.round(100*this._progress)}%</div>\n </div>\n <div class="fmode-task-info">任务 ${this._taskIndex} / ${this._taskTotal}</div>\n <div class="fmode-message">${this._message}</div>\n `,this.injectCss()}setPositionStyle(){if(!this.container)return;const e={top:{top:"20px",left:"50%",transform:"translateX(-50%)"},bottom:{bottom:"100px",left:"50%",transform:"translateX(-50%)"},middle:{top:"50%",left:"50%",transform:"translate(-50%, -50%)"},topleft:{top:"20px",left:"20px"},topright:{top:"20px",right:"20px"},bottomleft:{bottom:"100px",left:"20px"},bottomright:{bottom:"100px",right:"20px"}}[this.position];Object.assign(this.container.style,{position:"fixed",zIndex:"99999",display:"flex",flexDirection:"row",alignItems:"center",gap:"8px",...e})}injectCss(){if(!document.getElementById("fmode-loading-style")){const e=document.createElement("style");if(e.id="fmode-loading-style",e.innerHTML="\n .fmode-loading {\n position: fixed;\n z-index: 99999;\n display: flex;\n flex-direction: row; /* 横排 */\n align-items: center;\n gap: 12px;\n min-width: 360px; /* 防止消息过长时左边抖动 */\n padding: 8px 12px;\n border-radius: 8px;\n background: rgba(0,0,0,0.6);\n backdrop-filter: blur(6px);\n animation: fadeIn 0.3s ease;\n }\n\n /* 位置适配 */\n .fmode-loading-top { top: 20px; left: 50%; transform: translateX(-50%); }\n .fmode-loading-bottom { bottom: 100px; left: 50%; transform: translateX(-50%); }\n .fmode-loading-middle { top: 50%; left: 50%; transform: translate(-50%, -50%); }\n .fmode-loading-topleft { top: 20px; left: 20px; }\n .fmode-loading-topright { top: 20px; right: 20px; }\n .fmode-loading-bottomleft { bottom: 100px; left: 20px; }\n .fmode-loading-bottomright { bottom: 100px; right: 20px; }\n\n /* 背景发光 */\n .fmode-loader-glow {\n position: absolute;\n width: 120px;\n height: 120px;\n background: radial-gradient(circle, rgba(0,255,255,0.2), transparent);\n border-radius: 50%;\n filter: blur(20px);\n animation: glowPulse 2s infinite;\n }\n\n /* 圆形进度 */\n \n .fmode-loader-circle {\n flex-shrink: 0;\n position: relative;\n width: 48px;\n height: 48px;\n }\n .fmode-loader-circle svg {\n transform: rotate(-90deg);\n width: 100%;\n height: 100%;\n }\n .fmode-loader-circle circle {\n fill: none;\n stroke-width: 6;\n stroke-linecap: round;\n }\n .fmode-loader-circle .bg {\n stroke: rgba(255,255,255,0.1);\n }\n .fmode-loader-circle .progress {\n stroke: url(#fmode-gradient);\n stroke-dasharray: 283;\n stroke-dashoffset: 283;\n transition: stroke-dashoffset 0.3s ease;\n }\n .fmode-progress-text {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 12px;\n font-weight: bold;\n color: #0ff;\n text-shadow: 0 0 6px #0ff;\n }\n\n .fmode-task-info {\n flex-shrink: 0;\n font-size: 14px;\n font-weight: bold;\n color: #fff;\n text-shadow: 0 0 4px rgba(0,0,0,0.5);\n }\n .fmode-message {\n flex: 1;\n font-size: 14px;\n color: #fff;\n text-shadow: 0 0 4px rgba(0,0,0,0.5);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n\n @keyframes glowPulse {\n 0%, 100% { opacity: 0.6; transform: scale(1); }\n 50% { opacity: 1; transform: scale(1.1); }\n }\n @keyframes fadeIn {\n from { opacity: 0; transform: scale(0.9); }\n to { opacity: 1; transform: scale(1); }\n }\n ",document.head.appendChild(e),!document.getElementById("fmode-svg-gradient")){const e=document.createElementNS("http://www.w3.org/2000/svg","svg");e.style.position="absolute",e.style.width="0",e.style.height="0",e.innerHTML='\n <defs>\n <linearGradient id="fmode-gradient" x1="0%" y1="0%" x2="100%" y2="0%">\n <stop offset="0%" stop-color="#0ff" />\n <stop offset="100%" stop-color="#0f0" />\n </linearGradient>\n </defs>\n ',e.id="fmode-svg-gradient",document.body.appendChild(e)}}}async present(){this.container&&!document.body.contains(this.container)&&document.body.appendChild(this.container),this.updateUI(),this.handle?await this.handle():this.startAutoProgress()}dismiss(){this.container&&document.body.contains(this.container)&&document.body.removeChild(this.container),this.progressTimer&&(cancelAnimationFrame(this.progressTimer),this.progressTimer=null)}startAutoProgress(){let e=performance.now();const step=t=>{let n=(t-e)/5e4;var o;n>1&&(n=1),this.progress=(o=n,1-Math.pow(1-o,3)),this.updateUI(),n<1&&(this.progressTimer=requestAnimationFrame(step))};this.progressTimer=requestAnimationFrame(step)}updateUI(){if(!this.container)return;const e=this.container.querySelector(".progress"),t=this.container.querySelector(".fmode-progress-text"),n=this.container.querySelector(".fmode-message"),o=this.container.querySelector(".fmode-task-info");if(e){const t=2*Math.PI*45;e.style.strokeDashoffset=String(t*(1-this._progress))}t&&(t.textContent=`${Math.round(100*this._progress)}%`),n&&(n.textContent=this._message),o&&(o.textContent=`任务 ${this._taskIndex} / ${this._taskTotal}`)}}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}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.disableASR=!1,this.isRecording=!1,this.isUserFinish=!1,this.shouldReconnect=!0,this.reconnectAttempts=0,this.maxReconnectAttempts=3,this.reconnectDelay=1e3,this.recordWavBlob=null,this.recordPcmBlob=null,this.recordDuration=0,this.allRecordedBuffers=[],this.currentRecorder=null,this.btnStatus="UNDEFINED",this.connStatus="",this.resultText="",this.resultTextTemp="",this.durationStr="00:00",this.duration=0,this.recordType="pcm",this.encodingType="raw",this.APPID="50f4a46c",this.API_SECRET="NzFlNmFhZDJjMDNkZGM3NzI0Mzg2OGNm",this.API_KEY="106ddc40dfd4b9ca6d7b47c70fada749",this.requestPermission()}toggleRecord(){console.log("toggleRecord",this.btnStatus),"UNDEFINED"===this.btnStatus||"CLOSED"===this.btnStatus?this.startTalk():"CONNECTING"!==this.btnStatus&&"OPEN"!==this.btnStatus||this.finishTalk()}async startTalk(e){console.log("startTalk called"),this.resetState(),this.onBeforeStartTalk&&this.onBeforeStartTalk(),e?.preventDefault();try{await this.openWithPriviledge(),await this.startIndependentRecording(),this.isRecording=!0,this.shouldReconnect=!0,this.reconnectAttempts=0,setTimeout((()=>{this.connectWebSocket()}),100),this.startCountdown(),this.onAfterStartTalk&&this.onAfterStartTalk()}catch(e){console.error("Failed to start talk:",e),this.resetState()}}async finishTalk(){console.log("finishTalk called"),this.isUserFinish=!0,this.shouldReconnect=!1,this.onBeforeFinishTalk&&this.onBeforeFinishTalk();try{this.closeWebSocket(),await this.stopIndependentRecording(),this.isRecording=!1,this.clearTimers(),this.changeBtnStatus("CLOSED"),setTimeout((()=>{this.isUserFinish&&(this.onAfterFinishTalk&&this.onAfterFinishTalk(),this.isUserFinish=!1)}),500)}catch(e){console.error("Error finishing talk:",e)}}cancelTalk(){console.log("cancelTalk called"),this.onBeforeCancelTalk&&this.onBeforeCancelTalk(),this.isUserFinish=!1,this.shouldReconnect=!1,this.isRecording=!1,this.closeWebSocket(),this.cancelIndependentRecording(),this.resetState(),this.onAfterCancelTalk&&this.onAfterCancelTalk()}async startIndependentRecording(){return console.log("Starting independent recording"),this.allRecordedBuffers=[],this.createIndependentRecorder(),new Promise(((e,t)=>{this.currentRecorder.open((()=>{console.log("Independent recorder opened"),document.querySelector(".record-wave")&&Recorder.WaveView&&(this.waveClient=Recorder.WaveView({elem:".record-wave"})),this.currentRecorder.start(),this.onAfterRecordStart&&this.onAfterRecordStart(),e()}),((e,n)=>{console.error("Failed to open independent recorder:",e),t(new Error(e))}))}))}async stopIndependentRecording(){if(console.log("Stopping independent recording"),this.currentRecorder)return new Promise((e=>{this.currentRecorder.stop((async(t,n)=>{console.log("Independent recording stopped successfully",t,n),this.recordPcmBlob=t,this.recordWavBlob=await this.pcmBlobToWavBlob(t,44100),this.cleanupIndependentRecorder(),e()}),(t=>{console.error("独立录音停止失败:"+t),this.cleanupIndependentRecorder(),e()}))}));console.log("No independent recorder to stop")}cancelIndependentRecording(){if(console.log("Cancelling independent recording"),this.currentRecorder)try{this.currentRecorder.close()}catch(e){console.error("Error closing independent recorder:",e)}this.cleanupIndependentRecorder(),this.recordPcmBlob=null,this.recordWavBlob=null}createIndependentRecorder(){this.currentRecorder&&this.cleanupIndependentRecorder(),this.currentRecorder=Recorder({type:this.recordType,sampleRate:44100,bitRate:16,onProcess:(e,t,n,o,i,a)=>{if(!this.isRecording)return;this.allRecordedBuffers=e;let r=e.length&&e[e.length-1];r&&(r=resampleBuffer(r,44100,16e3),this.sendAudioToWebSocket(r),this.waveClient?.input(e[e.length-1],t,o))}})}cleanupIndependentRecorder(){if(this.currentRecorder){try{this.currentRecorder.close()}catch(e){console.error("Error cleaning up independent recorder:",e)}this.currentRecorder=null}}sendAudioToWebSocket(e){if(this.iatWS&&this.iatWS.readyState===WebSocket.OPEN&&!this.disableASR)try{this.iatWS.send(JSON.stringify({data:{status:1,format:"audio/L16;rate=16000",encoding:this.encodingType,audio:convertFrameBufferToBase64(e)}}))}catch(e){console.error("Error sending audio data to WebSocket:",e)}}connectWebSocket(){if(console.log("connectWebSocket called, shouldReconnect:",this.shouldReconnect),!this.shouldReconnect||!this.isRecording)return void console.log("Not connecting WebSocket - shouldReconnect:",this.shouldReconnect,"isRecording:",this.isRecording);this.closeWebSocket();const e=this.getWebSocketUrl();console.log("Connecting to:",e);try{if(!("WebSocket"in window))return console.error("浏览器不支持WebSocket"),void alert("浏览器不支持WebSocket");this.iatWS=new WebSocket(e),this.changeBtnStatus("CONNECTING"),this.iatWS.onopen=e=>{console.log("WebSocket connected for ASR"),this.reconnectAttempts=0,this.changeBtnStatus("OPEN");const t={common:{app_id:this.APPID},business:{language:"zh_cn",domain:"iat",accent:"mandarin",vad_eos:1e4,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("WebSocket error:",e),this.handleWebSocketError()},this.iatWS.onclose=e=>{console.log("WebSocket closed:",e.code,e.reason),this.handleWebSocketClose(e)}}catch(e){console.error("Failed to create WebSocket:",e),this.handleWebSocketError()}}handleWebSocketClose(e){if(console.log("handleWebSocketClose",{code:e.code,reason:e.reason,shouldReconnect:this.shouldReconnect,isRecording:this.isRecording,isUserFinish:this.isUserFinish}),!this.isUserFinish&&this.shouldReconnect&&this.isRecording){try{this.iatWS&&this.iatWS.readyState===WebSocket.OPEN&&this.iatWS.send(JSON.stringify({data:{status:2,format:"audio/L16;rate=16000",encoding:this.encodingType,audio:""}}))}catch(e){console.error("Error sending end frame on close:",e)}1e3===e.code||1006===e.code||1011===e.code?this.attemptReconnect():(console.error("WebSocket closed with error code:",e.code),this.handleWebSocketError())}}handleWebSocketError(){this.shouldReconnect&&this.isRecording&&this.attemptReconnect()}attemptReconnect(){this.reconnectAttempts>=this.maxReconnectAttempts?console.error("Max reconnect attempts reached"):(this.reconnectAttempts++,console.log(`Attempting WebSocket reconnect ${this.reconnectAttempts}/${this.maxReconnectAttempts}`),setTimeout((()=>{this.shouldReconnect&&this.isRecording&&!this.isUserFinish&&this.connectWebSocket()}),this.reconnectDelay*this.reconnectAttempts))}closeWebSocket(){if(this.iatWS){try{this.iatWS.readyState===WebSocket.OPEN&&this.iatWS.send(JSON.stringify({data:{status:2,format:"audio/L16;rate=16000",encoding:this.encodingType,audio:""}})),this.iatWS.readyState!==WebSocket.OPEN&&this.iatWS.readyState!==WebSocket.CONNECTING||this.iatWS.close(1e3,"User initiated close")}catch(e){console.error("Error closing WebSocket:",e)}this.iatWS=null}}resetState(){this.resultText="",this.resultTextTemp="",this.durationStr="00:00",this.duration=0,this.recordDuration=0,this.allRecordedBuffers=[],this.clearTimers()}clearTimers(){this.countdownInterval&&(clearInterval(this.countdownInterval),this.countdownInterval=null),this.durationInterval&&(clearInterval(this.durationInterval),this.durationInterval=null)}changeBtnStatus(e){switch(this.btnStatus=e,e){case"CONNECTING":this.connStatus="建立连接中";break;case"OPEN":this.connStatus=`录音中(${this.durationStr})`;break;case"CLOSING":this.connStatus="关闭连接中";break;case"CLOSED":this.connStatus="开始录音"}}startCountdown(){this.clearTimers(),this.recordDuration=0,this.duration=0,this.now=new Date,this.durationInterval=setInterval((()=>{this.isRecording&&(this.recordDuration+=100)}),100),this.countdownInterval=setInterval((()=>{this.isRecording&&this.countTimer()}),1e3)}countTimer(){this.duration++;let e=String(Math.floor(this.duration/60)).padStart(2,"0")+":"+String(this.duration%60).padStart(2,"0");this.durationStr=e,this.connStatus=`录音中(${this.durationStr})`,this.onDurationStrChange&&this.onDurationStrChange(e)}renderResult(e){try{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.onInputChange&&this.onInputChange(this.getUserInput())}0===t.code&&2===t.data.status&&(console.log("ASR session completed, will reconnect if still recording"),this.iatWS&&this.iatWS.readyState===WebSocket.OPEN&&this.iatWS.close()),0!==t.code&&(console.error("ASR error:",t),this.iatWS&&this.iatWS.readyState===WebSocket.OPEN&&this.iatWS.close())}catch(e){console.error("Error parsing result:",e)}}getUserInput(){return""+(this.resultTextTemp||this.resultText)}async openWithPriviledge(){return await this.requestPermission(),Recorder.IsOpen(),!0}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()}playRecord(){this.recordPcmBlob&&this.playPCM(this.recordPcmBlob,44100)}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)}isCapacitor(){return!!this.platform?.is&&(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()}}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"})}async playBuffers(){let e=await this.BuffersToBlob(this.allRecordedBuffers);this.playPCM(e,44100)}BuffersToBlob(e){let t=[];return e.forEach((e=>{e.forEach((e=>{t.push(e)}))})),new Blob([t],{type:"audio/pcm"})}}function wxdebug$1(...e){console.log(e)}function createMessageAPI(e,t){const n="message/send",baseMerge=e=>({touser:e?.touser,toparty:e?.toparty,totag:e?.totag,agentid:e?.agentid,safe:e?.safe??0,enable_id_trans:e?.enable_id_trans??0,enable_duplicate_check:e?.enable_duplicate_check??0,duplicate_check_interval:e?.duplicate_check_interval??1800});return{async sendText(o){const i={...baseMerge(o),msgtype:"text",text:{content:o.content}};return wxdebug$1("sendText:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},async sendImage(o){const i={...baseMerge(o),msgtype:"image",image:{media_id:o.media_id}};return wxdebug$1("sendImage:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},async sendVoice(o){const i={...baseMerge(o),msgtype:"voice",voice:{media_id:o.media_id}};return wxdebug$1("sendVoice:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},async sendVideo(o){const i={...baseMerge(o),msgtype:"video",video:{media_id:o.media_id,title:o.title,description:o.description}};return wxdebug$1("sendVideo:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},async sendFile(o){const i={...baseMerge(o),msgtype:"file",file:{media_id:o.media_id}};return wxdebug$1("sendFile:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},async sendTextCard(o){const i={...baseMerge(o),msgtype:"textcard",textcard:{title:o.title,description:o.description,url:o.url,btntxt:o.btntxt||"详情"}};return wxdebug$1("sendTextCard:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},async sendNews(o){const i={...baseMerge(o),msgtype:"news",news:{articles:o.articles}};return wxdebug$1("sendNews:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},async sendMarkdown(o){const i={...baseMerge(o),msgtype:"markdown",markdown:{content:o.content}};return wxdebug$1("sendMarkdown:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},send:async o=>(wxdebug$1("send(custom):"+JSON.stringify(o)),t({company:e,path:n,method:"POST",body:o}))}}class WxworkCorp{constructor(e){this.config={},this.ticket={get:async(e="agent_config")=>{let t={};e&&(t.type=e);let n=await WwRequest({company:this.company,path:"ticket/get",method:"GET",queryParams:t});return n?.ticket}},this.service={async corpIdToOpenCorpId(e){return await WwRequest({company:this.company,path:"auth/getuserinfo",method:"GET",body:{corpid:e}})}},this.auth={getuserinfo:async e=>{wxdebug$1("getuserinfo request");let t=await WwRequest({company:this.company,path:"auth/getuserinfo",method:"GET",queryParams:{code:e}});if(t?.user_ticket){let e=await WwRequest({company:this.company,path:"auth/getuserdetail",method:"POST",body:{user_ticket:t?.user_ticket}});e?.qr_code&&Object.keys(e).forEach((n=>{t[n]=e[n]})),console.log("企业用户详情:",t)}return t?.openid,t||null}},this.user={getUserId:async e=>{let t=await WwRequest({company:this.company,path:"user/getuserid",method:"POST",body:{mobile:e}});return console.log(t),t?.userid||null},get:async e=>{let t=await WwRequest({company:this.company,path:"user/get",method:"GET",queryParams:{id:e}});return console.log(t),t?.department||null},listId:async(e,t,n)=>{let o="user/list_id",i="POST",a={limit:100};(e=e||null)&&(o="user/simplelist",i="GET",a=null);let r=await WwRequest({company:this.company,method:i,queryParams:{department_id:e},path:o,body:a});return console.log(r),e?r?.userlist||[]:r?.dept_user||[]},list:async e=>{let t=e?.id,n=await WwRequest({company:this.company,path:"department/list",method:"GET",queryParams:{id:t}});return console.log(n),n}},this.department={get:async e=>{let t=await WwRequest({company:this.company,path:"department/get",method:"GET",queryParams:{id:e}});return console.log(t),t?.department||null},listId:async e=>{let t=e?.id,n=await WwRequest({company:this.company,method:"GET",queryParams:{id:t},path:"department/simplelist"});return console.log(n),n?.department_id||[]},list:async e=>{let t=e?.id,n=await WwRequest({company:this.company,path:"department/list",method:"GET",queryParams:{id:t}});return console.log(n),n}},this.externalContact={get:async e=>await WwRequest({method:"GET",company:this.company,path:"externalcontact/get",queryParams:{external_userid:e}}),groupChat:{addJoinWay:async e=>await WwRequest({method:"POST",company:this.company,path:"externalcontact/groupchat/add_join_way",body:e}),getJoinWay:async e=>{if(!e)return null;return await WwRequest({method:"POST",company:this.company,path:"externalcontact/groupchat/get_join_way",body:{config_id:e}})},get:async e=>await WwRequest({method:"POST",company:this.company,path:"externalcontact/groupchat/get",body:{chat_id:e,need_name:1}}),list:async e=>{let t={limit:e?.limit||20};e?.userid_list&&(t.owner_filter={userid_list:[e?.userid_list]});let n=await WwRequest({company:this.company,path:"externalcontact/groupchat/list",body:t});return console.log(n),n}}},this.appchat={sendText:async(e,t,n=0)=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:{chatid:e,msgtype:"text",text:{content:t},safe:n}}),sendImage:async(e,t,n=0)=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:{chatid:e,msgtype:"image",image:{media_id:t},safe:n}}),sendVideo:async(e,t,n,o,i=0)=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:{chatid:e,msgtype:"video",video:{media_id:t,title:n,description:o},safe:i}}),sendFile:async(e,t,n=0)=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:{chatid:e,msgtype:"file",file:{media_id:t},safe:n}}),sendTextCard:async(e,t,n,o,i,a=0)=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:{chatid:e,msgtype:"textcard",textcard:{title:t,description:n,url:o,btntxt:i||"详情"},safe:a}}),sendNews:async(e,t,n=0)=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:{chatid:e,msgtype:"news",news:{articles:t},safe:n}}),sendMarkdown:async(e,t)=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:{chatid:e,msgtype:"markdown",markdown:{content:t}}}),send:async e=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:e})},this.meeting={create:async e=>await WwRequest({company:this.company,path:"meeting/create",method:"POST",body:e}),list:async e=>{let t={limit:e?.limit||20};return e?.userid&&(t.userid=e.userid),e?.cursor&&(t.cursor=e.cursor),e?.begin_time&&(t.begin_time=e.begin_time),e?.end_time&&(t.end_time=e.end_time),await WwRequest({company:this.company,path:"meeting/list",method:"POST",body:t})},get:async e=>await WwRequest({company:this.company,path:"meeting/get",method:"POST",body:{meetingid:e}})},this.company=e,this.message=createMessageAPI(this.company,WwRequest)}}async function WwRequest(e){let t,n,o=e?.company,i=e?.path,a=e?.method||"POST",r="https://server.fmode.cn/api/wework/func";e?.body&&Object.keys(e?.body)?.length&&(t=e?.body),e?.queryParams&&(n=e?.queryParams),t||(t={});let s=JSON.stringify({company:o,path:i,body:t,queryParams:n,method:a});console.log(s);let l={method:"POST",headers:{"Content-Type":"application/json"},body:s};console.log(l,r);try{let e=await fetch(r,l);return await e.json()}catch(e){return alert("wxreqErr:"+JSON.stringify(e)),null}}const createLoginContainer=()=>{const e=document.getElementById("ww_login");e&&e.remove();const t=document.createElement("div");t.id="ww_login",t.style.cssText="\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: rgba(255, 255, 255, 0.9);\n z-index: 99999; /* 确保在最顶层 */\n ",document.body.appendChild(t)},removeLoginContainer=()=>{try{const e=document.getElementById("ww_login");e&&e.remove()}catch(e){}},Parse$B=defaultExport.with("nova");class WxworkSDK{constructor(e){this.companyMap={E4KpGvTEto:{corpResId:"vsVIWbd1i9"},uRiDGwEYLi:{corpResId:"JxfFXBr0ly"},cDL6R1hgSi:{corpResId:"SpL6gyD1Gu"}},this.suiteMap={crm:{suiteId:"dk2559ba758f33d8f5"}},this.ww=ww,this.groupChat={createGroupChat:async e=>{try{return wxdebug$1("createGroupChat"+JSON.stringify(e)),await this.registerCorpWithSuite()?new Promise(((t,n)=>{e.success=e=>{wxdebug$1(JSON.stringify(e)),t(e)},e.fail=e=>{wxdebug$1(JSON.stringify(e)),n(e)},ww.createCorpGroupChat(e)})):null}catch(e){wxdebug$1(JSON.stringify(e))}},addUserInfoGroup:async e=>{wxdebug$1("addUserInfoGroup"+JSON.stringify(e));try{let t=await this.registerCorpWithSuite();return wxdebug$1("isRegister"+t),t?(wxdebug$1(JSON.stringify(e)),new Promise(((t,n)=>{e.success=e=>{wxdebug$1(JSON.stringify(e)),t(e)},e.fail=e=>{wxdebug$1(JSON.stringify(e)),n(e)},ww.updateCorpGroupChat(e)}))):null}catch(e){wxdebug$1(JSON.stringify(e))}}},this.cid=e?.cid,this.appId=e?.appId,this.wecorp=new WxworkCorp(this.cid)}async syncGroupChat(e){let t=new Parse$B.Query("GroupChat");t.equalTo("chat_id",e?.chat_id);let n=await t.first();n?.id||(n=new Parse$B.Object("GroupChat"));let o=!1;if(!n?.get("joinUrl")){let t=(await this.wecorp.externalContact.groupChat.addJoinWay({scene:1,chat_id_list:[e.chat_id]}))?.config_id,i=(await this.wecorp.externalContact.groupChat.getJoinWay(t))?.join_way;n.set("joinUrl",i),o=!0}if(!n?.get("joinQrcode")){let t=(await this.wecorp.externalContact.groupChat.addJoinWay({scene:2,chat_id_list:[e.chat_id]}))?.config_id,i=(await this.wecorp.externalContact.groupChat.getJoinWay(t))?.join_way;n.set("joinQrcode",i),o=!0}let i={chat_id:e.chat_id,name:e.name,owner:e.owner,notice:e.notice};return n.get("chat_id")!=e.chat_id&&(o=!0),n.get("name")!=e.name&&(o=!0),n.get("owner")!=e.owner&&(o=!0),n.get("notice")!=e.notice&&(o=!0),n.get("member_version")!=e.member_version&&(o=!0,i.member_list=e.member_list,i.member_version=e.member_version),n.set(i),this.cid&&n.set("company",{__type:"Pointer",className:"Company",objectId:this.cid}),o&&(n=await n.save()),n}async syncContact(e){const t=e.external_contact||e,n=t.external_userid;let o=new Parse$B.Query("ContactInfo");o.equalTo("external_userid",n);const i=new Parse$B.Object("Company");i.id=this.cid,o.equalTo("company",i);let a=await o.first();a?.id||(a=new Parse$B.Object("ContactInfo"),i?.id&&a.set("company",i.toPointer()));const r=t.name||"",s=t.mobile||"",l={...t,follow_user:e.follow_user||t.follow_user||[]};let c=!1;a.get("external_userid")!=n&&(c=!0),a.get("name")!=r&&r&&(c=!0),a.get("mobile")!=s&&s&&(c=!0);const d=a.get("data");return JSON.stringify(d)!==JSON.stringify(l)&&(c=!0),a.set("external_userid",n),a.set("name",r),a.set("mobile",s),a.set("data",l),wxdebug$1("syncContact",a.toJSON()),c&&(a=await a.save()),a}async getCurrentChatObject(){const e=await this.getCurrentChat();if(!e)return{currentChat:null};let t,n;try{if("chatId"===e.type&&e.group)t=await this.syncGroupChat(e.group);else if("userId"===e.type&&e.id){const t=await this.wecorp.externalContact.get(e.id);n=await this.syncContact(t)}}catch(e){console.error("getCurrentChatObject error:",e)}return{GroupChat:t,Contact:n,currentChat:e}}async syncUserInfo(e){let t=null;1==e.gender&&(t="男"),2==e.gender&&(t="女");let n=await this.getContactOrProfile(e);console.log("thisUser",n),console.log("userInfo",e),"ContactInfo"==n.className&&n.set({data:{openid:e.openid,userid:e.userid,external_userid:e.external_userid,type:e.type&&String(e.type)||null,name:e.name,avatar:e.avatar,gender:t,qr_code:e.qr_code,mobile:e.mobile,email:e.email,biz_mail:e.biz_mail,address:e.address,position:e.position,corp_name:e.corp_name},type:"wecom-agency",company:{__type:"Pointer",className:"Company",objectId:this.cid}}),"Profile"==n.className&&(n.set({openid:e.openid,userid:e.userid,external_userid:e.external_userid,type:e.type&&String(e.type)||null,name:e.name,avatar:e.avatar,gender:t,qr_code:e.qr_code,mobile:e.mobile,email:e.email,biz_mail:e.biz_mail,address:e.address,position:e.position,corp_name:e.corp_name,company:{__type:"Pointer",className:"Company",objectId:this.cid}}),n.set("data",e));try{if(n?.id&&!n.get("user")?.id){let e=Parse$B.User.current();e?.id&&n.set("user",e?.toPointer())}n=await n.save()}catch(e){wxdebug$1(e)}return n}async getUserinfo(e){let t,n;wxdebug$1("getUserinfo");let o=localStorage.getItem(`${this.cid}/USERINFO`);if(!e){t=JSON.parse(o),t.cid=this.cid,wxdebug$1("getContactOrProfile");try{n=await this.getContactOrProfile(t)}catch(e){}if(wxdebug$1("getUserinfo:"+o),t&&n)return t}if(!(e=new URL(location.href).searchParams.get("code")||e))return null;let i=await this.wecorp.auth.getuserinfo(e);if(wxdebug$1("result"+JSON.stringify(i)),i?.errcode)return console.error(i?.errmsg),null;let a=i?.external_userid;if(a){let e=await this.wecorp.externalContact.get(a);e?.external_contact&&Object.keys(e?.external_contact).forEach((t=>{i[t]=e?.external_contact[t]}))}return i.cid=this.cid,t=i,n=await this.getContactOrProfile(t),n?.get("mobile")&&(t.mobile=n?.get("mobile")),o=JSON.stringify(i),localStorage.setItem(`${this.cid}/USERINFO`,o),t}async getCurrentUser(){const e=await this.getUserinfo();if(!e)return null;return await this.getContactOrProfile(e)}async getContactOrProfile(e){let t;(e.openid||e.external_userid)&&(t="ContactInfo"),e.userid&&(t="Profile");let n=[];"Profile"==t&&(e.openid&&n.push({openid:{$regex:e.openid}}),e.userid&&n.push({userid:{$regex:e.userid}}),e.mobile&&n.push({mobile:{$regex:e.mobile}}),e.email&&n.push({email:{$regex:e.email}}),e.external_userid&&n.push({external_userid:{$regex:e.external_userid}})),"ContactInfo"==t&&(e.openid&&n.push({"data.openid":{$regex:e.openid}}),e.userid&&n.push({"data.userid":{$regex:e.userid}}),e.mobile&&n.push({"data.mobile":{$regex:e.mobile}}),e.email&&n.push({"data.email":{$regex:e.email}}),e.external_userid&&n.push({"data.external_userid":{$regex:e.external_userid}}));let o,i=Parse$B.Query.fromJSON(t,{where:{$or:n}});i.equalTo("company",this.cid),i.equalTo("userid",e.userid);try{o=await i.first()}catch(e){console.error(e)}o?.id||(o=new Parse$B.Object(t));let a=Parse$B.User.current();return a?.id&&(o?.get("user")?.id||o.set("user",a.toPointer())),o}async loginPC(){let e=await this.getCorpByCid(this.cid);console.log(this.cid,e);const t=e?.corpId,n=e?.agentId,o=new URL("https://app.fmode.cn"+location.pathname+location?.search);o.searchParams.delete("code"),o.searchParams.delete("state");const i=o.href,a=ww.WWLoginType.corpApp,r=ww.WWLoginRedirectType.callback;console.log("loginPC1");return document.getElementById("ww_login")||createLoginContainer(),new Promise(((e,o)=>{console.log("loginPC2");const s=this.ww.createWWLoginPanel({el:"#ww_login",params:{login_type:a,appid:t,agentid:n,redirect_uri:i,state:"loginState",redirect_type:r},onCheckWeComLogin({isWeComLogin:e}){console.log(e)},onLoginSuccess({code:t}){console.log({code:t}),removeLoginContainer(),e(t)},onLoginFail(e){console.error("lpc",e),removeLoginContainer(),o(e)}});console.log(s,s.el)}))}async oauth(e="snsapi_base",t=!1){t&&localStorage.removeItem(`${this.cid}/USERINFO`),wxdebug$1("oauth");let n=await this.getCorpByCid(this.cid);console.log(this.cid,n);let o=n?.corpId,i=n?.agentId,a=new URL("https://app.fmode.cn"+location.pathname+location?.search);a.searchParams.delete("code"),a.searchParams.delete("state");let r=encodeURIComponent(a.href),s=`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${o}&redirect_uri=${r}&response_type=code&scope=${e}&state=STATE&agentid=${i}#wechat_redirect`;if("h5"==this.platform()){if(location.host?.startsWith("localhost"))return"";s=`https://login.work.weixin.qq.com/wwlogin/sso/login?login_type=CorpApp&appid=${o}&agentid=${i}&redirect_uri=${r}&state=WWLogin`,console.log("createWWLoginPanel")}return location.href=s,null}async getCorpByCid(e){if(console.log("cid",e),this.corpId)return this.corpId;let t=new Parse$B.Query("CloudResource"),n=(await t.get(this.companyMap[e]?.corpResId)).get("config");return console.log("config",n),n}async registerCorpWithSuite(e,t,n){if("wxwork"!=this.platform())return!1;if(!n?.length&&this.registerUrl==location.href)return!0;n=n||jsApiList;try{e=e||this.cid,t=t||this.appId;let o=await this.getCorpByCid(e);console.log(o);let i=o?.corpId,a=this.suiteMap[t]?.suiteId;console.log(i,a);let r=new Date,s=new Promise((e=>{ww.register({corpId:o.corpId,suiteId:a,agentId:o.agentId,jsApiList:n,getAgentConfigSignature:async()=>{let e=await this.wecorp.ticket.get();return ww.getSignature({ticket:e,nonceStr:"666",timestamp:(r.getTime()/1e3).toFixed(0),url:location.href})},onAgentConfigSuccess:()=>{this.registerUrl=location.href,e(!0)},onAgentConfigFail:t=>{e(!1)},onConfigFail:t=>{e(!1)}})}));return await s}catch(e){return wxdebug$1(JSON.stringify(e)),!1}}getUA(){return this.ua=navigator.userAgent.toLowerCase(),this.ua}platform(){return this.ua=navigator.userAgent.toLowerCase(),this.ua.indexOf("wxwork")>-1?"wxwork":this.ua.indexOf("wechat")>-1?"wechat":"h5"}async getContext(){await this.registerCorpWithSuite();try{let e=await ww.getContext();return e?.entry&&(this.entry=e?.entry),e}catch(e){this.entryError="请先注册JSAPI"+e.errCode+e.errMsg,console.error(e)}return null}async getCurrentChat(){let e;if(!await this.registerCorpWithSuite())return null;try{e=await ww.getContext()}catch(e){console.error(e)}let t,n,o,i,a=e?.entry;try{return"group_chat_tools"==a&&(t="chatId",n=(await ww.getCurExternalChat())?.chatId,i=await this.wecorp.externalContact.groupChat.get(n)),"contact_profile"!=a&&"single_chat_tools"!=a||(t="userId",n=(await ww.getCurExternalContact())?.userId,o=await this.wecorp.externalContact.get(n)),this.currentChat={type:t,id:n,group:i?.group_chat,contact:o?.external_contact,follow_user:o?.follow_user},this.currentChat}catch(e){return wxdebug$1(JSON.stringify(e)),null}}version(){return wxdebug$1(ww.SDK_VERSION),ww.SDK_VERSION}register(){ww.register({corpId:"ww7ca4776b2a70000",jsApiList:["getExternalContact"],getConfigSignature:this.getConfigSignature})}async getConfigSignature(e){return{timestamp:"",nonceStr:"",signature:""}}config(){}async selectEnterpriseContact(){let e=await ww.selectEnterpriseContact({fromDepartmentId:-1,mode:"multi",type:["department","user"]});console.log(e),wxdebug$1(e)}}const jsApiList=["getContext","getCurExternalChat","getCurExternalContact","createCorpGroupChat","updateCorpGroupChat","openExistedChatWithMsg","openEnterpriseChat","sendChatMessage","updateEnterpriseChat","checkJsApi","onMenuShareAppMessage","onMenuShareWechat","onMenuShareTimeline","shareAppMessage","shareWechatMessage","startRecord","stopRecord","onVoiceRecordEnd","playVoice","pauseVoice","stopVoice","uploadVoice","downloadVoice","chooseImage","previewImage","uploadImage","downloadImage","getNetworkType","openLocation","getLocation","hideOptionMenu","showOptionMenu","hideMenuItems","showMenuItems","hideAllNonBaseMenuItem","showAllNonBaseMenuItem","closeWindow","scanQRCode","previewFile","selectEnterpriseContact","onHistoryBack","openDefaultBrowser"],Parse$A=defaultExport.with("nova");async function checkWeworkLogin(e){console.log("WxworkAuthGuard");let t=e.paramMap.get("cid")||e.queryParamMap.get("cid")||localStorage.getItem("company");t&&localStorage.setItem("company",t);let n,o=e.paramMap.get("appId")||"crm",i=new WxworkAuth({cid:t,appId:o});console.log("init wxwork");try{if(n=await i.getUserInfo(),console.log("guard userInfo"+JSON.stringify(n)),n)return await i.syncUserInfo(n),await i.autoLogin(n),!0}catch(e){console.error(e),console.log("guierr"+JSON.stringify(e))}let a=new URL(location?.href).searchParams.get("code");if(console.log("WxworkAuthGuard"+t+a),!a){let e=navigator.userAgent.toLowerCase();if(console.log("ua",e),-1!==e.indexOf("micromessenger")){let e="snsapi_base";"wechat"==i.platform()&&(e="snsapi_base"),"wxwork"==i.platform()&&(e="snsapi_privateinfo");let t=await i.oauth(e);return t&&(a=t),!1}a||(a=await i.loginPC())}try{n=await i.getUserInfo(a)}catch(e){console.log("codeinfoerr:"+JSON.stringify(e))}return console.log("before sync"+n?.mobile),await i.syncUserInfo(n),await i.autoLogin(n),!0}class WxworkAuth{constructor(e){this.cid=e.cid||localStorage.getItem("company"),this.wxwork=new WxworkSDK({cid:e.cid,appId:e.appId||"crm"}),this.platform=this.wxwork.platform}async currentProfile(){let e=await this.getUserInfo(),t=await this.wxwork.getContactOrProfile(e);return"Profile"==t?.className?t:null}async currentContact(){let e=await this.getUserInfo(),t=await this.wxwork.getContactOrProfile(e);return"ContactInfo"==t?.className?t:null}async getUserInfo(e){try{return await this.wxwork.getUserinfo(e)}catch(e){throw console.error("WxworkAuth.getUserInfo error:",e),e}}async syncUserInfo(e){try{if(e||(e=await this.getUserInfo()),!e)throw new Error("无法获取用户信息");return await this.wxwork.syncUserInfo(e)}catch(e){throw console.error("WxworkAuth.syncUserInfo error:",e),e}}async autoLogin(e){try{e||(e=await this.getUserInfo());const t=Parse$A.User.current();if(t?.id){console.log("用户已登录:",t.get("username"));const n=await this.wxwork.getContactOrProfile(e);return n?.id&&!n.get("user")?.id&&(n.set("user",t.toPointer()),await n.save(),console.log("已同步 user 指针到 Profile/UserSocial")),t}if(e||(e=await this.getUserInfo()),!e)throw new Error("无法获取用户信息");const n=e.userid||e.external_userid||e.openid;if(!n||n.length<6)return console.warn("用户名太短,无法自动登录:",n),null;const o=n.slice(-6);try{let t;t=await Parse$A.User.logIn(n,o);const i=await this.wxwork.getContactOrProfile(e);return i?.id&&!i.get("user")?.id&&(i.set("user",t.toPointer()),await i.save(),console.log("已同步 user 指针到 Profile/UserSocial")),t}catch(t){if(console.log("loginError",t),!("string"==typeof t&&t.indexOf("Invalid")>-1||101===t?.code))throw console.error("自动登录失败:",t),t;{console.log("用户不存在,创建新用户:",n);const t=new Parse$A.User;t.set("username",n),t.set("password",o),e.mobile&&t.set("mobile",e.mobile),e.email&&t.set("email",e.email);try{const o=await t.signUp();console.log("自动注册成功:",n);const i=await this.wxwork.getContactOrProfile(e);return i?.id&&(i.set("user",o.toPointer()),await i.save(),console.log("已同步 user 指针到 Profile/UserSocial")),o}catch(e){throw console.error("自动注册失败:",e),e}}}}catch(e){throw console.error("WxworkAuth.autoLogin error:",e),e}}async authenticateAndLogin(e){try{const t=await this.getUserInfo(e),n=await this.autoLogin(t);return{userInfo:t,profile:await this.syncUserInfo(t),user:n}}catch(e){throw console.error("WxworkAuth.authenticateAndLogin error:",e),e}}async oauth(e="snsapi_base",t=!1){try{return await this.wxwork.oauth(e,t)}catch(e){throw console.error("WxworkAuth.oauth error:",e),e}}async loginPC(){try{return await this.wxwork.loginPC()}catch(e){throw console.error("WxworkAuth.loginPC error:",e),e}}getSDK(){return this.wxwork}}let PARSE_APP_ID=localStorage.getItem("PARSE_APP_ID")||"nova";const Parse$z=defaultExport.with(PARSE_APP_ID);class DingTalkAuth{constructor(e){this.config={clientId:e.clientId,corpId:e.corpId,redirectUri:e.redirectUri,agentId:e.agentId,apiOauthWeb:e.apiOauthWeb||"https://server.fmode.cn/api/dingtalk/oauth2/login",apiOauthDingtalk:e.apiOauthWeb||"https://server.fmode.cn/api/dingtalk/oauth2/dingtalk"},this.loadDingTalkSDK()}loadDingTalkSDK(){return new Promise(((e,t)=>{if(window.DTFrameLogin)return void e();const n=document.createElement("script");n.src="https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js",n.onload=()=>e(),n.onerror=()=>t(new Error("Failed to load DingTalk SDK")),document.head.appendChild(n)}))}isInDingTalkApp(){const e=navigator.userAgent.toLowerCase();return e.includes("dingtalk")||e.includes("dingtalk")}async getDingTalkAuthCode(){try{if(console.log("🔐 开始钉钉内免登录流程"),!this.isInDingTalkApp())return{success:!1,error:"不在钉钉环境内,请使用网页登录",loginType:"dingtalk"};await this.loadDingTalkSDK();const e=await this.getAuthCode();if(e){console.log("✅ 钉钉授权码获取成功:",e);return await this.completeDingTalkLogin(e,"dingtalk")}return{success:!1,error:"获取钉钉授权码失败",loginType:"dingtalk"}}catch(e){return console.error("❌ 钉钉免登录失败:",e),{success:!1,error:e.message||"钉钉免登录失败",loginType:"dingtalk"}}}async getAuthCode(){return new Promise(((e,t)=>{if(this.isInDingTalkApp())try{dd.requestAuthCode({corpId:this.config.corpId,clientId:this.config.clientId,onSuccess:t=>{console.log("📱 钉钉授权码获取成功:",t),e(t.code)},onFail:e=>{console.error("❌ 钉钉授权码获取失败:",e),t(new Error(e.errorMessage||"获取授权码失败"))}})}catch(n){if(console.error("❌ 钉钉JSAPI调用失败:",n),dd&&dd.ready)dd.ready((()=>{dd.getAuthCode({corpId:this.config.corpId,onSuccess:t=>{console.log("📱 钉钉授权码获取成功 (兼容模式):",t),e(t.code)},onFail:e=>{console.error("❌ 钉钉授权码获取失败 (兼容模式):",e),t(new Error(e.errorMessage||"获取授权码失败"))}})})),dd.error((e=>{console.error("❌ 钉钉SDK初始化失败:",e),t(new Error("钉钉SDK初始化失败"))}));else{const e=this.buildWebLoginUrl();console.log("📱 跳转到钉钉网页登录:",e),window.location.href=e,t(new Error("需要跳转到网页登录"))}}else t(new Error("不在钉钉环境内"))}))}async getUserInfoByDingTalkCode(e){console.log("🔄 使用钉钉免登授权码获取用户信息:",e);try{const t=await fetch(this.config.apiOauthDingtalk||"",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({appId:this.config.clientId,code:e})}),n=await t.json();if(console.log("🔍 钉钉免登接口返回:",n),1===n.code){const{userInfo:e,sessionToken:t}=n.data;return{userId:e.objectId,username:e.username||e.nickname,nickname:e.nickname,openId:e.openId,unionId:e.unionId,avatar:e.avatar,email:e.email,mobile:e.mobile,corpId:this.config.corpId,sessionToken:t,rawUserInfo:e}}throw new Error(n.mess||"获取用户信息失败")}catch(e){throw console.error("❌ 调用钉钉免登接口失败:",e),e instanceof Error?e:new Error("网络请求失败")}}async getUserInfoByQRCode(e){console.log("🔄 使用二维码授权码获取用户信息:",e);try{const t=await fetch(this.config.apiOauthWeb||"",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({appId:this.config.clientId,code:e,grantType:"authorization_code"})}),n=await t.json();if(console.log("🔍 OAuth2登录接口返回:",n),1===n.code){const{userInfo:e,tokenInfo:t,sessionToken:o}=n.data;return{userId:e.objectId,username:e.username||e.nick,nickname:e.nick||e.username,openId:e.openId,unionId:e.unionId,avatar:e.avatarUrl||e.avatar,email:e.email,mobile:e.mobile,corpId:this.config.corpId,sessionToken:o,tokenInfo:t,rawUserInfo:e}}throw new Error(n.mess||"获取用户信息失败")}catch(e){throw console.error("❌ 调用OAuth2登录接口失败:",e),e instanceof Error?e:new Error("网络请求失败")}}validateConfig(){const e=[];return this.config.clientId||e.push("Client ID 未配置"),this.config.corpId||e.push("Corp ID 未配置"),this.config.redirectUri?this.config.redirectUri.startsWith("http")||e.push("Redirect URI 格式不正确,应以 http 或 https 开头"):e.push("Redirect URI 未配置"),console.log("🔍 钉钉应用配置验证:",{clientId:this.config.clientId,corpId:this.config.corpId,redirectUri:this.config.redirectUri,agentId:this.config.agentId,errors:e,isValid:0===e.length}),{isValid:0===e.length,errors:e}}buildWebLoginUrl(e="nanchi_login"){const t=`https://login.dingtalk.com/oauth2/auth?${new URLSearchParams({client_id:this.config.clientId,response_type:"code",scope:"openid",state:e,redirect_uri:this.config.redirectUri,prompt:"consent"}).toString()}`;return console.log("🔗 构造钉钉网页登录URL:",t),t}initQRCodeLogin(e,t,n){console.log("📱 初始化二维码登录");const o=this.validateConfig();o.isValid?this.loadDingTalkSDK().then((()=>{const o={id:e,width:300,height:300},i={redirect_uri:encodeURIComponent(this.config.redirectUri),response_type:"code",client_id:this.config.clientId,scope:"openid",prompt:"consent",state:"nanchi_qr_login"};console.log("🔍 钉钉登录参数:",{clientId:this.config.clientId,corpId:this.config.corpId,redirectUri:this.config.redirectUri,redirectUriEncoded:encodeURIComponent(this.config.redirectUri),loginParams:i}),window.DTFrameLogin(o,i,(async e=>{console.log("✅ 二维码登录成功:",e);try{const o=await this.completeDingTalkLogin(e.authCode,"qrcode");o.success?t(o):n(o.error||"登录失败")}catch(e){console.error("❌ 二维码登录流程失败:",e),n(e.message||"登录失败")}}),(e=>{console.error("❌ 二维码登录失败:",e),n(e)}))})).catch((e=>{console.error("❌ 加载钉钉SDK失败:",e),n("加载钉钉SDK失败")})):n(`配置验证失败: ${o.errors.join(", ")}`)}async handleAuthCallback(e,t){try{if(console.log("🔄 处理网页登录回调:",{code:e,state:t}),!e)return{success:!1,error:"授权码缺失",loginType:"dingtalk"};return await this.completeDingTalkLogin(e,"dingtalk")}catch(e){return console.error("❌ 处理网页登录回调失败:",e),{success:!1,error:e.message||"处理登录回调失败",loginType:"dingtalk"}}}async webLogin(e,t){try{if(console.log("🔐 开始网页登录:",{username:e}),!e||!t)return{success:!1,error:"用户名或密码不能为空",loginType:"web"};console.log("🔄 调用Parse.User.logIn()进行用户登录...");const n=await Parse$z.User.logIn(e,t);console.log("✅ Parse用户登录成功:",n.id);const o=n.getSessionToken();return{success:!0,userInfo:{userId:n.id,username:n.get("username"),nickname:n.get("nickname")||n.get("username"),email:n.get("email"),mobile:n.get("mobile"),avatar:n.get("avatar"),sessionToken:o,parseUser:n,loginType:"web"},loginType:"web"}}catch(e){console.error("❌ 网页登录失败:",e);let t="登录失败,请重试";return 101===e.code?t="用户名或密码错误":200===e.code?t="连接服务器失败,请检查网络":e.message&&(t=e.message),{success:!1,error:t,loginType:"web"}}}setLogoutCallback(e){this.onLogoutCallback=e}async loginWithSessionToken(e){console.log("🔐 使用sessionToken完成Parse登录");try{const t=await Parse$z.User.become(e);return console.log("✅ Parse用户登录成功:",t.id),{parseUser:t,sessionToken:e,userId:t.id,username:t.get("username")}}catch(e){throw console.error("❌ Parse用户登录失败:",e),new Error("Parse用户登录失败: "+e.message)}}async completeDingTalkLogin(e,t="dingtalk"){try{let n;if(console.log("🚀 开始完整钉钉登录流程,类型:",t),"dingtalk"===t)n=await this.getUserInfoByDingTalkCode(e);else{if("qrcode"!==t)throw new Error("不支持的登录类型");n=await this.getUserInfoByQRCode(e)}if(n.sessionToken){const o=await this.loginWithSessionToken(n.sessionToken);return console.log("✅ 完整钉钉登录流程成功"),{success:!0,code:e,userInfo:{...n,parseUser:o.parseUser},loginType:t}}throw new Error("未获取到sessionToken,无法完成登录")}catch(e){return console.error("❌ 完整钉钉登录流程失败:",e),{success:!1,error:e.message,loginType:t}}}async logout(){console.log("🚪 用户退出登录"),Parse$z.User.logOut(),localStorage.removeItem("nanchi_user_info"),localStorage.removeItem("nanchi_auth_token"),localStorage.removeItem("nanchi_session_token"),localStorage.removeItem("nanchi_login_time"),console.log("🗑️ 本地存储已清除"),this.onLogoutCallback&&this.onLogoutCallback()}saveUserInfo(e){localStorage.setItem("nanchi_user_info",JSON.stringify(e)),localStorage.setItem("nanchi_login_time",Date.now().toString()),e.sessionToken&&localStorage.setItem("nanchi_session_token",e.sessionToken),console.log("💾 用户信息已保存到本地存储")}getUserInfo(){const e=localStorage.getItem("nanchi_user_info");return e?JSON.parse(e):null}isLoggedIn(){const e=this.getUserInfo(),t=localStorage.getItem("nanchi_login_time");if(!e||!t)return!1;return(Date.now()-parseInt(t))/36e5<24}async isParseUserLoggedIn(){try{return null!==Parse$z.User.current()}catch(e){return console.warn("检查Parse用户登录状态失败:",e),!1}}async getCurrentParseUser(){try{return Parse$z.User.current()}catch(e){return console.warn("获取当前Parse用户失败:",e),null}}}function genFileKey(e,t,n){const o=new Date,i=o.getFullYear(),a=String(o.getMonth()+1).padStart(2,"0"),r=String(o.getDate()).padStart(2,"0"),s=String(o.getHours()).padStart(2,"0"),l=String(o.getMinutes()).padStart(2,"0"),c=String(o.getSeconds()).padStart(2,"0"),d=Math.random().toString(36).slice(2,8);return`storage/company/${t||"undefined"}/${n?`${n.replace(/^\/+|\/+$/g,"")}/`:""}${i}${a}${r}/${s}${l}${c}-${d}-${e}`}class QiniuProvider{constructor(e){this.conf=e}setConfig(e){this.conf=e}async upload(e,t){const n=qiniu||window.qiniu||void 0;if(!n)throw new Error("qiniu-js is not available on window");const o=e.name||"blob.bin",i=t?.key||genFileKey(o,"undefined"),a={fname:o,params:{},mimeType:e.type||void 0},r={useCdnDomain:this.conf.useCdnDomain??!0,forceDirect:this.conf.forceDirect??!0};return new Promise(((s,l)=>{n.upload(e,i,this.conf.uptoken,a,r).subscribe({next:e=>{t?.onProgress?.(e)},error:e=>{l(e)},complete:t=>{const n=`${this.conf.domain}${t.key}`,i={key:t.key,url:n,name:o,type:e.type||"",size:e.size||(t.size??0)};s(i)}})}))}}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??Date.now(),metadata:{}};return t.metadata.lastModified=t.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,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)}}const Parse$y=defaultExport.with("nova");class NovaStorage{constructor(e){this.provider=e}setProvider(e){this.provider=e}async initByCid(e,t){this.cid=e,this.provider=await this.selectProvider(e,t)}static async withCid(e,t){const n=new NovaStorage;return await n.initByCid(e,t),n}async selectProvider(e,t){if("hwobs"===t)throw new Error("Hwobs requires explicit configuration. Use setProvider(new HwobsProvider(conf)).");const n=await this.fetchQiniuConf(e);return new QiniuProvider(n)}async fetchQiniuConf(e){const t=await Parse$y.Cloud.run("qiniu_uptoken",{company:e});if(!t?.uptoken||!t?.domain)throw new Error("qiniu_uptoken returned invalid config");return{uptoken:t.uptoken,domain:t.domain,useCdnDomain:!0,forceDirect:!0}}async upload(e,t){if(!this.provider)throw new Error("NovaStorage provider is not set");let n=await calcFileMd5(e),o=await getFileMetadata(e),i={id:"",name:"",type:"",size:0,key:"",url:""},a=await this.getAttachmentByMd5(n);if(a?.id)return i.id=a?.id,i.url=a?.get("url"),i.name=a?.get("name"),i.md5=a?.get("md5"),i.type=a?.get("mime"),i.size=a?.get("size"),i.metadata=a?.get("metadata"),i;const r={...t};!r.key&&e?.name&&(r.key=genFileKey(e.name,this.cid||"",r.prefixKey)),console.log(r);let s=await this.provider.upload(e,r);return s.md5=n,s.metadata=o,a=await this.saveAttachment(s),s.id=a.id,s}async getAttachmentByMd5(e){if(!e)return null;const t=new Parse$y.Query("Attachment");t.equalTo("md5",e),t.addDescending("createdAt");return await t.first()}async saveAttachment(e,t,n,o,i){const a=e.md5||(i?await calcFileMd5(i):void 0);let r=e.url||"";r&&!r.startsWith("http")&&(r=(t||"")+r),r=r.replace(/undefined\//,"");const s=Parse$y.User.current(),l=new Parse$y.Object("Attachment");l.set("size",e.size),l.set("url",r),l.set("name",e.name),l.set("mime",e.type),a&&l.set("md5",a),e.metadata&&l.set("metadata",e.metadata);const c=o||this.cid||localStorage.getItem("company")||void 0;c&&l.set("company",{__type:"Pointer",className:"Company",objectId:c}),n&&l.set("category",{__type:"Pointer",className:"Category",objectId:n}),s?.id&&l.set("user",s.toPointer?s.toPointer():{__type:"Pointer",className:"_User",objectId:s.id});return await l.save()}}class HwobsProvider{constructor(e){this.conf=e,this.client=new ObsClient({access_key_id:e.access_key_id,secret_access_key:e.secret_access_key,server:e.server})}setConfig(e){this.conf=e,this.client=new ObsClient({access_key_id:e.access_key_id,secret_access_key:e.secret_access_key,server:e.server})}genFileKey(e){const t=new Date;return`storage/web-2023/${t.getFullYear()}${String(t.getMonth()+1).padStart(2,"0")}${String(t.getDate()).padStart(2,"0")}/${String(t.getHours()).padStart(2,"0")}${String(t.getMinutes()).padStart(2,"0")}${String(t.getSeconds()).padStart(2,"0")}-${Math.random().toString(36).slice(2,8)}-${e}`}async upload(e,t){const n=e.name||"blob.bin",o=t?.key||this.genFileKey(n);return new Promise(((t,i)=>{this.client.putObject({Bucket:this.conf.bucket,Key:o,SourceFile:e},((a,r)=>{if(a)i(a);else{const i=this.conf.host||"",a={key:o,url:i?`${i}${o}`:o,name:n,type:e.type||"",size:e.size||0};t(a)}}))}))}}const Parse$x=defaultExport.with("nova");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$x.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}}const Parse$w=defaultExport.with("nova");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"})}}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}]});const Parse$v=defaultExport.with("nova");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){const n=e.type,o=e.name?.split(".")?.pop()||"";let i={id:"",name:"",type:"",size:0,key:"",url:""};const a=await this.getFileMd5(e);if(!this.storage)try{this.storage=await NovaStorage.withCid(this.getCompanyId())}catch{this.ensureStorage()}const r=await(this.storage?.getAttachmentByMd5(a));if(r?.id)i.url=r?.get("url"),i.name=r?.get("name"),i.type=r?.get("mime"),i.size=r?.get("size"),i.metadata=r?.get("metadata"),t&&t({total:{loaded:i.size,size:i.size,percent:100}});else{const a=this.fileToBlob(e);i=n.indexOf("image")>-1?await this.saveQiniuImageFile(a,o,null,t):await this.saveQiniuMediaFile(e,a,null,t)}i?.url?.indexOf("undefined")>-1&&(i.url=(this.qiniuDomain||"https://file-cloud.fmode.cn/")+i.url.replace("undefined/",""));const s=(await getFileMetadata(e)).metadata;let l;return i.metadata={...i.metadata||{},...s},i?.url&&(l=await(this.storage?.saveAttachment(i,this.qiniuDomain,null,this.getCompanyId(),e))),l?.id&&(i.id=l?.id),i.attachment=l,i}async getAttachByMd5(e){if(!e)return null;if(!this.storage)try{this.storage=await NovaStorage.withCid(this.getCompanyId())}catch{this.ensureStorage()}return this.storage?.getAttachmentByMd5(e)}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$v.Cloud.run("qiniu_uptoken",{company:this.getCompanyId()});console.log(e),this.qiniuConf=e,this.qiniuProviderConf={uptoken:this.qiniuConf?.uptoken,domain:this.qiniuConf?.domain,useCdnDomain:!0,forceDirect:!0},this.ensureStorage()}catch(e){console.error(e)}}ensureStorage(){if(this.qiniuProviderConf){const e=new QiniuProvider(this.qiniuProviderConf);this.storage=new NovaStorage(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$v.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){if(!this.storage)try{this.storage=await NovaStorage.withCid(this.getCompanyId())}catch{this.ensureStorage()}return await(this.storage?.saveAttachment(e,t,n,o,i))}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;const l=new File([e],r,{type:s}),c=this.genFileKey({id:a,name:r});if(this.storage||this.ensureStorage(),!this.storage)throw"Storage provider not initialized";return{...await this.storage.upload(l,{key:c,onProgress:e=>o&&o(e)}),name:r,type:s,size:e.size}}async saveQiniuMediaFile(e,t,n,o){let i=e.name,a=e.type,r=e.size;if(r>(this.maxSize||104857600))throw console.log("视频过大,超出限制100MB"),"超出文件大小";let s=new DatePipe("en").transform(new Date,"yyyyMMddHHmmss");const l=new File([t],i,{type:a}),c=this.genFileKey({id:s,name:i});if(this.storage||this.ensureStorage(),!this.storage)throw"Storage provider not initialized";return{...await this.storage.upload(l,{key:c,onProgress:e=>o&&o(e)}),name:i,type:a,size:r}}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}]});const Parse$u=defaultExport.with("nova");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$u.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$u?.User?.current()?.id)return;let t=new Parse$u.Query("ChatSession");e&&(t=Parse$u.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$u.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$u.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){console.log("createNewRoleChat",e);let t=new Parse$u.Query("AvatarRole");t.include("model");let n=await t.get(e);return console.log("role",n),new FmodeChat("new",n,null,this,this.navCtrl,this.ncloud,this.uploadServ)}async restoreChatPanel(e){let t=new Parse$u.Query("AvatarRole"),n=new Parse$u.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"})}}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}]});const Parse$t=defaultExport.with("nova");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$t.Query("ImagineWork");e.get(o?.id),n=await e.first(),console.log(n)}return n}async function myFetchFun(e,t){let n=Parse$t.User.current(),o=await fetch(e,{headers:{authorization:`Bearer ${n?.getSessionToken()}`,"Content-Type":"application/json"},mode:"cors",credentials:"omit",method:"POST",body:JSON.stringify(t)});return await o.json()}async function getJimengImg(e){let t,n,o=await myFetchFun("https://server.fmode.cn/api/volcengine/jimeng/getImg",e);t=o?.data?.workId;let i=new Parse$t.Query("ImagineWork");return n=await i.get(t),n}async function getJimengT_v(e){let t,n=await myFetchFun("https://server.fmode.cn/api/volcengine/jimeng/getVideoByText",e);if(console.log("获取的taskId:",n),t=n?.data?.workId,t){let e,n=new Parse$t.Query("ImagineWork");return e=await n.get(t),e}return n}async function getJimengI_v(e){let t,n=await myFetchFun("https://server.fmode.cn/api/volcengine/jimeng/getVideoByImg",e);if(console.log("获取的taskId:",n),t=n?.data?.workId,t){let e,n=new Parse$t.Query("ImagineWork");return e=await n.get(t),e}return n}async function getJimengV_data(e){let t,n,o=await myFetchFun("https://server.fmode.cn/api/volcengine/jimeng/getDataByTask",e);if(console.log("根据taskId请求出来的结果:",o),o?.error)return o;t=o?.data?.workId;let i=new Parse$t.Query("ImagineWork");return n=await i.get(t),n}const Parse$s=defaultExport.with("nova");class ImagineService{constructor(e,t,n,o){this.http=e,this.ncloud=t,this.uploadServ=n,this.toastCtrl=o,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$s.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$s.User.current();if(!e?.id)return;let t=this.getWorkQuery();return t.include("model","module","user"),t.equalTo("user",e.toPointer()),t}getWorkQuery(){new Date((new Date).getTime()-6e4);let e=Parse$s.Query.fromJSON("ImagineWork",{where:{}});return e.include("model","module","user"),e.notEqualTo("isDeleted",!0),e.notEqualTo("isFailed",!0),e.doesNotExist("respData.error"),e.doesNotExist("respData.data.taskLimitCount"),e.addDescending("createdAt"),e}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)}))}async getJimengImg(e){let t=new Parse$s.Object("ImagineWork");t.set("__pending",!0),t.set("__id",Symbol()),t.set("images",[""]),this.newWorkList.unshift(t);try{let n=await getJimengImg(e),o=this.newWorkList?.findIndex((e=>e?.get("__id")===t?.get("__id")));if(-1==o)return;if(!n?.id)return void this.newWorkList.splice(o,1);this.newWorkList.splice(o,1,n)}catch(e){let n=this.newWorkList?.findIndex((e=>e?.get("__id")===t?.get("__id")));if(-1==n)return;this.newWorkList.splice(n,1)}}async getJimengVideo(e,t){let n=new Parse$s.Object("ImagineWork");n.set("__pending",!0),n.set("__id",Symbol()),n.set("provider","volcengine"),n.set("taskId","1"),this.newWorkList.unshift(n);try{let o;o="i_v"==t?await getJimengI_v(e):await getJimengT_v(e);let i=this.newWorkList?.findIndex((e=>e?.get("__id")===n?.get("__id")));if(-1==i)return;if(!o?.id)return this.newWorkList.splice(i,1),void this.setToast("创建有误,请稍后再试");this.newWorkList.splice(i,1,o)}catch(e){let t=this.newWorkList?.findIndex((e=>e?.get("__id")===n?.get("__id")));if(-1==t)return;this.newWorkList.splice(t,1)}}async getJimengVideoData(e,t){try{let n=await getJimengV_data({video_by:e,workId:t});if(console.log("请求结果",n),n?.error)return void this.setToast(n?.error?.message||n?.error?.msg||n?.err?.message||n?.err?.msg||"请求错误");if(1!==n?.get("progress")||n?.get("videos")?.length<=0)return;let o=this.newWorkList?.findIndex((e=>e?.id===t));if(-1==o)return;return n?.id?(this.newWorkList.splice(o,1,n),n):void this.newWorkList.splice(o,1)}catch(e){let n=this.newWorkList?.findIndex((e=>e?.id===t));if(-1==n)return;this.newWorkList.splice(n,1)}}async setToast(e){(await this.toastCtrl.create({duration:1e3,message:e||"请求错误",color:"primary",icon:"information-circle",position:"top"})).present()}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},{token:i3.ToastController}],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},{type:i3.ToastController}]});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}]});const Parse$r=defaultExport.with("nova");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$r.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$r.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(){}highlightMarkdown(e){try{const t=/```(\w+)?\n([\s\S]*?)```/g,n=[];let o,i=0;for(;null!==(o=t.exec(e));)o.index>i&&n.push({type:"markdown",content:e.substring(i,o.index)}),n.push({type:"code",content:o[2],language:o[1]}),i=o.index+o[0].length;return i<e.length&&n.push({type:"markdown",content:e.substring(i)}),0===n.length?hljs.highlight(e,{language:"markdown"}).value:n.map((e=>"code"===e.type?this.highlightCodeBlock(e.content,e.language):e.content.trim()?hljs.highlight(e.content,{language:"markdown"}).value:e.content)).join("")}catch(t){return console.error("Markdown highlighting error:",t),e}}highlightCodeBlock(e,t){try{let n,o;if(t&&hljs.getLanguage(t))n=hljs.highlight(e,{language:t}).value,o=t;else{const t=hljs.highlightAuto(e);n=t.value,o=t.language||"plaintext"}return`<pre><code class="hljs language-${o}">${n}</code></pre>`}catch(t){return console.error("Code block highlighting error:",t),`<pre><code class="hljs">${this.escapeHtml(e)}</code></pre>`}}escapeHtml(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}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"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ClipboardService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i3.ToastController}]});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 h=0,u=0;u<a;h++,u+=i)0==u?o.moveTo(u,p[h]):o.lineTo(u,p[h]);h--;for(u=a-1;u>=0;h--,u-=i)o.lineTo(u,m[h]);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}();const Parse$q=defaultExport.with("nova");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()}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年"}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}]}});const Parse$p=defaultExport.with("nova");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$p.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}]}});const Parse$o=defaultExport.with("nova");class CompAvatarRoleVideoComponent{constructor(e){this.navCtrl=e,this.animClass="waiting",this.onClose=new EventEmitter,this.goBack=()=>{this.navCtrl.back()},this.videoMap={}}close(){this.onClose.emit(!0),this.fmodeChat.isAvatarShow=!1}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",goBack:"goBack"},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}],goBack:[{type:Input}]}});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$4.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:i1$4.MatDialogClose,selector:"[mat-dialog-close], [matDialogClose]",inputs:["aria-label","type","mat-dialog-close","matDialogClose"],exportAs:["matDialogClose"]},{kind:"directive",type:i1$4.MatDialogTitle,selector:"[mat-dialog-title], [matDialogTitle]",inputs:["id"],exportAs:["matDialogTitle"]},{kind:"directive",type:i1$4.MatDialogActions,selector:"[mat-dialog-actions], mat-dialog-actions, [matDialogActions]",inputs:["align"]},{kind:"directive",type:i1$4.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$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:i1$4.MatDialogRef},{type:void 0,decorators:[{type:Inject,args:[MAT_DIALOG_DATA]}]}],propDecorators:{stepper:[{type:ViewChild,args:[MatStepper]}]}}),addIcons({chevronBackOutline:chevronBackOutline,ellipsisHorizontalOutline:ellipsisHorizontalOutline,resizeOutline:resizeOutline});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 [goBack]="goBack" *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","goBack"],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 [goBack]="goBack" *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}]}});const Parse$n=defaultExport.with("nova");class WechatJssdkService{get initUrl(){return sessionStorage.getItem("initialUrl")}set initUrl(e){sessionStorage.getItem("initialUrl")||sessionStorage.setItem("initialUrl",window.location.href)}constructor(e){this.http=e,this.isInit=!1,this.isWechat=!1,this.company=localStorage.getItem("company"),this.wechatAccountId=localStorage.getItem("WECHAT_APP_ID"),this.isWechatConfigInit=!1,this.initUrl=window.location.href;let t=-1!==navigator.userAgent.toLowerCase().indexOf("micromessenger");this.isWechat=t,this.init()}async initWechatConfig(e,t){if(this.company=e||localStorage.getItem("company"),this.wechatAccountId=t||localStorage.getItem("WECHAT_APP_ID"),this.isWechatConfigInit)return;const n=await this.getWXSignPackageInWechat();wx.config({debug:!1,appId:n.appid,timestamp:n.timestamp,nonceStr:n.nonceStr,signature:n.signature,jsApiList:["chooseWXPay","onMenuShareTimeline","onMenuShareAppMessage","onMenuShareQQ","onMenuShareQZone","updateAppMessageShareData","updateTimelineShareData"]}),this.isWechatConfigInit=!0}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("取消分享")}}){await this.initWechatConfig(),"link"==e?.type&&(e.link=this.getInviteUrl(e.link)),this.replaceSameUrl(e.link),wx.ready((()=>{wx.updateAppMessageShareData(e),wx.updateTimelineShareData(e)})),wx.error((e=>{}))}replaceSameUrl(e){try{const t=new URL(e,window.location.href),{pathname:n,search:o,origin:i}=t;if(i!==window.location.origin)throw new Error(`目标URL与当前页面不同源(当前: ${window.location.origin}, 目标: ${i})`);const a=`${i}${n}${o}`;history.replaceState(null,"",a)}catch(e){throw new Error(`修改URL失败: ${e.message}`)}}getInviteUrl(e){let t=new URL(e),n=Parse$n.User?.current()?.id;return n&&t.searchParams.set("invite",n),t.href}getWXSignPackageInWechat(){let e={company:this.company,href:encodeURIComponent(this.initUrl)};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(){if(!this.wechatAccountId)return console.error("appId不存在,请先配置");let e=this.getQueryStringByName("code"),t=localStorage.getItem("openid");if(!t){if(!Parse$n.User.current())return;if(t=Parse$n?.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=window.location.pathname){if(!localStorage.getItem("openid")){let t=window.location.origin+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$n.User.current().set("wechat",o),await Parse$n.User.current().save(),n(!0)}}),(async e=>{console.log("Error updating items",e),this.authWechat(t),o(!1)}))}))}init(){return new Promise((e=>{if(this.isWechat||e(!1),!this.isInit||"undefined"==typeof wx)return"undefined"!=typeof wx?(this.isInit=!0,this.wx=wx,void e(!0)):void this.loadScript("https://res.wx.qq.com/open/js/jweixin-1.6.0.js",(()=>{this.isInit=!0,this.wx=wx,e(!0)}),(()=>{e(!1)}));e(!0)}))}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}],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}]});const Parse$m=defaultExport.with("nova");class AuthService{isGuardLock(e){let t=!0,n=Parse$m.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,i){this.router=e,this.wxjssdk=t,this.toastCtrl=n,this.novaCloud=o,this.http=i,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.appId=e.appId,this.wxjssdk.initWechatConfig(this.company,this.appId),this.saveParamsInvite()}checkLoginLock(){let e=Parse$m.User.current();return!!e?.id||(this.isModalShow=!0,this.isLoggedIn=!1,!1)}async checkLogin(e,t){await this.checkAndLoginWithToken(),await this.authWechat(),e&&(this.guardMap[e]=!0);let n=Parse$m.User.current();return console.log("currentUser",n),n&&n.id?(this.setAccount(n),this.isLoggedIn=!0,t?.onLogin?.(),!0):this.guardType&&"page"!=this.guardType?"modal"==this.guardType?(this.isModalShow=!0,this.isLoggedIn=!1,!0):void 0:(e&&(this.redirectUrl=e,this.router.navigate([this.LoginPage])),!1)}async authWechat(){return!(!this.wxjssdk.isWechat||!this.appId||Parse$m.User.current()?.id)&&new Promise((e=>{let t=this.getCompanyId(),n=this.wxjssdk.getQueryStringByName("code"),o=window.location.pathname;n?Parse$m.Cloud.run("auth_wechat",{code:n,c:t}).then((t=>{localStorage.removeItem("code");let n=t.token;console.log(n),t.openid&&localStorage.setItem("openid",t.openid),Parse$m.User.current()?.id&&e(!0),Parse$m.User.become(n).then((t=>{console.log(t),t.set("company",{__type:"Pointer",className:"Company",objectId:localStorage.getItem("company")}),t.save(),e(!0)})).catch((t=>{console.warn("become登录失败:"+t),e(!1)}))})).catch((t=>{console.warn("Wechat登录失败:"+t),e(!1)})):this.wxjssdk.authWechat(o)}))}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$m.User.current();if(!o?.id)try{o=await Parse$m.User.become(t)}catch(e){}}}async setAccount(e){if(this.account?.id)return;let t=e?.get("company")||{__type:"Pointer",className:"Company",objectId:this.getCompanyId()}||null,n=new Parse$m.Query("Account");n.equalTo("user",e.toPointer());let o=await n.first();return o?.id||(o=new Parse$m.Object("Account"),o.set({user:e.toPointer(),company:t}),o=await o.save()),this.account=o,o}login(e,t){return new Promise(((n,o)=>{Parse$m.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$m.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$m.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$m.User.logOut().then((e=>{})),this.router.navigate([t||"/pcuser/login"],{queryParams:{t:(new Date).getTime()},queryParamsHandling:"merge"})}async loginMobilePassword(e,t,n,o){let i=await this.getMobileUser(e);if(i)return new Promise(((e,o)=>{this.login(i,t).then((async t=>{this.isModalShow=!1,this.updateLoginState(),e(t)})).catch((e=>{console.log(e),n.create("error","错误的用户名或密码"),o(e)}))}));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$m.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)}))}))}updateLoginState(){new URLSearchParams(location.search).set("t",String((new Date).getTime()));let e="/"+(location.origin+location.pathname).replaceAll(document.baseURI,"");console.log(e),this.router.navigate([e],{queryParams:{t:(new Date).getTime()},queryParamsHandling:"merge"})}async getMobileCodeToken(e,t){return new Promise(((n,o)=>{let i=Parse$m.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$m.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 o?.(),this.updateLoginState(),!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,null,o)}}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$m.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:WechatJssdkService},{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:WechatJssdkService},{type:i1$3.ToastController},{type:NovaCloudService},{type:i1.HttpClient}]});const Parse$l=defaultExport.with("nova");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")||"",this.company=this.authServ.company||localStorage.getItem("company"),this.getBilling(),this.getProfile(),this.getUserOpenid()}async getProfile(){let e=Parse$l.User.current()?.id;if(!e)return;let t=new Parse$l.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$l.User.current()?.getSessionToken()){try{e=await this.ncloud.apig("aigc/account",null,"get")}catch(e){}return e?.credit&&(this.billing=e),e}}async getUserOpenid(){if(!this.appid)return;let e=-1!=navigator.userAgent.toLowerCase().indexOf("micromessenger"),t=this.getQueryStringByName("code"),n=localStorage.getItem("openid");if(!n){if(!Parse$l.User.current())return;let o=Parse$l.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$l.User.current().set("wechat",o),await Parse$l.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$l.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://server.fmode.cn/api/apig/saveAccountLog",{company:n,uid:Parse$l.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}]});const Parse$k=defaultExport.with("nova");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}]}]});const Parse$j=defaultExport.with("nova");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$j.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$j.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}]}});const Parse$i=defaultExport.with("nova");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$i.Query("ChatPrompt");e.notEqualTo("isDeleted",!0),console.log("getChatPrompt",this.role),e.equalTo("role",this.role),e.include("role");let t=await e.find();t?.length&&(console.log("this.chat.promptList?.length",this.chat.promptList),this.chat.promptList?.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;display:flex;justify-content:center;flex-direction:column;align-items:center}.prompt .prompt_cate .cate_info div img{border-radius:15px;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;display:flex;justify-content:center;flex-direction:column;align-items:center}.prompt .prompt_cate .cate_info div img{border-radius:15px;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}]}});const Parse$h=defaultExport.with("nova");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$h.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$h.User.current()?.id&&this.chatVoice.set("user",Parse$h.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"});this.uploadServ.maxSize=1073741824;let 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}]}});const Parse$g=defaultExport.with("nova");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$g.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$g.User.current();let e=new Parse$g.Query("ChatShare");e.equalTo("user",Parse$g.User.current().id),e.equalTo("session",this.chat?.sessionId);await e.first()}async toggleChatShare(){let e=new Parse$g.Query("ChatShare");e.equalTo("user",Parse$g.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$g.Object.extend("ChatShare")),t.set("user",{__type:"Pointer",className:"_User",objectId:Parse$g.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&&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: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&&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:"fm-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,htmlAttributes:t.htmlAttributes});return t?.fullscreen&&addModalChatPanelStyle(),await n.present(),n}function addModalChatPanelStyle(){const e="custom-modal-chat-panel-style";if(document.getElementById(e))return;const t=document.createElement("style");t.id=e,t.textContent="\n .modal-chat-panel {\n --width: 100%!important;\n --height: 100%!important;\n --max-width: 100%;\n --max-height: 100%;\n --border-radius: 0;\n }\n ",document.head.appendChild(t)}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatPanelComponent,decorators:[{type:Component,args:[{selector:"fm-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"]}]})}}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 Parse$f=defaultExport.with("nova");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$f.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:()=>[]});const Parse$e=defaultExport.with("nova");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$e.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$e.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$e.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: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]}]}]});const Parse$d=defaultExport.with("nova");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$d.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$d.GeoPoint({latitude:28.682634,longitude:115.86273})}):this.placeList.push({name:"八一广场",address:"南昌市八一广场",location:new Parse$d.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:()=>[]});const Parse$c=defaultExport.with("nova");class PageLocaScatterComponent{constructor(){this.amap={securityJsCode:"32aa3f4ab0fa0061de03edd4eafdd50a",key:"473b52010df7d3a32db0a2f5db245c8e"},this.initaMapConfig()}async initaMapConfig(){let e=localStorage.getItem("company");if(e){let t=new Parse$c.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]}]}]});const Parse$b=defaultExport.with("nova");class HwobsService{constructor(){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$b.Query("Attachment");o.equalTo("hash",n),o.equalTo("size",e.size);let i=await o.first();return i?.id||(i=new Parse$b.Object("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]}]}]});const WxworkAuthGuard=async(e,t)=>checkWeworkLogin(e);function wxdebug(...e){console.log(e)}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;}"]})}}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: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}]}});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"})}}function normalizeLineEndings(e){return e?e.replace(/\r\n|\r/g,"\n"):e}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FiletypePipe,decorators:[{type:Pipe,args:[{name:"filetype",standalone:!0}]}]});class CodemirrorComponent{set extensions(e){this._extensions=e||[],!this._differ&&e&&(this._differ=this._differs.find(e).create()),this.reconfigureEditor()}set options(e){this._options=e,this._extensions=this.convertOptionsToExtensions(e),!this._differ&&e&&(this._differ=this._differs.find(e).create()),this.reconfigureEditor()}constructor(e,t){this._differs=e,this._ngZone=t,this.className="",this.name="codemirror",this.autoFocus=!1,this.preserveScrollPosition=!1,this.cursorActivity=new EventEmitter,this.focusChange=new EventEmitter,this.scroll=new EventEmitter,this.drop=new EventEmitter,this.codeMirrorLoaded=new EventEmitter,this.value="",this.disabled=!1,this.isFocused=!1,this._options={},this._extensions=[],this.extensionsCompartment=new Compartment,this.readOnlyCompartment=new Compartment,this.onChange=e=>{},this.onTouched=()=>{}}ngAfterViewInit(){this._ngZone.runOutsideAngular((()=>{this.initializeEditor()}))}async initializeEditor(){const{EditorView:e}=await import("codemirror"),{EditorState:t}=await import("@codemirror/state"),n=[basicSetup,this.extensionsCompartment.of(this._extensions),this.readOnlyCompartment.of(this.disabled?t.readOnly.of(!0):[]),this.createUpdateListener(),this.createFocusExtension(),this.createScrollExtension(),this.createDropExtension()],o=t.create({doc:this.value,extensions:n});this.editorView=new e({state:o,parent:this.ref.nativeElement}),this.autoFocus&&this.editorView.focus(),this._ngZone.run((()=>{this.codeMirrorLoaded.emit(this)}))}createUpdateListener(){return EditorView.updateListener.of((e=>{e.docChanged&&this._ngZone.run((()=>{this.codemirrorValueChanged(e.view)})),e.selectionSet&&this._ngZone.run((()=>{this.cursorActive(e.view)}))}))}createFocusExtension(){return EditorView.domEventHandlers({focus:()=>(this._ngZone.run((()=>this.focusChanged(!0))),!1),blur:()=>(this._ngZone.run((()=>this.focusChanged(!1))),!1)})}createScrollExtension(){return EditorView.domEventHandlers({scroll:(e,t)=>(this._ngZone.run((()=>this.scrollChanged(t))),!1)})}createDropExtension(){return EditorView.domEventHandlers({drop:(e,t)=>(this._ngZone.run((()=>this.dropFiles(t,e))),!1)})}convertOptionsToExtensions(e){const t=[];return e?(e.mode,e.theme,e.lineNumbers,t):t}ngDoCheck(){if(!this._differ)return;this._differ.diff(this._options)&&this.reconfigureEditor()}async reconfigureEditor(){if(!this.editorView)return;const e=[this.extensionsCompartment.reconfigure(this._extensions)];this.editorView.dispatch({effects:e})}ngOnDestroy(){this.editorView&&this.editorView.destroy()}codemirrorValueChanged(e){const t=e.state.doc.toString();this.value!==t&&(this.value=t,this.onChange(this.value))}focusChanged(e){this.onTouched(),this.isFocused=e,this.focusChange.emit(e)}scrollChanged(e){const t=e.scrollDOM,n={left:t.scrollLeft,top:t.scrollTop,width:t.scrollWidth,height:t.scrollHeight,clientWidth:t.clientWidth,clientHeight:t.clientHeight};this.scroll.emit(n)}cursorActive(e){this.cursorActivity.emit(e)}dropFiles(e,t){this.drop.emit([e,t])}writeValue(e){if(null==e)return;if(!this.editorView)return void(this.value=e);const t=this.editorView.state.doc.toString();if(e!==t&&normalizeLineEndings(t)!==normalizeLineEndings(e))if(this.value=e,this.preserveScrollPosition){const t={left:this.editorView.scrollDOM.scrollLeft,top:this.editorView.scrollDOM.scrollTop};this.editorView.dispatch({changes:{from:0,to:this.editorView.state.doc.length,insert:e}}),this.editorView.scrollDOM.scrollTo(t.left,t.top)}else this.editorView.dispatch({changes:{from:0,to:this.editorView.state.doc.length,insert:e}})}registerOnChange(e){this.onChange=e}registerOnTouched(e){this.onTouched=e}async setDisabledState(e){if(this.disabled=e,this.editorView){const{EditorState:t}=await import("@codemirror/state");this.editorView.dispatch({effects:[this.readOnlyCompartment.reconfigure(e?t.readOnly.of(!0):[])]})}}focus(){this.editorView?.focus()}getEditorView(){return this.editorView}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CodemirrorComponent,deps:[{token:i0.KeyValueDiffers},{token:i0.NgZone}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CodemirrorComponent,isStandalone:!0,selector:"ngx-codemirror",inputs:{className:"className",name:"name",autoFocus:"autoFocus",extensions:"extensions",options:"options",preserveScrollPosition:"preserveScrollPosition"},outputs:{cursorActivity:"cursorActivity",focusChange:"focusChange",scroll:"scroll",drop:"drop",codeMirrorLoaded:"codeMirrorLoaded"},providers:[{provide:NG_VALUE_ACCESSOR,useExisting:forwardRef((()=>CodemirrorComponent)),multi:!0}],viewQueries:[{propertyName:"ref",first:!0,predicate:["ref"],descendants:!0}],ngImport:i0,template:'\n <div\n [class]="\'ngx-codemirror \' + className"\n [class.ngx-codemirror--focused]="isFocused"\n #ref\n ></div>\n ',isInline:!0,changeDetection:i0.ChangeDetectionStrategy.OnPush})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CodemirrorComponent,decorators:[{type:Component,args:[{selector:"ngx-codemirror",standalone:!0,template:'\n <div\n [class]="\'ngx-codemirror \' + className"\n [class.ngx-codemirror--focused]="isFocused"\n #ref\n ></div>\n ',providers:[{provide:NG_VALUE_ACCESSOR,useExisting:forwardRef((()=>CodemirrorComponent)),multi:!0}],preserveWhitespaces:!1,changeDetection:ChangeDetectionStrategy.OnPush}]}],ctorParameters:()=>[{type:i0.KeyValueDiffers},{type:i0.NgZone}],propDecorators:{className:[{type:Input}],name:[{type:Input}],autoFocus:[{type:Input}],extensions:[{type:Input}],options:[{type:Input}],preserveScrollPosition:[{type:Input}],cursorActivity:[{type:Output}],focusChange:[{type:Output}],scroll:[{type:Output}],drop:[{type:Output}],codeMirrorLoaded:[{type:Output}],ref:[{type:ViewChild,args:["ref"]}]}});const Parse$a=defaultExport.with("nova");class PaymentService{constructor(e,t){this.toast=e,this.http=t,this.company=""}setTradeNo(){let e=new Date;return"C"+String(e.getFullYear())+(e.getMonth()+1)+e.getDate()+e.getHours()+e.getMinutes()+e.getSeconds()+e.getMilliseconds()+Math.floor(1e4*Math.random())}async createdAccountLog(e){let t=new Parse$a.Query("Account");t.equalTo("user",Parse$a.User.current().id),t.equalTo("company",e.company);let n=await t.first(),o=new Parse$a.Object("AccountLog");if(e.orderId){let t=new Parse$a.Query("AccountLog");t.equalTo("orderId",e.orderId),t.equalTo("user",Parse$a.User.current()?.id);let n=await t.first();n?.id&&(o=n)}o.set("assetType","wxPay"),o.set("payType",e.payType),o.set("assetCount",e.price),o.set("desc",`${e.payType}支付(fm-sdk生成)`),o.set("orderType",e.orderType),o.set("orderNumber",e.tradeNo),e.orderId&&o.set("orderId",e.orderId),o.set("isVerified",!1),o.set("targetName","system"),n&&o.set("fromAccount",n.toPointer()),Parse$a.User.current()?.id&&(o.set("user",Parse$a.User.current().toPointer()),o.set("fromName",Parse$a.User.current().get("nickname"))),o.set("company",{__type:"Pointer",className:"Company",objectId:e.company}),await o.save()}async setOrder(e){return new Promise(((t,n)=>{this.http.post("https://server.gdchat.cn/api/apig/created-order",{fcompany:this.company,uid:Parse$a.User.current()?.id,type:e.type,gid:e.gid,invite:Parse$a.User.current()?.get("invite")?.id,params:e}).subscribe((e=>{t(e.data)}),(e=>{n(e)}))}))}async creatdRechargeLog(e){const t=Parse$a.User.current();let n=new Parse$a.Query("Account");n.equalTo("company",this.company),n.equalTo("user",t?.id),n.select("objectId");let o=await n.first();o?.id||(o=await this.createdAccount(t.id));let i=new Parse$a.Query("AccountLog");i.equalTo("orderNumber",e.tradeNo),i.equalTo("targetAccount",o?.id),i.notEqualTo("isVerified",!0),i.notEqualTo("isDeleted",!0);let a=await i.first();if(a?.id)return a;let r=new Parse$a.Object("AccountLog");return r.set("isVerified",!1),r.set("user",{__type:"Pointer",className:"_User",objectId:t.id}),r.set("company",{__type:"Pointer",className:"Company",objectId:this.company}),r.set("targetAccount",{__type:"Pointer",className:"Account",objectId:o?.id}),r.set("fromName","system"),r.set("fromAccountName","system"),r.set("orderNumber",e.tradeNo),r.set("desc",`${e.payType}充值${e.price}`),r.set("assetType","balance"),r.set("orderType",`${e.payType}-recharge`),r.set("payType",e.payType),r.set("assetCount",e.credit),r.set("serviceFee",e.price),await r.save()}async createdAccount(e){let t=new Parse$a.Query("Account");t.equalTo("company",this.company),t.equalTo("user",e);let n=await t.first();return n?.id||(n=new Parse$a.Object("Account"),n?.set("user",{__type:"Pointer",className:"_User",objectId:e}),n?.set("company",{__type:"Pointer",className:"Company",objectId:this.company}),n?.set("balance",0),n=await(n?.save())),n}async updateAccountLog(e,t){return new Promise(((n,o)=>{this.http.post("https://server.gdchat.cn/api/apig/saveAccountLog",{company:this.company,uid:Parse$a.User.current()?.id,orderid:t,info:e}).subscribe((e=>{console.log(e),n(!0)}),(async e=>{console.warn(e);(await this.toast.create({message:"支付成功,订单记录异常",color:"warning",duration:1500})).present(),o()}))}))}async updateRecharge(e){return e?.set("isVerified",!0),await(e?.save()),e}async getOrder(e){let t=new Parse$a.Query("Order");t.notEqualTo("isDeleted",!0),t.equalTo("status","100"),t.equalTo("orderNum",e),t.select("objectId");let n=await t.first();return n?.id}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PaymentService,deps:[{token:i3.ToastController},{token:i1.HttpClient}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PaymentService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PaymentService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i3.ToastController},{type:i1.HttpClient}]});const Parse$9=defaultExport.with("nova");class PaymentComponent{constructor(e,t,n,o,i){this.wxjssdk=e,this.http=t,this.activRoute=n,this.payServer=o,this.alertCtrl=i,this.price=0,this.title="支付订单",this.showTypes=["wxpay","alipay"],this.orderType="goods",this.isRechargeRule=!1,this.credit=0,this.payResult=new EventEmitter,this.isOpen=!0,this.checkpay=this.showTypes[0]||"",this.user=Parse$9.User.current(),this.isLoading=!1,this.isDisabled=!1}ngOnInit(){this.activRoute.paramMap.subscribe((async e=>{let t=navigator.userAgent.toLowerCase();console.log(t),-1!=t.indexOf("micromessenger")?(this.userAgent="weixin",await this.wxjssdk.initUserOpenid(),this.wxjssdk.setCurrentPageShareInfo()):-1==t.indexOf("windows")&&-1==t.indexOf("Macintosh")||(this.userAgent="pc")}))}onchangPay(e){this.checkpay=e,console.log(e)}async userPayment(){if(!this.isLoading&&this.checkpay){if(this.tradeNo||(this.tradeNo=this.payServer.setTradeNo()),this.isRechargeRule&&this.tradeNo&&(this.orderId=await this.payServer.getOrder(this.tradeNo),("vip"==this.orderType&&!this.orderId||"recharge"==this.orderType&&(!this.accountLog?.id||this.accountLog?.get("isVerified")))&&(this.tradeNo=this.payServer.setTradeNo())),console.log(this.tradeNo),0==this.price)return this.toast("支付成功","success"),this.isOpen=!1,this.payResult.emit({code:200,tradeNo:this.tradeNo,type:this.checkpay}),void(this.tradeNo=null);switch(this.checkpay){case"wxpay":this.openWxPay();break;case"alipay":this.openAlipay()}}}async openWxPay(){-1!=navigator.userAgent.toLowerCase().indexOf("micromessenger")?this.wxPayH5():this.wxPay()}async wxPayH5(){if(!this.isDisabled)try{this.isDisabled=!0;let e=Parse$9.User.current()?.get("wechat"),t=localStorage.getItem("openid")||e[this.wxjssdk.wechatAccountId]?.openid;if(t){let e={company:this.wxjssdk.company,body:this.title,out_trade_no:this.tradeNo,total_fee:+this.price,openid:t,appid:this.wxjssdk.wechatAccountId},n=this;this.http.post("https://server.fmode.cn/api/wxpay/neworder",e).pipe(catchError((async e=>{console.error(e),this.isDisabled=!1,this.isLoading=!1,this.toast("支付失败:"+e?.error?.mess,"fail")}))).subscribe((async e=>{await this.certificatePay();let t=e;wx.chooseWXPay({timestamp:t.timeStamp,nonceStr:t.nonceStr,package:t.package,signType:"MD5",paySign:t.paySign,success:async e=>{if(e){if(this.isRechargeRule){let e={out_trade_no:n.tradeNo,nonce_str:t.nonceStr,company:this.wxjssdk.company};this.orderId?this.payServer.updateAccountLog(e,this.orderId):"recharge"==this.orderType&&(this.accountLog=await this.payServer.updateRecharge(this.accountLog))}n.isOpen=!1,n.toast("支付成功","success"),n.payResult.emit({code:200,tradeNo:this.tradeNo,type:this.checkpay})}}}),this.isDisabled=!1}))}else{this.isDisabled=!1,(await this.alertCtrl.create({header:"提示",subHeader:"",message:"缺少openid,请刷新页面或重新登录",buttons:[{role:"ok",text:"确认",handler:()=>{location.reload()}}]})).present()}}catch(e){this.isDisabled=!1,(await this.alertCtrl.create({header:"异常错误",subHeader:"",message:e.message,buttons:[{role:"ok",text:"确认",handler:()=>{}}]})).present()}}async wxPay(){let e={company:this.wxjssdk.company,out_trade_no:this.tradeNo,total_fee:this.price,body:this.title};Parse$9.Cloud.run("pay_code2",e).then((async e=>{let t=e.nonce_str;this.codeLink=e.code_url[0],console.log(this.codeLink),await this.certificatePay(),this.updateOrder(t)})).catch((e=>{this.isDisabled=!1,this.toast(e.message,"danger")}))}async openAlipay(){if(!this.isDisabled){this.isLoading=!0;try{this.isDisabled=!0;let e=await this.getAliPayUrl();console.log(e),await this.certificatePay();const t=document.createElement("div");t.innerHTML=e;const n=t.querySelector("form");if(n){n.addEventListener("submit",(e=>{e.preventDefault()}));const e=document.createElement("iframe");e.style.display="none",document.body.appendChild(e),n.target=e.name,console.log(n),document.body.appendChild(n),n.submit(),document.body.removeChild(n)}else console.error("未找到表单元素"),this.isLoading=!1;this.timer=setInterval((async()=>{console.log("支付结果轮询");let e=new Parse$9.Query("AccountLog");e.equalTo("company",this.wxjssdk.company),e.equalTo("orderNumber",this.tradeNo),e.equalTo("payType","alipay"),e.equalTo("isVerified",!0);let t=await e.first();this.isLoading=!1,t&&t.id&&(clearInterval(this.timer),this.timer=null),this.timer||(this.toast("支付成功","success"),this.isOpen=!1,this.payResult.emit({code:200,tradeNo:this.tradeNo,type:this.checkpay}))}),1e3)}catch(e){this.isLoading=!1,this.isDisabled=!1,(await this.alertCtrl.create({header:"异常错误",subHeader:"",message:e.message,buttons:[{role:"ok",text:"确认",handler:()=>{}}]})).present()}}}async getAliPayUrl(){return new Promise(((e,t)=>{let n=window.location.href,o={company:this.wxjssdk.company,tradeNo:this.tradeNo,price:this.price,tradetype:"wap",orderTitle:this.title,returnUrl:n,returnType:"get",rechargeRule:this.isRechargeRule};try{this.http.post("https://server.fmode.cn/api/alipay/neworder",o).pipe(catchError((async e=>{console.error(e),this.isDisabled=!1,this.isLoading=!1,this.toast("支付失败:"+e?.error?.mess,"fail")}))).subscribe((t=>{200===t.code?t.data&&t.data.pay_url&&e(t.data.pay_url):this.toast("网络错误,请稍后重试","warning")}))}catch(e){e&&(this.toast("网络错误,请稍后重试","warning"),t(e))}}))}updateOrder(e){let t=this;t.timer=setInterval((()=>{let n={out_trade_no:t.tradeNo,nonce_str:e,company:this.wxjssdk.company};Parse$9.Cloud.run("order_status2",n).then((async e=>{e.status&&"SUCCESS"==e.status[0]&&(clearInterval(t.timer),this.isRechargeRule&&(this.orderId?this.payServer.updateAccountLog(n,this.orderId):"recharge"==this.orderType&&(this.accountLog=await this.payServer.updateRecharge(this.accountLog))),t.toast("支付成功","success"),t.isOpen=!1,t.payResult.emit({code:200,tradeNo:this.tradeNo,type:this.checkpay}))})).catch((e=>{}))}),3e3)}async certificatePay(){if(await this.payServer.createdAccountLog({company:this.wxjssdk.company,orderId:this.orderId,tradeNo:this.tradeNo,price:this.price,payType:this.checkpay,orderType:this.orderType}),this.isRechargeRule)if("vip"==this.orderType&&!this.orderId&&this.gid){let e=await this.payServer.setOrder({type:"service",gid:this.gid,price:this.price,total_fee:this.price,tradeNo:this.tradeNo,out_trade_no:this.tradeNo,payType:this.checkpay,code:this.codeLink});console.log(e),e?.objectId&&(this.orderId=e.objectId)}else"recharge"==this.orderType&&(this.accountLog=await this.payServer.creatdRechargeLog({tradeNo:this.tradeNo,payType:this.checkpay,price:this.price,credit:this.credit}))}onClose(){this.isOpen=!1;const e={code:0,tradeNo:this.tradeNo,type:this.checkpay};this.payResult.emit(e)}toast(e,t){const n=document.createElement("div"),o=t??"warning",i={success:{bg:"#10dc60",text:"#fff"},danger:{bg:"#f04141",text:"#fff"},fail:{bg:"#f04141",text:"#fff"},warning:{bg:"#ffce00",text:"#000"}};Object.assign(n.style,{position:"fixed",bottom:"20px",left:"50%",transform:"translateX(-50%)",padding:"12px 20px",borderRadius:"4px",zIndex:"9999",fontSize:"14px",textAlign:"center",minWidth:"200px",boxShadow:"0 3px 5px rgba(0,0,0,0.2)",opacity:"0",transition:"opacity 0.3s ease-in-out",backgroundColor:i[o]?.bg||i.warning.bg,color:i[o]?.text||i.warning.text}),n.textContent=e,document.body.appendChild(n),requestAnimationFrame((()=>{n.style.opacity="1",setTimeout((()=>{n.style.opacity="0",setTimeout((()=>document.body.removeChild(n)),300)}),1500)}))}ngOnDestroy(){this.timer&&clearInterval(this.timer)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PaymentComponent,deps:[{token:WechatJssdkService},{token:i1.HttpClient},{token:i1$1.ActivatedRoute},{token:PaymentService},{token:i1$3.AlertController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:PaymentComponent,isStandalone:!0,selector:"fm-payment",inputs:{price:"price",tradeNo:"tradeNo",title:"title",showTypes:"showTypes",orderType:"orderType",isRechargeRule:"isRechargeRule",credit:"credit",gid:"gid",orderId:"orderId",isOpen:"isOpen"},outputs:{payResult:"payResult"},ngImport:i0,template:'@if (isOpen) {\n <div class="payment-overlay">\n \x3c!-- 全局 Loading --\x3e\n @if (isLoading) {\n <div class="global-loading">\n <div class="loading-spinner"></div>\n <div class="loading-text">处理中...</div>\n </div>\n }\n\n <div class="payment-box" [class.blur-effect]="isLoading">\n <div class="pay-box">\n <div class="close-btn" (click)="!isLoading && onClose()">\n <span class="close-icon"></span>\n </div>\n @if (!codeLink) {\n <div class="pay-title">支付订单</div>\n <div class="pay-num">¥{{ price || 0 }}</div>\n <div class="options">\n @if (showTypes.includes("wxpay")) {\n <div class="row" (click)="onchangPay(\'wxpay\')">\n <div class="label">\n <img\n src="https://file-cloud.fmode.cn/E4KpGvTEto/20231123/s1sun8061000007.png"\n alt="微信支付"\n class="icon"\n />\n <div class="text">微信支付</div>\n </div>\n <div class="check" [class.check-active]="checkpay === \'wxpay\'">\n <div class="checkbox"></div>\n </div>\n </div>\n }\n @if (showTypes.length > 1) {\n <div class="divider"></div>\n }\n @if (showTypes.includes("alipay")) {\n <div class="row" (click)="onchangPay(\'alipay\')">\n <div class="label">\n <img\n src="https://file-cloud.fmode.cn/storage/company/E4KpGvTEto/20250815/110934166.png"\n alt="支付宝"\n class="icon"\n />\n <div class="text">支付宝</div>\n </div>\n <div class="check" [class.check-active]="checkpay === \'alipay\'">\n <div class="checkbox"></div>\n </div>\n </div>\n }\n </div>\n <div class="pay-footer">\n <div class="order-num">订单编号:{{ tradeNo ? tradeNo : "-" }}</div>\n <div\n class="pay-btn"\n (click)="!isLoading && userPayment()"\n [class.disabled]="isLoading || !checkpay"\n >\n 去付款\n @if (isLoading) {\n <span class="btn-loading"></span>\n }\n </div>\n </div>\n } @else {\n <div class="qrcode-section">\n <qr-code [value]="codeLink" value="请使用手机扫描二维码完成支付" [size]="180"></qr-code>\n <p class="qrcode-tip">请使用手机扫描二维码完成支付</p>\n </div>\n }\n </div>\n </div>\n </div>\n}\n',styles:['@charset "UTF-8";.global-loading{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1001;background:#ffffffe6;padding:20px 30px;border-radius:8px;box-shadow:0 2px 10px #0000001a;display:flex;flex-direction:column;align-items:center}.global-loading .loading-spinner{width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #1890ff;border-radius:50%;animation:spin 1s linear infinite;margin-bottom:10px}.global-loading .loading-text{color:#333;font-size:14px}.blur-effect{filter:blur(2px);pointer-events:none}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.payment-overlay{position:fixed;inset:0;background-color:#00000080;display:flex;justify-content:center;align-items:center;z-index:1000;animation:fadeIn .3s ease}.payment-box{width:90%;max-width:400px;background:#fff;border-radius:12px;box-shadow:0 4px 20px #00000026;animation:slideUp .3s ease;overflow:hidden}.pay-box{padding:20px;position:relative}.pay-box .close{position:absolute;right:16px;top:16px;font-size:24px;color:#999;cursor:pointer;transition:color .2s;padding:8px}.pay-box .close:hover{color:#666}.pay-box .pay-title{text-align:center;font-size:18px;font-weight:600;color:#333;margin-bottom:8px}.pay-box .pay-num{text-align:center;font-size:28px;color:#1890ff;margin:12px auto;font-weight:700}.pay-box .options{margin:20px 0}.pay-box .options .row{display:flex;align-items:center;justify-content:space-between;cursor:pointer;transition:background-color .2s;border-radius:8px;padding:12px}.pay-box .options .row:hover{background-color:#f9f9f9}.pay-box .options .row .label{display:flex;align-items:center}.pay-box .options .row .label img{width:32px;height:32px;object-fit:contain}.pay-box .options .row .label .text{font-size:16px;margin-left:12px;color:#333}.pay-box .options .row .check{border:2px solid #ddd;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;transition:all .2s}.pay-box .options .row .check .checkbox{width:12px;height:12px;border-radius:50%;background:transparent;transition:background .2s}.pay-box .options .row .check-active{border-color:#1890ff}.pay-box .options .row .check-active .checkbox{background:#1890ff}.pay-box .options .divider{margin:8px 0;height:1px;background:#eee}.pay-box .pay-footer{display:flex;flex-direction:column;align-items:center;margin-top:20px}.pay-box .pay-footer .order-num{color:#999;font-size:14px;margin-bottom:16px}.pay-box .pay-footer .pay-btn{padding:12px 0;width:100%;color:#fff;text-align:center;background:#1890ff;border-radius:8px;font-size:16px;font-weight:500;cursor:pointer;transition:background .2s;border:none;position:relative}.pay-box .pay-footer .pay-btn:hover,.pay-box .pay-footer .pay-btn:active{background:#1166b5}.pay-box .pay-footer .pay-btn.disabled{background:#ccc!important;cursor:not-allowed}.pay-box .pay-footer .pay-btn .btn-loading{display:inline-block;width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top:2px solid white;border-radius:50%;animation:spin .8s linear infinite;margin-left:8px;vertical-align:middle}.pay-box .qrcode{display:flex;justify-content:center;align-items:center;padding:20px}.pay-box .qrcode img{max-width:100%;height:auto;border:1px solid #eee;border-radius:8px}.pay-box .qrcode-section{text-align:center;margin:20px 0;padding:15px}.pay-box .qrcode-section .qrcode-image{max-width:200px;height:auto;border:1px solid #ddd;padding:10px;background:#fff}.pay-box .qrcode-section .qrcode-tip{margin-top:10px;font-size:14px;color:#666}.close-btn{position:absolute;right:16px;top:16px;width:40px;height:40px;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:50%;transition:background-color .2s ease;z-index:1}.close-btn:hover{background-color:#0000000d}.close-btn:active{background-color:#0000001a}.close-icon{position:relative;width:20px;height:20px}.close-icon:before,.close-icon:after{content:"";position:absolute;top:50%;left:50%;width:100%;height:2px;background-color:#666;border-radius:1px}.close-icon:before{transform:translate(-50%,-50%) rotate(45deg)}.close-icon:after{transform:translate(-50%,-50%) rotate(-45deg)}.close-btn.disabled{pointer-events:none;opacity:.5}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"ngmodule",type:QrCodeModule},{kind:"component",type:i6$1.QrCodeComponent,selector:"qr-code",inputs:["value","size","darkColor","lightColor","errorCorrectionLevel","centerImageSrc","centerImageSize","margin"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PaymentComponent,decorators:[{type:Component,args:[{selector:"fm-payment",standalone:!0,imports:[CommonModule,QrCodeModule],template:'@if (isOpen) {\n <div class="payment-overlay">\n \x3c!-- 全局 Loading --\x3e\n @if (isLoading) {\n <div class="global-loading">\n <div class="loading-spinner"></div>\n <div class="loading-text">处理中...</div>\n </div>\n }\n\n <div class="payment-box" [class.blur-effect]="isLoading">\n <div class="pay-box">\n <div class="close-btn" (click)="!isLoading && onClose()">\n <span class="close-icon"></span>\n </div>\n @if (!codeLink) {\n <div class="pay-title">支付订单</div>\n <div class="pay-num">¥{{ price || 0 }}</div>\n <div class="options">\n @if (showTypes.includes("wxpay")) {\n <div class="row" (click)="onchangPay(\'wxpay\')">\n <div class="label">\n <img\n src="https://file-cloud.fmode.cn/E4KpGvTEto/20231123/s1sun8061000007.png"\n alt="微信支付"\n class="icon"\n />\n <div class="text">微信支付</div>\n </div>\n <div class="check" [class.check-active]="checkpay === \'wxpay\'">\n <div class="checkbox"></div>\n </div>\n </div>\n }\n @if (showTypes.length > 1) {\n <div class="divider"></div>\n }\n @if (showTypes.includes("alipay")) {\n <div class="row" (click)="onchangPay(\'alipay\')">\n <div class="label">\n <img\n src="https://file-cloud.fmode.cn/storage/company/E4KpGvTEto/20250815/110934166.png"\n alt="支付宝"\n class="icon"\n />\n <div class="text">支付宝</div>\n </div>\n <div class="check" [class.check-active]="checkpay === \'alipay\'">\n <div class="checkbox"></div>\n </div>\n </div>\n }\n </div>\n <div class="pay-footer">\n <div class="order-num">订单编号:{{ tradeNo ? tradeNo : "-" }}</div>\n <div\n class="pay-btn"\n (click)="!isLoading && userPayment()"\n [class.disabled]="isLoading || !checkpay"\n >\n 去付款\n @if (isLoading) {\n <span class="btn-loading"></span>\n }\n </div>\n </div>\n } @else {\n <div class="qrcode-section">\n <qr-code [value]="codeLink" value="请使用手机扫描二维码完成支付" [size]="180"></qr-code>\n <p class="qrcode-tip">请使用手机扫描二维码完成支付</p>\n </div>\n }\n </div>\n </div>\n </div>\n}\n',styles:['@charset "UTF-8";.global-loading{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1001;background:#ffffffe6;padding:20px 30px;border-radius:8px;box-shadow:0 2px 10px #0000001a;display:flex;flex-direction:column;align-items:center}.global-loading .loading-spinner{width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #1890ff;border-radius:50%;animation:spin 1s linear infinite;margin-bottom:10px}.global-loading .loading-text{color:#333;font-size:14px}.blur-effect{filter:blur(2px);pointer-events:none}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.payment-overlay{position:fixed;inset:0;background-color:#00000080;display:flex;justify-content:center;align-items:center;z-index:1000;animation:fadeIn .3s ease}.payment-box{width:90%;max-width:400px;background:#fff;border-radius:12px;box-shadow:0 4px 20px #00000026;animation:slideUp .3s ease;overflow:hidden}.pay-box{padding:20px;position:relative}.pay-box .close{position:absolute;right:16px;top:16px;font-size:24px;color:#999;cursor:pointer;transition:color .2s;padding:8px}.pay-box .close:hover{color:#666}.pay-box .pay-title{text-align:center;font-size:18px;font-weight:600;color:#333;margin-bottom:8px}.pay-box .pay-num{text-align:center;font-size:28px;color:#1890ff;margin:12px auto;font-weight:700}.pay-box .options{margin:20px 0}.pay-box .options .row{display:flex;align-items:center;justify-content:space-between;cursor:pointer;transition:background-color .2s;border-radius:8px;padding:12px}.pay-box .options .row:hover{background-color:#f9f9f9}.pay-box .options .row .label{display:flex;align-items:center}.pay-box .options .row .label img{width:32px;height:32px;object-fit:contain}.pay-box .options .row .label .text{font-size:16px;margin-left:12px;color:#333}.pay-box .options .row .check{border:2px solid #ddd;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;transition:all .2s}.pay-box .options .row .check .checkbox{width:12px;height:12px;border-radius:50%;background:transparent;transition:background .2s}.pay-box .options .row .check-active{border-color:#1890ff}.pay-box .options .row .check-active .checkbox{background:#1890ff}.pay-box .options .divider{margin:8px 0;height:1px;background:#eee}.pay-box .pay-footer{display:flex;flex-direction:column;align-items:center;margin-top:20px}.pay-box .pay-footer .order-num{color:#999;font-size:14px;margin-bottom:16px}.pay-box .pay-footer .pay-btn{padding:12px 0;width:100%;color:#fff;text-align:center;background:#1890ff;border-radius:8px;font-size:16px;font-weight:500;cursor:pointer;transition:background .2s;border:none;position:relative}.pay-box .pay-footer .pay-btn:hover,.pay-box .pay-footer .pay-btn:active{background:#1166b5}.pay-box .pay-footer .pay-btn.disabled{background:#ccc!important;cursor:not-allowed}.pay-box .pay-footer .pay-btn .btn-loading{display:inline-block;width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top:2px solid white;border-radius:50%;animation:spin .8s linear infinite;margin-left:8px;vertical-align:middle}.pay-box .qrcode{display:flex;justify-content:center;align-items:center;padding:20px}.pay-box .qrcode img{max-width:100%;height:auto;border:1px solid #eee;border-radius:8px}.pay-box .qrcode-section{text-align:center;margin:20px 0;padding:15px}.pay-box .qrcode-section .qrcode-image{max-width:200px;height:auto;border:1px solid #ddd;padding:10px;background:#fff}.pay-box .qrcode-section .qrcode-tip{margin-top:10px;font-size:14px;color:#666}.close-btn{position:absolute;right:16px;top:16px;width:40px;height:40px;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:50%;transition:background-color .2s ease;z-index:1}.close-btn:hover{background-color:#0000000d}.close-btn:active{background-color:#0000001a}.close-icon{position:relative;width:20px;height:20px}.close-icon:before,.close-icon:after{content:"";position:absolute;top:50%;left:50%;width:100%;height:2px;background-color:#666;border-radius:1px}.close-icon:before{transform:translate(-50%,-50%) rotate(45deg)}.close-icon:after{transform:translate(-50%,-50%) rotate(-45deg)}.close-btn.disabled{pointer-events:none;opacity:.5}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}\n']}]}],ctorParameters:()=>[{type:WechatJssdkService},{type:i1.HttpClient},{type:i1$1.ActivatedRoute},{type:PaymentService},{type:i1$3.AlertController}],propDecorators:{price:[{type:Input,args:["price"]}],tradeNo:[{type:Input,args:["tradeNo"]}],title:[{type:Input,args:["title"]}],showTypes:[{type:Input,args:["showTypes"]}],orderType:[{type:Input,args:["orderType"]}],isRechargeRule:[{type:Input,args:["isRechargeRule"]}],credit:[{type:Input,args:["credit"]}],gid:[{type:Input,args:["gid"]}],orderId:[{type:Input,args:["orderId"]}],payResult:[{type:Output}],isOpen:[{type:Input,args:["isOpen"]}]}});const Parse$8=defaultExport.with("nova");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$8.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$8.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$8.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$8.Query("_User");e.contains("username",this.registPhone),e.equalTo("company",this.companyId);let t=await e.first();t?.id?this.message.info("该账户已激活,使用手机号密码直接登录"):Parse$8.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$8.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$8.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$8.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$8.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$8.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: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: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:i1$3.ToastController},{type:i1$1.Router},{type:i1$1.ActivatedRoute},{type:i1$1.ActivatedRoute},{type:i1.HttpClient}]});const Parse$7=defaultExport.with("nova");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.loginSuccess=new EventEmitter,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.authServ.loginMobilePassword(this.mobile,this.password,this.msg).then((e=>{this.loginSuccess.emit({user:Parse$7.User.current(),data:e}),this.setActiveButton("账号密码")}))})).catch((e=>{this.msg.error("注册失败,请更换手机号注册")})):this.msg.error("两次输入密码不同,请检查"):this.msg.error("请输入完整手机号和密码")}async loginMobilePassword(){if(!this.mobile||!this.password)return void this.msg.error("请输入完整手机号和密码");let e=await this.authServ.loginMobilePassword(this.mobile,this.password,this.msg,(()=>{console.log("登录成功",e),this.loginSuccess.emit({user:Parse$7.User.current(),data:e})}))}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$7.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}$/))if(this.loginInfo.code){this.loginInfo.code=this.loginInfo.code?.slice(0,6);try{e=await this.authServ.loginCode(this.loginInfo.mobile,this.loginInfo.code,this.msg,(()=>{let t=Parse$7.User.current();(e||t?.id)&&(this.loginSuccess.emit({user:t,res:e}),console.log(e,t?.id,"close"),this.close(),this.loginInfo={mobile:"",code:""},this.localCodeNum="",this.toast({color:"success",message:"登录成功"}),this.authServ.guardType)}))}catch(e){}}else this.msg.error("请输入短信验证码");else this.msg.error("请填写正确手机号")}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",outputs:{loginSuccess:"loginSuccess"},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 - 480px);height:530px;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{max-height:60px;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;margin:auto;padding:10px 10%;border-radius:10px}.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;padding:16px 0}.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:42px;padding:6px;border-radius:10px;line-height:40px;font-size:16px;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: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 - 480px);height:530px;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{max-height:60px;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;margin:auto;padding:10px 10%;border-radius:10px}.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;padding:16px 0}.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:42px;padding:6px;border-radius:10px;line-height:40px;font-size:16px;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"]}],loginSuccess:[{type:Output}],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: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}]}});const Parse$6=defaultExport.with("nova");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,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,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,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]}]}]});const Parse$5=defaultExport.with("nova");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$5.User.current();if(!t?.id)return;let n=localStorage.getItem("staffid");e&&(n=null);let o,i=new Parse$5.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}]});const Parse$4=defaultExport.with("nova");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$4.User.current()}set user(e){this._user=e}constructor(e){this.router=e,this.user=Parse$4.User.current()}async getProfile(){if(this.profile?.id)return this.profile;if(this.profileId){let e=new Parse$4.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$4.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$4.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}]});const Parse$3=defaultExport.with("nova");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}]});const Parse$2=defaultExport.with("nova");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}]}});const Parse$1=defaultExport.with("nova");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$1.User.current(),this.loadProfiles()}async loadProfiles(){this.isLoading=!0;try{let e=new Parse$1.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$1.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: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.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]}]}]});const Parse=defaultExport.with("nova");class CompMobileBindComponent{mobileChange(e){console.log(e),this.mobile=e?.detail?.value}codeChange(e){this.code=e?.detail?.value}async sendSmsCode(){this.startCountdown();/^1[3-9]\d{9}$/.test(this.mobile)?(await this.ncloud.apig("message",{company:this.cid,mobile:this.mobile},"POST"),this.isSended=!0,setTimeout((()=>{this.codeInput?.setFocus()}),500)):this.presentAlert("请检查手机号")}startCountdown(){this.countdown=60,this.countInt=setInterval((()=>{this.countdown--,0==this.countdown&&this.countInt&&clearInterval(this.countInt)}),1e3)}async presentAlert(e){const t=await this.alertCtrl.create({header:"提示",subHeader:e,buttons:["确定"]});await t.present()}constructor(e,t,n){this.modalCtrl=e,this.alertCtrl=t,this.ncloud=n,this.mobile="",this.code="",this.isSended=!1,this.countdown=0,this.isVerifying=!1}ngAfterViewInit(){setTimeout((()=>{this.mobileInput.setFocus()}),500)}async verifyMobile(){if(this.isVerifying)return;this.isVerifying=!0;let e=await this.ncloud.api(`/auth/mobile?company=${this.cid}&mobile=${this.mobile}&code=${this.code}`,null,"GET");if(e?.token){console.log(200,e);let t=await Parse.User.become(e.token);t?.id&&(this.modalCtrl.dismiss({mobile:this.mobile,user:t},"confirm"),this.countInt&&clearInterval(this.countInt))}this.isVerifying=!1}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompMobileBindComponent,deps:[{token:i1$3.ModalController},{token:i1$3.AlertController},{token:NovaCloudService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:CompMobileBindComponent,isStandalone:!0,selector:"app-comp-mobile-bind",inputs:{cid:"cid"},viewQueries:[{propertyName:"mobileInput",first:!0,predicate:["mobileInput"],descendants:!0,read:IonInput},{propertyName:"codeInput",first:!0,predicate:["codeInput"],descendants:!0,read:IonInput}],ngImport:i0,template:'\x3c!-- 用户登录状态 --\x3e\n<ion-card>\n <ion-card-header>\n <ion-card-title>\n 验证手机\n \x3c!-- <ion-segment [value]="type" (ionChange)="typeChange($event)">\n <ion-segment-button value="login">\n <ion-label>登录</ion-label>\n </ion-segment-button>\n <ion-segment-button value="signup">\n <ion-label>注册</ion-label>\n </ion-segment-button>\n </ion-segment> --\x3e\n </ion-card-title>\n \x3c!-- <ion-card-subtitle>请输入账号密码</ion-card-subtitle> --\x3e\n </ion-card-header>\n <ion-card-content>\n <ion-item>\n <ion-input #mobileInput [value]="mobile" (ionChange)="mobileChange($event)" label="手机号" placeholder="请您输入手机号"></ion-input>\n </ion-item>\n @if(isSended){\n <ion-item>\n <ion-input #codeInput [value]="code" (ionChange)="codeChange($event)" label="验证码" placeholder="请您输入6位数字"></ion-input>\n @if(countdown){\n <ion-button color="light">{{countdown}}</ion-button>\n }\n </ion-item>\n }\n @if(!countdown){\n <ion-button expand="block" (click)="sendSmsCode()">获取验证码</ion-button>\n }\n @if(isSended && countdown){\n <ion-button expand="block" (click)="verifyMobile()" [disabled]="isVerifying">确认</ion-button>\n }\n </ion-card-content>\n </ion-card>',styles:[""],dependencies:[{kind:"component",type:IonCard,selector:"ion-card",inputs:["button","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:IonCardContent,selector:"ion-card-content",inputs:["mode"]},{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:IonCardHeader,selector:"ion-card-header",inputs:["color","mode","translucent"]},{kind:"component",type:IonCardTitle,selector:"ion-card-title",inputs:["color","mode"]},{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:IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]}]})}}async function openMobileBindModal(e,t){console.log("openMobileBindModal");let n=Parse.User.current();if(n?.get("mobile"))return n?.get("mobile");let o=await e.create({component:CompMobileBindComponent,componentProps:{cid:t?.cid},cssClass:"modal-mobile-bind",backdropDismiss:!1,keyboardClose:!1,breakpoints:[.3,.5],initialBreakpoint:.3});await o.present();const{data:i,role:a}=await o.onWillDismiss();return"confirm"===a&&i?.mobile?i.mobile:null}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompMobileBindComponent,decorators:[{type:Component,args:[{selector:"app-comp-mobile-bind",standalone:!0,imports:[IonHeader,IonToolbar,IonTitle,IonContent,IonCard,IonCardContent,IonButton,IonCardHeader,IonCardTitle,IonCardSubtitle,IonInput,IonItem,IonSegment,IonSegmentButton,IonLabel],template:'\x3c!-- 用户登录状态 --\x3e\n<ion-card>\n <ion-card-header>\n <ion-card-title>\n 验证手机\n \x3c!-- <ion-segment [value]="type" (ionChange)="typeChange($event)">\n <ion-segment-button value="login">\n <ion-label>登录</ion-label>\n </ion-segment-button>\n <ion-segment-button value="signup">\n <ion-label>注册</ion-label>\n </ion-segment-button>\n </ion-segment> --\x3e\n </ion-card-title>\n \x3c!-- <ion-card-subtitle>请输入账号密码</ion-card-subtitle> --\x3e\n </ion-card-header>\n <ion-card-content>\n <ion-item>\n <ion-input #mobileInput [value]="mobile" (ionChange)="mobileChange($event)" label="手机号" placeholder="请您输入手机号"></ion-input>\n </ion-item>\n @if(isSended){\n <ion-item>\n <ion-input #codeInput [value]="code" (ionChange)="codeChange($event)" label="验证码" placeholder="请您输入6位数字"></ion-input>\n @if(countdown){\n <ion-button color="light">{{countdown}}</ion-button>\n }\n </ion-item>\n }\n @if(!countdown){\n <ion-button expand="block" (click)="sendSmsCode()">获取验证码</ion-button>\n }\n @if(isSended && countdown){\n <ion-button expand="block" (click)="verifyMobile()" [disabled]="isVerifying">确认</ion-button>\n }\n </ion-card-content>\n </ion-card>'}]}],ctorParameters:()=>[{type:i1$3.ModalController},{type:i1$3.AlertController},{type:NovaCloudService}],propDecorators:{mobileInput:[{type:ViewChild,args:["mobileInput",{read:IonInput}]}],codeInput:[{type:ViewChild,args:["codeInput",{read:IonInput}]}],cid:[{type:Input}]}});export{AccountService,AgentPrompt,AgentStory,AgentTaskStep,AudioPlayer,AuthPcuserGuard,AuthProfileGuard,AuthProfileService,AuthService,AuthStaffGuard,AvatarModule,AvatarRoutes,CaptchaComponent,ChatContentPipe,ChatListComponent,ChatPanelComponent,ChatService,ClipboardService,CodemirrorComponent,CompAvatarParticleComponent,CompAvatarRoleImageComponent,CompAvatarRoleVideoComponent,CompAvatarTalkComponent,CompMobileBindComponent,CompPoiPickerComponent,CompPoiPickerModule,CompRolePromptComponent,CompUserAvatarComponent,CrossService,DingTalkAuth,DurationStrPipe,FiletypePipe,FmAgentTaskComponent,FmChatHeaderArea,FmChatMessageCard,FmChatMesssageArea,FmChatModalInput,FmPushAudioOutputStreamCallback,FmTextQuillComponent,FmVideoComponent,FmaiService,FmodeChat,FmodeChatCompletion,FmodeGeoPoint,FmodeLoadingController,FmodeLoadingInstance,FmodeMapModule,FmodeObject,defaultExport as FmodeParse,FmodeQuery,FmodeStorgeModule,FmodeTTS,FmodeTTSProviderDoubao,FmodeUser,FmodeVoiceService,HidexmlPipe,HwobsManagerComponent,HwobsProvider,HwobsService,ImagineService,ImagineWork,LoginComponent,MASK_LIST,MarkdownMathJax,MarkdownParse,MarkdownPreviewComponent,MarkdownPreviewModule,ModalAudioMessageComponent,ModalChatVoiceInputComponent,ModalUserLoginComponent,NovaCloudService,NovaStorage,NovaUploadService,PCMStreamer,PaymentComponent,ProfileBindComponent,ProfileModule,ProfileRoutes,QiniuProvider,StaffModule,StaffService,TipsController,UserModule,UserNamePipe,UserRoutes,UtilnowPipe,WechatJssdkService,WwRequest,WxworkAuth,WxworkAuthGuard,WxworkCorp,WxworkSDK,apig,buildFullUrl,calcFileMd5,checkWeworkLogin,completionJSON,drawDalle,extractJSON,getFileMetadata,getJimengI_v,getJimengImg,getJimengT_v,getJimengV_data,getMessageContentText,getMessageImageUrl,jsApiList,ncloudApi,novaql,openChatPanelModal,openMobileBindModal,wxdebug};
8
+ import{PromptTemplate}from"@langchain/core/prompts";import{Subject,Observable,bufferTime,concatMap,delay,finalize,interval,take,map,of,BehaviorSubject,combineLatest}from"rxjs";import{bufferWhen,takeUntil,filter,catchError}from"rxjs/operators";import pako from"pako";import{v4}from"uuid";import Recorder from"recorder-core";import"recorder-core/src/engine/pcm";import"recorder-core/src/engine/wav";import"recorder-core/src/extensions/waveview";import CryptoJS from"crypto-js";import*as ww from"@wecom/jssdk";import*as dd from"dingtalk-jsapi";import*as qiniu from"qiniu-js";import*as SparkMD5 from"spark-md5";import ObsClient from"esdk-obs-browserjs";import*as i0 from"@angular/core";import{Injectable,Pipe,Input,ViewChild,Component,NgModule,EventEmitter,Output,Inject,forwardRef,ChangeDetectionStrategy,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,IonModal as IonModal$1}from"@ionic/angular";import*as i2 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 i5 from"@awesome-cordova-plugins/diagnostic/ngx";import{Diagnostic}from"@awesome-cordova-plugins/diagnostic/ngx";import{MediaCapture}from"@awesome-cordova-plugins/media-capture/ngx";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*as i6 from"@angular/forms";import{FormsModule,ReactiveFormsModule,NG_VALUE_ACCESSOR,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,IonCheckbox,IonCardContent,IonCardHeader,IonCardTitle,IonCardSubtitle,IonSegmentButton}from"@ionic/angular/standalone";import*as i3$1 from"@angular/material/button";import{MatButtonModule}from"@angular/material/button";import*as i1$4 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$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{resizeOutline,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 Quill from"quill";import{basicSetup,EditorView}from"codemirror";import{Compartment}from"@codemirror/state";import*as i6$1 from"ng-qrcode";import{QrCodeModule}from"ng-qrcode";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";class FmodeACL{static{this._instance=null}static bindInstance(e){this._instance=e}constructor(e){this.permissions={},e&&(this.permissions={...e})}setPublicReadAccess(e){return this.permissions["*"]=this.permissions["*"]||{read:!1,write:!1},this.permissions["*"].read=e,this}setPublicWriteAccess(e){return this.permissions["*"]=this.permissions["*"]||{read:!1,write:!1},this.permissions["*"].write=e,this}setReadAccess(e,t){const n="string"==typeof e?e:e.id;if(!n)throw new Error("Invalid user ID");return this.permissions[n]=this.permissions[n]||{read:!1,write:!1},this.permissions[n].read=t,this}setWriteAccess(e,t){const n="string"==typeof e?e:e.id;if(!n)throw new Error("Invalid user ID");return this.permissions[n]=this.permissions[n]||{read:!1,write:!1},this.permissions[n].write=t,this}getPublicReadAccess(){return!!this.permissions["*"]?.read}getPublicWriteAccess(){return!!this.permissions["*"]?.write}getReadAccess(e){const t="string"==typeof e?e:e.id;return!!this.permissions[t]?.read}getWriteAccess(e){const t="string"==typeof e?e:e.id;return!!this.permissions[t]?.write}toJSON(){return{...this.permissions}}}class FmodeQuery{static{this._instance=null}static bindInstance(e){this._instance=e}static get instance(){if(!this._instance)throw new Error("FmodeParse not initialized");return this._instance}get currentInstance(){return this._parseInstance||FmodeQuery.instance}static convertIncludedObjects(e){if(!e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map((e=>this.convertIncludedObjects(e)));if(e.objectId&&(e.createdAt||e.updatedAt)){const t=e.className||"Object",n=new FmodeObject(t);n.id=e.objectId,e.createdAt&&(n.createdAt="string"==typeof e.createdAt?new Date(e.createdAt):e.createdAt),e.updatedAt&&(n.updatedAt="string"==typeof e.updatedAt?new Date(e.updatedAt):e.updatedAt),e.ACL&&(n.ACL=e.ACL);const o={};for(const[t,n]of Object.entries(e))["__type","className","objectId","createdAt","updatedAt","ACL"].includes(t)||(o[t]=this.convertIncludedObjects(n));return n.set(o),n}if("Object"===e.__type&&e.className&&e.objectId){const t=new FmodeObject(e.className);t.id=e.objectId,e.createdAt&&(t.createdAt=new Date(e.createdAt)),e.updatedAt&&(t.updatedAt=new Date(e.updatedAt)),e.ACL&&(t.ACL=e.ACL);const n={};for(const[t,o]of Object.entries(e))["__type","className","objectId","createdAt","updatedAt","ACL"].includes(t)||(n[t]=this.convertIncludedObjects(o));return t.set(n),t}if("Pointer"===e.__type&&e.className&&e.objectId)return e;const t={};for(const[n,o]of Object.entries(e))t[n]=this.convertIncludedObjects(o);return t}constructor(e){this.where={},this._include=[],this._exclude=[],this._select=[],this._count=!1,this.className="string"==typeof e?e:e.prototype.constructor.name}equalTo(e,t){return t=this.fixPointer(t),this.where[e]=t,this}fixPointer(e){return e?.className&&e?.data?{__type:"Pointer",className:e?.className,objectId:e?.data?.id||e?.id}:e}notEqualTo(e,t){return t=this.fixPointer(t),this.where[e]={$ne:t},this}lessThan(e,t){return this.where[e]={$lt:t},this}lessThanOrEqualTo(e,t){return this.where[e]={$lte:t},this}greaterThan(e,t){return this.where[e]={$gt:t},this}greaterThanOrEqualTo(e,t){return this.where[e]={$gte:t},this}containedIn(e,t){return this.where[e]={$in:t},this}notContainedIn(e,t){return this.where[e]={$nin:t},this}exists(e){return this.where[e]={$exists:!0},this}doesNotExist(e){return this.where[e]={$exists:!1},this}containsAll(e,t){return this.where[e]={$all:t},this}contains(e,t){return this.where[e]={$regex:t,$options:"i"},this}startsWith(e,t){return this.where[e]={$regex:`^${t}`,$options:"i"},this}endsWith(e,t){return this.where[e]={$regex:`${t}$`,$options:"i"},this}matches(e,t,n){return this.where[e]={$regex:t.source,$options:n},this}matchesQuery(e,t){return this.where[e]={$inQuery:{className:t.className,where:t.where}},this}doesNotMatchQuery(e,t){return this.where[e]={$notInQuery:{className:t.className,where:t.where}},this}matchesKeyInQuery(e,t,n){return this.where[e]={$select:{key:t,query:{className:n.className,where:n.where}}},this}doesNotMatchKeyInQuery(e,t,n){return this.where[e]={$dontSelect:{key:t,query:{className:n.className,where:n.where}}},this}near(e,t){return this.where[e]={$nearSphere:t},this}withinRadians(e,t,n){return this.where[e]={$nearSphere:t,$maxDistance:n},this}withinMiles(e,t,n){return this.withinRadians(e,t,n/3959)}withinKilometers(e,t,n){return this.withinRadians(e,t,n/6371)}withinGeoBox(e,t,n){return this.where[e]={$within:{$box:[t,n]}},this}polygonContains(e,t){return this.where[e]={$geoWithin:{$polygon:t}},this}containedBy(e,t){return this.where[e]={$containedBy:t},this}fullText(e,t,n){return this.where[e]={$text:{$search:t,$caseSensitive:n?.caseSensitive,$diacriticSensitive:n?.diacriticSensitive}},this}containsAllStartingWith(e,t){return this.where[e]={$all:t.map((e=>({$regex:`^${e}`})))},this}sizeEqualTo(e,t){return this.where[e]={$size:t},this}relatedTo(e,t){if(!e.id)throw new Error("Parent object must have an ID");return this.where.$relatedTo={object:e.toPointer(),key:t},this}relatedToObject(e,t){if(!e.id)throw new Error("Parent object must have an ID");return this.where.$relatedTo={object:e.toPointer(),key:t},this}relatedToQuery(e,t,n){return this.where.$relatedTo={key:t,query:{className:e,where:n.where}},this}matchesPointer(e,t){if(!t.id)throw new Error("Object must have an ID");return this.where[e]=t.toPointer(),this}matchesAnyPointer(e,t){const n=t.map((e=>{if(!e.id)throw new Error("All objects must have IDs");return e.toPointer()}));return this.where[e]={$in:n},this}static async findRelation(e,t,n){if(!e.id)throw new Error("Parent object must have an ID");return new FmodeQuery(e.className).relatedTo(e,t).find(n)}static async countRelation(e,t,n){if(!e.id)throw new Error("Parent object must have an ID");return new FmodeQuery(e.className).relatedTo(e,t).count(n)}static async addToRelation(e,t,n,o){if(!e.id)throw new Error("Parent object must have an ID");if(n.some((e=>!e.id)))throw new Error("All objects to add must have IDs");const i=n.map((e=>e.toPointer())),a=e._parseInstance||FmodeQuery.instance,r=`${a.serverURL}/classes/${e.className}/${e.id}`,s={"Content-Type":"application/json","X-Parse-Application-Id":a.appId};if(o?.useMasterKey&&a.config.masterKey)s["X-Parse-Master-Key"]=a.config.masterKey;else{const e=a.sessionToken;e&&(s["X-Parse-Session-Token"]=e)}const l=await fetch(r,{method:"PUT",headers:s,body:JSON.stringify({[t]:{__op:"AddRelation",objects:i}})});if(!l.ok){const e=await l.json();throw new Error(e.error||"Failed to add to relation")}}static async removeFromRelation(e,t,n,o){if(!e.id)throw new Error("Parent object must have an ID");if(n.some((e=>!e.id)))throw new Error("All objects to remove must have IDs");const i=n.map((e=>e.toPointer())),a=e._parseInstance||FmodeQuery.instance,r=`${a.serverURL}/classes/${e.className}/${e.id}`,s={"Content-Type":"application/json","X-Parse-Application-Id":a.appId};if(o?.useMasterKey&&a.config.masterKey)s["X-Parse-Master-Key"]=a.config.masterKey;else{const e=a.sessionToken;e&&(s["X-Parse-Session-Token"]=e)}const l=await fetch(r,{method:"PUT",headers:s,body:JSON.stringify({[t]:{__op:"RemoveRelation",objects:i}})});if(!l.ok){const e=await l.json();throw new Error(e.error||"Failed to remove from relation")}}exclude(...e){let t={};return this._exclude.concat(e).forEach((e=>{t[e]=!0})),this._exclude=Object.keys(t),this}include(...e){let t={};return this._include.concat(e).forEach((e=>{t[e]=!0})),this._include=Object.keys(t),this}select(...e){return this._select=e,this}limit(e){return this._limit=e,this}skip(e){return this._skip=e,this}ascending(...e){return this._order=e.map((e=>e.startsWith("-")?e.substring(1):e)),this}descending(...e){return this._order=e.map((e=>e.startsWith("-")?e.substring(1):`-${e}`)),this}addAscending(...e){return this._order||(this._order=[]),this._order.push(...e),this}addDescending(...e){return this._order||(this._order=[]),this._order.push(...e.map((e=>`-${e}`))),this}readPreference(e){return this._readPreference=e,this}includeReadPreference(e){return this._includeReadPreference=e,this}excludeReadPreference(e){return this._excludeReadPreference=e,this}subqueryReadPreference(e){return this._subqueryReadPreference=e,this}hint(e){return this.hint=e,this}maxTimeMS(e){return this._maxTimeMS=e,this}explain(e=!0){return this._explain=e,this}withCount(e=!0){return this._count=e,this}async find(e){const t=this.currentInstance,n=new URL(`${t.serverURL}/classes/${this.className}`),o=this._buildQueryParams();Object.entries(o).forEach((([e,t])=>{void 0!==t&&n.searchParams.set(e,"string"==typeof t?t:JSON.stringify(t))}));const i={"X-Parse-Application-Id":t.appId};if(e?.useMasterKey&&t.config.masterKey)i["X-Parse-Master-Key"]=t.config.masterKey;else{const e=this._sessionToken||t.sessionToken;e&&(i["X-Parse-Session-Token"]=e)}const a=await fetch(n.toString(),{headers:i}),r=await a.json();if(209==r.code&&t.User.logOut(),r.error)throw console.error(a),new Error(r.error);return r.results.map((e=>{const t=new FmodeObject(this.className);t._parseInstance=this._parseInstance,t.id=e.objectId,e.createdAt&&(t.createdAt=new Date(e.createdAt)),e.updatedAt&&(t.updatedAt=new Date(e.updatedAt||e.createdAt)),e.ACL&&(t.ACL=e.ACL);const n={};for(const[t,o]of Object.entries(e))["__type","className","objectId","createdAt","updatedAt","ACL"].includes(t)||(this._include.includes(t)&&o&&"object"==typeof o&&o.objectId,n[t]=FmodeQuery.convertIncludedObjects(o));return t.set(n),t}))}async first(e){this.limit(1);return(await this.find(e))[0]||null}async get(e,t){const n=this.currentInstance,o=new URL(`${n.serverURL}/classes/${this.className}/${e}`);this._include.length>0&&o.searchParams.set("include",this._include.join(","));const i={"X-Parse-Application-Id":n.appId};if(t?.useMasterKey&&n.config.masterKey)i["X-Parse-Master-Key"]=n.config.masterKey;else{const e=this._sessionToken||n.sessionToken;e&&(i["X-Parse-Session-Token"]=e)}const a=await fetch(o.toString(),{headers:i}),r=await a.json();if(r.error)throw new Error(r.error);const s=new FmodeObject(this.className);s._parseInstance=this._parseInstance,s.id=r.objectId,r.createdAt&&(s.createdAt=new Date(r.createdAt)),r.updatedAt&&(s.updatedAt=new Date(r.updatedAt||r.createdAt)),r.ACL&&(s.ACL=r.ACL);const l={};for(const[e,t]of Object.entries(r))["__type","className","objectId","createdAt","updatedAt","ACL"].includes(e)||(this._include.includes(e)&&t&&"object"==typeof t&&t.objectId,l[e]=FmodeQuery.convertIncludedObjects(t));return s.set(l),s}async count(e){this.withCount();const t=this.currentInstance,n=new URL(`${t.serverURL}/classes/${this.className}`);n.searchParams.set("count","1"),n.searchParams.set("limit","0"),Object.keys(this.where).length>0&&n.searchParams.set("where",JSON.stringify(this.where));const o={"X-Parse-Application-Id":t.appId};if(e?.useMasterKey&&t.config.masterKey)o["X-Parse-Master-Key"]=t.config.masterKey;else{const e=this._sessionToken||t.sessionToken;e&&(o["X-Parse-Session-Token"]=e)}console.log(o,n?.href);const i=await fetch(n.toString(),{headers:o}),a=await i.json();if(a.error)throw new Error(a.error);return a.count||0}toJSON(){const e={className:this.className};return Object.keys(this.where).length>0&&(e.where=this.where),this._include.length>0&&(e.include=this._include.join(",")),this._exclude.length>0&&(e.exclude=this._exclude.join(",")),this._select.length>0&&(e.keys=this._select.join(",")),void 0!==this._limit&&(e.limit=this._limit),void 0!==this._skip&&(e.skip=this._skip),this._order&&this._order.length>0&&(e.order=this._order.join(",")),this._count&&(e.count=1),this._explain&&(e.explain=!0),this._hint&&(e.hint=this._hint),this._maxTimeMS&&(e.maxTimeMS=this._maxTimeMS),this._readPreference&&(e.readPreference=this._readPreference),this._includeReadPreference&&(e.includeReadPreference=this._includeReadPreference),this._excludeReadPreference&&(e.excludeReadPreference=this._excludeReadPreference),this._subqueryReadPreference&&(e.subqueryReadPreference=this._subqueryReadPreference),e}static fromJSON(e,t){const n=new FmodeQuery(e=e||t?.className);if(t.where&&(n.where=t.where),t.include){const e="string"==typeof t.include?t.include.split(","):t.include;n._include=e}if(t.exclude){const e="string"==typeof t.exclude?t.exclude.split(","):t.exclude;n._exclude=e}if(t.keys){const e="string"==typeof t.keys?t.keys.split(","):t.keys;n._select=e}if(void 0!==t.limit&&(n._limit=t.limit),void 0!==t.skip&&(n._skip=t.skip),t.order){const e="string"==typeof t.order?t.order.split(","):t.order;n._order=e}return t.count&&(n._count=!!t.count),t.explain&&(n._explain=!!t.explain),t.hint&&(n._hint=t.hint),t.maxTimeMS&&(n._maxTimeMS=t.maxTimeMS),t.readPreference&&(n._readPreference=t.readPreference),t.includeReadPreference&&(n._includeReadPreference=t.includeReadPreference),t.excludeReadPreference&&(n._excludeReadPreference=t.excludeReadPreference),t.subqueryReadPreference&&(n._subqueryReadPreference=t.subqueryReadPreference),n}_buildQueryParams(){const e={};return Object.keys(this.where).length>0&&(e.where=this.where),this._include.length>0&&(e.include=this._include.join(",")),this._exclude.length>0&&(e.excludeKeys=this._exclude.join(",")),this._select.length>0&&(e.keys=this._select.join(",")),void 0!==this._limit&&(e.limit=this._limit),void 0!==this._skip&&(e.skip=this._skip),this._order&&(e.order=this._order.join(",")),this._count&&(e.count=1),this._explain&&(e.explain=!0),this._hint&&(e.hint=this._hint),this._maxTimeMS&&(e.maxTimeMS=this._maxTimeMS),e}subscribe(){const e=new EventTarget,t=setInterval((async()=>{try{const t=await this.find();e.dispatchEvent(new CustomEvent("update",{detail:t}))}catch(t){e.dispatchEvent(new CustomEvent("error",{detail:t}))}}),5e3);return e.unsubscribe=()=>{clearInterval(t)},e}static or(...e){if(0===e.length)throw new Error("At least one query required");const t=e[0].className;if(e.some((e=>e.className!==t)))throw new Error("All queries must be for the same class");const n=new FmodeQuery(t);return n.where={$or:e.map((e=>e.where))},n}static and(...e){if(0===e.length)throw new Error("At least one query required");const t=e[0].className;if(e.some((e=>e.className!==t)))throw new Error("All queries must be for the same class");const n=new FmodeQuery(t);return n.where={$and:e.map((e=>e.where))},n}or(...e){return FmodeQuery.or(this,...e)}and(...e){return FmodeQuery.and(this,...e)}}class FmodeRelation{static{this._instance=null}static bindInstance(e){this._instance=e}constructor(e,t){this.__type="Relation",this.parent=e,this.key=t,this.className=e.className}add(e){if(!this.parent.id)throw new Error("Cannot add relation to unsaved object");if(Array.isArray(e)){e.map((e=>{if("function"!=typeof e.toPointer)throw new Error("Object does not have toPointer method");return e.toPointer()}))}else{if("function"!=typeof e.toPointer)throw new Error("Object does not have toPointer method");e.toPointer()}}remove(e){if(!this.parent.id)throw new Error("Cannot remove relation from unsaved object");e.map((e=>e.toPointer()))}query(){return new FmodeQuery(this.className).relatedTo(this.parent,this.key)}toJSON(){return{__type:"Relation",className:this.className}}}class FmodeObject{static{this._instance=null}static bindInstance(e){this._instance=e}constructor(e){this.data={},this.className=e,this._parseInstance=FmodeObject._instance}static extend(e){const t=class extends FmodeObject{constructor(){super(e)}};return t.extend=FmodeObject.extend,t.create=FmodeObject.create,t.fetchAll=FmodeObject.fetchAll,t.fromFile=FmodeObject.fromFile,t.bindInstance=FmodeObject.bindInstance,t._instance=FmodeObject._instance,t}toPointer(){return{__type:"Pointer",className:this.className,objectId:this.id}}toJSON(){const e={__type:"Object",className:this.className,...this.data};this.id&&(e.objectId=this.id),Object.keys(e).forEach((t=>{e[t]?.getTime?.()&&(e[t]={__type:"Date",iso:e[t].toISOString()})}));try{this.createdAt&&("string"==typeof this.createdAt&&(this.createdAt=new Date(this.createdAt)),e.createdAt={__type:"Date",iso:this.createdAt.toISOString()}),this.updatedAt&&("string"==typeof this.updatedAt&&(this.updatedAt=new Date(this.updatedAt)),console.log(this.updatedAt),e.updatedAt={__type:"Date",iso:this.updatedAt.toISOString()})}catch(e){}return this.ACL&&(e.ACL=this.ACL),e}get(e){return"Date"==this.data[e]?.__type?new Date(this.data[e]?.iso):this.data[e]}isoStrToDate(e){if(e?.indexOf?.("T")>-1&&e?.indexOf?.("Z")>-1&&24==e?.length)try{return new Date(e)}catch(e){}return e}set(e,t){return"object"==typeof e?(Object.keys(e).forEach((t=>{e[t]?.indexOf?.("T")>-1&&e[t]?.indexOf?.("Z")>-1&&(e[t]=this.isoStrToDate(e[t]))})),Object.assign(this.data,e)):(t&&(t=this.isoStrToDate(t)),this.data[e]=t),this}unset(e){return delete this.data[e],this}increment(e,t=1){const n=this.get(e)||0;return this.set(e,n+t),this}add(e,t){const n=this.get(e)||[];return this.set(e,[...n,...t]),this}addUnique(e,t){const n=new Set(this.get(e)||new Set);return t.forEach((e=>n.add(e))),this.set(e,Array.from(n)),this}remove(e,t){const n=this.get(e)||[],o=new Set(t);return this.set(e,n.filter((e=>!o.has(e)))),this}async save(e){const t=this._parseInstance||FmodeObject._instance;if(!t)throw new Error("Not initialized");const n=this.id?"PUT":"POST";let o=`${t.serverURL}/classes/${this.className}`;this.id&&(o+=`/${this.id}`);const i={"Content-Type":"application/json","X-Parse-Application-Id":t.appId};if(e?.useMasterKey&&t.config.masterKey)i["X-Parse-Master-Key"]=t.config.masterKey;else{const e=t.sessionToken;e&&(i["X-Parse-Session-Token"]=e)}const a=this.toJSON();delete a.createdAt,delete a.updatedAt,delete a.__type,delete a.className;for(const e in a)this.get(e)?.toPointer&&(a[e]=this.get(e).toPointer());let r,s;console.log(o,a);try{s=await fetch(o,{method:n,headers:i,body:JSON.stringify(a)}),console.log(JSON.stringify(a)),r=await s.json()}catch(e){alert(e)}if(console.log(r),r.error)throw new Error(r.error);return this.id=r.objectId||this.id,this.createdAt=new Date(r.createdAt||this.createdAt),this.updatedAt=new Date(r.updatedAt||this.updatedAt),this}async destroy(e){if(!this.id)throw new Error("Cannot destroy unsaved object");const t=this._parseInstance||FmodeObject._instance;if(!t)throw new Error("Not initialized");const n={"X-Parse-Application-Id":t.appId};if(e?.useMasterKey&&t.config.masterKey)n["X-Parse-Master-Key"]=t.config.masterKey;else{const e=t.sessionToken;e&&(n["X-Parse-Session-Token"]=e)}const o=`${t.serverURL}/classes/${this.className}/${this.id}`,i=await fetch(o,{method:"DELETE",headers:n});if(!i.ok){const e=await i.json();throw new Error(e.error||"Failed to delete object")}}static async create(e,t,n){const o=new this(e);return o.set(t),o.save(n)}static async fetchAll(e,t){if(!FmodeObject._instance)throw new Error("Not initialized");if(0===e.length)return[];const n={"Content-Type":"application/json","X-Parse-Application-Id":FmodeObject._instance.appId};if(t?.useMasterKey&&FmodeObject._instance.config.masterKey)n["X-Parse-Master-Key"]=FmodeObject._instance.config.masterKey;else{const e=FmodeObject._instance.sessionToken;e&&(n["X-Parse-Session-Token"]=e)}const o=`${FmodeObject._instance.serverURL}/batch`,i=e.map((e=>({method:"GET",path:`/classes/${e.className}/${e.id}`}))),a=await fetch(o,{method:"POST",headers:n,body:JSON.stringify({requests:i})}),r=await a.json();if(r.error)throw new Error(r.error);return r.map(((t,n)=>{const o=e[n];return o.set(t.success),o}))}relation(e){return new FmodeRelation(this,e)}static async fromFile(e,t,n){if(!FmodeObject._instance)throw new Error("Not initialized");const o=new FormData;o.append("file",t,e);const i={"X-Parse-Application-Id":FmodeObject._instance.appId},a=FmodeObject._instance.sessionToken;a&&(i["X-Parse-Session-Token"]=a);const r=`${FmodeObject._instance.serverURL}/files/${e}`,s=await fetch(r,{method:"POST",headers:i,body:o}),l=await s.json();if(l.error)throw new Error(l.error);return{__type:"File",name:l.name,url:l.url}}}class FmodeFile{static{this._instance=null}static bindInstance(e){this._instance=e}constructor(e,t){this.__type="File",this.name=e,this.data="object"==typeof t&&"base64"in t?this._base64ToArrayBuffer(t.base64):t,this.url=""}_base64ToArrayBuffer(e){const t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n.buffer}static async save(e,t,n){if(!FmodeObject._instance)throw new Error("Not initialized");const o=new FormData;if(t instanceof Blob||t instanceof File)o.append("file",t,e);else if(t instanceof ArrayBuffer){const i=new Blob([new Uint8Array(t)],{type:n?.type});o.append("file",i,e)}else{const i=new Blob([t],{type:n?.type||"text/plain"});o.append("file",i,e)}const i={"X-Parse-Application-Id":FmodeObject._instance.appId};n?.useMasterKey&&FmodeObject._instance.config.masterKey&&(i["X-Parse-Master-Key"]=FmodeObject._instance.config.masterKey);const a=`${FmodeObject._instance.serverURL}/files/${e}`,r=await fetch(a,{method:"POST",headers:i,body:o}),s=await r.json();if(s.error)throw new Error(s.error);return new FmodeFile(s.name,s.url)}toJSON(){return{__type:"File",name:this.name,url:this.url}}}class FmodeGeoPoint{static{this._instance=null}static bindInstance(e){this._instance=e}constructor(e,t){let n,o;if(this.__type="GeoPoint","object"==typeof e&&null!==e)n=e.latitude,o=e.longitude;else{if("number"!=typeof e||"number"!=typeof t)throw new Error("Invalid GeoPoint parameters. Use either GeoPoint(lat, lon) or GeoPoint({latitude, longitude})");n=e,o=t}if(n<-90||n>90)throw new Error("Latitude must be between -90 and 90");if(o<-180||o>180)throw new Error("Longitude must be between -180 and 180");this.latitude=n,this.longitude=o}static current(e){return new Promise(((t,n)=>{navigator.geolocation.getCurrentPosition((e=>{t(new FmodeGeoPoint(e.coords.latitude,e.coords.longitude))}),(e=>n(e)),e)}))}kilometersTo(e){return this._calculateDistance(e,"kilometers")}milesTo(e){return this._calculateDistance(e,"miles")}radiansTo(e){return this._calculateDistance(e,"radians")}_calculateDistance(e,t){const n={kilometers:6371,miles:3959,radians:1}[t],o=(e.latitude-this.latitude)*Math.PI/180,i=(e.longitude-this.longitude)*Math.PI/180,a=Math.sin(o/2)*Math.sin(o/2)+Math.cos(this.latitude*Math.PI/180)*Math.cos(e.latitude*Math.PI/180)*Math.sin(i/2)*Math.sin(i/2);return n*(2*Math.atan2(Math.sqrt(a),Math.sqrt(1-a)))}toJSON(){return{__type:"GeoPoint",latitude:this.latitude,longitude:this.longitude}}}class FmodeUser extends FmodeObject{static{this._instance=null}static{this.instanceKey=()=>{if(!this._instance)throw new Error("FmodeParse not initialized before using User");return"Parse/"+this._instance.appId+"/currentUser"}}static bindInstance(e){this._instance=e}static get instance(){if(!this._instance)throw new Error("FmodeParse not initialized");return this._instance}get username(){return this.get("username")}set username(e){this.set("username",e)}get email(){return this.get("email")}set email(e){this.set("email",e)}get password(){return this.get("password")}set password(e){this.set("password",e)}constructor(e){super("_User"),e&&(this.id=e?.objectId,this.createdAt=new Date(e?.createdAt),this.updatedAt=new Date(e?.updatedAt),e.sessionToken&&(this.sessionToken=e.sessionToken,delete e.sessionToken),this.set(e))}static async logIn(e,t){const n=`${this.instance.serverURL}/login`,o=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json","X-Parse-Application-Id":this.instance.appId},body:JSON.stringify({username:e,password:t})}),i=await o.json();if(i.error)throw i;const a=new this({...i,username:e,password:t});return a._saveToCache(),a}static async become(e){const t=`${this.instance.serverURL}/users/me`;let n={"X-Parse-Session-Token":e,"X-Parse-Application-Id":this.instance.appId};const o=await fetch(t,{headers:n}),i=await o.json();if(i.error)throw i.error;const a=new this({...i,sessionToken:e});return a._saveToCache(),a}static async signUp(e,t,n={}){return new this({...n,username:e,password:t}).signUp()}static async logOut(){if(this.current())try{await fetch(`${this.instance.serverURL}/logout`,{method:"POST",headers:{"X-Parse-Session-Token":this.current().sessionToken,"X-Parse-Application-Id":this.instance.appId}})}finally{this._clearCurrentUser()}}static async requestPasswordReset(e){const t=`${this.instance.serverURL}/requestPasswordReset`,n=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json","X-Parse-Application-Id":this.instance.appId},body:JSON.stringify({email:e})}),o=await n.json();if(o.error)throw o}static{this._currentUser=null}static current(){if(this._currentUser)return this._currentUser;try{const e=localStorage.getItem(this.instanceKey());if(!e)return null;const t=JSON.parse(e);if(!t.sessionToken)return null;const n=new this(t);return this._currentUser=n,n.sessionToken&&this._instance&&(this._instance.sessionToken=n.sessionToken),n}catch(e){return console.warn("Failed to restore user from cache",e),null}}static _clearCurrentUser(){this._currentUser=null,this._instance&&(this._instance.sessionToken=void 0),localStorage.removeItem(this.instanceKey())}async signUp(e){if(e&&this.set(e),!this.username)throw new Error("Username is required");if(!this.password)throw new Error("Password is required");const t=this._parseInstance||FmodeUser.instance;let n=this.toJSON();delete n.__type,delete n.className;const o=`${t.serverURL}/users`,i=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json","X-Parse-Application-Id":t.appId},body:JSON.stringify(n)}),a=await i.json();if(a.error)throw a;return this.id=a.objectId,this.createdAt=new Date(a.createdAt),this.sessionToken=a.sessionToken,this._saveToCache(),this}async save(){const e=this._parseInstance||FmodeUser.instance,t=`${e.serverURL}/users/${this.id||this.data.objectId}`,n={"Content-Type":"application/json","X-Parse-Application-Id":e.appId,"X-Parse-Session-Token":this.sessionToken},o=this.toJSON();delete o.__type,delete o.objectId,delete o.className,delete o.sessionToken,delete o.username,delete o.createdAt,delete o.updatedAt;const i=await fetch(t,{method:"PUT",headers:n,body:JSON.stringify(o)}),a=await i.json();if(a.error)throw 209===a.code&&FmodeUser._clearCurrentUser(),new Error(a.error);return this.set("updatedAt",new Date(a.updatedAt)),this._saveToCache(),this}_saveToCache(){if(!this.sessionToken)return;FmodeUser._currentUser=this;const e=this._parseInstance||FmodeUser._instance;e&&(e.sessionToken=this.sessionToken),localStorage.setItem(FmodeUser.instanceKey(),JSON.stringify(this.toJSONForCache()))}toJSONForCache(){return{...super.toJSON(),sessionToken:this.sessionToken}}getSessionToken(){return this.sessionToken}async destroy(e){if(!this.id)throw new Error("Cannot destroy unsaved user");const t=this._parseInstance||FmodeUser.instance,n=`${t.serverURL}/users/${this.id}`,o={"X-Parse-Session-Token":this.sessionToken,"X-Parse-Application-Id":t.appId};e?.useMasterKey&&t.config.masterKey&&(o["X-Parse-Master-Key"]=t.config.masterKey);const i=await fetch(n,{method:"DELETE",headers:o});if(!i.ok){const e=await i.json();throw new Error(e.error||"Failed to delete user")}FmodeUser._clearCurrentUser()}}class FmodeCloud{static{this._singletonInstance=null}constructor(){this._cloudFunctions=new Map}static getInstance(){return this._singletonInstance||(this._singletonInstance=new FmodeCloud),this._singletonInstance}static{this._instance=null}static bindInstance(e){this._instance=e}get currentConfig(){const e=FmodeCloud._instance;if(!e)throw new Error("FmodeCloud not initialized. Call FmodeParse.initialize() first.");return e.config}static get instance(){return this._instance}define(e,t){this._cloudFunctions.set(e,t)}async run(e,t={},n={}){const o=this.currentConfig,i=`${o.serverURL}/functions/${e}`,a={...t,_ApplicationId:o.appId,_InstallationId:n.installationId||this.generateInstallationId()},r=o.sessionToken;r&&(a._SessionToken=r);try{const e=await fetch(i,{method:"POST",headers:{"Content-Type":"application/json","X-Parse-Application-Id":o.appId,...o.javascriptKey&&{"X-Parse-JavaScript-Key":o.javascriptKey},...o.masterKey&&{"X-Parse-Master-Key":o.masterKey},...r&&{"X-Parse-Session-Token":r}},body:JSON.stringify(a)});if(!e.ok)throw new Error(`HTTP error! status: ${e.status}`);const t=await e.json();if(t.error)throw new Error(t.error.message||"Cloud function error");return t.result}catch(t){throw console.error(`Cloud function ${e} failed:`,t),t}}async afterDelete(e,t){this.define(`afterDelete_${e}`,t)}async afterSave(e,t){this.define(`afterSave_${e}`,t)}async beforeDelete(e,t){this.define(`beforeDelete_${e}`,t)}async beforeSave(e,t){this.define(`beforeSave_${e}`,t)}async beforeFind(e,t){this.define(`beforeFind_${e}`,t)}async afterFind(e,t){this.define(`afterFind_${e}`,t)}async job(e,t){this.define(`job_${e}`,t)}generateInstallationId(){return"undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(function(e){const t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)}))}}const Cloud=FmodeCloud.getInstance();class FmodeParse{static{this._instances={}}static{this._defaultInstance=null}constructor(e){this.config=e,this.Object=this.createObjectFactory(),this.Query=this.createQueryFactory(),this.User=this.createUserFactory(),this.GeoPoint=FmodeGeoPoint,this.File=FmodeFile,this.ACL=FmodeACL,this.Relation=FmodeRelation,this.Cloud=FmodeCloud.getInstance(),FmodeObject._instance||FmodeObject.bindInstance(this),FmodeQuery._instance||FmodeQuery.bindInstance(this),FmodeUser._instance||FmodeUser.bindInstance(this),FmodeGeoPoint._instance||FmodeGeoPoint.bindInstance(this),FmodeRelation._instance||FmodeRelation.bindInstance(this),FmodeFile._instance||FmodeFile.bindInstance(this),FmodeACL._instance||FmodeACL.bindInstance(this),FmodeCloud._instance||FmodeCloud.bindInstance(this)}createObjectFactory(){const e=this;return class Object extends FmodeObject{constructor(t){super(t),this._parseInstance=e}static extend(e){const t=class extends Object{constructor(){super(e)}};return t.extend=Object.extend,t.create=Object.create,t.fetchAll=Object.fetchAll,t.fromFile=Object.fromFile,t}static async create(e,t,n){const o=new this(e);return o.set(t),o.save(n)}static async fetchAll(t,n){if(!e)throw new Error("Not initialized");if(0===t.length)return[];const o={"Content-Type":"application/json","X-Parse-Application-Id":e.appId};if(n?.useMasterKey&&e.config.masterKey)o["X-Parse-Master-Key"]=e.config.masterKey;else{const t=e.sessionToken;t&&(o["X-Parse-Session-Token"]=t)}const i=`${e.serverURL}/batch`,a=t.map((e=>({method:"GET",path:`/classes/${e.className}/${e.id}`}))),r=await fetch(i,{method:"POST",headers:o,body:JSON.stringify({requests:a})}),s=await r.json();if(s.error)throw new Error(s.error);return s.map(((e,n)=>{const o=t[n];return o.set(e.success),o}))}static async fromFile(t,n,o){if(!e)throw new Error("Not initialized");const i=new FormData;i.append("file",n,t);const a={"X-Parse-Application-Id":e.appId},r=e.sessionToken;r&&(a["X-Parse-Session-Token"]=r);const s=`${e.serverURL}/files/${t}`,l=await fetch(s,{method:"POST",headers:a,body:i}),c=await l.json();if(c.error)throw new Error(c.error);return{__type:"File",name:c.name,url:c.url}}}}createQueryFactory(){const e=this;return class Query extends FmodeQuery{constructor(t){super(t),this._parseInstance=e}static get instance(){return e}static bindInstance(e){}}}createUserFactory(){const e=this;return class User extends FmodeUser{constructor(t){super(t),this._parseInstance=e}static get instance(){return e}static{this.instanceKey=()=>"Parse/"+e.appId+"/currentUser"}static bindInstance(e){}static async logIn(t,n){const o=`${e.serverURL}/login`,i=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json","X-Parse-Application-Id":e.appId},body:JSON.stringify({username:t,password:n})}),a=await i.json();if(a.error)throw a;const r=new this({...a,username:t,password:n});return r._saveToCache(),r}static async become(t){const n=`${e.serverURL}/users/me`;let o={"X-Parse-Session-Token":t,"X-Parse-Application-Id":e.appId};const i=await fetch(n,{headers:o}),a=await i.json();if(a.error)throw a.error;const r=new this({...a,sessionToken:t});return r._saveToCache(),r}static async signUp(e,t,n={}){return new this({...n,username:e,password:t}).signUp()}static async logOut(){if(this.current())try{await fetch(`${e.serverURL}/logout`,{method:"POST",headers:{"X-Parse-Session-Token":this.current().sessionToken,"X-Parse-Application-Id":e.appId}})}finally{this._clearCurrentUser()}}static async requestPasswordReset(t){const n=`${e.serverURL}/requestPasswordReset`,o=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json","X-Parse-Application-Id":e.appId},body:JSON.stringify({email:t})}),i=await o.json();if(i.error)throw i}static{this._currentUser=null}static current(){if(this._currentUser)return this._currentUser;try{const t=localStorage.getItem(this.instanceKey());if(!t)return null;const n=JSON.parse(t);if(!n.sessionToken)return null;const o=new this(n);return this._currentUser=o,o.sessionToken&&e&&(e.sessionToken=o.sessionToken),o}catch(e){return console.warn("Failed to restore user from cache",e),null}}static _clearCurrentUser(){this._currentUser=null,e&&(e.sessionToken=void 0),localStorage.removeItem(this.instanceKey())}_saveToCache(){if(!this.sessionToken)return;this.constructor._currentUser=this;const e=this._parseInstance||this.constructor.instance;e&&(e.sessionToken=this.sessionToken),localStorage.setItem(this.constructor.instanceKey(),JSON.stringify(this.toJSONForCache()))}}}static initialize(e){let t;if("string"==typeof e){let n="http://dev.fmode.cn:1337/parse";"undefined"!=typeof location&&"https:"===location.protocol&&(n="https://dev.fmode.cn/parse"),t=new FmodeParse({appId:e,serverURL:n}),this._defaultInstance=t,this._instances.default=t}else t=new FmodeParse(e),e.config&&(this._instances[e.config]=t),e.config&&"default"!==e.config||(this._defaultInstance=t);return t}static with(e){if(!this._instances.nova){let e=new FmodeParse({appId:"ncloudmaster",serverURL:"https://server.fmode.cn/parse"});this._instances.nova=e}if(!this._instances.dev){let e=new FmodeParse({appId:"dev",serverURL:"https://dev.fmode.cn/parse"});this._instances.dev=e}"dev"!=e||this._defaultInstance||(this._defaultInstance=this._instances.dev),"default"!=e||this._instances.default||(this._instances.default=this._instances.dev,this._defaultInstance=this._instances.dev);const t=this._instances[e]||this._defaultInstance;return FmodeObject.bindInstance(t),FmodeQuery.bindInstance(t),FmodeUser.bindInstance(t),FmodeFile.bindInstance(t),FmodeACL.bindInstance(t),FmodeGeoPoint.bindInstance(t),FmodeRelation.bindInstance(t),FmodeCloud.bindInstance(t),t}static getAllInstances(){return{...this._instances}}static getInstanceConfigs(){const e={};return Object.entries(this._instances).forEach((([t,n])=>{e[t]=n.config})),e}get serverURL(){return this.config.serverURL}set serverURL(e){this.config.serverURL=e}get appId(){return this.config.appId}get sessionToken(){if(this.config.sessionToken)return this.config.sessionToken;const e=this.User.current();return e?.sessionToken}set sessionToken(e){this.config.sessionToken=e}}!function(e){e.Object=FmodeObject,e.Query=FmodeQuery,e.User=FmodeUser,e.File=FmodeFile,e.Relation=FmodeRelation,e.ACL=FmodeACL,e.GeoPoint=FmodeGeoPoint,e.Cloud=FmodeCloud.getInstance()}(FmodeParse||(FmodeParse={}));const defaultExport=new Proxy(FmodeParse,{apply:(e,t,n)=>FmodeParse.initialize.apply(e,n),get:(e,t)=>t in e?e[t]:t in FmodeParse?FmodeParse[t]:FmodeParse.with("default")[t]});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}}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}}const Parse$J=defaultExport.with("nova");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,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.voiceConfig=e?.voiceConfig,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$J.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$J.User.current()?.id&&t.set("user",Parse$J.User.current().toPointer())}if(!t?.get("voiceFile")){const n=[];e&&n.push({ssml:e});const o=Parse$J.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")?(n?.onStart?.(t),this.playAudioData(t?.get("voiceFile")?.get("url"),t,n,!0),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?.()}),500),o(t)}),(e=>{this.isPlaying=!1,i(`Error occurred during synthesis: ${e}`)}),(()=>{n?.onStart?.()}))})))}async playAudioData(e,t,n,o=!1){let i;if(e?.indexOf?.("http")>=-1)i=e;else{const n=new Blob([e],{type:"audio/wav"});i=URL.createObjectURL(n),await this.uploadAndSaveVoice(n,t)}o||n?.onStart?.(t),this.isPlaying=!0;const a=this.audioPlayer;a.setAudioEvent("onloadeddata",(()=>{const e=1e3*a.duration;t?.get("duration")||(t.set("duration",e),t.save()),n?.onLoaded?.(a)})),["onended"].forEach((e=>{a.setAudioEvent(e,(()=>{this.isPlaying=!1,n?.onStop?.()}))}));const playAudio=()=>{a.play(i).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:this.voiceConfig?.voice||"zh_female_shuangkuaisisi_emo_v2_mars_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("&")}`}const Parse$I=defaultExport.with("nova");async function getFormatTpl(e,t){let n=await getPromptTpl(e);return await n.format(t)}async function getPromptTpl(e){let t=new Parse$I.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",Parse$H=defaultExport.with("nova");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-1.6-cn",this.max_tokens=t?.max_tokens||32768}sendCompletion(e={messages:[]}){e.intTime=e?.intTime||50,e.isDirect=e?.isDirect||!1,e?.isDirect&&(e.intTime=1);const 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 this.model.indexOf("1.6")>-1&&(t.thinking=t.thinking||{type:"disabled"}),e?.max_tokens&&(t.max_tokens=e?.max_tokens||this.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 ${localStorage.getItem("FMODE_AI_TOKEN")||Parse$H.User.current()?.getSessionToken()}`;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="";{const n=e.body?.getReader();if(!n)return void o.error(new Error("Response body reader is null"));const i=new TextDecoder;let a=new ReadableStream({start(e){!function read(){try{e&&n.read().then((({done:t,value:n})=>{if(t)return e?.close(),void o.complete();e?.enqueue(n),read()})).catch((e=>{}))}catch(e){console.log("err2",e)}}()}}).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}async function completionJSON(e,t,n,o=1,i){i=i||{};let a=0;const attemptCompletion=async()=>{const o=`请严格按照以下要求生成JSON数据:\n- 数据结构要求:${t}\n- 返回一个完整的JSON对象,请确保JSON格式完整,不要遗漏任何标点符号\n- 注意返回的JSON格式每个KEY都有""包裹和Value之间都有:\n- 注意""字符串内再出现"符号需要用\\"转义\n`;let r;if(Array.isArray(e))r=e;else if(i.vision&&i.images&&i.images.length>0){r=[{role:"user",content:[...i.images.map((e=>({type:"image_url",image_url:{url:e}}))),{type:"text",text:e+o}]}]}else r=[{role:"user",content:e+o}];i.response_format={type:"json_object"};const s=new FmodeChatCompletion(r,i);let l="";return new Promise(((e,t)=>{const o=s.sendCompletion({isDirect:!0,max_tokens:32768}).subscribe({next:i=>{if("string"==typeof i?.content&&(l=i.content,n&&n(l)),i.complete){try{const t=extractJSON(l);if(!t)throw new Error("未能从响应中提取有效的JSON对象");e(t)}catch(e){console.error(`JSON解析失败 (第${a+1}次尝试):`,e),t(new Error(`生成的响应不符合JSON格式: ${e.message}`))}o.unsubscribe()}},error:e=>{console.error("Completion请求失败:",e),o.unsubscribe(),t(e)}})}))};for(;a<=o;)try{const e=await attemptCompletion();return a>0&&console.log(`JSON生成成功,重试了 ${a} 次`),e}catch(e){if(a++,!(a<=o))throw console.error(`JSON生成失败,已重试 ${o} 次,最终错误:`,e),new Error(`经过 ${o} 次重试后仍无法生成有效JSON: ${e.message}`);console.warn(`第 ${a} 次尝试失败,正在重试... 错误信息:`,e.message),await new Promise((e=>setTimeout(e,1e3)))}}function extractJSON(e){try{return JSON.parse(e.trim())}catch(e){}let t=0,n=-1,o=null;for(let i=0;i<e.length;i++)if("{"===e[i])0===t&&(n=i),t++;else if("}"===e[i]&&(t--,0===t&&-1!==n))try{const t=e.slice(n,i+1);o=JSON.parse(t);break}catch(e){n=-1}return o||(o=tryFixAndParseJSON(e)),o}function tryFixAndParseJSON(e){const t=e.match(/\{[\s\S]*\}/);if(!t)return null;let n=t[0];const o=[e=>e.replace(/,(\s*[}\]])/g,"$1"),e=>e.replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g,'$1"$2":'),e=>e.replace(/'/g,'"'),e=>e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"")];for(const e of o)try{const t=e(n);return JSON.parse(t)}catch(e){}return null}const Parse$G=defaultExport.with("nova");var MessageScene,MessageType,MessageRole,MessageStatus;!function(e){e.ROLE="role",e.USER="user",e.GROUP="group",e.SERVICE="service"}(MessageScene||(MessageScene={})),function(e){e.TEXT="text",e.IMAGE="image",e.VOICE="voice",e.AGENT_TASK="agent_task",e.SYSTEM="system",e.EXTERNAL="external"}(MessageType||(MessageType={})),function(e){e.USER="user",e.ASSISTANT="assistant",e.SYSTEM="system",e.AGENT="agent",e.EXTERNAL="external"}(MessageRole||(MessageRole={})),function(e){e.SENDING="sending",e.SENT="sent",e.DELIVERED="delivered",e.READ="read",e.FAILED="failed"}(MessageStatus||(MessageStatus={}));class Message{constructor(e){this.parseObject=e||new Parse$G.Object("Message")}static create(e){const t=new Message;return t.parseObject.set("company",e.company),t.parseObject.set("content",e.content),t.parseObject.set("scene",e.scene),t.parseObject.set("session",e.session),t.parseObject.set("group",e.group),t.parseObject.set("userFrom",e.userFrom),t.parseObject.set("userTo",e.userTo),t.parseObject.set("role",e.role),t.parseObject.set("external",e.external),t.parseObject.set("contact",e.contact),t.parseObject.set("attachments",e.attachments||[]),t.parseObject.set("metadata",e.metadata||{}),t.parseObject.set("status",MessageStatus.SENT),t.parseObject.set("hidden",e.content.hidden||!1),t.parseObject.set("sentAt",new Date),t}async save(e){return await this.parseObject.save(e),this}updateContent(e){return this.parseObject.set("content",e),this}updateStatus(e){return this.parseObject.set("status",e),e===MessageStatus.READ&&this.parseObject.set("readAt",new Date),this}get id(){return this.parseObject.id}get(e){return this.parseObject.get(e)}set(e,t){return this.parseObject.set(e,t),this}toFmodeChatMessage(){const e=this.parseObject.get("content");return{role:e?.role||MessageRole.USER,content:e?.content||"",json:e?.json,hidden:e?.hidden,complete:!1!==e?.complete,createdAt:this.parseObject.get("sentAt")||this.parseObject.createdAt,voice:e?.voice,cid:e?.cid}}getParseObject(){return this.parseObject}static fromParseObject(e){return new Message(e)}static query(){return new FmodeQuery("Message")}static queryByScene(e){const t=Message.query();return t.equalTo("scene",e),t}static async findRoleMessages(e,t={}){const n=Message.queryByScene(MessageScene.ROLE);n.equalTo("session",e),t.limit&&n.limit(t.limit),t.skip&&n.skip(t.skip),!1!==t.ascending?n.ascending("sentAt"):n.descending("sentAt");return(await n.find()).map((e=>Message.fromParseObject(e)))}static async findGroupMessages(e,t={}){const n=Message.queryByScene(MessageScene.GROUP);n.equalTo("group",e),t.limit&&n.limit(t.limit),t.skip&&n.skip(t.skip),!1!==t.ascending?n.ascending("sentAt"):n.descending("sentAt");return(await n.find()).map((e=>Message.fromParseObject(e)))}static async findUserMessages(e,t,n={}){const o=Message.queryByScene(MessageScene.USER);o.containedIn("userFrom",[e,t]),o.containedIn("userTo",[e,t]),n.limit&&o.limit(n.limit),n.skip&&o.skip(n.skip),!1!==n.ascending?o.ascending("sentAt"):o.descending("sentAt");return(await o.find()).map((e=>Message.fromParseObject(e)))}static async findServiceMessages(e,t={}){const n=Message.queryByScene(MessageScene.SERVICE);n.equalTo("contact",e),t.limit&&n.limit(t.limit),t.skip&&n.skip(t.skip),!1!==t.ascending?n.ascending("sentAt"):n.descending("sentAt");return(await n.find()).map((e=>Message.fromParseObject(e)))}static async findByExternalId(e,t){const n=Message.query();n.equalTo("external.source",e),n.equalTo("external.id",t);const o=await n.first();return o?Message.fromParseObject(o):null}static getMessageType(e){if(e.voice)return MessageType.VOICE;if(e.json)return MessageType.AGENT_TASK;if(e.hidden)return MessageType.SYSTEM;if(Array.isArray(e.content)){return e.content.some((e=>e?.image_url))?MessageType.IMAGE:MessageType.TEXT}return MessageType.TEXT}static fromFmodeChatMessage(e,t){const n={type:Message.getMessageType(e),role:e.role||MessageRole.USER,content:e.content,json:e.json,hidden:e.hidden,complete:e.complete,voice:e.voice,cid:e.cid,createdAt:e.createdAt};return Message.create({...t,content:n})}}const Parse$F=defaultExport.with("nova");class MessageManager{constructor(e){this._newMessages=[],this._legacyMessages=[],this._mergedMessages=[],this._isDirty=!0,this.options=e}async getMessages(){return this._isDirty&&(await this.loadAndMergeMessages(),this._isDirty=!1),[...this._mergedMessages]}async addMessage(e,t){const n=t||this.options.scene||MessageScene.ROLE;try{const t={content:{type:Message.getMessageType(e),role:e.role||MessageRole.USER,content:e.content,json:e.json,hidden:e.hidden,complete:e.complete,voice:e.voice,cid:e.cid,createdAt:e.createdAt||new Date},scene:n,company:this.options.company,session:n===MessageScene.ROLE?this.options.chatSession:void 0,role:n===MessageScene.ROLE?this.options.role:void 0,group:n===MessageScene.GROUP?this.options.group:void 0,userFrom:n===MessageScene.USER?this.options.userFrom:void 0,userTo:n===MessageScene.USER?this.options.userTo:void 0,contact:n===MessageScene.SERVICE?this.options.contact:void 0},o=Message.create(t);await o.save(),this._newMessages.push(o),this._isDirty=!0}catch(t){console.error("保存新消息失败:",t),this._legacyMessages.push({...e,source:"legacy"}),this._isDirty=!0}}async updateMessage(e,t){const n=await this.getMessages();if(e<0||e>=n.length)return;const o=n[e];if("new"===o.source&&o.id){const e=this._newMessages.findIndex((e=>e.id===o.id));if(e>=0){const n={type:Message.getMessageType(t),role:t.role||MessageRole.USER,content:t.content,json:t.json,hidden:t.hidden,complete:t.complete,voice:t.voice,cid:t.cid,createdAt:t.createdAt||new Date};this._newMessages[e].updateContent(n),await this._newMessages[e].save()}}this._isDirty=!0}async reloadMessages(){this._newMessages=[],this._legacyMessages=[],this._isDirty=!0,await this.getMessages()}async loadAndMergeMessages(){this._legacyMessages=this.options.chatSession?.get("messageList")||[];try{switch(this.options.scene){case MessageScene.ROLE:this.options.chatSession&&(this._newMessages=await Message.findRoleMessages(this.options.chatSession,{ascending:!0}));break;case MessageScene.GROUP:this.options.group&&(this._newMessages=await Message.findGroupMessages(this.options.group,{ascending:!0}));break;case MessageScene.USER:this.options.userFrom&&this.options.userTo&&(this._newMessages=await Message.findUserMessages(this.options.userFrom,this.options.userTo,{ascending:!0}));break;case MessageScene.SERVICE:this.options.contact&&(this._newMessages=await Message.findServiceMessages(this.options.contact,{ascending:!0}));break;default:this._newMessages=[]}}catch(e){console.error("加载新版消息失败:",e),this._newMessages=[]}if(this._mergedMessages=[],this._legacyMessages.length>0&&this._mergedMessages.push(...this._legacyMessages.map((e=>({...e,source:"legacy"})))),this._newMessages.length>0){const e=this._newMessages.map((e=>({...e.toFmodeChatMessage(),source:"new",id:e.id})));this._mergedMessages.push(...e)}}getStats(){const e={total:this._mergedMessages.length,legacy:this._legacyMessages.length,new:this._newMessages.length,user:0,assistant:0};return this._mergedMessages.forEach((t=>{"user"===t.role&&e.user++,"assistant"===t.role&&e.assistant++})),e}async searchMessages(e){if(!e.trim())return await this.getMessages();const t=await this.getMessages(),n=e.toLowerCase();return t.filter((e=>{let t="";return"string"==typeof e.content?t=e.content:Array.isArray(e.content)&&(t=e.content.filter((e=>e?.text)).map((e=>e.text)).join(" ")),t.toLowerCase().includes(n)}))}clearCache(){this._newMessages=[],this._legacyMessages=[],this._mergedMessages=[],this._isDirty=!0}static createForRole(e,t,n){return new MessageManager({chatSession:e,role:t,company:n,scene:MessageScene.ROLE})}static createForGroup(e,t){return new MessageManager({group:e,company:t,scene:MessageScene.GROUP})}static createForUser(e,t,n){return new MessageManager({userFrom:e,userTo:t,company:n,scene:MessageScene.USER})}static createForService(e,t){return new MessageManager({contact:e,company:t,scene:MessageScene.SERVICE})}static create(e){return new MessageManager(e)}}const Parse$E=defaultExport.with("nova"),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$E.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-1.6-cn"==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$E.Object.extend("ChatSession"),this.messageManager=null,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()=>{const e=await this.getMessageList();let t=e?.filter((e=>"assistant"==e?.role));if(t?.length)return;let n=Parse$E.User.current(),o=await this.loadSelf("Person","userVerify"),i=await this.loadSelf("Profile","user"),a=o?.get("name")||o?.get("userVefiry")?.get("realname")||o?.get("userVefiry")?.get("nickname"),r=n?.get("nickname")||i?.get("name")||n?.get("realname")||n?.get("name");o?.get("userVerify")?.id==n?.id&&(a="您"),r||(r=a);let s=this.role.get("voiceConfig")?.welcome?.prompt;if(this.role.get("voiceConfig")?.welcome?.promptList?.length){let e=this.role.get("voiceConfig")?.welcome?.promptList;s=e[Math.floor(Math.random()*e.length)]}if(!s)return;let l=await PromptTemplate.fromTemplate(s,{templateFormat:"mustache"}).format({name:r,userName:r,personName:a,timeOfDay:this.getTimeOfDay()}),c=await this.getVoiceByContentText(l),d={role:"assistant",voice:c,content:l,complete:!0,createdAt:new Date};await this.addMessage(d,MessageScene.ROLE),this.voiceMap[c?.id],this.playChatVoice(this.voiceMap[c?.id])},this.self={},this.voiceMap={},this.VoiceTTSMap={},this.chatServ=o,this.role=t,this.sessionId=e,this.navCtrl=i,this.ncloud=a,this.uploadServ=r,this.initCompany(),n?.id&&(this.chatSession=n,this.sessionId=n?.id,this.initMessageManager()),this.role?.id&&(this.voiceConfig=this.role?.get("voiceConfig"),this.voiceConfig?.autoTalk&&(this.isTalkMode=this.isTalkMode||this.voiceConfig?.autoTalk,this.isDirect=!0))}async getMessageList(){return this.messageManager?await this.messageManager.getMessages():[{role:"system",content:"系统提示:AI仅供参考"}]}get messageList(){return this.messageManager?[]:[{role:"system",content:"系统提示:AI仅供参考"}]}set messageList(e){this.messageManager&&this.messageManager.clearCache()}initMessageManager(){this.chatSession&&this.role&&this.company&&(this.messageManager=MessageManager.createForRole(this.chatSession,this.role,this.company))}async initCompany(){const e=localStorage.getItem("company");e&&(this.company={__type:"Pointer",className:"Company",objectId:e})}async addMessage(e,t=MessageScene.ROLE){this.messageManager&&await this.messageManager.addMessage(e,t)}async updateMessage(e,t){this.messageManager&&await this.messageManager.updateMessage(e,t)}async reloadMessages(){this.messageManager&&await this.messageManager.reloadMessages()}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$E.User.current(),o=new Parse$E.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){let a;this.scrollToBottom&&this.scrollToBottom(),this.isPromptMessageAreaShow=!1,this.loadRolePrompt(),t?(a={role:"user",content:[{type:"image_url",image_url:{url:t}},{type:"text",text:e}],complete:!0,createdAt:new Date},i&&(a.voice={id:i?.id})):(a={role:"user",content:e,complete:!0,createdAt:new Date},i&&(a.voice={id:i?.id,duration:i?.duration})),await this.addMessage(a,MessageScene.ROLE);const r=await this.getMessageList();let s=new FmodeChatCompletion(this.fixMessageList(r),{model:this.currentModel?.get?.("code")||"fmode-1.6-cn"});if(this.onUserSend){if(!await this.onUserSend(this,a))return}this.userInput="",this.userImage="";let l=this.isDirect||!1;this.isTalkMode&&(l=!0);const c={role:"assistant",content:"",complete:!1,createdAt:new Date};await this.addMessage(c,MessageScene.ROLE);const d=await this.getMessageList(),p=d.length-1;let m=s.sendCompletion({isDirect:l,onComplete:n||null}).pipe(finalize((async()=>{let e=d[p];if(this.isTalkMode){let t=e?.content,n=await this.getVoiceByContentText(t,o);o?.onSSMLComplete&&o?.onSSMLComplete(n),e.voice=n,this.playChatVoice(this.voiceMap[n?.id],{onResult:t=>{t?.duration&&(e.voice.duration=t?.duration)}})}e.complete=!0,await this.updateMessage(p,e)}))).subscribe((async e=>{await this.updateMessage(p,e),this.latestAIResponse=this.getContentText(e?.content);let t=this.chatSession?.get("messageList")?.length;const n=await this.getMessageList();if(n?.length>t&&this.saveChatSession(),e?.complete){const e=await this.getMessageList();this.onMessage&&this.onMessage(this,e[e?.length-1]),this.saveChatSession(),m.unsubscribe()}this.scrollToBottom&&this.scrollToBottom()}))}getVoiceByContentText(e,t,n=!1){let o=this.getContentText(e),i=new(Parse$E.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$E.User.current()?.id&&i.set("user",Parse$E.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>`,"doubao"==e&&(a=o),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-1.6-cn"}).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||e?.provider,"doubao"==e?.provider&&(e.provider=new FmodeTTSProviderDoubao),e.voiceConfig=this.voiceConfig,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{n.voiceConfig=this.voiceConfig,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("user",Parse$E.User.current()?.toPointer()),this.chatSession.get("messageList")||this.chatSession.set("messageList",[]),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);const t=await this.getMessageList(),n=t[t?.length-1];let o="";if("string"==typeof n?.content)o=n.content.slice(0,20);else if(Array.isArray(n?.content)){const e=n.content.find((e=>e?.text));o=e?.text?.slice(0,20)||""}let i={sid:this.chatSession?.id,rid:this.role?.id,name:this.role?.get("name"),message:o,latest:this.chatSession?.createdAt};this.chatServ&&!this.chatServ?.chatList?.length&&(this.chatServ.chatList=[]);let a=this.chatServ?.chatList?.find((e=>e?.sid==i?.sid));a>-1?this.chatServ.chatList[a]=i:this.chatServ?.chatList.unshift(i)}}getInviteUrl(e){let t=new URL(e),n=Parse$E.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()}`}}const Parse$D=defaultExport.with("nova");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$D.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}}const Parse$C=defaultExport.with("nova");class AgentStory{constructor(e,t,n){this.Story=Parse$C.Object.extend("Story"),this.Document=Parse$C.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$C.User.current()?.toPointer())}async setAttachment(e){let t=new Parse$C.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 FmodeLoadingController{async create(e){return new FmodeLoadingInstance(e)}}class FmodeLoadingInstance{constructor(e){this._message="加载中...",this._progress=0,this._taskIndex=0,this._taskTotal=1,this.position="bottom",this.container=null,this.progressTimer=null,this._message=e.message??this._message,this._progress=e.progress??this._progress,this._taskIndex=e.taskIndex??this._taskIndex,this._taskTotal=e.taskTotal??this._taskTotal,this.position=e.position??this.position,this.handle=e.handle,this.initDom()}set message(e){this._message=e,this.updateUI()}get message(){return this._message}set progress(e){this._progress=e,this.updateUI()}get progress(){return this._progress}set taskIndex(e){this._taskIndex=e,this.updateUI()}get taskIndex(){return this._taskIndex}set taskTotal(e){this._taskTotal=e,this.updateUI()}get taskTotal(){return this._taskTotal}initDom(){this.container=document.createElement("div"),this.container.className="fmode-loading fmode-loading-"+this.position,this.setPositionStyle(),this.container.innerHTML=`\n <div class="fmode-loader-circle">\n <svg viewBox="0 0 100 100">\n <circle class="bg" cx="50" cy="50" r="45" />\n <circle class="progress" cx="50" cy="50" r="45" />\n </svg>\n <div class="fmode-progress-text">${Math.round(100*this._progress)}%</div>\n </div>\n <div class="fmode-task-info">任务 ${this._taskIndex} / ${this._taskTotal}</div>\n <div class="fmode-message">${this._message}</div>\n `,this.injectCss()}setPositionStyle(){if(!this.container)return;const e={top:{top:"20px",left:"50%",transform:"translateX(-50%)"},bottom:{bottom:"100px",left:"50%",transform:"translateX(-50%)"},middle:{top:"50%",left:"50%",transform:"translate(-50%, -50%)"},topleft:{top:"20px",left:"20px"},topright:{top:"20px",right:"20px"},bottomleft:{bottom:"100px",left:"20px"},bottomright:{bottom:"100px",right:"20px"}}[this.position];Object.assign(this.container.style,{position:"fixed",zIndex:"99999",display:"flex",flexDirection:"row",alignItems:"center",gap:"8px",...e})}injectCss(){if(!document.getElementById("fmode-loading-style")){const e=document.createElement("style");if(e.id="fmode-loading-style",e.innerHTML="\n .fmode-loading {\n position: fixed;\n z-index: 99999;\n display: flex;\n flex-direction: row; /* 横排 */\n align-items: center;\n gap: 12px;\n min-width: 360px; /* 防止消息过长时左边抖动 */\n padding: 8px 12px;\n border-radius: 8px;\n background: rgba(0,0,0,0.6);\n backdrop-filter: blur(6px);\n animation: fadeIn 0.3s ease;\n }\n\n /* 位置适配 */\n .fmode-loading-top { top: 20px; left: 50%; transform: translateX(-50%); }\n .fmode-loading-bottom { bottom: 100px; left: 50%; transform: translateX(-50%); }\n .fmode-loading-middle { top: 50%; left: 50%; transform: translate(-50%, -50%); }\n .fmode-loading-topleft { top: 20px; left: 20px; }\n .fmode-loading-topright { top: 20px; right: 20px; }\n .fmode-loading-bottomleft { bottom: 100px; left: 20px; }\n .fmode-loading-bottomright { bottom: 100px; right: 20px; }\n\n /* 背景发光 */\n .fmode-loader-glow {\n position: absolute;\n width: 120px;\n height: 120px;\n background: radial-gradient(circle, rgba(0,255,255,0.2), transparent);\n border-radius: 50%;\n filter: blur(20px);\n animation: glowPulse 2s infinite;\n }\n\n /* 圆形进度 */\n \n .fmode-loader-circle {\n flex-shrink: 0;\n position: relative;\n width: 48px;\n height: 48px;\n }\n .fmode-loader-circle svg {\n transform: rotate(-90deg);\n width: 100%;\n height: 100%;\n }\n .fmode-loader-circle circle {\n fill: none;\n stroke-width: 6;\n stroke-linecap: round;\n }\n .fmode-loader-circle .bg {\n stroke: rgba(255,255,255,0.1);\n }\n .fmode-loader-circle .progress {\n stroke: url(#fmode-gradient);\n stroke-dasharray: 283;\n stroke-dashoffset: 283;\n transition: stroke-dashoffset 0.3s ease;\n }\n .fmode-progress-text {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n font-size: 12px;\n font-weight: bold;\n color: #0ff;\n text-shadow: 0 0 6px #0ff;\n }\n\n .fmode-task-info {\n flex-shrink: 0;\n font-size: 14px;\n font-weight: bold;\n color: #fff;\n text-shadow: 0 0 4px rgba(0,0,0,0.5);\n }\n .fmode-message {\n flex: 1;\n font-size: 14px;\n color: #fff;\n text-shadow: 0 0 4px rgba(0,0,0,0.5);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n\n @keyframes glowPulse {\n 0%, 100% { opacity: 0.6; transform: scale(1); }\n 50% { opacity: 1; transform: scale(1.1); }\n }\n @keyframes fadeIn {\n from { opacity: 0; transform: scale(0.9); }\n to { opacity: 1; transform: scale(1); }\n }\n ",document.head.appendChild(e),!document.getElementById("fmode-svg-gradient")){const e=document.createElementNS("http://www.w3.org/2000/svg","svg");e.style.position="absolute",e.style.width="0",e.style.height="0",e.innerHTML='\n <defs>\n <linearGradient id="fmode-gradient" x1="0%" y1="0%" x2="100%" y2="0%">\n <stop offset="0%" stop-color="#0ff" />\n <stop offset="100%" stop-color="#0f0" />\n </linearGradient>\n </defs>\n ',e.id="fmode-svg-gradient",document.body.appendChild(e)}}}async present(){this.container&&!document.body.contains(this.container)&&document.body.appendChild(this.container),this.updateUI(),this.handle?await this.handle():this.startAutoProgress()}dismiss(){this.container&&document.body.contains(this.container)&&document.body.removeChild(this.container),this.progressTimer&&(cancelAnimationFrame(this.progressTimer),this.progressTimer=null)}startAutoProgress(){let e=performance.now();const step=t=>{let n=(t-e)/5e4;var o;n>1&&(n=1),this.progress=(o=n,1-Math.pow(1-o,3)),this.updateUI(),n<1&&(this.progressTimer=requestAnimationFrame(step))};this.progressTimer=requestAnimationFrame(step)}updateUI(){if(!this.container)return;const e=this.container.querySelector(".progress"),t=this.container.querySelector(".fmode-progress-text"),n=this.container.querySelector(".fmode-message"),o=this.container.querySelector(".fmode-task-info");if(e){const t=2*Math.PI*45;e.style.strokeDashoffset=String(t*(1-this._progress))}t&&(t.textContent=`${Math.round(100*this._progress)}%`),n&&(n.textContent=this._message),o&&(o.textContent=`任务 ${this._taskIndex} / ${this._taskTotal}`)}}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}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.disableASR=!1,this.isRecording=!1,this.isUserFinish=!1,this.shouldReconnect=!0,this.reconnectAttempts=0,this.maxReconnectAttempts=3,this.reconnectDelay=1e3,this.recordWavBlob=null,this.recordPcmBlob=null,this.recordDuration=0,this.allRecordedBuffers=[],this.currentRecorder=null,this.btnStatus="UNDEFINED",this.connStatus="",this.resultText="",this.resultTextTemp="",this.durationStr="00:00",this.duration=0,this.recordType="pcm",this.encodingType="raw",this.APPID="50f4a46c",this.API_SECRET="NzFlNmFhZDJjMDNkZGM3NzI0Mzg2OGNm",this.API_KEY="106ddc40dfd4b9ca6d7b47c70fada749",this.requestPermission()}toggleRecord(){console.log("toggleRecord",this.btnStatus),"UNDEFINED"===this.btnStatus||"CLOSED"===this.btnStatus?this.startTalk():"CONNECTING"!==this.btnStatus&&"OPEN"!==this.btnStatus||this.finishTalk()}async startTalk(e){console.log("startTalk called"),this.resetState(),this.onBeforeStartTalk&&this.onBeforeStartTalk(),e?.preventDefault();try{await this.openWithPriviledge(),await this.startIndependentRecording(),this.isRecording=!0,this.shouldReconnect=!0,this.reconnectAttempts=0,setTimeout((()=>{this.connectWebSocket()}),100),this.startCountdown(),this.onAfterStartTalk&&this.onAfterStartTalk()}catch(e){console.error("Failed to start talk:",e),this.resetState()}}async finishTalk(){console.log("finishTalk called"),this.isUserFinish=!0,this.shouldReconnect=!1,this.onBeforeFinishTalk&&this.onBeforeFinishTalk();try{this.closeWebSocket(),await this.stopIndependentRecording(),this.isRecording=!1,this.clearTimers(),this.changeBtnStatus("CLOSED"),setTimeout((()=>{this.isUserFinish&&(this.onAfterFinishTalk&&this.onAfterFinishTalk(),this.isUserFinish=!1)}),500)}catch(e){console.error("Error finishing talk:",e)}}cancelTalk(){console.log("cancelTalk called"),this.onBeforeCancelTalk&&this.onBeforeCancelTalk(),this.isUserFinish=!1,this.shouldReconnect=!1,this.isRecording=!1,this.closeWebSocket(),this.cancelIndependentRecording(),this.resetState(),this.onAfterCancelTalk&&this.onAfterCancelTalk()}async startIndependentRecording(){return console.log("Starting independent recording"),this.allRecordedBuffers=[],this.createIndependentRecorder(),new Promise(((e,t)=>{this.currentRecorder.open((()=>{console.log("Independent recorder opened"),document.querySelector(".record-wave")&&Recorder.WaveView&&(this.waveClient=Recorder.WaveView({elem:".record-wave"})),this.currentRecorder.start(),this.onAfterRecordStart&&this.onAfterRecordStart(),e()}),((e,n)=>{console.error("Failed to open independent recorder:",e),t(new Error(e))}))}))}async stopIndependentRecording(){if(console.log("Stopping independent recording"),this.currentRecorder)return new Promise((e=>{this.currentRecorder.stop((async(t,n)=>{console.log("Independent recording stopped successfully",t,n),this.recordPcmBlob=t,this.recordWavBlob=await this.pcmBlobToWavBlob(t,44100),this.cleanupIndependentRecorder(),e()}),(t=>{console.error("独立录音停止失败:"+t),this.cleanupIndependentRecorder(),e()}))}));console.log("No independent recorder to stop")}cancelIndependentRecording(){if(console.log("Cancelling independent recording"),this.currentRecorder)try{this.currentRecorder.close()}catch(e){console.error("Error closing independent recorder:",e)}this.cleanupIndependentRecorder(),this.recordPcmBlob=null,this.recordWavBlob=null}createIndependentRecorder(){this.currentRecorder&&this.cleanupIndependentRecorder(),this.currentRecorder=Recorder({type:this.recordType,sampleRate:44100,bitRate:16,onProcess:(e,t,n,o,i,a)=>{if(!this.isRecording)return;this.allRecordedBuffers=e;let r=e.length&&e[e.length-1];r&&(r=resampleBuffer(r,44100,16e3),this.sendAudioToWebSocket(r),this.waveClient?.input(e[e.length-1],t,o))}})}cleanupIndependentRecorder(){if(this.currentRecorder){try{this.currentRecorder.close()}catch(e){console.error("Error cleaning up independent recorder:",e)}this.currentRecorder=null}}sendAudioToWebSocket(e){if(this.iatWS&&this.iatWS.readyState===WebSocket.OPEN&&!this.disableASR)try{this.iatWS.send(JSON.stringify({data:{status:1,format:"audio/L16;rate=16000",encoding:this.encodingType,audio:convertFrameBufferToBase64(e)}}))}catch(e){console.error("Error sending audio data to WebSocket:",e)}}connectWebSocket(){if(console.log("connectWebSocket called, shouldReconnect:",this.shouldReconnect),!this.shouldReconnect||!this.isRecording)return void console.log("Not connecting WebSocket - shouldReconnect:",this.shouldReconnect,"isRecording:",this.isRecording);this.closeWebSocket();const e=this.getWebSocketUrl();console.log("Connecting to:",e);try{if(!("WebSocket"in window))return console.error("浏览器不支持WebSocket"),void alert("浏览器不支持WebSocket");this.iatWS=new WebSocket(e),this.changeBtnStatus("CONNECTING"),this.iatWS.onopen=e=>{console.log("WebSocket connected for ASR"),this.reconnectAttempts=0,this.changeBtnStatus("OPEN");const t={common:{app_id:this.APPID},business:{language:"zh_cn",domain:"iat",accent:"mandarin",vad_eos:1e4,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("WebSocket error:",e),this.handleWebSocketError()},this.iatWS.onclose=e=>{console.log("WebSocket closed:",e.code,e.reason),this.handleWebSocketClose(e)}}catch(e){console.error("Failed to create WebSocket:",e),this.handleWebSocketError()}}handleWebSocketClose(e){if(console.log("handleWebSocketClose",{code:e.code,reason:e.reason,shouldReconnect:this.shouldReconnect,isRecording:this.isRecording,isUserFinish:this.isUserFinish}),!this.isUserFinish&&this.shouldReconnect&&this.isRecording){try{this.iatWS&&this.iatWS.readyState===WebSocket.OPEN&&this.iatWS.send(JSON.stringify({data:{status:2,format:"audio/L16;rate=16000",encoding:this.encodingType,audio:""}}))}catch(e){console.error("Error sending end frame on close:",e)}1e3===e.code||1006===e.code||1011===e.code?this.attemptReconnect():(console.error("WebSocket closed with error code:",e.code),this.handleWebSocketError())}}handleWebSocketError(){this.shouldReconnect&&this.isRecording&&this.attemptReconnect()}attemptReconnect(){this.reconnectAttempts>=this.maxReconnectAttempts?console.error("Max reconnect attempts reached"):(this.reconnectAttempts++,console.log(`Attempting WebSocket reconnect ${this.reconnectAttempts}/${this.maxReconnectAttempts}`),setTimeout((()=>{this.shouldReconnect&&this.isRecording&&!this.isUserFinish&&this.connectWebSocket()}),this.reconnectDelay*this.reconnectAttempts))}closeWebSocket(){if(this.iatWS){try{this.iatWS.readyState===WebSocket.OPEN&&this.iatWS.send(JSON.stringify({data:{status:2,format:"audio/L16;rate=16000",encoding:this.encodingType,audio:""}})),this.iatWS.readyState!==WebSocket.OPEN&&this.iatWS.readyState!==WebSocket.CONNECTING||this.iatWS.close(1e3,"User initiated close")}catch(e){console.error("Error closing WebSocket:",e)}this.iatWS=null}}resetState(){this.resultText="",this.resultTextTemp="",this.durationStr="00:00",this.duration=0,this.recordDuration=0,this.allRecordedBuffers=[],this.clearTimers()}clearTimers(){this.countdownInterval&&(clearInterval(this.countdownInterval),this.countdownInterval=null),this.durationInterval&&(clearInterval(this.durationInterval),this.durationInterval=null)}changeBtnStatus(e){switch(this.btnStatus=e,e){case"CONNECTING":this.connStatus="建立连接中";break;case"OPEN":this.connStatus=`录音中(${this.durationStr})`;break;case"CLOSING":this.connStatus="关闭连接中";break;case"CLOSED":this.connStatus="开始录音"}}startCountdown(){this.clearTimers(),this.recordDuration=0,this.duration=0,this.now=new Date,this.durationInterval=setInterval((()=>{this.isRecording&&(this.recordDuration+=100)}),100),this.countdownInterval=setInterval((()=>{this.isRecording&&this.countTimer()}),1e3)}countTimer(){this.duration++;let e=String(Math.floor(this.duration/60)).padStart(2,"0")+":"+String(this.duration%60).padStart(2,"0");this.durationStr=e,this.connStatus=`录音中(${this.durationStr})`,this.onDurationStrChange&&this.onDurationStrChange(e)}renderResult(e){try{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.onInputChange&&this.onInputChange(this.getUserInput())}0===t.code&&2===t.data.status&&(console.log("ASR session completed, will reconnect if still recording"),this.iatWS&&this.iatWS.readyState===WebSocket.OPEN&&this.iatWS.close()),0!==t.code&&(console.error("ASR error:",t),this.iatWS&&this.iatWS.readyState===WebSocket.OPEN&&this.iatWS.close())}catch(e){console.error("Error parsing result:",e)}}getUserInput(){return""+(this.resultTextTemp||this.resultText)}async openWithPriviledge(){return await this.requestPermission(),Recorder.IsOpen(),!0}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()}playRecord(){this.recordPcmBlob&&this.playPCM(this.recordPcmBlob,44100)}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)}isCapacitor(){return!!this.platform?.is&&(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()}}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"})}async playBuffers(){let e=await this.BuffersToBlob(this.allRecordedBuffers);this.playPCM(e,44100)}BuffersToBlob(e){let t=[];return e.forEach((e=>{e.forEach((e=>{t.push(e)}))})),new Blob([t],{type:"audio/pcm"})}}function wxdebug$1(...e){console.log(e)}function createMessageAPI(e,t){const n="message/send",baseMerge=e=>({touser:e?.touser,toparty:e?.toparty,totag:e?.totag,agentid:e?.agentid,safe:e?.safe??0,enable_id_trans:e?.enable_id_trans??0,enable_duplicate_check:e?.enable_duplicate_check??0,duplicate_check_interval:e?.duplicate_check_interval??1800});return{async sendText(o){const i={...baseMerge(o),msgtype:"text",text:{content:o.content}};return wxdebug$1("sendText:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},async sendImage(o){const i={...baseMerge(o),msgtype:"image",image:{media_id:o.media_id}};return wxdebug$1("sendImage:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},async sendVoice(o){const i={...baseMerge(o),msgtype:"voice",voice:{media_id:o.media_id}};return wxdebug$1("sendVoice:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},async sendVideo(o){const i={...baseMerge(o),msgtype:"video",video:{media_id:o.media_id,title:o.title,description:o.description}};return wxdebug$1("sendVideo:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},async sendFile(o){const i={...baseMerge(o),msgtype:"file",file:{media_id:o.media_id}};return wxdebug$1("sendFile:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},async sendTextCard(o){const i={...baseMerge(o),msgtype:"textcard",textcard:{title:o.title,description:o.description,url:o.url,btntxt:o.btntxt||"详情"}};return wxdebug$1("sendTextCard:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},async sendNews(o){const i={...baseMerge(o),msgtype:"news",news:{articles:o.articles}};return wxdebug$1("sendNews:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},async sendMarkdown(o){const i={...baseMerge(o),msgtype:"markdown",markdown:{content:o.content}};return wxdebug$1("sendMarkdown:"+JSON.stringify(i)),t({company:e,path:n,method:"POST",body:i})},send:async o=>(wxdebug$1("send(custom):"+JSON.stringify(o)),t({company:e,path:n,method:"POST",body:o}))}}class WxworkCorp{constructor(e){this.config={},this.ticket={get:async(e="agent_config")=>{let t={};e&&(t.type=e);let n=await WwRequest({company:this.company,path:"ticket/get",method:"GET",queryParams:t});return n?.ticket}},this.service={async corpIdToOpenCorpId(e){return await WwRequest({company:this.company,path:"auth/getuserinfo",method:"GET",body:{corpid:e}})}},this.auth={getuserinfo:async e=>{wxdebug$1("getuserinfo request");let t=await WwRequest({company:this.company,path:"auth/getuserinfo",method:"GET",queryParams:{code:e}});if(t?.user_ticket){let e=await WwRequest({company:this.company,path:"auth/getuserdetail",method:"POST",body:{user_ticket:t?.user_ticket}});e?.qr_code&&Object.keys(e).forEach((n=>{t[n]=e[n]})),console.log("企业用户详情:",t)}return t?.openid,t||null}},this.user={getUserId:async e=>{let t=await WwRequest({company:this.company,path:"user/getuserid",method:"POST",body:{mobile:e}});return console.log(t),t?.userid||null},get:async e=>{let t=await WwRequest({company:this.company,path:"user/get",method:"GET",queryParams:{id:e}});return console.log(t),t?.department||null},listId:async(e,t,n)=>{let o="user/list_id",i="POST",a={limit:100};(e=e||null)&&(o="user/simplelist",i="GET",a=null);let r=await WwRequest({company:this.company,method:i,queryParams:{department_id:e},path:o,body:a});return console.log(r),e?r?.userlist||[]:r?.dept_user||[]},list:async e=>{let t=e?.id,n=await WwRequest({company:this.company,path:"department/list",method:"GET",queryParams:{id:t}});return console.log(n),n}},this.department={get:async e=>{let t=await WwRequest({company:this.company,path:"department/get",method:"GET",queryParams:{id:e}});return console.log(t),t?.department||null},listId:async e=>{let t=e?.id,n=await WwRequest({company:this.company,method:"GET",queryParams:{id:t},path:"department/simplelist"});return console.log(n),n?.department_id||[]},list:async e=>{let t=e?.id,n=await WwRequest({company:this.company,path:"department/list",method:"GET",queryParams:{id:t}});return console.log(n),n}},this.externalContact={get:async e=>await WwRequest({method:"GET",company:this.company,path:"externalcontact/get",queryParams:{external_userid:e}}),groupChat:{addJoinWay:async e=>await WwRequest({method:"POST",company:this.company,path:"externalcontact/groupchat/add_join_way",body:e}),getJoinWay:async e=>{if(!e)return null;return await WwRequest({method:"POST",company:this.company,path:"externalcontact/groupchat/get_join_way",body:{config_id:e}})},get:async e=>await WwRequest({method:"POST",company:this.company,path:"externalcontact/groupchat/get",body:{chat_id:e,need_name:1}}),list:async e=>{let t={limit:e?.limit||20};e?.userid_list&&(t.owner_filter={userid_list:[e?.userid_list]});let n=await WwRequest({company:this.company,path:"externalcontact/groupchat/list",body:t});return console.log(n),n}}},this.appchat={sendText:async(e,t,n=0)=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:{chatid:e,msgtype:"text",text:{content:t},safe:n}}),sendImage:async(e,t,n=0)=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:{chatid:e,msgtype:"image",image:{media_id:t},safe:n}}),sendVideo:async(e,t,n,o,i=0)=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:{chatid:e,msgtype:"video",video:{media_id:t,title:n,description:o},safe:i}}),sendFile:async(e,t,n=0)=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:{chatid:e,msgtype:"file",file:{media_id:t},safe:n}}),sendTextCard:async(e,t,n,o,i,a=0)=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:{chatid:e,msgtype:"textcard",textcard:{title:t,description:n,url:o,btntxt:i||"详情"},safe:a}}),sendNews:async(e,t,n=0)=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:{chatid:e,msgtype:"news",news:{articles:t},safe:n}}),sendMarkdown:async(e,t)=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:{chatid:e,msgtype:"markdown",markdown:{content:t}}}),send:async e=>await WwRequest({company:this.company,path:"appchat/send",method:"POST",body:e})},this.meeting={create:async e=>await WwRequest({company:this.company,path:"meeting/create",method:"POST",body:e}),list:async e=>{let t={limit:e?.limit||20};return e?.userid&&(t.userid=e.userid),e?.cursor&&(t.cursor=e.cursor),e?.begin_time&&(t.begin_time=e.begin_time),e?.end_time&&(t.end_time=e.end_time),await WwRequest({company:this.company,path:"meeting/list",method:"POST",body:t})},get:async e=>await WwRequest({company:this.company,path:"meeting/get",method:"POST",body:{meetingid:e}})},this.company=e,this.message=createMessageAPI(this.company,WwRequest)}}async function WwRequest(e){let t,n,o=e?.company,i=e?.path,a=e?.method||"POST",r="https://server.fmode.cn/api/wework/func";e?.body&&Object.keys(e?.body)?.length&&(t=e?.body),e?.queryParams&&(n=e?.queryParams),t||(t={});let s=JSON.stringify({company:o,path:i,body:t,queryParams:n,method:a});console.log(s);let l={method:"POST",headers:{"Content-Type":"application/json"},body:s};console.log(l,r);try{let e=await fetch(r,l);return await e.json()}catch(e){return alert("wxreqErr:"+JSON.stringify(e)),null}}const createLoginContainer=()=>{const e=document.getElementById("ww_login");e&&e.remove();const t=document.createElement("div");t.id="ww_login",t.style.cssText="\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: rgba(255, 255, 255, 0.9);\n z-index: 99999; /* 确保在最顶层 */\n ",document.body.appendChild(t)},removeLoginContainer=()=>{try{const e=document.getElementById("ww_login");e&&e.remove()}catch(e){}},Parse$B=defaultExport.with("nova");class WxworkSDK{constructor(e){this.companyMap={E4KpGvTEto:{corpResId:"vsVIWbd1i9"},uRiDGwEYLi:{corpResId:"JxfFXBr0ly"},cDL6R1hgSi:{corpResId:"SpL6gyD1Gu"}},this.suiteMap={crm:{suiteId:"dk2559ba758f33d8f5"}},this.ww=ww,this.groupChat={createGroupChat:async e=>{try{return wxdebug$1("createGroupChat"+JSON.stringify(e)),await this.registerCorpWithSuite()?new Promise(((t,n)=>{e.success=e=>{wxdebug$1(JSON.stringify(e)),t(e)},e.fail=e=>{wxdebug$1(JSON.stringify(e)),n(e)},ww.createCorpGroupChat(e)})):null}catch(e){wxdebug$1(JSON.stringify(e))}},addUserInfoGroup:async e=>{wxdebug$1("addUserInfoGroup"+JSON.stringify(e));try{let t=await this.registerCorpWithSuite();return wxdebug$1("isRegister"+t),t?(wxdebug$1(JSON.stringify(e)),new Promise(((t,n)=>{e.success=e=>{wxdebug$1(JSON.stringify(e)),t(e)},e.fail=e=>{wxdebug$1(JSON.stringify(e)),n(e)},ww.updateCorpGroupChat(e)}))):null}catch(e){wxdebug$1(JSON.stringify(e))}}},this.cid=e?.cid,this.appId=e?.appId,this.wecorp=new WxworkCorp(this.cid)}async syncGroupChat(e){let t=new Parse$B.Query("GroupChat");t.equalTo("chat_id",e?.chat_id);let n=await t.first();n?.id||(n=new Parse$B.Object("GroupChat"));let o=!1;if(!n?.get("joinUrl")){let t=(await this.wecorp.externalContact.groupChat.addJoinWay({scene:1,chat_id_list:[e.chat_id]}))?.config_id,i=(await this.wecorp.externalContact.groupChat.getJoinWay(t))?.join_way;n.set("joinUrl",i),o=!0}if(!n?.get("joinQrcode")){let t=(await this.wecorp.externalContact.groupChat.addJoinWay({scene:2,chat_id_list:[e.chat_id]}))?.config_id,i=(await this.wecorp.externalContact.groupChat.getJoinWay(t))?.join_way;n.set("joinQrcode",i),o=!0}let i={chat_id:e.chat_id,name:e.name,owner:e.owner,notice:e.notice};return n.get("chat_id")!=e.chat_id&&(o=!0),n.get("name")!=e.name&&(o=!0),n.get("owner")!=e.owner&&(o=!0),n.get("notice")!=e.notice&&(o=!0),n.get("member_version")!=e.member_version&&(o=!0,i.member_list=e.member_list,i.member_version=e.member_version),n.set(i),this.cid&&n.set("company",{__type:"Pointer",className:"Company",objectId:this.cid}),o&&(n=await n.save()),n}async syncContact(e){const t=e.external_contact||e,n=t.external_userid;let o=new Parse$B.Query("ContactInfo");o.equalTo("external_userid",n);const i=new Parse$B.Object("Company");i.id=this.cid,o.equalTo("company",i);let a=await o.first();a?.id||(a=new Parse$B.Object("ContactInfo"),i?.id&&a.set("company",i.toPointer()));const r=t.name||"",s=t.mobile||"",l={...t,follow_user:e.follow_user||t.follow_user||[]};let c=!1;a.get("external_userid")!=n&&(c=!0),a.get("name")!=r&&r&&(c=!0),a.get("mobile")!=s&&s&&(c=!0);const d=a.get("data");return JSON.stringify(d)!==JSON.stringify(l)&&(c=!0),a.set("external_userid",n),a.set("name",r),a.set("mobile",s),a.set("data",l),wxdebug$1("syncContact",a.toJSON()),c&&(a=await a.save()),a}async getCurrentChatObject(){const e=await this.getCurrentChat();if(!e)return{currentChat:null};let t,n;try{if("chatId"===e.type&&e.group)t=await this.syncGroupChat(e.group);else if("userId"===e.type&&e.id){const t=await this.wecorp.externalContact.get(e.id);n=await this.syncContact(t)}}catch(e){console.error("getCurrentChatObject error:",e)}return{GroupChat:t,Contact:n,currentChat:e}}async syncUserInfo(e){let t=null;1==e.gender&&(t="男"),2==e.gender&&(t="女");let n=await this.getContactOrProfile(e);console.log("thisUser",n),console.log("userInfo",e),"ContactInfo"==n.className&&n.set({data:{openid:e.openid,userid:e.userid,external_userid:e.external_userid,type:e.type&&String(e.type)||null,name:e.name,avatar:e.avatar,gender:t,qr_code:e.qr_code,mobile:e.mobile,email:e.email,biz_mail:e.biz_mail,address:e.address,position:e.position,corp_name:e.corp_name},type:"wecom-agency",company:{__type:"Pointer",className:"Company",objectId:this.cid}}),"Profile"==n.className&&(n.set({openid:e.openid,userid:e.userid,external_userid:e.external_userid,type:e.type&&String(e.type)||null,name:e.name,avatar:e.avatar,gender:t,qr_code:e.qr_code,mobile:e.mobile,email:e.email,biz_mail:e.biz_mail,address:e.address,position:e.position,corp_name:e.corp_name,company:{__type:"Pointer",className:"Company",objectId:this.cid}}),n.set("data",e));try{if(n?.id&&!n.get("user")?.id){let e=Parse$B.User.current();e?.id&&n.set("user",e?.toPointer())}n=await n.save()}catch(e){wxdebug$1(e)}return n}async getUserinfo(e){let t,n;wxdebug$1("getUserinfo");let o=localStorage.getItem(`${this.cid}/USERINFO`);if(!e){t=JSON.parse(o),t.cid=this.cid,wxdebug$1("getContactOrProfile");try{n=await this.getContactOrProfile(t)}catch(e){}if(wxdebug$1("getUserinfo:"+o),t&&n)return t}if(!(e=new URL(location.href).searchParams.get("code")||e))return null;let i=await this.wecorp.auth.getuserinfo(e);if(wxdebug$1("result"+JSON.stringify(i)),i?.errcode)return console.error(i?.errmsg),null;let a=i?.external_userid;if(a){let e=await this.wecorp.externalContact.get(a);e?.external_contact&&Object.keys(e?.external_contact).forEach((t=>{i[t]=e?.external_contact[t]}))}return i.cid=this.cid,t=i,n=await this.getContactOrProfile(t),n?.get("mobile")&&(t.mobile=n?.get("mobile")),o=JSON.stringify(i),localStorage.setItem(`${this.cid}/USERINFO`,o),t}async getCurrentUser(){const e=await this.getUserinfo();if(!e)return null;return await this.getContactOrProfile(e)}async getContactOrProfile(e){let t;(e.openid||e.external_userid)&&(t="ContactInfo"),e.userid&&(t="Profile");let n=[];"Profile"==t&&(e.openid&&n.push({openid:{$regex:e.openid}}),e.userid&&n.push({userid:{$regex:e.userid}}),e.mobile&&n.push({mobile:{$regex:e.mobile}}),e.email&&n.push({email:{$regex:e.email}}),e.external_userid&&n.push({external_userid:{$regex:e.external_userid}})),"ContactInfo"==t&&(e.openid&&n.push({"data.openid":{$regex:e.openid}}),e.userid&&n.push({"data.userid":{$regex:e.userid}}),e.mobile&&n.push({"data.mobile":{$regex:e.mobile}}),e.email&&n.push({"data.email":{$regex:e.email}}),e.external_userid&&n.push({"data.external_userid":{$regex:e.external_userid}}));let o,i=Parse$B.Query.fromJSON(t,{where:{$or:n}});i.equalTo("company",this.cid),i.equalTo("userid",e.userid);try{o=await i.first()}catch(e){console.error(e)}o?.id||(o=new Parse$B.Object(t));let a=Parse$B.User.current();return a?.id&&(o?.get("user")?.id||o.set("user",a.toPointer())),o}async loginPC(){let e=await this.getCorpByCid(this.cid);console.log(this.cid,e);const t=e?.corpId,n=e?.agentId,o=new URL("https://app.fmode.cn"+location.pathname+location?.search);o.searchParams.delete("code"),o.searchParams.delete("state");const i=o.href,a=ww.WWLoginType.corpApp,r=ww.WWLoginRedirectType.callback;console.log("loginPC1");return document.getElementById("ww_login")||createLoginContainer(),new Promise(((e,o)=>{console.log("loginPC2");const s=this.ww.createWWLoginPanel({el:"#ww_login",params:{login_type:a,appid:t,agentid:n,redirect_uri:i,state:"loginState",redirect_type:r},onCheckWeComLogin({isWeComLogin:e}){console.log(e)},onLoginSuccess({code:t}){console.log({code:t}),removeLoginContainer(),e(t)},onLoginFail(e){console.error("lpc",e),removeLoginContainer(),o(e)}});console.log(s,s.el)}))}async oauth(e="snsapi_base",t=!1){t&&localStorage.removeItem(`${this.cid}/USERINFO`),wxdebug$1("oauth");let n=await this.getCorpByCid(this.cid);console.log(this.cid,n);let o=n?.corpId,i=n?.agentId,a=new URL("https://app.fmode.cn"+location.pathname+location?.search);a.searchParams.delete("code"),a.searchParams.delete("state");let r=encodeURIComponent(a.href),s=`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${o}&redirect_uri=${r}&response_type=code&scope=${e}&state=STATE&agentid=${i}#wechat_redirect`;if("h5"==this.platform()){if(location.host?.startsWith("localhost"))return"";s=`https://login.work.weixin.qq.com/wwlogin/sso/login?login_type=CorpApp&appid=${o}&agentid=${i}&redirect_uri=${r}&state=WWLogin`,console.log("createWWLoginPanel")}return location.href=s,null}async getCorpByCid(e){if(console.log("cid",e),this.corpId)return this.corpId;let t=new Parse$B.Query("CloudResource"),n=(await t.get(this.companyMap[e]?.corpResId)).get("config");return console.log("config",n),n}async registerCorpWithSuite(e,t,n){if("wxwork"!=this.platform())return!1;if(!n?.length&&this.registerUrl==location.href)return!0;n=n||jsApiList;try{e=e||this.cid,t=t||this.appId;let o=await this.getCorpByCid(e);console.log(o);let i=o?.corpId,a=this.suiteMap[t]?.suiteId;console.log(i,a);let r=new Date,s=new Promise((e=>{ww.register({corpId:o.corpId,suiteId:a,agentId:o.agentId,jsApiList:n,getAgentConfigSignature:async()=>{let e=await this.wecorp.ticket.get();return ww.getSignature({ticket:e,nonceStr:"666",timestamp:(r.getTime()/1e3).toFixed(0),url:location.href})},onAgentConfigSuccess:()=>{this.registerUrl=location.href,e(!0)},onAgentConfigFail:t=>{e(!1)},onConfigFail:t=>{e(!1)}})}));return await s}catch(e){return wxdebug$1(JSON.stringify(e)),!1}}getUA(){return this.ua=navigator.userAgent.toLowerCase(),this.ua}platform(){return this.ua=navigator.userAgent.toLowerCase(),this.ua.indexOf("wxwork")>-1?"wxwork":this.ua.indexOf("wechat")>-1?"wechat":"h5"}async getContext(){await this.registerCorpWithSuite();try{let e=await ww.getContext();return e?.entry&&(this.entry=e?.entry),e}catch(e){this.entryError="请先注册JSAPI"+e.errCode+e.errMsg,console.error(e)}return null}async getCurrentChat(){let e;if(!await this.registerCorpWithSuite())return null;try{e=await ww.getContext()}catch(e){console.error(e)}let t,n,o,i,a=e?.entry;try{return"group_chat_tools"==a&&(t="chatId",n=(await ww.getCurExternalChat())?.chatId,i=await this.wecorp.externalContact.groupChat.get(n)),"contact_profile"!=a&&"single_chat_tools"!=a||(t="userId",n=(await ww.getCurExternalContact())?.userId,o=await this.wecorp.externalContact.get(n)),this.currentChat={type:t,id:n,group:i?.group_chat,contact:o?.external_contact,follow_user:o?.follow_user},this.currentChat}catch(e){return wxdebug$1(JSON.stringify(e)),null}}version(){return wxdebug$1(ww.SDK_VERSION),ww.SDK_VERSION}register(){ww.register({corpId:"ww7ca4776b2a70000",jsApiList:["getExternalContact"],getConfigSignature:this.getConfigSignature})}async getConfigSignature(e){return{timestamp:"",nonceStr:"",signature:""}}config(){}async selectEnterpriseContact(){let e=await ww.selectEnterpriseContact({fromDepartmentId:-1,mode:"multi",type:["department","user"]});console.log(e),wxdebug$1(e)}}const jsApiList=["getContext","getCurExternalChat","getCurExternalContact","createCorpGroupChat","updateCorpGroupChat","openExistedChatWithMsg","openEnterpriseChat","sendChatMessage","updateEnterpriseChat","checkJsApi","onMenuShareAppMessage","onMenuShareWechat","onMenuShareTimeline","shareAppMessage","shareWechatMessage","startRecord","stopRecord","onVoiceRecordEnd","playVoice","pauseVoice","stopVoice","uploadVoice","downloadVoice","chooseImage","previewImage","uploadImage","downloadImage","getNetworkType","openLocation","getLocation","hideOptionMenu","showOptionMenu","hideMenuItems","showMenuItems","hideAllNonBaseMenuItem","showAllNonBaseMenuItem","closeWindow","scanQRCode","previewFile","selectEnterpriseContact","onHistoryBack","openDefaultBrowser"],Parse$A=defaultExport.with("nova");async function checkWeworkLogin(e){console.log("WxworkAuthGuard");let t=e.paramMap.get("cid")||e.queryParamMap.get("cid")||localStorage.getItem("company");t&&localStorage.setItem("company",t);let n,o=e.paramMap.get("appId")||"crm",i=new WxworkAuth({cid:t,appId:o});console.log("init wxwork");try{if(n=await i.getUserInfo(),console.log("guard userInfo"+JSON.stringify(n)),n)return await i.syncUserInfo(n),await i.autoLogin(n),!0}catch(e){console.error(e),console.log("guierr"+JSON.stringify(e))}let a=new URL(location?.href).searchParams.get("code");if(console.log("WxworkAuthGuard"+t+a),!a){let e=navigator.userAgent.toLowerCase();if(console.log("ua",e),-1!==e.indexOf("micromessenger")){let e="snsapi_base";"wechat"==i.platform()&&(e="snsapi_base"),"wxwork"==i.platform()&&(e="snsapi_privateinfo");let t=await i.oauth(e);return t&&(a=t),!1}a||(a=await i.loginPC())}try{n=await i.getUserInfo(a)}catch(e){console.log("codeinfoerr:"+JSON.stringify(e))}return console.log("before sync"+n?.mobile),await i.syncUserInfo(n),await i.autoLogin(n),!0}class WxworkAuth{constructor(e){this.cid=e.cid||localStorage.getItem("company"),this.wxwork=new WxworkSDK({cid:e.cid,appId:e.appId||"crm"}),this.platform=this.wxwork.platform}async currentProfile(){let e=await this.getUserInfo(),t=await this.wxwork.getContactOrProfile(e);return"Profile"==t?.className?t:null}async currentContact(){let e=await this.getUserInfo(),t=await this.wxwork.getContactOrProfile(e);return"ContactInfo"==t?.className?t:null}async getUserInfo(e){try{return await this.wxwork.getUserinfo(e)}catch(e){throw console.error("WxworkAuth.getUserInfo error:",e),e}}async syncUserInfo(e){try{if(e||(e=await this.getUserInfo()),!e)throw new Error("无法获取用户信息");return await this.wxwork.syncUserInfo(e)}catch(e){throw console.error("WxworkAuth.syncUserInfo error:",e),e}}async autoLogin(e){try{e||(e=await this.getUserInfo());const t=Parse$A.User.current();if(t?.id){console.log("用户已登录:",t.get("username"));const n=await this.wxwork.getContactOrProfile(e);return n?.id&&!n.get("user")?.id&&(n.set("user",t.toPointer()),await n.save(),console.log("已同步 user 指针到 Profile/UserSocial")),t}if(e||(e=await this.getUserInfo()),!e)throw new Error("无法获取用户信息");const n=e.userid||e.external_userid||e.openid;if(!n||n.length<6)return console.warn("用户名太短,无法自动登录:",n),null;const o=n.slice(-6);try{let t;t=await Parse$A.User.logIn(n,o);const i=await this.wxwork.getContactOrProfile(e);return i?.id&&!i.get("user")?.id&&(i.set("user",t.toPointer()),await i.save(),console.log("已同步 user 指针到 Profile/UserSocial")),t}catch(t){if(console.log("loginError",t),!("string"==typeof t&&t.indexOf("Invalid")>-1||101===t?.code))throw console.error("自动登录失败:",t),t;{console.log("用户不存在,创建新用户:",n);const t=new Parse$A.User;t.set("username",n),t.set("password",o),e.mobile&&t.set("mobile",e.mobile),e.email&&t.set("email",e.email);try{const o=await t.signUp();console.log("自动注册成功:",n);const i=await this.wxwork.getContactOrProfile(e);return i?.id&&(i.set("user",o.toPointer()),await i.save(),console.log("已同步 user 指针到 Profile/UserSocial")),o}catch(e){throw console.error("自动注册失败:",e),e}}}}catch(e){throw console.error("WxworkAuth.autoLogin error:",e),e}}async authenticateAndLogin(e){try{const t=await this.getUserInfo(e),n=await this.autoLogin(t);return{userInfo:t,profile:await this.syncUserInfo(t),user:n}}catch(e){throw console.error("WxworkAuth.authenticateAndLogin error:",e),e}}async oauth(e="snsapi_base",t=!1){try{return await this.wxwork.oauth(e,t)}catch(e){throw console.error("WxworkAuth.oauth error:",e),e}}async loginPC(){try{return await this.wxwork.loginPC()}catch(e){throw console.error("WxworkAuth.loginPC error:",e),e}}getSDK(){return this.wxwork}}let PARSE_APP_ID=localStorage.getItem("PARSE_APP_ID")||"nova";const Parse$z=defaultExport.with(PARSE_APP_ID);class DingTalkAuth{constructor(e){this.config={clientId:e.clientId,corpId:e.corpId,redirectUri:e.redirectUri,agentId:e.agentId,apiOauthWeb:e.apiOauthWeb||"https://server.fmode.cn/api/dingtalk/oauth2/login",apiOauthDingtalk:e.apiOauthWeb||"https://server.fmode.cn/api/dingtalk/oauth2/dingtalk"},this.loadDingTalkSDK()}loadDingTalkSDK(){return new Promise(((e,t)=>{if(window.DTFrameLogin)return void e();const n=document.createElement("script");n.src="https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js",n.onload=()=>e(),n.onerror=()=>t(new Error("Failed to load DingTalk SDK")),document.head.appendChild(n)}))}isInDingTalkApp(){const e=navigator.userAgent.toLowerCase();return e.includes("dingtalk")||e.includes("dingtalk")}async getDingTalkAuthCode(){try{if(console.log("🔐 开始钉钉内免登录流程"),!this.isInDingTalkApp())return{success:!1,error:"不在钉钉环境内,请使用网页登录",loginType:"dingtalk"};await this.loadDingTalkSDK();const e=await this.getAuthCode();if(e){console.log("✅ 钉钉授权码获取成功:",e);return await this.completeDingTalkLogin(e,"dingtalk")}return{success:!1,error:"获取钉钉授权码失败",loginType:"dingtalk"}}catch(e){return console.error("❌ 钉钉免登录失败:",e),{success:!1,error:e.message||"钉钉免登录失败",loginType:"dingtalk"}}}async getAuthCode(){return new Promise(((e,t)=>{if(this.isInDingTalkApp())try{dd.requestAuthCode({corpId:this.config.corpId,clientId:this.config.clientId,onSuccess:t=>{console.log("📱 钉钉授权码获取成功:",t),e(t.code)},onFail:e=>{console.error("❌ 钉钉授权码获取失败:",e),t(new Error(e.errorMessage||"获取授权码失败"))}})}catch(n){if(console.error("❌ 钉钉JSAPI调用失败:",n),dd&&dd.ready)dd.ready((()=>{dd.getAuthCode({corpId:this.config.corpId,onSuccess:t=>{console.log("📱 钉钉授权码获取成功 (兼容模式):",t),e(t.code)},onFail:e=>{console.error("❌ 钉钉授权码获取失败 (兼容模式):",e),t(new Error(e.errorMessage||"获取授权码失败"))}})})),dd.error((e=>{console.error("❌ 钉钉SDK初始化失败:",e),t(new Error("钉钉SDK初始化失败"))}));else{const e=this.buildWebLoginUrl();console.log("📱 跳转到钉钉网页登录:",e),window.location.href=e,t(new Error("需要跳转到网页登录"))}}else t(new Error("不在钉钉环境内"))}))}async getUserInfoByDingTalkCode(e){console.log("🔄 使用钉钉免登授权码获取用户信息:",e);try{const t=await fetch(this.config.apiOauthDingtalk||"",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({appId:this.config.clientId,code:e})}),n=await t.json();if(console.log("🔍 钉钉免登接口返回:",n),1===n.code){const{userInfo:e,sessionToken:t}=n.data;return{userId:e.objectId,username:e.username||e.nickname,nickname:e.nickname,openId:e.openId,unionId:e.unionId,avatar:e.avatar,email:e.email,mobile:e.mobile,corpId:this.config.corpId,sessionToken:t,rawUserInfo:e}}throw new Error(n.mess||"获取用户信息失败")}catch(e){throw console.error("❌ 调用钉钉免登接口失败:",e),e instanceof Error?e:new Error("网络请求失败")}}async getUserInfoByQRCode(e){console.log("🔄 使用二维码授权码获取用户信息:",e);try{const t=await fetch(this.config.apiOauthWeb||"",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({appId:this.config.clientId,code:e,grantType:"authorization_code"})}),n=await t.json();if(console.log("🔍 OAuth2登录接口返回:",n),1===n.code){const{userInfo:e,tokenInfo:t,sessionToken:o}=n.data;return{userId:e.objectId,username:e.username||e.nick,nickname:e.nick||e.username,openId:e.openId,unionId:e.unionId,avatar:e.avatarUrl||e.avatar,email:e.email,mobile:e.mobile,corpId:this.config.corpId,sessionToken:o,tokenInfo:t,rawUserInfo:e}}throw new Error(n.mess||"获取用户信息失败")}catch(e){throw console.error("❌ 调用OAuth2登录接口失败:",e),e instanceof Error?e:new Error("网络请求失败")}}validateConfig(){const e=[];return this.config.clientId||e.push("Client ID 未配置"),this.config.corpId||e.push("Corp ID 未配置"),this.config.redirectUri?this.config.redirectUri.startsWith("http")||e.push("Redirect URI 格式不正确,应以 http 或 https 开头"):e.push("Redirect URI 未配置"),console.log("🔍 钉钉应用配置验证:",{clientId:this.config.clientId,corpId:this.config.corpId,redirectUri:this.config.redirectUri,agentId:this.config.agentId,errors:e,isValid:0===e.length}),{isValid:0===e.length,errors:e}}buildWebLoginUrl(e="nanchi_login"){const t=`https://login.dingtalk.com/oauth2/auth?${new URLSearchParams({client_id:this.config.clientId,response_type:"code",scope:"openid",state:e,redirect_uri:this.config.redirectUri,prompt:"consent"}).toString()}`;return console.log("🔗 构造钉钉网页登录URL:",t),t}initQRCodeLogin(e,t,n){console.log("📱 初始化二维码登录");const o=this.validateConfig();o.isValid?this.loadDingTalkSDK().then((()=>{const o={id:e,width:300,height:300},i={redirect_uri:encodeURIComponent(this.config.redirectUri),response_type:"code",client_id:this.config.clientId,scope:"openid",prompt:"consent",state:"nanchi_qr_login"};console.log("🔍 钉钉登录参数:",{clientId:this.config.clientId,corpId:this.config.corpId,redirectUri:this.config.redirectUri,redirectUriEncoded:encodeURIComponent(this.config.redirectUri),loginParams:i}),window.DTFrameLogin(o,i,(async e=>{console.log("✅ 二维码登录成功:",e);try{const o=await this.completeDingTalkLogin(e.authCode,"qrcode");o.success?t(o):n(o.error||"登录失败")}catch(e){console.error("❌ 二维码登录流程失败:",e),n(e.message||"登录失败")}}),(e=>{console.error("❌ 二维码登录失败:",e),n(e)}))})).catch((e=>{console.error("❌ 加载钉钉SDK失败:",e),n("加载钉钉SDK失败")})):n(`配置验证失败: ${o.errors.join(", ")}`)}async handleAuthCallback(e,t){try{if(console.log("🔄 处理网页登录回调:",{code:e,state:t}),!e)return{success:!1,error:"授权码缺失",loginType:"dingtalk"};return await this.completeDingTalkLogin(e,"dingtalk")}catch(e){return console.error("❌ 处理网页登录回调失败:",e),{success:!1,error:e.message||"处理登录回调失败",loginType:"dingtalk"}}}async webLogin(e,t){try{if(console.log("🔐 开始网页登录:",{username:e}),!e||!t)return{success:!1,error:"用户名或密码不能为空",loginType:"web"};console.log("🔄 调用Parse.User.logIn()进行用户登录...");const n=await Parse$z.User.logIn(e,t);console.log("✅ Parse用户登录成功:",n.id);const o=n.getSessionToken();return{success:!0,userInfo:{userId:n.id,username:n.get("username"),nickname:n.get("nickname")||n.get("username"),email:n.get("email"),mobile:n.get("mobile"),avatar:n.get("avatar"),sessionToken:o,parseUser:n,loginType:"web"},loginType:"web"}}catch(e){console.error("❌ 网页登录失败:",e);let t="登录失败,请重试";return 101===e.code?t="用户名或密码错误":200===e.code?t="连接服务器失败,请检查网络":e.message&&(t=e.message),{success:!1,error:t,loginType:"web"}}}setLogoutCallback(e){this.onLogoutCallback=e}async loginWithSessionToken(e){console.log("🔐 使用sessionToken完成Parse登录");try{const t=await Parse$z.User.become(e);return console.log("✅ Parse用户登录成功:",t.id),{parseUser:t,sessionToken:e,userId:t.id,username:t.get("username")}}catch(e){throw console.error("❌ Parse用户登录失败:",e),new Error("Parse用户登录失败: "+e.message)}}async completeDingTalkLogin(e,t="dingtalk"){try{let n;if(console.log("🚀 开始完整钉钉登录流程,类型:",t),"dingtalk"===t)n=await this.getUserInfoByDingTalkCode(e);else{if("qrcode"!==t)throw new Error("不支持的登录类型");n=await this.getUserInfoByQRCode(e)}if(n.sessionToken){const o=await this.loginWithSessionToken(n.sessionToken);return console.log("✅ 完整钉钉登录流程成功"),{success:!0,code:e,userInfo:{...n,parseUser:o.parseUser},loginType:t}}throw new Error("未获取到sessionToken,无法完成登录")}catch(e){return console.error("❌ 完整钉钉登录流程失败:",e),{success:!1,error:e.message,loginType:t}}}async logout(){console.log("🚪 用户退出登录"),Parse$z.User.logOut(),localStorage.removeItem("nanchi_user_info"),localStorage.removeItem("nanchi_auth_token"),localStorage.removeItem("nanchi_session_token"),localStorage.removeItem("nanchi_login_time"),console.log("🗑️ 本地存储已清除"),this.onLogoutCallback&&this.onLogoutCallback()}saveUserInfo(e){localStorage.setItem("nanchi_user_info",JSON.stringify(e)),localStorage.setItem("nanchi_login_time",Date.now().toString()),e.sessionToken&&localStorage.setItem("nanchi_session_token",e.sessionToken),console.log("💾 用户信息已保存到本地存储")}getUserInfo(){const e=localStorage.getItem("nanchi_user_info");return e?JSON.parse(e):null}isLoggedIn(){const e=this.getUserInfo(),t=localStorage.getItem("nanchi_login_time");if(!e||!t)return!1;return(Date.now()-parseInt(t))/36e5<24}async isParseUserLoggedIn(){try{return null!==Parse$z.User.current()}catch(e){return console.warn("检查Parse用户登录状态失败:",e),!1}}async getCurrentParseUser(){try{return Parse$z.User.current()}catch(e){return console.warn("获取当前Parse用户失败:",e),null}}}function genFileKey(e,t,n){const o=new Date,i=o.getFullYear(),a=String(o.getMonth()+1).padStart(2,"0"),r=String(o.getDate()).padStart(2,"0"),s=String(o.getHours()).padStart(2,"0"),l=String(o.getMinutes()).padStart(2,"0"),c=String(o.getSeconds()).padStart(2,"0"),d=Math.random().toString(36).slice(2,8);return`storage/company/${t||"undefined"}/${n?`${n.replace(/^\/+|\/+$/g,"")}/`:""}${i}${a}${r}/${s}${l}${c}-${d}-${e}`}class QiniuProvider{constructor(e){this.conf=e}setConfig(e){this.conf=e}async upload(e,t){const n=qiniu||window.qiniu||void 0;if(!n)throw new Error("qiniu-js is not available on window");const o=e.name||"blob.bin",i=t?.key||genFileKey(o,"undefined"),a={fname:o,params:{},mimeType:e.type||void 0},r={useCdnDomain:this.conf.useCdnDomain??!0,forceDirect:this.conf.forceDirect??!0};return new Promise(((s,l)=>{n.upload(e,i,this.conf.uptoken,a,r).subscribe({next:e=>{t?.onProgress?.(e)},error:e=>{l(e)},complete:t=>{const n=`${this.conf.domain}${t.key}`,i={key:t.key,url:n,name:o,type:e.type||"",size:e.size||(t.size??0)};s(i)}})}))}}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??Date.now(),metadata:{}};return t.metadata.lastModified=t.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,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)}}const Parse$y=defaultExport.with("nova");class NovaStorage{constructor(e){this.provider=e}setProvider(e){this.provider=e}async initByCid(e,t){this.cid=e,this.provider=await this.selectProvider(e,t)}static async withCid(e,t){const n=new NovaStorage;return await n.initByCid(e,t),n}async selectProvider(e,t){if("hwobs"===t)throw new Error("Hwobs requires explicit configuration. Use setProvider(new HwobsProvider(conf)).");const n=await this.fetchQiniuConf(e);return new QiniuProvider(n)}async fetchQiniuConf(e){const t=await Parse$y.Cloud.run("qiniu_uptoken",{company:e});if(!t?.uptoken||!t?.domain)throw new Error("qiniu_uptoken returned invalid config");return{uptoken:t.uptoken,domain:t.domain,useCdnDomain:!0,forceDirect:!0}}async upload(e,t){if(!this.provider)throw new Error("NovaStorage provider is not set");let n=await calcFileMd5(e),o=await getFileMetadata(e),i={id:"",name:"",type:"",size:0,key:"",url:""},a=await this.getAttachmentByMd5(n);if(a?.id)return i.id=a?.id,i.url=a?.get("url"),i.name=a?.get("name"),i.md5=a?.get("md5"),i.type=a?.get("mime"),i.size=a?.get("size"),i.metadata=a?.get("metadata"),i;const r={...t};!r.key&&e?.name&&(r.key=genFileKey(e.name,this.cid||"",r.prefixKey)),console.log(r);let s=await this.provider.upload(e,r);return s.md5=n,s.metadata=o,a=await this.saveAttachment(s),s.id=a.id,s}async getAttachmentByMd5(e){if(!e)return null;const t=new Parse$y.Query("Attachment");t.equalTo("md5",e),t.addDescending("createdAt");return await t.first()}async saveAttachment(e,t,n,o,i){const a=e.md5||(i?await calcFileMd5(i):void 0);let r=e.url||"";r&&!r.startsWith("http")&&(r=(t||"")+r),r=r.replace(/undefined\//,"");const s=Parse$y.User.current(),l=new Parse$y.Object("Attachment");l.set("size",e.size),l.set("url",r),l.set("name",e.name),l.set("mime",e.type),a&&l.set("md5",a),e.metadata&&l.set("metadata",e.metadata);const c=o||this.cid||localStorage.getItem("company")||void 0;c&&l.set("company",{__type:"Pointer",className:"Company",objectId:c}),n&&l.set("category",{__type:"Pointer",className:"Category",objectId:n}),s?.id&&l.set("user",s.toPointer?s.toPointer():{__type:"Pointer",className:"_User",objectId:s.id});return await l.save()}}class HwobsProvider{constructor(e){this.conf=e,this.client=new ObsClient({access_key_id:e.access_key_id,secret_access_key:e.secret_access_key,server:e.server})}setConfig(e){this.conf=e,this.client=new ObsClient({access_key_id:e.access_key_id,secret_access_key:e.secret_access_key,server:e.server})}genFileKey(e){const t=new Date;return`storage/web-2023/${t.getFullYear()}${String(t.getMonth()+1).padStart(2,"0")}${String(t.getDate()).padStart(2,"0")}/${String(t.getHours()).padStart(2,"0")}${String(t.getMinutes()).padStart(2,"0")}${String(t.getSeconds()).padStart(2,"0")}-${Math.random().toString(36).slice(2,8)}-${e}`}async upload(e,t){const n=e.name||"blob.bin",o=t?.key||this.genFileKey(n);return new Promise(((t,i)=>{this.client.putObject({Bucket:this.conf.bucket,Key:o,SourceFile:e},((a,r)=>{if(a)i(a);else{const i=this.conf.host||"",a={key:o,url:i?`${i}${o}`:o,name:n,type:e.type||"",size:e.size||0};t(a)}}))}))}}class ShopeeClient{constructor(e){if(this.environment="sandbox",!e.serverUrl)throw new Error("serverUrl is required in SDK configuration");this.serverUrl=e.serverUrl.replace(/\/$/,""),this.timeout=e.timeout||3e4,this.headers={"Content-Type":"application/json","User-Agent":"ShopeeSDK/1.0",...e.headers}}async request(e,t){const n=`${this.serverUrl}/api/ecom/shopee/forward`;console.log(e,n,this.serverUrl);const o={shop_id:e.toString(),method:t.method,path:t.path,query:t.query||{},...t.body&&{body:t.body},environment:this.environment},i=new AbortController,a=setTimeout((()=>i.abort()),this.timeout);try{const t=await fetch(n,{method:"POST",headers:this.headers,body:JSON.stringify(o),signal:i.signal});if(clearTimeout(a),!t.ok){const e=await t.text();throw new Error(`HTTP ${t.status}: ${e}`)}const r=await t.json();if(!r.success&&"AUTH_REQUIRED"===r.error){throw new Error(`Authorization required for shop ${e}. Please visit: ${r.data.auth_url}`)}if(!r.success&&"AUTH_EXPIRED"===r.error){throw new Error(`Authorization expired for shop ${e}. Please visit: ${r.data.auth_url}`)}if(!r.success){const e=r;throw new Error(`API request failed: ${e.message} (Status: ${e.data.status_code})`)}return r}catch(e){if(clearTimeout(a),e instanceof Error){if("AbortError"===e.name)throw new Error(`Request timeout after ${this.timeout}ms`);throw e}throw new Error("Unknown error occurred during API request")}}async get(e,t,n){return this.request(e,{method:"GET",path:t,query:n})}async post(e,t,n,o){return this.request(e,{method:"POST",path:t,body:n,query:o})}async put(e,t,n,o){return this.request(e,{method:"PUT",path:t,body:n,query:o})}async delete(e,t,n){return this.request(e,{method:"DELETE",path:t,query:n})}getServerUrl(){return this.serverUrl}getTimeout(){return this.timeout}setHeaders(e){this.headers={...this.headers,...e}}getHeaders(){return{...this.headers}}}class ShopeeShop{constructor(e,t){if(!t||t<=0)throw new Error("Valid shop_id is required");this.client=e,this.shopId=t}async getShopInfo(){return this.client.get(this.shopId,"/api/v2/shop/get_shop_info",{shop_id:this.shopId})}async getCategories(){return this.client.get(this.shopId,"/api/v2/product/get_category",{shop_id:this.shopId})}async getComments(e){return this.client.get(this.shopId,"/api/v2/product/get_comment",{shop_id:this.shopId,...e})}async getProductList(e={}){return e.offset=e?.offset||0,e.page_size=e?.page_size||10,e.item_status=e?.item_status||"NORMAL",this.client.get(this.shopId,"/api/v2/product/get_item_list",{shop_id:this.shopId,...e})}async getProductDetail(e){return this.client.get(this.shopId,"/api/v2/product/get_item_detail",{item_id:e})}async addProduct(e){return this.client.post(this.shopId,"/api/v2/product/add_item",e)}async updateProduct(e,t){return this.client.post(this.shopId,"/api/v2/product/update_item",{item_id:e,...t})}async deleteProduct(e){return this.client.post(this.shopId,"/api/v2/product/delete_item",{item_id:e})}async unlistProduct(e){return this.client.post(this.shopId,"/api/v2/product/unlist_item",{item_id:e})}async getOrderList(e={}){const t=Date.now(),n=t-2592e6,o={shop_id:this.shopId,time_from:Math.floor(n/1e3),time_to:Math.floor(t/1e3),time_range_field:"create_time",...e};return this.client.get(this.shopId,"/api/v2/order/get_order_list",o)}async getOrderDetail(e){return this.client.get(this.shopId,"/api/v2/order/get_order_detail",{order_sn:e})}async getPerformanceMetrics(){return this.client.get(this.shopId,"/api/v2/shop/get_shop_info",{shop_id:this.shopId})}async getLogistics(){return this.client.get(this.shopId,"/api/v2/logistics/get_channel_list",{shop_id:this.shopId})}async getDiscounts(){return this.client.get(this.shopId,"/api/v2/discount/get_discount_list",{shop_id:this.shopId})}async getAnalytics(e={}){return this.client.get(this.shopId,"/api/v2/shop/get_shop_info",{shop_id:this.shopId})}getShopId(){return this.shopId}getClient(){return this.client}}class ShopeeMerchant{constructor(e,t){if(!t||t<=0)throw new Error("Valid main_account_id is required");this.client=e,this.mainAccountId=t}async getMerchantInfo(){return this.client.get(this.mainAccountId,"/api/v2/merchant/get_merchant_info")}async getShopList(){return this.client.get(this.mainAccountId,"/api/v2/merchant/get_shop_list")}async getProfile(){return this.client.get(this.mainAccountId,"/api/v2/merchant/get_profile")}async updateProfile(e){return this.client.post(this.mainAccountId,"/api/v2/merchant/update_profile",e)}async getFinancialInfo(){return this.client.get(this.mainAccountId,"/api/v2/financial/get_financial_info")}async getWalletBalance(){return this.client.get(this.mainAccountId,"/api/v2/financial/get_wallet_balance")}async getTransactionHistory(e={}){return this.client.get(this.mainAccountId,"/api/v2/financial/get_transaction_history",e)}async createWithdrawal(e){return this.client.post(this.mainAccountId,"/api/v2/financial/create_withdrawal",e)}async getWithdrawalHistory(e={}){return this.client.get(this.mainAccountId,"/api/v2/financial/get_withdrawal_history",e)}async getStatistics(e={}){return this.client.get(this.mainAccountId,"/api/v2/merchant/get_statistics",e)}async getNotifications(e={}){return this.client.get(this.mainAccountId,"/api/v2/merchant/get_notifications",e)}async markNotificationAsRead(e){return this.client.post(this.mainAccountId,"/api/v2/merchant/mark_notification_read",{notification_id:e})}async getSettings(){return this.client.get(this.mainAccountId,"/api/v2/merchant/get_settings")}async updateSettings(e){return this.client.post(this.mainAccountId,"/api/v2/merchant/update_settings",e)}async getPermissions(){return this.client.get(this.mainAccountId,"/api/v2/merchant/get_permissions")}async getAuditLogs(e={}){return this.client.get(this.mainAccountId,"/api/v2/merchant/get_audit_logs",e)}getMainAccountId(){return this.mainAccountId}getClient(){return this.client}}class ShopeePublic{constructor(e){this.client=e}async generateAuthUrl(e){let t=new Headers;t.append("Content-Type","application/json");let n=await fetch(this.client.getServerUrl()+"/api/ecom/shopee/auth-url",{headers:t,method:"POST",body:JSON.stringify({redirect_uri:e})});return await n.json()}async generateCancelAuthUrl(e){return this.client.post(0,"/api/ecom/shopee/cancel-auth-url",{redirect_uri:e})}async getConfig(){return this.client.get(0,"/api/ecom/shopee/config")}async healthCheck(){return this.client.get(0,"/api/ecom/shopee/health")}async verifySignature(e,t,n){return this.client.post(0,"/api/ecom/shopee/verify-signature",{path:e,params:t,timestamp:n})}async getPublicCategories(e){return this.client.get(0,"/api/v2/public/category/get_category",{region:e})}async getPublicItemDetail(e,t,n){return this.client.get(0,"/api/v2/public/item/get_item_detail",{item_id:e,shop_id:t,region:n})}async searchPublicItems(e){return this.client.get(0,"/api/v2/public/item/search",e)}async getPublicShopInfo(e,t){return this.client.get(0,"/api/v2/public/shop/get_shop_info",{shop_id:e,region:t})}async getPublicShopItems(e,t,n={}){return this.client.get(0,"/api/v2/public/shop/get_items",{shop_id:e,region:t,...n})}async getPublicLogistics(e){return this.client.get(0,"/api/v2/public/logistics/get_channels",{region:e})}async getExchangeRates(e,t){const n={};return e&&(n.from_currency=e),t&&(n.to_currency=t),this.client.get(0,"/api/v2/public/currency/get_exchange_rate",n)}async getMarketplaceStats(e){return this.client.get(0,"/api/v2/public/marketplace/get_statistics",{region:e})}async getTrendingItems(e,t){const n={region:e};return t&&(n.category_id=t),this.client.get(0,"/api/v2/public/trending/get_items",n)}async validateWebhook(e,t){return this.client.post(0,"/api/v2/public/webhook/validate",{payload:e,signature:t})}getClient(){return this.client}}class ShopeeSDK{constructor(e){this.client=new ShopeeClient(e),this.public=new ShopeePublic(this.client)}shop(e,t="sandbox"){return this.client.environment=t,new ShopeeShop(this.client,e)}merchant(e){return new ShopeeMerchant(this.client,e)}getClient(){return this.client}updateConfig(e){e.serverUrl?(this.client=new ShopeeClient({...e,serverUrl:e.serverUrl}),this.public=new ShopeePublic(this.client)):(e.headers&&this.client.setHeaders(e.headers),e.timeout&&console.log("Timeout update would require client reinitialization"))}}const Parse$x=defaultExport.with("nova");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$x.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}}const Parse$w=defaultExport.with("nova");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"})}}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}]});const Parse$v=defaultExport.with("nova");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){const n=e.type,o=e.name?.split(".")?.pop()||"";let i={id:"",name:"",type:"",size:0,key:"",url:""};const a=await this.getFileMd5(e);if(!this.storage)try{this.storage=await NovaStorage.withCid(this.getCompanyId())}catch{this.ensureStorage()}const r=await(this.storage?.getAttachmentByMd5(a));if(r?.id)i.url=r?.get("url"),i.name=r?.get("name"),i.type=r?.get("mime"),i.size=r?.get("size"),i.metadata=r?.get("metadata"),t&&t({total:{loaded:i.size,size:i.size,percent:100}});else{const a=this.fileToBlob(e);i=n.indexOf("image")>-1?await this.saveQiniuImageFile(a,o,null,t):await this.saveQiniuMediaFile(e,a,null,t)}i?.url?.indexOf("undefined")>-1&&(i.url=(this.qiniuDomain||"https://file-cloud.fmode.cn/")+i.url.replace("undefined/",""));const s=(await getFileMetadata(e)).metadata;let l;return i.metadata={...i.metadata||{},...s},i?.url&&(l=await(this.storage?.saveAttachment(i,this.qiniuDomain,null,this.getCompanyId(),e))),l?.id&&(i.id=l?.id),i.attachment=l,i}async getAttachByMd5(e){if(!e)return null;if(!this.storage)try{this.storage=await NovaStorage.withCid(this.getCompanyId())}catch{this.ensureStorage()}return this.storage?.getAttachmentByMd5(e)}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$v.Cloud.run("qiniu_uptoken",{company:this.getCompanyId()});console.log(e),this.qiniuConf=e,this.qiniuProviderConf={uptoken:this.qiniuConf?.uptoken,domain:this.qiniuConf?.domain,useCdnDomain:!0,forceDirect:!0},this.ensureStorage()}catch(e){console.error(e)}}ensureStorage(){if(this.qiniuProviderConf){const e=new QiniuProvider(this.qiniuProviderConf);this.storage=new NovaStorage(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$v.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){if(!this.storage)try{this.storage=await NovaStorage.withCid(this.getCompanyId())}catch{this.ensureStorage()}return await(this.storage?.saveAttachment(e,t,n,o,i))}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;const l=new File([e],r,{type:s}),c=this.genFileKey({id:a,name:r});if(this.storage||this.ensureStorage(),!this.storage)throw"Storage provider not initialized";return{...await this.storage.upload(l,{key:c,onProgress:e=>o&&o(e)}),name:r,type:s,size:e.size}}async saveQiniuMediaFile(e,t,n,o){let i=e.name,a=e.type,r=e.size;if(r>(this.maxSize||104857600))throw console.log("视频过大,超出限制100MB"),"超出文件大小";let s=new DatePipe("en").transform(new Date,"yyyyMMddHHmmss");const l=new File([t],i,{type:a}),c=this.genFileKey({id:s,name:i});if(this.storage||this.ensureStorage(),!this.storage)throw"Storage provider not initialized";return{...await this.storage.upload(l,{key:c,onProgress:e=>o&&o(e)}),name:i,type:a,size:r}}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}]});const Parse$u=defaultExport.with("nova");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$u.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$u?.User?.current()?.id)return;let t=new Parse$u.Query("ChatSession");e&&(t=Parse$u.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$u.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$u.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){console.log("createNewRoleChat",e);let t=new Parse$u.Query("AvatarRole");t.include("model");let n=await t.get(e);return console.log("role",n),new FmodeChat("new",n,null,this,this.navCtrl,this.ncloud,this.uploadServ)}async restoreChatPanel(e){let t=new Parse$u.Query("AvatarRole"),n=new Parse$u.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"})}}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}]});const Parse$t=defaultExport.with("nova");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$t.Query("ImagineWork");e.get(o?.id),n=await e.first(),console.log(n)}return n}async function myFetchFun(e,t){let n=Parse$t.User.current(),o=await fetch(e,{headers:{authorization:`Bearer ${n?.getSessionToken()}`,"Content-Type":"application/json"},mode:"cors",credentials:"omit",method:"POST",body:JSON.stringify(t)});return await o.json()}async function getJimengImg(e){let t,n,o=await myFetchFun("https://server.fmode.cn/api/volcengine/jimeng/getImg",e);t=o?.data?.workId;let i=new Parse$t.Query("ImagineWork");return n=await i.get(t),n}async function getJimengT_v(e){let t,n=await myFetchFun("https://server.fmode.cn/api/volcengine/jimeng/getVideoByText",e);if(console.log("获取的taskId:",n),t=n?.data?.workId,t){let e,n=new Parse$t.Query("ImagineWork");return e=await n.get(t),e}return n}async function getJimengI_v(e){let t,n=await myFetchFun("https://server.fmode.cn/api/volcengine/jimeng/getVideoByImg",e);if(console.log("获取的taskId:",n),t=n?.data?.workId,t){let e,n=new Parse$t.Query("ImagineWork");return e=await n.get(t),e}return n}async function getJimengV_data(e){let t,n,o=await myFetchFun("https://server.fmode.cn/api/volcengine/jimeng/getDataByTask",e);if(console.log("根据taskId请求出来的结果:",o),o?.error)return o;t=o?.data?.workId;let i=new Parse$t.Query("ImagineWork");return n=await i.get(t),n}const Parse$s=defaultExport.with("nova");class ImagineService{constructor(e,t,n,o){this.http=e,this.ncloud=t,this.uploadServ=n,this.toastCtrl=o,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$s.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$s.User.current();if(!e?.id)return;let t=this.getWorkQuery();return t.include("model","module","user"),t.equalTo("user",e.toPointer()),t}getWorkQuery(){new Date((new Date).getTime()-6e4);let e=Parse$s.Query.fromJSON("ImagineWork",{where:{}});return e.include("model","module","user"),e.notEqualTo("isDeleted",!0),e.notEqualTo("isFailed",!0),e.doesNotExist("respData.error"),e.doesNotExist("respData.data.taskLimitCount"),e.addDescending("createdAt"),e}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)}))}async getJimengImg(e){let t=new Parse$s.Object("ImagineWork");t.set("__pending",!0),t.set("__id",Symbol()),t.set("images",[""]),this.newWorkList.unshift(t);try{let n=await getJimengImg(e),o=this.newWorkList?.findIndex((e=>e?.get("__id")===t?.get("__id")));if(-1==o)return;if(!n?.id)return void this.newWorkList.splice(o,1);this.newWorkList.splice(o,1,n)}catch(e){let n=this.newWorkList?.findIndex((e=>e?.get("__id")===t?.get("__id")));if(-1==n)return;this.newWorkList.splice(n,1)}}async getJimengVideo(e,t){let n=new Parse$s.Object("ImagineWork");n.set("__pending",!0),n.set("__id",Symbol()),n.set("provider","volcengine"),n.set("taskId","1"),this.newWorkList.unshift(n);try{let o;o="i_v"==t?await getJimengI_v(e):await getJimengT_v(e);let i=this.newWorkList?.findIndex((e=>e?.get("__id")===n?.get("__id")));if(-1==i)return;if(!o?.id)return this.newWorkList.splice(i,1),void this.setToast("创建有误,请稍后再试");this.newWorkList.splice(i,1,o)}catch(e){let t=this.newWorkList?.findIndex((e=>e?.get("__id")===n?.get("__id")));if(-1==t)return;this.newWorkList.splice(t,1)}}async getJimengVideoData(e,t){try{let n=await getJimengV_data({video_by:e,workId:t});if(console.log("请求结果",n),n?.error)return void this.setToast(n?.error?.message||n?.error?.msg||n?.err?.message||n?.err?.msg||"请求错误");if(1!==n?.get("progress")||n?.get("videos")?.length<=0)return;let o=this.newWorkList?.findIndex((e=>e?.id===t));if(-1==o)return;return n?.id?(this.newWorkList.splice(o,1,n),n):void this.newWorkList.splice(o,1)}catch(e){let n=this.newWorkList?.findIndex((e=>e?.id===t));if(-1==n)return;this.newWorkList.splice(n,1)}}async setToast(e){(await this.toastCtrl.create({duration:1e3,message:e||"请求错误",color:"primary",icon:"information-circle",position:"top"})).present()}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},{token:i3.ToastController}],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},{type:i3.ToastController}]});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}]});const Parse$r=defaultExport.with("nova");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$r.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$r.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(){}highlightMarkdown(e){try{const t=/```(\w+)?\n([\s\S]*?)```/g,n=[];let o,i=0;for(;null!==(o=t.exec(e));)o.index>i&&n.push({type:"markdown",content:e.substring(i,o.index)}),n.push({type:"code",content:o[2],language:o[1]}),i=o.index+o[0].length;return i<e.length&&n.push({type:"markdown",content:e.substring(i)}),0===n.length?hljs.highlight(e,{language:"markdown"}).value:n.map((e=>"code"===e.type?this.highlightCodeBlock(e.content,e.language):e.content.trim()?hljs.highlight(e.content,{language:"markdown"}).value:e.content)).join("")}catch(t){return console.error("Markdown highlighting error:",t),e}}highlightCodeBlock(e,t){try{let n,o;if(t&&hljs.getLanguage(t))n=hljs.highlight(e,{language:t}).value,o=t;else{const t=hljs.highlightAuto(e);n=t.value,o=t.language||"plaintext"}return`<pre><code class="hljs language-${o}">${n}</code></pre>`}catch(t){return console.error("Code block highlighting error:",t),`<pre><code class="hljs">${this.escapeHtml(e)}</code></pre>`}}escapeHtml(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}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"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ClipboardService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i3.ToastController}]});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 h=0,u=0;u<a;h++,u+=i)0==u?o.moveTo(u,p[h]):o.lineTo(u,p[h]);h--;for(u=a-1;u>=0;h--,u-=i)o.lineTo(u,m[h]);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}();const Parse$q=defaultExport.with("nova");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()}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年"}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}]}});const Parse$p=defaultExport.with("nova");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$p.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}]}});const Parse$o=defaultExport.with("nova");class CompAvatarRoleVideoComponent{constructor(e){this.navCtrl=e,this.animClass="waiting",this.onClose=new EventEmitter,this.goBack=()=>{this.navCtrl.back()},this.videoMap={}}close(){this.onClose.emit(!0),this.fmodeChat.isAvatarShow=!1}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",goBack:"goBack"},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}],goBack:[{type:Input}]}});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$4.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:i1$4.MatDialogClose,selector:"[mat-dialog-close], [matDialogClose]",inputs:["aria-label","type","mat-dialog-close","matDialogClose"],exportAs:["matDialogClose"]},{kind:"directive",type:i1$4.MatDialogTitle,selector:"[mat-dialog-title], [matDialogTitle]",inputs:["id"],exportAs:["matDialogTitle"]},{kind:"directive",type:i1$4.MatDialogActions,selector:"[mat-dialog-actions], mat-dialog-actions, [matDialogActions]",inputs:["align"]},{kind:"directive",type:i1$4.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$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:i1$4.MatDialogRef},{type:void 0,decorators:[{type:Inject,args:[MAT_DIALOG_DATA]}]}],propDecorators:{stepper:[{type:ViewChild,args:[MatStepper]}]}}),addIcons({chevronBackOutline:chevronBackOutline,ellipsisHorizontalOutline:ellipsisHorizontalOutline,resizeOutline:resizeOutline});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 [goBack]="goBack" *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","goBack"],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 [goBack]="goBack" *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}]}});const Parse$n=defaultExport.with("nova");class WechatJssdkService{get initUrl(){return sessionStorage.getItem("initialUrl")}set initUrl(e){sessionStorage.getItem("initialUrl")||sessionStorage.setItem("initialUrl",window.location.href)}constructor(e){this.http=e,this.isInit=!1,this.isWechat=!1,this.company=localStorage.getItem("company"),this.wechatAccountId=localStorage.getItem("WECHAT_APP_ID"),this.isWechatConfigInit=!1,this.initUrl=window.location.href;let t=-1!==navigator.userAgent.toLowerCase().indexOf("micromessenger");this.isWechat=t,this.init()}async initWechatConfig(e,t){if(this.company=e||localStorage.getItem("company"),this.wechatAccountId=t||localStorage.getItem("WECHAT_APP_ID"),this.isWechatConfigInit)return;const n=await this.getWXSignPackageInWechat();wx.config({debug:!1,appId:n.appid,timestamp:n.timestamp,nonceStr:n.nonceStr,signature:n.signature,jsApiList:["chooseWXPay","onMenuShareTimeline","onMenuShareAppMessage","onMenuShareQQ","onMenuShareQZone","updateAppMessageShareData","updateTimelineShareData"]}),this.isWechatConfigInit=!0}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("取消分享")}}){await this.initWechatConfig(),"link"==e?.type&&(e.link=this.getInviteUrl(e.link)),this.replaceSameUrl(e.link),wx.ready((()=>{wx.updateAppMessageShareData(e),wx.updateTimelineShareData(e)})),wx.error((e=>{}))}replaceSameUrl(e){try{const t=new URL(e,window.location.href),{pathname:n,search:o,origin:i}=t;if(i!==window.location.origin)throw new Error(`目标URL与当前页面不同源(当前: ${window.location.origin}, 目标: ${i})`);const a=`${i}${n}${o}`;history.replaceState(null,"",a)}catch(e){throw new Error(`修改URL失败: ${e.message}`)}}getInviteUrl(e){let t=new URL(e),n=Parse$n.User?.current()?.id;return n&&t.searchParams.set("invite",n),t.href}getWXSignPackageInWechat(){let e={company:this.company,href:encodeURIComponent(this.initUrl)};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(){if(!this.wechatAccountId)return console.error("appId不存在,请先配置");let e=this.getQueryStringByName("code"),t=localStorage.getItem("openid");if(!t){if(!Parse$n.User.current())return;if(t=Parse$n?.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=window.location.pathname){if(!localStorage.getItem("openid")){let t=window.location.origin+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$n.User.current().set("wechat",o),await Parse$n.User.current().save(),n(!0)}}),(async e=>{console.log("Error updating items",e),this.authWechat(t),o(!1)}))}))}init(){return new Promise((e=>{if(this.isWechat||e(!1),!this.isInit||"undefined"==typeof wx)return"undefined"!=typeof wx?(this.isInit=!0,this.wx=wx,void e(!0)):void this.loadScript("https://res.wx.qq.com/open/js/jweixin-1.6.0.js",(()=>{this.isInit=!0,this.wx=wx,e(!0)}),(()=>{e(!1)}));e(!0)}))}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}],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}]});const Parse$m=defaultExport.with("nova");class AuthService{isGuardLock(e){let t=!0,n=Parse$m.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,i){this.router=e,this.wxjssdk=t,this.toastCtrl=n,this.novaCloud=o,this.http=i,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.appId=e.appId,this.wxjssdk.initWechatConfig(this.company,this.appId),this.saveParamsInvite()}checkLoginLock(){let e=Parse$m.User.current();return!!e?.id||(this.isModalShow=!0,this.isLoggedIn=!1,!1)}async checkLogin(e,t){await this.checkAndLoginWithToken(),await this.authWechat(),e&&(this.guardMap[e]=!0);let n=Parse$m.User.current();return console.log("currentUser",n),n&&n.id?(this.setAccount(n),this.isLoggedIn=!0,t?.onLogin?.(),!0):this.guardType&&"page"!=this.guardType?"modal"==this.guardType?(this.isModalShow=!0,this.isLoggedIn=!1,!0):void 0:(e&&(this.redirectUrl=e,this.router.navigate([this.LoginPage])),!1)}async authWechat(){return!(!this.wxjssdk.isWechat||!this.appId||Parse$m.User.current()?.id)&&new Promise((e=>{let t=this.getCompanyId(),n=this.wxjssdk.getQueryStringByName("code"),o=window.location.pathname;n?Parse$m.Cloud.run("auth_wechat",{code:n,c:t}).then((t=>{localStorage.removeItem("code");let n=t.token;console.log(n),t.openid&&localStorage.setItem("openid",t.openid),Parse$m.User.current()?.id&&e(!0),Parse$m.User.become(n).then((t=>{console.log(t),t.set("company",{__type:"Pointer",className:"Company",objectId:localStorage.getItem("company")}),t.save(),e(!0)})).catch((t=>{console.warn("become登录失败:"+t),e(!1)}))})).catch((t=>{console.warn("Wechat登录失败:"+t),e(!1)})):this.wxjssdk.authWechat(o)}))}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$m.User.current();if(!o?.id)try{o=await Parse$m.User.become(t)}catch(e){}}}async setAccount(e){if(this.account?.id)return;let t=e?.get("company")||{__type:"Pointer",className:"Company",objectId:this.getCompanyId()}||null,n=new Parse$m.Query("Account");n.equalTo("user",e.toPointer());let o=await n.first();return o?.id||(o=new Parse$m.Object("Account"),o.set({user:e.toPointer(),company:t}),o=await o.save()),this.account=o,o}login(e,t){return new Promise(((n,o)=>{Parse$m.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$m.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$m.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$m.User.logOut().then((e=>{})),this.router.navigate([t||"/pcuser/login"],{queryParams:{t:(new Date).getTime()},queryParamsHandling:"merge"})}async loginMobilePassword(e,t,n,o){let i=await this.getMobileUser(e);if(i)return new Promise(((e,o)=>{this.login(i,t).then((async t=>{this.isModalShow=!1,this.updateLoginState(),e(t)})).catch((e=>{console.log(e),n.create("error","错误的用户名或密码"),o(e)}))}));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$m.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)}))}))}updateLoginState(){new URLSearchParams(location.search).set("t",String((new Date).getTime()));let e="/"+(location.origin+location.pathname).replaceAll(document.baseURI,"");console.log(e),this.router.navigate([e],{queryParams:{t:(new Date).getTime()},queryParamsHandling:"merge"})}async getMobileCodeToken(e,t){return new Promise(((n,o)=>{let i=Parse$m.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$m.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 o?.(),this.updateLoginState(),!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,null,o)}}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$m.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:WechatJssdkService},{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:WechatJssdkService},{type:i1$3.ToastController},{type:NovaCloudService},{type:i1.HttpClient}]});const Parse$l=defaultExport.with("nova");class AccountService{constructor(e,t,n){this.ncloud=e,this.authServ=t,this.http=n,this.company="",this.billing={credit:{usedDetail:{}}},this.billingCache=null,this.billingCachePromise=null,this.billingCacheTime=0,this.CACHE_EXPIRY_TIME=12e4,this.wxAppId="",this.wxpayEnabled=!1,this.appid=localStorage.getItem("WECHAT_APP_ID")||"",this.company=this.authServ.company||localStorage.getItem("company"),this.getBilling(),this.getProfile(),this.getUserOpenid()}async getProfile(){let e=Parse$l.User.current()?.id;if(!e)return;let t=new Parse$l.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(){const e=Date.now();return this.billingCache?(e-this.billingCacheTime>=this.CACHE_EXPIRY_TIME&&(this.billingCachePromise||(this.billingCachePromise=this.fetchBillingData())),this.billingCache):(this.billingCachePromise||(this.billingCachePromise=this.fetchBillingData()),this.billing={credit:{balance:4,usedDetail:{}}},this.billing)}async fetchBillingData(){let e;if(!Parse$l.User.current()?.getSessionToken())return this.billingCachePromise=null,this.billing;try{e=await this.ncloud.apig("aigc/account",null,"get"),e?.credit&&(this.billing=e,this.billingCache=e,this.billingCacheTime=Date.now())}catch(e){console.warn("Failed to fetch billing data:",e)}return this.billingCachePromise=null,this.billingCache||this.billing}async getUserOpenid(){if(!this.appid)return;let e=-1!=navigator.userAgent.toLowerCase().indexOf("micromessenger"),t=this.getQueryStringByName("code"),n=localStorage.getItem("openid");if(!n){if(!Parse$l.User.current())return;let o=Parse$l.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$l.User.current().set("wechat",o),await Parse$l.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$l.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://server.fmode.cn/api/apig/saveAccountLog",{company:n,uid:Parse$l.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}]});const Parse$k=defaultExport.with("nova");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}]}]});const Parse$j=defaultExport.with("nova");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$j.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$j.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}]}});const Parse$i=defaultExport.with("nova");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$i.Query("ChatPrompt");e.notEqualTo("isDeleted",!0),console.log("getChatPrompt",this.role),e.equalTo("role",this.role),e.include("role");let t=await e.find();t?.length&&(console.log("this.chat.promptList?.length",this.chat.promptList),this.chat.promptList?.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;display:flex;justify-content:center;flex-direction:column;align-items:center}.prompt .prompt_cate .cate_info div img{border-radius:15px;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;display:flex;justify-content:center;flex-direction:column;align-items:center}.prompt .prompt_cate .cate_info div img{border-radius:15px;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}]}});const Parse$h=defaultExport.with("nova");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$h.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$h.User.current()?.id&&this.chatVoice.set("user",Parse$h.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"});this.uploadServ.maxSize=1073741824;let 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}]}});const Parse$g=defaultExport.with("nova");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$g.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>=3&&(this.chat.isDirect=!0),!this.chat?.currentModel?.get?.("payLimit"))return!0;if(e?.credit?.balance<3){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$g.User.current();let e=new Parse$g.Query("ChatShare");e.equalTo("user",Parse$g.User.current().id),e.equalTo("session",this.chat?.sessionId);await e.first()}async toggleChatShare(){let e=new Parse$g.Query("ChatShare");e.equalTo("user",Parse$g.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$g.Object.extend("ChatShare")),t.set("user",{__type:"Pointer",className:"_User",objectId:Parse$g.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&&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: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&&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:"fm-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,htmlAttributes:t.htmlAttributes});return t?.fullscreen&&addModalChatPanelStyle(),await n.present(),n}function addModalChatPanelStyle(){const e="custom-modal-chat-panel-style";if(document.getElementById(e))return;const t=document.createElement("style");t.id=e,t.textContent="\n .modal-chat-panel {\n --width: 100%!important;\n --height: 100%!important;\n --max-width: 100%;\n --max-height: 100%;\n --border-radius: 0;\n }\n ",document.head.appendChild(t)}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ChatPanelComponent,decorators:[{type:Component,args:[{selector:"fm-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"]}]})}}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 Parse$f=defaultExport.with("nova");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$f.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:()=>[]});const Parse$e=defaultExport.with("nova");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$e.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$e.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$e.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: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]}]}]});const Parse$d=defaultExport.with("nova");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$d.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$d.GeoPoint({latitude:28.682634,longitude:115.86273})}):this.placeList.push({name:"八一广场",address:"南昌市八一广场",location:new Parse$d.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:()=>[]});const Parse$c=defaultExport.with("nova");class PageLocaScatterComponent{constructor(){this.amap={securityJsCode:"32aa3f4ab0fa0061de03edd4eafdd50a",key:"473b52010df7d3a32db0a2f5db245c8e"},this.initaMapConfig()}async initaMapConfig(){let e=localStorage.getItem("company");if(e){let t=new Parse$c.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]}]}]});const Parse$b=defaultExport.with("nova");class HwobsService{constructor(){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$b.Query("Attachment");o.equalTo("hash",n),o.equalTo("size",e.size);let i=await o.first();return i?.id||(i=new Parse$b.Object("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]}]}]});const WxworkAuthGuard=async(e,t)=>checkWeworkLogin(e);function wxdebug(...e){console.log(e)}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;}"]})}}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: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}]}});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"})}}function normalizeLineEndings(e){return e?e.replace(/\r\n|\r/g,"\n"):e}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:FiletypePipe,decorators:[{type:Pipe,args:[{name:"filetype",standalone:!0}]}]});class CodemirrorComponent{set extensions(e){this._extensions=e||[],!this._differ&&e&&(this._differ=this._differs.find(e).create()),this.reconfigureEditor()}set options(e){this._options=e,this._extensions=this.convertOptionsToExtensions(e),!this._differ&&e&&(this._differ=this._differs.find(e).create()),this.reconfigureEditor()}constructor(e,t){this._differs=e,this._ngZone=t,this.className="",this.name="codemirror",this.autoFocus=!1,this.preserveScrollPosition=!1,this.cursorActivity=new EventEmitter,this.focusChange=new EventEmitter,this.scroll=new EventEmitter,this.drop=new EventEmitter,this.codeMirrorLoaded=new EventEmitter,this.value="",this.disabled=!1,this.isFocused=!1,this._options={},this._extensions=[],this.extensionsCompartment=new Compartment,this.readOnlyCompartment=new Compartment,this.onChange=e=>{},this.onTouched=()=>{}}ngAfterViewInit(){this._ngZone.runOutsideAngular((()=>{this.initializeEditor()}))}async initializeEditor(){const{EditorView:e}=await import("codemirror"),{EditorState:t}=await import("@codemirror/state"),n=[basicSetup,this.extensionsCompartment.of(this._extensions),this.readOnlyCompartment.of(this.disabled?t.readOnly.of(!0):[]),this.createUpdateListener(),this.createFocusExtension(),this.createScrollExtension(),this.createDropExtension()],o=t.create({doc:this.value,extensions:n});this.editorView=new e({state:o,parent:this.ref.nativeElement}),this.autoFocus&&this.editorView.focus(),this._ngZone.run((()=>{this.codeMirrorLoaded.emit(this)}))}createUpdateListener(){return EditorView.updateListener.of((e=>{e.docChanged&&this._ngZone.run((()=>{this.codemirrorValueChanged(e.view)})),e.selectionSet&&this._ngZone.run((()=>{this.cursorActive(e.view)}))}))}createFocusExtension(){return EditorView.domEventHandlers({focus:()=>(this._ngZone.run((()=>this.focusChanged(!0))),!1),blur:()=>(this._ngZone.run((()=>this.focusChanged(!1))),!1)})}createScrollExtension(){return EditorView.domEventHandlers({scroll:(e,t)=>(this._ngZone.run((()=>this.scrollChanged(t))),!1)})}createDropExtension(){return EditorView.domEventHandlers({drop:(e,t)=>(this._ngZone.run((()=>this.dropFiles(t,e))),!1)})}convertOptionsToExtensions(e){const t=[];return e?(e.mode,e.theme,e.lineNumbers,t):t}ngDoCheck(){if(!this._differ)return;this._differ.diff(this._options)&&this.reconfigureEditor()}async reconfigureEditor(){if(!this.editorView)return;const e=[this.extensionsCompartment.reconfigure(this._extensions)];this.editorView.dispatch({effects:e})}ngOnDestroy(){this.editorView&&this.editorView.destroy()}codemirrorValueChanged(e){const t=e.state.doc.toString();this.value!==t&&(this.value=t,this.onChange(this.value))}focusChanged(e){this.onTouched(),this.isFocused=e,this.focusChange.emit(e)}scrollChanged(e){const t=e.scrollDOM,n={left:t.scrollLeft,top:t.scrollTop,width:t.scrollWidth,height:t.scrollHeight,clientWidth:t.clientWidth,clientHeight:t.clientHeight};this.scroll.emit(n)}cursorActive(e){this.cursorActivity.emit(e)}dropFiles(e,t){this.drop.emit([e,t])}writeValue(e){if(null==e)return;if(!this.editorView)return void(this.value=e);const t=this.editorView.state.doc.toString();if(e!==t&&normalizeLineEndings(t)!==normalizeLineEndings(e))if(this.value=e,this.preserveScrollPosition){const t={left:this.editorView.scrollDOM.scrollLeft,top:this.editorView.scrollDOM.scrollTop};this.editorView.dispatch({changes:{from:0,to:this.editorView.state.doc.length,insert:e}}),this.editorView.scrollDOM.scrollTo(t.left,t.top)}else this.editorView.dispatch({changes:{from:0,to:this.editorView.state.doc.length,insert:e}})}registerOnChange(e){this.onChange=e}registerOnTouched(e){this.onTouched=e}async setDisabledState(e){if(this.disabled=e,this.editorView){const{EditorState:t}=await import("@codemirror/state");this.editorView.dispatch({effects:[this.readOnlyCompartment.reconfigure(e?t.readOnly.of(!0):[])]})}}focus(){this.editorView?.focus()}getEditorView(){return this.editorView}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CodemirrorComponent,deps:[{token:i0.KeyValueDiffers},{token:i0.NgZone}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:CodemirrorComponent,isStandalone:!0,selector:"ngx-codemirror",inputs:{className:"className",name:"name",autoFocus:"autoFocus",extensions:"extensions",options:"options",preserveScrollPosition:"preserveScrollPosition"},outputs:{cursorActivity:"cursorActivity",focusChange:"focusChange",scroll:"scroll",drop:"drop",codeMirrorLoaded:"codeMirrorLoaded"},providers:[{provide:NG_VALUE_ACCESSOR,useExisting:forwardRef((()=>CodemirrorComponent)),multi:!0}],viewQueries:[{propertyName:"ref",first:!0,predicate:["ref"],descendants:!0}],ngImport:i0,template:'\n <div\n [class]="\'ngx-codemirror \' + className"\n [class.ngx-codemirror--focused]="isFocused"\n #ref\n ></div>\n ',isInline:!0,changeDetection:i0.ChangeDetectionStrategy.OnPush})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CodemirrorComponent,decorators:[{type:Component,args:[{selector:"ngx-codemirror",standalone:!0,template:'\n <div\n [class]="\'ngx-codemirror \' + className"\n [class.ngx-codemirror--focused]="isFocused"\n #ref\n ></div>\n ',providers:[{provide:NG_VALUE_ACCESSOR,useExisting:forwardRef((()=>CodemirrorComponent)),multi:!0}],preserveWhitespaces:!1,changeDetection:ChangeDetectionStrategy.OnPush}]}],ctorParameters:()=>[{type:i0.KeyValueDiffers},{type:i0.NgZone}],propDecorators:{className:[{type:Input}],name:[{type:Input}],autoFocus:[{type:Input}],extensions:[{type:Input}],options:[{type:Input}],preserveScrollPosition:[{type:Input}],cursorActivity:[{type:Output}],focusChange:[{type:Output}],scroll:[{type:Output}],drop:[{type:Output}],codeMirrorLoaded:[{type:Output}],ref:[{type:ViewChild,args:["ref"]}]}});const Parse$a=defaultExport.with("nova");class PaymentService{constructor(e,t){this.toast=e,this.http=t,this.company=""}setTradeNo(){let e=new Date;return"C"+String(e.getFullYear())+(e.getMonth()+1)+e.getDate()+e.getHours()+e.getMinutes()+e.getSeconds()+e.getMilliseconds()+Math.floor(1e4*Math.random())}async createdAccountLog(e){let t=new Parse$a.Query("Account");t.equalTo("user",Parse$a.User.current().id),t.equalTo("company",e.company);let n=await t.first(),o=new Parse$a.Object("AccountLog");if(e.orderId){let t=new Parse$a.Query("AccountLog");t.equalTo("orderId",e.orderId),t.equalTo("user",Parse$a.User.current()?.id);let n=await t.first();n?.id&&(o=n)}o.set("assetType","wxPay"),o.set("payType",e.payType),o.set("assetCount",e.price),o.set("desc",`${e.payType}支付(fm-sdk生成)`),o.set("orderType",e.orderType),o.set("orderNumber",e.tradeNo),e.orderId&&o.set("orderId",e.orderId),o.set("isVerified",!1),o.set("targetName","system"),n&&o.set("fromAccount",n.toPointer()),Parse$a.User.current()?.id&&(o.set("user",Parse$a.User.current().toPointer()),o.set("fromName",Parse$a.User.current().get("nickname"))),o.set("company",{__type:"Pointer",className:"Company",objectId:e.company}),await o.save()}async setOrder(e){return new Promise(((t,n)=>{this.http.post("https://server.gdchat.cn/api/apig/created-order",{fcompany:this.company,uid:Parse$a.User.current()?.id,type:e.type,gid:e.gid,invite:Parse$a.User.current()?.get("invite")?.id,params:e}).subscribe((e=>{t(e.data)}),(e=>{n(e)}))}))}async creatdRechargeLog(e){const t=Parse$a.User.current();let n=new Parse$a.Query("Account");n.equalTo("company",this.company),n.equalTo("user",t?.id),n.select("objectId");let o=await n.first();o?.id||(o=await this.createdAccount(t.id));let i=new Parse$a.Query("AccountLog");i.equalTo("orderNumber",e.tradeNo),i.equalTo("targetAccount",o?.id),i.notEqualTo("isVerified",!0),i.notEqualTo("isDeleted",!0);let a=await i.first();if(a?.id)return a;let r=new Parse$a.Object("AccountLog");return r.set("isVerified",!1),r.set("user",{__type:"Pointer",className:"_User",objectId:t.id}),r.set("company",{__type:"Pointer",className:"Company",objectId:this.company}),r.set("targetAccount",{__type:"Pointer",className:"Account",objectId:o?.id}),r.set("fromName","system"),r.set("fromAccountName","system"),r.set("orderNumber",e.tradeNo),r.set("desc",`${e.payType}充值${e.price}`),r.set("assetType","balance"),r.set("orderType",`${e.payType}-recharge`),r.set("payType",e.payType),r.set("assetCount",e.credit),r.set("serviceFee",e.price),await r.save()}async createdAccount(e){let t=new Parse$a.Query("Account");t.equalTo("company",this.company),t.equalTo("user",e);let n=await t.first();return n?.id||(n=new Parse$a.Object("Account"),n?.set("user",{__type:"Pointer",className:"_User",objectId:e}),n?.set("company",{__type:"Pointer",className:"Company",objectId:this.company}),n?.set("balance",0),n=await(n?.save())),n}async updateAccountLog(e,t){return new Promise(((n,o)=>{this.http.post("https://server.gdchat.cn/api/apig/saveAccountLog",{company:this.company,uid:Parse$a.User.current()?.id,orderid:t,info:e}).subscribe((e=>{console.log(e),n(!0)}),(async e=>{console.warn(e);(await this.toast.create({message:"支付成功,订单记录异常",color:"warning",duration:1500})).present(),o()}))}))}async updateRecharge(e){return e?.set("isVerified",!0),await(e?.save()),e}async getOrder(e){let t=new Parse$a.Query("Order");t.notEqualTo("isDeleted",!0),t.equalTo("status","100"),t.equalTo("orderNum",e),t.select("objectId");let n=await t.first();return n?.id}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PaymentService,deps:[{token:i3.ToastController},{token:i1.HttpClient}],target:i0.ɵɵFactoryTarget.Injectable})}static{this.ɵprov=i0.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PaymentService,providedIn:"root"})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PaymentService,decorators:[{type:Injectable,args:[{providedIn:"root"}]}],ctorParameters:()=>[{type:i3.ToastController},{type:i1.HttpClient}]});const Parse$9=defaultExport.with("nova");class PaymentComponent{constructor(e,t,n,o,i){this.wxjssdk=e,this.http=t,this.activRoute=n,this.payServer=o,this.alertCtrl=i,this.price=0,this.title="支付订单",this.showTypes=["wxpay","alipay"],this.orderType="goods",this.isRechargeRule=!1,this.credit=0,this.payResult=new EventEmitter,this.isOpen=!0,this.checkpay=this.showTypes[0]||"",this.user=Parse$9.User.current(),this.isLoading=!1,this.isDisabled=!1}ngOnInit(){this.activRoute.paramMap.subscribe((async e=>{let t=navigator.userAgent.toLowerCase();console.log(t),-1!=t.indexOf("micromessenger")?(this.userAgent="weixin",await this.wxjssdk.initUserOpenid(),this.wxjssdk.setCurrentPageShareInfo()):-1==t.indexOf("windows")&&-1==t.indexOf("Macintosh")||(this.userAgent="pc")}))}onchangPay(e){this.checkpay=e,console.log(e)}async userPayment(){if(!this.isLoading&&this.checkpay){if(this.tradeNo||(this.tradeNo=this.payServer.setTradeNo()),this.isRechargeRule&&this.tradeNo&&(this.orderId=await this.payServer.getOrder(this.tradeNo),("vip"==this.orderType&&!this.orderId||"recharge"==this.orderType&&(!this.accountLog?.id||this.accountLog?.get("isVerified")))&&(this.tradeNo=this.payServer.setTradeNo())),console.log(this.tradeNo),0==this.price)return this.toast("支付成功","success"),this.isOpen=!1,this.payResult.emit({code:200,tradeNo:this.tradeNo,type:this.checkpay}),void(this.tradeNo=null);switch(this.checkpay){case"wxpay":this.openWxPay();break;case"alipay":this.openAlipay()}}}async openWxPay(){-1!=navigator.userAgent.toLowerCase().indexOf("micromessenger")?this.wxPayH5():this.wxPay()}async wxPayH5(){if(!this.isDisabled)try{this.isDisabled=!0;let e=Parse$9.User.current()?.get("wechat"),t=localStorage.getItem("openid")||e[this.wxjssdk.wechatAccountId]?.openid;if(t){let e={company:this.wxjssdk.company,body:this.title,out_trade_no:this.tradeNo,total_fee:+this.price,openid:t,appid:this.wxjssdk.wechatAccountId},n=this;this.http.post("https://server.fmode.cn/api/wxpay/neworder",e).pipe(catchError((async e=>{console.error(e),this.isDisabled=!1,this.isLoading=!1,this.toast("支付失败:"+e?.error?.mess,"fail")}))).subscribe((async e=>{await this.certificatePay();let t=e;wx.chooseWXPay({timestamp:t.timeStamp,nonceStr:t.nonceStr,package:t.package,signType:"MD5",paySign:t.paySign,success:async e=>{if(e){if(this.isRechargeRule){let e={out_trade_no:n.tradeNo,nonce_str:t.nonceStr,company:this.wxjssdk.company};this.orderId?this.payServer.updateAccountLog(e,this.orderId):"recharge"==this.orderType&&(this.accountLog=await this.payServer.updateRecharge(this.accountLog))}n.isOpen=!1,n.toast("支付成功","success"),n.payResult.emit({code:200,tradeNo:this.tradeNo,type:this.checkpay})}}}),this.isDisabled=!1}))}else{this.isDisabled=!1,(await this.alertCtrl.create({header:"提示",subHeader:"",message:"缺少openid,请刷新页面或重新登录",buttons:[{role:"ok",text:"确认",handler:()=>{location.reload()}}]})).present()}}catch(e){this.isDisabled=!1,(await this.alertCtrl.create({header:"异常错误",subHeader:"",message:e.message,buttons:[{role:"ok",text:"确认",handler:()=>{}}]})).present()}}async wxPay(){let e={company:this.wxjssdk.company,out_trade_no:this.tradeNo,total_fee:this.price,body:this.title};Parse$9.Cloud.run("pay_code2",e).then((async e=>{let t=e.nonce_str;this.codeLink=e.code_url[0],console.log(this.codeLink),await this.certificatePay(),this.updateOrder(t)})).catch((e=>{this.isDisabled=!1,this.toast(e.message,"danger")}))}async openAlipay(){if(!this.isDisabled){this.isLoading=!0;try{this.isDisabled=!0;let e=await this.getAliPayUrl();console.log(e),await this.certificatePay();const t=document.createElement("div");t.innerHTML=e;const n=t.querySelector("form");if(n){n.addEventListener("submit",(e=>{e.preventDefault()}));const e=document.createElement("iframe");e.style.display="none",document.body.appendChild(e),n.target=e.name,console.log(n),document.body.appendChild(n),n.submit(),document.body.removeChild(n)}else console.error("未找到表单元素"),this.isLoading=!1;this.timer=setInterval((async()=>{console.log("支付结果轮询");let e=new Parse$9.Query("AccountLog");e.equalTo("company",this.wxjssdk.company),e.equalTo("orderNumber",this.tradeNo),e.equalTo("payType","alipay"),e.equalTo("isVerified",!0);let t=await e.first();this.isLoading=!1,t&&t.id&&(clearInterval(this.timer),this.timer=null),this.timer||(this.toast("支付成功","success"),this.isOpen=!1,this.payResult.emit({code:200,tradeNo:this.tradeNo,type:this.checkpay}))}),1e3)}catch(e){this.isLoading=!1,this.isDisabled=!1,(await this.alertCtrl.create({header:"异常错误",subHeader:"",message:e.message,buttons:[{role:"ok",text:"确认",handler:()=>{}}]})).present()}}}async getAliPayUrl(){return new Promise(((e,t)=>{let n=window.location.href,o={company:this.wxjssdk.company,tradeNo:this.tradeNo,price:this.price,tradetype:"wap",orderTitle:this.title,returnUrl:n,returnType:"get",rechargeRule:this.isRechargeRule};try{this.http.post("https://server.fmode.cn/api/alipay/neworder",o).pipe(catchError((async e=>{console.error(e),this.isDisabled=!1,this.isLoading=!1,this.toast("支付失败:"+e?.error?.mess,"fail")}))).subscribe((t=>{200===t.code?t.data&&t.data.pay_url&&e(t.data.pay_url):this.toast("网络错误,请稍后重试","warning")}))}catch(e){e&&(this.toast("网络错误,请稍后重试","warning"),t(e))}}))}updateOrder(e){let t=this;t.timer=setInterval((()=>{let n={out_trade_no:t.tradeNo,nonce_str:e,company:this.wxjssdk.company};Parse$9.Cloud.run("order_status2",n).then((async e=>{e.status&&"SUCCESS"==e.status[0]&&(clearInterval(t.timer),this.isRechargeRule&&(this.orderId?this.payServer.updateAccountLog(n,this.orderId):"recharge"==this.orderType&&(this.accountLog=await this.payServer.updateRecharge(this.accountLog))),t.toast("支付成功","success"),t.isOpen=!1,t.payResult.emit({code:200,tradeNo:this.tradeNo,type:this.checkpay}))})).catch((e=>{}))}),3e3)}async certificatePay(){if(await this.payServer.createdAccountLog({company:this.wxjssdk.company,orderId:this.orderId,tradeNo:this.tradeNo,price:this.price,payType:this.checkpay,orderType:this.orderType}),this.isRechargeRule)if("vip"==this.orderType&&!this.orderId&&this.gid){let e=await this.payServer.setOrder({type:"service",gid:this.gid,price:this.price,total_fee:this.price,tradeNo:this.tradeNo,out_trade_no:this.tradeNo,payType:this.checkpay,code:this.codeLink});console.log(e),e?.objectId&&(this.orderId=e.objectId)}else"recharge"==this.orderType&&(this.accountLog=await this.payServer.creatdRechargeLog({tradeNo:this.tradeNo,payType:this.checkpay,price:this.price,credit:this.credit}))}onClose(){this.isOpen=!1;const e={code:0,tradeNo:this.tradeNo,type:this.checkpay};this.payResult.emit(e)}toast(e,t){const n=document.createElement("div"),o=t??"warning",i={success:{bg:"#10dc60",text:"#fff"},danger:{bg:"#f04141",text:"#fff"},fail:{bg:"#f04141",text:"#fff"},warning:{bg:"#ffce00",text:"#000"}};Object.assign(n.style,{position:"fixed",bottom:"20px",left:"50%",transform:"translateX(-50%)",padding:"12px 20px",borderRadius:"4px",zIndex:"9999",fontSize:"14px",textAlign:"center",minWidth:"200px",boxShadow:"0 3px 5px rgba(0,0,0,0.2)",opacity:"0",transition:"opacity 0.3s ease-in-out",backgroundColor:i[o]?.bg||i.warning.bg,color:i[o]?.text||i.warning.text}),n.textContent=e,document.body.appendChild(n),requestAnimationFrame((()=>{n.style.opacity="1",setTimeout((()=>{n.style.opacity="0",setTimeout((()=>document.body.removeChild(n)),300)}),1500)}))}ngOnDestroy(){this.timer&&clearInterval(this.timer)}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PaymentComponent,deps:[{token:WechatJssdkService},{token:i1.HttpClient},{token:i1$1.ActivatedRoute},{token:PaymentService},{token:i1$3.AlertController}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:PaymentComponent,isStandalone:!0,selector:"fm-payment",inputs:{price:"price",tradeNo:"tradeNo",title:"title",showTypes:"showTypes",orderType:"orderType",isRechargeRule:"isRechargeRule",credit:"credit",gid:"gid",orderId:"orderId",isOpen:"isOpen"},outputs:{payResult:"payResult"},ngImport:i0,template:'@if (isOpen) {\n <div class="payment-overlay">\n \x3c!-- 全局 Loading --\x3e\n @if (isLoading) {\n <div class="global-loading">\n <div class="loading-spinner"></div>\n <div class="loading-text">处理中...</div>\n </div>\n }\n\n <div class="payment-box" [class.blur-effect]="isLoading">\n <div class="pay-box">\n <div class="close-btn" (click)="!isLoading && onClose()">\n <span class="close-icon"></span>\n </div>\n @if (!codeLink) {\n <div class="pay-title">支付订单</div>\n <div class="pay-num">¥{{ price || 0 }}</div>\n <div class="options">\n @if (showTypes.includes("wxpay")) {\n <div class="row" (click)="onchangPay(\'wxpay\')">\n <div class="label">\n <img\n src="https://file-cloud.fmode.cn/E4KpGvTEto/20231123/s1sun8061000007.png"\n alt="微信支付"\n class="icon"\n />\n <div class="text">微信支付</div>\n </div>\n <div class="check" [class.check-active]="checkpay === \'wxpay\'">\n <div class="checkbox"></div>\n </div>\n </div>\n }\n @if (showTypes.length > 1) {\n <div class="divider"></div>\n }\n @if (showTypes.includes("alipay")) {\n <div class="row" (click)="onchangPay(\'alipay\')">\n <div class="label">\n <img\n src="https://file-cloud.fmode.cn/storage/company/E4KpGvTEto/20250815/110934166.png"\n alt="支付宝"\n class="icon"\n />\n <div class="text">支付宝</div>\n </div>\n <div class="check" [class.check-active]="checkpay === \'alipay\'">\n <div class="checkbox"></div>\n </div>\n </div>\n }\n </div>\n <div class="pay-footer">\n <div class="order-num">订单编号:{{ tradeNo ? tradeNo : "-" }}</div>\n <div\n class="pay-btn"\n (click)="!isLoading && userPayment()"\n [class.disabled]="isLoading || !checkpay"\n >\n 去付款\n @if (isLoading) {\n <span class="btn-loading"></span>\n }\n </div>\n </div>\n } @else {\n <div class="qrcode-section">\n <qr-code [value]="codeLink" value="请使用手机扫描二维码完成支付" [size]="180"></qr-code>\n <p class="qrcode-tip">请使用手机扫描二维码完成支付</p>\n </div>\n }\n </div>\n </div>\n </div>\n}\n',styles:['@charset "UTF-8";.global-loading{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1001;background:#ffffffe6;padding:20px 30px;border-radius:8px;box-shadow:0 2px 10px #0000001a;display:flex;flex-direction:column;align-items:center}.global-loading .loading-spinner{width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #1890ff;border-radius:50%;animation:spin 1s linear infinite;margin-bottom:10px}.global-loading .loading-text{color:#333;font-size:14px}.blur-effect{filter:blur(2px);pointer-events:none}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.payment-overlay{position:fixed;inset:0;background-color:#00000080;display:flex;justify-content:center;align-items:center;z-index:1000;animation:fadeIn .3s ease}.payment-box{width:90%;max-width:400px;background:#fff;border-radius:12px;box-shadow:0 4px 20px #00000026;animation:slideUp .3s ease;overflow:hidden}.pay-box{padding:20px;position:relative}.pay-box .close{position:absolute;right:16px;top:16px;font-size:24px;color:#999;cursor:pointer;transition:color .2s;padding:8px}.pay-box .close:hover{color:#666}.pay-box .pay-title{text-align:center;font-size:18px;font-weight:600;color:#333;margin-bottom:8px}.pay-box .pay-num{text-align:center;font-size:28px;color:#1890ff;margin:12px auto;font-weight:700}.pay-box .options{margin:20px 0}.pay-box .options .row{display:flex;align-items:center;justify-content:space-between;cursor:pointer;transition:background-color .2s;border-radius:8px;padding:12px}.pay-box .options .row:hover{background-color:#f9f9f9}.pay-box .options .row .label{display:flex;align-items:center}.pay-box .options .row .label img{width:32px;height:32px;object-fit:contain}.pay-box .options .row .label .text{font-size:16px;margin-left:12px;color:#333}.pay-box .options .row .check{border:2px solid #ddd;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;transition:all .2s}.pay-box .options .row .check .checkbox{width:12px;height:12px;border-radius:50%;background:transparent;transition:background .2s}.pay-box .options .row .check-active{border-color:#1890ff}.pay-box .options .row .check-active .checkbox{background:#1890ff}.pay-box .options .divider{margin:8px 0;height:1px;background:#eee}.pay-box .pay-footer{display:flex;flex-direction:column;align-items:center;margin-top:20px}.pay-box .pay-footer .order-num{color:#999;font-size:14px;margin-bottom:16px}.pay-box .pay-footer .pay-btn{padding:12px 0;width:100%;color:#fff;text-align:center;background:#1890ff;border-radius:8px;font-size:16px;font-weight:500;cursor:pointer;transition:background .2s;border:none;position:relative}.pay-box .pay-footer .pay-btn:hover,.pay-box .pay-footer .pay-btn:active{background:#1166b5}.pay-box .pay-footer .pay-btn.disabled{background:#ccc!important;cursor:not-allowed}.pay-box .pay-footer .pay-btn .btn-loading{display:inline-block;width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top:2px solid white;border-radius:50%;animation:spin .8s linear infinite;margin-left:8px;vertical-align:middle}.pay-box .qrcode{display:flex;justify-content:center;align-items:center;padding:20px}.pay-box .qrcode img{max-width:100%;height:auto;border:1px solid #eee;border-radius:8px}.pay-box .qrcode-section{text-align:center;margin:20px 0;padding:15px}.pay-box .qrcode-section .qrcode-image{max-width:200px;height:auto;border:1px solid #ddd;padding:10px;background:#fff}.pay-box .qrcode-section .qrcode-tip{margin-top:10px;font-size:14px;color:#666}.close-btn{position:absolute;right:16px;top:16px;width:40px;height:40px;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:50%;transition:background-color .2s ease;z-index:1}.close-btn:hover{background-color:#0000000d}.close-btn:active{background-color:#0000001a}.close-icon{position:relative;width:20px;height:20px}.close-icon:before,.close-icon:after{content:"";position:absolute;top:50%;left:50%;width:100%;height:2px;background-color:#666;border-radius:1px}.close-icon:before{transform:translate(-50%,-50%) rotate(45deg)}.close-icon:after{transform:translate(-50%,-50%) rotate(-45deg)}.close-btn.disabled{pointer-events:none;opacity:.5}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}\n'],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"ngmodule",type:QrCodeModule},{kind:"component",type:i6$1.QrCodeComponent,selector:"qr-code",inputs:["value","size","darkColor","lightColor","errorCorrectionLevel","centerImageSrc","centerImageSize","margin"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:PaymentComponent,decorators:[{type:Component,args:[{selector:"fm-payment",standalone:!0,imports:[CommonModule,QrCodeModule],template:'@if (isOpen) {\n <div class="payment-overlay">\n \x3c!-- 全局 Loading --\x3e\n @if (isLoading) {\n <div class="global-loading">\n <div class="loading-spinner"></div>\n <div class="loading-text">处理中...</div>\n </div>\n }\n\n <div class="payment-box" [class.blur-effect]="isLoading">\n <div class="pay-box">\n <div class="close-btn" (click)="!isLoading && onClose()">\n <span class="close-icon"></span>\n </div>\n @if (!codeLink) {\n <div class="pay-title">支付订单</div>\n <div class="pay-num">¥{{ price || 0 }}</div>\n <div class="options">\n @if (showTypes.includes("wxpay")) {\n <div class="row" (click)="onchangPay(\'wxpay\')">\n <div class="label">\n <img\n src="https://file-cloud.fmode.cn/E4KpGvTEto/20231123/s1sun8061000007.png"\n alt="微信支付"\n class="icon"\n />\n <div class="text">微信支付</div>\n </div>\n <div class="check" [class.check-active]="checkpay === \'wxpay\'">\n <div class="checkbox"></div>\n </div>\n </div>\n }\n @if (showTypes.length > 1) {\n <div class="divider"></div>\n }\n @if (showTypes.includes("alipay")) {\n <div class="row" (click)="onchangPay(\'alipay\')">\n <div class="label">\n <img\n src="https://file-cloud.fmode.cn/storage/company/E4KpGvTEto/20250815/110934166.png"\n alt="支付宝"\n class="icon"\n />\n <div class="text">支付宝</div>\n </div>\n <div class="check" [class.check-active]="checkpay === \'alipay\'">\n <div class="checkbox"></div>\n </div>\n </div>\n }\n </div>\n <div class="pay-footer">\n <div class="order-num">订单编号:{{ tradeNo ? tradeNo : "-" }}</div>\n <div\n class="pay-btn"\n (click)="!isLoading && userPayment()"\n [class.disabled]="isLoading || !checkpay"\n >\n 去付款\n @if (isLoading) {\n <span class="btn-loading"></span>\n }\n </div>\n </div>\n } @else {\n <div class="qrcode-section">\n <qr-code [value]="codeLink" value="请使用手机扫描二维码完成支付" [size]="180"></qr-code>\n <p class="qrcode-tip">请使用手机扫描二维码完成支付</p>\n </div>\n }\n </div>\n </div>\n </div>\n}\n',styles:['@charset "UTF-8";.global-loading{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1001;background:#ffffffe6;padding:20px 30px;border-radius:8px;box-shadow:0 2px 10px #0000001a;display:flex;flex-direction:column;align-items:center}.global-loading .loading-spinner{width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #1890ff;border-radius:50%;animation:spin 1s linear infinite;margin-bottom:10px}.global-loading .loading-text{color:#333;font-size:14px}.blur-effect{filter:blur(2px);pointer-events:none}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.payment-overlay{position:fixed;inset:0;background-color:#00000080;display:flex;justify-content:center;align-items:center;z-index:1000;animation:fadeIn .3s ease}.payment-box{width:90%;max-width:400px;background:#fff;border-radius:12px;box-shadow:0 4px 20px #00000026;animation:slideUp .3s ease;overflow:hidden}.pay-box{padding:20px;position:relative}.pay-box .close{position:absolute;right:16px;top:16px;font-size:24px;color:#999;cursor:pointer;transition:color .2s;padding:8px}.pay-box .close:hover{color:#666}.pay-box .pay-title{text-align:center;font-size:18px;font-weight:600;color:#333;margin-bottom:8px}.pay-box .pay-num{text-align:center;font-size:28px;color:#1890ff;margin:12px auto;font-weight:700}.pay-box .options{margin:20px 0}.pay-box .options .row{display:flex;align-items:center;justify-content:space-between;cursor:pointer;transition:background-color .2s;border-radius:8px;padding:12px}.pay-box .options .row:hover{background-color:#f9f9f9}.pay-box .options .row .label{display:flex;align-items:center}.pay-box .options .row .label img{width:32px;height:32px;object-fit:contain}.pay-box .options .row .label .text{font-size:16px;margin-left:12px;color:#333}.pay-box .options .row .check{border:2px solid #ddd;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;transition:all .2s}.pay-box .options .row .check .checkbox{width:12px;height:12px;border-radius:50%;background:transparent;transition:background .2s}.pay-box .options .row .check-active{border-color:#1890ff}.pay-box .options .row .check-active .checkbox{background:#1890ff}.pay-box .options .divider{margin:8px 0;height:1px;background:#eee}.pay-box .pay-footer{display:flex;flex-direction:column;align-items:center;margin-top:20px}.pay-box .pay-footer .order-num{color:#999;font-size:14px;margin-bottom:16px}.pay-box .pay-footer .pay-btn{padding:12px 0;width:100%;color:#fff;text-align:center;background:#1890ff;border-radius:8px;font-size:16px;font-weight:500;cursor:pointer;transition:background .2s;border:none;position:relative}.pay-box .pay-footer .pay-btn:hover,.pay-box .pay-footer .pay-btn:active{background:#1166b5}.pay-box .pay-footer .pay-btn.disabled{background:#ccc!important;cursor:not-allowed}.pay-box .pay-footer .pay-btn .btn-loading{display:inline-block;width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top:2px solid white;border-radius:50%;animation:spin .8s linear infinite;margin-left:8px;vertical-align:middle}.pay-box .qrcode{display:flex;justify-content:center;align-items:center;padding:20px}.pay-box .qrcode img{max-width:100%;height:auto;border:1px solid #eee;border-radius:8px}.pay-box .qrcode-section{text-align:center;margin:20px 0;padding:15px}.pay-box .qrcode-section .qrcode-image{max-width:200px;height:auto;border:1px solid #ddd;padding:10px;background:#fff}.pay-box .qrcode-section .qrcode-tip{margin-top:10px;font-size:14px;color:#666}.close-btn{position:absolute;right:16px;top:16px;width:40px;height:40px;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:50%;transition:background-color .2s ease;z-index:1}.close-btn:hover{background-color:#0000000d}.close-btn:active{background-color:#0000001a}.close-icon{position:relative;width:20px;height:20px}.close-icon:before,.close-icon:after{content:"";position:absolute;top:50%;left:50%;width:100%;height:2px;background-color:#666;border-radius:1px}.close-icon:before{transform:translate(-50%,-50%) rotate(45deg)}.close-icon:after{transform:translate(-50%,-50%) rotate(-45deg)}.close-btn.disabled{pointer-events:none;opacity:.5}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}\n']}]}],ctorParameters:()=>[{type:WechatJssdkService},{type:i1.HttpClient},{type:i1$1.ActivatedRoute},{type:PaymentService},{type:i1$3.AlertController}],propDecorators:{price:[{type:Input,args:["price"]}],tradeNo:[{type:Input,args:["tradeNo"]}],title:[{type:Input,args:["title"]}],showTypes:[{type:Input,args:["showTypes"]}],orderType:[{type:Input,args:["orderType"]}],isRechargeRule:[{type:Input,args:["isRechargeRule"]}],credit:[{type:Input,args:["credit"]}],gid:[{type:Input,args:["gid"]}],orderId:[{type:Input,args:["orderId"]}],payResult:[{type:Output}],isOpen:[{type:Input,args:["isOpen"]}]}});const Parse$8=defaultExport.with("nova");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$8.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$8.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$8.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$8.Query("_User");e.contains("username",this.registPhone),e.equalTo("company",this.companyId);let t=await e.first();t?.id?this.message.info("该账户已激活,使用手机号密码直接登录"):Parse$8.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$8.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$8.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$8.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$8.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$8.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: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: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:i1$3.ToastController},{type:i1$1.Router},{type:i1$1.ActivatedRoute},{type:i1$1.ActivatedRoute},{type:i1.HttpClient}]});const Parse$7=defaultExport.with("nova");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.loginSuccess=new EventEmitter,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.authServ.loginMobilePassword(this.mobile,this.password,this.msg).then((e=>{this.loginSuccess.emit({user:Parse$7.User.current(),data:e}),this.setActiveButton("账号密码")}))})).catch((e=>{this.msg.error("注册失败,请更换手机号注册")})):this.msg.error("两次输入密码不同,请检查"):this.msg.error("请输入完整手机号和密码")}async loginMobilePassword(){if(!this.mobile||!this.password)return void this.msg.error("请输入完整手机号和密码");let e=await this.authServ.loginMobilePassword(this.mobile,this.password,this.msg,(()=>{console.log("登录成功",e),this.loginSuccess.emit({user:Parse$7.User.current(),data:e})}))}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$7.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}$/))if(this.loginInfo.code){this.loginInfo.code=this.loginInfo.code?.slice(0,6);try{e=await this.authServ.loginCode(this.loginInfo.mobile,this.loginInfo.code,this.msg,(()=>{let t=Parse$7.User.current();(e||t?.id)&&(this.loginSuccess.emit({user:t,res:e}),console.log(e,t?.id,"close"),this.close(),this.loginInfo={mobile:"",code:""},this.localCodeNum="",this.toast({color:"success",message:"登录成功"}),this.authServ.guardType)}))}catch(e){}}else this.msg.error("请输入短信验证码");else this.msg.error("请填写正确手机号")}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",outputs:{loginSuccess:"loginSuccess"},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 - 480px);height:530px;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{max-height:60px;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;margin:auto;padding:10px 10%;border-radius:10px}.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;padding:16px 0}.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:42px;padding:6px;border-radius:10px;line-height:40px;font-size:16px;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: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 - 480px);height:530px;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{max-height:60px;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;margin:auto;padding:10px 10%;border-radius:10px}.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;padding:16px 0}.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:42px;padding:6px;border-radius:10px;line-height:40px;font-size:16px;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"]}],loginSuccess:[{type:Output}],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: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}]}});const Parse$6=defaultExport.with("nova");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,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,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,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]}]}]});const Parse$5=defaultExport.with("nova");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$5.User.current();if(!t?.id)return;let n=localStorage.getItem("staffid");e&&(n=null);let o,i=new Parse$5.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}]});const Parse$4=defaultExport.with("nova");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$4.User.current()}set user(e){this._user=e}constructor(e){this.router=e,this.user=Parse$4.User.current()}async getProfile(){if(this.profile?.id)return this.profile;if(this.profileId){let e=new Parse$4.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$4.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$4.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}]});const Parse$3=defaultExport.with("nova");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}]});const Parse$2=defaultExport.with("nova");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}]}});const Parse$1=defaultExport.with("nova");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$1.User.current(),this.loadProfiles()}async loadProfiles(){this.isLoading=!0;try{let e=new Parse$1.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$1.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: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.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]}]}]});const Parse=defaultExport.with("nova");class CompMobileBindComponent{mobileChange(e){console.log(e),this.mobile=e?.detail?.value}codeChange(e){this.code=e?.detail?.value}async sendSmsCode(){this.startCountdown();/^1[3-9]\d{9}$/.test(this.mobile)?(await this.ncloud.apig("message",{company:this.cid,mobile:this.mobile},"POST"),this.isSended=!0,setTimeout((()=>{this.codeInput?.setFocus()}),500)):this.presentAlert("请检查手机号")}startCountdown(){this.countdown=60,this.countInt=setInterval((()=>{this.countdown--,0==this.countdown&&this.countInt&&clearInterval(this.countInt)}),1e3)}async presentAlert(e){const t=await this.alertCtrl.create({header:"提示",subHeader:e,buttons:["确定"]});await t.present()}constructor(e,t,n){this.modalCtrl=e,this.alertCtrl=t,this.ncloud=n,this.mobile="",this.code="",this.isSended=!1,this.countdown=0,this.isVerifying=!1}ngAfterViewInit(){setTimeout((()=>{this.mobileInput.setFocus()}),500)}async verifyMobile(){if(this.isVerifying)return;this.isVerifying=!0;let e=await this.ncloud.api(`/auth/mobile?company=${this.cid}&mobile=${this.mobile}&code=${this.code}`,null,"GET");if(e?.token){console.log(200,e);let t=await Parse.User.become(e.token);t?.id&&(this.modalCtrl.dismiss({mobile:this.mobile,user:t},"confirm"),this.countInt&&clearInterval(this.countInt))}this.isVerifying=!1}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompMobileBindComponent,deps:[{token:i1$3.ModalController},{token:i1$3.AlertController},{token:NovaCloudService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"17.0.0",version:"17.3.12",type:CompMobileBindComponent,isStandalone:!0,selector:"app-comp-mobile-bind",inputs:{cid:"cid"},viewQueries:[{propertyName:"mobileInput",first:!0,predicate:["mobileInput"],descendants:!0,read:IonInput},{propertyName:"codeInput",first:!0,predicate:["codeInput"],descendants:!0,read:IonInput}],ngImport:i0,template:'\x3c!-- 用户登录状态 --\x3e\n<ion-card>\n <ion-card-header>\n <ion-card-title>\n 验证手机\n \x3c!-- <ion-segment [value]="type" (ionChange)="typeChange($event)">\n <ion-segment-button value="login">\n <ion-label>登录</ion-label>\n </ion-segment-button>\n <ion-segment-button value="signup">\n <ion-label>注册</ion-label>\n </ion-segment-button>\n </ion-segment> --\x3e\n </ion-card-title>\n \x3c!-- <ion-card-subtitle>请输入账号密码</ion-card-subtitle> --\x3e\n </ion-card-header>\n <ion-card-content>\n <ion-item>\n <ion-input #mobileInput [value]="mobile" (ionChange)="mobileChange($event)" label="手机号" placeholder="请您输入手机号"></ion-input>\n </ion-item>\n @if(isSended){\n <ion-item>\n <ion-input #codeInput [value]="code" (ionChange)="codeChange($event)" label="验证码" placeholder="请您输入6位数字"></ion-input>\n @if(countdown){\n <ion-button color="light">{{countdown}}</ion-button>\n }\n </ion-item>\n }\n @if(!countdown){\n <ion-button expand="block" (click)="sendSmsCode()">获取验证码</ion-button>\n }\n @if(isSended && countdown){\n <ion-button expand="block" (click)="verifyMobile()" [disabled]="isVerifying">确认</ion-button>\n }\n </ion-card-content>\n </ion-card>',styles:[""],dependencies:[{kind:"component",type:IonCard,selector:"ion-card",inputs:["button","color","disabled","download","href","mode","rel","routerAnimation","routerDirection","target","type"]},{kind:"component",type:IonCardContent,selector:"ion-card-content",inputs:["mode"]},{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:IonCardHeader,selector:"ion-card-header",inputs:["color","mode","translucent"]},{kind:"component",type:IonCardTitle,selector:"ion-card-title",inputs:["color","mode"]},{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:IonItem,selector:"ion-item",inputs:["button","color","detail","detailIcon","disabled","download","href","lines","mode","rel","routerAnimation","routerDirection","target","type"]}]})}}async function openMobileBindModal(e,t){console.log("openMobileBindModal");let n=Parse.User.current();if(n?.get("mobile"))return n?.get("mobile");let o=await e.create({component:CompMobileBindComponent,componentProps:{cid:t?.cid},cssClass:"modal-mobile-bind",backdropDismiss:!1,keyboardClose:!1,breakpoints:[.3,.5],initialBreakpoint:.3});await o.present();const{data:i,role:a}=await o.onWillDismiss();return"confirm"===a&&i?.mobile?i.mobile:null}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:CompMobileBindComponent,decorators:[{type:Component,args:[{selector:"app-comp-mobile-bind",standalone:!0,imports:[IonHeader,IonToolbar,IonTitle,IonContent,IonCard,IonCardContent,IonButton,IonCardHeader,IonCardTitle,IonCardSubtitle,IonInput,IonItem,IonSegment,IonSegmentButton,IonLabel],template:'\x3c!-- 用户登录状态 --\x3e\n<ion-card>\n <ion-card-header>\n <ion-card-title>\n 验证手机\n \x3c!-- <ion-segment [value]="type" (ionChange)="typeChange($event)">\n <ion-segment-button value="login">\n <ion-label>登录</ion-label>\n </ion-segment-button>\n <ion-segment-button value="signup">\n <ion-label>注册</ion-label>\n </ion-segment-button>\n </ion-segment> --\x3e\n </ion-card-title>\n \x3c!-- <ion-card-subtitle>请输入账号密码</ion-card-subtitle> --\x3e\n </ion-card-header>\n <ion-card-content>\n <ion-item>\n <ion-input #mobileInput [value]="mobile" (ionChange)="mobileChange($event)" label="手机号" placeholder="请您输入手机号"></ion-input>\n </ion-item>\n @if(isSended){\n <ion-item>\n <ion-input #codeInput [value]="code" (ionChange)="codeChange($event)" label="验证码" placeholder="请您输入6位数字"></ion-input>\n @if(countdown){\n <ion-button color="light">{{countdown}}</ion-button>\n }\n </ion-item>\n }\n @if(!countdown){\n <ion-button expand="block" (click)="sendSmsCode()">获取验证码</ion-button>\n }\n @if(isSended && countdown){\n <ion-button expand="block" (click)="verifyMobile()" [disabled]="isVerifying">确认</ion-button>\n }\n </ion-card-content>\n </ion-card>'}]}],ctorParameters:()=>[{type:i1$3.ModalController},{type:i1$3.AlertController},{type:NovaCloudService}],propDecorators:{mobileInput:[{type:ViewChild,args:["mobileInput",{read:IonInput}]}],codeInput:[{type:ViewChild,args:["codeInput",{read:IonInput}]}],cid:[{type:Input}]}});export{AccountService,AgentPrompt,AgentStory,AgentTaskStep,AudioPlayer,AuthPcuserGuard,AuthProfileGuard,AuthProfileService,AuthService,AuthStaffGuard,AvatarModule,AvatarRoutes,CaptchaComponent,ChatContentPipe,ChatListComponent,ChatPanelComponent,ChatService,ClipboardService,CodemirrorComponent,CompAvatarParticleComponent,CompAvatarRoleImageComponent,CompAvatarRoleVideoComponent,CompAvatarTalkComponent,CompMobileBindComponent,CompPoiPickerComponent,CompPoiPickerModule,CompRolePromptComponent,CompUserAvatarComponent,CrossService,DingTalkAuth,DurationStrPipe,FiletypePipe,FmAgentTaskComponent,FmChatHeaderArea,FmChatMessageCard,FmChatMesssageArea,FmChatModalInput,FmPushAudioOutputStreamCallback,FmTextQuillComponent,FmVideoComponent,FmaiService,FmodeChat,FmodeChatCompletion,FmodeGeoPoint,FmodeLoadingController,FmodeLoadingInstance,FmodeMapModule,FmodeObject,defaultExport as FmodeParse,FmodeQuery,FmodeStorgeModule,FmodeTTS,FmodeTTSProviderDoubao,FmodeUser,FmodeVoiceService,HidexmlPipe,HwobsManagerComponent,HwobsProvider,HwobsService,ImagineService,ImagineWork,LoginComponent,MASK_LIST,MarkdownMathJax,MarkdownParse,MarkdownPreviewComponent,MarkdownPreviewModule,ModalAudioMessageComponent,ModalChatVoiceInputComponent,ModalUserLoginComponent,NovaCloudService,NovaStorage,NovaUploadService,PCMStreamer,PaymentComponent,ProfileBindComponent,ProfileModule,ProfileRoutes,QiniuProvider,ShopeeClient,ShopeeMerchant,ShopeePublic,ShopeeSDK,ShopeeShop,StaffModule,StaffService,TipsController,UserModule,UserNamePipe,UserRoutes,UtilnowPipe,WechatJssdkService,WwRequest,WxworkAuth,WxworkAuthGuard,WxworkCorp,WxworkSDK,apig,buildFullUrl,calcFileMd5,checkWeworkLogin,completionJSON,drawDalle,extractJSON,getFileMetadata,getJimengI_v,getJimengImg,getJimengT_v,getJimengV_data,getMessageContentText,getMessageImageUrl,jsApiList,ncloudApi,novaql,openChatPanelModal,openMobileBindModal,wxdebug};
9
9
  var MODULE_PATH_NEED = `6K+l5paH5Lu25piv5pys6aG555uu55qE5LiA6YOo5YiGIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIHRoZSBDb21wb25lbnRzIGluIEZtb2RlIEluYy4KICAgIOeJiOadg+aJgOaciSDCqSDmnKrmnaXpo57pqawgwqkg5rGf6KW/6ISR5o6n56eR5oqA5pyJ6ZmQ5YWs5Y+4IENvcHlyaWdodCDCqSBGbW9kZSBUZWNobm9sb2d5IENvLiwgTHRkLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCiAgICDkuKXnpoHlnKjmnKrnu4/mjojmnYPnmoTmg4XlhrXkuIvvvIzpgJrov4fku7vkvZXlqpLku4vlpI3liLbmraTmlofku7YgVW5hdXRob3JpemVkIGNvcHlpbmcgb2YgdGhpcyBmaWxlLCB2aWEgYW55IG1lZGl1bSBpcyBzdHJpY3RseSBwcm9oaWJpdGVkCiAgICDor6Xmlofku7bmmK/kuJPmnInnmoTmnLrlr4bmlofku7YgUHJvcHJpZXRhcnkgYW5kIGNvbmZpZGVudGlhbAogICAKICAgIENvcHlyaWdodCAyMDIxLW5vdyBGbW9kZSBJbmMuIHN1cHBvcnRAZm1vZGUuY24uIDE4NjA3MDA3MDczLgogICAg5L+d55WZ5omA5pyJ5p2D5YipIEFsbCByaWdodHMgcmVzZXJ2ZWQuCgogICAgUEFUSDovaG9tZS9yeWFuL3dvcmtzcGFjZS9ub3ZhL25vdmEtYWRtaW4vZGlzdC9mbW9kZS1uZy9mZXNtMjAyMi9mbW9kZS1uZy5tanM=`
10
10