2025-02-17 11:54:11 +00:00
|
|
|
import {createGlobalState, useLocalStorage} from '@vueuse/core'
|
2025-01-15 08:10:28 +00:00
|
|
|
import {ref} from "vue";
|
2025-01-23 11:29:29 +00:00
|
|
|
import {goodStore} from "@/stores/goods/index.js";
|
|
|
|
import {authStore} from "@/stores/auth/index.js";
|
2025-02-08 02:06:21 +00:00
|
|
|
import {message} from "~/components/x-message/useMessage.js";
|
2025-02-08 07:21:00 +00:00
|
|
|
import { WebSocketClient } from '@/utils/websocket'
|
2025-02-11 03:34:24 +00:00
|
|
|
import {logSendlog} from "~/api/goods/index.js";
|
|
|
|
import CryptoJS from "crypto-js";
|
2025-02-12 08:50:52 +00:00
|
|
|
import {useI18n} from 'vue-i18n'
|
2025-01-15 08:10:28 +00:00
|
|
|
export const liveStore = createGlobalState(() => {
|
2025-02-11 03:34:24 +00:00
|
|
|
const {auctionDetail} = goodStore();
|
2025-02-08 07:21:00 +00:00
|
|
|
const { token } = authStore()
|
2025-02-12 08:50:52 +00:00
|
|
|
const t=useI18n().t
|
2025-02-11 07:27:31 +00:00
|
|
|
const fullLive = ref(false)
|
2025-01-15 08:10:28 +00:00
|
|
|
const quoteStatus = ref(false)
|
2025-01-16 03:23:46 +00:00
|
|
|
const show = ref(false)
|
2025-02-08 02:06:21 +00:00
|
|
|
const cleanup = ref(null)
|
2025-02-08 07:21:00 +00:00
|
|
|
const show1=ref(false)
|
2025-01-16 03:07:38 +00:00
|
|
|
const playerId=ref('J_prismPlayer')
|
2025-02-17 11:54:11 +00:00
|
|
|
const auctionData=useLocalStorage('auctionData',{})
|
2025-02-08 07:21:00 +00:00
|
|
|
const socket=ref(null)
|
|
|
|
const config = useRuntimeConfig()
|
2025-02-11 03:34:24 +00:00
|
|
|
const pullLink=ref('')
|
2025-02-11 06:55:25 +00:00
|
|
|
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
|
|
|
|
}
|
2025-02-11 03:34:24 +00:00
|
|
|
// 解密工具函数
|
|
|
|
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))
|
|
|
|
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2025-02-14 07:01:20 +00:00
|
|
|
// 定义常量
|
|
|
|
const WS_TYPES = {
|
|
|
|
TIP: 'tip',
|
2025-02-19 13:03:54 +00:00
|
|
|
STOP_ARTWORK: 'stopArtwork',
|
2025-03-03 06:33:59 +00:00
|
|
|
OVER: 'over',
|
|
|
|
CHANGEPRICEINFO : 'changePriceInfo'
|
2025-02-14 07:01:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const TIP_TYPES = {
|
|
|
|
FALLING: 'falling',
|
|
|
|
OTHERS_BID: 'othersBid',
|
|
|
|
SUCCESS_BID: 'successBid',
|
|
|
|
ARTWORK_OVER: 'artworkOver',
|
|
|
|
FAIL_BID: 'failBid'
|
|
|
|
}
|
|
|
|
|
|
|
|
// 基础消息配置
|
|
|
|
const BASE_MESSAGE_STYLE = {
|
|
|
|
width: '151px',
|
|
|
|
bottom: '265px'
|
|
|
|
}
|
|
|
|
const createMessageConfig = (text, color, subText = '', extraStyle = {}) => ({
|
|
|
|
title: {
|
|
|
|
text,
|
|
|
|
color,
|
|
|
|
align: 'center'
|
|
|
|
},
|
|
|
|
icon: false,
|
|
|
|
...(subText && {
|
|
|
|
subTitle: {
|
|
|
|
text: subText,
|
|
|
|
color: '#939393',
|
|
|
|
align: 'center'
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
style: {
|
|
|
|
...BASE_MESSAGE_STYLE,
|
|
|
|
...extraStyle
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2025-02-08 02:06:21 +00:00
|
|
|
const getSocketData = async () => {
|
2025-02-08 07:21:00 +00:00
|
|
|
const wsClient = new WebSocketClient(
|
|
|
|
config.public.NUXT_PUBLIC_SOCKET_URL,
|
|
|
|
token.value
|
|
|
|
)
|
|
|
|
const ws = wsClient.connect('/api/v1/m/auction/live', {
|
2025-02-08 02:06:21 +00:00
|
|
|
auctionUuid: auctionDetail.value.uuid,
|
2025-02-08 07:21:00 +00:00
|
|
|
})
|
2025-01-23 11:29:29 +00:00
|
|
|
|
2025-02-14 07:01:20 +00:00
|
|
|
// 处理消息提示
|
|
|
|
const handleTipMessage = (tipType) => {
|
|
|
|
const tipConfigs = {
|
|
|
|
[TIP_TYPES.FALLING]: () =>
|
|
|
|
message.warning(createMessageConfig(t('live_room.text1'), '#F09F1F')),
|
|
|
|
|
|
|
|
[TIP_TYPES.OTHERS_BID]: () =>
|
|
|
|
message.error(createMessageConfig(t('live_room.text2'), '#CF3050', t('live_room.text3'))),
|
|
|
|
|
2025-02-26 03:11:29 +00:00
|
|
|
[TIP_TYPES.SUCCESS_BID]: ()=>{
|
|
|
|
quoteStatus.value=false
|
|
|
|
message.success(createMessageConfig(t('live_room.text4'), '#18A058', t('live_room.text5')))
|
|
|
|
},
|
|
|
|
[TIP_TYPES.ARTWORK_OVER]: () =>{
|
|
|
|
quoteStatus.value=false
|
2025-02-14 07:01:20 +00:00
|
|
|
message.success(createMessageConfig(
|
|
|
|
t('live_room.text6'),
|
|
|
|
'#575757',
|
|
|
|
t('live_room.text7'),
|
|
|
|
{ backgroundColor: '#fff', borderColor: '#fff' }
|
2025-02-26 03:11:29 +00:00
|
|
|
))
|
|
|
|
},
|
|
|
|
|
2025-02-14 07:01:20 +00:00
|
|
|
|
|
|
|
[TIP_TYPES.FAIL_BID]: () =>
|
|
|
|
message.error(createMessageConfig(
|
|
|
|
t('live_room.text8'),
|
|
|
|
'#CF3050',
|
|
|
|
t('live_room.text9'),
|
|
|
|
{ width: '186px' }
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
|
|
|
const handler = tipConfigs[tipType]
|
|
|
|
if (handler) handler()
|
|
|
|
}
|
|
|
|
|
|
|
|
// WebSocket 事件处理
|
2025-02-08 07:21:00 +00:00
|
|
|
ws.onOpen(() => {
|
2025-03-02 03:09:06 +00:00
|
|
|
})
|
2025-02-08 07:21:00 +00:00
|
|
|
|
|
|
|
ws.onMessage((data) => {
|
2025-02-06 07:43:23 +00:00
|
|
|
auctionData.value = data.data
|
2025-02-14 07:01:20 +00:00
|
|
|
const { wsType, tip } = data.data || {}
|
2025-02-10 07:47:26 +00:00
|
|
|
|
2025-02-14 07:01:20 +00:00
|
|
|
switch (wsType) {
|
|
|
|
case WS_TYPES.TIP:
|
|
|
|
handleTipMessage(tip?.tipType)
|
|
|
|
break
|
|
|
|
case WS_TYPES.STOP_ARTWORK:
|
2025-02-25 02:02:20 +00:00
|
|
|
//quoteStatus.value = false
|
2025-02-14 07:01:20 +00:00
|
|
|
break
|
|
|
|
case WS_TYPES.OVER:
|
2025-02-26 06:47:55 +00:00
|
|
|
|
2025-02-25 02:02:20 +00:00
|
|
|
quoteStatus.value = false
|
2025-02-14 07:01:20 +00:00
|
|
|
message.success(createMessageConfig(
|
|
|
|
t('live_room.text10'),
|
|
|
|
'#575757',
|
|
|
|
'',
|
|
|
|
{
|
|
|
|
width: '195px',
|
2025-02-10 07:47:26 +00:00
|
|
|
backgroundColor: '#fff',
|
2025-02-14 07:01:20 +00:00
|
|
|
borderColor: '#fff'
|
|
|
|
}
|
|
|
|
))
|
|
|
|
break
|
2025-03-03 06:56:04 +00:00
|
|
|
case WS_TYPES.CHANGEPRICEINFO:
|
|
|
|
message.warning(t('live_room.text11'))
|
|
|
|
break
|
2025-02-08 02:06:21 +00:00
|
|
|
}
|
2025-02-08 07:21:00 +00:00
|
|
|
|
2025-03-02 03:09:06 +00:00
|
|
|
})
|
2025-02-08 07:21:00 +00:00
|
|
|
|
|
|
|
ws.onClose(() => {
|
2025-03-02 03:09:06 +00:00
|
|
|
})
|
2025-02-08 07:21:00 +00:00
|
|
|
|
|
|
|
ws.onError((error) => {
|
2025-03-02 03:09:06 +00:00
|
|
|
})
|
2025-01-23 11:29:29 +00:00
|
|
|
}
|
2025-01-15 08:10:28 +00:00
|
|
|
const changeStatus = () => {
|
2025-02-19 07:14:01 +00:00
|
|
|
if (auctionData.value.artwork?.isSelling&&!auctionData.value.artwork.isSoled){
|
2025-02-17 07:18:55 +00:00
|
|
|
quoteStatus.value = !quoteStatus.value
|
2025-02-08 02:06:21 +00:00
|
|
|
}else {
|
|
|
|
if (quoteStatus.value){
|
|
|
|
quoteStatus.value = false
|
|
|
|
}
|
|
|
|
}
|
2025-03-02 03:09:06 +00:00
|
|
|
}
|
2025-01-15 08:10:28 +00:00
|
|
|
return{
|
2025-02-11 07:27:31 +00:00
|
|
|
fullLive,
|
2025-02-11 06:55:25 +00:00
|
|
|
isMinWindow,
|
|
|
|
lastSnapshot,
|
|
|
|
liveInfo,
|
|
|
|
setMinWindow,
|
|
|
|
setSnapshot,
|
|
|
|
setLiveInfo,
|
|
|
|
reset,
|
2025-02-11 03:34:24 +00:00
|
|
|
pullLink,
|
|
|
|
getLiveLink,
|
2025-01-23 11:29:29 +00:00
|
|
|
auctionData,
|
|
|
|
getSocketData,
|
2025-01-16 03:07:38 +00:00
|
|
|
show1,
|
|
|
|
playerId,
|
2025-01-15 08:10:28 +00:00
|
|
|
show,
|
|
|
|
quoteStatus,
|
|
|
|
changeStatus
|
|
|
|
}
|
|
|
|
})
|