Merge remote-tracking branch 'origin/tomato'

This commit is contained in:
plightfield 2024-11-11 11:56:31 +08:00
commit ea1bd25064
14 changed files with 257 additions and 70 deletions

View File

@ -33,6 +33,7 @@
"echarts": "^5.5.1", "echarts": "^5.5.1",
"gsap": "^3.12.5", "gsap": "^3.12.5",
"localforage": "^1.10.0", "localforage": "^1.10.0",
"lodash": "^4.17.21",
"lunar-typescript": "^1.7.5", "lunar-typescript": "^1.7.5",
"oh-vue-icons": "^1.0.0-rc3", "oh-vue-icons": "^1.0.0-rc3",
"pinia": "^2.1.7", "pinia": "^2.1.7",

View File

@ -33,11 +33,14 @@ const layout = useLayoutStore()
<GLobalModal /> <GLobalModal />
<SettingsOverlay /> <SettingsOverlay />
<SettingsButton /> <SettingsButton />
<Sider />
<Sider v-if="!layout.state.simple" />
<LoginModal v-if="router.path === 'global-login'" /> <LoginModal v-if="router.path === 'global-login'" />
<Grid v-if="layout.ready" /> <Transition>
<Dock /> <Grid v-if="layout.ready && !layout.state.simple" />
<div class="fixed z-40 right-[14%] top-8"> </Transition>
<Dock v-if="!layout.state.simple" />
<div class="fixed z-40 right-[14%] top-8" v-if="!layout.state.simple">
<Fox /> <Fox />
</div> </div>
<DirModal /> <DirModal />

View File

@ -44,7 +44,7 @@ export default defineComponent({
color: 'white', color: 'white',
transitionDuration: '.4s', transitionDuration: '.4s',
left: layout.isCompact ? '20px' : '50%', left: layout.isCompact ? '20px' : '50%',
top: layout.isCompact ? '20px' : '50px', top: layout.isCompact ? '20px' : layout.state.simple?'100px':'50px',
transform: layout.isCompact ? '' : 'translate(-50%,0)' transform: layout.isCompact ? '' : 'translate(-50%,0)'
}} }}
> >

View File

@ -0,0 +1,51 @@
import { addIcons, OhVueIcon } from "oh-vue-icons";
import { defineComponent, ref } from "vue";
import { BiEyeFill } from "oh-vue-icons/icons";
import { BiEyeSlashFill } from "oh-vue-icons/icons";
import useLayoutStore from "../useLayoutStore";
import clsx from "clsx";
import useSettingsStore from "@/settings/useSettingsStore";
addIcons(BiEyeFill, BiEyeSlashFill)
export default defineComponent(() => {
const layoutStore = useLayoutStore()
const settingStore = useSettingsStore()
const show = ref(false)
return () => (
<div class={"fixed w-[200px] h-[50px] text-white right-0 top-0 z-10 "}
onMouseenter={() => {
show.value = true
}}
onMouseleave={() => {
show.value = false
}}
>
<div class={clsx("absolute duration-300 right-7 text-[14px] items-center flex gap-x-4",
settingStore.state.showTop === 'auto'
? show.value
? 'top-5'
: '-top-[30px]'
: 'top-5'
)}>
<span class={"px-2 py-1 hover:bg-black/20 rounded cursor-pointer"}
onClick={() => {
layoutStore.state.simple = !layoutStore.state.simple
}}
>{layoutStore.state.simple ? '极简' : '常规'}</span>
<div onClick={() => {
settingStore.state.showTop = settingStore.state.showTop === 'auto' ? 'show' : 'auto'
}}>
{
settingStore.state.showTop === 'auto' ?
<OhVueIcon name={BiEyeSlashFill.name} class={"cursor-pointer opacity-60 hover:opacity-100"} fill="#fff" scale={1.5}></OhVueIcon>
:
<OhVueIcon name={BiEyeFill.name} class={"cursor-pointer opacity-60 hover:opacity-100"} fill="#fff" scale={1.5}></OhVueIcon>
}
</div>
</div>
</div>
)
})

View File

