<template>
|
<view class="page">
|
<view class="page_loading" v-if="pageLoading">
|
<view class="loading_spinner"></view>
|
<text class="loading_text">数据加载中...</text>
|
</view>
|
|
<template v-else>
|
<view class="page_bg" v-if="configuration && bgImg" :style="{ backgroundImage: 'url(' + bgImg + ')' }"></view>
|
<view class="page_bg" v-else-if="configuration" :style="{ background: mainBg }"></view>
|
<view class="page_bg default-bg" v-else></view>
|
|
<view class="page_content" :style="contentStyle">
|
<!-- 顶部 Banner -->
|
<view class="banner_wrap">
|
<view class="banner" :class="{ 'banner--custom': hasCustomTopImg }">
|
<image :src="topImg" mode="widthFix" class="banner_img"></image>
|
</view>
|
<view class="user_bar user_bar--banner">
|
<text>{{ username }}</text>
|
<image src="@/static/ic_logout@2x.png" mode="widthFix" @click="loginOut" @mouseenter="playHoverSound"></image>
|
</view>
|
</view>
|
|
<view class="nav_back" v-if="status > 0" @click="onClickSound(fanhuiPage)" @mouseenter="playHoverSound">
|
<image src="@/static/ic_left@2x.png" mode="widthFix"></image>
|
</view>
|
|
<!-- 提交订单 + 预算栏 + 精品优选:全页面常驻 -->
|
<view class="home_sticky_header" :style="{ background: mainBg }">
|
<view class="submit_row">
|
<view
|
class="submit_btn submit_btn--icon"
|
:style="submitBtnStyle"
|
@mouseenter="playHoverSound"
|
@click="onClickSound(submitOrderHandler)">
|
<image
|
class="submit_icon_img"
|
:src="submitOrderIconUrl"
|
mode="aspectFit"></image>
|
<text>提交订单</text>
|
</view>
|
</view>
|
|
<view class="home_top_section" :class="{ 'home_top_section--compact': status === 2 }" :style="homeTopSectionStyle">
|
<view class="order_bar">
|
<view class="order_left">
|
<text class="order_label">用户预算</text>
|
<text class="order_currency">¥</text>
|
<input type="digit" v-model="userBudget" placeholder="0" class="budget_input" />
|
<view class="remain_inline">
|
<text class="remain_label">剩余经费</text>
|
<text class="remain_val">¥ {{ remainingBudget }}</text>
|
</view>
|
</view>
|
<view class="order_right">
|
<view class="order_no_row">
|
<text class="order_label">订单编号</text>
|
<text class="order_no">{{ orderNo }}</text>
|
</view>
|
</view>
|
</view>
|
|
<view class="featured" v-if="featuredList.length">
|
<view class="featured_left">
|
<text class="featured_title">精品优选</text>
|
<text class="featured_sub">实测多维综合评定</text>
|
</view>
|
<view class="featured_products">
|
<view
|
class="featured_item"
|
v-for="(feat, fi) in featuredList"
|
:key="fi"
|
@mouseenter="playHoverSound">
|
<view class="featured_img_wrap">
|
<image
|
v-if="featuredImgUrl(feat)"
|
:src="featuredImgUrl(feat)"
|
mode="aspectFit"
|
class="featured_img"></image>
|
<view v-else class="featured_img_placeholder"></view>
|
</view>
|
<view class="featured_info">
|
<text class="featured_name">{{ featuredTitle(feat) }}</text>
|
<view class="featured_tag_row">
|
<text class="tag tag_dim" v-if="feat.tags && feat.tags[0]">{{ feat.tags[0] }}</text>
|
<text
|
class="tag"
|
:class="fi === 0 ? 'tag_blue' : 'tag_green'"
|
v-if="feat.tags && feat.tags[1]">{{ feat.tags[1] }}</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<view class="table_head_wrap" v-if="status === 0">
|
<view class="shop_table_head">
|
<view
|
class="col col_cat category_dropdown_anchor"
|
@mouseenter="onCategoryHeadEnter"
|
@mouseleave="onCategoryHeadLeave"
|
@click="onCategoryHeadClick">
|
<text>品类</text>
|
<text class="arrow">▼</text>
|
<view
|
class="category_picker"
|
v-if="showCategoryPicker"
|
:style="dropdownStyle"
|
@click.stop>
|
<view
|
class="category_picker_item"
|
v-for="cat in availableCategories"
|
:key="cat.id"
|
@click="onClickSound(() => addCategoryRow(cat))"
|
@mouseenter="playHoverSound">
|
<image v-if="cat.imgurl" :src="cat.prefixUrl + cat.imgurl" mode="aspectFit"></image>
|
<text>{{ cat.name }}</text>
|
</view>
|
<view class="category_picker_empty" v-if="!availableCategories.length">暂无可添加品类</view>
|
</view>
|
</view>
|
<view class="col col_model">型号</view>
|
<view class="col col_zd">旗舰价</view>
|
<view class="col col_price">指导价</view>
|
</view>
|
</view>
|
|
<view class="table_head_wrap product_list_head_wrap" v-if="status === 1">
|
<view class="shop_table_head product_shop_table_head">
|
<view
|
class="col col_cat product_brand_col category_dropdown_anchor"
|
@mouseenter="onBrandHeadEnter"
|
@mouseleave="onBrandHeadLeave"
|
@click="onBrandHeadClick">
|
<text>品牌</text>
|
<text class="arrow">▼</text>
|
<text class="brand_echo_inline">{{ shopPageBrand.name || '全部' }}</text>
|
<view
|
class="brand_picker"
|
v-if="showBrandPicker && brandData.length"
|
:style="dropdownStyle"
|
@click.stop>
|
<view
|
class="brand_picker_item"
|
v-for="(brand, bi) in brandData"
|
:key="brand.id || 'all-' + bi"
|
:class="{ active: String(shopPageBrand.id) === String(brand.id) }"
|
@click="onClickSound(() => selectBrand(brand))"
|
@mouseenter="playHoverSound">
|
{{ brand.name }}
|
</view>
|
</view>
|
</view>
|
<view class="col col_model product_search_col">
|
<view class="product_search_inline" :style="searchBarStyle">
|
<image class="search_icon" src="@/static/ic_search@2x.png" mode="aspectFit"></image>
|
<view class="search_divider"></view>
|
<input type="text" v-model="title" placeholder="搜索型号" @input="onProductSearch" />
|
</view>
|
</view>
|
<view class="col col_zd product_cat_col product_cat_col--span">
|
<view class="product_cat_inner">
|
<image
|
v-if="productListCategoryImg"
|
:src="productListCategoryImg"
|
mode="aspectFit"
|
class="product_cat_icon"></image>
|
<text class="cat_line">{{ productListCategoryText }}</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 首页表格 -->
|
<template v-if="status === 0">
|
<view class="shop_table" :style="{ background: mainBg }">
|
<view class="shop_table_body">
|
<view class="shop_table_empty" v-if="!shopList.length">
|
<text>暂无品类数据</text>
|
</view>
|
<view
|
class="shop_row"
|
v-for="(row, index) in shopList"
|
:key="index"
|
:id="'shop_row_' + index"
|
:class="{ expanded: hoverRowIndex === index }"
|
@mouseenter="onRowHover(index, true)"
|
@mouseleave="onRowHover(index, false)"
|
@click="onRowTap(index)">
|
|
<!-- 普通行 -->
|
<view class="shop_row_main" v-if="hoverRowIndex !== index">
|
<view class="row_cat_cell col col_cat" @click.stop="onClickSound(() => openProductList(index))" @mouseenter="playHoverSound">
|
<image v-if="row.categoryImgurl" :src="row.categoryImgurl" mode="aspectFit"></image>
|
<text class="cell_ellipsis">{{ row.categoryName }}</text>
|
</view>
|
<view class="row_info_group">
|
<view class="col col_model" :class="{ col_model_link: row.name }" @click.stop="onClickSound(() => onModelClick(index))">
|
<text class="cell_ellipsis">{{ row.name || '' }}</text>
|
</view>
|
<view class="col col_zd">
|
<text class="cell_ellipsis">{{ row.zdPrice || '' }}</text>
|
</view>
|
<view class="col col_price">
|
<input type="digit" v-model="row.price" placeholder="" />
|
</view>
|
</view>
|
</view>
|
|
<!-- 悬浮展开(参考截图) -->
|
<view class="shop_row_expand" v-else>
|
<view class="expand_cat_card" @click.stop="onClickSound(() => openProductList(index))" @mouseenter="playHoverSound">
|
<view class="row_delete" @click.stop="onClickSound(() => removeRow(index))" @mouseenter="playHoverSound">
|
<text>×</text>
|
</view>
|
<image v-if="row.categoryImgurl" :src="row.categoryImgurl" mode="aspectFit" class="expand_cat_img"></image>
|
<text class="expand_cat_name">{{ row.categoryName }}</text>
|
</view>
|
<view class="expand_panel">
|
<view class="expand_data_row" v-if="row.name">
|
<text class="expand_model expand_model_link" @click.stop="onClickSound(() => openRowProductPk(index))">{{ row.name }}</text>
|
<text class="expand_zd">{{ row.zdPrice }}</text>
|
<input type="digit" v-model="row.price" class="expand_price_input" />
|
</view>
|
<view class="sub_cat_grid" v-if="row.children && row.children.length">
|
<view
|
class="sub_cat_icon_item"
|
v-for="sub in row.children.slice(0, 5)"
|
:key="sub.id"
|
@click.stop="onClickSound(() => selectSubCategory(index, sub))"
|
@mouseenter="playHoverSound">
|
<image :src="subIcon(sub, row)" mode="aspectFit"></image>
|
<text>{{ sub.name }}</text>
|
</view>
|
</view>
|
<view class="expand_search_wrap">
|
<view class="expand_search" :style="searchBarStyle">
|
<image class="search_icon" src="@/static/ic_search@2x.png" mode="aspectFit"></image>
|
<input type="text" v-model="row.modelVal" placeholder="搜索商品名称/型号" @input="searchModel(row)" />
|
</view>
|
<view class="model_suggest_list" v-if="hasModelKeyword(row) && modelOptions(row).length">
|
<view
|
class="model_suggest_item"
|
v-for="(g, gi) in modelOptions(row)"
|
:key="g.id || gi"
|
@click.stop="onClickSound(() => selectGoodsFromSearch(index, g))"
|
@mouseenter="playHoverSound">
|
{{ g.name }}
|
</view>
|
</view>
|
<view class="model_suggest_empty" v-else-if="hasModelKeyword(row)">暂无匹配商品</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<!-- 商品列表 -->
|
<template v-if="status === 1">
|
<view class="product_page" :style="{ background: mainBg }">
|
<view class="product_grid">
|
<view
|
class="product_card"
|
v-for="(item, pi) in displayProducts"
|
:key="item.id || pi"
|
@click="onClickSound(() => clickProduct(item))"
|
@mouseenter="playHoverSound">
|
<view class="product_card_img">
|
<image :src="productImg(item)" mode="aspectFit"></image>
|
</view>
|
<view class="product_card_info">
|
<text class="product_brand">{{ item.brandName || '' }}</text>
|
<text class="product_model">{{ item.name }}</text>
|
<text class="product_price_label">指导价 ¥ {{ item.price || '' }}</text>
|
</view>
|
</view>
|
<view class="product_card placeholder" v-if="!displayProducts.length">
|
<text>暂无商品</text>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<!-- PK -->
|
<template v-if="status === 2">
|
<view class="pk_page" :style="pkShowcaseTheme">
|
<view class="pk_cards">
|
<view class="pk_side" @mouseenter="pkHoverSide = 'left'" @mouseleave="pkHoverSide = ''">
|
<view class="pk_delete" v-if="pkHoverSide === 'left' && leftShop.name" @click.stop="onClickSound(clearLeftShop)" @mouseenter="playHoverSound">×</view>
|
<template v-if="leftShop.name">
|
<view class="pk_showcase">
|
<view class="pk_showcase_glow"></view>
|
<view class="pk_showcase_frame">
|
<view class="pk_showcase_shine"></view>
|
<view class="pk_showcase_visual">
|
<view
|
class="pk_showcase_img_card"
|
@click.stop="onClickSound(() => openPkImagePreview('left'))"
|
@mouseenter="playHoverSound">
|
<image
|
class="pk_showcase_img"
|
:src="pkImgUrl(leftShop)"
|
mode="aspectFit"></image>
|
</view>
|
<view class="pk_showcase_reflect" aria-hidden="true">
|
<image
|
class="pk_showcase_reflect_img"
|
:src="pkImgUrl(leftShop)"
|
mode="aspectFit"></image>
|
</view>
|
<view class="pk_showcase_ground" aria-hidden="true"></view>
|
</view>
|
</view>
|
</view>
|
<view class="pk_podium"></view>
|
<view class="pk_detail">
|
<view class="pk_detail_head" :style="tableHeaderStyle">{{ leftShop.name }}</view>
|
<view class="pk_detail_body">
|
<view class="pk_price_cell">
|
<text class="pk_price_label">期间价</text>
|
<text class="pk_price_val">¥{{ leftShop.zdPrice }}</text>
|
</view>
|
<view class="pk_price_cell pk_price_cell--hot">
|
<text class="pk_price_label">指导价</text>
|
<text class="pk_price_val">¥{{ leftShop.price }}</text>
|
</view>
|
</view>
|
</view>
|
</template>
|
<view class="pk_empty" v-else @click="onClickSound(() => openSearch('left'))" @mouseenter="playHoverSound">
|
<text>+ 选择商品</text>
|
</view>
|
</view>
|
|
<view class="pk_vs" :style="{ color: pkVsColor }">VS</view>
|
|
<view class="pk_side" @mouseenter="pkHoverSide = 'right'" @mouseleave="pkHoverSide = ''">
|
<view class="pk_delete" v-if="pkHoverSide === 'right' && rightShop.name" @click.stop="onClickSound(clearRightShop)" @mouseenter="playHoverSound">×</view>
|
<template v-if="rightShop.name">
|
<view class="pk_showcase">
|
<view class="pk_showcase_glow"></view>
|
<view class="pk_showcase_frame">
|
<view class="pk_showcase_shine"></view>
|
<view class="pk_showcase_visual">
|
<view
|
class="pk_showcase_img_card"
|
@click.stop="onClickSound(() => openPkImagePreview('right'))"
|
@mouseenter="playHoverSound">
|
<image
|
class="pk_showcase_img"
|
:src="pkImgUrl(rightShop)"
|
mode="aspectFit"></image>
|
</view>
|
<view class="pk_showcase_reflect" aria-hidden="true">
|
<image
|
class="pk_showcase_reflect_img"
|
:src="pkImgUrl(rightShop)"
|
mode="aspectFit"></image>
|
</view>
|
<view class="pk_showcase_ground" aria-hidden="true"></view>
|
</view>
|
</view>
|
</view>
|
<view class="pk_podium"></view>
|
<view class="pk_detail">
|
<view class="pk_detail_head" :style="tableHeaderStyle">{{ rightShop.name }}</view>
|
<view class="pk_detail_body">
|
<view class="pk_price_cell">
|
<text class="pk_price_label">期间价</text>
|
<text class="pk_price_val">¥{{ rightShop.zdPrice }}</text>
|
</view>
|
<view class="pk_price_cell pk_price_cell--hot">
|
<text class="pk_price_label">指导价</text>
|
<text class="pk_price_val">¥{{ rightShop.price }}</text>
|
</view>
|
</view>
|
</view>
|
</template>
|
<view class="pk_empty" v-else @click="onClickSound(() => openSearch('right'))" @mouseenter="playHoverSound">
|
<text>+ 选择商品</text>
|
</view>
|
</view>
|
</view>
|
|
<view class="pk_params" v-if="leftShop.name || rightShop.name">
|
<view class="pk_param_col">
|
<template v-if="leftShop.name">
|
<view class="pk_param_head" :class="{ 'pk_param_head--solo': !pkcontent }" :style="tableHeaderStyle">
|
<view class="pk_action_group">
|
<view class="pk_change" @click.stop="onClickSound(() => openSearch('left'))" @mouseenter="playHoverSound">
|
<text class="pk_btn_ico">↻</text>
|
<text class="pk_btn_txt">换个商品</text>
|
</view>
|
<view class="pk_confirm pk_confirm--inhead" @click="onClickSound(confirmLeftToRow)" @mouseenter="playHoverSound">
|
<text class="pk_btn_ico pk_btn_ico--check">✓</text>
|
<text class="pk_btn_txt">选用左侧</text>
|
</view>
|
</view>
|
</view>
|
<view class="pk_param_pills" v-if="pkcontent">
|
<view class="pill" v-for="(p, pi) in param1" :key="'m-' + pi">
|
<text class="pill_label">{{ p.name }}</text>
|
<text class="pill_val">{{ p.val }}</text>
|
</view>
|
<view class="pill pill_diff" v-for="(p, pi) in (leftShop.param2 || [])" :key="'u-' + pi">
|
<text class="pill_label">{{ p.name }}</text>
|
<text class="pill_val">{{ p.val }}</text>
|
</view>
|
</view>
|
</template>
|
</view>
|
<view class="pk_vs pk_vs--spacer" aria-hidden="true">VS</view>
|
<view class="pk_param_col">
|
<template v-if="rightShop.name">
|
<view class="pk_param_head" :class="{ 'pk_param_head--solo': !pkcontent }" :style="tableHeaderStyle">
|
<view class="pk_action_group">
|
<view class="pk_change" @click.stop="onClickSound(() => openSearch('right'))" @mouseenter="playHoverSound">
|
<text class="pk_btn_ico">↻</text>
|
<text class="pk_btn_txt">换个商品</text>
|
</view>
|
<view class="pk_confirm pk_confirm--inhead" @click="onClickSound(confirmRightToRow)" @mouseenter="playHoverSound">
|
<text class="pk_btn_ico pk_btn_ico--check">✓</text>
|
<text class="pk_btn_txt">选用右侧</text>
|
</view>
|
</view>
|
</view>
|
<view class="pk_param_pills" v-if="pkcontent">
|
<view class="pill" v-for="(p, pi) in param2" :key="'m-' + pi">
|
<text class="pill_label">{{ p.name }}</text>
|
<text class="pill_val">{{ p.val }}</text>
|
</view>
|
<view class="pill pill_diff" v-for="(p, pi) in (rightShop.param2 || [])" :key="'u-' + pi">
|
<text class="pill_label">{{ p.name }}</text>
|
<text class="pill_val">{{ p.val }}</text>
|
</view>
|
</view>
|
</template>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<search
|
ref="searchRef"
|
:search="configuration ? configuration.search : null"
|
:conMark="configuration"
|
:fontColor="accentColor"
|
:categoryList="categoryList"
|
:shopList="shopPageData"
|
:allGoods="allGoods"
|
:categoryid="currentCategoryId"
|
:status="status"
|
:categoryName="currentCategoryName"
|
:excludeGoodsId="pkSearchExcludeGoodsId"
|
@result="result" />
|
<bigImg ref="pkBigImg" :imgList="pkPreviewImgList" />
|
</view>
|
</template>
|
</view>
|
</template>
|
|
<script>
|
import { mapState } from 'vuex'
|
import search from '@/components/search.vue'
|
import bigImg from '@/components/bigImg.vue'
|
import { playHoverSound, playClickSound, setupSoundUnlock } from '@/utils/sound.js'
|
import { ANCHOR_PAGE_V3, getAnchorHomePath, normalizeAnchorPageVersion } from '@/utils/anchorHome.js'
|
import { filterGoods, filterBrandsByCategory, matchKeyword } from '@/utils/goodsFilter.js'
|
import {
|
loadH5InitData,
|
generateOrderNo,
|
submitOrder,
|
logout
|
} from '@/apis/index.js'
|
|
const DEFAULT_MAIN = '#E8DCC8'
|
const DEFAULT_HEADER = '#4A3728'
|
const DEFAULT_ROW = '#FFFFFF'
|
|
export default {
|
components: { search, bigImg },
|
data() {
|
return {
|
status: 0,
|
pageLoading: true,
|
configuration: null,
|
topImg: require('@/static/banner.png'),
|
submitOrderIcon: require('@/static/ic_submit_order@2x.png'),
|
bgImg: '',
|
webParamPath: '',
|
|
allGoods: [],
|
allBrands: [],
|
|
shopList: [],
|
categoryList: [],
|
userBudget: 0,
|
orderNo: '',
|
sessionCreateTime: null,
|
|
showCategoryPicker: false,
|
categoryPickerTimer: null,
|
showBrandPicker: false,
|
brandPickerTimer: null,
|
hoverRowIndex: -1,
|
activeRowIndex: -1,
|
|
currentCategoryId: '',
|
currentCategoryName: '',
|
currentSubCategoryId: '',
|
currentSubCategoryName: '',
|
|
leftShop: {},
|
rightShop: {},
|
param1: [],
|
param2: [],
|
pkcontent: false,
|
pkHoverSide: '',
|
pkPreviewImgList: [],
|
pkSearchSide: '',
|
|
shopPageData: [],
|
shopPageDataSou: [],
|
shopPageBrand: { id: '', name: '' },
|
brandData: [],
|
title: '',
|
|
fontColor: '#FFDC6C'
|
}
|
},
|
computed: {
|
...mapState(['User']),
|
remainingBudget() {
|
const budget = Number(this.userBudget) || 0
|
const used = this.shopList.reduce((sum, row) => sum + (Number(row.price) || 0), 0)
|
return (budget - used).toFixed(2)
|
},
|
contentStyle() {
|
const w = this.configuration ? this.configuration.rangeSize : 750
|
return { maxWidth: w + 'px', minWidth: w + 'px' }
|
},
|
mainBg() {
|
if (!this.configuration) return DEFAULT_MAIN
|
const pageBg = this.configuration.pageBg
|
if (pageBg) {
|
const mode = Number(pageBg.mode) || 0
|
if (mode === 1) {
|
return this.percentage(pageBg.bgColor || DEFAULT_MAIN, pageBg.alpha || 100)
|
}
|
return DEFAULT_MAIN
|
}
|
const main = this.configuration.main
|
if (!main) return DEFAULT_MAIN
|
if (Number(main.bgType) === 0) return DEFAULT_MAIN
|
return this.percentage(main.bgColor || DEFAULT_MAIN, main.alpha || 100)
|
},
|
themeStyle() {
|
const theme = this.resolveThemeConfig()
|
return {
|
background: Number(theme.bgType) === 1 ? (theme.bgColor || DEFAULT_HEADER) : DEFAULT_HEADER,
|
color: Number(theme.colorType) === 1 ? (theme.color || '#FFFFFF') : '#FFFFFF'
|
}
|
},
|
homeTopSectionStyle() {
|
const { background: bg, color } = this.themeStyle
|
return {
|
background: bg,
|
color,
|
'--home-top-bg': bg
|
}
|
},
|
headerStyle() {
|
return this.themeStyle
|
},
|
tableHeaderStyle() {
|
return this.themeStyle
|
},
|
rowStyle() {
|
const t = (this.configuration && this.configuration.table) || {}
|
return { background: t.rowBg || DEFAULT_ROW }
|
},
|
dropdownStyle() {
|
return { background: this.themeStyle.background }
|
},
|
searchBarStyle() {
|
const s = (this.configuration && this.configuration.search) || {}
|
const defaultBg = 'rgba(255, 255, 255, 0.92)'
|
if (Number(s.bgType) !== 1) {
|
return { background: defaultBg }
|
}
|
return {
|
background: this.percentage(s.bgColor || '#FFFFFF', s.bgAlpha || 100)
|
}
|
},
|
productCardStyle() {
|
const p = (this.configuration && this.configuration.productList) || {}
|
return {
|
background: p.bgType === 1 ? this.percentage(p.bgColor || DEFAULT_ROW, p.bgAlpha || 100) : DEFAULT_ROW
|
}
|
},
|
pkVsColor() {
|
return (this.configuration && this.configuration.pk && this.configuration.pk.vsColor) || '#FF8C42'
|
},
|
pkThemeColor() {
|
const pk = (this.configuration && this.configuration.pk) || {}
|
if (Number(pk.bgColorType) === 1) {
|
return pk.bgColor || '#FF8C42'
|
}
|
if (pk.bgColorType == null && pk.vsColor) {
|
return pk.vsColor
|
}
|
return '#FF8C42'
|
},
|
pkShowcaseTheme() {
|
const primary = this.themeStyle.background
|
const accent = this.pkThemeColor
|
const gold = this.fontColor || '#FFD88A'
|
return {
|
'--pk-show-primary': primary,
|
'--pk-show-accent': accent,
|
'--pk-show-gold': gold,
|
'--pk-show-primary-soft': this.hexToRgba(primary, 0.22),
|
'--pk-show-accent-soft': this.hexToRgba(accent, 0.38),
|
'--pk-show-gold-soft': this.hexToRgba(gold, 0.5),
|
'--pk-show-accent-faint': this.hexToRgba(accent, 0.12)
|
}
|
},
|
accentColor() {
|
return this.fontColor
|
},
|
pkSearchExcludeGoodsId() {
|
if (this.pkSearchSide === 'left' && this.rightShop && this.rightShop.id != null) {
|
return this.rightShop.id
|
}
|
if (this.pkSearchSide === 'right' && this.leftShop && this.leftShop.id != null) {
|
return this.leftShop.id
|
}
|
return ''
|
},
|
topLevelCategories() {
|
return (this.categoryList || []).filter(c => c.parentId == null || c.parentId === 0)
|
},
|
availableCategories() {
|
return this.topLevelCategories
|
},
|
username() {
|
return (this.User && this.User.username) ? this.User.username : ''
|
},
|
featuredList() {
|
const featured = this.configuration && this.configuration.featured
|
if (!Array.isArray(featured)) return []
|
return featured.slice(0, 2)
|
},
|
displayProducts() {
|
return Array.isArray(this.shopPageDataSou) ? this.shopPageDataSou : []
|
},
|
productListCategoryImg() {
|
const row = this.activeRowIndex >= 0 ? this.shopList[this.activeRowIndex] : null
|
return (row && row.categoryImgurl) ? row.categoryImgurl : ''
|
},
|
productListCategoryText() {
|
const level1 = (this.currentCategoryName || '').trim()
|
const level2 = (this.currentSubCategoryName || '').trim()
|
if (level1 && level2) return `${level1} / ${level2}`
|
return level1 || level2
|
},
|
listTitle() {
|
if (this.currentSubCategoryId) {
|
const row = this.shopList[this.activeRowIndex]
|
return row ? (row.subCategoryName || row.categoryName) : '商品列表'
|
}
|
return this.currentCategoryName || '商品列表'
|
},
|
hasCustomTopImg() {
|
const top = this.configuration && this.configuration.topImg
|
if (!top) return false
|
const type = Number(top.type)
|
return type === 1 && !!(top.imgurl || top.img)
|
},
|
submitOrderIconUrl() {
|
return this.submitOrderIcon || require('@/static/ic_submit_order@2x.png')
|
},
|
submitBtnStyle() {
|
const DEFAULT_SUBMIT_COLOR = '#4A3728'
|
const bgCfg = (this.configuration && this.configuration.submitBtnBg) || {}
|
const colorCfg = (this.configuration && this.configuration.submitBtnColor) || {}
|
const style = {
|
color: Number(colorCfg.colorType) === 1
|
? (colorCfg.color || DEFAULT_SUBMIT_COLOR)
|
: DEFAULT_SUBMIT_COLOR
|
}
|
const defaultBg = '#FFFFFF'
|
if (Number(bgCfg.bgType) !== 1) {
|
style.background = defaultBg
|
} else {
|
style.background = this.percentage(bgCfg.bgColor || defaultBg, bgCfg.bgAlpha || 100)
|
}
|
return style
|
}
|
},
|
onLoad() {
|
setupSoundUnlock()
|
this.sessionCreateTime = new Date()
|
this.loadAllData()
|
},
|
methods: {
|
playHoverSound,
|
playClickSound,
|
onClickSound(fn) {
|
playClickSound()
|
if (typeof fn === 'function') fn()
|
},
|
|
percentage(bgColor, alpha) {
|
const res = +(Number(alpha) * 2.55).toFixed(0)
|
const hex = res.toString(16).padStart(2, '0')
|
return (bgColor || DEFAULT_HEADER) + hex
|
},
|
|
resolveThemeConfig() {
|
const cfg = this.configuration
|
if (!cfg) {
|
return { bgType: 0, bgColor: DEFAULT_HEADER, colorType: 0, color: '#FFFFFF' }
|
}
|
if (cfg.theme) return cfg.theme
|
const t = cfg.table || {}
|
const h = cfg.header || {}
|
return {
|
bgType: Number(t.headerBgType) === 1 ? 1 : (Number(h.bgType) === 1 ? 1 : 0),
|
bgColor: t.headerBg || h.bgColor || DEFAULT_HEADER,
|
colorType: Number(t.headerColorType) === 1 ? 1 : (Number(h.colorType) === 1 ? 1 : 0),
|
color: t.headerColor || h.color || '#FFFFFF'
|
}
|
},
|
|
hexToRgba(hex, alpha) {
|
if (!hex) return `rgba(74, 55, 40, ${alpha})`
|
let h = String(hex).replace('#', '')
|
if (h.length === 3) {
|
h = h.split('').map(c => c + c).join('')
|
}
|
const n = parseInt(h, 16)
|
if (Number.isNaN(n)) return `rgba(74, 55, 40, ${alpha})`
|
return `rgba(${(n >> 16) & 255}, ${(n >> 8) & 255}, ${n & 255}, ${alpha})`
|
},
|
|
loadAllData() {
|
this.pageLoading = true
|
loadH5InitData().then(res => {
|
if (!res || !res.data) return
|
const version = normalizeAnchorPageVersion(res.data.anchorPageVersion)
|
if (version !== ANCHOR_PAGE_V3) {
|
uni.redirectTo({ url: getAnchorHomePath(version) })
|
return
|
}
|
this.applyInitData(res.data)
|
}).catch(() => {
|
uni.showToast({ title: '数据加载失败', icon: 'none' })
|
}).finally(() => {
|
this.pageLoading = false
|
})
|
},
|
|
applyInitData(data) {
|
if (data.anchorParam) {
|
try {
|
this.configuration = JSON.parse(data.anchorParam)
|
} catch (e) {
|
console.error('anchorParam parse error', e)
|
this.configuration = null
|
}
|
}
|
this.applyBannerImages(data.resourcePath || '')
|
this.webParamPath = data.resourcePath || ''
|
this.categoryList = Array.isArray(data.categories) ? data.categories : []
|
this.allGoods = Array.isArray(data.goodsList) ? data.goodsList : []
|
this.allBrands = Array.isArray(data.brandList) ? data.brandList : []
|
this.orderNo = data.orderNo || ''
|
this.initShopListFromCategories()
|
},
|
|
resolveMediaUrl(raw, feat) {
|
if (!raw && feat) {
|
raw = feat.imgaddr || feat.imgurl || feat.img || ''
|
}
|
if (!raw) return ''
|
const str = String(raw)
|
const base = this.webParamPath || ''
|
|
if (/^https?:\/\//i.test(str)) {
|
const secondHttp = str.indexOf('http', str.indexOf('://') + 3)
|
if (secondHttp > 0) {
|
return str.substring(secondHttp)
|
}
|
return str
|
}
|
|
if (base && str.indexOf(base) === 0) {
|
return str
|
}
|
|
if (feat && feat.imgaddr && !feat.imgurl && !feat.img) {
|
return base ? base + String(feat.imgaddr).replace(/^\//, '') : feat.imgaddr
|
}
|
|
return base ? base + str.replace(/^\//, '') : str
|
},
|
|
resolveConfigImg(imgCfg, resourcePath, fallback) {
|
if (!imgCfg) return fallback
|
const type = Number(imgCfg.type)
|
if (Number.isNaN(type) || type === 0) return fallback
|
if (imgCfg.imgurl) {
|
if (/^https?:\/\//i.test(imgCfg.imgurl)) {
|
return imgCfg.imgurl
|
}
|
if (resourcePath) {
|
return resourcePath + String(imgCfg.imgurl).replace(/^\//, '')
|
}
|
return imgCfg.imgurl
|
}
|
if (resourcePath && imgCfg.img) {
|
return resourcePath + imgCfg.img
|
}
|
return fallback
|
},
|
|
applyBannerImages(resourcePath) {
|
const defaultBanner = require('@/static/banner.png')
|
const webParamPath = resourcePath || ''
|
const defaultSubmitIcon = require('@/static/ic_submit_order@2x.png')
|
if (!this.configuration) {
|
this.topImg = defaultBanner
|
this.submitOrderIcon = defaultSubmitIcon
|
return
|
}
|
this.topImg = this.resolveConfigImg(this.configuration.topImg, webParamPath, defaultBanner)
|
this.submitOrderIcon = this.resolveConfigImg(
|
this.configuration.submitBtnIcon,
|
webParamPath,
|
defaultSubmitIcon
|
)
|
this.bgImg = ''
|
const pageBg = this.configuration.pageBg
|
if (pageBg && Number(pageBg.mode) === 2) {
|
const resolved = this.resolveConfigImg(
|
{ type: 1, img: pageBg.img, imgurl: pageBg.imgurl },
|
webParamPath,
|
''
|
)
|
if (resolved) this.bgImg = resolved
|
return
|
}
|
const adImg = this.configuration.adImg
|
if (adImg && Number(adImg.type) === 1) {
|
const adResolved = this.resolveConfigImg(adImg, webParamPath, '')
|
if (adResolved) this.bgImg = adResolved
|
}
|
},
|
|
initShopListFromCategories() {
|
this.shopList = this.topLevelCategories.map(cat => this.createShopRow(cat))
|
},
|
|
loadOrderNo() {
|
generateOrderNo().then(res => {
|
this.orderNo = res.data || ''
|
})
|
},
|
|
goodsForRow(row, keyword) {
|
return filterGoods(this.allGoods, {
|
categoryId: row.categoryId,
|
subCategoryId: row.subCategoryId || '',
|
keyword: keyword || ''
|
})
|
},
|
|
createShopRow(cat, subCat) {
|
const children = (cat.children || []).slice(0, 5)
|
return {
|
categoryId: cat.id,
|
categoryName: cat.name,
|
categoryImgurl: cat.imgurl ? cat.prefixUrl + cat.imgurl : '',
|
subCategoryId: subCat ? subCat.id : '',
|
subCategoryName: subCat ? subCat.name : '',
|
name: '',
|
goodsId: '',
|
zdPrice: '',
|
price: '',
|
hoverActive: false,
|
modelVal: '',
|
modelSearchList: [],
|
children,
|
prefixUrl: cat.prefixUrl || ''
|
}
|
},
|
|
onCategoryHeadEnter() {
|
this.playHoverSound()
|
if (this.categoryPickerTimer) {
|
clearTimeout(this.categoryPickerTimer)
|
this.categoryPickerTimer = null
|
}
|
this.showCategoryPicker = true
|
},
|
|
onCategoryHeadLeave() {
|
this.categoryPickerTimer = setTimeout(() => {
|
this.showCategoryPicker = false
|
}, 180)
|
},
|
|
onCategoryHeadClick() {
|
const isTouch = typeof window !== 'undefined' &&
|
('ontouchstart' in window || (typeof navigator !== 'undefined' && navigator.maxTouchPoints > 0))
|
if (isTouch) {
|
this.showCategoryPicker = !this.showCategoryPicker
|
}
|
},
|
|
addCategoryRow(cat) {
|
this.shopList.push(this.createShopRow(cat))
|
this.showCategoryPicker = false
|
if (this.categoryPickerTimer) {
|
clearTimeout(this.categoryPickerTimer)
|
this.categoryPickerTimer = null
|
}
|
this.scrollToLastShopRow()
|
},
|
|
scrollToLastShopRow() {
|
const lastIndex = this.shopList.length - 1
|
if (lastIndex < 0) return
|
this.$nextTick(() => {
|
setTimeout(() => {
|
const rowId = 'shop_row_' + lastIndex
|
if (typeof document !== 'undefined') {
|
const el = document.getElementById(rowId)
|
if (el && el.scrollIntoView) {
|
el.scrollIntoView({ behavior: 'smooth', block: 'center' })
|
return
|
}
|
}
|
uni.pageScrollTo({
|
selector: '#' + rowId,
|
duration: 300
|
})
|
}, 80)
|
})
|
},
|
|
removeRow(index) {
|
this.shopList.splice(index, 1)
|
if (this.hoverRowIndex === index) this.hoverRowIndex = -1
|
},
|
|
onRowHover(index, active) {
|
this.hoverRowIndex = active ? index : -1
|
},
|
|
onRowTap(index) {
|
const isTouch = typeof window !== 'undefined' &&
|
('ontouchstart' in window || (typeof navigator !== 'undefined' && navigator.maxTouchPoints > 0))
|
if (isTouch) {
|
this.hoverRowIndex = this.hoverRowIndex === index ? -1 : index
|
}
|
},
|
|
hasModelKeyword(row) {
|
return !!(row && row.modelVal && String(row.modelVal).trim())
|
},
|
|
searchModel(row) {
|
const kw = (row.modelVal || '').trim()
|
if (!kw) {
|
row.modelSearchList = []
|
this.$forceUpdate()
|
return
|
}
|
row.modelSearchList = this.goodsForRow(row, kw)
|
this.$forceUpdate()
|
},
|
|
modelOptions(row) {
|
if (!this.hasModelKeyword(row)) return []
|
return row.modelSearchList || []
|
},
|
|
selectGoodsFromSearch(index, goods) {
|
this.applyGoodsToRow(index, goods)
|
this.hoverRowIndex = -1
|
},
|
|
selectSubCategory(index, sub) {
|
const row = this.shopList[index]
|
if (!row || !sub) return
|
this.openProductList(index, sub)
|
},
|
|
onModelClick(index) {
|
const row = this.shopList[index]
|
if (row && row.name) {
|
this.openRowProductPk(index)
|
}
|
},
|
|
openRowProductPk(index) {
|
const row = this.shopList[index]
|
if (!row || !row.name) return
|
let goods = null
|
if (row.goodsId && this.allGoods && this.allGoods.length) {
|
goods = this.allGoods.find(g => String(g.id) === String(row.goodsId))
|
}
|
if (goods) {
|
goods = JSON.parse(JSON.stringify(goods))
|
goods.price = row.price
|
goods.zdPrice = row.zdPrice
|
} else {
|
goods = {
|
id: row.goodsId,
|
name: row.name,
|
zdPrice: row.zdPrice,
|
price: row.price,
|
prefixUrl: row.prefixUrl,
|
imgurl: row.imgurl,
|
multifileList: row.multifileList,
|
goodsParamList: row.goodsParamList,
|
brandId: row.brandId,
|
brandName: row.brandName,
|
categoryId: row.categoryId
|
}
|
}
|
this.activeRowIndex = index
|
this.currentCategoryId = row.categoryId
|
this.currentCategoryName = row.categoryName
|
this.currentSubCategoryId = row.subCategoryId || ''
|
this.currentSubCategoryName = row.subCategoryName || ''
|
this.leftShop = goods
|
this.rightShop = {}
|
this.param1 = []
|
this.param2 = []
|
this.pkcontent = false
|
this.hoverRowIndex = -1
|
this.status = 2
|
},
|
|
openProductList(index, subCat = null) {
|
const row = this.shopList[index]
|
if (!row) return
|
row.subCategoryId = ''
|
row.subCategoryName = ''
|
this.activeRowIndex = index
|
this.currentCategoryId = row.categoryId
|
this.currentCategoryName = row.categoryName
|
this.currentSubCategoryId = subCat ? subCat.id : ''
|
this.currentSubCategoryName = subCat ? subCat.name : ''
|
this.title = ''
|
this.shopPageBrand = { id: '', name: '全部' }
|
this.showBrandPicker = false
|
this.leftShop = {}
|
this.rightShop = {}
|
this.pkcontent = false
|
this.hoverRowIndex = -1
|
this.status = 1
|
this.loadBrands(row.categoryId)
|
this.loadProducts()
|
},
|
|
onBrandHeadEnter() {
|
if (this.brandPickerTimer) {
|
clearTimeout(this.brandPickerTimer)
|
this.brandPickerTimer = null
|
}
|
this.showBrandPicker = true
|
},
|
|
onBrandHeadLeave() {
|
this.brandPickerTimer = setTimeout(() => {
|
this.showBrandPicker = false
|
}, 180)
|
},
|
|
onBrandHeadClick() {
|
const isTouch = typeof window !== 'undefined' &&
|
('ontouchstart' in window || (typeof navigator !== 'undefined' && navigator.maxTouchPoints > 0))
|
if (isTouch) {
|
this.showBrandPicker = !this.showBrandPicker
|
}
|
},
|
|
loadBrands(categoryId) {
|
const list = filterBrandsByCategory(this.allBrands, this.allGoods, categoryId)
|
this.brandData = [{ id: '', name: '全部' }, ...list]
|
},
|
|
loadProducts() {
|
const row = this.shopList[this.activeRowIndex]
|
if (!row) {
|
this.shopPageData = []
|
this.shopPageDataSou = []
|
return
|
}
|
const list = filterGoods(this.allGoods, {
|
categoryId: row.categoryId,
|
subCategoryId: this.currentSubCategoryId || '',
|
brandId: (this.shopPageBrand && this.shopPageBrand.id) || ''
|
})
|
this.shopPageData = list
|
this.filterProducts()
|
},
|
|
selectBrand(brand) {
|
this.shopPageBrand = { id: brand.id, name: brand.name }
|
this.showBrandPicker = false
|
if (this.brandPickerTimer) {
|
clearTimeout(this.brandPickerTimer)
|
this.brandPickerTimer = null
|
}
|
this.loadProducts()
|
},
|
|
onProductSearch() {
|
this.$nextTick(() => {
|
this.filterProducts()
|
})
|
},
|
|
filterProducts() {
|
const source = Array.isArray(this.shopPageData) ? this.shopPageData : []
|
const kw = (this.title || '').trim()
|
if (!kw) {
|
this.shopPageDataSou = source.slice()
|
return
|
}
|
this.shopPageDataSou = source.filter(item => matchKeyword(item, kw))
|
},
|
|
clickProduct(item) {
|
this.leftShop = JSON.parse(JSON.stringify(item))
|
this.rightShop = {}
|
this.param1 = []
|
this.param2 = []
|
this.pkcontent = false
|
this.currentCategoryId = item.categoryId || ''
|
this.currentCategoryName = item.categoryName || ''
|
this.status = 2
|
},
|
|
applyGoodsToRow(index, goods) {
|
const row = this.shopList[index]
|
if (!row || !goods) return
|
row.name = goods.name
|
row.goodsId = goods.id
|
row.zdPrice = goods.zdPrice
|
row.price = goods.price
|
row.modelVal = ''
|
row.modelSearchList = []
|
Object.assign(row, {
|
multifileList: goods.multifileList,
|
goodsParamList: goods.goodsParamList,
|
prefixUrl: goods.prefixUrl,
|
imgurl: goods.imgurl,
|
brandId: goods.brandId,
|
brandName: goods.brandName
|
})
|
},
|
|
confirmLeftToRow() {
|
if (this.activeRowIndex >= 0 && this.leftShop.name) {
|
this.applyGoodsToRow(this.activeRowIndex, this.leftShop)
|
}
|
this.status = 0
|
this.resetPkState()
|
},
|
|
confirmRightToRow() {
|
if (this.activeRowIndex >= 0 && this.rightShop.name) {
|
this.applyGoodsToRow(this.activeRowIndex, this.rightShop)
|
}
|
this.status = 0
|
this.resetPkState()
|
},
|
|
mergePkParams() {
|
const leftParamList = this.leftShop.goodsParamList || []
|
const rightParamList = this.rightShop.goodsParamList || []
|
const leftList1 = []
|
const leftList2 = []
|
const rightList1 = []
|
const rightList2 = []
|
|
leftParamList.forEach(item => {
|
const matched = rightParamList.find(r => r.name === item.name)
|
if (matched) {
|
leftList1.push(item)
|
rightList1.push(matched)
|
} else {
|
leftList2.push(item)
|
}
|
})
|
rightParamList.forEach(item => {
|
if (!rightList1.find(r => r.name === item.name)) {
|
rightList2.push(item)
|
}
|
})
|
|
this.param1 = leftList1
|
this.param2 = rightList1
|
this.$set(this.leftShop, 'param1', leftList1)
|
this.$set(this.leftShop, 'param2', leftList2)
|
this.$set(this.rightShop, 'param1', rightList1)
|
this.$set(this.rightShop, 'param2', rightList2)
|
},
|
|
tryAutoPkCompare() {
|
if (!this.leftShop.name || !this.rightShop.name) {
|
this.pkcontent = false
|
return
|
}
|
if (this.isSamePkGoods(this.leftShop, this.rightShop)) {
|
this.pkcontent = false
|
uni.showToast({ title: '左右不能选择同一商品', icon: 'none' })
|
return
|
}
|
this.mergePkParams()
|
this.pkcontent = true
|
},
|
|
openSearch(side) {
|
this.pkSearchSide = side
|
const cat = this.resolvePkSearchCategory()
|
if (cat.id) {
|
this.currentCategoryId = cat.id
|
this.currentCategoryName = cat.name
|
}
|
if (this.$refs.searchRef && typeof this.$refs.searchRef.open === 'function') {
|
this.$refs.searchRef.open(side)
|
}
|
},
|
|
isSamePkGoods(a, b) {
|
if (!a || !b || !a.name || !b.name) return false
|
if (a.id != null && b.id != null) return String(a.id) === String(b.id)
|
return a.name === b.name
|
},
|
|
resolvePkSearchCategory() {
|
if (this.activeRowIndex >= 0 && this.shopList[this.activeRowIndex]) {
|
const row = this.shopList[this.activeRowIndex]
|
return {
|
id: row.categoryId || '',
|
name: row.categoryName || ''
|
}
|
}
|
if (this.leftShop && this.leftShop.categoryId) {
|
return {
|
id: this.leftShop.categoryId,
|
name: this.leftShop.categoryName || this.currentCategoryName || ''
|
}
|
}
|
return {
|
id: this.currentCategoryId || '',
|
name: this.currentCategoryName || ''
|
}
|
},
|
|
result(val) {
|
const side = (this.$refs.searchRef && this.$refs.searchRef.typeName) || this.pkSearchSide
|
const otherShop = side === 'left' ? this.rightShop : this.leftShop
|
if (this.isSamePkGoods(val, otherShop)) {
|
uni.showToast({ title: '左右不能选择同一商品', icon: 'none' })
|
return
|
}
|
const goods = JSON.parse(JSON.stringify(val))
|
if (side === 'left') {
|
this.leftShop = goods
|
} else if (side === 'right') {
|
this.rightShop = goods
|
}
|
this.pkSearchSide = ''
|
this.tryAutoPkCompare()
|
},
|
|
pkImgUrl(shop) {
|
const urls = this.getPkImageUrls(shop)
|
return urls[0] || ''
|
},
|
|
getPkImageUrls(shop) {
|
if (!shop) return []
|
const prefix = shop.prefixUrl || ''
|
const list = shop.multifileList || []
|
if (list.length) {
|
return list.map(f => prefix + (f.fileurl || '')).filter(Boolean)
|
}
|
if (shop.imgurl) return [prefix + shop.imgurl]
|
return []
|
},
|
|
openPkImagePreview(side) {
|
const shop = side === 'left' ? this.leftShop : this.rightShop
|
if (!shop || !shop.name) return
|
this.pkPreviewImgList = this.getPkImageUrls(shop)
|
if (!this.pkPreviewImgList.length) return
|
this.$nextTick(() => {
|
if (this.$refs.pkBigImg) {
|
this.$refs.pkBigImg.open(0)
|
}
|
})
|
},
|
|
clearLeftShop() {
|
this.leftShop = {}
|
this.pkcontent = false
|
},
|
|
clearRightShop() {
|
this.rightShop = {}
|
this.param1 = []
|
this.param2 = []
|
this.pkcontent = false
|
},
|
|
resetPkState() {
|
this.leftShop = {}
|
this.rightShop = {}
|
this.param1 = []
|
this.param2 = []
|
this.pkcontent = false
|
this.activeRowIndex = -1
|
},
|
|
productImg(item) {
|
if (item.imgurl) return (item.prefixUrl || '') + item.imgurl
|
return ''
|
},
|
|
subIcon(sub, row) {
|
if (sub.imgurl) return (sub.prefixUrl || row.prefixUrl || '') + sub.imgurl
|
return row.categoryImgurl || ''
|
},
|
|
featuredTitle(feat) {
|
if (!feat) return ''
|
if (feat.goodsId && this.allGoods && this.allGoods.length) {
|
const goods = this.allGoods.find(g => String(g.id) === String(feat.goodsId))
|
if (goods && goods.name) return goods.name
|
}
|
return feat.title || ''
|
},
|
|
featuredImgUrl(feat) {
|
if (!feat) return ''
|
if (feat.goodsId && this.allGoods && this.allGoods.length) {
|
const goods = this.allGoods.find(g => String(g.id) === String(feat.goodsId))
|
if (goods && goods.imgurl) {
|
return (goods.prefixUrl || '') + goods.imgurl
|
}
|
}
|
if (feat.prefixUrl && feat.imgurl && !/^https?:\/\//i.test(feat.imgurl)) {
|
return feat.prefixUrl + feat.imgurl
|
}
|
if (feat.imgaddr) {
|
return this.resolveMediaUrl(feat.imgaddr, feat)
|
}
|
return this.resolveMediaUrl(feat.imgurl || feat.img, feat)
|
},
|
|
formatDateTime(date) {
|
const d = date instanceof Date ? date : new Date(date)
|
const pad = n => String(n).padStart(2, '0')
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
|
},
|
|
submitOrderHandler() {
|
const selectedRows = this.shopList.filter(row => {
|
return row.goodsId && String(row.name || '').trim()
|
})
|
|
if (!selectedRows.length) {
|
uni.showToast({ title: '请至少选择一个商品型号', icon: 'none' })
|
return
|
}
|
|
const items = selectedRows.map(row => ({
|
categoryId: row.categoryId,
|
categoryName: row.categoryName,
|
subCategoryId: row.subCategoryId || null,
|
subCategoryName: row.subCategoryName || '',
|
goodsId: row.goodsId,
|
goodsName: row.name,
|
zdPrice: row.zdPrice,
|
price: row.price
|
}))
|
|
if (!this.orderNo) {
|
uni.showToast({ title: '订单编号未生成', icon: 'none' })
|
return
|
}
|
|
submitOrder({
|
orderNo: this.orderNo,
|
userBudget: Number(this.userBudget) || 0,
|
sessionCreateTime: this.formatDateTime(this.sessionCreateTime),
|
items
|
}).then(() => {
|
uni.showToast({ title: '提交成功', icon: 'success' })
|
this.resetPage()
|
})
|
},
|
|
resetPage() {
|
this.userBudget = 0
|
this.sessionCreateTime = new Date()
|
this.status = 0
|
this.showCategoryPicker = false
|
this.hoverRowIndex = -1
|
this.resetPkState()
|
this.title = ''
|
this.shopPageData = []
|
this.shopPageDataSou = []
|
this.loadOrderNo()
|
this.initShopListFromCategories()
|
},
|
|
fanhuiPage() {
|
if (this.status === 2) {
|
this.status = this.shopPageData.length ? 1 : 0
|
this.resetPkState()
|
} else if (this.status === 1) {
|
this.status = 0
|
this.title = ''
|
this.showBrandPicker = false
|
this.shopPageData = []
|
this.shopPageDataSou = []
|
this.activeRowIndex = -1
|
this.currentSubCategoryName = ''
|
}
|
},
|
|
loginOut() {
|
logout({}).then(() => {
|
this.$store.commit('clean')
|
uni.redirectTo({ url: '/pages/login/login' })
|
})
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
$brown: #4A3728;
|
$brown-dark: #3D2E22;
|
$cream: #E8DCC8;
|
$row-bg: #FFFFFF;
|
$panel-bg: #F7F0E6;
|
$orange: #FF8C42;
|
$search-icon-filter: brightness(0) saturate(100%) invert(23%) sepia(14%) saturate(1067%) hue-rotate(349deg) brightness(95%) contrast(91%);
|
|
.page_loading {
|
position: fixed;
|
inset: 0;
|
z-index: 999;
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
background: $cream;
|
|
.loading_spinner {
|
width: 40px;
|
height: 40px;
|
border: 3px solid rgba(74, 55, 40, 0.15);
|
border-top-color: $brown;
|
border-radius: 50%;
|
animation: spin 0.8s linear infinite;
|
margin-bottom: 16px;
|
}
|
|
.loading_text {
|
font-size: 14px;
|
color: $brown;
|
opacity: 0.85;
|
}
|
}
|
|
@keyframes spin {
|
to { transform: rotate(360deg); }
|
}
|
|
.page {
|
width: 100vw;
|
min-height: 100vh;
|
position: relative;
|
display: flex;
|
justify-content: center;
|
}
|
|
.page_bg {
|
position: fixed;
|
top: 0;
|
left: 0;
|
width: 100vw;
|
height: 100vh;
|
background-size: cover;
|
background-repeat: no-repeat;
|
background-position: center;
|
z-index: 0;
|
|
&.default-bg {
|
background-color: $cream;
|
}
|
}
|
|
.page_content {
|
position: relative;
|
z-index: 1;
|
width: 100%;
|
padding: 0 0 24px;
|
box-sizing: border-box;
|
}
|
|
.banner_wrap {
|
position: relative;
|
margin-bottom: 0;
|
|
.banner {
|
position: relative;
|
width: 100%;
|
overflow: hidden;
|
background: transparent;
|
min-height: auto;
|
|
.banner_img {
|
width: 100%;
|
display: block;
|
}
|
}
|
}
|
|
.submit_row {
|
padding: 10px 14px 8px;
|
background: transparent;
|
}
|
|
.home_sticky_header {
|
position: sticky;
|
top: 0;
|
z-index: 30;
|
width: 100%;
|
box-sizing: border-box;
|
}
|
|
.submit_btn {
|
display: inline-flex;
|
align-items: center;
|
gap: 5px;
|
padding: 7px 16px;
|
border-radius: 18px;
|
font-size: 12px;
|
font-weight: 600;
|
cursor: pointer;
|
box-shadow: 0 2px 8px rgba(74, 55, 40, 0.1);
|
transition: transform 0.15s;
|
|
&:hover {
|
transform: scale(1.03);
|
}
|
|
.submit_icon_img {
|
width: 16px;
|
height: 16px;
|
flex-shrink: 0;
|
display: block;
|
}
|
|
&.submit_btn--icon {
|
display: inline-flex;
|
align-items: center;
|
gap: 5px;
|
}
|
}
|
|
.user_bar {
|
display: flex;
|
align-items: center;
|
justify-content: flex-end;
|
gap: 8px;
|
font-size: 12px;
|
color: $brown;
|
|
image {
|
width: 20px;
|
height: 20px;
|
cursor: pointer;
|
opacity: 0.75;
|
}
|
|
&.user_bar--banner {
|
position: absolute;
|
right: 12px;
|
top: 12px;
|
z-index: 4;
|
}
|
}
|
|
.order_bar {
|
display: flex;
|
justify-content: space-between;
|
align-items: stretch;
|
padding: 4px 4px 12px;
|
margin: 0;
|
font-size: 14px;
|
border-radius: 0;
|
|
.order_left {
|
display: flex;
|
align-items: center;
|
gap: 4px;
|
flex-wrap: nowrap;
|
flex: 1;
|
min-width: 0;
|
}
|
|
.order_right {
|
display: flex;
|
align-items: center;
|
justify-content: flex-end;
|
flex-shrink: 0;
|
margin-left: 8px;
|
}
|
|
.order_no_row {
|
display: flex;
|
align-items: center;
|
gap: 6px;
|
}
|
|
.remain_inline {
|
display: flex;
|
align-items: center;
|
gap: 6px;
|
margin-left: 10px;
|
font-size: 12px;
|
opacity: 0.85;
|
flex-shrink: 0;
|
white-space: nowrap;
|
|
.remain_val {
|
font-weight: 600;
|
color: #FFD88A;
|
}
|
}
|
|
.order_label {
|
opacity: 0.9;
|
font-size: 13px;
|
}
|
|
.order_currency {
|
font-weight: 700;
|
font-size: 15px;
|
}
|
|
.budget_input {
|
width: 12.5ch;
|
min-width: 12.5ch;
|
height: 28px;
|
background: transparent;
|
border: none;
|
padding: 0 2px;
|
color: inherit;
|
font-size: 16px;
|
font-weight: 700;
|
text-align: left;
|
flex-shrink: 0;
|
}
|
|
.order_no {
|
font-weight: 600;
|
font-size: 14px;
|
letter-spacing: 0.3px;
|
}
|
}
|
|
.home_top_section {
|
position: relative;
|
margin: 8px 12px 0;
|
padding: 12px 12px 0;
|
border-radius: 16px 16px 0 0;
|
overflow: visible;
|
z-index: 1;
|
--home-top-bg: #4A3728;
|
|
&::after {
|
content: '';
|
position: absolute;
|
top: -18px;
|
left: -24px;
|
right: -24px;
|
bottom: -18px;
|
border-radius: 24px 24px 0 0;
|
background: radial-gradient(
|
ellipse 88% 92% at 50% 48%,
|
var(--home-top-bg) 0%,
|
rgba(74, 55, 40, 0.55) 55%,
|
rgba(74, 55, 40, 0.15) 78%,
|
transparent 100%
|
);
|
filter: blur(10px);
|
z-index: -1;
|
pointer-events: none;
|
}
|
|
.order_bar,
|
.featured,
|
.table_head_wrap {
|
position: relative;
|
z-index: 1;
|
}
|
|
.order_bar,
|
.shop_table_head {
|
color: inherit;
|
background: transparent;
|
}
|
|
.product_list_head_wrap {
|
margin-top: 0;
|
}
|
|
&.home_top_section--compact {
|
padding-bottom: 12px;
|
border-radius: 16px;
|
|
&::after {
|
bottom: 0;
|
border-radius: 24px;
|
}
|
|
.featured {
|
margin-bottom: 0;
|
}
|
}
|
}
|
|
.featured {
|
display: flex;
|
align-items: center;
|
background: linear-gradient(180deg, #FFF9EC 0%, #FAF0E0 100%);
|
padding: 14px 14px 12px;
|
margin: 0 0 10px;
|
border-radius: 20px;
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
|
border: none;
|
|
.featured_left {
|
flex-shrink: 0;
|
width: 218px;
|
min-width: 218px;
|
display: flex;
|
text-align:center;
|
flex-direction: column;
|
justify-content: center;
|
padding-right: 12px;
|
border-right: 1px solid rgba(74, 55, 40, 0.08);
|
margin-right: 10px;
|
}
|
|
.featured_title {
|
display: block;
|
font-size: 22px;
|
font-weight: 700;
|
color: #333;
|
font-family: Georgia, 'Times New Roman', serif;
|
letter-spacing: 1px;
|
line-height: 1.15;
|
margin-bottom: 8px;
|
white-space: nowrap;
|
}
|
|
.featured_sub {
|
display: block;
|
font-size: 10px;
|
color: #aaa;
|
line-height: 1.45;
|
white-space: nowrap;
|
}
|
|
.featured_products {
|
flex: 1;
|
display: flex;
|
align-items: stretch;
|
min-width: 0;
|
}
|
|
.featured_item {
|
flex: 1;
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
padding: 2px 6px;
|
min-width: 0;
|
|
&:not(:last-child) {
|
border-right: 1px solid rgba(74, 55, 40, 0.08);
|
margin-right: 6px;
|
padding-right: 10px;
|
}
|
}
|
|
.featured_img_wrap {
|
flex-shrink: 0;
|
width: 44px;
|
height: 72px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.featured_img {
|
width: 44px;
|
height: 72px;
|
}
|
|
.featured_img_placeholder {
|
width: 36px;
|
height: 60px;
|
background: rgba(74, 55, 40, 0.06);
|
border-radius: 4px;
|
}
|
|
.featured_info {
|
flex: 1;
|
min-width: 0;
|
display: flex;
|
flex-direction: column;
|
justify-content: center;
|
gap: 6px;
|
}
|
|
.featured_name {
|
display: block;
|
font-size: 12px;
|
font-weight: 600;
|
color: #333;
|
line-height: 1.35;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.featured_tag_row {
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
flex-wrap: wrap;
|
}
|
|
.tag {
|
font-size: 11px;
|
line-height: 1.2;
|
|
&.tag_dim {
|
color: #888;
|
}
|
|
&.tag_blue {
|
color: #4A8FD4;
|
font-weight: 500;
|
}
|
|
&.tag_green {
|
color: #3CB371;
|
font-weight: 500;
|
}
|
}
|
}
|
|
.table_head_wrap {
|
position: relative;
|
border-radius: 0;
|
overflow: visible;
|
z-index: 3;
|
}
|
|
.home_top_section .shop_table_head {
|
display: grid;
|
grid-template-columns: 1.1fr 2fr 0.9fr 0.9fr;
|
padding: 11px 14px 12px;
|
font-size: 13px;
|
font-weight: 600;
|
border-radius: 0 !important;
|
box-shadow: none;
|
margin: 0;
|
background: transparent;
|
|
.col {
|
display: flex;
|
align-items: center;
|
}
|
|
.col_cat {
|
justify-content: flex-start;
|
gap: 4px;
|
cursor: pointer;
|
padding-left: 2px;
|
|
.arrow {
|
font-size: 9px;
|
opacity: 0.85;
|
}
|
}
|
|
.category_dropdown_anchor {
|
position: relative;
|
z-index: 12;
|
}
|
|
.col_model {
|
justify-content: flex-start;
|
text-align: left;
|
}
|
|
.col_zd,
|
.col_price {
|
justify-content: flex-end;
|
text-align: right;
|
}
|
}
|
|
.home_top_section .category_picker {
|
position: absolute;
|
top: calc(100% + 2px);
|
left: -26px;
|
min-width: 168px;
|
z-index: 20;
|
max-height: 240px;
|
overflow-y: auto;
|
border-radius: 0 0 6px 6px;
|
padding: 6px 0;
|
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.22);
|
|
.category_picker_item {
|
display: flex;
|
align-items: center;
|
gap: 10px;
|
padding: 10px 12px;
|
color: #fff;
|
cursor: pointer;
|
border-radius: 0;
|
|
&:hover {
|
background: rgba(255, 255, 255, 0.1);
|
}
|
|
image {
|
width: 28px;
|
height: 28px;
|
}
|
}
|
|
.category_picker_empty {
|
padding: 16px;
|
text-align: center;
|
color: rgba(255, 255, 255, 0.7);
|
font-size: 13px;
|
}
|
}
|
|
.home_top_section .product_list_head_wrap {
|
.product_shop_table_head {
|
.col {
|
min-width: 0;
|
}
|
}
|
|
.product_cat_col {
|
justify-content: flex-end;
|
width: 100%;
|
padding-right: 0;
|
text-align: right;
|
|
&.product_cat_col--span {
|
grid-column: 3 / -1;
|
}
|
}
|
|
.product_cat_inner {
|
display: inline-flex;
|
align-items: center;
|
justify-content: flex-end;
|
gap: 6px;
|
max-width: 100%;
|
margin-left: auto;
|
min-width: 0;
|
}
|
|
.product_cat_icon {
|
width: 22px;
|
height: 22px;
|
flex-shrink: 0;
|
}
|
|
.cat_line {
|
font-size: 13px;
|
font-weight: 600;
|
line-height: 1.2;
|
text-align: right;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
min-width: 0;
|
}
|
|
.product_search_col {
|
justify-content: flex-start;
|
padding: 0 4px;
|
}
|
|
.product_search_inline {
|
flex: 1;
|
display: flex;
|
align-items: center;
|
gap: 6px;
|
border-radius: 16px;
|
padding: 5px 10px;
|
min-width: 0;
|
|
.search_icon {
|
width: 13px;
|
height: 13px;
|
flex-shrink: 0;
|
display: block;
|
opacity: 1;
|
filter: $search-icon-filter;
|
}
|
|
.search_divider {
|
width: 1px;
|
height: 14px;
|
background: rgba(74, 55, 40, 0.12);
|
flex-shrink: 0;
|
}
|
|
input {
|
flex: 1;
|
min-width: 0;
|
font-size: 12px;
|
color: $brown;
|
background: transparent;
|
}
|
}
|
|
.product_brand_col {
|
justify-content: flex-start;
|
gap: 4px;
|
cursor: pointer;
|
flex-wrap: wrap;
|
|
.brand_echo_inline {
|
font-size: 12px;
|
font-weight: 500;
|
opacity: 0.9;
|
margin-left: 4px;
|
max-width: 56px;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.arrow {
|
font-size: 9px;
|
opacity: 0.85;
|
}
|
|
.brand_picker {
|
left: -26px;
|
right: auto;
|
}
|
}
|
|
.product_brand_echo {
|
justify-content: flex-end;
|
font-size: 12px;
|
font-weight: 500;
|
opacity: 0.9;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.brand_picker {
|
position: absolute;
|
top: calc(100% + 4px);
|
right: 0;
|
min-width: 120px;
|
max-height: 220px;
|
overflow-y: auto;
|
border-radius: 8px;
|
padding: 6px 0;
|
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.22);
|
z-index: 20;
|
|
.brand_picker_item {
|
padding: 10px 14px;
|
font-size: 13px;
|
color: #fff;
|
cursor: pointer;
|
white-space: nowrap;
|
|
&:hover,
|
&.active {
|
background: rgba(255, 255, 255, 0.12);
|
}
|
}
|
}
|
}
|
|
.shop_table {
|
position: relative;
|
margin: 10px 12px 10px;
|
border-radius: 0;
|
overflow: visible;
|
padding: 0;
|
background: transparent;
|
box-shadow: none;
|
}
|
|
.nav_back {
|
position: fixed;
|
left: 16px;
|
top: 50%;
|
transform: translateY(-50%);
|
width: 56px;
|
height: 56px;
|
min-width: 56px;
|
min-height: 56px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
cursor: pointer;
|
z-index: 50;
|
box-sizing: border-box;
|
padding: 8px;
|
|
image {
|
width: 36px;
|
height: 36px;
|
display: block;
|
}
|
}
|
|
.shop_table_body {
|
position: relative;
|
min-height: 48px;
|
padding: 0 10px 10px;
|
overflow: visible;
|
|
.shop_table_empty {
|
padding: 28px 16px;
|
text-align: center;
|
color: #999;
|
font-size: 13px;
|
background: #fff;
|
}
|
|
.shop_row {
|
position: relative;
|
margin-bottom: 10px;
|
transition: transform 0.2s, box-shadow 0.2s;
|
overflow: visible;
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
|
&.expanded {
|
z-index: 5;
|
}
|
}
|
|
.shop_row_main {
|
display: flex;
|
gap: 10px;
|
align-items: stretch;
|
padding: 0;
|
font-size: 13px;
|
color: $brown;
|
background: transparent;
|
border: none;
|
min-height: 52px;
|
|
.row_cat_cell,
|
.row_info_group {
|
background: #fff;
|
border-radius: 14px;
|
box-shadow: 0 2px 8px rgba(74, 55, 40, 0.08);
|
min-width: 0;
|
}
|
|
.row_cat_cell {
|
width: 108px;
|
flex-shrink: 0;
|
box-sizing: border-box;
|
display: flex;
|
flex-direction: row;
|
flex-wrap: nowrap;
|
align-items: center;
|
justify-content: flex-start;
|
gap: 6px;
|
padding: 10px 8px;
|
cursor: pointer;
|
overflow: hidden;
|
|
image {
|
width: 20px;
|
height: 20px;
|
flex-shrink: 0;
|
}
|
|
.cell_ellipsis {
|
flex: 1;
|
min-width: 0;
|
font-size: 12px;
|
font-weight: 600;
|
text-align: left;
|
line-height: 1.2;
|
white-space: nowrap;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
}
|
}
|
|
.row_info_group {
|
flex: 1;
|
display: grid;
|
grid-template-columns: 2fr 0.9fr 0.9fr;
|
gap: 10px;
|
align-items: center;
|
padding: 10px;
|
overflow: hidden;
|
|
> .col {
|
min-width: 0;
|
overflow: hidden;
|
}
|
}
|
|
.cell_ellipsis {
|
display: block;
|
width: 100%;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.col_model {
|
justify-content: flex-start;
|
|
.cell_ellipsis {
|
text-align: left;
|
padding: 0 2px;
|
}
|
|
&.col_model_link {
|
cursor: pointer;
|
}
|
}
|
|
.col_zd {
|
justify-content: flex-end;
|
|
.cell_ellipsis {
|
text-align: right;
|
}
|
}
|
|
.col_price {
|
justify-content: flex-end;
|
|
input {
|
width: 100%;
|
max-width: 72px;
|
min-width: 0;
|
height: 32px;
|
text-align: center;
|
background: $panel-bg;
|
border-radius: 8px;
|
font-size: 13px;
|
color: $brown;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
}
|
}
|
|
.shop_row_expand {
|
display: flex;
|
gap: 10px;
|
align-items: stretch;
|
padding: 0;
|
animation: expandIn 0.2s ease;
|
overflow: visible;
|
}
|
|
.expand_cat_card {
|
position: relative;
|
width: 88px;
|
flex-shrink: 0;
|
background: #fff;
|
border-radius: 14px;
|
padding: 16px 10px 12px;
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
box-shadow: 0 4px 16px rgba(74, 55, 40, 0.12);
|
cursor: pointer;
|
}
|
|
.expand_cat_img {
|
width: 48px;
|
height: 48px;
|
margin-bottom: 8px;
|
}
|
|
.expand_cat_name {
|
font-size: 13px;
|
font-weight: 600;
|
color: $brown;
|
text-align: center;
|
line-height: 1.3;
|
}
|
|
.expand_panel {
|
flex: 1;
|
background: #fff;
|
border-radius: 14px;
|
padding: 14px;
|
box-shadow: 0 4px 16px rgba(74, 55, 40, 0.12);
|
min-width: 0;
|
overflow: visible;
|
}
|
|
.expand_data_row {
|
display: grid;
|
grid-template-columns: 2fr 1fr 1fr;
|
gap: 8px;
|
align-items: center;
|
margin-bottom: 12px;
|
padding-bottom: 10px;
|
border-bottom: 1px solid rgba(74, 55, 40, 0.08);
|
font-size: 13px;
|
color: $brown;
|
|
.expand_model {
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
font-weight: 500;
|
|
&.expand_model_link {
|
cursor: pointer;
|
}
|
}
|
|
.expand_zd {
|
text-align: center;
|
}
|
|
.expand_price_input {
|
height: 30px;
|
text-align: center;
|
background: $panel-bg;
|
border-radius: 8px;
|
font-size: 13px;
|
color: $brown;
|
}
|
}
|
|
.sub_cat_grid {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 12px;
|
margin-bottom: 14px;
|
justify-content: flex-start;
|
}
|
|
.sub_cat_icon_item {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
width: 56px;
|
cursor: pointer;
|
transition: transform 0.15s;
|
|
&:hover {
|
transform: scale(1.06);
|
}
|
|
image {
|
width: 40px;
|
height: 40px;
|
margin-bottom: 4px;
|
}
|
|
text {
|
font-size: 11px;
|
color: $brown;
|
text-align: center;
|
line-height: 1.2;
|
}
|
}
|
|
.expand_search_wrap {
|
position: relative;
|
z-index: 2;
|
}
|
|
.expand_search {
|
display: flex;
|
align-items: center;
|
gap: 10px;
|
border-radius: 24px;
|
padding: 10px 16px;
|
|
.search_icon {
|
width: 14px;
|
height: 14px;
|
flex-shrink: 0;
|
display: block;
|
opacity: 1;
|
filter: $search-icon-filter;
|
}
|
|
input {
|
flex: 1;
|
font-size: 14px;
|
color: $brown;
|
background: transparent;
|
}
|
}
|
|
.model_suggest_empty {
|
position: absolute;
|
top: calc(100% + 4px);
|
left: 0;
|
right: 0;
|
margin-top: 0;
|
padding: 10px 14px;
|
font-size: 13px;
|
color: #999;
|
text-align: center;
|
background: #fff;
|
border-radius: 8px;
|
box-shadow: 0 8px 20px rgba(74, 55, 40, 0.16);
|
border: 1px solid rgba(74, 55, 40, 0.08);
|
z-index: 20;
|
}
|
|
.model_suggest_list {
|
position: absolute;
|
top: calc(100% + 4px);
|
left: 0;
|
right: 0;
|
margin-top: 0;
|
max-height: 160px;
|
overflow-y: auto;
|
border-radius: 8px;
|
background: #fff;
|
box-shadow: 0 8px 20px rgba(74, 55, 40, 0.16);
|
border: 1px solid rgba(74, 55, 40, 0.08);
|
z-index: 20;
|
}
|
|
.model_suggest_item {
|
padding: 10px 14px;
|
font-size: 13px;
|
color: $brown;
|
cursor: pointer;
|
border-bottom: 1px solid rgba(74, 55, 40, 0.06);
|
|
&:last-child {
|
border-bottom: none;
|
}
|
|
&:hover {
|
background: rgba(255, 255, 255, 0.6);
|
}
|
}
|
|
.col {
|
text-align: center;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.col_model {
|
justify-content: flex-start;
|
}
|
|
.col_zd,
|
.col_price {
|
justify-content: flex-end;
|
text-align: right;
|
}
|
|
.col_zd {
|
font-weight: 500;
|
}
|
|
.row_delete {
|
position: absolute;
|
right: -6px;
|
top: -6px;
|
width: 22px;
|
height: 22px;
|
background: $orange;
|
color: #fff;
|
border-radius: 50%;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
cursor: pointer;
|
font-size: 16px;
|
line-height: 1;
|
z-index: 4;
|
box-shadow: 0 2px 6px rgba(255, 140, 66, 0.4);
|
}
|
}
|
|
@keyframes expandIn {
|
from {
|
opacity: 0.6;
|
transform: scale(0.98);
|
}
|
to {
|
opacity: 1;
|
transform: scale(1);
|
}
|
}
|
|
.product_page {
|
padding: 10px 0 20px;
|
|
.product_grid {
|
display: grid;
|
grid-template-columns: repeat(5, 1fr);
|
gap: 8px;
|
padding: 0 12px;
|
}
|
|
.product_card {
|
border-radius: 10px;
|
overflow: hidden;
|
cursor: pointer;
|
transition: transform 0.15s;
|
background: #fff;
|
box-shadow: 0 2px 8px rgba(74, 55, 40, 0.08);
|
display: flex;
|
flex-direction: column;
|
|
&:hover {
|
transform: translateY(-2px);
|
}
|
|
.product_card_img {
|
background: #fff;
|
padding: 8px 4px 4px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
|
image {
|
width: 100%;
|
height: 72px;
|
}
|
}
|
|
.product_card_info {
|
background: #F5EFE6;
|
padding: 6px 4px 8px;
|
text-align: center;
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
justify-content: center;
|
gap: 2px;
|
}
|
|
.product_brand {
|
display: block;
|
font-size: 11px;
|
font-weight: 600;
|
color: $brown;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.product_model {
|
display: block;
|
font-size: 10px;
|
color: #666;
|
line-height: 1.25;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.product_price_label {
|
display: block;
|
font-size: 10px;
|
color: $brown;
|
margin-top: 2px;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
&.placeholder {
|
grid-column: 1 / -1;
|
padding: 40px;
|
color: #999;
|
background: #fff;
|
align-items: center;
|
justify-content: center;
|
}
|
}
|
}
|
|
.pk_page {
|
padding-top: 32px;
|
padding-bottom: 24px;
|
margin: 0 12px;
|
padding-left: 12px;
|
padding-right: 12px;
|
box-sizing: border-box;
|
max-width: 100%;
|
|
.pk_cards,
|
.pk_params {
|
display: grid;
|
grid-template-columns: 1fr auto 1fr;
|
gap: 12px;
|
align-items: stretch;
|
}
|
|
.pk_cards {
|
margin-bottom: 20px;
|
align-items: start;
|
}
|
|
.pk_side {
|
min-width: 0;
|
position: relative;
|
display: flex;
|
flex-direction: column;
|
align-items: stretch;
|
}
|
|
.pk_delete {
|
position: absolute;
|
right: 4px;
|
top: 4px;
|
width: 26px;
|
height: 26px;
|
background: $orange;
|
color: #fff;
|
border-radius: 50%;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
cursor: pointer;
|
font-size: 20px;
|
z-index: 4;
|
}
|
|
.pk_showcase {
|
position: relative;
|
border-radius: 14px;
|
padding: 3px;
|
background: linear-gradient(
|
135deg,
|
var(--pk-show-accent, #{$orange}) 0%,
|
var(--pk-show-gold, #FFD88A) 42%,
|
var(--pk-show-primary, #{$brown}) 100%
|
);
|
box-shadow:
|
0 0 0 1px rgba(255, 255, 255, 0.38) inset,
|
0 8px 24px var(--pk-show-accent-soft, rgba(255, 140, 66, 0.28)),
|
0 4px 14px var(--pk-show-primary-soft, rgba(74, 55, 40, 0.18));
|
overflow: hidden;
|
}
|
|
.pk_showcase_glow {
|
position: absolute;
|
inset: 0;
|
border-radius: 14px;
|
pointer-events: none;
|
background:
|
radial-gradient(circle at 18% 12%, var(--pk-show-gold-soft, rgba(255, 216, 138, 0.45)) 0%, transparent 42%),
|
radial-gradient(circle at 82% 88%, var(--pk-show-accent-soft, rgba(255, 140, 66, 0.35)) 0%, transparent 46%);
|
animation: pk_showcase_glow 3.2s ease-in-out infinite;
|
}
|
|
.pk_showcase_frame {
|
position: relative;
|
z-index: 1;
|
border-radius: 11px;
|
padding: 14px 10px 10px;
|
text-align: center;
|
min-height: 168px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
overflow: hidden;
|
background:
|
radial-gradient(circle at 50% 22%, var(--pk-show-accent-faint, rgba(255, 140, 66, 0.12)) 0%, transparent 58%),
|
linear-gradient(
|
165deg,
|
rgba(255, 255, 255, 0.98) 0%,
|
rgba(255, 251, 244, 0.94) 45%,
|
var(--pk-show-primary-soft, rgba(74, 55, 40, 0.1)) 100%
|
);
|
border: 1px solid rgba(255, 255, 255, 0.72);
|
box-shadow: inset 0 0 28px var(--pk-show-gold-soft, rgba(255, 216, 138, 0.22));
|
}
|
|
.pk_showcase_visual {
|
position: relative;
|
z-index: 2;
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
width: 100%;
|
}
|
|
.pk_showcase_img_card {
|
position: relative;
|
padding: 7px;
|
border-radius: 18px;
|
cursor: pointer;
|
background:
|
linear-gradient(180deg, #fff 0%, #fffaf3 100%) padding-box,
|
linear-gradient(
|
145deg,
|
var(--pk-show-gold, #FFD88A) 0%,
|
var(--pk-show-accent, #{$orange}) 48%,
|
var(--pk-show-primary, #{$brown}) 100%
|
) border-box;
|
border: 2px solid transparent;
|
box-shadow:
|
0 10px 24px var(--pk-show-primary-soft, rgba(74, 55, 40, 0.2)),
|
0 4px 10px var(--pk-show-accent-soft, rgba(255, 140, 66, 0.18)),
|
inset 0 1px 0 rgba(255, 255, 255, 0.95);
|
transition: transform 0.28s ease, box-shadow 0.28s ease;
|
|
&:hover {
|
transform: translateY(-4px) scale(1.03);
|
box-shadow:
|
0 16px 32px var(--pk-show-primary-soft, rgba(74, 55, 40, 0.26)),
|
0 8px 18px var(--pk-show-accent-soft, rgba(255, 140, 66, 0.28)),
|
inset 0 1px 0 rgba(255, 255, 255, 1);
|
}
|
}
|
|
.pk_showcase_img {
|
position: relative;
|
z-index: 1;
|
display: block;
|
width: 102px;
|
height: 102px;
|
border-radius: 14px;
|
background: #fff;
|
object-fit: contain;
|
}
|
|
.pk_showcase_reflect {
|
width: 102px;
|
height: 34px;
|
margin-top: 3px;
|
overflow: hidden;
|
border-radius: 0 0 14px 14px;
|
-webkit-mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.42) 0%, transparent 88%);
|
mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.42) 0%, transparent 88%);
|
pointer-events: none;
|
}
|
|
.pk_showcase_reflect_img {
|
display: block;
|
width: 102px;
|
height: 102px;
|
border-radius: 14px;
|
transform: scaleY(-1);
|
opacity: 0.55;
|
object-fit: contain;
|
}
|
|
.pk_showcase_ground {
|
width: 72%;
|
height: 10px;
|
margin-top: 2px;
|
border-radius: 50%;
|
background: radial-gradient(
|
ellipse at center,
|
var(--pk-show-primary-soft, rgba(74, 55, 40, 0.32)) 0%,
|
transparent 72%
|
);
|
pointer-events: none;
|
}
|
|
.pk_showcase_shine {
|
position: absolute;
|
top: -45%;
|
left: -25%;
|
width: 55%;
|
height: 90%;
|
pointer-events: none;
|
background: linear-gradient(120deg, transparent 0%, rgba(255, 255, 255, 0.62) 48%, transparent 100%);
|
transform: rotate(14deg);
|
animation: pk_showcase_shine 4.5s ease-in-out infinite;
|
}
|
|
.pk_podium {
|
width: 82%;
|
height: 22px;
|
margin: -2px auto 0;
|
background: linear-gradient(
|
180deg,
|
var(--pk-show-primary, #{$brown-dark}) 0%,
|
var(--pk-show-accent, #{$brown}) 52%,
|
rgba(0, 0, 0, 0.22) 100%
|
);
|
clip-path: polygon(10% 0, 90% 0, 100% 100%, 0 100%);
|
box-shadow:
|
0 6px 16px var(--pk-show-primary-soft, rgba(74, 55, 40, 0.22)),
|
0 0 14px var(--pk-show-accent-soft, rgba(255, 140, 66, 0.28)),
|
inset 0 1px 0 var(--pk-show-gold-soft, rgba(255, 216, 138, 0.4)),
|
inset 0 -2px 6px rgba(0, 0, 0, 0.18);
|
position: relative;
|
z-index: 1;
|
}
|
|
@keyframes pk_showcase_glow {
|
0%, 100% { opacity: 0.62; }
|
50% { opacity: 1; }
|
}
|
|
@keyframes pk_showcase_shine {
|
0%, 100% { transform: rotate(14deg) translateX(0); opacity: 0.45; }
|
50% { transform: rotate(14deg) translateX(18%); opacity: 0.85; }
|
}
|
|
.pk_detail {
|
width: 100%;
|
margin-top: 0;
|
}
|
|
.pk_detail_head {
|
padding: 9px 10px;
|
border-radius: 10px 10px 0 0;
|
font-size: 12px;
|
font-weight: 600;
|
text-align: center;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.pk_detail_body {
|
display: grid;
|
grid-template-columns: 1fr 1fr;
|
gap: 6px;
|
padding: 12px 10px;
|
background: #fff;
|
border: 1px solid rgba(74, 55, 40, 0.1);
|
border-top: none;
|
border-radius: 0 0 10px 10px;
|
box-shadow: 0 4px 12px rgba(74, 55, 40, 0.08);
|
}
|
|
.pk_price_cell {
|
text-align: center;
|
min-width: 0;
|
|
.pk_price_label {
|
display: block;
|
font-size: 11px;
|
color: rgba(74, 55, 40, 0.62);
|
line-height: 1.3;
|
}
|
|
.pk_price_val {
|
display: block;
|
margin-top: 6px;
|
font-size: 17px;
|
font-weight: 700;
|
color: $brown;
|
line-height: 1.2;
|
word-break: break-all;
|
}
|
|
&--hot .pk_price_val {
|
color: #c0392b;
|
}
|
}
|
|
.pk_action_group {
|
display: flex;
|
align-items: stretch;
|
gap: 8px;
|
padding: 4px;
|
border-radius: 12px;
|
background: rgba(0, 0, 0, 0.16);
|
box-shadow:
|
inset 0 1px 0 rgba(255, 255, 255, 0.12),
|
0 1px 4px rgba(0, 0, 0, 0.12);
|
}
|
|
.pk_btn_ico {
|
flex-shrink: 0;
|
font-size: 14px;
|
line-height: 1;
|
opacity: 0.92;
|
|
&--check {
|
font-size: 12px;
|
font-weight: 700;
|
}
|
}
|
|
.pk_btn_txt {
|
line-height: 1.2;
|
white-space: nowrap;
|
}
|
|
.pk_change {
|
display: inline-flex;
|
align-items: center;
|
justify-content: center;
|
gap: 5px;
|
flex: 0 1 auto;
|
min-width: 0;
|
padding: 9px 11px;
|
border-radius: 9px;
|
font-size: 11px;
|
font-weight: 500;
|
text-align: center;
|
cursor: pointer;
|
color: rgba(255, 255, 255, 0.92);
|
background: rgba(255, 255, 255, 0.1);
|
border: 1px solid rgba(255, 255, 255, 0.24);
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14);
|
transition: background 0.2s ease, border-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
|
|
.pk_btn_ico {
|
display: inline-block;
|
transform: rotate(-12deg);
|
}
|
|
&:hover {
|
background: rgba(255, 255, 255, 0.18);
|
border-color: rgba(255, 255, 255, 0.4);
|
transform: translateY(-1px);
|
box-shadow:
|
inset 0 1px 0 rgba(255, 255, 255, 0.22),
|
0 3px 8px rgba(0, 0, 0, 0.12);
|
}
|
}
|
|
.pk_confirm {
|
display: inline-flex;
|
align-items: center;
|
justify-content: center;
|
gap: 5px;
|
flex: 1;
|
min-width: 0;
|
padding: 9px 12px;
|
border-radius: 9px;
|
font-size: 12px;
|
font-weight: 700;
|
letter-spacing: 0.03em;
|
text-align: center;
|
cursor: pointer;
|
transition: transform 0.2s ease, filter 0.2s ease, box-shadow 0.2s ease;
|
|
&--inhead {
|
color: #fff;
|
background: linear-gradient(
|
135deg,
|
var(--pk-show-gold, #FFD88A) 0%,
|
var(--pk-show-accent, #{$orange}) 52%,
|
var(--pk-show-primary, #{$brown}) 100%
|
);
|
border: 1px solid rgba(255, 255, 255, 0.38);
|
box-shadow:
|
0 3px 12px var(--pk-show-accent-soft, rgba(255, 140, 66, 0.42)),
|
inset 0 1px 0 rgba(255, 255, 255, 0.48);
|
text-shadow: 0 1px 2px rgba(61, 46, 34, 0.28);
|
|
&:hover {
|
filter: brightness(1.07);
|
transform: translateY(-1px);
|
box-shadow:
|
0 5px 16px var(--pk-show-accent-soft, rgba(255, 140, 66, 0.52)),
|
inset 0 1px 0 rgba(255, 255, 255, 0.55);
|
}
|
}
|
}
|
|
.pk_empty {
|
min-height: 280px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
color: $brown;
|
cursor: pointer;
|
border: 2px dashed rgba(74, 55, 40, 0.3);
|
border-radius: 12px;
|
background: rgba(255, 255, 255, 0.45);
|
font-size: 14px;
|
}
|
|
.pk_vs {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
font-size: 28px;
|
font-weight: 700;
|
flex-shrink: 0;
|
min-width: 36px;
|
padding: 0 2px;
|
align-self: start;
|
margin-top: 68px;
|
|
&.pk_vs--spacer {
|
visibility: hidden;
|
pointer-events: none;
|
margin-top: 0;
|
}
|
}
|
|
.pk_params {
|
min-width: 0;
|
}
|
|
.pk_param_col {
|
min-width: 0;
|
}
|
|
.pk_param_head {
|
padding: 10px;
|
border-radius: 10px 10px 0 0;
|
overflow: hidden;
|
box-shadow: 0 2px 10px rgba(74, 55, 40, 0.1);
|
|
&--solo {
|
border-radius: 10px;
|
}
|
}
|
|
.pk_param_pills {
|
background: #fff;
|
border-radius: 0 0 8px 8px;
|
padding: 10px;
|
}
|
|
.pill {
|
display: flex;
|
justify-content: space-between;
|
padding: 8px 10px;
|
margin-bottom: 6px;
|
background: $row-bg;
|
border-radius: 20px;
|
font-size: 12px;
|
|
.pill_label {
|
color: #666;
|
}
|
|
.pill_val {
|
color: $brown;
|
font-weight: 500;
|
}
|
|
&.pill_diff {
|
background: $cream;
|
}
|
}
|
}
|
</style>
|