Compare commits

..

5 Commits

Author SHA1 Message Date
xingyy
65f8d2d1e9 feat(websocket): 实现 WebSocket通信功能
- 新增 useWebSocket 组合式函数,用于在组件中使用 WebSocket
- 添加 WebSocket 插件,提供全局 WebSocket 实例和相关方法
- 实现了连接、重连、发送消息、关闭连接等功能
- 通过自定义事件实现消息广播,供组件监听
2025-01-23 16:37:11 +08:00
xingyy
e2b5e6bcbf feat(env): 添加 websocket URL 并更新直播室相关功能
- 在 .env.test 中添加 NUXT_PUBLIC_SOCKET_URL 配置项
- 在直播室页面中实现 websocket连接和消息监听
-优化拍卖详情获取逻辑
- 更新首页和详情页相关组件
2025-01-23 16:34:34 +08:00
xingyy
9f9e96dc0c feat(home): 获取拍卖详情并优化首页组件
- 在 home 页面中调用 getAuctionDetail 方法获取拍卖详情
- 更新 Cescribe组件以显示拍卖详情信息和图片
- 在 ItemList 组件中添加 v-memo 指令以优化性能
- 调整 liveRoom 组件中的视频播放器样式
2025-01-23 15:43:48 +08:00
xingyy
2d909b276b perf(components): 添加 v-memo指令以优化性能
- 在 AppFooter 组件中,为最外层 div 添加 v-memo="[active]" 指令- 在 AppHeader 组件中,为 VanNavBar 组件添加 v-memo="[title, fullLive, showLeftArrow, subTitle]" 指令
- 移除了 AppHeader 组件中的 console.log 语句
2025-01-23 15:28:31 +08:00
xingyy
a6a5c20705 refactor(app): 移除颜色模式相关代码
- 删除了 app.vue 中的颜色模式相关代码
- 移除了 nuxt.config.js 中的 colorMode 配置
- 删除了 package.json 中的 @nuxtjs/color-mode 依赖
- 移除了 unocss 示例页面
- 注释掉了 liveRoom 页面中的视频播放代码
2025-01-23 15:24:49 +08:00
17 changed files with 1093 additions and 1330 deletions

View File

@ -9,10 +9,7 @@ useHead({
{name: 'keywords', content: useI18n().t('appSetting.appKeyWords')},
],
})
const color = useColorMode()
const mode = computed(() => {
return color.value
})
//
const router = useRouter()
@ -42,7 +39,7 @@ provide('slideDirection', slideDirection)
</script>
<template>
<VanConfigProvider :theme="mode">
<VanConfigProvider>
<NuxtLoadingIndicator
color="repeating-linear-gradient(to right,var(--c-primary) 0%,var(--c-primary-active) 100%)"/>
<NuxtLayout>

View File

