Merge remote-tracking branch 'upload/master'

pull/100/head
痴货 2024-08-23 09:52:07 +08:00
commit 354a3dc1c8
75 changed files with 4594 additions and 3102 deletions

View File

@ -216,7 +216,7 @@
"h5": { "h5": {
"template": "index.html", "template": "index.html",
"router": { "router": {
"mode": "hash", "mode": "history",
"base": "./" "base": "./"
}, },
"sdkConfigs": { "sdkConfigs": {

View File

@ -90,6 +90,7 @@
"dependencies": { "dependencies": {
"dayjs": "^1.11.7", "dayjs": "^1.11.7",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"luch-request": "^3.0.8", "luch-request": "^3.0.8",
"pinia": "^2.0.33", "pinia": "^2.0.33",
"pinia-plugin-persist-uni": "^1.2.0", "pinia-plugin-persist-uni": "^1.2.0",

View File

@ -307,6 +307,18 @@
"title": "编辑地址" "title": "编辑地址"
} }
}, },
{
"path": "goods_details_store/index",
"style": {
"navigationBarTitleText": "自提门店"
},
"meta": {
"auth": true,
"sync": true,
"title": "地址管理",
"group": "用户中心"
}
},
{ {
"path": "wallet/money", "path": "wallet/money",
"style": { "style": {

View File

@ -1,6 +1,11 @@
<!-- 拼团订单的详情 --> <!-- 拼团订单的详情 -->
<template> <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.loading"></view>
<view v-if="state.data && !state.loading"> <view v-if="state.data && !state.loading">
<!-- 团长信息 + 活动信息 --> <!-- 团长信息 + 活动信息 -->
@ -22,7 +27,7 @@
priceColor="#E1212B" priceColor="#E1212B"
@tap=" @tap="
sheep.$router.go('/pages/goods/groupon', { sheep.$router.go('/pages/goods/groupon', {
id: state.data.headRecord.activityId id: state.data.headRecord.activityId,
}) })
" "
:style="[{ top: Number(statusBarHeight + 108) + 'rpx' }]" :style="[{ top: Number(statusBarHeight + 108) + 'rpx' }]"
@ -71,7 +76,9 @@
</view> </view>
<view class="countdown-title ss-flex" v-else> <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="ss-flex countdown-time">
<view class="countdown-h ss-flex ss-row-center">{{ endTime.h }}</view> <view class="countdown-h ss-flex ss-row-center">{{ endTime.h }}</view>
@ -109,7 +116,11 @@
</view> </view>
</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 <image
:src="sheep.$url.static('/static/img/shop/avatar/unknown.png')" :src="sheep.$url.static('/static/img/shop/avatar/unknown.png')"
class="avatar-img" class="avatar-img"
@ -154,11 +165,7 @@
</view> </view>
<view v-else class="ss-flex ss-row-center"> <view v-else class="ss-flex ss-row-center">
<view v-if="state.data.orderId"> <view v-if="state.data.orderId">
<button <button class="ss-reset-button join-btn" :disabled="endTime.ms <= 0" @tap="onShare">
class="ss-reset-button join-btn"
:disabled="endTime.ms <= 0"
@tap="onShare"
>
邀请好友来拼团 邀请好友来拼团
</button> </button>
</view> </view>
@ -174,11 +181,11 @@
</view> </view>
</view> </view>
<!-- TODO 芋艿这里暂时没接入 --> <view v-if="!isEmpty(state.goodsInfo)">
<view v-if="state.data.goods"> <!-- 规格与数量弹框 -->
<s-select-groupon-sku <s-select-groupon-sku
:show="state.showSelectSku" :show="state.showSelectSku"
:goodsInfo="state.data.goods" :goodsInfo="state.goodsInfo"
:grouponAction="state.grouponAction" :grouponAction="state.grouponAction"
:grouponNum="state.grouponNum" :grouponNum="state.grouponNum"
@buy="onBuy" @buy="onBuy"
@ -186,6 +193,7 @@
@close="state.showSelectSku = false" @close="state.showSelectSku = false"
/> />
</view> </view>
</view> </view>
<s-empty v-if="!state.data && !state.loading" icon="/static/goods-empty.png" /> <s-empty v-if="!state.data && !state.loading" icon="/static/goods-empty.png" />
@ -196,25 +204,28 @@
import { computed, reactive } from 'vue'; import { computed, reactive } from 'vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import { onLoad } from '@dcloudio/uni-app'; 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 { showShareModal } from '@/sheep/hooks/useModal';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash-es';
import CombinationApi from "@/sheep/api/promotion/combination"; 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 headerBg = sheep.$url.css('/static/img/shop/user/withdraw_bg.png');
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2; const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
const state = reactive({ const state = reactive({
data: {}, // data: {}, //
loading: true, goodsId: 0, // ID
grouponAction: 'create', goodsInfo: {}, //
showSelectSku: false, showSelectSku: false, //
grouponNum: 0, selectedSkuPrice: {}, //
number: 0, activity: {}, //
activity: {}, grouponId: 0, // ID
grouponNum: 0, //
grouponAction: 'create', //
combinationHeadId: null, // combinationHeadId: null, //
loading: true,
}); });
// todo
const shareInfo = computed(() => { const shareInfo = computed(() => {
if (isEmpty(state.data)) return {}; if (isEmpty(state.data)) return {};
return sheep.$platform.share.getShareInfo( return sheep.$platform.share.getShareInfo(
@ -224,15 +235,14 @@
desc: state.data.goods?.subtitle, desc: state.data.goods?.subtitle,
params: { params: {
page: '5', page: '5',
query: state.data.id, query: state.data.headRecord.id,
}, },
}, },
{ {
type: 'groupon', // type: 'groupon', //
title: state.data.headRecord.spuName, // title: state.data.headRecord.spuName, //
image: sheep.$url.cdn(state.data.headRecord.picUrl), // image: sheep.$url.cdn(state.data.headRecord.picUrl), //
price: state.data.goods?.price, // price: fen2yuan(state.data.headRecord.combinationPrice), //
original_price: state.data.goods?.original_price, //
}, },
); );
}); });
@ -244,33 +254,33 @@
}); });
} }
// TODO //
function onCreateGroupon() { function onCreateGroupon() {
state.grouponAction = 'create'; state.grouponAction = 'create';
state.grouponId = 0; state.grouponId = 0;
state.showSelectSku = true; state.showSelectSku = true;
} }
// TODO //
function onSkuChange(e) { function onSkuChange(e) {
state.selectedSkuPrice = e; state.selectedSkuPrice = e;
} }
// TODO //
function onJoinGroupon() { function onJoinGroupon() {
state.grouponAction = 'join'; state.grouponAction = 'join';
state.grouponId = state.data.activityId; state.grouponId = state.data.headRecord.activityId;
state.combinationHeadId = state.data.id; state.combinationHeadId = state.data.headRecord.id;
state.grouponNum = state.data.num; state.grouponNum = state.data.headRecord.userSize;
state.showSelectSku = true; state.showSelectSku = true;
} }
// TODO //
function onBuy(sku) { function onBuy(sku) {
sheep.$router.go('/pages/order/confirm', { sheep.$router.go('/pages/order/confirm', {
data: JSON.stringify({ data: JSON.stringify({
order_type: 'goods', order_type: 'goods',
combinationActivityId: state.data.activity.id, combinationActivityId: state.activity.id,
combinationHeadId: state.combinationHeadId, combinationHeadId: state.combinationHeadId,
items: [ items: [
{ {
@ -295,8 +305,29 @@
state.remainNumber = remainNumber > 0 ? remainNumber : 0; 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.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 { } else {
state.data = null; state.data = null;
} }
@ -316,8 +347,7 @@
.recharge-box { .recharge-box {
position: relative; position: relative;
margin-bottom: 120rpx; margin-bottom: 120rpx;
background: v-bind(headerBg) center/750rpx 100% background: v-bind(headerBg) center/750rpx 100% no-repeat,
no-repeat,
linear-gradient(115deg, #f44739 0%, #ff6600 100%); linear-gradient(115deg, #f44739 0%, #ff6600 100%);
border-radius: 0 0 5% 5%; border-radius: 0 0 5% 5%;
height: 100rpx; height: 100rpx;

View File

@ -67,8 +67,8 @@
import { reactive } from 'vue'; import { reactive } from 'vue';
import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app'; import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app';
import sheep from '@/sheep'; import sheep from '@/sheep';
import _ from 'lodash'; import _ from 'lodash-es';
import {formatOrderColor} from "@/sheep/hooks/useGoods"; import { formatOrderColor } from '@/sheep/hooks/useGoods';
import { resetPagination } from '@/sheep/util'; import { resetPagination } from '@/sheep/util';
import CombinationApi from '@/sheep/api/promotion/combination'; import CombinationApi from '@/sheep/api/promotion/combination';
@ -121,7 +121,7 @@
if (code !== 0) { if (code !== 0) {
return; 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.pagination.total = data.total;
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore'; state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
} }

View File

@ -63,7 +63,7 @@
import { reactive } from 'vue'; import { reactive } from 'vue';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import sheep from '@/sheep'; import sheep from '@/sheep';
import _ from 'lodash'; import _ from 'lodash-es';
import RewardActivityApi from '@/sheep/api/promotion/rewardActivity'; import RewardActivityApi from '@/sheep/api/promotion/rewardActivity';
import { formatRewardActivityRule } from '@/sheep/hooks/useGoods'; import { formatRewardActivityRule } from '@/sheep/hooks/useGoods';
import SpuApi from '@/sheep/api/product/spu'; import SpuApi from '@/sheep/api/product/spu';
@ -118,7 +118,7 @@
const { code, data } = await SpuApi.getSpuPage({ const { code, data } = await SpuApi.getSpuPage({
pageNo: state.pagination.pageNo, pageNo: state.pagination.pageNo,
pageSize: state.pagination.pageSize, pageSize: state.pagination.pageSize,
...params ...params,
}); });
if (code !== 0) { if (code !== 0) {
return; return;

View File

@ -32,7 +32,7 @@
<script setup> <script setup>
import { reactive, watch } from 'vue'; import { reactive, watch } from 'vue';
import _ from 'lodash'; import _ from 'lodash-es';
import GoodsItem from './goods.vue'; import GoodsItem from './goods.vue';
import OrderItem from './order.vue'; import OrderItem from './order.vue';
import OrderApi from '@/sheep/api/trade/order'; import OrderApi from '@/sheep/api/trade/order';

View File

@ -8,14 +8,26 @@
<text class="cicon-forward" /> <text class="cicon-forward" />
</view> </view>
</view> </view>
<scroll-view scroll-y="true" @scrolltolower="loadmore" class="scroll-box log-scroll" <scroll-view
scroll-with-animation="true"> scroll-y="true"
@scrolltolower="loadmore"
class="scroll-box log-scroll"
scroll-with-animation="true"
>
<view v-if="state.pagination.list"> <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-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-wrap">
<view class="log-item ss-flex ss-ellipsis-1 ss-col-center"> <view class="log-item ss-flex ss-ellipsis-1 ss-col-center">
<view class="ss-flex 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" /> <image
class="log-img"
:src="sheep.$url.static('/static/img/shop/avatar/notice.png')"
mode="aspectFill"
/>
</view> </view>
<view class="log-text ss-ellipsis-1"> <view class="log-text ss-ellipsis-1">
{{ item.title }} {{ fen2yuan(item.price) }} {{ item.title }} {{ fen2yuan(item.price) }}
@ -27,8 +39,12 @@
</view> </view>
<!-- 加载更多 --> <!-- 加载更多 -->
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" color="#333333" <uni-load-more
@tap="loadmore" /> v-if="state.pagination.total > 0"
:status="state.loadStatus"
color="#333333"
@tap="loadmore"
/>
</scroll-view> </scroll-view>
</view> </view>
</template> </template>
@ -36,7 +52,7 @@
<script setup> <script setup>
import sheep from '@/sheep'; import sheep from '@/sheep';
import { reactive } from 'vue'; import { reactive } from 'vue';
import _ from 'lodash'; import _ from 'lodash-es';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import BrokerageApi from '@/sheep/api/trade/brokerage'; import BrokerageApi from '@/sheep/api/trade/brokerage';
import { fen2yuan } from '../../../sheep/hooks/useGoods'; import { fen2yuan } from '../../../sheep/hooks/useGoods';
@ -55,7 +71,7 @@
state.loadStatus = 'loading'; state.loadStatus = 'loading';
const { code, data } = await BrokerageApi.getBrokerageRecordPage({ const { code, data } = await BrokerageApi.getBrokerageRecordPage({
pageNo: state.pagination.pageNo, pageNo: state.pagination.pageNo,
pageSize: state.pagination.pageSize pageSize: state.pagination.pageSize,
}); });
if (code !== 0) { if (code !== 0) {
return; return;

View File

@ -14,12 +14,18 @@
> >
<template #rightBottom> <template #rightBottom>
<view class="ss-flex ss-row-between"> <view class="ss-flex ss-row-between">
<view class="commission-num" v-if="item.brokerageMinPrice === undefined"></view> <view class="commission-num" v-if="item.brokerageMinPrice === undefined"
<view class="commission-num" v-else-if="item.brokerageMinPrice === item.brokerageMaxPrice"> >预计佣金计算中</view
>
<view
class="commission-num"
v-else-if="item.brokerageMinPrice === item.brokerageMaxPrice"
>
预计佣金{{ fen2yuan(item.brokerageMinPrice) }} 预计佣金{{ fen2yuan(item.brokerageMinPrice) }}
</view> </view>
<view class="commission-num" v-else> <view class="commission-num" v-else>
预计佣金{{ fen2yuan(item.brokerageMinPrice) }} ~ {{ fen2yuan(item.brokerageMaxPrice) }} 预计佣金{{ fen2yuan(item.brokerageMinPrice) }} ~
{{ fen2yuan(item.brokerageMaxPrice) }}
</view> </view>
<button <button
class="ss-reset-button share-btn ui-BG-Main-Gradient" class="ss-reset-button share-btn ui-BG-Main-Gradient"
@ -53,7 +59,7 @@
import $share from '@/sheep/platform/share'; import $share from '@/sheep/platform/share';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import { reactive } from 'vue'; import { reactive } from 'vue';
import _ from 'lodash'; import _ from 'lodash-es';
import { showShareModal } from '@/sheep/hooks/useModal'; import { showShareModal } from '@/sheep/hooks/useModal';
import SpuApi from '@/sheep/api/product/spu'; import SpuApi from '@/sheep/api/product/spu';
import BrokerageApi from '@/sheep/api/trade/brokerage'; import BrokerageApi from '@/sheep/api/trade/brokerage';

View File

@ -41,10 +41,7 @@
<view class="no-box ss-flex ss-col-center ss-row-between"> <view class="no-box ss-flex ss-col-center ss-row-between">
<text class="order-code">订单编号{{ item.bizId }}</text> <text class="order-code">订单编号{{ item.bizId }}</text>
<text class="order-state"> <text class="order-state">
{{ {{ item.status === 0 ? '待结算' : item.status === 1 ? '已结算' : '已取消' }}
item.status === 0 ? '待结算'
: item.status === 1 ? '已结算' : '已取消'
}}
( 佣金 {{ fen2yuan(item.price) }} ) ( 佣金 {{ fen2yuan(item.price) }} )
</text> </text>
</view> </view>
@ -77,7 +74,7 @@
import sheep from '@/sheep'; import sheep from '@/sheep';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import { reactive } from 'vue'; import { reactive } from 'vue';
import _ from 'lodash'; import _ from 'lodash-es';
import { onPageScroll } from '@dcloudio/uni-app'; import { onPageScroll } from '@dcloudio/uni-app';
import { resetPagination } from '@/sheep/util'; import { resetPagination } from '@/sheep/util';
import BrokerageApi from '@/sheep/api/trade/brokerage'; import BrokerageApi from '@/sheep/api/trade/brokerage';

View File

@ -235,7 +235,7 @@
import sheep from '@/sheep'; import sheep from '@/sheep';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import { computed, reactive, ref } from 'vue'; import { computed, reactive, ref } from 'vue';
import _ from 'lodash'; import _ from 'lodash-es';
import { onPageScroll } from '@dcloudio/uni-app'; import { onPageScroll } from '@dcloudio/uni-app';
import BrokerageApi from '@/sheep/api/trade/brokerage'; import BrokerageApi from '@/sheep/api/trade/brokerage';

View File

@ -6,14 +6,22 @@
<view class="card-box ui-BG-Main ui-Shadow-Main"> <view class="card-box ui-BG-Main ui-Shadow-Main">
<view class="card-head ss-flex ss-col-center"> <view class="card-head ss-flex ss-col-center">
<view class="card-title ss-m-r-10">当前佣金</view> <view class="card-title ss-m-r-10">当前佣金</view>
<view @tap="state.showMoney = !state.showMoney" class="ss-eye-icon" <view
:class="state.showMoney ? 'cicon-eye' : 'cicon-eye-off'" /> @tap="state.showMoney = !state.showMoney"
class="ss-eye-icon"
:class="state.showMoney ? 'cicon-eye' : 'cicon-eye-off'"
/>
</view> </view>
<view class="ss-flex ss-row-between ss-col-center ss-m-t-30"> <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="money-num">{{
state.showMoney ? fen2yuan(state.summary.withdrawPrice || 0) : '*****'
}}</view>
<view class="ss-flex"> <view class="ss-flex">
<view class="ss-m-r-20"> <view class="ss-m-r-20">
<button class="ss-reset-button withdraw-btn" @tap="sheep.$router.go('/pages/commission/withdraw')"> <button
class="ss-reset-button withdraw-btn"
@tap="sheep.$router.go('/pages/commission/withdraw')"
>
提现 提现
</button> </button>
</view> </view>
@ -43,7 +51,12 @@
<su-sticky> <su-sticky>
<!-- 统计 --> <!-- 统计 -->
<view class="filter-box ss-p-x-30 ss-flex ss-col-center ss-row-between"> <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"> <uni-datetime-picker
v-model="state.date"
type="daterange"
@change="onChangeTime"
:end="state.today"
>
<button class="ss-reset-button date-btn"> <button class="ss-reset-button date-btn">
<text>{{ dateFilterText }}</text> <text>{{ dateFilterText }}</text>
<text class="cicon-drop-down ss-seldate-icon" /> <text class="cicon-drop-down ss-seldate-icon" />
@ -56,21 +69,44 @@
<!-- <view>总支出{{ (-state.pagination.expense).toFixed(2) }}</view> --> <!-- <view>总支出{{ (-state.pagination.expense).toFixed(2) }}</view> -->
</view> </view>
</view> </view>
<su-tabs :list="tabMaps" @change="onChangeTab" :scrollable="false" :current="state.currentTab" /> <su-tabs
:list="tabMaps"
@change="onChangeTab"
:scrollable="false"
:current="state.currentTab"
/>
</su-sticky> </su-sticky>
<s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据"></s-empty> <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> <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="ss-p-x-20 ss-p-y-30">
<view class="model-title ss-m-b-30 ss-m-l-20">转余额</view> <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="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="input-box ss-flex ss-col-center border-bottom ss-m-b-70 ss-m-x-20">
<view class="unit"></view> <view class="unit"></view>
<uni-easyinput :inputBorder="false" class="ss-flex-1 ss-p-l-10" v-model="state.price" type="number" <uni-easyinput
placeholder="请输入金额" /> :inputBorder="false"
class="ss-flex-1 ss-p-l-10"
v-model="state.price"
type="number"
placeholder="请输入金额"
/>
</view> </view>
<button class="ss-reset-button model-btn ui-BG-Main-Gradient ui-Shadow-Main" @tap="onConfirm"> <button
class="ss-reset-button model-btn ui-BG-Main-Gradient ui-Shadow-Main"
@tap="onConfirm"
>
确定 确定
</button> </button>
</view> </view>
@ -78,7 +114,11 @@
<!-- 钱包记录 --> <!-- 钱包记录 -->
<view v-if="state.pagination.total > 0"> <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="wallet-list ss-flex border-bottom"
v-for="item in state.pagination.list"
:key="item.id"
>
<view class="list-content"> <view class="list-content">
<view class="title-box ss-flex ss-row-between ss-m-b-20"> <view class="title-box ss-flex ss-row-between ss-m-b-20">
<text class="title ss-line-1">{{ item.title }}</text> <text class="title ss-line-1">{{ item.title }}</text>
@ -87,15 +127,21 @@
<text v-else class="minus">{{ fen2yuan(item.price) }}</text> <text v-else class="minus">{{ fen2yuan(item.price) }}</text>
</view> </view>
</view> </view>
<text class="time">{{ sheep.$helper.timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</text> <text class="time">{{
sheep.$helper.timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss')
}}</text>
</view> </view>
</view> </view>
</view> </view>
<!-- <u-gap></u-gap> --> <!-- <u-gap></u-gap> -->
<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: '上拉加载更多', contentdown: '上拉加载更多',
}" /> }"
/>
</s-layout> </s-layout>
</template> </template>
@ -104,7 +150,7 @@
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import sheep from '@/sheep'; import sheep from '@/sheep';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import _ from 'lodash'; import _ from 'lodash-es';
import BrokerageApi from '@/sheep/api/trade/brokerage'; import BrokerageApi from '@/sheep/api/trade/brokerage';
import { fen2yuan } from '@/sheep/hooks/useGoods'; import { fen2yuan } from '@/sheep/hooks/useGoods';
import { resetPagination } from '@/sheep/util'; import { resetPagination } from '@/sheep/util';
@ -130,14 +176,15 @@
showModal: false, showModal: false,
}); });
const tabMaps = [{ const tabMaps = [
{
name: '分佣', name: '分佣',
value: '1', // BrokerageRecordBizTypeEnum.ORDER value: '1', // BrokerageRecordBizTypeEnum.ORDER
}, },
{ {
name: '提现', name: '提现',
value: '2', // BrokerageRecordBizTypeEnum.WITHDRAW value: '2', // BrokerageRecordBizTypeEnum.WITHDRAW
} },
]; ];
const dateFilterText = computed(() => { const dateFilterText = computed(() => {
@ -199,10 +246,10 @@
state.showModal = false; state.showModal = false;
await getAgentInfo(); await getAgentInfo();
onChangeTab({ onChangeTab({
index: 1 index: 1,
}); });
} }
} },
}); });
} }
@ -217,7 +264,8 @@
onLoad(async (options) => { onLoad(async (options) => {
state.today = dayjs().format('YYYY-MM-DD'); state.today = dayjs().format('YYYY-MM-DD');
state.date = [state.today, state.today]; state.date = [state.today, state.today];
if (options.type === 2) { // tab if (options.type === 2) {
// tab
state.currentTab = 1; state.currentTab = 1;
} }
getLogList(); getLogList();

View File

@ -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="title ss-m-t-50 ss-m-b-20 ss-m-x-20">{{ state.coupon.name }}</view>
<view class="subtitle ss-m-b-50"> <view class="subtitle ss-m-b-50">
{{ fen2yuan(state.coupon.usePrice) }} {{ fen2yuan(state.coupon.usePrice) }}
{{ state.coupon.discountType === 1 {{
state.coupon.discountType === 1
? '减 ' + fen2yuan(state.coupon.discountPrice) + ' 元' ? '减 ' + fen2yuan(state.coupon.discountPrice) + ' 元'
: '打 ' + state.coupon.discountPercent / 10.0 + ' 折' }} : '打 ' + state.coupon.discountPercent / 10.0 + ' 折'
}}
</view> </view>
<button <button
class="ss-reset-button ss-m-b-30" 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' // 使 ? 'use-btn' // 使
: 'disable-btn' : 'disable-btn'
" "
@ -31,7 +34,13 @@
> >
<text v-if="state.id > 0">{{ state.coupon.canTake ? '' : '' }}</text> <text v-if="state.id > 0">{{ state.coupon.canTake ? '' : '' }}</text>
<text v-else> <text v-else>
{{ state.coupon.status === 1 ? '立即使用' : state.coupon.status === 2 ? '已使用' : '已过期' }} {{
state.coupon.status === 1
? '立即使用'
: state.coupon.status === 2
? '已使用'
: '已过期'
}}
</text> </text>
</button> </button>
<view class="time ss-m-y-30" v-if="state.coupon.validityType === 2"> <view class="time ss-m-y-30" v-if="state.coupon.validityType === 2">
@ -140,7 +149,7 @@
import sheep from '@/sheep'; import sheep from '@/sheep';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import { reactive } from 'vue'; import { reactive } from 'vue';
import _ from 'lodash'; import _ from 'lodash-es';
import CouponApi from '@/sheep/api/promotion/coupon'; import CouponApi from '@/sheep/api/promotion/coupon';
import { fen2yuan } from '@/sheep/hooks/useGoods'; import { fen2yuan } from '@/sheep/hooks/useGoods';
import SpuApi from '@/sheep/api/product/spu'; import SpuApi from '@/sheep/api/product/spu';
@ -176,7 +185,7 @@
const { code, data } = await SpuApi.getSpuPage({ const { code, data } = await SpuApi.getSpuPage({
categoryId: state.categoryId, categoryId: state.categoryId,
pageNo: state.pagination.pageNo, pageNo: state.pagination.pageNo,
pageSize: state.pagination.pageSize pageSize: state.pagination.pageSize,
}); });
if (code !== 0) { if (code !== 0) {
return; return;
@ -197,7 +206,9 @@
// //
async function getCategoryList() { 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) { if (code !== 0) {
return; return;
} }
@ -225,7 +236,9 @@
// //
async function getCouponContent() { async function getCouponContent() {
const { code, data } = state.id > 0 ? await CouponApi.getCouponTemplate(state.id) const { code, data } =
state.id > 0
? await CouponApi.getCouponTemplate(state.id)
: await CouponApi.getCoupon(state.couponId); : await CouponApi.getCoupon(state.couponId);
if (code !== 0) { if (code !== 0) {
return; return;

View File

@ -56,9 +56,14 @@
</view> </view>
</template> </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: '上拉加载更多', contentdown: '上拉加载更多',
}" @tap="loadMore" /> }"
@tap="loadMore"
/>
</s-layout> </s-layout>
</template> </template>
@ -66,7 +71,7 @@
import sheep from '@/sheep'; import sheep from '@/sheep';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import { reactive } from 'vue'; import { reactive } from 'vue';
import _ from 'lodash'; import _ from 'lodash-es';
import { resetPagination } from '@/sheep/util'; import { resetPagination } from '@/sheep/util';
import CouponApi from '@/sheep/api/promotion/coupon'; import CouponApi from '@/sheep/api/promotion/coupon';
@ -78,7 +83,7 @@
list: [], list: [],
total: 0, total: 0,
pageNo: 1, pageNo: 1,
pageSize: 5 pageSize: 5,
}, },
loadStatus: '', loadStatus: '',
}); });
@ -106,7 +111,7 @@
function onTabsChange(e) { function onTabsChange(e) {
state.currentTab = e.index; state.currentTab = e.index;
state.type = e.value; state.type = e.value;
resetPagination(state.pagination) resetPagination(state.pagination);
if (state.currentTab === 0) { if (state.currentTab === 0) {
getData(); getData();
} else { } else {
@ -135,7 +140,7 @@
const { data, code } = await CouponApi.getCouponPage({ const { data, code } = await CouponApi.getCouponPage({
pageNo: state.pagination.pageNo, pageNo: state.pagination.pageNo,
pageSize: state.pagination.pageSize, pageSize: state.pagination.pageSize,
status: state.type status: state.type,
}); });
if (code !== 0) { if (code !== 0) {
return; return;

View File

@ -30,7 +30,7 @@
import CommentApi from '@/sheep/api/product/comment'; import CommentApi from '@/sheep/api/product/comment';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import { reactive } from 'vue'; import { reactive } from 'vue';
import _ from 'lodash'; import _ from 'lodash-es';
import commentItem from '../components/detail/comment-item.vue'; import commentItem from '../components/detail/comment-item.vue';
const state = reactive({ const state = reactive({

View File

@ -7,7 +7,11 @@
<detailSkeleton v-if="state.skeletonLoading" /> <detailSkeleton v-if="state.skeletonLoading" />
<!-- 下架/售罄提醒 --> <!-- 下架/售罄提醒 -->
<s-empty <s-empty
v-else-if="state.goodsInfo === null || state.activity.status !== 0 || state.activity.endTime < new Date().getTime()" v-else-if="
state.goodsInfo === null ||
state.activity.status !== 0 ||
state.activity.endTime < new Date().getTime()
"
text="活动不存在或已结束" text="活动不存在或已结束"
icon="/static/soldout-empty.png" icon="/static/soldout-empty.png"
showAction showAction
@ -47,10 +51,7 @@
</view> </view>
</view> </view>
<view class="ss-flex ss-row-between"> <view class="ss-flex ss-row-between">
<view <view class="origin-price ss-flex ss-col-center" v-if="state.goodsInfo.price">
class="origin-price ss-flex ss-col-center"
v-if="state.goodsInfo.price"
>
单买价 单买价
<view class="origin-price-text"> <view class="origin-price-text">
{{ fen2yuan(state.goodsInfo.price) }} {{ fen2yuan(state.goodsInfo.price) }}
@ -79,7 +80,7 @@
<!-- 功能卡片 --> <!-- 功能卡片 -->
<view class="detail-cell-card detail-card ss-flex-col"> <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> </view>
<!-- 参团列表 --> <!-- 参团列表 -->
@ -89,6 +90,7 @@
<s-select-groupon-sku <s-select-groupon-sku
:show="state.showSelectSku" :show="state.showSelectSku"
:goodsInfo="state.goodsInfo" :goodsInfo="state.goodsInfo"
:selectedSku="state.selectedSku"
:grouponAction="state.grouponAction" :grouponAction="state.grouponAction"
:grouponNum="state.grouponNum" :grouponNum="state.grouponNum"
@buy="onBuy" @buy="onBuy"
@ -123,7 +125,9 @@
" "
:disabled="state.goodsInfo.stock === 0 || state.activity.status !== 0" :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-if="state.activity.startTime > new Date().getTime()"></view>
<view v-else-if="state.activity.endTime <= new Date().getTime()">已结束</view> <view v-else-if="state.activity.endTime <= new Date().getTime()">已结束</view>
<view v-else> <view v-else>
@ -141,7 +145,7 @@
import { reactive, computed } from 'vue'; import { reactive, computed } from 'vue';
import { onLoad, onPageScroll } from '@dcloudio/uni-app'; import { onLoad, onPageScroll } from '@dcloudio/uni-app';
import sheep from '@/sheep'; import sheep from '@/sheep';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash-es';
import detailNavbar from './components/detail/detail-navbar.vue'; import detailNavbar from './components/detail/detail-navbar.vue';
import detailCellSku from './components/detail/detail-cell-sku.vue'; import detailCellSku from './components/detail/detail-cell-sku.vue';
import detailTabbar from './components/detail/detail-tabbar.vue'; import detailTabbar from './components/detail/detail-tabbar.vue';
@ -150,14 +154,12 @@
import detailContentCard from './components/detail/detail-content-card.vue'; import detailContentCard from './components/detail/detail-content-card.vue';
import grouponCardList from './components/groupon/groupon-card-list.vue'; import grouponCardList from './components/groupon/groupon-card-list.vue';
import { useDurationTime, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods'; import { useDurationTime, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods';
import CombinationApi from "@/sheep/api/promotion/combination"; import CombinationApi from '@/sheep/api/promotion/combination';
import SpuApi from "@/sheep/api/product/spu"; import SpuApi from '@/sheep/api/product/spu';
const headerBg = sheep.$url.css('/static/img/shop/goods/groupon-bg.png'); 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 btnBg = sheep.$url.css('/static/img/shop/goods/groupon-btn.png');
const disabledBtnBg = sheep.$url.css( const disabledBtnBg = sheep.$url.css('/static/img/shop/goods/activity-btn-disabled.png');
'/static/img/shop/goods/activity-btn-disabled.png',
);
const grouponBg = sheep.$url.css('/static/img/shop/goods/groupon-tip-bg.png'); const grouponBg = sheep.$url.css('/static/img/shop/goods/groupon-tip-bg.png');
onPageScroll(() => {}); onPageScroll(() => {});
@ -167,7 +169,7 @@
goodsInfo: {}, // goodsInfo: {}, //
goodsSwiper: [], // goodsSwiper: [], //
showSelectSku: false, // showSelectSku: false, //
selectedSkuPrice: {}, // selectedSku: {}, //
activity: {}, // activity: {}, //
grouponId: 0, // ID grouponId: 0, // ID
grouponNum: 0, // grouponNum: 0, //
@ -182,7 +184,7 @@
// //
function onSkuChange(e) { function onSkuChange(e) {
state.selectedSkuPrice = e; state.selectedSku = e;
} }
function onSkuClose() { function onSkuClose() {
@ -198,6 +200,7 @@
/** /**
* 去参团 * 去参团
*
* @param record 团长的团购记录 * @param record 团长的团购记录
*/ */
function onJoinGroupon(record) { function onJoinGroupon(record) {
@ -226,7 +229,6 @@
} }
// //
// TODO @
const shareInfo = computed(() => { const shareInfo = computed(() => {
if (isEmpty(state.activity)) return {}; if (isEmpty(state.activity)) return {};
return sheep.$platform.share.getShareInfo( return sheep.$platform.share.getShareInfo(
@ -261,9 +263,21 @@
// //
const { data: spu } = await SpuApi.getSpuDetail(activity.spuId); const { data: spu } = await SpuApi.getSpuDetail(activity.spuId);
state.goodsId = spu.id; state.goodsId = spu.id;
activity.products.forEach(product => { //
activity.products.forEach((product) => {
spu.price = Math.min(spu.price, product.combinationPrice); // SPU 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; state.skeletonLoading = false;
if (code === 0) { if (code === 0) {
@ -475,8 +489,7 @@
} }
.groupon-box { .groupon-box {
background: v-bind(grouponBg) background: v-bind(grouponBg) no-repeat;
no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
} }

View File

@ -113,7 +113,7 @@
import detailCommentCard from './components/detail/detail-comment-card.vue'; import detailCommentCard from './components/detail/detail-comment-card.vue';
import detailContentCard from './components/detail/detail-content-card.vue'; import detailContentCard from './components/detail/detail-content-card.vue';
import detailActivityTip from './components/detail/detail-activity-tip.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'; import SpuApi from '@/sheep/api/product/spu';
onPageScroll(() => {}); onPageScroll(() => {});
@ -156,11 +156,9 @@
data: JSON.stringify({ data: JSON.stringify({
items: [{ items: [{
skuId: e.id, skuId: e.id,
count: e.goods_num count: e.goods_num,
}], categoryId: state.goodsInfo.categoryId
// TODO 2 }]
deliveryType: 1,
pointStatus: false,
}), }),
}); });
} }

View File

@ -1,12 +1,22 @@
<template> <template>
<s-layout navbar="normal" :leftWidth="0" :rightWidth="0" tools="search" :defaultSearch="state.keyword" <s-layout
@search="onSearch"> navbar="normal"
:leftWidth="0"
:rightWidth="0"
tools="search"
:defaultSearch="state.keyword"
@search="onSearch"
>
<!-- 筛选 --> <!-- 筛选 -->
<su-sticky bgColor="#fff"> <su-sticky bgColor="#fff">
<view class="ss-flex"> <view class="ss-flex">
<view class="ss-flex-1"> <view class="ss-flex-1">
<su-tabs :list="state.tabList" :scrollable="false" @change="onTabsChange" <su-tabs
:current="state.currentTab" /> :list="state.tabList"
:scrollable="false"
@change="onTabsChange"
:current="state.currentTab"
/>
</view> </view>
<view class="list-icon" @tap="state.iconStatus = !state.iconStatus"> <view class="list-icon" @tap="state.iconStatus = !state.iconStatus">
<text v-if="state.iconStatus" class="sicon-goods-list" /> <text v-if="state.iconStatus" class="sicon-goods-list" />
@ -16,12 +26,23 @@
</su-sticky> </su-sticky>
<!-- 弹窗 --> <!-- 弹窗 -->
<su-popup :show="state.showFilter" type="top" round="10" :space="sys_navBar + 38" backgroundColor="#F6F6F6" <su-popup
:zIndex="10" @close="state.showFilter = false"> :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-list-box">
<view class="filter-item" v-for="(item, index) in state.tabList[state.currentTab].list" <view
:key="item.value" :class="[{ 'filter-item-active': index === state.curFilter }]" class="filter-item"
@tap="onFilterItem(index)"> 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 }} {{ item.label }}
</view> </view>
</view> </view>
@ -29,7 +50,11 @@
<!-- 情况一单列布局 --> <!-- 情况一单列布局 -->
<view v-if="state.iconStatus && state.pagination.total > 0" class="goods-list ss-m-t-20"> <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"> <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 <s-goods-column
class="" class=""
size="lg" size="lg"
@ -41,8 +66,10 @@
</view> </view>
</view> </view>
<!-- 情况二双列布局 --> <!-- 情况二双列布局 -->
<view v-if="!state.iconStatus && state.pagination.total > 0" <view
class="ss-flex ss-flex-wrap ss-p-x-20 ss-m-t-20 ss-col-top"> 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="goods-list-box">
<view class="left-list" v-for="item in state.leftGoodsList" :key="item.id"> <view class="left-list" v-for="item in state.leftGoodsList" :key="item.id">
<s-goods-column <s-goods-column
@ -78,9 +105,14 @@
</view> </view>
</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: '上拉加载更多', contentdown: '上拉加载更多',
}" @tap="loadMore" /> }"
@tap="loadMore"
/>
<s-empty v-if="state.pagination.total === 0" icon="/static/soldout-empty.png" text="暂无商品" /> <s-empty v-if="state.pagination.total === 0" icon="/static/soldout-empty.png" text="暂无商品" />
</s-layout> </s-layout>
</template> </template>
@ -89,7 +121,7 @@
import { reactive } from 'vue'; import { reactive } from 'vue';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import sheep from '@/sheep'; import sheep from '@/sheep';
import _ from 'lodash'; import _ from 'lodash-es';
import { resetPagination } from '@/sheep/util'; import { resetPagination } from '@/sheep/util';
import SpuApi from '@/sheep/api/product/spu'; import SpuApi from '@/sheep/api/product/spu';
@ -111,10 +143,12 @@
iconStatus: false, // true - false - iconStatus: false, // true - false -
keyword: '', keyword: '',
categoryId: 0, categoryId: 0,
tabList: [{ tabList: [
{
name: '综合推荐', name: '综合推荐',
list: [{ list: [
label: '综合推荐' {
label: '综合推荐',
}, },
{ {
label: '价格升序', label: '价格升序',
@ -131,12 +165,12 @@
{ {
name: '销量', name: '销量',
sort: 'salesCount', sort: 'salesCount',
order: false order: false,
}, },
{ {
name: '新品优先', name: '新品优先',
value: 'createTime', value: 'createTime',
order: false order: false,
}, },
], ],
loadStatus: '', loadStatus: '',
@ -211,8 +245,10 @@
const onFilterItem = (val) => { const onFilterItem = (val) => {
// //
// tabList[0] list // tabList[0] list
if (state.currentSort === state.tabList[0].list[val].sort if (
&& state.currentOrder === state.tabList[0].list[val].order) { state.currentSort === state.tabList[0].list[val].sort &&
state.currentOrder === state.tabList[0].list[val].order
) {
state.showFilter = false; state.showFilter = false;
return; return;
} }
@ -226,7 +262,7 @@
// + // +
emptyList(); emptyList();
getList(); getList();
} };
async function getList() { async function getList() {
state.loadStatus = 'loading'; state.loadStatus = 'loading';
@ -241,7 +277,7 @@
if (code !== 0) { if (code !== 0) {
return; 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.pagination.total = data.total;
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore'; state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
mountMasonry(); mountMasonry();

View File

@ -63,16 +63,13 @@
<detail-progress :percent="state.percent" /> <detail-progress :percent="state.percent" />
</view> </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 class="subtitle-text ss-line-1">{{ state.goodsInfo.introduction }}</view>
</view> </view>
<!-- 功能卡片 --> <!-- 功能卡片 -->
<view class="detail-cell-card detail-card ss-flex-col"> <view class="detail-cell-card detail-card ss-flex-col">
<detail-cell-sku <detail-cell-sku :sku="state.selectedSku" @tap="state.showSelectSku = true" />
:sku="state.selectedSku"
@tap="state.showSelectSku = true"
/>
</view> </view>
<!-- 规格与数量弹框 --> <!-- 规格与数量弹框 -->
<s-select-seckill-sku <s-select-seckill-sku
@ -107,7 +104,9 @@
<button v-else class="ss-reset-button origin-price-btn ss-flex-col"> <button v-else class="ss-reset-button origin-price-btn ss-flex-col">
<view <view
class="no-original" class="no-original"
:class="state.goodsInfo.stock === 0 || timeStatusEnum !== TimeStatusEnum.STARTED ? '' : ''" :class="
state.goodsInfo.stock === 0 || timeStatusEnum !== TimeStatusEnum.STARTED ? '' : ''
"
> >
秒杀价 秒杀价
</view> </view>
@ -136,10 +135,10 @@
</template> </template>
<script setup> <script setup>
import {reactive, computed, ref} from 'vue'; import { reactive, computed, ref, unref } from 'vue';
import { onLoad, onPageScroll } from '@dcloudio/uni-app'; import { onLoad, onPageScroll } from '@dcloudio/uni-app';
import sheep from '@/sheep'; import sheep from '@/sheep';
import {isEmpty, min} from 'lodash'; import { isEmpty, min } from 'lodash-es';
import { useDurationTime, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods'; import { useDurationTime, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods';
import detailNavbar from './components/detail/detail-navbar.vue'; import detailNavbar from './components/detail/detail-navbar.vue';
import detailCellSku from './components/detail/detail-cell-sku.vue'; import detailCellSku from './components/detail/detail-cell-sku.vue';
@ -148,15 +147,13 @@
import detailCommentCard from './components/detail/detail-comment-card.vue'; import detailCommentCard from './components/detail/detail-comment-card.vue';
import detailContentCard from './components/detail/detail-content-card.vue'; import detailContentCard from './components/detail/detail-content-card.vue';
import detailProgress from './components/detail/detail-progress.vue'; import detailProgress from './components/detail/detail-progress.vue';
import SeckillApi from "@/sheep/api/promotion/seckill"; import SeckillApi from '@/sheep/api/promotion/seckill';
import SpuApi from "@/sheep/api/product/spu"; import SpuApi from '@/sheep/api/product/spu';
import {getTimeStatusEnum, TimeStatusEnum} from "@/sheep/util/const"; import { getTimeStatusEnum, TimeStatusEnum } from '@/sheep/util/const';
const headerBg = sheep.$url.css('/static/img/shop/goods/seckill-bg.png'); 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 btnBg = sheep.$url.css('/static/img/shop/goods/seckill-btn.png');
const disabledBtnBg = sheep.$url.css( const disabledBtnBg = sheep.$url.css('/static/img/shop/goods/activity-btn-disabled.png');
'/static/img/shop/goods/activity-btn-disabled.png',
);
const seckillBg = sheep.$url.css('/static/img/shop/goods/seckill-tip-bg.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'); const grouponBg = sheep.$url.css('/static/img/shop/goods/groupon-tip-bg.png');
@ -199,9 +196,9 @@
}); });
} }
// TODO //
const shareInfo = computed(() => { const shareInfo = computed(() => {
if (isEmpty(activity)) return {}; if (isEmpty(unref(activity))) return {};
return sheep.$platform.share.getShareInfo( return sheep.$platform.share.getShareInfo(
{ {
title: activity.value.name, title: activity.value.name,
@ -221,36 +218,41 @@
); );
}); });
const activity = ref() const activity = ref();
const timeStatusEnum = ref('') const timeStatusEnum = ref('');
// //
const getActivity = async (id) => { const getActivity = async (id) => {
const { data } = await SeckillApi.getSeckillActivity(id) const { data } = await SeckillApi.getSeckillActivity(id);
activity.value = data activity.value = data;
timeStatusEnum.value = getTimeStatusEnum(activity.startTime, activity.endTime) timeStatusEnum.value = getTimeStatusEnum(activity.startTime, activity.endTime);
// //
await getSpu(data.spuId) await getSpu(data.spuId);
} };
//
const getSpu = async (id) => { const getSpu = async (id) => {
const { data } = await SpuApi.getSpuDetail(id) const { data } = await SpuApi.getSpuDetail(id);
// data.activity_type = 'seckill';
data.activity_type = 'seckill' state.goodsInfo = data;
state.goodsInfo = data
// //
state.goodsSwiper = formatGoodsSwiper(state.goodsInfo.sliderPicUrls); 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 => { data.skus.forEach((sku) => {
const product = activity.value.products.find(product => product.skuId === sku.id); const product = activity.value.products.find((product) => product.skuId === sku.id);
if (product) { if (product) {
sku.price = product.seckillPrice; sku.price = product.seckillPrice;
sku.stock = Math.min(sku.stock, product.stock); sku.stock = Math.min(sku.stock, product.stock);
} else { // } else {
//
sku.stock = 0; sku.stock = 0;
} }
// //
@ -264,7 +266,7 @@
}); });
state.skeletonLoading = false; state.skeletonLoading = false;
} };
onLoad((options) => { onLoad((options) => {
// //
@ -274,7 +276,7 @@
} }
// //
getActivity(options.id) getActivity(options.id);
}); });
</script> </script>

View File

@ -107,6 +107,7 @@
skuId: item.sku.id, skuId: item.sku.id,
count: item.count, count: item.count,
cartId: item.id, cartId: item.id,
categoryId: item.spu.categoryId
}) })
goods_list.push({ goods_list.push({
// goods_id: item.goods_id, // goods_id: item.goods_id,
@ -124,12 +125,7 @@
} }
sheep.$router.go('/pages/order/confirm', { sheep.$router.go('/pages/order/confirm', {
data: JSON.stringify({ data: JSON.stringify({
// order_type: 'goods', items
// goods_list,
items,
// from: 'cart',
deliveryType: 1,
pointStatus: false,
}), }),
}); });
} }

View File

@ -63,7 +63,7 @@
import SpuApi from '@/sheep/api/product/spu'; import SpuApi from '@/sheep/api/product/spu';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import { computed, reactive } from 'vue'; import { computed, reactive } from 'vue';
import _ from 'lodash'; import _ from 'lodash-es';
import { handleTree } from '@/sheep/util'; import { handleTree } from '@/sheep/util';
const state = reactive({ const state = reactive({
@ -131,12 +131,13 @@
getGoodsList(); getGoodsList();
} }
onLoad(async () => { onLoad(async (params) => {
await getList(); 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(() => { onReachBottom(() => {

View File

@ -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>

View File

@ -98,11 +98,7 @@
</view> </view>
<view class="modal-content content_box"> <view class="modal-content content_box">
<radio-group @change="onChange"> <radio-group @change="onChange">
<label <label class="radio ss-flex ss-col-center" v-for="item in state.reasonList" :key="item">
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> <view class="ss-flex-1 ss-p-20">{{ item }}</view>
<radio <radio
:value="item" :value="item"
@ -153,9 +149,9 @@
], ],
reasonList: [], // reasonList: [], //
showModal: false, // showModal: false, //
currentValue: '' // currentValue: '', //
}); });
const formData = reactive({ let formData = reactive({
way: '', way: '',
applyReason: '', applyReason: '',
applyDescription: '', applyDescription: '',

View File

@ -3,24 +3,38 @@
<s-layout title="售后详情" :navbar="!isEmpty(state.info) && state.loading ? 'inner' : 'normal'"> <s-layout title="售后详情" :navbar="!isEmpty(state.info) && state.loading ? 'inner' : 'normal'">
<view class="content_box" v-if="!isEmpty(state.info) && state.loading"> <view class="content_box" v-if="!isEmpty(state.info) && state.loading">
<!-- 步骤条 --> <!-- 步骤条 -->
<view class="steps-box ss-flex" :style="[ <view
class="steps-box ss-flex"
:style="[
{ {
marginTop: '-' + Number(statusBarHeight + 88) + 'rpx', marginTop: '-' + Number(statusBarHeight + 88) + 'rpx',
paddingTop: Number(statusBarHeight + 88) + 'rpx', paddingTop: Number(statusBarHeight + 88) + 'rpx',
}, },
]"> ]"
>
<view class="ss-flex"> <view class="ss-flex">
<view class="steps-item" v-for="(item, index) in state.list" :key="index"> <view class="steps-item" v-for="(item, index) in state.list" :key="index">
<view class="ss-flex"> <view class="ss-flex">
<text class="sicon-circleclose" <text
v-if="state.list.length - 1 === index && [61, 62, 63].includes(state.info.status)" /> class="sicon-circleclose"
<text class="sicon-circlecheck" v-else v-if="state.list.length - 1 === index && [61, 62, 63].includes(state.info.status)"
:class="state.active >= index ? 'activity-color' : 'info-color'" /> />
<text
class="sicon-circlecheck"
v-else
:class="state.active >= index ? 'activity-color' : 'info-color'"
/>
<view v-if="state.list.length - 1 !== index" class="line" <view
:class="state.active >= index ? 'activity-bg' : 'info-bg'" /> v-if="state.list.length - 1 !== index"
class="line"
:class="state.active >= index ? 'activity-bg' : 'info-bg'"
/>
</view> </view>
<view class="steps-item-title" :class="state.active >= index ? 'activity-color' : 'info-color'"> <view
class="steps-item-title"
:class="state.active >= index ? 'activity-color' : 'info-color'"
>
{{ item.title }} {{ item.title }}
</view> </view>
</view> </view>
@ -28,8 +42,10 @@
</view> </view>
<!-- 服务状态 --> <!-- 服务状态 -->
<view class="status-box ss-flex ss-col-center ss-row-between ss-m-x-20" <view
@tap="sheep.$router.go('/pages/order/aftersale/log', { id: state.id })"> 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="">
<view class="status-text"> <view class="status-text">
{{ formatAfterSaleStatusDescription(state.info) }} {{ formatAfterSaleStatusDescription(state.info) }}
@ -86,18 +102,31 @@
</view> </view>
<!-- 操作区 --> <!-- 操作区 -->
<s-empty v-if="isEmpty(state.info) && state.loading" icon="/static/order-empty.png" text="暂无该订单售后详情" /> <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)"> <su-fixed bottom placeholder bg="bg-white" v-if="!isEmpty(state.info)">
<view class="foot_box"> <view class="foot_box">
<button class="ss-reset-button btn" v-if="state.info.buttons?.includes('cancel')" <button
@tap="onApply(state.info.id)"> class="ss-reset-button btn"
v-if="state.info.buttons?.includes('cancel')"
@tap="onApply(state.info.id)"
>
取消申请 取消申请
</button> </button>
<button class="ss-reset-button btn" v-if="state.info.buttons?.includes('delivery')" <button
@tap="sheep.$router.go('/pages/order/aftersale/return-delivery', { id: state.info.id })"> 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>
<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> </button>
</view> </view>
@ -109,8 +138,12 @@
import sheep from '@/sheep'; import sheep from '@/sheep';
import { onLoad } from '@dcloudio/uni-app'; import { onLoad } from '@dcloudio/uni-app';
import { reactive } from 'vue'; import { reactive } from 'vue';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash-es';
import { fen2yuan, formatAfterSaleStatusDescription, handleAfterSaleButtons } from '@/sheep/hooks/useGoods'; import {
fen2yuan,
formatAfterSaleStatusDescription,
handleAfterSaleButtons,
} from '@/sheep/hooks/useGoods';
import AfterSaleApi from '@/sheep/api/trade/afterSale'; import AfterSaleApi from '@/sheep/api/trade/afterSale';
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2; const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
@ -120,13 +153,17 @@
info: {}, // info: {}, //
loading: false, loading: false,
active: 0, // list active: 0, // list
list: [{ list: [
{
title: '提交申请', title: '提交申请',
}, { },
{
title: '处理中', title: '处理中',
}, { },
title: '完成' {
}], // title: '完成',
},
], //
}); });
function onApply(id) { function onApply(id) {
@ -175,7 +212,7 @@
onLoad((options) => { onLoad((options) => {
if (!options.id) { if (!options.id) {
sheep.$helper.toast(`缺少订单信息,请检查`); sheep.$helper.toast(`缺少订单信息,请检查`);
return return;
} }
state.id = options.id; state.id = options.id;
getDetail(options.id); getDetail(options.id);

View File

@ -3,13 +3,22 @@
<s-layout title="售后列表"> <s-layout title="售后列表">
<!-- tab --> <!-- tab -->
<su-sticky bgColor="#fff"> <su-sticky bgColor="#fff">
<su-tabs :list="tabMaps" :scrollable="false" @change="onTabsChange" :current="state.currentTab" /> <su-tabs
:list="tabMaps"
:scrollable="false"
@change="onTabsChange"
:current="state.currentTab"
/>
</su-sticky> </su-sticky>
<s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据" /> <s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据" />
<!-- 列表 --> <!-- 列表 -->
<view v-if="state.pagination.total > 0"> <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" <view
@tap="sheep.$router.go('/pages/order/aftersale/detail', { id: order.id })"> 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"> <view class="order-head ss-flex ss-col-center ss-row-between">
<text class="no">服务单号{{ order.no }}</text> <text class="no">服务单号{{ order.no }}</text>
<text class="state">{{ formatAfterSaleStatus(order) }}</text> <text class="state">{{ formatAfterSaleStatus(order) }}</text>
@ -30,15 +39,24 @@
<view class="tool-btn-box ss-flex ss-col-center ss-row-right ss-p-r-20"> <view class="tool-btn-box ss-flex ss-col-center ss-row-right ss-p-r-20">
<!-- TODO 功能缺失填写退货信息 --> <!-- TODO 功能缺失填写退货信息 -->
<view> <view>
<button class="ss-reset-button tool-btn" @tap.stop="onApply(order.id)" <button
v-if="order?.buttons.includes('cancel')">取消申请</button> class="ss-reset-button tool-btn"
@tap.stop="onApply(order.id)"
v-if="order?.buttons.includes('cancel')"
>取消申请</button
>
</view> </view>
</view> </view>
</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: '上拉加载更多', contentdown: '上拉加载更多',
}" @tap="loadMore" /> }"
@tap="loadMore"
/>
</s-layout> </s-layout>
</template> </template>
@ -46,8 +64,12 @@
import sheep from '@/sheep'; import sheep from '@/sheep';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import { reactive } from 'vue'; import { reactive } from 'vue';
import _ from 'lodash'; import _ from 'lodash-es';
import { formatAfterSaleStatus, formatAfterSaleStatusDescription, handleAfterSaleButtons } from '@/sheep/hooks/useGoods'; import {
formatAfterSaleStatus,
formatAfterSaleStatusDescription,
handleAfterSaleButtons,
} from '@/sheep/hooks/useGoods';
import AfterSaleApi from '@/sheep/api/trade/afterSale'; import AfterSaleApi from '@/sheep/api/trade/afterSale';
import { resetPagination } from '@/sheep/util'; import { resetPagination } from '@/sheep/util';
@ -58,13 +80,14 @@
list: [], list: [],
total: 0, total: 0,
pageNo: 1, pageNo: 1,
pageSize: 10 pageSize: 10,
}, },
loadStatus: '', loadStatus: '',
}); });
// TODO // TODO
const tabMaps = [{ const tabMaps = [
{
name: '全部', name: '全部',
value: 'all', value: 'all',
}, },
@ -104,7 +127,7 @@
if (code !== 0) { if (code !== 0) {
return; return;
} }
data.list.forEach(order => handleAfterSaleButtons(order)); data.list.forEach((order) => handleAfterSaleButtons(order));
state.pagination.list = _.concat(state.pagination.list, data.list); state.pagination.list = _.concat(state.pagination.list, data.list);
state.pagination.total = data.total; state.pagination.total = data.total;
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore'; state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
@ -137,7 +160,7 @@
// //
function loadMore() { function loadMore() {
if (state.loadStatus === 'noMore') { if (state.loadStatus === 'noMore') {
return return;
} }
state.pagination.pageNo++; state.pagination.pageNo++;
getOrderList(); getOrderList();

View File

@ -1,13 +1,7 @@
<template> <template>
<s-layout title="确认订单"> <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"> <AddressSelection v-model="addressState" />
<s-address-item :item="state.addressInfo" :hasBorderBottom="false">
<view class="ss-rest-button">
<text class="_icon-forward" />
</view>
</s-address-item>
</view>
<!-- 商品信息 --> <!-- 商品信息 -->
<view class="order-card-box ss-m-b-14"> <view class="order-card-box ss-m-b-14">
@ -46,26 +40,58 @@
</text> </text>
</view> </view>
</view> </view>
<!-- TODO 芋艿接入积分 -->
<view <view
class="order-item ss-flex ss-col-center ss-row-between" 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"> <view class="ss-flex ss-col-center">
{{ state.pointStatus ? '剩余积分' : '当前积分' }}
<image <image
:src="sheep.$url.static('/static/img/shop/goods/score1.svg')" :src="sheep.$url.static('/static/img/shop/goods/score1.svg')"
class="score-img" 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> </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="item-title">运费</view>
<view class="ss-flex ss-col-center"> <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) }} +{{ fen2yuan(state.orderInfo.price.deliveryPrice) }}
</text> </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>
</view> </view>
<!-- 优惠劵只有 type = 0 普通订单非拼团秒杀砍价才可以使用优惠劵 --> <!-- 优惠劵只有 type = 0 普通订单非拼团秒杀砍价才可以使用优惠劵 -->
@ -159,14 +185,13 @@
</template> </template>
<script setup> <script setup>
import { reactive } from 'vue'; import { reactive, ref } from 'vue';
import { onLoad } from '@dcloudio/uni-app'; import { onLoad } from '@dcloudio/uni-app';
import AddressSelection from '@/pages/order/addressSelection.vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import { isEmpty } from 'lodash';
import OrderApi from '@/sheep/api/trade/order'; import OrderApi from '@/sheep/api/trade/order';
import CouponApi from '@/sheep/api/promotion/coupon'; import CouponApi from '@/sheep/api/promotion/coupon';
import { fen2yuan } from '@/sheep/hooks/useGoods'; import { fen2yuan } from '@/sheep/hooks/useGoods';
import { WxaSubscribeTemplate } from '@/sheep/util/const';
const state = reactive({ const state = reactive({
orderPayload: {}, orderPayload: {},
@ -174,27 +199,30 @@
items: [], // items: [], //
price: {}, // price: {}, //
}, },
addressInfo: {}, //
showCoupon: false, // showCoupon: false, //
couponInfo: [], // couponInfo: [], //
showDiscount: false, // showDiscount: false, //
// ========== ==========
pointStatus: false, //使
}); });
// const addressState = ref({
function onSelectAddress() { addressInfo: {}, //
uni.$once('SELECT_ADDRESS', (e) => { deliveryType: 1, // 1 - 2 -
changeConsignee(e.addressInfo); isPickUp: true, // TODO puhui999:
pickUpInfo: {}, //
receiverName: '', //
receiverMobile: '', //
}); });
sheep.$router.go('/pages/user/address/list');
}
// & // ========== ==========
async function changeConsignee(addressInfo = {}) { /**
if (!isEmpty(addressInfo)) { * 使用积分抵扣
state.addressInfo = addressInfo; */
} const changeIntegral = async () => {
state.pointStatus = !state.pointStatus;
await getOrderInfo(); await getOrderInfo();
} };
// //
async function onSelectCoupon(couponId) { async function onSelectCoupon(couponId) {
@ -205,10 +233,28 @@
// //
function onConfirm() { function onConfirm() {
if (!state.addressInfo.id) { if (addressState.value.deliveryType === 1 && !addressState.value.addressInfo.id) {
sheep.$helper.toast('请选择收货地址'); sheep.$helper.toast('请选择收货地址');
return; 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(); submitOrder();
} }
@ -218,12 +264,15 @@
items: state.orderPayload.items, items: state.orderPayload.items,
couponId: state.orderPayload.couponId, couponId: state.orderPayload.couponId,
remark: state.orderPayload.remark, remark: state.orderPayload.remark,
addressId: state.addressInfo.id, deliveryType: addressState.value.deliveryType,
deliveryType: 1, // TODO addressId: addressState.value.addressInfo.id, //
pointStatus: false, // TODO pickUpStoreId: addressState.value.pickUpInfo.id,//
receiverName: addressState.value.receiverName,//
receiverMobile: addressState.value.receiverMobile,//
pointStatus: state.pointStatus,
combinationActivityId: state.orderPayload.combinationActivityId, combinationActivityId: state.orderPayload.combinationActivityId,
combinationHeadId: state.orderPayload.combinationHeadId, combinationHeadId: state.orderPayload.combinationHeadId,
seckillActivityId: state.orderPayload.seckillActivityId seckillActivityId: state.orderPayload.seckillActivityId,
}); });
if (code !== 0) { if (code !== 0) {
return; return;
@ -245,12 +294,15 @@
const { data, code } = await OrderApi.settlementOrder({ const { data, code } = await OrderApi.settlementOrder({
items: state.orderPayload.items, items: state.orderPayload.items,
couponId: state.orderPayload.couponId, couponId: state.orderPayload.couponId,
addressId: state.addressInfo.id, deliveryType: addressState.value.deliveryType,
deliveryType: 1, // TODO addressId: addressState.value.addressInfo.id, //
pointStatus: false, // TODO pickUpStoreId: addressState.value.pickUpInfo.id,//
receiverName: addressState.value.receiverName,//
receiverMobile: addressState.value.receiverMobile,//
pointStatus: state.pointStatus,
combinationActivityId: state.orderPayload.combinationActivityId, combinationActivityId: state.orderPayload.combinationActivityId,
combinationHeadId: state.orderPayload.combinationHeadId, combinationHeadId: state.orderPayload.combinationHeadId,
seckillActivityId: state.orderPayload.seckillActivityId seckillActivityId: state.orderPayload.seckillActivityId,
}); });
if (code !== 0) { if (code !== 0) {
return; return;
@ -258,7 +310,7 @@
state.orderInfo = data; state.orderInfo = data;
// //
if (state.orderInfo.address) { if (state.orderInfo.address) {
state.addressInfo = state.orderInfo.address; addressState.value.addressInfo = state.orderInfo.address;
} }
} }

View File

@ -45,9 +45,9 @@
</image> </image>
<view class="ss-font-30">{{ formatOrderStatus(state.orderInfo) }}</view> <view class="ss-font-30">{{ formatOrderStatus(state.orderInfo) }}</view>
</view> </view>
<view class="ss-font-26 ss-m-x-20 ss-m-b-70">{{ <view class="ss-font-26 ss-m-x-20 ss-m-b-70">
formatOrderStatusDescription(state.orderInfo) {{ formatOrderStatusDescription(state.orderInfo) }}
}}</view> </view>
</view> </view>
<!-- 收货地址 --> <!-- 收货地址 -->
@ -126,6 +126,9 @@
</view> </view>
</view> </view>
<!-- 自提核销 -->
<PickUpVerify :order-info="state.orderInfo" :systemStore="systemStore" ref="pickUpVerifyRef"></PickUpVerify>
<!-- 订单信息 --> <!-- 订单信息 -->
<view class="notice-box"> <view class="notice-box">
<view class="notice-box__content"> <view class="notice-box__content">
@ -167,11 +170,14 @@
<text class="title">运费</text> <text class="title">运费</text>
<text class="detail">{{ fen2yuan(state.orderInfo.deliveryPrice) }}</text> <text class="detail">{{ fen2yuan(state.orderInfo.deliveryPrice) }}</text>
</view> </view>
<!-- TODO 芋艿优惠劵抵扣积分抵扣 -->
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.couponPrice > 0"> <view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.couponPrice > 0">
<text class="title">优惠劵金额</text> <text class="title">优惠劵金额</text>
<text class="detail">-¥{{ fen2yuan(state.orderInfo.couponPrice) }}</text> <text class="detail">-¥{{ fen2yuan(state.orderInfo.couponPrice) }}</text>
</view> </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"> <view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.discountPrice > 0">
<text class="title">活动优惠</text> <text class="title">活动优惠</text>
<text class="detail">¥{{ fen2yuan(state.orderInfo.discountPrice) }}</text> <text class="detail">¥{{ fen2yuan(state.orderInfo.discountPrice) }}</text>
@ -251,8 +257,8 @@
<script setup> <script setup>
import sheep from '@/sheep'; import sheep from '@/sheep';
import { onLoad } from '@dcloudio/uni-app'; import { onLoad } from '@dcloudio/uni-app';
import { reactive } from 'vue'; import { reactive, ref } from 'vue';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash-es';
import { import {
fen2yuan, fen2yuan,
formatOrderStatus, formatOrderStatus,
@ -260,6 +266,8 @@
handleOrderButtons, handleOrderButtons,
} from '@/sheep/hooks/useGoods'; } from '@/sheep/hooks/useGoods';
import OrderApi from '@/sheep/api/trade/order'; 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 statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png'); const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
@ -270,6 +278,9 @@
comeinType: '', // comeinType: '', //
}); });
// ========== ==========
const systemStore = ref({}); //
// //
const onCopy = () => { const onCopy = () => {
sheep.$helper.copyText(state.orderInfo.no); sheep.$helper.copyText(state.orderInfo.no);
@ -313,7 +324,7 @@
}); });
} }
// TODO //
async function onConfirm(orderId, ignore = false) { async function onConfirm(orderId, ignore = false) {
// //
// todo: // todo:
@ -366,15 +377,18 @@
}, },
}); });
} }
// #endif // #endif
// //
function onComment(id) { function onComment(id) {
sheep.$router.go('/pages/goods/comment/add', { sheep.$router.go('/pages/goods/comment/add', {
id id,
}); });
} }
const pickUpVerifyRef = ref();
async function getOrderDetail(id) { async function getOrderDetail(id) {
// //
let res; let res;
@ -389,6 +403,14 @@
if (res.code === 0) { if (res.code === 0) {
state.orderInfo = res.data; state.orderInfo = res.data;
handleOrderButtons(state.orderInfo); 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 { } else {
sheep.$router.back(); sheep.$router.back();
} }

View File

@ -2,12 +2,21 @@
<template> <template>
<s-layout title="我的订单"> <s-layout title="我的订单">
<su-sticky bgColor="#fff"> <su-sticky bgColor="#fff">
<su-tabs :list="tabMaps" :scrollable="false" @change="onTabsChange" :current="state.currentTab" /> <su-tabs
:list="tabMaps"
:scrollable="false"
@change="onTabsChange"
:current="state.currentTab"
/>
</su-sticky> </su-sticky>
<s-empty v-if="state.pagination.total === 0" icon="/static/order-empty.png" text="暂无订单" /> <s-empty v-if="state.pagination.total === 0" icon="/static/order-empty.png" text="暂无订单" />
<view v-if="state.pagination.total > 0"> <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" <view
:key="order.id" @tap="onOrderDetail(order.id)"> 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-card-header ss-flex ss-col-center ss-row-between ss-p-x-20">
<view class="order-no">订单号{{ order.no }}</view> <view class="order-no">订单号{{ order.no }}</view>
<view class="order-state ss-font-26" :class="formatOrderColor(order)"> <view class="order-state ss-font-26" :class="formatOrderColor(order)">
@ -25,45 +34,71 @@
</view> </view>
<view class="pay-box ss-m-t-30 ss-flex ss-row-right ss-p-r-20"> <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="ss-flex ss-col-center">
<view class="discounts-title pay-color"> {{ order.productCount }} 件商品,总金额:</view> <view class="discounts-title pay-color"
<view class="discounts-money pay-color"> > {{ order.productCount }} 件商品,总金额:</view
{{ fen2yuan(order.payPrice) }} >
<view class="discounts-money pay-color"> {{ fen2yuan(order.payPrice) }} </view>
</view> </view>
</view> </view>
</view> <view
<view class="order-card-footer ss-flex ss-col-center ss-p-x-20" class="order-card-footer ss-flex ss-col-center ss-p-x-20"
:class="order.buttons.length > 3 ? 'ss-row-between' : 'ss-row-right'"> :class="order.buttons.length > 3 ? 'ss-row-between' : 'ss-row-right'"
>
<view class="ss-flex ss-col-center"> <view class="ss-flex ss-col-center">
<button v-if="order.buttons.includes('combination')" class="tool-btn ss-reset-button" <button
@tap.stop="onOrderGroupon(order)"> v-if="order.buttons.includes('combination')"
class="tool-btn ss-reset-button"
@tap.stop="onOrderGroupon(order)"
>
拼团详情 拼团详情
</button> </button>
<button v-if="order.buttons.length === 0" class="tool-btn ss-reset-button" <button
@tap.stop="onOrderDetail(order.id)"> v-if="order.buttons.length === 0"
class="tool-btn ss-reset-button"
@tap.stop="onOrderDetail(order.id)"
>
查看详情 查看详情
</button> </button>
<button v-if="order.buttons.includes('confirm')" class="tool-btn ss-reset-button" <button
@tap.stop="onConfirm(order)"> v-if="order.buttons.includes('confirm')"
class="tool-btn ss-reset-button"
@tap.stop="onConfirm(order)"
>
确认收货 确认收货
</button> </button>
<button v-if="order.buttons.includes('express')" class="tool-btn ss-reset-button" <button
@tap.stop="onExpress(order.id)"> v-if="order.buttons.includes('express')"
class="tool-btn ss-reset-button"
@tap.stop="onExpress(order.id)"
>
查看物流 查看物流
</button> </button>
<button v-if="order.buttons.includes('cancel')" class="tool-btn ss-reset-button" <button
@tap.stop="onCancel(order.id)"> v-if="order.buttons.includes('cancel')"
class="tool-btn ss-reset-button"
@tap.stop="onCancel(order.id)"
>
取消订单 取消订单
</button> </button>
<button v-if="order.buttons.includes('comment')" class="tool-btn ss-reset-button" <button
@tap.stop="onComment(order.id)"> v-if="order.buttons.includes('comment')"
class="tool-btn ss-reset-button"
@tap.stop="onComment(order.id)"
>
评价 评价
</button> </button>
<button v-if="order.buttons.includes('delete')" class="delete-btn ss-reset-button" <button
@tap.stop="onDelete(order.id)"> v-if="order.buttons.includes('delete')"
class="delete-btn ss-reset-button"
@tap.stop="onDelete(order.id)"
>
删除订单 删除订单
</button> </button>
<button v-if="order.buttons.includes('pay')" class="tool-btn ss-reset-button ui-BG-Main-Gradient" <button
@tap.stop="onPay(order.payOrderId)"> v-if="order.buttons.includes('pay')"
class="tool-btn ss-reset-button ui-BG-Main-Gradient"
@tap.stop="onPay(order.payOrderId)"
>
继续支付 继续支付
</button> </button>
</view> </view>
@ -72,9 +107,14 @@
</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: '上拉加载更多', contentdown: '上拉加载更多',
}" @tap="loadMore" /> }"
@tap="loadMore"
/>
</s-layout> </s-layout>
</template> </template>
@ -83,13 +123,13 @@
import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app'; import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app';
import { import {
fen2yuan, fen2yuan,
formatOrderColor, formatOrderStatus, handleOrderButtons, formatOrderColor,
formatOrderStatus,
handleOrderButtons,
} from '@/sheep/hooks/useGoods'; } from '@/sheep/hooks/useGoods';
import sheep from '@/sheep'; import sheep from '@/sheep';
import _ from 'lodash'; import _ from 'lodash-es';
import { import { isEmpty } from 'lodash-es';
isEmpty
} from 'lodash';
import OrderApi from '@/sheep/api/trade/order'; import OrderApi from '@/sheep/api/trade/order';
import { resetPagination } from '@/sheep/util'; import { resetPagination } from '@/sheep/util';
@ -102,11 +142,12 @@
pageNo: 1, pageNo: 1,
pageSize: 5, pageSize: 5,
}, },
loadStatus: '' loadStatus: '',
}); });
const tabMaps = [{ const tabMaps = [
name: '全部' {
name: '全部',
}, },
{ {
name: '待付款', name: '待付款',
@ -275,13 +316,13 @@
pageNo: state.pagination.pageNo, pageNo: state.pagination.pageNo,
pageSize: state.pagination.pageSize, pageSize: state.pagination.pageSize,
status: tabMaps[state.currentTab].value, status: tabMaps[state.currentTab].value,
commentStatus: tabMaps[state.currentTab].value === 30 ? false : null commentStatus: tabMaps[state.currentTab].value === 30 ? false : null,
}); });
if (code !== 0) { if (code !== 0) {
return; return;
} }
data.list.forEach(order => handleOrderButtons(order)); data.list.forEach((order) => handleOrderButtons(order));
state.pagination.list = _.concat(state.pagination.list, data.list) state.pagination.list = _.concat(state.pagination.list, data.list);
state.pagination.total = data.total; state.pagination.total = data.total;
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore'; state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
} }
@ -296,7 +337,7 @@
// //
function loadMore() { function loadMore() {
if (state.loadStatus === 'noMore') { if (state.loadStatus === 'noMore') {
return return;
} }
state.pagination.pageNo++; state.pagination.pageNo++;
getOrderList(); getOrderList();
@ -380,7 +421,8 @@
font-weight: 500; font-weight: 500;
} }
.order-state {} .order-state {
}
} }
.pay-box { .pay-box {

View File

@ -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>

View File

@ -30,7 +30,9 @@
</view> </view>
<view class="time-box item ss-flex ss-col-center ss-row-between"> <view class="time-box item ss-flex ss-col-center ss-row-between">
<text class="item-title">充值时间</text> <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> </view>
</view> </view>
@ -53,7 +55,7 @@
<script setup> <script setup>
import { reactive } from 'vue'; import { reactive } from 'vue';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import _ from 'lodash'; import _ from 'lodash-es';
import PayWalletApi from '@/sheep/api/pay/wallet'; import PayWalletApi from '@/sheep/api/pay/wallet';
import sheep from '@/sheep'; import sheep from '@/sheep';
import { fen2yuan } from '../../sheep/hooks/useGoods'; import { fen2yuan } from '../../sheep/hooks/useGoods';

View File

@ -50,7 +50,10 @@
</view> </view>
<!-- #ifdef MP --> <!-- #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')" /> <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-title ss-m-r-48 ss-m-l-16">获取实时发货信息与订单状态</view>
<view class="subscribe-start" @tap="subscribeMessage"></view> <view class="subscribe-start" @tap="subscribeMessage"></view>
@ -63,7 +66,7 @@
<script setup> <script setup>
import { onLoad, onHide, onShow } from '@dcloudio/uni-app'; import { onLoad, onHide, onShow } from '@dcloudio/uni-app';
import { reactive, computed, ref } from 'vue'; import { reactive, computed, ref } from 'vue';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash-es';
import sheep from '@/sheep'; import sheep from '@/sheep';
import PayOrderApi from '@/sheep/api/pay/order'; import PayOrderApi from '@/sheep/api/pay/order';
import { fen2yuan } from '@/sheep/hooks/useGoods'; import { fen2yuan } from '@/sheep/hooks/useGoods';
@ -114,12 +117,12 @@
uni.showModal({ uni.showModal({
title: '支付结果', title: '支付结果',
showCancel: false, // showCancel: false, //
content: "支付成功", content: '支付成功',
success: () => { success: () => {
// showModal // showModal
autoSubscribeMessage(); autoSubscribeMessage();
} },
}) });
// #endif // #endif
// //
@ -153,8 +156,8 @@
} }
// #ifdef MP // #ifdef MP
const showSubscribeBtn = ref(false) // const showSubscribeBtn = ref(false); //
const SUBSCRIBE_BTN_STATUS_STORAGE_KEY = "subscribe_btn_status" const SUBSCRIBE_BTN_STATUS_STORAGE_KEY = 'subscribe_btn_status';
function subscribeMessage() { function subscribeMessage() {
if (state.orderType !== 'goods') { if (state.orderType !== 'goods') {
return; return;
@ -176,11 +179,11 @@
const subscribeBtnStatus = uni.getStorageSync(SUBSCRIBE_BTN_STATUS_STORAGE_KEY); const subscribeBtnStatus = uni.getStorageSync(SUBSCRIBE_BTN_STATUS_STORAGE_KEY);
if (!subscribeBtnStatus) { if (!subscribeBtnStatus) {
showSubscribeBtn.value = true; showSubscribeBtn.value = true;
return return;
} }
// 2. // 2.
subscribeMessage() subscribeMessage();
} }
// #endif // #endif

View File

@ -1,34 +1,70 @@
<!-- 收货地址的新增/编辑 --> <!-- 收货地址的新增/编辑 -->
<template> <template>
<s-layout :title="state.model.id ? '编辑地址' : '新增地址'"> <s-layout :title="state.model.id ? '编辑地址' : '新增地址'">
<uni-forms ref="addressFormRef" v-model="state.model" :rules="rules" validateTrigger="bind" <uni-forms
labelWidth="160" labelAlign="left" border :labelStyle="{ fontWeight: 'bold' }"> 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"> <view class="bg-white form-box ss-p-x-30">
<uni-forms-item name="name" label="收货人" class="form-item"> <uni-forms-item name="name" label="收货人" class="form-item">
<uni-easyinput v-model="state.model.name" placeholder="请填写收货人姓名" :inputBorder="false" <uni-easyinput
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal" /> 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>
<uni-forms-item name="mobile" label="手机号" class="form-item"> <uni-forms-item name="mobile" label="手机号" class="form-item">
<uni-easyinput v-model="state.model.mobile" type="number" placeholder="请输入手机号" :inputBorder="false" <uni-easyinput
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"> 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-easyinput>
</uni-forms-item> </uni-forms-item>
<uni-forms-item name="areaName" label="省市区" @tap="state.showRegion = true" class="form-item"> <uni-forms-item
<uni-easyinput v-model="state.model.areaName" disabled :inputBorder="false" 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' }" :styles="{ disableColor: '#fff', color: '#333' }"
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal" placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
placeholder="请选择省市区"> placeholder="请选择省市区"
>
<template v-slot:right> <template v-slot:right>
<uni-icons type="right" /> <uni-icons type="right" />
</template> </template>
</uni-easyinput> </uni-easyinput>
</uni-forms-item> </uni-forms-item>
<uni-forms-item name="detailAddress" label="详细地址" :formItemStyle="{ alignItems: 'flex-start' }" <uni-forms-item
:labelStyle="{ lineHeight: '5em' }" class="textarea-item"> name="detailAddress"
<uni-easyinput :inputBorder="false" type="textarea" v-model="state.model.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" placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
placeholder="请输入详细地址" clearable /> placeholder="请输入详细地址"
clearable
/>
</uni-forms-item> </uni-forms-item>
</view> </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="ss-m-y-20 bg-white ss-p-x-30 ss-flex ss-row-between ss-col-center default-box">
@ -48,7 +84,11 @@
</su-fixed> </su-fixed>
<!-- 省市区弹窗 --> <!-- 省市区弹窗 -->
<su-region-picker :show="state.showRegion" @cancel="state.showRegion = false" @confirm="onRegionConfirm" /> <su-region-picker
:show="state.showRegion"
@cancel="state.showRegion = false"
@confirm="onRegionConfirm"
/>
</s-layout> </s-layout>
</template> </template>
@ -56,7 +96,7 @@
import { ref, reactive, unref } from 'vue'; import { ref, reactive, unref } from 'vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import { onLoad } from '@dcloudio/uni-app'; import { onLoad } from '@dcloudio/uni-app';
import _ from 'lodash'; import _ from 'lodash-es';
import { mobile } from '@/sheep/validate/form'; import { mobile } from '@/sheep/validate/form';
import AreaApi from '@/sheep/api/system/area'; import AreaApi from '@/sheep/api/system/area';
import AddressApi from '@/sheep/api/member/address'; import AddressApi from '@/sheep/api/member/address';
@ -85,22 +125,26 @@
}, },
mobile, mobile,
detailAddress: { detailAddress: {
rules: [{ rules: [
{
required: true, required: true,
errorMessage: '请输入详细地址', errorMessage: '请输入详细地址',
}] },
],
}, },
areaName: { areaName: {
rules: [{ rules: [
{
required: true, required: true,
errorMessage: '请选择您的位置' errorMessage: '请选择您的位置',
}] },
],
}, },
}; };
// //
const onRegionConfirm = (e) => { const onRegionConfirm = (e) => {
state.model.areaName = `${e.province_name} ${e.city_name} ${e.district_name}` state.model.areaName = `${e.province_name} ${e.city_name} ${e.district_name}`;
state.model.areaId = e.district_id; state.model.areaId = e.district_id;
state.showRegion = false; state.showRegion = false;
}; };
@ -130,9 +174,11 @@
// //
const formData = { const formData = {
...state.model ...state.model,
} };
const {code } = state.model.id > 0 ? await AddressApi.updateAddress(formData) const { code } =
state.model.id > 0
? await AddressApi.updateAddress(formData)
: await AddressApi.createAddress(formData); : await AddressApi.createAddress(formData);
if (code === 0) { if (code === 0) {
sheep.$router.back(); sheep.$router.back();
@ -171,7 +217,7 @@
if (options.data) { if (options.data) {
let data = JSON.parse(options.data); let data = JSON.parse(options.data);
const areaData = uni.getStorageSync('areaData'); 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 provinceObj = findAreaByName(areaData, data.province_name);
let cityObj = provinceObj ? findAreaByName(provinceObj.children, data.city_name) : undefined; let cityObj = provinceObj ? findAreaByName(provinceObj.children, data.city_name) : undefined;
@ -181,7 +227,9 @@
state.model = { state.model = {
...state.model, ...state.model,
areaId, 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, defaultStatus: false,
detailAddress: data.address, detailAddress: data.address,
mobile: data.mobile, mobile: data.mobile,

View File

@ -2,44 +2,61 @@
<template> <template>
<s-layout title="收货地址" :bgStyle="{ color: '#FFF' }"> <s-layout title="收货地址" :bgStyle="{ color: '#FFF' }">
<view v-if="state.list.length"> <view v-if="state.list.length">
<s-address-item hasBorderBottom v-for="item in state.list" :key="item.id" :item="item" <s-address-item
@tap="onSelect(item)" /> hasBorderBottom
v-for="item in state.list"
:key="item.id"
:item="item"
@tap="onSelect(item)"
/>
</view> </view>
<su-fixed bottom placeholder> <su-fixed bottom placeholder>
<view class="footer-box ss-flex ss-row-between ss-p-20"> <view class="footer-box ss-flex ss-row-between ss-p-20">
<!-- 微信小程序和微信H5 --> <!-- 微信小程序和微信H5 -->
<button v-if="['WechatMiniProgram', 'WechatOfficialAccount'].includes(sheep.$platform.name)" <button
v-if="['WechatMiniProgram', 'WechatOfficialAccount'].includes(sheep.$platform.name)"
@tap="importWechatAddress" @tap="importWechatAddress"
class="border ss-reset-button sync-wxaddress ss-m-20 ss-flex ss-row-center ss-col-center"> 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> <text class="cicon-weixin ss-p-r-10" style="color: #09bb07; font-size: 40rpx"></text>
导入微信地址 导入微信地址
</button> </button>
<button class="add-btn ss-reset-button ui-Shadow-Main" <button
@tap="sheep.$router.go('/pages/user/address/edit')"> class="add-btn ss-reset-button ui-Shadow-Main"
@tap="sheep.$router.go('/pages/user/address/edit')"
>
新增收货地址 新增收货地址
</button> </button>
</view> </view>
</su-fixed> </su-fixed>
<s-empty v-if="state.list.length === 0 && !state.loading" text="暂无收货地址" icon="/static/data-empty.png" /> <s-empty
v-if="state.list.length === 0 && !state.loading"
text="暂无收货地址"
icon="/static/data-empty.png"
/>
</s-layout> </s-layout>
</template> </template>
<script setup> <script setup>
import { reactive, onBeforeMount } from 'vue'; import { onBeforeMount, reactive } from 'vue';
import { onShow } from '@dcloudio/uni-app'; import { onShow, onLoad } from '@dcloudio/uni-app';
import sheep from '@/sheep'; import sheep from '@/sheep';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash-es';
import AreaApi from '@/sheep/api/system/area'; import AreaApi from '@/sheep/api/system/area';
import AddressApi from '@/sheep/api/member/address'; import AddressApi from '@/sheep/api/member/address';
const state = reactive({ const state = reactive({
list: [], // list: [], //
loading: true, loading: true,
openType: '', //
}); });
// //
const onSelect = (addressInfo) => { const onSelect = (addressInfo) => {
if (state.openType !== 'select'){ //
return
}
uni.$emit('SELECT_ADDRESS', { uni.$emit('SELECT_ADDRESS', {
addressInfo, addressInfo,
}); });
@ -97,6 +114,12 @@
// #endif // #endif
} }
onLoad((option) => {
if (option.type) {
state.openType = option.type;
}
});
onShow(async () => { onShow(async () => {
state.list = (await AddressApi.getAddressList()).data; state.list = (await AddressApi.getAddressList()).data;
state.loading = false; state.loading = false;

View File

@ -5,7 +5,8 @@
<!-- 头部 --> <!-- 头部 -->
<view class="cart-header ss-flex ss-col-center ss-row-between ss-p-x-30"> <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"> <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>
<view class="header-right"> <view class="header-right">
<button <button
@ -77,7 +78,8 @@
<view class="footer-right"> <view class="footer-right">
<button <button
class="ss-reset-button ui-BG-Main-Gradient pay-btn ss-font-28 ui-Shadow-Main" class="ss-reset-button ui-BG-Main-Gradient pay-btn ss-font-28 ui-Shadow-Main"
@tap="onCancel"> @tap="onCancel"
>
取消收藏 取消收藏
</button> </button>
</view> </view>
@ -100,7 +102,7 @@
import sheep from '@/sheep'; import sheep from '@/sheep';
import { reactive } from 'vue'; import { reactive } from 'vue';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import _ from 'lodash'; import _ from 'lodash-es';
import FavoriteApi from '@/sheep/api/product/favorite'; import FavoriteApi from '@/sheep/api/product/favorite';
import { resetPagination } from '@/sheep/util'; import { resetPagination } from '@/sheep/util';
@ -129,7 +131,7 @@
if (code !== 0) { if (code !== 0) {
return; 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.pagination.total = data.total;
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore'; state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
} }
@ -174,7 +176,7 @@
// //
function loadMore() { function loadMore() {
if (state.loadStatus === 'noMore') { if (state.loadStatus === 'noMore') {
return return;
} }
state.pagination.pageNo++; state.pagination.pageNo++;
getData(); getData();

View File

@ -81,11 +81,13 @@
</view> </view>
<view class="footer-right ss-flex"> <view class="footer-right ss-flex">
<button <button
:class="['ss-reset-button pay-btn ss-font-28 ', :class="[
'ss-reset-button pay-btn ss-font-28 ',
{ {
'ui-BG-Main-Gradient': state.selectedSpuIdList.length > 0, 'ui-BG-Main-Gradient': state.selectedSpuIdList.length > 0,
'ui-Shadow-Main': state.selectedSpuIdList.length > 0 'ui-Shadow-Main': state.selectedSpuIdList.length > 0,
}]" },
]"
@tap="onDelete" @tap="onDelete"
> >
删除足迹 删除足迹
@ -120,9 +122,9 @@
import sheep from '@/sheep'; import sheep from '@/sheep';
import { reactive } from 'vue'; import { reactive } from 'vue';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import _ from 'lodash'; import _ from 'lodash-es';
import SpuHistoryApi from "@/sheep/api/product/history"; import SpuHistoryApi from '@/sheep/api/product/history';
import {cloneDeep} from "@/sheep/helper/utils"; import { cloneDeep } from '@/sheep/helper/utils';
const sys_navBar = sheep.$platform.navbar; const sys_navBar = sheep.$platform.navbar;
const pagination = { const pagination = {

View File

@ -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>

View File

@ -26,7 +26,8 @@
<button <button
class="ss-reset-button avatar-action-btn" class="ss-reset-button avatar-action-btn"
open-type="chooseAvatar" open-type="chooseAvatar"
@chooseavatar="onChooseAvatar"> @chooseavatar="onChooseAvatar"
>
修改 修改
</button> </button>
<!-- #endif --> <!-- #endif -->
@ -154,10 +155,7 @@
</view> </view>
<view class="ss-flex ss-col-center"> <view class="ss-flex ss-col-center">
<view class="info ss-flex ss-col-center" v-if="state.thirdInfo"> <view class="info ss-flex ss-col-center" v-if="state.thirdInfo">
<image <image class="avatar ss-m-r-20" :src="sheep.$url.cdn(state.thirdInfo.avatar)" />
class="avatar ss-m-r-20"
:src="sheep.$url.cdn(state.thirdInfo.avatar)"
/>
<text class="name">{{ state.thirdInfo.nickname }}</text> <text class="name">{{ state.thirdInfo.nickname }}</text>
</view> </view>
<view class="bind-box ss-m-l-20"> <view class="bind-box ss-m-l-20">
@ -185,7 +183,7 @@
<script setup> <script setup>
import { computed, reactive, onBeforeMount } from 'vue'; import { computed, reactive, onBeforeMount } from 'vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import { clone } from 'lodash'; import { clone } from 'lodash-es';
import { showAuthModal } from '@/sheep/hooks/useModal'; import { showAuthModal } from '@/sheep/hooks/useModal';
import FileApi from '@/sheep/api/infra/file'; import FileApi from '@/sheep/api/infra/file';
import UserApi from '@/sheep/api/member/user'; import UserApi from '@/sheep/api/member/user';
@ -198,14 +196,15 @@
const placeholderStyle = 'color:#BBBBBB;font-size:28rpx;line-height:normal'; const placeholderStyle = 'color:#BBBBBB;font-size:28rpx;line-height:normal';
const sexRadioMap = [{ const sexRadioMap = [
{
name: '男', name: '男',
value: '1', value: '1',
}, },
{ {
name: '女', name: '女',
value: '2', value: '2',
} },
]; ];
const userInfo = computed(() => sheep.$store('user').userInfo); const userInfo = computed(() => sheep.$store('user').userInfo);

View File

@ -13,7 +13,9 @@
/> />
</view> </view>
<view class="ss-flex ss-row-between ss-col-center ss-m-t-64"> <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 class="ss-reset-button topup-btn" @tap="sheep.$router.go('/pages/pay/recharge')">
充值 充值
</button> </button>
@ -24,7 +26,12 @@
<su-sticky> <su-sticky>
<!-- 统计 --> <!-- 统计 -->
<view class="filter-box ss-p-x-30 ss-flex ss-col-center ss-row-between"> <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"> <button class="ss-reset-button date-btn">
<text>{{ dateFilterText }}</text> <text>{{ dateFilterText }}</text>
<text class="cicon-drop-down ss-seldate-icon"></text> <text class="cicon-drop-down ss-seldate-icon"></text>
@ -82,7 +89,7 @@
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import sheep from '@/sheep'; import sheep from '@/sheep';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import _ from 'lodash'; import _ from 'lodash-es';
import PayWalletApi from '@/sheep/api/pay/wallet'; import PayWalletApi from '@/sheep/api/pay/wallet';
import { fen2yuan } from '@/sheep/hooks/useGoods'; import { fen2yuan } from '@/sheep/hooks/useGoods';
import { resetPagination } from '@/sheep/util'; import { resetPagination } from '@/sheep/util';
@ -98,7 +105,7 @@
list: [], list: [],
total: 0, total: 0,
pageNo: 1, pageNo: 1,
pageSize: 8 pageSize: 8,
}, },
summary: { summary: {
totalIncome: 0, totalIncome: 0,
@ -155,7 +162,7 @@
// //
async function getSummary() { async function getSummary() {
const { data, code } = await PayWalletApi.getWalletTransactionSummary({ 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) { if (code !== 0) {
return; return;
@ -226,8 +233,7 @@
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
background: v-bind(headerBg) background: v-bind(headerBg) no-repeat;
no-repeat;
pointer-events: none; pointer-events: none;
} }

View File

@ -24,7 +24,12 @@
<su-sticky :customNavHeight="sys_navBar"> <su-sticky :customNavHeight="sys_navBar">
<!-- 统计 --> <!-- 统计 -->
<view class="filter-box ss-p-x-30 ss-flex ss-col-center ss-row-between"> <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"> <uni-datetime-picker
v-model="state.date"
type="daterange"
@change="onChangeTime"
:end="state.today"
>
<button class="ss-reset-button date-btn"> <button class="ss-reset-button date-btn">
<text>{{ dateFilterText }}</text> <text>{{ dateFilterText }}</text>
<text class="cicon-drop-down ss-seldate-icon"></text> <text class="cicon-drop-down ss-seldate-icon"></text>
@ -83,7 +88,7 @@
import sheep from '@/sheep'; import sheep from '@/sheep';
import { onLoad, onReachBottom } from '@dcloudio/uni-app'; import { onLoad, onReachBottom } from '@dcloudio/uni-app';
import { computed, reactive } from 'vue'; import { computed, reactive } from 'vue';
import _ from 'lodash'; import _ from 'lodash-es';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import PointApi from '@/sheep/api/member/point'; import PointApi from '@/sheep/api/member/point';
import { resetPagination } from '@/sheep/util'; import { resetPagination } from '@/sheep/util';

View File

@ -1,14 +0,0 @@
import request from '@/sheep/request';
// TODO 芋艿:暂不支持 socket 聊天
export default {
// 获取聊天token
unifiedToken: () =>
request({
url: 'unifiedToken',
custom: {
showError: false,
showLoading: false,
},
}),
};

View File

@ -7,7 +7,25 @@ const DeliveryApi = {
url: `/trade/delivery/express/list`, url: `/trade/delivery/express/list`,
method: 'get', 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; export default DeliveryApi;

View File

@ -1,4 +1,5 @@
import request from '@/sheep/request'; import request from '@/sheep/request';
import { isEmpty } from '@/sheep/helper/utils';
const OrderApi = { const OrderApi = {
// 计算订单信息 // 计算订单信息
@ -13,6 +14,15 @@ const OrderApi = {
if (!(data.addressId > 0)) { if (!(data.addressId > 0)) {
delete data2.addressId; 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)) { if (!(data.combinationActivityId > 0)) {
delete data2.combinationActivityId; delete data2.combinationActivityId;
} }

View File

@ -18,9 +18,7 @@
<view class="address-text"> <view class="address-text">
{{ props.item.detailAddress }} {{ props.item.detailAddress }}
</view> </view>
<view class="person-text"> <view class="person-text"> {{ props.item.name }} {{ props.item.mobile }} </view>
{{ props.item.name }} {{ props.item.mobile }}
</view>
</view> </view>
<view v-else> <view v-else>
<view class="address-text ss-m-b-10">请选择收货地址</view> <view class="address-text ss-m-b-10">请选择收货地址</view>
@ -47,7 +45,7 @@
* @slot - 默认插槽 * @slot - 默认插槽
*/ */
import sheep from '@/sheep'; import sheep from '@/sheep';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash-es';
const props = defineProps({ const props = defineProps({
item: { item: {
type: Object, type: Object,

View File

@ -9,7 +9,7 @@
<!-- 基础组件列表导航 --> <!-- 基础组件列表导航 -->
<s-menu-list v-if="type === 'MenuList'" :data="data" /> <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" /> <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-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> </view>
</template> </template>

View File

@ -1,39 +1,20 @@
<!-- 装修营销组件优惠券 --> <!-- 装修营销组件优惠券 -->
<template> <template>
<scroll-view class="scroll-box" scroll-x scroll-anchoring> <scroll-view class="scroll-box" scroll-x scroll-anchoring :style="[bgStyle, { marginLeft: `${data.space}px` }]">
<view class="coupon-box ss-flex"> <view class="coupon-box ss-flex" :style="couponList.length === 2 ? couponBoxStyleTwo : couponBoxStyleNormal">
<view <view class="coupon-item" :style="[couponBg, { marginLeft: `${data.space}px` }]"
class="coupon-item" v-for="(item, index) in couponList" :key="index">
:style="[couponBg, { marginLeft: `${data.space}px` }]" <su-coupon :size="SIZE_LIST[columns - 1]" :textColor="data.textColor" background="" :couponId="item.id"
v-for="(item, index) in couponList" :title="item.name" :type="formatCouponDiscountType(item)" :value="formatCouponDiscountValue(item)"
:key="index" :sellBy="formatValidityType(item)">
>
<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> <template v-slot:btn>
<!-- 两列时领取按钮坚排 --> <!-- 两列时领取按钮坚排 -->
<button <button v-if="columns === 2" @click.stop="onGetCoupon(item.id)"
v-if="columns === 2" class="ss-reset-button card-btn vertical" :style="[btnStyles]">
@click.stop="onGetCoupon(item.id)"
class="ss-reset-button card-btn vertical"
:style="[btnStyles]"
>
<view class="btn-text">立即领取</view> <view class="btn-text">立即领取</view>
</button> </button>
<button <button v-else class="ss-reset-button card-btn" :style="[btnStyles]"
v-else @click.stop="onGetCoupon(item.id)">
class="ss-reset-button card-btn"
:style="[btnStyles]"
@click.stop="onGetCoupon(item.id)"
>
立即领取 立即领取
</button> </button>
</template> </template>
@ -46,9 +27,19 @@
<script setup> <script setup>
import sheep from '@/sheep'; import sheep from '@/sheep';
import CouponApi from '@/sheep/api/promotion/coupon'; import CouponApi from '@/sheep/api/promotion/coupon';
import { ref, onMounted } from 'vue'; import {
import { CouponTemplateValidityTypeEnum, PromotionDiscountTypeEnum } from "@/sheep/util/const"; ref,
import { floatToFixed2, formatDate } from "@/sheep/util"; onMounted,
computed
} from 'vue';
import {
CouponTemplateValidityTypeEnum,
PromotionDiscountTypeEnum
} from "@/sheep/util/const";
import {
floatToFixed2,
formatDate
} from "@/sheep/util";
const props = defineProps({ const props = defineProps({
data: { data: {
@ -60,7 +51,10 @@
default: () => ({}), default: () => ({}),
}, },
}); });
const { columns, button } = props.data; const {
columns,
button
} = props.data;
const SIZE_LIST = ['lg', 'md', 'xs'] const SIZE_LIST = ['lg', 'md', 'xs']
const couponBg = { const couponBg = {
background: `url(${sheep.$url.cdn(props.data.bgImg)}) no-repeat top center / 100% 100%`, background: `url(${sheep.$url.cdn(props.data.bgImg)}) no-repeat top center / 100% 100%`,
@ -69,7 +63,30 @@
background: button.bgColor, background: button.bgColor,
color: button.color, 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;
// bgType
return {
background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
};
});
// //
const formatCouponDiscountType = (coupon) => { const formatCouponDiscountType = (coupon) => {
if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) { if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
@ -106,7 +123,10 @@
const couponList = ref([]); const couponList = ref([]);
// //
async function onGetCoupon(id) { async function onGetCoupon(id) {
const { error, msg } = await CouponApi.takeCoupon(id); const {
error,
msg
} = await CouponApi.takeCoupon(id);
if (error === 0) { if (error === 0) {
uni.showToast({ uni.showToast({
title: msg, title: msg,
@ -117,7 +137,9 @@
await getCouponTemplateList() await getCouponTemplateList()
} }
const getCouponTemplateList = async () => { const getCouponTemplateList = async () => {
const { data } = await CouponApi.getCouponTemplateListByIds(props.data.couponIds.join(',')); const {
data
} = await CouponApi.getCouponTemplateListByIds(props.data.couponIds.join(','));
couponList.value = data; couponList.value = data;
} }
onMounted(() => { onMounted(() => {
@ -132,6 +154,7 @@
border-radius: 25rpx; border-radius: 25rpx;
font-size: 24rpx; font-size: 24rpx;
line-height: 50rpx; line-height: 50rpx;
&.vertical { &.vertical {
width: 50rpx; width: 50rpx;
height: 140rpx; height: 140rpx;
@ -144,6 +167,7 @@
} }
} }
} }
.coupon-item { .coupon-item {
&:nth-of-type(1) { &:nth-of-type(1) {
margin-left: 0 !important; margin-left: 0 !important;

View File

@ -1,6 +1,6 @@
<!-- 装修用户组件用户卡券 --> <!-- 装修用户组件用户卡券 -->
<template> <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" <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 })" @tap="sheep.$router.go(item.path, { type: item.type })"
:class="item.type === 'all' ? 'menu-wallet' : 'ss-flex-1'"> :class="item.type === 'all' ? 'menu-wallet' : 'ss-flex-1'">
@ -15,6 +15,7 @@
* 装修组件 - 优惠券菜单 * 装修组件 - 优惠券菜单
*/ */
import sheep from '@/sheep'; import sheep from '@/sheep';
import { computed } from 'vue';
// //
const props = defineProps({ 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> </script>

View File

@ -1,24 +1,19 @@
<!-- 订单确认的优惠劵选择弹窗 --> <!-- 订单确认的优惠劵选择弹窗 -->
<template> <template>
<su-popup <su-popup :show="show" type="bottom" round="20" @close="emits('close')" showClose backgroundColor="#f2f2f2">
:show="show"
type="bottom"
round="20"
@close="emits('close')"
showClose
backgroundColor="#f2f2f2"
>
<view class="model-box"> <view class="model-box">
<view class="title ss-m-t-16 ss-m-l-20 ss-flex">优惠券</view> <view class="title ss-m-t-16 ss-m-l-20 ss-flex">优惠券</view>
<scroll-view <scroll-view class="model-content" scroll-y :scroll-with-animation="false" :enable-back-to-top="true">
class="model-content" <!--可使用的优惠券区域-->
scroll-y
:scroll-with-animation="false"
:enable-back-to-top="true"
>
<view class="subtitle ss-m-l-20">可使用优惠券</view> <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"> <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> <template #default>
<label class="ss-flex ss-col-center" @tap="radioChange(item.id)"> <label class="ss-flex ss-col-center" @tap="radioChange(item.id)">
<radio <radio
@ -31,19 +26,18 @@
</template> </template>
</s-coupon-list> </s-coupon-list>
</view> </view>
<!-- TODO 芋艿未来接口需要支持下 <!--不可使用的优惠券区域-->
<view class="subtitle ss-m-t-40 ss-m-l-20">不可使用优惠券</view> <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"> <s-coupon-list :data="item" type="user" :disabled="true">
<template v-slot:reason> <template v-slot:reason>
<view class="ss-flex ss-m-t-24"> <view class="ss-flex ss-m-t-24">
<view class="reason-title"> 不可用原因</view> <view class="reason-title"> 不可用原因</view>
<view class="reason-desc">{{ item.cannot_use_msg }}</view> <view class="reason-desc">{{ item.description || '未达到使用门槛' }}</view>
</view> </view>
</template> </template>
</s-coupon-list> </s-coupon-list>
</view> </view>
-->
</scroll-view> </scroll-view>
</view> </view>
<view class="modal-footer ss-flex"> <view class="modal-footer ss-flex">
@ -57,7 +51,8 @@
const props = defineProps({ const props = defineProps({
modelValue: { // modelValue: { //
type: Object, type: Object,
default() {}, default() {
},
}, },
show: { show: {
type: Boolean, type: Boolean,
@ -84,7 +79,7 @@
// //
const onConfirm = () => { const onConfirm = () => {
emits('confirm', state.couponId); emits('confirm', state.couponId);
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep() { :deep() {
@ -96,25 +91,30 @@
.model-box { .model-box {
height: 60vh; height: 60vh;
} }
.title { .title {
font-size: 36rpx; font-size: 36rpx;
height: 80rpx; height: 80rpx;
font-weight: bold; font-weight: bold;
color: #333333; color: #333333;
} }
.subtitle { .subtitle {
font-size: 26rpx; font-size: 26rpx;
font-weight: 500; font-weight: 500;
color: #333333; color: #333333;
} }
.model-content { .model-content {
height: 54vh; height: 54vh;
} }
.modal-footer { .modal-footer {
width: 100%; width: 100%;
height: 120rpx; height: 120rpx;
background: #fff; background: #fff;
} }
.confirm-btn { .confirm-btn {
width: 710rpx; width: 710rpx;
margin-left: 20rpx; margin-left: 20rpx;
@ -123,12 +123,14 @@
border-radius: 40rpx; border-radius: 40rpx;
color: #fff; color: #fff;
} }
.reason-title { .reason-title {
font-weight: 600; font-weight: 600;
font-size: 20rpx; font-size: 20rpx;
line-height: 26rpx; line-height: 26rpx;
color: #ff0003; color: #ff0003;
} }
.reason-desc { .reason-desc {
font-weight: 600; font-weight: 600;
font-size: 20rpx; font-size: 20rpx;

View File

@ -11,7 +11,11 @@
<view v-if="tagStyle.show" class="tag-icon-box"> <view v-if="tagStyle.show" class="tag-icon-box">
<image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image> <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
</view> </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 <view
v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show" v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
class="xs-goods-content ss-flex-col ss-row-around" class="xs-goods-content ss-flex-col ss-row-around"
@ -39,14 +43,21 @@
<view v-if="tagStyle.show" class="tag-icon-box"> <view v-if="tagStyle.show" class="tag-icon-box">
<image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image> <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
</view> </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 <view
v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show" v-if="goodsFields.title?.show || goodsFields.name?.show || goodsFields.price?.show"
class="sm-goods-content" class="sm-goods-content"
:style="[{ color: titleColor, width: titleWidth ? titleWidth + 'rpx' : '' }]" :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 }} {{ data.title || data.name }}
</view> </view>
<view <view
@ -65,7 +76,11 @@
<view v-if="tagStyle.show" class="tag-icon-box"> <view v-if="tagStyle.show" class="tag-icon-box">
<image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image> <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
</view> </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 <view
class="md-goods-content ss-flex-col ss-row-around ss-p-b-20 ss-p-t-20 ss-p-x-16" class="md-goods-content ss-flex-col ss-row-around ss-p-b-20 ss-p-t-20 ss-p-x-16"
:id="elId" :id="elId"
@ -106,7 +121,10 @@
</view> </view>
<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" class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex"
:style="[{ color: originPriceColor }]" :style="[{ color: originPriceColor }]"
> >
@ -141,7 +159,11 @@
<view v-if="grouponTag" class="groupon-tag ss-flex ss-row-center"> <view v-if="grouponTag" class="groupon-tag ss-flex ss-row-center">
<view class="tag-icon">拼团</view> <view class="tag-icon">拼团</view>
</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 class="lg-goods-content ss-flex-1 ss-flex-col ss-row-between ss-p-b-10 ss-p-t-20">
<view> <view>
<view <view
@ -177,7 +199,10 @@
{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }} {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
</view> </view>
<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" class="goods-origin-price ss-flex ss-col-bottom font-OPPOSANS"
:style="[{ color: originPriceColor }]" :style="[{ color: originPriceColor }]"
> >
@ -192,9 +217,7 @@
</view> </view>
<slot name="cart"> <slot name="cart">
<view class="buy-box ss-flex ss-col-center ss-row-center" v-if="buttonShow"> <view class="buy-box ss-flex ss-col-center ss-row-center" v-if="buttonShow"> </view>
去购买
</view>
</slot> </slot>
</view> </view>
@ -204,7 +227,11 @@
<image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image> <image class="tag-icon" :src="sheep.$url.cdn(tagStyle.src || tagStyle.imgUrl)"></image>
</view> </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 class="sl-goods-content">
<view> <view>
@ -241,7 +268,10 @@
{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }} {{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
</view> </view>
<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" class="goods-origin-price ss-m-t-16 font-OPPOSANS ss-flex"
:style="[{ color: originPriceColor }]" :style="[{ color: originPriceColor }]"
> >
@ -296,7 +326,7 @@
import { fen2yuan, formatSales } from '@/sheep/hooks/useGoods'; import { fen2yuan, formatSales } from '@/sheep/hooks/useGoods';
import { formatStock } from '@/sheep/hooks/useGoods'; import { formatStock } from '@/sheep/hooks/useGoods';
import goodsCollectVue from '@/pages/user/goods-collect.vue'; import goodsCollectVue from '@/pages/user/goods-collect.vue';
import { isArray } from 'lodash'; import { isArray } from 'lodash-es';
// //
const state = reactive({}); const state = reactive({});

View File

@ -1,65 +1,38 @@
<!-- 装修组件 - 拼团 --> <!-- 装修组件 - 拼团 -->
<template> <template>
<view> <view>
<view <view v-if="layoutType === 'threeCol'" class="goods-sm-box ss-flex ss-flex-wrap" :style="[{ margin: '-' + data.space + 'rpx' }]">
v-if="layoutType === 'threeCol'" <view v-for="product in productList" class="goods-card-box" :key="product.id" :style="[{padding: data.space + 'rpx',},]">
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 <s-goods-column
class="goods-card" class="goods-card"
size="sm" size="sm"
:goodsFields="data.fields" :goodsFields="goodsFields"
:tagStyle="tagStyle" :tagStyle="badge"
:data="product" :data="product"
:titleColor="data.fields.name?.color" :titleColor="data.fields.name?.color"
:topRadius="data.borderRadiusTop" :topRadius="data.borderRadiusTop"
:bottomRadius="data.borderRadiusBottom" :bottomRadius="data.borderRadiusBottom"
@click=" @click="sheep.$router.go('/pages/goods/groupon', { id: props.data.activityId, })">
sheep.$router.go('/pages/goods/groupon', { </s-goods-column>
id: props.data.activityId,
})
"
></s-goods-column>
</view> </view>
</view> </view>
<!-- 样式2 一行一个 图片左 文案右 --> <!-- 样式2 一行一个 图片左 文案右 -->
<view class="goods-box" v-if="layoutType === 'oneCol'"> <view class="goods-box" v-if="layoutType === 'oneCol'">
<view <view class="goods-list" v-for="(product, index) in productList" :key="index" :style="[{ marginBottom: space + 'px' }]">
class="goods-list"
v-for="(product, index) in productList"
:key="index"
:style="[{ marginBottom: space + 'px' }]"
>
<s-goods-column <s-goods-column
class="goods-card" class="goods-card" size="lg"
size="lg" :grouponTag="true"
:goodsFields="data.fields" :goodsFields="goodsFields"
:tagStyle="tagStyle" :tagStyle="badge"
:data="product" :data="product"
:titleColor="data.fields.name?.color" :titleColor="data.fields.name?.color"
:subTitleColor="data.fields.introduction?.color" :subTitleColor="data.fields.introduction?.color"
:topRadius="data.borderRadiusTop" :topRadius="data.borderRadiusTop"
:bottomRadius="data.borderRadiusBottom" :bottomRadius="data.borderRadiusBottom"
@click=" @click="sheep.$router.go('/pages/goods/groupon', { id: props.data.activityId, })">
sheep.$router.go('/pages/goods/groupon', {
id: props.data.activityId,
})
"
>
<template v-slot:cart> <template v-slot:cart>
<button class="ss-reset-button cart-btn" :style="[buyStyle]"> <button class="ss-reset-button cart-btn" :style="[buyStyle]">
{{ btnBuy?.type === 'text' ? btnBuy.text : '' }} {{ btnBuy?.type === 'text' ? btnBuy.text : '去拼团' }}
</button> </button>
</template> </template>
</s-goods-column> </s-goods-column>
@ -72,27 +45,58 @@
/** /**
* 拼团 * 拼团
*/ */
import { computed, onMounted, ref } from 'vue'; import {
computed,
onMounted,
reactive,
ref
} from 'vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import SpuApi from "@/sheep/api/product/spu"; import SpuApi from "@/sheep/api/product/spu";
import CombinationApi from "@/sheep/api/promotion/combination"; import CombinationApi from "@/sheep/api/promotion/combination";
// //
const props = defineProps({ const props = defineProps({
//
data: { data: {
type: Object, type: Object,
default() {}, default: () => ({}),
}, },
//
styles: { styles: {
type: Object, type: Object,
default() {}, default: () => ({}),
}, },
}); });
let { layoutType, tagStyle, btnBuy, space } = props.data; //
let { marginLeft, marginRight } = props.styles; 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;
//
const buyStyle = computed(() => { const buyStyle = computed(() => {
let btnBuy = props.data.btnBuy; let btnBuy = props.data.btnBuy;
if (btnBuy?.type === 'text') { if (btnBuy?.type === 'text') {
@ -114,8 +118,16 @@
const productList = ref([]); const productList = ref([]);
onMounted(async () => { onMounted(async () => {
// todo@owen Yudao // todo@owen Yudao
const { data: activity } = await CombinationApi.getCombinationActivity(props.data.activityId); const {
const { data: spu } = await SpuApi.getSpuDetail(activity.spuId) 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]; productList.value = [spu];
}); });
</script> </script>
@ -123,6 +135,7 @@
<style lang="scss" scoped> <style lang="scss" scoped>
.goods-list { .goods-list {
position: relative; position: relative;
.cart-btn { .cart-btn {
position: absolute; position: absolute;
bottom: 10rpx; bottom: 10rpx;
@ -134,16 +147,20 @@
border-radius: 25rpx; border-radius: 25rpx;
font-size: 24rpx; font-size: 24rpx;
color: #fff; color: #fff;
background: linear-gradient(90deg, #ff6600 0%, #fe832a 100%);
} }
} }
.goods-list { .goods-list {
&:nth-last-of-type(1) { &:nth-last-of-type(1) {
margin-bottom: 0 !important; margin-bottom: 0 !important;
} }
} }
.goods-sm-box { .goods-sm-box {
margin: 0 auto; margin: 0 auto;
box-sizing: border-box; box-sizing: border-box;
.goods-card-box { .goods-card-box {
flex-shrink: 0; flex-shrink: 0;
overflow: hidden; overflow: hidden;

View File

@ -31,7 +31,11 @@
></view> ></view>
<!-- 顶部导航栏-情况4装修组件导航栏-沉浸式 --> <!-- 顶部导航栏-情况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 /> <slot />
@ -58,7 +62,7 @@
*/ */
import { computed, reactive, ref } from 'vue'; import { computed, reactive, ref } from 'vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash-es';
import { onShow } from '@dcloudio/uni-app'; import { onShow } from '@dcloudio/uni-app';
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
import { onShareAppMessage } from '@dcloudio/uni-app'; import { onShareAppMessage } from '@dcloudio/uni-app';

View File

@ -1,61 +1,31 @@
<!-- 装修基础组件菜单导航金刚区 --> <!-- 装修基础组件菜单导航金刚区 -->
<template> <template>
<!-- 包裹层 --> <!-- 包裹层 -->
<view <view class="ui-swiper" :class="[props.mode, props.ui]"
class="ui-swiper" :style="[bgStyle, { height: swiperHeight + (menuList.length > 1 ? 50 : 0) + 'rpx' }]">
:class="[props.mode, props.bg, props.ui]"
:style="[{ height: swiperHeight + (menuList.length > 1 ? 50 : 0) + 'rpx' }]"
>
<!-- 轮播 --> <!-- 轮播 -->
<swiper <swiper :circular="props.circular" :current="state.cur" :autoplay="props.autoplay" :interval="props.interval"
:circular="props.circular" :duration="props.duration" :style="[{ height: swiperHeight + 'rpx' }]" @change="swiperChange">
:current="state.cur" <swiper-item v-for="(arr, index) in menuList" :key="index" :class="{ cur: state.cur == index }">
: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 class="grid-wrap">
<view <view v-for="(item, index) in arr" :key="index"
v-for="(item, index) in arr"
:key="index"
class="grid-item ss-flex ss-flex-col ss-col-center ss-row-center" class="grid-item ss-flex ss-flex-col ss-col-center ss-row-center"
:style="[{ width: `${100 * (1 / data.column)}%`, height: '200rpx' }]" :style="[{ width: `${100 * (1 / data.column)}%`, height: '200rpx' }]" hover-class="ss-hover-btn"
hover-class="ss-hover-btn" @tap="sheep.$router.go(item.url)">
@tap="sheep.$router.go(item.url)"
>
<view class="menu-box ss-flex ss-flex-col ss-col-center ss-row-center"> <view class="menu-box ss-flex ss-flex-col ss-col-center ss-row-center">
<view <view v-if="item.badge.show" class="tag-box"
v-if="item.badge.show" :style="[{ background: item.badge.bgColor, color: item.badge.textColor }]">
class="tag-box"
:style="[{ background: item.badge.bgColor, color: item.badge.textColor }]"
>
{{ item.badge.text }} {{ item.badge.text }}
</view> </view>
<image <image v-if="item.iconUrl" class="menu-icon" :style="[
v-if="item.iconUrl"
class="menu-icon"
:style="[
{ {
width: props.iconSize + 'rpx', width: props.iconSize + 'rpx',
height: props.iconSize + 'rpx', height: props.iconSize + 'rpx',
}, },
]" ]" :src="sheep.$url.cdn(item.iconUrl)" mode="aspectFill"></image>
:src="sheep.$url.cdn(item.iconUrl)" <view v-if="data.layout === 'iconText'" class="menu-title"
mode="aspectFill" :style="[{ color: item.titleColor }]">
></image>
<view
v-if="data.layout === 'iconText'"
class="menu-title"
:style="[{ color: item.titleColor }]"
>
{{ item.title }} {{ item.title }}
</view> </view>
</view> </view>
@ -66,12 +36,8 @@
<!-- 指示点 --> <!-- 指示点 -->
<template v-if="menuList.length > 1"> <template v-if="menuList.length > 1">
<view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle != 'tag'"> <view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle != 'tag'">
<view <view class="line-box" v-for="(item, index) in menuList.length" :key="index"
class="line-box" :class="[state.cur == index ? 'cur' : '', props.dotCur]"></view>
v-for="(item, index) in menuList.length"
:key="index"
:class="[state.cur == index ? 'cur' : '', props.dotCur]"
></view>
</view> </view>
<view class="ui-swiper-dot" :class="props.dotStyle" v-if="props.dotStyle == 'tag'"> <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 class="ui-tag radius" :class="[props.dotCur]" style="pointer-events: none">
@ -111,7 +77,10 @@
* *
*/ */
import { reactive, computed } from 'vue'; import {
reactive,
computed
} from 'vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
// //
@ -122,13 +91,15 @@
// //
const props = defineProps({ const props = defineProps({
//
data: { data: {
type: Object, type: Object,
default() {}, default: () => ({}),
}, },
//
styles: { styles: {
type: Object, type: Object,
default() {}, default: () => ({}),
}, },
circular: { circular: {
type: Boolean, type: Boolean,
@ -146,7 +117,6 @@
type: Number, type: Number,
default: 500, default: 500,
}, },
ui: { ui: {
type: String, type: String,
default: '', default: '',
@ -164,15 +134,10 @@
type: String, type: String,
default: 'ui-BG-Main', default: 'ui-BG-Main',
}, },
bg: {
type: String,
default: 'bg-none',
},
height: { height: {
type: Number, type: Number,
default: 300, default: 300,
}, },
// //
hasBorder: { hasBorder: {
type: Boolean, type: Boolean,
@ -206,6 +171,21 @@
}, },
}); });
//
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 menuList = computed(() => splitData(props.data.list, props.data.row * props.data.column)); 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 swiperHeight = computed(() => props.data.row * (props.data.layout === 'iconText' ? 200 : 180));
@ -244,6 +224,7 @@
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
} }
.menu-box { .menu-box {
position: relative; position: relative;
z-index: 1; z-index: 1;
@ -332,8 +313,7 @@
opacity: 1; opacity: 1;
} }
&.cur::after { &.cur::after {}
}
} }
&.line { &.line {

View File

@ -1,18 +1,12 @@
<!-- 装修基础组件宫格导航 --> <!-- 装修基础组件宫格导航 -->
<template> <template>
<view :style="[bgStyle, { marginLeft: `${data.space}px` }]">
<uni-grid :showBorder="Boolean(data.border)" :column="data.column"> <uni-grid :showBorder="Boolean(data.border)" :column="data.column">
<uni-grid-item <uni-grid-item v-for="(item, index) in data.list" :key="index" @tap="sheep.$router.go(item.url)">
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="grid-item-box ss-flex ss-flex-col ss-row-center ss-col-center">
<view class="img-box"> <view class="img-box">
<view <view class="tag-box" v-if="item.badge.show"
class="tag-box" :style="[{ background: item.badge.bgColor, color: item.badge.textColor }]">
v-if="item.badge.show"
:style="[{ background: item.badge.bgColor, color: item.badge.textColor }]"
>
{{ item.badge.text }} {{ item.badge.text }}
</view> </view>
<image class="menu-image" :src="sheep.$url.cdn(item.iconUrl)"></image> <image class="menu-image" :src="sheep.$url.cdn(item.iconUrl)"></image>
@ -29,16 +23,41 @@
</view> </view>
</uni-grid-item> </uni-grid-item>
</uni-grid> </uni-grid>
</view>
</template> </template>
<script setup> <script setup>
import sheep from '@/sheep'; import sheep from '@/sheep';
import {
computed
} from 'vue';
const props = defineProps({ const props = defineProps({
//
data: { data: {
type: Object, type: Object,
default() {}, 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> </script>
@ -47,6 +66,7 @@
width: 24px; width: 24px;
height: 24px; height: 24px;
} }
.grid-item-box { .grid-item-box {
flex: 1; flex: 1;
display: flex; display: flex;
@ -54,8 +74,10 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 100%; height: 100%;
.img-box { .img-box {
position: relative; position: relative;
.tag-box { .tag-box {
position: absolute; position: absolute;
z-index: 2; z-index: 2;

View File

@ -1,6 +1,6 @@
<!-- 装修用户组件用户订单 --> <!-- 装修用户组件用户订单 -->
<template> <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 <view
class="menu-item ss-flex-1 ss-flex-col ss-row-center ss-col-center" class="menu-item ss-flex-1 ss-flex-col ss-row-center ss-col-center"
v-for="item in orderMap" v-for="item in orderMap"
@ -67,8 +67,32 @@
path: '/pages/order/list', path: '/pages/order/list',
}, },
]; ];
//
const props = defineProps({
//
data: {
type: Object,
default: () => ({}),
},
//
styles: {
type: Object,
default: () => ({}),
},
});
//
const numData = computed(() => sheep.$store('user').numData); 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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -2,65 +2,39 @@
<template> <template>
<view> <view>
<!-- 样式一三列 - 上图下文 --> <!-- 样式一三列 - 上图下文 -->
<view <view v-if="layoutType === 'threeCol'" class="goods-sm-box ss-flex ss-flex-wrap" :style="[{ margin: '-' + data.space + 'rpx' }]">
v-if="layoutType === 'threeCol'" <view v-for="product in productList" :key="product.id" class="goods-card-box" :style="[{padding: data.space + 'rpx',},]">
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 <s-goods-column
class="goods-card" class="goods-card" size="sm"
size="sm" :goodsFields="goodsFields"
:goodsFields="data.fields" :tagStyle="badge"
:tagStyle="tagStyle"
:data="product" :data="product"
:titleColor="data.fields.name?.color" :titleColor="data.fields.name?.color"
:topRadius="data.borderRadiusTop" :topRadius="data.borderRadiusTop"
:bottomRadius="data.borderRadiusBottom" :bottomRadius="data.borderRadiusBottom"
@click=" @click="sheep.$router.go('/pages/goods/seckill', { id: props.data.activityId, })">
sheep.$router.go('/pages/goods/seckill', { </s-goods-column>
id: props.data.activityId,
})
"
></s-goods-column>
</view> </view>
</view> </view>
<!-- 样式二一列 - 左图右文 --> <!-- 样式二一列 - 左图右文 -->
<view class="goods-box" v-if="layoutType === 'oneCol'"> <view class="goods-box" v-if="layoutType === 'oneCol'">
<view <view class="goods-list" v-for="(product, index) in productList" :key="index"
class="goods-list" :style="[{ marginBottom: space + 'px' }]">
v-for="(product, index) in productList"
:key="index"
:style="[{ marginBottom: space + 'px' }]"
>
<s-goods-column <s-goods-column
class="goods-card" class="goods-card"
size="lg" size="lg"
:goodsFields="data.fields" :goodsFields="goodsFields"
:tagStyle="tagStyle" :seckillTag="true"
:tagStyle="badge"
:data="product" :data="product"
:titleColor="data.fields.name?.color" :titleColor="data.fields.name?.color"
:subTitleColor="data.fields.introduction?.color" :subTitleColor="data.fields.introduction?.color"
:topRadius="data.borderRadiusTop" :topRadius="data.borderRadiusTop"
:bottomRadius="data.borderRadiusBottom" :bottomRadius="data.borderRadiusBottom"
@click=" @click="sheep.$router.go('/pages/goods/seckill', { id: props.data.activityId, })">
sheep.$router.go('/pages/goods/seckill', {
id: props.data.activityId,
})
"
>
<template v-slot:cart> <template v-slot:cart>
<button class="ss-reset-button cart-btn" :style="[buyStyle]"> <button class="ss-reset-button cart-btn" :style="[buyStyle]">
{{ btnBuy?.type === 'text' ? btnBuy.text : '' }} {{ btnBuy?.type === 'text' ? btnBuy.text : '立即秒杀' }}
</button> </button>
</template> </template>
</s-goods-column> </s-goods-column>
@ -75,25 +49,56 @@
* *
* @property {Array} list 商品列表 * @property {Array} list 商品列表
*/ */
import { computed, onMounted, ref } from 'vue'; import {
computed,
onMounted,
reactive,
ref
} from 'vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import SeckillApi from "@/sheep/api/promotion/seckill"; import SeckillApi from "@/sheep/api/promotion/seckill";
import SpuApi from "@/sheep/api/product/spu"; import SpuApi from "@/sheep/api/product/spu";
// //
const props = defineProps({ const props = defineProps({
//
data: { data: {
type: Object, type: Object,
default() {}, default: () => ({}),
}, },
//
styles: { styles: {
type: Object, type: Object,
default() {}, default: () => ({}),
}, },
}); });
let { layoutType, tagStyle, btnBuy, space } = props.data; //
let { marginLeft, marginRight } = props.styles; 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;
// //
const buyStyle = computed(() => { const buyStyle = computed(() => {
@ -118,8 +123,20 @@
// //
onMounted(async () => { onMounted(async () => {
// todo@owen Yudao // todo@owen Yudao
const { data: activity } = await SeckillApi.getSeckillActivity(props.data.activityId); const {
const { data: spu } = await SpuApi.getSpuDetail(activity.spuId) 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]; productList.value = [spu];
}); });
</script> </script>
@ -131,9 +148,11 @@
.goods-list { .goods-list {
position: relative; position: relative;
&:nth-last-child(1) { &:nth-last-child(1) {
margin-bottom: 0 !important; margin-bottom: 0 !important;
} }
.cart-btn { .cart-btn {
position: absolute; position: absolute;
bottom: 10rpx; bottom: 10rpx;
@ -145,11 +164,14 @@
border-radius: 25rpx; border-radius: 25rpx;
font-size: 24rpx; font-size: 24rpx;
color: #fff; color: #fff;
background: linear-gradient(90deg, #ff6600 0%, #fe832a 100%);
} }
} }
.goods-sm-box { .goods-sm-box {
margin: 0 auto; margin: 0 auto;
box-sizing: border-box; box-sizing: border-box;
.goods-card-box { .goods-card-box {
flex-shrink: 0; flex-shrink: 0;
overflow: hidden; overflow: hidden;

View File

@ -22,7 +22,7 @@
</view> </view>
</view> </view>
<view class="header-right-bottom ss-flex ss-col-center ss-row-between"> <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"> <view class="stock-text ss-m-l-20">
库存{{ state.selectedSku.stock || goodsInfo.stock }} 库存{{ state.selectedSku.stock || goodsInfo.stock }}
@ -63,7 +63,7 @@
<view class="btn-title">{{ grouponNum + '人团' }}</view> <view class="btn-title">{{ grouponNum + '人团' }}</view>
</button> </button>
<button class="ss-reset-button btn-tox ss-flex-col" @tap="onBuy"> <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-if="grouponAction === 'create'"></view>
<view v-else-if="grouponAction === 'join'">参与拼团</view> <view v-else-if="grouponAction === 'join'">参与拼团</view>
</button> </button>

View File

@ -91,8 +91,8 @@
// active,nostock // active,nostock
import { computed, reactive, watch } from 'vue'; import { computed, reactive, watch } from 'vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import {convertProductPropertyList, fen2yuan} from "@/sheep/hooks/useGoods"; import { convertProductPropertyList, fen2yuan } from '@/sheep/hooks/useGoods';
import {min} from "lodash"; import { min } from 'lodash-es';
const emits = defineEmits(['change', 'addCart', 'buy', 'close']); const emits = defineEmits(['change', 'addCart', 'buy', 'close']);
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {
@ -107,7 +107,7 @@
singleLimitCount: { singleLimitCount: {
type: Number, type: Number,
default: 1, default: 1,
} },
}); });
const state = reactive({ const state = reactive({
goodsInfo: computed(() => props.modelValue), goodsInfo: computed(() => props.modelValue),
@ -120,7 +120,7 @@
const skuList = computed(() => { const skuList = computed(() => {
let skuPrices = state.goodsInfo.skus; let skuPrices = state.goodsInfo.skus;
for (let price of skuPrices) { 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; return skuPrices;
}); });
@ -258,7 +258,10 @@
const onSelectSku = (propertyId, valueId) => { const onSelectSku = (propertyId, valueId) => {
// //
let isChecked = true; // or let isChecked = true; // or
if (state.currentPropertyArray[propertyId] !== undefined && state.currentPropertyArray[propertyId] === valueId) { if (
state.currentPropertyArray[propertyId] !== undefined &&
state.currentPropertyArray[propertyId] === valueId
) {
// '' // ''
isChecked = false; isChecked = false;
state.currentPropertyArray.splice(propertyId, 1, ''); state.currentPropertyArray.splice(propertyId, 1, '');

View File

@ -66,7 +66,7 @@
css: { css: {
// //
width: sheep.$platform.device.windowWidth * 0.9, width: sheep.$platform.device.windowWidth * 0.9,
height: 550, height: 600,
}, },
views: [], views: [],
}); });

View File

@ -82,12 +82,12 @@ const groupon = async (poster) => {
type: 'text', type: 'text',
text: '2人团', text: '2人团',
css: { css: {
color: '#ff0000', color: '#fff',
fontSize: 30, fontSize: 12,
fontFamily: 'OPPOSANS', fontFamily: 'OPPOSANS',
position: 'fixed', position: 'fixed',
left: width * 0.3, left: width * 0.84,
top: width * 1.32, top: width * 1.3,
}, },
}, },
// #ifndef MP-WEIXIN // #ifndef MP-WEIXIN
@ -96,7 +96,7 @@ const groupon = async (poster) => {
text: poster.shareInfo.link, text: poster.shareInfo.link,
css: { css: {
position: 'fixed', position: 'fixed',
left: width * 0.75, left: width * 0.5,
top: width * 1.3, top: width * 1.3,
width: width * 0.2, width: width * 0.2,
height: width * 0.2, height: width * 0.2,

View File

@ -1,10 +1,6 @@
<!-- 装修商品组件标题栏 --> <!-- 装修商品组件标题栏 -->
<template> <template>
<view <view class="ss-title-wrap ss-flex ss-col-center" :class="[state.typeMap[data.textAlign]]" :style="[bgStyle, { marginLeft: `${data.space}px` }]">
class="ss-title-wrap ss-flex ss-col-center"
:class="[state.typeMap[data.textAlign]]"
:style="[elStyles]"
>
<view class="title-content"> <view class="title-content">
<!-- 主标题 --> <!-- 主标题 -->
<view v-if="data.title" class="title-text" :style="[titleStyles]">{{ data.title }}</view> <view v-if="data.title" class="title-text" :style="[titleStyles]">{{ data.title }}</view>
@ -24,7 +20,10 @@
/** /**
* 标题栏 * 标题栏
*/ */
import { reactive } from 'vue'; import {
reactive,
computed
} from 'vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
// //
@ -37,22 +36,31 @@
// //
const props = defineProps({ const props = defineProps({
//
data: { data: {
type: Object, type: Object,
default() {}, default: () => ({}),
}, },
//
styles: { styles: {
type: Object, type: Object,
default() {}, default: () => ({}),
}, },
}); });
//
const bgStyle = computed(() => {
// props.styles
const {
bgType,
bgImg,
bgColor
} = props.styles;
// // bgType
const elStyles = { return {
background: `url(${sheep.$url.cdn(props.data.bgImgUrl)}) no-repeat top center / 100% auto`, background: bgType === 'img' ? `url(${bgImg}) no-repeat top center / 100% 100%` : bgColor
fontSize: `${props.data.titleSize}px`,
fontWeight: `${props.data.titleWeight}px`,
}; };
});
// //
const titleStyles = { const titleStyles = {

View File

@ -1,6 +1,6 @@
<!-- 装修用户组件用户卡片 --> <!-- 装修用户组件用户卡片 -->
<template> <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="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="left-box ss-flex ss-col-center ss-m-l-36">
<view class="avatar-box ss-m-r-24"> <view class="avatar-box ss-m-r-24">
@ -70,9 +70,15 @@
const isLogin = computed(() => sheep.$store('user').isLogin); const isLogin = computed(() => sheep.$store('user').isLogin);
// //
const props = defineProps({ const props = defineProps({
background: { //
type: String, data: {
default: '', type: Object,
default: () => ({}),
},
//
styles: {
type: Object,
default: () => ({}),
}, },
// //
avatar: { avatar: {
@ -97,6 +103,19 @@
}, },
}); });
//
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() { function onBind() {
showAuthModal('changeMobile'); showAuthModal('changeMobile');
} }

View File

@ -1,6 +1,6 @@
<!-- 装修用户组件用户资产 --> <!-- 装修用户组件用户资产 -->
<template> <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" <view class="menu-item ss-flex-1 ss-flex-col ss-row-center ss-col-center"
@tap="sheep.$router.go('/pages/user/wallet/money')"> @tap="sheep.$router.go('/pages/user/wallet/money')">
<view class="value-box ss-flex ss-col-bottom"> <view class="value-box ss-flex ss-col-bottom">
@ -44,6 +44,32 @@
import sheep from '@/sheep'; 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 userWallet = computed(() => sheep.$store('user').userWallet);
const userInfo = computed(() => sheep.$store('user').userInfo); const userInfo = computed(() => sheep.$store('user').userInfo);
const numData = computed(() => sheep.$store('user').numData); const numData = computed(() => sheep.$store('user').numData);

View File

@ -23,6 +23,10 @@ export function isString(value) {
} }
export function isEmpty(value) { export function isEmpty(value) {
if (value === '' || value === undefined || value === null){
return true;
}
if (isArray(value)) { if (isArray(value)) {
return value.length === 0; return value.length === 0;
} }
@ -31,7 +35,7 @@ export function isEmpty(value) {
return Object.keys(value).length === 0; return Object.keys(value).length === 0;
} }
return value === '' || value === undefined || value === null; return false
} }
export function isBoolean(value) { export function isBoolean(value) {

View File

@ -14,7 +14,7 @@ export function showAuthModal(type = 'smsLogin') {
modal.$patch((state) => { modal.$patch((state) => {
state.auth = type; state.auth = type;
}); });
}, 200); }, 500);
closeAuthModal(); closeAuthModal();
} else { } else {
modal.$patch((state) => { modal.$patch((state) => {

View File

@ -1,9 +1,10 @@
/** /**
* 本模块封装微信浏览器下的一些方法 * 本模块封装微信浏览器下的一些方法
* 更多微信网页开发sdk方法,详见:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html * 更多微信网页开发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 $helper from '@/sheep/helper';
import AuthUtil from '@/sheep/api/member/auth'; import AuthUtil from '@/sheep/api/member/auth';
@ -38,7 +39,7 @@ export default {
timestamp: data.timestamp, timestamp: data.timestamp,
nonceStr: data.nonceStr, nonceStr: data.nonceStr,
signature: data.signature, signature: data.signature,
jsApiList: ['chooseWXPay'], // TODO 芋艿:后续可以设置更多权限; jsApiList: ['chooseWXPay', 'openLocation', 'getLocation','updateTimelineShareData','scanQRCode'], // TODO 芋艿:后续可以设置更多权限;
openTagList: data.openTagList openTagList: data.openTagList
}); });
} }
@ -77,7 +78,7 @@ export default {
}); });
}, },
//获取微信收货地址 TODO 芋艿:未测试 // 获取微信收货地址
openAddress(callback) { openAddress(callback) {
this.isReady(() => { this.isReady(() => {
jweixin.openAddress({ jweixin.openAddress({
@ -137,9 +138,10 @@ export default {
openLocation(data, callback) { openLocation(data, callback) {
this.isReady(() => { this.isReady(() => {
jweixin.openLocation({ jweixin.openLocation({
//根据传入的坐标打开地图 ...data,
latitude: data.latitude, success: function (res) {
longitude: data.longitude, console.log(res);
}
}); });
}); });
}, },

View File

@ -9,7 +9,7 @@
* @param {Object} device - 设备信息 * @param {Object} device - 设备信息
*/ */
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash-es';
// #ifdef H5 // #ifdef H5
import { isWxBrowser } from '@/sheep/helper/utils'; import { isWxBrowser } from '@/sheep/helper/utils';
// #endif // #endif

View File

@ -54,7 +54,6 @@ const mobileLogin = async (e) => {
} else { } else {
return resolve(false); return resolve(false);
} }
// TODO 芋艿shareInfo: uni.getStorageSync('shareLog') || {},
}); });
}; };

View File

@ -24,7 +24,6 @@ async function login(code = '', state = '') {
// 解密 code 发起登陆 // 解密 code 发起登陆
const loginResult = await AuthUtil.socialLogin(socialType, code, state); const loginResult = await AuthUtil.socialLogin(socialType, code, state);
if (loginResult.code === 0) { if (loginResult.code === 0) {
// TODO 芋艿shareLog
setOpenid(loginResult.data.openid); setOpenid(loginResult.data.openid);
return loginResult; return loginResult;
} }
@ -103,5 +102,5 @@ export default {
unbind, unbind,
getInfo, getInfo,
getOpenid, getOpenid,
jssdk: $wxsdk, jsWxSdk: $wxsdk,
}; };

View File

@ -4,13 +4,12 @@
*/ */
import Request from 'luch-request'; 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 $store from '@/sheep/store';
import $platform from '@/sheep/platform'; import $platform from '@/sheep/platform';
import { import { showAuthModal } from '@/sheep/hooks/useModal';
showAuthModal
} from '@/sheep/hooks/useModal';
import AuthUtil from '@/sheep/api/member/auth'; import AuthUtil from '@/sheep/api/member/auth';
import { getTerminal } from '@/sheep/util/const';
const options = { const options = {
// 显示操作成功消息 默认不显示 // 显示操作成功消息 默认不显示
@ -95,11 +94,10 @@ http.interceptors.request.use(
if (token) { if (token) {
config.header['Authorization'] = token; config.header['Authorization'] = token;
} }
// TODO 芋艿:特殊处理 config.header['terminal'] = getTerminal();
config.header['Accept'] = '*/*'; config.header['Accept'] = '*/*';
config.header['tenant-id'] = tenantId; config.header['tenant-id'] = tenantId;
config.header['terminal'] = '20';
// config.header['Authorization'] = 'Bearer test247';
return config; return config;
}, },
(error) => { (error) => {

View File

@ -1,6 +1,6 @@
import $store from '@/sheep/store'; import $store from '@/sheep/store';
import { showAuthModal, showShareModal } from '@/sheep/hooks/useModal'; 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'; import throttle from '@/sheep/helper/throttle';
const _go = ( const _go = (

View File

@ -57,7 +57,13 @@ const cart = defineStore({
// 移除购物车 // 移除购物车
async delete(ids) { 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) { if (code === 0) {
await this.getList(); await this.getList();
} }

View File

@ -1,6 +1,6 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import $share from '@/sheep/platform/share'; import $share from '@/sheep/platform/share';
import { clone, cloneDeep } from 'lodash'; import { clone, cloneDeep } from 'lodash-es';
import cart from './cart'; import cart from './cart';
import app from './app'; import app from './app';
import { showAuthModal } from '@/sheep/hooks/useModal'; import { showAuthModal } from '@/sheep/hooks/useModal';
@ -68,12 +68,12 @@ const user = defineStore({
// 获取订单、优惠券等其他资产信息 // 获取订单、优惠券等其他资产信息
getNumData() { getNumData() {
OrderApi.getOrderCount().then(res => { OrderApi.getOrderCount().then((res) => {
if (res.code === 0) { if (res.code === 0) {
this.numData.orderCount = res.data; this.numData.orderCount = res.data;
} }
}); });
CouponApi.getUnusedCouponCount().then(res => { CouponApi.getUnusedCouponCount().then((res) => {
if (res.code === 0) { if (res.code === 0) {
this.numData.unusedCouponCount = res.data; this.numData.unusedCouponCount = res.data;
} }
@ -143,20 +143,22 @@ const user = defineStore({
} }
// 绑定推广员 // 绑定推广员
$share.bindBrokerageUser() $share.bindBrokerageUser();
}, },
// 登出系统 // 登出系统
async logout() { async logout() {
this.resetUserData(); this.resetUserData();
return !this.isLogin; return !this.isLogin;
} },
}, },
persist: { persist: {
enabled: true, enabled: true,
strategies: [{ strategies: [
{
key: 'user-store', key: 'user-store',
}] },
],
}, },
}); });

View File

@ -88,7 +88,7 @@
import { reactive, computed } from 'vue'; import { reactive, computed } from 'vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import { clone } from 'lodash'; import { clone } from 'lodash-es';
// //
const state = reactive({ const state = reactive({
@ -200,7 +200,7 @@
if (item.type === 'video') { if (item.type === 'video') {
previewImage.splice(index, 1); previewImage.splice(index, 1);
} }
}) });
uni.previewImage({ uni.previewImage({
urls: urls:
previewImage.length < 1 previewImage.length < 1

View File

@ -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 - 营销模块 ========== // ========== MALL - 营销模块 ==========
import dayjs from "dayjs"; import dayjs from "dayjs";

BIN
static/images/line.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
static/images/writeOff.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB