Compare commits

..

9 Commits

Author SHA1 Message Date
xingyy
dee871759e feat(goods): 获取用户艺术品并优化首页布局
- 在 goods API 中添加 userArtworks 函数- 更新 auth store,将 userInfo 默认值改为对象
- 优化 LiveRoom 页面布局,添加安全区域支持
- 修改 AppFooter 组件,修复路由判断逻辑
- 更新首页 Column 组件,调整图片显示样式
- 在 Profile 页面添加用户信息展示
2025-01-21 14:16:54 +08:00
xingyy
e23fed8c74 perf(layout): 使用 keep-alive优化页面性能
- 在 default.vue 文件中添加 keep-alive 组件,以提高页面渲染效率
- 此修改可以保留页面状态,减少重复渲染,提升用户体验
2025-01-21 12:00:40 +08:00
xingyy
f3d5a3440c refactor(login): 调整登录页面验证码功能
- 启用验证码发送功能
- 注释掉模拟数据发送代码
-优化代码结构,提高可读性
2025-01-21 11:46:47 +08:00
xingyy
7a968f1fe6 feat(api): 添加 401 状态码处理逻辑
- 在 http.js 中添加了对 401 状态码的处理,重定向到登录页面
- 更新了 LiveRoom 组件,暂时注释掉了 initializePlayer 方法
- 在 goods store 中添加了 currentItem 和 artWorkDetail 两个状态
- 更新了 message 组件,添加了对错误信息的处理
-调整了首页布局,移除了多余的 transition 标签
- 更新了登录页面的默认验证码
2025-01-21 11:43:27 +08:00
xingyy
1b996eafca feat(api): 新增 artworkDetail接口并更新相关页面
- 在 goods API 中添加 artworkDetail函数,用于获取艺术品详情
- 在首页的 ItemList 组件中调用 artworkDetail 获取详情信息- 移除首页中未使用的 useRect 和 itemDetail 组件
2025-01-20 16:57:22 +08:00
xingyy
bad45f8d82 refactor(goods): 重构商品相关功能
- 修改测试环境配置
- 重命名 homeStore为 goodStore
- 优化直播房间组件导入路径
- 重构商品列表和详情功能
- 新增 ItemList 组件
-调整首页布局和功能
2025-01-20 16:17:49 +08:00
xingyy
efc47a27fd refactor(app): 优化登录功能并添加新组件
- 在 Column 组件中使用可选链操作符,提高代码健壮性- 添加 ItemList 组件,但未提供具体实现
- 在 login 组件中:
  - 引入消息提示功能
  -优化登录流程,添加 loading 状态
  - 修复登录后的页面跳转
  - 为登录按钮添加 loading 状态和文本
2025-01-20 13:59:50 +08:00
xingyy
bda4666782 fix(home): 修复首页拍卖商品成交价显示错误
- 将显示成交价的字段从 transactionPrice 改为 soldPrice
-修复了成交价显示逻辑,确保正确展示拍卖商品的最终成交价格
2025-01-20 11:46:01 +08:00
xingyy
0f92a99b32 feat(home): 更新首页布局和数据获取逻辑
- 移除多余的组件和模板代码
- 新增拍卖详情和艺术品列表获取功能- 优化首页数据展示和布局结构
- 调整登录页面样式和逻辑
2025-01-20 11:42:25 +08:00
23 changed files with 268 additions and 351 deletions

View File

@ -13,4 +13,18 @@ export async function defaultDetail(data) {
method: 'POST', method: 'POST',
body: data, body: data,
}) })
}
export async function artworkDetail(data) {
const http = getHttp()
return await http('/api/v1/m/artwork/detail', {
method: 'POST',
body: data,
})
}
export async function userArtworks(data) {
const http = getHttp()
return await http('/api/v1/m/user/artworks', {
method: 'POST',
body: data,
})
} }

View File

