feat(router): 更新路由结构并优化页面组件
- 移除经营范围按钮,精简导航栏 - 实现文章标题链接功能,提升用户体验 - 添加商品详情页面包屑导航,支持分类跳转 - 引入配送管理相关页面(区域、接单台、配送员、派单) - 替换控制台布局为站点头部和底部组件 - 重构商品分类页面,集成CMS导航功能 - 新增文章详情页面,支持多种访问方式 - 删除已迁移的创建应用和空应用页面 - 优化样式和组件导入,提升代码质量
This commit is contained in:
@@ -8,8 +8,9 @@
|
||||
|
||||
<div class="topbar-right">
|
||||
<div class="hidden md:flex items-center gap-2">
|
||||
<a-button size="small" @click="navigateTo('/products')">经营范围</a-button>
|
||||
<a-button size="small" type="primary" @click="navigateTo('/contact')">联系我们</a-button>
|
||||
<a-button size="small" @click="navigateTo('/join')">招商加盟</a-button>
|
||||
<a-button v-if="isLoggedIn" size="small" type="primary" @click="navigateTo('/console')">用户中心</a-button>
|
||||
<a-button v-else size="small" type="primary" @click="navigateTo('/login')">会员登录</a-button>
|
||||
</div>
|
||||
|
||||
<a-button class="md:hidden" size="small" @click="open = true">菜单</a-button>
|
||||
@@ -107,6 +108,7 @@
|
||||
<a-space direction="vertical" class="w-full">
|
||||
<a-button type="primary" block @click="onNav('/contact')">联系我们</a-button>
|
||||
<a-button block @click="onNav('/products')">经营范围</a-button>
|
||||
<a-button block @click="onNav('/join')">招商加盟</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</a-drawer>
|
||||
@@ -116,10 +118,16 @@
|
||||
import { mainNav } from '@/config/nav'
|
||||
import type { CmsNavigation } from '@/api/cms/cmsNavigation/model'
|
||||
import { COMPANY } from '@/config/company'
|
||||
import { getToken } from '@/utils/token-util'
|
||||
|
||||
const route = useRoute()
|
||||
const open = ref(false)
|
||||
const isAffixed = ref(false)
|
||||
const isHydrated = ref(false)
|
||||
const token = ref('')
|
||||
|
||||
const TOKEN_EVENT = 'auth-token-changed'
|
||||
const isLoggedIn = computed(() => isHydrated.value && !!token.value)
|
||||
|
||||
type HeaderNavItem = {
|
||||
key: string
|
||||
@@ -286,6 +294,20 @@ const todayText = computed(() => {
|
||||
function onAffixChange(affixed: boolean) {
|
||||
isAffixed.value = affixed
|
||||
}
|
||||
|
||||
function syncToken() {
|
||||
token.value = getToken()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
isHydrated.value = true
|
||||
syncToken()
|
||||
window.addEventListener(TOKEN_EVENT, syncToken)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener(TOKEN_EVENT, syncToken)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -126,8 +126,8 @@
|
||||
<script setup lang="ts">
|
||||
import { pageShopGoods } from '@/api/shop/shopGoods'
|
||||
import type { ShopGoods } from '@/api/shop/shopGoods/model'
|
||||
import { getShopGoodsCategory } from '@/api/shop/shopGoodsCategory'
|
||||
import type { ShopGoodsCategory } from '@/api/shop/shopGoodsCategory/model'
|
||||
import { getCmsNavigation } from '@/api/cms/cmsNavigation'
|
||||
import type { CmsNavigation } from '@/api/cms/cmsNavigation/model'
|
||||
import type { LocationQueryRaw } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
@@ -195,11 +195,11 @@ function onPageSizeChange(_current: number, nextSize: number) {
|
||||
updateQuery({ limit: nextSize, page: 1 })
|
||||
}
|
||||
|
||||
const { data: category } = await useAsyncData<ShopGoodsCategory | null>(
|
||||
() => `shop-goods-category-${String(route.params.navigationId)}`,
|
||||
const { data: navigation } = await useAsyncData<CmsNavigation | null>(
|
||||
() => `cms-navigation-${String(route.params.navigationId)}`,
|
||||
async () => {
|
||||
if (!isValidCategoryId.value) return null
|
||||
return await getShopGoodsCategory(categoryId.value).catch(() => null)
|
||||
return await getCmsNavigation(categoryId.value).catch(() => null)
|
||||
},
|
||||
{ watch: [categoryId] }
|
||||
)
|
||||
@@ -242,14 +242,16 @@ function pickString(obj: unknown, key: string) {
|
||||
}
|
||||
|
||||
const pageTitle = computed(() => {
|
||||
const name = category.value?.title?.trim()
|
||||
const nav = navigation.value as unknown as Record<string, unknown> | null
|
||||
const name = nav ? pickString(nav, 'title') || pickString(nav, 'label') : ''
|
||||
if (name) return name
|
||||
if (isValidCategoryId.value) return `分类 ${categoryId.value}`
|
||||
return '商品列表'
|
||||
})
|
||||
|
||||
const heroStyle = computed(() => {
|
||||
const banner = pickString(category.value, 'image')
|
||||
const nav = navigation.value as unknown as Record<string, unknown> | null
|
||||
const banner = nav ? (pickString(nav, 'banner') || pickString(nav, 'image')) : ''
|
||||
if (banner) {
|
||||
return {
|
||||
backgroundImage: `url(${banner})`
|
||||
@@ -294,8 +296,9 @@ function resolveGoodsImage(g: ShopGoods) {
|
||||
try {
|
||||
const parsed = JSON.parse(files) as unknown
|
||||
if (Array.isArray(parsed)) {
|
||||
const first = parsed[0] as any
|
||||
const url = typeof first?.url === 'string' ? first.url.trim() : ''
|
||||
const first = parsed[0] as unknown
|
||||
const rec = first && typeof first === 'object' ? (first as Record<string, unknown>) : null
|
||||
const url = rec && typeof rec.url === 'string' ? rec.url.trim() : ''
|
||||
if (url) return url
|
||||
}
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user