@ -18,7 +18,7 @@ onMounted(()=>{
</script>
<template>
<div v-if="show">
<div v-if="show" v-memo="[active]" >
<van-tabbar v-model="active" route placeholder fixed>
<van-tabbar-item replace to="/">
<span>{{ $t('tabbar.home') }}</span>

View File

@ -30,13 +30,12 @@ const subTitle = computed(() => {
return route.meta.subTitle ? t(route.meta.subTitle) : ''
})
const showLeftArrow = computed(() => route.name && routeWhiteList.includes(route.name))
console.log('route.meta.i18n',route.meta.i18n)
console.log('t(route.meta.i18n)',route.meta.i18n)
console.log('route.meta.title',route.meta.title)
</script>
<template>
<VanNavBar
v-memo="[title,fullLive,showLeftArrow,subTitle]"
:title="title"
:left-arrow="!showLeftArrow||fullLive"
placeholder clickable fixed

View File

@ -43,8 +43,8 @@ const props = defineProps({
</div>
<div class="px-[16px] bg-#fff pt-12px pb-18px">
<div class="text-[#575757] text-[14px] mb-4px">竞价表</div>
<div>
<img src="@/static/images/1981736313.png" alt="">
<div v-if="detailInfo?.priceRuleType!=='diy'">
<xImage :src="detailInfo?.priceRuleImage" alt=""/>
</div>
</div>
</div>

View File

@ -1,6 +1,5 @@
<script setup>
import { showImagePreview } from 'vant';
import { NuxtImg } from '#components'
const props = defineProps({
src: {
type: String,
@ -35,7 +34,9 @@ const showImage = () => {
</script>
<template>
<nuxt-img
v-if="src"
loading="lazy"
v-bind="{ ...props, ...$attrs }"
style="object-fit: cover"
@ -46,6 +47,7 @@ const showImage = () => {
:quality="quality"
placeholder
/>
<van-empty v-else description="暂无" />
</template>
<style scoped>

View File

@ -0,0 +1,21 @@
export function useWebSocket() {
const { $ws } = useNuxtApp()
const messages = ref<any[]>([])
// 监听消息
const onMessage = (callback: (data: any) => void) => {
const handler = (event: CustomEvent) => callback(event.detail)
window.addEventListener('ws-message', handler as EventListener)
// 返回清理函数
return () => {
window.removeEventListener('ws-message', handler as EventListener)
}
}
return {
ws: $ws,
messages,
onMessage
}
}

View File

@ -1,12 +1,16 @@
<script setup>
import {goodStore} from "~/stores/goods/index.js";
import xImage from '@/components/x-image/index.vue'
const {
auctionDetail
} = goodStore()
</script>
<template>
<div class="px-16px pt-14px">
<div class="text-#575757 text-14px">
这里是后台富文本配置的说明啊即可打开三等奖撒度老师的湿答答是快乐的阿四大皆空
<div class="text-#575757 text-14px" v-html="auctionDetail.info">
</div>
<xImage :src="auctionDetail.image" class="w-343px"></xImage>
</div>
</template>

View File

@ -57,7 +57,7 @@ const openShow = async (item) => {
@refresh="onRefresh"
>
<template #success>
<van-icon name="success" /> 刷新成功
<van-icon name="success" /> <span>刷新成功</span>
</template>
<van-list
v-model:loading="storeLoading"
@ -65,7 +65,7 @@ const openShow = async (item) => {
finished-text="没有更多了"
@load="loadMore"
>
<div class="w-full flex gap-[16px]">
<div class="w-full flex gap-[16px]" v-memo="[itemList]">
<masonry-wall :items="itemList" :ssr-columns="2" :maxColumns="2" :minColumns="2" :gap="5">
<template #default="{ item, index }">
<div

View File

@ -3,15 +3,18 @@ import liveRoom from '@/pages/liveRoom/index.client.vue';
import {goodStore} from "@/stores/goods/index.js";
import ItemList from './components/ItemList/index.vue'
import Cescribe from './components/Cescribe/index.vue'
const {fullLive, liveRef} = goodStore();
const {fullLive,getAuctionDetail,auctionDetail} = goodStore();
const changeLive = () => {
fullLive.value = true;
};
if (!auctionDetail.value.uuid){
await getAuctionDetail()
}
</script>
<template>
<div class="flex-grow-1">
<client-only>
<liveRoom @click="changeLive" :class="['changeLive', fullLive ? 'expanded' : 'collapsed']" ref="liveRef"
<liveRoom @click="changeLive" :class="['changeLive', fullLive ? 'expanded' : 'collapsed']"
:fullLive="fullLive"/>
</client-only>
<div v-show="!fullLive" class="bg-#fff">

View File

@ -8,6 +8,10 @@ import {liveStore} from "~/stores/live/index.js";
import paymentResults from '~/pages/liveRoom/components/PaymentResults/index.vue'
import paymentInput from '~/pages/liveRoom/components/PaymentInput/index.vue'
import xButton from '@/components/x-button/index.vue'
import {goodStore} from "~/stores/goods/index.js";
import {authStore} from "~/stores/auth/index.js";
const {auctionDetail,getAuctionDetail} = goodStore();
const { token } = authStore()
const player = ref(null)
const {quoteStatus, changeStatus, show, playerId, show1} = liveStore()
const isPlayerReady = ref(false)
@ -57,8 +61,23 @@ const initializePlayer = () => {
}
onMounted(() => {
onMounted(async () => {
if (!auctionDetail.value.uuid){
await getAuctionDetail()
}
/* initializePlayer()*/
const { ws, messages, onMessage } = useWebSocket()
//
ws.connect('/api/v1/m/auction/live',{auctionUuid: auctionDetail.value.uuid,token:token.value})
/*// 发送消息
ws.send({ type: 'chat', content: 'Hello!' })*/
//
onMessage((data) => {
console.log('收到消息:', data)
})
})
onBeforeUnmount(() => {
if (player.value) {

View File

@ -1,22 +0,0 @@
<script setup lang="ts">
definePageMeta({
title: '🎨 Unocss 示例',
i18n: 'menu.unocssExample',
})
</script>
<template>
<div>
<h1 class="text-6xl color-pink font-semibold">
{{ $t('unocss_page.hello', ['Unocss!']) }}
</h1>
<p class="mt-10 text-gray-700 dark:text-white">
{{ $t('unocss_page.desc') }}
</p>
<button class="mt-10 btn">
{{ $t('unocss_page.btn_txt') }}
</button>
</div>
</template>

86
app/plugins/websocket.ts Normal file
View File

@ -0,0 +1,86 @@
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig()
const ws = reactive({
instance: null as WebSocket | null,
isConnected: false,
// 修改 connect 方法接收路径和数据对象
connect(path: string, data?: Record<string, any>) {
if (this.instance?.readyState === WebSocket.OPEN) {
this.instance.close()
}
// 构建查询字符串
const queryString = data
? '?' + Object.entries(data)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&')
: ''
// 构建完整的 WebSocket URL
const wsUrl = `${config.public.NUXT_PUBLIC_SOCKET_URL}${path}${queryString}`
this.instance = new WebSocket(wsUrl)
this.instance.onopen = () => {
this.isConnected = true
console.log('WebSocket 已连接')
}
this.instance.onclose = () => {
this.isConnected = false
console.log('WebSocket 已断开')
/* this.reconnect(path, data)*/
}
this.instance.onerror = (error) => {
console.error('WebSocket 错误:', error)
}
this.instance.onmessage = (event) => {
try {
const data = JSON.parse(event.data)
this.handleMessage(data)
} catch (error) {
console.error('消息解析错误:', error)
}
}
},
// 更新重连方法以支持数据对象
reconnect(path: string, data?: Record<string, any>) {
setTimeout(() => {
console.log('尝试重新连接...')
this.connect(path, data)
}, 3000)
},
// 发送消息
send(data: any) {
if (this.instance?.readyState === WebSocket.OPEN) {
this.instance.send(JSON.stringify(data))
} else {
console.warn('WebSocket 未连接,无法发送消息')
}
},
// 关闭连接
disconnect() {
if (this.instance) {
this.instance.close()
this.instance = null
}
},
// 消息处理
handleMessage(data: any) {
// 触发自定义事件,让组件可以监听
window.dispatchEvent(new CustomEvent('ws-message', { detail: data }))
}
})
return {
provide: {
ws
}
}
})

View File

@ -6,7 +6,6 @@ export const goodStore = createGlobalState(() => {
// 状态定义
const actionDetails = ref({})
const fullLive = ref(false)
const liveRef = ref(null)
const currentItem = ref({})
const myArtWorks = ref([])
const pageRef = ref({
@ -97,7 +96,7 @@ export const goodStore = createGlobalState(() => {
// 状态
actionDetails,
fullLive,
liveRef,
currentItem,
myArtWorks,
pageRef,

2
env/.env.test vendored
View File

@ -2,6 +2,6 @@
NUXT_PUBLIC_API_BASE=http://172.16.100.99:8005
NUXT_PUBLIC_WS_URL=ws://test-ws.example.com
NUXT_API_SECRET=test-secret
NUXT_PUBLIC_SOCKET_URL=ws://172.16.100.99:8005
# 阿里云播放器配置
NUXT_PUBLIC_PLAYER_SOURCE=artc://live-pull-sh-01.szjixun.cn/live/live?auth_key=1737080180-0-0-42ad4cf26ba26eee78ca7de9c524d1e0

View File

@ -12,21 +12,18 @@ const publicConfig = Object.entries(process.env)
}, {})
export default defineNuxtConfig({
modules: [
'@vant/nuxt',
'@unocss/nuxt',
'@nuxt/image',
'@nuxtjs/color-mode',
'@nuxtjs/i18n',
],
runtimeConfig: {
// 私有配置,只有在服务端可用
apiSecret: process.env.NUXT_API_SECRET || 'default_secret',
apiSecret: process.env.NUXT_API_SECRET,
// 公共配置,客户端和服务端都可用
public: publicConfig,
},
css: [
'@unocss/reset/tailwind.css',
'@/static/styles/default-theme.css',
@ -51,14 +48,6 @@ export default defineNuxtConfig({
},
},
},
colorMode: {
classSuffix: '',
preference: 'system',
fallback: 'light',
storageKey: 'nuxt-color-mode',
},
i18n: {
locales: currentLocales,
lazy: true,

View File

@ -18,7 +18,6 @@
},
"dependencies": {
"@fingerprintjs/fingerprintjs": "^4.5.1",
"@nuxtjs/color-mode": "^3.5.2",
"@nuxtjs/i18n": "^9.1.1",
"@vueuse/core": "^12.4.0",
"@yeger/vue-masonry-wall": "^5.0.17",

File diff suppressed because it is too large Load Diff