mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-11-06 17:09:08 +08:00
- buyer(95) / seller(169) / im(53) / manager(280) 共 597 个组件全部从 Options API 转换为 <script setup> - 四端 vuex 全部移除,状态管理统一迁移至 pinia 4(stores/ 目录) - util.js 等基础设施去除 vm 首参依赖;全局属性($Message/$filters 等)在 script 内改为具名导入 - 被外部 ref 访问的公共组件均已补齐 defineExpose(清单见各端 MIGRATION-VUE3.md) - 各端 eslint 启用 vue/component-api-style 防止新代码回退 Options API - 四端 yarn build 全部通过;迁移约定与注意事项已更新至各端 MIGRATION-VUE3.md
288 lines
8.1 KiB
Vue
288 lines
8.1 KiB
Vue
<template>
|
||
<div class="container">
|
||
<el-dialog v-model="showCpmodel" width="350">
|
||
<template #header>
|
||
<p style="color:black;text-align:left">
|
||
<!-- <el-icon><InfoFilled /></el-icon> -->
|
||
<span>活动优惠券</span>
|
||
</p>
|
||
</template>
|
||
<div class="coupon-scroll" @scroll="handleReachBottom">
|
||
<el-card shadow="never" v-for="(item, index) in autoCoupList" :key="index" style="margin: 10px 15px">
|
||
<span v-if="item.couponType === 'PRICE'" class="fontsize_12 global_color" style="font-size: 15px;">¥<span class="price">{{ $filters.unitPrice(item.price) }}</span></span>
|
||
<span v-if="item.couponType === 'DISCOUNT'" class="fontsize_12 global_color" style="font-size: 15px;"><span class="price">{{item.discount}}</span>折</span>
|
||
<span class="describe" style="font-size: 15px;margin-left: 5px;">满{{item.consumeThreshold}}元可用</span>
|
||
<p style="font-size: 14px;">使用范围:{{useScope(item.scopeType, item.storeName)}}</p>
|
||
<p style="font-size: 14px;">有效期:{{item.endTime}}</p>
|
||
</el-card>
|
||
</div>
|
||
<template #footer>
|
||
<el-button type="danger" @click="showCpmodel=false">确定</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- 固定头部 -->
|
||
<hover-search class="hover-search" :class="{show: topSearchShow}"></hover-search>
|
||
<!-- 顶部广告 -->
|
||
<FixedTopPage :data="topAdvert"></FixedTopPage>
|
||
<!-- 头部 包括登录,我的订单等 -->
|
||
<BaseHeader></BaseHeader>
|
||
<!-- 搜索框、logo -->
|
||
<Search></Search>
|
||
<div class="index-main">
|
||
<!-- 商品分类 + 楼层装修(同一宽度容器,保证与分类栏左缘对齐) -->
|
||
<cateNav :showAlways="true" v-if="showNav" :large="carouselLarge" :opacity="carouselOpacity"></cateNav>
|
||
<model-form :data="modelFormData"></model-form>
|
||
</div>
|
||
<!-- 底部栏 -->
|
||
<BaseFooter></BaseFooter>
|
||
<!-- 侧边栏 -->
|
||
<fixedBar class="fixed-bar" :class="{'show-fixed': topSearchShow}"></fixedBar>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { onMounted, onUnmounted, ref } from "vue";
|
||
import Search from '@/components/Search';
|
||
import ModelForm from '@/components/indexDecorate/ModelForm';
|
||
import HoverSearch from '@/components/header/hoverSearch';
|
||
import fixedBar from '@/components/fixed/index';
|
||
import storage from "@/plugins/storage";
|
||
import { indexData, getAutoCoup } from '@/api/index.js';
|
||
import { seckillByDay } from '@/api/promotion';
|
||
|
||
defineOptions({ name: "Index" });
|
||
|
||
const props = defineProps({
|
||
pageData: {
|
||
type: null,
|
||
default: "",
|
||
},
|
||
});
|
||
|
||
const autoCoupList = ref([]);
|
||
const showCpmodel = ref(false);
|
||
const modelFormData = ref({ list: [] }); // 楼层装修数据
|
||
const topAdvert = ref({}); // 顶部广告
|
||
const showNav = ref(false); // 是否展示分类栏
|
||
const topSearchShow = ref(false); // 滚动后顶部搜索栏展示
|
||
const carouselLarge = ref(false); // 不同轮播分类尺寸
|
||
const carouselOpacity = ref(false); // 不同轮播分类样式
|
||
|
||
// 优惠券可用范围
|
||
function useScope(type, storeName) {
|
||
let shop = '平台';
|
||
let goods = '全部商品';
|
||
if (storeName !== 'platform') shop = storeName;
|
||
switch (type) {
|
||
case 'ALL':
|
||
goods = '全部商品';
|
||
break;
|
||
case 'PORTION_GOODS':
|
||
goods = '部分商品';
|
||
break;
|
||
case 'PORTION_GOODS_CATEGORY':
|
||
goods = '部分分类商品';
|
||
break;
|
||
}
|
||
return `${shop}${goods}可用`;
|
||
}
|
||
|
||
function fetchAutoCoup() {
|
||
let data = new Date();
|
||
let datas = data.getDate();
|
||
let hours = data.getHours();
|
||
let flagCoup = storage.getItem('getTimes'); //缓存
|
||
if (flagCoup && flagCoup != undefined && flagCoup != null) { //判断当前是否有缓存
|
||
if (Number(datas) > Number(flagCoup)) { //判断缓存是否小于当前天数
|
||
if (Number(hours) >= 6) { //超过或等于6时清楚缓存
|
||
storage.setItem('getTimes', datas); //存储缓存
|
||
getcps();
|
||
}
|
||
}
|
||
} else {
|
||
getcps();
|
||
}
|
||
}
|
||
|
||
function getcps() {
|
||
let data = new Date();
|
||
let datas = data.getDate();
|
||
getAutoCoup().then(res => { //调用自动发券
|
||
if (res.success) {
|
||
autoCoupList.value.push(...res.result);
|
||
let objs = {};
|
||
autoCoupList.value = autoCoupList.value.reduce((cur, next) => {
|
||
//对象去重
|
||
if (next.id != undefined) {
|
||
objs[next.id]
|
||
? ""
|
||
: (objs[next.id] = true && cur.push(next));
|
||
}
|
||
return cur;
|
||
}, []);
|
||
if (autoCoupList.value != '' && autoCoupList.value.length > 0) {
|
||
showCpmodel.value = true;
|
||
}
|
||
storage.setItem('getTimes', datas); //存储缓存
|
||
}
|
||
}).catch((err) => {
|
||
console.warn('获取自动发券信息失败', err);
|
||
});
|
||
}
|
||
|
||
function handleReachBottom() {
|
||
}
|
||
|
||
function getIndexData() {
|
||
if (props.pageData) {
|
||
parsePageData(JSON.stringify(props.pageData)).catch(() => {
|
||
// 装修数据解析失败时保持默认空楼层
|
||
});
|
||
} else {
|
||
// 获取首页装修数据
|
||
indexData({ clientType: 'PC' }).then(async (res) => {
|
||
if (res.success && res.result?.pageData) {
|
||
try {
|
||
await parsePageData(res.result.pageData);
|
||
} catch {
|
||
// 装修数据解析失败时保持默认空楼层
|
||
}
|
||
}
|
||
}).catch((err) => {
|
||
console.warn('获取首页装修数据失败', err);
|
||
});
|
||
}
|
||
}
|
||
|
||
async function parsePageData(pageData) {
|
||
const dataJson = typeof pageData === "string" ? JSON.parse(pageData) : pageData;
|
||
if (!dataJson?.list?.length) {
|
||
return;
|
||
}
|
||
// 秒杀活动不是装修的数据,需要调用接口判断是否有秒杀商品
|
||
// 轮播图根据不同轮播,样式不同
|
||
for (let i = 0; i < dataJson.list.length; i++) {
|
||
let type = dataJson.list[i].type;
|
||
if (type === 'carousel2') {
|
||
carouselLarge.value = true;
|
||
} else if (type === 'carousel1') {
|
||
carouselLarge.value = true;
|
||
carouselOpacity.value = true;
|
||
} else if (type === 'seckill') {
|
||
let seckill = await getListByDay();
|
||
dataJson.list[i].options.list = seckill;
|
||
}
|
||
}
|
||
modelFormData.value = dataJson;
|
||
if (dataJson.list[1]) {
|
||
storage.setItem('navList', dataJson.list[1]);
|
||
}
|
||
showNav.value = true;
|
||
if (dataJson.list[0]) {
|
||
topAdvert.value = dataJson.list[0];
|
||
}
|
||
}
|
||
|
||
async function getListByDay() { // 当天秒杀活动
|
||
try {
|
||
const res = await seckillByDay();
|
||
if (res.success && res.result?.length) {
|
||
return res.result;
|
||
}
|
||
} catch {
|
||
// 秒杀接口失败时不影响首页其他模块
|
||
}
|
||
return [];
|
||
}
|
||
|
||
function handleScroll() {
|
||
const top = document.documentElement.scrollTop || document.body.scrollTop;
|
||
topSearchShow.value = top > 300;
|
||
}
|
||
|
||
onMounted(() => {
|
||
getIndexData();
|
||
window.onscroll = handleScroll;
|
||
if (storage.getItem('userInfo')) {
|
||
fetchAutoCoup();
|
||
}
|
||
});
|
||
|
||
onUnmounted(() => {
|
||
if (window.onscroll === handleScroll) {
|
||
window.onscroll = null;
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
@import '../assets/styles/coupon.scss';
|
||
.container {
|
||
@include sub_background_color($light_background_color);
|
||
}
|
||
</style>
|
||
<style>
|
||
.hover-search {
|
||
width: 100%;
|
||
height: 60px;
|
||
transform: translateY(-200px);
|
||
background-color: #fff;
|
||
position: fixed;
|
||
top: 0;
|
||
z-index: 9999;
|
||
box-shadow:0 0 10px 2px rgb(90 90 90 / 60%);
|
||
transition: 0.35s;
|
||
}
|
||
.show {
|
||
transform: translateY(0) translateZ(0);
|
||
top: 0;
|
||
}
|
||
.fixed-bar{
|
||
opacity: 0 !important;
|
||
transform: translateY(-10px);
|
||
transition: .35s;
|
||
z-index: 999999;
|
||
height: 0px !important;
|
||
overflow: hidden;
|
||
}
|
||
.show-fixed{
|
||
height: 354px !important;
|
||
opacity: 1 !important;
|
||
transform: translateY(0) translateZ(0);
|
||
}
|
||
|
||
|
||
/* 2K */
|
||
@media screen and (min-width: 2561px) and (max-width: 3840px) {
|
||
/* 样式 */
|
||
.fixed-bar{
|
||
position: fixed;
|
||
right:900px;
|
||
top: 500px;
|
||
}
|
||
}
|
||
|
||
/* 1080p */
|
||
@media screen and (max-width: 2560px) {
|
||
/* 样式 */
|
||
.fixed-bar{
|
||
position: fixed;
|
||
right:300px;
|
||
top: 500px;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
@media screen and (max-width: 2025px) {
|
||
/* 样式 */
|
||
.fixed-bar{
|
||
position: fixed;
|
||
right:150px;
|
||
top: 300px;
|
||
}
|
||
}
|
||
|
||
</style>
|