Merge remote-tracking branch 'upload/master'
commit
354a3dc1c8
|
|
@ -216,7 +216,7 @@
|
|||
"h5": {
|
||||
"template": "index.html",
|
||||
"router": {
|
||||
"mode": "hash",
|
||||
"mode": "history",
|
||||
"base": "./"
|
||||
},
|
||||
"sdkConfigs": {
|
||||
|
|
@ -236,4 +236,4 @@
|
|||
"_spaceID": "192b4892-5452-4e1d-9f09-eee1ece40639",
|
||||
"locale": "zh-Hans",
|
||||
"fallbackLocale": "zh-Hans"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@
|
|||
"dependencies": {
|
||||
"dayjs": "^1.11.7",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"luch-request": "^3.0.8",
|
||||
"pinia": "^2.0.33",
|
||||
"pinia-plugin-persist-uni": "^1.2.0",
|
||||
|
|
|
|||
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": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
<!-- 拼团订单的详情 -->
|
||||
<template>
|
||||
<s-layout title="拼团详情" class="detail-wrap" :navbar="state.data && !state.loading ? 'inner': 'normal'" :onShareAppMessage="shareInfo">
|
||||
<s-layout
|
||||
title="拼团详情"
|
||||
class="detail-wrap"
|
||||
:navbar="state.data && !state.loading ? 'inner' : 'normal'"
|
||||
:onShareAppMessage="shareInfo"
|
||||
>
|
||||
<view v-if="state.loading"></view>
|
||||
<view v-if="state.data && !state.loading">
|
||||
<!-- 团长信息 + 活动信息 -->
|
||||
|
|
@ -22,7 +27,7 @@
|
|||
priceColor="#E1212B"
|
||||
@tap="
|
||||
sheep.$router.go('/pages/goods/groupon', {
|
||||
id: state.data.headRecord.activityId
|
||||
id: state.data.headRecord.activityId,
|
||||
})
|
||||
"
|
||||
:style="[{ top: Number(statusBarHeight + 108) + 'rpx' }]"
|
||||
|
|
@ -71,7 +76,9 @@
|
|||
</view>
|
||||
<view class="countdown-title ss-flex" v-else>
|
||||
还差
|
||||
<view class="num">{{ state.data.headRecord.userSize - state.data.headRecord.userCount }}人</view>
|
||||
<view class="num"
|
||||
>{{ state.data.headRecord.userSize - state.data.headRecord.userCount }}人</view
|
||||
>
|
||||
拼团成功
|
||||
<view class="ss-flex countdown-time">
|
||||
<view class="countdown-h ss-flex ss-row-center">{{ endTime.h }}</view>
|
||||
|
|
@ -109,7 +116,11 @@
|
|||
</view>
|
||||
</view>
|
||||
<!-- 还有几个坑位 -->
|
||||
<view class="default-avatar ss-m-r-24 ss-m-b-20" v-for="item in state.remainNumber" :key="item">
|
||||
<view
|
||||
class="default-avatar ss-m-r-24 ss-m-b-20"
|
||||
v-for="item in state.remainNumber"
|
||||
:key="item"
|
||||
>
|
||||
<image
|
||||
:src="sheep.$url.static('/static/img/shop/avatar/unknown.png')"
|
||||
class="avatar-img"
|
||||
|
|
@ -154,11 +165,7 @@
|
|||
</view>
|
||||
<view v-else class="ss-flex ss-row-center">
|
||||
<view v-if="state.data.orderId">
|
||||
<button
|
||||
class="ss-reset-button join-btn"
|
||||
:disabled="endTime.ms <= 0"
|
||||
@tap="onShare"
|
||||
>
|
||||
<button class="ss-reset-button join-btn" :disabled="endTime.ms <= 0" @tap="onShare">
|
||||
邀请好友来拼团
|
||||
</button>
|
||||
</view>
|
||||
|
|
@ -174,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"
|
||||
|
|
@ -186,6 +193,7 @@
|
|||
@close="state.showSelectSku = false"
|
||||
/>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<s-empty v-if="!state.data && !state.loading" icon="/static/goods-empty.png" />
|
||||
|
|
@ -196,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';
|
||||
import CombinationApi from "@/sheep/api/promotion/combination";
|
||||
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(
|
||||
|
|
@ -224,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), // 商品价格
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
@ -244,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: [
|
||||
{
|
||||
|
|
@ -295,8 +305,29 @@
|
|||
state.remainNumber = remainNumber > 0 ? remainNumber : 0;
|
||||
|
||||
// 获取活动信息
|
||||
const { data: activity } = await CombinationApi.getCombinationActivity(data.headRecord.activityId);
|
||||
const { data: activity } = await CombinationApi.getCombinationActivity(
|
||||
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;
|
||||
}
|
||||
|
|
@ -316,8 +347,7 @@
|
|||
.recharge-box {
|
||||
position: relative;
|
||||
margin-bottom: 120rpx;
|
||||
background: v-bind(headerBg) center/750rpx 100%
|
||||
no-repeat,
|
||||
background: v-bind(headerBg) center/750rpx 100% no-repeat,
|
||||
linear-gradient(115deg, #f44739 0%, #ff6600 100%);
|
||||
border-radius: 0 0 5% 5%;
|
||||
height: 100rpx;
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@
|
|||
</view>
|
||||
<view class="border-bottom">
|
||||
<s-goods-item
|
||||
:img="record.picUrl"
|
||||
:title="record.spuName"
|
||||
:price="record.combinationPrice"
|
||||
:img="record.picUrl"
|
||||
:title="record.spuName"
|
||||
:price="record.combinationPrice"
|
||||
>
|
||||
<template #groupon>
|
||||
<view class="ss-flex">
|
||||
|
|
@ -67,8 +67,8 @@
|
|||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash';
|
||||
import {formatOrderColor} from "@/sheep/hooks/useGoods";
|
||||
import _ from 'lodash-es';
|
||||
import { formatOrderColor } from '@/sheep/hooks/useGoods';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
import CombinationApi from '@/sheep/api/promotion/combination';
|
||||
|
||||
|
|
@ -121,7 +121,7 @@
|
|||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list)
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import RewardActivityApi from '@/sheep/api/promotion/rewardActivity';
|
||||
import { formatRewardActivityRule } from '@/sheep/hooks/useGoods';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
|
|
@ -118,7 +118,7 @@
|
|||
const { code, data } = await SpuApi.getSpuPage({
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
...params
|
||||
...params,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
<script setup>
|
||||
import { reactive, watch } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import GoodsItem from './goods.vue';
|
||||
import OrderItem from './order.vue';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
|
|
|
|||
|
|
@ -1,74 +1,90 @@
|
|||
<!-- 分销首页:明细列表 -->
|
||||
<template>
|
||||
<view class="distribution-log-wrap">
|
||||
<view class="header-box">
|
||||
<image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title2.png')" />
|
||||
<view class="ss-flex header-title">
|
||||
<view class="title">实时动态</view>
|
||||
<text class="cicon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" @scrolltolower="loadmore" class="scroll-box log-scroll"
|
||||
scroll-with-animation="true">
|
||||
<view v-if="state.pagination.list">
|
||||
<view class="log-item-box ss-flex ss-row-between" v-for="item in state.pagination.list" :key="item.id">
|
||||
<view class="log-item-wrap">
|
||||
<view class="log-item ss-flex ss-ellipsis-1 ss-col-center">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<image class="log-img" :src="sheep.$url.static('/static/img/shop/avatar/notice.png')" mode="aspectFill" />
|
||||
</view>
|
||||
<view class="log-text ss-ellipsis-1">
|
||||
<view class="distribution-log-wrap">
|
||||
<view class="header-box">
|
||||
<image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title2.png')" />
|
||||
<view class="ss-flex header-title">
|
||||
<view class="title">实时动态</view>
|
||||
<text class="cicon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view
|
||||
scroll-y="true"
|
||||
@scrolltolower="loadmore"
|
||||
class="scroll-box log-scroll"
|
||||
scroll-with-animation="true"
|
||||
>
|
||||
<view v-if="state.pagination.list">
|
||||
<view
|
||||
class="log-item-box ss-flex ss-row-between"
|
||||
v-for="item in state.pagination.list"
|
||||
:key="item.id"
|
||||
>
|
||||
<view class="log-item-wrap">
|
||||
<view class="log-item ss-flex ss-ellipsis-1 ss-col-center">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<image
|
||||
class="log-img"
|
||||
:src="sheep.$url.static('/static/img/shop/avatar/notice.png')"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</view>
|
||||
<view class="log-text ss-ellipsis-1">
|
||||
{{ item.title }} {{ fen2yuan(item.price) }} 元
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="log-time">{{ dayjs(item.createTime).fromNow() }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="log-time">{{ dayjs(item.createTime).fromNow() }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" color="#333333"
|
||||
@tap="loadmore" />
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- 加载更多 -->
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
color="#333333"
|
||||
@tap="loadmore"
|
||||
/>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import dayjs from 'dayjs';
|
||||
import sheep from '@/sheep';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash-es';
|
||||
import dayjs from 'dayjs';
|
||||
import BrokerageApi from '@/sheep/api/trade/brokerage';
|
||||
import { fen2yuan } from '../../../sheep/hooks/useGoods';
|
||||
|
||||
const state = reactive({
|
||||
loadStatus: '',
|
||||
pagination: {
|
||||
const state = reactive({
|
||||
loadStatus: '',
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 1,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
async function getLog() {
|
||||
async function getLog() {
|
||||
state.loadStatus = 'loading';
|
||||
const { code, data } = await BrokerageApi.getBrokerageRecordPage({
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize
|
||||
});
|
||||
pageSize: state.pagination.pageSize,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
}
|
||||
|
||||
getLog();
|
||||
getLog();
|
||||
|
||||
// 加载更多
|
||||
function loadmore() {
|
||||
// 加载更多
|
||||
function loadmore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
|
|
@ -78,88 +94,88 @@
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.distribution-log-wrap {
|
||||
width: 690rpx;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
z-index: 3;
|
||||
position: relative;
|
||||
.distribution-log-wrap {
|
||||
width: 690rpx;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 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;
|
||||
}
|
||||
}
|
||||
|
||||
.log-scroll {
|
||||
height: 600rpx;
|
||||
background: #fdfae9;
|
||||
padding: 10rpx 20rpx 0;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12rpx 12rpx;
|
||||
.log-scroll {
|
||||
height: 600rpx;
|
||||
background: #fdfae9;
|
||||
padding: 10rpx 20rpx 0;
|
||||
box-sizing: border-box;
|
||||
border-radius: 0 0 12rpx 12rpx;
|
||||
|
||||
.log-item-box {
|
||||
margin-bottom: 20rpx;
|
||||
.log-item-box {
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.log-time {
|
||||
// margin-left: 30rpx;
|
||||
text-align: right;
|
||||
font-size: 24rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 400;
|
||||
color: #c4c4c4;
|
||||
}
|
||||
}
|
||||
.log-time {
|
||||
// margin-left: 30rpx;
|
||||
text-align: right;
|
||||
font-size: 24rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 400;
|
||||
color: #c4c4c4;
|
||||
}
|
||||
}
|
||||
|
||||
.loadmore-wrap {
|
||||
// line-height: 80rpx;
|
||||
}
|
||||
.loadmore-wrap {
|
||||
// line-height: 80rpx;
|
||||
}
|
||||
|
||||
.log-item {
|
||||
// background: rgba(#ffffff, 0.2);
|
||||
border-radius: 24rpx;
|
||||
padding: 6rpx 20rpx 6rpx 12rpx;
|
||||
.log-item {
|
||||
// background: rgba(#ffffff, 0.2);
|
||||
border-radius: 24rpx;
|
||||
padding: 6rpx 20rpx 6rpx 12rpx;
|
||||
|
||||
.log-img {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.log-img {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.log-text {
|
||||
max-width: 480rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.log-text {
|
||||
max-width: 480rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -14,12 +14,18 @@
|
|||
>
|
||||
<template #rightBottom>
|
||||
<view class="ss-flex ss-row-between">
|
||||
<view class="commission-num" v-if="item.brokerageMinPrice === undefined">预计佣金:计算中</view>
|
||||
<view class="commission-num" v-else-if="item.brokerageMinPrice === item.brokerageMaxPrice">
|
||||
<view class="commission-num" v-if="item.brokerageMinPrice === undefined"
|
||||
>预计佣金:计算中</view
|
||||
>
|
||||
<view
|
||||
class="commission-num"
|
||||
v-else-if="item.brokerageMinPrice === item.brokerageMaxPrice"
|
||||
>
|
||||
预计佣金:{{ fen2yuan(item.brokerageMinPrice) }}
|
||||
</view>
|
||||
<view class="commission-num" v-else>
|
||||
预计佣金:{{ fen2yuan(item.brokerageMinPrice) }} ~ {{ fen2yuan(item.brokerageMaxPrice) }}
|
||||
预计佣金:{{ fen2yuan(item.brokerageMinPrice) }} ~
|
||||
{{ fen2yuan(item.brokerageMaxPrice) }}
|
||||
</view>
|
||||
<button
|
||||
class="ss-reset-button share-btn ui-BG-Main-Gradient"
|
||||
|
|
@ -53,7 +59,7 @@
|
|||
import $share from '@/sheep/platform/share';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import { showShareModal } from '@/sheep/hooks/useModal';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
import BrokerageApi from '@/sheep/api/trade/brokerage';
|
||||
|
|
|
|||
|
|
@ -41,10 +41,7 @@
|
|||
<view class="no-box ss-flex ss-col-center ss-row-between">
|
||||
<text class="order-code">订单编号:{{ item.bizId }}</text>
|
||||
<text class="order-state">
|
||||
{{
|
||||
item.status === 0 ? '待结算'
|
||||
: item.status === 1 ? '已结算' : '已取消'
|
||||
}}
|
||||
{{ item.status === 0 ? '待结算' : item.status === 1 ? '已结算' : '已取消' }}
|
||||
( 佣金 {{ fen2yuan(item.price) }} 元 )
|
||||
</text>
|
||||
</view>
|
||||
|
|
@ -77,7 +74,7 @@
|
|||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import { onPageScroll } from '@dcloudio/uni-app';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
import BrokerageApi from '@/sheep/api/trade/brokerage';
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@
|
|||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import { onPageScroll } from '@dcloudio/uni-app';
|
||||
import BrokerageApi from '@/sheep/api/trade/brokerage';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,196 +1,243 @@
|
|||
<!-- 分销 - 佣金明细 -->
|
||||
<template>
|
||||
<s-layout class="wallet-wrap" title="佣金">
|
||||
<!-- 钱包卡片 -->
|
||||
<view class="header-box ss-flex ss-row-center ss-col-center">
|
||||
<view class="card-box ui-BG-Main ui-Shadow-Main">
|
||||
<view class="card-head ss-flex ss-col-center">
|
||||
<view class="card-title ss-m-r-10">当前佣金(元)</view>
|
||||
<view @tap="state.showMoney = !state.showMoney" class="ss-eye-icon"
|
||||
:class="state.showMoney ? 'cicon-eye' : 'cicon-eye-off'" />
|
||||
</view>
|
||||
<view class="ss-flex ss-row-between ss-col-center ss-m-t-30">
|
||||
<view class="money-num">{{ state.showMoney ? fen2yuan(state.summary.withdrawPrice || 0) : '*****' }}</view>
|
||||
<view class="ss-flex">
|
||||
<view class="ss-m-r-20">
|
||||
<button class="ss-reset-button withdraw-btn" @tap="sheep.$router.go('/pages/commission/withdraw')">
|
||||
提现
|
||||
</button>
|
||||
</view>
|
||||
<button class="ss-reset-button balance-btn ss-m-l-20" @tap="state.showModal = true">
|
||||
转余额
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
<s-layout class="wallet-wrap" title="佣金">
|
||||
<!-- 钱包卡片 -->
|
||||
<view class="header-box ss-flex ss-row-center ss-col-center">
|
||||
<view class="card-box ui-BG-Main ui-Shadow-Main">
|
||||
<view class="card-head ss-flex ss-col-center">
|
||||
<view class="card-title ss-m-r-10">当前佣金(元)</view>
|
||||
<view
|
||||
@tap="state.showMoney = !state.showMoney"
|
||||
class="ss-eye-icon"
|
||||
:class="state.showMoney ? 'cicon-eye' : 'cicon-eye-off'"
|
||||
/>
|
||||
</view>
|
||||
<view class="ss-flex ss-row-between ss-col-center ss-m-t-30">
|
||||
<view class="money-num">{{
|
||||
state.showMoney ? fen2yuan(state.summary.withdrawPrice || 0) : '*****'
|
||||
}}</view>
|
||||
<view class="ss-flex">
|
||||
<view class="ss-m-r-20">
|
||||
<button
|
||||
class="ss-reset-button withdraw-btn"
|
||||
@tap="sheep.$router.go('/pages/commission/withdraw')"
|
||||
>
|
||||
提现
|
||||
</button>
|
||||
</view>
|
||||
<button class="ss-reset-button balance-btn ss-m-l-20" @tap="state.showModal = true">
|
||||
转余额
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="ss-flex">
|
||||
<view class="loading-money">
|
||||
<view class="loading-money-title">冻结佣金</view>
|
||||
<view class="loading-money-num">
|
||||
<view class="ss-flex">
|
||||
<view class="loading-money">
|
||||
<view class="loading-money-title">冻结佣金</view>
|
||||
<view class="loading-money-num">
|
||||
{{ state.showMoney ? fen2yuan(state.summary.frozenPrice || 0) : '*****' }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="loading-money ss-m-l-100">
|
||||
<view class="loading-money-title">可提现佣金</view>
|
||||
<view class="loading-money-num">
|
||||
</view>
|
||||
<view class="loading-money ss-m-l-100">
|
||||
<view class="loading-money-title">可提现佣金</view>
|
||||
<view class="loading-money-num">
|
||||
{{ state.showMoney ? fen2yuan(state.summary.brokeragePrice || 0) : '*****' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<su-sticky>
|
||||
<!-- 统计 -->
|
||||
<view class="filter-box ss-p-x-30 ss-flex ss-col-center ss-row-between">
|
||||
<uni-datetime-picker v-model="state.date" type="daterange" @change="onChangeTime" :end="state.today">
|
||||
<button class="ss-reset-button date-btn">
|
||||
<text>{{ dateFilterText }}</text>
|
||||
<text class="cicon-drop-down ss-seldate-icon" />
|
||||
</button>
|
||||
</uni-datetime-picker>
|
||||
<su-sticky>
|
||||
<!-- 统计 -->
|
||||
<view class="filter-box ss-p-x-30 ss-flex ss-col-center ss-row-between">
|
||||
<uni-datetime-picker
|
||||
v-model="state.date"
|
||||
type="daterange"
|
||||
@change="onChangeTime"
|
||||
:end="state.today"
|
||||
>
|
||||
<button class="ss-reset-button date-btn">
|
||||
<text>{{ dateFilterText }}</text>
|
||||
<text class="cicon-drop-down ss-seldate-icon" />
|
||||
</button>
|
||||
</uni-datetime-picker>
|
||||
|
||||
<view class="total-box">
|
||||
<view class="total-box">
|
||||
<!-- TODO 芋艿:这里暂时不考虑做 -->
|
||||
<!-- <view class="ss-m-b-10">总收入¥{{ state.pagination.income.toFixed(2) }}</view> -->
|
||||
<!-- <view>总支出¥{{ (-state.pagination.expense).toFixed(2) }}</view> -->
|
||||
</view>
|
||||
</view>
|
||||
<su-tabs :list="tabMaps" @change="onChangeTab" :scrollable="false" :current="state.currentTab" />
|
||||
</su-sticky>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据"></s-empty>
|
||||
<!-- <view class="ss-m-b-10">总收入¥{{ state.pagination.income.toFixed(2) }}</view> -->
|
||||
<!-- <view>总支出¥{{ (-state.pagination.expense).toFixed(2) }}</view> -->
|
||||
</view>
|
||||
</view>
|
||||
<su-tabs
|
||||
:list="tabMaps"
|
||||
@change="onChangeTab"
|
||||
:scrollable="false"
|
||||
:current="state.currentTab"
|
||||
/>
|
||||
</su-sticky>
|
||||
<s-empty
|
||||
v-if="state.pagination.total === 0"
|
||||
icon="/static/data-empty.png"
|
||||
text="暂无数据"
|
||||
></s-empty>
|
||||
|
||||
<!-- 转余额弹框 -->
|
||||
<su-popup :show="state.showModal" type="bottom" round="20" @close="state.showModal = false" showClose>
|
||||
<view class="ss-p-x-20 ss-p-y-30">
|
||||
<view class="model-title ss-m-b-30 ss-m-l-20">转余额</view>
|
||||
<view class="model-subtitle ss-m-b-100 ss-m-l-20">将您的佣金转到余额中继续消费</view>
|
||||
<view class="input-box ss-flex ss-col-center border-bottom ss-m-b-70 ss-m-x-20">
|
||||
<view class="unit">¥</view>
|
||||
<uni-easyinput :inputBorder="false" class="ss-flex-1 ss-p-l-10" v-model="state.price" type="number"
|
||||
placeholder="请输入金额" />
|
||||
</view>
|
||||
<button class="ss-reset-button model-btn ui-BG-Main-Gradient ui-Shadow-Main" @tap="onConfirm">
|
||||
确定
|
||||
</button>
|
||||
</view>
|
||||
</su-popup>
|
||||
<su-popup
|
||||
:show="state.showModal"
|
||||
type="bottom"
|
||||
round="20"
|
||||
@close="state.showModal = false"
|
||||
showClose
|
||||
>
|
||||
<view class="ss-p-x-20 ss-p-y-30">
|
||||
<view class="model-title ss-m-b-30 ss-m-l-20">转余额</view>
|
||||
<view class="model-subtitle ss-m-b-100 ss-m-l-20">将您的佣金转到余额中继续消费</view>
|
||||
<view class="input-box ss-flex ss-col-center border-bottom ss-m-b-70 ss-m-x-20">
|
||||
<view class="unit">¥</view>
|
||||
<uni-easyinput
|
||||
:inputBorder="false"
|
||||
class="ss-flex-1 ss-p-l-10"
|
||||
v-model="state.price"
|
||||
type="number"
|
||||
placeholder="请输入金额"
|
||||
/>
|
||||
</view>
|
||||
<button
|
||||
class="ss-reset-button model-btn ui-BG-Main-Gradient ui-Shadow-Main"
|
||||
@tap="onConfirm"
|
||||
>
|
||||
确定
|
||||
</button>
|
||||
</view>
|
||||
</su-popup>
|
||||
|
||||
<!-- 钱包记录 -->
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view class="wallet-list ss-flex border-bottom" v-for="item in state.pagination.list" :key="item.id">
|
||||
<view class="list-content">
|
||||
<view class="title-box ss-flex ss-row-between ss-m-b-20">
|
||||
<text class="title ss-line-1">{{ item.title }}</text>
|
||||
<view class="money">
|
||||
<text v-if="item.price >= 0" class="add">+{{ fen2yuan(item.price) }}</text>
|
||||
<text v-else class="minus">{{ fen2yuan(item.price) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="time">{{ sheep.$helper.timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 钱包记录 -->
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view
|
||||
class="wallet-list ss-flex border-bottom"
|
||||
v-for="item in state.pagination.list"
|
||||
:key="item.id"
|
||||
>
|
||||
<view class="list-content">
|
||||
<view class="title-box ss-flex ss-row-between ss-m-b-20">
|
||||
<text class="title ss-line-1">{{ item.title }}</text>
|
||||
<view class="money">
|
||||
<text v-if="item.price >= 0" class="add">+{{ fen2yuan(item.price) }}</text>
|
||||
<text v-else class="minus">{{ fen2yuan(item.price) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="time">{{
|
||||
sheep.$helper.timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss')
|
||||
}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- <u-gap></u-gap> -->
|
||||
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{
|
||||
<!-- <u-gap></u-gap> -->
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}" />
|
||||
</s-layout>
|
||||
}"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import dayjs from 'dayjs';
|
||||
import _ from 'lodash';
|
||||
import { computed, reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import dayjs from 'dayjs';
|
||||
import _ from 'lodash-es';
|
||||
import BrokerageApi from '@/sheep/api/trade/brokerage';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
||||
const headerBg = sheep.$url.css('/static/img/shop/user/wallet_card_bg.png');
|
||||
const headerBg = sheep.$url.css('/static/img/shop/user/wallet_card_bg.png');
|
||||
|
||||
const state = reactive({
|
||||
const state = reactive({
|
||||
showMoney: false,
|
||||
summary: {}, // 分销信息
|
||||
|
||||
today: '',
|
||||
date: [],
|
||||
currentTab: 0,
|
||||
pagination: {
|
||||
currentTab: 0,
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 1,
|
||||
},
|
||||
loadStatus: '',
|
||||
loadStatus: '',
|
||||
|
||||
price: undefined,
|
||||
showModal: false,
|
||||
});
|
||||
showModal: false,
|
||||
});
|
||||
|
||||
const tabMaps = [{
|
||||
name: '分佣',
|
||||
value: '1', // BrokerageRecordBizTypeEnum.ORDER
|
||||
},
|
||||
{
|
||||
name: '提现',
|
||||
value: '2', // BrokerageRecordBizTypeEnum.WITHDRAW
|
||||
}
|
||||
];
|
||||
const tabMaps = [
|
||||
{
|
||||
name: '分佣',
|
||||
value: '1', // BrokerageRecordBizTypeEnum.ORDER
|
||||
},
|
||||
{
|
||||
name: '提现',
|
||||
value: '2', // BrokerageRecordBizTypeEnum.WITHDRAW
|
||||
},
|
||||
];
|
||||
|
||||
const dateFilterText = computed(() => {
|
||||
if (state.date[0] === state.date[1]) {
|
||||
return state.date[0];
|
||||
} else {
|
||||
return state.date.join('~');
|
||||
}
|
||||
});
|
||||
const dateFilterText = computed(() => {
|
||||
if (state.date[0] === state.date[1]) {
|
||||
return state.date[0];
|
||||
} else {
|
||||
return state.date.join('~');
|
||||
}
|
||||
});
|
||||
|
||||
async function getLogList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { code, data } = await BrokerageApi.getBrokerageRecordPage({
|
||||
pageSize: state.pagination.pageSize,
|
||||
pageNo: state.pagination.pageNo,
|
||||
async function getLogList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { code, data } = await BrokerageApi.getBrokerageRecordPage({
|
||||
pageSize: state.pagination.pageSize,
|
||||
pageNo: state.pagination.pageNo,
|
||||
bizType: tabMaps[state.currentTab].value,
|
||||
'createTime[0]': state.date[0] + ' 00:00:00',
|
||||
'createTime[1]': state.date[1] + ' 23:59:59',
|
||||
});
|
||||
if (code !== 0) {
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
}
|
||||
|
||||
function onChangeTab(e) {
|
||||
resetPagination(state.pagination);
|
||||
state.currentTab = e.index;
|
||||
getLogList();
|
||||
}
|
||||
|
||||
function onChangeTime(e) {
|
||||
state.date[0] = e[0];
|
||||
state.date[1] = e[e.length - 1];
|
||||
function onChangeTab(e) {
|
||||
resetPagination(state.pagination);
|
||||
getLogList();
|
||||
}
|
||||
state.currentTab = e.index;
|
||||
getLogList();
|
||||
}
|
||||
|
||||
// 确认操作(转账到余额)
|
||||
async function onConfirm() {
|
||||
if (state.price <= 0) {
|
||||
sheep.$helper.toast('请输入正确的金额');
|
||||
return;
|
||||
}
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确认把您的佣金转入到余额钱包中?',
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
function onChangeTime(e) {
|
||||
state.date[0] = e[0];
|
||||
state.date[1] = e[e.length - 1];
|
||||
resetPagination(state.pagination);
|
||||
getLogList();
|
||||
}
|
||||
|
||||
// 确认操作(转账到余额)
|
||||
async function onConfirm() {
|
||||
if (state.price <= 0) {
|
||||
sheep.$helper.toast('请输入正确的金额');
|
||||
return;
|
||||
}
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确认把您的佣金转入到余额钱包中?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const { code } = await BrokerageApi.createBrokerageWithdraw({
|
||||
type: 1, // 钱包
|
||||
price: state.price * 100,
|
||||
|
|
@ -199,272 +246,273 @@
|
|||
state.showModal = false;
|
||||
await getAgentInfo();
|
||||
onChangeTab({
|
||||
index: 1
|
||||
index: 1,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function getAgentInfo() {
|
||||
const { code, data } = await BrokerageApi.getBrokerageUserSummary();
|
||||
async function getAgentInfo() {
|
||||
const { code, data } = await BrokerageApi.getBrokerageUserSummary();
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.summary = data;
|
||||
}
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
state.today = dayjs().format('YYYY-MM-DD');
|
||||
state.date = [state.today, state.today];
|
||||
if (options.type === 2) { // 切换到“提现” tab 下
|
||||
onLoad(async (options) => {
|
||||
state.today = dayjs().format('YYYY-MM-DD');
|
||||
state.date = [state.today, state.today];
|
||||
if (options.type === 2) {
|
||||
// 切换到“提现” tab 下
|
||||
state.currentTab = 1;
|
||||
}
|
||||
getLogList();
|
||||
getAgentInfo();
|
||||
});
|
||||
getLogList();
|
||||
getAgentInfo();
|
||||
});
|
||||
|
||||
onReachBottom(() => {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
onReachBottom(() => {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getLogList();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 钱包
|
||||
.header-box {
|
||||
background-color: $white;
|
||||
padding: 30rpx;
|
||||
// 钱包
|
||||
.header-box {
|
||||
background-color: $white;
|
||||
padding: 30rpx;
|
||||
|
||||
.card-box {
|
||||
width: 100%;
|
||||
min-height: 300rpx;
|
||||
padding: 40rpx;
|
||||
background-size: 100% 100%;
|
||||
border-radius: 30rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
.card-box {
|
||||
width: 100%;
|
||||
min-height: 300rpx;
|
||||
padding: 40rpx;
|
||||
background-size: 100% 100%;
|
||||
border-radius: 30rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: v-bind(headerBg) no-repeat;
|
||||
pointer-events: none;
|
||||
}
|
||||
&::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: v-bind(headerBg) no-repeat;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.card-head {
|
||||
color: $white;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.card-head {
|
||||
color: $white;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.ss-eye-icon {
|
||||
font-size: 40rpx;
|
||||
color: $white;
|
||||
}
|
||||
.ss-eye-icon {
|
||||
font-size: 40rpx;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.money-num {
|
||||
font-size: 40rpx;
|
||||
line-height: normal;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
.money-num {
|
||||
font-size: 40rpx;
|
||||
line-height: normal;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.reduce-num {
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
color: $white;
|
||||
}
|
||||
.reduce-num {
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.withdraw-btn {
|
||||
width: 120rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border-radius: 30px;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
background-color: $white;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
.withdraw-btn {
|
||||
width: 120rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border-radius: 30px;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
background-color: $white;
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
.balance-btn {
|
||||
width: 120rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border-radius: 30px;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
border: 1px solid $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
.balance-btn {
|
||||
width: 120rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border-radius: 30px;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: $white;
|
||||
border: 1px solid $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading-money {
|
||||
margin-top: 56rpx;
|
||||
.loading-money {
|
||||
margin-top: 56rpx;
|
||||
|
||||
.loading-money-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: normal;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
.loading-money-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: normal;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.loading-money-num {
|
||||
font-size: 30rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 500;
|
||||
color: #fefefe;
|
||||
}
|
||||
}
|
||||
.loading-money-num {
|
||||
font-size: 30rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 500;
|
||||
color: #fefefe;
|
||||
}
|
||||
}
|
||||
|
||||
// 筛选
|
||||
// 筛选
|
||||
|
||||
.filter-box {
|
||||
height: 120rpx;
|
||||
padding: 0 30rpx;
|
||||
background-color: $bg-page;
|
||||
.filter-box {
|
||||
height: 120rpx;
|
||||
padding: 0 30rpx;
|
||||
background-color: $bg-page;
|
||||
|
||||
.total-box {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: $dark-9;
|
||||
}
|
||||
.total-box {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: $dark-9;
|
||||
}
|
||||
|
||||
.date-btn {
|
||||
background-color: $white;
|
||||
line-height: 54rpx;
|
||||
border-radius: 27rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: $dark-6;
|
||||
.date-btn {
|
||||
background-color: $white;
|
||||
line-height: 54rpx;
|
||||
border-radius: 27rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: $dark-6;
|
||||
|
||||
.ss-seldate-icon {
|
||||
font-size: 50rpx;
|
||||
color: $dark-9;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ss-seldate-icon {
|
||||
font-size: 50rpx;
|
||||
color: $dark-9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tab
|
||||
.wallet-tab-card {
|
||||
.tab-item {
|
||||
height: 80rpx;
|
||||
position: relative;
|
||||
// tab
|
||||
.wallet-tab-card {
|
||||
.tab-item {
|
||||
height: 80rpx;
|
||||
position: relative;
|
||||
|
||||
.tab-title {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.tab-title {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.cur-tab-title {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
.cur-tab-title {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
|
||||
.tab-line {
|
||||
width: 60rpx;
|
||||
height: 6rpx;
|
||||
border-radius: 6rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 2rpx;
|
||||
background-color: var(--ui-BG-Main);
|
||||
}
|
||||
}
|
||||
}
|
||||
.tab-line {
|
||||
width: 60rpx;
|
||||
height: 6rpx;
|
||||
border-radius: 6rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 2rpx;
|
||||
background-color: var(--ui-BG-Main);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 钱包记录
|
||||
.wallet-list {
|
||||
padding: 30rpx;
|
||||
background-color: #ffff;
|
||||
// 钱包记录
|
||||
.wallet-list {
|
||||
padding: 30rpx;
|
||||
background-color: #ffff;
|
||||
|
||||
.head-img {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 50%;
|
||||
background: $gray-c;
|
||||
}
|
||||
.head-img {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 50%;
|
||||
background: $gray-c;
|
||||
}
|
||||
|
||||
.list-content {
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
flex: 1;
|
||||
.list-content {
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
flex: 1;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: $dark-3;
|
||||
width: 400rpx;
|
||||
}
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: $dark-3;
|
||||
width: 400rpx;
|
||||
}
|
||||
|
||||
.time {
|
||||
color: $gray-c;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
.time {
|
||||
color: $gray-c;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.money {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
font-family: OPPOSANS;
|
||||
.money {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
font-family: OPPOSANS;
|
||||
|
||||
.add {
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
.add {
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
|
||||
.minus {
|
||||
color: $dark-3;
|
||||
}
|
||||
}
|
||||
}
|
||||
.minus {
|
||||
color: $dark-3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.model-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
.model-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.model-subtitle {
|
||||
font-size: 26rpx;
|
||||
color: #c2c7cf;
|
||||
}
|
||||
.model-subtitle {
|
||||
font-size: 26rpx;
|
||||
color: #c2c7cf;
|
||||
}
|
||||
|
||||
.model-btn {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: normal;
|
||||
}
|
||||
.model-btn {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.input-box {
|
||||
height: 100rpx;
|
||||
.input-box {
|
||||
height: 100rpx;
|
||||
|
||||
.unit {
|
||||
font-size: 48rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
}
|
||||
.unit {
|
||||
font-size: 48rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.uni-easyinput__placeholder-class {
|
||||
font-size: 30rpx;
|
||||
height: 40rpx;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.uni-easyinput__placeholder-class {
|
||||
font-size: 30rpx;
|
||||
height: 40rpx;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -16,13 +16,16 @@
|
|||
<view class="title ss-m-t-50 ss-m-b-20 ss-m-x-20">{{ state.coupon.name }}</view>
|
||||
<view class="subtitle ss-m-b-50">
|
||||
满 {{ fen2yuan(state.coupon.usePrice) }} 元,
|
||||
{{ state.coupon.discountType === 1
|
||||
? '减 ' + fen2yuan(state.coupon.discountPrice) + ' 元'
|
||||
: '打 ' + state.coupon.discountPercent / 10.0 + ' 折' }}
|
||||
{{
|
||||
state.coupon.discountType === 1
|
||||
? '减 ' + fen2yuan(state.coupon.discountPrice) + ' 元'
|
||||
: '打 ' + state.coupon.discountPercent / 10.0 + ' 折'
|
||||
}}
|
||||
</view>
|
||||
<button
|
||||
class="ss-reset-button ss-m-b-30"
|
||||
:class="state.coupon.canTake || state.coupon.status === 1
|
||||
:class="
|
||||
state.coupon.canTake || state.coupon.status === 1
|
||||
? 'use-btn' // 优惠劵模版(可领取)、优惠劵(可使用)
|
||||
: 'disable-btn'
|
||||
"
|
||||
|
|
@ -31,7 +34,13 @@
|
|||
>
|
||||
<text v-if="state.id > 0">{{ state.coupon.canTake ? '立即领取' : '已领取' }}</text>
|
||||
<text v-else>
|
||||
{{ state.coupon.status === 1 ? '立即使用' : state.coupon.status === 2 ? '已使用' : '已过期' }}
|
||||
{{
|
||||
state.coupon.status === 1
|
||||
? '立即使用'
|
||||
: state.coupon.status === 2
|
||||
? '已使用'
|
||||
: '已过期'
|
||||
}}
|
||||
</text>
|
||||
</button>
|
||||
<view class="time ss-m-y-30" v-if="state.coupon.validityType === 2">
|
||||
|
|
@ -140,7 +149,7 @@
|
|||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
|
|
@ -176,7 +185,7 @@
|
|||
const { code, data } = await SpuApi.getSpuPage({
|
||||
categoryId: state.categoryId,
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize
|
||||
pageSize: state.pagination.pageSize,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
|
|
@ -197,7 +206,9 @@
|
|||
|
||||
// 获得分类列表
|
||||
async function getCategoryList() {
|
||||
const { data, code } = await CategoryApi.getCategoryListByIds(state.coupon.productScopeValues.join(','));
|
||||
const { data, code } = await CategoryApi.getCategoryListByIds(
|
||||
state.coupon.productScopeValues.join(','),
|
||||
);
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -225,8 +236,10 @@
|
|||
|
||||
// 加载优惠劵信息
|
||||
async function getCouponContent() {
|
||||
const { code, data } = state.id > 0 ? await CouponApi.getCouponTemplate(state.id)
|
||||
: await CouponApi.getCoupon(state.couponId);
|
||||
const { code, data } =
|
||||
state.id > 0
|
||||
? await CouponApi.getCouponTemplate(state.id)
|
||||
: await CouponApi.getCoupon(state.couponId);
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
<template #default>
|
||||
<button
|
||||
class="ss-reset-button card-btn ss-flex ss-row-center ss-col-center"
|
||||
:class=" item.status !== 1 ? 'disabled-btn': ''"
|
||||
:class="item.status !== 1 ? 'disabled-btn' : ''"
|
||||
:disabled="item.status !== 1"
|
||||
@click.stop="sheep.$router.go('/pages/coupon/detail', { couponId: item.id })"
|
||||
>
|
||||
|
|
@ -56,9 +56,14 @@
|
|||
</view>
|
||||
</template>
|
||||
|
||||
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}" @tap="loadMore" />
|
||||
}"
|
||||
@tap="loadMore"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
|
|
@ -66,7 +71,7 @@
|
|||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
|
||||
|
|
@ -78,7 +83,7 @@
|
|||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 5
|
||||
pageSize: 5,
|
||||
},
|
||||
loadStatus: '',
|
||||
});
|
||||
|
|
@ -106,9 +111,9 @@
|
|||
function onTabsChange(e) {
|
||||
state.currentTab = e.index;
|
||||
state.type = e.value;
|
||||
resetPagination(state.pagination)
|
||||
resetPagination(state.pagination);
|
||||
if (state.currentTab === 0) {
|
||||
getData();
|
||||
getData();
|
||||
} else {
|
||||
getCoupon();
|
||||
}
|
||||
|
|
@ -135,7 +140,7 @@
|
|||
const { data, code } = await CouponApi.getCouponPage({
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
status: state.type
|
||||
status: state.type,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
|
|
@ -177,13 +182,13 @@
|
|||
// 领劵中心
|
||||
if (Option.type === 'all' || !Option.type) {
|
||||
getData();
|
||||
// 我的优惠劵
|
||||
// 我的优惠劵
|
||||
} else {
|
||||
Option.type === 'geted'
|
||||
? (state.currentTab = 1)
|
||||
: Option.type === 'used'
|
||||
? (state.currentTab = 2)
|
||||
: (state.currentTab = 3);
|
||||
? (state.currentTab = 2)
|
||||
: (state.currentTab = 3);
|
||||
state.type = state.currentTab;
|
||||
getCoupon();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
import CommentApi from '@/sheep/api/product/comment';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import commentItem from '../components/detail/comment-item.vue';
|
||||
|
||||
const state = reactive({
|
||||
|
|
|
|||
|
|
@ -7,12 +7,16 @@
|
|||
<detailSkeleton v-if="state.skeletonLoading" />
|
||||
<!-- 下架/售罄提醒 -->
|
||||
<s-empty
|
||||
v-else-if="state.goodsInfo === null || state.activity.status !== 0 || state.activity.endTime < new Date().getTime()"
|
||||
text="活动不存在或已结束"
|
||||
icon="/static/soldout-empty.png"
|
||||
showAction
|
||||
actionText="返回上一页"
|
||||
@clickAction="sheep.$router.back()"
|
||||
v-else-if="
|
||||
state.goodsInfo === null ||
|
||||
state.activity.status !== 0 ||
|
||||
state.activity.endTime < new Date().getTime()
|
||||
"
|
||||
text="活动不存在或已结束"
|
||||
icon="/static/soldout-empty.png"
|
||||
showAction
|
||||
actionText="返回上一页"
|
||||
@clickAction="sheep.$router.back()"
|
||||
/>
|
||||
<block v-else>
|
||||
<view class="detail-swiper-selector">
|
||||
|
|
@ -47,10 +51,7 @@
|
|||
</view>
|
||||
</view>
|
||||
<view class="ss-flex ss-row-between">
|
||||
<view
|
||||
class="origin-price ss-flex ss-col-center"
|
||||
v-if="state.goodsInfo.price"
|
||||
>
|
||||
<view class="origin-price ss-flex ss-col-center" v-if="state.goodsInfo.price">
|
||||
单买价:
|
||||
<view class="origin-price-text">
|
||||
{{ fen2yuan(state.goodsInfo.price) }}
|
||||
|
|
@ -79,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>
|
||||
|
||||
<!-- 参团列表 -->
|
||||
|
|
@ -89,6 +90,7 @@
|
|||
<s-select-groupon-sku
|
||||
:show="state.showSelectSku"
|
||||
:goodsInfo="state.goodsInfo"
|
||||
:selectedSku="state.selectedSku"
|
||||
:grouponAction="state.grouponAction"
|
||||
:grouponNum="state.grouponNum"
|
||||
@buy="onBuy"
|
||||
|
|
@ -123,7 +125,9 @@
|
|||
"
|
||||
:disabled="state.goodsInfo.stock === 0 || state.activity.status !== 0"
|
||||
>
|
||||
<view class="btn-price">{{ fen2yuan(state.activity.price || state.goodsInfo.price) }}</view>
|
||||
<view class="btn-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>
|
||||
<view v-else>
|
||||
|
|
@ -141,7 +145,7 @@
|
|||
import { reactive, computed } from 'vue';
|
||||
import { onLoad, onPageScroll } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
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';
|
||||
|
|
@ -149,29 +153,27 @@
|
|||
import detailCommentCard from './components/detail/detail-comment-card.vue';
|
||||
import detailContentCard from './components/detail/detail-content-card.vue';
|
||||
import grouponCardList from './components/groupon/groupon-card-list.vue';
|
||||
import {useDurationTime, formatGoodsSwiper, fen2yuan} from '@/sheep/hooks/useGoods';
|
||||
import CombinationApi from "@/sheep/api/promotion/combination";
|
||||
import SpuApi from "@/sheep/api/product/spu";
|
||||
import { useDurationTime, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import CombinationApi from '@/sheep/api/promotion/combination';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
|
||||
const headerBg = sheep.$url.css('/static/img/shop/goods/groupon-bg.png');
|
||||
const btnBg = sheep.$url.css('/static/img/shop/goods/groupon-btn.png');
|
||||
const disabledBtnBg = sheep.$url.css(
|
||||
'/static/img/shop/goods/activity-btn-disabled.png',
|
||||
);
|
||||
const disabledBtnBg = sheep.$url.css('/static/img/shop/goods/activity-btn-disabled.png');
|
||||
const grouponBg = sheep.$url.css('/static/img/shop/goods/groupon-tip-bg.png');
|
||||
|
||||
onPageScroll(() => {});
|
||||
const state = reactive({
|
||||
skeletonLoading: true, // 骨架屏
|
||||
goodsId: 0, // 商品ID
|
||||
goodsInfo: {}, // 商品信息
|
||||
goodsSwiper: [], // 商品轮播图
|
||||
showSelectSku: false, // 显示规格弹框
|
||||
selectedSkuPrice: {}, // 选中的规格价格
|
||||
activity: {}, // 团购活动
|
||||
grouponId: 0, // 团购ID
|
||||
grouponNum: 0, // 团购人数
|
||||
grouponAction: 'create', // 团购操作
|
||||
skeletonLoading: true, // 骨架屏
|
||||
goodsId: 0, // 商品ID
|
||||
goodsInfo: {}, // 商品信息
|
||||
goodsSwiper: [], // 商品轮播图
|
||||
showSelectSku: false, // 显示规格弹框
|
||||
selectedSku: {}, // 选中的规格属性
|
||||
activity: {}, // 团购活动
|
||||
grouponId: 0, // 团购ID
|
||||
grouponNum: 0, // 团购人数
|
||||
grouponAction: 'create', // 团购操作
|
||||
combinationHeadId: null, // 拼团团长编号
|
||||
});
|
||||
|
||||
|
|
@ -182,7 +184,7 @@
|
|||
|
||||
// 规格变更
|
||||
function onSkuChange(e) {
|
||||
state.selectedSkuPrice = e;
|
||||
state.selectedSku = e;
|
||||
}
|
||||
|
||||
function onSkuClose() {
|
||||
|
|
@ -198,6 +200,7 @@
|
|||
|
||||
/**
|
||||
* 去参团
|
||||
*
|
||||
* @param record 团长的团购记录
|
||||
*/
|
||||
function onJoinGroupon(record) {
|
||||
|
|
@ -226,7 +229,6 @@
|
|||
}
|
||||
|
||||
// 分享信息
|
||||
// TODO @芋艿:分享的接入
|
||||
const shareInfo = computed(() => {
|
||||
if (isEmpty(state.activity)) return {};
|
||||
return sheep.$platform.share.getShareInfo(
|
||||
|
|
@ -261,9 +263,21 @@
|
|||
// 加载商品信息
|
||||
const { data: spu } = await SpuApi.getSpuDetail(activity.spuId);
|
||||
state.goodsId = spu.id;
|
||||
activity.products.forEach(product => {
|
||||
// 默认显示最低价
|
||||
activity.products.forEach((product) => {
|
||||
spu.price = Math.min(spu.price, product.combinationPrice); // 设置 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;
|
||||
}
|
||||
});
|
||||
|
||||
// 关闭骨架屏
|
||||
state.skeletonLoading = false;
|
||||
if (code === 0) {
|
||||
|
|
@ -475,8 +489,7 @@
|
|||
}
|
||||
|
||||
.groupon-box {
|
||||
background: v-bind(grouponBg)
|
||||
no-repeat;
|
||||
background: v-bind(grouponBg) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@
|
|||
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';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
|
||||
onPageScroll(() => {});
|
||||
|
|
@ -156,11 +156,9 @@
|
|||
data: JSON.stringify({
|
||||
items: [{
|
||||
skuId: e.id,
|
||||
count: e.goods_num
|
||||
}],
|
||||
// TODO 芋艿:后续清理掉这 2 参数
|
||||
deliveryType: 1,
|
||||
pointStatus: false,
|
||||
count: e.goods_num,
|
||||
categoryId: state.goodsInfo.categoryId
|
||||
}]
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,362 +1,398 @@
|
|||
<template>
|
||||
<s-layout navbar="normal" :leftWidth="0" :rightWidth="0" tools="search" :defaultSearch="state.keyword"
|
||||
@search="onSearch">
|
||||
<!-- 筛选 -->
|
||||
<su-sticky bgColor="#fff">
|
||||
<view class="ss-flex">
|
||||
<view class="ss-flex-1">
|
||||
<su-tabs :list="state.tabList" :scrollable="false" @change="onTabsChange"
|
||||
:current="state.currentTab" />
|
||||
</view>
|
||||
<view class="list-icon" @tap="state.iconStatus = !state.iconStatus">
|
||||
<text v-if="state.iconStatus" class="sicon-goods-list" />
|
||||
<text v-else class="sicon-goods-card" />
|
||||
</view>
|
||||
</view>
|
||||
</su-sticky>
|
||||
<s-layout
|
||||
navbar="normal"
|
||||
:leftWidth="0"
|
||||
:rightWidth="0"
|
||||
tools="search"
|
||||
:defaultSearch="state.keyword"
|
||||
@search="onSearch"
|
||||
>
|
||||
<!-- 筛选 -->
|
||||
<su-sticky bgColor="#fff">
|
||||
<view class="ss-flex">
|
||||
<view class="ss-flex-1">
|
||||
<su-tabs
|
||||
:list="state.tabList"
|
||||
:scrollable="false"
|
||||
@change="onTabsChange"
|
||||
:current="state.currentTab"
|
||||
/>
|
||||
</view>
|
||||
<view class="list-icon" @tap="state.iconStatus = !state.iconStatus">
|
||||
<text v-if="state.iconStatus" class="sicon-goods-list" />
|
||||
<text v-else class="sicon-goods-card" />
|
||||
</view>
|
||||
</view>
|
||||
</su-sticky>
|
||||
|
||||
<!-- 弹窗 -->
|
||||
<su-popup :show="state.showFilter" type="top" round="10" :space="sys_navBar + 38" backgroundColor="#F6F6F6"
|
||||
:zIndex="10" @close="state.showFilter = false">
|
||||
<view class="filter-list-box">
|
||||
<view class="filter-item" v-for="(item, index) in state.tabList[state.currentTab].list"
|
||||
:key="item.value" :class="[{ 'filter-item-active': index === state.curFilter }]"
|
||||
@tap="onFilterItem(index)">
|
||||
{{ item.label }}
|
||||
</view>
|
||||
</view>
|
||||
</su-popup>
|
||||
<!-- 弹窗 -->
|
||||
<su-popup
|
||||
:show="state.showFilter"
|
||||
type="top"
|
||||
round="10"
|
||||
:space="sys_navBar + 38"
|
||||
backgroundColor="#F6F6F6"
|
||||
:zIndex="10"
|
||||
@close="state.showFilter = false"
|
||||
>
|
||||
<view class="filter-list-box">
|
||||
<view
|
||||
class="filter-item"
|
||||
v-for="(item, index) in state.tabList[state.currentTab].list"
|
||||
:key="item.value"
|
||||
:class="[{ 'filter-item-active': index === state.curFilter }]"
|
||||
@tap="onFilterItem(index)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</view>
|
||||
</view>
|
||||
</su-popup>
|
||||
|
||||
<!-- 情况一:单列布局 -->
|
||||
<view v-if="state.iconStatus && state.pagination.total > 0" class="goods-list ss-m-t-20">
|
||||
<view class="ss-p-l-20 ss-p-r-20 ss-m-b-20" v-for="item in state.pagination.list" :key="item.id">
|
||||
<s-goods-column
|
||||
<view v-if="state.iconStatus && state.pagination.total > 0" class="goods-list ss-m-t-20">
|
||||
<view
|
||||
class="ss-p-l-20 ss-p-r-20 ss-m-b-20"
|
||||
v-for="item in state.pagination.list"
|
||||
:key="item.id"
|
||||
>
|
||||
<s-goods-column
|
||||
class=""
|
||||
size="lg"
|
||||
:data="item"
|
||||
:topRadius="10"
|
||||
:bottomRadius="10"
|
||||
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
|
||||
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 情况二:双列布局 -->
|
||||
<view v-if="!state.iconStatus && state.pagination.total > 0"
|
||||
class="ss-flex ss-flex-wrap ss-p-x-20 ss-m-t-20 ss-col-top">
|
||||
<view class="goods-list-box">
|
||||
<view class="left-list" v-for="item in state.leftGoodsList" :key="item.id">
|
||||
<s-goods-column
|
||||
<view
|
||||
v-if="!state.iconStatus && state.pagination.total > 0"
|
||||
class="ss-flex ss-flex-wrap ss-p-x-20 ss-m-t-20 ss-col-top"
|
||||
>
|
||||
<view class="goods-list-box">
|
||||
<view class="left-list" v-for="item in state.leftGoodsList" :key="item.id">
|
||||
<s-goods-column
|
||||
class="goods-md-box"
|
||||
size="md"
|
||||
:data="item"
|
||||
:topRadius="10"
|
||||
:bottomRadius="10"
|
||||
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
|
||||
@getHeight="mountMasonry($event, 'left')"
|
||||
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
|
||||
@getHeight="mountMasonry($event, 'left')"
|
||||
>
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" />
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-list-box">
|
||||
<view class="right-list" v-for="item in state.rightGoodsList" :key="item.id">
|
||||
<s-goods-column
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" />
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-list-box">
|
||||
<view class="right-list" v-for="item in state.rightGoodsList" :key="item.id">
|
||||
<s-goods-column
|
||||
class="goods-md-box"
|
||||
size="md"
|
||||
:topRadius="10"
|
||||
:bottomRadius="10"
|
||||
:data="item"
|
||||
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
|
||||
@getHeight="mountMasonry($event, 'right')"
|
||||
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
|
||||
@getHeight="mountMasonry($event, 'right')"
|
||||
>
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" />
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{
|
||||
<template v-slot:cart>
|
||||
<button class="ss-reset-button cart-btn" />
|
||||
</template>
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}" @tap="loadMore" />
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/soldout-empty.png" text="暂无商品" />
|
||||
</s-layout>
|
||||
}"
|
||||
@tap="loadMore"
|
||||
/>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/soldout-empty.png" text="暂无商品" />
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash';
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash-es';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
|
||||
const sys_navBar = sheep.$platform.navbar;
|
||||
const emits = defineEmits(['close', 'change']);
|
||||
const sys_navBar = sheep.$platform.navbar;
|
||||
const emits = defineEmits(['close', 'change']);
|
||||
|
||||
const state = reactive({
|
||||
pagination: {
|
||||
list: [],
|
||||
const state = reactive({
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 6,
|
||||
},
|
||||
currentSort: undefined,
|
||||
currentOrder: undefined,
|
||||
currentTab: 0, // 当前选中的 tab
|
||||
curFilter: 0, // 当前选中的 list 筛选项
|
||||
showFilter: false,
|
||||
iconStatus: false, // true - 单列布局;false - 双列布局
|
||||
pageSize: 6,
|
||||
},
|
||||
currentSort: undefined,
|
||||
currentOrder: undefined,
|
||||
currentTab: 0, // 当前选中的 tab
|
||||
curFilter: 0, // 当前选中的 list 筛选项
|
||||
showFilter: false,
|
||||
iconStatus: false, // true - 单列布局;false - 双列布局
|
||||
keyword: '',
|
||||
categoryId: 0,
|
||||
tabList: [{
|
||||
name: '综合推荐',
|
||||
list: [{
|
||||
label: '综合推荐'
|
||||
},
|
||||
{
|
||||
label: '价格升序',
|
||||
sort: 'price',
|
||||
order: true,
|
||||
},
|
||||
{
|
||||
label: '价格降序',
|
||||
sort: 'price',
|
||||
order: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '销量',
|
||||
sort: 'salesCount',
|
||||
order: false
|
||||
},
|
||||
{
|
||||
name: '新品优先',
|
||||
value: 'createTime',
|
||||
order: false
|
||||
},
|
||||
],
|
||||
loadStatus: '',
|
||||
leftGoodsList: [], // 双列布局 - 左侧商品
|
||||
rightGoodsList: [], // 双列布局 - 右侧商品
|
||||
});
|
||||
tabList: [
|
||||
{
|
||||
name: '综合推荐',
|
||||
list: [
|
||||
{
|
||||
label: '综合推荐',
|
||||
},
|
||||
{
|
||||
label: '价格升序',
|
||||
sort: 'price',
|
||||
order: true,
|
||||
},
|
||||
{
|
||||
label: '价格降序',
|
||||
sort: 'price',
|
||||
order: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '销量',
|
||||
sort: 'salesCount',
|
||||
order: false,
|
||||
},
|
||||
{
|
||||
name: '新品优先',
|
||||
value: 'createTime',
|
||||
order: false,
|
||||
},
|
||||
],
|
||||
loadStatus: '',
|
||||
leftGoodsList: [], // 双列布局 - 左侧商品
|
||||
rightGoodsList: [], // 双列布局 - 右侧商品
|
||||
});
|
||||
|
||||
// 加载瀑布流
|
||||
let count = 0;
|
||||
let leftHeight = 0;
|
||||
let rightHeight = 0;
|
||||
// 加载瀑布流
|
||||
let count = 0;
|
||||
let leftHeight = 0;
|
||||
let rightHeight = 0;
|
||||
|
||||
// 处理双列布局 leftGoodsList + rightGoodsList
|
||||
function mountMasonry(height = 0, where = 'left') {
|
||||
if (!state.pagination.list[count]) {
|
||||
function mountMasonry(height = 0, where = 'left') {
|
||||
if (!state.pagination.list[count]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (where === 'left') {
|
||||
leftHeight += height;
|
||||
} else {
|
||||
rightHeight += height;
|
||||
}
|
||||
if (leftHeight <= rightHeight) {
|
||||
state.leftGoodsList.push(state.pagination.list[count]);
|
||||
} else {
|
||||
state.rightGoodsList.push(state.pagination.list[count]);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
if (where === 'left') {
|
||||
leftHeight += height;
|
||||
} else {
|
||||
rightHeight += height;
|
||||
}
|
||||
if (leftHeight <= rightHeight) {
|
||||
state.leftGoodsList.push(state.pagination.list[count]);
|
||||
} else {
|
||||
state.rightGoodsList.push(state.pagination.list[count]);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
// 清空列表
|
||||
function emptyList() {
|
||||
function emptyList() {
|
||||
resetPagination(state.pagination);
|
||||
state.leftGoodsList = [];
|
||||
state.rightGoodsList = [];
|
||||
count = 0;
|
||||
leftHeight = 0;
|
||||
rightHeight = 0;
|
||||
}
|
||||
state.rightGoodsList = [];
|
||||
count = 0;
|
||||
leftHeight = 0;
|
||||
rightHeight = 0;
|
||||
}
|
||||
|
||||
// 搜索
|
||||
function onSearch(e) {
|
||||
state.keyword = e;
|
||||
emptyList();
|
||||
getList(state.currentSort, state.currentOrder);
|
||||
}
|
||||
// 搜索
|
||||
function onSearch(e) {
|
||||
state.keyword = e;
|
||||
emptyList();
|
||||
getList(state.currentSort, state.currentOrder);
|
||||
}
|
||||
|
||||
// 点击
|
||||
function onTabsChange(e) {
|
||||
// 点击
|
||||
function onTabsChange(e) {
|
||||
// 如果点击的是【综合推荐】,则直接展开或者收起筛选项
|
||||
if (state.tabList[e.index].list) {
|
||||
state.currentTab = e.index;
|
||||
state.showFilter = !state.showFilter;
|
||||
return;
|
||||
}
|
||||
if (state.tabList[e.index].list) {
|
||||
state.currentTab = e.index;
|
||||
state.showFilter = !state.showFilter;
|
||||
return;
|
||||
}
|
||||
state.showFilter = false;
|
||||
|
||||
// 如果点击的是【销量】或者【新品优先】,则直接切换 tab
|
||||
if (e.index === state.currentTab) {
|
||||
return;
|
||||
}
|
||||
if (e.index === state.currentTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.currentTab = e.index;
|
||||
state.currentSort = e.sort;
|
||||
state.currentOrder = e.order;
|
||||
emptyList();
|
||||
getList(e.sort, e.order);
|
||||
}
|
||||
emptyList();
|
||||
getList(e.sort, e.order);
|
||||
}
|
||||
|
||||
// 点击 tab 的 list 筛选项
|
||||
const onFilterItem = (val) => {
|
||||
// 点击 tab 的 list 筛选项
|
||||
const onFilterItem = (val) => {
|
||||
// 如果点击的是当前的筛选项,则直接收起筛选项,不要加载数据
|
||||
// 这里选择 tabList[0] 的原因,是目前只有它有 list
|
||||
if (state.currentSort === state.tabList[0].list[val].sort
|
||||
&& state.currentOrder === state.tabList[0].list[val].order) {
|
||||
state.showFilter = false;
|
||||
return;
|
||||
}
|
||||
if (
|
||||
state.currentSort === state.tabList[0].list[val].sort &&
|
||||
state.currentOrder === state.tabList[0].list[val].order
|
||||
) {
|
||||
state.showFilter = false;
|
||||
return;
|
||||
}
|
||||
state.showFilter = false;
|
||||
|
||||
// 设置筛选条件
|
||||
state.curFilter = val;
|
||||
state.tabList[0].name = state.tabList[0].list[val].label;
|
||||
state.currentSort = state.tabList[0].list[val].sort;
|
||||
state.currentOrder = state.tabList[0].list[val].order;
|
||||
// 清空 + 加载数据
|
||||
state.curFilter = val;
|
||||
state.tabList[0].name = state.tabList[0].list[val].label;
|
||||
state.currentSort = state.tabList[0].list[val].sort;
|
||||
state.currentOrder = state.tabList[0].list[val].order;
|
||||
// 清空 + 加载数据
|
||||
emptyList();
|
||||
getList();
|
||||
}
|
||||
getList();
|
||||
};
|
||||
|
||||
async function getList() {
|
||||
state.loadStatus = 'loading';
|
||||
const { code, data } = await SpuApi.getSpuPage({
|
||||
async function getList() {
|
||||
state.loadStatus = 'loading';
|
||||
const { code, data } = await SpuApi.getSpuPage({
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
sortField: state.currentSort,
|
||||
sortAsc: state.currentOrder,
|
||||
categoryId: state.categoryId,
|
||||
keyword: state.keyword,
|
||||
});
|
||||
sortField: state.currentSort,
|
||||
sortAsc: state.currentOrder,
|
||||
categoryId: state.categoryId,
|
||||
keyword: state.keyword,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list)
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
mountMasonry();
|
||||
}
|
||||
}
|
||||
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getList(state.currentSort, state.currentOrder);
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
state.categoryId = options.categoryId;
|
||||
state.keyword = options.keyword;
|
||||
getList(state.currentSort, state.currentOrder);
|
||||
});
|
||||
onLoad((options) => {
|
||||
state.categoryId = options.categoryId;
|
||||
state.keyword = options.keyword;
|
||||
getList(state.currentSort, state.currentOrder);
|
||||
});
|
||||
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.goods-list-box {
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
.goods-list-box {
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.left-list {
|
||||
margin-right: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.left-list {
|
||||
margin-right: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.right-list {
|
||||
margin-left: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
}
|
||||
.right-list {
|
||||
margin-left: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-box {
|
||||
&:nth-last-of-type(1) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.goods-box {
|
||||
&:nth-last-of-type(1) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
&:nth-child(2n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
&:nth-child(2n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.list-icon {
|
||||
width: 80rpx;
|
||||
.list-icon {
|
||||
width: 80rpx;
|
||||
|
||||
.sicon-goods-card {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
.sicon-goods-card {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
|
||||
.sicon-goods-list {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
}
|
||||
.sicon-goods-list {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-card {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
.goods-card {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.list-filter-tabs {
|
||||
background-color: #fff;
|
||||
}
|
||||
.list-filter-tabs {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.filter-list-box {
|
||||
padding: 28rpx 52rpx;
|
||||
.filter-list-box {
|
||||
padding: 28rpx 52rpx;
|
||||
|
||||
.filter-item {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: normal;
|
||||
margin-bottom: 24rpx;
|
||||
.filter-item {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: normal;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.filter-item-active {
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
}
|
||||
.filter-item-active {
|
||||
color: var(--ui-BG-Main);
|
||||
}
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
height: 50px;
|
||||
position: relative;
|
||||
z-index: 11;
|
||||
.tab-item {
|
||||
height: 50px;
|
||||
position: relative;
|
||||
z-index: 11;
|
||||
|
||||
.tab-title {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.tab-title {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.cur-tab-title {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
.cur-tab-title {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
|
||||
.tab-line {
|
||||
width: 60rpx;
|
||||
height: 6rpx;
|
||||
border-radius: 6rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 10rpx;
|
||||
background-color: var(--ui-BG-Main);
|
||||
z-index: 12;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.tab-line {
|
||||
width: 60rpx;
|
||||
height: 6rpx;
|
||||
border-radius: 6rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 10rpx;
|
||||
background-color: var(--ui-BG-Main);
|
||||
z-index: 12;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -63,16 +63,13 @@
|
|||
<detail-progress :percent="state.percent" />
|
||||
</view>
|
||||
|
||||
<view class="title-text ss-line-2 ss-m-b-6">{{ state.goodsInfo?.name }}</view>
|
||||
<view class="title-text ss-line-2 ss-m-b-6">{{ state.goodsInfo.name || '' }}</view>
|
||||
<view class="subtitle-text ss-line-1">{{ state.goodsInfo.introduction }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 功能卡片 -->
|
||||
<view class="detail-cell-card detail-card ss-flex-col">
|
||||
<detail-cell-sku
|
||||
:sku="state.selectedSku"
|
||||
@tap="state.showSelectSku = true"
|
||||
/>
|
||||
<detail-cell-sku :sku="state.selectedSku" @tap="state.showSelectSku = true" />
|
||||
</view>
|
||||
<!-- 规格与数量弹框 -->
|
||||
<s-select-seckill-sku
|
||||
|
|
@ -107,7 +104,9 @@
|
|||
<button v-else class="ss-reset-button origin-price-btn ss-flex-col">
|
||||
<view
|
||||
class="no-original"
|
||||
:class="state.goodsInfo.stock === 0 || timeStatusEnum !== TimeStatusEnum.STARTED ? '' : ''"
|
||||
:class="
|
||||
state.goodsInfo.stock === 0 || timeStatusEnum !== TimeStatusEnum.STARTED ? '' : ''
|
||||
"
|
||||
>
|
||||
秒杀价
|
||||
</view>
|
||||
|
|
@ -136,11 +135,11 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import {reactive, computed, ref} from 'vue';
|
||||
import { reactive, computed, ref, unref } from 'vue';
|
||||
import { onLoad, onPageScroll } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import {isEmpty, min} from 'lodash';
|
||||
import {useDurationTime, formatGoodsSwiper, fen2yuan} from '@/sheep/hooks/useGoods';
|
||||
import { isEmpty, min } from 'lodash-es';
|
||||
import { useDurationTime, 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';
|
||||
|
|
@ -148,15 +147,13 @@
|
|||
import detailCommentCard from './components/detail/detail-comment-card.vue';
|
||||
import detailContentCard from './components/detail/detail-content-card.vue';
|
||||
import detailProgress from './components/detail/detail-progress.vue';
|
||||
import SeckillApi from "@/sheep/api/promotion/seckill";
|
||||
import SpuApi from "@/sheep/api/product/spu";
|
||||
import {getTimeStatusEnum, TimeStatusEnum} from "@/sheep/util/const";
|
||||
import SeckillApi from '@/sheep/api/promotion/seckill';
|
||||
import SpuApi from '@/sheep/api/product/spu';
|
||||
import { getTimeStatusEnum, TimeStatusEnum } from '@/sheep/util/const';
|
||||
|
||||
const headerBg = sheep.$url.css('/static/img/shop/goods/seckill-bg.png');
|
||||
const btnBg = sheep.$url.css('/static/img/shop/goods/seckill-btn.png');
|
||||
const disabledBtnBg = sheep.$url.css(
|
||||
'/static/img/shop/goods/activity-btn-disabled.png',
|
||||
);
|
||||
const disabledBtnBg = sheep.$url.css('/static/img/shop/goods/activity-btn-disabled.png');
|
||||
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');
|
||||
|
||||
|
|
@ -199,9 +196,9 @@
|
|||
});
|
||||
}
|
||||
|
||||
// 分享信息 TODO 芋艿:待接入
|
||||
// 分享信息
|
||||
const shareInfo = computed(() => {
|
||||
if (isEmpty(activity)) return {};
|
||||
if (isEmpty(unref(activity))) return {};
|
||||
return sheep.$platform.share.getShareInfo(
|
||||
{
|
||||
title: activity.value.name,
|
||||
|
|
@ -221,36 +218,41 @@
|
|||
);
|
||||
});
|
||||
|
||||
const activity = ref()
|
||||
const timeStatusEnum = ref('')
|
||||
const activity = ref();
|
||||
const timeStatusEnum = ref('');
|
||||
|
||||
// 查询活动
|
||||
const getActivity = async (id) => {
|
||||
const { data } = await SeckillApi.getSeckillActivity(id)
|
||||
activity.value = data
|
||||
timeStatusEnum.value = getTimeStatusEnum(activity.startTime, activity.endTime)
|
||||
const { data } = await SeckillApi.getSeckillActivity(id);
|
||||
activity.value = data;
|
||||
timeStatusEnum.value = getTimeStatusEnum(activity.startTime, activity.endTime);
|
||||
|
||||
// 查询商品
|
||||
await getSpu(data.spuId)
|
||||
}
|
||||
await getSpu(data.spuId);
|
||||
};
|
||||
|
||||
// 查询商品
|
||||
const getSpu = async (id) => {
|
||||
const { data } = await SpuApi.getSpuDetail(id)
|
||||
// 模拟
|
||||
data.activity_type = 'seckill'
|
||||
state.goodsInfo = data
|
||||
const { data } = await SpuApi.getSpuDetail(id);
|
||||
data.activity_type = 'seckill';
|
||||
state.goodsInfo = data;
|
||||
// 处理轮播图
|
||||
state.goodsSwiper = formatGoodsSwiper(state.goodsInfo.sliderPicUrls);
|
||||
|
||||
// 默认显示最低价
|
||||
state.goodsInfo.price = min([state.goodsInfo.price, ...activity.value.products.map(spu => spu.seckillPrice)])
|
||||
state.goodsInfo.price = min([
|
||||
state.goodsInfo.price,
|
||||
...activity.value.products.map((spu) => spu.seckillPrice),
|
||||
]);
|
||||
|
||||
// 价格、库存使用活动的
|
||||
data.skus.forEach(sku => {
|
||||
const product = activity.value.products.find(product => product.skuId === sku.id);
|
||||
data.skus.forEach((sku) => {
|
||||
const product = activity.value.products.find((product) => product.skuId === sku.id);
|
||||
if (product) {
|
||||
sku.price = product.seckillPrice;
|
||||
sku.stock = Math.min(sku.stock, product.stock);
|
||||
} else { // 找不到可能是没配置,则不能发起秒杀
|
||||
} else {
|
||||
// 找不到可能是没配置,则不能发起秒杀
|
||||
sku.stock = 0;
|
||||
}
|
||||
// 设置限购数量
|
||||
|
|
@ -264,7 +266,7 @@
|
|||
});
|
||||
|
||||
state.skeletonLoading = false;
|
||||
}
|
||||
};
|
||||
|
||||
onLoad((options) => {
|
||||
// 非法参数
|
||||
|
|
@ -274,7 +276,7 @@
|
|||
}
|
||||
|
||||
// 查询活动
|
||||
getActivity(options.id)
|
||||
getActivity(options.id);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
import SpuApi from '@/sheep/api/product/spu';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { computed, reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import { handleTree } from '@/sheep/util';
|
||||
|
||||
const state = reactive({
|
||||
|
|
@ -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(() => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,261 @@
|
|||
<!-- 下单界面,收货地址 or 自提门店的选择组件 -->
|
||||
<template>
|
||||
<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>
|
||||
<!-- 情况一:收货地址的选择 -->
|
||||
<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>
|
||||
</view>
|
||||
</view>
|
||||
<view class='addressCon' v-else>
|
||||
<view class='setaddress'>设置收货地址</view>
|
||||
</view>
|
||||
<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>
|
||||
<view class="line1"> {{ state.pickUpInfo.areaName }}{{ ', ' + state.pickUpInfo.detailAddress }}
|
||||
</view>
|
||||
</view>
|
||||
<view class='addressCon' v-else>
|
||||
<view class='setaddress'>选择自提门店</view>
|
||||
</view>
|
||||
<view class='iconfont'>
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class='line'>
|
||||
<image :src="sheep.$url.static('/static/images/line.png', 'local')" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default() {},
|
||||
}
|
||||
});
|
||||
const emits = defineEmits(['update:modelValue']);
|
||||
|
||||
// computed 解决父子组件双向数据同步
|
||||
const state = computed({
|
||||
get(){
|
||||
return new Proxy(props.modelValue, {
|
||||
set(obj, name, val) {
|
||||
emits('update:modelValue', {
|
||||
...obj,
|
||||
[name]: val,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
})
|
||||
},
|
||||
set(val){
|
||||
emits('update:modelValue', val);
|
||||
}
|
||||
})
|
||||
|
||||
// 选择地址
|
||||
function onSelectAddress() {
|
||||
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'
|
||||
}
|
||||
uni.$once(emitName, (e) => {
|
||||
changeConsignee(e.addressInfo);
|
||||
});
|
||||
sheep.$router.go(addressPage);
|
||||
}
|
||||
|
||||
// 更改收货人地址&计算订单信息
|
||||
async function changeConsignee(addressInfo = {}) {
|
||||
if (!isEmpty(addressInfo)) {
|
||||
if (state.value.deliveryType === 1){
|
||||
state.value.addressInfo = addressInfo;
|
||||
}
|
||||
if (state.value.deliveryType === 2){
|
||||
state.value.pickUpInfo = addressInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 收货方式切换
|
||||
const switchDeliveryType = (type) =>{
|
||||
state.value.deliveryType = type;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.allAddress .font-color{
|
||||
color: #E93323!important
|
||||
}
|
||||
.line2{
|
||||
width: 504rpx;
|
||||
}
|
||||
.textR {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 100%;
|
||||
height: 3rpx;
|
||||
}
|
||||
|
||||
.line image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.address {
|
||||
padding: 28rpx;
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.address .addressCon {
|
||||
width: 596rpx;
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.address .addressCon .name {
|
||||
font-size: 30rpx;
|
||||
color: #282828;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.address .addressCon .name .phone {
|
||||
margin-left: 50rpx;
|
||||
}
|
||||
|
||||
.address .addressCon .default {
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.address .addressCon .setaddress {
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.address .iconfont {
|
||||
font-size: 35rpx;
|
||||
color: #707070;
|
||||
}
|
||||
|
||||
.allAddress {
|
||||
width: 100%;
|
||||
background: linear-gradient(to bottom, #e93323 0%, #f5f5f5 100%);
|
||||
// background-image: linear-gradient(to bottom, #e93323 0%, #f5f5f5 100%);
|
||||
// background-image: -webkit-linear-gradient(to bottom, #e93323 0%, #f5f5f5 100%);
|
||||
// background-image: -moz-linear-gradient(to bottom, #e93323 0%, #f5f5f5 100%);
|
||||
//padding: 100rpx 30rpx 0 30rpx;
|
||||
padding-top: 100rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav {
|
||||
width: 690rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.allAddress .nav .item {
|
||||
width: 334rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav .item.on {
|
||||
position: relative;
|
||||
width: 230rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav .item.on::before {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
content: "快递配送";
|
||||
font-size: 28rpx;
|
||||
display: block;
|
||||
height: 0;
|
||||
width: 336rpx;
|
||||
border-width: 0 20rpx 80rpx 0;
|
||||
border-style: none solid solid;
|
||||
border-color: transparent transparent #fff;
|
||||
z-index: 2;
|
||||
border-radius: 14rpx 36rpx 0 0;
|
||||
text-align: center;
|
||||
line-height: 80rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav .item:nth-of-type(2).on::before {
|
||||
content: "到店自提";
|
||||
border-width: 0 0 80rpx 20rpx;
|
||||
border-radius: 36rpx 14rpx 0 0;
|
||||
}
|
||||
|
||||
.allAddress .nav .item.on2 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.allAddress .nav .item.on2::before {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
content: "到店自提";
|
||||
font-size: 28rpx;
|
||||
display: block;
|
||||
height: 0;
|
||||
width: 401rpx;
|
||||
border-width: 0 0 60rpx 60rpx;
|
||||
border-style: none solid solid;
|
||||
border-color: transparent transparent #f7c1bd;
|
||||
border-radius: 36rpx 14rpx 0 0;
|
||||
text-align: center;
|
||||
line-height: 60rpx;
|
||||
}
|
||||
|
||||
.allAddress .nav .item:nth-of-type(1).on2::before {
|
||||
content: "快递配送";
|
||||
border-width: 0 60rpx 60rpx 0;
|
||||
border-radius: 14rpx 36rpx 0 0;
|
||||
}
|
||||
|
||||
.allAddress .address {
|
||||
width: 690rpx;
|
||||
max-height: 180rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.allAddress .line {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -98,11 +98,7 @@
|
|||
</view>
|
||||
<view class="modal-content content_box">
|
||||
<radio-group @change="onChange">
|
||||
<label
|
||||
class="radio ss-flex ss-col-center"
|
||||
v-for="item in state.reasonList"
|
||||
:key="item"
|
||||
>
|
||||
<label class="radio ss-flex ss-col-center" v-for="item in state.reasonList" :key="item">
|
||||
<view class="ss-flex-1 ss-p-20">{{ item }}</view>
|
||||
<radio
|
||||
:value="item"
|
||||
|
|
@ -153,9 +149,9 @@
|
|||
],
|
||||
reasonList: [], // 可选的申请原因数组
|
||||
showModal: false, // 是否显示申请原因弹窗
|
||||
currentValue: '' // 当前选择的售后原因
|
||||
currentValue: '', // 当前选择的售后原因
|
||||
});
|
||||
const formData = reactive({
|
||||
let formData = reactive({
|
||||
way: '',
|
||||
applyReason: '',
|
||||
applyDescription: '',
|
||||
|
|
|
|||
|
|
@ -1,156 +1,193 @@
|
|||
<!-- 售后详情 -->
|
||||
<template>
|
||||
<s-layout title="售后详情" :navbar="!isEmpty(state.info) && state.loading ? 'inner' : 'normal'">
|
||||
<view class="content_box" v-if="!isEmpty(state.info) && state.loading">
|
||||
<!-- 步骤条 -->
|
||||
<view class="steps-box ss-flex" :style="[
|
||||
<s-layout title="售后详情" :navbar="!isEmpty(state.info) && state.loading ? 'inner' : 'normal'">
|
||||
<view class="content_box" v-if="!isEmpty(state.info) && state.loading">
|
||||
<!-- 步骤条 -->
|
||||
<view
|
||||
class="steps-box ss-flex"
|
||||
:style="[
|
||||
{
|
||||
marginTop: '-' + Number(statusBarHeight + 88) + 'rpx',
|
||||
paddingTop: Number(statusBarHeight + 88) + 'rpx',
|
||||
},
|
||||
]">
|
||||
<view class="ss-flex">
|
||||
<view class="steps-item" v-for="(item, index) in state.list" :key="index">
|
||||
<view class="ss-flex">
|
||||
<text class="sicon-circleclose"
|
||||
v-if="state.list.length - 1 === index && [61, 62, 63].includes(state.info.status)" />
|
||||
<text class="sicon-circlecheck" v-else
|
||||
:class="state.active >= index ? 'activity-color' : 'info-color'" />
|
||||
]"
|
||||
>
|
||||
<view class="ss-flex">
|
||||
<view class="steps-item" v-for="(item, index) in state.list" :key="index">
|
||||
<view class="ss-flex">
|
||||
<text
|
||||
class="sicon-circleclose"
|
||||
v-if="state.list.length - 1 === index && [61, 62, 63].includes(state.info.status)"
|
||||
/>
|
||||
<text
|
||||
class="sicon-circlecheck"
|
||||
v-else
|
||||
:class="state.active >= index ? 'activity-color' : 'info-color'"
|
||||
/>
|
||||
|
||||
<view v-if="state.list.length - 1 !== index" class="line"
|
||||
:class="state.active >= index ? 'activity-bg' : 'info-bg'" />
|
||||
</view>
|
||||
<view class="steps-item-title" :class="state.active >= index ? 'activity-color' : 'info-color'">
|
||||
{{ item.title }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
v-if="state.list.length - 1 !== index"
|
||||
class="line"
|
||||
:class="state.active >= index ? 'activity-bg' : 'info-bg'"
|
||||
/>
|
||||
</view>
|
||||
<view
|
||||
class="steps-item-title"
|
||||
:class="state.active >= index ? 'activity-color' : 'info-color'"
|
||||
>
|
||||
{{ item.title }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 服务状态 -->
|
||||
<view class="status-box ss-flex ss-col-center ss-row-between ss-m-x-20"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/log', { id: state.id })">
|
||||
<view class="">
|
||||
<view class="status-text">
|
||||
<!-- 服务状态 -->
|
||||
<view
|
||||
class="status-box ss-flex ss-col-center ss-row-between ss-m-x-20"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/log', { id: state.id })"
|
||||
>
|
||||
<view class="">
|
||||
<view class="status-text">
|
||||
{{ formatAfterSaleStatusDescription(state.info) }}
|
||||
</view>
|
||||
<view class="status-time">
|
||||
<view class="status-time">
|
||||
{{ sheep.$helper.timeFormat(state.info.updateTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</view>
|
||||
</view>
|
||||
<text class="ss-iconfont _icon-forward" style="color: #666" />
|
||||
</view>
|
||||
</view>
|
||||
<text class="ss-iconfont _icon-forward" style="color: #666" />
|
||||
</view>
|
||||
|
||||
<!-- 退款金额 -->
|
||||
<view class="aftersale-money ss-flex ss-col-center ss-row-between">
|
||||
<view class="aftersale-money--title">退款总额</view>
|
||||
<view class="aftersale-money--num">¥{{ fen2yuan(state.info.refundPrice) }}</view>
|
||||
</view>
|
||||
<!-- 服务商品 -->
|
||||
<view class="order-shop">
|
||||
<s-goods-item
|
||||
:img=" state.info.picUrl"
|
||||
:title=" state.info.spuName"
|
||||
:titleWidth="480"
|
||||
<!-- 退款金额 -->
|
||||
<view class="aftersale-money ss-flex ss-col-center ss-row-between">
|
||||
<view class="aftersale-money--title">退款总额</view>
|
||||
<view class="aftersale-money--num">¥{{ fen2yuan(state.info.refundPrice) }}</view>
|
||||
</view>
|
||||
<!-- 服务商品 -->
|
||||
<view class="order-shop">
|
||||
<s-goods-item
|
||||
:img="state.info.picUrl"
|
||||
:title="state.info.spuName"
|
||||
:titleWidth="480"
|
||||
:skuText="state.info.properties.map((property) => property.valueName).join(' ')"
|
||||
:num=" state.info.count"
|
||||
:num="state.info.count"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 服务内容 -->
|
||||
<view class="aftersale-content">
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">服务单号:</view>
|
||||
<view class="item-content ss-m-r-16">{{ state.info.no }}</view>
|
||||
<button class="ss-reset-button copy-btn" @tap="onCopy">复制</button>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">申请时间:</view>
|
||||
<view class="item-content">
|
||||
{{ sheep.$helper.timeFormat(state.info.createTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">售后类型:</view>
|
||||
<view class="item-content">{{ state.info.way === 10 ? '仅退款' : '退款退货' }}</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">申请原因:</view>
|
||||
<view class="item-content">{{ state.info.applyReason }}</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">相关描述:</view>
|
||||
<view class="item-content">{{ state.info.applyDescription }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 服务内容 -->
|
||||
<view class="aftersale-content">
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">服务单号:</view>
|
||||
<view class="item-content ss-m-r-16">{{ state.info.no }}</view>
|
||||
<button class="ss-reset-button copy-btn" @tap="onCopy">复制</button>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">申请时间:</view>
|
||||
<view class="item-content">
|
||||
{{ sheep.$helper.timeFormat(state.info.createTime, 'yyyy-mm-dd hh:MM:ss') }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">售后类型:</view>
|
||||
<view class="item-content">{{ state.info.way === 10 ? '仅退款' : '退款退货' }}</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">申请原因:</view>
|
||||
<view class="item-content">{{ state.info.applyReason }}</view>
|
||||
</view>
|
||||
<view class="aftersale-item ss-flex ss-col-center">
|
||||
<view class="item-title">相关描述:</view>
|
||||
<view class="item-content">{{ state.info.applyDescription }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作区 -->
|
||||
<s-empty v-if="isEmpty(state.info) && state.loading" icon="/static/order-empty.png" text="暂无该订单售后详情" />
|
||||
<su-fixed bottom placeholder bg="bg-white" v-if="!isEmpty(state.info)">
|
||||
<view class="foot_box">
|
||||
<button class="ss-reset-button btn" v-if="state.info.buttons?.includes('cancel')"
|
||||
@tap="onApply(state.info.id)">
|
||||
<s-empty
|
||||
v-if="isEmpty(state.info) && state.loading"
|
||||
icon="/static/order-empty.png"
|
||||
text="暂无该订单售后详情"
|
||||
/>
|
||||
<su-fixed bottom placeholder bg="bg-white" v-if="!isEmpty(state.info)">
|
||||
<view class="foot_box">
|
||||
<button
|
||||
class="ss-reset-button btn"
|
||||
v-if="state.info.buttons?.includes('cancel')"
|
||||
@tap="onApply(state.info.id)"
|
||||
>
|
||||
取消申请
|
||||
</button>
|
||||
<button class="ss-reset-button btn" v-if="state.info.buttons?.includes('delivery')"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/return-delivery', { id: state.info.id })">
|
||||
<button
|
||||
class="ss-reset-button btn"
|
||||
v-if="state.info.buttons?.includes('delivery')"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/return-delivery', { id: state.info.id })"
|
||||
>
|
||||
填写退货
|
||||
</button>
|
||||
<button class="ss-reset-button contcat-btn btn" @tap="sheep.$router.go('/pages/chat/index')">
|
||||
<button
|
||||
class="ss-reset-button contcat-btn btn"
|
||||
@tap="sheep.$router.go('/pages/chat/index')"
|
||||
>
|
||||
联系客服
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
</view>
|
||||
</su-fixed>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { fen2yuan, formatAfterSaleStatusDescription, handleAfterSaleButtons } from '@/sheep/hooks/useGoods';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import {
|
||||
fen2yuan,
|
||||
formatAfterSaleStatusDescription,
|
||||
handleAfterSaleButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import AfterSaleApi from '@/sheep/api/trade/afterSale';
|
||||
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
|
||||
const state = reactive({
|
||||
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
|
||||
const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
|
||||
const state = reactive({
|
||||
id: 0, // 售后编号
|
||||
info: {}, // 收货信息
|
||||
loading: false,
|
||||
loading: false,
|
||||
active: 0, // 在 list 的激活位置
|
||||
list: [{
|
||||
title: '提交申请',
|
||||
}, {
|
||||
title: '处理中',
|
||||
}, {
|
||||
title: '完成'
|
||||
}], // 时间轴
|
||||
});
|
||||
list: [
|
||||
{
|
||||
title: '提交申请',
|
||||
},
|
||||
{
|
||||
title: '处理中',
|
||||
},
|
||||
{
|
||||
title: '完成',
|
||||
},
|
||||
], // 时间轴
|
||||
});
|
||||
|
||||
function onApply(id) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消此申请吗?',
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
function onApply(id) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消此申请吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await AfterSaleApi.cancelAfterSale(id);
|
||||
if (code === 0) {
|
||||
await getDetail(id);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 复制
|
||||
const onCopy = () => {
|
||||
sheep.$helper.copyText(state.info.no);
|
||||
};
|
||||
sheep.$helper.copyText(state.info.no);
|
||||
};
|
||||
|
||||
async function getDetail(id) {
|
||||
async function getDetail(id) {
|
||||
state.loading = true;
|
||||
const { code, data } = await AfterSaleApi.getAfterSale(id);
|
||||
if (code !== 0) {
|
||||
|
|
@ -170,173 +207,173 @@
|
|||
} else if ([61, 62, 63].includes(state.info.status)) {
|
||||
state.active = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
onLoad((options) => {
|
||||
if (!options.id) {
|
||||
sheep.$helper.toast(`缺少订单信息,请检查`);
|
||||
return
|
||||
return;
|
||||
}
|
||||
state.id = options.id;
|
||||
getDetail(options.id);
|
||||
});
|
||||
state.id = options.id;
|
||||
getDetail(options.id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 步骤条
|
||||
.steps-box {
|
||||
width: 100%;
|
||||
height: 190rpx;
|
||||
background: v-bind(headerBg) no-repeat,
|
||||
linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
background-size: 750rpx 100%;
|
||||
padding-left: 72rpx;
|
||||
// 步骤条
|
||||
.steps-box {
|
||||
width: 100%;
|
||||
height: 190rpx;
|
||||
background: v-bind(headerBg) no-repeat,
|
||||
linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
background-size: 750rpx 100%;
|
||||
padding-left: 72rpx;
|
||||
|
||||
.steps-item {
|
||||
.sicon-circleclose {
|
||||
font-size: 24rpx;
|
||||
color: #fff;
|
||||
}
|
||||
.steps-item {
|
||||
.sicon-circleclose {
|
||||
font-size: 24rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sicon-circlecheck {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.sicon-circlecheck {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.steps-item-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
margin-top: 16rpx;
|
||||
margin-left: -36rpx;
|
||||
width: 100rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
.steps-item-title {
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
margin-top: 16rpx;
|
||||
margin-left: -36rpx;
|
||||
width: 100rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.activity-color {
|
||||
color: #fff;
|
||||
}
|
||||
.activity-color {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.info-color {
|
||||
color: rgba(#fff, 0.4);
|
||||
}
|
||||
.info-color {
|
||||
color: rgba(#fff, 0.4);
|
||||
}
|
||||
|
||||
.activity-bg {
|
||||
background: #fff;
|
||||
}
|
||||
.activity-bg {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.info-bg {
|
||||
background: rgba(#fff, 0.4);
|
||||
}
|
||||
.info-bg {
|
||||
background: rgba(#fff, 0.4);
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 270rpx;
|
||||
height: 4rpx;
|
||||
}
|
||||
.line {
|
||||
width: 270rpx;
|
||||
height: 4rpx;
|
||||
}
|
||||
|
||||
// 服务状态
|
||||
.status-box {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx 20rpx 0px 0px;
|
||||
padding: 20rpx;
|
||||
margin-top: -20rpx;
|
||||
// 服务状态
|
||||
.status-box {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx 20rpx 0px 0px;
|
||||
padding: 20rpx;
|
||||
margin-top: -20rpx;
|
||||
|
||||
.status-text {
|
||||
font-size: 28rpx;
|
||||
.status-text {
|
||||
font-size: 28rpx;
|
||||
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.status-time {
|
||||
font-size: 24rpx;
|
||||
.status-time {
|
||||
font-size: 24rpx;
|
||||
|
||||
font-weight: 400;
|
||||
color: rgba(153, 153, 153, 1);
|
||||
}
|
||||
}
|
||||
font-weight: 400;
|
||||
color: rgba(153, 153, 153, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 退款金额
|
||||
.aftersale-money {
|
||||
background-color: #fff;
|
||||
height: 98rpx;
|
||||
padding: 0 20rpx;
|
||||
margin: 20rpx;
|
||||
// 退款金额
|
||||
.aftersale-money {
|
||||
background-color: #fff;
|
||||
height: 98rpx;
|
||||
padding: 0 20rpx;
|
||||
margin: 20rpx;
|
||||
|
||||
.aftersale-money--title {
|
||||
font-size: 28rpx;
|
||||
.aftersale-money--title {
|
||||
font-size: 28rpx;
|
||||
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
font-weight: 500;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
|
||||
.aftersale-money--num {
|
||||
font-size: 28rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 500;
|
||||
color: #ff3000;
|
||||
}
|
||||
}
|
||||
.aftersale-money--num {
|
||||
font-size: 28rpx;
|
||||
font-family: OPPOSANS;
|
||||
font-weight: 500;
|
||||
color: #ff3000;
|
||||
}
|
||||
}
|
||||
|
||||
// order-shop
|
||||
.order-shop {
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
}
|
||||
// order-shop
|
||||
.order-shop {
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
}
|
||||
|
||||
// 服务内容
|
||||
.aftersale-content {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
margin: 0 20rpx;
|
||||
// 服务内容
|
||||
.aftersale-content {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
margin: 0 20rpx;
|
||||
|
||||
.aftersale-item {
|
||||
height: 60rpx;
|
||||
.aftersale-item {
|
||||
height: 60rpx;
|
||||
|
||||
.copy-btn {
|
||||
background: #eeeeee;
|
||||
color: #333;
|
||||
border-radius: 20rpx;
|
||||
width: 75rpx;
|
||||
height: 40rpx;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
.copy-btn {
|
||||
background: #eeeeee;
|
||||
color: #333;
|
||||
border-radius: 20rpx;
|
||||
width: 75rpx;
|
||||
height: 40rpx;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.item-title {
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item-content {
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 底部功能
|
||||
.foot_box {
|
||||
height: 100rpx;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
// 底部功能
|
||||
.foot_box {
|
||||
height: 100rpx;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
|
||||
.btn {
|
||||
width: 160rpx;
|
||||
line-height: 60rpx;
|
||||
background: rgba(238, 238, 238, 1);
|
||||
border-radius: 30rpx;
|
||||
padding: 0;
|
||||
margin-right: 20rpx;
|
||||
font-size: 26rpx;
|
||||
.btn {
|
||||
width: 160rpx;
|
||||
line-height: 60rpx;
|
||||
background: rgba(238, 238, 238, 1);
|
||||
border-radius: 30rpx;
|
||||
padding: 0;
|
||||
margin-right: 20rpx;
|
||||
font-size: 26rpx;
|
||||
|
||||
font-weight: 400;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
font-weight: 400;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,187 +1,210 @@
|
|||
<!-- 售后列表 -->
|
||||
<template>
|
||||
<s-layout title="售后列表">
|
||||
<!-- tab -->
|
||||
<su-sticky bgColor="#fff">
|
||||
<su-tabs :list="tabMaps" :scrollable="false" @change="onTabsChange" :current="state.currentTab" />
|
||||
</su-sticky>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据" />
|
||||
<!-- 列表 -->
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view class="list-box ss-m-y-20" v-for="order in state.pagination.list" :key="order.id"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/detail', { id: order.id })">
|
||||
<view class="order-head ss-flex ss-col-center ss-row-between">
|
||||
<text class="no">服务单号:{{ order.no }}</text>
|
||||
<text class="state">{{ formatAfterSaleStatus(order) }}</text>
|
||||
</view>
|
||||
<s-goods-item
|
||||
<s-layout title="售后列表">
|
||||
<!-- tab -->
|
||||
<su-sticky bgColor="#fff">
|
||||
<su-tabs
|
||||
:list="tabMaps"
|
||||
:scrollable="false"
|
||||
@change="onTabsChange"
|
||||
:current="state.currentTab"
|
||||
/>
|
||||
</su-sticky>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据" />
|
||||
<!-- 列表 -->
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view
|
||||
class="list-box ss-m-y-20"
|
||||
v-for="order in state.pagination.list"
|
||||
:key="order.id"
|
||||
@tap="sheep.$router.go('/pages/order/aftersale/detail', { id: order.id })"
|
||||
>
|
||||
<view class="order-head ss-flex ss-col-center ss-row-between">
|
||||
<text class="no">服务单号:{{ order.no }}</text>
|
||||
<text class="state">{{ formatAfterSaleStatus(order) }}</text>
|
||||
</view>
|
||||
<s-goods-item
|
||||
:img="order.picUrl"
|
||||
:title="order.spuName"
|
||||
:skuText="order.properties.map((property) => property.valueName).join(' ')"
|
||||
:skuText="order.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="order.refundPrice"
|
||||
/>
|
||||
<view class="apply-box ss-flex ss-col-center ss-row-between border-bottom ss-p-x-20">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="title ss-m-r-20">{{ order.way === 10 ? '仅退款' : '退款退货' }}</view>
|
||||
<view class="value">{{ formatAfterSaleStatusDescription(order) }}</view>
|
||||
</view>
|
||||
<text class="_icon-forward"></text>
|
||||
</view>
|
||||
<view class="tool-btn-box ss-flex ss-col-center ss-row-right ss-p-r-20">
|
||||
<view class="apply-box ss-flex ss-col-center ss-row-between border-bottom ss-p-x-20">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="title ss-m-r-20">{{ order.way === 10 ? '仅退款' : '退款退货' }}</view>
|
||||
<view class="value">{{ formatAfterSaleStatusDescription(order) }}</view>
|
||||
</view>
|
||||
<text class="_icon-forward"></text>
|
||||
</view>
|
||||
<view class="tool-btn-box ss-flex ss-col-center ss-row-right ss-p-r-20">
|
||||
<!-- TODO 功能缺失:填写退货信息 -->
|
||||
<view>
|
||||
<button class="ss-reset-button tool-btn" @tap.stop="onApply(order.id)"
|
||||
v-if="order?.buttons.includes('cancel')">取消申请</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{
|
||||
<view>
|
||||
<button
|
||||
class="ss-reset-button tool-btn"
|
||||
@tap.stop="onApply(order.id)"
|
||||
v-if="order?.buttons.includes('cancel')"
|
||||
>取消申请</button
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}" @tap="loadMore" />
|
||||
</s-layout>
|
||||
}"
|
||||
@tap="loadMore"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import { formatAfterSaleStatus, formatAfterSaleStatusDescription, handleAfterSaleButtons } from '@/sheep/hooks/useGoods';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import _ from 'lodash-es';
|
||||
import {
|
||||
formatAfterSaleStatus,
|
||||
formatAfterSaleStatusDescription,
|
||||
handleAfterSaleButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import AfterSaleApi from '@/sheep/api/trade/afterSale';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
||||
const state = reactive({
|
||||
currentTab: 0,
|
||||
showApply: false,
|
||||
pagination: {
|
||||
const state = reactive({
|
||||
currentTab: 0,
|
||||
showApply: false,
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 10
|
||||
},
|
||||
loadStatus: '',
|
||||
});
|
||||
pageSize: 10,
|
||||
},
|
||||
loadStatus: '',
|
||||
});
|
||||
|
||||
// TODO 芋艿:优化点,增加筛选
|
||||
const tabMaps = [{
|
||||
name: '全部',
|
||||
value: 'all',
|
||||
},
|
||||
// {
|
||||
// name: '申请中',
|
||||
// value: 'nooper',
|
||||
// },
|
||||
// {
|
||||
// name: '处理中',
|
||||
// value: 'ing',
|
||||
// },
|
||||
// {
|
||||
// name: '已完成',
|
||||
// value: 'completed',
|
||||
// },
|
||||
// {
|
||||
// name: '已拒绝',
|
||||
// value: 'refuse',
|
||||
// },
|
||||
];
|
||||
const tabMaps = [
|
||||
{
|
||||
name: '全部',
|
||||
value: 'all',
|
||||
},
|
||||
// {
|
||||
// name: '申请中',
|
||||
// value: 'nooper',
|
||||
// },
|
||||
// {
|
||||
// name: '处理中',
|
||||
// value: 'ing',
|
||||
// },
|
||||
// {
|
||||
// name: '已完成',
|
||||
// value: 'completed',
|
||||
// },
|
||||
// {
|
||||
// name: '已拒绝',
|
||||
// value: 'refuse',
|
||||
// },
|
||||
];
|
||||
|
||||
// 切换选项卡
|
||||
function onTabsChange(e) {
|
||||
// 切换选项卡
|
||||
function onTabsChange(e) {
|
||||
resetPagination(state.pagination);
|
||||
state.currentTab = e.index;
|
||||
getOrderList();
|
||||
}
|
||||
state.currentTab = e.index;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 获取售后列表
|
||||
async function getOrderList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { data, code } = await AfterSaleApi.getAfterSalePage({
|
||||
// type: tabMaps[state.currentTab].value,
|
||||
// 获取售后列表
|
||||
async function getOrderList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { data, code } = await AfterSaleApi.getAfterSalePage({
|
||||
// type: tabMaps[state.currentTab].value,
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
});
|
||||
if (code !== 0) {
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
data.list.forEach(order => handleAfterSaleButtons(order));
|
||||
}
|
||||
data.list.forEach((order) => handleAfterSaleButtons(order));
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
}
|
||||
|
||||
function onApply(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消此申请吗?',
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
function onApply(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消此申请吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const { code } = await AfterSaleApi.cancelAfterSale(orderId);
|
||||
if (code === 0) {
|
||||
resetPagination(state.pagination);
|
||||
await getOrderList();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (options.type) {
|
||||
state.currentTab = options.type;
|
||||
}
|
||||
await getOrderList();
|
||||
});
|
||||
onLoad(async (options) => {
|
||||
if (options.type) {
|
||||
state.currentTab = options.type;
|
||||
}
|
||||
await getOrderList();
|
||||
});
|
||||
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getOrderList();
|
||||
}
|
||||
}
|
||||
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list-box {
|
||||
background-color: #fff;
|
||||
.list-box {
|
||||
background-color: #fff;
|
||||
|
||||
.order-head {
|
||||
padding: 0 25rpx;
|
||||
height: 77rpx;
|
||||
}
|
||||
.order-head {
|
||||
padding: 0 25rpx;
|
||||
height: 77rpx;
|
||||
}
|
||||
|
||||
.apply-box {
|
||||
height: 82rpx;
|
||||
.apply-box {
|
||||
height: 82rpx;
|
||||
|
||||
.title {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.title {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 22rpx;
|
||||
color: $dark-6;
|
||||
}
|
||||
}
|
||||
.value {
|
||||
font-size: 22rpx;
|
||||
color: $dark-6;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-btn-box {
|
||||
height: 100rpx;
|
||||
.tool-btn-box {
|
||||
height: 100rpx;
|
||||
|
||||
.tool-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #f6f6f6;
|
||||
border-radius: 30rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.tool-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #f6f6f6;
|
||||
border-radius: 30rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,7 @@
|
|||
<template>
|
||||
<s-layout title="确认订单">
|
||||
<!-- TODO:这个判断先删除 v-if="state.orderInfo.need_address === 1" -->
|
||||
<view class="bg-white address-box ss-m-b-14 ss-r-b-10" @tap="onSelectAddress">
|
||||
<s-address-item :item="state.addressInfo" :hasBorderBottom="false">
|
||||
<view class="ss-rest-button">
|
||||
<text class="_icon-forward" />
|
||||
</view>
|
||||
</s-address-item>
|
||||
</view>
|
||||
<!-- 头部地址选择【配送地址】【自提地址】 -->
|
||||
<AddressSelection v-model="addressState" />
|
||||
|
||||
<!-- 商品信息 -->
|
||||
<view class="order-card-box ss-m-b-14">
|
||||
|
|
@ -46,26 +40,58 @@
|
|||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- TODO 芋艿:接入积分 -->
|
||||
<view
|
||||
class="order-item ss-flex ss-col-center ss-row-between"
|
||||
v-if="state.orderPayload.order_type === 'score'"
|
||||
v-if="state.orderInfo.type === 0"
|
||||
>
|
||||
<view class="item-title">扣除积分</view>
|
||||
<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"
|
||||
/>
|
||||
<text class="item-value ss-m-r-24">{{ state.orderInfo.score_amount }}</text>
|
||||
<text class="item-value ss-m-r-24">
|
||||
{{ 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-group>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-item ss-flex ss-col-center ss-row-between">
|
||||
<!-- 快递配置时,信息的展示 -->
|
||||
<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">
|
||||
<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>
|
||||
</view>
|
||||
<!-- 门店自提时,需要填写姓名和手机号 -->
|
||||
<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"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<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"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 优惠劵:只有 type = 0 普通订单(非拼团、秒杀、砍价),才可以使用优惠劵 -->
|
||||
|
|
@ -120,7 +146,7 @@
|
|||
共{{ state.orderInfo.items.reduce((acc, item) => acc + item.count, 0) }}件
|
||||
</view>
|
||||
<view>合计:</view>
|
||||
<view class="total-num text-red"> ¥{{ fen2yuan(state.orderInfo.price.payPrice) }} </view>
|
||||
<view class="total-num text-red"> ¥{{ fen2yuan(state.orderInfo.price.payPrice) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
|
@ -159,14 +185,13 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive } from 'vue';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import AddressSelection from '@/pages/order/addressSelection.vue';
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import CouponApi from '@/sheep/api/promotion/coupon';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import { WxaSubscribeTemplate } from '@/sheep/util/const';
|
||||
|
||||
const state = reactive({
|
||||
orderPayload: {},
|
||||
|
|
@ -174,27 +199,30 @@
|
|||
items: [], // 商品项列表
|
||||
price: {}, // 价格信息
|
||||
},
|
||||
addressInfo: {}, // 选择的收货地址
|
||||
showCoupon: false, // 是否展示优惠劵
|
||||
couponInfo: [], // 优惠劵列表
|
||||
showDiscount: false, // 是否展示营销活动
|
||||
// ========== 积分 ==========
|
||||
pointStatus: false, //是否使用积分
|
||||
});
|
||||
|
||||
// 选择地址
|
||||
function onSelectAddress() {
|
||||
uni.$once('SELECT_ADDRESS', (e) => {
|
||||
changeConsignee(e.addressInfo);
|
||||
});
|
||||
sheep.$router.go('/pages/user/address/list');
|
||||
}
|
||||
const addressState = ref({
|
||||
addressInfo: {}, // 选择的收货地址
|
||||
deliveryType: 1, // 收货方式 1 - 快递配送;2 - 门店自提
|
||||
isPickUp: true, // 门店自提是否开启 TODO puhui999: 默认开启,看看后端有开关的话接入
|
||||
pickUpInfo: {}, // 选择的自提门店信息
|
||||
receiverName: '', // 收件人名称
|
||||
receiverMobile: '', // 收件人手机
|
||||
});
|
||||
|
||||
// 更改收货人地址&计算订单信息
|
||||
async function changeConsignee(addressInfo = {}) {
|
||||
if (!isEmpty(addressInfo)) {
|
||||
state.addressInfo = addressInfo;
|
||||
}
|
||||
// ========== 积分 ==========
|
||||
/**
|
||||
* 使用积分抵扣
|
||||
*/
|
||||
const changeIntegral = async () => {
|
||||
state.pointStatus = !state.pointStatus;
|
||||
await getOrderInfo();
|
||||
}
|
||||
};
|
||||
|
||||
// 选择优惠券
|
||||
async function onSelectCoupon(couponId) {
|
||||
|
|
@ -205,10 +233,28 @@
|
|||
|
||||
// 提交订单
|
||||
function onConfirm() {
|
||||
if (!state.addressInfo.id) {
|
||||
if (addressState.value.deliveryType === 1 && !addressState.value.addressInfo.id) {
|
||||
sheep.$helper.toast('请选择收货地址');
|
||||
return;
|
||||
}
|
||||
if (addressState.value.deliveryType === 2) {
|
||||
if (!addressState.value.pickUpInfo.id) {
|
||||
sheep.$helper.toast('请选择自提门店地址');
|
||||
return;
|
||||
}
|
||||
if (addressState.value.receiverName === '' || addressState.value.receiverMobile === '') {
|
||||
sheep.$helper.toast('请填写联系人或联系人电话');
|
||||
return;
|
||||
}
|
||||
if (!/^[\u4e00-\u9fa5\w]{2,16}$/.test(addressState.value.receiverName)) {
|
||||
sheep.$helper.toast('请填写您的真实姓名');
|
||||
return;
|
||||
}
|
||||
if (!/^1(3|4|5|7|8|9|6)\d{9}$/.test(addressState.value.receiverMobile)) {
|
||||
sheep.$helper.toast('请填写正确的手机号');
|
||||
return;
|
||||
}
|
||||
}
|
||||
submitOrder();
|
||||
}
|
||||
|
||||
|
|
@ -218,12 +264,15 @@
|
|||
items: state.orderPayload.items,
|
||||
couponId: state.orderPayload.couponId,
|
||||
remark: state.orderPayload.remark,
|
||||
addressId: state.addressInfo.id,
|
||||
deliveryType: 1, // TODO 芋艿:需要支持【门店自提】
|
||||
pointStatus: false, // TODO 芋艿:需要支持【积分选择】
|
||||
deliveryType: addressState.value.deliveryType,
|
||||
addressId: addressState.value.addressInfo.id, // 收件地址编号
|
||||
pickUpStoreId: addressState.value.pickUpInfo.id,//自提门店编号
|
||||
receiverName: addressState.value.receiverName,// 选择门店自提时,该字段为联系人名
|
||||
receiverMobile: addressState.value.receiverMobile,// 选择门店自提时,该字段为联系人手机
|
||||
pointStatus: state.pointStatus,
|
||||
combinationActivityId: state.orderPayload.combinationActivityId,
|
||||
combinationHeadId: state.orderPayload.combinationHeadId,
|
||||
seckillActivityId: state.orderPayload.seckillActivityId
|
||||
seckillActivityId: state.orderPayload.seckillActivityId,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
|
|
@ -245,12 +294,15 @@
|
|||
const { data, code } = await OrderApi.settlementOrder({
|
||||
items: state.orderPayload.items,
|
||||
couponId: state.orderPayload.couponId,
|
||||
addressId: state.addressInfo.id,
|
||||
deliveryType: 1, // TODO 芋艿:需要支持【门店自提】
|
||||
pointStatus: false, // TODO 芋艿:需要支持【积分选择】
|
||||
deliveryType: addressState.value.deliveryType,
|
||||
addressId: addressState.value.addressInfo.id, // 收件地址编号
|
||||
pickUpStoreId: addressState.value.pickUpInfo.id,//自提门店编号
|
||||
receiverName: addressState.value.receiverName,// 选择门店自提时,该字段为联系人名
|
||||
receiverMobile: addressState.value.receiverMobile,// 选择门店自提时,该字段为联系人手机
|
||||
pointStatus: state.pointStatus,
|
||||
combinationActivityId: state.orderPayload.combinationActivityId,
|
||||
combinationHeadId: state.orderPayload.combinationHeadId,
|
||||
seckillActivityId: state.orderPayload.seckillActivityId
|
||||
seckillActivityId: state.orderPayload.seckillActivityId,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
|
|
@ -258,7 +310,7 @@
|
|||
state.orderInfo = data;
|
||||
// 设置收货地址
|
||||
if (state.orderInfo.address) {
|
||||
state.addressInfo = state.orderInfo.address;
|
||||
addressState.value.addressInfo = state.orderInfo.address;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,8 +257,8 @@
|
|||
<script setup>
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import {
|
||||
fen2yuan,
|
||||
formatOrderStatus,
|
||||
|
|
@ -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,15 +377,18 @@
|
|||
},
|
||||
});
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// 评价
|
||||
function onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/add', {
|
||||
id
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,243 +1,284 @@
|
|||
<!-- 订单列表 -->
|
||||
<template>
|
||||
<s-layout title="我的订单">
|
||||
<su-sticky bgColor="#fff">
|
||||
<su-tabs :list="tabMaps" :scrollable="false" @change="onTabsChange" :current="state.currentTab" />
|
||||
</su-sticky>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/order-empty.png" text="暂无订单" />
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view class="bg-white order-list-card-box ss-r-10 ss-m-t-14 ss-m-20" v-for="order in state.pagination.list"
|
||||
:key="order.id" @tap="onOrderDetail(order.id)">
|
||||
<view class="order-card-header ss-flex ss-col-center ss-row-between ss-p-x-20">
|
||||
<view class="order-no">订单号:{{ order.no }}</view>
|
||||
<view class="order-state ss-font-26" :class="formatOrderColor(order)">
|
||||
<s-layout title="我的订单">
|
||||
<su-sticky bgColor="#fff">
|
||||
<su-tabs
|
||||
:list="tabMaps"
|
||||
:scrollable="false"
|
||||
@change="onTabsChange"
|
||||
:current="state.currentTab"
|
||||
/>
|
||||
</su-sticky>
|
||||
<s-empty v-if="state.pagination.total === 0" icon="/static/order-empty.png" text="暂无订单" />
|
||||
<view v-if="state.pagination.total > 0">
|
||||
<view
|
||||
class="bg-white order-list-card-box ss-r-10 ss-m-t-14 ss-m-20"
|
||||
v-for="order in state.pagination.list"
|
||||
:key="order.id"
|
||||
@tap="onOrderDetail(order.id)"
|
||||
>
|
||||
<view class="order-card-header ss-flex ss-col-center ss-row-between ss-p-x-20">
|
||||
<view class="order-no">订单号:{{ order.no }}</view>
|
||||
<view class="order-state ss-font-26" :class="formatOrderColor(order)">
|
||||
{{ formatOrderStatus(order) }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="border-bottom" v-for="item in order.items" :key="item.id">
|
||||
<s-goods-item
|
||||
</view>
|
||||
<view class="border-bottom" v-for="item in order.items" :key="item.id">
|
||||
<s-goods-item
|
||||
:img="item.picUrl"
|
||||
:title="item.spuName"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:skuText="item.properties.map((property) => property.valueName).join(' ')"
|
||||
:price="item.price"
|
||||
:num="item.count"
|
||||
/>
|
||||
</view>
|
||||
<view class="pay-box ss-m-t-30 ss-flex ss-row-right ss-p-r-20">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="discounts-title pay-color">共 {{ order.productCount }} 件商品,总金额:</view>
|
||||
<view class="discounts-money pay-color">
|
||||
¥{{ fen2yuan(order.payPrice) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-card-footer ss-flex ss-col-center ss-p-x-20"
|
||||
:class="order.buttons.length > 3 ? 'ss-row-between' : 'ss-row-right'">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<button v-if="order.buttons.includes('combination')" class="tool-btn ss-reset-button"
|
||||
@tap.stop="onOrderGroupon(order)">
|
||||
</view>
|
||||
<view class="pay-box ss-m-t-30 ss-flex ss-row-right ss-p-r-20">
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="discounts-title pay-color"
|
||||
>共 {{ order.productCount }} 件商品,总金额:</view
|
||||
>
|
||||
<view class="discounts-money pay-color"> ¥{{ fen2yuan(order.payPrice) }} </view>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="order-card-footer ss-flex ss-col-center ss-p-x-20"
|
||||
:class="order.buttons.length > 3 ? 'ss-row-between' : 'ss-row-right'"
|
||||
>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<button
|
||||
v-if="order.buttons.includes('combination')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onOrderGroupon(order)"
|
||||
>
|
||||
拼团详情
|
||||
</button>
|
||||
<button v-if="order.buttons.length === 0" class="tool-btn ss-reset-button"
|
||||
@tap.stop="onOrderDetail(order.id)">
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.length === 0"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onOrderDetail(order.id)"
|
||||
>
|
||||
查看详情
|
||||
</button>
|
||||
<button v-if="order.buttons.includes('confirm')" class="tool-btn ss-reset-button"
|
||||
@tap.stop="onConfirm(order)">
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('confirm')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onConfirm(order)"
|
||||
>
|
||||
确认收货
|
||||
</button>
|
||||
<button v-if="order.buttons.includes('express')" class="tool-btn ss-reset-button"
|
||||
@tap.stop="onExpress(order.id)">
|
||||
查看物流
|
||||
</button>
|
||||
<button v-if="order.buttons.includes('cancel')" class="tool-btn ss-reset-button"
|
||||
@tap.stop="onCancel(order.id)">
|
||||
取消订单
|
||||
</button>
|
||||
<button v-if="order.buttons.includes('comment')" class="tool-btn ss-reset-button"
|
||||
@tap.stop="onComment(order.id)">
|
||||
评价
|
||||
</button>
|
||||
<button v-if="order.buttons.includes('delete')" class="delete-btn ss-reset-button"
|
||||
@tap.stop="onDelete(order.id)">
|
||||
删除订单
|
||||
</button>
|
||||
<button v-if="order.buttons.includes('pay')" class="tool-btn ss-reset-button ui-BG-Main-Gradient"
|
||||
@tap.stop="onPay(order.payOrderId)">
|
||||
继续支付
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('express')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onExpress(order.id)"
|
||||
>
|
||||
查看物流
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('cancel')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onCancel(order.id)"
|
||||
>
|
||||
取消订单
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('comment')"
|
||||
class="tool-btn ss-reset-button"
|
||||
@tap.stop="onComment(order.id)"
|
||||
>
|
||||
评价
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('delete')"
|
||||
class="delete-btn ss-reset-button"
|
||||
@tap.stop="onDelete(order.id)"
|
||||
>
|
||||
删除订单
|
||||
</button>
|
||||
<button
|
||||
v-if="order.buttons.includes('pay')"
|
||||
class="tool-btn ss-reset-button ui-BG-Main-Gradient"
|
||||
@tap.stop="onPay(order.payOrderId)"
|
||||
>
|
||||
继续支付
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{
|
||||
<!-- 加载更多 -->
|
||||
<uni-load-more
|
||||
v-if="state.pagination.total > 0"
|
||||
:status="state.loadStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
}" @tap="loadMore" />
|
||||
</s-layout>
|
||||
}"
|
||||
@tap="loadMore"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app';
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app';
|
||||
import {
|
||||
fen2yuan,
|
||||
formatOrderColor, formatOrderStatus, handleOrderButtons,
|
||||
formatOrderColor,
|
||||
formatOrderStatus,
|
||||
handleOrderButtons,
|
||||
} from '@/sheep/hooks/useGoods';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
isEmpty
|
||||
} from 'lodash';
|
||||
import sheep from '@/sheep';
|
||||
import _ from 'lodash-es';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import OrderApi from '@/sheep/api/trade/order';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
||||
// 数据
|
||||
const state = reactive({
|
||||
currentTab: 0, // 选中的 tabMaps 下标
|
||||
pagination: {
|
||||
// 数据
|
||||
const state = reactive({
|
||||
currentTab: 0, // 选中的 tabMaps 下标
|
||||
pagination: {
|
||||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 5,
|
||||
},
|
||||
loadStatus: ''
|
||||
});
|
||||
},
|
||||
loadStatus: '',
|
||||
});
|
||||
|
||||
const tabMaps = [{
|
||||
name: '全部'
|
||||
},
|
||||
{
|
||||
name: '待付款',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: '待发货',
|
||||
value: 10,
|
||||
},
|
||||
{
|
||||
name: '待收货',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: '待评价',
|
||||
value: 30,
|
||||
},
|
||||
];
|
||||
const tabMaps = [
|
||||
{
|
||||
name: '全部',
|
||||
},
|
||||
{
|
||||
name: '待付款',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
name: '待发货',
|
||||
value: 10,
|
||||
},
|
||||
{
|
||||
name: '待收货',
|
||||
value: 20,
|
||||
},
|
||||
{
|
||||
name: '待评价',
|
||||
value: 30,
|
||||
},
|
||||
];
|
||||
|
||||
// 切换选项卡
|
||||
function onTabsChange(e) {
|
||||
if (state.currentTab === e.index) {
|
||||
// 切换选项卡
|
||||
function onTabsChange(e) {
|
||||
if (state.currentTab === e.index) {
|
||||
return;
|
||||
}
|
||||
// 重头加载代码
|
||||
resetPagination(state.pagination);
|
||||
state.currentTab = e.index;
|
||||
getOrderList();
|
||||
}
|
||||
resetPagination(state.pagination);
|
||||
state.currentTab = e.index;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 订单详情
|
||||
function onOrderDetail(id) {
|
||||
sheep.$router.go('/pages/order/detail', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
// 订单详情
|
||||
function onOrderDetail(id) {
|
||||
sheep.$router.go('/pages/order/detail', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 跳转拼团记录的详情
|
||||
function onOrderGroupon(order) {
|
||||
sheep.$router.go('/pages/activity/groupon/detail', {
|
||||
id: order.combinationRecordId,
|
||||
});
|
||||
}
|
||||
// 跳转拼团记录的详情
|
||||
function onOrderGroupon(order) {
|
||||
sheep.$router.go('/pages/activity/groupon/detail', {
|
||||
id: order.combinationRecordId,
|
||||
});
|
||||
}
|
||||
|
||||
// 继续支付
|
||||
function onPay(payOrderId) {
|
||||
sheep.$router.go('/pages/pay/index', {
|
||||
id: payOrderId,
|
||||
});
|
||||
}
|
||||
// 继续支付
|
||||
function onPay(payOrderId) {
|
||||
sheep.$router.go('/pages/pay/index', {
|
||||
id: payOrderId,
|
||||
});
|
||||
}
|
||||
|
||||
// 评价
|
||||
function onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/add', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
// 评价
|
||||
function onComment(id) {
|
||||
sheep.$router.go('/pages/goods/comment/add', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
// 确认收货 TODO 芋艿:待测试
|
||||
async function onConfirm(order, ignore = false) {
|
||||
// 需开启确认收货组件
|
||||
// todo: 芋艿:需要后续接入微信收货组件
|
||||
// 1.怎么检测是否开启了发货组件功能?如果没有开启的话就不能在这里return出去
|
||||
// 2.如果开启了走mpConfirm方法,需要在App.vue的show方法中拿到确认收货结果
|
||||
let isOpenBusinessView = true;
|
||||
if (
|
||||
sheep.$platform.name === 'WechatMiniProgram' &&
|
||||
!isEmpty(order.wechat_extra_data) &&
|
||||
isOpenBusinessView &&
|
||||
!ignore
|
||||
) {
|
||||
mpConfirm(order);
|
||||
return;
|
||||
}
|
||||
// 确认收货 TODO 芋艿:待测试
|
||||
async function onConfirm(order, ignore = false) {
|
||||
// 需开启确认收货组件
|
||||
// todo: 芋艿:需要后续接入微信收货组件
|
||||
// 1.怎么检测是否开启了发货组件功能?如果没有开启的话就不能在这里return出去
|
||||
// 2.如果开启了走mpConfirm方法,需要在App.vue的show方法中拿到确认收货结果
|
||||
let isOpenBusinessView = true;
|
||||
if (
|
||||
sheep.$platform.name === 'WechatMiniProgram' &&
|
||||
!isEmpty(order.wechat_extra_data) &&
|
||||
isOpenBusinessView &&
|
||||
!ignore
|
||||
) {
|
||||
mpConfirm(order);
|
||||
return;
|
||||
}
|
||||
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.receiveOrder(order.id);
|
||||
if (code === 0) {
|
||||
// 正常的确认收货流程
|
||||
const { code } = await OrderApi.receiveOrder(order.id);
|
||||
if (code === 0) {
|
||||
resetPagination(state.pagination);
|
||||
await getOrderList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// 小程序确认收货组件 TODO 芋艿:后续再接入
|
||||
function mpConfirm(order) {
|
||||
if (!wx.openBusinessView) {
|
||||
sheep.$helper.toast(`请升级微信版本`);
|
||||
return;
|
||||
}
|
||||
wx.openBusinessView({
|
||||
businessType: 'weappOrderConfirm',
|
||||
extraData: {
|
||||
merchant_id: '1481069012',
|
||||
merchant_trade_no: order.wechat_extra_data.merchant_trade_no,
|
||||
transaction_id: order.wechat_extra_data.transaction_id,
|
||||
},
|
||||
success(response) {
|
||||
console.log('success:', response);
|
||||
if (response.errMsg === 'openBusinessView:ok') {
|
||||
if (response.extraData.status === 'success') {
|
||||
onConfirm(order, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
fail(error) {
|
||||
console.log('error:', error);
|
||||
},
|
||||
complete(result) {
|
||||
console.log('result:', result);
|
||||
},
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
// 小程序确认收货组件 TODO 芋艿:后续再接入
|
||||
function mpConfirm(order) {
|
||||
if (!wx.openBusinessView) {
|
||||
sheep.$helper.toast(`请升级微信版本`);
|
||||
return;
|
||||
}
|
||||
wx.openBusinessView({
|
||||
businessType: 'weappOrderConfirm',
|
||||
extraData: {
|
||||
merchant_id: '1481069012',
|
||||
merchant_trade_no: order.wechat_extra_data.merchant_trade_no,
|
||||
transaction_id: order.wechat_extra_data.transaction_id,
|
||||
},
|
||||
success(response) {
|
||||
console.log('success:', response);
|
||||
if (response.errMsg === 'openBusinessView:ok') {
|
||||
if (response.extraData.status === 'success') {
|
||||
onConfirm(order, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
fail(error) {
|
||||
console.log('error:', error);
|
||||
},
|
||||
complete(result) {
|
||||
console.log('result:', result);
|
||||
},
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
|
||||
// 查看物流
|
||||
async function onExpress(id) {
|
||||
sheep.$router.go('/pages/order/express/log', {
|
||||
// 查看物流
|
||||
async function onExpress(id) {
|
||||
sheep.$router.go('/pages/order/express/log', {
|
||||
id,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 取消订单
|
||||
async function onCancel(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消订单吗?',
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
// 取消订单
|
||||
async function onCancel(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消订单吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const { code } = await OrderApi.cancelOrder(orderId);
|
||||
if (code === 0) {
|
||||
// 修改数据的状态
|
||||
|
|
@ -246,208 +287,209 @@
|
|||
orderInfo.status = 40;
|
||||
handleOrderButtons(orderInfo);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 删除订单
|
||||
function onDelete(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要删除订单吗?',
|
||||
success: async function(res) {
|
||||
if (res.confirm) {
|
||||
const { code } = await OrderApi.deleteOrder(orderId);
|
||||
if (code === 0) {
|
||||
// 删除订单
|
||||
function onDelete(orderId) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要删除订单吗?',
|
||||
success: async function (res) {
|
||||
if (res.confirm) {
|
||||
const { code } = await OrderApi.deleteOrder(orderId);
|
||||
if (code === 0) {
|
||||
// 删除数据
|
||||
let index = state.pagination.list.findIndex((order) => order.id === orderId);
|
||||
state.pagination.list.splice(index, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
let index = state.pagination.list.findIndex((order) => order.id === orderId);
|
||||
state.pagination.list.splice(index, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 获取订单列表
|
||||
async function getOrderList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { code, data } = await OrderApi.getOrderPage({
|
||||
// 获取订单列表
|
||||
async function getOrderList() {
|
||||
state.loadStatus = 'loading';
|
||||
let { code, data } = await OrderApi.getOrderPage({
|
||||
pageNo: state.pagination.pageNo,
|
||||
pageSize: state.pagination.pageSize,
|
||||
status: tabMaps[state.currentTab].value,
|
||||
commentStatus: tabMaps[state.currentTab].value === 30 ? false : null
|
||||
});
|
||||
commentStatus: tabMaps[state.currentTab].value === 30 ? false : null,
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
data.list.forEach(order => handleOrderButtons(order));
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list)
|
||||
data.list.forEach((order) => handleOrderButtons(order));
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
|
||||
onLoad(async (options) => {
|
||||
if (options.type) {
|
||||
state.currentTab = options.type;
|
||||
}
|
||||
await getOrderList();
|
||||
});
|
||||
onLoad(async (options) => {
|
||||
if (options.type) {
|
||||
state.currentTab = options.type;
|
||||
}
|
||||
await getOrderList();
|
||||
});
|
||||
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return
|
||||
}
|
||||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getOrderList();
|
||||
}
|
||||
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
// 上拉加载更多
|
||||
onReachBottom(() => {
|
||||
loadMore();
|
||||
});
|
||||
|
||||
// 下拉刷新
|
||||
onPullDownRefresh(() => {
|
||||
// 下拉刷新
|
||||
onPullDownRefresh(() => {
|
||||
resetPagination(state.pagination);
|
||||
getOrderList();
|
||||
setTimeout(function() {
|
||||
uni.stopPullDownRefresh();
|
||||
}, 800);
|
||||
});
|
||||
getOrderList();
|
||||
setTimeout(function () {
|
||||
uni.stopPullDownRefresh();
|
||||
}, 800);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.score-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
.score-img {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
|
||||
.tool-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #f6f6f6;
|
||||
font-size: 26rpx;
|
||||
border-radius: 30rpx;
|
||||
margin-right: 10rpx;
|
||||
.tool-btn {
|
||||
width: 160rpx;
|
||||
height: 60rpx;
|
||||
background: #f6f6f6;
|
||||
font-size: 26rpx;
|
||||
border-radius: 30rpx;
|
||||
margin-right: 10rpx;
|
||||
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
width: 160rpx;
|
||||
height: 56rpx;
|
||||
color: #ff3000;
|
||||
background: #fee;
|
||||
border-radius: 28rpx;
|
||||
font-size: 26rpx;
|
||||
margin-right: 10rpx;
|
||||
line-height: normal;
|
||||
.delete-btn {
|
||||
width: 160rpx;
|
||||
height: 56rpx;
|
||||
color: #ff3000;
|
||||
background: #fee;
|
||||
border-radius: 28rpx;
|
||||
font-size: 26rpx;
|
||||
margin-right: 10rpx;
|
||||
line-height: normal;
|
||||
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.apply-btn {
|
||||
width: 140rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
border: 2rpx solid #dcdcdc;
|
||||
line-height: normal;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
.apply-btn {
|
||||
width: 140rpx;
|
||||
height: 50rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
border: 2rpx solid #dcdcdc;
|
||||
line-height: normal;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.swiper-box {
|
||||
flex: 1;
|
||||
.swiper-box {
|
||||
flex: 1;
|
||||
|
||||
.swiper-item {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.swiper-item {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.order-list-card-box {
|
||||
.order-card-header {
|
||||
height: 80rpx;
|
||||
.order-list-card-box {
|
||||
.order-card-header {
|
||||
height: 80rpx;
|
||||
|
||||
.order-no {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
.order-no {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.order-state {}
|
||||
}
|
||||
.order-state {
|
||||
}
|
||||
}
|
||||
|
||||
.pay-box {
|
||||
.discounts-title {
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
color: #999999;
|
||||
}
|
||||
.pay-box {
|
||||
.discounts-title {
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.discounts-money {
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
color: #999;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
.discounts-money {
|
||||
font-size: 24rpx;
|
||||
line-height: normal;
|
||||
color: #999;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.pay-color {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
.pay-color {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.order-card-footer {
|
||||
height: 100rpx;
|
||||
.order-card-footer {
|
||||
height: 100rpx;
|
||||
|
||||
.more-item-box {
|
||||
padding: 20rpx;
|
||||
.more-item-box {
|
||||
padding: 20rpx;
|
||||
|
||||
.more-item {
|
||||
height: 60rpx;
|
||||
.more-item {
|
||||
height: 60rpx;
|
||||
|
||||
.title {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.title {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.more-btn {
|
||||
color: $dark-9;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.more-btn {
|
||||
color: $dark-9;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 154rpx;
|
||||
color: #333333;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content {
|
||||
width: 154rpx;
|
||||
color: #333333;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.uni-tooltip-popup) {
|
||||
background: var(--ui-BG);
|
||||
}
|
||||
:deep(.uni-tooltip-popup) {
|
||||
background: var(--ui-BG);
|
||||
}
|
||||
|
||||
.warning-color {
|
||||
color: #faad14;
|
||||
}
|
||||
.warning-color {
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
.danger-color {
|
||||
color: #ff3000;
|
||||
}
|
||||
.danger-color {
|
||||
color: #ff3000;
|
||||
}
|
||||
|
||||
.success-color {
|
||||
color: #52c41a;
|
||||
}
|
||||
.success-color {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.info-color {
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
||||
.info-color {
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
<view class="title">充值金额</view>
|
||||
<view class="num" :class="item.refundStatus === 10 ? 'danger-color' : 'success-color'">
|
||||
{{ fen2yuan(item.payPrice) }} 元
|
||||
<text v-if="item.bonusPrice > 0">(赠送 {{ fen2yuan(item.bonusPrice)}} 元)</text>
|
||||
<text v-if="item.bonusPrice > 0">(赠送 {{ fen2yuan(item.bonusPrice) }} 元)</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="status-box item ss-flex ss-col-center ss-row-between">
|
||||
|
|
@ -30,7 +30,9 @@
|
|||
</view>
|
||||
<view class="time-box item ss-flex ss-col-center ss-row-between">
|
||||
<text class="item-title">充值时间</text>
|
||||
<view class="time"> {{ sheep.$helper.timeFormat(item.payTime, 'yyyy-mm-dd hh:MM:ss') }}</view>
|
||||
<view class="time">
|
||||
{{ sheep.$helper.timeFormat(item.payTime, 'yyyy-mm-dd hh:MM:ss') }}</view
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -53,7 +55,7 @@
|
|||
<script setup>
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import PayWalletApi from '@/sheep/api/pay/wallet';
|
||||
import sheep from '@/sheep';
|
||||
import { fen2yuan } from '../../sheep/hooks/useGoods';
|
||||
|
|
|
|||
|
|
@ -50,7 +50,10 @@
|
|||
</view>
|
||||
|
||||
<!-- #ifdef MP -->
|
||||
<view class="subscribe-box ss-flex ss-m-t-44" v-if="showSubscribeBtn && state.orderType === 'goods'">
|
||||
<view
|
||||
class="subscribe-box ss-flex ss-m-t-44"
|
||||
v-if="showSubscribeBtn && state.orderType === 'goods'"
|
||||
>
|
||||
<image class="subscribe-img" :src="sheep.$url.static('/static/img/shop/order/cargo.png')" />
|
||||
<view class="subscribe-title ss-m-r-48 ss-m-l-16">获取实时发货信息与订单状态</view>
|
||||
<view class="subscribe-start" @tap="subscribeMessage">立即订阅</view>
|
||||
|
|
@ -63,7 +66,7 @@
|
|||
<script setup>
|
||||
import { onLoad, onHide, onShow } from '@dcloudio/uni-app';
|
||||
import { reactive, computed, ref } from 'vue';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import sheep from '@/sheep';
|
||||
import PayOrderApi from '@/sheep/api/pay/order';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
|
|
@ -114,12 +117,12 @@
|
|||
uni.showModal({
|
||||
title: '支付结果',
|
||||
showCancel: false, // 不要取消按钮
|
||||
content: "支付成功",
|
||||
content: '支付成功',
|
||||
success: () => {
|
||||
// 订阅只能由用户主动触发,只能包一层 showModal 诱导用户点击
|
||||
autoSubscribeMessage();
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
// #endif
|
||||
// 特殊:获得商品订单信息
|
||||
|
|
@ -153,8 +156,8 @@
|
|||
}
|
||||
|
||||
// #ifdef MP
|
||||
const showSubscribeBtn = ref(false) // 默认隐藏
|
||||
const SUBSCRIBE_BTN_STATUS_STORAGE_KEY = "subscribe_btn_status"
|
||||
const showSubscribeBtn = ref(false); // 默认隐藏
|
||||
const SUBSCRIBE_BTN_STATUS_STORAGE_KEY = 'subscribe_btn_status';
|
||||
function subscribeMessage() {
|
||||
if (state.orderType !== 'goods') {
|
||||
return;
|
||||
|
|
@ -176,11 +179,11 @@
|
|||
const subscribeBtnStatus = uni.getStorageSync(SUBSCRIBE_BTN_STATUS_STORAGE_KEY);
|
||||
if (!subscribeBtnStatus) {
|
||||
showSubscribeBtn.value = true;
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 订阅消息
|
||||
subscribeMessage()
|
||||
subscribeMessage();
|
||||
}
|
||||
// #endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1,78 +1,118 @@
|
|||
<!-- 收货地址的新增/编辑 -->
|
||||
<template>
|
||||
<s-layout :title="state.model.id ? '编辑地址' : '新增地址'">
|
||||
<uni-forms ref="addressFormRef" v-model="state.model" :rules="rules" validateTrigger="bind"
|
||||
labelWidth="160" labelAlign="left" border :labelStyle="{ fontWeight: 'bold' }">
|
||||
<view class="bg-white form-box ss-p-x-30">
|
||||
<uni-forms-item name="name" label="收货人" class="form-item">
|
||||
<uni-easyinput v-model="state.model.name" placeholder="请填写收货人姓名" :inputBorder="false"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal" />
|
||||
</uni-forms-item>
|
||||
<s-layout :title="state.model.id ? '编辑地址' : '新增地址'">
|
||||
<uni-forms
|
||||
ref="addressFormRef"
|
||||
v-model="state.model"
|
||||
:rules="rules"
|
||||
validateTrigger="bind"
|
||||
labelWidth="160"
|
||||
labelAlign="left"
|
||||
border
|
||||
:labelStyle="{ fontWeight: 'bold' }"
|
||||
>
|
||||
<view class="bg-white form-box ss-p-x-30">
|
||||
<uni-forms-item name="name" label="收货人" class="form-item">
|
||||
<uni-easyinput
|
||||
v-model="state.model.name"
|
||||
placeholder="请填写收货人姓名"
|
||||
:inputBorder="false"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
|
||||
/>
|
||||
</uni-forms-item>
|
||||
|
||||
<uni-forms-item name="mobile" label="手机号" class="form-item">
|
||||
<uni-easyinput v-model="state.model.mobile" type="number" placeholder="请输入手机号" :inputBorder="false"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal">
|
||||
</uni-easyinput>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item name="areaName" label="省市区" @tap="state.showRegion = true" class="form-item">
|
||||
<uni-easyinput v-model="state.model.areaName" disabled :inputBorder="false"
|
||||
:styles="{ disableColor: '#fff', color: '#333' }"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
|
||||
placeholder="请选择省市区">
|
||||
<template v-slot:right>
|
||||
<uni-icons type="right" />
|
||||
</template>
|
||||
</uni-easyinput>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item name="detailAddress" label="详细地址" :formItemStyle="{ alignItems: 'flex-start' }"
|
||||
:labelStyle="{ lineHeight: '5em' }" class="textarea-item">
|
||||
<uni-easyinput :inputBorder="false" type="textarea" v-model="state.model.detailAddress"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
|
||||
placeholder="请输入详细地址" clearable />
|
||||
</uni-forms-item>
|
||||
</view>
|
||||
<view class="ss-m-y-20 bg-white ss-p-x-30 ss-flex ss-row-between ss-col-center default-box">
|
||||
<view class="default-box-title"> 设为默认地址 </view>
|
||||
<su-switch style="transform: scale(0.8)" v-model="state.model.defaultStatus" />
|
||||
</view>
|
||||
</uni-forms>
|
||||
<su-fixed bottom :opacity="false" bg="" placeholder :noFixed="false" :index="10">
|
||||
<view class="footer-box ss-flex-col ss-row-between ss-p-20">
|
||||
<view class="ss-m-b-20">
|
||||
<uni-forms-item name="mobile" label="手机号" class="form-item">
|
||||
<uni-easyinput
|
||||
v-model="state.model.mobile"
|
||||
type="number"
|
||||
placeholder="请输入手机号"
|
||||
:inputBorder="false"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
|
||||
>
|
||||
</uni-easyinput>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item
|
||||
name="areaName"
|
||||
label="省市区"
|
||||
@tap="state.showRegion = true"
|
||||
class="form-item"
|
||||
>
|
||||
<uni-easyinput
|
||||
v-model="state.model.areaName"
|
||||
disabled
|
||||
:inputBorder="false"
|
||||
:styles="{ disableColor: '#fff', color: '#333' }"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
|
||||
placeholder="请选择省市区"
|
||||
>
|
||||
<template v-slot:right>
|
||||
<uni-icons type="right" />
|
||||
</template>
|
||||
</uni-easyinput>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item
|
||||
name="detailAddress"
|
||||
label="详细地址"
|
||||
:formItemStyle="{ alignItems: 'flex-start' }"
|
||||
:labelStyle="{ lineHeight: '5em' }"
|
||||
class="textarea-item"
|
||||
>
|
||||
<uni-easyinput
|
||||
:inputBorder="false"
|
||||
type="textarea"
|
||||
v-model="state.model.detailAddress"
|
||||
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
|
||||
placeholder="请输入详细地址"
|
||||
clearable
|
||||
/>
|
||||
</uni-forms-item>
|
||||
</view>
|
||||
<view class="ss-m-y-20 bg-white ss-p-x-30 ss-flex ss-row-between ss-col-center default-box">
|
||||
<view class="default-box-title"> 设为默认地址 </view>
|
||||
<su-switch style="transform: scale(0.8)" v-model="state.model.defaultStatus" />
|
||||
</view>
|
||||
</uni-forms>
|
||||
<su-fixed bottom :opacity="false" bg="" placeholder :noFixed="false" :index="10">
|
||||
<view class="footer-box ss-flex-col ss-row-between ss-p-20">
|
||||
<view class="ss-m-b-20">
|
||||
<button class="ss-reset-button save-btn ui-Shadow-Main" @tap="onSave">保存</button>
|
||||
</view>
|
||||
<button v-if="state.model.id" class="ss-reset-button cancel-btn" @tap="onDelete">
|
||||
删除
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
<button v-if="state.model.id" class="ss-reset-button cancel-btn" @tap="onDelete">
|
||||
删除
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
|
||||
<!-- 省市区弹窗 -->
|
||||
<su-region-picker :show="state.showRegion" @cancel="state.showRegion = false" @confirm="onRegionConfirm" />
|
||||
</s-layout>
|
||||
<!-- 省市区弹窗 -->
|
||||
<su-region-picker
|
||||
:show="state.showRegion"
|
||||
@cancel="state.showRegion = false"
|
||||
@confirm="onRegionConfirm"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, unref } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import _ from 'lodash';
|
||||
import { mobile } from '@/sheep/validate/form';
|
||||
import { ref, reactive, unref } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import _ from 'lodash-es';
|
||||
import { mobile } from '@/sheep/validate/form';
|
||||
import AreaApi from '@/sheep/api/system/area';
|
||||
import AddressApi from '@/sheep/api/member/address';
|
||||
|
||||
const addressFormRef = ref(null);
|
||||
const state = reactive({
|
||||
showRegion: false,
|
||||
model: {
|
||||
name: '',
|
||||
mobile: '',
|
||||
const addressFormRef = ref(null);
|
||||
const state = reactive({
|
||||
showRegion: false,
|
||||
model: {
|
||||
name: '',
|
||||
mobile: '',
|
||||
detailAddress: '',
|
||||
defaultStatus: false,
|
||||
defaultStatus: false,
|
||||
areaName: '',
|
||||
},
|
||||
},
|
||||
rules: {},
|
||||
});
|
||||
});
|
||||
|
||||
const rules = {
|
||||
name: {
|
||||
|
|
@ -85,93 +125,99 @@
|
|||
},
|
||||
mobile,
|
||||
detailAddress: {
|
||||
rules: [{
|
||||
required: true,
|
||||
errorMessage: '请输入详细地址',
|
||||
}]
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
errorMessage: '请输入详细地址',
|
||||
},
|
||||
],
|
||||
},
|
||||
areaName: {
|
||||
rules: [{
|
||||
required: true,
|
||||
errorMessage: '请选择您的位置'
|
||||
}]
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
errorMessage: '请选择您的位置',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
// 确认选择地区
|
||||
const onRegionConfirm = (e) => {
|
||||
state.model.areaName = `${e.province_name} ${e.city_name} ${e.district_name}`
|
||||
const onRegionConfirm = (e) => {
|
||||
state.model.areaName = `${e.province_name} ${e.city_name} ${e.district_name}`;
|
||||
state.model.areaId = e.district_id;
|
||||
state.showRegion = false;
|
||||
};
|
||||
state.showRegion = false;
|
||||
};
|
||||
|
||||
// 获得地区数据
|
||||
const getAreaData = () => {
|
||||
if (_.isEmpty(uni.getStorageSync('areaData'))) {
|
||||
const getAreaData = () => {
|
||||
if (_.isEmpty(uni.getStorageSync('areaData'))) {
|
||||
AreaApi.getAreaTree().then((res) => {
|
||||
if (res.code === 0) {
|
||||
uni.setStorageSync('areaData', res.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// 保存收货地址
|
||||
const onSave = async () => {
|
||||
const onSave = async () => {
|
||||
// 参数校验
|
||||
const validate = await unref(addressFormRef)
|
||||
.validate()
|
||||
.catch((error) => {
|
||||
console.log('error: ', error);
|
||||
});
|
||||
if (!validate) {
|
||||
const validate = await unref(addressFormRef)
|
||||
.validate()
|
||||
.catch((error) => {
|
||||
console.log('error: ', error);
|
||||
});
|
||||
if (!validate) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 提交请求
|
||||
const formData = {
|
||||
...state.model
|
||||
...state.model,
|
||||
};
|
||||
const { code } =
|
||||
state.model.id > 0
|
||||
? await AddressApi.updateAddress(formData)
|
||||
: await AddressApi.createAddress(formData);
|
||||
if (code === 0) {
|
||||
sheep.$router.back();
|
||||
}
|
||||
const {code } = state.model.id > 0 ? await AddressApi.updateAddress(formData)
|
||||
: await AddressApi.createAddress(formData);
|
||||
if (code === 0) {
|
||||
sheep.$router.back();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// 删除收货地址
|
||||
const onDelete = () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确认删除此收货地址吗?',
|
||||
success: async function(res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const onDelete = () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确认删除此收货地址吗?',
|
||||
success: async function (res) {
|
||||
if (!res.confirm) {
|
||||
return;
|
||||
}
|
||||
const { code } = await AddressApi.deleteAddress(state.model.id);
|
||||
if (code === 0) {
|
||||
sheep.$router.back();
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
onLoad(async (options) => {
|
||||
onLoad(async (options) => {
|
||||
// 获得地区数据
|
||||
getAreaData();
|
||||
getAreaData();
|
||||
// 情况一:基于 id 获得收件地址
|
||||
if (options.id) {
|
||||
let { code, data} = await AddressApi.getAddress(options.id);
|
||||
if (options.id) {
|
||||
let { code, data } = await AddressApi.getAddress(options.id);
|
||||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.model = data;
|
||||
}
|
||||
// 情况二:微信导入
|
||||
}
|
||||
// 情况二:微信导入
|
||||
if (options.data) {
|
||||
let data = JSON.parse(options.data);
|
||||
const areaData = uni.getStorageSync('areaData');
|
||||
const findAreaByName = (areas, name) => areas.find(item => item.name === name);
|
||||
const findAreaByName = (areas, name) => areas.find((item) => item.name === name);
|
||||
|
||||
let provinceObj = findAreaByName(areaData, data.province_name);
|
||||
let cityObj = provinceObj ? findAreaByName(provinceObj.children, data.city_name) : undefined;
|
||||
|
|
@ -181,77 +227,79 @@
|
|||
state.model = {
|
||||
...state.model,
|
||||
areaId,
|
||||
areaName: [data.province_name, data.city_name, data.district_name].filter(Boolean).join(" "),
|
||||
areaName: [data.province_name, data.city_name, data.district_name]
|
||||
.filter(Boolean)
|
||||
.join(' '),
|
||||
defaultStatus: false,
|
||||
detailAddress: data.address,
|
||||
mobile: data.mobile,
|
||||
name: data.consignee,
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep() {
|
||||
.uni-forms-item__label .label-text {
|
||||
font-size: 28rpx !important;
|
||||
color: #333333 !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
:deep() {
|
||||
.uni-forms-item__label .label-text {
|
||||
font-size: 28rpx !important;
|
||||
color: #333333 !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
|
||||
.uni-easyinput__content-input {
|
||||
font-size: 28rpx !important;
|
||||
color: #333333 !important;
|
||||
line-height: normal !important;
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
.uni-easyinput__content-input {
|
||||
font-size: 28rpx !important;
|
||||
color: #333333 !important;
|
||||
line-height: normal !important;
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
|
||||
.uni-easyinput__content-textarea {
|
||||
font-size: 28rpx !important;
|
||||
color: #333333 !important;
|
||||
line-height: normal !important;
|
||||
margin-top: 8rpx !important;
|
||||
}
|
||||
.uni-easyinput__content-textarea {
|
||||
font-size: 28rpx !important;
|
||||
color: #333333 !important;
|
||||
line-height: normal !important;
|
||||
margin-top: 8rpx !important;
|
||||
}
|
||||
|
||||
.uni-icons {
|
||||
font-size: 40rpx !important;
|
||||
}
|
||||
.uni-icons {
|
||||
font-size: 40rpx !important;
|
||||
}
|
||||
|
||||
.is-textarea-icon {
|
||||
margin-top: 22rpx;
|
||||
}
|
||||
.is-textarea-icon {
|
||||
margin-top: 22rpx;
|
||||
}
|
||||
|
||||
.is-disabled {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
.is-disabled {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.default-box {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
height: 100rpx;
|
||||
.default-box {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
height: 100rpx;
|
||||
|
||||
.default-box-title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
.default-box-title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-box {
|
||||
.save-btn {
|
||||
width: 710rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
color: $white;
|
||||
}
|
||||
.footer-box {
|
||||
.save-btn {
|
||||
width: 710rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
width: 710rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background: var(--ui-BG);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.cancel-btn {
|
||||
width: 710rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background: var(--ui-BG);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,143 +1,166 @@
|
|||
<!-- 收件地址列表 -->
|
||||
<template>
|
||||
<s-layout title="收货地址" :bgStyle="{ color: '#FFF' }">
|
||||
<view v-if="state.list.length">
|
||||
<s-address-item hasBorderBottom v-for="item in state.list" :key="item.id" :item="item"
|
||||
@tap="onSelect(item)" />
|
||||
</view>
|
||||
<s-layout title="收货地址" :bgStyle="{ color: '#FFF' }">
|
||||
<view v-if="state.list.length">
|
||||
<s-address-item
|
||||
hasBorderBottom
|
||||
v-for="item in state.list"
|
||||
:key="item.id"
|
||||
:item="item"
|
||||
@tap="onSelect(item)"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<su-fixed bottom placeholder>
|
||||
<view class="footer-box ss-flex ss-row-between ss-p-20">
|
||||
<!-- 微信小程序和微信H5 -->
|
||||
<button v-if="['WechatMiniProgram', 'WechatOfficialAccount'].includes(sheep.$platform.name)"
|
||||
@tap="importWechatAddress"
|
||||
class="border ss-reset-button sync-wxaddress ss-m-20 ss-flex ss-row-center ss-col-center">
|
||||
<text class="cicon-weixin ss-p-r-10" style="color: #09bb07; font-size: 40rpx"></text>
|
||||
导入微信地址
|
||||
</button>
|
||||
<button class="add-btn ss-reset-button ui-Shadow-Main"
|
||||
@tap="sheep.$router.go('/pages/user/address/edit')">
|
||||
新增收货地址
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
<s-empty v-if="state.list.length === 0 && !state.loading" text="暂无收货地址" icon="/static/data-empty.png" />
|
||||
</s-layout>
|
||||
<su-fixed bottom placeholder>
|
||||
<view class="footer-box ss-flex ss-row-between ss-p-20">
|
||||
<!-- 微信小程序和微信H5 -->
|
||||
<button
|
||||
v-if="['WechatMiniProgram', 'WechatOfficialAccount'].includes(sheep.$platform.name)"
|
||||
@tap="importWechatAddress"
|
||||
class="border ss-reset-button sync-wxaddress ss-m-20 ss-flex ss-row-center ss-col-center"
|
||||
>
|
||||
<text class="cicon-weixin ss-p-r-10" style="color: #09bb07; font-size: 40rpx"></text>
|
||||
导入微信地址
|
||||
</button>
|
||||
<button
|
||||
class="add-btn ss-reset-button ui-Shadow-Main"
|
||||
@tap="sheep.$router.go('/pages/user/address/edit')"
|
||||
>
|
||||
新增收货地址
|
||||
</button>
|
||||
</view>
|
||||
</su-fixed>
|
||||
<s-empty
|
||||
v-if="state.list.length === 0 && !state.loading"
|
||||
text="暂无收货地址"
|
||||
icon="/static/data-empty.png"
|
||||
/>
|
||||
</s-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, onBeforeMount } from 'vue';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash';
|
||||
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';
|
||||
import AddressApi from '@/sheep/api/member/address';
|
||||
|
||||
const state = reactive({
|
||||
list: [], // 地址列表
|
||||
loading: true,
|
||||
});
|
||||
const state = reactive({
|
||||
list: [], // 地址列表
|
||||
loading: true,
|
||||
openType: '', // 页面打开类型
|
||||
});
|
||||
|
||||
// 选择收货地址
|
||||
const onSelect = (addressInfo) => {
|
||||
uni.$emit('SELECT_ADDRESS', {
|
||||
addressInfo,
|
||||
});
|
||||
sheep.$router.back();
|
||||
};
|
||||
// 选择收货地址
|
||||
const onSelect = (addressInfo) => {
|
||||
if (state.openType !== 'select'){ // 不作为选择组件时阻断操作
|
||||
return
|
||||
}
|
||||
uni.$emit('SELECT_ADDRESS', {
|
||||
addressInfo,
|
||||
});
|
||||
sheep.$router.back();
|
||||
};
|
||||
|
||||
// 导入微信地址
|
||||
// 导入微信地址
|
||||
// TODO 芋艿:未测试
|
||||
function importWechatAddress() {
|
||||
let wechatAddress = {};
|
||||
// #ifdef MP
|
||||
uni.chooseAddress({
|
||||
success: (res) => {
|
||||
wechatAddress = {
|
||||
consignee: res.userName,
|
||||
mobile: res.telNumber,
|
||||
province_name: res.provinceName,
|
||||
city_name: res.cityName,
|
||||
district_name: res.countyName,
|
||||
address: res.detailInfo,
|
||||
region: '',
|
||||
is_default: false,
|
||||
};
|
||||
if (!isEmpty(wechatAddress)) {
|
||||
sheep.$router.go('/pages/user/address/edit', {
|
||||
data: JSON.stringify(wechatAddress),
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('%cuni.chooseAddress,调用失败', 'color:green;background:yellow');
|
||||
},
|
||||
});
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
sheep.$platform.useProvider('wechat').jssdk.openAddress({
|
||||
success: (res) => {
|
||||
wechatAddress = {
|
||||
consignee: res.userName,
|
||||
mobile: res.telNumber,
|
||||
province_name: res.provinceName,
|
||||
city_name: res.cityName,
|
||||
district_name: res.countryName,
|
||||
address: res.detailInfo,
|
||||
region: '',
|
||||
is_default: false,
|
||||
};
|
||||
if (!isEmpty(wechatAddress)) {
|
||||
sheep.$router.go('/pages/user/address/edit', {
|
||||
data: JSON.stringify(wechatAddress),
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
// #endif
|
||||
}
|
||||
function importWechatAddress() {
|
||||
let wechatAddress = {};
|
||||
// #ifdef MP
|
||||
uni.chooseAddress({
|
||||
success: (res) => {
|
||||
wechatAddress = {
|
||||
consignee: res.userName,
|
||||
mobile: res.telNumber,
|
||||
province_name: res.provinceName,
|
||||
city_name: res.cityName,
|
||||
district_name: res.countyName,
|
||||
address: res.detailInfo,
|
||||
region: '',
|
||||
is_default: false,
|
||||
};
|
||||
if (!isEmpty(wechatAddress)) {
|
||||
sheep.$router.go('/pages/user/address/edit', {
|
||||
data: JSON.stringify(wechatAddress),
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('%cuni.chooseAddress,调用失败', 'color:green;background:yellow');
|
||||
},
|
||||
});
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
sheep.$platform.useProvider('wechat').jssdk.openAddress({
|
||||
success: (res) => {
|
||||
wechatAddress = {
|
||||
consignee: res.userName,
|
||||
mobile: res.telNumber,
|
||||
province_name: res.provinceName,
|
||||
city_name: res.cityName,
|
||||
district_name: res.countryName,
|
||||
address: res.detailInfo,
|
||||
region: '',
|
||||
is_default: false,
|
||||
};
|
||||
if (!isEmpty(wechatAddress)) {
|
||||
sheep.$router.go('/pages/user/address/edit', {
|
||||
data: JSON.stringify(wechatAddress),
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
// #endif
|
||||
}
|
||||
|
||||
onShow(async () => {
|
||||
state.list = (await AddressApi.getAddressList()).data;
|
||||
state.loading = false;
|
||||
});
|
||||
onLoad((option) => {
|
||||
if (option.type) {
|
||||
state.openType = option.type;
|
||||
}
|
||||
});
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (!!uni.getStorageSync('areaData')) {
|
||||
return;
|
||||
}
|
||||
// 提前加载省市区数据
|
||||
onShow(async () => {
|
||||
state.list = (await AddressApi.getAddressList()).data;
|
||||
state.loading = false;
|
||||
});
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (!!uni.getStorageSync('areaData')) {
|
||||
return;
|
||||
}
|
||||
// 提前加载省市区数据
|
||||
AreaApi.getAreaTree().then((res) => {
|
||||
if (res.code === 0) {
|
||||
uni.setStorageSync('areaData', res.data);
|
||||
}
|
||||
});
|
||||
});
|
||||
if (res.code === 0) {
|
||||
uni.setStorageSync('areaData', res.data);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.footer-box {
|
||||
.add-btn {
|
||||
flex: 1;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
border-radius: 80rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
line-height: 80rpx;
|
||||
color: $white;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.footer-box {
|
||||
.add-btn {
|
||||
flex: 1;
|
||||
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
|
||||
border-radius: 80rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
line-height: 80rpx;
|
||||
color: $white;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.sync-wxaddress {
|
||||
flex: 1;
|
||||
line-height: 80rpx;
|
||||
background: $white;
|
||||
border-radius: 80rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: $dark-6;
|
||||
margin-right: 18rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.sync-wxaddress {
|
||||
flex: 1;
|
||||
line-height: 80rpx;
|
||||
background: $white;
|
||||
border-radius: 80rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: $dark-6;
|
||||
margin-right: 18rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@
|
|||
<!-- 头部 -->
|
||||
<view class="cart-header ss-flex ss-col-center ss-row-between ss-p-x-30">
|
||||
<view class="header-left ss-flex ss-col-center ss-font-26">
|
||||
共 <text class="goods-number ui-TC-Main ss-flex">{{ state.pagination.total }}</text> 件商品
|
||||
共
|
||||
<text class="goods-number ui-TC-Main ss-flex">{{ state.pagination.total }}</text> 件商品
|
||||
</view>
|
||||
<view class="header-right">
|
||||
<button
|
||||
|
|
@ -77,7 +78,8 @@
|
|||
<view class="footer-right">
|
||||
<button
|
||||
class="ss-reset-button ui-BG-Main-Gradient pay-btn ss-font-28 ui-Shadow-Main"
|
||||
@tap="onCancel">
|
||||
@tap="onCancel"
|
||||
>
|
||||
取消收藏
|
||||
</button>
|
||||
</view>
|
||||
|
|
@ -100,7 +102,7 @@
|
|||
import sheep from '@/sheep';
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import FavoriteApi from '@/sheep/api/product/favorite';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
||||
|
|
@ -129,7 +131,7 @@
|
|||
if (code !== 0) {
|
||||
return;
|
||||
}
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list)
|
||||
state.pagination.list = _.concat(state.pagination.list, data.list);
|
||||
state.pagination.total = data.total;
|
||||
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
|
||||
}
|
||||
|
|
@ -174,7 +176,7 @@
|
|||
// 加载更多
|
||||
function loadMore() {
|
||||
if (state.loadStatus === 'noMore') {
|
||||
return
|
||||
return;
|
||||
}
|
||||
state.pagination.pageNo++;
|
||||
getData();
|
||||
|
|
|
|||
|
|
@ -81,11 +81,13 @@
|
|||
</view>
|
||||
<view class="footer-right ss-flex">
|
||||
<button
|
||||
:class="['ss-reset-button pay-btn ss-font-28 ',
|
||||
{
|
||||
'ui-BG-Main-Gradient': state.selectedSpuIdList.length > 0,
|
||||
'ui-Shadow-Main': state.selectedSpuIdList.length > 0
|
||||
}]"
|
||||
:class="[
|
||||
'ss-reset-button pay-btn ss-font-28 ',
|
||||
{
|
||||
'ui-BG-Main-Gradient': state.selectedSpuIdList.length > 0,
|
||||
'ui-Shadow-Main': state.selectedSpuIdList.length > 0,
|
||||
},
|
||||
]"
|
||||
@tap="onDelete"
|
||||
>
|
||||
删除足迹
|
||||
|
|
@ -120,9 +122,9 @@
|
|||
import sheep from '@/sheep';
|
||||
import { reactive } from 'vue';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import _ from 'lodash';
|
||||
import SpuHistoryApi from "@/sheep/api/product/history";
|
||||
import {cloneDeep} from "@/sheep/helper/utils";
|
||||
import _ from 'lodash-es';
|
||||
import SpuHistoryApi from '@/sheep/api/product/history';
|
||||
import { cloneDeep } from '@/sheep/helper/utils';
|
||||
|
||||
const sys_navBar = sheep.$platform.navbar;
|
||||
const pagination = {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,275 @@
|
|||
<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) => {
|
||||
console.log(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 {
|
||||
}
|
||||
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) {
|
||||
// error
|
||||
}
|
||||
});
|
||||
</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>
|
||||
|
|
@ -26,7 +26,8 @@
|
|||
<button
|
||||
class="ss-reset-button avatar-action-btn"
|
||||
open-type="chooseAvatar"
|
||||
@chooseavatar="onChooseAvatar">
|
||||
@chooseavatar="onChooseAvatar"
|
||||
>
|
||||
修改
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
|
|
@ -154,10 +155,7 @@
|
|||
</view>
|
||||
<view class="ss-flex ss-col-center">
|
||||
<view class="info ss-flex ss-col-center" v-if="state.thirdInfo">
|
||||
<image
|
||||
class="avatar ss-m-r-20"
|
||||
:src="sheep.$url.cdn(state.thirdInfo.avatar)"
|
||||
/>
|
||||
<image class="avatar ss-m-r-20" :src="sheep.$url.cdn(state.thirdInfo.avatar)" />
|
||||
<text class="name">{{ state.thirdInfo.nickname }}</text>
|
||||
</view>
|
||||
<view class="bind-box ss-m-l-20">
|
||||
|
|
@ -185,7 +183,7 @@
|
|||
<script setup>
|
||||
import { computed, reactive, onBeforeMount } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { clone } from 'lodash';
|
||||
import { clone } from 'lodash-es';
|
||||
import { showAuthModal } from '@/sheep/hooks/useModal';
|
||||
import FileApi from '@/sheep/api/infra/file';
|
||||
import UserApi from '@/sheep/api/member/user';
|
||||
|
|
@ -198,14 +196,15 @@
|
|||
|
||||
const placeholderStyle = 'color:#BBBBBB;font-size:28rpx;line-height:normal';
|
||||
|
||||
const sexRadioMap = [{
|
||||
const sexRadioMap = [
|
||||
{
|
||||
name: '男',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
name: '女',
|
||||
value: '2',
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
const userInfo = computed(() => sheep.$store('user').userInfo);
|
||||
|
|
@ -279,7 +278,7 @@
|
|||
|
||||
// 保存信息
|
||||
async function onSubmit() {
|
||||
const { code } = await UserApi.updateUser({
|
||||
const { code } = await UserApi.updateUser({
|
||||
avatar: state.model.avatar,
|
||||
nickname: state.model.nickname,
|
||||
sex: state.model.sex,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@
|
|||
/>
|
||||
</view>
|
||||
<view class="ss-flex ss-row-between ss-col-center ss-m-t-64">
|
||||
<view class="money-num">{{ state.showMoney ? fen2yuan(userWallet.balance) : '*****' }}</view>
|
||||
<view class="money-num">{{
|
||||
state.showMoney ? fen2yuan(userWallet.balance) : '*****'
|
||||
}}</view>
|
||||
<button class="ss-reset-button topup-btn" @tap="sheep.$router.go('/pages/pay/recharge')">
|
||||
充值
|
||||
</button>
|
||||
|
|
@ -24,7 +26,12 @@
|
|||
<su-sticky>
|
||||
<!-- 统计 -->
|
||||
<view class="filter-box ss-p-x-30 ss-flex ss-col-center ss-row-between">
|
||||
<uni-datetime-picker v-model="state.data" type="daterange" @change="onChangeTime" :end="state.today">
|
||||
<uni-datetime-picker
|
||||
v-model="state.data"
|
||||
type="daterange"
|
||||
@change="onChangeTime"
|
||||
:end="state.today"
|
||||
>
|
||||
<button class="ss-reset-button date-btn">
|
||||
<text>{{ dateFilterText }}</text>
|
||||
<text class="cicon-drop-down ss-seldate-icon"></text>
|
||||
|
|
@ -82,7 +89,7 @@
|
|||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import sheep from '@/sheep';
|
||||
import dayjs from 'dayjs';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import PayWalletApi from '@/sheep/api/pay/wallet';
|
||||
import { fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
|
@ -98,7 +105,7 @@
|
|||
list: [],
|
||||
total: 0,
|
||||
pageNo: 1,
|
||||
pageSize: 8
|
||||
pageSize: 8,
|
||||
},
|
||||
summary: {
|
||||
totalIncome: 0,
|
||||
|
|
@ -155,7 +162,7 @@
|
|||
// 获得钱包统计
|
||||
async function getSummary() {
|
||||
const { data, code } = await PayWalletApi.getWalletTransactionSummary({
|
||||
'createTime': [state.date[0] + ' 00:00:00', state.date[1] + ' 23:59:59'],
|
||||
createTime: [state.date[0] + ' 00:00:00', state.date[1] + ' 23:59:59'],
|
||||
});
|
||||
if (code !== 0) {
|
||||
return;
|
||||
|
|
@ -226,8 +233,7 @@
|
|||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: v-bind(headerBg)
|
||||
no-repeat;
|
||||
background: v-bind(headerBg) no-repeat;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,19 +24,24 @@
|
|||
<su-sticky :customNavHeight="sys_navBar">
|
||||
<!-- 统计 -->
|
||||
<view class="filter-box ss-p-x-30 ss-flex ss-col-center ss-row-between">
|
||||
<uni-datetime-picker v-model="state.date" type="daterange" @change="onChangeTime" :end="state.today">
|
||||
<button class="ss-reset-button date-btn">
|
||||
<text>{{ dateFilterText }}</text>
|
||||
<text class="cicon-drop-down ss-seldate-icon"></text>
|
||||
</button>
|
||||
</uni-datetime-picker>
|
||||
<uni-datetime-picker
|
||||
v-model="state.date"
|
||||
type="daterange"
|
||||
@change="onChangeTime"
|
||||
:end="state.today"
|
||||
>
|
||||
<button class="ss-reset-button date-btn">
|
||||
<text>{{ dateFilterText }}</text>
|
||||
<text class="cicon-drop-down ss-seldate-icon"></text>
|
||||
</button>
|
||||
</uni-datetime-picker>
|
||||
|
||||
<!-- TODO 芋艿:优化 -->
|
||||
<!-- <view class="total-box">-->
|
||||
<!-- <view class="ss-m-b-10">总收入¥{{ state.pagination.income }}</view>-->
|
||||
<!-- <view>总支出¥{{ -state.pagination.expense }}</view>-->
|
||||
<!-- </view>-->
|
||||
</view>
|
||||
<!-- <view class="total-box">-->
|
||||
<!-- <view class="ss-m-b-10">总收入¥{{ state.pagination.income }}</view>-->
|
||||
<!-- <view>总支出¥{{ -state.pagination.expense }}</view>-->
|
||||
<!-- </view>-->
|
||||
</view>
|
||||
<su-tabs
|
||||
:list="tabMaps"
|
||||
@change="onChange"
|
||||
|
|
@ -83,7 +88,7 @@
|
|||
import sheep from '@/sheep';
|
||||
import { onLoad, onReachBottom } from '@dcloudio/uni-app';
|
||||
import { computed, reactive } from 'vue';
|
||||
import _ from 'lodash';
|
||||
import _ from 'lodash-es';
|
||||
import dayjs from 'dayjs';
|
||||
import PointApi from '@/sheep/api/member/point';
|
||||
import { resetPagination } from '@/sheep/util';
|
||||
|
|
@ -274,4 +279,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
import request from '@/sheep/request';
|
||||
|
||||
// TODO 芋艿:暂不支持 socket 聊天
|
||||
export default {
|
||||
// 获取聊天token
|
||||
unifiedToken: () =>
|
||||
request({
|
||||
url: 'unifiedToken',
|
||||
custom: {
|
||||
showError: false,
|
||||
showLoading: false,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,7 @@
|
|||
<view class="address-text">
|
||||
{{ props.item.detailAddress }}
|
||||
</view>
|
||||
<view class="person-text">
|
||||
{{ props.item.name }} {{ props.item.mobile }}
|
||||
</view>
|
||||
<view class="person-text"> {{ props.item.name }} {{ props.item.mobile }} </view>
|
||||
</view>
|
||||
<view v-else>
|
||||
<view class="address-text ss-m-b-10">请选择收货地址</view>
|
||||
|
|
@ -47,7 +45,7 @@
|
|||
* @slot - 默认插槽
|
||||
*/
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,24 +1,19 @@
|
|||
<!-- 订单确认的优惠劵选择弹窗 -->
|
||||
<template>
|
||||
<su-popup
|
||||
:show="show"
|
||||
type="bottom"
|
||||
round="20"
|
||||
@close="emits('close')"
|
||||
showClose
|
||||
backgroundColor="#f2f2f2"
|
||||
>
|
||||
<su-popup :show="show" type="bottom" round="20" @close="emits('close')" showClose backgroundColor="#f2f2f2">
|
||||
<view class="model-box">
|
||||
<view class="title ss-m-t-16 ss-m-l-20 ss-flex">优惠券</view>
|
||||
<scroll-view
|
||||
class="model-content"
|
||||
scroll-y
|
||||
:scroll-with-animation="false"
|
||||
:enable-back-to-top="true"
|
||||
>
|
||||
<scroll-view class="model-content" scroll-y :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 v-slot:reason>
|
||||
<view class="ss-flex ss-m-t-24">
|
||||
<view class="reason-title">可用原因:</view>
|
||||
<view class="reason-desc">{{ item.description || '已达到使用门槛' }}</view>
|
||||
</view>
|
||||
</template>
|
||||
<template #default>
|
||||
<label class="ss-flex ss-col-center" @tap="radioChange(item.id)">
|
||||
<radio
|
||||
|
|
@ -31,19 +26,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.description || '未达到使用门槛' }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</s-coupon-list>
|
||||
</view>
|
||||
-->
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="modal-footer ss-flex">
|
||||
|
|
@ -57,7 +51,8 @@
|
|||
const props = defineProps({
|
||||
modelValue: { // 优惠劵列表
|
||||
type: Object,
|
||||
default() {},
|
||||
default() {
|
||||
},
|
||||
},
|
||||
show: {
|
||||
type: Boolean,
|
||||
|
|
@ -84,7 +79,7 @@
|
|||
// 确认优惠劵
|
||||
const onConfirm = () => {
|
||||
emits('confirm', state.couponId);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
:deep() {
|
||||
|
|
@ -96,25 +91,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 +123,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;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,11 @@
|
|||
<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>
|
||||
<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"
|
||||
|
|
@ -39,14 +43,21 @@
|
|||
<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"
|
||||
class="sm-goods-title ss-line-1 ss-m-b-16"
|
||||
>
|
||||
{{ data.title || data.name }}
|
||||
</view>
|
||||
<view
|
||||
|
|
@ -65,7 +76,11 @@
|
|||
<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>
|
||||
<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"
|
||||
|
|
@ -106,7 +121,10 @@
|
|||
</view>
|
||||
|
||||
<view
|
||||
v-if="(goodsFields.original_price?.show||goodsFields.marketPrice?.show) &&( data.original_price > 0|| data.marketPrice > 0)"
|
||||
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 }]"
|
||||
>
|
||||
|
|
@ -141,7 +159,11 @@
|
|||
<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
|
||||
|
|
@ -177,7 +199,10 @@
|
|||
{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
|
||||
</view>
|
||||
<view
|
||||
v-if="(goodsFields.original_price?.show||goodsFields.marketPrice?.show) &&( data.original_price > 0|| data.marketPrice > 0)"
|
||||
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 }]"
|
||||
>
|
||||
|
|
@ -192,9 +217,7 @@
|
|||
</view>
|
||||
|
||||
<slot name="cart">
|
||||
<view class="buy-box ss-flex ss-col-center ss-row-center" v-if="buttonShow">
|
||||
去购买
|
||||
</view>
|
||||
<view class="buy-box ss-flex ss-col-center ss-row-center" v-if="buttonShow"> 去购买 </view>
|
||||
</slot>
|
||||
</view>
|
||||
|
||||
|
|
@ -204,7 +227,11 @@
|
|||
<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>
|
||||
|
|
@ -241,7 +268,10 @@
|
|||
{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
|
||||
</view>
|
||||
<view
|
||||
v-if="(goodsFields.original_price?.show||goodsFields.marketPrice?.show) &&( data.original_price > 0|| data.marketPrice > 0)"
|
||||
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 }]"
|
||||
>
|
||||
|
|
@ -296,7 +326,7 @@
|
|||
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';
|
||||
import { isArray } from 'lodash-es';
|
||||
|
||||
// 数据
|
||||
const state = reactive({});
|
||||
|
|
|
|||
|
|
@ -1,154 +1,171 @@
|
|||
<!-- 装修组件 - 拼团 -->
|
||||
<template>
|
||||
<view>
|
||||
<view
|
||||
v-if="layoutType === 'threeCol'"
|
||||
class="goods-sm-box ss-flex ss-flex-wrap"
|
||||
:style="[{ margin: '-' + data.space + 'rpx' }]"
|
||||
>
|
||||
<view
|
||||
v-for="product in productList"
|
||||
:key="product.id"
|
||||
class="goods-card-box"
|
||||
:style="[
|
||||
{
|
||||
padding: data.space + 'rpx',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<s-goods-column
|
||||
class="goods-card"
|
||||
size="sm"
|
||||
:goodsFields="data.fields"
|
||||
:tagStyle="tagStyle"
|
||||
:data="product"
|
||||
:titleColor="data.fields.name?.color"
|
||||
:topRadius="data.borderRadiusTop"
|
||||
:bottomRadius="data.borderRadiusBottom"
|
||||
@click="
|
||||
sheep.$router.go('/pages/goods/groupon', {
|
||||
id: props.data.activityId,
|
||||
})
|
||||
"
|
||||
></s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 样式2 一行一个 图片左 文案右 -->
|
||||
<view class="goods-box" v-if="layoutType === 'oneCol'">
|
||||
<view
|
||||
class="goods-list"
|
||||
v-for="(product, index) in productList"
|
||||
:key="index"
|
||||
:style="[{ marginBottom: space + 'px' }]"
|
||||
>
|
||||
<s-goods-column
|
||||
class="goods-card"
|
||||
size="lg"
|
||||
:goodsFields="data.fields"
|
||||
:tagStyle="tagStyle"
|
||||
:data="product"
|
||||
: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,
|
||||
})
|
||||
"
|
||||
>
|
||||
<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>
|
||||
<view v-if="layoutType === 'threeCol'" class="goods-sm-box ss-flex ss-flex-wrap" :style="[{ margin: '-' + data.space + 'rpx' }]">
|
||||
<view v-for="product in productList" class="goods-card-box" :key="product.id" :style="[{padding: data.space + 'rpx',},]">
|
||||
<s-goods-column
|
||||
class="goods-card"
|
||||
size="sm"
|
||||
:goodsFields="goodsFields"
|
||||
:tagStyle="badge"
|
||||
:data="product"
|
||||
:titleColor="data.fields.name?.color"
|
||||
:topRadius="data.borderRadiusTop"
|
||||
:bottomRadius="data.borderRadiusBottom"
|
||||
@click="sheep.$router.go('/pages/goods/groupon', { id: props.data.activityId, })">
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 样式2 一行一个 图片左 文案右 -->
|
||||
<view class="goods-box" v-if="layoutType === 'oneCol'">
|
||||
<view class="goods-list" v-for="(product, index) in productList" :key="index" :style="[{ marginBottom: space + 'px' }]">
|
||||
<s-goods-column
|
||||
class="goods-card" size="lg"
|
||||
:grouponTag="true"
|
||||
:goodsFields="goodsFields"
|
||||
:tagStyle="badge"
|
||||
:data="product"
|
||||
: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, })">
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
/**
|
||||
* 拼团
|
||||
*/
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import SpuApi from "@/sheep/api/product/spu";
|
||||
import CombinationApi from "@/sheep/api/promotion/combination";
|
||||
/**
|
||||
* 拼团
|
||||
*/
|
||||
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";
|
||||
|
||||
// 接收参数
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
});
|
||||
// 接收参数
|
||||
const props = defineProps({
|
||||
// 装修数据
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 装修样式
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
// 设置相关信息是否显示
|
||||
const goodsFields = reactive({
|
||||
// 商品价格
|
||||
price: { show: true },
|
||||
// 库存
|
||||
stock: { show: true },
|
||||
// 商品名称
|
||||
name: { show: true },
|
||||
// 商品介绍
|
||||
introduction: { show: true },
|
||||
// 市场价
|
||||
marketPrice: { show: true },
|
||||
// 销量
|
||||
salesCount: { show: true },
|
||||
});
|
||||
|
||||
let { layoutType, tagStyle, btnBuy, space } = props.data;
|
||||
let { marginLeft, marginRight } = props.styles;
|
||||
let {
|
||||
layoutType,
|
||||
badge,
|
||||
btnBuy,
|
||||
space,
|
||||
} = props.data;
|
||||
let {
|
||||
marginLeft,
|
||||
marginRight
|
||||
} = props.styles;
|
||||
|
||||
// 购买按钮样式
|
||||
const buyStyle = computed(() => {
|
||||
let btnBuy = props.data.btnBuy;
|
||||
if (btnBuy?.type === 'text') {
|
||||
return {
|
||||
background: `linear-gradient(to right, ${btnBuy.bgBeginColor}, ${btnBuy.bgEndColor})`,
|
||||
};
|
||||
}
|
||||
// 购买按钮样式(暂未实现)
|
||||
const buyStyle = computed(() => {
|
||||
let btnBuy = props.data.btnBuy;
|
||||
if (btnBuy?.type === 'text') {
|
||||
return {
|
||||
background: `linear-gradient(to right, ${btnBuy.bgBeginColor}, ${btnBuy.bgEndColor})`,
|
||||
};
|
||||
}
|
||||
|
||||
if (btnBuy?.type === 'img') {
|
||||
return {
|
||||
width: '54rpx',
|
||||
height: '54rpx',
|
||||
background: `url(${sheep.$url.cdn(btnBuy.imgUrl)}) no-repeat`,
|
||||
backgroundSize: '100% 100%',
|
||||
};
|
||||
}
|
||||
});
|
||||
if (btnBuy?.type === 'img') {
|
||||
return {
|
||||
width: '54rpx',
|
||||
height: '54rpx',
|
||||
background: `url(${sheep.$url.cdn(btnBuy.imgUrl)}) no-repeat`,
|
||||
backgroundSize: '100% 100%',
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const productList = ref([]);
|
||||
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 productList = ref([]);
|
||||
onMounted(async () => {
|
||||
// todo:@owen 与Yudao结构不一致,待重构
|
||||
const {
|
||||
data: activity
|
||||
} = await CombinationApi.getCombinationActivity(props.data.activityId);
|
||||
const {
|
||||
data: spu
|
||||
} = await SpuApi.getSpuDetail(activity.spuId)
|
||||
// 循环活动信息,赋值拼团最低价格
|
||||
activity.products.forEach((product) => {
|
||||
spu.price = Math.min(spu.price, product.combinationPrice); // 设置 SPU 的最低价格
|
||||
});
|
||||
productList.value = [spu];
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.goods-list {
|
||||
position: relative;
|
||||
.cart-btn {
|
||||
position: absolute;
|
||||
bottom: 10rpx;
|
||||
right: 20rpx;
|
||||
z-index: 11;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
padding: 0 20rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
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>
|
||||
.goods-list {
|
||||
position: relative;
|
||||
|
||||
.cart-btn {
|
||||
position: absolute;
|
||||
bottom: 10rpx;
|
||||
right: 20rpx;
|
||||
z-index: 11;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
padding: 0 20rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
color: #fff;
|
||||
background: linear-gradient(90deg, #ff6600 0%, #fe832a 100%);
|
||||
}
|
||||
}
|
||||
|
||||
.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>
|
||||
|
|
@ -31,7 +31,11 @@
|
|||
></view>
|
||||
|
||||
<!-- 顶部导航栏-情况4:装修组件导航栏-沉浸式 -->
|
||||
<s-custom-navbar v-if="navbar === 'custom' && navbarMode === 'inner'" :data="navbarStyle" :showLeftButton="showLeftButton" />
|
||||
<s-custom-navbar
|
||||
v-if="navbar === 'custom' && navbarMode === 'inner'"
|
||||
:data="navbarStyle"
|
||||
:showLeftButton="showLeftButton"
|
||||
/>
|
||||
|
||||
<!-- 页面内容插槽 -->
|
||||
<slot />
|
||||
|
|
@ -58,7 +62,7 @@
|
|||
*/
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
// #ifdef MP-WEIXIN
|
||||
import { onShareAppMessage } from '@dcloudio/uni-app';
|
||||
|
|
|
|||
|
|
@ -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,160 +1,182 @@
|
|||
<!-- 装修组件 - 秒杀 -->
|
||||
<template>
|
||||
<view>
|
||||
<!-- 样式一:三列 - 上图下文 -->
|
||||
<view
|
||||
v-if="layoutType === 'threeCol'"
|
||||
class="goods-sm-box ss-flex ss-flex-wrap"
|
||||
:style="[{ margin: '-' + data.space + 'rpx' }]"
|
||||
>
|
||||
<view
|
||||
v-for="product in productList"
|
||||
:key="product.id"
|
||||
class="goods-card-box"
|
||||
:style="[
|
||||
{
|
||||
padding: data.space + 'rpx',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<s-goods-column
|
||||
class="goods-card"
|
||||
size="sm"
|
||||
:goodsFields="data.fields"
|
||||
:tagStyle="tagStyle"
|
||||
:data="product"
|
||||
:titleColor="data.fields.name?.color"
|
||||
:topRadius="data.borderRadiusTop"
|
||||
:bottomRadius="data.borderRadiusBottom"
|
||||
@click="
|
||||
sheep.$router.go('/pages/goods/seckill', {
|
||||
id: props.data.activityId,
|
||||
})
|
||||
"
|
||||
></s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 样式二:一列 - 左图右文 -->
|
||||
<view class="goods-box" v-if="layoutType === 'oneCol'">
|
||||
<view
|
||||
class="goods-list"
|
||||
v-for="(product, index) in productList"
|
||||
:key="index"
|
||||
:style="[{ marginBottom: space + 'px' }]"
|
||||
>
|
||||
<s-goods-column
|
||||
class="goods-card"
|
||||
size="lg"
|
||||
:goodsFields="data.fields"
|
||||
:tagStyle="tagStyle"
|
||||
:data="product"
|
||||
: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,
|
||||
})
|
||||
"
|
||||
>
|
||||
<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>
|
||||
<!-- 样式一:三列 - 上图下文 -->
|
||||
<view v-if="layoutType === 'threeCol'" class="goods-sm-box ss-flex ss-flex-wrap" :style="[{ margin: '-' + data.space + 'rpx' }]">
|
||||
<view v-for="product in productList" :key="product.id" class="goods-card-box" :style="[{padding: data.space + 'rpx',},]">
|
||||
<s-goods-column
|
||||
class="goods-card" size="sm"
|
||||
:goodsFields="goodsFields"
|
||||
:tagStyle="badge"
|
||||
:data="product"
|
||||
:titleColor="data.fields.name?.color"
|
||||
:topRadius="data.borderRadiusTop"
|
||||
:bottomRadius="data.borderRadiusBottom"
|
||||
@click="sheep.$router.go('/pages/goods/seckill', { id: props.data.activityId, })">
|
||||
</s-goods-column>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 样式二:一列 - 左图右文 -->
|
||||
<view class="goods-box" v-if="layoutType === 'oneCol'">
|
||||
<view class="goods-list" v-for="(product, index) in productList" :key="index"
|
||||
:style="[{ marginBottom: space + 'px' }]">
|
||||
<s-goods-column
|
||||
class="goods-card"
|
||||
size="lg"
|
||||
:goodsFields="goodsFields"
|
||||
:seckillTag="true"
|
||||
:tagStyle="badge"
|
||||
:data="product"
|
||||
: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, })">
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
/**
|
||||
* 秒杀商品列表
|
||||
*
|
||||
* @property {Array} list 商品列表
|
||||
*/
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import SeckillApi from "@/sheep/api/promotion/seckill";
|
||||
import SpuApi from "@/sheep/api/product/spu";
|
||||
/**
|
||||
* 秒杀商品列表
|
||||
*
|
||||
* @property {Array} list 商品列表
|
||||
*/
|
||||
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";
|
||||
|
||||
// 接收参数
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default() {},
|
||||
},
|
||||
});
|
||||
// 接收参数
|
||||
const props = defineProps({
|
||||
// 装修数据
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 装修样式
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
// 设置相关信息是否显示
|
||||
const goodsFields = reactive({
|
||||
// 商品价格
|
||||
price: { show: true },
|
||||
// 库存
|
||||
stock: { show: true },
|
||||
// 商品名称
|
||||
name: { show: true },
|
||||
// 商品介绍
|
||||
introduction: { show: true },
|
||||
// 市场价
|
||||
marketPrice: { show: true },
|
||||
// 销量
|
||||
salesCount: { show: true },
|
||||
});
|
||||
|
||||
let {
|
||||
layoutType,
|
||||
badge,
|
||||
btnBuy,
|
||||
space,
|
||||
} = props.data;
|
||||
let {
|
||||
marginLeft,
|
||||
marginRight
|
||||
} = props.styles;
|
||||
|
||||
let { layoutType, tagStyle, btnBuy, space } = props.data;
|
||||
let { marginLeft, marginRight } = props.styles;
|
||||
// 购买按钮样式
|
||||
const buyStyle = computed(() => {
|
||||
let btnBuy = props.data.btnBuy;
|
||||
if (btnBuy?.type === 'text') {
|
||||
return {
|
||||
background: `linear-gradient(to right, ${btnBuy.bgBeginColor}, ${btnBuy.bgEndColor})`,
|
||||
};
|
||||
}
|
||||
if (btnBuy?.type === 'img') {
|
||||
return {
|
||||
width: '54rpx',
|
||||
height: '54rpx',
|
||||
background: `url(${sheep.$url.cdn(btnBuy.imgUrl)}) no-repeat`,
|
||||
backgroundSize: '100% 100%',
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// 购买按钮样式
|
||||
const buyStyle = computed(() => {
|
||||
let btnBuy = props.data.btnBuy;
|
||||
if (btnBuy?.type === 'text') {
|
||||
return {
|
||||
background: `linear-gradient(to right, ${btnBuy.bgBeginColor}, ${btnBuy.bgEndColor})`,
|
||||
};
|
||||
}
|
||||
if (btnBuy?.type === 'img') {
|
||||
return {
|
||||
width: '54rpx',
|
||||
height: '54rpx',
|
||||
background: `url(${sheep.$url.cdn(btnBuy.imgUrl)}) no-repeat`,
|
||||
backgroundSize: '100% 100%',
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// 商品列表
|
||||
const productList = ref([]);
|
||||
// 查询秒杀活动商品
|
||||
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 productList = ref([]);
|
||||
// 查询秒杀活动商品
|
||||
onMounted(async () => {
|
||||
// todo:@owen 与Yudao结构不一致,待重构
|
||||
const {
|
||||
data: activity
|
||||
} = await SeckillApi.getSeckillActivity(props.data.activityId);
|
||||
const {
|
||||
data: spu
|
||||
} = await SpuApi.getSpuDetail(activity.spuId)
|
||||
// 循环活动信息,赋值秒杀最低价格
|
||||
activity.products.forEach((product) => {
|
||||
spu.price = Math.min(spu.price, product.seckillPrice); // 设置 SPU 的最低价格
|
||||
});
|
||||
// 将活动库存赋值给商品库存
|
||||
spu.stock = activity.stock
|
||||
// 活动总库存 - 活动库存 = 销量
|
||||
spu.salesCount = activity.totalStock - activity.stock
|
||||
productList.value = [spu];
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header-box {
|
||||
height: 100rpx;
|
||||
}
|
||||
.header-box {
|
||||
height: 100rpx;
|
||||
}
|
||||
|
||||
.goods-list {
|
||||
position: relative;
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.cart-btn {
|
||||
position: absolute;
|
||||
bottom: 10rpx;
|
||||
right: 20rpx;
|
||||
z-index: 11;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
padding: 0 20rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
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>
|
||||
.goods-list {
|
||||
position: relative;
|
||||
|
||||
&:nth-last-child(1) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.cart-btn {
|
||||
position: absolute;
|
||||
bottom: 10rpx;
|
||||
right: 20rpx;
|
||||
z-index: 11;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
padding: 0 20rpx;
|
||||
border-radius: 25rpx;
|
||||
font-size: 24rpx;
|
||||
color: #fff;
|
||||
background: linear-gradient(90deg, #ff6600 0%, #fe832a 100%);
|
||||
}
|
||||
}
|
||||
|
||||
.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>
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
</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 }}件
|
||||
|
|
@ -63,7 +63,7 @@
|
|||
<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>
|
||||
|
|
|
|||
|
|
@ -1,31 +1,31 @@
|
|||
<!-- 秒杀商品的 SKU 选择,和 s-select-sku.vue 类似 -->
|
||||
<template>
|
||||
<!-- 规格弹窗 -->
|
||||
<su-popup :show="show" round="10" @close="emits('close')">
|
||||
<!-- 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"
|
||||
:src="sheep.$url.cdn(state.selectedSku.picUrl || state.goodsInfo.picUrl)"
|
||||
mode="aspectFill"
|
||||
>
|
||||
</image>
|
||||
</view>
|
||||
<view class="header-right ss-flex-col ss-row-between ss-flex-1">
|
||||
<!-- 名称 -->
|
||||
<view class="goods-title ss-line-2">{{ state.goodsInfo.name }}</view>
|
||||
<view class="header-right-bottom ss-flex ss-col-center ss-row-between">
|
||||
<!-- 价格 -->
|
||||
<view class="price-text">
|
||||
{{ fen2yuan(state.selectedSku.price || state.goodsInfo.price) }}
|
||||
</view>
|
||||
<!-- 秒杀价格标签 -->
|
||||
<view class="tig ss-flex ss-col-center">
|
||||
<view class="tig-icon ss-flex ss-col-center ss-row-center">
|
||||
<text class="cicon-alarm"></text>
|
||||
<!-- 规格弹窗 -->
|
||||
<su-popup :show="show" round="10" @close="emits('close')">
|
||||
<!-- 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"
|
||||
:src="sheep.$url.cdn(state.selectedSku.picUrl || state.goodsInfo.picUrl)"
|
||||
mode="aspectFill"
|
||||
>
|
||||
</image>
|
||||
</view>
|
||||
<view class="header-right ss-flex-col ss-row-between ss-flex-1">
|
||||
<!-- 名称 -->
|
||||
<view class="goods-title ss-line-2">{{ state.goodsInfo.name }}</view>
|
||||
<view class="header-right-bottom ss-flex ss-col-center ss-row-between">
|
||||
<!-- 价格 -->
|
||||
<view class="price-text">
|
||||
{{ fen2yuan(state.selectedSku.price || state.goodsInfo.price) }}
|
||||
</view>
|
||||
<!-- 秒杀价格标签 -->
|
||||
<view class="tig ss-flex ss-col-center">
|
||||
<view class="tig-icon ss-flex ss-col-center ss-row-center">
|
||||
<text class="cicon-alarm"></text>
|
||||
</view>
|
||||
<view class="tig-title">秒杀价</view>
|
||||
</view>
|
||||
|
|
@ -91,8 +91,8 @@
|
|||
// 按钮状态: active,nostock
|
||||
import { computed, reactive, watch } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import {convertProductPropertyList, fen2yuan} from "@/sheep/hooks/useGoods";
|
||||
import {min} from "lodash";
|
||||
import { convertProductPropertyList, fen2yuan } from '@/sheep/hooks/useGoods';
|
||||
import { min } from 'lodash-es';
|
||||
const emits = defineEmits(['change', 'addCart', 'buy', 'close']);
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
|
|
@ -107,7 +107,7 @@
|
|||
singleLimitCount: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
}
|
||||
},
|
||||
});
|
||||
const state = reactive({
|
||||
goodsInfo: computed(() => props.modelValue),
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
const skuList = computed(() => {
|
||||
let skuPrices = state.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;
|
||||
});
|
||||
|
|
@ -228,7 +228,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 不禁用
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -258,7 +258,10 @@
|
|||
const 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, '');
|
||||
|
|
|
|||
|
|
@ -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,6 +1,6 @@
|
|||
<!-- 装修用户组件:用户卡片 -->
|
||||
<template>
|
||||
<view class="ss-user-info-wrap ss-p-t-50">
|
||||
<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">
|
||||
|
|
@ -70,9 +70,15 @@
|
|||
const isLogin = computed(() => sheep.$store('user').isLogin);
|
||||
// 接收参数
|
||||
const props = defineProps({
|
||||
background: {
|
||||
type: String,
|
||||
default: '',
|
||||
// 装修数据
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 装修样式
|
||||
styles: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 头像
|
||||
avatar: {
|
||||
|
|
@ -96,7 +102,20 @@
|
|||
default: '1',
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
// 设置背景样式
|
||||
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');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
* @param {Object} device - 设备信息
|
||||
*/
|
||||
|
||||
import { isEmpty } from 'lodash';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
// #ifdef H5
|
||||
import { isWxBrowser } from '@/sheep/helper/utils';
|
||||
// #endif
|
||||
|
|
|
|||
|
|
@ -54,7 +54,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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@
|
|||
*/
|
||||
|
||||
import Request from 'luch-request';
|
||||
import { baseUrl, apiPath, tenantId } from '@/sheep/config';
|
||||
import { apiPath, baseUrl, tenantId } from '@/sheep/config';
|
||||
import $store from '@/sheep/store';
|
||||
import $platform from '@/sheep/platform';
|
||||
import {
|
||||
showAuthModal
|
||||
} from '@/sheep/hooks/useModal';
|
||||
import { showAuthModal } from '@/sheep/hooks/useModal';
|
||||
import AuthUtil from '@/sheep/api/member/auth';
|
||||
import { getTerminal } from '@/sheep/util/const';
|
||||
|
||||
const options = {
|
||||
// 显示操作成功消息 默认不显示
|
||||
|
|
@ -93,13 +92,12 @@ http.interceptors.request.use(
|
|||
// 增加 token 令牌、terminal 终端、tenant 租户的请求头
|
||||
const token = getAccessToken();
|
||||
if (token) {
|
||||
config.header['Authorization'] = token;
|
||||
}
|
||||
// TODO 芋艿:特殊处理
|
||||
config.header['Authorization'] = token;
|
||||
}
|
||||
config.header['terminal'] = getTerminal();
|
||||
|
||||
config.header['Accept'] = '*/*';
|
||||
config.header['tenant-id'] = tenantId;
|
||||
config.header['terminal'] = '20';
|
||||
// config.header['Authorization'] = 'Bearer test247';
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import $store from '@/sheep/store';
|
||||
import { showAuthModal, showShareModal } from '@/sheep/hooks/useModal';
|
||||
import { isNumber, isString, isEmpty, startsWith, isObject, isNil, clone } from 'lodash';
|
||||
import { isNumber, isString, isEmpty, startsWith, isObject, isNil, clone } from 'lodash-es';
|
||||
import throttle from '@/sheep/helper/throttle';
|
||||
|
||||
const _go = (
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { defineStore } from 'pinia';
|
||||
import $share from '@/sheep/platform/share';
|
||||
import { clone, cloneDeep } from 'lodash';
|
||||
import { clone, cloneDeep } from 'lodash-es';
|
||||
import cart from './cart';
|
||||
import app from './app';
|
||||
import { showAuthModal } from '@/sheep/hooks/useModal';
|
||||
|
|
@ -68,12 +68,12 @@ const user = defineStore({
|
|||
|
||||
// 获取订单、优惠券等其他资产信息
|
||||
getNumData() {
|
||||
OrderApi.getOrderCount().then(res => {
|
||||
OrderApi.getOrderCount().then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.numData.orderCount = res.data;
|
||||
}
|
||||
});
|
||||
CouponApi.getUnusedCouponCount().then(res => {
|
||||
CouponApi.getUnusedCouponCount().then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.numData.unusedCouponCount = res.data;
|
||||
}
|
||||
|
|
@ -143,20 +143,22 @@ const user = defineStore({
|
|||
}
|
||||
|
||||
// 绑定推广员
|
||||
$share.bindBrokerageUser()
|
||||
$share.bindBrokerageUser();
|
||||
},
|
||||
|
||||
// 登出系统
|
||||
async logout() {
|
||||
this.resetUserData();
|
||||
return !this.isLogin;
|
||||
}
|
||||
},
|
||||
},
|
||||
persist: {
|
||||
enabled: true,
|
||||
strategies: [{
|
||||
key: 'user-store',
|
||||
}]
|
||||
strategies: [
|
||||
{
|
||||
key: 'user-store',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@
|
|||
|
||||
import { reactive, computed } from 'vue';
|
||||
import sheep from '@/sheep';
|
||||
import { clone } from 'lodash';
|
||||
import { clone } from 'lodash-es';
|
||||
|
||||
// 数据
|
||||
const state = reactive({
|
||||
|
|
@ -196,11 +196,11 @@
|
|||
const onPreview = () => {
|
||||
if (!props.isPreview) return;
|
||||
let previewImage = clone(props.list);
|
||||
previewImage.forEach((item,index) => {
|
||||
if(item.type === 'video') {
|
||||
previewImage.forEach((item, index) => {
|
||||
if (item.type === 'video') {
|
||||
previewImage.splice(index, 1);
|
||||
}
|
||||
})
|
||||
});
|
||||
uni.previewImage({
|
||||
urls:
|
||||
previewImage.length < 1
|
||||
|
|
|
|||
|
|
@ -1,3 +1,36 @@
|
|||
// ========== COMMON - 公共模块 ==========
|
||||
|
||||
/**
|
||||
* 与后端Terminal枚举一一对应
|
||||
*/
|
||||
export const TerminalEnum = {
|
||||
UNKNOWN: 0, // 未知, 目的:在无法解析到 terminal 时,使用它
|
||||
WECHAT_MINI_PROGRAM: 10, //微信小程序
|
||||
WECHAT_WAP: 11, // 微信公众号
|
||||
H5: 20, // H5 网页
|
||||
APP: 31, // 手机 App
|
||||
};
|
||||
|
||||
/**
|
||||
* 将 uni-app 提供的平台转换为后端所需的 terminal值
|
||||
*
|
||||
* @return 终端
|
||||
*/
|
||||
export const getTerminal = () => {
|
||||
const platformType = uni.getSystemInfoSync().uniPlatform;
|
||||
// 与后端terminal枚举一一对应
|
||||
switch (platformType) {
|
||||
case 'app':
|
||||
return TerminalEnum.APP;
|
||||
case 'web':
|
||||
return TerminalEnum.H5;
|
||||
case 'mp-weixin':
|
||||
return TerminalEnum.WECHAT_MINI_PROGRAM;
|
||||
default:
|
||||
return TerminalEnum.UNKNOWN;
|
||||
}
|
||||
};
|
||||
|
||||
// ========== MALL - 营销模块 ==========
|
||||
|
||||
import dayjs from "dayjs";
|
||||
|
|
|
|||
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