feat(style): 购物车样式动画交互修改

This commit is contained in:
woody 2025-04-27 16:33:44 +08:00
parent 336b372536
commit 820dae5c84
4 changed files with 423 additions and 319 deletions

View File

@ -22,86 +22,92 @@
>
<div class="pop_t">
<div class="pop_tt">
<!-- <div class="kong"></div> -->
<div>{{ '购物车' }}</div>
<!-- <img src="@/assets/images/x.png"
alt=""> -->
<div>购物车</div>
</div>
<div class="pop_tb">
<div
class="pop_i"
v-for="(item, index) in shopCarList[0].shoppingCartList"
:key="index"
>
<img :src="item.cover1" alt="" />
<div class="pop_ill">
<div class="tit1 pop_illd">{{ item.waresName }}</div>
<div class="dis">
<span class="tit2"
>{{ userInfo.currencyIcon
}}{{ item.waresPrice | numberToCurrency }}</span
>
<span class="tit3"
>{{ '业绩' }}:{{
item.achieve | numberToCurrency
}}</span
>
<span
class="tit3"
v-show="shopCarList[0].specialArea == 13"
style="margin-left: 10px"
>BV:{{ item.assAchieve | numberToCurrency }}</span
>
</div>
<div class="pop_ilb">
<el-input-number
v-model="item.number"
size="mini"
@change="changeCar(item, index)"
:min="1"
></el-input-number>
<el-popover
placement="bottom"
v-if="shopCarList[0].specialArea != 21"
trigger="click"
>
<div
v-for="(stem, sndex) in item.productParams"
:key="sndex"
class="tab_i2i"
<el-empty
v-if="
!shopCarList[0] ||
!shopCarList[0].shoppingCartList ||
shopCarList[0].shoppingCartList.length === 0
"
description="购物车还是空的,快去逛逛吧!"
:image-size="80"
></el-empty>
<div v-else>
<div
class="pop_i"
v-for="(item, index) in shopCarList[0].shoppingCartList"
:key="index"
>
<img :src="item.cover1" alt="" />
<div class="pop_ill">
<div class="tit1 pop_illd">{{ item.waresName }}</div>
<div class="dis">
<span class="tit2"
>{{ userInfo.currencyIcon
}}{{ item.waresPrice | numberToCurrency }}</span
>
<div class="tab_i2il">
{{ stem.productName
}}{{
stem.waresItemsParamsList.length > 0 &&
stem.waresItemsParamsList[0].specsName
}}
</div>
<div class="tab_i2ir">
*{{ stem.waresItemsParamsList[0].quantity }}
</div>
</div>
<div slot="reference">{{ '查看规格' }}</div>
</el-popover>
<el-popover placement="bottom" v-else trigger="click">
<div
v-for="(stem, sndex) in item.waresSkuList"
:key="sndex"
class="tab_i2i"
<span class="tit3"
>{{ "业绩" }}:{{ item.achieve | numberToCurrency }}</span
>
<div class="tab_i2il">{{ stem.specValueNames }}</div>
</div>
<div slot="reference">{{ '查看规格' }}</div>
</el-popover>
</div>
</div>
<span
class="tit3"
v-show="shopCarList[0].specialArea == 13"
style="margin-left: 10px"
>BV:{{ item.assAchieve | numberToCurrency }}</span
>
</div>
<div class="pop_ilb">
<el-input-number
v-model="item.number"
size="mini"
@change="changeCar(item, index)"
:min="1"
></el-input-number>
<div class="delImg" @click="delData(item)">
<img src="@/assets/images/delImg.png" alt="" />
<el-popover
placement="bottom"
v-if="shopCarList[0].specialArea != 21"
trigger="click"
>
<div
v-for="(stem, sndex) in item.productParams"
:key="sndex"
class="tab_i2i"
>
<div class="tab_i2il">
{{ stem.productName
}}{{
stem.waresItemsParamsList.length > 0 &&
stem.waresItemsParamsList[0].specsName
}}
</div>
<div class="tab_i2ir">
*{{ stem.waresItemsParamsList[0].quantity }}
</div>
</div>
<div slot="reference">{{ "查看规格" }}</div>
</el-popover>
<el-popover placement="bottom" v-else trigger="click">
<div
v-for="(stem, sndex) in item.waresSkuList"
:key="sndex"
class="tab_i2i"
>
<div class="tab_i2il">{{ stem.specValueNames }}</div>
</div>
<div slot="reference">{{ "查看规格" }}</div>
</el-popover>
</div>
</div>
<div class="delImg" @click="delData(item)">
<img src="@/assets/images/delImg.png" alt="" />
</div>
<!-- <div class="tit4"
@click="delData(item)">删除</div> -->
</div>
<!-- <div class="tit4"
@click="delData(item)">删除</div> -->
</div>
</div>
</div>
@ -109,13 +115,13 @@
<div class="tit5">
<div class="pop_bl">
<div class="pop_bl">
{{ '总价' }}:<span class="tit2"
{{ "总价" }}:<span class="tit2"
>{{ userInfo.currencyIcon
}}{{ totalPrice | numberToCurrency }}</span
>
</div>
<div class="pop_bl">
{{ '业绩' }}:<span class="tit3"
{{ "业绩" }}:<span class="tit3"
>{{ userInfo.pkCountry == 1 ? "¥" : "$"
}}{{ totalAchive | numberToCurrency }}</span
>
@ -130,28 +136,23 @@
<!-- <div style="margin-top:10px">{{ howLevel }}</div> -->
</div>
<div class="pop_br" @click="toBuy">{{ '立即购买' }}</div>
<!-- <div class="pop_br" @click="toBuy">立即购买</div> -->
<el-button type="primary" @click="toBuy" :disabled="orderBtnDisabled">
立即购买</el-button
>
</div>
<div class="bian_i" ref="shoppCar" slot="reference">
<div class="dian_f">
<img src="@/assets/images/car.jpg" alt="" />
<div class="dian">{{ specialCarNum }}</div>
</div>
<div>{{ '购物车' }}</div>
<div>购物车</div>
</div>
</el-popover>
<div class="bian_i" @click="openKf">
<img src="@/assets/images/lxkf.jpg" alt="" />
<div>{{ '联系客服' }}</div>
</div>
<!-- v-show="shareShow&&userInfo.pkSettleCountry==1" -->
<div class="bian_i" @click="showShare">
<img src="@/assets/images/fx.jpg" alt="" />
<div>{{ '分享' }}</div>
</div>
<div class="bian_i" v-show="goTopShow" @click="toTop">
<img src="@/assets/images/hddb.jpg" alt="" />
<div>{{ '回到顶部' }}</div>
<div>{{ "回到顶部" }}</div>
</div>
</div>
<!-- 嗨粉分享 -->
@ -251,7 +252,6 @@
import html2canvas from "html2canvas";
import * as api from "@/api/goods.js";
import { memLevel } from "@/api/register.js";
import { mapGetters } from "vuex";
export default {
@ -280,11 +280,14 @@ export default {
};
},
props: {
showCar: false,
shareShow: false,
showCar: Boolean,
shareShow: Boolean,
},
computed: {
...mapGetters(["userInfo", "specialCarNum"]),
orderBtnDisabled() {
return !this.goodsCheck[0]?.orderItemsParams?.length;
},
},
mounted() {
window.addEventListener("scroll", this.showIcon);
@ -344,6 +347,7 @@ export default {
closePopover() {
this.$refs.popover.doClose();
},
// eslint-disable-next-line no-unused-vars
carShow(e) {
this.$emit("showCar");
},
@ -419,6 +423,7 @@ export default {
this.total = total;
this.selTable = val;
},
// eslint-disable-next-line no-unused-vars
calPrice(e) {
let total = 0;
this.selTable.forEach((item) => {
@ -452,7 +457,6 @@ export default {
this.goodsCheck[0].specialArea == 22 ||
this.goodsCheck[0].specialArea == 26 ||
this.goodsCheck[0].specialArea == 28
) {
this.$router.push({
path: "repurchase",
@ -460,21 +464,6 @@ export default {
specialArea: this.goodsCheck[0].specialArea,
},
});
}else if(this.goodsCheck[0].specialArea == 31){
if (this.totalPrice < 1000) {
this.$message({
message: "购买商品总价格不能低于1000元",
type: "warning",
});
return false;
}else{
this.$router.push({
path: "repurchase",
query: {
specialArea: this.goodsCheck[0].specialArea,
},
});
}
} else if (this.goodsCheck[0].specialArea == 30) {
if (this.goodsCheck[0].orderItemsParams.length > 1) {
this.$message({
@ -501,18 +490,10 @@ export default {
});
}
}
} else if (this.goodsCheck[0].specialArea == 13) {
this.$router.push({
path: "welfare",
});
} else if (this.goodsCheck[0].specialArea == 14) {
this.$router.push({
path: "tvIng",
});
} else if (this.goodsCheck[0].specialArea == 11) {
this.$router.push({
path: "integral",
});
} else if (this.goodsCheck[0].specialArea == 10) {
this.$router.push({
path: "rescission",
@ -566,32 +547,6 @@ export default {
},
});
} else if (this.goodsCheck[0].specialArea == 2) {
// let deleteList = []
// shoppArr.forEach((item) => {
// deleteList.push({
// shoppingId: item,
// })
// })
// api
// .validShop({
// specialArea: this.goodsCheck[0].specialArea,
// deleteList: deleteList,
// })
// .then((res) => {
// if (res.code == 200) {
// this.$router.push({
// path: 'upgrade',
// query: {
// specialArea: this.goodsCheck[0].specialArea,
// },
// })
// } else {
// this.$message({
// type: 'warning',
// message: res.msg,
// })
// }
// })
let deleteList = [];
shoppArr.forEach((item) => {
deleteList.push({
@ -832,20 +787,17 @@ export default {
})
.then((res) => {
this.getCarList(this.specialArea);
this.$store.dispatch(
"SpecialQuantity",
{
specialArea: this.shopCarList[0].specialArea,
pkCountry: Number(localStorage.getItem("pkCountry")),
}
);
this.$store.dispatch("SpecialQuantity", {
specialArea: this.shopCarList[0].specialArea,
pkCountry: Number(localStorage.getItem("pkCountry")),
});
this.$message({
type: "success",
message: '删除成功' + "!",
message: "删除成功" + "!",
});
});
},
// eslint-disable-next-line no-unused-vars
tableRowClassName({ row, rowIndex }) {
if (rowIndex % 2 == 1) {
return "warning-row";
@ -984,7 +936,7 @@ export default {
.pop_br {
width: 117px;
height: 38px;
background: #d61820;
background: var(--primary-color);
border-radius: 8px 8px 8px 8px;
font-size: 12px;
font-weight: 400;

View File

@ -2,4 +2,6 @@
--primary-color: #005BAC; /* 主题色 */
--highlight-color: #1E90FF; /* 替换 #b42b2a 的高亮/强调色 */
--price-color: #FF8C00; /* 商品价格颜色 */
--button-hover-color: #1A75C8; /* 按钮悬停颜色 */
--disabled-color: #B8CDE0; /* 禁用状态颜色 (基于主题色) */
}

View File

@ -144,10 +144,6 @@
</div>
</div>
</div>
<!-- 三级分类 海粉-->
<!-- <div class="twoType_a" v-if="specialArea==21">
</div> -->
<!-- 商品查询 -->
<div v-if="specialArea == 21" class="search">
<el-row :gutter="10">
@ -205,168 +201,185 @@
</el-row>
</div>
<!-- 商品列表 -->
<div class="goodList">
<div class="good_i" v-for="item in goodList" :key="item.waresCode">
<!-- 缺货无货售罄 -->
<div v-show="item.preSaleStatus == 3 || item.isSale == 1">
<div class="cool" v-if="item.coolLabelTarget != undefined">
<img :src="item.coolLabelTarget.labelImage" alt="" />
</div>
<div class="motai"></div>
<div
class="goodList"
v-loading="isLoading"
element-loading-background="rgba(255, 255, 255, 0.8)"
:class="{ 'is-empty': !isLoading && goodList.length === 0 }"
>
<!-- 空状态 -->
<el-empty
v-if="!isLoading && goodList.length === 0"
description="暂无商品"
></el-empty>
<img class="goodImg" :src="item.cover1" alt="" />
<div class="goodBtm">
<div class="disFlex">
<div class="tit1 hui">
{{ userInfo.currencyIcon
}}{{ item.waresPrice | numberToCurrency }}
</div>
<!-- 商品项 -->
<template v-if="!isLoading && goodList.length > 0">
<div class="good_i" v-for="item in goodList" :key="item.waresCode">
<!-- 缺货无货售罄 -->
<div v-show="item.preSaleStatus == 3 || item.isSale == 1">
<div class="cool" v-if="item.coolLabelTarget != undefined">
<img :src="item.coolLabelTarget.labelImage" alt="" />
</div>
<div class="disFlex">
<div class="tit3">
<span
class="qzbq hui_b"
v-if="item.prefixLabelTarget != undefined"
>{{ item.prefixLabelTarget.label }}</span
<div class="motai"></div>
<img class="goodImg" :src="item.cover1" alt="" />
<div class="goodBtm">
<div class="disFlex">
<div class="tit1 hui">
{{ userInfo.currencyIcon
}}{{ item.waresPrice | numberToCurrency }}
</div>
</div>
<div class="disFlex">
<div class="tit3">
<span
class="qzbq hui_b"
v-if="item.prefixLabelTarget != undefined"
>{{ item.prefixLabelTarget.label }}</span
>
<span>{{ item.waresName }}</span>
</div>
</div>
<div class="disFlex">
<div class="tit4 hui">
{{ "销量" }}:{{ item.sales | seles }}
</div>
<div
class="tit4 hui"
v-show="specialArea != 13"
style="margin-left: 10px"
>
<span>{{ item.waresName }}</span>
{{ "业绩" }}:{{ item.waresAchieve | numberToCurrency }}
</div>
<div
class="tit4"
v-show="specialArea == 13"
style="margin-left: 10px"
>
BV:{{ item.assAchieve | numberToCurrency }}
</div>
</div>
</div>
<div class="disFlex">
<div class="tit4 hui">
{{ "销量" }}:{{ item.sales | seles }}
<!-- <img class="addCarImg" :src="addCarImg3" alt=""> -->
<div class="addCarImg1">
<img :src="addCarImg2" alt="" />
<div>加入购物车</div>
</div>
<div
class="tit4 hui"
v-show="specialArea != 13"
style="margin-left: 10px"
>
{{ "业绩" }}:{{ item.waresAchieve | numberToCurrency }}
<div class="md">
<img
v-for="ctem in item.sellingLabelList"
v-show="item.sellingLabelList"
:key="ctem.pkId"
:src="ctem.labelImage || ''"
alt=""
/>
</div>
<div
class="tit4"
v-show="specialArea == 13"
style="margin-left: 10px"
>
BV:{{ item.assAchieve | numberToCurrency }}
</div>
</div>
<!-- <img class="addCarImg" :src="addCarImg3" alt=""> -->
<div class="addCarImg1">
<img :src="addCarImg2" alt="" />
<div>加入购物车</div>
</div>
<div class="md">
<img
v-for="ctem in item.sellingLabelList"
v-show="item.sellingLabelList"
:key="ctem.pkId"
:src="ctem.labelImage || ''"
alt=""
/>
</div>
</div>
</div>
<!-- 正常商品 -->
<div
v-show="item.preSaleStatus != 3 && item.isSale != 1"
@click="goDetails(item)"
>
<div class="cool" v-if="item.coolLabelTarget != undefined">
<img :src="item.coolLabelTarget.labelImage" alt="" />
</div>
<img class="goodImg" :src="item.cover1" alt="" />
<div class="goodBtm">
<div class="disFlex" v-show="specialArea != 31">
<div class="tit1">
{{ userInfo.currencyIcon
}}{{ item.waresPrice | numberToCurrency }}
</div>
<!-- 正常商品 -->
<div
v-show="item.preSaleStatus != 3 && item.isSale != 1"
@click="goDetails(item)"
>
<div class="cool" v-if="item.coolLabelTarget != undefined">
<img :src="item.coolLabelTarget.labelImage" alt="" />
</div>
<div v-show="specialArea == 31">
<div class="disFlex1" v-if="userInfo.isMakerSpace == 0">
<img class="goodImg" :src="item.cover1" alt="" />
<div class="goodBtm">
<div class="disFlex" v-show="specialArea != 31">
<div class="tit1">
{{ userInfo.currencyIcon
}}{{ item.waresPrice | numberToCurrency }}
</div>
<!-- <div class="fflex">
<div class="ling">统一零售价:</div>
<div class="ling">{{ userInfo.currencyIcon }}{{ item.retailPrice |numberToCurrency}}</div>
</div> -->
</div>
<div class="disFlex1" v-if="userInfo.isMakerSpace == 1">
<div class="tit1">
{{ userInfo.currencyIcon
}}{{ item.vipPrice | numberToCurrency }}
<div v-show="specialArea == 31">
<div class="disFlex1" v-if="userInfo.isMakerSpace == 0">
<div class="tit1">
{{ userInfo.currencyIcon
}}{{ item.waresPrice | numberToCurrency }}
</div>
<!-- <div class="fflex">
<div class="ling">统一零售价:</div>
<div class="ling">{{ userInfo.currencyIcon }}{{ item.retailPrice |numberToCurrency}}</div>
</div> -->
</div>
<div class="disFlex1" v-if="userInfo.isMakerSpace == 1">
<div class="tit1">
{{ userInfo.currencyIcon
}}{{ item.vipPrice | numberToCurrency }}
</div>
<!-- <div class="fflex">
<div class="ling">统一零售价:</div>
<div class="ling">{{ userInfo.currencyIcon }}{{ item.retailPrice |numberToCurrency}}</div>
</div> -->
</div>
<!-- <div class="fflex">
<div class="ling">统一零售价:</div>
<div class="ling">{{ userInfo.currencyIcon }}{{ item.retailPrice |numberToCurrency}}</div>
</div> -->
</div>
</div>
<div class="disFlex">
<div class="tit3">
<span
class="qzbq"
v-if="item.prefixLabelTarget != undefined"
>{{ item.prefixLabelTarget.label }}</span
<div class="disFlex">
<div class="tit3">
<span
class="qzbq"
v-if="item.prefixLabelTarget != undefined"
>{{ item.prefixLabelTarget.label }}</span
>
<span>{{ item.waresName }}</span>
</div>
</div>
<div class="disFlex">
<div class="tit4">{{ "销量" }}:{{ item.sales | seles }}</div>
<div
class="tit4"
v-show="specialArea != 13 && specialArea != 31"
style="margin-left: 10px"
>
<span>{{ item.waresName }}</span>
</div>
</div>
<div class="disFlex">
<div class="tit4">{{ "销量" }}:{{ item.sales | seles }}</div>
<div
class="tit4"
v-show="specialArea != 13 && specialArea != 31"
style="margin-left: 10px"
>
{{ "业绩" }}:{{ item.waresAchieve | numberToCurrency }}
{{ "业绩" }}:{{ item.waresAchieve | numberToCurrency }}
</div>
<div
class="tit4"
v-show="specialArea == 31 && userInfo.isMakerSpace == 0"
style="margin-left: 10px"
>
{{ "业绩" }}:{{ item.waresAchieve | numberToCurrency }}
</div>
<div
class="tit4"
v-show="specialArea == 13"
style="margin-left: 10px"
>
BV:{{ item.assAchieve | numberToCurrency }}
</div>
</div>
<div
class="tit4"
v-show="specialArea == 31 && userInfo.isMakerSpace == 0"
style="margin-left: 10px"
v-show="specialArea == 10 || specialArea == 11"
>
{{ "业绩" }}:{{ item.waresAchieve | numberToCurrency }}
{{ "积分可抵扣" }}:{{ item.deductMoney | numberToCurrency }}
</div>
<div
class="tit4"
v-show="specialArea == 13"
style="margin-left: 10px"
>
BV:{{ item.assAchieve | numberToCurrency }}
</div>
</div>
<div class="tit4" v-show="specialArea == 10 || specialArea == 11">
{{ "积分可抵扣" }}:{{ item.deductMoney | numberToCurrency }}
</div>
<!-- <img class="addCarImg" v-show="isClick != item.waresCode" :src="addCarImg1" @click.stop='addToCar($event,item)' alt="">
<!-- <img class="addCarImg" v-show="isClick != item.waresCode" :src="addCarImg1" @click.stop='addToCar($event,item)' alt="">
<img class="addCarImg" v-show="isClick== item.waresCode" :src="addCarImg2" alt=""> -->
<div
class="addCarImg"
v-show="
(specialArea == 31 && userInfo.isMakerSpace == 0) ||
specialArea != 31
"
@click.stop="addToCar($event, item)"
>
<img :src="addCarImg1" alt="" />
<div>加入购物车</div>
</div>
<div class="md">
<img
v-for="ctem in item.sellingLabelList"
v-show="item.sellingLabelList"
:key="ctem.pkId"
:src="ctem.labelImage || ''"
alt=""
/>
<div
class="addCarImg"
v-show="
(specialArea == 31 && userInfo.isMakerSpace == 0) ||
specialArea != 31
"
@click.stop="addToCar($event, item)"
>
<img :src="addCarImg1" alt="" />
<div>加入购物车</div>
</div>
<div class="md">
<img
v-for="ctem in item.sellingLabelList"
v-show="item.sellingLabelList"
:key="ctem.pkId"
:src="ctem.labelImage || ''"
alt=""
/>
</div>
</div>
</div>
</div>
</div>
</template>
</div>
<pagination
v-show="total > 0 && specialArea == 21"
@ -377,10 +390,15 @@
/>
</div>
<poster v-if="isPost"></poster>
<vue-ball ref="ball" :duration="300" @after-enter="afterEnter">
<div class="ccc" :style="{ top: carTop + 'px' }"></div>
<div slot="icon" class="dian"></div>
</vue-ball>
<!-- Flying animation element -->
<div
v-if="isAnimating"
ref="flyer"
class="flyer-element"
:style="flyerStyle"
>
<img :src="flyerImage" alt="flying item" />
</div>
<div>
<!-- 公告弹窗 -->
<notice-popup
@ -393,11 +411,10 @@
</template>
<script>
import personInfo from "@/components/personInfo.vue";
// import personInfo from "@/components/personInfo.vue";
import Sidebar from "@/components/Sidebar.vue";
import poster from "@/components/poster.vue";
import * as api from "@/api/goods.js";
import { Ball as vueBall } from "@hyhello/vue-ball";
import { mapGetters } from "vuex";
import noticePopup from "@/components/noticePopup.vue";
import selSpaceGoods from "@/components/selSpaceGoods.vue";
@ -406,9 +423,8 @@ import * as ads from "@/api/register.js";
export default {
components: {
noticePopup,
personInfo,
// personInfo,
Sidebar,
vueBall,
poster,
selSpaceGoods,
},
@ -541,7 +557,6 @@ export default {
addCarImg3: require("@/assets/images/addCar3.png"),
isClick: false,
heartBeat: false,
carTop: 0,
oneList: [],
twoList: [],
threeList: [],
@ -562,10 +577,14 @@ export default {
pageSize: 50,
total: 100,
moneySymbol: "",
isLoading: false,
isAnimating: false,
flyerImage: "",
flyerStyle: {},
};
},
watch: {
$route(n, o) {
$route(n) {
if (n.query.idTh != undefined) {
this.specialArea0 = n.query.id;
this.specialArea = n.query.idTh;
@ -594,9 +613,6 @@ export default {
// this.getAllGoods()
//
this.getClassIfy();
this.carTop =
this.$children[1].$refs.shoppCar.getBoundingClientRect().top;
},
specialArea(n) {
if (n == 1) {
@ -645,8 +661,9 @@ export default {
this.getClassIfy();
this.$nextTick(() => {
this.carTop =
this.$children[1].$refs.shoppCar.getBoundingClientRect().top;
// Remove carTop calculation from mounted
// this.carTop =
// this.$children[1].$refs.shoppCar.getBoundingClientRect().top;
});
// this.zoneList = JSON.parse(localStorage.getItem('productMenu'))
@ -676,7 +693,7 @@ export default {
id: 30,
},
});
this.$refs.sideBar.getSpecial(item.value);
// this.$refs.sideBar.getSpecial(item.value);
} else {
this.$confirm(`${"请先进行实名认证"}?`, "提示", {
confirmButtonText: "确定",
@ -893,7 +910,7 @@ export default {
});
},
trimSpace(array) {
return new Promise((resolve, reject) => {
return new Promise((resolve) => {
for (var i = 0; i < array.length; i++) {
//
if (
@ -985,12 +1002,105 @@ export default {
this.getCatLength();
}
});
this.isClick = item.waresCode;
let that = this;
// --- Start Manual Animation ---
const startElement = ev.target;
const sidebarComponent = this.$refs.sideBar;
const targetElement = sidebarComponent
? sidebarComponent.$refs.shoppCar
: null;
if (!(startElement instanceof Element)) {
console.error(
"Animation start element is not a valid DOM element:",
startElement
);
return;
}
if (!(targetElement instanceof Element)) {
console.error(
"Animation target element is not a valid DOM element or not found:",
targetElement
);
return;
}
// 1. Get coordinates
console.log("[Animation Debug] Start Element:", startElement);
console.log("[Animation Debug] Target Element:", targetElement);
const startRect = startElement.getBoundingClientRect();
const targetRect = targetElement.getBoundingClientRect();
console.log("[Animation Debug] Start Rect:", startRect);
console.log("[Animation Debug] Target Rect:", targetRect);
// Calculate start position (center of button)
const startX = startRect.left + startRect.width / 2;
const startY = startRect.top + startRect.height / 2;
console.log(
`[Animation Debug] Calculated Coords: Start(${startX}, ${startY})`
);
// Calculate end position (center of cart icon)
const endX = targetRect.left + targetRect.width / 2;
const endY = targetRect.top + targetRect.height / 2;
console.log(
`[Animation Debug] Calculated Coords: End(${endX}, ${endY})`
);
// 2. Set flyer image and initial style
this.flyerImage = item.cover1;
this.flyerStyle = {
transform: "scale(1)",
opacity: 1,
// Set initial position (adjusting for new flyer size 70px)
left: `${startX - 35}px`,
top: `${startY - 35}px`,
};
console.log(
"[Animation Debug] Initial flyerStyle:",
JSON.stringify(this.flyerStyle)
);
console.log("[Animation Debug] Setting isAnimating to true...");
// 3. Start animation
this.isAnimating = true;
// 4. Apply end state styles in the next frame to trigger transition
this.$nextTick(() => {
console.log(
"[Animation Debug] Inside $nextTick. Requesting animation frame..."
);
requestAnimationFrame(() => {
console.log(
"[Animation Debug] Inside requestAnimationFrame. Applying end styles..."
);
this.flyerStyle = {
...this.flyerStyle, // Keep initial position
// Apply final position and style changes for transition
transform: "scale(0.1)",
opacity: 0.8, // Increase final opacity further
left: `${endX - 4}px`, // Adjust for final smaller size (70px * 0.1 / 2 = 3.5 -> 4)
top: `${endY - 4}px`,
};
console.log(
"[Animation Debug] End flyerStyle applied:",
JSON.stringify(this.flyerStyle)
);
});
});
// 5. Hide flyer after animation duration (match CSS transition duration)
console.log(
"[Animation Debug] Setting timeout to hide flyer in 1200ms"
);
setTimeout(() => {
that.isClick = "";
}, 60);
this.$refs.ball.action(ev.target).then(() => {});
console.log(
"[Animation Debug] Timeout finished. Setting isAnimating to false."
);
this.isAnimating = false;
}, 1200); // Match the new CSS transition duration (1.2s)
// --- End Manual Animation ---
}
},
changeArea(item) {
@ -1020,7 +1130,7 @@ export default {
id: item.value,
},
});
this.$refs.sideBar.getSpecial(item.value);
// this.$refs.sideBar.getSpecial(item.value);
}
}
// this.$refs.sideBar.getCarList(this.specialArea)
@ -1038,7 +1148,7 @@ export default {
});
},
getAllGoods(id) {
let that = this;
this.isLoading = true;
if (this.specialArea == "21") {
api
.sharingWares({
@ -1053,6 +1163,9 @@ export default {
item.waresName = item.waresName.substring(0, 26) + "...";
}
});
})
.finally(() => {
this.isLoading = false;
});
} else {
api
@ -1068,11 +1181,14 @@ export default {
item.waresName = item.waresName.substring(0, 26) + "...";
}
});
})
.finally(() => {
this.isLoading = false;
});
}
},
getAllGoods1(id) {
let that = this;
this.isLoading = true;
if (this.specialArea == "21") {
api
.sharingWares({
@ -1094,6 +1210,9 @@ export default {
item.waresName = item.waresName.substring(0, 26) + "...";
}
});
})
.finally(() => {
this.isLoading = false;
});
} else {
api
@ -1110,6 +1229,9 @@ export default {
item.waresName = item.waresName.substring(0, 26) + "...";
}
});
})
.finally(() => {
this.isLoading = false;
});
}
},
@ -1119,8 +1241,6 @@ export default {
this.heartBeat = true;
});
},
//
afterEnter() {},
},
};
</script>
@ -1188,6 +1308,8 @@ export default {
align-items: center; // justify-content: space-around;
padding: 20px 60px;
flex-wrap: wrap;
position: relative;
min-height: 400px;
.good_i {
position: relative;
@ -1555,4 +1677,32 @@ export default {
color: #fff;
border-color: var(--primary-color);
}
.goodList.is-empty {
display: flex;
justify-content: center;
align-items: center;
}
/* Add styles for the new flyer element */
.flyer-element {
position: fixed; /* Use fixed for viewport-relative positioning */
z-index: 9999; /* Ensure it's on top */
width: 70px; /* Increase initial size */
height: 70px; /* Increase initial size */
border-radius: 50%;
overflow: hidden;
opacity: 1;
/* Use standard easing and ensure all properties are included, increase duration */
transition: left 1.2s ease-in-out, top 1.2s ease-in-out,
transform 1.2s ease-out, opacity 1.2s ease-out;
pointer-events: none; /* Ignore clicks */
will-change: transform, top, left, opacity; /* Performance hint */
}
.flyer-element img {
width: 100%;
height: 100%;
object-fit: cover;
}
</style>

File diff suppressed because one or more lines are too long