Browse Source

feat: 各处跳转导览

潮流
jiannibang 4 years ago
parent
commit
0801294178
  1. 10
      src/base/ShopItem/ShopItem.vue
  2. 42
      src/components/BrandScroll/BrandScroll.vue
  3. 9
      src/components/Search/Search.vue
  4. 2
      src/router/routes.js
  5. 2
      src/store/root/state.js
  6. 8
      src/views/Brand/Brand.vue
  7. 10
      src/views/Foods/Foods.vue
  8. 69
      src/views/Guide/Guide.vue
  9. 2
      src/views/Index/Index.vue

10
src/base/ShopItem/ShopItem.vue

@ -18,20 +18,14 @@
</template>
<script setup>
import { computed } from 'vue'
import { storeToRefs } from 'pinia'
import { useStore } from '@/store/root'
const props = defineProps({
shop: Object,
config: Object,
isRow: Boolean,
isFood: Boolean
isFood: Boolean,
isActive: Boolean
})
const store = useStore()
const { shop: activeShop } = storeToRefs(store)
const isActive = computed(() => activeShop.value && activeShop.value.shopId === props.shop.shopId)
const emits = defineEmits(['click'])
function handleShop() {
emits('click', props.shop)

42
src/components/BrandScroll/BrandScroll.vue

@ -1,12 +1,21 @@
<template>
<ScrollView ref="scroll" :class="['brand-scroll', $route.path === '/guide' ? 'guide' : 'brand']" scrollbar :list="list">
<ScrollView ref="scroll" :class="['brand-scroll', $route.path === '/guide' ? 'guide' : 'brand']" scrollbar>
<div class="brand-content">
<div class="groups" v-for="item of list" v-show="item.shopList.length" :key="item.name">
<h1 class="info">
{{ item.name }}<span class="meta">/ {{ item.shopList.length }}</span> <span v-if="item.name === currentFloor.floor" class="current">您在本层</span>
</h1>
<TransitionGroup name="zoom" mode="out-in" tag="div" :class="{ group: true, isRow }">
<ShopItem :config="config" :isRow="isRow" :isFood="isFood" :shop="el" @click="handleShop(el)" v-for="el of item.shopList" :key="el.shopId" />
<ShopItem
:config="config"
:isRow="isRow"
:isFood="isFood"
:shop="el"
@click="handleShop(el)"
v-for="el of item.shopList"
:isActive="shop && shop.shopId === el.shopId"
:key="el.shopId"
/>
</TransitionGroup>
</div>
</div>
@ -19,16 +28,17 @@ import ShopItem from '@/base/ShopItem/ShopItem.vue'
import ScrollView from '@/base/ScrollView/ScrollView.vue'
import { storeToRefs } from 'pinia'
import { useStore } from '@/store/root'
const store = useStore()
const { currentFloor, shop } = storeToRefs(store)
const { currentFloor } = storeToRefs(store)
const scroll = ref(null)
const props = defineProps({
list: Array,
config: Object,
isRow: Boolean,
isFood: Boolean
isFood: Boolean,
shop: Object,
needFocus: Boolean
})
const emits = defineEmits(['click'])
@ -42,9 +52,25 @@ watch(
scroll.value.refresh()
})
)
watch(shop, nxt => {
if (!nxt) return
const el = document.getElementById(nxt.houseNumber)
watch(
() => props.list,
() =>
nextTick(() => {
scroll.value.refresh()
scroll.value.scrollTo(0, 0)
if (props.shop) {
const el = document.getElementById(props.shop.houseNumber)
if (!el) return
nextTick(() => {
scroll.value.scrollToElement(el, 500, 0, -100)
})
}
})
)
watch([scroll, () => props.shop], () => {
if (!props.needFocus || !scroll.value || !props.shop || !props.list) return
const el = document.getElementById(props.shop.houseNumber)
if (!el) return
nextTick(() => {
scroll.value.scrollToElement(el, 500, 0, -100)

9
src/components/Search/Search.vue

@ -66,17 +66,22 @@ const MAX_LENGTH = 7
const { _handleFacility } = useFacilityNav()
const router = useRouter()
const store = useStore()
const { indexList, shopList, facilityList, config, showVoice } = storeToRefs(store)
const hotRecommend = computed(() => indexList.value.hotSearch ?? [])
const showClassify = ref(false)
function handleShop(item) {
async function handleShop(item) {
useStatistics('brandSearch')
const shop = shopList.value.find(_shop => _shop.shopId === item.shopId)
store.SET_SHOP(shop)
store.SET_SHOW_DETAIL(true)
if (router.currentRoute.value.fullPath !== '/guide') {
store.SET_SELECTED_MODULE('Guide')
await router.push('/guide')
}
store.SET_SHOW_SEARCH(false)
}
async function handleActivity() {
await router.push('/activity')

2
src/router/routes.js

@ -6,7 +6,7 @@ export const staticRoutes = [
{
path: '/billboard',
name: 'Billboard',
component: () => import(/* webpackChunkName: "guide" */ '@/views/Billboard/Billboard'),
component: () => import(/* webpackChunkName: "billboard" */ '@/views/Billboard/Billboard'),
meta: {
showMenu: true,
showMap: true

2
src/store/root/state.js

@ -10,7 +10,7 @@ export const state = () => ({
facilityList: [], //设施列表
language: 'zh', //语言 zh: 简体中文 en: 英文 tw: 繁体中文
config: {}, //配置文件
shop: {}, //选中的店铺信息
shop: null, //选中的店铺信息
showSearch: false, //是否显示搜索
showVoice: false, //是否显示语音搜索
showDetail: false, //是否显示详情

8
src/views/Brand/Brand.vue

@ -1,6 +1,6 @@
<template>
<View>
<BrandScroll class="brand" @click="handleShop" :list="selectedList" :config="config" />
<BrandScroll class="brand" :shop="shop" @click="handleShop" :list="selectedList" :config="config" />
</View>
</template>
@ -14,7 +14,7 @@ import BrandScroll from '@/components/BrandScroll/BrandScroll.vue'
const store = useStore()
const { config, shopList } = storeToRefs(store)
const shop = ref(null)
const selectedList = ref([])
Promise.all([getBrandListByFloor()]).then(([_brandList]) => {
@ -24,9 +24,7 @@ Promise.all([getBrandListByFloor()]).then(([_brandList]) => {
})
function handleShop(item) {
const shop = shopList.value.find(_shop => _shop.shopId === item.shopId)
store.SET_SHOP(shop)
store.SET_SHOW_DETAIL(true)
shop.value = shopList.value.find(_shop => _shop.shopId === item.shopId)
}
</script>

10
src/views/Foods/Foods.vue

@ -1,6 +1,6 @@
<template>
<View>
<BrandScroll :isFood="true" class="foods" @click="handleShop" :list="selectedList" :config="config" />
<BrandScroll :isFood="true" class="foods" :shop="shop" @click="handleShop" :list="selectedList" :config="config" />
</View>
</template>
@ -14,22 +14,20 @@ import BrandScroll from '@/components/BrandScroll/BrandScroll.vue'
const store = useStore()
const { config, shopList } = storeToRefs(store)
const shop = ref(null)
const selectedList = ref([])
Promise.all([getBrandListByFloor()]).then(([_brandList]) => {
const list = _brandList.data.list.map(item => ({
name: item.name,
shopList: item.shopList.filter(shop => shop.isSpecial)
shopList: item.shopList.filter(_ => _.isSpecial)
}))
selectedList.value = list
})
function handleShop(item) {
const shop = shopList.value.find(_shop => _shop.shopId === item.shopId)
store.SET_SHOP(shop)
store.SET_SHOW_DETAIL(true)
shop.value = shopList.value.find(_shop => _shop.shopId === item.shopId)
}
</script>

69
src/views/Guide/Guide.vue

@ -5,7 +5,7 @@
<div style="display: inline-block; white-space: nowrap">
<div class="floors-item all" @click="showAll = true" :class="{ active: showAll }">全部楼层</div>
<div
@click="handleFloor(item, index)"
@click="handleSelectFloor(index)"
:class="{ active: !showAll && floorIdx === index, current: currentFloor.floorCode === item.floorCode }"
class="floors-item"
v-for="(item, index) of currentBuildingFloorsList"
@ -48,7 +48,7 @@
</Teleport>
<div class="shop-list-wrapper">
<BrandScroll @click="handleShop" :list="selectedShopList" :isRow="isRow" :config="config" />
<BrandScroll v-if="initiated" :shop="shop" :need-focus="true" @click="handleShop" :list="selectedShopList" :isRow="isRow" :config="config" />
<div class="switch">
<div :class="{ btn: true, active: !isRow }" @click="isRow = false">
<img v-if="isRow" src="./grid.svg" />
@ -64,7 +64,7 @@
</template>
<script setup>
import { ref, watch, onBeforeUnmount } from 'vue'
import { ref, watch, onBeforeUnmount, computed, nextTick } from 'vue'
import { storeToRefs } from 'pinia'
import { useStore } from '@/store/root'
import { RESET, DIRECTION, ACTIVITY_BRAND, list as buttonList } from './list'
@ -80,7 +80,7 @@ const isRow = ref(false)
const store = useStore()
const formatMap = ref({})
const facMap = ref({})
const { currentBuildingFloorsList, currentFloor, config, currentFloorShopMap } = storeToRefs(store)
const { currentBuildingFloorsList, currentFloor, config, currentFloorShopMap, shop } = storeToRefs(store)
try {
const facs = window.Map_QM.getAllIcon()
@ -90,11 +90,6 @@ try {
console.log('error: ', error)
}
try {
window.Map_QM?.showFloor?.(currentFloor.value.floorOrder)
} catch (error) {
console.log('error: ', error)
}
getBrandListByFloor().then(({ data }) => {
formatMap.value = data.list
.map(({ name, shopList: list }) => ({ name, format: Object.keys(list.reduce((acc, nxt) => ({ ...acc, [nxt.industryFatherName]: true }), {})).join('/') }))
@ -158,58 +153,86 @@ function handleMapIcon(item, index) {
function handleShop(item) {
mapIdx.value = -1
store.SET_SHOP(item)
setShopActive(item)
}
watch(shop, async nxt => {
if (nxt && initiated.value) {
if (currentBuildingFloorsList.value[floorIdx.value].floorOrder !== nxt.floorOrder) {
const index = currentBuildingFloorsList.value.findIndex(item => item.floorOrder === nxt.floorOrder)
await changeFloor(index)
setTimeout(() => setShopActive(nxt), 500)
} else setShopActive(nxt)
}
})
const floorIdx = ref(-1)
function handleFloor(item, index) {
function changeFloor(index) {
return new Promise(resolve => {
const floor = currentBuildingFloorsList.value[index]
showAll.value = false
hideMapDialog()
mapIdx.value = -1
cancelIdleCallback(idle.value)
window.Map_QM.showFloor(item.floorOrder)
window.Map_QM.showFloor(floor.floorOrder)
idle.value = requestIdleCallback(() => {
floorIdx.value = index
selectedShopList.value = shopList.value.map(brand => ({
...brand,
shopList: brand.shopList
.filter(shop => shop.floor === item.floor)
.map(shop => {
const meta = currentFloorShopMap.value[shop.shopId]
return { ...shop, ...(meta ? meta : {}) }
.filter(item => item.floor === floor.floor)
.map(item => {
const meta = currentFloorShopMap.value[item.shopId]
return { ...item, ...(meta ? meta : {}) }
})
}))
resolve()
})
})
}
const handleSelectFloor = index => {
store.SET_SHOP(null)
nextTick(() => {
changeFloor(index)
})
}
//
function filterAboutCurrentInfo() {
const floorCode = shop.value ? shop.value.floorCode : currentFloor.value.floorCode
const floor = shop.value ? shop.value.floor : currentFloor.value.floor
const floorOrder = shop.value ? shop.value.floorOrder : currentFloor.value.floorOrder
window.Map_QM.showFloor(floorOrder)
cancelIdleCallback(idle.value)
idle.value = requestIdleCallback(() => {
floorIdx.value = currentBuildingFloorsList.value.findIndex(item => item.floorCode === currentFloor.value.floorCode)
floorIdx.value = currentBuildingFloorsList.value.findIndex(item => item.floorCode === floorCode)
selectedShopList.value = shopList.value.map(brand => ({
...brand,
shopList: brand.shopList
.filter(shop => shop.floor === currentFloor.value.floor)
.map(shop => {
const meta = currentFloorShopMap.value[shop.shopId]
return { ...shop, ...(meta ? meta : {}) }
.filter(item => item.floor === floor)
.map(item => {
const meta = currentFloorShopMap.value[item.shopId]
return { ...item, ...(meta ? meta : {}) }
})
}))
})
nextTick(() => {
if (shop.value) {
setShopActive(shop.value)
}
})
}
const initiated = computed(() => selectedShopList.value && selectedShopList.value.length)
onBeforeUnmount(() => {
cancelIdleCallback(idle.value)
clearTimeout(mapTimer.value)
clearTimeout(mapIconTimer.value)
hideMapDialog()
store.SET_SHOP(null)
})
watch(
[shopList, currentFloor],
([_shopList, _currentFloor]) => {
if (_shopList.length && Reflect.ownKeys(_currentFloor).length) {
console.log('guide page initiated')
filterAboutCurrentInfo()
}
},

2
src/views/Index/Index.vue

@ -103,7 +103,7 @@ const goPage = item => {
function handleHot(item) {
const shop = shopList.value.find(_shop => _shop.shopId === item.shopId)
store.SET_SHOP(shop)
store.SET_SHOW_DETAIL(true)
goPage({ title: 'Guide', path: '/guide' })
}
getActivityList(3).then(({ data }) => {
activityList.value = data?.activityList ?? []

Loading…
Cancel
Save