This commit is contained in:
caiyx 2024-11-19 13:57:36 +08:00
parent dcad444645
commit aab593f281
9 changed files with 323 additions and 16 deletions

View File

@ -8,7 +8,11 @@
"pages": [ "pages": [
{ {
"path": "pages/index/index", "path": "pages/index/index",
"type": "page" "type": "page",
"style": {
"navigationStyle": "custom",
"enablePullDownRefresh":false
}
}, },

View File

@ -1,17 +1,111 @@
<script setup>
import XTabbar from "@/components/x-tabbar/index.vue"
import { tabbar } from '@/config/tabbar/index.js'
import {useStatus} from "@/store/status"
const {tabBarIndex}= useStatus()
</script>
<template> <template>
<div class="flex flex-col h-[100vh]" > <div class="outer-layer">
<div>
123 <tm-navbar :hideBack="false" hideHome :title="123"> </tm-navbar>
</div>
<div class="root">
<div class="searchRoot">
<tm-input placeholder="请输入…" color="#F9F9FD" :round="1" prefix="tmicon-search" prefixColor="#46299D" ></tm-input>
</div>
<div class="contentRoot">
<div class="chatItem" >
<div class="avatarImg">
<tm-image preview :width="96" :height="96" :src="userInfo.Avatar"></tm-image>
</div>
<div class="chatInfo" >
<div class="chatInfo_1" >
<div class="flex items-center">
<div class="text-[#000000] text-[32rpx] font-bold opacity-90" >泰丰国际600</div>
<div>
<div class="companyTag" >公司</div>
</div>
</div>
<div class="text-[#000000] text-[28rpx] font-medium opacity-26" >12:00</div>
</div>
<div class="chatInfo_2 w-full mr-[6rpx]">
<div class="w-full chatInfo_2_1 textEllipsis" >欢迎加入欢迎加入欢迎加入欢迎加入欢迎加入欢迎加入欢迎加入欢迎加入</div>
</div>
</div>
</div>
</div>
</div>
</div> </div>
</template> </template>
<style scoped lang="scss"> <script setup>
import { useChatList } from "@/store/chatList/index.js";
import {useAuth} from "@/store/auth";
const {userInfo}=useAuth()
</script>
<style scoped lang="scss">
.outer-layer {
overflow-y: auto;
flex: 1;
background-image: url("@/static/image/clockIn/z3280@3x.png");
background-size: cover;
padding: 0 32rpx 20rpx 32rpx;
display: flex;
flex-direction: column;
}
.root {
flex: 1;
padding: 20rpx 0;
}
.searchRoot {
background-color: #fff;
padding: 22rpx 18rpx;
}
.contentRoot {
margin-top: 20rpx;
background-color: #fff;
}
.chatItem{
width: 100%;
padding: 30rpx 16rpx;
display: flex;
align-items: center;
}
.avatarImg{
height: 96rpx;
width: 96rpx;
}
.chatInfo{
flex:1;
margin-left: 20rpx;
}
.chatInfo_1{
display: flex;
align-items: center;
justify-content: space-between;
}
.chatInfo_2{
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 6rpx;
}
.chatInfo_2_1{
font-size: 28rpx;
color: #000000;
opacity: 40%;
}
.companyTag{
width: 76rpx;
height: 38rpx;
border: 1px solid #7A58DE;
font-size: 24rpx;
text-align: center;
border-radius: 6rpx;
color: #7A58DE;
font-weight: bold;
}
.textEllipsis {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
</style> </style>

163
src/plugins/websocket.ts Normal file
View File

@ -0,0 +1,163 @@
const cache = new Set()
const maxAttempts = 100
const defaultEvent = {
onError: (evt: any) => console.error('WebSocket Error:', evt),
onOpen: (evt: any) => console.log('WebSocket Opened:', evt),
onClose: (evt: any) => console.log('WebSocket Closed:', evt)
}
class WsSocket {
connect: WebSocket | null = null
config: any = {
heartbeat: {
setInterval: null,
pingInterval: 20000,
pingTimeout: 60000
},
reconnect: {
lockReconnect: false,
setTimeout: null,
interval: [2000, 2500, 3000, 3000, 5000, 8000], // Exponential backoff
attempts: maxAttempts
}
}
lastTime: number = 0
onCallBacks: Record<string, Function> = {}
defaultEvent: Record<string, Function> = defaultEvent
constructor(
private urlCallBack: () => string,
private events: Partial<typeof defaultEvent>
) {
this.events = { ...this.defaultEvent, ...events }
}
on(event: string, callback: Function): this {
this.onCallBacks[event] = callback
return this
}
loadSocket(): void {
this.connect = new WebSocket(this.urlCallBack())
this.connect.onerror = this.onError.bind(this)
this.connect.onopen = this.onOpen.bind(this)
this.connect.onmessage = this.onMessage.bind(this)
this.connect.onclose = this.onClose.bind(this)
}
connection(): void {
this.connect === null && this.loadSocket()
}
reconnect(): void {
if (this.config.reconnect.lockReconnect || this.config.reconnect.attempts <= 0) return
this.config.reconnect.lockReconnect = true
this.config.reconnect.attempts--
const delay = this.config.reconnect.interval.shift()
this.config.reconnect.setTimeout = setTimeout(() => {
console.log(new Date().toLocaleString(), 'Attempting to reconnect to WebSocket...')
this.connection()
}, delay || 10000)
}
onParse(evt: MessageEvent): any {
return JSON.parse(evt.data)
}
onOpen(evt: Event): void {
this.lastTime = Date.now()
this.events.onOpen?.(evt)
this.config.reconnect.interval = [1000, 1000, 3000, 5000, 10000]
this.config.reconnect.lockReconnect = false
this.config.reconnect.attempts = maxAttempts
this.heartbeat()
}
onClose(evt: CloseEvent): void {
this.events.onClose?.(evt)
this.connect = null
this.config.heartbeat.setInterval && clearInterval(this.config.heartbeat.setInterval)
this.config.reconnect.lockReconnect = false
if (evt.code !== 1000) {
this.reconnect()
}
}
onError(evt: Event): void {
this.events.onError?.(evt)
}
onMessage(evt: MessageEvent): void {
this.lastTime = Date.now()
const data = this.onParse(evt)
if (data.event === 'pong') {
return
}
if (data.ackid) {
this.connect?.send(`{"event":"ack","ackid":"${data.ackid}"}`)
if (cache.has(data.ackid)) return
cache.add(data.ackid)
}
if (this.onCallBacks[data.event]) {
this.onCallBacks[data.event](data.payload, evt.data)
} else {
console.warn(`WsSocket message event [${data.event}] not bound...`)
}
}
heartbeat(): void {
this.config.heartbeat.setInterval && clearInterval(this.config.heartbeat.setInterval)
this.config.heartbeat.setInterval = setInterval(() => {
this.ping()
}, this.config.heartbeat.pingInterval)
}
ping(): void {
this.connect?.send(JSON.stringify({ event: 'ping' }))
}
send(message: any): void {
if (this.connect && this.connect.readyState === WebSocket.OPEN) {
this.connect.send(typeof message === 'string' ? message : JSON.stringify(message))
} else {
alert('WebSocket 连接已关闭')
}
}
close(): void {
this.connect?.close()
this.config.heartbeat.setInterval && clearInterval(this.config.heartbeat.setInterval)
}
emit(event: string, payload: any): void {
if (this.connect && this.connect.readyState === WebSocket.OPEN) {
this.connect.send(JSON.stringify({ event, payload }))
} else {
console.error('WebSocket connection closed...', this.connect)
}
}
}
export default WsSocket

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -7,12 +7,38 @@ export const useAuth = createGlobalState(() => {
const refreshToken = useStorage('refreshToken', '', uniStorage) const refreshToken = useStorage('refreshToken', '', uniStorage)
const userInfo = useStorage('userInfo', {}, uniStorage) const userInfo = useStorage('userInfo', {}, uniStorage)
const leaderList = useStorage('leaderList', [], uniStorage) const leaderList = useStorage('leaderList', [], uniStorage)
const myCompany = useStorage('myCompany','', uniStorage)
const isLeader=ref(false) const isLeader=ref(false)
// const leaderList=ref([]) // const leaderList=ref([])
const getUserInfo=async ()=>{
const data={
ID:userInfo.value.ID
}
const res= await userInfoApi(data)
if (res.status===0){
userInfo.value=res.data
}
}
const getUserLeader=async ()=>{
const data={
departmentId:userInfo.value.PositionUsers?.map(x=>x.DepartmentId)
}
const res= await userLeaderApi(data)
if (res.status===0){
isLeader.value=!!res.data.departmentLeaders?.find((x) => {
return x.userID === userInfo.value.ID
})
leaderList.value=res.data.departmentLeaders
myCompany.value=res.data.company
}
}
return { return {
leaderList, leaderList,
myCompany,
getUserLeader,
getUserInfo,
userInfo, userInfo,
token, token,
refreshToken, refreshToken,

View File

@ -0,0 +1,20 @@
import {createGlobalState,useStorage} from '@vueuse/core'
import {uniStorage} from "@/utils/uniStorage.js"
import {ref} from 'vue'
export const useChatList = createGlobalState(() => {
// const token = useStorage('token', '', uniStorage)
// const refreshToken = useStorage('refreshToken', '', uniStorage)
// const userInfo = useStorage('userInfo', {}, uniStorage)
// const leaderList = useStorage('leaderList', [], uniStorage)
// const isLeader=ref(false)
// const leaderList=ref([])
return {
// leaderList,
// userInfo,
// token,
// refreshToken,
}
})