Merge branch 'master' of https://gitee.com/yudaocode/yudao-mall-uniapp into develop
# Conflicts: # pages/goods/index.vue # pages/order/addressSelection.vue # pages/order/confirm.vue # sheep/components/s-goods-column/s-goods-column.vuepull/102/MERGE
commit
f03fcf1373
3
.env
3
.env
|
@ -18,7 +18,8 @@ SHOPRO_WEBSOCKET_PATH = /infra/ws
|
|||
SHOPRO_DEV_PORT = 3000
|
||||
|
||||
# 客户端静态资源地址 空=默认使用服务端指定的CDN资源地址前缀 | local=本地 | http(s)://xxx.xxx=自定义静态资源地址前缀
|
||||
SHOPRO_STATIC_URL = https://file.sheepjs.com
|
||||
SHOPRO_STATIC_URL = http://test.yudao.iocoder.cn
|
||||
### SHOPRO_STATIC_URL = https://file.sheepjs.com
|
||||
|
||||
# 是否开启直播 1 开启直播 | 0 关闭直播 (小程序官方后台未审核开通直播权限时请勿开启)
|
||||
SHOPRO_MPLIVE_ON = 0
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"appid": "__UNI__460BC4C",
|
||||
"description": "基于 uni-app + Vue3 技术驱动的在线商城系统,内含诸多功能与丰富的活动,期待您的使用和反馈。",
|
||||
"versionName": "2.1.0",
|
||||
"versionCode": 183,
|
||||
"versionCode": "183",
|
||||
"transformPx": false,
|
||||
"app-plus": {
|
||||
"usingComponents": true,
|
||||
|
@ -188,7 +188,8 @@
|
|||
"setting": {
|
||||
"urlCheck": false,
|
||||
"minified": true,
|
||||
"postcss": true
|
||||
"postcss": false,
|
||||
"es6": false
|
||||
},
|
||||
"optimization": {
|
||||
"subPackages": true
|
||||
|
@ -216,7 +217,7 @@
|
|||
"h5": {
|
||||
"template": "index.html",
|
||||
"router": {
|
||||
"mode": "hash",
|
||||
"mode": "history",
|
||||
"base": "./"
|
||||
},
|
||||
"sdkConfigs": {
|
||||
|
|
12
pages.json
12
pages.json
|
@ -307,6 +307,18 @@
|
|||
"title": "编辑地址"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "goods_details_store/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "自提门店"
|
||||
},
|
||||
"meta": {
|
||||
"auth": true,
|
||||
"sync": true,
|
||||
"title": "地址管理",
|
||||
"group": "用户中心"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "wallet/money",
|
||||
"style": {
|
||||
|
|
|
@ -181,11 +181,11 @@
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<!-- TODO 芋艿:这里暂时没接入 -->
|
||||
<view v-if="state.data.goods">
|
||||
<view v-if="!isEmpty(state.goodsInfo)">
|
||||
<!-- 规格与数量弹框 -->
|
||||
<s-select-groupon-sku
|
||||
:show="state.showSelectSku"
|
||||
:goodsInfo="state.data.goods"
|
||||
:goodsInfo="state.goodsInfo"
|
||||
:grouponAction="state.grouponAction"
|
||||
:grouponNum="state.grouponNum"
|
||||
@buy="onBuy"
|
||||
|
@ -193,6 +193,7 @@
|
|||
@close="state.showSelectSku = false"
|
||||
/>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<s-empty v-if="!state.data && !state.loading" icon="/static/goods-empty.png" />
|
||||
|
@ -203,25 +204,28 @@
|
|||
import { computed, reactive } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { useDurationTime } from '@/sheep/hooks/useGoods';
|
||||
import { fen2yuan, useDurationTime } from '@/sheep/hooks/useGoods';
|
||||
import { showShareModal } from '@/sheep/hooks/useModal';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import CombinationApi from '@/sheep/api/promotion/combination';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
|
||||
const headerBg = sheep.$url.css('/static/img/shop/user/withdraw_bg.png');
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const state = reactive({
|
||||
data: {}, // 拼团详情
|
||||
loading: true,
|
||||
grouponAction: 'create',
|
||||
showSelectSku: false,
|
||||
grouponNum: 0,
|
||||
number: 0,
|
||||
activity: {},
|
||||
goodsId: 0, // 商品ID
|
||||
goodsInfo: {}, // 商品信息
|
||||
showSelectSku: false, // 显示规格弹框
|
||||
selectedSkuPrice: {}, // 选中的规格价格
|
||||
activity: {}, // 团购活动
|
||||
grouponId: 0, // 团购ID
|
||||
grouponNum: 0, // 团购人数
|
||||
grouponAction: 'create', // 团购操作
|
||||
combinationHeadId: null, // 拼团团长编号
|
||||
loading: true,
|
||||
});
|
||||
|
||||
// todo 芋艿:分享要再接下
|
||||
const shareInfo = computed(() => {
|
||||
if (isEmpty(state.data)) return {};
|
||||
return sheep.$platform.share.getShareInfo(
|
||||
|
@ -231,15 +235,14 @@
|
|||
desc: state.data.goods?.subtitle,
|
||||
params: {
|
||||
page: '5',
|
||||
query: state.data.id,
|
||||
query: state.data.headRecord.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'groupon', // 邀请拼团海报
|
||||
title: state.data.headRecord.spuName, // 商品标题
|
||||
image: sheep.$url.cdn(state.data.headRecord.picUrl), // 商品主图
|
||||
price: state.data.goods?.price, // 商品价格
|
||||
original_price: state.data.goods?.original_price, // 商品原价
|
||||
price: fen2yuan(state.data.headRecord.combinationPrice), // 商品价格
|
||||
},
|
||||
);
|
||||
});
|
||||
|
@ -251,33 +254,33 @@
|
|||
});
|
||||
}
|
||||
|
||||
// 去开团 TODO 芋艿:这里没接入
|
||||
// 去开团
|
||||
function onCreateGroupon() {
|
||||
state.grouponAction = 'create';
|
||||
state.grouponId = 0;
|
||||
state.showSelectSku = true;
|
||||
}
|
||||
|
||||
// 规格变更 TODO 芋艿:这里没接入
|
||||
// 规格变更
|
||||
function onSkuChange(e) {
|
||||
state.selectedSkuPrice = e;
|
||||
}
|
||||
|
||||
// 立即参团 TODO 芋艿:这里没接入
|
||||
// 立即参团
|
||||
function onJoinGroupon() {
|
||||
state.grouponAction = 'join';
|
||||
state.grouponId = state.data.activityId;
|
||||
state.combinationHeadId = state.data.id;
|
||||
state.grouponNum = state.data.num;
|
||||
state.grouponId = state.data.headRecord.activityId;
|
||||
state.combinationHeadId = state.data.headRecord.id;
|
||||
state.grouponNum = state.data.headRecord.userSize;
|
||||
state.showSelectSku = true;
|
||||
}
|
||||
|
||||
// 立即购买 TODO 芋艿:这里没接入
|
||||
// 立即购买
|
||||
function onBuy(sku) {
|
||||
sheep.$router.go('/pages/order/confirm', {
|
||||
data: JSON.stringify({
|
||||
order_type: 'goods',
|
||||
combinationActivityId: state.data.activity.id,
|
||||
combinationActivityId: state.activity.id,
|
||||
combinationHeadId: state.combinationHeadId,
|
||||
items: [
|
||||
{
|
||||
|
@ -306,6 +309,25 @@
|
|||
data.headRecord.activityId,
|
||||
);
|
||||
state.activity = activity;
|
||||
state.grouponNum = activity.userSize;
|
||||
// 加载商品信息
|
||||
const { data: spu } = await SpuApi.getSpuDetail(activity.spuId);
|
||||
state.goodsId = spu.id;
|
||||
// 默认显示最低价
|
||||
activity.products.forEach((product) => {
|
||||
spu.price = Math.min(spu.price, product.combinationPrice); // 设置 SPU 的最低价格
|
||||
});
|
||||
state.goodsInfo = spu;
|
||||
// 价格、库存使用活动的
|
||||
spu.skus.forEach((sku) => {
|
||||
const product = activity.products.find((product) => product.skuId === sku.id);
|
||||
if (product) {
|
||||
sku.price = product.combinationPrice;
|
||||
} else {
|
||||
// 找不到可能是没配置,则不能发起秒杀
|
||||
sku.stock = 0;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
state.data = null;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 签到说明 TODO @科举:这里改成【已累计签到】 -->
|
||||
<!-- 签到说明 TODO @芋艿:【签到】这里改成【已累计签到】;改版,接入 sheepjs -->
|
||||
<view class="bg-white ss-m-t-16 ss-p-t-30 ss-p-b-60 ss-p-x-40">
|
||||
<view class="activity-title ss-m-b-30">签到说明</view>
|
||||
<view class="activity-des">1、已累计签到{{state.signInfo.totalDay}}天</view>
|
||||
|
@ -110,7 +110,7 @@
|
|||
signInfo: {}, // 签到信息
|
||||
|
||||
signConfigList: [], // 签到配置列表
|
||||
maxDay: 0, // 最大的签到天数
|
||||
maxDay: 0, // 最大的签到天数
|
||||
|
||||
showModel: false, // 签到弹框
|
||||
signResult: {}, // 签到结果
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
@scrolltoupper="onScrollToUpper" @query="queryList">
|
||||
<template #top>
|
||||
<!-- 撑一下顶部导航 -->
|
||||
<view style="height: 45px"></view>
|
||||
<view :style="{ height: sys_navBar + 'px' }"></view>
|
||||
</template>
|
||||
<!-- style="transform: scaleY(-1)"必须写,否则会导致列表倒置!!! -->
|
||||
<!-- 注意不要直接在chat-item组件标签上设置style,因为在微信小程序中是无效的,请包一层view -->
|
||||
|
@ -33,7 +33,9 @@
|
|||
import { reactive, ref } from 'vue';
|
||||
import KeFuApi from '@/sheep/api/promotion/kefu';
|
||||
import { isEmpty } from '@/sheep/helper/utils';
|
||||
|
||||
import sheep from '@/sheep';
|
||||
|
||||
const sys_navBar = sheep.$platform.navbar;
|
||||
const messageList = ref([]); // 消息列表
|
||||
const showNewMessageTip = ref(false); // 显示有新消息提示
|
||||
const backToTopStyle = reactive({
|
||||
|
@ -67,7 +69,7 @@
|
|||
};
|
||||
/** 刷新消息列表 */
|
||||
const refreshMessageList = (message = undefined) => {
|
||||
if (queryParams.pageNo != 1 && message !== undefined) {
|
||||
if (message !== undefined) {
|
||||
showNewMessageTip.value = true;
|
||||
// 追加数据
|
||||
pagingRef.value.addChatRecordData([message], false);
|
||||
|
@ -87,8 +89,6 @@
|
|||
return;
|
||||
}
|
||||
showNewMessageTip.value = false;
|
||||
// 到底重置消息列表
|
||||
refreshMessageList();
|
||||
};
|
||||
defineExpose({ getMessageList, refreshMessageList });
|
||||
</script>
|
||||
|
|
|
@ -4,12 +4,20 @@
|
|||
<view class="message-item ss-flex-col scroll-item">
|
||||
<view class="ss-flex ss-row-center ss-col-center">
|
||||
<!-- 日期 -->
|
||||
<view v-if="message.contentType !== KeFuMessageContentTypeEnum.SYSTEM && showTime(message, messageIndex)"
|
||||
class="date-message">
|
||||
<view
|
||||
v-if="
|
||||
message.contentType !== KeFuMessageContentTypeEnum.SYSTEM &&
|
||||
showTime(message, messageIndex)
|
||||
"
|
||||
class="date-message"
|
||||
>
|
||||
{{ formatDate(message.createTime) }}
|
||||
</view>
|
||||
<!-- 系统消息 -->
|
||||
<view v-if="message.contentType === KeFuMessageContentTypeEnum.SYSTEM" class="system-message">
|
||||
<view
|
||||
v-if="message.contentType === KeFuMessageContentTypeEnum.SYSTEM"
|
||||
class="system-message"
|
||||
>
|
||||
{{ message.content }}
|
||||
</view>
|
||||
</view>
|
||||
|
@ -18,32 +26,35 @@
|
|||
v-if="message.contentType !== KeFuMessageContentTypeEnum.SYSTEM"
|
||||
class="ss-flex ss-col-top"
|
||||
:class="[
|
||||
message.senderType === UserTypeEnum.ADMIN
|
||||
? `ss-row-left`
|
||||
: message.senderType === UserTypeEnum.MEMBER
|
||||
? `ss-row-right`
|
||||
: '',
|
||||
]"
|
||||
message.senderType === UserTypeEnum.ADMIN
|
||||
? `ss-row-left`
|
||||
: message.senderType === UserTypeEnum.MEMBER
|
||||
? `ss-row-right`
|
||||
: '',
|
||||
]"
|
||||
>
|
||||
<!-- 客服头像 -->
|
||||
<image
|
||||
v-show="message.senderType === UserTypeEnum.ADMIN"
|
||||
class="chat-avatar ss-m-r-24"
|
||||
:src="
|
||||
sheep.$url.cdn(message.senderAvatar) ||
|
||||
sheep.$url.static('/static/img/shop/chat/default.png')
|
||||
"
|
||||
sheep.$url.cdn(message.senderAvatar) ||
|
||||
sheep.$url.static('/static/img/shop/chat/default.png')
|
||||
"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<!-- 内容 -->
|
||||
<template v-if="message.contentType === KeFuMessageContentTypeEnum.TEXT">
|
||||
<view class="message-box" :class="{'admin': message.senderType === UserTypeEnum.ADMIN}">
|
||||
<view class="message-box" :class="{ admin: message.senderType === UserTypeEnum.ADMIN }">
|
||||
<mp-html :content="replaceEmoji(message.content)" />
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="message.contentType === KeFuMessageContentTypeEnum.IMAGE">
|
||||
<view class="message-box" :class="{'admin': message.senderType === UserTypeEnum.ADMIN}"
|
||||
:style="{ width: '200rpx' }">
|
||||
<view
|
||||
class="message-box"
|
||||
:class="{ admin: message.senderType === UserTypeEnum.ADMIN }"
|
||||
:style="{ width: '200rpx' }"
|
||||
>
|
||||
<su-image
|
||||
class="message-img"
|
||||
isPreview
|
||||
|
@ -59,29 +70,23 @@
|
|||
<template v-if="message.contentType === KeFuMessageContentTypeEnum.PRODUCT">
|
||||
<GoodsItem
|
||||
:goodsData="getMessageContent(message)"
|
||||
@tap="
|
||||
sheep.$router.go('/pages/goods/index', {
|
||||
id: getMessageContent(message).id,
|
||||
})
|
||||
"
|
||||
@tap="sheep.$router.go('/pages/goods/index', { id: getMessageContent(message).spuId })"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="message.contentType === KeFuMessageContentTypeEnum.ORDER">
|
||||
<OrderItem
|
||||
:orderData="getMessageContent(message)"
|
||||
@tap="
|
||||
sheep.$router.go('/pages/order/detail', {
|
||||
id: getMessageContent(message).id,
|
||||
})
|
||||
"
|
||||
@tap="sheep.$router.go('/pages/order/detail', { id: getMessageContent(message).id })"
|
||||
/>
|
||||
</template>
|
||||
<!-- user头像 -->
|
||||
<image
|
||||
v-if="message.senderType === UserTypeEnum.MEMBER"
|
||||
class="chat-avatar ss-m-l-24"
|
||||
:src="sheep.$url.cdn(message.senderAvatar) ||
|
||||
sheep.$url.static('/static/img/shop/chat/default.png')"
|
||||
:src="
|
||||
sheep.$url.cdn(message.senderAvatar) ||
|
||||
sheep.$url.static('/static/img/shop/chat/default.png')
|
||||
"
|
||||
mode="aspectFill"
|
||||
>
|
||||
</image>
|
||||
|
@ -104,7 +109,7 @@
|
|||
// 消息
|
||||
message: {
|
||||
type: Object,
|
||||
default: ()=>({}),
|
||||
default: () => ({}),
|
||||
},
|
||||
// 消息索引
|
||||
messageIndex: {
|
||||
|
@ -112,10 +117,10 @@
|
|||
default: 0,
|
||||
},
|
||||
// 消息列表
|
||||
messageList:{
|
||||
messageList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
}
|
||||
},
|
||||
});
|
||||
const getMessageContent = computed(() => (item) => JSON.parse(item.content)); // 解析消息内容
|
||||
|
||||
|
|
|
@ -1,138 +1,145 @@
|
|||
<!-- 分销:商菜单栏 -->
|
||||
<template>
|
||||
<view class="menu-box ss-flex-col">
|
||||
<view class="header-box">
|
||||
<image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title1.png')" />
|
||||
<view class="ss-flex header-title">
|
||||
<view class="title">功能专区</view>
|
||||
<text class="cicon-forward"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="menu-list ss-flex ss-flex-wrap">
|
||||
<view v-for="(item, index) in state.menuList" :key="index" class="item-box ss-flex-col ss-col-center"
|
||||
@tap="sheep.$router.go(item.path)">
|
||||
<image class="menu-icon ss-m-b-10" :src="sheep.$url.static(item.img)" mode="aspectFill"></image>
|
||||
<view>{{ item.title }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="menu-box ss-flex-col">
|
||||
<view class="header-box">
|
||||
<image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title1.png')" />
|
||||
<view class="ss-flex header-title">
|
||||
<view class="title">功能专区</view>
|
||||
<text class="cicon-forward"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="menu-list ss-flex ss-flex-wrap">
|
||||
<view
|
||||
v-for="(item, index) in state.menuList"
|
||||
:key="index"
|
||||
class="item-box ss-flex-col ss-col-center"
|
||||
@tap="sheep.$router.go(item.path)"
|
||||
>
|
||||
<image
|
||||
class="menu-icon ss-m-b-10"
|
||||
:src="sheep.$url.static(item.img)"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view>{{ item.title }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { reactive } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { reactive } from 'vue';
|
||||
|
||||
const state = reactive({
|
||||
menuList: [{
|
||||
img: '/static/img/shop/commission/commission_icon1.png',
|
||||
title: '我的团队',
|
||||
path: '/pages/commission/team',
|
||||
},
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon2.png',
|
||||
title: '佣金明细',
|
||||
path: '/pages/commission/wallet',
|
||||
},
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon3.png',
|
||||
title: '分销订单',
|
||||
path: '/pages/commission/order',
|
||||
},
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon4.png',
|
||||
title: '推广商品',
|
||||
path: '/pages/commission/goods',
|
||||
},
|
||||
// {
|
||||
// img: '/static/img/shop/commission/commission_icon5.png',
|
||||
// title: '我的资料',
|
||||
// path: '/pages/commission/apply',
|
||||
// isAgentFrom: true,
|
||||
// },
|
||||
// todo @芋艿:邀请海报需要登录后的个人数据
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon7.png',
|
||||
title: '邀请海报',
|
||||
path: 'action:showShareModal',
|
||||
},
|
||||
// TODO @芋艿:缺少 icon
|
||||
const state = reactive({
|
||||
menuList: [
|
||||
{
|
||||
// img: '/static/img/shop/commission/commission_icon7.png',
|
||||
title: '推广排行',
|
||||
path: '/pages/commission/promoter',
|
||||
},
|
||||
img: '/static/img/shop/commission/commission_icon1.png',
|
||||
title: '我的团队',
|
||||
path: '/pages/commission/team',
|
||||
},
|
||||
{
|
||||
// img: '/static/img/shop/commission/commission_icon7.png',
|
||||
title: '佣金排行',
|
||||
path: '/pages/commission/commission-ranking',
|
||||
}
|
||||
],
|
||||
});
|
||||
img: '/static/img/shop/commission/commission_icon2.png',
|
||||
title: '佣金明细',
|
||||
path: '/pages/commission/wallet',
|
||||
},
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon3.png',
|
||||
title: '分销订单',
|
||||
path: '/pages/commission/order',
|
||||
},
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon4.png',
|
||||
title: '推广商品',
|
||||
path: '/pages/commission/goods',
|
||||
},
|
||||
// {
|
||||
// img: '/static/img/shop/commission/commission_icon5.png',
|
||||
// title: '我的资料',
|
||||
// path: '/pages/commission/apply',
|
||||
// isAgentFrom: true,
|
||||
// },
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon7.png',
|
||||
title: '邀请海报',
|
||||
path: 'action:showShareModal',
|
||||
},
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon8.png',
|
||||
title: '推广排行',
|
||||
path: '/pages/commission/promoter',
|
||||
},
|
||||
{
|
||||
img: '/static/img/shop/commission/commission_icon9.png',
|
||||
title: '佣金排行',
|
||||
path: '/pages/commission/commission-ranking',
|
||||
},
|
||||
],
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.menu-box {
|
||||
margin: 0 auto;
|
||||
width: 690rpx;
|
||||
margin-bottom: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
z-index: 3;
|
||||
position: relative;
|
||||
}
|
||||
.menu-box {
|
||||
margin: 0 auto;
|
||||
width: 690rpx;
|
||||
margin-bottom: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
z-index: 3;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header-box {
|
||||
width: 690rpx;
|
||||
height: 76rpx;
|
||||
position: relative;
|
||||
.header-box {
|
||||
width: 690rpx;
|
||||
height: 76rpx;
|
||||
position: relative;
|
||||
|
||||
.header-bg {
|
||||
width: 690rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
.header-bg {
|
||||
width: 690rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
position: absolute;
|
||||
left: 20rpx;
|
||||
top: 24rpx;
|
||||
}
|
||||
.header-title {
|
||||
position: absolute;
|
||||
left: 20rpx;
|
||||
top: 24rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
|
||||
.cicon-forward {
|
||||
font-size: 30rpx;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
}
|
||||
.cicon-forward {
|
||||
font-size: 30rpx;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-list {
|
||||
padding: 50rpx 0 10rpx 0;
|
||||
background: #fdfae9;
|
||||
border-radius: 0 0 12rpx 12rpx;
|
||||
}
|
||||
.menu-list {
|
||||
padding: 50rpx 0 10rpx 0;
|
||||
background: #fdfae9;
|
||||
border-radius: 0 0 12rpx 12rpx;
|
||||
}
|
||||
|
||||
.item-box {
|
||||
width: 25%;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
.item-box {
|
||||
width: 25%;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
width: 68rpx;
|
||||
height: 68rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.menu-icon {
|
||||
width: 68rpx;
|
||||
height: 68rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.menu-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
.menu-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
shareInfo: {},
|
||||
});
|
||||
|
||||
// TODO 芋艿:分享的接入
|
||||
// TODO @puhui999:【分享】接入
|
||||
function onShareGoods(goodsInfo) {
|
||||
state.shareInfo = $share.getShareInfo(
|
||||
{
|
||||
|
|
|
@ -1,8 +1,29 @@
|
|||
<!-- 页面 TODO 芋艿:该页面的实现代码需要优化,包括 js 和 css,以及相关的样式设计 -->
|
||||
<template>
|
||||
<s-layout title="我的团队" :class="state.scrollTop ? 'team-wrap' : ''" navbar="inner">
|
||||
<view
|
||||
class="header-box"
|
||||
:style="[
|
||||
{
|
||||
marginTop: '-' + Number(statusBarHeight + 88) + 'rpx',
|
||||
paddingTop: Number(statusBarHeight + 108) + 'rpx',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<!-- 推广数据总览 -->
|
||||
<view class="team-data-box ss-flex ss-col-center ss-row-between" style="width: 100%">
|
||||
<view class="data-card" style="width: 100%">
|
||||
<view class="total-item" style="width: 100%">
|
||||
<view class="item-title" style="text-align: center">推广人数</view>
|
||||
<view class="total-num" style="text-align: center">
|
||||
{{ state.summary.firstBrokerageUserCount + state.summary.secondBrokerageUserCount || 0 }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="promoter-list">
|
||||
<view
|
||||
<!--<view
|
||||
class="promoterHeader bg-color"
|
||||
style="backgroundcolor: #e93323 !important; height: 218rpx; color: #fff"
|
||||
>
|
||||
|
@ -21,9 +42,9 @@
|
|||
</view>
|
||||
<view class="iconfont icon-tuandui" />
|
||||
</view>
|
||||
</view>
|
||||
<view style="padding: 0 30rpx">
|
||||
<view class="nav acea-row row-around l1">
|
||||
</view>-->
|
||||
<view style="padding: 0 20rpx">
|
||||
<view class="nav acea-row row-around l1" style="margin-top:20rpx;">
|
||||
<view :class="state.level == 1 ? 'item on' : 'item'" @click="setType(1)">
|
||||
一级({{ state.summary.firstBrokerageUserCount || 0 }})
|
||||
</view>
|
||||
|
@ -152,7 +173,7 @@
|
|||
</view>
|
||||
</block>
|
||||
<block v-if="state.pagination.list.length === 0">
|
||||
<view style="text-align: center">暂无推广人数</view>
|
||||
<view style="text-align: center;margin-top:30rpx;">暂无推广人数</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
|
@ -456,7 +477,7 @@
|
|||
.promoter-list .nav .item.on {
|
||||
border-bottom: 5rpx solid;
|
||||
// $theme-color
|
||||
color: red;
|
||||
color: var(--ui-BG-Main);
|
||||
// $theme-color
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,10 @@
|
|||
<view class="num-title">可提现金额(元)</view>
|
||||
<view class="wallet-num">{{ fen2yuan(state.brokerageInfo.brokeragePrice) }}</view>
|
||||
</view>
|
||||
<button class="ss-reset-button log-btn" @tap="sheep.$router.go('/pages/commission/wallet', { type: 2 })">
|
||||
<button
|
||||
class="ss-reset-button log-btn"
|
||||
@tap="sheep.$router.go('/pages/commission/wallet', { type: 2 })"
|
||||
>
|
||||
提现记录
|
||||
</button>
|
||||
</view>
|
||||
|
@ -98,12 +101,23 @@
|
|||
v-show="state.accountInfo.type === '2'"
|
||||
>
|
||||
<view class="unit" />
|
||||
<uni-easyinput
|
||||
:inputBorder="false"
|
||||
class="ss-flex-1 ss-p-l-10"
|
||||
v-model="state.accountInfo.bankName"
|
||||
placeholder="请输入提现银行"
|
||||
/>
|
||||
<!--银行改为下拉选择-->
|
||||
<picker
|
||||
@change="bankChange"
|
||||
:value="state.bankListSelectedIndex"
|
||||
:range="state.bankList"
|
||||
range-key="label"
|
||||
style="width: 100%"
|
||||
>
|
||||
<uni-easyinput
|
||||
:inputBorder="false"
|
||||
:value="state.accountInfo.bankName"
|
||||
placeholder="请选择银行"
|
||||
suffixIcon="right"
|
||||
disabled
|
||||
:styles="{ disableColor: '#fff', borderColor: '#fff', color: '#333!important' }"
|
||||
/>
|
||||
</picker>
|
||||
</view>
|
||||
<!-- 开户地址 -->
|
||||
<view class="card-title" v-show="state.accountInfo.type === '2'">开户地址</view>
|
||||
|
@ -152,6 +166,7 @@
|
|||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import TradeConfigApi from '@/sheep/api/trade/config';
|
||||
import BrokerageApi from '@/sheep/api/trade/brokerage';
|
||||
import DictApi from '@/sheep/api/system/dict';
|
||||
|
||||
const headerBg = sheep.$url.css('/static/img/shop/user/withdraw_bg.png');
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
|
@ -176,6 +191,8 @@
|
|||
frozenDays: 0, // 冻结天数
|
||||
minPrice: 0, // 最低提现金额
|
||||
withdrawTypes: [], // 提现方式
|
||||
bankList: [], // 银行字典数据
|
||||
bankListSelectedIndex: '', // 选中银行 bankList 的 index
|
||||
});
|
||||
|
||||
// 打开提现方式的弹窗
|
||||
|
@ -186,7 +203,7 @@
|
|||
// 提交提现
|
||||
const onConfirm = async () => {
|
||||
// 参数校验
|
||||
debugger;
|
||||
//debugger;
|
||||
if (
|
||||
!state.accountInfo.price ||
|
||||
state.accountInfo.price > state.brokerageInfo.price ||
|
||||
|
@ -215,12 +232,12 @@
|
|||
confirmText: '查看记录',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
sheep.$router.go('/pages/commission/wallet', { type: 2 })
|
||||
sheep.$router.go('/pages/commission/wallet', { type: 2 });
|
||||
return;
|
||||
}
|
||||
getBrokerageUser();
|
||||
state.accountInfo = {};
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -245,10 +262,29 @@
|
|||
}
|
||||
}
|
||||
|
||||
// 获取提现银行配置字典
|
||||
async function getDictDataListByType() {
|
||||
let { code, data } = await DictApi.getDictDataListByType('brokerage_bank_name');
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
if (data && data.length > 0) {
|
||||
state.bankList = data;
|
||||
}
|
||||
}
|
||||
|
||||
// 银行选择
|
||||
function bankChange(e) {
|
||||
const value = e.detail.value;
|
||||
state.bankListSelectedIndex = value;
|
||||
state.accountInfo.bankName = state.bankList[value].label;
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
getWithdrawRules();
|
||||
getBrokerageUser()
|
||||
})
|
||||
getBrokerageUser();
|
||||
getDictDataListByType(); //获取银行字典数据
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -107,7 +107,6 @@
|
|||
},
|
||||
];
|
||||
|
||||
// TODO yunai:
|
||||
function onTabsChange(e) {
|
||||
state.currentTab = e.index;
|
||||
state.type = e.value;
|
||||
|
|
|
@ -1,89 +1,130 @@
|
|||
<!-- 评价 -->
|
||||
<template>
|
||||
<s-layout title="评价">
|
||||
<view>
|
||||
<view v-for="(item, index) in state.orderInfo.items" :key="item.id">
|
||||
<view>
|
||||
<view class="commont-from-wrap">
|
||||
<!-- 评价商品 -->
|
||||
<s-goods-item
|
||||
<s-layout title="评价">
|
||||
<view>
|
||||
<view v-for="(item, index) in state.orderInfo.items" :key="item.id">
|
||||
<view>
|
||||
<view class="commont-from-wrap">
|
||||
<!-- 评价商品 -->
|
||||
<s-goods-item
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.payPrice"
|
||||
:price="item.payPrice"
|
||||
:num="item.count"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<!-- 评分 -->
|
||||
<view class="star-box ss-flex ss-col-center">
|
||||
<view class="star-title ss-m-r-40">商品质量</view>
|
||||
<uni-rate v-model="state.commentList[index].descriptionScores" />
|
||||
</view>
|
||||
<view class="star-box ss-flex ss-col-center">
|
||||
<view class="star-title ss-m-r-40">服务态度</view>
|
||||
<uni-rate v-model="state.commentList[index].benefitScores" />
|
||||
</view>
|
||||
<!-- 评价 -->
|
||||
<view class="area-box">
|
||||
<uni-easyinput :inputBorder="false" type="textarea" maxlength="120" autoHeight
|
||||
v-model="state.commentList[index].content"
|
||||
placeholder="宝贝满足你的期待吗?说说你的使用心得,分享给想买的他们吧~" />
|
||||
<!-- TODO 芋艿:文件上传 -->
|
||||
<view class="img-box">
|
||||
<s-uploader v-model:url="state.commentList[index].images" fileMediatype="image"
|
||||
limit="9" mode="grid" :imageStyles="{ width: '168rpx', height: '168rpx' }" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- TODO 芋艿:是否匿名 -->
|
||||
|
||||
<su-fixed bottom placeholder>
|
||||
<view class="foot_box ss-flex ss-row-center ss-col-center">
|
||||
<button class="ss-reset-button post-btn ui-BG-Main-Gradient ui-Shadow-Main" @tap="onSubmit">
|
||||
发布
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
<view class="form-item">
|
||||
<!-- 评分 -->
|
||||
<view class="star-box ss-flex ss-col-center">
|
||||
<view class="star-title ss-m-r-40">商品质量</view>
|
||||
<uni-rate v-model="state.commentList[index].descriptionScores" />
|
||||
</view>
|
||||
<view class="star-box ss-flex ss-col-center">
|
||||
<view class="star-title ss-m-r-40">服务态度</view>
|
||||
<uni-rate v-model="state.commentList[index].benefitScores" />
|
||||
</view>
|
||||
<!-- 评价 -->
|
||||
<view class="area-box">
|
||||
<uni-easyinput
|
||||
:inputBorder="false"
|
||||
type="textarea"
|
||||
maxlength="120"
|
||||
autoHeight
|
||||
v-model="state.commentList[index].content"
|
||||
placeholder="宝贝满足你的期待吗?说说你的使用心得,分享给想买的他们吧~"
|
||||
/>
|
||||
<view class="img-box">
|
||||
<s-uploader
|
||||
v-model:url="state.commentList[index].images"
|
||||
fileMediatype="image"
|
||||
limit="9"
|
||||
mode="grid"
|
||||
:imageStyles="{ width: '168rpx', height: '168rpx' }"
|
||||
@success="(payload) => uploadSuccess(payload, index)"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="checkbox-container">
|
||||
<checkbox-group @change="(event) => toggleAnonymous(index, event)">
|
||||
<label>
|
||||
<checkbox value="anonymousChecked" />
|
||||
匿名评论
|
||||
</label>
|
||||
</checkbox-group>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<su-fixed bottom placeholder>
|
||||
<view class="foot_box ss-flex ss-row-center ss-col-center">
|
||||
<button class="ss-reset-button post-btn ui-BG-Main-Gradient ui-Shadow-Main" @tap="onSubmit">
|
||||
发布
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive, ref } from 'vue';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
|
||||
const state = reactive({
|
||||
orderInfo: {},
|
||||
commentList: [],
|
||||
id: null
|
||||
});
|
||||
const state = reactive({
|
||||
orderInfo: {},
|
||||
commentList: [],
|
||||
id: null,
|
||||
});
|
||||
|
||||
async function onSubmit() {
|
||||
/**
|
||||
* 切换是否匿名
|
||||
*
|
||||
* @param commentIndex 当前评论下标
|
||||
* @param event 复选框事件
|
||||
*/
|
||||
function toggleAnonymous(commentIndex, event) {
|
||||
state.commentList[commentIndex].anonymous = event.detail.value[0] === 'anonymousChecked';
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布评论
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function onSubmit() {
|
||||
// 顺序提交评论
|
||||
for (const comment of state.commentList) {
|
||||
await OrderApi.createOrderItemComment(comment);
|
||||
}
|
||||
// 都评论好,返回
|
||||
sheep.$router.back();
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
/**
|
||||
* 图片添加到表单
|
||||
*
|
||||
* @param payload 上传成功后的回调数据
|
||||
* @param commentIndex 当前评论的下标
|
||||
*/
|
||||
function uploadSuccess(payload, commentIndex) {
|
||||
state.commentList[commentIndex].picUrls = state.commentList[commentIndex].images;
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (!options.id) {
|
||||
sheep.$helper.toast(`缺少订单信息,请检查`);
|
||||
return
|
||||
return;
|
||||
}
|
||||
state.id = options.id;
|
||||
state.id = options.id;
|
||||
|
||||
const { code, data } = await OrderApi.getOrder(state.id);
|
||||
const { code, data } = await OrderApi.getOrder(state.id);
|
||||
if (code !== 0) {
|
||||
sheep.$helper.toast('无待评价订单');
|
||||
return
|
||||
return;
|
||||
}
|
||||
// 处理评论
|
||||
data.items.forEach((item) => {
|
||||
|
@ -93,53 +134,57 @@
|
|||
descriptionScores: 5,
|
||||
benefitScores: 5,
|
||||
content: '',
|
||||
picUrls: []
|
||||
picUrls: [],
|
||||
});
|
||||
});
|
||||
state.orderInfo = data;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 评价商品
|
||||
.goods-card {
|
||||
margin: 10rpx 0;
|
||||
padding: 20rpx;
|
||||
background: #fff;
|
||||
}
|
||||
// 评价商品
|
||||
.goods-card {
|
||||
margin: 10rpx 0;
|
||||
padding: 20rpx;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
// 评论,选择图片
|
||||
.form-item {
|
||||
background: #fff;
|
||||
// 评论,选择图片
|
||||
.form-item {
|
||||
background: #fff;
|
||||
|
||||
.star-box {
|
||||
height: 100rpx;
|
||||
padding: 0 25rpx;
|
||||
}
|
||||
.star-box {
|
||||
height: 100rpx;
|
||||
padding: 0 25rpx;
|
||||
}
|
||||
|
||||
.star-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
.star-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.area-box {
|
||||
width: 690rpx;
|
||||
min-height: 306rpx;
|
||||
background: rgba(249, 250, 251, 1);
|
||||
border-radius: 20rpx;
|
||||
padding: 28rpx;
|
||||
margin: auto;
|
||||
.area-box {
|
||||
width: 690rpx;
|
||||
min-height: 306rpx;
|
||||
background: rgba(249, 250, 251, 1);
|
||||
border-radius: 20rpx;
|
||||
padding: 28rpx;
|
||||
margin: auto;
|
||||
|
||||
.img-box {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
.img-box {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.post-btn {
|
||||
width: 690rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
color: rgba(#fff, 0.9);
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
</style>
|
||||
.checkbox-container {
|
||||
padding: 10rpx;
|
||||
}
|
||||
|
||||
.post-btn {
|
||||
width: 690rpx;
|
||||
line-height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
color: rgba(#fff, 0.9);
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!-- 商品评论的分页 -->
|
||||
<template>
|
||||
<s-layout title="全部评价">
|
||||
<s-layout title="全部评论">
|
||||
<su-tabs
|
||||
:list="state.type"
|
||||
:scrollable="false"
|
||||
|
@ -16,6 +16,7 @@
|
|||
<s-empty v-if="state.pagination.total === 0" text="暂无数据" icon="/static/data-empty.png" />
|
||||
<!-- 下拉 -->
|
||||
<uni-load-more
|
||||
icon-type="auto"
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<su-fixed bottom placeholder :val="44">
|
||||
<view>
|
||||
<view v-for="activity in props.activityList" :key="activity.id">
|
||||
<!-- TODO 芋艿:拼团 -->
|
||||
<view
|
||||
class="activity-box ss-p-x-38 ss-flex ss-row-between ss-col-center"
|
||||
:class="activity.type === 1 ? 'seckill-box' : 'groupon-box'"
|
||||
|
@ -14,7 +13,6 @@
|
|||
:src="sheep.$url.static('/static/img/shop/goods/seckill-icon.png')"
|
||||
class="activity-icon"
|
||||
/>
|
||||
<!-- TODO 芋艿:拼团 -->
|
||||
<image
|
||||
v-else-if="activity.type === 3"
|
||||
:src="sheep.$url.static('/static/img/shop/goods/groupon-icon.png')"
|
||||
|
@ -33,7 +31,6 @@
|
|||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
|
||||
// TODO 芋艿:这里要迁移下;
|
||||
const seckillBg = sheep.$url.css('/static/img/shop/goods/seckill-tip-bg.png');
|
||||
const grouponBg = sheep.$url.css('/static/img/shop/goods/groupon-tip-bg.png');
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
<view class="origin-price ss-flex ss-col-center" v-if="state.goodsInfo.price">
|
||||
单买价:
|
||||
<view class="origin-price-text">
|
||||
{{ fen2yuan(state.goodsInfo.price) }}
|
||||
{{ fen2yuan(state.goodsInfo.marketPrice) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
@ -80,7 +80,7 @@
|
|||
<!-- 功能卡片 -->
|
||||
<view class="detail-cell-card detail-card ss-flex-col">
|
||||
<!-- 规格 -->
|
||||
<detail-cell-sku :sku="state.selectedSkuPrice" @tap="state.showSelectSku = true" />
|
||||
<detail-cell-sku :sku="state.selectedSku" @tap="state.showSelectSku = true" />
|
||||
</view>
|
||||
|
||||
<!-- 参团列表 -->
|
||||
|
@ -104,7 +104,6 @@
|
|||
<detail-content-card class="detail-content-selector" :content="state.goodsInfo.description" />
|
||||
|
||||
<!-- 商品tabbar -->
|
||||
<!-- TODO: 已售罄、预热 判断 设计-->
|
||||
<detail-tabbar v-model="state.goodsInfo">
|
||||
<view class="buy-box ss-flex ss-col-center ss-p-r-20">
|
||||
<button
|
||||
|
@ -125,7 +124,12 @@
|
|||
:disabled="state.goodsInfo.stock === 0 || state.activity.status !== 0"
|
||||
>
|
||||
<view class="btn-price">{{
|
||||
fen2yuan(state.activity.price || state.goodsInfo.price)
|
||||
fen2yuan(
|
||||
state.selectedSku.price * state.selectedSku.count ||
|
||||
state.activity.price * state.selectedSku.count ||
|
||||
state.goodsInfo.price * state.selectedSku.count ||
|
||||
state.goodsInfo.price,
|
||||
)
|
||||
}}</view>
|
||||
<view v-if="state.activity.startTime > new Date().getTime()">未开始</view>
|
||||
<view v-else-if="state.activity.endTime <= new Date().getTime()">已结束</view>
|
||||
|
@ -168,7 +172,7 @@
|
|||
goodsInfo: {}, // 商品信息
|
||||
goodsSwiper: [], // 商品轮播图
|
||||
showSelectSku: false, // 显示规格弹框
|
||||
selectedSkuPrice: {}, // 选中的规格价格
|
||||
selectedSku: {}, // 选中的规格属性
|
||||
activity: {}, // 团购活动
|
||||
grouponId: 0, // 团购ID
|
||||
grouponNum: 0, // 团购人数
|
||||
|
@ -183,7 +187,7 @@
|
|||
|
||||
// 规格变更
|
||||
function onSkuChange(e) {
|
||||
state.selectedSkuPrice = e;
|
||||
state.selectedSku = e;
|
||||
}
|
||||
|
||||
function onSkuClose() {
|
||||
|
@ -199,6 +203,7 @@
|
|||
|
||||
/**
|
||||
* 去参团
|
||||
*
|
||||
* @param record 团长的团购记录
|
||||
*/
|
||||
function onJoinGroupon(record) {
|
||||
|
@ -227,7 +232,6 @@
|
|||
}
|
||||
|
||||
// 分享信息
|
||||
// TODO @芋艿:分享的接入
|
||||
const shareInfo = computed(() => {
|
||||
if (isEmpty(state.activity)) return {};
|
||||
return sheep.$platform.share.getShareInfo(
|
||||
|
@ -262,9 +266,23 @@
|
|||
// 加载商品信息
|
||||
const { data: spu } = await SpuApi.getSpuDetail(activity.spuId);
|
||||
state.goodsId = spu.id;
|
||||
activity.products.forEach((product) => {
|
||||
spu.price = Math.min(spu.price, product.combinationPrice); // 设置 SPU 的最低价格
|
||||
|
||||
// 默认显示最低价
|
||||
spu.price = activity.products.reduce((min, product) => {
|
||||
return Math.min(min, product.combinationPrice || Infinity);
|
||||
}, Infinity);
|
||||
|
||||
// 价格、库存使用活动的
|
||||
spu.skus.forEach((sku) => {
|
||||
const product = activity.products.find((product) => product.skuId === sku.id);
|
||||
if (product) {
|
||||
sku.price = product.combinationPrice;
|
||||
} else {
|
||||
// 找不到可能是没配置,则不能发起秒杀
|
||||
sku.stock = 0;
|
||||
}
|
||||
});
|
||||
|
||||
// 关闭骨架屏
|
||||
state.skeletonLoading = false;
|
||||
if (code === 0) {
|
||||
|
|
|
@ -7,47 +7,30 @@
|
|||
<!-- 骨架屏 -->
|
||||
<detailSkeleton v-if="state.skeletonLoading" />
|
||||
<!-- 下架/售罄提醒 -->
|
||||
<s-empty v-else-if="state.goodsInfo === null" text="商品不存在或已下架" icon="/static/soldout-empty.png" showAction
|
||||
actionText="再逛逛" actionUrl="/pages/goods/list" />
|
||||
<s-empty
|
||||
v-else-if="state.goodsInfo === null"
|
||||
text="商品不存在或已下架"
|
||||
icon="/static/soldout-empty.png"
|
||||
showAction
|
||||
actionText="再逛逛"
|
||||
actionUrl="/pages/goods/list"
|
||||
/>
|
||||
<block v-else>
|
||||
<view class="detail-swiper-selector">
|
||||
<!-- 商品轮播图 -->
|
||||
<su-swiper class="ss-m-b-14" isPreview :list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)"
|
||||
otStyle="tag" imageMode="widthFix" dotCur="bg-mask-40" :seizeHeight="750" />
|
||||
<!-- 限时折扣 -->
|
||||
<view class="discount" v-if="setShow">
|
||||
<image class="disImg" src="../../static/images/dis.png"></image>
|
||||
<view class="discountCont">
|
||||
<view class="disContT">
|
||||
<view class="disContT1">
|
||||
<view class="disContT1P">
|
||||
¥{{fen2yuan(settleData.price)}}
|
||||
</view>
|
||||
<view class="disContT1End">
|
||||
直降¥{{fen2yuan( state.goodsInfo.price - settleData.price)}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="disContT2">
|
||||
限时折扣
|
||||
</view>
|
||||
</view>
|
||||
<view class="disContB">
|
||||
<view class="disContB1">
|
||||
价格:¥{{fen2yuan(state.goodsInfo.price)}} 丨 剩余:{{settleData.stock}}
|
||||
</view>
|
||||
<view class="disContB2">
|
||||
距结束仅剩
|
||||
<countDown :tipText="' '" :bgColor="bgColor" :dayText="':'" :hourText="':'"
|
||||
:minuteText="':'" :secondText="' '" :datatime="settleData.endTime / 1000"
|
||||
:isDay="false" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 限时折扣 -->
|
||||
<su-swiper
|
||||
class="ss-m-b-14"
|
||||
isPreview
|
||||
:list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)"
|
||||
otStyle="tag"
|
||||
imageMode="widthFix"
|
||||
dotCur="bg-mask-40"
|
||||
:seizeHeight="750"
|
||||
/>
|
||||
|
||||
<!-- 价格+标题 -->
|
||||
<view class="title-card detail-card ss-p-y-40 ss-p-x-20">
|
||||
<view class="ss-flex ss-row-between ss-col-center ss-m-b-26" v-if="!setShow">
|
||||
<view class="ss-flex ss-row-between ss-col-center ss-m-b-26">
|
||||
<view class="price-box ss-flex ss-col-bottom">
|
||||
<view class="price-text ss-m-r-16">
|
||||
{{ fen2yuan(state.selectedSku.price || state.goodsInfo.price) }}
|
||||
|
@ -64,16 +47,23 @@
|
|||
<!-- 满减送/限时折扣活动的提示 -->
|
||||
<div class="tag-content">
|
||||
<view class="tag-box ss-flex">
|
||||
<view class="tag ss-m-r-10" v-for="promos in state.activityInfo" :key="promos.id"
|
||||
@tap="onActivity">
|
||||
<view
|
||||
class="tag ss-m-r-10"
|
||||
v-for="promos in state.activityInfo"
|
||||
:key="promos.id"
|
||||
@tap="onActivity"
|
||||
>
|
||||
{{ promos.name }}
|
||||
</view>
|
||||
</view>
|
||||
</div>
|
||||
|
||||
<!-- 优惠劵@tap="state.showModel = true" -->
|
||||
<view class="get-coupon-box ss-flex ss-col-center ss-m-l-20" @tap="onActivity"
|
||||
v-if="state.couponInfo.length">
|
||||
<!-- 优惠劵 -->
|
||||
<view
|
||||
class="get-coupon-box ss-flex ss-col-center ss-m-l-20"
|
||||
@tap="state.showModel = true"
|
||||
v-if="state.couponInfo.length"
|
||||
>
|
||||
<view class="discounts-title ss-m-r-8">领券</view>
|
||||
<text class="cicon-forward"></text>
|
||||
</view>
|
||||
|
@ -84,30 +74,51 @@
|
|||
|
||||
<!-- 功能卡片 -->
|
||||
<view class="detail-cell-card detail-card ss-flex-col">
|
||||
<detail-cell-sku v-model="state.selectedSku.goods_sku_text" :sku="state.selectedSku"
|
||||
@tap="state.showSelectSku = true" />
|
||||
<detail-cell-sku
|
||||
v-model="state.selectedSku.goods_sku_text"
|
||||
:sku="state.selectedSku"
|
||||
@tap="state.showSelectSku = true"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 规格与数量弹框 -->
|
||||
<s-select-sku :goodsInfo="state.goodsInfo" :show="state.showSelectSku" @addCart="onAddCart"
|
||||
@buy="onBuy" @change="onSkuChange" @close="state.showSelectSku = false" />
|
||||
<s-select-sku
|
||||
:goodsInfo="state.goodsInfo"
|
||||
:show="state.showSelectSku"
|
||||
@addCart="onAddCart"
|
||||
@buy="onBuy"
|
||||
@change="onSkuChange"
|
||||
@close="state.showSelectSku = false"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 评价 -->
|
||||
<detail-comment-card class="detail-comment-selector" :goodsId="state.goodsId" />
|
||||
<!-- 详情 -->
|
||||
<detail-content-card class="detail-content-selector" :content="state.goodsInfo.description" />
|
||||
<detail-content-card
|
||||
class="detail-content-selector"
|
||||
:content="state.goodsInfo.description"
|
||||
/>
|
||||
|
||||
<!-- 活动跳转:拼团/秒杀/砍价活动 -->
|
||||
<detail-activity-tip v-if="state.activityList.length > 0" :activity-list="state.activityList" />
|
||||
<detail-activity-tip
|
||||
v-if="state.activityList.length > 0"
|
||||
:activity-list="state.activityList"
|
||||
/>
|
||||
|
||||
<!-- 详情 tabbar -->
|
||||
<detail-tabbar v-model="state.goodsInfo">
|
||||
<view class="buy-box ss-flex ss-col-center ss-p-r-20" v-if="state.goodsInfo.stock > 0">
|
||||
<button class="ss-reset-button add-btn ui-Shadow-Main" @tap="state.showSelectSku = true">
|
||||
<button
|
||||
class="ss-reset-button add-btn ui-Shadow-Main"
|
||||
@tap="state.showSelectSku = true"
|
||||
>
|
||||
加入购物车
|
||||
</button>
|
||||
<button class="ss-reset-button buy-btn ui-Shadow-Main" @tap="state.showSelectSku = true">
|
||||
<button
|
||||
class="ss-reset-button buy-btn ui-Shadow-Main"
|
||||
@tap="state.showSelectSku = true"
|
||||
>
|
||||
立即购买
|
||||
</button>
|
||||
</view>
|
||||
|
@ -117,38 +128,32 @@
|
|||
</detail-tabbar>
|
||||
|
||||
<!-- 优惠劵弹窗 -->
|
||||
<!-- <s-coupon-get v-model="state.couponInfo" :show="state.showModel" @close="state.showModel = false"
|
||||
@get="onGet" /> -->
|
||||
<s-coupon-get
|
||||
v-model="state.couponInfo"
|
||||
:show="state.showModel"
|
||||
@close="state.showModel = false"
|
||||
@get="onGet"
|
||||
/>
|
||||
|
||||
<!-- 满减送/限时折扣活动弹窗 -->
|
||||
<s-activity-pop v-model="state" :show="state.showActivityModel"
|
||||
@close="state.showActivityModel = false" @get="onGet" />
|
||||
<s-activity-pop
|
||||
v-model="state.activityInfo"
|
||||
:show="state.showActivityModel"
|
||||
@close="state.showActivityModel = false"
|
||||
/>
|
||||
</block>
|
||||
</s-layout>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
computed,
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad,
|
||||
onPageScroll
|
||||
} from '@dcloudio/uni-app';
|
||||
import { reactive, computed } from 'vue';
|
||||
import { onLoad, onPageScroll } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import ActivityApi from '@/sheep/api/promotion/activity';
|
||||
import FavoriteApi from '@/sheep/api/product/favorite';
|
||||
import {
|
||||
formatSales,
|
||||
formatGoodsSwiper,
|
||||
fen2yuan,
|
||||
handList,
|
||||
handListPrice
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import { formatSales, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import detailNavbar from './components/detail/detail-navbar.vue';
|
||||
import detailCellSku from './components/detail/detail-cell-sku.vue';
|
||||
import detailTabbar from './components/detail/detail-tabbar.vue';
|
||||
|
@ -156,22 +161,11 @@
|
|||
import detailCommentCard from './components/detail/detail-comment-card.vue';
|
||||
import detailContentCard from './components/detail/detail-content-card.vue';
|
||||
import detailActivityTip from './components/detail/detail-activity-tip.vue';
|
||||
import {
|
||||
isEmpty
|
||||
} from 'lodash-es';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
|
||||
onPageScroll(() => {
|
||||
});
|
||||
import countDown from '@/sheep/components/countDown/index.vue'
|
||||
onPageScroll(() => {});
|
||||
|
||||
const bgColor = {
|
||||
'bgColor': '#E93323',
|
||||
'Color': '#fff',
|
||||
'width': '44rpx',
|
||||
'timeTxtwidth': '16rpx',
|
||||
'isDay': true
|
||||
}
|
||||
const isLogin = computed(() => sheep.$store('user').isLogin);
|
||||
const state = reactive({
|
||||
goodsId: 0,
|
||||
|
@ -182,19 +176,13 @@
|
|||
showModel: false, // 是否展示 Coupon 优惠劵的弹窗
|
||||
couponInfo: [], // 可领取的 Coupon 优惠劵的列表
|
||||
showActivityModel: false, // 【满减送/限时折扣】是否展示 Activity 营销活动的弹窗
|
||||
activityInfo: [], // 【满减送/限时折扣】可参与的 Activity 营销活动的列表
|
||||
activityInfo: [], // 【满减送/限时折扣】可参与的 Activity 营销活动的列表 TODO 芋艿:正在接入中
|
||||
activityList: [], // 【秒杀/拼团/砍价】可参与的 Activity 营销活动的列表
|
||||
});
|
||||
|
||||
// 规格变更
|
||||
function onSkuChange(e) {
|
||||
if (e.type == 4) {
|
||||
settleData.value = e
|
||||
setShow.value = true
|
||||
} else {
|
||||
state.selectedSku = e;
|
||||
setShow.value = false
|
||||
}
|
||||
state.selectedSku = e;
|
||||
}
|
||||
|
||||
// 添加购物车
|
||||
|
@ -208,17 +196,19 @@
|
|||
|
||||
// 立即购买
|
||||
function onBuy(e) {
|
||||
if (!e.id) {
|
||||
if (!state.selectedSku.id) {
|
||||
sheep.$helper.toast('请选择商品规格');
|
||||
return;
|
||||
}
|
||||
sheep.$router.go('/pages/order/confirm', {
|
||||
data: JSON.stringify({
|
||||
items: [{
|
||||
skuId: e.id,
|
||||
count: e.goods_num,
|
||||
categoryId: state.goodsInfo.categoryId
|
||||
}]
|
||||
items: [
|
||||
{
|
||||
skuId: e.id,
|
||||
count: e.goods_num,
|
||||
categoryId: state.goodsInfo.categoryId,
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
@ -230,9 +220,7 @@
|
|||
|
||||
// 立即领取
|
||||
async function onGet(id) {
|
||||
const {
|
||||
code
|
||||
} = await CouponApi.takeCoupon(id);
|
||||
const { code } = await CouponApi.takeCoupon(id);
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -244,69 +232,35 @@
|
|||
}, 1000);
|
||||
}
|
||||
|
||||
// TODO 芋艿:待测试
|
||||
const shareInfo = computed(() => {
|
||||
if (isEmpty(state.goodsInfo)) return {};
|
||||
return sheep.$platform.share.getShareInfo({
|
||||
title: state.goodsInfo.name,
|
||||
image: sheep.$url.cdn(state.goodsInfo.picUrl),
|
||||
desc: state.goodsInfo.introduction,
|
||||
params: {
|
||||
page: '2',
|
||||
query: state.goodsInfo.id,
|
||||
return sheep.$platform.share.getShareInfo(
|
||||
{
|
||||
title: state.goodsInfo.name,
|
||||
image: sheep.$url.cdn(state.goodsInfo.picUrl),
|
||||
desc: state.goodsInfo.introduction,
|
||||
params: {
|
||||
page: '2',
|
||||
query: state.goodsInfo.id,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
type: 'goods', // 商品海报
|
||||
title: state.goodsInfo.name, // 商品名称
|
||||
image: sheep.$url.cdn(state.goodsInfo.picUrl), // 商品主图
|
||||
price: fen2yuan(state.goodsInfo.price), // 商品价格
|
||||
original_price: fen2yuan(state.goodsInfo.marketPrice), // 商品原价
|
||||
});
|
||||
{
|
||||
type: 'goods', // 商品海报
|
||||
title: state.goodsInfo.name, // 商品名称
|
||||
image: sheep.$url.cdn(state.goodsInfo.picUrl), // 商品主图
|
||||
price: fen2yuan(state.goodsInfo.price), // 商品价格
|
||||
original_price: fen2yuan(state.goodsInfo.marketPrice), // 商品原价
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
async function getCoupon() {
|
||||
const {
|
||||
code,
|
||||
data
|
||||
} = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10);
|
||||
const { code, data } = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10);
|
||||
if (code === 0) {
|
||||
state.couponInfo = data;
|
||||
}
|
||||
}
|
||||
|
||||
//获取结算信息
|
||||
const setShow = ref(false)
|
||||
const settleData = ref()
|
||||
|
||||
async function getSettlementByIds(ids) {
|
||||
const { data } = await SpuApi.getSettlementProduct(ids);
|
||||
settleData.value = handle(data)
|
||||
state.goodsInfo.skus = handListPrice(state.goodsInfo.skus, data[0].skus)
|
||||
}
|
||||
|
||||
//判断是否有限时折扣信息
|
||||
function handle(array) {
|
||||
let setList = {}
|
||||
array.some(item => {
|
||||
return item.skus.some(items => {
|
||||
if (items.type === 4) {
|
||||
setShow.value = true;
|
||||
setList = items;
|
||||
return true; // 返回true以结束some循环
|
||||
}
|
||||
return false; // 继续遍历
|
||||
});
|
||||
});
|
||||
// 将库存信息加入
|
||||
state.goodsInfo.skus.forEach(item => {
|
||||
if (item.id == setList.skuId) {
|
||||
setList.stock = item.stock
|
||||
}
|
||||
})
|
||||
|
||||
return setList
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
// 非法参数
|
||||
if (!options.id) {
|
||||
|
@ -324,6 +278,7 @@
|
|||
// 加载到商品
|
||||
state.skeletonLoading = false;
|
||||
state.goodsInfo = res.data;
|
||||
|
||||
// 加载是否收藏
|
||||
if (isLogin.value) {
|
||||
FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
|
||||
|
@ -338,24 +293,13 @@
|
|||
// 2. 加载优惠劵信息
|
||||
getCoupon();
|
||||
|
||||
// 3. 加载营销活动信息
|
||||
// 3. 获得单个商品,进行中的拼团、秒杀、砍价活动信息
|
||||
ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
|
||||
if (res.code !== 0) {
|
||||
return;
|
||||
}
|
||||
let activData = handList(res.data)
|
||||
activData.forEach(activity => {
|
||||
if ([1, 2, 3].includes(activity.type)) { // 情况一:拼团/秒杀/砍价
|
||||
state.activityList.push(activity);
|
||||
} else if (activity.type === 5) { // 情况二:满减送
|
||||
state.activityInfo.push(activity);
|
||||
} else { // 情况三:限时折扣 TODO 芋艿
|
||||
// console.log('待实现!优先级不高');
|
||||
}
|
||||
})
|
||||
state.activityList = res.data;
|
||||
});
|
||||
//获取结算信息
|
||||
getSettlementByIds(state.goodsId)
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -504,101 +448,4 @@
|
|||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
// 限时折扣
|
||||
.discount {
|
||||
width: 750rpx;
|
||||
height: 100rpx;
|
||||
// background-color: red;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.disImg {
|
||||
width: 750rpx;
|
||||
height: 100rpx;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.discountCont {
|
||||
width: 680rpx;
|
||||
height: 90rpx;
|
||||
margin: 10rpx auto 0 auto;
|
||||
// background-color: gold;
|
||||
}
|
||||
|
||||
.disContT {
|
||||
width: 680rpx;
|
||||
height: 50rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.disContT1 {
|
||||
width: 400rpx;
|
||||
height: 50rpx;
|
||||
// background-color: green;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.disContT2 {
|
||||
width: 200rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
// background-color: gold;
|
||||
font-size: 30rpx;
|
||||
text-align: end;
|
||||
color: white;
|
||||
font-weight: bolder;
|
||||
font-style: oblique 20deg;
|
||||
letter-spacing: .1rem;
|
||||
}
|
||||
|
||||
.disContT1P {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.disContT1End {
|
||||
// width: 180rpx;
|
||||
padding: 0 10rpx;
|
||||
height: 30rpx;
|
||||
line-height: 28rpx;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
background-color: white;
|
||||
color: #ff3000;
|
||||
font-size: 23rpx;
|
||||
border-radius: 20rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.disContB {
|
||||
width: 680rpx;
|
||||
height: 40rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 20rpx;
|
||||
color: white;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.disContB1 {
|
||||
width: 300rpx;
|
||||
height: 40rpx;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
|
||||
.disContB2 {
|
||||
width: 300rpx;
|
||||
height: 40rpx;
|
||||
line-height: 40rpx;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -107,6 +107,7 @@
|
|||
skuId: item.sku.id,
|
||||
count: item.count,
|
||||
cartId: item.id,
|
||||
categoryId: item.spu.categoryId
|
||||
})
|
||||
goods_list.push({
|
||||
// goods_id: item.goods_id,
|
||||
|
@ -124,12 +125,7 @@
|
|||
}
|
||||
sheep.$router.go('/pages/order/confirm', {
|
||||
data: JSON.stringify({
|
||||
// order_type: 'goods',
|
||||
// goods_list,
|
||||
items,
|
||||
// from: 'cart',
|
||||
deliveryType: 1,
|
||||
pointStatus: false,
|
||||
items
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -131,12 +131,13 @@
|
|||
getGoodsList();
|
||||
}
|
||||
|
||||
onLoad(async () => {
|
||||
onLoad(async (params) => {
|
||||
await getList();
|
||||
// 如果是 first 风格,需要加载商品分页
|
||||
if (state.style === 'first_one' || state.style === 'first_two') {
|
||||
onMenu(0);
|
||||
}
|
||||
|
||||
// 首页点击分类的处理:查找满足条件的分类
|
||||
const foundCategory = state.categoryList.find(category => category.id === params.id);
|
||||
// 如果找到则调用 onMenu 自动勾选相应分类,否则调用 onMenu(0) 勾选第一个分类
|
||||
onMenu(foundCategory ? state.categoryList.indexOf(foundCategory) : 0);
|
||||
});
|
||||
|
||||
onReachBottom(() => {
|
||||
|
|
|
@ -1,52 +1,69 @@
|
|||
<!-- 下单界面,收货地址 or 自提门店的选择组件 -->
|
||||
<template>
|
||||
<view class="allAddress" :style="state.isPickUp ? '':'padding-top:10rpx;'">
|
||||
<view class="allAddress" :style="state.isPickUp ? '' : 'padding-top:10rpx;'">
|
||||
<view class="nav flex flex-wrap">
|
||||
<view class="item font-color" :class="state.deliveryType === 1 ? 'on' : 'on2'"
|
||||
@tap="switchDeliveryType(1)" v-if='state.isPickUp' />
|
||||
<view class="item font-color" :class="state.deliveryType === 2 ? 'on' : 'on2'"
|
||||
@tap="switchDeliveryType(2)" v-if='state.isPickUp' />
|
||||
<view
|
||||
class="item font-color"
|
||||
:class="state.deliveryType === 1 ? 'on' : 'on2'"
|
||||
@tap="switchDeliveryType(1)"
|
||||
v-if="state.isPickUp"
|
||||
/>
|
||||
<view
|
||||
class="item font-color"
|
||||
:class="state.deliveryType === 2 ? 'on' : 'on2'"
|
||||
@tap="switchDeliveryType(2)"
|
||||
v-if="state.isPickUp"
|
||||
/>
|
||||
</view>
|
||||
<!-- 情况一:收货地址的选择 -->
|
||||
<view class='address flex flex-wrap flex-center ss-row-between' @tap='onSelectAddress' v-if='state.deliveryType === 1'
|
||||
:style="state.isPickUp ? '':'border-top-left-radius: 14rpx;border-top-right-radius: 14rpx;'">
|
||||
<view class='addressCon' v-if="state.addressInfo.name">
|
||||
<view class='name'>{{ state.addressInfo.name }}
|
||||
<text class='phone'>{{ state.addressInfo.mobile }}</text>
|
||||
<view
|
||||
class="address flex flex-wrap flex-center ss-row-between"
|
||||
@tap="onSelectAddress"
|
||||
v-if="state.deliveryType === 1"
|
||||
:style="state.isPickUp ? '' : 'border-top-left-radius: 14rpx;border-top-right-radius: 14rpx;'"
|
||||
>
|
||||
<view class="addressCon" v-if="state.addressInfo.name">
|
||||
<view class="name"
|
||||
>{{ state.addressInfo.name }}
|
||||
<text class="phone">{{ state.addressInfo.mobile }}</text>
|
||||
</view>
|
||||
<view class="flex flex-wrap">
|
||||
<text class='default font-color' v-if="state.addressInfo.defaultStatus">[默认]</text>
|
||||
<text class="line2">{{ state.addressInfo.areaName }} {{ state.addressInfo.detailAddress }}</text>
|
||||
<text class="default font-color" v-if="state.addressInfo.defaultStatus">[默认]</text>
|
||||
<text class="line2"
|
||||
>{{ state.addressInfo.areaName }} {{ state.addressInfo.detailAddress }}</text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
<view class='addressCon' v-else>
|
||||
<view class='setaddress'>设置收货地址</view>
|
||||
<view class="addressCon" v-else>
|
||||
<view class="setaddress">设置收货地址</view>
|
||||
</view>
|
||||
<view class='iconfont'>
|
||||
<view class="iconfont">
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 情况二:门店的选择 -->
|
||||
<view class='address flex flex-wrap flex-center ss-row-between' v-else @tap="onSelectAddress">
|
||||
<view class='addressCon' v-if="state.pickUpInfo.name">
|
||||
<view class='name'>{{ state.pickUpInfo.name }}
|
||||
<text class='phone'>{{ state.pickUpInfo.phone }}</text>
|
||||
<view class="address flex flex-wrap flex-center ss-row-between" v-else @tap="onSelectAddress">
|
||||
<view class="addressCon" v-if="state.pickUpInfo.name">
|
||||
<view class="name"
|
||||
>{{ state.pickUpInfo.name }}
|
||||
<text class="phone">{{ state.pickUpInfo.phone }}</text>
|
||||
</view>
|
||||
<view class="line1"> {{ state.pickUpInfo.areaName }}{{ ', ' + state.pickUpInfo.detailAddress }}
|
||||
<view class="line1">
|
||||
{{ state.pickUpInfo.areaName }}{{ ', ' + state.pickUpInfo.detailAddress }}
|
||||
</view>
|
||||
</view>
|
||||
<view class='addressCon' v-else>
|
||||
<view class='setaddress'>选择自提门店</view>
|
||||
<view class="addressCon" v-else>
|
||||
<view class="setaddress">选择自提门店</view>
|
||||
</view>
|
||||
<view class='iconfont'>
|
||||
<view class="iconfont">
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class='line'>
|
||||
<view class="line">
|
||||
<image :src="sheep.$url.static('/static/images/line.png', 'local')" />
|
||||
</view>
|
||||
</view>
|
||||
|
@ -61,13 +78,13 @@
|
|||
modelValue: {
|
||||
type: Object,
|
||||
default() {},
|
||||
}
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(['update:modelValue','change']);
|
||||
const emits = defineEmits(['update:modelValue']);
|
||||
|
||||
// computed 解决父子组件双向数据同步
|
||||
const state = computed({
|
||||
get(){
|
||||
get() {
|
||||
return new Proxy(props.modelValue, {
|
||||
set(obj, name, val) {
|
||||
emits('update:modelValue', {
|
||||
|
@ -75,21 +92,21 @@
|
|||
[name]: val,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
},
|
||||
set(val){
|
||||
set(val) {
|
||||
emits('update:modelValue', val);
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
// 选择地址
|
||||
function onSelectAddress() {
|
||||
let emitName = 'SELECT_ADDRESS'
|
||||
let emitName = 'SELECT_ADDRESS';
|
||||
let addressPage = '/pages/user/address/list?type=select';
|
||||
if (state.value.deliveryType === 2){
|
||||
emitName = 'SELECT_PICK_UP_INFO'
|
||||
addressPage = '/pages/user/goods_details_store/index'
|
||||
if (state.value.deliveryType === 2) {
|
||||
emitName = 'SELECT_PICK_UP_INFO';
|
||||
addressPage = '/pages/user/goods_details_store/index';
|
||||
}
|
||||
uni.$once(emitName, (e) => {
|
||||
changeConsignee(e.addressInfo);
|
||||
|
@ -100,28 +117,26 @@
|
|||
// 更改收货人地址&计算订单信息
|
||||
async function changeConsignee(addressInfo = {}) {
|
||||
if (!isEmpty(addressInfo)) {
|
||||
if (state.value.deliveryType === 1){
|
||||
if (state.value.deliveryType === 1) {
|
||||
state.value.addressInfo = addressInfo;
|
||||
}
|
||||
if (state.value.deliveryType === 2){
|
||||
if (state.value.deliveryType === 2) {
|
||||
state.value.pickUpInfo = addressInfo;
|
||||
}
|
||||
emits('change')
|
||||
}
|
||||
}
|
||||
|
||||
// 收货方式切换
|
||||
const switchDeliveryType = (type) =>{
|
||||
const switchDeliveryType = (type) => {
|
||||
state.value.deliveryType = type;
|
||||
emits('change')
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.allAddress .font-color{
|
||||
color: #E93323!important
|
||||
.allAddress .font-color {
|
||||
color: #e93323 !important;
|
||||
}
|
||||
.line2{
|
||||
.line2 {
|
||||
width: 504rpx;
|
||||
}
|
||||
.textR {
|
||||
|
@ -204,7 +219,7 @@
|
|||
.allAddress .nav .item.on::before {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
content: "快递配送";
|
||||
content: '快递配送';
|
||||
font-size: 28rpx;
|
||||
display: block;
|
||||
height: 0;
|
||||
|
@ -219,7 +234,7 @@
|
|||
}
|
||||
|
||||
.allAddress .nav .item:nth-of-type(2).on::before {
|
||||
content: "到店自提";
|
||||
content: '到店自提';
|
||||
border-width: 0 0 80rpx 20rpx;
|
||||
border-radius: 36rpx 14rpx 0 0;
|
||||
}
|
||||
|
@ -231,7 +246,7 @@
|
|||
.allAddress .nav .item.on2::before {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
content: "到店自提";
|
||||
content: '到店自提';
|
||||
font-size: 28rpx;
|
||||
display: block;
|
||||
height: 0;
|
||||
|
@ -245,7 +260,7 @@
|
|||
}
|
||||
|
||||
.allAddress .nav .item:nth-of-type(1).on2::before {
|
||||
content: "快递配送";
|
||||
content: '快递配送';
|
||||
border-width: 0 60rpx 60rpx 0;
|
||||
border-radius: 14rpx 36rpx 0 0;
|
||||
}
|
||||
|
|
|
@ -1,18 +1,30 @@
|
|||
<template>
|
||||
<s-layout title="确认订单">
|
||||
<!-- 头部地址选择【配送地址】【自提地址】 -->
|
||||
<AddressSelection v-model="addressState" @change="getOrderInfo()" />
|
||||
<AddressSelection v-model="addressState" />
|
||||
|
||||
<!-- 商品信息 -->
|
||||
<view class="order-card-box ss-m-b-14">
|
||||
<s-goods-item v-for="item in state.orderInfo.items" :key="item.skuId" :img="item.picUrl"
|
||||
:title="item.spuName" :skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price" :num="item.count" marginBottom="10" />
|
||||
<s-goods-item
|
||||
v-for="item in state.orderInfo.items"
|
||||
:key="item.skuId"
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:num="item.count"
|
||||
marginBottom="10"
|
||||
/>
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between ss-p-x-20 bg-white ss-r-10">
|
||||
<view class="item-title">订单备注</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<uni-easyinput maxlength="20" placeholder="建议留言前先与商家沟通" v-model="state.orderPayload.remark"
|
||||
:inputBorder="false" :clearable="false" />
|
||||
<uni-easyinput
|
||||
maxlength="20"
|
||||
placeholder="建议留言前先与商家沟通"
|
||||
v-model="state.orderPayload.remark"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
@ -28,71 +40,121 @@
|
|||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between" v-if="state.orderInfo.type === 0">
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.type === 0"
|
||||
>
|
||||
<view class="item-title">积分抵扣</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
{{ state.pointStatus ? '剩余积分' : '当前积分' }}
|
||||
<image :src="sheep.$url.static('/static/img/shop/goods/score1.svg')" class="score-img" />
|
||||
<image
|
||||
:src="sheep.$url.static('/static/img/shop/goods/score1.svg')"
|
||||
class="score-img"
|
||||
/>
|
||||
<text class="item-value ss-m-r-24">
|
||||
{{ state.pointStatus ? state.orderInfo.totalPoint - state.orderInfo.usePoint : (state.orderInfo.totalPoint || 0) }}
|
||||
{{
|
||||
state.pointStatus
|
||||
? state.orderInfo.totalPoint - state.orderInfo.usePoint
|
||||
: state.orderInfo.totalPoint || 0
|
||||
}}
|
||||
</text>
|
||||
<checkbox-group @change="changeIntegral">
|
||||
<checkbox :checked='state.pointStatus'
|
||||
:disabled="!state.orderInfo.totalPoint || state.orderInfo.totalPoint <= 0" />
|
||||
<checkbox
|
||||
:checked="state.pointStatus"
|
||||
:disabled="!state.orderInfo.totalPoint || state.orderInfo.totalPoint <= 0"
|
||||
/>
|
||||
</checkbox-group>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 快递配置时,信息的展示 -->
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between" v-if='addressState.deliveryType === 1'>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="addressState.deliveryType === 1"
|
||||
>
|
||||
<view class="item-title">运费</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="item-value ss-m-r-24" v-if="state.orderInfo.price.deliveryPrice > 0">
|
||||
+¥{{ fen2yuan(state.orderInfo.price.deliveryPrice) }}
|
||||
</text>
|
||||
<view class='item-value ss-m-r-24' v-else>免运费</view>
|
||||
<view class="item-value ss-m-r-24" v-else>免运费</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 门店自提时,需要填写姓名和手机号 -->
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between" v-if='addressState.deliveryType === 2'>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="addressState.deliveryType === 2"
|
||||
>
|
||||
<view class="item-title">联系人</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<uni-easyinput maxlength="20" placeholder="请填写您的联系姓名" v-model="addressState.receiverName"
|
||||
:inputBorder="false" :clearable="false" />
|
||||
<uni-easyinput
|
||||
maxlength="20"
|
||||
placeholder="请填写您的联系姓名"
|
||||
v-model="addressState.receiverName"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between" v-if='addressState.deliveryType === 2'>
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="addressState.deliveryType === 2"
|
||||
>
|
||||
<view class="item-title">联系电话</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<uni-easyinput maxlength="20" placeholder="请填写您的联系电话" v-model="addressState.receiverMobile"
|
||||
:inputBorder="false" :clearable="false" />
|
||||
<uni-easyinput
|
||||
maxlength="20"
|
||||
placeholder="请填写您的联系电话"
|
||||
v-model="addressState.receiverMobile"
|
||||
:inputBorder="false"
|
||||
:clearable="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 优惠劵:只有 type = 0 普通订单(非拼团、秒杀、砍价),才可以使用优惠劵 -->
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between" v-if="state.orderInfo.type === 0">
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.type === 0"
|
||||
>
|
||||
<view class="item-title">优惠券</view>
|
||||
<view class="ss-flex ss-col-center" @tap="state.showCoupon = true">
|
||||
<text class="item-value text-red" v-if="state.orderPayload.couponId > 0">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.couponPrice) }}
|
||||
</text>
|
||||
<text class="item-value" :class="couponNumber > 0 ? 'text-red' : 'text-disabled'" v-else>
|
||||
<text
|
||||
class="item-value"
|
||||
:class="
|
||||
state.couponInfo.filter((coupon) => coupon.match).length > 0
|
||||
? 'text-red'
|
||||
: 'text-disabled'
|
||||
"
|
||||
v-else
|
||||
>
|
||||
{{
|
||||
couponNumber > 0 ? couponNumber + ' 张可用' : '暂无可用优惠券'
|
||||
state.couponInfo.filter((coupon) => coupon.match).length > 0
|
||||
? state.couponInfo.filter((coupon) => coupon.match).length + ' 张可用'
|
||||
: '暂无可用优惠券'
|
||||
}}
|
||||
</text>
|
||||
<text class="_icon-forward item-icon" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.price.discountPrice > 0">
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.price.discountPrice > 0"
|
||||
>
|
||||
<view class="item-title">活动优惠</view>
|
||||
<view class="ss-flex ss-col-center" @tap="state.showDiscount = true">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<!-- @tap="state.showDiscount = true" TODO puhui999:【折扣】后续要把优惠信息打进去 -->
|
||||
<text class="item-value text-red">
|
||||
-¥{{ fen2yuan(state.orderInfo.price.discountPrice) }}
|
||||
</text>
|
||||
<text class="_icon-forward item-icon" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between" v-if="state.orderInfo.price.vipPrice > 0">
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderInfo.price.vipPrice > 0"
|
||||
>
|
||||
<view class="item-title">会员优惠</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<text class="item-value text-red">
|
||||
|
@ -111,11 +173,19 @@
|
|||
</view>
|
||||
|
||||
<!-- 选择优惠券弹框 -->
|
||||
<s-coupon-select v-model="state.couponInfo" :show="state.showCoupon" @confirm="onSelectCoupon"
|
||||
@close="state.showCoupon = false" />
|
||||
<s-coupon-select
|
||||
v-model="state.couponInfo"
|
||||
:show="state.showCoupon"
|
||||
@confirm="onSelectCoupon"
|
||||
@close="state.showCoupon = false"
|
||||
/>
|
||||
|
||||
<!-- 满额折扣弹框 TODO 芋艿:后续要把优惠信息打进去 -->
|
||||
<s-discount-list v-model="state.orderInfo" :show="state.showDiscount" @close="state.showDiscount = false" />
|
||||
<!-- 满额折扣弹框 TODO @puhui999:【折扣】后续要把优惠信息打进去 -->
|
||||
<s-discount-list
|
||||
v-model="state.orderInfo"
|
||||
:show="state.showDiscount"
|
||||
@close="state.showDiscount = false"
|
||||
/>
|
||||
|
||||
<!-- 底部 -->
|
||||
<su-fixed bottom :opacity="false" bg="bg-white" placeholder :noFixed="false" :index="200">
|
||||
|
@ -125,7 +195,10 @@
|
|||
¥{{ fen2yuan(state.orderInfo.price.payPrice) }}
|
||||
</view>
|
||||
</view>
|
||||
<button class="ss-reset-button ui-BG-Main-Gradient ss-r-40 submit-btn ui-Shadow-Main" @tap="onConfirm">
|
||||
<button
|
||||
class="ss-reset-button ui-BG-Main-Gradient ss-r-40 submit-btn ui-Shadow-Main"
|
||||
@tap="onConfirm"
|
||||
>
|
||||
提交订单
|
||||
</button>
|
||||
</view>
|
||||
|
@ -134,20 +207,13 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import AddressSelection from '@/pages/order/addressSelection.vue';
|
||||
import sheep from '@/sheep';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import {
|
||||
fen2yuan
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import TradeConfigApi from '@/sheep/api/trade/config';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
|
||||
const state = reactive({
|
||||
orderPayload: {},
|
||||
|
@ -164,8 +230,8 @@
|
|||
|
||||
const addressState = ref({
|
||||
addressInfo: {}, // 选择的收货地址
|
||||
deliveryType: 1, // 收货方式 1 - 快递配送;2 - 门店自提
|
||||
isPickUp: true, // 门店自提是否开启 TODO puhui999: 默认开启,看看后端有开关的话接入
|
||||
deliveryType: 1, // 收货方式:1-快递配送,2-门店自提
|
||||
isPickUp: true, // 门店自提是否开启
|
||||
pickUpInfo: {}, // 选择的自提门店信息
|
||||
receiverName: '', // 收件人名称
|
||||
receiverMobile: '', // 收件人手机
|
||||
|
@ -182,7 +248,7 @@
|
|||
|
||||
// 选择优惠券
|
||||
async function onSelectCoupon(couponId) {
|
||||
state.orderPayload.couponId = couponId || 0;
|
||||
state.orderPayload.couponId = couponId;
|
||||
await getOrderInfo();
|
||||
state.showCoupon = false;
|
||||
}
|
||||
|
@ -216,10 +282,7 @@
|
|||
|
||||
// 创建订单&跳转
|
||||
async function submitOrder() {
|
||||
const {
|
||||
code,
|
||||
data
|
||||
} = await OrderApi.createOrder({
|
||||
const { code, data } = await OrderApi.createOrder({
|
||||
items: state.orderPayload.items,
|
||||
couponId: state.orderPayload.couponId,
|
||||
remark: state.orderPayload.remark,
|
||||
|
@ -250,10 +313,7 @@
|
|||
// 检查库存 & 计算订单价格
|
||||
async function getOrderInfo() {
|
||||
// 计算价格
|
||||
const {
|
||||
data,
|
||||
code
|
||||
} = await OrderApi.settlementOrder({
|
||||
const { data, code } = await OrderApi.settlementOrder({
|
||||
items: state.orderPayload.items,
|
||||
couponId: state.orderPayload.couponId,
|
||||
deliveryType: addressState.value.deliveryType,
|
||||
|
@ -267,38 +327,16 @@
|
|||
seckillActivityId: state.orderPayload.seckillActivityId,
|
||||
});
|
||||
if (code !== 0) {
|
||||
setTimeout(() => {
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
})
|
||||
}, 1500)
|
||||
return;
|
||||
}
|
||||
state.orderInfo = data;
|
||||
state.couponInfo = data.coupons;
|
||||
// 设置收货地址
|
||||
if (state.orderInfo.address) {
|
||||
addressState.value.addressInfo = state.orderInfo.address;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取可用优惠券
|
||||
let couponNumber = ref(0)
|
||||
async function getCoupons() {
|
||||
const {
|
||||
code,
|
||||
data
|
||||
} = await CouponApi.getMatchCouponList(
|
||||
state.orderInfo.price.payPrice,
|
||||
state.orderInfo.items.map((item) => item.spuId),
|
||||
state.orderPayload.items.map((item) => item.skuId),
|
||||
state.orderPayload.items.map((item) => item.categoryId),
|
||||
);
|
||||
if (code === 0) {
|
||||
state.couponInfo = data;
|
||||
couponNumber.value = state.couponInfo.filter(item => item.match).length;
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (!options.data) {
|
||||
sheep.$helper.toast('参数不正确,请检查!');
|
||||
|
@ -306,7 +344,22 @@
|
|||
}
|
||||
state.orderPayload = JSON.parse(options.data);
|
||||
await getOrderInfo();
|
||||
await getCoupons();
|
||||
// 获取交易配置
|
||||
const { data, code } = await TradeConfigApi.getTradeConfig();
|
||||
if (code === 0) {
|
||||
addressState.value.isPickUp = data.deliveryPickUpEnabled;
|
||||
}
|
||||
});
|
||||
|
||||
// 使用 watch 监听地址和配送方式的变化
|
||||
watch(addressState, async (newAddress, oldAddress) => {
|
||||
// 如果收货地址或配送方式有变化,则重新计算价格
|
||||
if (
|
||||
newAddress.addressInfo.id !== oldAddress.addressInfo.id ||
|
||||
newAddress.deliveryType !== oldAddress.deliveryType
|
||||
) {
|
||||
await getOrderInfo();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -429,4 +482,4 @@
|
|||
font-size: 36rpx;
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -45,9 +45,9 @@
|
|||
</image>
|
||||
<view class="ss-font-30">{{ formatOrderStatus(state.orderInfo) }}</view>
|
||||
</view>
|
||||
<view class="ss-font-26 ss-m-x-20 ss-m-b-70">{{
|
||||
formatOrderStatusDescription(state.orderInfo)
|
||||
}}</view>
|
||||
<view class="ss-font-26 ss-m-x-20 ss-m-b-70">
|
||||
{{ formatOrderStatusDescription(state.orderInfo) }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 收货地址 -->
|
||||
|
@ -126,6 +126,9 @@
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 自提核销 -->
|
||||
<PickUpVerify :order-info="state.orderInfo" :systemStore="systemStore" ref="pickUpVerifyRef"></PickUpVerify>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="notice-box">
|
||||
<view class="notice-box__content">
|
||||
|
@ -167,11 +170,14 @@
|
|||
<text class="title">运费</text>
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.deliveryPrice) }}</text>
|
||||
</view>
|
||||
<!-- TODO 芋艿:优惠劵抵扣、积分抵扣 -->
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.couponPrice > 0">
|
||||
<text class="title">优惠劵金额</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.couponPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.pointPrice > 0">
|
||||
<text class="title">积分抵扣</text>
|
||||
<text class="detail">-¥{{ fen2yuan(state.orderInfo.pointPrice) }}</text>
|
||||
</view>
|
||||
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.discountPrice > 0">
|
||||
<text class="title">活动优惠</text>
|
||||
<text class="detail">¥{{ fen2yuan(state.orderInfo.discountPrice) }}</text>
|
||||
|
@ -251,7 +257,7 @@
|
|||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import {
|
||||
fen2yuan,
|
||||
|
@ -260,6 +266,8 @@
|
|||
handleOrderButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import DeliveryApi from '@/sheep/api/trade/delivery';
|
||||
import PickUpVerify from '@/pages/order/pickUpVerify.vue';
|
||||
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
|
||||
|
@ -270,6 +278,9 @@
|
|||
comeinType: '', // 进入订单详情的来源类型
|
||||
});
|
||||
|
||||
// ========== 门店自提(核销) ==========
|
||||
const systemStore = ref({}); // 门店信息
|
||||
|
||||
// 复制
|
||||
const onCopy = () => {
|
||||
sheep.$helper.copyText(state.orderInfo.no);
|
||||
|
@ -294,7 +305,7 @@
|
|||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消订单吗?',
|
||||
success: async function (res) {
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
|
@ -313,7 +324,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
// 确认收货 TODO 芋艿:待测试
|
||||
// 确认收货
|
||||
async function onConfirm(orderId, ignore = false) {
|
||||
// 需开启确认收货组件
|
||||
// todo: 芋艿:待接入微信
|
||||
|
@ -366,6 +377,7 @@
|
|||
},
|
||||
});
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// 评价
|
||||
|
@ -375,6 +387,8 @@
|
|||
});
|
||||
}
|
||||
|
||||
const pickUpVerifyRef = ref();
|
||||
|
||||
async function getOrderDetail(id) {
|
||||
// 对详情数据进行适配
|
||||
let res;
|
||||
|
@ -389,6 +403,14 @@
|
|||
if (res.code === 0) {
|
||||
state.orderInfo = res.data;
|
||||
handleOrderButtons(state.orderInfo);
|
||||
// 配送方式:门店自提
|
||||
if (res.data.pickUpStoreId) {
|
||||
const { data } = await DeliveryApi.getDeliveryPickUpStore(res.data.pickUpStoreId);
|
||||
systemStore.value = data || {};
|
||||
}
|
||||
if (state.orderInfo.deliveryType === 2 && state.orderInfo.payStatus) {
|
||||
pickUpVerifyRef.value && pickUpVerifyRef.value.markCode(res.data.pickUpVerifyCode);
|
||||
}
|
||||
} else {
|
||||
sheep.$router.back();
|
||||
}
|
||||
|
@ -429,7 +451,7 @@
|
|||
color: rgba(#fff, 0.9);
|
||||
width: 100%;
|
||||
background: v-bind(headerBg) no-repeat,
|
||||
linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
background-size: 750rpx 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</swiper>
|
||||
</uni-swiper-dot>
|
||||
<view class="log-card-msg">
|
||||
<!-- TODO 芋艿:优化点:展示状态 -->
|
||||
<!-- TODO 芋艿:【物流】优化点:展示状态 -->
|
||||
<!-- <view class="ss-flex ss-m-b-8">-->
|
||||
<!-- <view>物流状态:</view>-->
|
||||
<!-- <view class="warning-color">{{ state.info.status_text }}</view>-->
|
||||
|
@ -34,7 +34,7 @@
|
|||
<view v-if="state.tracks.length - 1 !== index" class="line" />
|
||||
</view>
|
||||
<view class="log-content-msg">
|
||||
<!-- TODO 芋艿:优化点:展示状态 -->
|
||||
<!-- TODO 芋艿:【物流】优化点:展示状态 -->
|
||||
<!-- <view class="log-msg-title ss-m-b-20">-->
|
||||
<!-- {{ item.status_text }}-->
|
||||
<!-- </view>-->
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
<template>
|
||||
<view class='order-details'>
|
||||
<!-- 自提商品核销 -->
|
||||
<view v-if="orderInfo.deliveryType === 2 && orderInfo.payStatus" class="writeOff borRadius14">
|
||||
<view class="title">核销信息</view>
|
||||
<view class="grayBg flex-center">
|
||||
<view class="pictrue">
|
||||
<image
|
||||
v-if="!!painterImageUrl"
|
||||
:src="painterImageUrl"
|
||||
:style="{width: `${state.qrcodeSize}px`, height: `${state.qrcodeSize}px`}"
|
||||
:show-menu-by-longpress="true"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="gear">
|
||||
<image :src="sheep.$url.static('/static/images/writeOff.png', 'local')"></image>
|
||||
</view>
|
||||
<view class="num">{{ orderInfo.pickUpVerifyCode }}</view>
|
||||
<view class="rules">
|
||||
<!-- TODO puhui999: 需要后端放回:使用 receiveTime 即可 -->
|
||||
<!-- <view class="item">-->
|
||||
<!-- <view class="rulesTitle flex flex-wrap align-center">-->
|
||||
<!-- 核销时间-->
|
||||
<!-- </view>-->
|
||||
<!-- <view class="info">-->
|
||||
<!-- 每日:-->
|
||||
<!-- <text class="time">2020-2-+52</text>-->
|
||||
<!-- </view>-->
|
||||
<!-- </view>-->
|
||||
<view class="item">
|
||||
<view class="rulesTitle flex flex-wrap align-center">
|
||||
<text class="iconfont icon-shuoming1"></text>
|
||||
使用说明
|
||||
</view>
|
||||
<view class="info">可将二维码出示给店员扫描或提供数字核销码</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="orderInfo.deliveryType === 2" class="map flex flex-wrap align-center ss-row-between borRadius14">
|
||||
<view>自提地址信息</view>
|
||||
<view class="place cart-color flex flex-wrap flex-center" @tap="showMaoLocation">
|
||||
查看位置
|
||||
</view>
|
||||
</view>
|
||||
<!-- 海报画板:默认隐藏只用来生成海报。生成方式为主动调用 -->
|
||||
<l-painter
|
||||
v-if="showPainter"
|
||||
isCanvasToTempFilePath
|
||||
pathType="url"
|
||||
@success="setPainterImageUrl"
|
||||
hidden
|
||||
ref="painterRef"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
orderInfo: {
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
systemStore:{
|
||||
type: Object,
|
||||
default() {},
|
||||
}
|
||||
});
|
||||
const state = reactive({
|
||||
qrcodeSize: 145
|
||||
})
|
||||
|
||||
/**
|
||||
* 打开地图
|
||||
*/
|
||||
const showMaoLocation = () => {
|
||||
console.log(props.systemStore);
|
||||
if (!props.systemStore.latitude || !props.systemStore.longitude) {
|
||||
sheep.$helper.toast('缺少经纬度信息无法查看地图!');
|
||||
return
|
||||
}
|
||||
uni.openLocation({
|
||||
latitude: props.systemStore.latitude,
|
||||
longitude: props.systemStore.longitude,
|
||||
scale: 8,
|
||||
name: props.systemStore.name,
|
||||
address: props.systemStore.areaName + props.systemStore.detailAddress,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 拨打电话
|
||||
*/
|
||||
const makePhone = () => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: props.systemStore.phone
|
||||
})
|
||||
}
|
||||
|
||||
const painterRef = ref(); // 海报画板
|
||||
const painterImageUrl = ref(); // 海报 url
|
||||
const showPainter = ref(true)
|
||||
// 渲染海报
|
||||
const renderPoster = async (poster) => {
|
||||
await painterRef.value.render(poster);
|
||||
};
|
||||
// 获得生成的图片
|
||||
const setPainterImageUrl = (path) => {
|
||||
painterImageUrl.value = path;
|
||||
showPainter.value = false
|
||||
};
|
||||
/**
|
||||
* 生成核销二维码
|
||||
*/
|
||||
const markCode = (text) => {
|
||||
renderPoster({
|
||||
css: {
|
||||
width: `${state.qrcodeSize}px`,
|
||||
height: `${state.qrcodeSize}px`
|
||||
},
|
||||
views:[
|
||||
{
|
||||
type: 'qrcode',
|
||||
text: text,
|
||||
css: {
|
||||
width: `${state.qrcodeSize}px`,
|
||||
height: `${state.qrcodeSize}px`
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
defineExpose({
|
||||
markCode
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
// TODO puhui999: 样式需要调整有 bug
|
||||
.borRadius14 {
|
||||
border-radius: 14rpx !important;
|
||||
}
|
||||
.cart-color {
|
||||
color: #E93323 !important;
|
||||
border: 1px solid #E93323 !important
|
||||
}
|
||||
.order-details{
|
||||
border-radius: 10rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
}
|
||||
.order-details .writeOff {
|
||||
background-color: #fff;
|
||||
margin-top: 15rpx;
|
||||
padding-bottom: 50rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .title {
|
||||
font-size: 30rpx;
|
||||
color: #282828;
|
||||
height: 87rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
padding: 0 24rpx;
|
||||
line-height: 87rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .grayBg {
|
||||
background-color: #f2f5f7;
|
||||
width: 590rpx;
|
||||
height: 384rpx;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
margin: 50rpx auto 0 auto;
|
||||
padding-top: 55rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .grayBg .pictrue {
|
||||
width: 290rpx;
|
||||
height: 290rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .grayBg .pictrue image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.order-details .writeOff .gear {
|
||||
width: 590rpx;
|
||||
height: 30rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.order-details .writeOff .gear image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.order-details .writeOff .num {
|
||||
background-color: #f0c34c;
|
||||
width: 590rpx;
|
||||
height: 84rpx;
|
||||
color: #282828;
|
||||
font-size: 48rpx;
|
||||
margin: 0 auto;
|
||||
border-radius: 0 0 20rpx 20rpx;
|
||||
text-align: center;
|
||||
padding-top: 4rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules {
|
||||
margin: 46rpx 30rpx 0 30rpx;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
padding-top: 10rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item .rulesTitle {
|
||||
font-size: 28rpx;
|
||||
color: #282828;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item .rulesTitle .iconfont {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
margin-right: 8rpx;
|
||||
margin-top: 5rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item .info {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
margin-top: 7rpx;
|
||||
}
|
||||
|
||||
.order-details .writeOff .rules .item .info .time {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.order-details .map {
|
||||
height: 86rpx;
|
||||
font-size: 30rpx;
|
||||
color: #282828;
|
||||
line-height: 86rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
margin-top: 15rpx;
|
||||
background-color: #fff;
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
|
||||
.order-details .map .place {
|
||||
font-size: 26rpx;
|
||||
width: 176rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
line-height: 50rpx;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
|
@ -174,6 +174,12 @@
|
|||
return
|
||||
}
|
||||
state.payMethods = getPayMethods(data)
|
||||
state.payMethods.find(item => {
|
||||
if (item.value && !item.disabled) {
|
||||
state.payment = item.value;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
<button class="check-btn ss-reset-button" v-if="payResult === 'success'" @tap="onOrder">
|
||||
查看订单
|
||||
</button>
|
||||
<!-- TODO 芋艿:拼团接入 -->
|
||||
<button
|
||||
class="check-btn ss-reset-button"
|
||||
v-if="payResult === 'success' && state.tradeOrder.type === 3"
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
}
|
||||
}
|
||||
onLoad(() => {
|
||||
// TODO 芋艿:目前简单做,使用营销文章,作为 faq
|
||||
// TODO 芋艿:【文章】目前简单做,使用营销文章,作为 faq
|
||||
if (true) {
|
||||
sheep.$router.go('/pages/public/richtext', {
|
||||
title: '常见问题',
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, onBeforeMount } from 'vue';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
import { onBeforeMount, reactive } from 'vue';
|
||||
import { onShow, onLoad } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import AreaApi from '@/sheep/api/system/area';
|
||||
|
@ -49,10 +49,14 @@
|
|||
const state = reactive({
|
||||
list: [], // 地址列表
|
||||
loading: true,
|
||||
openType: '', // 页面打开类型
|
||||
});
|
||||
|
||||
// 选择收货地址
|
||||
const onSelect = (addressInfo) => {
|
||||
if (state.openType !== 'select'){ // 不作为选择组件时阻断操作
|
||||
return
|
||||
}
|
||||
uni.$emit('SELECT_ADDRESS', {
|
||||
addressInfo,
|
||||
});
|
||||
|
@ -60,7 +64,6 @@
|
|||
};
|
||||
|
||||
// 导入微信地址
|
||||
// TODO 芋艿:未测试
|
||||
function importWechatAddress() {
|
||||
let wechatAddress = {};
|
||||
// #ifdef MP
|
||||
|
@ -110,6 +113,12 @@
|
|||
// #endif
|
||||
}
|
||||
|
||||
onLoad((option) => {
|
||||
if (option.type) {
|
||||
state.openType = option.type;
|
||||
}
|
||||
});
|
||||
|
||||
onShow(async () => {
|
||||
state.list = (await AddressApi.getAddressList()).data;
|
||||
state.loading = false;
|
||||
|
|
|
@ -0,0 +1,282 @@
|
|||
<template>
|
||||
<s-layout title="选择自提门店" :bgStyle="{ color: '#FFF' }">
|
||||
<view class="storeBox" ref="container">
|
||||
<view
|
||||
class="storeBox-box"
|
||||
v-for="(item, index) in state.storeList"
|
||||
:key="index"
|
||||
@tap="checked(item)"
|
||||
>
|
||||
<view class="store-img">
|
||||
<image :src="item.logo" class="img" />
|
||||
</view>
|
||||
<view class="store-cent-left">
|
||||
<view class="store-name">{{ item.name }}</view>
|
||||
<view class="store-address line1">
|
||||
{{ item.areaName }}{{ ', ' + item.detailAddress }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="row-right ss-flex-col ss-col-center">
|
||||
<view>
|
||||
<!-- #ifdef H5 -->
|
||||
<a class="store-phone" :href="'tel:' + item.phone">
|
||||
<view class="iconfont">
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
</a>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP -->
|
||||
<view class="store-phone" @click="call(item.phone)">
|
||||
<view class="iconfont">
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<view class="store-distance ss-flex ss-row-center" @tap.stop="showMaoLocation(item)">
|
||||
<text class="addressTxt" v-if="item.distance">
|
||||
距离{{ item.distance.toFixed(2) }}千米
|
||||
</text>
|
||||
<text class="addressTxt" v-else>查看地图</text>
|
||||
<view class="iconfont">
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import DeliveryApi from '@/sheep/api/trade/delivery';
|
||||
import { onMounted, reactive } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
|
||||
const LONGITUDE = 'user_longitude';
|
||||
const LATITUDE = 'user_latitude';
|
||||
const state = reactive({
|
||||
loaded: false,
|
||||
loading: false,
|
||||
storeList: [],
|
||||
system_store: {},
|
||||
locationShow: false,
|
||||
user_latitude: 0,
|
||||
user_longitude: 0,
|
||||
});
|
||||
|
||||
const call = (phone) => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: phone,
|
||||
});
|
||||
};
|
||||
const selfLocation = () => {
|
||||
// #ifdef H5
|
||||
const jsWxSdk = sheep.$platform.useProvider('wechat').jsWxSdk;
|
||||
if (jsWxSdk.isWechat()) {
|
||||
jsWxSdk.getLocation((res) => {
|
||||
state.user_latitude = res.latitude;
|
||||
state.user_longitude = res.longitude;
|
||||
uni.setStorageSync(LATITUDE, res.latitude);
|
||||
uni.setStorageSync(LONGITUDE, res.longitude);
|
||||
getList();
|
||||
});
|
||||
} else {
|
||||
// #endif
|
||||
uni.getLocation({
|
||||
type: 'gcj02',
|
||||
success: (res) => {
|
||||
try {
|
||||
state.user_latitude = res.latitude;
|
||||
state.user_longitude = res.longitude;
|
||||
uni.setStorageSync(LATITUDE, res.latitude);
|
||||
uni.setStorageSync(LONGITUDE, res.longitude);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
getList();
|
||||
},
|
||||
complete: () => {
|
||||
getList();
|
||||
},
|
||||
});
|
||||
// #ifdef H5
|
||||
}
|
||||
// #endif
|
||||
};
|
||||
const showMaoLocation = (e) => {
|
||||
// #ifdef H5
|
||||
const jsWxSdk = sheep.$platform.useProvider('wechat').jsWxSdk;
|
||||
if (jsWxSdk.isWechat()) {
|
||||
jsWxSdk.openLocation({
|
||||
latitude: Number(e.latitude),
|
||||
longitude: Number(e.longitude),
|
||||
name: e.name,
|
||||
address: `${e.areaName}-${e.detailAddress}`,
|
||||
});
|
||||
} else {
|
||||
// #endif
|
||||
uni.openLocation({
|
||||
latitude: Number(e.latitude),
|
||||
longitude: Number(e.longitude),
|
||||
name: e.name,
|
||||
address: `${e.areaName}-${e.detailAddress}`,
|
||||
success: function () {
|
||||
console.log('success');
|
||||
},
|
||||
});
|
||||
// #ifdef H5
|
||||
}
|
||||
// #endif
|
||||
};
|
||||
|
||||
/**
|
||||
* 选中门店
|
||||
*/
|
||||
const checked = (addressInfo) => {
|
||||
uni.$emit('SELECT_PICK_UP_INFO', {
|
||||
addressInfo,
|
||||
});
|
||||
sheep.$router.back();
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取门店列表数据
|
||||
*/
|
||||
const getList = async () => {
|
||||
if (state.loading || state.loaded) {
|
||||
return;
|
||||
}
|
||||
state.loading = true;
|
||||
const { data, code } = await DeliveryApi.getDeliveryPickUpStoreList({
|
||||
latitude: state.user_latitude,
|
||||
longitude: state.user_longitude,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.loading = false;
|
||||
state.storeList = data;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (state.user_latitude && state.user_longitude) {
|
||||
getList();
|
||||
} else {
|
||||
selfLocation();
|
||||
getList();
|
||||
}
|
||||
});
|
||||
onLoad(() => {
|
||||
try {
|
||||
state.user_latitude = uni.getStorageSync(LATITUDE);
|
||||
state.user_longitude = uni.getStorageSync(LONGITUDE);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.line1 {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.geoPage {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.storeBox {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.storeBox-box {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 23rpx 0;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.store-cent {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.store-cent-left {
|
||||
//width: 45%;
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.store-img {
|
||||
flex: 1;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 6rpx;
|
||||
margin-right: 22rpx;
|
||||
}
|
||||
|
||||
.store-img .img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.store-name {
|
||||
color: #282828;
|
||||
font-size: 30rpx;
|
||||
margin-bottom: 22rpx;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.store-address {
|
||||
color: #666666;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.store-phone {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
text-align: center;
|
||||
line-height: 48rpx;
|
||||
background-color: #e83323;
|
||||
margin-bottom: 22rpx;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.store-distance {
|
||||
font-size: 22rpx;
|
||||
color: #e83323;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-size: 20rpx;
|
||||
}
|
||||
|
||||
.row-right {
|
||||
flex: 2;
|
||||
//display: flex;
|
||||
//flex-direction: column;
|
||||
//align-items: flex-end;
|
||||
//width: 33.5%;
|
||||
}
|
||||
</style>
|
|
@ -36,7 +36,7 @@
|
|||
</button>
|
||||
</uni-datetime-picker>
|
||||
|
||||
<!-- TODO 芋艿:优化 -->
|
||||
<!-- TODO 芋艿:【钱包】可优化 -->
|
||||
<!-- <view class="total-box">-->
|
||||
<!-- <view class="ss-m-b-10">总收入¥{{ state.pagination.income }}</view>-->
|
||||
<!-- <view>总支出¥{{ -state.pagination.expense }}</view>-->
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
import request from '@/sheep/request';
|
||||
|
||||
// TODO 芋艿:暂不支持 socket 聊天
|
||||
export default {
|
||||
// 获取聊天token
|
||||
unifiedToken: () =>
|
||||
request({
|
||||
url: 'unifiedToken',
|
||||
custom: {
|
||||
showError: false,
|
||||
showLoading: false,
|
||||
},
|
||||
}),
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
import request from '@/sheep/request';
|
||||
|
||||
const ActivityApi = {
|
||||
// 获得单个商品,近期参与的每个活动
|
||||
// 获得单个商品,进行中的拼团、秒杀、砍价活动信息
|
||||
getActivityListBySpuId: (spuId) => {
|
||||
return request({
|
||||
url: '/promotion/activity/list-by-spu-id',
|
||||
|
|
|
@ -2,15 +2,6 @@ import request from '@/sheep/request';
|
|||
|
||||
// 拼团 API
|
||||
const CombinationApi = {
|
||||
// 获得拼团活动列表
|
||||
getCombinationActivityList: (count) => {
|
||||
return request({
|
||||
url: '/promotion/combination-activity/list',
|
||||
method: 'GET',
|
||||
params: { count },
|
||||
});
|
||||
},
|
||||
|
||||
// 获得拼团活动分页
|
||||
getCombinationActivityPage: (params) => {
|
||||
return request({
|
||||
|
@ -31,6 +22,17 @@ const CombinationApi = {
|
|||
});
|
||||
},
|
||||
|
||||
// 获得拼团活动列表,基于活动编号数组
|
||||
getCombinationActivityListByIds: (ids) => {
|
||||
return request({
|
||||
url: '/promotion/combination-activity/list-by-ids',
|
||||
method: 'GET',
|
||||
params: {
|
||||
ids,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 获得最近 n 条拼团记录(团长发起的)
|
||||
getHeadCombinationRecordList: (activityId, status, count) => {
|
||||
return request({
|
||||
|
@ -47,9 +49,9 @@ const CombinationApi = {
|
|||
// 获得我的拼团记录分页
|
||||
getCombinationRecordPage: (params) => {
|
||||
return request({
|
||||
url: "/promotion/combination-record/page",
|
||||
url: '/promotion/combination-record/page',
|
||||
method: 'GET',
|
||||
params
|
||||
params,
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -79,23 +79,6 @@ const CouponApi = {
|
|||
},
|
||||
});
|
||||
},
|
||||
// 获得匹配指定商品的优惠劵列表
|
||||
getMatchCouponList: (price, spuIds, skuIds, categoryIds) => {
|
||||
return request({
|
||||
url: '/promotion/coupon/match-list',
|
||||
method: 'GET',
|
||||
params: {
|
||||
price,
|
||||
spuIds: spuIds.join(','),
|
||||
skuIds: skuIds.join(','),
|
||||
categoryIds: categoryIds.join(','),
|
||||
},
|
||||
custom: {
|
||||
showError: false,
|
||||
showLoading: false, // 避免影响 settlementOrder 结算的结果
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default CouponApi;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import request from "@/sheep/request";
|
||||
import request from '@/sheep/request';
|
||||
|
||||
const SeckillApi = {
|
||||
// 获得秒杀时间段列表
|
||||
|
@ -16,6 +16,17 @@ const SeckillApi = {
|
|||
return request({ url: 'promotion/seckill-activity/page', method: 'GET', params });
|
||||
},
|
||||
|
||||
// 获得秒杀活动列表,基于活动编号数组
|
||||
getSeckillActivityListByIds: (ids) => {
|
||||
return request({
|
||||
url: '/promotion/seckill-activity/list-by-ids',
|
||||
method: 'GET',
|
||||
params: {
|
||||
ids,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 获得秒杀活动明细
|
||||
* @param {number} id 秒杀活动编号
|
||||
|
@ -25,9 +36,9 @@ const SeckillApi = {
|
|||
return request({
|
||||
url: 'promotion/seckill-activity/get-detail',
|
||||
method: 'GET',
|
||||
params: { id }
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default SeckillApi;
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import request from '@/sheep/request';
|
||||
|
||||
const DictApi = {
|
||||
// 根据字典类型查询字典数据信息
|
||||
getDictDataListByType: (type) => {
|
||||
return request({
|
||||
url: `/system/dict-data/type`,
|
||||
method: 'GET',
|
||||
params: {
|
||||
type,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default DictApi;
|
|
@ -7,7 +7,25 @@ const DeliveryApi = {
|
|||
url: `/trade/delivery/express/list`,
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
},
|
||||
// 获得自提门店列表
|
||||
getDeliveryPickUpStoreList: (params) => {
|
||||
return request({
|
||||
url: `/trade/delivery/pick-up-store/list`,
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
},
|
||||
// 获得自提门店
|
||||
getDeliveryPickUpStore: (id) => {
|
||||
return request({
|
||||
url: `/trade/delivery/pick-up-store/get`,
|
||||
method: 'GET',
|
||||
params: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default DeliveryApi;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import request from '@/sheep/request';
|
||||
import { isEmpty } from '@/sheep/helper/utils';
|
||||
|
||||
const OrderApi = {
|
||||
// 计算订单信息
|
||||
|
@ -13,6 +14,15 @@ const OrderApi = {
|
|||
if (!(data.addressId > 0)) {
|
||||
delete data2.addressId;
|
||||
}
|
||||
if (!(data.pickUpStoreId > 0)) {
|
||||
delete data2.pickUpStoreId;
|
||||
}
|
||||
if (isEmpty(data.receiverName)) {
|
||||
delete data2.receiverName;
|
||||
}
|
||||
if (isEmpty(data.receiverMobile)) {
|
||||
delete data2.receiverMobile;
|
||||
}
|
||||
if (!(data.combinationActivityId > 0)) {
|
||||
delete data2.combinationActivityId;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
/>
|
||||
|
||||
<!-- 2. 短信登录 smsLogin -->
|
||||
<sms-login v-if="authType === 'smsLogin'" :agreeStatus="state.protocol" @onConfirm="onConfirm" />
|
||||
<sms-login
|
||||
v-if="authType === 'smsLogin'"
|
||||
:agreeStatus="state.protocol"
|
||||
@onConfirm="onConfirm"
|
||||
/>
|
||||
|
||||
<!-- 3. 忘记密码 resetPassword-->
|
||||
<reset-password v-if="authType === 'resetPassword'" />
|
||||
|
@ -32,7 +36,11 @@
|
|||
<!-- 7.1 微信小程序的快捷登录 -->
|
||||
<view v-if="sheep.$platform.name === 'WechatMiniProgram'" class="ss-flex register-box">
|
||||
<view class="register-title">还没有账号?</view>
|
||||
<button class="ss-reset-button login-btn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">
|
||||
<button
|
||||
class="ss-reset-button login-btn"
|
||||
open-type="getPhoneNumber"
|
||||
@getphonenumber="getPhoneNumber"
|
||||
>
|
||||
快捷登录
|
||||
</button>
|
||||
<view class="circle" />
|
||||
|
@ -81,17 +89,13 @@
|
|||
/>
|
||||
<view class="agreement-text ss-flex ss-col-center ss-m-l-8">
|
||||
我已阅读并遵守
|
||||
<view class="tcp-text" @tap.stop="onProtocol('用户协议')">
|
||||
《用户协议》
|
||||
</view>
|
||||
<view class="tcp-text" @tap.stop="onProtocol('用户协议')"> 《用户协议》 </view>
|
||||
<view class="agreement-text">与</view>
|
||||
<view class="tcp-text" @tap.stop="onProtocol('隐私协议')">
|
||||
《隐私协议》
|
||||
</view>
|
||||
<view class="tcp-text" @tap.stop="onProtocol('隐私协议')"> 《隐私协议》 </view>
|
||||
</view>
|
||||
</label>
|
||||
</view>
|
||||
<view class="safe-box"/>
|
||||
<view class="safe-box" />
|
||||
</view>
|
||||
</su-popup>
|
||||
</template>
|
||||
|
@ -107,8 +111,6 @@
|
|||
import mpAuthorization from './components/mp-authorization.vue';
|
||||
import { closeAuthModal, showAuthModal } from '@/sheep/hooks/useModal';
|
||||
|
||||
const appInfo = computed(() => sheep.$store('app').info);
|
||||
|
||||
const modalStore = sheep.$store('modal');
|
||||
// 授权弹窗类型
|
||||
const authType = computed(() => modalStore.auth);
|
||||
|
@ -152,7 +154,13 @@
|
|||
}
|
||||
const loginRes = await sheep.$platform.useProvider(provider).login();
|
||||
if (loginRes) {
|
||||
const userInfo = await sheep.$store('user').getInfo();
|
||||
closeAuthModal();
|
||||
// 如果用户已经有头像和昵称,不需要再次授权
|
||||
if (userInfo.avatar && userInfo.nickname) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 触发小程序授权信息弹框
|
||||
// #ifdef MP-WEIXIN
|
||||
showAuthModal('mpAuthorization');
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<!-- 基础组件:列表导航 -->
|
||||
<s-menu-list v-if="type === 'MenuList'" :data="data" />
|
||||
<!-- 基础组件:宫格导航 -->
|
||||
<s-menu-grid v-if="type === 'MenuGrid'" :data="data" />
|
||||
<s-menu-grid v-if="type === 'MenuGrid'" :data="data" :styles="styles" />
|
||||
<!-- 基础组件:弹窗广告 -->
|
||||
<s-popup-image v-if="type === 'Popover'" :data="data" />
|
||||
<!-- 基础组件:悬浮按钮 -->
|
||||
|
@ -47,13 +47,13 @@
|
|||
<s-richtext-block v-if="type === 'PromotionArticle'" :data="data" :styles="styles" />
|
||||
|
||||
<!-- 用户组件:用户卡片 -->
|
||||
<s-user-card v-if="type === 'UserCard'" />
|
||||
<s-user-card v-if="type === 'UserCard'" :data="data" :styles="styles" />
|
||||
<!-- 用户组件:用户订单 -->
|
||||
<s-order-card v-if="type === 'UserOrder'" :data="data" />
|
||||
<s-order-card v-if="type === 'UserOrder'" :data="data" :styles="styles" />
|
||||
<!-- 用户组件:用户资产 -->
|
||||
<s-wallet-card v-if="type === 'UserWallet'" />
|
||||
<s-wallet-card v-if="type === 'UserWallet'" :data="data" :styles="styles" />
|
||||
<!-- 用户组件:用户卡券 -->
|
||||
<s-coupon-card v-if="type === 'UserCoupon'" />
|
||||
<s-coupon-card v-if="type === 'UserCoupon'" :data="data" :styles="styles" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,152 +1,176 @@
|
|||
<!-- 装修营销组件:优惠券 -->
|
||||
<template>
|
||||
<scroll-view class="scroll-box" scroll-x scroll-anchoring>
|
||||
<view class="coupon-box ss-flex">
|
||||
<view
|
||||
class="coupon-item"
|
||||
:style="[couponBg, { marginLeft: `${data.space}px` }]"
|
||||
v-for="(item, index) in couponList"
|
||||
:key="index"
|
||||
>
|
||||
<su-coupon
|
||||
:size="SIZE_LIST[columns - 1]"
|
||||
:textColor="data.textColor"
|
||||
background=""
|
||||
:couponId="item.id"
|
||||
:title="item.name"
|
||||
:type="formatCouponDiscountType(item)"
|
||||
:value="formatCouponDiscountValue(item)"
|
||||
:sellBy="formatValidityType(item)"
|
||||
>
|
||||
<template v-slot:btn>
|
||||
<!-- 两列时,领取按钮坚排 -->
|
||||
<button
|
||||
v-if="columns === 2"
|
||||
@click.stop="onGetCoupon(item.id)"
|
||||
class="ss-reset-button card-btn vertical"
|
||||
:style="[btnStyles]"
|
||||
>
|
||||
<view class="btn-text">立即领取</view>
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
class="ss-reset-button card-btn"
|
||||
:style="[btnStyles]"
|
||||
@click.stop="onGetCoupon(item.id)"
|
||||
>
|
||||
立即领取
|
||||
</button>
|
||||
</template>
|
||||
</su-coupon>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<scroll-view class="scroll-box" scroll-x scroll-anchoring :style="[bgStyle, { marginLeft: `${data.space}px` }]">
|
||||
<view class="coupon-box ss-flex" :style="couponList.length === 2 ? couponBoxStyleTwo : couponBoxStyleNormal">
|
||||
<view class="coupon-item" :style="[couponBg, { marginLeft: `${data.space}px` }]"
|
||||
v-for="(item, index) in couponList" :key="index">
|
||||
<su-coupon :size="SIZE_LIST[columns - 1]" :textColor="data.textColor" background="" :couponId="item.id"
|
||||
:title="item.name" :type="formatCouponDiscountType(item)" :value="formatCouponDiscountValue(item)"
|
||||
:sellBy="formatValidityType(item)">
|
||||
<template v-slot:btn>
|
||||
<!-- 两列时,领取按钮坚排 -->
|
||||
<button v-if="columns === 2" @click.stop="onGetCoupon(item.id)"
|
||||
class="ss-reset-button card-btn vertical" :style="[btnStyles]">
|
||||
<view class="btn-text">立即领取</view>
|
||||
</button>
|
||||
<button v-else class="ss-reset-button card-btn" :style="[btnStyles]"
|
||||
@click.stop="onGetCoupon(item.id)">
|
||||
立即领取
|
||||
</button>
|
||||
</template>
|
||||
</su-coupon>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { CouponTemplateValidityTypeEnum, PromotionDiscountTypeEnum } from "@/sheep/util/const";
|
||||
import { floatToFixed2, formatDate } from "@/sheep/util";
|
||||
import sheep from '@/sheep';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import {
|
||||
ref,
|
||||
onMounted,
|
||||
computed
|
||||
} from 'vue';
|
||||
import {
|
||||
CouponTemplateValidityTypeEnum,
|
||||
PromotionDiscountTypeEnum
|
||||
} from "@/sheep/util/const";
|
||||
import {
|
||||
floatToFixed2,
|
||||
formatDate
|
||||
} from "@/sheep/util";
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
const { columns, button } = props.data;
|
||||
const SIZE_LIST = ['lg', 'md', 'xs']
|
||||
const couponBg = {
|
||||
background: `url(${sheep.$url.cdn(props.data.bgImg)}) no-repeat top center / 100% 100%`,
|
||||
};
|
||||
const btnStyles = {
|
||||
background: button.bgColor,
|
||||
color: button.color,
|
||||
};
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
const {
|
||||
columns,
|
||||
button
|
||||
} = props.data;
|
||||
const SIZE_LIST = ['lg', 'md', 'xs']
|
||||
const couponBg = {
|
||||
background: `url(${sheep.$url.cdn(props.data.bgImg)}) no-repeat top center / 100% 100%`,
|
||||
};
|
||||
const btnStyles = {
|
||||
background: button.bgColor,
|
||||
color: button.color,
|
||||
};
|
||||
// 两列优惠券时的排版方式
|
||||
const couponBoxStyleNormal = {
|
||||
'display': 'flex',
|
||||
'justify-content': 'space-between'
|
||||
};
|
||||
// 非两列优惠券时的排版方式
|
||||
const couponBoxStyleTwo = {
|
||||
'display': 'flex',
|
||||
'justify-content': 'space-around'
|
||||
};
|
||||
// 设置背景样式
|
||||
const bgStyle = computed(() => {
|
||||
// 直接从 props.styles 解构
|
||||
const {
|
||||
bgType,
|
||||
bgImg,
|
||||
bgColor
|
||||
} = props.styles;
|
||||
|
||||
// 格式化【折扣类型】
|
||||
const formatCouponDiscountType = (coupon) => {
|
||||
if(coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
|
||||
return 'reduce'
|
||||
}
|
||||
if(coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
|
||||
return 'percent'
|
||||
}
|
||||
return `未知【${coupon.discountType}】`
|
||||
}
|
||||
// 根据 bgType 返回相应的样式
|
||||
return {
|
||||
background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
|
||||
};
|
||||
});
|
||||
// 格式化【折扣类型】
|
||||
const formatCouponDiscountType = (coupon) => {
|
||||
if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
|
||||
return 'reduce'
|
||||
}
|
||||
if (coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
|
||||
return 'percent'
|
||||
}
|
||||
return `未知【${coupon.discountType}】`
|
||||
}
|
||||
|
||||
// 格式化【折扣】
|
||||
const formatCouponDiscountValue = (coupon) => {
|
||||
if(coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
|
||||
return floatToFixed2(coupon.discountPrice)
|
||||
}
|
||||
if(coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
|
||||
return coupon.discountPercent
|
||||
}
|
||||
return `未知【${coupon.discountType}】`
|
||||
}
|
||||
// 格式化【折扣】
|
||||
const formatCouponDiscountValue = (coupon) => {
|
||||
if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
|
||||
return floatToFixed2(coupon.discountPrice)
|
||||
}
|
||||
if (coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
|
||||
return coupon.discountPercent
|
||||
}
|
||||
return `未知【${coupon.discountType}】`
|
||||
}
|
||||
|
||||
// 格式化【有效期限】
|
||||
const formatValidityType = (row) => {
|
||||
if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) {
|
||||
return `${formatDate(row.validStartTime)} 至 ${formatDate(row.validEndTime)}`
|
||||
}
|
||||
if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) {
|
||||
return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`
|
||||
}
|
||||
return '未知【' + row.validityType + '】'
|
||||
}
|
||||
// 格式化【有效期限】
|
||||
const formatValidityType = (row) => {
|
||||
if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) {
|
||||
return `${formatDate(row.validStartTime)} 至 ${formatDate(row.validEndTime)}`
|
||||
}
|
||||
if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) {
|
||||
return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`
|
||||
}
|
||||
return '未知【' + row.validityType + '】'
|
||||
}
|
||||
|
||||
const couponList = ref([]);
|
||||
// 立即领取优惠券
|
||||
async function onGetCoupon(id) {
|
||||
const { error, msg } = await CouponApi.takeCoupon(id);
|
||||
if (error === 0) {
|
||||
uni.showToast({
|
||||
title: msg,
|
||||
icon: 'none',
|
||||
});
|
||||
return
|
||||
}
|
||||
await getCouponTemplateList()
|
||||
}
|
||||
const getCouponTemplateList = async () => {
|
||||
const { data } = await CouponApi.getCouponTemplateListByIds(props.data.couponIds.join(','));
|
||||
couponList.value = data;
|
||||
}
|
||||
onMounted(() => {
|
||||
getCouponTemplateList()
|
||||
});
|
||||
const couponList = ref([]);
|
||||
// 立即领取优惠券
|
||||
async function onGetCoupon(id) {
|
||||
const {
|
||||
error,
|
||||
msg
|
||||
} = await CouponApi.takeCoupon(id);
|
||||
if (error === 0) {
|
||||
uni.showToast({
|
||||
title: msg,
|
||||
icon: 'none',
|
||||
});
|
||||
return
|
||||
}
|
||||
await getCouponTemplateList()
|
||||
}
|
||||
const getCouponTemplateList = async () => {
|
||||
const {
|
||||
data
|
||||
} = await CouponApi.getCouponTemplateListByIds(props.data.couponIds.join(','));
|
||||
couponList.value = data;
|
||||
}
|
||||
onMounted(() => {
|
||||
getCouponTemplateList()
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-btn {
|
||||
width: 140rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 50rpx;
|
||||
&.vertical {
|
||||
width: 50rpx;
|
||||
height: 140rpx;
|
||||
margin: auto 20rpx auto 0;
|
||||
.card-btn {
|
||||
width: 140rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 50rpx;
|
||||
|
||||
.btn-text {
|
||||
font-size: 24rpx;
|
||||
text-align: center;
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
}
|
||||
}
|
||||
.coupon-item {
|
||||
&:nth-of-type(1) {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
&.vertical {
|
||||
width: 50rpx;
|
||||
height: 140rpx;
|
||||
margin: auto 20rpx auto 0;
|
||||
|
||||
.btn-text {
|
||||
font-size: 24rpx;
|
||||
text-align: center;
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.coupon-item {
|
||||
&:nth-of-type(1) {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,6 +1,6 @@
|
|||
<!-- 装修用户组件:用户卡券 -->
|
||||
<template>
|
||||
<view class="ss-coupon-menu-wrap ss-flex ss-col-center">
|
||||
<view class="ss-coupon-menu-wrap ss-flex ss-col-center" :style="[bgStyle, { marginLeft: `${data.space}px` }]">
|
||||
<view class="menu-item ss-flex-col ss-row-center ss-col-center" v-for="item in props.list" :key="item.title"
|
||||
@tap="sheep.$router.go(item.path, { type: item.type })"
|
||||
:class="item.type === 'all' ? 'menu-wallet' : 'ss-flex-1'">
|
||||
|
@ -15,6 +15,7 @@
|
|||
* 装修组件 - 优惠券菜单
|
||||
*/
|
||||
import sheep from '@/sheep';
|
||||
import { computed } from 'vue';
|
||||
|
||||
// 接收参数
|
||||
const props = defineProps({
|
||||
|
@ -52,6 +53,28 @@
|
|||
];
|
||||
},
|
||||
},
|
||||
// 装修数据
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 装修样式
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
// 设置背景样式
|
||||
const bgStyle = computed(() => {
|
||||
// 直接从 props.styles 解构
|
||||
const { bgType, bgImg, bgColor } = props.styles;
|
||||
|
||||
// 根据 bgType 返回相应的样式
|
||||
return {
|
||||
background: bgType === 'img'
|
||||
? `url(${bgImg}) no-repeat top center / 100% 100%`
|
||||
: bgColor
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -37,30 +37,22 @@
|
|||
<view class="ss-flex ss-row-between ss-m-t-16">
|
||||
<view
|
||||
class="sellby-text"
|
||||
:class=" isDisable ? 'disabled-color' : 'subtitle-color'"
|
||||
:class="isDisable ? 'disabled-color' : 'subtitle-color'"
|
||||
v-if="data.validityType === 2"
|
||||
>
|
||||
有效期:领取后 {{ data.fixedEndTerm }} 天内可用
|
||||
</view>
|
||||
<view
|
||||
class="sellby-text"
|
||||
:class=" isDisable ? 'disabled-color' : 'subtitle-color'"
|
||||
v-else
|
||||
>
|
||||
<view class="sellby-text" :class="isDisable ? 'disabled-color' : 'subtitle-color'" v-else>
|
||||
有效期: {{ sheep.$helper.timeFormat(data.validStartTime, 'yyyy-mm-dd') }} 至
|
||||
{{ sheep.$helper.timeFormat(data.validEndTime, 'yyyy-mm-dd') }}
|
||||
</view>
|
||||
<view
|
||||
class="value-enough"
|
||||
:class="isDisable ? 'disabled-color' : 'subtitle-color'"
|
||||
>
|
||||
<view class="value-enough" :class="isDisable ? 'disabled-color' : 'subtitle-color'">
|
||||
满 {{ fen2yuan(data.usePrice) }} 可用
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- TODO 芋艿:可优化,增加优惠劵的描述 -->
|
||||
<view class="desc ss-flex ss-row-between">
|
||||
<view>
|
||||
<view class="desc-title">{{ data.description }}</view>
|
||||
|
@ -76,17 +68,15 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, reactive } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import { fen2yuan } from '../../hooks/useGoods';
|
||||
import sheep from '../../index';
|
||||
|
||||
const state = reactive({});
|
||||
|
||||
const isDisable = computed(() => {
|
||||
if (props.type === 'coupon') {
|
||||
return false;
|
||||
}
|
||||
return props.data.status !== 1;
|
||||
return props.disabled;
|
||||
});
|
||||
|
||||
// 接受参数
|
||||
|
@ -202,4 +192,4 @@
|
|||
.price-text {
|
||||
color: #ff0000;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -16,8 +16,12 @@
|
|||
:scroll-with-animation="false"
|
||||
:enable-back-to-top="true"
|
||||
>
|
||||
<!--可使用的优惠券区域-->
|
||||
<view class="subtitle ss-m-l-20">可使用优惠券</view>
|
||||
<view v-for="(item, index) in state.couponInfo" :key="index">
|
||||
<view
|
||||
v-for="(item, index) in state.couponInfo.filter((coupon) => coupon.match)"
|
||||
:key="index"
|
||||
>
|
||||
<s-coupon-list :data="item" type="user" :disabled="false">
|
||||
<template #default>
|
||||
<label class="ss-flex ss-col-center" @tap="radioChange(item.id)">
|
||||
|
@ -31,19 +35,18 @@
|
|||
</template>
|
||||
</s-coupon-list>
|
||||
</view>
|
||||
<!-- TODO 芋艿:未来接口需要支持下
|
||||
<!--不可使用的优惠券区域-->
|
||||
<view class="subtitle ss-m-t-40 ss-m-l-20">不可使用优惠券</view>
|
||||
<view v-for="item in state.couponInfo.cannot_use" :key="item.id">
|
||||
<view v-for="item in state.couponInfo.filter((coupon) => !coupon.match)" :key="item.id">
|
||||
<s-coupon-list :data="item" type="user" :disabled="true">
|
||||
<template v-slot:reason>
|
||||
<view class="ss-flex ss-m-t-24">
|
||||
<view class="reason-title"> 不可用原因:</view>
|
||||
<view class="reason-desc">{{ item.cannot_use_msg }}</view>
|
||||
<view class="reason-desc">{{ item.mismatchReason || '未达到使用门槛' }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</s-coupon-list>
|
||||
</view>
|
||||
-->
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="modal-footer ss-flex">
|
||||
|
@ -55,7 +58,8 @@
|
|||
import { computed, reactive } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: { // 优惠劵列表
|
||||
modelValue: {
|
||||
// 优惠劵列表
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
|
@ -69,13 +73,13 @@
|
|||
|
||||
const state = reactive({
|
||||
couponInfo: computed(() => props.modelValue), // 优惠劵列表
|
||||
couponId: 0, // 选中的优惠劵编号
|
||||
couponId: undefined, // 选中的优惠劵编号
|
||||
});
|
||||
|
||||
// 选中优惠劵
|
||||
function radioChange(couponId) {
|
||||
if (state.couponId === couponId) {
|
||||
state.couponId = 0;
|
||||
state.couponId = undefined;
|
||||
} else {
|
||||
state.couponId = couponId;
|
||||
}
|
||||
|
@ -84,7 +88,7 @@
|
|||
// 确认优惠劵
|
||||
const onConfirm = () => {
|
||||
emits('confirm', state.couponId);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep() {
|
||||
|
@ -96,25 +100,30 @@
|
|||
.model-box {
|
||||
height: 60vh;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
height: 80rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.model-content {
|
||||
height: 54vh;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
width: 100%;
|
||||
height: 120rpx;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
width: 710rpx;
|
||||
margin-left: 20rpx;
|
||||
|
@ -123,12 +132,14 @@
|
|||
border-radius: 40rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.reason-title {
|
||||
font-weight: 600;
|
||||
font-size: 20rpx;
|
||||
line-height: 26rpx;
|
||||
color: #ff0003;
|
||||
}
|
||||
|
||||
.reason-desc {
|
||||
font-weight: 600;
|
||||
font-size: 20rpx;
|
||||
|
|
|
@ -44,9 +44,9 @@
|
|||
*
|
||||
* @property {Number | String} alwaysShow = [0,1] - 是否常驻
|
||||
* @property {Number | String} styleType = [inner] - 是否沉浸式
|
||||
* @property {String | Number} type - 标题背景模式
|
||||
* @property {String} color - 页面背景色
|
||||
* @property {String} src - 页面背景图片
|
||||
* @property {String | Number} type - 标题背景模式
|
||||
* @property {String} color - 页面背景色
|
||||
* @property {String} src - 页面背景图片
|
||||
*/
|
||||
import { computed, unref } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
|
@ -77,7 +77,7 @@
|
|||
});
|
||||
const navList = computed(() => {
|
||||
// #ifdef MP
|
||||
return props.data.mapCells || [];
|
||||
return props.data.mpCells || [];
|
||||
// #endif
|
||||
return props.data.otherCells || [];
|
||||
});
|
||||
|
@ -117,11 +117,12 @@
|
|||
const bgStyles = computed(() => {
|
||||
return {
|
||||
background:
|
||||
props.data.bgType === 'img' && props.data.bgImg
|
||||
props.data.bgType === 'img' && props.data.bgImg
|
||||
? `url(${sheep.$url.cdn(props.data.bgImg)}) no-repeat top center / 100% 100%`
|
||||
: props.data.bgColor
|
||||
: props.data.bgColor,
|
||||
};
|
||||
});
|
||||
|
||||
// 左侧按钮:返回上一页或首页
|
||||
function onClickLeft() {
|
||||
if (hasHistory) {
|
||||
|
@ -130,6 +131,7 @@
|
|||
sheep.$router.go('/pages/index/index');
|
||||
}
|
||||
}
|
||||
|
||||
// 右侧按钮:打开快捷菜单
|
||||
function onClickRight() {
|
||||
showMenuTools();
|
||||
|
@ -147,44 +149,53 @@
|
|||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.nav-icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: 20rpx;
|
||||
|
||||
.inner-icon-box {
|
||||
border: 1px solid rgba(#fff, 0.4);
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
.icon-box {
|
||||
background: #ffffff;
|
||||
box-shadow: 0px 0px 4rpx rgba(51, 51, 51, 0.08),
|
||||
0px 4rpx 6rpx 2rpx rgba(102, 102, 102, 0.12);
|
||||
box-shadow: 0px 0px 4rpx rgba(51, 51, 51, 0.08), 0px 4rpx 6rpx 2rpx rgba(102, 102, 102, 0.12);
|
||||
border-radius: 30rpx;
|
||||
width: 134rpx;
|
||||
height: 56rpx;
|
||||
margin-left: 8rpx;
|
||||
|
||||
.line {
|
||||
width: 2rpx;
|
||||
height: 24rpx;
|
||||
background: #e5e5e7;
|
||||
}
|
||||
|
||||
.sicon-back {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.sicon-home {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.sicon-more {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.icon-button {
|
||||
width: 67rpx;
|
||||
height: 56rpx;
|
||||
|
||||
&-left:hover {
|
||||
background: rgba(0, 0, 0, 0.16);
|
||||
border-radius: 30rpx 0px 0px 30rpx;
|
||||
}
|
||||
|
||||
&-right:hover {
|
||||
background: rgba(0, 0, 0, 0.16);
|
||||
border-radius: 0px 30rpx 30rpx 0px;
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
<!-- 商品卡片 -->
|
||||
<view>
|
||||
<!-- 布局1. 单列大图(上图,下内容)-->
|
||||
<view v-if="layoutType === LayoutTypeEnum.ONE_COL_BIG_IMG && state.goodsList.length" class="goods-sl-box">
|
||||
<view
|
||||
v-if="layoutType === LayoutTypeEnum.ONE_COL_BIG_IMG && state.goodsList.length"
|
||||
class="goods-sl-box"
|
||||
>
|
||||
<view
|
||||
class="goods-box"
|
||||
v-for="item in state.goodsList"
|
||||
|
@ -100,7 +103,10 @@
|
|||
</view>
|
||||
|
||||
<!-- 布局3. 单列小图(左图,右内容) -->
|
||||
<view v-if="layoutType === LayoutTypeEnum.ONE_COL_SMALL_IMG && state.goodsList.length" class="goods-lg-box">
|
||||
<view
|
||||
v-if="layoutType === LayoutTypeEnum.ONE_COL_SMALL_IMG && state.goodsList.length"
|
||||
class="goods-lg-box"
|
||||
>
|
||||
<view
|
||||
class="goods-box"
|
||||
:style="[{ marginBottom: data.space + 'px' }]"
|
||||
|
@ -147,7 +153,7 @@
|
|||
TWO_COL: 'twoCol',
|
||||
// 单列小图
|
||||
ONE_COL_SMALL_IMG: 'oneColSmallImg',
|
||||
}
|
||||
};
|
||||
|
||||
const state = reactive({
|
||||
goodsList: [],
|
||||
|
@ -157,16 +163,16 @@
|
|||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default() {},
|
||||
default: () => ({}),
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default() {},
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
const { layoutType, btnBuy, spuIds } = props.data ?? {};
|
||||
const { marginLeft, marginRight } = props.styles ?? {};
|
||||
const { layoutType, btnBuy, spuIds } = props.data || {};
|
||||
const { marginLeft, marginRight } = props.styles || {};
|
||||
|
||||
// 购买按钮样式
|
||||
const buyStyle = computed(() => {
|
||||
|
@ -215,6 +221,7 @@
|
|||
// 计数
|
||||
count++;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
/**
|
||||
|
@ -283,7 +290,7 @@
|
|||
settleData.value = await getSettlementByIds(spuIds.join(','))
|
||||
state.goodsList = await enrichDataWithSkus(ms,settleData.value)
|
||||
// 只有双列布局时需要
|
||||
if (layoutType === LayoutTypeEnum.TWO_COL){
|
||||
if (layoutType === LayoutTypeEnum.TWO_COL) {
|
||||
// 分列
|
||||
calculateGoodsColumn();
|
||||
}
|
||||
|
@ -298,11 +305,13 @@
|
|||
.goods-list-box {
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.left-list {
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.right-list {
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0 !important;
|
||||
|
|
|
@ -2,29 +2,38 @@
|
|||
<template>
|
||||
<view class="ss-goods-wrap">
|
||||
<!-- xs卡片:横向紧凑型,一行放两个,图片左内容右边 -->
|
||||
<view v-if="size === 'xs'" class="xs-goods-card ss-flex ss-col-stretch" :style="[elStyles]" @tap="onClick">
|
||||
<view
|
||||
v-if="size === 'xs'"
|
||||
class="xs-goods-card ss-flex ss-col-stretch"
|
||||
:style="[elStyles]"
|
||||
@tap="onClick"
|
||||
>
|
||||
<view v-if="tagStyle.show" class="tag-icon-box">
|
||||
<image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
|
||||
</view>
|
||||
<image class="xs-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="aspectFit"></image>
|
||||
<view v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
|
||||
class="xs-goods-content ss-flex-col ss-row-around">
|
||||
<view v-if="goodsFields.title?.show || goodsFields.name?.show" class="xs-goods-title ss-line-1"
|
||||
:style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]">
|
||||
<image
|
||||
class="xs-img-box"
|
||||
:src="sheep.$url.cdn(data.image || data.picUrl)"
|
||||
mode="aspectFit"
|
||||
></image>
|
||||
<view
|
||||
v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
|
||||
class="xs-goods-content ss-flex-col ss-row-around"
|
||||
>
|
||||
<view
|
||||
v-if="goodsFields.title?.show || goodsFields.name?.show"
|
||||
class="xs-goods-title ss-line-1"
|
||||
:style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]"
|
||||
>
|
||||
{{ data.title || data.name }}
|
||||
</view>
|
||||
<!-- 这里是新加的会员价和限时优惠 -->
|
||||
<view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
|
||||
<view class="card" v-if="iconShow">{{iconShow}}</view>
|
||||
<view class="card2" v-if="data.reward">{{data.reward.rewardActivity}}</view>
|
||||
</view>
|
||||
<!-- 这里是新加的会员价和限时优惠结束 -->
|
||||
<view v-if="goodsFields.price?.show" class="xs-goods-price font-OPPOSANS"
|
||||
:style="[{ color: goodsFields.price.color }]">
|
||||
<view
|
||||
v-if="goodsFields.price?.show"
|
||||
class="xs-goods-price font-OPPOSANS"
|
||||
:style="[{ color: goodsFields.price.color }]"
|
||||
>
|
||||
<text class="price-unit ss-font-24">{{ priceUnit }}</text>
|
||||
<text v-if="iconShow=='限时优惠'">{{fen2yuan(data.discountPrice)}}</text>
|
||||
<text v-else-if="iconShow=='会员价'">{{fen2yuan(data.vipPrice)}}</text>
|
||||
<text v-else>{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}</text>
|
||||
{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
@ -34,26 +43,30 @@
|
|||
<view v-if="tagStyle.show" class="tag-icon-box">
|
||||
<image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
|
||||
</view>
|
||||
<image class="sm-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="aspectFill"></image>
|
||||
<image
|
||||
class="sm-img-box"
|
||||
:src="sheep.$url.cdn(data.image || data.picUrl)"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
|
||||
<view v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
|
||||
class="sm-goods-content" :style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]">
|
||||
<view v-if="goodsFields.title?.show || goodsFields.name?.show"
|
||||
class="sm-goods-title ss-line-1 ss-m-b-16">
|
||||
<view
|
||||
v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
|
||||
class="sm-goods-content"
|
||||
:style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]"
|
||||
>
|
||||
<view
|
||||
v-if="goodsFields.title?.show || goodsFields.name?.show"
|
||||
class="sm-goods-title ss-line-1 ss-m-b-16"
|
||||
>
|
||||
{{ data.title || data.name }}
|
||||
</view>
|
||||
<!-- 这里是新加的会员价和限时优惠 -->
|
||||
<view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
|
||||
<view class="card" v-if="iconShow">{{iconShow}}</view>
|
||||
<view class="card2" v-if="data.reward">{{data.reward.rewardActivity}}</view>
|
||||
</view>
|
||||
<!-- 这里是新加的会员价和限时优惠结束 -->
|
||||
<view v-if="goodsFields.price?.show" class="sm-goods-price font-OPPOSANS"
|
||||
:style="[{ color: goodsFields.price.color }]">
|
||||
<view
|
||||
v-if="goodsFields.price?.show"
|
||||
class="sm-goods-price font-OPPOSANS"
|
||||
:style="[{ color: goodsFields.price.color }]"
|
||||
>
|
||||
<text class="price-unit ss-font-24">{{ priceUnit }}</text>
|
||||
<text v-if="iconShow=='限时优惠'">{{fen2yuan(data.discountPrice)}}</text>
|
||||
<text v-else-if="iconShow=='会员价'">{{fen2yuan(data.vipPrice)}}</text>
|
||||
<text v-else>{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}</text>
|
||||
{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
@ -63,43 +76,58 @@
|
|||
<view v-if="tagStyle.show" class="tag-icon-box">
|
||||
<image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
|
||||
</view>
|
||||
<image class="md-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="widthFix"></image>
|
||||
<view class="md-goods-content ss-flex-col ss-row-around ss-p-b-20 ss-p-t-20 ss-p-x-16" :id="elId">
|
||||
<view v-if="goodsFields.title?.show || goodsFields.name?.show" class="md-goods-title ss-line-1"
|
||||
:style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]">
|
||||
<image
|
||||
class="md-img-box"
|
||||
:src="sheep.$url.cdn(data.image || data.picUrl)"
|
||||
mode="widthFix"
|
||||
></image>
|
||||
<view
|
||||
class="md-goods-content ss-flex-col ss-row-around ss-p-b-20 ss-p-t-20 ss-p-x-16"
|
||||
:id="elId"
|
||||
>
|
||||
<view
|
||||
v-if="goodsFields.title?.show || goodsFields.name?.show"
|
||||
class="md-goods-title ss-line-1"
|
||||
:style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]"
|
||||
>
|
||||
{{ data.title || data.name }}
|
||||
</view>
|
||||
<view v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
|
||||
class="md-goods-subtitle ss-m-t-16 ss-line-1"
|
||||
:style="[{ color: subTitleColor, background: subTitleBackground }]">
|
||||
<view
|
||||
v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
|
||||
class="md-goods-subtitle ss-m-t-16 ss-line-1"
|
||||
:style="[{ color: subTitleColor, background: subTitleBackground }]"
|
||||
>
|
||||
{{ data.subtitle || data.introduction }}
|
||||
</view>
|
||||
<slot name="activity">
|
||||
<view v-if="data.promos?.length" class="tag-box ss-flex-wrap ss-flex ss-col-center">
|
||||
<view class="activity-tag ss-m-r-10 ss-m-t-16" v-for="item in data.promos" :key="item.id">
|
||||
<view
|
||||
class="activity-tag ss-m-r-10 ss-m-t-16"
|
||||
v-for="item in data.promos"
|
||||
:key="item.id"
|
||||
>
|
||||
{{ item.title }}
|
||||
</view>
|
||||
</view>
|
||||
</slot>
|
||||
<!-- 这里是新加的会员价和限时优惠 -->
|
||||
<view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
|
||||
<view class="card" v-if="iconShow">{{iconShow}}</view>
|
||||
<view class="card2" v-if="data.reward">{{data.reward.rewardActivity}}</view>
|
||||
</view>
|
||||
<!-- 这里是新加的会员价和限时优惠结束 -->
|
||||
<view class="ss-flex ss-col-bottom">
|
||||
<view v-if="goodsFields.price?.show" class="md-goods-price ss-m-t-16 font-OPPOSANS ss-m-r-10"
|
||||
:style="[{ color: goodsFields.price.color }]">
|
||||
<view
|
||||
v-if="goodsFields.price?.show"
|
||||
class="md-goods-price ss-m-t-16 font-OPPOSANS ss-m-r-10"
|
||||
:style="[{ color: goodsFields.price.color }]"
|
||||
>
|
||||
<text class="price-unit ss-font-24">{{ priceUnit }}</text>
|
||||
<text v-if="iconShow=='限时优惠'">{{fen2yuan(data.discountPrice)}}</text>
|
||||
<text v-else-if="iconShow=='会员价'">{{fen2yuan(data.vipPrice)}}</text>
|
||||
<text v-else>{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}</text>
|
||||
{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
|
||||
</view>
|
||||
|
||||
<view v-if="
|
||||
<view
|
||||
v-if="
|
||||
(goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
|
||||
(data.original_price > 0 || data.marketPrice > 0)
|
||||
" class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex" :style="[{ color: originPriceColor }]">
|
||||
"
|
||||
class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex"
|
||||
:style="[{ color: originPriceColor }]"
|
||||
>
|
||||
<text class="price-unit ss-font-20">{{ priceUnit }}</text>
|
||||
<view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
|
||||
</view>
|
||||
|
@ -118,24 +146,38 @@
|
|||
</view>
|
||||
|
||||
<!-- lg卡片:横向型,一行放一个,图片左内容右边 -->
|
||||
<view v-if="size === 'lg'" class="lg-goods-card ss-flex ss-col-stretch" :style="[elStyles]" @tap="onClick">
|
||||
<view
|
||||
v-if="size === 'lg'"
|
||||
class="lg-goods-card ss-flex ss-col-stretch"
|
||||
:style="[elStyles]"
|
||||
@tap="onClick"
|
||||
>
|
||||
<view v-if="tagStyle.show" class="tag-icon-box">
|
||||
<image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
|
||||
</view>
|
||||
<view v-if="seckillTag" class="seckill-tag ss-flex ss-row-center"> 秒杀 </view>
|
||||
<view v-if="seckillTag" class="seckill-tag ss-flex ss-row-center">秒杀</view>
|
||||
<view v-if="grouponTag" class="groupon-tag ss-flex ss-row-center">
|
||||
<view class="tag-icon">拼团</view>
|
||||
</view>
|
||||
<image class="lg-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="aspectFill"></image>
|
||||
<image
|
||||
class="lg-img-box"
|
||||
:src="sheep.$url.cdn(data.image || data.picUrl)"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view class="lg-goods-content ss-flex-1 ss-flex-col ss-row-between ss-p-b-10 ss-p-t-20">
|
||||
<view>
|
||||
<view v-if="goodsFields.title?.show || goodsFields.name?.show" class="lg-goods-title ss-line-2"
|
||||
:style="[{ color: titleColor }]">
|
||||
<view
|
||||
v-if="goodsFields.title?.show || goodsFields.name?.show"
|
||||
class="lg-goods-title ss-line-2"
|
||||
:style="[{ color: titleColor }]"
|
||||
>
|
||||
{{ data.title || data.name }}
|
||||
</view>
|
||||
<view v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
|
||||
class="lg-goods-subtitle ss-m-t-10 ss-line-1"
|
||||
:style="[{ color: subTitleColor, background: subTitleBackground }]">
|
||||
<view
|
||||
v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
|
||||
class="lg-goods-subtitle ss-m-t-10 ss-line-1"
|
||||
:style="[{ color: subTitleColor, background: subTitleBackground }]"
|
||||
>
|
||||
{{ data.subtitle || data.introduction }}
|
||||
</view>
|
||||
</view>
|
||||
|
@ -147,27 +189,25 @@
|
|||
</view>
|
||||
</view>
|
||||
</slot>
|
||||
<!-- 这里是新加的会员价和限时优惠 -->
|
||||
<view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
|
||||
<view class="card" v-if="iconShow">{{iconShow}}</view>
|
||||
<view class="card2" v-if="data.reward">{{data.reward.rewardActivity}}</view>
|
||||
</view>
|
||||
<!-- 这里是新加的会员价和限时优惠结束 -->
|
||||
<view class="ss-flex ss-col-bottom ss-m-t-10">
|
||||
<view v-if="goodsFields.price?.show"
|
||||
class="lg-goods-price ss-m-r-12 ss-flex ss-col-bottom font-OPPOSANS"
|
||||
:style="[{ color: goodsFields.price.color }]">
|
||||
<view
|
||||
v-if="goodsFields.price?.show"
|
||||
class="lg-goods-price ss-m-r-12 ss-flex ss-col-bottom font-OPPOSANS"
|
||||
:style="[{ color: goodsFields.price.color }]"
|
||||
>
|
||||
<text class="ss-font-24">{{ priceUnit }}</text>
|
||||
{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
|
||||
</view>
|
||||
<view v-if="
|
||||
<view
|
||||
v-if="
|
||||
(goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
|
||||
(data.original_price > 0 || data.marketPrice > 0)
|
||||
" class="goods-origin-price ss-flex ss-col-bottom font-OPPOSANS" :style="[{ color: originPriceColor }]">
|
||||
"
|
||||
class="goods-origin-price ss-flex ss-col-bottom font-OPPOSANS"
|
||||
:style="[{ color: originPriceColor }]"
|
||||
>
|
||||
<text class="price-unit ss-font-20">{{ priceUnit }}</text>
|
||||
<text v-if="iconShow=='限时优惠'">{{fen2yuan(data.discountPrice)}}</text>
|
||||
<text v-else-if="iconShow=='会员价'">{{fen2yuan(data.vipPrice)}}</text>
|
||||
<text v-else>{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}</text>
|
||||
<view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="ss-m-t-8 ss-flex ss-col-center ss-flex-wrap">
|
||||
|
@ -187,45 +227,54 @@
|
|||
<image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
|
||||
</view>
|
||||
|
||||
<image class="sl-img-box" :src="sheep.$url.cdn(data.image || data.picUrl)" mode="aspectFill"></image>
|
||||
<image
|
||||
class="sl-img-box"
|
||||
:src="sheep.$url.cdn(data.image || data.picUrl)"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
|
||||
<view class="sl-goods-content">
|
||||
<view>
|
||||
<view v-if="goodsFields.title?.show || goodsFields.name?.show" class="sl-goods-title ss-line-1"
|
||||
:style="[{ color: titleColor }]">
|
||||
<view
|
||||
v-if="goodsFields.title?.show || goodsFields.name?.show"
|
||||
class="sl-goods-title ss-line-1"
|
||||
:style="[{ color: titleColor }]"
|
||||
>
|
||||
{{ data.title || data.name }}
|
||||
</view>
|
||||
<view v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
|
||||
class="sl-goods-subtitle ss-m-t-16"
|
||||
:style="[{ color: subTitleColor, background: subTitleBackground }]">
|
||||
<view
|
||||
v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
|
||||
class="sl-goods-subtitle ss-m-t-16"
|
||||
:style="[{ color: subTitleColor, background: subTitleBackground }]"
|
||||
>
|
||||
{{ data.subtitle || data.introduction }}
|
||||
</view>
|
||||
</view>
|
||||
<view>
|
||||
<slot name="activity">
|
||||
<view v-if="data.promos?.length" class="tag-box ss-flex ss-col-center ss-flex-wrap">
|
||||
<view class="activity-tag ss-m-r-10 ss-m-t-16" v-for="item in data.promos" :key="item.id">
|
||||
<view
|
||||
class="activity-tag ss-m-r-10 ss-m-t-16"
|
||||
v-for="item in data.promos"
|
||||
:key="item.id"
|
||||
>
|
||||
{{ item.title }}
|
||||
</view>
|
||||
</view>
|
||||
</slot>
|
||||
<!-- 这里是新加的会员价和限时优惠 -->
|
||||
<view class="iconBox" v-if="data.discountPrice || data.vipPrice || data.reward">
|
||||
<view class="card" v-if="iconShow">{{iconShow}}</view>
|
||||
<view class="card2" v-if="data.reward">{{data.reward.rewardActivity}}</view>
|
||||
</view>
|
||||
<!-- 这里是新加的会员价和限时优惠结束 -->
|
||||
<view v-if="goodsFields.price?.show" class="ss-flex ss-col-bottom font-OPPOSANS">
|
||||
<view class="sl-goods-price ss-m-r-12" :style="[{ color: goodsFields.price.color }]">
|
||||
<text class="price-unit ss-font-24">{{ priceUnit }}</text>
|
||||
<text v-if="iconShow=='限时优惠'">{{fen2yuan(data.discountPrice)}}</text>
|
||||
<text v-else-if="iconShow=='会员价'">{{fen2yuan(data.vipPrice)}}</text>
|
||||
<text v-else>{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}</text>
|
||||
{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
|
||||
</view>
|
||||
<view v-if="
|
||||
<view
|
||||
v-if="
|
||||
(goodsFields.original_price?.show || goodsFields.marketPrice?.show) &&
|
||||
(data.original_price > 0 || data.marketPrice > 0)
|
||||
" class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex" :style="[{ color: originPriceColor }]">
|
||||
"
|
||||
class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex"
|
||||
:style="[{ color: originPriceColor }]"
|
||||
>
|
||||
<text class="price-unit ss-font-20">{{ priceUnit }}</text>
|
||||
<view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
|
||||
</view>
|
||||
|
@ -248,50 +297,36 @@
|
|||
* 商品卡片
|
||||
*
|
||||
* @property {Array} size = [xs | sm | md | lg | sl ] - 列表数据
|
||||
* @property {String} tag - md及以上才有
|
||||
* @property {String} img - 图片
|
||||
* @property {String} background - 背景色
|
||||
* @property {String} topRadius - 上圆角
|
||||
* @property {String} bottomRadius - 下圆角
|
||||
* @property {String} title - 标题
|
||||
* @property {String} titleColor - 标题颜色
|
||||
* @property {String} tag - md及以上才有
|
||||
* @property {String} img - 图片
|
||||
* @property {String} background - 背景色
|
||||
* @property {String} topRadius - 上圆角
|
||||
* @property {String} bottomRadius - 下圆角
|
||||
* @property {String} title - 标题
|
||||
* @property {String} titleColor - 标题颜色
|
||||
* @property {Number} titleWidth = 0 - 标题宽度,默认0,单位rpx
|
||||
* @property {String} subTitle - 副标题
|
||||
* @property {String} subTitleColor - 副标题颜色
|
||||
* @property {String} subTitleBackground - 副标题背景
|
||||
* @property {String | Number} price - 价格
|
||||
* @property {String} priceColor - 价格颜色
|
||||
* @property {String | Number} originPrice - 原价/划线价
|
||||
* @property {String} originPriceColor - 原价颜色
|
||||
* @property {String | Number} sales - 销售数量
|
||||
* @property {String} salesColor - 销售数量颜色
|
||||
* @property {String} subTitle - 副标题
|
||||
* @property {String} subTitleColor - 副标题颜色
|
||||
* @property {String} subTitleBackground - 副标题背景
|
||||
* @property {String | Number} price - 价格
|
||||
* @property {String} priceColor - 价格颜色
|
||||
* @property {String | Number} originPrice - 原价/划线价
|
||||
* @property {String} originPriceColor - 原价颜色
|
||||
* @property {String | Number} sales - 销售数量
|
||||
* @property {String} salesColor - 销售数量颜色
|
||||
*
|
||||
* @slots activity - 活动插槽
|
||||
* @slots cart - 购物车插槽,默认包含文字,背景色,文字颜色 || 图片 || 行为
|
||||
*
|
||||
* @event {Function()} click - 点击卡片
|
||||
* @event {Function()} click - 点击卡片
|
||||
*
|
||||
*/
|
||||
import {
|
||||
computed,
|
||||
reactive,
|
||||
getCurrentInstance,
|
||||
onMounted,
|
||||
nextTick,
|
||||
ref
|
||||
} from 'vue';
|
||||
import { computed, reactive, getCurrentInstance, onMounted, nextTick } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import {
|
||||
fen2yuan,
|
||||
formatSales
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import {
|
||||
formatStock
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import goodsCollectVue from '@/pages/user/goods-collect.vue';
|
||||
import {
|
||||
isArray
|
||||
} from 'lodash-es';
|
||||
import { fen2yuan, formatSales } from '@/sheep/hooks/useGoods';
|
||||
import { formatStock } from '@/sheep/hooks/useGoods';
|
||||
import { isArray } from 'lodash-es';
|
||||
|
||||
// 数据
|
||||
const state = reactive({});
|
||||
|
||||
|
@ -299,42 +334,30 @@
|
|||
const props = defineProps({
|
||||
goodsFields: {
|
||||
type: [Array, Object],
|
||||
default () {
|
||||
default() {
|
||||
return {
|
||||
// 商品价格
|
||||
price: {
|
||||
show: true
|
||||
},
|
||||
price: { show: true },
|
||||
// 库存
|
||||
stock: {
|
||||
show: true
|
||||
},
|
||||
stock: { show: true },
|
||||
// 商品名称
|
||||
name: {
|
||||
show: true
|
||||
},
|
||||
name: { show: true },
|
||||
// 商品介绍
|
||||
introduction: {
|
||||
show: true
|
||||
},
|
||||
introduction: { show: true },
|
||||
// 市场价
|
||||
marketPrice: {
|
||||
show: true
|
||||
},
|
||||
marketPrice: { show: true },
|
||||
// 销量
|
||||
salesCount: {
|
||||
show: true
|
||||
},
|
||||
salesCount: { show: true },
|
||||
};
|
||||
},
|
||||
},
|
||||
tagStyle: {
|
||||
type: Object,
|
||||
default: {},
|
||||
default: () => ({}),
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default: {},
|
||||
default: () => ({}),
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
|
@ -393,25 +416,7 @@
|
|||
default: false,
|
||||
},
|
||||
});
|
||||
//判断限时优惠和会员价标签内容暂时导致页面出错,又舍不得丢,等着把新的数据整合到商品信息中,也用起来
|
||||
const iconShow = handle()
|
||||
|
||||
function handle() {
|
||||
if (props.data.discountPrice === null && props.data.vipPrice === null) {
|
||||
// 如果两个值都为 null,则不展示任何内容
|
||||
return '';
|
||||
} else if (props.data.discountPrice === null) {
|
||||
// 如果 discountPrice 为 null,展示 vipPrice
|
||||
return '会员价';
|
||||
} else if (props.data.vipPrice === null) {
|
||||
// 如果 vipPrice 为 null,展示 discountPrice
|
||||
return '限时优惠';
|
||||
} else if (props.data.discountPrice < props.data.vipPrice) {
|
||||
return '限时优惠';
|
||||
} else if (props.data.discountPrice > props.data.vipPrice) {
|
||||
return '会员价';
|
||||
}
|
||||
}
|
||||
// 组件样式
|
||||
const elStyles = computed(() => {
|
||||
return {
|
||||
|
@ -443,18 +448,13 @@
|
|||
};
|
||||
|
||||
// 获取卡片实时高度
|
||||
const {
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
const { proxy } = getCurrentInstance();
|
||||
const elId = `sheep_${Math.ceil(Math.random() * 10e5).toString(36)}`;
|
||||
|
||||
function getGoodsPriceCardWH() {
|
||||
if (props.size === 'md') {
|
||||
const view = uni.createSelectorQuery().in(proxy);
|
||||
view.select(`#${elId}`).fields({
|
||||
size: true,
|
||||
scrollOffset: true
|
||||
});
|
||||
view.select(`#${elId}`).fields({ size: true, scrollOffset: true });
|
||||
view.exec((data) => {
|
||||
let totalHeight = 0;
|
||||
const goodsPriceCard = data[0];
|
||||
|
@ -469,6 +469,7 @@
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
getGoodsPriceCardWH();
|
||||
|
@ -762,31 +763,4 @@
|
|||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
padding: 2rpx 10rpx;
|
||||
background-color: red;
|
||||
color: #ffffff;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.card2 {
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
padding: 2rpx 10rpx;
|
||||
background-color: rgb(255, 242, 241);
|
||||
color: #ff2621;
|
||||
font-size: 24rpx;
|
||||
margin-left: 5rpx;
|
||||
}
|
||||
|
||||
.iconBox {
|
||||
width: 100%;
|
||||
height: fit-content;
|
||||
margin-top: 10rpx;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -1,83 +1,166 @@
|
|||
<!-- 装修组件 - 拼团 -->
|
||||
<!-- 装修商品组件:【拼团】商品卡片 -->
|
||||
<template>
|
||||
<!-- 商品卡片 -->
|
||||
<view>
|
||||
<!-- 布局1. 单列大图(上图,下内容)-->
|
||||
<view
|
||||
v-if="layoutType === 'threeCol'"
|
||||
class="goods-sm-box ss-flex ss-flex-wrap"
|
||||
:style="[{ margin: '-' + data.space + 'rpx' }]"
|
||||
v-if="layoutType === LayoutTypeEnum.ONE_COL_BIG_IMG && state.spuList.length"
|
||||
class="goods-sl-box"
|
||||
>
|
||||
<view
|
||||
v-for="product in productList"
|
||||
:key="product.id"
|
||||
class="goods-card-box"
|
||||
:style="[
|
||||
{
|
||||
padding: data.space + 'rpx',
|
||||
},
|
||||
]"
|
||||
class="goods-box"
|
||||
v-for="item in state.spuList"
|
||||
:key="item.id"
|
||||
:style="[{ marginBottom: data.space * 2 + 'rpx' }]"
|
||||
>
|
||||
<s-goods-column
|
||||
class="goods-card"
|
||||
size="sm"
|
||||
class=""
|
||||
size="sl"
|
||||
:goodsFields="data.fields"
|
||||
:tagStyle="tagStyle"
|
||||
:data="product"
|
||||
:tagStyle="data.badge"
|
||||
:data="item"
|
||||
:titleColor="data.fields.name?.color"
|
||||
:subTitleColor="data.fields.introduction.color"
|
||||
:topRadius="data.borderRadiusTop"
|
||||
:bottomRadius="data.borderRadiusBottom"
|
||||
@click="
|
||||
sheep.$router.go('/pages/goods/groupon', {
|
||||
id: props.data.activityId,
|
||||
})
|
||||
"
|
||||
></s-goods-column>
|
||||
@click="sheep.$router.go('/pages/goods/groupon', { id: item.activityId })"
|
||||
>
|
||||
<!-- 购买按钮 -->
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" :style="[buyStyle]">
|
||||
{{ btnBuy.type === 'text' ? btnBuy.text : '' }}
|
||||
</button>
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 样式2 一行一个 图片左 文案右 -->
|
||||
<view class="goods-box" v-if="layoutType === 'oneCol'">
|
||||
|
||||
<!-- 布局2. 单列小图(左图,右内容) -->
|
||||
<view
|
||||
v-if="layoutType === LayoutTypeEnum.ONE_COL_SMALL_IMG && state.spuList.length"
|
||||
class="goods-lg-box"
|
||||
>
|
||||
<view
|
||||
class="goods-list"
|
||||
v-for="(product, index) in productList"
|
||||
:key="index"
|
||||
:style="[{ marginBottom: space + 'px' }]"
|
||||
class="goods-box"
|
||||
:style="[{ marginBottom: data.space + 'px' }]"
|
||||
v-for="item in state.spuList"
|
||||
:key="item.id"
|
||||
>
|
||||
<s-goods-column
|
||||
class="goods-card"
|
||||
size="lg"
|
||||
:goodsFields="data.fields"
|
||||
:tagStyle="tagStyle"
|
||||
:data="product"
|
||||
:data="item"
|
||||
:tagStyle="data.badge"
|
||||
:titleColor="data.fields.name?.color"
|
||||
:subTitleColor="data.fields.introduction?.color"
|
||||
:subTitleColor="data.fields.introduction.color"
|
||||
:topRadius="data.borderRadiusTop"
|
||||
:bottomRadius="data.borderRadiusBottom"
|
||||
@click="
|
||||
sheep.$router.go('/pages/goods/groupon', {
|
||||
id: props.data.activityId,
|
||||
})
|
||||
"
|
||||
@tap="sheep.$router.go('/pages/goods/groupon', { id: item.activityId })"
|
||||
>
|
||||
<!-- 购买按钮 -->
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" :style="[buyStyle]">
|
||||
{{ btnBuy?.type === 'text' ? btnBuy.text : '' }}
|
||||
{{ btnBuy.type === 'text' ? btnBuy.text : '' }}
|
||||
</button>
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 布局3. 双列(每一列:上图,下内容)-->
|
||||
<view
|
||||
v-if="layoutType === LayoutTypeEnum.TWO_COL && state.spuList.length"
|
||||
class="goods-md-wrap ss-flex ss-flex-wrap ss-col-top"
|
||||
>
|
||||
<view class="goods-list-box">
|
||||
<view
|
||||
class="left-list"
|
||||
:style="[{ paddingRight: data.space + 'rpx', marginBottom: data.space + 'px' }]"
|
||||
v-for="item in state.leftSpuList"
|
||||
:key="item.id"
|
||||
>
|
||||
<s-goods-column
|
||||
class="goods-md-box"
|
||||
size="md"
|
||||
:goodsFields="data.fields"
|
||||
:tagStyle="data.badge"
|
||||
:data="item"
|
||||
:titleColor="data.fields.name?.color"
|
||||
:subTitleColor="data.fields.introduction.color"
|
||||
:topRadius="data.borderRadiusTop"
|
||||
:bottomRadius="data.borderRadiusBottom"
|
||||
:titleWidth="330 - marginLeft - marginRight"
|
||||
@click="sheep.$router.go('/pages/goods/groupon', { id: item.activityId })"
|
||||
@getHeight="calculateGoodsColumn($event, 'left')"
|
||||
>
|
||||
<!-- 购买按钮 -->
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" :style="[buyStyle]">
|
||||
{{ btnBuy.type === 'text' ? btnBuy.text : '' }}
|
||||
</button>
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-list-box">
|
||||
<view
|
||||
class="right-list"
|
||||
:style="[{ paddingLeft: data.space + 'rpx', marginBottom: data.space + 'px' }]"
|
||||
v-for="item in state.rightSpuList"
|
||||
:key="item.id"
|
||||
>
|
||||
<s-goods-column
|
||||
class="goods-md-box"
|
||||
size="md"
|
||||
:goodsFields="data.fields"
|
||||
:tagStyle="data.badge"
|
||||
:data="item"
|
||||
:titleColor="data.fields.name?.color"
|
||||
:subTitleColor="data.fields.introduction.color"
|
||||
:topRadius="data.borderRadiusTop"
|
||||
:bottomRadius="data.borderRadiusBottom"
|
||||
:titleWidth="330 - marginLeft - marginRight"
|
||||
@click="sheep.$router.go('/pages/goods/groupon', { id: item.activityId })"
|
||||
@getHeight="calculateGoodsColumn($event, 'right')"
|
||||
>
|
||||
<!-- 购买按钮 -->
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" :style="[buyStyle]">
|
||||
{{ btnBuy.type === 'text' ? btnBuy.text : '' }}
|
||||
</button>
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
/**
|
||||
* 拼团
|
||||
* 商品卡片
|
||||
*/
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import SpuApi from "@/sheep/api/product/spu";
|
||||
import CombinationApi from "@/sheep/api/promotion/combination";
|
||||
import CombinationApi from '@/sheep/api/promotion/combination';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
|
||||
// 接收参数
|
||||
// 布局类型
|
||||
const LayoutTypeEnum = {
|
||||
// 单列大图
|
||||
ONE_COL_BIG_IMG: 'oneColBigImg',
|
||||
// 双列
|
||||
TWO_COL: 'twoCol',
|
||||
// 单列小图
|
||||
ONE_COL_SMALL_IMG: 'oneColSmallImg',
|
||||
};
|
||||
|
||||
const state = reactive({
|
||||
spuList: [],
|
||||
leftSpuList: [],
|
||||
rightSpuList: [],
|
||||
});
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
|
@ -89,19 +172,19 @@
|
|||
},
|
||||
});
|
||||
|
||||
let { layoutType, tagStyle, btnBuy, space } = props.data;
|
||||
let { marginLeft, marginRight } = props.styles;
|
||||
const { layoutType, btnBuy, activityIds } = props.data || {};
|
||||
const { marginLeft, marginRight } = props.styles || {};
|
||||
|
||||
// 购买按钮样式
|
||||
const buyStyle = computed(() => {
|
||||
let btnBuy = props.data.btnBuy;
|
||||
if (btnBuy?.type === 'text') {
|
||||
if (btnBuy.type === 'text') {
|
||||
// 文字按钮:线性渐变背景颜色
|
||||
return {
|
||||
background: `linear-gradient(to right, ${btnBuy.bgBeginColor}, ${btnBuy.bgEndColor})`,
|
||||
};
|
||||
}
|
||||
|
||||
if (btnBuy?.type === 'img') {
|
||||
if (btnBuy.type === 'img') {
|
||||
// 图片按钮
|
||||
return {
|
||||
width: '54rpx',
|
||||
height: '54rpx',
|
||||
|
@ -111,21 +194,124 @@
|
|||
}
|
||||
});
|
||||
|
||||
const productList = ref([]);
|
||||
//region 商品瀑布流布局
|
||||
// 下一个要处理的商品索引
|
||||
let count = 0;
|
||||
// 左列的高度
|
||||
let leftHeight = 0;
|
||||
// 右列的高度
|
||||
let rightHeight = 0;
|
||||
|
||||
/**
|
||||
* 计算商品在左列还是右列
|
||||
* @param height 商品的高度
|
||||
* @param where 添加到哪一列
|
||||
*/
|
||||
function calculateGoodsColumn(height = 0, where = 'left') {
|
||||
// 处理完
|
||||
if (!state.spuList[count]) return;
|
||||
// 增加列的高度
|
||||
if (where === 'left') leftHeight += height;
|
||||
if (where === 'right') rightHeight += height;
|
||||
// 添加到矮的一列
|
||||
if (leftHeight <= rightHeight) {
|
||||
state.leftSpuList.push(state.spuList[count]);
|
||||
} else {
|
||||
state.rightSpuList.push(state.spuList[count]);
|
||||
}
|
||||
// 计数
|
||||
count++;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
/**
|
||||
* 根据商品编号列表,获取商品列表
|
||||
* @param ids 商品编号列表
|
||||
* @return {Promise<undefined>} 商品列表
|
||||
*/
|
||||
async function getCombinationActivityDetailList(ids) {
|
||||
const { data } = await CombinationApi.getCombinationActivityListByIds(ids);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据商品编号,获取商品详情
|
||||
* @param ids 商品编号列表
|
||||
* @return {Promise<undefined>} 商品列表
|
||||
*/
|
||||
async function getSpuDetail(ids) {
|
||||
const { data: spu } = await SpuApi.getSpuDetail(ids);
|
||||
return spu;
|
||||
}
|
||||
|
||||
// 初始化
|
||||
onMounted(async () => {
|
||||
// todo:@owen 与Yudao结构不一致,待重构
|
||||
const { data: activity } = await CombinationApi.getCombinationActivity(props.data.activityId);
|
||||
const { data: spu } = await SpuApi.getSpuDetail(activity.spuId)
|
||||
productList.value = [spu];
|
||||
// 加载活动列表
|
||||
const activityList = await getCombinationActivityDetailList(activityIds.join(','));
|
||||
// 循环获取活动商品SPU详情并添加到spuList
|
||||
for (const activity of activityList) {
|
||||
state.spuList.push(await getSpuDetail(activity.spuId));
|
||||
}
|
||||
|
||||
// 循环活动列表
|
||||
activityList.forEach((activity) => {
|
||||
// 提取活动价格
|
||||
const combinationPrice = activity.combinationPrice || Infinity;
|
||||
// 查找对应的 spu 并更新价格
|
||||
const spu = state.spuList.find((spu) => activity.spuId === spu.id);
|
||||
if (spu) {
|
||||
// 赋值最低价格
|
||||
spu.price = Math.min(combinationPrice, spu.price);
|
||||
// 赋值活动ID,为了点击跳转详情页
|
||||
spu.activityId = activity.id;
|
||||
}
|
||||
});
|
||||
|
||||
// 只有双列布局时需要
|
||||
if (layoutType === LayoutTypeEnum.TWO_COL) {
|
||||
// 分列
|
||||
calculateGoodsColumn();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.goods-list {
|
||||
.goods-md-wrap {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.goods-list-box {
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.left-list {
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.right-list {
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.goods-box {
|
||||
&:nth-last-of-type(1) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-md-box,
|
||||
.goods-sl-box,
|
||||
.goods-lg-box {
|
||||
position: relative;
|
||||
|
||||
.cart-btn {
|
||||
position: absolute;
|
||||
bottom: 10rpx;
|
||||
bottom: 18rpx;
|
||||
right: 20rpx;
|
||||
z-index: 11;
|
||||
height: 50rpx;
|
||||
|
@ -136,19 +322,4 @@
|
|||
color: #fff;
|
||||
}
|
||||
}
|
||||
.goods-list {
|
||||
&:nth-last-of-type(1) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
.goods-sm-box {
|
||||
margin: 0 auto;
|
||||
box-sizing: border-box;
|
||||
.goods-card-box {
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
width: 33.3%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -70,8 +70,8 @@
|
|||
default() {},
|
||||
},
|
||||
});
|
||||
const { mode, goodsFields, mpliveIds } = props.data ?? {};
|
||||
const { marginLeft, marginRight } = props.styles ?? {};
|
||||
const { mode, goodsFields, mpliveIds } = props.data || {};
|
||||
const { marginLeft, marginRight } = props.styles || {};
|
||||
|
||||
async function getLiveListByIds(ids) {
|
||||
const { data } = await sheep.$api.app.mplive.getRoomList(ids);
|
||||
|
|
|
@ -1,363 +1,343 @@
|
|||
<!-- 装修基础组件:菜单导航(金刚区) -->
|
||||
<template>
|
||||
<!-- 包裹层 -->
|
||||
<view
|
||||
class="ui-swiper"
|
||||
:class="[props.mode, props.bg, props.ui]"
|
||||
:style="[{ height: swiperHeight + (menuList.length > 1 ? 50 : 0) + 'rpx' }]"
|
||||
>
|
||||
<!-- 轮播 -->
|
||||
<swiper
|
||||
:circular="props.circular"
|
||||
:current="state.cur"
|
||||
:autoplay="props.autoplay"
|
||||
:interval="props.interval"
|
||||
:duration="props.duration"
|
||||
:style="[{ height: swiperHeight + 'rpx' }]"
|
||||
@change="swiperChange"
|
||||
>
|
||||
<swiper-item
|
||||
v-for="(arr, index) in menuList"
|
||||
:key="index"
|
||||
:class="{ cur: state.cur == index }"
|
||||
>
|
||||
<!-- 宫格 -->
|
||||
<view class="grid-wrap">
|
||||
<view
|
||||
v-for="(item, index) in arr"
|
||||
:key="index"
|
||||
class="grid-item ss-flex ss-flex-col ss-col-center ss-row-center"
|
||||
:style="[{ width: `${100 * (1 / data.column)}%`, height: '200rpx' }]"
|
||||
hover-class="ss-hover-btn"
|
||||
@tap="sheep.$router.go(item.url)"
|
||||
>
|
||||
<view class="menu-box ss-flex ss-flex-col ss-col-center ss-row-center">
|
||||
<view
|
||||
v-if="item.badge.show"
|
||||
class="tag-box"
|
||||
:style="[{ background: item.badge.bgColor, color: item.badge.textColor }]"
|
||||
>
|
||||
{{ item.badge.text }}
|
||||
</view>
|
||||
<image
|
||||
v-if="item.iconUrl"
|
||||
class="menu-icon"
|
||||
:style="[
|
||||
<!-- 包裹层 -->
|
||||
<view class="ui-swiper" :class="[props.mode, props.ui]"
|
||||
:style="[bgStyle, { height: swiperHeight + (menuList.length > 1 ? 50 : 0) + 'rpx' }]">
|
||||
<!-- 轮播 -->
|
||||
<swiper :circular="props.circular" :current="state.cur" :autoplay="props.autoplay" :interval="props.interval"
|
||||
:duration="props.duration" :style="[{ height: swiperHeight + 'rpx' }]" @change="swiperChange">
|
||||
<swiper-item v-for="(arr, index) in menuList" :key="index" :class="{ cur: state.cur == index }">
|
||||
<!-- 宫格 -->
|
||||
<view class="grid-wrap">
|
||||
<view v-for="(item, index) in arr" :key="index"
|
||||
class="grid-item ss-flex ss-flex-col ss-col-center ss-row-center"
|
||||
:style="[{ width: `${100 * (1 / data.column)}%`, height: '200rpx' }]" hover-class="ss-hover-btn"
|
||||
@tap="sheep.$router.go(item.url)">
|
||||
<view class="menu-box ss-flex ss-flex-col ss-col-center ss-row-center">
|
||||
<view v-if="item.badge.show" class="tag-box"
|
||||
:style="[{ background: item.badge.bgColor, color: item.badge.textColor }]">
|
||||
{{ item.badge.text }}
|
||||
</view>
|
||||
<image v-if="item.iconUrl" class="menu-icon" :style="[
|
||||
{
|
||||
width: props.iconSize + 'rpx',
|
||||
height: props.iconSize + 'rpx',
|
||||
},
|
||||
]"
|
||||
:src="sheep.$url.cdn(item.iconUrl)"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view
|
||||
v-if="data.layout === 'iconText'"
|
||||
class="menu-title"
|
||||
:style="[{ color: item.titleColor }]"
|
||||
>
|
||||
{{ item.title }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<!-- 指示点 -->
|
||||
<template v-if="menuList.length > 1">
|
||||
<view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle != 'tag'">
|
||||
<view
|
||||
class="line-box"
|
||||
v-for="(item, index) in menuList.length"
|
||||
:key="index"
|
||||
:class="[state.cur == index ? 'cur' : '', props.dotCur]"
|
||||
></view>
|
||||
</view>
|
||||
<view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle == 'tag'">
|
||||
<view class="ui-tag radius" :class="[props.dotCur]" style="pointer-events: none">
|
||||
<view style="transform: scale(0.7)">{{ state.cur + 1 }} / {{ menuList.length }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
]" :src="sheep.$url.cdn(item.iconUrl)" mode="aspectFill"></image>
|
||||
<view v-if="data.layout === 'iconText'" class="menu-title"
|
||||
:style="[{ color: item.titleColor }]">
|
||||
{{ item.title }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<!-- 指示点 -->
|
||||
<template v-if="menuList.length > 1">
|
||||
<view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle != 'tag'">
|
||||
<view class="line-box" v-for="(item, index) in menuList.length" :key="index"
|
||||
:class="[state.cur == index ? 'cur' : '', props.dotCur]"></view>
|
||||
</view>
|
||||
<view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle == 'tag'">
|
||||
<view class="ui-tag radius" :class="[props.dotCur]" style="pointer-events: none">
|
||||
<view style="transform: scale(0.7)">{{ state.cur + 1 }} / {{ menuList.length }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
/**
|
||||
* 轮播menu
|
||||
*
|
||||
* @property {Boolean} circular = false - 是否采用衔接滑动,即播放到末尾后重新回到开头
|
||||
* @property {Boolean} autoplay = true - 是否自动切换
|
||||
* @property {Number} interval = 5000 - 自动切换时间间隔
|
||||
* @property {Number} duration = 500 - 滑动动画时长,app-nvue不支持
|
||||
* @property {Array} list = [] - 轮播数据
|
||||
* @property {String} ui = '' - 样式class
|
||||
* @property {String} mode - 模式
|
||||
* @property {String} dotStyle - 指示点样式
|
||||
* @property {String} dotCur= 'ui-BG-Main' - 当前指示点样式,默认主题色
|
||||
* @property {String} bg - 背景
|
||||
*
|
||||
* @property {String|Number} col = 4 - 一行数量
|
||||
* @property {String|Number} row = 1 - 几行
|
||||
* @property {String} hasBorder - 是否有边框
|
||||
* @property {String} borderColor - 边框颜色
|
||||
* @property {String} background - 背景
|
||||
* @property {String} hoverClass - 按压样式类
|
||||
* @property {String} hoverStayTime - 动画时间
|
||||
*
|
||||
* @property {Array} list - 导航列表
|
||||
* @property {Number} iconSize - 图标大小
|
||||
* @property {String} color - 标题颜色
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* 轮播menu
|
||||
*
|
||||
* @property {Boolean} circular = false - 是否采用衔接滑动,即播放到末尾后重新回到开头
|
||||
* @property {Boolean} autoplay = true - 是否自动切换
|
||||
* @property {Number} interval = 5000 - 自动切换时间间隔
|
||||
* @property {Number} duration = 500 - 滑动动画时长,app-nvue不支持
|
||||
* @property {Array} list = [] - 轮播数据
|
||||
* @property {String} ui = '' - 样式class
|
||||
* @property {String} mode - 模式
|
||||
* @property {String} dotStyle - 指示点样式
|
||||
* @property {String} dotCur= 'ui-BG-Main' - 当前指示点样式,默认主题色
|
||||
* @property {String} bg - 背景
|
||||
*
|
||||
* @property {String|Number} col = 4 - 一行数量
|
||||
* @property {String|Number} row = 1 - 几行
|
||||
* @property {String} hasBorder - 是否有边框
|
||||
* @property {String} borderColor - 边框颜色
|
||||
* @property {String} background - 背景
|
||||
* @property {String} hoverClass - 按压样式类
|
||||
* @property {String} hoverStayTime - 动画时间
|
||||
*
|
||||
* @property {Array} list - 导航列表
|
||||
* @property {Number} iconSize - 图标大小
|
||||
* @property {String} color - 标题颜色
|
||||
*
|
||||
*/
|
||||
|
||||
import { reactive, computed } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import {
|
||||
reactive,
|
||||
computed
|
||||
} from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
|
||||
// 数据
|
||||
const state = reactive({
|
||||
cur: 0,
|
||||
});
|
||||
// 数据
|
||||
const state = reactive({
|
||||
cur: 0,
|
||||
});
|
||||
|
||||
// 接收参数
|
||||
// 接收参数
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
circular: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
autoplay: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
interval: {
|
||||
type: Number,
|
||||
default: 5000,
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 500,
|
||||
},
|
||||
const props = defineProps({
|
||||
// 装修数据
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 装修样式
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
circular: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
autoplay: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
interval: {
|
||||
type: Number,
|
||||
default: 5000,
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 500,
|
||||
},
|
||||
ui: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
mode: {
|
||||
//default
|
||||
type: String,
|
||||
default: 'default',
|
||||
},
|
||||
dotStyle: {
|
||||
type: String,
|
||||
default: 'long', //default long tag
|
||||
},
|
||||
dotCur: {
|
||||
type: String,
|
||||
default: 'ui-BG-Main',
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 300,
|
||||
},
|
||||
// 是否有边框
|
||||
hasBorder: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
// 边框颜色
|
||||
borderColor: {
|
||||
type: String,
|
||||
default: 'red',
|
||||
},
|
||||
background: {
|
||||
type: String,
|
||||
default: 'blue',
|
||||
},
|
||||
hoverClass: {
|
||||
type: String,
|
||||
default: 'ss-hover-class', //'none'为没有hover效果
|
||||
},
|
||||
// 一排宫格数
|
||||
col: {
|
||||
type: [Number, String],
|
||||
default: 3,
|
||||
},
|
||||
iconSize: {
|
||||
type: Number,
|
||||
default: 80,
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#000',
|
||||
},
|
||||
});
|
||||
|
||||
ui: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
mode: {
|
||||
//default
|
||||
type: String,
|
||||
default: 'default',
|
||||
},
|
||||
dotStyle: {
|
||||
type: String,
|
||||
default: 'long', //default long tag
|
||||
},
|
||||
dotCur: {
|
||||
type: String,
|
||||
default: 'ui-BG-Main',
|
||||
},
|
||||
bg: {
|
||||
type: String,
|
||||
default: 'bg-none',
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 300,
|
||||
},
|
||||
// 设置背景样式
|
||||
const bgStyle = computed(() => {
|
||||
// 直接从 props.styles 解构
|
||||
const {
|
||||
bgType,
|
||||
bgImg,
|
||||
bgColor
|
||||
} = props.styles;
|
||||
|
||||
// 是否有边框
|
||||
hasBorder: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
// 边框颜色
|
||||
borderColor: {
|
||||
type: String,
|
||||
default: 'red',
|
||||
},
|
||||
background: {
|
||||
type: String,
|
||||
default: 'blue',
|
||||
},
|
||||
hoverClass: {
|
||||
type: String,
|
||||
default: 'ss-hover-class', //'none'为没有hover效果
|
||||
},
|
||||
// 一排宫格数
|
||||
col: {
|
||||
type: [Number, String],
|
||||
default: 3,
|
||||
},
|
||||
iconSize: {
|
||||
type: Number,
|
||||
default: 80,
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#000',
|
||||
},
|
||||
});
|
||||
// 根据 bgType 返回相应的样式
|
||||
return {
|
||||
background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
|
||||
};
|
||||
});
|
||||
|
||||
// 生成数据
|
||||
const menuList = computed(() => splitData(props.data.list, props.data.row * props.data.column));
|
||||
const swiperHeight = computed(() => props.data.row * (props.data.layout === 'iconText' ? 200 : 180));
|
||||
const windowWidth = sheep.$platform.device.windowWidth;
|
||||
// 生成数据
|
||||
const menuList = computed(() => splitData(props.data.list, props.data.row * props.data.column));
|
||||
const swiperHeight = computed(() => props.data.row * (props.data.layout === 'iconText' ? 200 : 180));
|
||||
const windowWidth = sheep.$platform.device.windowWidth;
|
||||
|
||||
// current 改变时会触发 change 事件
|
||||
const swiperChange = (e) => {
|
||||
state.cur = e.detail.current;
|
||||
};
|
||||
// current 改变时会触发 change 事件
|
||||
const swiperChange = (e) => {
|
||||
state.cur = e.detail.current;
|
||||
};
|
||||
|
||||
// 重组数据
|
||||
const splitData = (oArr = [], length = 1) => {
|
||||
let arr = [];
|
||||
let minArr = [];
|
||||
oArr.forEach((c) => {
|
||||
if (minArr.length === length) {
|
||||
minArr = [];
|
||||
}
|
||||
if (minArr.length === 0) {
|
||||
arr.push(minArr);
|
||||
}
|
||||
minArr.push(c);
|
||||
});
|
||||
// 重组数据
|
||||
const splitData = (oArr = [], length = 1) => {
|
||||
let arr = [];
|
||||
let minArr = [];
|
||||
oArr.forEach((c) => {
|
||||
if (minArr.length === length) {
|
||||
minArr = [];
|
||||
}
|
||||
if (minArr.length === 0) {
|
||||
arr.push(minArr);
|
||||
}
|
||||
minArr.push(c);
|
||||
});
|
||||
|
||||
return arr;
|
||||
};
|
||||
return arr;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.grid-wrap {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
.menu-box {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
transform: translate(0, 0);
|
||||
.grid-wrap {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tag-box {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
right: -6rpx;
|
||||
font-size: 2em;
|
||||
line-height: 1;
|
||||
padding: 0.4em 0.6em 0.3em;
|
||||
transform: scale(0.4) translateX(0.5em) translatey(-0.6em);
|
||||
transform-origin: 100% 0;
|
||||
border-radius: 200rpx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.menu-box {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
transform: translate(0, 0);
|
||||
|
||||
.menu-icon {
|
||||
transform: translate(0, 0);
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
.tag-box {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
right: -6rpx;
|
||||
font-size: 2em;
|
||||
line-height: 1;
|
||||
padding: 0.4em 0.6em 0.3em;
|
||||
transform: scale(0.4) translateX(0.5em) translatey(-0.6em);
|
||||
transform-origin: 100% 0;
|
||||
border-radius: 200rpx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.menu-title {
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
.menu-icon {
|
||||
transform: translate(0, 0);
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
::v-deep(.ui-swiper) {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
.menu-title {
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-swiper-dot {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 20rpx;
|
||||
height: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 2;
|
||||
::v-deep(.ui-swiper) {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
&.default .line-box {
|
||||
display: inline-flex;
|
||||
border-radius: 50rpx;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border: 2px solid transparent;
|
||||
margin: 0 10rpx;
|
||||
opacity: 0.3;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.ui-swiper-dot {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 20rpx;
|
||||
height: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 2;
|
||||
|
||||
&.cur {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
opacity: 1;
|
||||
border: 0px solid transparent;
|
||||
}
|
||||
&.default .line-box {
|
||||
display: inline-flex;
|
||||
border-radius: 50rpx;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border: 2px solid transparent;
|
||||
margin: 0 10rpx;
|
||||
opacity: 0.3;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&.cur::after {
|
||||
content: '';
|
||||
border-radius: 50rpx;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
&.cur {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
opacity: 1;
|
||||
border: 0px solid transparent;
|
||||
}
|
||||
|
||||
&.long .line-box {
|
||||
display: inline-block;
|
||||
border-radius: 100rpx;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
margin: 0 10rpx;
|
||||
opacity: 0.3;
|
||||
position: relative;
|
||||
&.cur::after {
|
||||
content: '';
|
||||
border-radius: 50rpx;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&.cur {
|
||||
width: 24rpx;
|
||||
opacity: 1;
|
||||
}
|
||||
&.long .line-box {
|
||||
display: inline-block;
|
||||
border-radius: 100rpx;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
margin: 0 10rpx;
|
||||
opacity: 0.3;
|
||||
position: relative;
|
||||
|
||||
&.cur::after {
|
||||
}
|
||||
}
|
||||
&.cur {
|
||||
width: 24rpx;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.line {
|
||||
bottom: 20rpx;
|
||||
&.cur::after {}
|
||||
}
|
||||
|
||||
.line-box {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 3px;
|
||||
opacity: 0.3;
|
||||
position: relative;
|
||||
&.line {
|
||||
bottom: 20rpx;
|
||||
|
||||
&.cur {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.line-box {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 3px;
|
||||
opacity: 0.3;
|
||||
position: relative;
|
||||
|
||||
&.tag {
|
||||
justify-content: flex-end;
|
||||
position: absolute;
|
||||
bottom: 20rpx;
|
||||
right: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
&.cur {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.tag {
|
||||
justify-content: flex-end;
|
||||
position: absolute;
|
||||
bottom: 20rpx;
|
||||
right: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,82 +1,104 @@
|
|||
<!-- 装修基础组件:宫格导航 -->
|
||||
<template>
|
||||
<uni-grid :showBorder="Boolean(data.border)" :column="data.column">
|
||||
<uni-grid-item
|
||||
v-for="(item, index) in data.list"
|
||||
:key="index"
|
||||
@tap="sheep.$router.go(item.url)"
|
||||
>
|
||||
<view class="grid-item-box ss-flex ss-flex-col ss-row-center ss-col-center">
|
||||
<view class="img-box">
|
||||
<view
|
||||
class="tag-box"
|
||||
v-if="item.badge.show"
|
||||
:style="[{ background: item.badge.bgColor, color: item.badge.textColor }]"
|
||||
>
|
||||
{{ item.badge.text }}
|
||||
</view>
|
||||
<image class="menu-image" :src="sheep.$url.cdn(item.iconUrl)"></image>
|
||||
</view>
|
||||
<view :style="[bgStyle, { marginLeft: `${data.space}px` }]">
|
||||
<uni-grid :showBorder="Boolean(data.border)" :column="data.column">
|
||||
<uni-grid-item v-for="(item, index) in data.list" :key="index" @tap="sheep.$router.go(item.url)">
|
||||
<view class="grid-item-box ss-flex ss-flex-col ss-row-center ss-col-center">
|
||||
<view class="img-box">
|
||||
<view class="tag-box" v-if="item.badge.show"
|
||||
:style="[{ background: item.badge.bgColor, color: item.badge.textColor }]">
|
||||
{{ item.badge.text }}
|
||||
</view>
|
||||
<image class="menu-image" :src="sheep.$url.cdn(item.iconUrl)"></image>
|
||||
</view>
|
||||
|
||||
<view class="title-box ss-flex ss-flex-col ss-row-center ss-col-center">
|
||||
<view class="grid-text" :style="[{ color: item.titleColor }]">
|
||||
{{ item.title }}
|
||||
</view>
|
||||
<view class="grid-tip" :style="[{ color: item.subtitleColor }]">
|
||||
{{ item.subtitle }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-grid-item>
|
||||
</uni-grid>
|
||||
</view>
|
||||
|
||||
<view class="title-box ss-flex ss-flex-col ss-row-center ss-col-center">
|
||||
<view class="grid-text" :style="[{ color: item.titleColor }]">
|
||||
{{ item.title }}
|
||||
</view>
|
||||
<view class="grid-tip" :style="[{ color: item.subtitleColor }]">
|
||||
{{ item.subtitle }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-grid-item>
|
||||
</uni-grid>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import sheep from '@/sheep';
|
||||
import {
|
||||
computed
|
||||
} from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
});
|
||||
const props = defineProps({
|
||||
// 装修数据
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 装修样式
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
// 设置背景样式
|
||||
const bgStyle = computed(() => {
|
||||
// 直接从 props.styles 解构
|
||||
const {
|
||||
bgType,
|
||||
bgImg,
|
||||
bgColor
|
||||
} = props.styles;
|
||||
|
||||
// 根据 bgType 返回相应的样式
|
||||
return {
|
||||
background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.menu-image {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
.grid-item-box {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
.img-box {
|
||||
position: relative;
|
||||
.tag-box {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
right: 0;
|
||||
font-size: 2em;
|
||||
line-height: 1;
|
||||
padding: 0.4em 0.6em 0.3em;
|
||||
transform: scale(0.4) translateX(0.5em) translatey(-0.6em);
|
||||
transform-origin: 100% 0;
|
||||
border-radius: 200rpx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
.menu-image {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.title-box {
|
||||
.grid-tip {
|
||||
font-size: 24rpx;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.grid-item-box {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
|
||||
.img-box {
|
||||
position: relative;
|
||||
|
||||
.tag-box {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
right: 0;
|
||||
font-size: 2em;
|
||||
line-height: 1;
|
||||
padding: 0.4em 0.6em 0.3em;
|
||||
transform: scale(0.4) translateX(0.5em) translatey(-0.6em);
|
||||
transform-origin: 100% 0;
|
||||
border-radius: 200rpx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.title-box {
|
||||
.grid-tip {
|
||||
font-size: 24rpx;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,6 +1,6 @@
|
|||
<!-- 装修用户组件:用户订单 -->
|
||||
<template>
|
||||
<view class="ss-order-menu-wrap ss-flex ss-col-center">
|
||||
<view class="ss-order-menu-wrap ss-flex ss-col-center" :style="[style, { marginLeft: `${data.space}px` }]">
|
||||
<view
|
||||
class="menu-item ss-flex-1 ss-flex-col ss-row-center ss-col-center"
|
||||
v-for="item in orderMap"
|
||||
|
@ -67,8 +67,32 @@
|
|||
path: '/pages/order/list',
|
||||
},
|
||||
];
|
||||
|
||||
// 接收参数
|
||||
const props = defineProps({
|
||||
// 装修数据
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 装修样式
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
// 设置角标
|
||||
const numData = computed(() => sheep.$store('user').numData);
|
||||
// 设置背景样式
|
||||
const style = computed(() => {
|
||||
// 直接从 props.styles 解构
|
||||
const { bgType, bgImg, bgColor } = props.styles;
|
||||
// 根据 bgType 返回相应的样式
|
||||
return {
|
||||
background: bgType === 'img'
|
||||
? `url(${bgImg}) no-repeat top center / 100% 100%`
|
||||
: bgColor
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -1,86 +1,166 @@
|
|||
<!-- 装修组件 - 秒杀 -->
|
||||
<!-- 装修商品组件:【秒杀】商品卡片 -->
|
||||
<template>
|
||||
<!-- 商品卡片 -->
|
||||
<view>
|
||||
<!-- 样式一:三列 - 上图下文 -->
|
||||
<!-- 布局1. 单列大图(上图,下内容)-->
|
||||
<view
|
||||
v-if="layoutType === 'threeCol'"
|
||||
class="goods-sm-box ss-flex ss-flex-wrap"
|
||||
:style="[{ margin: '-' + data.space + 'rpx' }]"
|
||||
v-if="layoutType === LayoutTypeEnum.ONE_COL_BIG_IMG && state.spuList.length"
|
||||
class="goods-sl-box"
|
||||
>
|
||||
<view
|
||||
v-for="product in productList"
|
||||
:key="product.id"
|
||||
class="goods-card-box"
|
||||
:style="[
|
||||
{
|
||||
padding: data.space + 'rpx',
|
||||
},
|
||||
]"
|
||||
class="goods-box"
|
||||
v-for="item in state.spuList"
|
||||
:key="item.id"
|
||||
:style="[{ marginBottom: data.space * 2 + 'rpx' }]"
|
||||
>
|
||||
<s-goods-column
|
||||
class="goods-card"
|
||||
size="sm"
|
||||
class=""
|
||||
size="sl"
|
||||
:goodsFields="data.fields"
|
||||
:tagStyle="tagStyle"
|
||||
:data="product"
|
||||
:tagStyle="data.badge"
|
||||
:data="item"
|
||||
:titleColor="data.fields.name?.color"
|
||||
:subTitleColor="data.fields.introduction.color"
|
||||
:topRadius="data.borderRadiusTop"
|
||||
:bottomRadius="data.borderRadiusBottom"
|
||||
@click="
|
||||
sheep.$router.go('/pages/goods/seckill', {
|
||||
id: props.data.activityId,
|
||||
})
|
||||
"
|
||||
></s-goods-column>
|
||||
@click="sheep.$router.go('/pages/goods/seckill', { id: item.activityId })"
|
||||
>
|
||||
<!-- 购买按钮 -->
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" :style="[buyStyle]">
|
||||
{{ btnBuy.type === 'text' ? btnBuy.text : '' }}
|
||||
</button>
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 样式二:一列 - 左图右文 -->
|
||||
<view class="goods-box" v-if="layoutType === 'oneCol'">
|
||||
|
||||
<!-- 布局2. 单列小图(左图,右内容) -->
|
||||
<view
|
||||
v-if="layoutType === LayoutTypeEnum.ONE_COL_SMALL_IMG && state.spuList.length"
|
||||
class="goods-lg-box"
|
||||
>
|
||||
<view
|
||||
class="goods-list"
|
||||
v-for="(product, index) in productList"
|
||||
:key="index"
|
||||
:style="[{ marginBottom: space + 'px' }]"
|
||||
class="goods-box"
|
||||
:style="[{ marginBottom: data.space + 'px' }]"
|
||||
v-for="item in state.spuList"
|
||||
:key="item.id"
|
||||
>
|
||||
<s-goods-column
|
||||
class="goods-card"
|
||||
size="lg"
|
||||
:goodsFields="data.fields"
|
||||
:tagStyle="tagStyle"
|
||||
:data="product"
|
||||
:data="item"
|
||||
:tagStyle="data.badge"
|
||||
:titleColor="data.fields.name?.color"
|
||||
:subTitleColor="data.fields.introduction?.color"
|
||||
:subTitleColor="data.fields.introduction.color"
|
||||
:topRadius="data.borderRadiusTop"
|
||||
:bottomRadius="data.borderRadiusBottom"
|
||||
@click="
|
||||
sheep.$router.go('/pages/goods/seckill', {
|
||||
id: props.data.activityId,
|
||||
})
|
||||
"
|
||||
@tap="sheep.$router.go('/pages/goods/seckill', { id: item.activityId })"
|
||||
>
|
||||
<!-- 购买按钮 -->
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" :style="[buyStyle]">
|
||||
{{ btnBuy?.type === 'text' ? btnBuy.text : '' }}
|
||||
{{ btnBuy.type === 'text' ? btnBuy.text : '' }}
|
||||
</button>
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 布局3. 双列(每一列:上图,下内容)-->
|
||||
<view
|
||||
v-if="layoutType === LayoutTypeEnum.TWO_COL && state.spuList.length"
|
||||
class="goods-md-wrap ss-flex ss-flex-wrap ss-col-top"
|
||||
>
|
||||
<view class="goods-list-box">
|
||||
<view
|
||||
class="left-list"
|
||||
:style="[{ paddingRight: data.space + 'rpx', marginBottom: data.space + 'px' }]"
|
||||
v-for="item in state.leftSpuList"
|
||||
:key="item.id"
|
||||
>
|
||||
<s-goods-column
|
||||
class="goods-md-box"
|
||||
size="md"
|
||||
:goodsFields="data.fields"
|
||||
:tagStyle="data.badge"
|
||||
:data="item"
|
||||
:titleColor="data.fields.name?.color"
|
||||
:subTitleColor="data.fields.introduction.color"
|
||||
:topRadius="data.borderRadiusTop"
|
||||
:bottomRadius="data.borderRadiusBottom"
|
||||
:titleWidth="330 - marginLeft - marginRight"
|
||||
@click="sheep.$router.go('/pages/goods/seckill', { id: item.activityId })"
|
||||
@getHeight="calculateGoodsColumn($event, 'left')"
|
||||
>
|
||||
<!-- 购买按钮 -->
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" :style="[buyStyle]">
|
||||
{{ btnBuy.type === 'text' ? btnBuy.text : '' }}
|
||||
</button>
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-list-box">
|
||||
<view
|
||||
class="right-list"
|
||||
:style="[{ paddingLeft: data.space + 'rpx', marginBottom: data.space + 'px' }]"
|
||||
v-for="item in state.rightSpuList"
|
||||
:key="item.id"
|
||||
>
|
||||
<s-goods-column
|
||||
class="goods-md-box"
|
||||
size="md"
|
||||
:goodsFields="data.fields"
|
||||
:tagStyle="data.badge"
|
||||
:data="item"
|
||||
:titleColor="data.fields.name?.color"
|
||||
:subTitleColor="data.fields.introduction.color"
|
||||
:topRadius="data.borderRadiusTop"
|
||||
:bottomRadius="data.borderRadiusBottom"
|
||||
:titleWidth="330 - marginLeft - marginRight"
|
||||
@click="sheep.$router.go('/pages/goods/seckill', { id: item.activityId })"
|
||||
@getHeight="calculateGoodsColumn($event, 'right')"
|
||||
>
|
||||
<!-- 购买按钮 -->
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" :style="[buyStyle]">
|
||||
{{ btnBuy.type === 'text' ? btnBuy.text : '' }}
|
||||
</button>
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
/**
|
||||
* 秒杀商品列表
|
||||
*
|
||||
* @property {Array} list 商品列表
|
||||
* 商品卡片
|
||||
*/
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import SeckillApi from "@/sheep/api/promotion/seckill";
|
||||
import SpuApi from "@/sheep/api/product/spu";
|
||||
import SeckillApi from '@/sheep/api/promotion/seckill';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
|
||||
// 接收参数
|
||||
// 布局类型
|
||||
const LayoutTypeEnum = {
|
||||
// 单列大图
|
||||
ONE_COL_BIG_IMG: 'oneColBigImg',
|
||||
// 双列
|
||||
TWO_COL: 'twoCol',
|
||||
// 单列小图
|
||||
ONE_COL_SMALL_IMG: 'oneColSmallImg',
|
||||
};
|
||||
|
||||
const state = reactive({
|
||||
spuList: [],
|
||||
leftSpuList: [],
|
||||
rightSpuList: [],
|
||||
});
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
|
@ -92,18 +172,19 @@
|
|||
},
|
||||
});
|
||||
|
||||
let { layoutType, tagStyle, btnBuy, space } = props.data;
|
||||
let { marginLeft, marginRight } = props.styles;
|
||||
const { layoutType, btnBuy, activityIds } = props.data || {};
|
||||
const { marginLeft, marginRight } = props.styles || {};
|
||||
|
||||
// 购买按钮样式
|
||||
const buyStyle = computed(() => {
|
||||
let btnBuy = props.data.btnBuy;
|
||||
if (btnBuy?.type === 'text') {
|
||||
if (btnBuy.type === 'text') {
|
||||
// 文字按钮:线性渐变背景颜色
|
||||
return {
|
||||
background: `linear-gradient(to right, ${btnBuy.bgBeginColor}, ${btnBuy.bgEndColor})`,
|
||||
};
|
||||
}
|
||||
if (btnBuy?.type === 'img') {
|
||||
if (btnBuy.type === 'img') {
|
||||
// 图片按钮
|
||||
return {
|
||||
width: '54rpx',
|
||||
height: '54rpx',
|
||||
|
@ -113,30 +194,124 @@
|
|||
}
|
||||
});
|
||||
|
||||
// 商品列表
|
||||
const productList = ref([]);
|
||||
// 查询秒杀活动商品
|
||||
//region 商品瀑布流布局
|
||||
// 下一个要处理的商品索引
|
||||
let count = 0;
|
||||
// 左列的高度
|
||||
let leftHeight = 0;
|
||||
// 右列的高度
|
||||
let rightHeight = 0;
|
||||
|
||||
/**
|
||||
* 计算商品在左列还是右列
|
||||
* @param height 商品的高度
|
||||
* @param where 添加到哪一列
|
||||
*/
|
||||
function calculateGoodsColumn(height = 0, where = 'left') {
|
||||
// 处理完
|
||||
if (!state.spuList[count]) return;
|
||||
// 增加列的高度
|
||||
if (where === 'left') leftHeight += height;
|
||||
if (where === 'right') rightHeight += height;
|
||||
// 添加到矮的一列
|
||||
if (leftHeight <= rightHeight) {
|
||||
state.leftSpuList.push(state.spuList[count]);
|
||||
} else {
|
||||
state.rightSpuList.push(state.spuList[count]);
|
||||
}
|
||||
// 计数
|
||||
count++;
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
/**
|
||||
* 根据商品编号列表,获取商品列表
|
||||
* @param ids 商品编号列表
|
||||
* @return {Promise<undefined>} 商品列表
|
||||
*/
|
||||
async function getSeckillActivityDetailList(ids) {
|
||||
const { data } = await SeckillApi.getSeckillActivityListByIds(ids);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据商品编号,获取商品详情
|
||||
* @param ids 商品编号列表
|
||||
* @return {Promise<undefined>} 商品列表
|
||||
*/
|
||||
async function getSpuDetail(ids) {
|
||||
const { data: spu } = await SpuApi.getSpuDetail(ids);
|
||||
return spu;
|
||||
}
|
||||
|
||||
// 初始化
|
||||
onMounted(async () => {
|
||||
// todo:@owen 与Yudao结构不一致,待重构
|
||||
const { data: activity } = await SeckillApi.getSeckillActivity(props.data.activityId);
|
||||
const { data: spu } = await SpuApi.getSpuDetail(activity.spuId)
|
||||
productList.value = [spu];
|
||||
// 加载活动列表
|
||||
const activityList = await getSeckillActivityDetailList(activityIds.join(','));
|
||||
// 循环获取活动商品SPU详情并添加到spuList
|
||||
for (const activity of activityList) {
|
||||
state.spuList.push(await getSpuDetail(activity.spuId));
|
||||
}
|
||||
|
||||
// 循环活动列表
|
||||
activityList.forEach((activity) => {
|
||||
// 提取活动价格
|
||||
const seckillPrice = activity.seckillPrice || Infinity;
|
||||
// 查找对应的 spu 并更新价格
|
||||
const spu = state.spuList.find((spu) => activity.spuId === spu.id);
|
||||
if (spu) {
|
||||
// 赋值最低价格
|
||||
spu.price = Math.min(seckillPrice, spu.price);
|
||||
// 赋值活动ID,为了点击跳转详情页
|
||||
spu.activityId = activity.id;
|
||||
}
|
||||
});
|
||||
|
||||
// 只有双列布局时需要
|
||||
if (layoutType === LayoutTypeEnum.TWO_COL) {
|
||||
// 分列
|
||||
calculateGoodsColumn();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header-box {
|
||||
height: 100rpx;
|
||||
.goods-md-wrap {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.goods-list {
|
||||
position: relative;
|
||||
&:nth-last-child(1) {
|
||||
.goods-list-box {
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.left-list {
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.right-list {
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.goods-box {
|
||||
&:nth-last-of-type(1) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-md-box,
|
||||
.goods-sl-box,
|
||||
.goods-lg-box {
|
||||
position: relative;
|
||||
|
||||
.cart-btn {
|
||||
position: absolute;
|
||||
bottom: 10rpx;
|
||||
bottom: 18rpx;
|
||||
right: 20rpx;
|
||||
z-index: 11;
|
||||
height: 50rpx;
|
||||
|
@ -147,14 +322,4 @@
|
|||
color: #fff;
|
||||
}
|
||||
}
|
||||
.goods-sm-box {
|
||||
margin: 0 auto;
|
||||
box-sizing: border-box;
|
||||
.goods-card-box {
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
width: 33.3%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -5,7 +5,11 @@
|
|||
<view class="ss-modal-box bg-white ss-flex-col">
|
||||
<view class="modal-header ss-flex ss-col-center">
|
||||
<view class="header-left ss-m-r-30">
|
||||
<image class="sku-image" :src="sheep.$url.cdn(state.selectedSku.picUrl || goodsInfo.picUrl)" mode="aspectFill" />
|
||||
<image
|
||||
class="sku-image"
|
||||
:src="sheep.$url.cdn(state.selectedSku.picUrl || goodsInfo.picUrl)"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</view>
|
||||
<view class="header-right ss-flex-col ss-row-between ss-flex-1">
|
||||
<view class="goods-title ss-line-2">
|
||||
|
@ -22,7 +26,13 @@
|
|||
</view>
|
||||
</view>
|
||||
<view class="header-right-bottom ss-flex ss-col-center ss-row-between">
|
||||
<view class="price-text"> {{ fen2yuan(goodsInfo.price) }}</view>
|
||||
<view class="price-text">
|
||||
{{
|
||||
fen2yuan(
|
||||
state.selectedSku.price || goodsInfo.price || state.selectedSku.marketPrice,
|
||||
)
|
||||
}}</view
|
||||
>
|
||||
|
||||
<view class="stock-text ss-m-l-20">
|
||||
库存{{ state.selectedSku.stock || goodsInfo.stock }}件
|
||||
|
@ -35,22 +45,35 @@
|
|||
<view class="sku-item ss-m-b-20" v-for="property in propertyList" :key="property.id">
|
||||
<view class="label-text ss-m-b-20">{{ property.name }}</view>
|
||||
<view class="ss-flex ss-col-center ss-flex-wrap">
|
||||
<button class="ss-reset-button spec-btn" v-for="value in property.values" :class="[
|
||||
<button
|
||||
class="ss-reset-button spec-btn"
|
||||
v-for="value in property.values"
|
||||
:class="[
|
||||
{
|
||||
'checked-btn': state.currentPropertyArray[property.id] === value.id,
|
||||
},
|
||||
{
|
||||
'disabled-btn': value.disabled === true,
|
||||
},
|
||||
]" :key="value.id" :disabled="value.disabled === true" @tap="onSelectSku(property.id, value.id)">
|
||||
]"
|
||||
:key="value.id"
|
||||
:disabled="value.disabled === true"
|
||||
@tap="onSelectSku(property.id, value.id)"
|
||||
>
|
||||
{{ value.name }}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
<view class="buy-num-box ss-flex ss-col-center ss-row-between">
|
||||
<view class="label-text">购买数量</view>
|
||||
<su-number-box :min="1" :max="state.selectedSku.stock" :step="1"
|
||||
v-model="state.selectedSku.count" @change="onNumberChange($event)" activity="groupon" />
|
||||
<su-number-box
|
||||
:min="1"
|
||||
:max="state.selectedSku.stock"
|
||||
:step="1"
|
||||
v-model="state.selectedSku.count"
|
||||
@change="onNumberChange($event)"
|
||||
activity="groupon"
|
||||
/>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
@ -63,7 +86,16 @@
|
|||
<view class="btn-title">{{ grouponNum + '人团' }}</view>
|
||||
</button>
|
||||
<button class="ss-reset-button btn-tox ss-flex-col" @tap="onBuy">
|
||||
<view class="btn-price">{{ fen2yuan(goodsInfo.price) }}</view>
|
||||
<view class="btn-price">
|
||||
{{
|
||||
fen2yuan(
|
||||
state.selectedSku.price * state.selectedSku.count ||
|
||||
goodsInfo.price * state.selectedSku.count ||
|
||||
state.selectedSku.marketPrice * state.selectedSku.count ||
|
||||
goodsInfo.price,
|
||||
)
|
||||
}}
|
||||
</view>
|
||||
<view v-if="grouponAction === 'create'">立即开团</view>
|
||||
<view v-else-if="grouponAction === 'join'">参与拼团</view>
|
||||
</button>
|
||||
|
@ -77,7 +109,7 @@
|
|||
<script setup>
|
||||
import { computed, reactive, watch } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import {convertProductPropertyList, fen2yuan} from '@/sheep/hooks/useGoods';
|
||||
import { convertProductPropertyList, fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
|
||||
const headerBg = sheep.$url.css('/static/img/shop/goods/groupon-btn-long.png');
|
||||
const emits = defineEmits(['change', 'addCart', 'buy', 'close', 'ladder']);
|
||||
|
@ -88,7 +120,7 @@
|
|||
},
|
||||
goodsInfo: {
|
||||
type: Object,
|
||||
default () {},
|
||||
default() {},
|
||||
},
|
||||
grouponAction: {
|
||||
type: String,
|
||||
|
@ -111,7 +143,7 @@
|
|||
const skuList = computed(() => {
|
||||
let skuPrices = props.goodsInfo.skus;
|
||||
for (let price of skuPrices) {
|
||||
price.value_id_array = price.properties.map((item) => item.valueId)
|
||||
price.value_id_array = price.properties.map((item) => item.valueId);
|
||||
}
|
||||
return skuPrices;
|
||||
});
|
||||
|
@ -120,7 +152,8 @@
|
|||
() => state.selectedSku,
|
||||
(newVal) => {
|
||||
emits('change', newVal);
|
||||
}, {
|
||||
},
|
||||
{
|
||||
immediate: true, // 立即执行
|
||||
deep: true, // 深度监听
|
||||
},
|
||||
|
@ -215,7 +248,7 @@
|
|||
// 如果当前 property id 不存在于有库存的 SKU 中,则禁用
|
||||
for (let valueIndex in propertyList[propertyIndex]['values']) {
|
||||
propertyList[propertyIndex]['values'][valueIndex]['disabled'] =
|
||||
noChooseValueIds.indexOf(propertyList[propertyIndex]['values'][valueIndex]['id']) < 0; // true 禁用 or false 不禁用
|
||||
noChooseValueIds.indexOf(propertyList[propertyIndex]['values'][valueIndex]['id']) < 0; // true 禁用 or false 不禁用
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -245,7 +278,10 @@
|
|||
function onSelectSku(propertyId, valueId) {
|
||||
// 清空已选择
|
||||
let isChecked = true; // 选中 or 取消选中
|
||||
if (state.currentPropertyArray[propertyId] !== undefined && state.currentPropertyArray[propertyId] === valueId) {
|
||||
if (
|
||||
state.currentPropertyArray[propertyId] !== undefined &&
|
||||
state.currentPropertyArray[propertyId] === valueId
|
||||
) {
|
||||
// 点击已被选中的,删除并填充 ''
|
||||
isChecked = false;
|
||||
state.currentPropertyArray.splice(propertyId, 1, '');
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<!-- SKU 信息 -->
|
||||
<view class="ss-modal-box bg-white ss-flex-col">
|
||||
<view class="modal-header ss-flex ss-col-center">
|
||||
<!-- 规格图 -->
|
||||
<!-- 规格图片 -->
|
||||
<view class="header-left ss-m-r-30">
|
||||
<image
|
||||
class="sku-image"
|
||||
|
@ -125,10 +125,6 @@
|
|||
return skuPrices;
|
||||
});
|
||||
|
||||
if (!state.goodsInfo.is_sku) {
|
||||
state.selectedSku = state.goodsInfo.skus[0];
|
||||
}
|
||||
|
||||
watch(
|
||||
() => state.selectedSku,
|
||||
(newVal) => {
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
css: {
|
||||
// 根节点若无尺寸,自动获取父级节点
|
||||
width: sheep.$platform.device.windowWidth * 0.9,
|
||||
height: 550,
|
||||
height: 600,
|
||||
},
|
||||
views: [],
|
||||
});
|
||||
|
|
|
@ -82,12 +82,12 @@ const groupon = async (poster) => {
|
|||
type: 'text',
|
||||
text: '2人团',
|
||||
css: {
|
||||
color: '#ff0000',
|
||||
fontSize: 30,
|
||||
color: '#fff',
|
||||
fontSize: 12,
|
||||
fontFamily: 'OPPOSANS',
|
||||
position: 'fixed',
|
||||
left: width * 0.3,
|
||||
top: width * 1.32,
|
||||
left: width * 0.84,
|
||||
top: width * 1.3,
|
||||
},
|
||||
},
|
||||
// #ifndef MP-WEIXIN
|
||||
|
@ -96,7 +96,7 @@ const groupon = async (poster) => {
|
|||
text: poster.shareInfo.link,
|
||||
css: {
|
||||
position: 'fixed',
|
||||
left: width * 0.75,
|
||||
left: width * 0.5,
|
||||
top: width * 1.3,
|
||||
width: width * 0.2,
|
||||
height: width * 0.2,
|
||||
|
|
|
@ -1,100 +1,108 @@
|
|||
<!-- 装修商品组件:标题栏 -->
|
||||
<template>
|
||||
<view
|
||||
class="ss-title-wrap ss-flex ss-col-center"
|
||||
:class="[state.typeMap[data.textAlign]]"
|
||||
:style="[elStyles]"
|
||||
>
|
||||
<view class="title-content">
|
||||
<!-- 主标题 -->
|
||||
<view v-if="data.title" class="title-text" :style="[titleStyles]">{{ data.title }}</view>
|
||||
<!-- 副标题 -->
|
||||
<view v-if="data.description" :style="[descStyles]" class="sub-title-text">{{ data.description }}</view>
|
||||
</view>
|
||||
<!-- 查看更多 -->
|
||||
<view v-if="data.more?.show" class="more-box ss-flex ss-col-center" @tap="sheep.$router.go(data.more.url)"
|
||||
:style="{color: data.descriptionColor}">
|
||||
<view class="more-text" v-if="data.more.type !== 'icon'">{{ data.more.text }} </view>
|
||||
<text class="_icon-forward" v-if="data.more.type !== 'text'"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="ss-title-wrap ss-flex ss-col-center" :class="[state.typeMap[data.textAlign]]" :style="[bgStyle, { marginLeft: `${data.space}px` }]">
|
||||
<view class="title-content">
|
||||
<!-- 主标题 -->
|
||||
<view v-if="data.title" class="title-text" :style="[titleStyles]">{{ data.title }}</view>
|
||||
<!-- 副标题 -->
|
||||
<view v-if="data.description" :style="[descStyles]" class="sub-title-text">{{ data.description }}</view>
|
||||
</view>
|
||||
<!-- 查看更多 -->
|
||||
<view v-if="data.more?.show" class="more-box ss-flex ss-col-center" @tap="sheep.$router.go(data.more.url)"
|
||||
:style="{color: data.descriptionColor}">
|
||||
<view class="more-text" v-if="data.more.type !== 'icon'">{{ data.more.text }} </view>
|
||||
<text class="_icon-forward" v-if="data.more.type !== 'text'"></text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
/**
|
||||
* 标题栏
|
||||
*/
|
||||
import { reactive } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
/**
|
||||
* 标题栏
|
||||
*/
|
||||
import {
|
||||
reactive,
|
||||
computed
|
||||
} from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
|
||||
// 数据
|
||||
const state = reactive({
|
||||
typeMap: {
|
||||
left: 'ss-row-left',
|
||||
center: 'ss-row-center',
|
||||
},
|
||||
});
|
||||
// 数据
|
||||
const state = reactive({
|
||||
typeMap: {
|
||||
left: 'ss-row-left',
|
||||
center: 'ss-row-center',
|
||||
},
|
||||
});
|
||||
|
||||
// 接收参数
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
});
|
||||
// 接收参数
|
||||
const props = defineProps({
|
||||
// 装修数据
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 装修样式
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
// 设置背景样式
|
||||
const bgStyle = computed(() => {
|
||||
// 直接从 props.styles 解构
|
||||
const {
|
||||
bgType,
|
||||
bgImg,
|
||||
bgColor
|
||||
} = props.styles;
|
||||
|
||||
// 组件样式
|
||||
const elStyles = {
|
||||
background: `url(${sheep.$url.cdn(props.data.bgImgUrl)}) no-repeat top center / 100% auto`,
|
||||
fontSize: `${props.data.titleSize}px`,
|
||||
fontWeight: `${props.data.titleWeight}px`,
|
||||
};
|
||||
// 根据 bgType 返回相应的样式
|
||||
return {
|
||||
background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
|
||||
};
|
||||
});
|
||||
|
||||
// 标题样式
|
||||
const titleStyles = {
|
||||
color: props.data.titleColor,
|
||||
fontSize: `${props.data.titleSize}px`,
|
||||
textAlign: props.data.textAlign
|
||||
};
|
||||
// 标题样式
|
||||
const titleStyles = {
|
||||
color: props.data.titleColor,
|
||||
fontSize: `${props.data.titleSize}px`,
|
||||
textAlign: props.data.textAlign
|
||||
};
|
||||
|
||||
// 副标题
|
||||
const descStyles = {
|
||||
color: props.data.descriptionColor,
|
||||
textAlign: props.data.textAlign,
|
||||
fontSize: `${props.data.descriptionSize}px`,
|
||||
fontWeight: `${props.data.descriptionWeight}px`,
|
||||
};
|
||||
// 副标题
|
||||
const descStyles = {
|
||||
color: props.data.descriptionColor,
|
||||
textAlign: props.data.textAlign,
|
||||
fontSize: `${props.data.descriptionSize}px`,
|
||||
fontWeight: `${props.data.descriptionWeight}px`,
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ss-title-wrap {
|
||||
height: 80rpx;
|
||||
position: relative;
|
||||
.ss-title-wrap {
|
||||
height: 80rpx;
|
||||
position: relative;
|
||||
|
||||
.title-content {
|
||||
.title-text {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
}
|
||||
.title-content {
|
||||
.title-text {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.sub-title-text {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
.sub-title-text {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.more-box {
|
||||
white-space: nowrap;
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
right: 20rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.more-box {
|
||||
white-space: nowrap;
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
right: 20rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,167 +1,185 @@
|
|||
<!-- 装修用户组件:用户卡片 -->
|
||||
<template>
|
||||
<view class="ss-user-info-wrap ss-p-t-50">
|
||||
<view class="ss-flex ss-col-center ss-row-between ss-m-b-20">
|
||||
<view class="left-box ss-flex ss-col-center ss-m-l-36">
|
||||
<view class="avatar-box ss-m-r-24">
|
||||
<image class="avatar-img" :src="
|
||||
<view class="ss-user-info-wrap ss-p-t-50" :style="[bgStyle, { marginLeft: `${data.space}px` }]">
|
||||
<view class="ss-flex ss-col-center ss-row-between ss-m-b-20">
|
||||
<view class="left-box ss-flex ss-col-center ss-m-l-36">
|
||||
<view class="avatar-box ss-m-r-24">
|
||||
<image class="avatar-img" :src="
|
||||
isLogin
|
||||
? sheep.$url.cdn(userInfo.avatar)
|
||||
: sheep.$url.static('/static/img/shop/default_avatar.png')
|
||||
" mode="aspectFill" @tap="sheep.$router.go('/pages/user/info')"></image>
|
||||
</view>
|
||||
<view>
|
||||
<view class="nickname-box ss-flex ss-col-center">
|
||||
<view class="nick-name ss-m-r-20">{{ userInfo?.nickname || nickname }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right-box ss-m-r-52">
|
||||
<button class="ss-reset-button" @tap="showShareModal">
|
||||
<text class="sicon-qrcode"></text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
: sheep.$url.static('/static/img/shop/default_avatar.png')"
|
||||
mode="aspectFill" @tap="sheep.$router.go('/pages/user/info')">
|
||||
</image>
|
||||
</view>
|
||||
<view>
|
||||
<view class="nickname-box ss-flex ss-col-center">
|
||||
<view class="nick-name ss-m-r-20">{{ userInfo?.nickname || nickname }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right-box ss-m-r-52">
|
||||
<button class="ss-reset-button" @tap="showShareModal">
|
||||
<text class="sicon-qrcode"></text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提示绑定手机号 先隐藏 yudao 需要再修改 -->
|
||||
<view
|
||||
<!-- 提示绑定手机号 先隐藏 yudao 需要再修改 -->
|
||||
<view
|
||||
class="bind-mobile-box ss-flex ss-row-between ss-col-center"
|
||||
v-if="isLogin && !userInfo.mobile"
|
||||
>
|
||||
<view class="ss-flex">
|
||||
<text class="cicon-mobile-o" />
|
||||
<view class="mobile-title ss-m-l-20"> 点击绑定手机号确保账户安全 </view>
|
||||
<view class="mobile-title ss-m-l-20"> 点击绑定手机号确保账户安全</view>
|
||||
</view>
|
||||
<button class="ss-reset-button bind-btn" @tap="onBind">去绑定</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
/**
|
||||
* 用户卡片
|
||||
*
|
||||
* @property {Number} leftSpace - 容器左间距
|
||||
* @property {Number} rightSpace - 容器右间距
|
||||
*
|
||||
* @property {String} avatar - 头像
|
||||
* @property {String} nickname - 昵称
|
||||
* @property {String} vip - 等级
|
||||
* @property {String} collectNum - 收藏数
|
||||
* @property {String} likeNum - 点赞数
|
||||
*
|
||||
*
|
||||
*/
|
||||
import {
|
||||
computed,
|
||||
reactive
|
||||
} from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import {
|
||||
showShareModal,
|
||||
showAuthModal
|
||||
} from '@/sheep/hooks/useModal';
|
||||
/**
|
||||
* 用户卡片
|
||||
*
|
||||
* @property {Number} leftSpace - 容器左间距
|
||||
* @property {Number} rightSpace - 容器右间距
|
||||
*
|
||||
* @property {String} avatar - 头像
|
||||
* @property {String} nickname - 昵称
|
||||
* @property {String} vip - 等级
|
||||
* @property {String} collectNum - 收藏数
|
||||
* @property {String} likeNum - 点赞数
|
||||
*
|
||||
*
|
||||
*/
|
||||
import { computed } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import {
|
||||
showShareModal,
|
||||
showAuthModal,
|
||||
} from '@/sheep/hooks/useModal';
|
||||
|
||||
// 用户信息
|
||||
const userInfo = computed(() => sheep.$store('user').userInfo);
|
||||
console.log('用户信息', userInfo)
|
||||
// 用户信息
|
||||
const userInfo = computed(() => sheep.$store('user').userInfo);
|
||||
console.log('用户信息', userInfo);
|
||||
|
||||
// 是否登录
|
||||
const isLogin = computed(() => sheep.$store('user').isLogin);
|
||||
// 接收参数
|
||||
const props = defineProps({
|
||||
background: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
// 头像
|
||||
avatar: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
nickname: {
|
||||
type: String,
|
||||
default: '请先登录',
|
||||
},
|
||||
vip: {
|
||||
type: [String, Number],
|
||||
default: '1',
|
||||
},
|
||||
collectNum: {
|
||||
type: [String, Number],
|
||||
default: '1',
|
||||
},
|
||||
likeNum: {
|
||||
type: [String, Number],
|
||||
default: '1',
|
||||
},
|
||||
});
|
||||
// 是否登录
|
||||
const isLogin = computed(() => sheep.$store('user').isLogin);
|
||||
// 接收参数
|
||||
const props = defineProps({
|
||||
// 装修数据
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 装修样式
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 头像
|
||||
avatar: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
nickname: {
|
||||
type: String,
|
||||
default: '请先登录',
|
||||
},
|
||||
vip: {
|
||||
type: [String, Number],
|
||||
default: '1',
|
||||
},
|
||||
collectNum: {
|
||||
type: [String, Number],
|
||||
default: '1',
|
||||
},
|
||||
likeNum: {
|
||||
type: [String, Number],
|
||||
default: '1',
|
||||
},
|
||||
});
|
||||
|
||||
function onBind() {
|
||||
showAuthModal('changeMobile');
|
||||
}
|
||||
// 设置背景样式
|
||||
const bgStyle = computed(() => {
|
||||
// 直接从 props.styles 解构
|
||||
const { bgType, bgImg, bgColor } = props.styles;
|
||||
|
||||
// 根据 bgType 返回相应的样式
|
||||
return {
|
||||
background: bgType === 'img'
|
||||
? `url(${bgImg}) no-repeat top center / 100% 100%`
|
||||
: bgColor,
|
||||
};
|
||||
});
|
||||
|
||||
// 绑定手机号
|
||||
function onBind() {
|
||||
showAuthModal('changeMobile');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ss-user-info-wrap {
|
||||
box-sizing: border-box;
|
||||
.ss-user-info-wrap {
|
||||
box-sizing: border-box;
|
||||
|
||||
.avatar-box {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
.avatar-box {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
|
||||
.avatar-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.avatar-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.nick-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
line-height: normal;
|
||||
}
|
||||
.nick-name {
|
||||
font-size: 34rpx;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.vip-img {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
.vip-img {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
|
||||
.sicon-qrcode {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
}
|
||||
.sicon-qrcode {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.bind-mobile-box {
|
||||
width: 100%;
|
||||
height: 84rpx;
|
||||
padding: 0 34rpx 0 44rpx;
|
||||
box-sizing: border-box;
|
||||
background: #ffffff;
|
||||
box-shadow: 0px -8rpx 9rpx 0px rgba(#e0e0e0, 0.3);
|
||||
.bind-mobile-box {
|
||||
width: 100%;
|
||||
height: 84rpx;
|
||||
padding: 0 34rpx 0 44rpx;
|
||||
box-sizing: border-box;
|
||||
background: #ffffff;
|
||||
box-shadow: 0px -8rpx 9rpx 0px rgba(#e0e0e0, 0.3);
|
||||
|
||||
.cicon-mobile-o {
|
||||
font-size: 30rpx;
|
||||
color: #ff690d;
|
||||
}
|
||||
.cicon-mobile-o {
|
||||
font-size: 30rpx;
|
||||
color: #ff690d;
|
||||
}
|
||||
|
||||
.mobile-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: #ff690d;
|
||||
}
|
||||
.mobile-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: #ff690d;
|
||||
}
|
||||
|
||||
.bind-btn {
|
||||
width: 100rpx;
|
||||
height: 50rpx;
|
||||
background: #ff6100;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
.bind-btn {
|
||||
width: 100rpx;
|
||||
height: 50rpx;
|
||||
background: #ff6100;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,6 +1,6 @@
|
|||
<!-- 装修用户组件:用户资产 -->
|
||||
<template>
|
||||
<view class="ss-wallet-menu-wrap ss-flex ss-col-center">
|
||||
<view class="ss-wallet-menu-wrap ss-flex ss-col-center" :style="[bgStyle, { marginLeft: `${data.space}px` }]">
|
||||
<view class="menu-item ss-flex-1 ss-flex-col ss-row-center ss-col-center"
|
||||
@tap="sheep.$router.go('/pages/user/wallet/money')">
|
||||
<view class="value-box ss-flex ss-col-bottom">
|
||||
|
@ -42,8 +42,34 @@
|
|||
*/
|
||||
import { computed } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { fen2yuan } from '../../hooks/useGoods';
|
||||
import { fen2yuan } from '../../hooks/useGoods';
|
||||
|
||||
// 接收参数
|
||||
const props = defineProps({
|
||||
// 装修数据
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 装修样式
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
// 设置背景样式
|
||||
const bgStyle = computed(() => {
|
||||
// 直接从 props.styles 解构
|
||||
const { bgType, bgImg, bgColor } = props.styles;
|
||||
|
||||
// 根据 bgType 返回相应的样式
|
||||
return {
|
||||
background: bgType === 'img'
|
||||
? `url(${bgImg}) no-repeat top center / 100% 100%`
|
||||
: bgColor
|
||||
};
|
||||
});
|
||||
|
||||
const userWallet = computed(() => sheep.$store('user').userWallet);
|
||||
const userInfo = computed(() => sheep.$store('user').userInfo);
|
||||
const numData = computed(() => sheep.$store('user').numData);
|
||||
|
|
|
@ -621,7 +621,7 @@ function setProperty(obj, key, value) {
|
|||
function page() {
|
||||
const pages = getCurrentPages();
|
||||
// 某些特殊情况下(比如页面进行redirectTo时的一些时机),pages可能为空数组
|
||||
return `/${pages[pages.length - 1]?.route ?? ''}`;
|
||||
return `/${pages[pages.length - 1]?.route || ''}`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,6 +23,10 @@ export function isString(value) {
|
|||
}
|
||||
|
||||
export function isEmpty(value) {
|
||||
if (value === '' || value === undefined || value === null){
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isArray(value)) {
|
||||
return value.length === 0;
|
||||
}
|
||||
|
@ -31,7 +35,7 @@ export function isEmpty(value) {
|
|||
return Object.keys(value).length === 0;
|
||||
}
|
||||
|
||||
return value === '' || value === undefined || value === null;
|
||||
return false
|
||||
}
|
||||
|
||||
export function isBoolean(value) {
|
||||
|
|
|
@ -14,7 +14,7 @@ export function showAuthModal(type = 'smsLogin') {
|
|||
modal.$patch((state) => {
|
||||
state.auth = type;
|
||||
});
|
||||
}, 200);
|
||||
}, 500);
|
||||
closeAuthModal();
|
||||
} else {
|
||||
modal.$patch((state) => {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
/**
|
||||
* 本模块封装微信浏览器下的一些方法。
|
||||
* 更多微信网页开发sdk方法,详见:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
|
||||
* 有 the permission value is offline verifying 报错请参考 @see https://segmentfault.com/a/1190000042289419 解决
|
||||
*/
|
||||
|
||||
import jweixin, { ready } from 'weixin-js-sdk';
|
||||
import jweixin from 'weixin-js-sdk';
|
||||
import $helper from '@/sheep/helper';
|
||||
import AuthUtil from '@/sheep/api/member/auth';
|
||||
|
||||
|
@ -38,7 +39,7 @@ export default {
|
|||
timestamp: data.timestamp,
|
||||
nonceStr: data.nonceStr,
|
||||
signature: data.signature,
|
||||
jsApiList: ['chooseWXPay'], // TODO 芋艿:后续可以设置更多权限;
|
||||
jsApiList: ['chooseWXPay', 'openLocation', 'getLocation','updateTimelineShareData','scanQRCode'], // TODO 芋艿:后续可以设置更多权限;
|
||||
openTagList: data.openTagList
|
||||
});
|
||||
}
|
||||
|
@ -77,7 +78,7 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
//获取微信收货地址 TODO 芋艿:未测试
|
||||
// 获取微信收货地址
|
||||
openAddress(callback) {
|
||||
this.isReady(() => {
|
||||
jweixin.openAddress({
|
||||
|
@ -137,9 +138,10 @@ export default {
|
|||
openLocation(data, callback) {
|
||||
this.isReady(() => {
|
||||
jweixin.openLocation({
|
||||
//根据传入的坐标打开地图
|
||||
latitude: data.latitude,
|
||||
longitude: data.longitude,
|
||||
...data,
|
||||
success: function (res) {
|
||||
console.log(res);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
|
|
@ -53,7 +53,6 @@ const mobileLogin = async (e) => {
|
|||
} else {
|
||||
return resolve(false);
|
||||
}
|
||||
// TODO 芋艿:shareInfo: uni.getStorageSync('shareLog') || {},
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ async function login(code = '', state = '') {
|
|||
// 解密 code 发起登陆
|
||||
const loginResult = await AuthUtil.socialLogin(socialType, code, state);
|
||||
if (loginResult.code === 0) {
|
||||
// TODO 芋艿:shareLog
|
||||
setOpenid(loginResult.data.openid);
|
||||
return loginResult;
|
||||
}
|
||||
|
@ -103,5 +102,5 @@ export default {
|
|||
unbind,
|
||||
getInfo,
|
||||
getOpenid,
|
||||
jssdk: $wxsdk,
|
||||
jsWxSdk: $wxsdk,
|
||||
};
|
||||
|
|
|
@ -178,7 +178,7 @@ const decryptSpm = (spm) => {
|
|||
};
|
||||
|
||||
// 绑定推广员
|
||||
const bindBrokerageUser = async (val= undefined) => {
|
||||
const bindBrokerageUser = async (val = undefined) => {
|
||||
try {
|
||||
const shareId = val || uni.getStorageSync('shareId');
|
||||
if (!shareId) {
|
||||
|
@ -186,7 +186,8 @@ const bindBrokerageUser = async (val= undefined) => {
|
|||
}
|
||||
await BrokerageApi.bindBrokerageUser({ bindUserId: shareId });
|
||||
uni.removeStorageSync('shareId');
|
||||
} catch {
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import $store from '@/sheep/store';
|
|||
import $platform from '@/sheep/platform';
|
||||
import { showAuthModal } from '@/sheep/hooks/useModal';
|
||||
import AuthUtil from '@/sheep/api/member/auth';
|
||||
import { getTerminalEnumByUniPlatform } from '@/sheep/util/const';
|
||||
import { getTerminal } from '@/sheep/util/const';
|
||||
|
||||
const options = {
|
||||
// 显示操作成功消息 默认不显示
|
||||
|
@ -94,9 +94,7 @@ http.interceptors.request.use(
|
|||
if (token) {
|
||||
config.header['Authorization'] = token;
|
||||
}
|
||||
|
||||
const terminalType = uni.getSystemInfoSync().uniPlatform
|
||||
config.header['terminal'] = getTerminalEnumByUniPlatform(terminalType);
|
||||
config.header['terminal'] = getTerminal();
|
||||
|
||||
config.header['Accept'] = '*/*';
|
||||
config.header['tenant-id'] = tenantId;
|
||||
|
|
|
@ -57,7 +57,13 @@ const cart = defineStore({
|
|||
|
||||
// 移除购物车
|
||||
async delete(ids) {
|
||||
const { code } = await CartApi.deleteCart(ids.join(','));
|
||||
let idsTemp = '';
|
||||
if (Array.isArray(ids)) {
|
||||
idsTemp = ids.join(',');
|
||||
} else {
|
||||
idsTemp = ids;
|
||||
}
|
||||
const { code } = await CartApi.deleteCart(idsTemp);
|
||||
if (code === 0) {
|
||||
await this.getList();
|
||||
}
|
||||
|
|
|
@ -12,26 +12,23 @@ export const TerminalEnum = {
|
|||
};
|
||||
|
||||
/**
|
||||
* 将Uniapp提供的平台转换为后端所需的Terminal值
|
||||
* @param platformType Uniapp提供的平台类型
|
||||
* 将 uni-app 提供的平台转换为后端所需的 terminal值
|
||||
*
|
||||
* @return 终端
|
||||
*/
|
||||
export const getTerminalEnumByUniPlatform = (platformType) => {
|
||||
let terminal;
|
||||
export const getTerminal = () => {
|
||||
const platformType = uni.getSystemInfoSync().uniPlatform;
|
||||
// 与后端terminal枚举一一对应
|
||||
switch (platformType) {
|
||||
case 'app':
|
||||
terminal = TerminalEnum.APP;
|
||||
break;
|
||||
return TerminalEnum.APP;
|
||||
case 'web':
|
||||
terminal = TerminalEnum.H5;
|
||||
break;
|
||||
return TerminalEnum.H5;
|
||||
case 'mp-weixin':
|
||||
terminal = TerminalEnum.WECHAT_MINI_PROGRAM;
|
||||
break;
|
||||
return TerminalEnum.WECHAT_MINI_PROGRAM;
|
||||
default:
|
||||
terminal = TerminalEnum.UNKNOWN;
|
||||
return TerminalEnum.UNKNOWN;
|
||||
}
|
||||
return terminal;
|
||||
};
|
||||
|
||||
// ========== MALL - 营销模块 ==========
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
Loading…
Reference in New Issue