liveh5-nuxt/app/stores/live/index.js

276 lines
8.7 KiB
JavaScript
Raw Normal View History

import { createGlobalState } from '@vueuse/core'
import {ref} from "vue";
import {goodStore} from "@/stores/goods/index.js";
import {authStore} from "@/stores/auth/index.js";
import {message} from "~/components/x-message/useMessage.js";
import { WebSocketClient } from '@/utils/websocket'
import {logSendlog} from "~/api/goods/index.js";
import CryptoJS from "crypto-js";
export const liveStore = createGlobalState(() => {
const {auctionDetail} = goodStore();
const { token } = authStore()
const fullLive = ref(false)
const quoteStatus = ref(false)
const show = ref(false)
const cleanup = ref(null)
const show1=ref(false)
const playerId=ref('J_prismPlayer')
const auctionData=ref({})
const socket=ref(null)
const config = useRuntimeConfig()
const pullLink=ref('')
const isMinWindow = ref(false)
const lastSnapshot = ref('')
const liveInfo = ref(null)
// 设置最小化状态
const setMinWindow = (status) => {
isMinWindow.value = status
}
// 设置截图
const setSnapshot = (snapshot) => {
lastSnapshot.value = snapshot
}
// 设置直播信息
const setLiveInfo = (info) => {
liveInfo.value = info
}
// 重置状态
const reset = () => {
isMinWindow.value = false
lastSnapshot.value = ''
liveInfo.value = null
}
// 解密工具函数
const decryptUtils = {
// 解密配置
cryptConfig: {
password: 'live-skkoql-1239-key',
salt: 'aldk100128ls',
iterations: 10000,
keySize: 32
},
// 生成密钥
generateKey(password, salt, iterations, keySize) {
return CryptoJS.PBKDF2(password, salt, {
keySize: keySize / 4,
iterations: iterations,
hasher: CryptoJS.algo.SHA1
}).toString(CryptoJS.enc.Hex)
},
// AES解密
decrypt(ciphertextBase64, key) {
const combined = CryptoJS.enc.Base64.parse(ciphertextBase64)
const iv = CryptoJS.lib.WordArray.create(combined.words.slice(0, 4))
const ciphertext = CryptoJS.lib.WordArray.create(combined.words.slice(4))
const decrypted = CryptoJS.AES.decrypt(
{ciphertext: ciphertext},
CryptoJS.enc.Hex.parse(key),
{
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}
)
return decrypted.toString(CryptoJS.enc.Utf8)
},
// 解密数据的主函数
decryptData(encryptedData) {
const keyDerived = this.generateKey(
this.cryptConfig.password,
this.cryptConfig.salt,
this.cryptConfig.iterations,
this.cryptConfig.keySize
)
return this.decrypt(encryptedData, keyDerived)
}
}
const getLiveLink = () => {
return new Promise(async(resolve, reject) => {
const res = await logSendlog({
uuid: auctionDetail.value.uuid
})
if (res.status===0){
pullLink.value=decryptUtils.decryptData(res.data.code)
resolve(decryptUtils.decryptData(res.data.code))
}
})
}
const getSocketData = async () => {
const wsClient = new WebSocketClient(
config.public.NUXT_PUBLIC_SOCKET_URL,
token.value
)
const ws = wsClient.connect('/api/v1/m/auction/live', {
auctionUuid: auctionDetail.value.uuid,
})
ws.onOpen(() => {
console.log('WebSocket connected')
})
ws.onMessage((data) => {
auctionData.value = data.data
if (data.data?.wsType === 'tip' ) {
if (data.data?.tip?.tipType === 'falling'){
message.warning({
title: {
text: '即将落槌',
color: '#F09F1F',
align: 'center',
},
style: {
width: '151px',
bottom: '230px',
},
})
}else if (data.data?.tip?.tipType === 'othersBid'){
message.error({
title: {
text: '已有人出价',
color: '#CF3050',
align: 'center',
},
icon:false,
subTitle:{
text:'更新后再出价',
color: '#939393',
align: 'center',
},
style: {
width: '151px',
bottom: '230px'
},
})
}else if (data.data?.tip?.tipType === 'successBid'){
message.success({
title: {
text: '恭喜您,竞拍成功',
color: '#18A058',
align: 'center',
},
icon:false,
subTitle:{
text:'请缴款',
color: '#939393',
align: 'center',
},
style: {
width: '151px',
bottom: '230px'
},
})
}else if (data.data?.tip?.tipType === 'artworkOver'){
message.success({
title: {
text: '本拍品已结束',
color: '#575757',
align: 'center',
},
icon:false,
subTitle:{
text:'请期待下个拍品',
color: '#939393',
align: 'center',
},
style: {
width: '151px',
bottom: '230px',
backgroundColor: '#fff',
borderColor:'#fff'
},
})
}else if (data.data?.tip?.tipType === 'failBid'){
message.error({
title: {
text: '很遗憾,竞拍失败',
color: '#CF3050',
align: 'center',
},
icon:false,
subTitle:{
text:'竞拍结束',
color: '#939393',
align: 'center',
},
style: {
width: '186px',
bottom: '230px'
},
})
}
}else if (data.data?.wsType==='stopArtwor'){
quoteStatus.value=false
}else if (data.data?.wsType==='over'){
message.success({
title: {
text: '竞拍结束,谢谢参与',
color: '#575757',
align: 'center',
},
icon:false,
style: {
width: '195px',
bottom: '230px',
backgroundColor: '#fff',
borderColor:'#fff'
},
})
}
console.log('onmessage', data)
})
ws.onClose(() => {
console.log('WebSocket disconnected')
})
ws.onError((error) => {
console.error('WebSocket error:', error)
})
}
const changeStatus = () => {
if (auctionData.value.artwork.isSelling&&!auctionData.value.artwork.isSoled){
quoteStatus.value = true
}else {
if (quoteStatus.value){
quoteStatus.value = false
}
}
}
return{
fullLive,
isMinWindow,
lastSnapshot,
liveInfo,
setMinWindow,
setSnapshot,
setLiveInfo,
reset,
pullLink,
getLiveLink,
auctionData,
getSocketData,
show1,
playerId,
show,
quoteStatus,
changeStatus
}
})