From 408d93a7fed0403381400ce2fc028819bb203eec Mon Sep 17 00:00:00 2001
From: peng <peng.com>
Date: 星期一, 21 七月 2025 09:51:42 +0800
Subject: [PATCH] 解决主包过大问题
---
pages/subComponents/m-goods-list/common.vue | 69 +++
pages/subComponents/m-goods-list/promotion.vue | 171 ++++++++
pages/product/goods.vue | 13
pages/subComponents/m-goods-list/base-list.vue | 277 +++++++++++++
pages/subComponents/m-goods-list/README.md | 11
pages.json | 16
pages/subComponents/popups/popups.vue | 346 ++++++++++++++++
pages/commodity-square/commoditySquare.vue | 4
pages/subComponents/m-goods-list/list.vue | 343 ++++++++++++++++
9 files changed, 1,240 insertions(+), 10 deletions(-)
diff --git a/pages.json b/pages.json
index 06eec49..93752ba 100644
--- a/pages.json
+++ b/pages.json
@@ -1026,7 +1026,8 @@
"componentPlaceholder": {
"u-icon": "view",
"u-navbar": "view",
- "u-popup": "view"
+ "u-popup": "view",
+ "popups":"view"
}
}
},
@@ -1714,6 +1715,19 @@
{
"navigationBarTitleText" : "鍒嗗寘鍗犱綅"
}
+ },{
+ "path" : "popups/popups",
+ "style" :
+ {
+ "componentPlaceholder": {
+ "u-modal": "view",
+ "u-tabs": "view",
+ "u-image": "view",
+ "u-search": "view",
+ "u-icon": "view",
+ "u-loadmore": "view"
+ }
+ }
}
]
},
diff --git a/pages/commodity-square/commoditySquare.vue b/pages/commodity-square/commoditySquare.vue
index 7bbfbd0..68da6c9 100644
--- a/pages/commodity-square/commoditySquare.vue
+++ b/pages/commodity-square/commoditySquare.vue
@@ -16,8 +16,8 @@
</scroll-view>
</view>
- <view class="goodsInfos">
- <scroll-view :scroll-y="true" :show-scrollbar="false">
+ <view class="goodsInfos" >
+ <scroll-view :scroll-y="true" :show-scrollbar="false" style="height: 100%;">
<view class="goodsItem" v-for="item in goodsList" :key="item.id"
@click.prevent="goToGoodsInfo(item.id)"
diff --git a/pages/product/goods.vue b/pages/product/goods.vue
index b905084..c315288 100644
--- a/pages/product/goods.vue
+++ b/pages/product/goods.vue
@@ -184,24 +184,24 @@
<Evaluation id="main5" :goodsDetail="goodsDetail" />
<!-- 搴楅摵鎺ㄨ崘 -->
- <storeLayout id="main7" :storeDetail="storeDetail" :goodsDetail="goodsDetail" :res="recommendList" />
+ <!-- <storeLayout id="main7" :storeDetail="storeDetail" :goodsDetail="goodsDetail" :res="recommendList" /> -->
<!-- 瀹濊礉璇︽儏 -->
<GoodsIntro id="main9" :res="goodsDetail" :goodsParams="goodsParams" :goodsId="goodsDetail.goodsId"
v-if="goodsDetail.id" />
<!-- 瀹濊礉鎺ㄨ崘 -->
- <GoodsRecommend id="main11" :res="likeGoodsList" />
+ <!-- <GoodsRecommend id="main11" :res="likeGoodsList" /> -->
</view>
</scroll-view>
<view class="page-bottom mp-iphonex-bottom" id="pageBottom">
<view class="icon-btn">
- <view class="icon-btn-item" @click="navigateToStore(goodsDetail.storeId)">
+<!-- <view class="icon-btn-item" @click="navigateToStore(goodsDetail.storeId)">
<u-icon size="34" class="red" name="home-fill"></u-icon>
<view class="red icon-btn-name">搴楅摵</view>
- </view>
+ </view> -->
<view class="icon-btn-item" @click="linkMsgDetail()">
<u-icon size="34" name="kefu-ermai"></u-icon>
<view class="icon-btn-name">瀹㈡湇</view>
@@ -295,14 +295,14 @@
import PromotionAssembleListLayout from "./product/promotion/-promotion-assemble-list"; //鎷煎洟鐢ㄦ埛鍒楄〃
import PromotionCoupon from "./product/promotion/-promotion-coupon"; //浼樻儬鍒哥粍浠�
import GoodsIntro from "./product/goods/-goods-intro"; //鍟嗗搧浠嬬粛缁勪欢
-import GoodsRecommend from "./product/goods/-goods-recommend"; //瀹濊礉鎺ㄨ崘
+// import GoodsRecommend from "./product/goods/-goods-recommend"; //瀹濊礉鎺ㄨ崘
import storeLayout from "./product/shop/-shop"; //搴楅摵缁勪欢
import Evaluation from "./product/evaluation/-evaluation"; //璇勪环缁勪欢
import GoodsSwiper from "./product/goods/-goods-swiper"; //杞挱鍥剧粍浠�
import popupGoods from "@/pages/product/m-buy/goods.vue"; //璐墿杞﹀晢鍝佺殑妯″潡
import popupAddress from "./product/popup/address"; //鍦板潃閫夋嫨妯″潡
import shares from "@/pages/product/m-share/index.vue"; //鍒嗕韩
-import popups from "@/pages/product/popups/popups.vue"; //姘旀场妗�
+import popups from "@/pages/subComponents/popups/popups.vue"; //姘旀场妗�
import takeDownFormSaleGoods from "@/pages/product/m-take-down-sale-goods/index"; //涓嬫灦妗�
import setup from "./product/popup/popup";
import {
@@ -318,7 +318,6 @@
PromotionAssembleListLayout,
PromotionCoupon,
GoodsIntro,
- GoodsRecommend,
storeLayout,
Evaluation,
GoodsSwiper,
diff --git a/pages/subComponents/m-goods-list/README.md b/pages/subComponents/m-goods-list/README.md
new file mode 100644
index 0000000..bade838
--- /dev/null
+++ b/pages/subComponents/m-goods-list/README.md
@@ -0,0 +1,11 @@
+## 鍟嗗搧鍒楄〃灞曠ず
+
+### OBJECT 鍙傛暟璇存槑
+
+| 灞炴�� | 璇存槑 | 绫诲瀷 | 蹇呭~ |
+| ----------- | ---------------------------------------------------------- | ------- | ---- |
+| `res` | 鏄剧ず鏁版嵁 | Array | 鏄� |
+| `type` | 鍟嗗搧灞曠ず绫诲瀷 oneColumns twoColumns 锛岄粯璁ゅ睍绀轰竴琛屼袱鍒楀晢鍝� | String | 鍚� |
+| `storeName` | 鏄惁灞曠ず搴楅摵鍚嶇О锛岄粯璁ゅ睍绀� | Boolean | 鍚� |
+| `keywords` | 楂樹寒灞曠ず鎼滅储鍐呭 | String | 鍚� |
+
diff --git a/pages/subComponents/m-goods-list/base-list.vue b/pages/subComponents/m-goods-list/base-list.vue
new file mode 100644
index 0000000..62d57a4
--- /dev/null
+++ b/pages/subComponents/m-goods-list/base-list.vue
@@ -0,0 +1,277 @@
+<template>
+ <div>
+ <!-- 涓�琛屼袱鍒楀晢鍝佸睍绀� -->
+ <view class="goods-list" v-if="type == 'twoColumns'">
+ <view v-for="(item, index) in res" :key="index" class="goods-item">
+ <view class="image-wrapper" @click="navigateToDetailPage(item)">
+ <u-image
+ :src="item.thumbnail"
+ width="100%"
+ height="330rpx"
+ mode="aspectFit"
+ >
+ <u-loading slot="loading"></u-loading>
+ </u-image>
+ </view>
+ <view class="goods-detail">
+ <div
+ class="title clamp"
+ v-html="lightSearchStr(keyword, item.goodsName)"
+ @click="navigateToDetailPage(item)"
+ ></div>
+ <view class="price-box" @click="navigateToDetailPage(item)">
+ <div class="price" v-if="item.price != undefined">
+ 楼<span
+ >{{
+ $options.filters.goodsFormatPrice(item.price)[0]
+ }} </span
+ >.{{ $options.filters.goodsFormatPrice(item.price)[1] }}
+ </div>
+ </view>
+ <div class="count-config" @click="navigateToDetailPage(item)">
+ <span>宸插敭 {{ item.buyCount || "0" }}</span>
+ <span>{{ item.commentNum || "0" }}鏉¤瘎璁�</span>
+ </div>
+ <div
+ class="store-seller-name"
+ v-if="storeName"
+ @click="navigateToStoreDetailPage(item)"
+ >
+ <div class="text-hidden">
+ <u-tag
+ style="margin-right: 10rpx"
+ size="mini"
+ mode="dark"
+ v-if="item.selfOperated"
+ text="鑷惀"
+ type="error"
+ />
+ <span>{{ item.storeName || "鏆傛棤" }}</span>
+ </div>
+ <span>
+ <u-icon name="arrow-right"></u-icon>
+ </span>
+ </div>
+ </view>
+ </view>
+ </view>
+ <!-- 涓�琛屼竴鍒楀晢鍝佸睍绀� -->
+ <div v-if="type == 'oneColumns'">
+ <div v-for="(item, index) in res" :key="index" class="goods-row">
+ <div class="flex goods-col">
+ <div class="goods-img" @click="navigateToDetailPage(item)">
+ <u-image
+ width="230rpx"
+ border-radius="16"
+ height="230rpx"
+ mode="aspectFit"
+ :src="item.goodsImage || item.thumbnail"
+ >
+ <u-loading slot="loading"></u-loading>
+ </u-image>
+ </div>
+ <div class="goods-detail">
+ <div class="title clamp3" @click="navigateToDetailPage(item)">
+ {{ item.goodsName }}
+ </div>
+ <view class="price-box" @click="navigateToDetailPage(item)">
+ <div class="price" v-if="item.price != undefined">
+ 楼<span
+ >{{ $options.filters.goodsFormatPrice(item.price)[0] }} </span
+ >.{{ $options.filters.goodsFormatPrice(item.price)[1] }}
+ </div>
+ </view>
+ <div class="promotion" @click="navigateToDetailPage(item)">
+ <div v-if="item.salesModel == 'WHOLESALE'">
+ <span>鎵�</span>
+ </div>
+ <div
+ v-for="(promotionItem, promotionIndex) in getPromotion(item)"
+ :key="promotionIndex"
+ >
+ <span v-if="promotionItem.indexOf('COUPON') != -1">鍔�</span>
+ <span v-if="promotionItem.indexOf('FULL_DISCOUNT') != -1"
+ >婊″噺</span
+ >
+ <span v-if="promotionItem.indexOf('SECKILL') != -1">绉掓潃</span>
+ </div>
+ </div>
+ <div
+ style="overflow: hidden"
+ @click="navigateToDetailPage(item)"
+ class="count-config"
+ >
+ <span style="float: left; font-size: 22rpx"
+ >宸插敭 {{ item.buyCount || "0" }}</span
+ >
+ <span style="float: right; font-size: 22rpx"
+ >{{ item.commentNum || "0" }}鏉¤瘎璁�</span
+ >
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+import commonTpl from "@/pages/product/m-goods-list/common.vue";
+export default {
+ data() {
+ return {
+ lightColor: this.$mainColor,
+ };
+ },
+ mixins: [commonTpl],
+ props: {
+ // 灞曠ず鐨勭被鍨�
+ type:{
+ type:String,
+ default:"oneColumns"
+ },
+ // 閬嶅巻鐨勬暟鎹�
+ res: {
+ type: Array,
+ default: () => {
+ return [];
+ },
+ },
+ },
+ methods: {
+ // 璺宠浆鍒板晢鍝佽鎯�
+ navigateToDetailPage(item) {
+ uni.navigateTo({
+ url: `/pages/product/goods?id=${item.id}&goodsId=${item.goodsId}`,
+ });
+ },
+ },
+};
+</script>
+
+<style lang="scss" scoped>
+.goods-list {
+ display: flex;
+ flex-wrap: wrap;
+ margin: 10rpx 20rpx 284rpx;
+ width: 100%;
+
+ > .goods-item {
+ background-color: #ffffff;
+ display: flex;
+ border-radius: 16rpx;
+ flex-direction: column;
+ width: calc(50% - 30rpx);
+ margin-bottom: 20rpx;
+ padding-bottom: 20rpx;
+
+ &:nth-child(2n + 1) {
+ margin-right: 20rpx;
+ }
+
+ .image-wrapper {
+ width: 100%;
+ height: 330rpx;
+ border-radius: 16rpx 16rpx 0 0;
+ overflow: hidden;
+ padding: 0;
+ }
+ }
+
+ .count-config,
+ .store-seller-name {
+ font-size: $font-sm;
+ }
+
+ .text-hidden {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+}
+
+.goods-row {
+ background: #fff;
+ padding: 16rpx;
+
+ > .goods-col {
+ display: flex;
+
+ > .goods-img {
+ overflow: hidden;
+ flex: 4;
+ }
+
+ > .goods-detail {
+ flex: 7;
+ }
+ }
+}
+
+.goods-detail {
+ margin: 0 20rpx;
+
+ > .title {
+ font-size: $font-base;
+ color: $font-color-dark;
+ line-height: 1.5;
+ height: 86rpx;
+ padding: 10rpx 0 0;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
+ overflow: hidden;
+ }
+
+ .promotion {
+ margin-top: 4rpx;
+ display: flex;
+
+ div {
+ span {
+ font-size: 24rpx;
+ color: $light-color;
+ margin-right: 10rpx;
+ padding: 0 4rpx;
+ border-radius: 2rpx;
+ }
+ }
+ }
+
+ .store-seller-name {
+ color: #666;
+ overflow: hidden;
+ display: flex;
+ justify-content: space-between;
+ }
+
+ .count-config {
+ padding: 5rpx 0;
+ color: #666;
+ display: flex;
+ font-size: 24rpx;
+ justify-content: space-between;
+ }
+
+ > .price-box {
+ margin-top: 10rpx;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding-right: 10rpx;
+ font-size: 24rpx;
+ color: $font-color-light;
+
+ > .price {
+ font-size: 26rpx;
+ line-height: 1;
+ color: $main-color;
+ font-weight: bold;
+
+ /deep/ span:nth-of-type(1) {
+ font-size: 38rpx;
+ }
+ }
+ }
+}
+</style>
diff --git a/pages/subComponents/m-goods-list/common.vue b/pages/subComponents/m-goods-list/common.vue
new file mode 100644
index 0000000..c4cdc56
--- /dev/null
+++ b/pages/subComponents/m-goods-list/common.vue
@@ -0,0 +1,69 @@
+<template>
+</template>
+
+<script>
+ export default {
+ methods: {
+ // 楂樹寒鏄剧ず鎼滅储鍐呭
+ lightSearchStr(keyword, str) {
+ if (!keyword) {
+ return str
+ } else {
+ let unicodes = '';
+ for (let i of Array.from(keyword)) {
+ unicodes += this.unicode(i) + "|"
+ }
+ const rule = '(' + unicodes + ')'
+ const reg = new RegExp(rule, 'gi');
+ return str ? str.replace(reg, matchValue =>
+ `<span style="color:${this.lightColor}">${matchValue}</span>`
+ ) : ''
+ }
+ },
+ // 杞崲涓簎nicode
+ unicode(str) {
+ var value = '';
+ for (var i = 0; i < str.length; i++) {
+ value += '\\u' + this.left_zero_4(parseInt(str.charCodeAt(i)).toString(16));
+ }
+ return value;
+ },
+ left_zero_4(str) {
+ if (str != null && str != '' && str != 'undefined') {
+ if (str.length == 2) {
+ return '00' + str;
+ }
+ }
+ return str;
+ },
+ // 鏁版嵁鍘婚噸涓�涓� 鍙樉绀轰竴娆� 鍑忓厤 鍔� 浠�涔堢殑
+ getPromotion(item) {
+ if (item.promotionMap) {
+ let array = [];
+ Object.keys(item.promotionMap).forEach((child) => {
+ if (!array.includes(child.split("-")[0])) {
+ array.push(child.split("-")[0]);
+ }
+ });
+ return array;
+ }
+ },
+ // 璺宠浆鍒板晢鍝佽鎯�
+ navigateToDetailPage(item) {
+ uni.navigateTo({
+ url: `/pages/product/goods?id=${item.id}&goodsId=${item.goodsId}`,
+ });
+ },
+ // 璺宠浆鍦板潃
+ navigateToStoreDetailPage(item) {
+ uni.navigateTo({
+ url: `/pages/product/shopPage?id=${item.storeId}`,
+ });
+ },
+ },
+ }
+</script>
+
+<style lang='scss' scoped>
+
+</style>
diff --git a/pages/subComponents/m-goods-list/list.vue b/pages/subComponents/m-goods-list/list.vue
new file mode 100644
index 0000000..fa54ff5
--- /dev/null
+++ b/pages/subComponents/m-goods-list/list.vue
@@ -0,0 +1,343 @@
+<template>
+ <view>
+ <!-- 涓�琛屼袱鍒楀晢鍝佸睍绀� -->
+ <view class="goods-list" v-if="type == 'twoColumns'">
+ <view v-for="(item, index) in res" :key="index" class="goods-item">
+ <view class="image-wrapper" @click="navigateToDetailPage(item)">
+ <u-image :src="item.thumbnail" width="100%" height='330rpx' mode="aspectFit">
+ <u-loading slot="loading"></u-loading>
+ </u-image>
+ </view>
+ <view class="goods-detail">
+ <div class="title clamp" v-html="lightSearchStr(keyword,item.goodsName)"
+ @click="navigateToDetailPage(item)">
+
+ </div>
+ <view class="price-box" @click="navigateToDetailPage(item)">
+ <div class="price" v-if="item.price!=undefined">
+ 楼<span>{{ $options.filters.goodsFormatPrice(item.price )[0] }} </span>.{{
+ $options.filters.goodsFormatPrice(item.price )[1]
+ }}
+ </div>
+ </view>
+ <div class="promotion" @click="navigateToDetailPage(item)">
+ <div v-if="item.salesModel == 'WHOLESALE'">
+ <span>鎵�</span>
+ </div>
+ <div v-for="(promotionItem,promotionIndex) in getPromotion(item)" :key="promotionIndex">
+ <span v-if="promotionItem.indexOf('COUPON') != -1">鍔�</span>
+ <span v-if="promotionItem.indexOf('FULL_DISCOUNT') != -1">婊″噺</span>
+ <span v-if="promotionItem.indexOf('SECKILL') != -1">绉掓潃</span>
+ </div>
+ </div>
+ <div class="count-config" @click="navigateToDetailPage(item)">
+ <span>宸插敭 {{ item.buyCount || "0" }}</span>
+ <span>{{ item.commentNum || "0" }}鏉¤瘎璁�</span>
+ </div>
+ <div class="store-seller-name" v-if="storeName" @click="navigateToStoreDetailPage(item)">
+ <div class="text-hidden">
+ <u-tag style="margin-right: 10rpx" size="mini" mode="dark" v-if="item.selfOperated"
+ text="鑷惀" type="error" />
+ <span>{{ item.storeName || "鏆傛棤" }}</span>
+ </div>
+ <span>
+ <u-icon name="arrow-right"></u-icon>
+ </span>
+ </div>
+ </view>
+ </view>
+ </view>
+ <!-- 涓�琛屼竴鍒楀晢鍝佸睍绀� -->
+ <div v-if="type == 'oneColumns'" class="goods-one-row">
+ <div v-for="(item, index) in res" :key="index" class="goods-row">
+ <div class="flex goods-col">
+ <div class="goods-img" @click="navigateToDetailPage(item)">
+ <u-image width="230rpx" mode="aspectFit" border-radius='16' height="230rpx" :src="item.thumbnail">
+ <u-loading slot="loading"></u-loading>
+ </u-image>
+ </div>
+ <div class="goods-detail">
+ <div class="title clamp3" @click="navigateToDetailPage(item)">{{ item.goodsName }}</div>
+ <view class="price-box" @click="navigateToDetailPage(item)">
+ <div class="price" v-if="item.price!=undefined">
+ 楼<span>{{ $options.filters.goodsFormatPrice(item.price )[0] }} </span>.{{
+ $options.filters.goodsFormatPrice(item.price )[1]
+ }}
+ </div>
+ </view>
+ <div class="promotion" @click="navigateToDetailPage(item)">
+ <div v-if="item.salesModel == 'WHOLESALE'">
+ <span>鎵�</span>
+ </div>
+ <div v-for="(promotionItem,promotionIndex) in getPromotion(item)" :key="promotionIndex">
+ <span v-if="promotionItem.indexOf('COUPON') != -1">鍔�</span>
+ <span v-if="promotionItem.indexOf('FULL_DISCOUNT') != -1">婊″噺</span>
+ <span v-if="promotionItem.indexOf('SECKILL') != -1">绉掓潃</span>
+ </div>
+ </div>
+ <div style="overflow: hidden" @click="navigateToDetailPage(item)" class="count-config">
+ <span style="float: left; font-size: 22rpx">宸插敭 {{ item.buyCount || '0' }}</span>
+ <span style="float: right; font-size: 22rpx">{{ item.commentNum || '0' }}鏉¤瘎璁�</span>
+ </div>
+ <div style="overflow: hidden" @click="navigateToStoreDetailPage(item)" class="count-config">
+ <div class="text-hidden" v-if="storeName">
+ <u-tag style="margin-right: 10rpx" size="mini" mode="dark" v-if="item.selfOperated"
+ text="鑷惀" type="error" />
+ <span class="line1-store-name">{{ item.storeName }}</span>
+ <span class="to-store">杩涘簵<u-icon size="24" name="arrow-right" color="#666"></u-icon>
+ </span>
+ </div>
+ <span>
+ <u-icon name="arrow-right" color="#c5c5c5"></u-icon>
+ </span>
+ </div>
+ </div>
+ </div>
+
+ </div>
+ </div>
+
+ </view>
+</template>
+
+<script>
+ import '@/components/uview-components/uview-ui';
+
+ import commonTpl from '@/pages/product/m-goods-list/common.vue'
+ export default {
+ data() {
+ return {
+ lightColor: this.$mainColor
+ }
+ },
+ mixins: [commonTpl],
+
+ props: {
+ // 閬嶅巻鐨勬暟鎹�
+ res: {
+ type: Array,
+ default: () => {
+ return []
+ }
+ },
+ // 涓�琛屼袱鍒楄繕鏄竴琛屼竴鍒楁樉绀�
+ type: {
+ type: String,
+ default: 'twoColumns',
+ validator() {
+ return ['twoColumns', 'oneColumns']
+ }
+ },
+ storeName: {
+ type: Boolean,
+ default: true
+ },
+ keyword: {
+ type: null,
+ default: ''
+ }
+
+ },
+ watch: {
+ keyword(val) {
+ if (val) {
+ this.lightSearchStr(val)
+ }
+ }
+ },
+ methods: {
+
+ // 楂樹寒鏄剧ず鎼滅储鍐呭
+ lightSearchStr(keyword, str) {
+ if (!keyword) {
+ return str
+ } else {
+ let unicodes = '';
+ for (let i of Array.from(keyword)) {
+ unicodes += this.unicode(i) + "|"
+ }
+ const rule = '(' + unicodes + ')'
+ const reg = new RegExp(rule, 'gi');
+ return str ? str.replace(reg, matchValue =>
+ `<span style="color:${this.lightColor}">${matchValue}</span>`
+ ) : ''
+ }
+ },
+ // 杞崲涓簎nicode
+ unicode(str) {
+ var value = '';
+ for (var i = 0; i < str.length; i++) {
+ value += '\\u' + this.left_zero_4(parseInt(str.charCodeAt(i)).toString(16));
+ }
+ return value;
+ },
+ left_zero_4(str) {
+ if (str != null && str != '' && str != 'undefined') {
+ if (str.length == 2) {
+ return '00' + str;
+ }
+ }
+ return str;
+ },
+ // 鏁版嵁鍘婚噸涓�涓� 鍙樉绀轰竴娆� 鍑忓厤 鍔� 浠�涔堢殑
+ getPromotion(item) {
+ if (item ? item.promotionMap : item.promotionMap) {
+ const fieldList = item ? item.promotionMap : item.promotionMap
+ let array = [];
+ Object.keys(fieldList).forEach((child) => {
+ if (!array.includes(child.split("-")[0])) {
+ array.push(child.split("-")[0]);
+ }
+ });
+ return array;
+ }
+ },
+ // 璺宠浆鍒板晢鍝佽鎯�
+ navigateToDetailPage(item) {
+ uni.navigateTo({
+ url: `/pages/product/goods?id=${item.id}&goodsId=${item.goodsId}`,
+ });
+ },
+ // 璺宠浆鍦板潃
+ navigateToStoreDetailPage(item) {
+ uni.navigateTo({
+ url: `/pages/product/shopPage?id=${item.storeId}`,
+ });
+ },
+ }
+ }
+</script>
+
+<style lang='scss' scoped>
+ .goods-one-row{
+ padding-bottom: 250rpx;
+ }
+ /* 鍟嗗搧鍒楄〃 */
+ .goods-list {
+ display: flex;
+ flex-wrap: wrap;
+ margin: 10rpx 20rpx 284rpx;
+ width: 100%;
+
+ >.goods-item {
+ background-color: #ffffff;
+ display: flex;
+ border-radius: 16rpx;
+ flex-direction: column;
+ width: calc(50% - 30rpx);
+ margin-bottom: 20rpx;
+ padding-bottom: 20rpx;
+
+ &:nth-child(2n + 1) {
+ margin-right: 20rpx;
+ }
+
+
+ .image-wrapper {
+ width: 100%;
+ height: 330rpx;
+ border-radius: 16rpx 16rpx 0 0;
+ overflow: hidden;
+ padding: 0;
+ }
+ }
+
+ .count-config,
+ .store-seller-name {
+ font-size: $font-sm;
+ }
+
+ .text-hidden {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ }
+
+
+ .goods-row {
+ background: #fff;
+ padding: 16rpx;
+
+ >.goods-col {
+ display: flex;
+
+ >.goods-img {
+ overflow: hidden;
+ flex: 4;
+ }
+
+ >.goods-detail {
+ flex: 7;
+ }
+ }
+ }
+
+ .goods-detail {
+ margin: 0 20rpx;
+
+ >.title {
+ font-size: $font-base;
+ color: $font-color-dark;
+ line-height: 1.5;
+ height: 86rpx;
+ padding: 10rpx 0 0;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
+ overflow: hidden;
+ }
+
+ .promotion {
+ margin-top: 4rpx;
+ display: flex;
+
+ div {
+ span {
+ font-size: 24rpx;
+ color: $light-color;
+ margin-right: 10rpx;
+ padding: 0 4rpx;
+ border-radius: 2rpx;
+ }
+ }
+ }
+
+ .store-seller-name {
+ color: #666;
+ overflow: hidden;
+ display: flex;
+ justify-content: space-between;
+ }
+
+ .count-config {
+ padding: 5rpx 0;
+ color: #666;
+ display: flex;
+ font-size: 24rpx;
+ justify-content: space-between;
+ }
+
+ >.price-box {
+ margin-top: 10rpx;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding-right: 10rpx;
+ font-size: 24rpx;
+ color: $font-color-light;
+
+ >.price {
+ font-size: 26rpx;
+ line-height: 1;
+ color: $main-color;
+ font-weight: bold;
+
+ /deep/ span:nth-of-type(1) {
+ font-size: 38rpx;
+ }
+ }
+ }
+
+ }
+</style>
diff --git a/pages/subComponents/m-goods-list/promotion.vue b/pages/subComponents/m-goods-list/promotion.vue
new file mode 100644
index 0000000..90bc250
--- /dev/null
+++ b/pages/subComponents/m-goods-list/promotion.vue
@@ -0,0 +1,171 @@
+<template>
+ <div>
+ <div v-for="(item, index) in res" :key="index" class="goods-row" @click="navigateToDetailPage(item)">
+ <div class="flex goods-col">
+ <div class="goods-img">
+ <u-image width="230rpx" mode="aspectFit" border-radius='16' height="230rpx" :src="item.goodsImage || item.thumbnail">
+ <u-loading slot="loading"></u-loading>
+ </u-image>
+ </div>
+ <div class="goods-detail">
+ <div class="title clamp3">{{ item.goodsName }}</div>
+ <div class='flex flex-a-c flex-j-sb'>
+ <view class="price-box">
+ <!-- 绉掓潃 / 鎷煎洟 -->
+ <div class="price" v-if="!type && item.price!=undefined">
+ 楼<span>{{ $options.filters.goodsFormatPrice(item.price )[0] }} </span>.{{
+ $options.filters.goodsFormatPrice(item.price )[1]
+ }}
+ </div>
+ <!-- 鐮嶄环 -->
+ <div class="price" v-if="type && item.purchasePrice!=undefined">
+ 鏈�浣庯細
+ 楼<span>{{ $options.filters.goodsFormatPrice(item.purchasePrice )[0] }} </span>.{{
+ $options.filters.goodsFormatPrice(item.purchasePrice )[1]
+ }}
+ </div>
+ <!-- 鍏滃簳绛栫暐濡傛灉閲戦鏄�0 -->
+ <div class="price" v-if="!item.price && !type">
+ 楼<span>0 </span>.00
+ </div>
+ </view>
+ <div>
+ <image class='buy' :src="buy"></image>
+ </div>
+ </div>
+ <div class='count-config' v-if="!type">
+ <span>鍗冲皢鎭㈠{{ item.originalPrice}}鍏�</span>
+ </div>
+ </div>
+ </div>
+
+ </div>
+ </div>
+</template>
+
+<script>
+ import '@/components/uview-components/uview-ui'
+ import commonTpl from '@/pages/product/m-goods-list/common.vue'
+ export default {
+ data() {
+ return {
+ lightColor: this.$mainColor,
+ buy: require('@/pages/subComponents/static/buy.png')
+ }
+ },
+ mixins: [commonTpl],
+ props: {
+ // 閬嶅巻鐨勬暟鎹�
+ res: {
+ type: Array,
+ default: () => {
+ return []
+ }
+ },
+ type:{
+ type:null,
+ default:""
+ }
+ },
+ methods: {
+ // 璺宠浆鍒板晢鍝佽鎯�
+ navigateToDetailPage(item) {
+ if(this.type == 'kanJia'){
+ uni.navigateTo({
+ url: `/pages/promotion/bargain/detail?id=${item.id}`,
+ });
+ return
+ }
+ uni.navigateTo({
+ url: `/pages/product/goods?id=${item.skuId}&goodsId=${item.goodsId}`,
+ });
+ },
+ }
+ }
+</script>
+
+<style lang='scss' scoped>
+ .buy {
+ width: 152rpx;
+ height: 108rpx;
+ }
+ .flex-j-sb {
+ width: 100%;
+ }
+ .goods-row {
+ background: #fff;
+ padding: 16rpx;
+ >.goods-col {
+ display: flex;
+ >.goods-img {
+ overflow: hidden;
+ flex: 4;
+ }
+ >.goods-detail {
+ flex: 7;
+ }
+ }
+ }
+ .goods-detail {
+ margin: 0 20rpx;
+ >.title {
+ font-size: $font-base;
+ color: $font-color-dark;
+ line-height: 1.5;
+ height: 86rpx;
+ padding: 10rpx 0 0;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
+ overflow: hidden;
+ }
+
+ .promotion {
+ margin-top: 4rpx;
+ display: flex;
+
+ div {
+ span {
+ font-size: 24rpx;
+ color: $light-color;
+ margin-right: 10rpx;
+ padding: 0 4rpx;
+ border-radius: 2rpx;
+ }
+ }
+ }
+
+ .count-config {
+ padding: 5rpx 0;
+ color: #666;
+ display: flex;
+ font-size: 24rpx;
+ letter-spacing:2rpx;
+ padding-left: 10rpx;
+ }
+
+
+
+ }
+
+ .price-box {
+ margin-top: 10rpx;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding-right: 10rpx;
+ font-size: 24rpx;
+ color: $font-color-light;
+
+ >.price {
+ font-size: 26rpx;
+ line-height: 1;
+ color: $main-color;
+ font-weight: bold;
+
+ /deep/ span:nth-of-type(1) {
+ font-size: 48rpx;
+ }
+ }
+ }
+</style>
diff --git a/pages/subComponents/popups/popups.vue b/pages/subComponents/popups/popups.vue
new file mode 100644
index 0000000..ce373f9
--- /dev/null
+++ b/pages/subComponents/popups/popups.vue
@@ -0,0 +1,346 @@
+<template>
+ <view class="shadow" :class="!show?'':'shadow-show'" :style="{backgroundColor:show?maskBg:'rgba(0,0,0,0)'}" @tap="tapMask">
+ <view class="popups" :class="[theme]" :style="{top: popupsTop ,left: popupsLeft,flexDirection:direction}">
+ <text :class="dynPlace" :style="{width:'0px',height:'0px'}" v-if="triangle"></text>
+ <view v-for="(item,index) in popData" :key="index" @tap.stop="tapItem(item)" class="itemChild view" :class="[direction=='row'?'solid-right':'solid-bottom',item.disabled?'disabledColor':'']">
+ <u-icon size="35" :name="item.icon" v-if="item.icon"></u-icon><span class="title">{{item.title}}</span>
+ </view>
+ <slot></slot>
+ </view>
+ </view>
+</template>
+
+<script>
+import '@/components/uview-components/uview-ui';
+
+export default {
+
+ props: {
+ maskBg: {
+ type: String,
+ default: "rgba(0,0,0,0)",
+ },
+ placement: {
+ type: String,
+ default: "default", //default top-start top-end bottom-start bottom-end
+ },
+ direction: {
+ type: String,
+ default: "column", //column row
+ },
+ x: {
+ type: Number,
+ default: 0,
+ },
+ y: {
+ type: Number,
+ default: 0,
+ },
+ value: {
+ type: Boolean,
+ default: false,
+ },
+ popData: {
+ type: Array,
+ default: () => [],
+ },
+ theme: {
+ type: String,
+ default: "light", //light dark
+ },
+ dynamic: {
+ type: Boolean,
+ default: false,
+ },
+ gap: {
+ type: Number,
+ default: 20,
+ },
+ triangle: {
+ type: Boolean,
+ default: true,
+ },
+ },
+ data() {
+ return {
+ popupsTop: "0rpx",
+ popupsLeft: "0rpx",
+ show: false,
+ dynPlace: "",
+ };
+ },
+ mounted() {
+ this.popupsPosition();
+ },
+ methods: {
+ tapMask() {
+ this.$emit("input", !this.value);
+ },
+ tapItem(item) {
+ if (item.disabled) return;
+ this.$emit("tapPopup", item);
+ this.$emit("input", !this.value);
+ },
+ getStatusBar() {
+ let promise = new Promise((resolve, reject) => {
+ uni.getSystemInfo({
+ success: function (e) {
+ let customBar;
+ // #ifdef H5
+
+ customBar = e.statusBarHeight + e.windowTop;
+
+ // #endif
+ resolve(customBar);
+ },
+ });
+ });
+ return promise;
+ },
+ async popupsPosition() {
+ let statusBar = await this.getStatusBar();
+ let promise = new Promise((resolve, reject) => {
+ let popupsDom = uni.createSelectorQuery().in(this).select(".popups");
+ popupsDom
+ .fields(
+ {
+ size: true,
+ },
+ (data) => {
+ let width = data.width;
+ let height = data.height;
+
+
+
+ let y = this.dynamic
+ ? this.dynamicGetY(this.y, this.gap)
+ : this.transformRpx(this.y);
+
+ let x = this.dynamic
+ ? this.dynamicGetX(this.x, this.gap)
+ : this.transformRpx(this.x);
+
+ // #ifdef H5
+ y = this.dynamic
+ ? this.y + statusBar
+ : this.transformRpx(this.y + statusBar);
+ // #endif
+
+ this.dynPlace =
+ this.placement == "default"
+ ? this.getPlacement(x, y)
+ : this.placement;
+
+ switch (this.dynPlace) {
+ case "top-start":
+ this.popupsTop = `${y + 9}rpx`;
+ this.popupsLeft = `${x - 15}rpx`;
+ break;
+ case "top-end":
+ this.popupsTop = `${y + 9}rpx`;
+ this.popupsLeft = `${x + 15 - width}rpx`;
+ break;
+ case "bottom-start":
+ this.popupsTop = `${y - 18 - height}rpx`;
+ this.popupsLeft = `${x - 15}rpx`;
+ break;
+ case "bottom-end":
+ this.popupsTop = `${y - 9 - height}rpx`;
+ this.popupsLeft = `${x + 15 - width}rpx`;
+ break;
+ }
+ resolve();
+ }
+ )
+ .exec();
+ });
+ return promise;
+ },
+ getPlacement(x, y) {
+ let width = uni.getSystemInfoSync().windowWidth;
+ let height = uni.getSystemInfoSync().windowHeight;
+ if (x > width / 2 && y > height / 2) {
+ return "bottom-end";
+ } else if (x < width / 2 && y < height / 2) {
+ return "top-start";
+ } else if (x > width / 2 && y < height / 2) {
+ return "top-end";
+ } else if (x < width / 2 && y > height / 2) {
+ return "bottom-start";
+ } else if (x > width / 2) {
+ return "top-end";
+ } else {
+ return "top-start";
+ }
+ },
+ dynamicGetY(y, gap) {
+ let height = uni.getSystemInfoSync().windowHeight;
+ y = y < gap ? gap : y;
+ y = height - y < gap ? height - gap : y;
+
+ return y;
+ },
+ dynamicGetX(x, gap) {
+ let width = uni.getSystemInfoSync().windowWidth;
+ x = x < gap ? gap : x;
+ x = width - x < gap ? width - gap : x;
+ return x;
+ },
+ transformRpx(params) {
+ return (params * uni.getSystemInfoSync().screenWidth) / 375;
+ },
+ },
+ watch: {
+ value: {
+ immediate: true,
+ handler: async function (newVal, oldVal) {
+ if (newVal) await this.popupsPosition();
+ this.show = newVal;
+ },
+ },
+ placement: {
+ immediate: true,
+ handler(newVal, oldVal) {
+ this.dynPlace = newVal;
+ },
+ },
+ },
+};
+</script>
+
+<style lang="scss" scoped>
+.title {
+ margin-left: 20rpx;
+}
+.shadow {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ height: 100%;
+ z-index: 9999;
+ transition: background 0.3s ease-in-out;
+ visibility: hidden;
+
+ &.shadow-show {
+ visibility: visible;
+ }
+}
+
+.popups {
+ position: absolute;
+ padding: 20rpx;
+ border-radius: 5px;
+ display: flex;
+ .view {
+ display: flex;
+ align-items: center;
+ padding: 15rpx 10rpx;
+ font-size: 25rpx;
+ }
+ .image {
+ display: inline-block;
+ vertical-align: middle;
+ width: 40rpx;
+ height: 40rpx;
+ margin-right: 20rpx;
+ }
+}
+.dark {
+ background-color: #4c4c4c;
+ color: #fff;
+ .top-start:after {
+ content: "";
+ position: absolute;
+ top: -18rpx;
+ left: 10rpx;
+ border-width: 0 20rpx 20rpx;
+ border-style: solid;
+ border-color: transparent transparent #4c4c4c;
+ }
+ .top-end:after {
+ content: "";
+ position: absolute;
+ top: -18rpx;
+ right: 10rpx;
+ border-width: 0 20rpx 20rpx;
+ border-style: solid;
+ border-color: transparent transparent #4c4c4c;
+ }
+ .bottom-start:after {
+ content: "";
+ position: absolute;
+ bottom: -18rpx;
+ left: 10rpx;
+ border-width: 20rpx 20rpx 0;
+ border-style: solid;
+ border-color: #4c4c4c transparent transparent;
+ }
+ .bottom-end:after {
+ content: "";
+ position: absolute;
+ bottom: -18rpx;
+ right: 10rpx;
+ border-width: 20rpx 20rpx 0;
+ border-style: solid;
+ border-color: #4c4c4c transparent transparent;
+ }
+ .disabledColor {
+ color: #c5c8ce;
+ }
+}
+.light {
+ color: #515a6e;
+ box-shadow: 0upx 0upx 30upx rgba(0, 0, 0, 0.2);
+ background: #fff;
+ .top-start:after {
+ content: "";
+ position: absolute;
+ top: -18rpx;
+ left: 10rpx;
+ border-width: 0 20rpx 20rpx;
+ border-style: solid;
+ border-color: transparent transparent #fff;
+ }
+ .top-end:after {
+ content: "";
+ position: absolute;
+ top: -18rpx;
+ right: 10rpx;
+ border-width: 0 20rpx 20rpx;
+ border-style: solid;
+ border-color: transparent transparent #fff;
+ }
+ .bottom-start:after {
+ content: "";
+ position: absolute;
+ bottom: -18rpx;
+ left: 10rpx;
+ border-width: 20rpx 20rpx 0;
+ border-style: solid;
+ border-color: #fff transparent transparent;
+ }
+ .bottom-end:after {
+ content: "";
+ position: absolute;
+ bottom: -18rpx;
+ right: 10rpx;
+ border-width: 20rpx 20rpx 0;
+ border-style: solid;
+ border-color: #fff transparent transparent;
+ }
+ .disabledColor {
+ color: #c5c8ce;
+ }
+}
+.solid-bottom {
+ border-bottom: 1px solid #f3f5f7;
+}
+.solid-right {
+ border-right: 1px solid #ccc;
+}
+.popups .itemChild:last-child {
+ border: none;
+}
+</style>
--
Gitblit v1.8.0