344 lines
10 KiB
JavaScript
344 lines
10 KiB
JavaScript
import {
|
||
getActiveLayout,
|
||
getActiveSchemes,
|
||
getActiveVars,
|
||
getThemeFeatures,
|
||
getThemeMeta,
|
||
loadAndApplyTheme,
|
||
} from '@/utils/theme'
|
||
import { resolvePageTabBar, syncTabBarByRoute } from '@/utils/tabbar'
|
||
import {
|
||
PC_PAGE_MAX_WIDTH,
|
||
catColsByWidth,
|
||
getWindowWidth,
|
||
goodsColsByWidth,
|
||
isPcWeixin,
|
||
watchWindowWidth,
|
||
} from '@/utils/device'
|
||
|
||
/**
|
||
* 页面主题 mixin:暴露色板 + layout + 进入动效 class
|
||
* 严禁按 themeMeta.code 特判业务结构
|
||
*/
|
||
export default {
|
||
data() {
|
||
return {
|
||
themeVars: getActiveVars(),
|
||
themeLayout: getActiveLayout(),
|
||
themeMeta: getThemeMeta(),
|
||
themeSchemes: getActiveSchemes(),
|
||
themeFeatures: getThemeFeatures(),
|
||
pcWindowWidth: getWindowWidth(),
|
||
}
|
||
},
|
||
computed: {
|
||
isPcWeixin() {
|
||
return isPcWeixin()
|
||
},
|
||
/** 首页 / 列表商品列数,随窗口宽度变(不限 PC) */
|
||
pcGoodsCols() {
|
||
return goodsColsByWidth(this.pcWindowWidth)
|
||
},
|
||
/** 首页分类宫格列数,格子更小所以更早加列 */
|
||
pcCatCols() {
|
||
return catColsByWidth(this.pcWindowWidth)
|
||
},
|
||
themeEffect() {
|
||
return (this.themeLayout && this.themeLayout.effect) || {}
|
||
},
|
||
themePageStyle() {
|
||
const v = this.themeVars || {}
|
||
const style = {
|
||
backgroundColor: v['--color-bg'] || '#F7F8FA',
|
||
color: v['--color-text'] || '#1a1a1a',
|
||
}
|
||
// PC 大窗不要把手机版拉成一条超宽带,内容限宽居中
|
||
if (isPcWeixin()) {
|
||
style.maxWidth = PC_PAGE_MAX_WIDTH + 'px'
|
||
style.marginLeft = 'auto'
|
||
style.marginRight = 'auto'
|
||
style.width = '100%'
|
||
style.boxSizing = 'border-box'
|
||
}
|
||
return style
|
||
},
|
||
themePrimary() {
|
||
return (this.themeVars && this.themeVars['--color-primary']) || '#B08D57'
|
||
},
|
||
themeAccent() {
|
||
return (this.themeVars && this.themeVars['--color-accent']) || this.themePrimary
|
||
},
|
||
themeSurface() {
|
||
return (this.themeVars && this.themeVars['--color-surface']) || '#ffffff'
|
||
},
|
||
themeSurfaceSoft() {
|
||
return (this.themeVars && this.themeVars['--color-surface-soft']) || this.themeSurface
|
||
},
|
||
themeText() {
|
||
return (this.themeVars && this.themeVars['--color-text']) || '#1a1a1a'
|
||
},
|
||
themeTextSoft() {
|
||
return (this.themeVars && this.themeVars['--color-text-soft']) || '#666666'
|
||
},
|
||
themeBorder() {
|
||
return (this.themeVars && this.themeVars['--color-border']) || '#eeeeee'
|
||
},
|
||
themePrice() {
|
||
return (this.themeVars && this.themeVars['--color-price']) || this.themePrimary
|
||
},
|
||
themeRadius() {
|
||
return (this.themeVars && this.themeVars['--radius-md']) || '16rpx'
|
||
},
|
||
themeRadiusLg() {
|
||
return (this.themeVars && this.themeVars['--radius-lg']) || '20rpx'
|
||
},
|
||
themeShadow() {
|
||
return (this.themeVars && this.themeVars['--shadow-md']) || 'none'
|
||
},
|
||
themeIconColor() {
|
||
return this.themePrimary
|
||
},
|
||
themeCardMode() {
|
||
return this.themeEffect.card || 'elevated'
|
||
},
|
||
themeIconMode() {
|
||
return this.themeEffect.icon || 'line'
|
||
},
|
||
themeEnterClass() {
|
||
const t = this.themeEffect.transition || 'fade'
|
||
return `theme-enter theme-enter--${t}`
|
||
},
|
||
homeHero() {
|
||
return this.sectionVariant(
|
||
'home',
|
||
'hero',
|
||
(this.themeLayout.home && this.themeLayout.home.hero) || 'carousel',
|
||
)
|
||
},
|
||
homeCategory() {
|
||
return this.sectionVariant(
|
||
'home',
|
||
'category',
|
||
(this.themeLayout.home && this.themeLayout.home.category) || 'grid',
|
||
)
|
||
},
|
||
homeProduct() {
|
||
return this.sectionVariant(
|
||
'home',
|
||
'product',
|
||
(this.themeLayout.home && this.themeLayout.home.product) || 'grid',
|
||
)
|
||
},
|
||
homePackage() {
|
||
return this.sectionVariant(
|
||
'home',
|
||
'package',
|
||
(this.themeLayout.home && this.themeLayout.home.package) || 'card',
|
||
)
|
||
},
|
||
packageList() {
|
||
return this.sectionVariant(
|
||
'package',
|
||
'list',
|
||
(this.themeLayout.package && this.themeLayout.package.list) || 'card',
|
||
)
|
||
},
|
||
/** 套餐页搜索:优先本页 search 区块,没有则复用首页搜索样式 */
|
||
packageSearch() {
|
||
const own = this.sectionVariant('package', 'search', '')
|
||
if (own) return own
|
||
return this.homeSearch
|
||
},
|
||
packageEnabled() {
|
||
return !!(this.themeFeatures && this.themeFeatures.package_enabled)
|
||
},
|
||
productGallery() {
|
||
return this.sectionVariant(
|
||
'product',
|
||
'gallery',
|
||
(this.themeLayout.product && this.themeLayout.product.gallery) || 'swiper',
|
||
)
|
||
},
|
||
productPrice() {
|
||
return this.sectionVariant(
|
||
'product',
|
||
'price',
|
||
(this.themeLayout.product && this.themeLayout.product.price) || 'inline',
|
||
)
|
||
},
|
||
productAction() {
|
||
return this.sectionVariant(
|
||
'product',
|
||
'action',
|
||
(this.themeLayout.product && this.themeLayout.product.action) || 'fixed',
|
||
)
|
||
},
|
||
catalogFilter() {
|
||
return this.sectionVariant('catalog', 'filter', 'chip')
|
||
},
|
||
catalogList() {
|
||
return this.sectionVariant('catalog', 'list', 'waterfall')
|
||
},
|
||
searchList() {
|
||
return this.sectionVariant('search', 'list', 'waterfall')
|
||
},
|
||
listStyle() {
|
||
return this.sectionVariant(
|
||
'cart',
|
||
'list',
|
||
(this.themeLayout.list && this.themeLayout.list.style) || 'card',
|
||
)
|
||
},
|
||
mineHeader() {
|
||
return this.sectionVariant(
|
||
'mine',
|
||
'header',
|
||
(this.themeLayout.mine && this.themeLayout.mine.header) || 'gradient',
|
||
)
|
||
},
|
||
mineMenu() {
|
||
return this.sectionVariant(
|
||
'mine',
|
||
'menu',
|
||
(this.themeLayout.mine && this.themeLayout.mine.menu) || 'list',
|
||
)
|
||
},
|
||
themeSkeleton() {
|
||
return this.themeEffect.skeleton || 'shimmer'
|
||
},
|
||
themeCardScheme() {
|
||
return this.themeLayout.card_scheme || 'champagne-foil'
|
||
},
|
||
pageCardScheme() {
|
||
const meta = this.pageMeta(this.currentThemePage || '')
|
||
return (meta && meta.card_scheme) || this.themeCardScheme
|
||
},
|
||
pageCardCaption() {
|
||
const meta = this.pageMeta(this.currentThemePage || '')
|
||
return (meta && meta.card_caption) || ''
|
||
},
|
||
themeChrome() {
|
||
return (this.themeLayout && this.themeLayout.chrome) || {}
|
||
},
|
||
themeTabbar() {
|
||
return this.themeChrome.tabbar || 'plain'
|
||
},
|
||
themeNavbar() {
|
||
return this.themeChrome.navbar || 'solid'
|
||
},
|
||
homeSections() {
|
||
return this.pageSections('home')
|
||
},
|
||
homeSearch() {
|
||
return this.sectionVariant('home', 'search', 'bar')
|
||
},
|
||
/** 当前页皮肤:先读本页 pages.xxx.skin,没有再回落到首页 */
|
||
pageSkin() {
|
||
const page = this.pageMeta(this.currentThemePage || 'home')
|
||
const home = this.pageMeta('home')
|
||
return page.skin || home.skin || 'shop'
|
||
},
|
||
pageDensity() {
|
||
const page = this.pageMeta(this.currentThemePage || 'home')
|
||
const home = this.pageMeta('home')
|
||
return page.density || home.density || 'regular'
|
||
},
|
||
pageFrame() {
|
||
const page = this.pageMeta(this.currentThemePage || 'home')
|
||
const home = this.pageMeta('home')
|
||
return page.frame || home.frame || 'none'
|
||
},
|
||
productInfo() {
|
||
return this.sectionVariant('product', 'info', 'plain')
|
||
},
|
||
productSpec() {
|
||
return this.sectionVariant('product', 'spec', 'plain')
|
||
},
|
||
},
|
||
methods: {
|
||
pageMeta(page) {
|
||
const pages = (this.themeLayout && this.themeLayout.pages) || {}
|
||
return pages[page] || {}
|
||
},
|
||
pagePreset(page) {
|
||
const map = (this.themeLayout && this.themeLayout.page_presets) || {}
|
||
return map[page] || ''
|
||
},
|
||
pageSections(page) {
|
||
const pages = (this.themeLayout && this.themeLayout.pages) || {}
|
||
const list = pages[page] && pages[page].sections
|
||
if (Array.isArray(list) && list.length) {
|
||
return list
|
||
}
|
||
return []
|
||
},
|
||
sectionVisible(page, type) {
|
||
const list = this.pageSections(page)
|
||
if (!list.length) {
|
||
return !(page === 'home' && type === 'product')
|
||
}
|
||
const found = list.find((s) => s.type === type)
|
||
if (!found) return !(page === 'home' && type === 'product')
|
||
return found.visible !== false
|
||
},
|
||
sectionOrder(page, type) {
|
||
const list = this.pageSections(page)
|
||
const index = list.findIndex((s) => s.type === type)
|
||
return index < 0 ? 50 : index
|
||
},
|
||
sectionVariant(page, type, fallback) {
|
||
const list = this.pageSections(page)
|
||
const found = list.find((s) => s.type === type)
|
||
return (found && found.variant) || fallback
|
||
},
|
||
/**
|
||
* 拉主题并按当前路由对齐底栏。
|
||
* 页面自己写了 onShow 时可能盖掉 mixin 钩子,所以抽成方法让页面显式调用。
|
||
*/
|
||
unbindWindowWidth() {
|
||
if (typeof this._unwatchWindowWidth === 'function') {
|
||
this._unwatchWindowWidth()
|
||
this._unwatchWindowWidth = null
|
||
}
|
||
},
|
||
async applyThemeOnShow() {
|
||
// 先对齐当前页底栏,不要等主题接口,否则邻项互切时 pending 还在栏已经画死
|
||
syncTabBarByRoute(this)
|
||
try {
|
||
const theme = await loadAndApplyTheme()
|
||
this.themeVars = (theme && theme.css_vars) || getActiveVars()
|
||
this.themeLayout = (theme && theme.layout) || getActiveLayout()
|
||
this.themeSchemes = (theme && theme.card_schemes) || getActiveSchemes()
|
||
this.themeMeta = {
|
||
code: (theme && theme.code) || '',
|
||
name: (theme && theme.name) || '',
|
||
style_tag: (theme && theme.style_tag) || '',
|
||
fallback: !!(theme && theme.fallback),
|
||
}
|
||
this.themeFeatures = (theme && theme.features) || getThemeFeatures()
|
||
} catch (e) {
|
||
this.themeVars = getActiveVars()
|
||
this.themeLayout = getActiveLayout()
|
||
this.themeMeta = getThemeMeta()
|
||
this.themeFeatures = getThemeFeatures()
|
||
}
|
||
const bar = resolvePageTabBar(this)
|
||
if (bar && typeof bar.pullTheme === 'function') bar.pullTheme()
|
||
},
|
||
},
|
||
created() {
|
||
this._unwatchWindowWidth = watchWindowWidth((width) => {
|
||
this.pcWindowWidth = width
|
||
})
|
||
},
|
||
beforeDestroy() {
|
||
this.unbindWindowWidth()
|
||
},
|
||
beforeUnmount() {
|
||
this.unbindWindowWidth()
|
||
},
|
||
async onShow() {
|
||
await this.applyThemeOnShow()
|
||
},
|
||
}
|