generated from chenhao/template-h5
数据字典改按需请求、商城爆款改茶品飘香轮播、分类页支持 pid 定位
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
7083c8d27e
commit
1f98c287cd
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.1 KiB |
@ -99,7 +99,8 @@ export default {
|
||||
this._skipWatch = true
|
||||
this.loadMore()
|
||||
this.$emit('refresh', this.list)
|
||||
this._skipWatch = false
|
||||
// 等 params 的 deep watcher 排队回调跑完再解锁,避免同一轮 tick 里被再触发一次
|
||||
this.$nextTick(() => { this._skipWatch = false })
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
10
src/main.js
10
src/main.js
@ -68,12 +68,11 @@ window.__currentPath = () => currentPath;
|
||||
app.use(router);
|
||||
|
||||
import pinia from './stores';
|
||||
import { useDatadicStore, dictCache } from './stores/datadic';
|
||||
import { useDatadicStore } from './stores/datadic';
|
||||
import { useUserStore } from './stores/user';
|
||||
app.use(pinia);
|
||||
|
||||
const datadicStore = useDatadicStore()
|
||||
datadicStore.init()
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
@ -90,8 +89,11 @@ const userStore = useUserStore()
|
||||
// });
|
||||
|
||||
app.config.globalProperties.$datadic = {
|
||||
get: (code) => dictCache[code] || null,
|
||||
getContent: (code) => dictCache[code] ? dictCache[code].contents : '',
|
||||
get: (code) => datadicStore.fetch(code),
|
||||
getContent: async (code) => {
|
||||
const item = await datadicStore.fetch(code)
|
||||
return item ? item.contents : ''
|
||||
},
|
||||
}
|
||||
|
||||
app.config.globalProperties.$userInfo = userStore.getUserInfo;
|
||||
|
||||
@ -1,53 +1,17 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { get } from '@/api/http'
|
||||
|
||||
export let dictCache = {}
|
||||
|
||||
const SESSION_KEY = 'dict_cache'
|
||||
|
||||
// 按需请求:调用时才拉,不做本地缓存
|
||||
export const useDatadicStore = defineStore('datadic', {
|
||||
state: () => ({
|
||||
dicts: {},
|
||||
loaded: false
|
||||
}),
|
||||
getters: {
|
||||
getByCode: (state) => (code) => {
|
||||
return dictCache[code] || null
|
||||
},
|
||||
getContent: (code) => {
|
||||
const item = dictCache[code]
|
||||
return item ? item.contents : ''
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
async init() {
|
||||
// 优先从 sessionStorage 读取缓存
|
||||
const cached = sessionStorage.getItem(SESSION_KEY)
|
||||
if (cached) {
|
||||
try {
|
||||
dictCache = JSON.parse(cached)
|
||||
this.dicts = dictCache
|
||||
this.loaded = true
|
||||
return
|
||||
} catch (e) {
|
||||
sessionStorage.removeItem(SESSION_KEY)
|
||||
}
|
||||
}
|
||||
if (this.loaded) return
|
||||
async fetch(code) {
|
||||
try {
|
||||
// 使用持久请求,防止被路由切换时的 abortAll() 取消
|
||||
const res = await get('/v1/client/CDatadicsClient', undefined, undefined, undefined, true)
|
||||
if (res.status === 200 && res.data) {
|
||||
res.data.forEach(item => {
|
||||
dictCache[item.code] = item
|
||||
})
|
||||
this.dicts = dictCache
|
||||
this.loaded = true
|
||||
sessionStorage.setItem(SESSION_KEY, JSON.stringify(dictCache))
|
||||
}
|
||||
const res = await get(`/v1/client/CDatadicsClient/${code}`)
|
||||
return res?.data || null
|
||||
} catch (e) {
|
||||
console.error('数据字典加载失败', e)
|
||||
console.error('数据字典加载失败', code, e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@ -1134,53 +1134,74 @@
|
||||
}
|
||||
|
||||
.mall_page__hot {
|
||||
background: #fff;
|
||||
border-radius: 2vw;
|
||||
overflow: hidden;
|
||||
margin-top: 4vw;
|
||||
margin-bottom: 4vw;
|
||||
background-image: linear-gradient(0deg,
|
||||
#ffffff 0%,
|
||||
#d5ecd6 100%);
|
||||
border-radius: 2.67vw;
|
||||
|
||||
.mall_page__hot_header {
|
||||
.box;
|
||||
.box-align-center;
|
||||
height: 10vw;
|
||||
padding: 0vw 2.8vw;
|
||||
background-color: #ffb43d;
|
||||
color: #a86906;
|
||||
height: 12.53vw;
|
||||
padding: 2.93vw;
|
||||
|
||||
color: #2e5d31;
|
||||
|
||||
img {
|
||||
width: 4.27vw;
|
||||
width: 4.8vw;
|
||||
}
|
||||
|
||||
b {
|
||||
font-size: 4.8vw;
|
||||
color: #ffffff;
|
||||
color: #000000;
|
||||
margin: 0 3.6vw 0 1.47vw;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #a86906;
|
||||
color: #2e5d31;
|
||||
}
|
||||
}
|
||||
|
||||
.van-swipe {
|
||||
width: calc(100% - 5.86vw);
|
||||
}
|
||||
|
||||
|
||||
.mall_page__hot_list {
|
||||
.box;
|
||||
// margin-bottom: 3vw;
|
||||
padding: 4vw 3.33vw;
|
||||
overflow-x: auto
|
||||
background-color: #ffffff;
|
||||
border-radius: 2.67vw;
|
||||
// padding: 4vw 3.73vw;
|
||||
padding: 4vw 0;
|
||||
margin: 0 2.93vw;
|
||||
|
||||
.van-swipe-item {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
row-gap: 3.2vw;
|
||||
column-gap: 4vw;
|
||||
box-sizing: border-box;
|
||||
padding: 0 3.73vw;
|
||||
}
|
||||
|
||||
.van-swipe__indicators {
|
||||
bottom: 1.6vw;
|
||||
}
|
||||
}
|
||||
|
||||
.mall_page__hot_item {
|
||||
.box;
|
||||
.box-tb;
|
||||
margin-right: 2.67vw;
|
||||
width: 34.67vw;
|
||||
.box-align-start;
|
||||
width: max-content;
|
||||
|
||||
img {
|
||||
object-fit: contain;
|
||||
width: 34.67vw;
|
||||
height: 34.67vw;
|
||||
background-color: #e5e5e5;
|
||||
width: 24vw;
|
||||
height: 24vw;
|
||||
border-radius: 1.33vw;
|
||||
}
|
||||
|
||||
@ -1188,23 +1209,17 @@
|
||||
font-size: 3.2vw;
|
||||
font-weight: bold;
|
||||
line-height: 4vw;
|
||||
min-height: 4vw;
|
||||
max-width: 24.27vw;
|
||||
color: #333333;
|
||||
min-height: 8vw;
|
||||
.text-hide(2);
|
||||
margin-top: 2.8vw;
|
||||
}
|
||||
|
||||
.mall_page__hot_price--original {
|
||||
font-size: 3.2vw;
|
||||
text-decoration: line-through;
|
||||
// line-height: 4.8vw;
|
||||
color: #b1b1b1;
|
||||
margin-top: 1.67vw;
|
||||
.text-hide(1);
|
||||
margin-top: 1.6vw;
|
||||
}
|
||||
|
||||
.mall_page__hot_price {
|
||||
font-size: 4vw;
|
||||
font-size: 3.47vw;
|
||||
font-weight: bold;
|
||||
line-height: 4.8vw;
|
||||
color: #ea3e23;
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@
|
||||
<!-- 用户协议 -->
|
||||
<van-checkbox icon-size="3.73vw" class="login_page__agreement" v-model="checked"
|
||||
checked-color="var(--main-color)">
|
||||
选中即代表同意<a @click.stop="showContract = true">《用户协议》</a>和<a @click.stop="showPolicy = true">《隐私政策》</a>
|
||||
选中即代表同意<a @click.stop="openContract">《用户协议》</a>和<a @click.stop="openPolicy">《隐私政策》</a>
|
||||
</van-checkbox>
|
||||
|
||||
<!-- 底部链接 -->
|
||||
@ -106,13 +106,13 @@
|
||||
<!-- 用户协议弹窗 -->
|
||||
<van-action-sheet v-model:show="showContract" safe-area-inset-bottom title="用户协议" closeable
|
||||
style="min-height: 50%; padding: 0px 10px 10px 10px">
|
||||
<div class="w100 html" v-html="$datadic.getContent('code_yhxy')"></div>
|
||||
<div class="w100 html" v-html="contractHtml"></div>
|
||||
</van-action-sheet>
|
||||
|
||||
<!-- 隐私政策弹窗 -->
|
||||
<van-action-sheet v-model:show="showPolicy" safe-area-inset-bottom title="隐私政策" closeable
|
||||
style="min-height: 50%; padding: 0px 10px 10px 10px">
|
||||
<div class="w100 html" v-html="$datadic.getContent('code_yszc')"></div>
|
||||
<div class="w100 html" v-html="policyHtml"></div>
|
||||
</van-action-sheet>
|
||||
</template>
|
||||
|
||||
@ -137,6 +137,8 @@ export default {
|
||||
showConfirmPassword: false,
|
||||
showContract: false,
|
||||
showPolicy: false,
|
||||
contractHtml: '',
|
||||
policyHtml: '',
|
||||
loading: false,
|
||||
smsCode: '', // 接口返回的验证码
|
||||
countdown: {
|
||||
@ -147,6 +149,14 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async openContract() {
|
||||
this.showContract = true
|
||||
this.contractHtml = await this.$datadic.getContent('code_yhxy')
|
||||
},
|
||||
async openPolicy() {
|
||||
this.showPolicy = true
|
||||
this.policyHtml = await this.$datadic.getContent('code_yszc')
|
||||
},
|
||||
init() {
|
||||
// 防止刷新重复处理微信 code
|
||||
if (sessionStorage.getItem('wx_code_processed') === '1') {
|
||||
|
||||
@ -74,7 +74,7 @@
|
||||
<b><span>¥</span>{{ item.saleprice?.toFixed(2) }}</b>
|
||||
<span class="r" style="color: #8a8a8a;font-size: 3.2vw;">销量{{
|
||||
item.salenums
|
||||
}}</span>
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -186,6 +186,9 @@ export default {
|
||||
if (this.$route.query.id) {
|
||||
this.changeMainById(Number(this.$route.query.id));
|
||||
}
|
||||
if (this.$route.query.pid) {
|
||||
this.selectByPid(Number(this.$route.query.pid));
|
||||
}
|
||||
if (this.$route.query.SortType == 2) {
|
||||
this.searchParams.orderby = 'salenumdown';
|
||||
}
|
||||
@ -263,6 +266,52 @@ export default {
|
||||
this.changeMain(item);
|
||||
}
|
||||
},
|
||||
// 根据 pid 定位到对应层级并激活选中态
|
||||
selectByPid(pid) {
|
||||
const third = this.thirdCategories.find(x => x.id === pid);
|
||||
if (third) {
|
||||
const first = this.firstCategories.find(x => x.id === third.rootId);
|
||||
if (first) {
|
||||
this.mainCategory = first.id;
|
||||
this.typeName = first.name;
|
||||
this.selectedSecond = this.secondCategories.filter(x => x.parentId === first.id);
|
||||
}
|
||||
this.selectedThird = this.thirdCategories.filter(x => x.parentId === third.parentId);
|
||||
this.goodsCategoryIndex = this.selectedThird.findIndex(x => x.id === pid) + 1;
|
||||
this.currentThirdId = pid;
|
||||
this.queryParams.pid = pid;
|
||||
this.refreshProductList();
|
||||
this.$nextTick(() => {
|
||||
this.secondCategory = third.parentId;
|
||||
});
|
||||
return;
|
||||
}
|
||||
const second = this.secondCategories.find(x => x.id === pid);
|
||||
if (second) {
|
||||
const first = this.firstCategories.find(x => x.id === second.parentId);
|
||||
if (first) {
|
||||
this.mainCategory = first.id;
|
||||
this.typeName = first.name;
|
||||
this.selectedSecond = this.secondCategories.filter(x => x.parentId === first.id);
|
||||
}
|
||||
this.selectedThird = this.thirdCategories.filter(x => x.parentId === pid);
|
||||
this.goodsCategoryIndex = 0;
|
||||
this.currentThirdId = '';
|
||||
this.queryParams.pid = pid;
|
||||
this.refreshProductList();
|
||||
this.$nextTick(() => {
|
||||
this.secondCategory = pid;
|
||||
});
|
||||
return;
|
||||
}
|
||||
const first = this.firstCategories.find(x => x.id === pid);
|
||||
if (first) {
|
||||
this.changeMain(first);
|
||||
return;
|
||||
}
|
||||
this.queryParams.pid = pid;
|
||||
this.refreshProductList();
|
||||
},
|
||||
changeSecond(e) {
|
||||
if (e) {
|
||||
this.queryParams.pid = e;
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
<div class="mall_page__banner">
|
||||
<van-swipe :autoplay="3000" indicator-color="white" @change="onSwipeChange">
|
||||
<van-swipe-item v-for="item in data.Carousel">
|
||||
<a @click="item.link ? $openUrl(item.link) : ''"><img :src="$file(item.img) || '/img/img-avatar-default.png'"
|
||||
width="100%"></a>
|
||||
<a @click="item.link ? $openUrl(item.link) : ''"><img
|
||||
:src="$file(item.img) || '/img/img-avatar-default.png'" width="100%"></a>
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
</div>
|
||||
@ -41,18 +41,33 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mall_page__hot" v-if="hotData.length > 0">
|
||||
<div class="mall_page__hot">
|
||||
<div class="mall_page__hot_header">
|
||||
<img src="/img/icon-hot.png" alt="">
|
||||
<b>爆款好物</b>
|
||||
<p>超多会员已购买</p>
|
||||
<span class="r" @click="$navigate('Category?SortType=2')">
|
||||
<b>茶品飘香</b>
|
||||
<p>精选茶叶礼盒</p>
|
||||
<span class="r" @click="$navigate('Category?pid=1044')">
|
||||
查看更多
|
||||
<van-icon name="arrow" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="mall_page__hot_list">
|
||||
<van-swipe class="mall_page__hot_list" indicator-color="white" :autoplay="3000">
|
||||
<van-swipe-item class="contaniar" v-for="(group, gi) in comHotData" :key="gi">
|
||||
<div class="mall_page__hot_item" v-for="list in group" :key="list.id"
|
||||
@click="$navigate('GoodsDetail?id=' + list.id)">
|
||||
<img :src="$file(list.img)" alt="">
|
||||
<span class="mall_page__hot_title">
|
||||
{{ list.name }}
|
||||
</span>
|
||||
<span class="mall_page__hot_price">
|
||||
¥{{ list.saleprice?.toFixed(2) }}
|
||||
</span>
|
||||
</div>
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
|
||||
<!-- <div class="mall_page__hot_list">
|
||||
<div class="mall_page__hot_item" v-for="list in hotData" @click="$navigate('GoodsDetail?id=' + list.id)">
|
||||
<img :src="$file(list.img)" alt="">
|
||||
<span class="mall_page__hot_title">
|
||||
@ -65,7 +80,7 @@
|
||||
¥{{ list.saleprice?.toFixed(2) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<div class="mall_page__goods">
|
||||
@ -148,7 +163,7 @@ export default {
|
||||
this.data.Carousel = res.data
|
||||
this.bgcolor = res.data?.[0]?.bgcolor || ''
|
||||
}),
|
||||
this.$get('/v1/client/EProsClient?recommend=true').then(res => {
|
||||
this.$get('/v1/client/EProsClient?pid=1044&pageSize=100').then(res => {
|
||||
this.hotData = res.data.items || []
|
||||
}),
|
||||
this.$get('/v1/client/EProcatesClient/3').then(res => {
|
||||
@ -175,6 +190,13 @@ export default {
|
||||
btnStyle() {
|
||||
return this.bgcolor ? { background: this.bgcolor } : {}
|
||||
},
|
||||
comHotData() {
|
||||
const groups = []
|
||||
for (let i = 0; i < this.hotData.length; i += 9) {
|
||||
groups.push(this.hotData.slice(i, i + 9))
|
||||
}
|
||||
return groups
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<div class="balance_page__top">
|
||||
<div class="balance_page__line">
|
||||
<b class="balance_page__title">
|
||||
当前余额 <van-icon name="question-o" @click.stop="showTerm = true"></van-icon>
|
||||
当前余额 <van-icon name="question-o" @click.stop="onShowTerm"></van-icon>
|
||||
</b>
|
||||
|
||||
<div v-if="!hide" class="balance_page__record_link" @click="$navigate('CashoutRecord')">
|
||||
@ -124,7 +124,7 @@
|
||||
</van-popup>
|
||||
<van-action-sheet v-model:show="showTerm" safe-area-inset-bottom :title="`${this.$route.meta.title}说明`"
|
||||
closeable style="min-height: 50%; padding: 0px 10px 10px 10px">
|
||||
<div class="w100 html" v-html="$datadic.getContent('code_yesm')" />
|
||||
<div class="w100 html" v-html="termHtml" />
|
||||
</van-action-sheet>
|
||||
|
||||
</BasePage>
|
||||
@ -158,6 +158,7 @@ export default {
|
||||
},
|
||||
loading: false,
|
||||
showTerm: false,
|
||||
termHtml: '',
|
||||
list: [],
|
||||
isVIP: '',
|
||||
hide: false,
|
||||
@ -200,8 +201,9 @@ export default {
|
||||
this.searchParams.type = e || '';
|
||||
// this.$refs.baselist.refresh();
|
||||
},
|
||||
onShowTerm() {
|
||||
async onShowTerm() {
|
||||
this.showTerm = true;
|
||||
this.termHtml = await this.$datadic.getContent('code_yesm');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user