@ -14,6 +14,7 @@ export function setupHttp() {
const config = useRuntimeConfig() const config = useRuntimeConfig()
const baseURL = config.public.NUXT_PUBLIC_API_BASE const baseURL = config.public.NUXT_PUBLIC_API_BASE
const {token}= authStore() const {token}= authStore()
const router = useRouter()
http = ofetch.create({ http = ofetch.create({
baseURL, baseURL,
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
@ -27,6 +28,9 @@ export function setupHttp() {
if (response._data.status===1){ if (response._data.status===1){
message.error(response._data.msg) message.error(response._data.msg)
} }
if (response._data.status===401){
router.replace('/login')
}
}, },
async onResponseError({ response }) { async onResponseError({ response }) {
const { message } = response._data const { message } = response._data

View File

@ -78,4 +78,7 @@ provide('slideDirection', slideDirection)
.slide-right-leave-to { .slide-right-leave-to {
transform: translateX(100%); transform: translateX(100%);
} }
:root{
--safe-area-inset-bottom: env(safe-area-inset-bottom);
}
</style> </style>

View File

@ -11,13 +11,17 @@ const show = computed(() => {
return false return false
}) })
const initData=()=>{ const initData=()=>{
active.value=route.path==='/'?0:1 active.value=route.path==='/profile'?1:0
} }
initData()
onMounted(()=>{
initData()
})
</script> </script>
<template> <template>
<div v-if="show"> <div v-if="show">
<van-tabbar v-model="active" route placeholder fixed> <van-tabbar v-model="active" route placeholder fixed>
<van-tabbar-item replace to="/"> <van-tabbar-item replace to="/">
<span>{{ $t('tabbar.home') }}</span> <span>{{ $t('tabbar.home') }}</span>

View File

@ -1,7 +1,7 @@
<script setup> <script setup>
import { useAppHeaderRouteNames as routeWhiteList } from '~/config' import { useAppHeaderRouteNames as routeWhiteList } from '~/config'
import { homeStore } from "@/stores/goods/index.js"; import { goodStore } from "@/stores/goods/index.js";
const { fullLive } = homeStore() const { fullLive } = goodStore()
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()

View File

@ -1,4 +1,5 @@
<script setup> <script setup>
import error from '../images/error.png' import error from '../images/error.png'
import success from '../images/success.png' import success from '../images/success.png'
import warning from '../images/warning.png' import warning from '../images/warning.png'

View File

@ -2,12 +2,14 @@
<main class="flex flex-col min-h-svh"> <main class="flex flex-col min-h-svh">
<AppHeader class="h-[var(--van-nav-bar-height)]" /> <AppHeader class="h-[var(--van-nav-bar-height)]" />
<div class="flex-1 flex flex-col"> <div class="flex-1 flex flex-col">
<slot /> <keep-alive>
<slot />
</keep-alive>
</div> </div>
<AppFooter /> <AppFooter />
</main> </main>
</template> </template>
<script setup > <script setup >
import { homeStore } from "@/stores/goods/index.js"; import { goodStore } from "@/stores/goods/index.js";
const { fullLive } = homeStore() const { fullLive } = goodStore()
</script> </script>

View File

@ -11,7 +11,6 @@ const list = ref([
} }
]); ]);
// ID
let intervalId = null; let intervalId = null;
const addItem = () => { const addItem = () => {
@ -32,7 +31,7 @@ const scrollToBottom = () => {
if (container) { if (container) {
setTimeout(() => { setTimeout(() => {
container.scrollTop = container.scrollHeight; container.scrollTop = container.scrollHeight;
}, 100); // }, 100);
} }
}; };

View File

@ -2,12 +2,12 @@
import {ref, onMounted, onBeforeUnmount} from 'vue' import {ref, onMounted, onBeforeUnmount} from 'vue'
import Aliplayer from 'aliyun-aliplayer' import Aliplayer from 'aliyun-aliplayer'
import 'aliyun-aliplayer/build/skins/default/aliplayer-min.css' import 'aliyun-aliplayer/build/skins/default/aliplayer-min.css'
import sideButton from './components/sideButton/index.vue' import sideButton from '~/pages/LiveRoom/components/SideButton/index.vue'
import broadcast from './components/broadcast/index.vue' import broadcast from '~/pages/LiveRoom/components/Broadcast/index.vue'
import {liveStore} from "~/stores/live/index.js"; import {liveStore} from "~/stores/live/index.js";
import paymentResults from './components/paymentResults/index.vue' import paymentResults from '~/pages/LiveRoom/components/PaymentResults/index.vue'
import paymentInput from './components/paymentInput/index.vue' import paymentInput from '~/pages/LiveRoom/components/PaymentInput/index.vue'
import PressableButton from './components/sideButton/PressableButton.vue' import PressableButton from '~/pages/LiveRoom/components/SideButton/PressableButton.vue'
const player = ref(null) const player = ref(null)
const {quoteStatus, changeStatus, show, playerId, show1} = liveStore() const {quoteStatus, changeStatus, show, playerId, show1} = liveStore()
@ -59,7 +59,7 @@ const initializePlayer = () => {
onMounted(() => { onMounted(() => {
initializePlayer() /* initializePlayer()*/
}) })
onBeforeUnmount(() => { onBeforeUnmount(() => {
if (player.value) { if (player.value) {
@ -74,32 +74,48 @@ const goPay = () => {
<template> <template>
<div class="relative h-full"> <div class="relative h-full">
<div :id="playerId" class="w-screen" <div class="w-full h-full">
:style="fullLive?'height: calc(100vh - var(--van-nav-bar-height))':'height:100%'"></div> <video
<template v-if="fullLive"> class="h-full w-full"
<sideButton class="absolute top-196px right-0 z-999"></sideButton> autoplay
<div class="absolute top-505px left-1/2 transform -translate-x-1/2 flex flex-col items-center"> loop
<div class="text-16px text-#FFB25F font-600"> muted
当前价RMB playsinline
<van-rolling-text class="my-rolling-text" :start-num="0" :target-num="3000" direction="up"/> style=" object-fit: cover"
</div> >
<div class="text-16px text-#fff font-600"> <source src="@/static/video/example.mp4" type="video/mp4" />
下口价RMB 您的浏览器不支持 HTML5 视频
<van-rolling-text class="my-rolling-text1" :start-num="0" :target-num="3500" direction="up"/> </video>
</div> </div>
<PressableButton> <!-- <div :id="playerId" class="w-screen"
<div :style="fullLive?'height: calc(100vh - var(&#45;&#45;van-nav-bar-height))':'height:100%'"></div>-->
:class="`w-344px h-[40px] ${quoteStatus ? 'bg-#FFB25F' : 'bg-#D6D6D8'} rounded-4px ${quoteStatus ? 'text-#fff' : 'text-#7D7D7F'} text-14px flex justify-center items-center mt-10px mb-10px`"> <transition>
{{ quoteStatus ? '确认出价 RMB 3,000' : '点击"开启出价",即刻参与竞拍 ' }} <div v-if="fullLive">
<sideButton class="absolute top-196px right-0 z-999"></sideButton>
<div class="absolute left-1/2 transform -translate-x-1/2 flex flex-col items-center" style="bottom:calc(var(--safe-area-inset-bottom) + 26px)">
<div class="text-16px text-#FFB25F font-600">
当前价RMB
<van-rolling-text class="my-rolling-text" :start-num="0" :target-num="3000" direction="up"/>
</div> </div>
</PressableButton> <div class="text-16px text-#fff font-600">
<broadcast></broadcast> 下口价RMB
<van-rolling-text class="my-rolling-text1" :start-num="0" :target-num="3500" direction="up"/>
</div>
<PressableButton>
<div
:class="`w-344px h-[40px] ${quoteStatus ? 'bg-#FFB25F' : 'bg-#D6D6D8'} rounded-4px ${quoteStatus ? 'text-#fff' : 'text-#7D7D7F'} text-14px flex justify-center items-center mt-10px mb-10px`">
{{ quoteStatus ? '确认出价 RMB 3,000' : '点击"开启出价",即刻参与竞拍 ' }}
</div>
</PressableButton>
<broadcast></broadcast>
</div>
<paymentInput v-model:show="show"/>
<div>
</div>
<paymentResults v-model:show="show1" type="error"/>
</div> </div>
<paymentInput v-model:show="show"/> </transition>
<div>
</div>
<paymentResults v-model:show="show1" type="error"/>
</template>
</div> </div>
</template> </template>
@ -109,7 +125,15 @@ const goPay = () => {
} }
</style> </style>
<style scoped> <style scoped>
.v-enter-active,
.v-leave-active {
transition: opacity 0.5s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
.my-rolling-text { .my-rolling-text {
--van-rolling-text-item-width: 10px; --van-rolling-text-item-width: 10px;
--van-rolling-text-font-size: 16px; --van-rolling-text-font-size: 16px;

View File

@ -4,14 +4,13 @@
v-for="(item, index) in items" v-for="(item, index) in items"
:key="index" :key="index"
class="w-full" class="w-full"
@click="openShow" @click="openShow(item,index)"
> >
<div class="relative w-full"> <div class="relative w-full">
<van-image <img
:src="item.image" :src="item.artwork?.hdPic"
:style="{ aspectRatio: item.ratio }" class="w-full object-cover rounded-4px"
fit="cover"
class="w-full"
/> />
<div <div
class="absolute left-[8px] top-[8px] h-[17px] w-[45px] flex items-center justify-center bg-[#2b53ac] text-[12px] text-[#fff]" class="absolute left-[8px] top-[8px] h-[17px] w-[45px] flex items-center justify-center bg-[#2b53ac] text-[12px] text-[#fff]"
@ -21,16 +20,16 @@
</div> </div>
<div class="pt-[8px]"> <div class="pt-[8px]">
<div class="text-[14px] text-[#000000] leading-[20px]"> <div class="text-[14px] text-[#000000] leading-[20px]">
{{ item.title }} {{ item.name }}
</div> </div>
<div class="mt-[4px] text-[12px] text-[#575757]"> <div class="mt-[4px] text-[12px] text-[#575757]">
起拍价{{ item.startingPrice }} 起拍价{{ item?.startPrice??0 }}
</div> </div>
<div <div
v-if="item.transactionPrice" v-if="item.soldPrice"
class="mt-[4px] text-[12px] text-[#b58047]" class="mt-[4px] text-[12px] text-[#b58047]"
> >
成交价{{ item.transactionPrice }} 成交价{{ item?.startPrice??0 }}
</div> </div>
</div> </div>
</div> </div>
@ -48,7 +47,7 @@ const props = defineProps({
const emit = defineEmits(['openShow']); const emit = defineEmits(['openShow']);
const openShow = () => { const openShow = (item,index) => {
emit('openShow'); emit('openShow', item,index);
}; };
</script> </script>

View File

@ -1,81 +1,78 @@
<script setup> <script setup>
import Column from "~/pages/home/components/Column/index.vue";
import Column from "@/pages/home/components/Column/index.vue"; import {goodStore} from "~/stores/goods";
import {artworkList} from "@/api/goods/index.js"; import {artworkDetail, artworkList} from "~/api/goods";
import {homeStore} from "~/stores/goods/index.js"; import {useRect} from "@vant/use";
const {itemList, pageRef,auctionDetail,liveRef,artWorkDetail,currentItem} = goodStore();
const loading = ref(false); const loading = ref(false);
const showHeight = ref('');
const show = ref(false);
const loading1 = ref(false);
const finished = ref(false); const finished = ref(false);
const {fullLive,actionDetails,itemList} = homeStore(); const getArtworkList=async ()=>{
const list = ref([{ const res= await artworkList({auctionUuid: auctionDetail.value.uuid,...pageRef.value})
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/637d95b4-2ae9-4a74-bd60-a3a9d2ca2ca0.png', if (res.status===0){
title: '张天赐 | 日出而作,日落而息', itemList.value.push(...res.data.data)
startingPrice: 'RMB 1,000', pageRef.value.itemCount=res.data.count
transactionPrice: 'RMB 10,000', }
}, { }
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/f7b65e23-ce21-41b4-8e58-9e6dc6950727.png', const loadData = async () => {
title: '张天赐 | 日出而作,日落而息', pageRef.value.page++
startingPrice: 'RMB 1,000', await getArtworkList()
transactionPrice: '', loading.value = false;
}, { if (pageRef.value.itemCount <= itemList.value.length) {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/41eceb23-d168-4049-ae8e-48c5328b192f.png', finished.value = true
title: '张天赐 | 日出而作,日落而息', }
startingPrice: 'RMB 1,000', };
transactionPrice: '',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/25c3f03c-9e0b-456b-963f-79b3d812c89a.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: '',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/25c3f03c-9e0b-456b-963f-79b3d812c89a.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: '',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/25c3f03c-9e0b-456b-963f-79b3d812c89a.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: '',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/637d95b4-2ae9-4a74-bd60-a3a9d2ca2ca0.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: 'RMB 10,000',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/637d95b4-2ae9-4a74-bd60-a3a9d2ca2ca0.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: 'RMB 10,000',
}])
const columns = computed(() => { const columns = computed(() => {
const result = [[], []]; const result = [[], []];
// itemList itemList.value.forEach((item, index) => {
if (itemList.value && itemList.value.length > 0) { result[index % 2].push({...item, index});
itemList.value.forEach((item, index) => { });
result[index % 2].push(item);
});
}
return result; return result;
}); });
const loadData = async () => { const refreshData = async () => {
// ... pageRef.value.page = 1
finished.value=false
const res= await artworkList({auctionUuid: auctionDetail.value.uuid,...pageRef.value})
if (res.status===0){
itemList.value=res.data.data
pageRef.value.itemCount=res.data.count
}
loading1.value = false
}
const getDetail=async ()=>{
const res=await artworkDetail({uuid:currentItem.value.artworkUuid})
if (res.status===0){
artWorkDetail.value
}
}
const openShow = (item,index) => {
currentItem.value=item
getDetail()
const rect = useRect(liveRef.value.$el);
showHeight.value = rect.height;
nextTick(() => {
show.value = true;
});
}; };
</script> </script>
<template> <template>
<div class="px-[16px] pt-[16px]"> <div class="px-[16px] pt-[16px]">
<van-pull-refresh> <van-pull-refresh v-model="loading1" success-text="刷新成功" @refresh="refreshData">
<van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="loadData"> <van-list :immediate-check="false" v-model:loading="loading" :finished="finished" finished-text="没有更多了"
@load="loadData">
<div class="w-full flex gap-[16px]"> <div class="w-full flex gap-[16px]">
<Column v-for="(column, colIndex) in columns" :key="colIndex" :items="column" /> <Column v-for="(column, colIndex) in columns" :key="colIndex" :colIndex="colIndex" :items="column" @openShow="openShow" />
</div> </div>
</van-list> </van-list>
</van-pull-refresh> </van-pull-refresh>
<van-action-sheet teleport="#__nuxt" :round="false" v-model:show="show" title="拍品详情">
<div class="content bg-[#F0F0F0]" :style="`height: calc(100vh - ${showHeight + 85}px)`">
<itemDetail/>
</div>
</van-action-sheet>
</div> </div>
</template> </template>
<style scoped>
</style>

View File

@ -1,50 +0,0 @@
<script setup>
const props = defineProps({
items: Array
});
const emit = defineEmits(['openShow']);
const openShow = () => {
emit('openShow');
};
</script>
<template>
<div class="flex flex-1 flex-col gap-[16px]">
<div
v-for="(item, index) in items"
:key="index"
class="w-full"
@click="openShow"
>
<div class="relative w-full">
<van-image
:src="item.image"
:style="{ aspectRatio: item.ratio }"
fit="cover"
class="w-full"
/>
<div
class="absolute left-[8px] top-[8px] h-[17px] w-[45px] flex items-center justify-center bg-[#2b53ac] text-[12px] text-[#fff]"
>
LOT{{ item.index + 1 }}
</div>
</div>
<div class="pt-[8px]">
<div class="text-[14px] text-[#000000] leading-[20px]">
{{ item.title }}
</div>
<div class="mt-[4px] text-[12px] text-[#575757]">
起拍价{{ item.startingPrice }}
</div>
<div
v-if="item.transactionPrice"
class="mt-[4px] text-[12px] text-[#b58047]"
>
成交价{{ item.transactionPrice }}
</div>
</div>
</div>
</div>
</template>

View File

@ -1,134 +1,44 @@
<script setup> <script setup>
import {useRect} from '@vant/use';
import LiveRoom from '@/pages/LiveRoom/index.client.vue'; import LiveRoom from '@/pages/LiveRoom/index.client.vue';
import itemDetail from '@/components/itemDetail/index.vue'; import {goodStore} from "@/stores/goods/index.js";
import {homeStore} from "@/stores/goods/index.js"; import ItemList from './components/ItemList/index.vue'
import Column from './components/Column/index.vue' import Cescribe from './components/Cescribe/index.vue'
import {artworkList} from "~/api/goods/index.js";
const {fullLive} = homeStore(); const {fullLive,getAuctionDetail,auctionDetail,itemList,pageRef,liveRef} = goodStore();
definePageMeta({ definePageMeta({
layout: 'default', layout: 'default',
i18n: 'menu.home', i18n: 'menu.home',
}) })
const liveRef = ref(null);
const loading = ref(false);
const finished = ref(false);
const refreshing = ref(false);
const page = ref(1);
const show = ref(false);
const showHeight = ref('');
const list = ref([{
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/637d95b4-2ae9-4a74-bd60-a3a9d2ca2ca0.png',
title: '张天赐 | 日出而作日落而息1',
startingPrice: 'RMB 1,000',
transactionPrice: 'RMB 10,000',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/f7b65e23-ce21-41b4-8e58-9e6dc6950727.png',
title: '张天赐 | 日出而作日落而息2',
startingPrice: 'RMB 1,000',
transactionPrice: '',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/41eceb23-d168-4049-ae8e-48c5328b192f.png',
title: '张天赐 | 日出而作日落而息3',
startingPrice: 'RMB 1,000',
transactionPrice: '',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/25c3f03c-9e0b-456b-963f-79b3d812c89a.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: '',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/25c3f03c-9e0b-456b-963f-79b3d812c89a.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: '',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/25c3f03c-9e0b-456b-963f-79b3d812c89a.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: '',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/637d95b4-2ae9-4a74-bd60-a3a9d2ca2ca0.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: 'RMB 10,000',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/637d95b4-2ae9-4a74-bd60-a3a9d2ca2ca0.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: 'RMB 10,000',
}])
const loadData = async () => {
// ...
};
const onRefresh = () => {
finished.value = false;
page.value = 1;
refreshing.value = true;
loadData();
};
const columns = computed(() => {
const result = [[], []];
list.value.forEach((item, index) => {
// index
result[index % 2].push({ ...item, index });
});
return result;
});
const openShow = () => {
const rect = useRect(liveRef.value.$el);
showHeight.value = rect.height;
nextTick(() => {
show.value = true;
});
};
const changeLive = () => { const changeLive = () => {
fullLive.value = true; fullLive.value = true;
}; };
const initData=async ()=>{
await getAuctionDetail()
const res= await artworkList({auctionUuid: auctionDetail.value.uuid,...pageRef.value})
if (res.status===0){
itemList.value=res.data.data
pageRef.value.itemCount=res.data.count
}
}
initData()
</script> </script>
<template> <template>
<div class="flex-grow-1"> <div class="flex-grow-1">
<div @click="changeLive" :class="['changeLive', fullLive ? 'expanded' : 'collapsed']"> <client-only>
<client-only> <LiveRoom @click="changeLive" :class="['changeLive', fullLive ? 'expanded' : 'collapsed']" ref="liveRef" :fullLive="fullLive"/>
<LiveRoom ref="liveRef" :fullLive="fullLive"/> </client-only>
</client-only> <div v-show="!fullLive" class="bg-#fff">
<van-tabs sticky animated>
<van-tab title="拍品列表">
<ItemList></ItemList>
</van-tab>
<van-tab title="拍卖说明">
<Cescribe></Cescribe>
</van-tab>
</van-tabs>
<van-back-top right="15vw" bottom="10vh"/>
</div> </div>
<transition name="fade">
<div v-show="!fullLive" class="bg-#fff">
<van-tabs sticky animated>
<van-tab title="拍品列表">
<div class="px-[16px] pt-[16px]">
<van-pull-refresh>
<van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="loadData">
<div class="w-full flex gap-[16px]">
<Column v-for="(column, colIndex) in columns" :key="colIndex" :colIndex="colIndex" :items="column" @openShow="openShow"/>
</div>
</van-list>
</van-pull-refresh>
</div>
</van-tab>
<van-tab title="拍卖说明">
<div class="px-16px pt-14px">
<div class="text-#575757 text-14px">
这里是后台富文本配置的说明啊即可打开三等奖撒度老师的湿答答是快乐的阿四大皆空
</div>
</div>
</van-tab>
</van-tabs>
<van-back-top right="15vw" bottom="10vh"/>
<van-action-sheet :round="false" v-model:show="show" title="拍品详情">
<div class="content bg-[#F0F0F0]" :style="`height: calc(100vh - ${showHeight + 85}px)`">
<itemDetail/>
</div>
</van-action-sheet>
</div>
</transition>
</div> </div>
</template> </template>
<style> <style>

View File

@ -4,6 +4,7 @@ import { useI18n } from 'vue-i18n'
import countryCode from '../countryRegion/data/index.js' import countryCode from '../countryRegion/data/index.js'
import {senCode, userLogin} from "@/api/auth/index.js"; import {senCode, userLogin} from "@/api/auth/index.js";
import {authStore} from "~/stores/auth/index.js"; import {authStore} from "~/stores/auth/index.js";
import {message} from '@/components/x-message/useMessage.js'
const {userInfo,token}= authStore() const {userInfo,token}= authStore()
const router = useRouter(); const router = useRouter();
const route = useRoute(); const route = useRoute();
@ -13,26 +14,31 @@ definePageMeta({
i18n: 'login.title', i18n: 'login.title',
}) })
const loadingRef=ref({ const loadingRef=ref({
loading1:false loading1:false,
loading2:false,
}) })
const isExist=ref(false)// true const isExist=ref(false)// true
const isReal=ref(false) //isReal const isReal=ref(false) //isReal
function goToPage() { function goToPage() {
router.push('/countryRegion'); router.push('/countryRegion');
} }
const interval=ref(null)
const startCountdown=()=> { const startCountdown=()=> {
if (interval.value){
clearInterval(interval.value);
}
countdown.value = 60; countdown.value = 60;
const interval = setInterval(() => { interval.value = setInterval(() => {
if (countdown.value > 0) { if (countdown.value > 0) {
countdown.value--; countdown.value--;
} else { } else {
clearInterval(interval); clearInterval(interval.value);
} }
}, 1000); }, 1000);
} }
const countdown = ref(0); const countdown = ref(0);
const phoneNum = ref('17630920520') const phoneNum = ref('17630920520')
const code = ref('655119') const code = ref('123789')
const pane = ref(0) const pane = ref(0)
const showKeyboard = ref(false); const showKeyboard = ref(false);
// //
@ -79,23 +85,23 @@ watch(locale, () => {
}) })
const vanSwipeRef=ref(null) const vanSwipeRef=ref(null)
const getCode =async () => { const getCode =async () => {
// loadingRef.value.loading1=true loadingRef.value.loading1=true
// const res=await senCode({ const res=await senCode({
// telNum:phoneNum.value, telNum:phoneNum.value,
// zone:selectedZone.value zone:selectedZone.value
// }) })
// loadingRef.value.loading1=false loadingRef.value.loading1=false
// if (res.status===0){ if (res.status===0){
// pane.value = 1 pane.value = 1
// vanSwipeRef.value?.swipeTo(pane.value) vanSwipeRef.value?.swipeTo(pane.value)
// showKeyboard.value=true showKeyboard.value=true
// startCountdown(); startCountdown();
//
// } }
pane.value = 1 /* pane.value = 1
vanSwipeRef.value?.swipeTo(pane.value) vanSwipeRef.value?.swipeTo(pane.value)
showKeyboard.value=true showKeyboard.value=true
startCountdown(); startCountdown();*/
} }
const goBack = () => { const goBack = () => {
@ -104,6 +110,7 @@ const goBack = () => {
vanSwipeRef.value?.swipeTo(pane.value) vanSwipeRef.value?.swipeTo(pane.value)
} }
const goLogin =async () => { const goLogin =async () => {
loadingRef.value.loading2=true
const res=await userLogin({ const res=await userLogin({
telNum:phoneNum.value, telNum:phoneNum.value,
zone:selectedZone.value, zone:selectedZone.value,
@ -112,10 +119,14 @@ const goLogin =async () => {
if (res.status===0){ if (res.status===0){
userInfo.value=res.data.accountInfo userInfo.value=res.data.accountInfo
token.value=res.data.token token.value=res.data.token
if (!res.data.isReal){ if (!res.data.isReal){
router.push('/realAuth'); await router.push('/realAuth');
}else {
await router.push('/');
} }
} }
loadingRef.value.loading2=false
} }
</script> </script>
@ -164,7 +175,7 @@ const goLogin =async () => {
{{ $t('login.reSend') }}<span v-if="countdown>0">({{countdown}})</span> {{ $t('login.reSend') }}<span v-if="countdown>0">({{countdown}})</span>
</div> </div>
<div class="mt-[17px]"> <div class="mt-[17px]">
<van-button v-if="code.length === 6" type="primary" block style="height: 48px" @click="goLogin">{{ <van-button v-if="code.length === 6" type="primary" block :loading="loadingRef.loading2" :loading-text="$t('login.login')" style="height: 48px" @click="goLogin">{{
$t('login.login') $t('login.login')
}}</van-button> }}</van-button>
<van-button v-else type="primary" color="#D3D3D3" block style="height: 48px">{{ $t('login.login') }}</van-button> <van-button v-else type="primary" color="#D3D3D3" block style="height: 48px">{{ $t('login.login') }}</van-button>

View File

@ -1,9 +1,20 @@
<script setup> <script setup>
import {userArtworks} from "~/api/goods/index.js";
import {authStore} from "~/stores/auth/index.js";
definePageMeta({ definePageMeta({
layout: 'default', layout: 'default',
title: '我的', title: '我的',
i18n: 'menu.profile', i18n: 'menu.profile',
}) })
const {userInfo}= authStore()
const initData=async ()=>{
const res=await userArtworks({})
if (res.status===0){
}
}
initData()
</script> </script>
<template> <template>
@ -13,8 +24,8 @@ definePageMeta({
<img class="w-57px h-57px" src="@/static/images/5514@2x.png" alt=""> <img class="w-57px h-57px" src="@/static/images/5514@2x.png" alt="">
</div> </div>
<div class="flex flex-col"> <div class="flex flex-col">
<div class="text-18px text-#181818">张三</div> <div class="text-18px text-#181818">{{userInfo.realName}}</div>
<div class="text-#575757 text-14px">15834362333</div> <div class="text-#575757 text-14px">{{userInfo.telNum}}</div>
</div> </div>
</div> </div>
<div class="flex-grow-1"> <div class="flex-grow-1">

Binary file not shown.

View File

@ -2,7 +2,7 @@ import { createGlobalState,useLocalStorage } from '@vueuse/core'
export const authStore = createGlobalState(() => { export const authStore = createGlobalState(() => {
const token=useLocalStorage('token','') const token=useLocalStorage('token','')
const RefreshToken=useLocalStorage('RefreshToken','') const RefreshToken=useLocalStorage('RefreshToken','')
const userInfo=useLocalStorage('userInfo','') const userInfo=useLocalStorage('userInfo',{})
return{ return{
userInfo, userInfo,
RefreshToken, RefreshToken,

View File

@ -1,50 +1,38 @@
import { createGlobalState } from '@vueuse/core' import {createGlobalState} from '@vueuse/core'
export const homeStore = createGlobalState(() => { import {artworkList, defaultDetail} from "~/api/goods/index.js";
const actionDetails=ref({})
const fullLive=ref(false)
const itemList = ref([{
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/637d95b4-2ae9-4a74-bd60-a3a9d2ca2ca0.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: 'RMB 10,000',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/f7b65e23-ce21-41b4-8e58-9e6dc6950727.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: '',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/41eceb23-d168-4049-ae8e-48c5328b192f.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: '',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/25c3f03c-9e0b-456b-963f-79b3d812c89a.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: '',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/25c3f03c-9e0b-456b-963f-79b3d812c89a.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: '',
}, {
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/25c3f03c-9e0b-456b-963f-79b3d812c89a.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: '',
},{
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/637d95b4-2ae9-4a74-bd60-a3a9d2ca2ca0.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: 'RMB 10,000',
},{
image: 'https://e-cdn.fontree.cn/fonchain-main/prod/file/default/setting/637d95b4-2ae9-4a74-bd60-a3a9d2ca2ca0.png',
title: '张天赐 | 日出而作,日落而息',
startingPrice: 'RMB 1,000',
transactionPrice: 'RMB 10,000',
}])
return{ export const goodStore = createGlobalState(() => {
const actionDetails = ref({})
const fullLive = ref(false)
const liveRef = ref(null);
const currentItem=ref({})
const myArtWorks=ref([])
const pageRef = ref({
page: 1,
pageSize: 5,
itemCount: 0
})
const artWorkDetail=ref(null)
const itemList = ref([])
const auctionDetail = ref({})
const getAuctionDetail = async () => {
const res = await defaultDetail({})
if (res.status === 0) {
auctionDetail.value = res.data
}
}
const getArtworkList = async (page = pageRef.value) => {
return artworkList({auctionUuid: auctionDetail.value.uuid, ...page})
}
return {
myArtWorks,
currentItem,
artWorkDetail,
liveRef,
pageRef,
getArtworkList,
auctionDetail,
getAuctionDetail,
actionDetails, actionDetails,
itemList, itemList,
fullLive fullLive

2
env/.env.test vendored
View File

@ -1,5 +1,5 @@
# 测试环境配置 # 测试环境配置
NUXT_PUBLIC_API_BASE=http://192.168.88.139:9021 NUXT_PUBLIC_API_BASE=http://172.16.100.99:8005
NUXT_PUBLIC_WS_URL=ws://test-ws.example.com NUXT_PUBLIC_WS_URL=ws://test-ws.example.com
NUXT_API_SECRET=test-secret NUXT_API_SECRET=test-secret