vue-chat-kit 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- (function(N,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue"),require("@element-plus/icons-vue"),require("dayjs"),require("element-plus")):typeof define=="function"&&define.amd?define(["exports","vue","@element-plus/icons-vue","dayjs","element-plus"],e):(N=typeof globalThis<"u"?globalThis:N||self,e(N.VueChatKit={},N.Vue,N.ElementPlusIconsVue,N.dayjs,N.ElementPlus))})(this,(function(N,e,_,de,I){"use strict";class _e{constructor(t,a={}){this.userId=t,this.wsUrl=a.wsUrl||"",this.socket=null,this.reconnectAttempts=0,this.maxReconnectAttempts=a.maxReconnectAttempts||5,this.reconnectDelay=a.reconnectDelay||3e3,this.handlers={message:[],open:[],close:[],error:[]},this.isConnecting=!1,this.manualClose=!1}connect(){if(!(this.isConnecting||this.isConnected())){this.isConnecting=!0,this.manualClose=!1;try{this.socket=new WebSocket(this.wsUrl),this.socket.onopen=()=>{console.log("[VueChatKit] WebSocket 连接成功"),this.isConnecting=!1,this.reconnectAttempts=0,this.emit("open")},this.socket.onmessage=t=>{try{const a=t.data;this.emit("message",a)}catch(a){console.error("[VueChatKit] WebSocket 消息解析失败",a)}},this.socket.onclose=t=>{console.log("[VueChatKit] WebSocket 连接关闭",t.code),this.isConnecting=!1,this.emit("close",t),!this.manualClose&&t.code!==1e3&&this.reconnect()},this.socket.onerror=t=>{console.error("[VueChatKit] WebSocket 连接错误",t),this.isConnecting=!1,this.emit("error",t)}}catch(t){console.error("[VueChatKit] WebSocket 创建连接失败",t),this.isConnecting=!1}}}send(t,a,l="text",V="",E="",B=0){if(this.isConnected()){const g=JSON.stringify({to:t,msg:a,type:l,fileUrl:V,fileName:E,fileSize:B});return this.socket.send(g),!0}return console.warn("[VueChatKit] WebSocket 连接未建立,无法发送消息"),!1}on(t,a){this.handlers[t]&&this.handlers[t].push(a)}off(t,a){if(this.handlers[t]){const l=this.handlers[t].indexOf(a);l>-1&&this.handlers[t].splice(l,1)}}emit(t,...a){this.handlers[t]&&this.handlers[t].forEach(l=>l(...a))}reconnect(){this.reconnectAttempts<this.maxReconnectAttempts?(this.reconnectAttempts++,console.log(`[VueChatKit] 尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`),setTimeout(()=>this.connect(),this.reconnectDelay)):console.error("[VueChatKit] 重连次数已达上限")}close(){this.manualClose=!0,this.socket&&(this.socket.close(),this.socket=null,this.handlers={message:[],open:[],close:[],error:[]})}isConnected(){return this.socket&&this.socket.readyState===WebSocket.OPEN}}class re extends Error{constructor(t,a,l,V){super(t),this.name="RequestError",this.status=a||0,this.code=l||0,this.data=V}}class Ne{constructor(t={}){this.baseUrl=t.baseUrl||"",this.timeout=t.timeout||1e4,this.headers=t.headers||{},this.requestInterceptors=[],this.responseInterceptors=[],this.addRequestInterceptor(a=>(a.body instanceof FormData||(a.headers={"Content-Type":"application/json",...a.headers}),a))}addRequestInterceptor(t){this.requestInterceptors.push(t)}addResponseInterceptor(t){this.responseInterceptors.push(t)}timeoutPromise(t){return new Promise((a,l)=>{setTimeout(()=>{l(new re("请求超时",408,408))},t)})}async request(t,a={}){const{method:l="GET",headers:V={},body:E,params:B}=a;let g=t.startsWith("http")?t:`${this.baseUrl}${t}`,y={method:l,headers:{...this.headers,...V},body:E,params:B};this.requestInterceptors.forEach(m=>{y=m(y)});const w={method:y.method,headers:y.headers,credentials:"include"};if(y.body&&l!=="GET"&&(y.body instanceof FormData?w.body=y.body:typeof y.body=="object"?w.body=JSON.stringify(y.body):w.body=y.body),y.params){const m=new URLSearchParams;for(const u in y.params)y.params[u]!==void 0&&y.params[u]!==null&&y.params[u]!==""&&m.append(u,y.params[u]);const h=m.toString();h&&(g+=(g.includes("?")?"&":"?")+h)}try{let h=await Promise.race([fetch(g,w),this.timeoutPromise(this.timeout)]);if(this.responseInterceptors.forEach(z=>{h=z(h)}),!h.ok)throw new re(`HTTP ${h.status}: ${h.statusText}`,h.status,h.status);const u=h.headers.get("content-type");let C;return u&&u.includes("application/json")?C=await h.json():C=await h.text(),C}catch(m){throw m instanceof re?m:new re(m instanceof Error?m.message:"网络错误",0,0)}}get(t,a,l){return this.request(t,{...l,method:"GET",params:a})}post(t,a,l){return this.request(t,{...l,method:"POST",body:a})}put(t,a,l){return this.request(t,{...l,method:"PUT",body:a})}delete(t,a){return this.request(t,{...a,method:"DELETE"})}}class Ee{constructor(t,a=null){this.config=t,this.endpoints=t.api.endpoints,this.customAdapter=t.api.adapter,a?this.http=a:this.http=new Ne({baseUrl:t.api.baseUrl,headers:t.headers})}async _call(t,...a){return this.customAdapter&&typeof this.customAdapter[t]=="function"?this.customAdapter[t](...a):this[`_${t}`](...a)}async getFriends(t){return this._call("getFriends",t)}async _getFriends(t){return this.http.get(this.endpoints.getFriends,{currentUser:t})}async getAvailableUsers(t){return this._call("getAvailableUsers",t)}async _getAvailableUsers(t){return this.http.get(this.endpoints.getAvailableUsers,{currentUser:t})}async addFriend(t,a){return this._call("addFriend",t,a)}async _addFriend(t,a){return this.http.post(this.endpoints.addFriend,{currentUser:t,friendUser:a})}async getApplyList(t){return this._call("getApplyList",t)}async _getApplyList(t){return this.http.get(this.endpoints.getApplyList,{currentUser:t})}async agreeFriend(t,a){return this._call("agreeFriend",t,a)}async _agreeFriend(t,a){return this.http.post(this.endpoints.agreeFriend,{applyUser:t,friendUser:a})}async setChatStatus(t,a,l=1){return this._call("setChatStatus",t,a,l)}async _setChatStatus(t,a,l){return this.http.post(this.endpoints.setChatStatus,null,{params:{currentUser:t,friendUser:a,status:l}})}async getHistory(t,a){return this._call("getHistory",t,a)}async _getHistory(t,a){return this.http.get(this.endpoints.getHistory,{fromUser:t,toUser:a})}async setRead(t,a){return this._call("setRead",t,a)}async _setRead(t,a){return this.http.post(this.endpoints.setRead,{currentUser:t,friendUser:a})}async uploadFile(t){return this._call("uploadFile",t)}async _uploadFile(t){const a=new FormData;return a.append("file",t),this.http.post(this.endpoints.uploadFile,a)}async getUserInfo(t){return this._call("getUserInfo",t)}async _getUserInfo(t){return this.http.get(this.endpoints.getUserInfo,{username:t})}async updateUserInfo(t,a){return this._call("updateUserInfo",t,a)}async _updateUserInfo(t,a){return this.http.put(this.endpoints.updateUserInfo,{username:t,...a})}async getUserAvatar(t){return this._call("getUserAvatar",t)}async _getUserAvatar(t){return this.http.get(this.endpoints.getUserAvatar,{username:t})}async uploadAvatar(t,a){return this._call("uploadAvatar",t,a)}async _uploadAvatar(t,a){const l=new FormData;return l.append("file",t),l.append("username",a),this.http.post(this.endpoints.uploadAvatar,l)}}function Ue(p){const t=new Ee(p);let a=null;const l=p.user.username,V=e.ref(p.user.avatar||`https://api.dicebear.com/7.x/avataaars/svg?seed=${l}`),E=e.ref({username:l,nickname:p.user.nickname||"",email:p.user.email||"",phone:p.user.phone||"",bio:p.user.bio||""}),B=e.ref(!1),g=e.ref([]),y=e.ref([]),w=e.ref([]),m=e.ref(""),h=e.ref(""),u=e.ref(""),C=e.ref(null),z=e.ref(!1),v=e.ref(""),K=e.ref([]),W=e.ref(!1),X=e.ref([]),O=e.ref(!1),f=e.computed(()=>{let o=y.value;if(h.value){const n=h.value.toLowerCase();o=o.filter(i=>i.username?.toLowerCase().includes(n))}return o.map(n=>({id:n.username,name:n.username,avatar:n.avatar||V.value,online:n.online,lastMsg:n.lastMsg||"暂无消息",lastTime:n.lastTime,unread:n.unReadNum||0}))}),x=e.computed(()=>{let o=g.value;if(h.value){const n=h.value.toLowerCase();o=o.filter(i=>i.username?.toLowerCase().includes(n))}return o.map(n=>({id:n.username,name:n.username,avatar:n.avatar||V.value,online:n.online,isChatting:n.isChatting}))}),b=e.computed(()=>v.value?K.value.filter(o=>o.username?.toLowerCase().includes(v.value.toLowerCase())):K.value),F=e.computed(()=>f.value.find(o=>o.id===m.value)||null),Y=e.computed(()=>w.value.map(o=>{const n=o.type==="file"||o.fileUrl||o.fileName,i=o.fileName||o.msgContent;return{text:o.msgContent,isSelf:o.sendUsername===l,time:o.createTime,sendUsername:o.sendUsername,type:n?"file":"text",fileType:ae(i)?"image":ne(i),fileUrl:o.fileUrl||"",fileName:i,fileSize:o.fileSize||0}})),M=o=>de(o).format("HH:mm"),se=o=>{if(!o)return"";const n=de(),i=de(o);return n.isSame(i,"day")?i.format("HH:mm"):n.diff(i,"day")===1?"昨天":n.diff(i,"day")<7?["周日","周一","周二","周三","周四","周五","周六"][i.day()]:i.format("MM/DD")},ae=o=>{if(!o)return!1;const n=["jpg","jpeg","png","gif","bmp","webp","svg"],i=o.split(".").pop().toLowerCase();return n.includes(i)},ne=o=>{if(!o)return"default";const n=o.split(".").pop().toLowerCase();return["xls","xlsx"].includes(n)?"excel":["pdf"].includes(n)?"pdf":["doc","docx"].includes(n)?"docx":"default"},j=()=>{e.nextTick(()=>{C.value&&(C.value.scrollTop=C.value.scrollHeight)})},D=async()=>{try{const n=(await t.getFriends(l)).data||[];g.value=n,y.value=n.filter(i=>i.isChatting===1);for(const i of y.value)try{const P=(await t.getHistory(l,i.username)).data||[];i.unReadNum=P.filter(q=>q.isRead===0&&q.sendUsername===i.username).length}catch{i.unReadNum=0}}catch(o){console.error("[VueChatKit] 获取好友列表失败",o)}},G=async o=>{try{const n=await t.getHistory(l,o);w.value=n.data||[],j()}catch(n){console.error("[VueChatKit] 获取聊天历史失败",n)}},De=async o=>{try{await t.setRead(l,o),D()}catch(n){console.error("[VueChatKit] 标记已读失败",n)}},me=async o=>{m.value=o.id,await G(o.id),await De(o.id),j()},fe=async(o,n=1)=>{try{return await t.setChatStatus(l,o,n),await D(),!0}catch(i){return console.error("[VueChatKit] 设置聊天状态失败",i),!1}},le=()=>{if(!u.value.trim()||!m.value||!a)return;if(a.send(m.value,u.value.trim(),"text")){const n={msgContent:u.value.trim(),sendUsername:l,receiveUsername:m.value,createTime:new Date,isRead:0,type:"text"};w.value.push(n),u.value="",j(),setTimeout(()=>{G(m.value),D()},300)}},ie=async o=>{if(!m.value||!a)return!1;try{const n=await t.uploadFile(o);if(n.code===200&&n.data){const{fileUrl:i,fileName:U}=n.data;if(a.send(m.value,U,"file",i,U,o.size)){const q={msgContent:U,sendUsername:l,receiveUsername:m.value,createTime:new Date,isRead:0,type:"file",fileUrl:i,fileName:U,fileSize:o.size};return w.value.push(q),j(),!0}}return!1}catch(n){return console.error("[VueChatKit] 发送文件失败",n),!1}},ce=async(o,n)=>{if(!(!m.value||!a)){if(n&&n.trim()&&a.send(m.value,n.trim(),"text")){const U={msgContent:n.trim(),sendUsername:l,receiveUsername:m.value,createTime:new Date,isRead:0,type:"text"};w.value.push(U)}for(const i of o){const U=i.file||i;await ie(U)}setTimeout(()=>{G(m.value),D()},300)}},pe=o=>{try{try{const i=JSON.parse(o);if(i.to||i.msg)return{to:i.to,content:i.msg,type:i.type||"text",fileUrl:i.fileUrl||"",fileName:i.fileName||"",fileSize:i.fileSize||0}}catch{}const n=o.match(/^\[(.+?)\]:(.+)$/);if(n)return{username:n[1],content:n[2],type:"text"}}catch(n){console.error("[VueChatKit] 解析消息失败",n)}return null},he=o=>{if(o.includes("【状态变更】")){const i=/【状态变更】(.+?) 已(上线|下线)/,U=o.match(i);if(U){const P=U[1],q=U[2]==="上线",ee=g.value.find(T=>T.username===P);ee&&(ee.online=q)}return}const n=pe(o);if(n){if(m.value){try{let i={msgContent:n.content,sendUsername:n.username||m.value,receiveUsername:l,createTime:new Date,isRead:0,type:n.type||"text",fileUrl:n.fileUrl||"",fileName:n.fileName||"",fileSize:n.fileSize||0};w.value.push(i),j()}catch(i){console.error("[VueChatKit] 添加临时消息失败",i)}G(m.value)}D()}},ue=()=>{const o=`${p.api.websocketUrl}?userId=${l}`;a=new _e(l,{wsUrl:o,maxReconnectAttempts:p.websocket.maxReconnectAttempts,reconnectDelay:p.websocket.reconnectDelay}),a.on("message",he),a.connect()},ge=()=>{a&&(a.close(),a=null)},ye=async()=>{z.value=!0,v.value="",await xe()},xe=async()=>{W.value=!0;try{const o=await t.getAvailableUsers(l);K.value=o?.data||[]}catch(o){console.error("[VueChatKit] 获取可用用户失败",o)}finally{W.value=!1}},be=async o=>{try{await t.addFriend(l,o.username),await D(),z.value=!1}catch(n){console.error("[VueChatKit] 添加好友失败",n)}},H=async()=>{O.value=!0;try{const o=await t.getApplyList(l);X.value=o.data||[]}catch(o){console.error("[VueChatKit] 获取好友申请列表失败",o)}finally{O.value=!1}},Q=async o=>{try{await t.agreeFriend(o,l),await H(),await D()}catch(n){console.error("[VueChatKit] 同意好友申请失败",n)}},S=async()=>{try{const o=await t.getUserAvatar(l);o.code===200&&o.data&&(V.value=o.data)}catch(o){console.warn("[VueChatKit] 加载头像失败",o)}},A=o=>{V.value=o},Z=async()=>{B.value=!0;try{const o=await t.getUserInfo(l);o.code===200&&o.data&&(E.value={...E.value,...o.data})}catch(o){console.error("[VueChatKit] 获取用户信息失败",o)}finally{B.value=!1}},L=async o=>{try{return(await t.updateUserInfo(l,o)).code===200?(E.value={...E.value,...o},!0):!1}catch(n){return console.error("[VueChatKit] 更新用户信息失败",n),!1}},R=()=>{m.value="",w.value=[],u.value="",h.value=""};return S(),{myUsername:l,myAvatar:V,userInfo:E,loadingUserInfo:B,friendList:g,chatList:y,filteredFriendList:x,chatMsgList:w,currentSelectName:m,searchText:h,inputText:u,messagesContainer:C,filteredUsers:f,filteredAvailableUsers:b,currentUser:F,currentMessages:Y,addFriendDialogVisible:z,addFriendSearchText:v,availableUsers:K,loadingAvailableUsers:W,friendApplyList:X,loadingFriendApply:O,formatTime:M,formatLastTime:se,scrollToBottom:j,getFriendList:D,getChatHistory:G,setFriendToChatStatus:fe,selectUser:me,sendMessage:le,sendFile:ie,sendFilesAndText:ce,initWebSocket:ue,closeWebSocket:ge,reset:R,openAddFriendDialog:ye,addFriend:be,loadFriendApplyList:H,agreeFriend:Q,updateMyAvatar:A,getUserInfo:Z,updateUserInfo:L}}const Be=(p,t)=>{const a=p.__vccOpts||p;for(const[l,V]of t)a[l]=V;return a},Me={class:"avatar-crop-container"},je=["src"],$e={class:"crop-overlay"},ve={class:"crop-box"},Ke={key:0,class:"crop-mask"},We={class:"zoom-controls"},Se=Be({__name:"AvatarCrop",props:{modelValue:{type:Boolean,default:!1},src:{type:String,default:""}},emits:["update:modelValue","confirm"],setup(p,{emit:t}){const a=p,l=t,V=e.computed({get:()=>a.modelValue,set:f=>l("update:modelValue",f)}),E=e.ref(""),B=e.ref(null),g=e.ref(null),y=e.ref(null),w=e.ref(1),m=e.ref({x:0,y:0}),h=e.ref(!1),u=e.ref({x:0,y:0}),C=e.ref({width:0,height:0});e.watch(()=>a.src,f=>{f&&(E.value=f,w.value=1,m.value={x:0,y:0})});const z=()=>{e.nextTick(()=>{if(B.value&&g.value){const f=B.value,x=g.value,b=Math.min(x.clientWidth,x.clientHeight);f.naturalWidth>f.naturalHeight?(C.value.height=b,C.value.width=f.naturalWidth/f.naturalHeight*b):(C.value.width=b,C.value.height=f.naturalHeight/f.naturalWidth*b),m.value={x:(b-C.value.width)/2,y:(b-C.value.height)/2}}})},v=f=>{h.value=!0;const x=f.touches?f.touches[0].clientX:f.clientX,b=f.touches?f.touches[0].clientY:f.clientY;u.value={x:x-m.value.x,y:b-m.value.y},document.addEventListener("mousemove",K),document.addEventListener("mouseup",W),document.addEventListener("touchmove",K),document.addEventListener("touchend",W)},K=f=>{if(!h.value)return;const x=f.touches?f.touches[0].clientX:f.clientX,b=f.touches?f.touches[0].clientY:f.clientY;m.value={x:x-u.value.x,y:b-u.value.y}},W=()=>{h.value=!1,document.removeEventListener("mousemove",K),document.removeEventListener("mouseup",W),document.removeEventListener("touchmove",K),document.removeEventListener("touchend",W)},X=()=>{const f=document.createElement("canvas"),x=f.getContext("2d"),b=200;f.width=b,f.height=b;const F=B.value,Y=y.value,M=g.value;if(F&&Y&&M){const se=Y.getBoundingClientRect(),ae=M.getBoundingClientRect(),ne=(se.left-ae.left-m.value.x)/w.value,j=(se.top-ae.top-m.value.y)/w.value,D=se.width/w.value;x.drawImage(F,ne*(F.naturalWidth/C.value.width),j*(F.naturalHeight/C.value.height),D*(F.naturalWidth/C.value.width),D*(F.naturalHeight/C.value.height),0,0,b,b),f.toBlob(G=>{l("confirm",{file:G,url:f.toDataURL("image/png")}),V.value=!1},"image/png")}},O=()=>{E.value="",w.value=1,m.value={x:0,y:0}};return(f,x)=>{const b=e.resolveComponent("el-slider"),F=e.resolveComponent("el-button"),Y=e.resolveComponent("el-dialog");return e.openBlock(),e.createBlock(Y,{modelValue:V.value,"onUpdate:modelValue":x[2]||(x[2]=M=>V.value=M),title:"裁剪头像",width:"500px","close-on-click-modal":!1,onClosed:O},{footer:e.withCtx(()=>[e.createVNode(F,{onClick:x[1]||(x[1]=M=>V.value=!1)},{default:e.withCtx(()=>[...x[3]||(x[3]=[e.createTextVNode("取消",-1)])]),_:1}),e.createVNode(F,{type:"primary",onClick:X},{default:e.withCtx(()=>[...x[4]||(x[4]=[e.createTextVNode("确定",-1)])]),_:1})]),default:e.withCtx(()=>[e.createElementVNode("div",Me,[e.createElementVNode("div",{class:"crop-area",ref_key:"cropAreaRef",ref:g},[e.createElementVNode("img",{src:E.value,ref_key:"imageRef",ref:B,class:"crop-image",onLoad:z,onMousedown:v,onTouchstart:v},null,40,je),e.createElementVNode("div",$e,[e.createElementVNode("div",ve,[e.createElementVNode("div",{class:"crop-border",ref_key:"cropBoxRef",ref:y},null,512)])]),h.value?(e.openBlock(),e.createElementBlock("div",Ke)):e.createCommentVNode("",!0)],512),e.createElementVNode("div",We,[e.createVNode(b,{modelValue:w.value,"onUpdate:modelValue":x[0]||(x[0]=M=>w.value=M),min:.5,max:3,step:.1,"show-tooltip":!1},null,8,["modelValue"])])])]),_:1},8,["modelValue"])}}},[["__scopeId","data-v-4e4a992b"]]),He={class:"chat-container flex h-[680px] bg-white overflow-hidden"},qe={class:"w-16 theme-white flex flex-col items-center gap-2 bg-gray-50 border-r"},Oe=["src"],Pe=["onClick"],Xe={key:0,class:"absolute -top-1 -right-1 w-4 h-4 bg-red-500 rounded-full text-xs text-white flex items-center justify-center"},Ye={class:"w-72 bg-[#f5f5f5] border-r border-gray-200 flex flex-col"},Ge={class:"p-3"},Je={class:"flex-1 overflow-y-auto min-h-0"},Qe={key:0},Ze=["onClick","onContextmenu"],et={class:"relative flex-shrink-0"},tt=["src","alt"],st={key:0,class:"absolute bottom-0 right-0 w-3 h-3 bg-green-500 rounded-full border-2 border-white"},at={class:"ml-3 flex-1 overflow-hidden"},ot={class:"flex justify-between items-center"},rt={class:"font-medium text-gray-800 text-sm"},nt={class:"text-xs text-gray-400"},lt={class:"flex justify-between items-center mt-1"},it={class:"text-xs text-gray-500 truncate pr-2"},ct={key:0,class:"bg-red-500 text-white text-xs rounded-full px-1.5 py-0.5 min-w-[18px] text-center"},dt={key:1},mt={class:"p-3"},ft={class:"w-11 h-11 bg-green-500 rounded-lg flex items-center justify-center"},pt=["onClick"],ht={class:"relative flex-shrink-0"},ut=["src","alt"],gt={class:"ml-3"},yt={class:"font-medium text-gray-800 text-sm"},xt={key:2},bt={class:"flex items-center"},kt=["src","alt"],wt={class:"ml-3"},Vt={class:"font-medium text-gray-800 text-sm"},Ct={class:"flex-1 flex flex-col min-w-0 bg-white"},_t={key:0,class:"flex-1 flex flex-col min-h-0"},Nt={class:"flex-1 flex flex-col items-center justify-center p-8 bg-[#f5f5f5]"},Et=["src","alt"],Ut={class:"text-xl font-medium text-gray-800 mb-2"},Bt={class:"flex items-center gap-2 mb-8"},St={class:"text-sm text-gray-500"},At={key:1,class:"flex-1 flex flex-col min-h-0"},Ft={class:"h-14 border-b border-gray-200 flex items-center justify-between px-4 bg-white"},Dt={class:"flex items-center gap-3"},Rt={class:"font-medium text-gray-800"},Tt={class:"flex items-center gap-3 text-gray-500"},zt={class:"flex-shrink-0"},Lt=["src"],It={key:0,class:"text-xs text-gray-500 mb-1 ml-1"},Mt={class:"relative group"},jt=["onClick"],$t=["src","alt"],vt={key:0,class:"absolute left-1 bottom-0 text-white"},Kt=["onClick"],Wt={class:"w-10 h-10 flex items-center justify-center rounded-lg flex-shrink-0"},Ht={class:"flex-1 min-w-0"},qt={key:0},Ot={class:"bg-white border-t border-gray-200"},Pt={key:0,class:"px-3 py-2 border-b border-gray-100 flex flex-wrap gap-2"},Xt={key:0,class:"relative w-20 h-20 rounded-lg overflow-hidden border border-gray-200"},Yt=["src","alt"],Gt=["onClick"],Jt={key:1,class:"relative w-24 h-20 rounded-lg border border-gray-200 bg-gray-50 flex flex-col items-center justify-center p-1"},Qt={class:"text-xs text-gray-500 truncate w-full text-center px-1"},Zt=["onClick"],es={key:1,class:"flex items-center p-3 gap-2"},ts={class:"px-3 pb-3"},ss=["onKeydown"],as={class:"flex justify-end px-3 pb-3"},os={key:2,class:"flex-1 flex items-center justify-center flex-col bg-[#f5f5f5]"},rs={class:"text-gray-400"},ns={key:0,class:"w-64 bg-[#f5f5f5] border-l border-gray-200 flex flex-col"},ls={class:"flex-1 p-4"},is={class:"flex flex-col items-center"},cs=["src","alt"],ds={class:"mt-3 font-medium text-gray-800 text-lg"},ms={class:"mb-4"},fs={class:"relative"},ps={class:"max-h-[400px] overflow-y-auto"},hs={class:"flex items-center"},us=["src","alt"],gs={class:"ml-3"},ys={class:"font-medium text-gray-800"},xs={class:"flex flex-col"},bs={class:"flex flex-col items-center mb-8 pb-6 border-b border-gray-100"},ks={class:"relative mb-4"},ws=["src"],Vs={class:"text-center"},Cs={class:"font-semibold text-gray-800 text-xl"},_s={class:"text-sm text-gray-500 mt-1"},Ns={class:"space-y-5"},Es={class:"flex items-center justify-between mb-2"},Us={class:"text-gray-700 font-semibold flex items-center gap-2"},Bs={class:"bg-gray-50 rounded-xl p-6 space-y-5"},Ss={key:1,class:"text-gray-800 bg-white rounded-lg px-4 py-3 border border-gray-200"},As={key:1,class:"text-gray-800 bg-white rounded-lg px-4 py-3 border border-gray-200"},Fs={key:1,class:"text-gray-800 bg-white rounded-lg px-4 py-3 border border-gray-200"},Ds={key:1,class:"text-gray-800 bg-white rounded-lg px-4 py-3 border border-gray-200 min-h-[80px]"},Rs={key:0,class:"flex gap-3 justify-end pt-2"},Ts=Be({__name:"ChatWindow",props:{modelValue:{type:Boolean,default:!1},config:{type:Object,required:!0},width:{type:[String,Number],default:"1100px"}},emits:["update:modelValue","open","close","message","send","error"],setup(p,{emit:t}){const a=p,l=t,V=e.computed({get:()=>a.modelValue,set:c=>l("update:modelValue",c)}),{myUsername:E,myAvatar:B,userInfo:g,loadingUserInfo:y,friendList:w,filteredFriendList:m,searchText:h,inputText:u,messagesContainer:C,filteredUsers:z,filteredAvailableUsers:v,currentUser:K,currentMessages:W,addFriendDialogVisible:X,addFriendSearchText:O,availableUsers:f,loadingAvailableUsers:x,friendApplyList:b,loadingFriendApply:F,formatTime:Y,formatLastTime:M,scrollToBottom:se,getFriendList:ae,getChatHistory:ne,setFriendToChatStatus:j,selectUser:D,sendMessage:G,sendFile:De,sendFilesAndText:me,initWebSocket:fe,closeWebSocket:le,reset:ie,openAddFriendDialog:ce,addFriend:pe,loadFriendApplyList:he,agreeFriend:ue,updateMyAvatar:ge,getUserInfo:ye,updateUserInfo:xe}=Ue(a.config),be=e.computed(()=>{const c=[{id:"chat",icon:_.ChatDotRound,badge:0}];return a.config.modules.friends&&c.push({id:"friends",icon:_.UserFilled,badge:0}),a.config.modules.apply&&c.push({id:"apply",icon:_.Bell,badge:b.value?.length||0}),c}),H=e.ref("chat"),Q=e.ref(null),S=e.ref(null),A=e.ref(null),Z=e.ref(!1),L=e.ref(!1),R=e.ref({nickname:"",email:"",phone:"",bio:""}),o=e.ref(!1),n=e.ref(!1),i=e.ref(!1),U=e.ref(!1),P=e.ref(null),q=e.ref(""),ee=e.ref(null),T=e.ref([]),J=e.ref({visible:!1,x:0,y:0,chat:null}),Is=(c,r)=>{c.preventDefault(),c.stopPropagation(),J.value={visible:!0,x:c.clientX,y:c.clientY,chat:r}},ke=()=>{J.value.visible=!1},Ms=async()=>{if(!J.value.chat)return;await j(J.value.chat.id,0)&&Q.value===J.value.chat.id&&(Q.value=null,S.value=null),ke()},we=c=>{Q.value=c.id,S.value=c,A.value=null,Z.value=!1,D({id:c.id,name:c.name,avatar:c.avatar,online:c.online})},js=c=>{A.value=c,Q.value=null,S.value=null},$s=async()=>{if(!A.value)return;if(await j(A.value.id)){H.value="chat",await e.nextTick();const r=z.value.find(d=>d.id===A.value.id);r&&we(r),A.value=null}},vs=()=>{n.value=!0},Ks=()=>{P.value?.click()},Ws=()=>{ee.value?.click()},Hs=c=>{const r=Array.from(c.target.files||[]);if(r.length!==0){for(const d of r){if(d.size>50*1024*1024){I.ElMessage.warning(`文件 ${d.name} 超过50MB,已跳过`);continue}const k=URL.createObjectURL(d);T.value.push({id:Date.now()+Math.random(),file:d,name:d.name,size:d.size,type:d.type,previewUrl:k,isImage:d.type.startsWith("image/")})}ee.value&&(ee.value.value="")}},Re=c=>{const r=T.value[c];r.previewUrl&&URL.revokeObjectURL(r.previewUrl),T.value.splice(c,1)},Te=c=>{if(c===0)return"0 B";const r=1024,d=["B","KB","MB","GB"],k=Math.floor(Math.log(c)/Math.log(r));return parseFloat((c/Math.pow(r,k)).toFixed(2))+" "+d[k]},ze=async()=>{if(!u.value.trim()&&T.value.length===0)return;const c=[...T.value],r=u.value;u.value="",T.value.forEach(d=>{d.previewUrl&&URL.revokeObjectURL(d.previewUrl)}),T.value=[],await me(c,r),l("send",{text:r,files:c})},qs=c=>{const r=c.clipboardData?.items;if(r){for(const d of r)if(d.kind==="file"){const k=d.getAsFile();if(k){if(k.size>50*1024*1024){I.ElMessage.warning(`文件 ${k.name} 超过50MB,已跳过`);continue}const oe=URL.createObjectURL(k);T.value.push({id:Date.now()+Math.random(),file:k,name:k.name,size:k.size,type:k.type,previewUrl:oe,isImage:k.type.startsWith("image/")})}}}},Le=c=>{if(!c){I.ElMessage.warning("文件地址无效");return}window.open(c,"_blank")},Os=c=>{console.warn("图片加载失败",c)},Ps=c=>{const r=c.target.files[0];if(!r)return;if(!r.type.startsWith("image/")){I.ElMessage.error("只能上传图片文件");return}if(r.size>5*1024*1024){I.ElMessage.error("图片大小不能超过 5MB");return}const d=new FileReader;d.onload=k=>{q.value=k.target.result,i.value=!0},d.readAsDataURL(r)},Xs=async({file:c})=>{if(c){U.value=!0;try{const d=await new(require("../core/api.js")).ChatApi(a.config).uploadAvatar(c,E);d.code===200?(I.ElMessage.success("头像上传成功"),ge(d.data),Ie()):I.ElMessage.error(d.msg||"头像上传失败")}catch(r){console.error(r),I.ElMessage.error("头像上传失败")}finally{U.value=!1}}},Ie=()=>{q.value="",i.value=!1,P.value&&(P.value.value="")},Ys=()=>{R.value={nickname:g.value.nickname||"",email:g.value.email||"",phone:g.value.phone||"",bio:g.value.bio||""},L.value=!0},Gs=()=>{L.value=!1,R.value={nickname:"",email:"",phone:"",bio:""}},Js=async()=>{o.value=!0;try{await xe(R.value)?(I.ElMessage.success("保存成功"),L.value=!1):I.ElMessage.error("保存失败")}catch(c){console.error(c),I.ElMessage.error("保存失败")}finally{o.value=!1}},Qs=()=>{ie(),le(),Z.value=!1,n.value=!1,Ie(),L.value=!1,l("close")},Zs=async()=>{await Promise.all([ae(),he(),ye()]),fe(),z.value.length>0&&we(z.value[0]),l("open")};return e.onMounted(()=>{document.addEventListener("click",ke)}),e.onUnmounted(()=>{document.removeEventListener("click",ke),le()}),(c,r)=>{const d=e.resolveComponent("el-icon"),k=e.resolveComponent("el-input"),oe=e.resolveComponent("el-empty"),te=e.resolveComponent("el-button"),Ve=e.resolveComponent("el-dialog");return e.openBlock(),e.createBlock(Ve,{modelValue:V.value,"onUpdate:modelValue":r[13]||(r[13]=s=>V.value=s),width:p.width,"close-on-click-modal":!1,class:"chat-dialog","append-to-body":"",onClosed:Qs,onOpen:Zs},{default:e.withCtx(()=>[e.createElementVNode("div",He,[e.createElementVNode("div",qe,[e.createElementVNode("div",{class:"mb-4 cursor-pointer mt-4",onClick:vs},[e.createElementVNode("img",{src:e.unref(B),alt:"头像",class:"w-10 h-10 rounded-full border-2 border-gray-200"},null,8,Oe)]),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(be.value,s=>(e.openBlock(),e.createElementBlock("div",{key:s.id,class:e.normalizeClass(["w-10 h-10 flex items-center justify-center cursor-pointer rounded-lg transition-all relative",H.value===s.id?"bg-green-50 text-green-600":"text-gray-500 hover:bg-gray-100"]),onClick:$=>H.value=s.id},[e.createVNode(d,{size:24},{default:e.withCtx(()=>[(e.openBlock(),e.createBlock(e.resolveDynamicComponent(s.icon)))]),_:2},1024),s.badge?(e.openBlock(),e.createElementBlock("span",Xe,e.toDisplayString(s.badge>99?"99+":s.badge),1)):e.createCommentVNode("",!0)],10,Pe))),128)),r[14]||(r[14]=e.createElementVNode("div",{class:"flex-1"},null,-1)),p.config.modules.settings?(e.openBlock(),e.createElementBlock("div",{key:0,class:"w-10 h-10 flex items-center justify-center cursor-pointer rounded-lg hover:bg-gray-100 transition-all mb-4 text-gray-500",onClick:r[0]||(r[0]=s=>n.value=!0),title:"设置"},[e.createVNode(d,{size:24},{default:e.withCtx(()=>[e.createVNode(e.unref(_.Setting))]),_:1})])):e.createCommentVNode("",!0)]),e.createElementVNode("div",Ye,[e.createElementVNode("div",Ge,[e.createVNode(k,{modelValue:e.unref(h),"onUpdate:modelValue":r[1]||(r[1]=s=>e.isRef(h)?h.value=s:null),placeholder:"搜索","prefix-icon":e.unref(_.Search)},null,8,["modelValue","prefix-icon"])]),e.createElementVNode("div",Je,[H.value==="chat"?(e.openBlock(),e.createElementBlock("div",Qe,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(z),s=>(e.openBlock(),e.createElementBlock("div",{key:s.id,class:e.normalizeClass(["flex items-center p-3 cursor-pointer hover:bg-[#e5e5e5] transition-colors",Q.value===s.id?"bg-[#d6d6d6]":""]),onClick:$=>we(s),onContextmenu:e.withModifiers($=>Is($,s),["prevent","stop"])},[e.createElementVNode("div",et,[e.createElementVNode("img",{src:s.avatar,alt:s.name,class:"w-11 h-11 rounded-full object-cover"},null,8,tt),s.online?(e.openBlock(),e.createElementBlock("span",st)):e.createCommentVNode("",!0)]),e.createElementVNode("div",at,[e.createElementVNode("div",ot,[e.createElementVNode("span",rt,e.toDisplayString(s.name),1),e.createElementVNode("span",nt,e.toDisplayString(e.unref(M)(s.lastTime)),1)]),e.createElementVNode("div",lt,[e.createElementVNode("span",it,e.toDisplayString(s.lastMsg),1),s.unread>0?(e.openBlock(),e.createElementBlock("span",ct,e.toDisplayString(s.unread>99?"99+":s.unread),1)):e.createCommentVNode("",!0)])])],42,Ze))),128))])):e.createCommentVNode("",!0),H.value==="friends"&&p.config.modules.friends?(e.openBlock(),e.createElementBlock("div",dt,[e.createElementVNode("div",mt,[e.createElementVNode("div",{class:"flex items-center gap-2 p-2 rounded-lg cursor-pointer hover:bg-[#e5e5e5]",onClick:r[2]||(r[2]=(...s)=>e.unref(ce)&&e.unref(ce)(...s))},[e.createElementVNode("div",ft,[e.createVNode(d,{class:"text-white",size:20},{default:e.withCtx(()=>[e.createVNode(e.unref(_.Plus))]),_:1})]),r[15]||(r[15]=e.createElementVNode("span",{class:"text-sm text-gray-800"},"添加好友",-1))])]),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(m),s=>(e.openBlock(),e.createElementBlock("div",{key:s.id,class:"flex items-center p-3 cursor-pointer hover:bg-[#e5e5e5] transition-colors",onClick:$=>js(s)},[e.createElementVNode("div",ht,[e.createElementVNode("img",{src:s.avatar,alt:s.name,class:"w-11 h-11 rounded-full object-cover"},null,8,ut),e.createElementVNode("span",{class:e.normalizeClass(["absolute bottom-0 right-0 w-3 h-3 rounded-full border-2 border-white",s.online?"bg-green-500":"bg-gray-400"])},null,2)]),e.createElementVNode("div",gt,[e.createElementVNode("span",yt,e.toDisplayString(s.name),1)])],8,pt))),128))])):e.createCommentVNode("",!0),H.value==="apply"&&p.config.modules.apply?(e.openBlock(),e.createElementBlock("div",xt,[e.unref(F)?(e.openBlock(),e.createBlock(oe,{key:0,description:"加载中..."})):e.unref(b).length===0?(e.openBlock(),e.createBlock(oe,{key:1,description:"暂无好友申请"})):(e.openBlock(!0),e.createElementBlock(e.Fragment,{key:2},e.renderList(e.unref(b),s=>(e.openBlock(),e.createElementBlock("div",{key:s.applyUser||s.id,class:"flex items-center justify-between p-3 hover:bg-[#e5e5e5]"},[e.createElementVNode("div",bt,[e.createElementVNode("img",{src:`https://api.dicebear.com/7.x/avataaars/svg?seed=${s.applyUser}`,alt:s.applyUser,class:"w-11 h-11 rounded-full object-cover"},null,8,kt),e.createElementVNode("div",wt,[e.createElementVNode("div",Vt,e.toDisplayString(s.applyUser),1),r[16]||(r[16]=e.createElementVNode("div",{class:"text-xs text-gray-500 mt-1"},"请求添加你为好友",-1))])]),e.createVNode(te,{type:"primary",size:"small",onClick:$=>e.unref(ue)(s.applyUser)},{default:e.withCtx(()=>[...r[17]||(r[17]=[e.createTextVNode("同意",-1)])]),_:1},8,["onClick"])]))),128))])):e.createCommentVNode("",!0)])]),e.createElementVNode("div",Ct,[A.value&&!S.value?(e.openBlock(),e.createElementBlock("div",_t,[e.createElementVNode("div",Nt,[e.createElementVNode("img",{src:A.value.avatar,alt:A.value.name,class:"w-24 h-24 rounded-full object-cover mb-6"},null,8,Et),e.createElementVNode("div",Ut,e.toDisplayString(A.value.name),1),e.createElementVNode("div",Bt,[e.createElementVNode("span",{class:e.normalizeClass(["w-2 h-2 rounded-full",A.value.online?"bg-green-500":"bg-gray-400"])},null,2),e.createElementVNode("span",St,e.toDisplayString(A.value.online?"在线":"离线"),1)]),e.createVNode(te,{type:"primary",size:"large",onClick:$s,class:"w-40"},{default:e.withCtx(()=>[e.createVNode(d,null,{default:e.withCtx(()=>[e.createVNode(e.unref(_.ChatDotRound))]),_:1}),r[18]||(r[18]=e.createElementVNode("span",null,"发消息",-1))]),_:1})])])):e.createCommentVNode("",!0),S.value?(e.openBlock(),e.createElementBlock("div",At,[e.createElementVNode("div",Ft,[e.createElementVNode("div",Dt,[e.createElementVNode("span",Rt,e.toDisplayString(S.value.name),1),e.createElementVNode("span",{class:e.normalizeClass(["text-xs px-2 py-0.5 rounded",S.value.online?"bg-green-100 text-green-600":"bg-gray-100 text-gray-500"])},e.toDisplayString(S.value.online?"在线":"离线"),3)]),e.createElementVNode("div",Tt,[e.createVNode(d,{class:"cursor-pointer hover:text-gray-700"},{default:e.withCtx(()=>[e.createVNode(e.unref(_.Search))]),_:1}),e.createVNode(d,{class:"cursor-pointer hover:text-gray-700",onClick:r[3]||(r[3]=s=>Z.value=!Z.value)},{default:e.withCtx(()=>[e.createVNode(e.unref(_.MoreFilled))]),_:1})])]),e.createElementVNode("div",{ref_key:"messagesContainer",ref:C,class:"flex-1 overflow-y-auto p-4 bg-[#f5f5f5] min-h-0 message-list"},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(W),(s,$)=>(e.openBlock(),e.createElementBlock("div",{key:$,class:e.normalizeClass(["flex mb-6 items-start",s.isSelf?"flex-row-reverse":"flex-row"])},[e.createElementVNode("div",zt,[e.createElementVNode("img",{src:s.isSelf?e.unref(B):S.value.avatar,class:"w-10 h-10 rounded-lg object-cover"},null,8,Lt)]),e.createElementVNode("div",{class:e.normalizeClass(["flex flex-col max-w-[75%]",s.isSelf?"mr-3 items-end":"ml-3 items-start"])},[s.isSelf?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",It,e.toDisplayString(S.value.name),1)),e.createElementVNode("div",Mt,[s.type==="text"?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["px-3 py-2 text-sm break-all whitespace-pre-wrap rounded-lg shadow-sm",s.isSelf?"bg-[#95ec69] text-gray-800 self-end message-bubble-self":"bg-white text-gray-800 message-bubble-other"])},e.toDisplayString(s.text),3)):s.type==="file"&&s.fileType==="image"?(e.openBlock(),e.createElementBlock("div",{key:1,class:e.normalizeClass(["rounded-lg relative shadow-sm cursor-pointer overflow-hidden max-w-[300px]",s.isSelf?"self-end":"self-start"]),onClick:Ce=>Le(s.fileUrl)},[e.createElementVNode("img",{src:s.fileUrl,alt:s.fileName,class:"w-full h-auto block",onError:Os},null,40,$t),s.fileName||s.fileSize?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass([s.isSelf?"bg-[#95ec69] text-gray-700":"bg-white text-gray-500"])},[s.fileSize?(e.openBlock(),e.createElementBlock("div",vt,e.toDisplayString(Te(s.fileSize)),1)):e.createCommentVNode("",!0)],2)):e.createCommentVNode("",!0)],10,jt)):s.type==="file"?(e.openBlock(),e.createElementBlock("div",{key:2,class:e.normalizeClass(["rounded-lg shadow-sm cursor-pointer overflow-hidden min-w-[200px]",s.isSelf?"self-end message-bubble-self":"message-bubble-other"]),onClick:Ce=>Le(s.fileUrl)},[e.createElementVNode("div",{class:e.normalizeClass(["flex items-center gap-3 px-4 py-3",s.isSelf?"bg-[#95ec69]":"bg-white"])},[e.createElementVNode("div",Wt,[e.createVNode(d,{size:28,class:e.normalizeClass(s.isSelf?"text-gray-700":"text-gray-500")},{default:e.withCtx(()=>[e.createVNode(e.unref(_.Document))]),_:1},8,["class"])]),e.createElementVNode("div",Ht,[e.createElementVNode("div",{class:e.normalizeClass(["truncate text-sm font-medium leading-tight",(s.isSelf,"text-gray-800")])},e.toDisplayString(s.fileName||s.text),3),e.createElementVNode("div",{class:e.normalizeClass(["text-xs mt-1 flex items-center gap-2",s.isSelf?"text-gray-600":"text-gray-500"])},[e.createVNode(d,{size:12},{default:e.withCtx(()=>[e.createVNode(e.unref(_.Download))]),_:1}),r[19]||(r[19]=e.createElementVNode("span",null,"点击下载",-1)),s.fileSize?(e.openBlock(),e.createElementBlock("span",qt,"· "+e.toDisplayString(Te(s.fileSize)),1)):e.createCommentVNode("",!0)],2)])],2)],10,Kt)):e.createCommentVNode("",!0),e.createElementVNode("div",{class:e.normalizeClass(["text-[10px] text-gray-400 mt-1",s.isSelf?"text-right":"text-left"])},e.toDisplayString(e.unref(Y)(s.time)),3)])],2)],2))),128))],512),e.createElementVNode("div",Ot,[T.value.length>0?(e.openBlock(),e.createElementBlock("div",Pt,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(T.value,(s,$)=>(e.openBlock(),e.createElementBlock("div",{key:s.id,class:"relative group"},[s.isImage?(e.openBlock(),e.createElementBlock("div",Xt,[e.createElementVNode("img",{src:s.previewUrl,alt:s.name,class:"w-full h-full object-cover"},null,8,Yt),e.createElementVNode("button",{onClick:Ce=>Re($),class:"absolute top-1 right-1 w-5 h-5 bg-black/50 text-white rounded-full flex items-center justify-center hover:bg-black/70 transition-colors text-xs"}," × ",8,Gt)])):(e.openBlock(),e.createElementBlock("div",Jt,[e.createVNode(d,{class:"text-gray-400 text-2xl mb-1"},{default:e.withCtx(()=>[e.createVNode(e.unref(_.Folder))]),_:1}),e.createElementVNode("span",Qt,e.toDisplayString(s.name),1),e.createElementVNode("button",{onClick:Ce=>Re($),class:"absolute top-1 right-1 w-5 h-5 bg-black/50 text-white rounded-full flex items-center justify-center hover:bg-black/70 transition-colors text-xs"}," × ",8,Zt)]))]))),128))])):e.createCommentVNode("",!0),p.config.modules.fileUpload?(e.openBlock(),e.createElementBlock("div",es,[e.createVNode(d,{class:"text-gray-500 cursor-pointer hover:text-gray-700"},{default:e.withCtx(()=>[e.createVNode(e.unref(_.ChatDotRound))]),_:1}),e.createVNode(d,{class:"text-gray-500 cursor-pointer hover:text-gray-700",onClick:Ws},{default:e.withCtx(()=>[e.createVNode(e.unref(_.Folder))]),_:1}),e.createVNode(d,{class:"text-gray-500 cursor-pointer hover:text-gray-700"},{default:e.withCtx(()=>[e.createVNode(e.unref(_.Picture))]),_:1})])):e.createCommentVNode("",!0),e.createElementVNode("div",ts,[e.withDirectives(e.createElementVNode("textarea",{"onUpdate:modelValue":r[4]||(r[4]=s=>e.isRef(u)?u.value=s:null),onKeydown:e.withKeys(e.withModifiers(ze,["prevent"]),["enter"]),onPaste:qs,placeholder:"输入消息或粘贴文件...",class:"w-full resize-none border-0 outline-none text-sm h-[80px]",rows:"3"},null,40,ss),[[e.vModelText,e.unref(u)]])]),e.createElementVNode("div",as,[e.createVNode(te,{type:"primary",disabled:!e.unref(u).trim()&&T.value.length===0,onClick:ze,class:"bg-[#07c160] hover:bg-[#06ad56] border-0 text-sm px-6"},{default:e.withCtx(()=>[...r[20]||(r[20]=[e.createTextVNode(" 发送 ",-1)])]),_:1},8,["disabled"])]),e.createElementVNode("input",{ref_key:"fileInputRef",ref:ee,type:"file",multiple:"",class:"hidden",onChange:Hs},null,544)])])):A.value?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",os,[e.createVNode(d,{size:64,class:"text-gray-300 mb-2"},{default:e.withCtx(()=>[e.createVNode(e.unref(_.ChatLineRound))]),_:1}),e.createElementVNode("div",rs,e.toDisplayString(H.value==="apply"?"在左侧选择好友申请":"在左侧选择好友开始聊天"),1)]))]),Z.value?(e.openBlock(),e.createElementBlock("div",ns,[r[22]||(r[22]=e.createElementVNode("div",{class:"h-14 flex items-center justify-center border-b border-gray-200"},[e.createElementVNode("span",{class:"font-medium text-gray-700"},"聊天详情")],-1)),e.createElementVNode("div",ls,[e.createElementVNode("div",is,[e.createElementVNode("img",{src:S.value?.avatar,alt:S.value?.name,class:"w-20 h-20 rounded-full object-cover"},null,8,cs),e.createElementVNode("div",ds,e.toDisplayString(S.value?.name),1),r[21]||(r[21]=e.createElementVNode("div",{class:"mt-6 w-full"},[e.createElementVNode("div",{class:"bg-white rounded-lg"},[e.createElementVNode("div",{class:"p-3 border-b border-gray-100 cursor-pointer hover:bg-gray-50"},[e.createElementVNode("span",{class:"text-sm text-gray-700"},"查找聊天记录")]),e.createElementVNode("div",{class:"p-3 border-b border-gray-100 cursor-pointer hover:bg-gray-50"},[e.createElementVNode("span",{class:"text-sm text-gray-700"},"清空聊天记录")])])],-1))])])])):e.createCommentVNode("",!0)]),e.createVNode(Ve,{modelValue:e.unref(X),"onUpdate:modelValue":r[6]||(r[6]=s=>e.isRef(X)?X.value=s:null),title:"添加好友",width:"500px","append-to-body":""},{default:e.withCtx(()=>[e.createElementVNode("div",ms,[e.createElementVNode("div",fs,[e.createVNode(k,{modelValue:e.unref(O),"onUpdate:modelValue":r[5]||(r[5]=s=>e.isRef(O)?O.value=s:null),placeholder:"搜索用户","prefix-icon":e.unref(_.Search)},null,8,["modelValue","prefix-icon"])])]),e.createElementVNode("div",ps,[e.unref(x)?(e.openBlock(),e.createBlock(oe,{key:0,description:"加载中..."})):e.unref(v).length===0?(e.openBlock(),e.createBlock(oe,{key:1,description:"暂无用户"})):(e.openBlock(!0),e.createElementBlock(e.Fragment,{key:2},e.renderList(e.unref(v),s=>(e.openBlock(),e.createElementBlock("div",{key:s.username,class:"flex items-center justify-between p-3 hover:bg-gray-50 rounded-lg mb-2 transition-colors"},[e.createElementVNode("div",hs,[e.createElementVNode("img",{src:`https://api.dicebear.com/7.x/avataaars/svg?seed=${s.username}`,alt:s.username,class:"w-10 h-10 rounded-full object-cover"},null,8,us),e.createElementVNode("div",gs,[e.createElementVNode("div",ys,e.toDisplayString(s.username),1)])]),e.createVNode(te,{type:"primary",size:"small",onClick:$=>e.unref(pe)(s)},{default:e.withCtx(()=>[...r[23]||(r[23]=[e.createTextVNode("添加",-1)])]),_:1},8,["onClick"])]))),128))])]),_:1},8,["modelValue"]),e.createVNode(Ve,{modelValue:n.value,"onUpdate:modelValue":r[11]||(r[11]=s=>n.value=s),title:"个人设置",width:"560px","close-on-click-modal":!1,"append-to-body":"",class:"settings-dialog"},{default:e.withCtx(()=>[e.createElementVNode("div",xs,[e.createElementVNode("div",bs,[e.createElementVNode("div",ks,[e.createElementVNode("img",{src:e.unref(B),alt:"头像",class:"w-28 h-28 rounded-full object-cover border-4 border-white shadow-lg"},null,8,ws),p.config.modules.avatarCrop?(e.openBlock(),e.createElementBlock("div",{key:0,class:"absolute -bottom-1 -right-1 w-10 h-10 bg-green-500 rounded-full flex items-center justify-center cursor-pointer hover:bg-green-600 transition-all shadow-md",onClick:Ks},[e.createVNode(d,{size:18,class:"text-white"},{default:e.withCtx(()=>[e.createVNode(e.unref(_.Camera))]),_:1})])):e.createCommentVNode("",!0),e.createElementVNode("input",{ref_key:"avatarInputRef",ref:P,type:"file",accept:"image/*",class:"hidden",onChange:Ps},null,544)]),e.createElementVNode("div",Vs,[e.createElementVNode("div",Cs,e.toDisplayString(e.unref(g).nickname||e.unref(E)),1),e.createElementVNode("div",_s,"@"+e.toDisplayString(e.unref(E)),1)])]),e.createElementVNode("div",Ns,[e.createElementVNode("div",Es,[e.createElementVNode("div",Us,[e.createVNode(d,null,{default:e.withCtx(()=>[e.createVNode(e.unref(_.UserFilled))]),_:1}),r[24]||(r[24]=e.createTextVNode(" 个人信息 ",-1))]),L.value?e.createCommentVNode("",!0):(e.openBlock(),e.createBlock(te,{key:0,type:"primary",size:"small",onClick:Ys,class:"rounded-full"},{default:e.withCtx(()=>[...r[25]||(r[25]=[e.createTextVNode(" 编辑 ",-1)])]),_:1}))]),e.createElementVNode("div",Bs,[e.createElementVNode("div",null,[r[26]||(r[26]=e.createElementVNode("label",{class:"block text-sm text-gray-600 mb-2 font-medium"},"昵称",-1)),L.value?(e.openBlock(),e.createBlock(k,{key:0,modelValue:R.value.nickname,"onUpdate:modelValue":r[7]||(r[7]=s=>R.value.nickname=s),placeholder:"请输入昵称",size:"large"},null,8,["modelValue"])):(e.openBlock(),e.createElementBlock("div",Ss,e.toDisplayString(e.unref(g).nickname||"未设置"),1))]),e.createElementVNode("div",null,[r[27]||(r[27]=e.createElementVNode("label",{class:"block text-sm text-gray-600 mb-2 font-medium"},"邮箱",-1)),L.value?(e.openBlock(),e.createBlock(k,{key:0,modelValue:R.value.email,"onUpdate:modelValue":r[8]||(r[8]=s=>R.value.email=s),placeholder:"请输入邮箱",size:"large"},null,8,["modelValue"])):(e.openBlock(),e.createElementBlock("div",As,e.toDisplayString(e.unref(g).email||"未设置"),1))]),e.createElementVNode("div",null,[r[28]||(r[28]=e.createElementVNode("label",{class:"block text-sm text-gray-600 mb-2 font-medium"},"手机号",-1)),L.value?(e.openBlock(),e.createBlock(k,{key:0,modelValue:R.value.phone,"onUpdate:modelValue":r[9]||(r[9]=s=>R.value.phone=s),placeholder:"请输入手机号",size:"large"},null,8,["modelValue"])):(e.openBlock(),e.createElementBlock("div",Fs,e.toDisplayString(e.unref(g).phone||"未设置"),1))]),e.createElementVNode("div",null,[r[29]||(r[29]=e.createElementVNode("label",{class:"block text-sm text-gray-600 mb-2 font-medium"},"个人简介",-1)),L.value?(e.openBlock(),e.createBlock(k,{key:0,modelValue:R.value.bio,"onUpdate:modelValue":r[10]||(r[10]=s=>R.value.bio=s),type:"textarea",rows:4,placeholder:"介绍一下自己吧...",size:"large"},null,8,["modelValue"])):(e.openBlock(),e.createElementBlock("div",Ds,e.toDisplayString(e.unref(g).bio||"这个人很懒,什么都没写~"),1))]),L.value?(e.openBlock(),e.createElementBlock("div",Rs,[e.createVNode(te,{size:"default",onClick:Gs},{default:e.withCtx(()=>[...r[30]||(r[30]=[e.createTextVNode("取消",-1)])]),_:1}),e.createVNode(te,{type:"primary",size:"default",loading:o.value,onClick:Js},{default:e.withCtx(()=>[...r[31]||(r[31]=[e.createTextVNode("保存更改",-1)])]),_:1},8,["loading"])])):e.createCommentVNode("",!0)])])])]),_:1},8,["modelValue"]),e.createVNode(Se,{modelValue:i.value,"onUpdate:modelValue":r[12]||(r[12]=s=>i.value=s),src:q.value,onConfirm:Xs},null,8,["modelValue","src"]),J.value.visible?(e.openBlock(),e.createElementBlock("div",{key:0,class:"context-menu fixed bg-white rounded-lg shadow-lg border py-1 z-50",style:e.normalizeStyle({left:J.value.x+"px",top:J.value.y+"px"})},[e.createElementVNode("div",{class:"px-4 py-2 hover:bg-gray-100 cursor-pointer",onClick:Ms},"删除聊天")],4)):e.createCommentVNode("",!0)]),_:1},8,["modelValue","width"])}}},[["__scopeId","data-v-fc6ab10a"]]),zs={api:{baseUrl:"",websocketUrl:"",endpoints:{getFriends:"/chart/friends",getHistory:"/chart/history",setRead:"/chart/read",uploadFile:"/chart/upload/file",addFriend:"/chart/friend/add",getApplyList:"/chart/friend/applyList",agreeFriend:"/chart/friend/agree",setChatStatus:"/chart/friend/chat/status",getAvailableUsers:"/chart/user/canAddFriend",getUserInfo:"/user/info",updateUserInfo:"/user/info",getUserAvatar:"/user/getAvatar",uploadAvatar:"/user/uploadAvatar"},adapter:null},user:{username:"",avatar:"",nickname:"",email:"",phone:"",bio:""},modules:{friends:!0,apply:!0,settings:!0,fileUpload:!0,avatarCrop:!0},theme:{primaryColor:"#07c160",selfMessageBg:"#95ec69",otherMessageBg:"#ffffff"},headers:{},websocket:{maxReconnectAttempts:5,reconnectDelay:3e3},file:{maxSize:50*1024*1024,allowedTypes:["*"]}};function Ls(p={}){const t=Ae(zs,p);return t.api.baseUrl||console.warn("[VueChatKit] 请配置 api.baseUrl"),t.api.websocketUrl||console.warn("[VueChatKit] 请配置 api.websocketUrl"),t.user.username||console.warn("[VueChatKit] 请配置 user.username"),t}function Ae(p,t){const a={...p};for(const l in t)t[l]&&typeof t[l]=="object"&&!Array.isArray(t[l])?a[l]=Ae(p[l]||{},t[l]):a[l]=t[l];return a}const Fe={install(p){p.component("ChatWindow",ChatWindow),p.component("AvatarCrop",AvatarCrop)}};N.AvatarCrop=Se,N.ChatApi=Ee,N.ChatWebSocket=_e,N.ChatWindow=Ts,N.HttpClient=Ne,N.VueChatKit=Fe,N.createChatConfig=Ls,N.default=Fe,N.useChat=Ue,Object.defineProperties(N,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
1
+ (function(U,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue"),require("@element-plus/icons-vue"),require("dayjs"),require("element-plus")):typeof define=="function"&&define.amd?define(["exports","vue","@element-plus/icons-vue","dayjs","element-plus"],e):(U=typeof globalThis<"u"?globalThis:U||self,e(U.VueChatKit={},U.Vue,U.ElementPlusIconsVue,U.dayjs,U.ElementPlus))})(this,function(U,e,b,pe,M){"use strict";class Ue{constructor(t,a={}){this.userId=t,this.wsUrl=a.wsUrl||"",this.socket=null,this.reconnectAttempts=0,this.maxReconnectAttempts=a.maxReconnectAttempts||5,this.reconnectDelay=a.reconnectDelay||3e3,this.handlers={message:[],open:[],close:[],error:[]},this.isConnecting=!1,this.manualClose=!1}connect(){if(!(this.isConnecting||this.isConnected())){this.isConnecting=!0,this.manualClose=!1;try{this.socket=new WebSocket(this.wsUrl),this.socket.onopen=()=>{console.log("[VueChatKit] WebSocket 连接成功"),this.isConnecting=!1,this.reconnectAttempts=0,this.emit("open")},this.socket.onmessage=t=>{try{const a=t.data;this.emit("message",a)}catch(a){console.error("[VueChatKit] WebSocket 消息解析失败",a)}},this.socket.onclose=t=>{console.log("[VueChatKit] WebSocket 连接关闭",t.code),this.isConnecting=!1,this.emit("close",t),!this.manualClose&&t.code!==1e3&&this.reconnect()},this.socket.onerror=t=>{console.error("[VueChatKit] WebSocket 连接错误",t),this.isConnecting=!1,this.emit("error",t)}}catch(t){console.error("[VueChatKit] WebSocket 创建连接失败",t),this.isConnecting=!1}}}send(t,a,r="text",N="",B="",x=0){if(this.isConnected()){const g=JSON.stringify({to:t,msg:a,type:r,fileUrl:N,fileName:B,fileSize:x});return this.socket.send(g),!0}return console.warn("[VueChatKit] WebSocket 连接未建立,无法发送消息"),!1}on(t,a){this.handlers[t]&&this.handlers[t].push(a)}off(t,a){if(this.handlers[t]){const r=this.handlers[t].indexOf(a);r>-1&&this.handlers[t].splice(r,1)}}emit(t,...a){this.handlers[t]&&this.handlers[t].forEach(r=>r(...a))}reconnect(){this.reconnectAttempts<this.maxReconnectAttempts?(this.reconnectAttempts++,console.log(`[VueChatKit] 尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`),setTimeout(()=>this.connect(),this.reconnectDelay)):console.error("[VueChatKit] 重连次数已达上限")}close(){this.manualClose=!0,this.socket&&(this.socket.close(),this.socket=null,this.handlers={message:[],open:[],close:[],error:[]})}isConnected(){return this.socket&&this.socket.readyState===WebSocket.OPEN}}class oe extends Error{constructor(t,a,r,N){super(t),this.name="RequestError",this.status=a||0,this.code=r||0,this.data=N}}class Be{constructor(t={}){this.baseUrl=t.baseUrl||"",this.timeout=t.timeout||1e4,this.headers=t.headers||{},this.requestInterceptors=[],this.responseInterceptors=[],this.addRequestInterceptor(a=>(a.body instanceof FormData||(a.headers={"Content-Type":"application/json",...a.headers}),a))}addRequestInterceptor(t){this.requestInterceptors.push(t)}addResponseInterceptor(t){this.responseInterceptors.push(t)}timeoutPromise(t){return new Promise((a,r)=>{setTimeout(()=>{r(new oe("请求超时",408,408))},t)})}async request(t,a={}){const{method:r="GET",headers:N={},body:B,params:x}=a;let g=t.startsWith("http")?t:`${this.baseUrl}${t}`,y={method:r,headers:{...this.headers,...N},body:B,params:x};this.requestInterceptors.forEach(d=>{y=d(y)});const C={method:y.method,headers:y.headers,credentials:"include"};if(y.body&&r!=="GET"&&(y.body instanceof FormData?C.body=y.body:typeof y.body=="object"?C.body=JSON.stringify(y.body):C.body=y.body),y.params){const d=new URLSearchParams;for(const u in y.params)y.params[u]!==void 0&&y.params[u]!==null&&y.params[u]!==""&&d.append(u,y.params[u]);const h=d.toString();h&&(g+=(g.includes("?")?"&":"?")+h)}try{let h=await Promise.race([fetch(g,C),this.timeoutPromise(this.timeout)]);if(this.responseInterceptors.forEach(z=>{h=z(h)}),!h.ok)throw new oe(`HTTP ${h.status}: ${h.statusText}`,h.status,h.status);const u=h.headers.get("content-type");let E;return u&&u.includes("application/json")?E=await h.json():E=await h.text(),E}catch(d){throw d instanceof oe?d:new oe(d instanceof Error?d.message:"网络错误",0,0)}}get(t,a,r){return this.request(t,{...r,method:"GET",params:a})}post(t,a,r){return this.request(t,{...r,method:"POST",body:a})}put(t,a,r){return this.request(t,{...r,method:"PUT",body:a})}delete(t,a){return this.request(t,{...a,method:"DELETE"})}}class le{constructor(t,a=null){this.config=t,this.endpoints=t.api.endpoints,this.customAdapter=t.api.adapter,a?this.http=a:this.http=new Be({baseUrl:t.api.baseUrl,headers:t.headers})}async _call(t,...a){return this.customAdapter&&typeof this.customAdapter[t]=="function"?this.customAdapter[t](...a):this[`_${t}`](...a)}async getFriends(t){return this._call("getFriends",t)}async _getFriends(t){return this.http.get(this.endpoints.getFriends,{currentUser:t})}async getAvailableUsers(t){return this._call("getAvailableUsers",t)}async _getAvailableUsers(t){return this.http.get(this.endpoints.getAvailableUsers,{currentUser:t})}async addFriend(t,a){return this._call("addFriend",t,a)}async _addFriend(t,a){return this.http.post(this.endpoints.addFriend,{currentUser:t,friendUser:a})}async getApplyList(t){return this._call("getApplyList",t)}async _getApplyList(t){return this.http.get(this.endpoints.getApplyList,{currentUser:t})}async agreeFriend(t,a){return this._call("agreeFriend",t,a)}async _agreeFriend(t,a){return this.http.post(this.endpoints.agreeFriend,{applyUser:t,friendUser:a})}async setChatStatus(t,a,r=1){return this._call("setChatStatus",t,a,r)}async _setChatStatus(t,a,r){return this.http.post(this.endpoints.setChatStatus,null,{params:{currentUser:t,friendUser:a,status:r}})}async getHistory(t,a){return this._call("getHistory",t,a)}async _getHistory(t,a){return this.http.get(this.endpoints.getHistory,{fromUser:t,toUser:a})}async setRead(t,a){return this._call("setRead",t,a)}async _setRead(t,a){return this.http.post(this.endpoints.setRead,{currentUser:t,friendUser:a})}async uploadFile(t){return this._call("uploadFile",t)}async _uploadFile(t){const a=new FormData;return a.append("file",t),this.http.post(this.endpoints.uploadFile,a)}async getUserInfo(t){return this._call("getUserInfo",t)}async _getUserInfo(t){return this.http.get(this.endpoints.getUserInfo,{username:t})}async updateUserInfo(t,a){return this._call("updateUserInfo",t,a)}async _updateUserInfo(t,a){return this.http.put(this.endpoints.updateUserInfo,{username:t,...a})}async getUserAvatar(t){return this._call("getUserAvatar",t)}async _getUserAvatar(t){return this.http.get(this.endpoints.getUserAvatar,{username:t})}async uploadAvatar(t,a){return this._call("uploadAvatar",t,a)}async _uploadAvatar(t,a){const r=new FormData;return r.append("file",t),r.append("username",a),this.http.post(this.endpoints.uploadAvatar,r)}}const Ke=Object.freeze(Object.defineProperty({__proto__:null,ChatApi:le,default:le},Symbol.toStringTag,{value:"Module"}));function xe(f){const t=new le(f);let a=null;const r=f.user.username,N=e.ref(f.user.avatar||`https://api.dicebear.com/7.x/avataaars/svg?seed=${r}`),B=e.ref({username:r,nickname:f.user.nickname||"",email:f.user.email||"",phone:f.user.phone||"",bio:f.user.bio||""}),x=e.ref(!1),g=e.ref([]),y=e.ref([]),C=e.ref([]),d=e.ref(""),h=e.ref(""),u=e.ref(""),E=e.ref(null),z=e.ref(!1),W=e.ref(""),q=e.ref([]),H=e.ref(!1),G=e.ref([]),P=e.ref(!1),p=e.computed(()=>{let s=y.value;if(h.value){const l=h.value.toLowerCase();s=s.filter(i=>{var V;return(V=i.username)==null?void 0:V.toLowerCase().includes(l)})}return s.map(l=>({id:l.username,name:l.username,avatar:l.avatar||N.value,online:l.online,lastMsg:l.lastMsg||"暂无消息",lastTime:l.lastTime,unread:l.unReadNum||0}))}),k=e.computed(()=>{let s=g.value;if(h.value){const l=h.value.toLowerCase();s=s.filter(i=>{var V;return(V=i.username)==null?void 0:V.toLowerCase().includes(l)})}return s.map(l=>({id:l.username,name:l.username,avatar:l.avatar||N.value,online:l.online,isChatting:l.isChatting}))}),_=e.computed(()=>W.value?q.value.filter(s=>{var l;return(l=s.username)==null?void 0:l.toLowerCase().includes(W.value.toLowerCase())}):q.value),D=e.computed(()=>p.value.find(s=>s.id===d.value)||null),J=e.computed(()=>C.value.map(s=>{const l=s.type==="file"||s.fileUrl||s.fileName,i=s.fileName||s.msgContent;return{text:s.msgContent,isSelf:s.sendUsername===r,time:s.createTime,sendUsername:s.sendUsername,type:l?"file":"text",fileType:ne(i)?"image":re(i),fileUrl:s.fileUrl||"",fileName:i,fileSize:s.fileSize||0}})),v=s=>pe(s).format("HH:mm"),se=s=>{if(!s)return"";const l=pe(),i=pe(s);return l.isSame(i,"day")?i.format("HH:mm"):l.diff(i,"day")===1?"昨天":l.diff(i,"day")<7?["周日","周一","周二","周三","周四","周五","周六"][i.day()]:i.format("MM/DD")},ne=s=>{if(!s)return!1;const l=["jpg","jpeg","png","gif","bmp","webp","svg"],i=s.split(".").pop().toLowerCase();return l.includes(i)},re=s=>{if(!s)return"default";const l=s.split(".").pop().toLowerCase();return["xls","xlsx"].includes(l)?"excel":["pdf"].includes(l)?"pdf":["doc","docx"].includes(l)?"docx":"default"},$=()=>{e.nextTick(()=>{E.value&&(E.value.scrollTop=E.value.scrollHeight)})},T=async()=>{try{const l=(await t.getFriends(r)).data||[];g.value=l,y.value=l.filter(i=>i.isChatting===1);for(const i of y.value)try{const X=(await t.getHistory(r,i.username)).data||[];i.unReadNum=X.filter(O=>O.isRead===0&&O.sendUsername===i.username).length}catch{i.unReadNum=0}}catch(s){console.error("[VueChatKit] 获取好友列表失败",s)}},Q=async s=>{try{const l=await t.getHistory(r,s);C.value=l.data||[],$()}catch(l){console.error("[VueChatKit] 获取聊天历史失败",l)}},Te=async s=>{try{await t.setRead(r,s),T()}catch(l){console.error("[VueChatKit] 标记已读失败",l)}},fe=async s=>{d.value=s.id,await Q(s.id),await Te(s.id),$()},he=async(s,l=1)=>{try{return await t.setChatStatus(r,s,l),await T(),!0}catch(i){return console.error("[VueChatKit] 设置聊天状态失败",i),!1}},ie=()=>{if(!u.value.trim()||!d.value||!a)return;if(a.send(d.value,u.value.trim(),"text")){const l={msgContent:u.value.trim(),sendUsername:r,receiveUsername:d.value,createTime:new Date,isRead:0,type:"text"};C.value.push(l),u.value="",$(),setTimeout(()=>{Q(d.value),T()},300)}},ce=async s=>{if(!d.value||!a)return!1;try{const l=await t.uploadFile(s);if(l.code===200&&l.data){const{fileUrl:i,fileName:V}=l.data;if(a.send(d.value,V,"file",i,V,s.size)){const O={msgContent:V,sendUsername:r,receiveUsername:d.value,createTime:new Date,isRead:0,type:"file",fileUrl:i,fileName:V,fileSize:s.size};return C.value.push(O),$(),!0}}return!1}catch(l){return console.error("[VueChatKit] 发送文件失败",l),!1}},de=async(s,l)=>{if(!(!d.value||!a)){if(l&&l.trim()&&a.send(d.value,l.trim(),"text")){const V={msgContent:l.trim(),sendUsername:r,receiveUsername:d.value,createTime:new Date,isRead:0,type:"text"};C.value.push(V)}for(const i of s){const V=i.file||i;await ce(V)}setTimeout(()=>{Q(d.value),T()},300)}},ue=s=>{try{try{const i=JSON.parse(s);if(i.to||i.msg)return{to:i.to,content:i.msg,type:i.type||"text",fileUrl:i.fileUrl||"",fileName:i.fileName||"",fileSize:i.fileSize||0}}catch{}const l=s.match(/^\[(.+?)\]:(.+)$/);if(l)return{username:l[1],content:l[2],type:"text"}}catch(l){console.error("[VueChatKit] 解析消息失败",l)}return null},ge=s=>{if(s.includes("【状态变更】")){const i=/【状态变更】(.+?) 已(上线|下线)/,V=s.match(i);if(V){const X=V[1],O=V[2]==="上线",te=g.value.find(L=>L.username===X);te&&(te.online=O)}return}const l=ue(s);if(l){if(d.value){try{let i={msgContent:l.content,sendUsername:l.username||d.value,receiveUsername:r,createTime:new Date,isRead:0,type:l.type||"text",fileUrl:l.fileUrl||"",fileName:l.fileName||"",fileSize:l.fileSize||0};C.value.push(i),$()}catch(i){console.error("[VueChatKit] 添加临时消息失败",i)}Q(d.value)}T()}},ye=()=>{const s=`${f.api.websocketUrl}?userId=${r}`;a=new Ue(r,{wsUrl:s,maxReconnectAttempts:f.websocket.maxReconnectAttempts,reconnectDelay:f.websocket.reconnectDelay}),a.on("message",ge),a.connect()},ke=()=>{a&&(a.close(),a=null)},_e=async()=>{z.value=!0,W.value="",await Ve()},Ve=async()=>{H.value=!0;try{const s=await t.getAvailableUsers(r);q.value=(s==null?void 0:s.data)||[]}catch(s){console.error("[VueChatKit] 获取可用用户失败",s)}finally{H.value=!1}},Ce=async s=>{try{await t.addFriend(r,s.username),await T(),z.value=!1}catch(l){console.error("[VueChatKit] 添加好友失败",l)}},j=async()=>{P.value=!0;try{const s=await t.getApplyList(r);G.value=s.data||[]}catch(s){console.error("[VueChatKit] 获取好友申请列表失败",s)}finally{P.value=!1}},Z=async s=>{try{await t.agreeFriend(s,r),await j(),await T()}catch(l){console.error("[VueChatKit] 同意好友申请失败",l)}},S=async()=>{try{const s=await t.getUserAvatar(r);s.code===200&&s.data&&(N.value=s.data)}catch(s){console.warn("[VueChatKit] 加载头像失败",s)}},A=s=>{N.value=s},ee=async()=>{x.value=!0;try{const s=await t.getUserInfo(r);s.code===200&&s.data&&(B.value={...B.value,...s.data})}catch(s){console.error("[VueChatKit] 获取用户信息失败",s)}finally{x.value=!1}},I=async s=>{try{return(await t.updateUserInfo(r,s)).code===200?(B.value={...B.value,...s},!0):!1}catch(l){return console.error("[VueChatKit] 更新用户信息失败",l),!1}},R=()=>{d.value="",C.value=[],u.value="",h.value=""};return S(),{myUsername:r,myAvatar:N,userInfo:B,loadingUserInfo:x,friendList:g,chatList:y,filteredFriendList:k,chatMsgList:C,currentSelectName:d,searchText:h,inputText:u,messagesContainer:E,filteredUsers:p,filteredAvailableUsers:_,currentUser:D,currentMessages:J,addFriendDialogVisible:z,addFriendSearchText:W,availableUsers:q,loadingAvailableUsers:H,friendApplyList:G,loadingFriendApply:P,formatTime:v,formatLastTime:se,scrollToBottom:$,getFriendList:T,getChatHistory:Q,setFriendToChatStatus:he,selectUser:fe,sendMessage:ie,sendFile:ce,sendFilesAndText:de,initWebSocket:ye,closeWebSocket:ke,reset:R,openAddFriendDialog:_e,addFriend:Ce,loadFriendApplyList:j,agreeFriend:Z,updateMyAvatar:A,getUserInfo:ee,updateUserInfo:I}}const Se=(f,t)=>{const a=f.__vccOpts||f;for(const[r,N]of t)a[r]=N;return a},We={class:"avatar-crop-container"},qe=["src"],He={class:"crop-overlay"},je={class:"crop-box"},Oe={key:0,class:"crop-mask"},Pe={class:"zoom-controls"},Ae=Se({__name:"AvatarCrop",props:{modelValue:{type:Boolean,default:!1},src:{type:String,default:""}},emits:["update:modelValue","confirm"],setup(f,{emit:t}){const a=f,r=t,N=e.computed({get:()=>a.modelValue,set:p=>r("update:modelValue",p)}),B=e.ref(""),x=e.ref(null),g=e.ref(null),y=e.ref(null),C=e.ref(1),d=e.ref({x:0,y:0}),h=e.ref(!1),u=e.ref({x:0,y:0}),E=e.ref({width:0,height:0});e.watch(()=>a.src,p=>{p&&(B.value=p,C.value=1,d.value={x:0,y:0})});const z=()=>{e.nextTick(()=>{if(x.value&&g.value){const p=x.value,k=g.value,_=Math.min(k.clientWidth,k.clientHeight);p.naturalWidth>p.naturalHeight?(E.value.height=_,E.value.width=p.naturalWidth/p.naturalHeight*_):(E.value.width=_,E.value.height=p.naturalHeight/p.naturalWidth*_),d.value={x:(_-E.value.width)/2,y:(_-E.value.height)/2}}})},W=p=>{h.value=!0;const k=p.touches?p.touches[0].clientX:p.clientX,_=p.touches?p.touches[0].clientY:p.clientY;u.value={x:k-d.value.x,y:_-d.value.y},document.addEventListener("mousemove",q),document.addEventListener("mouseup",H),document.addEventListener("touchmove",q),document.addEventListener("touchend",H)},q=p=>{if(!h.value)return;const k=p.touches?p.touches[0].clientX:p.clientX,_=p.touches?p.touches[0].clientY:p.clientY;d.value={x:k-u.value.x,y:_-u.value.y}},H=()=>{h.value=!1,document.removeEventListener("mousemove",q),document.removeEventListener("mouseup",H),document.removeEventListener("touchmove",q),document.removeEventListener("touchend",H)},G=()=>{const p=document.createElement("canvas"),k=p.getContext("2d"),_=200;p.width=_,p.height=_;const D=x.value,J=y.value,v=g.value;if(D&&J&&v){const se=J.getBoundingClientRect(),ne=v.getBoundingClientRect(),re=(se.left-ne.left-d.value.x)/C.value,$=(se.top-ne.top-d.value.y)/C.value,T=se.width/C.value;k.drawImage(D,re*(D.naturalWidth/E.value.width),$*(D.naturalHeight/E.value.height),T*(D.naturalWidth/E.value.width),T*(D.naturalHeight/E.value.height),0,0,_,_),p.toBlob(Q=>{r("confirm",{file:Q,url:p.toDataURL("image/png")}),N.value=!1},"image/png")}},P=()=>{B.value="",C.value=1,d.value={x:0,y:0}};return(p,k)=>{const _=e.resolveComponent("el-slider"),D=e.resolveComponent("el-button"),J=e.resolveComponent("el-dialog");return e.openBlock(),e.createBlock(J,{modelValue:N.value,"onUpdate:modelValue":k[2]||(k[2]=v=>N.value=v),title:"裁剪头像",width:"500px","close-on-click-modal":!1,onClosed:P},{footer:e.withCtx(()=>[e.createVNode(D,{onClick:k[1]||(k[1]=v=>N.value=!1)},{default:e.withCtx(()=>[...k[3]||(k[3]=[e.createTextVNode("取消",-1)])]),_:1}),e.createVNode(D,{type:"primary",onClick:G},{default:e.withCtx(()=>[...k[4]||(k[4]=[e.createTextVNode("确定",-1)])]),_:1})]),default:e.withCtx(()=>[e.createElementVNode("div",We,[e.createElementVNode("div",{class:"crop-area",ref_key:"cropAreaRef",ref:g},[e.createElementVNode("img",{src:B.value,ref_key:"imageRef",ref:x,class:"crop-image",onLoad:z,onMousedown:W,onTouchstart:W},null,40,qe),e.createElementVNode("div",He,[e.createElementVNode("div",je,[e.createElementVNode("div",{class:"crop-border",ref_key:"cropBoxRef",ref:y},null,512)])]),h.value?(e.openBlock(),e.createElementBlock("div",Oe)):e.createCommentVNode("",!0)],512),e.createElementVNode("div",Pe,[e.createVNode(_,{modelValue:C.value,"onUpdate:modelValue":k[0]||(k[0]=v=>C.value=v),min:.5,max:3,step:.1,"show-tooltip":!1},null,8,["modelValue"])])])]),_:1},8,["modelValue"])}}},[["__scopeId","data-v-4e4a992b"]]),Xe={class:"chat-container"},Ye={class:"sidebar-nav"},Ge=["src"],Je=["onClick"],Qe={key:0,class:"nav-badge"},Ze={class:"content-panel"},et={class:"search-bar"},tt={class:"content-scroll"},at={key:0},st=["onClick","onContextmenu"],nt={class:"friend-avatar-wrapper"},ot=["src","alt"],lt={key:0,class:"online-indicator"},rt={class:"friend-info"},it={class:"friend-header"},ct={class:"friend-name"},dt={class:"last-time"},mt={class:"friend-preview"},pt={class:"last-msg"},ft={key:0,class:"unread-badge"},ht={key:1},ut={class:"add-friend-section"},gt={class:"add-friend-icon"},yt=["onClick"],kt={class:"friend-avatar-wrapper"},_t=["src","alt"],Vt={class:"friend-info"},Ct={class:"friend-name"},Nt={key:2},Et={class:"request-info"},wt=["src","alt"],bt={class:"request-details"},Ut={class:"request-username"},Bt={class:"chat-area"},xt={key:0,class:"friend-profile"},St=["src","alt"],At={class:"profile-name"},Ft={class:"profile-status"},Dt={key:1,class:"chat-window"},Tt={class:"chat-header"},Rt={class:"chat-title"},Lt={class:"chat-name"},zt={class:"chat-actions"},It={class:"message-avatar"},Mt=["src"],vt={key:0,class:"sender-name"},$t={class:"message-bubble-wrapper"},Kt=["onClick"],Wt=["src","alt"],qt={key:0,class:"image-size"},Ht=["onClick"],jt={class:"file-content"},Ot={class:"file-icon"},Pt={class:"file-info"},Xt={class:"file-name"},Yt={class:"file-meta"},Gt={key:0},Jt={class:"input-area"},Qt={key:0,class:"pending-files"},Zt={key:0,class:"pending-image-wrapper"},ea=["src","alt"],ta=["onClick"],aa={key:1,class:"pending-file-wrapper"},sa={class:"pending-file-name"},na=["onClick"],oa={key:1,class:"input-actions"},la={class:"input-wrapper"},ra=["onKeydown"],ia={class:"send-btn-wrapper"},ca={key:2,class:"empty-state"},da={class:"empty-text"},ma={key:0,class:"detail-panel"},pa={class:"detail-content"},fa={class:"detail-profile"},ha=["src","alt"],ua={class:"detail-name"},ga={class:"search-users-wrapper"},ya={class:"search-users-input"},ka={class:"users-list-scroll"},_a={class:"available-user-info"},Va=["src","alt"],Ca={class:"available-user-name"},Na={class:"settings-container"},Ea={class:"settings-avatar-section"},wa={class:"settings-avatar-wrapper"},ba=["src"],Ua={class:"settings-user-display"},Ba={class:"settings-nickname"},xa={class:"settings-username"},Sa={class:"settings-form-section"},Aa={class:"settings-form-header"},Fa={class:"settings-form-title"},Da={class:"settings-form"},Ta={class:"settings-form-item"},Ra={key:1,class:"settings-form-value"},La={class:"settings-form-item"},za={key:1,class:"settings-form-value"},Ia={class:"settings-form-item"},Ma={key:1,class:"settings-form-value"},va={class:"settings-form-item"},$a={key:1,class:"settings-form-value bio-value"},Ka={key:0,class:"settings-form-actions"},Wa=Se({__name:"ChatWindow",props:{modelValue:{type:Boolean,default:!1},config:{type:Object,required:!0},width:{type:[String,Number],default:"1100px"}},emits:["update:modelValue","open","close","message","send","error"],setup(f,{emit:t}){const a=f,r=t,N=e.computed({get:()=>a.modelValue,set:c=>r("update:modelValue",c)}),{myUsername:B,myAvatar:x,userInfo:g,loadingUserInfo:y,friendList:C,filteredFriendList:d,searchText:h,inputText:u,messagesContainer:E,filteredUsers:z,filteredAvailableUsers:W,currentUser:q,currentMessages:H,addFriendDialogVisible:G,addFriendSearchText:P,availableUsers:p,loadingAvailableUsers:k,friendApplyList:_,loadingFriendApply:D,formatTime:J,formatLastTime:v,scrollToBottom:se,getFriendList:ne,getChatHistory:re,setFriendToChatStatus:$,selectUser:T,sendMessage:Q,sendFile:Te,sendFilesAndText:fe,initWebSocket:he,closeWebSocket:ie,reset:ce,openAddFriendDialog:de,addFriend:ue,loadFriendApplyList:ge,agreeFriend:ye,updateMyAvatar:ke,getUserInfo:_e,updateUserInfo:Ve}=xe(a.config),Ce=e.computed(()=>{var o;const c=[{id:"chat",icon:b.ChatDotRound,badge:0}];return a.config.modules.friends&&c.push({id:"friends",icon:b.UserFilled,badge:0}),a.config.modules.apply&&c.push({id:"apply",icon:b.Bell,badge:((o=_.value)==null?void 0:o.length)||0}),c}),j=e.ref("chat"),Z=e.ref(null),S=e.ref(null),A=e.ref(null),ee=e.ref(!1),I=e.ref(!1),R=e.ref({nickname:"",email:"",phone:"",bio:""}),s=e.ref(!1),l=e.ref(!1),i=e.ref(!1),V=e.ref(!1),X=e.ref(null),O=e.ref(""),te=e.ref(null),L=e.ref([]),ae=e.ref({visible:!1,x:0,y:0,chat:null}),Ne=()=>{ae.value.visible=!1},ja=async()=>{if(!ae.value.chat)return;await $(ae.value.chat.id,0)&&Z.value===ae.value.chat.id&&(Z.value=null,S.value=null),Ne()},Ee=c=>{Z.value=c.id,S.value=c,A.value=null,ee.value=!1,T({id:c.id,name:c.name,avatar:c.avatar,online:c.online})},Oa=c=>{A.value=c,Z.value=null,S.value=null},Pa=async()=>{if(!A.value)return;if(await $(A.value.id)){j.value="chat",await e.nextTick();const o=z.value.find(m=>m.id===A.value.id);o&&Ee(o),A.value=null}},Xa=()=>{l.value=!0},Ya=()=>{var c;(c=X.value)==null||c.click()},Ga=()=>{var c;(c=te.value)==null||c.click()},Ja=c=>{const o=Array.from(c.target.files||[]);if(o.length!==0){for(const m of o){if(m.size>50*1024*1024){M.ElMessage.warning(`文件 ${m.name} 超过50MB,已跳过`);continue}const w=URL.createObjectURL(m);L.value.push({id:Date.now()+Math.random(),file:m,name:m.name,size:m.size,type:m.type,previewUrl:w,isImage:m.type.startsWith("image/")})}te.value&&(te.value.value="")}},Re=c=>{const o=L.value[c];o.previewUrl&&URL.revokeObjectURL(o.previewUrl),L.value.splice(c,1)},Le=c=>{if(c===0)return"0 B";const o=1024,m=["B","KB","MB","GB"],w=Math.floor(Math.log(c)/Math.log(o));return parseFloat((c/Math.pow(o,w)).toFixed(2))+" "+m[w]},ze=async()=>{if(!u.value.trim()&&L.value.length===0)return;const c=[...L.value],o=u.value;u.value="",L.value.forEach(m=>{m.previewUrl&&URL.revokeObjectURL(m.previewUrl)}),L.value=[],await fe(c,o),r("send",{text:o,files:c})},Qa=c=>{var m;const o=(m=c.clipboardData)==null?void 0:m.items;if(o){for(const w of o)if(w.kind==="file"){const F=w.getAsFile();if(F){if(F.size>50*1024*1024){M.ElMessage.warning(`文件 ${F.name} 超过50MB,已跳过`);continue}const Y=URL.createObjectURL(F);L.value.push({id:Date.now()+Math.random(),file:F,name:F.name,size:F.size,type:F.type,previewUrl:Y,isImage:F.type.startsWith("image/")})}}}},Ie=c=>{if(!c){M.ElMessage.warning("文件地址无效");return}window.open(c,"_blank")},Za=c=>{console.warn("图片加载失败",c)},es=c=>{const o=c.target.files[0];if(!o)return;if(!o.type.startsWith("image/")){M.ElMessage.error("只能上传图片文件");return}if(o.size>5*1024*1024){M.ElMessage.error("图片大小不能超过 5MB");return}const m=new FileReader;m.onload=w=>{O.value=w.target.result,i.value=!0},m.readAsDataURL(o)},ts=async({file:c})=>{if(c){V.value=!0;try{const{ChatApi:o}=await Promise.resolve().then(()=>Ke),w=await new o(a.config).uploadAvatar(c,B);w.code===200?(M.ElMessage.success("头像上传成功"),ke(w.data),Me()):M.ElMessage.error(w.msg||"头像上传失败")}catch(o){console.error(o),M.ElMessage.error("头像上传失败")}finally{V.value=!1}}},Me=()=>{O.value="",i.value=!1,X.value&&(X.value.value="")},as=()=>{R.value={nickname:g.value.nickname||"",email:g.value.email||"",phone:g.value.phone||"",bio:g.value.bio||""},I.value=!0},ss=()=>{I.value=!1,R.value={nickname:"",email:"",phone:"",bio:""}},ns=async()=>{s.value=!0;try{await Ve(R.value)?(M.ElMessage.success("保存成功"),I.value=!1):M.ElMessage.error("保存失败")}catch(c){console.error(c),M.ElMessage.error("保存失败")}finally{s.value=!1}},os=()=>{ce(),ie(),ee.value=!1,l.value=!1,Me(),I.value=!1,r("close")},ls=async()=>{await Promise.all([ne(),ge(),_e()]),he(),z.value.length>0&&Ee(z.value[0]),r("open")};return e.onMounted(()=>{document.addEventListener("click",Ne)}),e.onUnmounted(()=>{document.removeEventListener("click",Ne),ie()}),(c,o)=>{const m=e.resolveComponent("el-icon"),w=e.resolveComponent("el-input"),F=e.resolveComponent("el-empty"),Y=e.resolveComponent("el-button"),we=e.resolveComponent("el-dialog");return e.openBlock(),e.createBlock(we,{modelValue:N.value,"onUpdate:modelValue":o[13]||(o[13]=me=>N.value=me),width:f.width,"close-on-click-modal":!1,class:"chat-dialog","append-to-body":"",onClosed:os,onOpen:ls},{default:e.withCtx(()=>{var me,ve,$e;return[e.createElementVNode("div",Xe,[e.createElementVNode("div",Ye,[e.createElementVNode("div",{class:"sidebar-avatar",onClick:Xa},[e.createElementVNode("img",{src:e.unref(x),alt:"头像",class:"avatar-img"},null,8,Ge)]),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(Ce.value,n=>(e.openBlock(),e.createElementBlock("div",{key:n.id,class:e.normalizeClass(["nav-item",j.value===n.id?"nav-item-active":"nav-item-inactive"]),onClick:K=>j.value=n.id},[e.createVNode(m,{size:24},{default:e.withCtx(()=>[(e.openBlock(),e.createBlock(e.resolveDynamicComponent(n.icon)))]),_:2},1024),n.badge?(e.openBlock(),e.createElementBlock("span",Qe,e.toDisplayString(n.badge>99?"99+":n.badge),1)):e.createCommentVNode("",!0)],10,Je))),128)),o[14]||(o[14]=e.createElementVNode("div",{class:"nav-spacer"},null,-1)),f.config.modules.settings?(e.openBlock(),e.createElementBlock("div",{key:0,class:"nav-item nav-item-inactive",onClick:o[0]||(o[0]=n=>l.value=!0),title:"设置"},[e.createVNode(m,{size:24},{default:e.withCtx(()=>[e.createVNode(e.unref(b.Setting))]),_:1})])):e.createCommentVNode("",!0)]),e.createElementVNode("div",Ze,[e.createElementVNode("div",et,[e.createVNode(w,{modelValue:e.unref(h),"onUpdate:modelValue":o[1]||(o[1]=n=>e.isRef(h)?h.value=n:null),placeholder:"搜索","prefix-icon":e.unref(b.Search)},null,8,["modelValue","prefix-icon"])]),e.createElementVNode("div",tt,[j.value==="chat"?(e.openBlock(),e.createElementBlock("div",at,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(z),n=>(e.openBlock(),e.createElementBlock("div",{key:n.id,class:e.normalizeClass(["chat-item",Z.value===n.id?"chat-item-active":""]),onClick:K=>Ee(n),onContextmenu:e.withModifiers(K=>c.showContextMenu(K,n),["prevent","stop"])},[e.createElementVNode("div",nt,[e.createElementVNode("img",{src:n.avatar,alt:n.name,class:"friend-avatar"},null,8,ot),n.online?(e.openBlock(),e.createElementBlock("span",lt)):e.createCommentVNode("",!0)]),e.createElementVNode("div",rt,[e.createElementVNode("div",it,[e.createElementVNode("span",ct,e.toDisplayString(n.name),1),e.createElementVNode("span",dt,e.toDisplayString(e.unref(v)(n.lastTime)),1)]),e.createElementVNode("div",mt,[e.createElementVNode("span",pt,e.toDisplayString(n.lastMsg),1),n.unread>0?(e.openBlock(),e.createElementBlock("span",ft,e.toDisplayString(n.unread>99?"99+":n.unread),1)):e.createCommentVNode("",!0)])])],42,st))),128))])):e.createCommentVNode("",!0),j.value==="friends"&&f.config.modules.friends?(e.openBlock(),e.createElementBlock("div",ht,[e.createElementVNode("div",ut,[e.createElementVNode("div",{class:"add-friend-btn",onClick:o[2]||(o[2]=(...n)=>e.unref(de)&&e.unref(de)(...n))},[e.createElementVNode("div",gt,[e.createVNode(m,{class:"text-white",size:20},{default:e.withCtx(()=>[e.createVNode(e.unref(b.Plus))]),_:1})]),o[15]||(o[15]=e.createElementVNode("span",{class:"add-friend-text"},"添加好友",-1))])]),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(d),n=>(e.openBlock(),e.createElementBlock("div",{key:n.id,class:"chat-item",onClick:K=>Oa(n)},[e.createElementVNode("div",kt,[e.createElementVNode("img",{src:n.avatar,alt:n.name,class:"friend-avatar"},null,8,_t),e.createElementVNode("span",{class:e.normalizeClass(["online-indicator",n.online?"online":"offline"])},null,2)]),e.createElementVNode("div",Vt,[e.createElementVNode("span",Ct,e.toDisplayString(n.name),1)])],8,yt))),128))])):e.createCommentVNode("",!0),j.value==="apply"&&f.config.modules.apply?(e.openBlock(),e.createElementBlock("div",Nt,[e.unref(D)?(e.openBlock(),e.createBlock(F,{key:0,description:"加载中..."})):e.unref(_).length===0?(e.openBlock(),e.createBlock(F,{key:1,description:"暂无好友申请"})):(e.openBlock(!0),e.createElementBlock(e.Fragment,{key:2},e.renderList(e.unref(_),n=>(e.openBlock(),e.createElementBlock("div",{key:n.applyUser||n.id,class:"friend-request-item"},[e.createElementVNode("div",Et,[e.createElementVNode("img",{src:`https://api.dicebear.com/7.x/avataaars/svg?seed=${n.applyUser}`,alt:n.applyUser,class:"request-avatar"},null,8,wt),e.createElementVNode("div",bt,[e.createElementVNode("div",Ut,e.toDisplayString(n.applyUser),1),o[16]||(o[16]=e.createElementVNode("div",{class:"request-desc"},"请求添加你为好友",-1))])]),e.createVNode(Y,{type:"primary",size:"small",onClick:K=>e.unref(ye)(n.applyUser)},{default:e.withCtx(()=>[...o[17]||(o[17]=[e.createTextVNode("同意",-1)])]),_:1},8,["onClick"])]))),128))])):e.createCommentVNode("",!0)])]),e.createElementVNode("div",Bt,[A.value&&!S.value?(e.openBlock(),e.createElementBlock("div",xt,[e.createElementVNode("img",{src:A.value.avatar,alt:A.value.name,class:"profile-avatar"},null,8,St),e.createElementVNode("div",At,e.toDisplayString(A.value.name),1),e.createElementVNode("div",Ft,[e.createElementVNode("span",{class:e.normalizeClass(["status-dot",A.value.online?"status-online":"status-offline"])},null,2),e.createElementVNode("span",null,e.toDisplayString(A.value.online?"在线":"离线"),1)]),e.createVNode(Y,{type:"primary",size:"large",onClick:Pa,class:"start-chat-btn"},{default:e.withCtx(()=>[e.createVNode(m,null,{default:e.withCtx(()=>[e.createVNode(e.unref(b.ChatDotRound))]),_:1}),o[18]||(o[18]=e.createElementVNode("span",null,"发消息",-1))]),_:1})])):e.createCommentVNode("",!0),S.value?(e.openBlock(),e.createElementBlock("div",Dt,[e.createElementVNode("div",Tt,[e.createElementVNode("div",Rt,[e.createElementVNode("span",Lt,e.toDisplayString(S.value.name),1),e.createElementVNode("span",{class:e.normalizeClass(["status-badge",S.value.online?"status-badge-online":"status-badge-offline"])},e.toDisplayString(S.value.online?"在线":"离线"),3)]),e.createElementVNode("div",zt,[e.createVNode(m,{class:"action-icon"},{default:e.withCtx(()=>[e.createVNode(e.unref(b.Search))]),_:1}),e.createVNode(m,{class:"action-icon",onClick:o[3]||(o[3]=n=>ee.value=!ee.value)},{default:e.withCtx(()=>[e.createVNode(e.unref(b.MoreFilled))]),_:1})])]),e.createElementVNode("div",{ref_key:"messagesContainer",ref:E,class:"messages-container"},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(H),(n,K)=>(e.openBlock(),e.createElementBlock("div",{key:K,class:e.normalizeClass(["message-wrapper",n.isSelf?"message-self":"message-other"])},[e.createElementVNode("div",It,[e.createElementVNode("img",{src:n.isSelf?e.unref(x):S.value.avatar,class:"avatar-sm"},null,8,Mt)]),e.createElementVNode("div",{class:e.normalizeClass(["message-content-wrapper",n.isSelf?"content-self":"content-other"])},[n.isSelf?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",vt,e.toDisplayString(S.value.name),1)),e.createElementVNode("div",$t,[n.type==="text"?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["message-bubble",n.isSelf?"bubble-self":"bubble-other"])},e.toDisplayString(n.text),3)):n.type==="file"&&n.fileType==="image"?(e.openBlock(),e.createElementBlock("div",{key:1,class:e.normalizeClass(["message-bubble","image-bubble",n.isSelf?"bubble-self":"bubble-other"]),onClick:be=>Ie(n.fileUrl)},[e.createElementVNode("img",{src:n.fileUrl,alt:n.fileName,class:"message-image",onError:Za},null,40,Wt),n.fileSize?(e.openBlock(),e.createElementBlock("div",qt,e.toDisplayString(Le(n.fileSize)),1)):e.createCommentVNode("",!0)],10,Kt)):n.type==="file"?(e.openBlock(),e.createElementBlock("div",{key:2,class:e.normalizeClass(["message-bubble","file-bubble",n.isSelf?"bubble-self":"bubble-other"]),onClick:be=>Ie(n.fileUrl)},[e.createElementVNode("div",jt,[e.createElementVNode("div",Ot,[e.createVNode(m,{size:28},{default:e.withCtx(()=>[e.createVNode(e.unref(b.Document))]),_:1})]),e.createElementVNode("div",Pt,[e.createElementVNode("div",Xt,e.toDisplayString(n.fileName||n.text),1),e.createElementVNode("div",Yt,[e.createVNode(m,{size:12},{default:e.withCtx(()=>[e.createVNode(e.unref(b.Download))]),_:1}),o[19]||(o[19]=e.createElementVNode("span",null,"点击下载",-1)),n.fileSize?(e.openBlock(),e.createElementBlock("span",Gt,"· "+e.toDisplayString(Le(n.fileSize)),1)):e.createCommentVNode("",!0)])])])],10,Ht)):e.createCommentVNode("",!0),e.createElementVNode("div",{class:e.normalizeClass(["message-time",n.isSelf?"time-right":"time-left"])},e.toDisplayString(e.unref(J)(n.time)),3)])],2)],2))),128))],512),e.createElementVNode("div",Jt,[L.value.length>0?(e.openBlock(),e.createElementBlock("div",Qt,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(L.value,(n,K)=>(e.openBlock(),e.createElementBlock("div",{key:n.id,class:"pending-file"},[n.isImage?(e.openBlock(),e.createElementBlock("div",Zt,[e.createElementVNode("img",{src:n.previewUrl,alt:n.name,class:"pending-image"},null,8,ea),e.createElementVNode("button",{onClick:be=>Re(K),class:"remove-file-btn"}," × ",8,ta)])):(e.openBlock(),e.createElementBlock("div",aa,[e.createVNode(m,{class:"pending-file-icon"},{default:e.withCtx(()=>[e.createVNode(e.unref(b.Folder))]),_:1}),e.createElementVNode("span",sa,e.toDisplayString(n.name),1),e.createElementVNode("button",{onClick:be=>Re(K),class:"remove-file-btn"}," × ",8,na)]))]))),128))])):e.createCommentVNode("",!0),f.config.modules.fileUpload?(e.openBlock(),e.createElementBlock("div",oa,[e.createVNode(m,{class:"action-icon"},{default:e.withCtx(()=>[e.createVNode(e.unref(b.ChatDotRound))]),_:1}),e.createVNode(m,{class:"action-icon",onClick:Ga},{default:e.withCtx(()=>[e.createVNode(e.unref(b.Folder))]),_:1}),e.createVNode(m,{class:"action-icon"},{default:e.withCtx(()=>[e.createVNode(e.unref(b.Picture))]),_:1})])):e.createCommentVNode("",!0),e.createElementVNode("div",la,[e.withDirectives(e.createElementVNode("textarea",{"onUpdate:modelValue":o[4]||(o[4]=n=>e.isRef(u)?u.value=n:null),onKeydown:e.withKeys(e.withModifiers(ze,["prevent"]),["enter"]),onPaste:Qa,placeholder:"输入消息或粘贴文件...",class:"message-input",rows:"3"},null,40,ra),[[e.vModelText,e.unref(u)]])]),e.createElementVNode("div",ia,[e.createVNode(Y,{type:"primary",disabled:!e.unref(u).trim()&&L.value.length===0,onClick:ze,class:"send-btn"},{default:e.withCtx(()=>[...o[20]||(o[20]=[e.createTextVNode(" 发送 ",-1)])]),_:1},8,["disabled"])]),e.createElementVNode("input",{ref_key:"fileInputRef",ref:te,type:"file",multiple:"",class:"hidden-file-input",onChange:Ja},null,544)])])):A.value?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("div",ca,[e.createVNode(m,{size:64,class:"empty-icon"},{default:e.withCtx(()=>[e.createVNode(e.unref(b.ChatLineRound))]),_:1}),e.createElementVNode("div",da,e.toDisplayString(j.value==="apply"?"在左侧选择好友申请":"在左侧选择好友开始聊天"),1)]))]),ee.value?(e.openBlock(),e.createElementBlock("div",ma,[o[22]||(o[22]=e.createElementVNode("div",{class:"detail-header"},"聊天详情",-1)),e.createElementVNode("div",pa,[e.createElementVNode("div",fa,[e.createElementVNode("img",{src:(me=S.value)==null?void 0:me.avatar,alt:(ve=S.value)==null?void 0:ve.name,class:"detail-avatar"},null,8,ha),e.createElementVNode("div",ua,e.toDisplayString(($e=S.value)==null?void 0:$e.name),1),o[21]||(o[21]=e.createElementVNode("div",{class:"detail-actions"},[e.createElementVNode("div",{class:"detail-action-item"},"查找聊天记录"),e.createElementVNode("div",{class:"detail-action-item"},"清空聊天记录")],-1))])])])):e.createCommentVNode("",!0)]),e.createVNode(we,{modelValue:e.unref(G),"onUpdate:modelValue":o[6]||(o[6]=n=>e.isRef(G)?G.value=n:null),title:"添加好友",width:"500px","append-to-body":""},{default:e.withCtx(()=>[e.createElementVNode("div",ga,[e.createElementVNode("div",ya,[e.createVNode(w,{modelValue:e.unref(P),"onUpdate:modelValue":o[5]||(o[5]=n=>e.isRef(P)?P.value=n:null),placeholder:"搜索用户","prefix-icon":e.unref(b.Search)},null,8,["modelValue","prefix-icon"])])]),e.createElementVNode("div",ka,[e.unref(k)?(e.openBlock(),e.createBlock(F,{key:0,description:"加载中..."})):e.unref(W).length===0?(e.openBlock(),e.createBlock(F,{key:1,description:"暂无用户"})):(e.openBlock(!0),e.createElementBlock(e.Fragment,{key:2},e.renderList(e.unref(W),n=>(e.openBlock(),e.createElementBlock("div",{key:n.username,class:"available-user-item"},[e.createElementVNode("div",_a,[e.createElementVNode("img",{src:`https://api.dicebear.com/7.x/avataaars/svg?seed=${n.username}`,alt:n.username,class:"available-user-avatar"},null,8,Va),e.createElementVNode("div",Ca,e.toDisplayString(n.username),1)]),e.createVNode(Y,{type:"primary",size:"small",onClick:K=>e.unref(ue)(n)},{default:e.withCtx(()=>[...o[23]||(o[23]=[e.createTextVNode("添加",-1)])]),_:1},8,["onClick"])]))),128))])]),_:1},8,["modelValue"]),e.createVNode(we,{modelValue:l.value,"onUpdate:modelValue":o[11]||(o[11]=n=>l.value=n),title:"个人设置",width:"560px","close-on-click-modal":!1,"append-to-body":"",class:"settings-dialog"},{default:e.withCtx(()=>[e.createElementVNode("div",Na,[e.createElementVNode("div",Ea,[e.createElementVNode("div",wa,[e.createElementVNode("img",{src:e.unref(x),alt:"头像",class:"settings-avatar"},null,8,ba),f.config.modules.avatarCrop?(e.openBlock(),e.createElementBlock("div",{key:0,class:"settings-avatar-edit",onClick:Ya},[e.createVNode(m,{size:18,class:"settings-avatar-icon"},{default:e.withCtx(()=>[e.createVNode(e.unref(b.Camera))]),_:1})])):e.createCommentVNode("",!0),e.createElementVNode("input",{ref_key:"avatarInputRef",ref:X,type:"file",accept:"image/*",class:"hidden-avatar-input",onChange:es},null,544)]),e.createElementVNode("div",Ua,[e.createElementVNode("div",Ba,e.toDisplayString(e.unref(g).nickname||e.unref(B)),1),e.createElementVNode("div",xa,"@"+e.toDisplayString(e.unref(B)),1)])]),e.createElementVNode("div",Sa,[e.createElementVNode("div",Aa,[e.createElementVNode("div",Fa,[e.createVNode(m,null,{default:e.withCtx(()=>[e.createVNode(e.unref(b.UserFilled))]),_:1}),o[24]||(o[24]=e.createTextVNode(" 个人信息 ",-1))]),I.value?e.createCommentVNode("",!0):(e.openBlock(),e.createBlock(Y,{key:0,type:"primary",size:"small",onClick:as,class:"settings-edit-btn"},{default:e.withCtx(()=>[...o[25]||(o[25]=[e.createTextVNode(" 编辑 ",-1)])]),_:1}))]),e.createElementVNode("div",Da,[e.createElementVNode("div",Ta,[o[26]||(o[26]=e.createElementVNode("label",{class:"settings-form-label"},"昵称",-1)),I.value?(e.openBlock(),e.createBlock(w,{key:0,modelValue:R.value.nickname,"onUpdate:modelValue":o[7]||(o[7]=n=>R.value.nickname=n),placeholder:"请输入昵称",size:"large"},null,8,["modelValue"])):(e.openBlock(),e.createElementBlock("div",Ra,e.toDisplayString(e.unref(g).nickname||"未设置"),1))]),e.createElementVNode("div",La,[o[27]||(o[27]=e.createElementVNode("label",{class:"settings-form-label"},"邮箱",-1)),I.value?(e.openBlock(),e.createBlock(w,{key:0,modelValue:R.value.email,"onUpdate:modelValue":o[8]||(o[8]=n=>R.value.email=n),placeholder:"请输入邮箱",size:"large"},null,8,["modelValue"])):(e.openBlock(),e.createElementBlock("div",za,e.toDisplayString(e.unref(g).email||"未设置"),1))]),e.createElementVNode("div",Ia,[o[28]||(o[28]=e.createElementVNode("label",{class:"settings-form-label"},"手机号",-1)),I.value?(e.openBlock(),e.createBlock(w,{key:0,modelValue:R.value.phone,"onUpdate:modelValue":o[9]||(o[9]=n=>R.value.phone=n),placeholder:"请输入手机号",size:"large"},null,8,["modelValue"])):(e.openBlock(),e.createElementBlock("div",Ma,e.toDisplayString(e.unref(g).phone||"未设置"),1))]),e.createElementVNode("div",va,[o[29]||(o[29]=e.createElementVNode("label",{class:"settings-form-label"},"个人简介",-1)),I.value?(e.openBlock(),e.createBlock(w,{key:0,modelValue:R.value.bio,"onUpdate:modelValue":o[10]||(o[10]=n=>R.value.bio=n),type:"textarea",rows:4,placeholder:"介绍一下自己吧...",size:"large"},null,8,["modelValue"])):(e.openBlock(),e.createElementBlock("div",$a,e.toDisplayString(e.unref(g).bio||"这个人很懒,什么都没写~"),1))]),I.value?(e.openBlock(),e.createElementBlock("div",Ka,[e.createVNode(Y,{size:"default",onClick:ss},{default:e.withCtx(()=>[...o[30]||(o[30]=[e.createTextVNode("取消",-1)])]),_:1}),e.createVNode(Y,{type:"primary",size:"default",loading:s.value,onClick:ns},{default:e.withCtx(()=>[...o[31]||(o[31]=[e.createTextVNode("保存更改",-1)])]),_:1},8,["loading"])])):e.createCommentVNode("",!0)])])])]),_:1},8,["modelValue"]),e.createVNode(Ae,{modelValue:i.value,"onUpdate:modelValue":o[12]||(o[12]=n=>i.value=n),src:O.value,onConfirm:ts},null,8,["modelValue","src"]),ae.value.visible?(e.openBlock(),e.createElementBlock("div",{key:0,class:"context-menu",style:e.normalizeStyle({left:ae.value.x+"px",top:ae.value.y+"px"})},[e.createElementVNode("div",{class:"context-menu-item",onClick:ja},"删除聊天")],4)):e.createCommentVNode("",!0)]}),_:1},8,["modelValue","width"])}}},[["__scopeId","data-v-a76a4ef3"]]),qa={api:{baseUrl:"",websocketUrl:"",endpoints:{getFriends:"/chart/friends",getHistory:"/chart/history",setRead:"/chart/read",uploadFile:"/chart/upload/file",addFriend:"/chart/friend/add",getApplyList:"/chart/friend/applyList",agreeFriend:"/chart/friend/agree",setChatStatus:"/chart/friend/chat/status",getAvailableUsers:"/chart/user/canAddFriend",getUserInfo:"/user/info",updateUserInfo:"/user/info",getUserAvatar:"/user/getAvatar",uploadAvatar:"/user/uploadAvatar"},adapter:null},user:{username:"",avatar:"",nickname:"",email:"",phone:"",bio:""},modules:{friends:!0,apply:!0,settings:!0,fileUpload:!0,avatarCrop:!0},theme:{primaryColor:"#07c160",selfMessageBg:"#95ec69",otherMessageBg:"#ffffff"},headers:{},websocket:{maxReconnectAttempts:5,reconnectDelay:3e3},file:{maxSize:50*1024*1024,allowedTypes:["*"]}};function Ha(f={}){const t=Fe(qa,f);return t.api.baseUrl||console.warn("[VueChatKit] 请配置 api.baseUrl"),t.api.websocketUrl||console.warn("[VueChatKit] 请配置 api.websocketUrl"),t.user.username||console.warn("[VueChatKit] 请配置 user.username"),t}function Fe(f,t){const a={...f};for(const r in t)t[r]&&typeof t[r]=="object"&&!Array.isArray(t[r])?a[r]=Fe(f[r]||{},t[r]):a[r]=t[r];return a}const De={install(f){f.component("ChatWindow",ChatWindow),f.component("AvatarCrop",AvatarCrop)}};U.AvatarCrop=Ae,U.ChatApi=le,U.ChatWebSocket=Ue,U.ChatWindow=Wa,U.HttpClient=Be,U.VueChatKit=De,U.createChatConfig=Ha,U.default=De,U.useChat=xe,Object.defineProperties(U,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-chat-kit",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "一个功能完整的 Vue 3 聊天组件库,支持 WebSocket 实时通信、文件上传、好友管理等功能",
5
5
  "type": "module",
6
6
  "main": "dist/vue-chat-kit.umd.js",