@ -1,5 +1,6 @@
import { defineAsyncComponent, defineComponent } from 'vue' import { defineAsyncComponent, defineComponent } from 'vue'
import Search from './search' import Search from './search'
import ModeChange from './ModeChange'
const GlobalTime = defineAsyncComponent({ const GlobalTime = defineAsyncComponent({
loader: () => import('./GlobalTime') loader: () => import('./GlobalTime')
@ -11,6 +12,7 @@ export default defineComponent({
<> <>
<GlobalTime /> <GlobalTime />
<Search /> <Search />
<ModeChange />
</> </>
) )
} }

View File

@ -23,7 +23,7 @@ export default defineComponent(
props.isMini props.isMini
? {} ? {}
: { : {
top: layout.isCompact ? '40px' : '172px', top: layout.isCompact ? '40px' : layout.state.simple ? '230px' : '172px',
width: settings.state.searchWidth + 'rem' width: settings.state.searchWidth + 'rem'
} }
} }

View File

@ -2,8 +2,15 @@ import { defineStore } from 'pinia'
import { ref, watch } from 'vue' import { ref, watch } from 'vue'
import useSearchConfigStore from './useSearchConfigStore' import useSearchConfigStore from './useSearchConfigStore'
import jump from '@/utils/jump' import jump from '@/utils/jump'
import debounce from 'lodash/debounce'
import { aIUrl, translateUrl } from '@/config' import { aIUrl, translateUrl } from '@/config'
import request from '@/utils/request'
export type SearchAdType = {
name: string
icon: string
url: string
id: string
}
export default defineStore('search', () => { export default defineStore('search', () => {
const searchRef = ref<HTMLInputElement | null>(null) const searchRef = ref<HTMLInputElement | null>(null)
const focus = ref(false) const focus = ref(false)
@ -26,6 +33,7 @@ export default defineStore('search', () => {
const searchStr = ref('') const searchStr = ref('')
const current = ref(-1) const current = ref(-1)
const sugList = ref<string[]>([]) const sugList = ref<string[]>([])
const addList = ref<SearchAdType[]>([])
watch( watch(
searchStr, searchStr,
(val) => { (val) => {
@ -45,6 +53,15 @@ export default defineStore('search', () => {
immediate: true immediate: true
} }
) )
const debouncedHandler = debounce((newValue) => {
console.log('数值改变并已防抖处理:', newValue)
request<SearchAdType[]>("GET", `/api/app/searchBars`).then((res) => {
addList.value = res
})
}, 500) //
watch(searchStr, (newValue) => {
debouncedHandler(newValue)
})
const searchConfig = useSearchConfigStore() const searchConfig = useSearchConfigStore()
const handle = (e: KeyboardEvent) => { const handle = (e: KeyboardEvent) => {
const n = sugList.value.length const n = sugList.value.length

View File

@ -134,7 +134,7 @@ body {
/* 默认动画 */ /* 默认动画 */
.v-enter-active, .v-enter-active,
.v-leave-active { .v-leave-active {
transition: opacity 0.3s ease-in-out; transition: opacity 0.15s ease-in-out;
} }
.v-enter-from, .v-enter-from,

View File

@ -15,6 +15,7 @@ export default defineStore(
showSider: 'show' as VisibleState, showSider: 'show' as VisibleState,
showDock: 'show' as VisibleState, showDock: 'show' as VisibleState,
showPet: 'show' as VisibleState, showPet: 'show' as VisibleState,
showTop: 'show' as VisibleState,
showTime: true, showTime: true,
timeOptions: ['date', 'week', '12hour', 'lunal', 'second'] as TimeUnit[], timeOptions: ['date', 'week', '12hour', 'lunal', 'second'] as TimeUnit[],
showAdder: true, showAdder: true,

View File

@ -1,9 +1,58 @@
import { defineComponent } from 'vue' import { computed, defineComponent, onMounted, ref } from 'vue'
import useDiscountStore from './useDiscountStore'
export default defineComponent(() => { export default defineComponent(() => {
const store = useDiscountStore()
const idx = ref(0)
const selectItem = computed(() => {
return store.list[idx.value]
})
onMounted(() => {
setInterval(() => {
idx.value = idx.value + 1
if (idx.value > store.list.length - 1) {
idx.value = 0
}
}, 5000)
})
return () => ( return () => (
<div class="w-full h-full bg-[#ecfbff] flex flex-col"> <div class="w-full h-full bg-[#ecfbff] flex flex-col" style={{
large background: `url('${selectItem.value?.commdity[0]?.img}')`
}}>
<div class={"absolute left-0 top-0 flex text-[14px] h-[26px] bg-[#78635D] rounded-lg items-center text-white"}>
<div class="bg-[#ef5a41] flex items-center h-full text-white rounded px-2 font-bold ">
-13%
</div>
<span class={" rounded-lg px-2"}>1</span>
</div>
<div
class={
'absolute right-0 h-full w-1/2 rounded-lg bg-[#0003] backdrop-blur-md'
}
>
<div class="flex flex-col w-full h-full justify-center gap-y-2 py-2 px-3">
<span class="text-white text-[14px]">{selectItem.value.name}</span>
<div>
<span
class={
'border-[1px] border-[#f6d1b8] border-solid text-[#f6d1b8] p-1 text-[12px] rounded'
}
>
{selectItem.value.typename}
</span>
</div>
<div class={"flex flex-col"}>
<span class="text-[#fffbc2] text-[18px] font-bold ">
{selectItem.value.commdity[0]?.price}
</span>
<span class="text-[12px] text-[#bdbdbd] line-through decoration-current">
{selectItem.value.commdity[0]?.oldprice}
</span>
</div>
</div>
</div>
</div> </div>
) )
}) })

View File

@ -1,10 +1,49 @@
import { defineComponent } from 'vue' import { computed, defineComponent, onMounted, ref } from 'vue'
import useDiscountStore from './useDiscountStore'
export default defineComponent(() => { export default defineComponent(() => {
const store = useDiscountStore()
const idx = ref(0)
const selectItem = computed(() => {
return store.list[idx.value]
})
onMounted(() => {
setInterval(() => {
idx.value = idx.value + 1
if (idx.value > store.list.length - 1) {
idx.value = 0
}
}, 5000)
})
return () => ( return () => (
<div class="w-full h-full bg-[#ecfbff] flex flex-col"> <div class="w-full h-full bg-[#ecfbff] flex flex-col" style={{
middle background: `url('${selectItem.value?.commdity[0]?.img}')`
}}>
<div class={"absolute left-0 top-0 flex text-[14px] h-[26px] bg-[#78635D] rounded-lg items-center text-white"}>
<div class="bg-[#ef5a41] flex items-center h-full text-white rounded px-2 font-bold ">
-13%
</div>
</div>
<div
class={
'absolute bottom-0 h-1/2 w-full rounded-lg bg-[#0003] backdrop-blur-md'
}
>
<div class="flex flex-col w-full h-full justify-center gap-y-1 py-2 px-3">
<span class="text-white text-[14px]">{selectItem.value.name}</span>
<div class={"flex flex-col"}>
<span class="text-[#fffbc2] text-[18px] font-bold ">
{selectItem.value.commdity[0]?.price}
</span>
<span class="text-[12px] text-[#bdbdbd] line-through decoration-current">
{selectItem.value.commdity[0]?.oldprice}
</span>
</div>
</div>
</div>
</div> </div>
) )
}) })

View File

@ -1,10 +1,9 @@
import { defineComponent, ref, watch, type VNodeRef } from 'vue' import { defineComponent, onMounted, ref, watch, type VNodeRef } from 'vue'
import useGameNews from './useDiscountStore'
import { RiTimeLine } from 'oh-vue-icons/icons' import { RiTimeLine } from 'oh-vue-icons/icons'
import { addIcons, OhVueIcon } from 'oh-vue-icons' import { addIcons, OhVueIcon } from 'oh-vue-icons'
import { IoCloseCircleOutline, RiCloseCircleLine } from 'oh-vue-icons/icons' import { IoCloseCircleOutline, RiCloseCircleLine } from 'oh-vue-icons/icons'
import dayjs from 'dayjs'
import useDiscountStore from './useDiscountStore' import useDiscountStore from './useDiscountStore'
import { debounce } from 'lodash'
addIcons(RiTimeLine, IoCloseCircleOutline, RiCloseCircleLine) addIcons(RiTimeLine, IoCloseCircleOutline, RiCloseCircleLine)
export default defineComponent(() => { export default defineComponent(() => {
const store = useDiscountStore() const store = useDiscountStore()
@ -12,11 +11,28 @@ export default defineComponent(() => {
const searchText = ref('') const searchText = ref('')
const handleScroll = () => { const handleScroll = () => {
const container = containerRef.value const container = containerRef.value
if (store.loading) return
if (container.scrollTop + container.clientHeight >= container.scrollHeight - 15) {
store.state.pageIndex += 1;
if (container.scrollTop + container.clientHeight >= container.scrollHeight - 50) {
store.getNews() store.getNews()
} }
} }
const debouncedHandler = debounce((newValue) => {
searchText.value = newValue
store.state.find = newValue
store.searchList = []
store.state.pageIndex = 1
store.noMoreData = false
store.getNews()
}, 500) //
watch(searchText, (newValue) => {
debouncedHandler(newValue)
})
onMounted(() => {
store.state.pageIndex = 1
store.getNews()
})
return () => ( return () => (
<div <div
class="w-full h-full flex flex-col p-5 bg-[#17212d]" class="w-full h-full flex flex-col p-5 bg-[#17212d]"
@ -53,7 +69,9 @@ export default defineComponent(() => {
ref={containerRef} ref={containerRef}
> >
<div class={'grid grid-cols-3 gap-4 '}> <div class={'grid grid-cols-3 gap-4 '}>
{store.list.map((item, index) => { {
(store.state.find ? store.searchList :
store.list).map((item, index) => {
return ( return (
<div <div
class={ class={
@ -79,7 +97,7 @@ export default defineComponent(() => {
{item.typename} {item.typename}
</span> </span>
</div> </div>
<div class="bg-white/20 flex rounded items-center"> <div class="bg-white/20 flex rounded items-center gap-x-2">
<div class="bg-[#ef5a41] h-full text-white rounded px-2 text-[18px] font-bold "> <div class="bg-[#ef5a41] h-full text-white rounded px-2 text-[18px] font-bold ">
-13% -13%
</div> </div>
@ -89,8 +107,8 @@ export default defineComponent(() => {
<span class="text-[12px] text-[#bdbdbd] line-through decoration-current"> <span class="text-[12px] text-[#bdbdbd] line-through decoration-current">
{item.commdity[0]?.oldprice} {item.commdity[0]?.oldprice}
</span> </span>
<span class="text-[12px] text-[#ebebeb] line-through decoration-current"> <span class="text-[12px] text-[#ebebeb] ">
{item.commdity[0]?.oldprice} {1}
</span> </span>
</div> </div>
</div> </div>
@ -100,7 +118,7 @@ export default defineComponent(() => {
})} })}
</div> </div>
{store.loading && ( {store.loading && (
<div class={'w-full font-bold flex justify-center text-white py-2'}>...</div> <div class={'w-full font-bold flex absolute bottom-2 bg-[#17212d] justify-center text-white py-2'}>...</div>
)} )}
{store.noMoreData && ( {store.noMoreData && (
<div class={'w-full font-bold flex justify-center text-white py-2'}></div> <div class={'w-full font-bold flex justify-center text-white py-2'}></div>

View File

@ -20,17 +20,18 @@ export interface GameDiscount {
} }
export default defineStore("gameDiscount", () => { export default defineStore("gameDiscount", () => {
const list = ref<GameDiscount[]>([]) const list = ref<GameDiscount[]>([])
const searchList = ref<GameDiscount[]>([])
const loading = ref(false) const loading = ref(false)
const noMoreData = ref(false) const noMoreData = ref(false)
const state = reactive({ const state = reactive({
pageSize: 1, pageSize: 10,
pageIndex: 1, pageIndex: 1,
find: '' find: ''
}) })
const getList = async () => { const getList = async () => {
const res = await request< const res = await request<
GameDiscount[] GameDiscount[]
>('GET', `/api/gameDiscount?pageSize=${state.pageSize}&pageIndex=${state.pageIndex}&find=${state.find}&type=all`) >('GET', `/api/gameDiscount?pagesize=${state.pageSize}&pageindex=${state.pageIndex}&find=${state.find}&type=all`)
return res return res
} }
const getNews = async () => { const getNews = async () => {
@ -41,9 +42,13 @@ export default defineStore("gameDiscount", () => {
const data = await getList() const data = await getList()
if (data.length === 0) { if (data.length === 0) {
noMoreData.value = true; noMoreData.value = true;
} else {
if (state.find !== '') {
searchList.value.push(...data);
} else { } else {
list.value.push(...data); list.value.push(...data);
state.pageIndex += 1; }
} }
} catch (e) { } catch (e) {
console.log(e); console.log(e);
@ -58,6 +63,7 @@ export default defineStore("gameDiscount", () => {
list, list,
loading, loading,
noMoreData, noMoreData,
searchList,
getNews, getNews,
state, state,
} }