新闻列表装修

This commit is contained in:
77 2024-08-07 21:40:27 +08:00
parent f1c5ac864a
commit bab2d48441
158 changed files with 6067 additions and 5228 deletions

View File

@ -82,6 +82,14 @@
"title": "自定义页面", "title": "自定义页面",
"group": "商城" "group": "商城"
} }
},
{
"path" : "pages/mulu/mulu",
"style" :
{
"navigationBarTitleText" : "详情",
"enablePullDownRefresh" : false
}
} }
], ],
"subPackages": [{ "subPackages": [{

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>
@ -199,7 +206,7 @@
import { useDurationTime } from '@/sheep/hooks/useGoods'; import { 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';
import CombinationApi from "@/sheep/api/promotion/combination"; import CombinationApi from '@/sheep/api/promotion/combination';
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;
@ -295,7 +302,9 @@
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;
} else { } else {
state.data = null; state.data = null;
@ -316,8 +325,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

@ -24,9 +24,9 @@
</view> </view>
<view class="border-bottom"> <view class="border-bottom">
<s-goods-item <s-goods-item
:img="record.picUrl" :img="record.picUrl"
:title="record.spuName" :title="record.spuName"
:price="record.combinationPrice" :price="record.combinationPrice"
> >
<template #groupon> <template #groupon>
<view class="ss-flex"> <view class="ss-flex">
@ -68,7 +68,7 @@
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';
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

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

@ -3,13 +3,20 @@
<s-layout navbar="inner" :bgStyle="{ color: 'rgb(245,28,19)' }"> <s-layout navbar="inner" :bgStyle="{ color: 'rgb(245,28,19)' }">
<!--顶部背景图--> <!--顶部背景图-->
<view <view
class="page-bg" class="page-bg"
:style="[{ marginTop: '-' + Number(statusBarHeight + 88) + 'rpx' }]" :style="[{ marginTop: '-' + Number(statusBarHeight + 88) + 'rpx' }]"
></view> ></view>
<!-- 时间段轮播图 --> <!-- 时间段轮播图 -->
<view class="header" v-if="activeTimeConfig?.sliderPicUrls?.length > 0"> <view class="header" v-if="activeTimeConfig?.sliderPicUrls?.length > 0">
<swiper indicator-dots="true" autoplay="true" :circular="true" interval="3000" duration="1500" <swiper
indicator-color="rgba(255,255,255,0.6)" indicator-active-color="#fff"> indicator-dots="true"
autoplay="true"
:circular="true"
interval="3000"
duration="1500"
indicator-color="rgba(255,255,255,0.6)"
indicator-active-color="#fff"
>
<block v-for="(picUrl, index) in activeTimeConfig.sliderPicUrls" :key="index"> <block v-for="(picUrl, index) in activeTimeConfig.sliderPicUrls" :key="index">
<swiper-item class="borRadius14"> <swiper-item class="borRadius14">
<image :src="picUrl" class="slide-image borRadius14" lazy-load /> <image :src="picUrl" class="slide-image borRadius14" lazy-load />
@ -22,13 +29,24 @@
<!-- 左侧图标 --> <!-- 左侧图标 -->
<view class="time-icon"> <view class="time-icon">
<!-- TODO 芋艿图片统一维护 --> <!-- TODO 芋艿图片统一维护 -->
<image class="ss-w-100 ss-h-100" src="http://mall.yudao.iocoder.cn/static/images/priceTag.png" /> <image
class="ss-w-100 ss-h-100"
src="http://mall.yudao.iocoder.cn/static/images/priceTag.png"
/>
</view> </view>
<scroll-view class="time-list" :scroll-into-view="activeTimeElId" scroll-x scroll-with-animation> <scroll-view
<view v-for="(config, index) in timeConfigList" :key="index" class="time-list"
:class="['item', { active: activeTimeIndex === index}]" :scroll-into-view="activeTimeElId"
:id="`timeItem${index}`" scroll-x
@tap="handleChangeTimeConfig(index)"> scroll-with-animation
>
<view
v-for="(config, index) in timeConfigList"
:key="index"
:class="['item', { active: activeTimeIndex === index }]"
:id="`timeItem${index}`"
@tap="handleChangeTimeConfig(index)"
>
<!-- 活动起始时间 --> <!-- 活动起始时间 -->
<view class="time">{{ config.startTime }}</view> <view class="time">{{ config.startTime }}</view>
<!-- 活动状态 --> <!-- 活动状态 -->
@ -42,7 +60,10 @@
<!-- 活动倒计时 --> <!-- 活动倒计时 -->
<view class="content-header ss-flex-col ss-col-center ss-row-center"> <view class="content-header ss-flex-col ss-col-center ss-row-center">
<view class="content-header-box ss-flex ss-row-center"> <view class="content-header-box ss-flex ss-row-center">
<view class="countdown-box ss-flex" v-if="activeTimeConfig?.status === TimeStatusEnum.STARTED"> <view
class="countdown-box ss-flex"
v-if="activeTimeConfig?.status === TimeStatusEnum.STARTED"
>
<view class="countdown-title ss-m-r-12">距结束</view> <view class="countdown-title ss-m-r-12">距结束</view>
<view class="ss-flex countdown-time"> <view class="ss-flex countdown-time">
<view class="ss-flex countdown-h">{{ countDown.h }}</view> <view class="ss-flex countdown-h">{{ countDown.h }}</view>
@ -74,12 +95,20 @@
> >
<!-- 抢购进度 --> <!-- 抢购进度 -->
<template #activity> <template #activity>
<view class="limit">限量 <text class="ss-m-l-5">{{ activity.stock}} {{activity.unitName}}</text></view> <view class="limit"
>限量
<text class="ss-m-l-5">{{ activity.stock }} {{ activity.unitName }}</text></view
>
<su-progress :percentage="activity.percent" strokeWidth="10" textInside isAnimate /> <su-progress :percentage="activity.percent" strokeWidth="10" textInside isAnimate />
</template> </template>
<!-- 抢购按钮 --> <!-- 抢购按钮 -->
<template #cart> <template #cart>
<button :class="['ss-reset-button cart-btn', { disabled: activeTimeConfig.status === TimeStatusEnum.END }]"> <button
:class="[
'ss-reset-button cart-btn',
{ disabled: activeTimeConfig.status === TimeStatusEnum.END },
]"
>
<span v-if="activeTimeConfig?.status === TimeStatusEnum.WAIT_START">未开始</span> <span v-if="activeTimeConfig?.status === TimeStatusEnum.WAIT_START">未开始</span>
<span v-else-if="activeTimeConfig?.status === TimeStatusEnum.STARTED">马上抢</span> <span v-else-if="activeTimeConfig?.status === TimeStatusEnum.STARTED">马上抢</span>
<span v-else>已结束</span> <span v-else>已结束</span>
@ -100,18 +129,19 @@
</s-layout> </s-layout>
</template> </template>
<script setup> <script setup>
import {reactive, computed, ref, nextTick} from 'vue'; import { reactive, computed, ref, nextTick } 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 { useDurationTime } from '@/sheep/hooks/useGoods'; import { useDurationTime } from '@/sheep/hooks/useGoods';
import SeckillApi from "@/sheep/api/promotion/seckill"; import SeckillApi from '@/sheep/api/promotion/seckill';
import dayjs from "dayjs"; import dayjs from 'dayjs';
import {TimeStatusEnum} from "@/sheep/util/const"; import { TimeStatusEnum } from '@/sheep/util/const';
// //
const { safeAreaInsets, safeArea } = sheep.$platform.device; const { safeAreaInsets, safeArea } = sheep.$platform.device;
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2; const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
const pageHeight = (safeArea.height + safeAreaInsets.bottom) * 2 + statusBarHeight - sheep.$platform.navbar - 350; const pageHeight =
(safeArea.height + safeAreaInsets.bottom) * 2 + statusBarHeight - sheep.$platform.navbar - 350;
const headerBg = sheep.$url.css('/static/img/shop/goods/seckill-header.png'); const headerBg = sheep.$url.css('/static/img/shop/goods/seckill-header.png');
// //
@ -124,16 +154,16 @@
//#region //#region
// //
const timeConfigList = ref([]) const timeConfigList = ref([]);
// //
const getSeckillConfigList = async () => { const getSeckillConfigList = async () => {
const { data } = await SeckillApi.getSeckillConfigList() const { data } = await SeckillApi.getSeckillConfigList();
const now = dayjs(); const now = dayjs();
const today = now.format('YYYY-MM-DD') const today = now.format('YYYY-MM-DD');
// //
data.forEach((config, index) => { data.forEach((config, index) => {
const startTime = dayjs(`${today} ${config.startTime}`) const startTime = dayjs(`${today} ${config.startTime}`);
const endTime = dayjs(`${today} ${config.endTime}`) const endTime = dayjs(`${today} ${config.endTime}`);
if (now.isBefore(startTime)) { if (now.isBefore(startTime)) {
config.status = TimeStatusEnum.WAIT_START; config.status = TimeStatusEnum.WAIT_START;
} else if (now.isAfter(endTime)) { } else if (now.isAfter(endTime)) {
@ -142,35 +172,35 @@
config.status = TimeStatusEnum.STARTED; config.status = TimeStatusEnum.STARTED;
activeTimeIndex.value = index; activeTimeIndex.value = index;
} }
}) });
timeConfigList.value = data timeConfigList.value = data;
// //
handleChangeTimeConfig(activeTimeIndex.value); handleChangeTimeConfig(activeTimeIndex.value);
// //
scrollToTimeConfig(activeTimeIndex.value) scrollToTimeConfig(activeTimeIndex.value);
} };
// //
const activeTimeElId = ref('') // ID const activeTimeElId = ref(''); // ID
const scrollToTimeConfig = (index) => { const scrollToTimeConfig = (index) => {
nextTick(() => activeTimeElId.value = `timeItem${index}`) nextTick(() => (activeTimeElId.value = `timeItem${index}`));
} };
// //
const activeTimeIndex = ref(0) // const activeTimeIndex = ref(0); //
const activeTimeConfig = computed(() => timeConfigList.value[activeTimeIndex.value]) // const activeTimeConfig = computed(() => timeConfigList.value[activeTimeIndex.value]); //
const handleChangeTimeConfig = (index) => { const handleChangeTimeConfig = (index) => {
activeTimeIndex.value = index activeTimeIndex.value = index;
// //
activityPageParams.pageNo = 1 activityPageParams.pageNo = 1;
activityList.value = [] activityList.value = [];
getActivityList(); getActivityList();
} };
// //
const countDown = computed(() => { const countDown = computed(() => {
const endTime = activeTimeConfig.value?.endTime const endTime = activeTimeConfig.value?.endTime;
if (endTime) { if (endTime) {
return useDurationTime(`${dayjs().format('YYYY-MM-DD')} ${endTime}`); return useDurationTime(`${dayjs().format('YYYY-MM-DD')} ${endTime}`);
} }
@ -185,17 +215,19 @@
id: 0, // ID id: 0, // ID
pageNo: 1, // pageNo: 1, //
pageSize: 5, // pageSize: 5, //
}) });
const activityTotal = ref(0) // const activityTotal = ref(0); //
const activityList = ref([]) // const activityList = ref([]); //
const loadStatus = ref('') // const loadStatus = ref(''); //
async function getActivityList() { async function getActivityList() {
loadStatus.value = 'loading'; loadStatus.value = 'loading';
const { data } = await SeckillApi.getSeckillActivityPage(activityPageParams) const { data } = await SeckillApi.getSeckillActivityPage(activityPageParams);
data.list.forEach(activity => { data.list.forEach((activity) => {
// //
activity.percent = parseInt(100 * (activity.totalStock - activity.stock) / activity.totalStock); activity.percent = parseInt(
}) (100 * (activity.totalStock - activity.stock)) / activity.totalStock,
);
});
activityList.value = activityList.value.concat(...data.list); activityList.value = activityList.value.concat(...data.list);
activityTotal.value = data.total; activityTotal.value = data.total;
@ -205,7 +237,7 @@
// //
function loadMore() { function loadMore() {
if (loadStatus.value !== 'noMore') { if (loadStatus.value !== 'noMore') {
activityPageParams.pageNo += 1 activityPageParams.pageNo += 1;
getActivityList(); getActivityList();
} }
} }
@ -216,7 +248,7 @@
// //
onLoad(async () => { onLoad(async () => {
await getSeckillConfigList() await getSeckillConfigList();
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -235,7 +267,7 @@
margin: -276rpx auto 0 auto; margin: -276rpx auto 0 auto;
border-radius: 14rpx; border-radius: 14rpx;
overflow: hidden; overflow: hidden;
swiper{ swiper {
height: 330rpx !important; height: 330rpx !important;
border-radius: 14rpx; border-radius: 14rpx;
overflow: hidden; overflow: hidden;
@ -246,7 +278,7 @@
height: 100%; height: 100%;
border-radius: 14rpx; border-radius: 14rpx;
overflow: hidden; overflow: hidden;
img{ img {
border-radius: 14rpx; border-radius: 14rpx;
} }
} }

View File

@ -25,7 +25,7 @@
<view class="item" v-for="(item, index) in state.signConfigList" :key="index"> <view class="item" v-for="(item, index) in state.signConfigList" :key="index">
<view <view
:class=" :class="
(index === state.signConfigList.length ? 'reward' : '') + (index === state.signConfigList.length ? 'reward' : '') +
' ' + ' ' +
(state.signInfo.continuousDay >= item.day ? 'rewardTxt' : '') (state.signInfo.continuousDay >= item.day ? 'rewardTxt' : '')
" "
@ -65,7 +65,7 @@
<!-- 签到说明 TODO @科举这里改成已累计签到 --> <!-- 签到说明 TODO @科举这里改成已累计签到 -->
<view class="bg-white ss-m-t-16 ss-p-t-30 ss-p-b-60 ss-p-x-40"> <view class="bg-white ss-m-t-16 ss-p-t-30 ss-p-b-60 ss-p-x-40">
<view class="activity-title ss-m-b-30">签到说明</view> <view class="activity-title ss-m-b-30">签到说明</view>
<view class="activity-des">1已累计签到{{state.signInfo.totalDay}}</view> <view class="activity-des">1已累计签到{{ state.signInfo.totalDay }}</view>
<view class="activity-des"> <view class="activity-des">
2据说连续签到第 {{ state.maxDay }} 天可获得超额积分一定要坚持签到哦~~~ 2据说连续签到第 {{ state.maxDay }} 天可获得超额积分一定要坚持签到哦~~~
</view> </view>
@ -110,7 +110,7 @@
signInfo: {}, // signInfo: {}, //
signConfigList: [], // signConfigList: [], //
maxDay: 0, // maxDay: 0, //
showModel: false, // showModel: false, //
signResult: {}, // signResult: {}, //

View File

@ -10,7 +10,6 @@
</template> </template>
<script setup> <script setup>
const props = defineProps({ const props = defineProps({
goodsData: { goodsData: {
type: Object, type: Object,
@ -18,4 +17,3 @@
}, },
}); });
</script> </script>

View File

@ -16,9 +16,7 @@
:class="{ 'is-active': toolsMode === 'tools' }" :class="{ 'is-active': toolsMode === 'tools' }"
@tap.stop="onTools('tools')" @tap.stop="onTools('tools')"
></text> ></text>
<button v-if="message" class="ss-reset-button send-btn" @tap="sendMessage"> <button v-if="message" class="ss-reset-button send-btn" @tap="sendMessage"> 发送 </button>
发送
</button>
</view> </view>
</template> </template>
@ -46,10 +44,9 @@
}, },
set(newValue) { set(newValue) {
emits(`update:modelValue`, newValue); emits(`update:modelValue`, newValue);
} },
}); });
// //
function onTools(mode) { function onTools(mode) {
emits('onTools', mode); emits('onTools', mode);

View File

@ -1,20 +1,35 @@
<template> <template>
<!-- 聊天虚拟列表 --> <!-- 聊天虚拟列表 -->
<z-paging ref="pagingRef" v-model="messageList" use-chat-record-mode use-virtual-list <z-paging
cell-height-mode="dynamic" default-page-size="20" :auto-clean-list-when-reload="false" ref="pagingRef"
safe-area-inset-bottom bottom-bg-color="#f8f8f8" :back-to-top-style="backToTopStyle" v-model="messageList"
:auto-show-back-to-top="showNewMessageTip" @backToTopClick="onBackToTopClick" use-chat-record-mode
@scrolltoupper="onScrollToUpper" @query="queryList"> use-virtual-list
cell-height-mode="dynamic"
default-page-size="20"
:auto-clean-list-when-reload="false"
safe-area-inset-bottom
bottom-bg-color="#f8f8f8"
:back-to-top-style="backToTopStyle"
:auto-show-back-to-top="showNewMessageTip"
@backToTopClick="onBackToTopClick"
@scrolltoupper="onScrollToUpper"
@query="queryList"
>
<template #top> <template #top>
<!-- 撑一下顶部导航 --> <!-- 撑一下顶部导航 -->
<view style="height: 45px"></view> <view style="height: 45px"></view>
</template> </template>
<!-- style="transform: scaleY(-1)"必须写否则会导致列表倒置 --> <!-- style="transform: scaleY(-1)"必须写否则会导致列表倒置 -->
<!-- 注意不要直接在chat-item组件标签上设置style因为在微信小程序中是无效的请包一层view --> <!-- 注意不要直接在chat-item组件标签上设置style因为在微信小程序中是无效的请包一层view -->
<template #cell="{item,index}"> <template #cell="{ item, index }">
<view style="transform: scaleY(-1)"> <view style="transform: scaleY(-1)">
<!-- 消息渲染 --> <!-- 消息渲染 -->
<MessageListItem :message="item" :message-index="index" :message-list="messageList"></MessageListItem> <MessageListItem
:message="item"
:message-index="index"
:message-list="messageList"
></MessageListItem>
</view> </view>
</template> </template>
<!-- 底部聊天输入框 --> <!-- 底部聊天输入框 -->
@ -37,13 +52,13 @@
const messageList = ref([]); // const messageList = ref([]); //
const showNewMessageTip = ref(false); // const showNewMessageTip = ref(false); //
const backToTopStyle = reactive({ const backToTopStyle = reactive({
'width': '100px', width: '100px',
'background-color': '#fff', 'background-color': '#fff',
'border-radius': '30px', 'border-radius': '30px',
'box-shadow': '0 2px 4px rgba(0, 0, 0, 0.1)', 'box-shadow': '0 2px 4px rgba(0, 0, 0, 0.1)',
'display': 'flex', display: 'flex',
'justifyContent': 'center', justifyContent: 'center',
'alignItems': 'center', alignItems: 'center',
}); // }); //
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1, pageNo: 1,

View File

@ -4,12 +4,20 @@
<view class="message-item ss-flex-col scroll-item"> <view class="message-item ss-flex-col scroll-item">
<view class="ss-flex ss-row-center ss-col-center"> <view class="ss-flex ss-row-center ss-col-center">
<!-- 日期 --> <!-- 日期 -->
<view v-if="message.contentType !== KeFuMessageContentTypeEnum.SYSTEM && showTime(message, messageIndex)" <view
class="date-message"> v-if="
message.contentType !== KeFuMessageContentTypeEnum.SYSTEM &&
showTime(message, messageIndex)
"
class="date-message"
>
{{ formatDate(message.createTime) }} {{ formatDate(message.createTime) }}
</view> </view>
<!-- 系统消息 --> <!-- 系统消息 -->
<view v-if="message.contentType === KeFuMessageContentTypeEnum.SYSTEM" class="system-message"> <view
v-if="message.contentType === KeFuMessageContentTypeEnum.SYSTEM"
class="system-message"
>
{{ message.content }} {{ message.content }}
</view> </view>
</view> </view>
@ -18,32 +26,35 @@
v-if="message.contentType !== KeFuMessageContentTypeEnum.SYSTEM" v-if="message.contentType !== KeFuMessageContentTypeEnum.SYSTEM"
class="ss-flex ss-col-top" class="ss-flex ss-col-top"
:class="[ :class="[
message.senderType === UserTypeEnum.ADMIN message.senderType === UserTypeEnum.ADMIN
? `ss-row-left` ? `ss-row-left`
: message.senderType === UserTypeEnum.MEMBER : message.senderType === UserTypeEnum.MEMBER
? `ss-row-right` ? `ss-row-right`
: '', : '',
]" ]"
> >
<!-- 客服头像 --> <!-- 客服头像 -->
<image <image
v-show="message.senderType === UserTypeEnum.ADMIN" v-show="message.senderType === UserTypeEnum.ADMIN"
class="chat-avatar ss-m-r-24" class="chat-avatar ss-m-r-24"
:src=" :src="
sheep.$url.cdn(message.senderAvatar) || sheep.$url.cdn(message.senderAvatar) ||
sheep.$url.static('/static/img/shop/chat/default.png') sheep.$url.static('/static/img/shop/chat/default.png')
" "
mode="aspectFill" mode="aspectFill"
></image> ></image>
<!-- 内容 --> <!-- 内容 -->
<template v-if="message.contentType === KeFuMessageContentTypeEnum.TEXT"> <template v-if="message.contentType === KeFuMessageContentTypeEnum.TEXT">
<view class="message-box" :class="{'admin': message.senderType === UserTypeEnum.ADMIN}"> <view class="message-box" :class="{ admin: message.senderType === UserTypeEnum.ADMIN }">
<mp-html :content="replaceEmoji(message.content)" /> <mp-html :content="replaceEmoji(message.content)" />
</view> </view>
</template> </template>
<template v-if="message.contentType === KeFuMessageContentTypeEnum.IMAGE"> <template v-if="message.contentType === KeFuMessageContentTypeEnum.IMAGE">
<view class="message-box" :class="{'admin': message.senderType === UserTypeEnum.ADMIN}" <view
:style="{ width: '200rpx' }"> class="message-box"
:class="{ admin: message.senderType === UserTypeEnum.ADMIN }"
:style="{ width: '200rpx' }"
>
<su-image <su-image
class="message-img" class="message-img"
isPreview isPreview
@ -60,28 +71,30 @@
<GoodsItem <GoodsItem
:goodsData="getMessageContent(message)" :goodsData="getMessageContent(message)"
@tap=" @tap="
sheep.$router.go('/pages/goods/index', { sheep.$router.go('/pages/goods/index', {
id: getMessageContent(message).id, id: getMessageContent(message).id,
}) })
" "
/> />
</template> </template>
<template v-if="message.contentType === KeFuMessageContentTypeEnum.ORDER"> <template v-if="message.contentType === KeFuMessageContentTypeEnum.ORDER">
<OrderItem <OrderItem
:orderData="getMessageContent(message)" :orderData="getMessageContent(message)"
@tap=" @tap="
sheep.$router.go('/pages/order/detail', { sheep.$router.go('/pages/order/detail', {
id: getMessageContent(message).id, id: getMessageContent(message).id,
}) })
" "
/> />
</template> </template>
<!-- user头像 --> <!-- user头像 -->
<image <image
v-if="message.senderType === UserTypeEnum.MEMBER" v-if="message.senderType === UserTypeEnum.MEMBER"
class="chat-avatar ss-m-l-24" class="chat-avatar ss-m-l-24"
:src="sheep.$url.cdn(message.senderAvatar) || :src="
sheep.$url.static('/static/img/shop/chat/default.png')" sheep.$url.cdn(message.senderAvatar) ||
sheep.$url.static('/static/img/shop/chat/default.png')
"
mode="aspectFill" mode="aspectFill"
> >
</image> </image>
@ -104,7 +117,7 @@
// //
message: { message: {
type: Object, type: Object,
default: ()=>({}), default: () => ({}),
}, },
// //
messageIndex: { messageIndex: {
@ -112,10 +125,10 @@
default: 0, default: 0,
}, },
// //
messageList:{ messageList: {
type: Array, type: Array,
default: () => [], default: () => [],
} },
}); });
const getMessageContent = computed(() => (item) => JSON.parse(item.content)); // const getMessageContent = computed(() => (item) => JSON.parse(item.content)); //

View File

@ -1,6 +1,5 @@
<template> <template>
<view class="bg-white order-list-card-box ss-r-10 ss-m-t-14 ss-m-20" <view class="bg-white order-list-card-box ss-r-10 ss-m-t-14 ss-m-20" :key="orderData.id">
:key="orderData.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">订单号{{ orderData.no }}</view> <view class="order-no">订单号{{ orderData.no }}</view>
<view class="order-state ss-font-26" :class="formatOrderColor(orderData)"> <view class="order-state ss-font-26" :class="formatOrderColor(orderData)">
@ -18,10 +17,10 @@
</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"> {{ orderData.productCount }} 件商品,总金额:</view> <view class="discounts-title pay-color"
<view class="discounts-money pay-color"> > {{ orderData.productCount }} 件商品,总金额:</view
{{ fen2yuan(orderData.payPrice) }} >
</view> <view class="discounts-money pay-color"> {{ fen2yuan(orderData.payPrice) }} </view>
</view> </view>
</view> </view>
</view> </view>
@ -48,7 +47,8 @@
font-weight: 500; font-weight: 500;
} }
.order-state {} .order-state {
}
} }
.pay-box { .pay-box {
.discounts-title { .discounts-title {

View File

@ -1,8 +1,5 @@
<template> <template>
<su-popup <su-popup :show="showTools" @close="handleClose">
:show="showTools"
@close="handleClose"
>
<view class="ss-modal-box ss-flex-col"> <view class="ss-modal-box ss-flex-col">
<slot></slot> <slot></slot>
<view class="content ss-flex ss-flex-1"> <view class="content ss-flex ss-flex-1">
@ -20,7 +17,8 @@
<swiper-item v-for="emoji in emojiPage" :key="emoji"> <swiper-item v-for="emoji in emojiPage" :key="emoji">
<view class="ss-flex ss-flex-wrap"> <view class="ss-flex ss-flex-wrap">
<image <image
v-for="item in emoji" :key="item" v-for="item in emoji"
:key="item"
class="emoji-img" class="emoji-img"
:src="sheep.$url.cdn(`/static/img/chat/emoji/${item.file}`)" :src="sheep.$url.cdn(`/static/img/chat/emoji/${item.file}`)"
@tap="onEmoji(item)" @tap="onEmoji(item)"

View File

@ -1,17 +1,35 @@
<template> <template>
<s-layout class="chat-wrap" :title="!isReconnecting ? '连接客服成功' : '会话重连中'" navbar="inner"> <s-layout
class="chat-wrap"
:title="!isReconnecting ? '连接客服成功' : '会话重连中'"
navbar="inner"
>
<!-- 覆盖头部导航栏背景颜色 --> <!-- 覆盖头部导航栏背景颜色 -->
<div class="page-bg" :style="{ height: sys_navBar + 'px' }"></div> <div class="page-bg" :style="{ height: sys_navBar + 'px' }"></div>
<!-- 聊天区域 --> <!-- 聊天区域 -->
<MessageList ref="messageListRef"> <MessageList ref="messageListRef">
<template #bottom> <template #bottom>
<message-input v-model="chat.msg" @on-tools="onTools" @send-message="onSendMessage"></message-input> <message-input
v-model="chat.msg"
@on-tools="onTools"
@send-message="onSendMessage"
></message-input>
</template> </template>
</MessageList> </MessageList>
<!-- 聊天工具 --> <!-- 聊天工具 -->
<tools-popup :show-tools="chat.showTools" :tools-mode="chat.toolsMode" @close="handleToolsClose" <tools-popup
@on-emoji="onEmoji" @image-select="onSelect" @on-show-select="onShowSelect"> :show-tools="chat.showTools"
<message-input v-model="chat.msg" @on-tools="onTools" @send-message="onSendMessage"></message-input> :tools-mode="chat.toolsMode"
@close="handleToolsClose"
@on-emoji="onEmoji"
@image-select="onSelect"
@on-show-select="onShowSelect"
>
<message-input
v-model="chat.msg"
@on-tools="onTools"
@send-message="onSendMessage"
></message-input>
</tools-popup> </tools-popup>
<!-- 商品订单选择 --> <!-- 商品订单选择 -->
<SelectPopup <SelectPopup
@ -30,7 +48,10 @@
import ToolsPopup from '@/pages/chat/components/toolsPopup.vue'; import ToolsPopup from '@/pages/chat/components/toolsPopup.vue';
import MessageInput from '@/pages/chat/components/messageInput.vue'; import MessageInput from '@/pages/chat/components/messageInput.vue';
import SelectPopup from '@/pages/chat/components/select-popup.vue'; import SelectPopup from '@/pages/chat/components/select-popup.vue';
import { KeFuMessageContentTypeEnum, WebSocketMessageTypeConstants } from '@/pages/chat/util/constants'; import {
KeFuMessageContentTypeEnum,
WebSocketMessageTypeConstants,
} from '@/pages/chat/util/constants';
import FileApi from '@/sheep/api/infra/file'; import FileApi from '@/sheep/api/infra/file';
import KeFuApi from '@/sheep/api/promotion/kefu'; import KeFuApi from '@/sheep/api/promotion/kefu';
import { useWebSocket } from '@/sheep/hooks/useWebSocket'; import { useWebSocket } from '@/sheep/hooks/useWebSocket';
@ -134,8 +155,7 @@
//======================= end ======================= //======================= end =======================
const { options } = useWebSocket({ const { options } = useWebSocket({
// //
onConnected: async () => { onConnected: async () => {},
},
// //
onMessage: async (data) => { onMessage: async (data) => {
const type = data.type; const type = data.type;
@ -160,7 +180,6 @@
<style scoped lang="scss"> <style scoped lang="scss">
.chat-wrap { .chat-wrap {
.page-bg { .page-bg {
width: 100%; width: 100%;
position: absolute; position: absolute;

View File

@ -5,8 +5,8 @@ export const KeFuMessageContentTypeEnum = {
VIDEO: 4, // 视频消息 VIDEO: 4, // 视频消息
SYSTEM: 5, // 系统消息 SYSTEM: 5, // 系统消息
// ========== 商城特殊消息 ========== // ========== 商城特殊消息 ==========
PRODUCT: 10,// 商品消息 PRODUCT: 10, // 商品消息
ORDER: 11,// 订单消息" ORDER: 11, // 订单消息"
}; };
export const UserTypeEnum = { export const UserTypeEnum = {
MEMBER: 1, // 会员 面向 c 端,普通用户 MEMBER: 1, // 会员 面向 c 端,普通用户
@ -15,5 +15,5 @@ export const UserTypeEnum = {
// Promotion 的 WebSocket 消息类型枚举类 // Promotion 的 WebSocket 消息类型枚举类
export const WebSocketMessageTypeConstants = { export const WebSocketMessageTypeConstants = {
KEFU_MESSAGE_TYPE: 'kefu_message_type', // 客服消息类型 KEFU_MESSAGE_TYPE: 'kefu_message_type', // 客服消息类型
KEFU_MESSAGE_ADMIN_READ: 'kefu_message_read_status_change' // 客服消息管理员已读 KEFU_MESSAGE_ADMIN_READ: 'kefu_message_read_status_change', // 客服消息管理员已读
} };

File diff suppressed because one or more lines are too long

View File

@ -63,7 +63,7 @@
onMounted(async () => { onMounted(async () => {
let { code, data } = await BrokerageApi.getBrokerageUserSummary(); let { code, data } = await BrokerageApi.getBrokerageUserSummary();
if (code === 0) { if (code === 0) {
state.summary = data || {} state.summary = data || {};
} }
}); });
</script> </script>
@ -122,4 +122,4 @@
} }
} }
} }
</style> </style>

View File

@ -45,7 +45,8 @@
type: Boolean, type: Boolean,
default: false, default: false,
}, },
methods: { // methods: {
//
type: Array, type: Array,
default: [], default: [],
}, },
@ -89,7 +90,7 @@
} }
// //
emits('update:modelValue', { emits('update:modelValue', {
type: state.currentValue type: state.currentValue,
}); });
// //
emits('close'); emits('close');

View File

@ -1,113 +1,112 @@
<!-- 分销商信息 --> <!-- 分销商信息 -->
<template> <template>
<!-- 用户资料 --> <!-- 用户资料 -->
<view class="user-card ss-flex ss-col-bottom"> <view class="user-card ss-flex ss-col-bottom">
<view class="card-top ss-flex ss-row-between"> <view class="card-top ss-flex ss-row-between">
<view class="ss-flex"> <view class="ss-flex">
<view class="head-img-box"> <view class="head-img-box">
<image class="head-img" :src="sheep.$url.cdn(userInfo.avatar)" mode="aspectFill"></image> <image class="head-img" :src="sheep.$url.cdn(userInfo.avatar)" mode="aspectFill"></image>
</view> </view>
<view class="ss-flex-col"> <view class="ss-flex-col">
<view class="user-name">{{ userInfo.nickname }}</view> <view class="user-name">{{ userInfo.nickname }}</view>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script setup> <script setup>
import sheep from '@/sheep'; import sheep from '@/sheep';
import { computed, reactive } from 'vue'; import { computed, reactive } from 'vue';
const userInfo = computed(() => sheep.$store('user').userInfo); const userInfo = computed(() => sheep.$store('user').userInfo);
const headerBg = sheep.$url.css('/static/img/shop/commission/background.png'); const headerBg = sheep.$url.css('/static/img/shop/commission/background.png');
const state = reactive({
showMoney: false,
});
const state = reactive({
showMoney: false,
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
// //
.user-card { .user-card {
width: 690rpx; width: 690rpx;
height: 192rpx; height: 192rpx;
margin: -88rpx 20rpx 0 20rpx; margin: -88rpx 20rpx 0 20rpx;
padding-top: 88rpx; padding-top: 88rpx;
background: v-bind(headerBg) no-repeat; background: v-bind(headerBg) no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
.head-img-box { .head-img-box {
margin-right: 20rpx; margin-right: 20rpx;
width: 100rpx; width: 100rpx;
height: 100rpx; height: 100rpx;
border-radius: 50%; border-radius: 50%;
position: relative; position: relative;
background: #fce0ad; background: #fce0ad;
.head-img { .head-img {
width: 92rpx; width: 92rpx;
height: 92rpx; height: 92rpx;
border-radius: 50%; border-radius: 50%;
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
} }
} }
.card-top { .card-top {
box-sizing: border-box; box-sizing: border-box;
padding-bottom: 34rpx; padding-bottom: 34rpx;
.user-name { .user-name {
font-size: 32rpx; font-size: 32rpx;
font-weight: bold; font-weight: bold;
color: #692e04; color: #692e04;
line-height: 30rpx; line-height: 30rpx;
margin-bottom: 20rpx; margin-bottom: 20rpx;
} }
.log-btn { .log-btn {
width: 84rpx; width: 84rpx;
height: 42rpx; height: 42rpx;
border: 2rpx solid rgba(#ffffff, 0.33); border: 2rpx solid rgba(#ffffff, 0.33);
border-radius: 21rpx; border-radius: 21rpx;
font-size: 22rpx; font-size: 22rpx;
font-weight: 400; font-weight: 400;
color: #ffffff; color: #ffffff;
margin-bottom: 20rpx; margin-bottom: 20rpx;
} }
.look-btn { .look-btn {
color: #fff; color: #fff;
width: 40rpx; width: 40rpx;
height: 40rpx; height: 40rpx;
} }
} }
.user-info-box { .user-info-box {
.tag-box { .tag-box {
background: #ff6000; background: #ff6000;
border-radius: 18rpx; border-radius: 18rpx;
line-height: 36rpx; line-height: 36rpx;
.tag-img { .tag-img {
width: 36rpx; width: 36rpx;
height: 36rpx; height: 36rpx;
border-radius: 50%; border-radius: 50%;
margin-left: -2rpx; margin-left: -2rpx;
} }
.tag-title { .tag-title {
font-size: 24rpx; font-size: 24rpx;
padding: 0 10rpx; padding: 0 10rpx;
font-weight: 500; font-weight: 500;
line-height: 36rpx; line-height: 36rpx;
color: #fff; color: #fff;
} }
} }
} }
} }
</style> </style>

View File

@ -1,74 +1,90 @@
<!-- 分销首页明细列表 --> <!-- 分销首页明细列表 -->
<template> <template>
<view class="distribution-log-wrap"> <view class="distribution-log-wrap">
<view class="header-box"> <view class="header-box">
<image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title2.png')" /> <image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title2.png')" />
<view class="ss-flex header-title"> <view class="ss-flex header-title">
<view class="title">实时动态</view> <view class="title">实时动态</view>
<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"
<view v-if="state.pagination.list"> @scrolltolower="loadmore"
<view class="log-item-box ss-flex ss-row-between" v-for="item in state.pagination.list" :key="item.id"> class="scroll-box log-scroll"
<view class="log-item-wrap"> scroll-with-animation="true"
<view class="log-item ss-flex ss-ellipsis-1 ss-col-center"> >
<view class="ss-flex ss-col-center"> <view v-if="state.pagination.list">
<image class="log-img" :src="sheep.$url.static('/static/img/shop/avatar/notice.png')" mode="aspectFill" /> <view
</view> class="log-item-box ss-flex ss-row-between"
<view class="log-text ss-ellipsis-1"> v-for="item in state.pagination.list"
:key="item.id"
>
<view class="log-item-wrap">
<view class="log-item ss-flex ss-ellipsis-1 ss-col-center">
<view class="ss-flex ss-col-center">
<image
class="log-img"
:src="sheep.$url.static('/static/img/shop/avatar/notice.png')"
mode="aspectFill"
/>
</view>
<view class="log-text ss-ellipsis-1">
{{ item.title }} {{ fen2yuan(item.price) }} {{ item.title }} {{ fen2yuan(item.price) }}
</view> </view>
</view> </view>
</view> </view>
<text class="log-time">{{ dayjs(item.createTime).fromNow() }}</text> <text class="log-time">{{ dayjs(item.createTime).fromNow() }}</text>
</view> </view>
</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"
</scroll-view> :status="state.loadStatus"
</view> color="#333333"
@tap="loadmore"
/>
</scroll-view>
</view>
</template> </template>
<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';
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';
const state = reactive({ const state = reactive({
loadStatus: '', loadStatus: '',
pagination: { pagination: {
list: [], list: [],
total: 0, total: 0,
pageNo: 1, pageNo: 1,
pageSize: 1, pageSize: 1,
}, },
}); });
async function getLog() { async function getLog() {
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;
} }
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';
} }
getLog(); getLog();
// //
function loadmore() { function loadmore() {
if (state.loadStatus === 'noMore') { if (state.loadStatus === 'noMore') {
return; return;
} }
@ -78,88 +94,88 @@
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.distribution-log-wrap { .distribution-log-wrap {
width: 690rpx; width: 690rpx;
margin: 0 auto; margin: 0 auto;
margin-bottom: 20rpx; margin-bottom: 20rpx;
border-radius: 12rpx; border-radius: 12rpx;
z-index: 3; z-index: 3;
position: relative; position: relative;
.header-box { .header-box {
width: 690rpx; width: 690rpx;
height: 76rpx; height: 76rpx;
position: relative; position: relative;
.header-bg { .header-bg {
width: 690rpx; width: 690rpx;
height: 76rpx; height: 76rpx;
} }
.header-title { .header-title {
position: absolute; position: absolute;
left: 20rpx; left: 20rpx;
top: 24rpx; top: 24rpx;
} }
.title { .title {
font-size: 28rpx; font-size: 28rpx;
font-weight: 500; font-weight: 500;
color: #ffffff; color: #ffffff;
line-height: 30rpx; line-height: 30rpx;
} }
.cicon-forward { .cicon-forward {
font-size: 30rpx; font-size: 30rpx;
font-weight: 400; font-weight: 400;
color: #ffffff; color: #ffffff;
line-height: 30rpx; line-height: 30rpx;
} }
} }
.log-scroll { .log-scroll {
height: 600rpx; height: 600rpx;
background: #fdfae9; background: #fdfae9;
padding: 10rpx 20rpx 0; padding: 10rpx 20rpx 0;
box-sizing: border-box; box-sizing: border-box;
border-radius: 0 0 12rpx 12rpx; border-radius: 0 0 12rpx 12rpx;
.log-item-box { .log-item-box {
margin-bottom: 20rpx; margin-bottom: 20rpx;
.log-time { .log-time {
// margin-left: 30rpx; // margin-left: 30rpx;
text-align: right; text-align: right;
font-size: 24rpx; font-size: 24rpx;
font-family: OPPOSANS; font-family: OPPOSANS;
font-weight: 400; font-weight: 400;
color: #c4c4c4; color: #c4c4c4;
} }
} }
.loadmore-wrap { .loadmore-wrap {
// line-height: 80rpx; // line-height: 80rpx;
} }
.log-item { .log-item {
// background: rgba(#ffffff, 0.2); // background: rgba(#ffffff, 0.2);
border-radius: 24rpx; border-radius: 24rpx;
padding: 6rpx 20rpx 6rpx 12rpx; padding: 6rpx 20rpx 6rpx 12rpx;
.log-img { .log-img {
width: 40rpx; width: 40rpx;
height: 40rpx; height: 40rpx;
border-radius: 50%; border-radius: 50%;
margin-right: 10rpx; margin-right: 10rpx;
} }
.log-text { .log-text {
max-width: 480rpx; max-width: 480rpx;
font-size: 24rpx; font-size: 24rpx;
font-weight: 500; font-weight: 500;
color: #333333; color: #333333;
} }
} }
} }
} }
</style> </style>

View File

@ -1,138 +1,147 @@
<!-- 分销商菜单栏 --> <!-- 分销商菜单栏 -->
<template> <template>
<view class="menu-box ss-flex-col"> <view class="menu-box ss-flex-col">
<view class="header-box"> <view class="header-box">
<image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title1.png')" /> <image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title1.png')" />
<view class="ss-flex header-title"> <view class="ss-flex header-title">
<view class="title">功能专区</view> <view class="title">功能专区</view>
<text class="cicon-forward"></text> <text class="cicon-forward"></text>
</view> </view>
</view> </view>
<view class="menu-list ss-flex ss-flex-wrap"> <view class="menu-list ss-flex ss-flex-wrap">
<view v-for="(item, index) in state.menuList" :key="index" class="item-box ss-flex-col ss-col-center" <view
@tap="sheep.$router.go(item.path)"> v-for="(item, index) in state.menuList"
<image class="menu-icon ss-m-b-10" :src="sheep.$url.static(item.img)" mode="aspectFill"></image> :key="index"
<view>{{ item.title }}</view> class="item-box ss-flex-col ss-col-center"
</view> @tap="sheep.$router.go(item.path)"
</view> >
</view> <image
class="menu-icon ss-m-b-10"
:src="sheep.$url.static(item.img)"
mode="aspectFill"
></image>
<view>{{ item.title }}</view>
</view>
</view>
</view>
</template> </template>
<script setup> <script setup>
import sheep from '@/sheep'; import sheep from '@/sheep';
import { reactive } from 'vue'; import { reactive } from 'vue';
const state = reactive({ const state = reactive({
menuList: [{ menuList: [
img: '/static/img/shop/commission/commission_icon1.png', {
title: '我的团队', img: '/static/img/shop/commission/commission_icon1.png',
path: '/pages/commission/team', title: '我的团队',
}, path: '/pages/commission/team',
{ },
img: '/static/img/shop/commission/commission_icon2.png', {
title: '佣金明细', img: '/static/img/shop/commission/commission_icon2.png',
path: '/pages/commission/wallet', title: '佣金明细',
}, path: '/pages/commission/wallet',
{ },
img: '/static/img/shop/commission/commission_icon3.png', {
title: '分销订单', img: '/static/img/shop/commission/commission_icon3.png',
path: '/pages/commission/order', title: '分销订单',
}, path: '/pages/commission/order',
{ },
img: '/static/img/shop/commission/commission_icon4.png', {
title: '推广商品', img: '/static/img/shop/commission/commission_icon4.png',
path: '/pages/commission/goods', title: '推广商品',
}, path: '/pages/commission/goods',
// { },
// img: '/static/img/shop/commission/commission_icon5.png', // {
// title: '', // img: '/static/img/shop/commission/commission_icon5.png',
// path: '/pages/commission/apply', // title: '',
// isAgentFrom: true, // path: '/pages/commission/apply',
// }, // isAgentFrom: true,
// todo @ // },
{ // todo @
img: '/static/img/shop/commission/commission_icon7.png', {
title: '邀请海报', img: '/static/img/shop/commission/commission_icon7.png',
path: 'action:showShareModal', title: '邀请海报',
}, path: 'action:showShareModal',
},
// TODO @ icon // TODO @ icon
{ {
// img: '/static/img/shop/commission/commission_icon7.png', // img: '/static/img/shop/commission/commission_icon7.png',
title: '推广排行', title: '推广排行',
path: '/pages/commission/promoter', path: '/pages/commission/promoter',
}, },
{ {
// img: '/static/img/shop/commission/commission_icon7.png', // img: '/static/img/shop/commission/commission_icon7.png',
title: '佣金排行', title: '佣金排行',
path: '/pages/commission/commission-ranking', path: '/pages/commission/commission-ranking',
} },
], ],
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.menu-box { .menu-box {
margin: 0 auto; margin: 0 auto;
width: 690rpx; width: 690rpx;
margin-bottom: 20rpx; margin-bottom: 20rpx;
margin-top: 20rpx; margin-top: 20rpx;
border-radius: 12rpx; border-radius: 12rpx;
z-index: 3; z-index: 3;
position: relative; position: relative;
} }
.header-box { .header-box {
width: 690rpx; width: 690rpx;
height: 76rpx; height: 76rpx;
position: relative; position: relative;
.header-bg { .header-bg {
width: 690rpx; width: 690rpx;
height: 76rpx; height: 76rpx;
} }
.header-title { .header-title {
position: absolute; position: absolute;
left: 20rpx; left: 20rpx;
top: 24rpx; top: 24rpx;
} }
.title { .title {
font-size: 28rpx; font-size: 28rpx;
font-weight: 500; font-weight: 500;
color: #ffffff; color: #ffffff;
line-height: 30rpx; line-height: 30rpx;
} }
.cicon-forward { .cicon-forward {
font-size: 30rpx; font-size: 30rpx;
font-weight: 400; font-weight: 400;
color: #ffffff; color: #ffffff;
line-height: 30rpx; line-height: 30rpx;
} }
} }
.menu-list { .menu-list {
padding: 50rpx 0 10rpx 0; padding: 50rpx 0 10rpx 0;
background: #fdfae9; background: #fdfae9;
border-radius: 0 0 12rpx 12rpx; border-radius: 0 0 12rpx 12rpx;
} }
.item-box { .item-box {
width: 25%; width: 25%;
margin-bottom: 40rpx; margin-bottom: 40rpx;
} }
.menu-icon { .menu-icon {
width: 68rpx; width: 68rpx;
height: 68rpx; height: 68rpx;
background: #ffffff; background: #ffffff;
border-radius: 50%; border-radius: 50%;
} }
.menu-title { .menu-title {
font-size: 26rpx; font-size: 26rpx;
font-weight: 500; font-weight: 500;
color: #ffffff; color: #ffffff;
} }
</style> </style>

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"

View File

@ -1,46 +1,55 @@
<!-- 分销中心 --> <!-- 分销中心 -->
<template> <template>
<s-layout navbar="inner" class="index-wrap" title="分销中心" :bgStyle="bgStyle" :onShareAppMessage="shareInfo"> <s-layout
<!-- 分销商信息 --> navbar="inner"
<commission-info /> class="index-wrap"
<!-- 账户信息 --> title="分销中心"
<account-info /> :bgStyle="bgStyle"
<!-- 菜单栏 --> :onShareAppMessage="shareInfo"
<commission-menu /> >
<!-- 分销记录 --> <!-- 分销商信息 -->
<commission-log /> <commission-info />
<!-- 账户信息 -->
<account-info />
<!-- 菜单栏 -->
<commission-menu />
<!-- 分销记录 -->
<commission-log />
<!-- 权限弹窗 --> <!-- 权限弹窗 -->
<commission-auth /> <commission-auth />
</s-layout> </s-layout>
</template> </template>
<script setup> <script setup>
import { computed } from 'vue'; import { computed } from 'vue';
import commissionInfo from './components/commission-info.vue'; import commissionInfo from './components/commission-info.vue';
import accountInfo from './components/account-info.vue'; import accountInfo from './components/account-info.vue';
import commissionLog from './components/commission-log.vue'; import commissionLog from './components/commission-log.vue';
import commissionMenu from './components/commission-menu.vue'; import commissionMenu from './components/commission-menu.vue';
import commissionAuth from './components/commission-auth.vue'; import commissionAuth from './components/commission-auth.vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
const shareInfo = computed(() => { const shareInfo = computed(() => {
return sheep.$platform.share.getShareInfo({ return sheep.$platform.share.getShareInfo(
params: { {
page: '6', params: {
page: '6',
},
}, },
}, { {
type: 'user', type: 'user',
}); },
);
}); });
const bgStyle = { const bgStyle = {
color: '#F7D598', color: '#F7D598',
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep(.page-main) { :deep(.page-main) {
background-size: 100% 100% !important; background-size: 100% 100% !important;
} }
</style> </style>

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>

File diff suppressed because one or more lines are too long

View File

@ -1,196 +1,243 @@
<!-- 分销 - 佣金明细 --> <!-- 分销 - 佣金明细 -->
<template> <template>
<s-layout class="wallet-wrap" title="佣金"> <s-layout class="wallet-wrap" title="佣金">
<!-- 钱包卡片 --> <!-- 钱包卡片 -->
<view class="header-box ss-flex ss-row-center ss-col-center"> <view class="header-box ss-flex ss-row-center ss-col-center">
<view class="card-box ui-BG-Main ui-Shadow-Main"> <view class="card-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"
</view> class="ss-eye-icon"
<view class="ss-flex ss-row-between ss-col-center ss-m-t-30"> :class="state.showMoney ? 'cicon-eye' : 'cicon-eye-off'"
<view class="money-num">{{ state.showMoney ? fen2yuan(state.summary.withdrawPrice || 0) : '*****' }}</view> />
<view class="ss-flex"> </view>
<view class="ss-m-r-20"> <view class="ss-flex ss-row-between ss-col-center ss-m-t-30">
<button class="ss-reset-button withdraw-btn" @tap="sheep.$router.go('/pages/commission/withdraw')"> <view class="money-num">{{
提现 state.showMoney ? fen2yuan(state.summary.withdrawPrice || 0) : '*****'
</button> }}</view>
</view> <view class="ss-flex">
<button class="ss-reset-button balance-btn ss-m-l-20" @tap="state.showModal = true"> <view class="ss-m-r-20">
转余额 <button
</button> class="ss-reset-button withdraw-btn"
</view> @tap="sheep.$router.go('/pages/commission/withdraw')"
</view> >
提现
</button>
</view>
<button class="ss-reset-button balance-btn ss-m-l-20" @tap="state.showModal = true">
转余额
</button>
</view>
</view>
<view class="ss-flex"> <view class="ss-flex">
<view class="loading-money"> <view class="loading-money">
<view class="loading-money-title">冻结佣金</view> <view class="loading-money-title">冻结佣金</view>
<view class="loading-money-num"> <view class="loading-money-num">
{{ state.showMoney ? fen2yuan(state.summary.frozenPrice || 0) : '*****' }} {{ state.showMoney ? fen2yuan(state.summary.frozenPrice || 0) : '*****' }}
</view> </view>
</view> </view>
<view class="loading-money ss-m-l-100"> <view class="loading-money ss-m-l-100">
<view class="loading-money-title">可提现佣金</view> <view class="loading-money-title">可提现佣金</view>
<view class="loading-money-num"> <view class="loading-money-num">
{{ state.showMoney ? fen2yuan(state.summary.brokeragePrice || 0) : '*****' }} {{ state.showMoney ? fen2yuan(state.summary.brokeragePrice || 0) : '*****' }}
</view> </view>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<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
<button class="ss-reset-button date-btn"> v-model="state.date"
<text>{{ dateFilterText }}</text> type="daterange"
<text class="cicon-drop-down ss-seldate-icon" /> @change="onChangeTime"
</button> :end="state.today"
</uni-datetime-picker> >
<button class="ss-reset-button date-btn">
<text>{{ dateFilterText }}</text>
<text class="cicon-drop-down ss-seldate-icon" />
</button>
</uni-datetime-picker>
<view class="total-box"> <view class="total-box">
<!-- TODO 芋艿这里暂时不考虑做 --> <!-- TODO 芋艿这里暂时不考虑做 -->
<!-- <view class="ss-m-b-10">总收入{{ state.pagination.income.toFixed(2) }}</view> --> <!-- <view class="ss-m-b-10">总收入{{ state.pagination.income.toFixed(2) }}</view> -->
<!-- <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
</su-sticky> :list="tabMaps"
<s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据"></s-empty> @change="onChangeTab"
:scrollable="false"
:current="state.currentTab"
/>
</su-sticky>
<s-empty
v-if="state.pagination.total === 0"
icon="/static/data-empty.png"
text="暂无数据"
></s-empty>
<!-- 转余额弹框 --> <!-- 转余额弹框 -->
<su-popup :show="state.showModal" type="bottom" round="20" @close="state.showModal = false" showClose> <su-popup
<view class="ss-p-x-20 ss-p-y-30"> :show="state.showModal"
<view class="model-title ss-m-b-30 ss-m-l-20">转余额</view> type="bottom"
<view class="model-subtitle ss-m-b-100 ss-m-l-20">将您的佣金转到余额中继续消费</view> round="20"
<view class="input-box ss-flex ss-col-center border-bottom ss-m-b-70 ss-m-x-20"> @close="state.showModal = false"
<view class="unit"></view> showClose
<uni-easyinput :inputBorder="false" class="ss-flex-1 ss-p-l-10" v-model="state.price" type="number" >
placeholder="请输入金额" /> <view class="ss-p-x-20 ss-p-y-30">
</view> <view class="model-title ss-m-b-30 ss-m-l-20">转余额</view>
<button class="ss-reset-button model-btn ui-BG-Main-Gradient ui-Shadow-Main" @tap="onConfirm"> <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">
</button> <view class="unit"></view>
</view> <uni-easyinput
</su-popup> :inputBorder="false"
class="ss-flex-1 ss-p-l-10"
v-model="state.price"
type="number"
placeholder="请输入金额"
/>
</view>
<button
class="ss-reset-button model-btn ui-BG-Main-Gradient ui-Shadow-Main"
@tap="onConfirm"
>
确定
</button>
</view>
</su-popup>
<!-- 钱包记录 --> <!-- 钱包记录 -->
<view v-if="state.pagination.total > 0"> <view 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
<view class="list-content"> class="wallet-list ss-flex border-bottom"
<view class="title-box ss-flex ss-row-between ss-m-b-20"> v-for="item in state.pagination.list"
<text class="title ss-line-1">{{ item.title }}</text> :key="item.id"
<view class="money"> >
<text v-if="item.price >= 0" class="add">+{{ fen2yuan(item.price) }}</text> <view class="list-content">
<text v-else class="minus">{{ fen2yuan(item.price) }}</text> <view class="title-box ss-flex ss-row-between ss-m-b-20">
</view> <text class="title ss-line-1">{{ item.title }}</text>
</view> <view class="money">
<text class="time">{{ sheep.$helper.timeFormat(item.createTime, 'yyyy-mm-dd hh:MM:ss') }}</text> <text v-if="item.price >= 0" class="add">+{{ fen2yuan(item.price) }}</text>
</view> <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>
</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>
<script setup> <script setup>
import { computed, reactive } from 'vue'; import { computed, 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 dayjs from 'dayjs'; import dayjs from 'dayjs';
import _ from 'lodash'; import _ from 'lodash';
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';
const headerBg = sheep.$url.css('/static/img/shop/user/wallet_card_bg.png'); const headerBg = sheep.$url.css('/static/img/shop/user/wallet_card_bg.png');
const state = reactive({ const state = reactive({
showMoney: false, showMoney: false,
summary: {}, // summary: {}, //
today: '', today: '',
date: [], date: [],
currentTab: 0, currentTab: 0,
pagination: { pagination: {
list: [], list: [],
total: 0, total: 0,
pageNo: 1, pageNo: 1,
pageSize: 1, pageSize: 1,
}, },
loadStatus: '', loadStatus: '',
price: undefined, price: undefined,
showModal: false, showModal: false,
}); });
const tabMaps = [{ const tabMaps = [
name: '分佣', {
value: '1', // BrokerageRecordBizTypeEnum.ORDER name: '分佣',
}, value: '1', // BrokerageRecordBizTypeEnum.ORDER
{ },
name: '提现', {
value: '2', // BrokerageRecordBizTypeEnum.WITHDRAW name: '提现',
} value: '2', // BrokerageRecordBizTypeEnum.WITHDRAW
]; },
];
const dateFilterText = computed(() => { const dateFilterText = computed(() => {
if (state.date[0] === state.date[1]) { if (state.date[0] === state.date[1]) {
return state.date[0]; return state.date[0];
} else { } else {
return state.date.join('~'); return state.date.join('~');
} }
}); });
async function getLogList() { async function getLogList() {
state.loadStatus = 'loading'; state.loadStatus = 'loading';
let { code, data } = await BrokerageApi.getBrokerageRecordPage({ let { code, data } = await BrokerageApi.getBrokerageRecordPage({
pageSize: state.pagination.pageSize, pageSize: state.pagination.pageSize,
pageNo: state.pagination.pageNo, pageNo: state.pagination.pageNo,
bizType: tabMaps[state.currentTab].value, bizType: tabMaps[state.currentTab].value,
'createTime[0]': state.date[0] + ' 00:00:00', 'createTime[0]': state.date[0] + ' 00:00:00',
'createTime[1]': state.date[1] + ' 23:59:59', 'createTime[1]': state.date[1] + ' 23:59:59',
}); });
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';
} }
function onChangeTab(e) { function onChangeTab(e) {
resetPagination(state.pagination);
state.currentTab = e.index;
getLogList();
}
function onChangeTime(e) {
state.date[0] = e[0];
state.date[1] = e[e.length - 1];
resetPagination(state.pagination); resetPagination(state.pagination);
getLogList(); state.currentTab = e.index;
} getLogList();
}
// function onChangeTime(e) {
async function onConfirm() { state.date[0] = e[0];
if (state.price <= 0) { state.date[1] = e[e.length - 1];
sheep.$helper.toast('请输入正确的金额'); resetPagination(state.pagination);
return; getLogList();
} }
uni.showModal({
title: '提示', //
content: '确认把您的佣金转入到余额钱包中?', async function onConfirm() {
success: async function(res) { if (state.price <= 0) {
if (!res.confirm) { sheep.$helper.toast('请输入正确的金额');
return;
}
uni.showModal({
title: '提示',
content: '确认把您的佣金转入到余额钱包中?',
success: async function (res) {
if (!res.confirm) {
return; return;
} }
const { code } = await BrokerageApi.createBrokerageWithdraw({ const { code } = await BrokerageApi.createBrokerageWithdraw({
type: 1, // type: 1, //
price: state.price * 100, price: state.price * 100,
@ -199,272 +246,273 @@
state.showModal = false; state.showModal = false;
await getAgentInfo(); await getAgentInfo();
onChangeTab({ onChangeTab({
index: 1 index: 1,
}); });
} }
} },
}); });
} }
async function getAgentInfo() { async function getAgentInfo() {
const { code, data } = await BrokerageApi.getBrokerageUserSummary(); const { code, data } = await BrokerageApi.getBrokerageUserSummary();
if (code !== 0) { if (code !== 0) {
return; return;
} }
state.summary = data; state.summary = data;
} }
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();
getAgentInfo(); getAgentInfo();
}); });
onReachBottom(() => { onReachBottom(() => {
if (state.loadStatus === 'noMore') { if (state.loadStatus === 'noMore') {
return; return;
} }
state.pagination.pageNo++; state.pagination.pageNo++;
getLogList(); getLogList();
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
// //
.header-box { .header-box {
background-color: $white; background-color: $white;
padding: 30rpx; padding: 30rpx;
.card-box { .card-box {
width: 100%; width: 100%;
min-height: 300rpx; min-height: 300rpx;
padding: 40rpx; padding: 40rpx;
background-size: 100% 100%; background-size: 100% 100%;
border-radius: 30rpx; border-radius: 30rpx;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
z-index: 1; z-index: 1;
box-sizing: border-box; box-sizing: border-box;
&::after { &::after {
content: ''; content: '';
display: block; display: block;
width: 100%; width: 100%;
height: 100%; height: 100%;
z-index: 2; z-index: 2;
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
background: v-bind(headerBg) no-repeat; background: v-bind(headerBg) no-repeat;
pointer-events: none; pointer-events: none;
} }
.card-head { .card-head {
color: $white; color: $white;
font-size: 24rpx; font-size: 24rpx;
} }
.ss-eye-icon { .ss-eye-icon {
font-size: 40rpx; font-size: 40rpx;
color: $white; color: $white;
} }
.money-num { .money-num {
font-size: 40rpx; font-size: 40rpx;
line-height: normal; line-height: normal;
font-weight: 500; font-weight: 500;
color: $white; color: $white;
font-family: OPPOSANS; font-family: OPPOSANS;
} }
.reduce-num { .reduce-num {
font-size: 26rpx; font-size: 26rpx;
font-weight: 400; font-weight: 400;
color: $white; color: $white;
} }
.withdraw-btn { .withdraw-btn {
width: 120rpx; width: 120rpx;
height: 60rpx; height: 60rpx;
line-height: 60rpx; line-height: 60rpx;
border-radius: 30px; border-radius: 30px;
font-size: 24rpx; font-size: 24rpx;
font-weight: 500; font-weight: 500;
background-color: $white; background-color: $white;
color: var(--ui-BG-Main); color: var(--ui-BG-Main);
} }
.balance-btn { .balance-btn {
width: 120rpx; width: 120rpx;
height: 60rpx; height: 60rpx;
line-height: 60rpx; line-height: 60rpx;
border-radius: 30px; border-radius: 30px;
font-size: 24rpx; font-size: 24rpx;
font-weight: 500; font-weight: 500;
color: $white; color: $white;
border: 1px solid $white; border: 1px solid $white;
} }
} }
} }
.loading-money { .loading-money {
margin-top: 56rpx; margin-top: 56rpx;
.loading-money-title { .loading-money-title {
font-size: 24rpx; font-size: 24rpx;
font-weight: 400; font-weight: 400;
color: #ffffff; color: #ffffff;
line-height: normal; line-height: normal;
margin-bottom: 30rpx; margin-bottom: 30rpx;
} }
.loading-money-num { .loading-money-num {
font-size: 30rpx; font-size: 30rpx;
font-family: OPPOSANS; font-family: OPPOSANS;
font-weight: 500; font-weight: 500;
color: #fefefe; color: #fefefe;
} }
} }
// //
.filter-box { .filter-box {
height: 120rpx; height: 120rpx;
padding: 0 30rpx; padding: 0 30rpx;
background-color: $bg-page; background-color: $bg-page;
.total-box { .total-box {
font-size: 24rpx; font-size: 24rpx;
font-weight: 500; font-weight: 500;
color: $dark-9; color: $dark-9;
} }
.date-btn { .date-btn {
background-color: $white; background-color: $white;
line-height: 54rpx; line-height: 54rpx;
border-radius: 27rpx; border-radius: 27rpx;
padding: 0 20rpx; padding: 0 20rpx;
font-size: 24rpx; font-size: 24rpx;
font-weight: 500; font-weight: 500;
color: $dark-6; color: $dark-6;
.ss-seldate-icon { .ss-seldate-icon {
font-size: 50rpx; font-size: 50rpx;
color: $dark-9; color: $dark-9;
} }
} }
} }
// tab // tab
.wallet-tab-card { .wallet-tab-card {
.tab-item { .tab-item {
height: 80rpx; height: 80rpx;
position: relative; position: relative;
.tab-title { .tab-title {
font-size: 30rpx; font-size: 30rpx;
} }
.cur-tab-title { .cur-tab-title {
font-weight: $font-weight-bold; font-weight: $font-weight-bold;
} }
.tab-line { .tab-line {
width: 60rpx; width: 60rpx;
height: 6rpx; height: 6rpx;
border-radius: 6rpx; border-radius: 6rpx;
position: absolute; position: absolute;
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
bottom: 2rpx; bottom: 2rpx;
background-color: var(--ui-BG-Main); background-color: var(--ui-BG-Main);
} }
} }
} }
// //
.wallet-list { .wallet-list {
padding: 30rpx; padding: 30rpx;
background-color: #ffff; background-color: #ffff;
.head-img { .head-img {
width: 70rpx; width: 70rpx;
height: 70rpx; height: 70rpx;
border-radius: 50%; border-radius: 50%;
background: $gray-c; background: $gray-c;
} }
.list-content { .list-content {
justify-content: space-between; justify-content: space-between;
align-items: flex-start; align-items: flex-start;
flex: 1; flex: 1;
.title { .title {
font-size: 28rpx; font-size: 28rpx;
color: $dark-3; color: $dark-3;
width: 400rpx; width: 400rpx;
} }
.time { .time {
color: $gray-c; color: $gray-c;
font-size: 22rpx; font-size: 22rpx;
} }
} }
.money { .money {
font-size: 28rpx; font-size: 28rpx;
font-weight: bold; font-weight: bold;
font-family: OPPOSANS; font-family: OPPOSANS;
.add { .add {
color: var(--ui-BG-Main); color: var(--ui-BG-Main);
} }
.minus { .minus {
color: $dark-3; color: $dark-3;
} }
} }
} }
.model-title { .model-title {
font-size: 36rpx; font-size: 36rpx;
font-weight: bold; font-weight: bold;
color: #333333; color: #333333;
} }
.model-subtitle { .model-subtitle {
font-size: 26rpx; font-size: 26rpx;
color: #c2c7cf; color: #c2c7cf;
} }
.model-btn { .model-btn {
width: 100%; width: 100%;
height: 80rpx; height: 80rpx;
border-radius: 40rpx; border-radius: 40rpx;
font-size: 28rpx; font-size: 28rpx;
font-weight: 500; font-weight: 500;
color: #ffffff; color: #ffffff;
line-height: normal; line-height: normal;
} }
.input-box { .input-box {
height: 100rpx; height: 100rpx;
.unit { .unit {
font-size: 48rpx; font-size: 48rpx;
color: #333; color: #333;
font-weight: 500; font-weight: 500;
line-height: normal; line-height: normal;
} }
.uni-easyinput__placeholder-class { .uni-easyinput__placeholder-class {
font-size: 30rpx; font-size: 30rpx;
height: 40rpx; height: 40rpx;
line-height: normal; line-height: normal;
} }
} }
</style> </style>

View File

@ -15,7 +15,10 @@
<view class="num-title">可提现金额</view> <view class="num-title">可提现金额</view>
<view class="wallet-num">{{ fen2yuan(state.brokerageInfo.brokeragePrice) }}</view> <view class="wallet-num">{{ fen2yuan(state.brokerageInfo.brokeragePrice) }}</view>
</view> </view>
<button class="ss-reset-button log-btn" @tap="sheep.$router.go('/pages/commission/wallet', { type: 2 })"> <button
class="ss-reset-button log-btn"
@tap="sheep.$router.go('/pages/commission/wallet', { type: 2 })"
>
提现记录 提现记录
</button> </button>
</view> </view>
@ -215,12 +218,12 @@
confirmText: '查看记录', confirmText: '查看记录',
success: (res) => { success: (res) => {
if (res.confirm) { if (res.confirm) {
sheep.$router.go('/pages/commission/wallet', { type: 2 }) sheep.$router.go('/pages/commission/wallet', { type: 2 });
return; return;
} }
getBrokerageUser(); getBrokerageUser();
state.accountInfo = {}; state.accountInfo = {};
} },
}); });
}; };
@ -247,8 +250,8 @@
onBeforeMount(() => { onBeforeMount(() => {
getWithdrawRules(); getWithdrawRules();
getBrokerageUser() getBrokerageUser();
}) });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

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 {{
? '减 ' + fen2yuan(state.coupon.discountPrice) + ' 元' state.coupon.discountType === 1
: '打 ' + state.coupon.discountPercent / 10.0 + ' 折' }} ? '减 ' + fen2yuan(state.coupon.discountPrice) + ' 元'
: '打 ' + 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">
@ -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,8 +236,10 @@
// //
async function getCouponContent() { async function getCouponContent() {
const { code, data } = state.id > 0 ? await CouponApi.getCouponTemplate(state.id) const { code, data } =
: await CouponApi.getCoupon(state.couponId); state.id > 0
? await CouponApi.getCouponTemplate(state.id)
: await CouponApi.getCoupon(state.couponId);
if (code !== 0) { if (code !== 0) {
return; return;
} }

View File

@ -45,7 +45,7 @@
<template #default> <template #default>
<button <button
class="ss-reset-button card-btn ss-flex ss-row-center ss-col-center" class="ss-reset-button card-btn ss-flex ss-row-center ss-col-center"
:class=" item.status !== 1 ? 'disabled-btn': ''" :class="item.status !== 1 ? 'disabled-btn' : ''"
:disabled="item.status !== 1" :disabled="item.status !== 1"
@click.stop="sheep.$router.go('/pages/coupon/detail', { couponId: item.id })" @click.stop="sheep.$router.go('/pages/coupon/detail', { couponId: item.id })"
> >
@ -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>
@ -78,7 +83,7 @@
list: [], list: [],
total: 0, total: 0,
pageNo: 1, pageNo: 1,
pageSize: 5 pageSize: 5,
}, },
loadStatus: '', loadStatus: '',
}); });
@ -106,9 +111,9 @@
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 {
getCoupon(); getCoupon();
} }
@ -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;
@ -177,13 +182,13 @@
// //
if (Option.type === 'all' || !Option.type) { if (Option.type === 'all' || !Option.type) {
getData(); getData();
// //
} else { } else {
Option.type === 'geted' Option.type === 'geted'
? (state.currentTab = 1) ? (state.currentTab = 1)
: Option.type === 'used' : Option.type === 'used'
? (state.currentTab = 2) ? (state.currentTab = 2)
: (state.currentTab = 3); : (state.currentTab = 3);
state.type = state.currentTab; state.type = state.currentTab;
getCoupon(); getCoupon();
} }

View File

@ -1,89 +1,99 @@
<!-- 评价 --> <!-- 评价 -->
<template> <template>
<s-layout title="评价"> <s-layout title="评价">
<view> <view>
<view v-for="(item, index) in state.orderInfo.items" :key="item.id"> <view v-for="(item, index) in state.orderInfo.items" :key="item.id">
<view> <view>
<view class="commont-from-wrap"> <view class="commont-from-wrap">
<!-- 评价商品 --> <!-- 评价商品 -->
<s-goods-item <s-goods-item
:img="item.picUrl" :img="item.picUrl"
:title="item.spuName" :title="item.spuName"
:skuText="item.properties.map((property) => property.valueName).join(' ')" :skuText="item.properties.map((property) => property.valueName).join(' ')"
:price="item.payPrice" :price="item.payPrice"
:num="item.count" :num="item.count"
/> />
</view> </view>
<view class="form-item"> <view class="form-item">
<!-- 评分 --> <!-- 评分 -->
<view class="star-box ss-flex ss-col-center"> <view class="star-box ss-flex ss-col-center">
<view class="star-title ss-m-r-40">商品质量</view> <view class="star-title ss-m-r-40">商品质量</view>
<uni-rate v-model="state.commentList[index].descriptionScores" /> <uni-rate v-model="state.commentList[index].descriptionScores" />
</view> </view>
<view class="star-box ss-flex ss-col-center"> <view class="star-box ss-flex ss-col-center">
<view class="star-title ss-m-r-40">服务态度</view> <view class="star-title ss-m-r-40">服务态度</view>
<uni-rate v-model="state.commentList[index].benefitScores" /> <uni-rate v-model="state.commentList[index].benefitScores" />
</view> </view>
<!-- 评价 --> <!-- 评价 -->
<view class="area-box"> <view class="area-box">
<uni-easyinput :inputBorder="false" type="textarea" maxlength="120" autoHeight <uni-easyinput
v-model="state.commentList[index].content" :inputBorder="false"
placeholder="宝贝满足你的期待吗?说说你的使用心得,分享给想买的他们吧~" /> type="textarea"
maxlength="120"
autoHeight
v-model="state.commentList[index].content"
placeholder="宝贝满足你的期待吗?说说你的使用心得,分享给想买的他们吧~"
/>
<!-- TODO 芋艿文件上传 --> <!-- TODO 芋艿文件上传 -->
<view class="img-box"> <view class="img-box">
<s-uploader v-model:url="state.commentList[index].images" fileMediatype="image" <s-uploader
limit="9" mode="grid" :imageStyles="{ width: '168rpx', height: '168rpx' }" /> v-model:url="state.commentList[index].images"
</view> fileMediatype="image"
</view> limit="9"
</view> mode="grid"
</view> :imageStyles="{ width: '168rpx', height: '168rpx' }"
</view> />
</view> </view>
</view>
</view>
</view>
</view>
</view>
<!-- TODO 芋艿是否匿名 --> <!-- TODO 芋艿是否匿名 -->
<su-fixed bottom placeholder> <su-fixed bottom placeholder>
<view class="foot_box ss-flex ss-row-center ss-col-center"> <view class="foot_box ss-flex ss-row-center ss-col-center">
<button class="ss-reset-button post-btn ui-BG-Main-Gradient ui-Shadow-Main" @tap="onSubmit"> <button class="ss-reset-button post-btn ui-BG-Main-Gradient ui-Shadow-Main" @tap="onSubmit">
发布 发布
</button> </button>
</view> </view>
</su-fixed> </su-fixed>
</s-layout> </s-layout>
</template> </template>
<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 } from 'vue';
import OrderApi from '@/sheep/api/trade/order'; import OrderApi from '@/sheep/api/trade/order';
const state = reactive({ const state = reactive({
orderInfo: {}, orderInfo: {},
commentList: [], commentList: [],
id: null id: null,
}); });
async function onSubmit() { async function onSubmit() {
// //
for (const comment of state.commentList) { for (const comment of state.commentList) {
await OrderApi.createOrderItemComment(comment); await OrderApi.createOrderItemComment(comment);
} }
// //
sheep.$router.back(); sheep.$router.back();
} }
onLoad(async (options) => { onLoad(async (options) => {
if (!options.id) { if (!options.id) {
sheep.$helper.toast(`缺少订单信息,请检查`); sheep.$helper.toast(`缺少订单信息,请检查`);
return return;
} }
state.id = options.id; state.id = options.id;
const { code, data } = await OrderApi.getOrder(state.id); const { code, data } = await OrderApi.getOrder(state.id);
if (code !== 0) { if (code !== 0) {
sheep.$helper.toast('无待评价订单'); sheep.$helper.toast('无待评价订单');
return return;
} }
// //
data.items.forEach((item) => { data.items.forEach((item) => {
@ -93,53 +103,53 @@
descriptionScores: 5, descriptionScores: 5,
benefitScores: 5, benefitScores: 5,
content: '', content: '',
picUrls: [] picUrls: [],
}); });
}); });
state.orderInfo = data; state.orderInfo = data;
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
// //
.goods-card { .goods-card {
margin: 10rpx 0; margin: 10rpx 0;
padding: 20rpx; padding: 20rpx;
background: #fff; background: #fff;
} }
// //
.form-item { .form-item {
background: #fff; background: #fff;
.star-box { .star-box {
height: 100rpx; height: 100rpx;
padding: 0 25rpx; padding: 0 25rpx;
} }
.star-title { .star-title {
font-weight: 600; font-weight: 600;
} }
} }
.area-box { .area-box {
width: 690rpx; width: 690rpx;
min-height: 306rpx; min-height: 306rpx;
background: rgba(249, 250, 251, 1); background: rgba(249, 250, 251, 1);
border-radius: 20rpx; border-radius: 20rpx;
padding: 28rpx; padding: 28rpx;
margin: auto; margin: auto;
.img-box { .img-box {
margin-top: 20rpx; margin-top: 20rpx;
} }
} }
.post-btn { .post-btn {
width: 690rpx; width: 690rpx;
line-height: 80rpx; line-height: 80rpx;
border-radius: 40rpx; border-radius: 40rpx;
color: rgba(#fff, 0.9); color: rgba(#fff, 0.9);
margin-bottom: 20rpx; margin-bottom: 20rpx;
} }
</style> </style>

View File

@ -42,14 +42,13 @@
type: Array, type: Array,
default() { default() {
return []; return [];
} },
} },
}); });
function onActivity(activity) { function onActivity(activity) {
const type = activity.type; const type = activity.type;
const typePath = type === 1 ? 'seckill' : const typePath = type === 1 ? 'seckill' : type === 2 ? 'TODO 拼团' : 'groupon';
type === 2 ? 'TODO 拼团' : 'groupon';
sheep.$router.go(`/pages/goods/${typePath}`, { sheep.$router.go(`/pages/goods/${typePath}`, {
id: activity.id, id: activity.id,
}); });

View File

@ -15,15 +15,15 @@
}, },
}, },
sku: { sku: {
type: Object type: Object,
} },
}); });
const value = computed(() => { const value = computed(() => {
if (!props.sku?.id) { if (!props.sku?.id) {
return '请选择商品规格'; return '请选择商品规格';
} }
let str = ''; let str = '';
props.sku.properties.forEach(property => { props.sku.properties.forEach((property) => {
str += property.propertyName + ':' + property.valueName + ' '; str += property.propertyName + ':' + property.valueName + ' ';
}); });
return str; return str;

View File

@ -98,7 +98,8 @@
function getCommentCardNode() { function getCommentCardNode() {
return new Promise((res, rej) => { return new Promise((res, rej) => {
uni.createSelectorQuery() uni
.createSelectorQuery()
.select('.detail-comment-selector') .select('.detail-comment-selector')
.boundingClientRect((data) => { .boundingClientRect((data) => {
if (data) { if (data) {

View File

@ -119,15 +119,15 @@
if (props.modelValue.favorite) { if (props.modelValue.favorite) {
const { code } = await FavoriteApi.deleteFavorite(props.modelValue.id); const { code } = await FavoriteApi.deleteFavorite(props.modelValue.id);
if (code !== 0) { if (code !== 0) {
return return;
} }
sheep.$helper.toast('取消收藏'); sheep.$helper.toast('取消收藏');
props.modelValue.favorite = false; props.modelValue.favorite = false;
// //
} else { } else {
const { code } = await FavoriteApi.createFavorite(props.modelValue.id); const { code } = await FavoriteApi.createFavorite(props.modelValue.id);
if (code !== 0) { if (code !== 0) {
return return;
} }
sheep.$helper.toast('收藏成功'); sheep.$helper.toast('收藏成功');
props.modelValue.favorite = true; props.modelValue.favorite = true;

View File

@ -37,7 +37,7 @@
import { onMounted, reactive } from 'vue'; import { onMounted, reactive } from 'vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import { useDurationTime } from '@/sheep/hooks/useGoods'; import { useDurationTime } from '@/sheep/hooks/useGoods';
import CombinationApi from "@/sheep/api/promotion/combination"; import CombinationApi from '@/sheep/api/promotion/combination';
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {
@ -74,7 +74,7 @@
onMounted(async () => { onMounted(async () => {
// //
// status = 0 // status = 0
const { data } = await CombinationApi.getHeadCombinationRecordList(props.modelValue.id, 0 , 10); const { data } = await CombinationApi.getHeadCombinationRecordList(props.modelValue.id, 0, 10);
state.list = data; state.list = data;
}); });
</script> </script>

View File

@ -7,12 +7,16 @@
<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="
text="活动不存在或已结束" state.goodsInfo === null ||
icon="/static/soldout-empty.png" state.activity.status !== 0 ||
showAction state.activity.endTime < new Date().getTime()
actionText="返回上一页" "
@clickAction="sheep.$router.back()" text="活动不存在或已结束"
icon="/static/soldout-empty.png"
showAction
actionText="返回上一页"
@clickAction="sheep.$router.back()"
/> />
<block v-else> <block v-else>
<view class="detail-swiper-selector"> <view class="detail-swiper-selector">
@ -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) }}
@ -123,7 +124,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.activity.price || 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>
@ -149,29 +152,27 @@
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 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(() => {});
const state = reactive({ const state = reactive({
skeletonLoading: true, // skeletonLoading: true, //
goodsId: 0, // ID goodsId: 0, // ID
goodsInfo: {}, // goodsInfo: {}, //
goodsSwiper: [], // goodsSwiper: [], //
showSelectSku: false, // showSelectSku: false, //
selectedSkuPrice: {}, // selectedSkuPrice: {}, //
activity: {}, // activity: {}, //
grouponId: 0, // ID grouponId: 0, // ID
grouponNum: 0, // grouponNum: 0, //
grouponAction: 'create', // grouponAction: 'create', //
combinationHeadId: null, // combinationHeadId: null, //
}); });
@ -261,7 +262,7 @@
// //
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
}); });
// //
@ -475,8 +476,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

@ -1,177 +1,227 @@
<template> <template>
<view> <view>
<s-layout :onShareAppMessage="shareInfo" navbar="goods"> <s-layout :onShareAppMessage="shareInfo" navbar="goods">
<!-- 标题栏 --> <!-- 标题栏 -->
<detailNavbar /> <detailNavbar />
<!-- 骨架屏 --> <!-- 骨架屏 -->
<detailSkeleton v-if="state.skeletonLoading" /> <detailSkeleton v-if="state.skeletonLoading" />
<!-- 下架/售罄提醒 --> <!-- 下架/售罄提醒 -->
<s-empty v-else-if="state.goodsInfo === null" text="商品不存在或已下架" icon="/static/soldout-empty.png" showAction <s-empty
actionText="再逛逛" actionUrl="/pages/goods/list" /> v-else-if="state.goodsInfo === null"
<block v-else> text="商品不存在或已下架"
<view class="detail-swiper-selector"> icon="/static/soldout-empty.png"
<!-- 商品轮播图 --> showAction
<su-swiper class="ss-m-b-14" isPreview :list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)" actionText="再逛逛"
otStyle="tag" imageMode="widthFix" dotCur="bg-mask-40" :seizeHeight="750" /> actionUrl="/pages/goods/list"
/>
<block v-else>
<view class="detail-swiper-selector">
<!-- 商品轮播图 -->
<su-swiper
class="ss-m-b-14"
isPreview
:list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)"
otStyle="tag"
imageMode="widthFix"
dotCur="bg-mask-40"
:seizeHeight="750"
/>
<!-- 价格+标题 --> <!-- 价格+标题 -->
<view class="title-card detail-card ss-p-y-40 ss-p-x-20"> <view class="title-card detail-card ss-p-y-40 ss-p-x-20">
<view class="ss-flex ss-row-between ss-col-center ss-m-b-26"> <view class="ss-flex ss-row-between ss-col-center ss-m-b-26">
<view class="price-box ss-flex ss-col-bottom"> <view class="price-box ss-flex ss-col-bottom">
<view class="price-text ss-m-r-16"> <view class="price-text ss-m-r-16">
{{ fen2yuan(state.selectedSku.price || state.goodsInfo.price) }} {{ fen2yuan(state.selectedSku.price || state.goodsInfo.price) }}
</view> </view>
<view class="origin-price-text" v-if="state.goodsInfo.marketPrice > 0"> <view class="origin-price-text" v-if="state.goodsInfo.marketPrice > 0">
{{ fen2yuan(state.selectedSku.marketPrice || state.goodsInfo.marketPrice) }} {{ fen2yuan(state.selectedSku.marketPrice || state.goodsInfo.marketPrice) }}
</view> </view>
</view> </view>
<view class="sales-text"> <view class="sales-text">
{{ formatSales('exact', state.goodsInfo.salesCount) }} {{ formatSales('exact', state.goodsInfo.salesCount) }}
</view> </view>
</view> </view>
<view class="discounts-box ss-flex ss-row-between ss-m-b-28"> <view class="discounts-box ss-flex ss-row-between ss-m-b-28">
<!-- 满减送/限时折扣活动的提示 --> <!-- 满减送/限时折扣活动的提示 -->
<div class="tag-content"> <div class="tag-content">
<view class="tag-box ss-flex"> <view class="tag-box ss-flex">
<view class="tag ss-m-r-10" v-for="promos in state.activityInfo" <view
:key="promos.id" @tap="onActivity"> class="tag ss-m-r-10"
{{ promos.name }} v-for="promos in state.activityInfo"
</view> :key="promos.id"
</view> @tap="onActivity"
</div> >
{{ promos.name }}
</view>
</view>
</div>
<!-- 优惠劵 --> <!-- 优惠劵 -->
<view class="get-coupon-box ss-flex ss-col-center ss-m-l-20" @tap="state.showModel = true" <view
v-if="state.couponInfo.length"> class="get-coupon-box ss-flex ss-col-center ss-m-l-20"
<view class="discounts-title ss-m-r-8">领券</view> @tap="state.showModel = true"
<text class="cicon-forward"></text> v-if="state.couponInfo.length"
</view> >
</view> <view class="discounts-title ss-m-r-8">领券</view>
<view class="title-text ss-line-2 ss-m-b-6">{{ state.goodsInfo.name }}</view> <text class="cicon-forward"></text>
<view class="subtitle-text ss-line-1">{{ state.goodsInfo.introduction }}</view> </view>
</view> </view>
<view class="title-text ss-line-2 ss-m-b-6">{{ state.goodsInfo.name }}</view>
<view class="subtitle-text ss-line-1">{{ state.goodsInfo.introduction }}</view>
</view>
<!-- 功能卡片 --> <!-- 功能卡片 -->
<view class="detail-cell-card detail-card ss-flex-col"> <view class="detail-cell-card detail-card ss-flex-col">
<detail-cell-sku v-model="state.selectedSku.goods_sku_text" :sku="state.selectedSku" <detail-cell-sku
@tap="state.showSelectSku = true" /> v-model="state.selectedSku.goods_sku_text"
</view> :sku="state.selectedSku"
@tap="state.showSelectSku = true"
/>
</view>
<!-- 规格与数量弹框 --> <!-- 规格与数量弹框 -->
<s-select-sku :goodsInfo="state.goodsInfo" :show="state.showSelectSku" @addCart="onAddCart" <s-select-sku
@buy="onBuy" @change="onSkuChange" @close="state.showSelectSku = false" /> :goodsInfo="state.goodsInfo"
</view> :show="state.showSelectSku"
@addCart="onAddCart"
@buy="onBuy"
@change="onSkuChange"
@close="state.showSelectSku = false"
/>
</view>
<!-- 评价 --> <!-- 评价 -->
<detail-comment-card class="detail-comment-selector" :goodsId="state.goodsId" /> <detail-comment-card class="detail-comment-selector" :goodsId="state.goodsId" />
<!-- 详情 --> <!-- 详情 -->
<detail-content-card class="detail-content-selector" :content="state.goodsInfo.description" /> <detail-content-card
class="detail-content-selector"
:content="state.goodsInfo.description"
/>
<!-- 活动跳转拼团/秒杀/砍价活动 --> <!-- 活动跳转拼团/秒杀/砍价活动 -->
<detail-activity-tip v-if="state.activityList.length > 0" :activity-list="state.activityList" /> <detail-activity-tip
v-if="state.activityList.length > 0"
:activity-list="state.activityList"
/>
<!-- 详情 tabbar --> <!-- 详情 tabbar -->
<detail-tabbar v-model="state.goodsInfo"> <detail-tabbar v-model="state.goodsInfo">
<view class="buy-box ss-flex ss-col-center ss-p-r-20" v-if="state.goodsInfo.stock > 0"> <view class="buy-box ss-flex ss-col-center ss-p-r-20" v-if="state.goodsInfo.stock > 0">
<button class="ss-reset-button add-btn ui-Shadow-Main" @tap="state.showSelectSku = true"> <button
加入购物车 class="ss-reset-button add-btn ui-Shadow-Main"
</button> @tap="state.showSelectSku = true"
<button class="ss-reset-button buy-btn ui-Shadow-Main" @tap="state.showSelectSku = true"> >
立即购买 加入购物车
</button> </button>
</view> <button
<view class="buy-box ss-flex ss-col-center ss-p-r-20" v-else> class="ss-reset-button buy-btn ui-Shadow-Main"
<button class="ss-reset-button disabled-btn" disabled> 已售罄 </button> @tap="state.showSelectSku = true"
</view> >
</detail-tabbar> 立即购买
</button>
</view>
<view class="buy-box ss-flex ss-col-center ss-p-r-20" v-else>
<button class="ss-reset-button disabled-btn" disabled> 已售罄 </button>
</view>
</detail-tabbar>
<!-- 优惠劵弹窗 --> <!-- 优惠劵弹窗 -->
<s-coupon-get v-model="state.couponInfo" :show="state.showModel" @close="state.showModel = false" <s-coupon-get
@get="onGet" /> v-model="state.couponInfo"
:show="state.showModel"
@close="state.showModel = false"
@get="onGet"
/>
<!-- 满减送/限时折扣活动弹窗 --> <!-- 满减送/限时折扣活动弹窗 -->
<s-activity-pop v-model="state.activityInfo" :show="state.showActivityModel" <s-activity-pop
@close="state.showActivityModel = false" /> v-model="state.activityInfo"
</block> :show="state.showActivityModel"
</s-layout> @close="state.showActivityModel = false"
</view> />
</block>
</s-layout>
</view>
</template> </template>
<script setup> <script setup>
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 CouponApi from '@/sheep/api/promotion/coupon'; import CouponApi from '@/sheep/api/promotion/coupon';
import ActivityApi from '@/sheep/api/promotion/activity'; import ActivityApi from '@/sheep/api/promotion/activity';
import FavoriteApi from '@/sheep/api/product/favorite'; import FavoriteApi from '@/sheep/api/product/favorite';
import { formatSales, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods'; import { formatSales, 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';
import detailTabbar from './components/detail/detail-tabbar.vue'; import detailTabbar from './components/detail/detail-tabbar.vue';
import detailSkeleton from './components/detail/detail-skeleton.vue'; import detailSkeleton from './components/detail/detail-skeleton.vue';
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';
import SpuApi from '@/sheep/api/product/spu'; import SpuApi from '@/sheep/api/product/spu';
onPageScroll(() => {}); onPageScroll(() => {});
const isLogin = computed(() => sheep.$store('user').isLogin); const isLogin = computed(() => sheep.$store('user').isLogin);
const state = reactive({ const state = reactive({
goodsId: 0, goodsId: 0,
skeletonLoading: true, // SPU skeletonLoading: true, // SPU
goodsInfo: {}, // SPU goodsInfo: {}, // SPU
showSelectSku: false, // SKU showSelectSku: false, // SKU
selectedSku: {}, // SKU selectedSku: {}, // SKU
showModel: false, // Coupon showModel: false, // Coupon
couponInfo: [], // Coupon couponInfo: [], // Coupon
showActivityModel: false, // / Activity showActivityModel: false, // / Activity
activityInfo: [], // / Activity activityInfo: [], // / Activity
activityList: [], // // Activity activityList: [], // // Activity
}); });
// //
function onSkuChange(e) { function onSkuChange(e) {
state.selectedSku = e; state.selectedSku = e;
} }
// //
function onAddCart(e) { function onAddCart(e) {
if (!e.id) { if (!e.id) {
sheep.$helper.toast('请选择商品规格'); sheep.$helper.toast('请选择商品规格');
return; return;
} }
sheep.$store('cart').add(e); sheep.$store('cart').add(e);
} }
// //
function onBuy(e) { function onBuy(e) {
if (!state.selectedSku.id) { if (!state.selectedSku.id) {
sheep.$helper.toast('请选择商品规格'); sheep.$helper.toast('请选择商品规格');
return; return;
} }
sheep.$router.go('/pages/order/confirm', { sheep.$router.go('/pages/order/confirm', {
data: JSON.stringify({ data: JSON.stringify({
items: [{ items: [
skuId: e.id, {
count: e.goods_num skuId: e.id,
}], count: e.goods_num,
},
],
// TODO 2 // TODO 2
deliveryType: 1, deliveryType: 1,
pointStatus: false, pointStatus: false,
}), }),
}); });
} }
// //
function onActivity() { function onActivity() {
state.showActivityModel = true; state.showActivityModel = true;
} }
// //
async function onGet(id) { async function onGet(id) {
const { code } = await CouponApi.takeCoupon(id); const { code } = await CouponApi.takeCoupon(id);
if (code !== 0) { if (code !== 0) {
return; return;
@ -182,27 +232,30 @@
setTimeout(() => { setTimeout(() => {
getCoupon(); getCoupon();
}, 1000); }, 1000);
} }
// TODO // TODO
const shareInfo = computed(() => { const shareInfo = computed(() => {
if (isEmpty(state.goodsInfo)) return {}; if (isEmpty(state.goodsInfo)) return {};
return sheep.$platform.share.getShareInfo({ return sheep.$platform.share.getShareInfo(
title: state.goodsInfo.name, {
image: sheep.$url.cdn(state.goodsInfo.picUrl), title: state.goodsInfo.name,
desc: state.goodsInfo.introduction, image: sheep.$url.cdn(state.goodsInfo.picUrl),
params: { desc: state.goodsInfo.introduction,
page: '2', params: {
query: state.goodsInfo.id, page: '2',
}, query: state.goodsInfo.id,
}, { },
type: 'goods', // },
title: state.goodsInfo.name, // {
image: sheep.$url.cdn(state.goodsInfo.picUrl), // type: 'goods', //
price: fen2yuan(state.goodsInfo.price), // title: state.goodsInfo.name, //
original_price: fen2yuan(state.goodsInfo.marketPrice), // image: sheep.$url.cdn(state.goodsInfo.picUrl), //
}); price: fen2yuan(state.goodsInfo.price), //
}); original_price: fen2yuan(state.goodsInfo.marketPrice), //
},
);
});
async function getCoupon() { async function getCoupon() {
const { code, data } = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10); const { code, data } = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10);
@ -211,23 +264,23 @@
} }
} }
onLoad((options) => { onLoad((options) => {
// //
if (!options.id) { if (!options.id) {
state.goodsInfo = null; state.goodsInfo = null;
return; return;
} }
state.goodsId = options.id; state.goodsId = options.id;
// 1. // 1.
SpuApi.getSpuDetail(state.goodsId).then((res) => { SpuApi.getSpuDetail(state.goodsId).then((res) => {
// //
if (res.code !== 0 || !res.data) { if (res.code !== 0 || !res.data) {
state.goodsInfo = null; state.goodsInfo = null;
return; return;
} }
// //
state.skeletonLoading = false; state.skeletonLoading = false;
state.goodsInfo = res.data; state.goodsInfo = res.data;
// //
if (isLogin.value) { if (isLogin.value) {
@ -238,172 +291,175 @@
state.goodsInfo.favorite = res.data; state.goodsInfo.favorite = res.data;
}); });
} }
}); });
// 2. // 2.
getCoupon(); getCoupon();
// 3. // 3.
ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => { ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
if (res.code !== 0) { if (res.code !== 0) {
return; return;
} }
res.data.forEach(activity => { res.data.forEach((activity) => {
if ([1, 2, 3].includes(activity.type)) { // // if ([1, 2, 3].includes(activity.type)) {
// //
state.activityList.push(activity); state.activityList.push(activity);
} else if (activity.type === 5) { // } else if (activity.type === 5) {
//
state.activityInfo.push(activity); state.activityInfo.push(activity);
} else { // TODO } else {
// TODO
console.log('待实现!优先级不高'); console.log('待实现!优先级不高');
} }
}) });
}); });
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.detail-card { .detail-card {
background-color: #ffff; background-color: #ffff;
margin: 14rpx 20rpx; margin: 14rpx 20rpx;
border-radius: 10rpx; border-radius: 10rpx;
overflow: hidden; overflow: hidden;
} }
// //
.title-card { .title-card {
.price-box { .price-box {
.price-text { .price-text {
font-size: 42rpx; font-size: 42rpx;
font-weight: 500; font-weight: 500;
color: #ff3000; color: #ff3000;
line-height: 30rpx; line-height: 30rpx;
font-family: OPPOSANS; font-family: OPPOSANS;
&::before { &::before {
content: '¥'; content: '¥';
font-size: 30rpx; font-size: 30rpx;
} }
} }
.origin-price-text { .origin-price-text {
font-size: 26rpx; font-size: 26rpx;
font-weight: 400; font-weight: 400;
text-decoration: line-through; text-decoration: line-through;
color: $gray-c; color: $gray-c;
font-family: OPPOSANS; font-family: OPPOSANS;
&::before { &::before {
content: '¥'; content: '¥';
} }
} }
} }
.sales-text { .sales-text {
font-size: 26rpx; font-size: 26rpx;
font-weight: 500; font-weight: 500;
color: $gray-c; color: $gray-c;
} }
.discounts-box { .discounts-box {
.tag-content { .tag-content {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
white-space: nowrap; white-space: nowrap;
} }
.tag-box { .tag-box {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.tag { .tag {
flex-shrink: 0; flex-shrink: 0;
padding: 4rpx 10rpx; padding: 4rpx 10rpx;
font-size: 24rpx; font-size: 24rpx;
font-weight: 500; font-weight: 500;
border-radius: 4rpx; border-radius: 4rpx;
color: var(--ui-BG-Main); color: var(--ui-BG-Main);
background: var(--ui-BG-Main-tag); background: var(--ui-BG-Main-tag);
} }
.discounts-title { .discounts-title {
font-size: 24rpx; font-size: 24rpx;
font-weight: 500; font-weight: 500;
color: var(--ui-BG-Main); color: var(--ui-BG-Main);
line-height: normal; line-height: normal;
} }
.cicon-forward { .cicon-forward {
color: var(--ui-BG-Main); color: var(--ui-BG-Main);
font-size: 24rpx; font-size: 24rpx;
line-height: normal; line-height: normal;
margin-top: 4rpx; margin-top: 4rpx;
} }
} }
.title-text { .title-text {
font-size: 30rpx; font-size: 30rpx;
font-weight: bold; font-weight: bold;
line-height: 42rpx; line-height: 42rpx;
} }
.subtitle-text { .subtitle-text {
font-size: 26rpx; font-size: 26rpx;
font-weight: 400; font-weight: 400;
color: $dark-9; color: $dark-9;
line-height: 42rpx; line-height: 42rpx;
} }
} }
// //
.buy-box { .buy-box {
.add-btn { .add-btn {
width: 214rpx; width: 214rpx;
height: 72rpx; height: 72rpx;
font-weight: 500; font-weight: 500;
font-size: 28rpx; font-size: 28rpx;
border-radius: 40rpx 0 0 40rpx; border-radius: 40rpx 0 0 40rpx;
background-color: var(--ui-BG-Main-light); background-color: var(--ui-BG-Main-light);
color: var(--ui-BG-Main); color: var(--ui-BG-Main);
} }
.buy-btn { .buy-btn {
width: 214rpx; width: 214rpx;
height: 72rpx; height: 72rpx;
font-weight: 500; font-weight: 500;
font-size: 28rpx; font-size: 28rpx;
border-radius: 0 40rpx 40rpx 0; border-radius: 0 40rpx 40rpx 0;
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient)); background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
color: $white; color: $white;
} }
.disabled-btn { .disabled-btn {
width: 428rpx; width: 428rpx;
height: 72rpx; height: 72rpx;
border-radius: 40rpx; border-radius: 40rpx;
background: #999999; background: #999999;
color: $white; color: $white;
} }
} }
.model-box { .model-box {
height: 60vh; height: 60vh;
.model-content { .model-content {
height: 56vh; height: 56vh;
} }
.title { .title {
font-size: 36rpx; font-size: 36rpx;
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;
} }
} }
</style> </style>

View File

@ -1,362 +1,398 @@
<template> <template>
<s-layout navbar="normal" :leftWidth="0" :rightWidth="0" tools="search" :defaultSearch="state.keyword" <s-layout
@search="onSearch"> navbar="normal"
<!-- 筛选 --> :leftWidth="0"
<su-sticky bgColor="#fff"> :rightWidth="0"
<view class="ss-flex"> tools="search"
<view class="ss-flex-1"> :defaultSearch="state.keyword"
<su-tabs :list="state.tabList" :scrollable="false" @change="onTabsChange" @search="onSearch"
:current="state.currentTab" /> >
</view> <!-- 筛选 -->
<view class="list-icon" @tap="state.iconStatus = !state.iconStatus"> <su-sticky bgColor="#fff">
<text v-if="state.iconStatus" class="sicon-goods-list" /> <view class="ss-flex">
<text v-else class="sicon-goods-card" /> <view class="ss-flex-1">
</view> <su-tabs
</view> :list="state.tabList"
</su-sticky> :scrollable="false"
@change="onTabsChange"
:current="state.currentTab"
/>
</view>
<view class="list-icon" @tap="state.iconStatus = !state.iconStatus">
<text v-if="state.iconStatus" class="sicon-goods-list" />
<text v-else class="sicon-goods-card" />
</view>
</view>
</su-sticky>
<!-- 弹窗 --> <!-- 弹窗 -->
<su-popup :show="state.showFilter" type="top" round="10" :space="sys_navBar + 38" backgroundColor="#F6F6F6" <su-popup
:zIndex="10" @close="state.showFilter = false"> :show="state.showFilter"
<view class="filter-list-box"> type="top"
<view class="filter-item" v-for="(item, index) in state.tabList[state.currentTab].list" round="10"
:key="item.value" :class="[{ 'filter-item-active': index === state.curFilter }]" :space="sys_navBar + 38"
@tap="onFilterItem(index)"> backgroundColor="#F6F6F6"
{{ item.label }} :zIndex="10"
</view> @close="state.showFilter = false"
</view> >
</su-popup> <view class="filter-list-box">
<view
class="filter-item"
v-for="(item, index) in state.tabList[state.currentTab].list"
:key="item.value"
:class="[{ 'filter-item-active': index === state.curFilter }]"
@tap="onFilterItem(index)"
>
{{ item.label }}
</view>
</view>
</su-popup>
<!-- 情况一单列布局 --> <!-- 情况一单列布局 -->
<view v-if="state.iconStatus && state.pagination.total > 0" class="goods-list ss-m-t-20"> <view 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
<s-goods-column class="ss-p-l-20 ss-p-r-20 ss-m-b-20"
v-for="item in state.pagination.list"
:key="item.id"
>
<s-goods-column
class="" class=""
size="lg" size="lg"
:data="item" :data="item"
:topRadius="10" :topRadius="10"
:bottomRadius="10" :bottomRadius="10"
@click="sheep.$router.go('/pages/goods/index', { id: item.id })" @click="sheep.$router.go('/pages/goods/index', { id: item.id })"
/> />
</view> </view>
</view> </view>
<!-- 情况二双列布局 --> <!-- 情况二双列布局 -->
<view v-if="!state.iconStatus && state.pagination.total > 0" <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"
<view class="goods-list-box"> class="ss-flex ss-flex-wrap ss-p-x-20 ss-m-t-20 ss-col-top"
<view class="left-list" v-for="item in state.leftGoodsList" :key="item.id"> >
<s-goods-column <view class="goods-list-box">
<view class="left-list" v-for="item in state.leftGoodsList" :key="item.id">
<s-goods-column
class="goods-md-box" class="goods-md-box"
size="md" size="md"
:data="item" :data="item"
:topRadius="10" :topRadius="10"
:bottomRadius="10" :bottomRadius="10"
@click="sheep.$router.go('/pages/goods/index', { id: item.id })" @click="sheep.$router.go('/pages/goods/index', { id: item.id })"
@getHeight="mountMasonry($event, 'left')" @getHeight="mountMasonry($event, 'left')"
> >
<template v-slot:cart> <template v-slot:cart>
<button class="ss-reset-button cart-btn" /> <button class="ss-reset-button cart-btn" />
</template> </template>
</s-goods-column> </s-goods-column>
</view> </view>
</view> </view>
<view class="goods-list-box"> <view class="goods-list-box">
<view class="right-list" v-for="item in state.rightGoodsList" :key="item.id"> <view class="right-list" v-for="item in state.rightGoodsList" :key="item.id">
<s-goods-column <s-goods-column
class="goods-md-box" class="goods-md-box"
size="md" size="md"
:topRadius="10" :topRadius="10"
:bottomRadius="10" :bottomRadius="10"
:data="item" :data="item"
@click="sheep.$router.go('/pages/goods/index', { id: item.id })" @click="sheep.$router.go('/pages/goods/index', { id: item.id })"
@getHeight="mountMasonry($event, 'right')" @getHeight="mountMasonry($event, 'right')"
> >
<template v-slot:cart> <template v-slot:cart>
<button class="ss-reset-button cart-btn" /> <button class="ss-reset-button cart-btn" />
</template> </template>
</s-goods-column> </s-goods-column>
</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" /> }"
<s-empty v-if="state.pagination.total === 0" icon="/static/soldout-empty.png" text="暂无商品" /> @tap="loadMore"
</s-layout> />
<s-empty v-if="state.pagination.total === 0" icon="/static/soldout-empty.png" text="暂无商品" />
</s-layout>
</template> </template>
<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 sheep from '@/sheep'; import sheep from '@/sheep';
import _ from 'lodash'; import _ from 'lodash';
import { resetPagination } from '@/sheep/util'; import { resetPagination } from '@/sheep/util';
import SpuApi from '@/sheep/api/product/spu'; import SpuApi from '@/sheep/api/product/spu';
const sys_navBar = sheep.$platform.navbar; const sys_navBar = sheep.$platform.navbar;
const emits = defineEmits(['close', 'change']); const emits = defineEmits(['close', 'change']);
const state = reactive({ const state = reactive({
pagination: { pagination: {
list: [], list: [],
total: 0, total: 0,
pageNo: 1, pageNo: 1,
pageSize: 6, pageSize: 6,
}, },
currentSort: undefined, currentSort: undefined,
currentOrder: undefined, currentOrder: undefined,
currentTab: 0, // tab currentTab: 0, // tab
curFilter: 0, // list curFilter: 0, // list
showFilter: false, showFilter: false,
iconStatus: false, // true - false - iconStatus: false, // true - false -
keyword: '', keyword: '',
categoryId: 0, categoryId: 0,
tabList: [{ tabList: [
name: '综合推荐', {
list: [{ name: '综合推荐',
label: '综合推荐' list: [
}, {
{ label: '综合推荐',
label: '价格升序', },
sort: 'price', {
order: true, label: '价格升序',
}, sort: 'price',
{ order: true,
label: '价格降序', },
sort: 'price', {
order: false, label: '价格降序',
}, sort: 'price',
], order: false,
}, },
{ ],
name: '销量', },
sort: 'salesCount', {
order: false name: '销量',
}, sort: 'salesCount',
{ order: false,
name: '新品优先', },
value: 'createTime', {
order: false name: '新品优先',
}, value: 'createTime',
], order: false,
loadStatus: '', },
leftGoodsList: [], // - ],
rightGoodsList: [], // - loadStatus: '',
}); leftGoodsList: [], // -
rightGoodsList: [], // -
});
// //
let count = 0; let count = 0;
let leftHeight = 0; let leftHeight = 0;
let rightHeight = 0; let rightHeight = 0;
// leftGoodsList + rightGoodsList // leftGoodsList + rightGoodsList
function mountMasonry(height = 0, where = 'left') { function mountMasonry(height = 0, where = 'left') {
if (!state.pagination.list[count]) { if (!state.pagination.list[count]) {
return; return;
} }
if (where === 'left') { if (where === 'left') {
leftHeight += height; leftHeight += height;
} else { } else {
rightHeight += height; rightHeight += height;
} }
if (leftHeight <= rightHeight) { if (leftHeight <= rightHeight) {
state.leftGoodsList.push(state.pagination.list[count]); state.leftGoodsList.push(state.pagination.list[count]);
} else { } else {
state.rightGoodsList.push(state.pagination.list[count]); state.rightGoodsList.push(state.pagination.list[count]);
} }
count++; count++;
} }
// //
function emptyList() { function emptyList() {
resetPagination(state.pagination); resetPagination(state.pagination);
state.leftGoodsList = []; state.leftGoodsList = [];
state.rightGoodsList = []; state.rightGoodsList = [];
count = 0; count = 0;
leftHeight = 0; leftHeight = 0;
rightHeight = 0; rightHeight = 0;
} }
// //
function onSearch(e) { function onSearch(e) {
state.keyword = e; state.keyword = e;
emptyList(); emptyList();
getList(state.currentSort, state.currentOrder); getList(state.currentSort, state.currentOrder);
} }
// //
function onTabsChange(e) { function onTabsChange(e) {
// //
if (state.tabList[e.index].list) { if (state.tabList[e.index].list) {
state.currentTab = e.index; state.currentTab = e.index;
state.showFilter = !state.showFilter; state.showFilter = !state.showFilter;
return; return;
} }
state.showFilter = false; state.showFilter = false;
// tab // tab
if (e.index === state.currentTab) { if (e.index === state.currentTab) {
return; return;
} }
state.currentTab = e.index; state.currentTab = e.index;
state.currentSort = e.sort; state.currentSort = e.sort;
state.currentOrder = e.order; state.currentOrder = e.order;
emptyList(); emptyList();
getList(e.sort, e.order); getList(e.sort, e.order);
} }
// tab list // tab list
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.showFilter = false; state.currentOrder === state.tabList[0].list[val].order
return; ) {
} state.showFilter = false;
return;
}
state.showFilter = false; state.showFilter = false;
// //
state.curFilter = val; state.curFilter = val;
state.tabList[0].name = state.tabList[0].list[val].label; state.tabList[0].name = state.tabList[0].list[val].label;
state.currentSort = state.tabList[0].list[val].sort; state.currentSort = state.tabList[0].list[val].sort;
state.currentOrder = state.tabList[0].list[val].order; state.currentOrder = state.tabList[0].list[val].order;
// + // +
emptyList(); emptyList();
getList(); getList();
} };
async function getList() { async function getList() {
state.loadStatus = 'loading'; state.loadStatus = 'loading';
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,
sortField: state.currentSort, sortField: state.currentSort,
sortAsc: state.currentOrder, sortAsc: state.currentOrder,
categoryId: state.categoryId, categoryId: state.categoryId,
keyword: state.keyword, keyword: state.keyword,
}); });
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();
} }
// //
function loadMore() { function loadMore() {
if (state.loadStatus === 'noMore') { if (state.loadStatus === 'noMore') {
return; return;
} }
state.pagination.pageNo++; state.pagination.pageNo++;
getList(state.currentSort, state.currentOrder); getList(state.currentSort, state.currentOrder);
} }
onLoad((options) => { onLoad((options) => {
state.categoryId = options.categoryId; state.categoryId = options.categoryId;
state.keyword = options.keyword; state.keyword = options.keyword;
getList(state.currentSort, state.currentOrder); getList(state.currentSort, state.currentOrder);
}); });
// //
onReachBottom(() => { onReachBottom(() => {
loadMore(); loadMore();
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.goods-list-box { .goods-list-box {
width: 50%; width: 50%;
box-sizing: border-box; box-sizing: border-box;
.left-list { .left-list {
margin-right: 10rpx; margin-right: 10rpx;
margin-bottom: 20rpx; margin-bottom: 20rpx;
} }
.right-list { .right-list {
margin-left: 10rpx; margin-left: 10rpx;
margin-bottom: 20rpx; margin-bottom: 20rpx;
} }
} }
.goods-box { .goods-box {
&:nth-last-of-type(1) { &:nth-last-of-type(1) {
margin-bottom: 0 !important; margin-bottom: 0 !important;
} }
&:nth-child(2n) { &:nth-child(2n) {
margin-right: 0; margin-right: 0;
} }
} }
.list-icon { .list-icon {
width: 80rpx; width: 80rpx;
.sicon-goods-card { .sicon-goods-card {
font-size: 40rpx; font-size: 40rpx;
} }
.sicon-goods-list { .sicon-goods-list {
font-size: 40rpx; font-size: 40rpx;
} }
} }
.goods-card { .goods-card {
margin-left: 20rpx; margin-left: 20rpx;
} }
.list-filter-tabs { .list-filter-tabs {
background-color: #fff; background-color: #fff;
} }
.filter-list-box { .filter-list-box {
padding: 28rpx 52rpx; padding: 28rpx 52rpx;
.filter-item { .filter-item {
font-size: 28rpx; font-size: 28rpx;
font-weight: 500; font-weight: 500;
color: #333333; color: #333333;
line-height: normal; line-height: normal;
margin-bottom: 24rpx; margin-bottom: 24rpx;
&:nth-last-child(1) { &:nth-last-child(1) {
margin-bottom: 0; margin-bottom: 0;
} }
} }
.filter-item-active { .filter-item-active {
color: var(--ui-BG-Main); color: var(--ui-BG-Main);
} }
} }
.tab-item { .tab-item {
height: 50px; height: 50px;
position: relative; position: relative;
z-index: 11; z-index: 11;
.tab-title { .tab-title {
font-size: 30rpx; font-size: 30rpx;
} }
.cur-tab-title { .cur-tab-title {
font-weight: $font-weight-bold; font-weight: $font-weight-bold;
} }
.tab-line { .tab-line {
width: 60rpx; width: 60rpx;
height: 6rpx; height: 6rpx;
border-radius: 6rpx; border-radius: 6rpx;
position: absolute; position: absolute;
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
bottom: 10rpx; bottom: 10rpx;
background-color: var(--ui-BG-Main); background-color: var(--ui-BG-Main);
z-index: 12; z-index: 12;
} }
} }
</style> </style>

View File

@ -69,10 +69,7 @@
<!-- 功能卡片 --> <!-- 功能卡片 -->
<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,11 +135,11 @@
</template> </template>
<script setup> <script setup>
import {reactive, computed, ref} from 'vue'; import { reactive, computed, ref } 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';
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';
import detailTabbar from './components/detail/detail-tabbar.vue'; import detailTabbar from './components/detail/detail-tabbar.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');
@ -221,36 +218,40 @@
); );
}); });
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 +265,7 @@
}); });
state.skeletonLoading = false; state.skeletonLoading = false;
} };
onLoad((options) => { onLoad((options) => {
// //
@ -274,7 +275,7 @@
} }
// //
getActivity(options.id) getActivity(options.id);
}); });
</script> </script>

View File

@ -1,196 +1,230 @@
<template> <template>
<s-layout title="购物车" tabbar="/pages/index/cart" :bgStyle="{ color: '#fff' }"> <s-layout title="购物车" tabbar="/pages/index/cart" :bgStyle="{ color: '#fff' }">
<s-empty v-if="state.list.length === 0" text="购物车空空如也,快去逛逛吧~" icon="/static/cart-empty.png" /> <s-empty
v-if="state.list.length === 0"
text="购物车空空如也,快去逛逛吧~"
icon="/static/cart-empty.png"
/>
<!-- 头部 --> <!-- 头部 -->
<view class="cart-box ss-flex ss-flex-col ss-row-between" v-if="state.list.length"> <view class="cart-box ss-flex ss-flex-col ss-row-between" v-if="state.list.length">
<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.list.length }}</text> <text class="goods-number ui-TC-Main ss-flex">{{ state.list.length }}</text>
件商品 件商品
</view> </view>
<view class="header-right"> <view class="header-right">
<button v-if="state.editMode" class="ss-reset-button" @tap="state.editMode = false"> <button v-if="state.editMode" class="ss-reset-button" @tap="state.editMode = false">
取消 取消
</button> </button>
<button v-else class="ss-reset-button ui-TC-Main" @tap="state.editMode = true"> <button v-else class="ss-reset-button ui-TC-Main" @tap="state.editMode = true">
编辑 编辑
</button> </button>
</view> </view>
</view> </view>
<!-- 内容 --> <!-- 内容 -->
<view class="cart-content ss-flex-1 ss-p-x-30 ss-m-b-40"> <view class="cart-content ss-flex-1 ss-p-x-30 ss-m-b-40">
<view class="goods-box ss-r-10 ss-m-b-14" v-for="item in state.list" :key="item.id"> <view class="goods-box ss-r-10 ss-m-b-14" v-for="item in state.list" :key="item.id">
<view class="ss-flex ss-col-center"> <view class="ss-flex ss-col-center">
<label class="check-box ss-flex ss-col-center ss-p-l-10" @tap="onSelectSingle(item.id)"> <label class="check-box ss-flex ss-col-center ss-p-l-10" @tap="onSelectSingle(item.id)">
<radio :checked="state.selectedIds.includes(item.id)" color="var(--ui-BG-Main)" <radio
style="transform: scale(0.8)" @tap.stop="onSelectSingle(item.id)" /> :checked="state.selectedIds.includes(item.id)"
</label> color="var(--ui-BG-Main)"
<s-goods-item :title="item.spu.name" :img="item.spu.picUrl || item.goods.image" style="transform: scale(0.8)"
:price="item.sku.price" @tap.stop="onSelectSingle(item.id)"
:skuText="item.sku.properties.length>1? item.sku.properties.reduce((items2,items)=>items2.valueName+' '+items.valueName):item.sku.properties[0].valueName" />
priceColor="#FF3000" :titleWidth="400"> </label>
<template v-if="!state.editMode" v-slot:tool> <s-goods-item
<su-number-box :min="0" :max="item.sku.stock" :step="1" v-model="item.count" @change="onNumberChange($event, item)" /> :title="item.spu.name"
</template> :img="item.spu.picUrl || item.goods.image"
</s-goods-item> :price="item.sku.price"
</view> :skuText="
</view> item.sku.properties.length > 1
</view> ? item.sku.properties.reduce(
<!-- 底部 --> (items2, items) => items2.valueName + ' ' + items.valueName,
<su-fixed bottom :val="48" placeholder v-if="state.list.length > 0" :isInset="false"> )
<view class="cart-footer ss-flex ss-col-center ss-row-between ss-p-x-30 border-bottom"> : item.sku.properties[0].valueName
<view class="footer-left ss-flex ss-col-center"> "
<label class="check-box ss-flex ss-col-center ss-p-r-30" @tap="onSelectAll"> priceColor="#FF3000"
<radio :checked="state.isAllSelected" color="var(--ui-BG-Main)" :titleWidth="400"
style="transform: scale(0.8)" @tap.stop="onSelectAll" /> >
<view class="ss-m-l-8"> 全选 </view> <template v-if="!state.editMode" v-slot:tool>
</label> <su-number-box
<text>合计</text> :min="0"
<view class="text-price price-text"> :max="item.sku.stock"
{{ fen2yuan(state.totalPriceSelected) }} :step="1"
</view> v-model="item.count"
</view> @change="onNumberChange($event, item)"
<view class="footer-right"> />
<button v-if="state.editMode" class="ss-reset-button ui-BG-Main-Gradient pay-btn ui-Shadow-Main" </template>
@tap="onDelete"> </s-goods-item>
删除 </view>
</button> </view>
<button v-else class="ss-reset-button ui-BG-Main-Gradient pay-btn ui-Shadow-Main" </view>
@tap="onConfirm"> <!-- 底部 -->
去结算 <su-fixed bottom :val="48" placeholder v-if="state.list.length > 0" :isInset="false">
{{ state.selectedIds?.length ? `(${state.selectedIds.length})` : '' }} <view class="cart-footer ss-flex ss-col-center ss-row-between ss-p-x-30 border-bottom">
</button> <view class="footer-left ss-flex ss-col-center">
</view> <label class="check-box ss-flex ss-col-center ss-p-r-30" @tap="onSelectAll">
</view> <radio
</su-fixed> :checked="state.isAllSelected"
</view> color="var(--ui-BG-Main)"
</s-layout> style="transform: scale(0.8)"
@tap.stop="onSelectAll"
/>
<view class="ss-m-l-8"> 全选 </view>
</label>
<text>合计</text>
<view class="text-price price-text">
{{ fen2yuan(state.totalPriceSelected) }}
</view>
</view>
<view class="footer-right">
<button
v-if="state.editMode"
class="ss-reset-button ui-BG-Main-Gradient pay-btn ui-Shadow-Main"
@tap="onDelete"
>
删除
</button>
<button
v-else
class="ss-reset-button ui-BG-Main-Gradient pay-btn ui-Shadow-Main"
@tap="onConfirm"
>
去结算
{{ state.selectedIds?.length ? `(${state.selectedIds.length})` : '' }}
</button>
</view>
</view>
</su-fixed>
</view>
</s-layout>
</template> </template>
<script setup> <script setup>
import sheep from '@/sheep'; import sheep from '@/sheep';
import { computed, reactive } from 'vue'; import { computed, reactive } from 'vue';
import { fen2yuan } from '../../sheep/hooks/useGoods'; import { fen2yuan } from '../../sheep/hooks/useGoods';
const sys_navBar = sheep.$platform.navbar; const sys_navBar = sheep.$platform.navbar;
const cart = sheep.$store('cart'); const cart = sheep.$store('cart');
const state = reactive({ const state = reactive({
editMode: false, editMode: false,
list: computed(() => cart.list), list: computed(() => cart.list),
selectedList: [], selectedList: [],
selectedIds: computed(() => cart.selectedIds), selectedIds: computed(() => cart.selectedIds),
isAllSelected: computed(() => cart.isAllSelected), isAllSelected: computed(() => cart.isAllSelected),
totalPriceSelected: computed(() => cart.totalPriceSelected), totalPriceSelected: computed(() => cart.totalPriceSelected),
}); });
// //
function onSelectSingle(id) { function onSelectSingle(id) {
cart.selectSingle(id); cart.selectSingle(id);
} }
// //
function onSelectAll() { function onSelectAll() {
cart.selectAll(!state.isAllSelected); cart.selectAll(!state.isAllSelected);
} }
// //
function onConfirm() { function onConfirm() {
let items = [] let items = [];
let goods_list = []; let goods_list = [];
state.selectedList = state.list.filter((item) => state.selectedIds.includes(item.id)); state.selectedList = state.list.filter((item) => state.selectedIds.includes(item.id));
state.selectedList.map((item) => { state.selectedList.map((item) => {
// //
items.push({ items.push({
skuId: item.sku.id, skuId: item.sku.id,
count: item.count, count: item.count,
cartId: item.id, cartId: item.id,
}) });
goods_list.push({ goods_list.push({
// goods_id: item.goods_id, // goods_id: item.goods_id,
goods_id: item.spu.id, goods_id: item.spu.id,
// goods_num: item.goods_num, // goods_num: item.goods_num,
goods_num: item.count, goods_num: item.count,
// id // id
// goods_sku_price_id: item.goods_sku_price_id, // goods_sku_price_id: item.goods_sku_price_id,
}); });
}); });
// return; // return;
if (goods_list.length === 0) { if (goods_list.length === 0) {
sheep.$helper.toast('请选择商品'); sheep.$helper.toast('请选择商品');
return; return;
} }
sheep.$router.go('/pages/order/confirm', { sheep.$router.go('/pages/order/confirm', {
data: JSON.stringify({ data: JSON.stringify({
// order_type: 'goods', // order_type: 'goods',
// goods_list, // goods_list,
items, items,
// from: 'cart', // from: 'cart',
deliveryType: 1, deliveryType: 1,
pointStatus: false, pointStatus: false,
}), }),
}); });
} }
function onNumberChange(e, cartItem) { function onNumberChange(e, cartItem) {
if (e === 0) { if (e === 0) {
cart.delete(cartItem.id); cart.delete(cartItem.id);
return; return;
} }
if (cartItem.goods_num === e) return; if (cartItem.goods_num === e) return;
cartItem.goods_num = e; cartItem.goods_num = e;
cart.update({ cart.update({
goods_id: cartItem.id, goods_id: cartItem.id,
goods_num: e, goods_num: e,
goods_sku_price_id: cartItem.goods_sku_price_id, goods_sku_price_id: cartItem.goods_sku_price_id,
}); });
} }
async function onDelete() { async function onDelete() {
cart.delete(state.selectedIds); cart.delete(state.selectedIds);
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep(.ui-fixed) { :deep(.ui-fixed) {
height: 72rpx; height: 72rpx;
} }
.cart-box { .cart-box {
width: 100%; width: 100%;
.cart-header { .cart-header {
height: 70rpx; height: 70rpx;
background-color: #f6f6f6; background-color: #f6f6f6;
width: 100%; width: 100%;
position: fixed; position: fixed;
left: 0; left: 0;
top: v-bind('sys_navBar') rpx; top: v-bind('sys_navBar') rpx;
z-index: 1000; z-index: 1000;
box-sizing: border-box; box-sizing: border-box;
} }
.cart-footer { .cart-footer {
height: 100rpx; height: 100rpx;
background-color: #fff; background-color: #fff;
.pay-btn { .pay-btn {
width: 180rpx; width: 180rpx;
height: 70rpx; height: 70rpx;
font-size: 28rpx; font-size: 28rpx;
line-height: 28rpx; line-height: 28rpx;
font-weight: 500; font-weight: 500;
border-radius: 40rpx; border-radius: 40rpx;
} }
} }
.cart-content { .cart-content {
margin-top: 70rpx; margin-top: 70rpx;
.goods-box { .goods-box {
background-color: #fff; background-color: #fff;
} }
} }
} }
</style> </style>

View File

@ -1,88 +1,91 @@
<!-- 首页支持店铺装修 --> <!-- 首页支持店铺装修 -->
<template> <template>
<view v-if="template"> <view v-if="template">
<s-layout title="首页" navbar="custom" tabbar="/pages/index/index" :bgStyle="template.page" <s-layout
:navbarStyle="template.navigationBar" onShareAppMessage> title="首页"
<s-block v-for="(item, index) in template.components" :key="index" :styles="item.property.style"> navbar="custom"
<s-block-item :type="item.id" :data="item.property" :styles="item.property.style" /> tabbar="/pages/index/index"
</s-block> :bgStyle="template.page"
</s-layout> :navbarStyle="template.navigationBar"
</view> onShareAppMessage
>
<s-block
v-for="(item, index) in template.components"
:key="index"
:styles="item.property.style"
>
<s-block-item :type="item.id" :data="item.property" :styles="item.property.style" />
</s-block>
</s-layout>
</view>
</template> </template>
<script setup> <script setup>
import { import { computed } from 'vue';
computed import { onLoad, onPageScroll, onPullDownRefresh } from '@dcloudio/uni-app';
} from 'vue'; import sheep from '@/sheep';
import { import $share from '@/sheep/platform/share';
onLoad, // tabBar
onPageScroll, uni.hideTabBar();
onPullDownRefresh
} from '@dcloudio/uni-app';
import sheep from '@/sheep';
import $share from '@/sheep/platform/share';
// tabBar
uni.hideTabBar();
const template = computed(() => sheep.$store('app').template?.home); const template = computed(() => sheep.$store('app').template?.home);
// //
// (async function() { // (async function() {
// console.log('',template) // console.log('',template)
// let { // let {
// data // data
// } = await index2Api.decorate(); // } = await index2Api.decorate();
// console.log('',JSON.parse(data[1].value)) // console.log('',JSON.parse(data[1].value))
// id // id
// let { // let {
// data: datas // data: datas
// } = await index2Api.spids(); // } = await index2Api.spids();
// template.value.data[9].data.goodsIds = datas.list.map(item => item.id); // template.value.data[9].data.goodsIds = datas.list.map(item => item.id);
// template.value.data[0].data.list = JSON.parse(data[0].value).map(item => { // template.value.data[0].data.list = JSON.parse(data[0].value).map(item => {
// return { // return {
// src: item.picUrl, // src: item.picUrl,
// url: item.url, // url: item.url,
// title: item.name, // title: item.name,
// type: "image" // type: "image"
// } // }
// }) // })
// }()) // }())
onLoad((options) => {
// #ifdef MP
//
if (options.scene) {
const sceneParams = decodeURIComponent(options.scene).split('=');
console.log('sceneParams=>', sceneParams);
options[sceneParams[0]] = sceneParams[1];
}
// #endif
onLoad((options) => { //
// #ifdef MP if (options.templateId) {
// sheep.$store('app').init(options.templateId);
if (options.scene) { }
const sceneParams = decodeURIComponent(options.scene).split('=');
console.log("sceneParams=>",sceneParams);
options[sceneParams[0]] = sceneParams[1];
}
// #endif
// //
if (options.templateId) { if (options.spm) {
sheep.$store('app').init(options.templateId); $share.decryptSpm(options.spm);
} }
// // ()
if (options.spm) { if (options.page) {
$share.decryptSpm(options.spm); sheep.$router.go(decodeURIComponent(options.page));
} }
});
// () //
if (options.page) { onPullDownRefresh(() => {
sheep.$router.go(decodeURIComponent(options.page)); sheep.$store('app').init();
} setTimeout(function () {
}); uni.stopPullDownRefresh();
}, 800);
});
// onPageScroll(() => {});
onPullDownRefresh(() => {
sheep.$store('app').init();
setTimeout(function() {
uni.stopPullDownRefresh();
}, 800);
});
onPageScroll(() => {});
</script> </script>
<style></style> <style></style>

View File

@ -17,16 +17,18 @@
const event = options.event; const event = options.event;
const code = options.code; const code = options.code;
const state = options.state; const state = options.state;
if (event === 'login') { // if (event === 'login') {
//
const res = await sheep.$platform.useProvider().login(code, state); const res = await sheep.$platform.useProvider().login(code, state);
} else if (event === 'bind') { // } else if (event === 'bind') {
//
sheep.$platform.useProvider().bind(code, state); sheep.$platform.useProvider().bind(code, state);
} }
// H5 // H5
let returnUrl = uni.getStorageSync('returnUrl'); let returnUrl = uni.getStorageSync('returnUrl');
if (returnUrl) { if (returnUrl) {
uni.removeStorage({key:'returnUrl'}); uni.removeStorage({ key: 'returnUrl' });
location.replace(returnUrl); location.replace(returnUrl);
} else { } else {
uni.switchTab({ uni.switchTab({

View File

@ -26,7 +26,7 @@
page: {}, page: {},
}); });
onLoad(async (options) => { onLoad(async (options) => {
let id = options.id let id = options.id;
// #ifdef MP // #ifdef MP
// //

View File

@ -8,7 +8,11 @@
:navbarStyle="template.navigationBar" :navbarStyle="template.navigationBar"
onShareAppMessage onShareAppMessage
> >
<s-block v-for="(item, index) in template.components" :key="index" :styles="item.property.style"> <s-block
v-for="(item, index) in template.components"
:key="index"
:styles="item.property.style"
>
<s-block-item :type="item.id" :data="item.property" :styles="item.property.style" /> <s-block-item :type="item.id" :data="item.property" :styles="item.property.style" />
</s-block> </s-block>
</s-layout> </s-layout>

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"
@ -152,7 +148,7 @@
], ],
reasonList: [], // reasonList: [], //
showModal: false, // showModal: false, //
currentValue: '' // currentValue: '', //
}); });
const formData = reactive({ const formData = reactive({
way: '', way: '',

View File

@ -1,156 +1,193 @@
<!-- 售后详情 --> <!-- 售后详情 -->
<template> <template>
<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="steps-item" v-for="(item, index) in state.list" :key="index"> <view class="ss-flex">
<view class="ss-flex"> <view class="steps-item" v-for="(item, index) in state.list" :key="index">
<text class="sicon-circleclose" <view class="ss-flex">
v-if="state.list.length - 1 === index && [61, 62, 63].includes(state.info.status)" /> <text
<text class="sicon-circlecheck" v-else class="sicon-circleclose"
:class="state.active >= index ? 'activity-color' : 'info-color'" /> v-if="state.list.length - 1 === index && [61, 62, 63].includes(state.info.status)"
/>
<text
class="sicon-circlecheck"
v-else
:class="state.active >= index ? 'activity-color' : 'info-color'"
/>
<view v-if="state.list.length - 1 !== index" class="line" <view
:class="state.active >= index ? 'activity-bg' : 'info-bg'" /> v-if="state.list.length - 1 !== index"
</view> class="line"
<view class="steps-item-title" :class="state.active >= index ? 'activity-color' : 'info-color'"> :class="state.active >= index ? 'activity-bg' : 'info-bg'"
{{ item.title }} />
</view> </view>
</view> <view
</view> class="steps-item-title"
</view> :class="state.active >= index ? 'activity-color' : 'info-color'"
>
{{ item.title }}
</view>
</view>
</view>
</view>
<!-- 服务状态 --> <!-- 服务状态 -->
<view class="status-box ss-flex ss-col-center ss-row-between ss-m-x-20" <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"
<view class=""> @tap="sheep.$router.go('/pages/order/aftersale/log', { id: state.id })"
<view class="status-text"> >
<view class="">
<view class="status-text">
{{ formatAfterSaleStatusDescription(state.info) }} {{ formatAfterSaleStatusDescription(state.info) }}
</view> </view>
<view class="status-time"> <view class="status-time">
{{ sheep.$helper.timeFormat(state.info.updateTime, 'yyyy-mm-dd hh:MM:ss') }} {{ sheep.$helper.timeFormat(state.info.updateTime, 'yyyy-mm-dd hh:MM:ss') }}
</view> </view>
</view> </view>
<text class="ss-iconfont _icon-forward" style="color: #666" /> <text class="ss-iconfont _icon-forward" style="color: #666" />
</view> </view>
<!-- 退款金额 --> <!-- 退款金额 -->
<view class="aftersale-money ss-flex ss-col-center ss-row-between"> <view class="aftersale-money ss-flex ss-col-center ss-row-between">
<view class="aftersale-money--title">退款总额</view> <view class="aftersale-money--title">退款总额</view>
<view class="aftersale-money--num">{{ fen2yuan(state.info.refundPrice) }}</view> <view class="aftersale-money--num">{{ fen2yuan(state.info.refundPrice) }}</view>
</view> </view>
<!-- 服务商品 --> <!-- 服务商品 -->
<view class="order-shop"> <view class="order-shop">
<s-goods-item <s-goods-item
:img=" state.info.picUrl" :img="state.info.picUrl"
:title=" state.info.spuName" :title="state.info.spuName"
:titleWidth="480" :titleWidth="480"
:skuText="state.info.properties.map((property) => property.valueName).join(' ')" :skuText="state.info.properties.map((property) => property.valueName).join(' ')"
:num=" state.info.count" :num="state.info.count"
/> />
</view> </view>
<!-- 服务内容 --> <!-- 服务内容 -->
<view class="aftersale-content"> <view class="aftersale-content">
<view class="aftersale-item ss-flex ss-col-center"> <view class="aftersale-item ss-flex ss-col-center">
<view class="item-title">服务单号</view> <view class="item-title">服务单号</view>
<view class="item-content ss-m-r-16">{{ state.info.no }}</view> <view class="item-content ss-m-r-16">{{ state.info.no }}</view>
<button class="ss-reset-button copy-btn" @tap="onCopy">复制</button> <button class="ss-reset-button copy-btn" @tap="onCopy">复制</button>
</view> </view>
<view class="aftersale-item ss-flex ss-col-center"> <view class="aftersale-item ss-flex ss-col-center">
<view class="item-title">申请时间</view> <view class="item-title">申请时间</view>
<view class="item-content"> <view class="item-content">
{{ sheep.$helper.timeFormat(state.info.createTime, 'yyyy-mm-dd hh:MM:ss') }} {{ sheep.$helper.timeFormat(state.info.createTime, 'yyyy-mm-dd hh:MM:ss') }}
</view> </view>
</view> </view>
<view class="aftersale-item ss-flex ss-col-center"> <view class="aftersale-item ss-flex ss-col-center">
<view class="item-title">售后类型</view> <view class="item-title">售后类型</view>
<view class="item-content">{{ state.info.way === 10 ? '仅退款' : '退款退货' }}</view> <view class="item-content">{{ state.info.way === 10 ? '仅退款' : '退款退货' }}</view>
</view> </view>
<view class="aftersale-item ss-flex ss-col-center"> <view class="aftersale-item ss-flex ss-col-center">
<view class="item-title">申请原因</view> <view class="item-title">申请原因</view>
<view class="item-content">{{ state.info.applyReason }}</view> <view class="item-content">{{ state.info.applyReason }}</view>
</view> </view>
<view class="aftersale-item ss-flex ss-col-center"> <view class="aftersale-item ss-flex ss-col-center">
<view class="item-title">相关描述</view> <view class="item-title">相关描述</view>
<view class="item-content">{{ state.info.applyDescription }}</view> <view class="item-content">{{ state.info.applyDescription }}</view>
</view> </view>
</view> </view>
</view> </view>
<!-- 操作区 --> <!-- 操作区 -->
<s-empty v-if="isEmpty(state.info) && state.loading" icon="/static/order-empty.png" text="暂无该订单售后详情" /> <s-empty
<su-fixed bottom placeholder bg="bg-white" v-if="!isEmpty(state.info)"> v-if="isEmpty(state.info) && state.loading"
<view class="foot_box"> icon="/static/order-empty.png"
<button class="ss-reset-button btn" v-if="state.info.buttons?.includes('cancel')" text="暂无该订单售后详情"
@tap="onApply(state.info.id)"> />
<su-fixed bottom placeholder bg="bg-white" v-if="!isEmpty(state.info)">
<view class="foot_box">
<button
class="ss-reset-button btn"
v-if="state.info.buttons?.includes('cancel')"
@tap="onApply(state.info.id)"
>
取消申请 取消申请
</button> </button>
<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>
</su-fixed> </su-fixed>
</s-layout> </s-layout>
</template> </template>
<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 } from 'vue';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
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;
const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png'); const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
const state = reactive({ const state = reactive({
id: 0, // id: 0, //
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) {
uni.showModal({ uni.showModal({
title: '提示', title: '提示',
content: '确定要取消此申请吗?', content: '确定要取消此申请吗?',
success: async function(res) { success: async function (res) {
if (!res.confirm) { if (!res.confirm) {
return; return;
} }
const { code } = await AfterSaleApi.cancelAfterSale(id); const { code } = await AfterSaleApi.cancelAfterSale(id);
if (code === 0) { if (code === 0) {
await getDetail(id); await getDetail(id);
} }
}, },
}); });
} }
// //
const onCopy = () => { const onCopy = () => {
sheep.$helper.copyText(state.info.no); sheep.$helper.copyText(state.info.no);
}; };
async function getDetail(id) { async function getDetail(id) {
state.loading = true; state.loading = true;
const { code, data } = await AfterSaleApi.getAfterSale(id); const { code, data } = await AfterSaleApi.getAfterSale(id);
if (code !== 0) { if (code !== 0) {
@ -170,173 +207,173 @@
} else if ([61, 62, 63].includes(state.info.status)) { } else if ([61, 62, 63].includes(state.info.status)) {
state.active = 2; state.active = 2;
} }
} }
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);
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
// //
.steps-box { .steps-box {
width: 100%; width: 100%;
height: 190rpx; height: 190rpx;
background: v-bind(headerBg) no-repeat, background: v-bind(headerBg) no-repeat,
linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient)); linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
background-size: 750rpx 100%; background-size: 750rpx 100%;
padding-left: 72rpx; padding-left: 72rpx;
.steps-item { .steps-item {
.sicon-circleclose { .sicon-circleclose {
font-size: 24rpx; font-size: 24rpx;
color: #fff; color: #fff;
} }
.sicon-circlecheck { .sicon-circlecheck {
font-size: 24rpx; font-size: 24rpx;
} }
.steps-item-title { .steps-item-title {
font-size: 24rpx; font-size: 24rpx;
font-weight: 400; font-weight: 400;
margin-top: 16rpx; margin-top: 16rpx;
margin-left: -36rpx; margin-left: -36rpx;
width: 100rpx; width: 100rpx;
text-align: center; text-align: center;
} }
} }
} }
.activity-color { .activity-color {
color: #fff; color: #fff;
} }
.info-color { .info-color {
color: rgba(#fff, 0.4); color: rgba(#fff, 0.4);
} }
.activity-bg { .activity-bg {
background: #fff; background: #fff;
} }
.info-bg { .info-bg {
background: rgba(#fff, 0.4); background: rgba(#fff, 0.4);
} }
.line { .line {
width: 270rpx; width: 270rpx;
height: 4rpx; height: 4rpx;
} }
// //
.status-box { .status-box {
position: relative; position: relative;
z-index: 3; z-index: 3;
background-color: #fff; background-color: #fff;
border-radius: 20rpx 20rpx 0px 0px; border-radius: 20rpx 20rpx 0px 0px;
padding: 20rpx; padding: 20rpx;
margin-top: -20rpx; margin-top: -20rpx;
.status-text { .status-text {
font-size: 28rpx; font-size: 28rpx;
font-weight: 500; font-weight: 500;
color: rgba(51, 51, 51, 1); color: rgba(51, 51, 51, 1);
margin-bottom: 20rpx; margin-bottom: 20rpx;
} }
.status-time { .status-time {
font-size: 24rpx; font-size: 24rpx;
font-weight: 400; font-weight: 400;
color: rgba(153, 153, 153, 1); color: rgba(153, 153, 153, 1);
} }
} }
// 退 // 退
.aftersale-money { .aftersale-money {
background-color: #fff; background-color: #fff;
height: 98rpx; height: 98rpx;
padding: 0 20rpx; padding: 0 20rpx;
margin: 20rpx; margin: 20rpx;
.aftersale-money--title { .aftersale-money--title {
font-size: 28rpx; font-size: 28rpx;
font-weight: 500; font-weight: 500;
color: rgba(51, 51, 51, 1); color: rgba(51, 51, 51, 1);
} }
.aftersale-money--num { .aftersale-money--num {
font-size: 28rpx; font-size: 28rpx;
font-family: OPPOSANS; font-family: OPPOSANS;
font-weight: 500; font-weight: 500;
color: #ff3000; color: #ff3000;
} }
} }
// order-shop // order-shop
.order-shop { .order-shop {
padding: 20rpx; padding: 20rpx;
background-color: #fff; background-color: #fff;
margin: 0 20rpx 20rpx 20rpx; margin: 0 20rpx 20rpx 20rpx;
} }
// //
.aftersale-content { .aftersale-content {
background-color: #fff; background-color: #fff;
padding: 20rpx; padding: 20rpx;
margin: 0 20rpx; margin: 0 20rpx;
.aftersale-item { .aftersale-item {
height: 60rpx; height: 60rpx;
.copy-btn { .copy-btn {
background: #eeeeee; background: #eeeeee;
color: #333; color: #333;
border-radius: 20rpx; border-radius: 20rpx;
width: 75rpx; width: 75rpx;
height: 40rpx; height: 40rpx;
font-size: 22rpx; font-size: 22rpx;
} }
.item-title { .item-title {
color: #999; color: #999;
font-size: 28rpx; font-size: 28rpx;
} }
.item-content { .item-content {
color: #333; color: #333;
font-size: 28rpx; font-size: 28rpx;
} }
} }
} }
// //
.foot_box { .foot_box {
height: 100rpx; height: 100rpx;
background-color: #fff; background-color: #fff;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
.btn { .btn {
width: 160rpx; width: 160rpx;
line-height: 60rpx; line-height: 60rpx;
background: rgba(238, 238, 238, 1); background: rgba(238, 238, 238, 1);
border-radius: 30rpx; border-radius: 30rpx;
padding: 0; padding: 0;
margin-right: 20rpx; margin-right: 20rpx;
font-size: 26rpx; font-size: 26rpx;
font-weight: 400; font-weight: 400;
color: rgba(51, 51, 51, 1); color: rgba(51, 51, 51, 1);
} }
} }
</style> </style>

View File

@ -1,187 +1,210 @@
<!-- 售后列表 --> <!-- 售后列表 -->
<template> <template>
<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
</su-sticky> :list="tabMaps"
<s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据" /> :scrollable="false"
<!-- 列表 --> @change="onTabsChange"
<view v-if="state.pagination.total > 0"> :current="state.currentTab"
<view class="list-box ss-m-y-20" v-for="order in state.pagination.list" :key="order.id" />
@tap="sheep.$router.go('/pages/order/aftersale/detail', { id: order.id })"> </su-sticky>
<view class="order-head ss-flex ss-col-center ss-row-between"> <s-empty v-if="state.pagination.total === 0" icon="/static/data-empty.png" text="暂无数据" />
<text class="no">服务单号{{ order.no }}</text> <!-- 列表 -->
<text class="state">{{ formatAfterSaleStatus(order) }}</text> <view v-if="state.pagination.total > 0">
</view> <view
<s-goods-item class="list-box ss-m-y-20"
v-for="order in state.pagination.list"
:key="order.id"
@tap="sheep.$router.go('/pages/order/aftersale/detail', { id: order.id })"
>
<view class="order-head ss-flex ss-col-center ss-row-between">
<text class="no">服务单号{{ order.no }}</text>
<text class="state">{{ formatAfterSaleStatus(order) }}</text>
</view>
<s-goods-item
:img="order.picUrl" :img="order.picUrl"
:title="order.spuName" :title="order.spuName"
:skuText="order.properties.map((property) => property.valueName).join(' ')" :skuText="order.properties.map((property) => property.valueName).join(' ')"
:price="order.refundPrice" :price="order.refundPrice"
/> />
<view class="apply-box ss-flex ss-col-center ss-row-between border-bottom ss-p-x-20"> <view class="apply-box ss-flex ss-col-center ss-row-between border-bottom ss-p-x-20">
<view class="ss-flex ss-col-center"> <view class="ss-flex ss-col-center">
<view class="title ss-m-r-20">{{ order.way === 10 ? '仅退款' : '退款退货' }}</view> <view class="title ss-m-r-20">{{ order.way === 10 ? '仅退款' : '退款退货' }}</view>
<view class="value">{{ formatAfterSaleStatusDescription(order) }}</view> <view class="value">{{ formatAfterSaleStatusDescription(order) }}</view>
</view> </view>
<text class="_icon-forward"></text> <text class="_icon-forward"></text>
</view> </view>
<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"
</view> @tap.stop="onApply(order.id)"
</view> v-if="order?.buttons.includes('cancel')"
</view> >取消申请</button
</view> >
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{ </view>
</view>
</view>
</view>
<uni-load-more
v-if="state.pagination.total > 0"
:status="state.loadStatus"
:content-text="{
contentdown: '上拉加载更多', contentdown: '上拉加载更多',
}" @tap="loadMore" /> }"
</s-layout> @tap="loadMore"
/>
</s-layout>
</template> </template>
<script setup> <script setup>
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';
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';
const state = reactive({ const state = reactive({
currentTab: 0, currentTab: 0,
showApply: false, showApply: false,
pagination: { pagination: {
list: [], list: [],
total: 0, total: 0,
pageNo: 1, pageNo: 1,
pageSize: 10 pageSize: 10,
}, },
loadStatus: '', loadStatus: '',
}); });
// TODO // TODO
const tabMaps = [{ const tabMaps = [
name: '全部', {
value: 'all', name: '全部',
}, value: 'all',
// { },
// name: '', // {
// value: 'nooper', // name: '',
// }, // value: 'nooper',
// { // },
// name: '', // {
// value: 'ing', // name: '',
// }, // value: 'ing',
// { // },
// name: '', // {
// value: 'completed', // name: '',
// }, // value: 'completed',
// { // },
// name: '', // {
// value: 'refuse', // name: '',
// }, // value: 'refuse',
]; // },
];
// //
function onTabsChange(e) { function onTabsChange(e) {
resetPagination(state.pagination); resetPagination(state.pagination);
state.currentTab = e.index; state.currentTab = e.index;
getOrderList(); getOrderList();
} }
// //
async function getOrderList() { async function getOrderList() {
state.loadStatus = 'loading'; state.loadStatus = 'loading';
let { data, code } = await AfterSaleApi.getAfterSalePage({ let { data, code } = await AfterSaleApi.getAfterSalePage({
// type: tabMaps[state.currentTab].value, // type: tabMaps[state.currentTab].value,
pageNo: state.pagination.pageNo, pageNo: state.pagination.pageNo,
pageSize: state.pagination.pageSize, pageSize: state.pagination.pageSize,
}); });
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';
} }
function onApply(orderId) { function onApply(orderId) {
uni.showModal({ uni.showModal({
title: '提示', title: '提示',
content: '确定要取消此申请吗?', content: '确定要取消此申请吗?',
success: async function(res) { success: async function (res) {
if (!res.confirm) { if (!res.confirm) {
return; return;
} }
const { code } = await AfterSaleApi.cancelAfterSale(orderId); const { code } = await AfterSaleApi.cancelAfterSale(orderId);
if (code === 0) { if (code === 0) {
resetPagination(state.pagination); resetPagination(state.pagination);
await getOrderList(); await getOrderList();
} }
}, },
}); });
} }
onLoad(async (options) => { onLoad(async (options) => {
if (options.type) { if (options.type) {
state.currentTab = options.type; state.currentTab = options.type;
} }
await getOrderList(); await getOrderList();
}); });
// //
function loadMore() { function loadMore() {
if (state.loadStatus === 'noMore') { if (state.loadStatus === 'noMore') {
return return;
} }
state.pagination.pageNo++; state.pagination.pageNo++;
getOrderList(); getOrderList();
} }
// //
onReachBottom(() => { onReachBottom(() => {
loadMore(); loadMore();
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.list-box { .list-box {
background-color: #fff; background-color: #fff;
.order-head { .order-head {
padding: 0 25rpx; padding: 0 25rpx;
height: 77rpx; height: 77rpx;
} }
.apply-box { .apply-box {
height: 82rpx; height: 82rpx;
.title { .title {
font-size: 24rpx; font-size: 24rpx;
} }
.value { .value {
font-size: 22rpx; font-size: 22rpx;
color: $dark-6; color: $dark-6;
} }
} }
.tool-btn-box { .tool-btn-box {
height: 100rpx; height: 100rpx;
.tool-btn { .tool-btn {
width: 160rpx; width: 160rpx;
height: 60rpx; height: 60rpx;
background: #f6f6f6; background: #f6f6f6;
border-radius: 30rpx; border-radius: 30rpx;
font-size: 26rpx; font-size: 26rpx;
font-weight: 400; font-weight: 400;
} }
} }
} }
</style> </style>

View File

@ -1,54 +1,82 @@
<template> <template>
<s-layout title="退货物流"> <s-layout title="退货物流">
<view> <view>
<form @submit="subRefund" report-submit='true'> <form @submit="subRefund" report-submit="true">
<view class='apply-return'> <view class="apply-return">
<view class='list borRadius14'> <view class="list borRadius14">
<view class='item acea-row row-between-wrapper' style="display: flex;align-items: center;"> <view
<view>物流公司</view> class="item acea-row row-between-wrapper"
<view v-if="state.expresses.length>0" style="flex:1"> style="display: flex; align-items: center"
<picker mode='selector' class='num' @change="bindPickerChange" :value="state.expressIndex" >
:range="state.expresses" range-key="name"> <view>物流公司</view>
<view class="picker acea-row row-between-wrapper" style="display: flex;justify-content: space-between;"> <view v-if="state.expresses.length > 0" style="flex: 1">
<view class='reason'>{{ state.expresses[state.expressIndex].name }}</view> <picker
<text class='iconfont _icon-forward' /> mode="selector"
</view> class="num"
</picker> @change="bindPickerChange"
</view> :value="state.expressIndex"
</view> :range="state.expresses"
<view class='item textarea acea-row row-between' style="display: flex;align-items: center;"> range-key="name"
<view>物流单号</view> >
<input placeholder='请填写物流单号' class='num' name="logisticsNo" <view
placeholder-class='placeholder' /> class="picker acea-row row-between-wrapper"
</view> style="display: flex; justify-content: space-between"
<button class='returnBnt bg-color ss-reset-button ui-BG-Main-Gradient sub-btn' >
form-type="submit" <view class="reason">{{ state.expresses[state.expressIndex].name }}</view>
style="background: linear-gradient(90deg,var(--ui-BG-Main),var(--ui-BG-Main-gradient))!important">提交</button> <text class="iconfont _icon-forward" />
</view> </view>
</view> </picker>
</form> </view>
</view> </view>
</s-layout> <view
class="item textarea acea-row row-between"
style="display: flex; align-items: center"
>
<view>物流单号</view>
<input
placeholder="请填写物流单号"
class="num"
name="logisticsNo"
placeholder-class="placeholder"
/>
</view>
<button
class="returnBnt bg-color ss-reset-button ui-BG-Main-Gradient sub-btn"
form-type="submit"
style="
background: linear-gradient(
90deg,
var(--ui-BG-Main),
var(--ui-BG-Main-gradient)
) !important;
"
>提交</button
>
</view>
</view>
</form>
</view>
</s-layout>
</template> </template>
<script setup> <script setup>
import { onLoad } from '@dcloudio/uni-app'; import { onLoad } from '@dcloudio/uni-app';
import { reactive } from 'vue'; import { reactive } from 'vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import AfterSaleApi from '@/sheep/api/trade/afterSale'; import AfterSaleApi from '@/sheep/api/trade/afterSale';
import DeliveryApi from '@/sheep/api/trade/delivery'; import DeliveryApi from '@/sheep/api/trade/delivery';
const state = reactive({ const state = reactive({
id: 0, // id: 0, //
expressIndex: 0, // expresses expressIndex: 0, // expresses
expresses: [], // expresses: [], //
}) });
function bindPickerChange(e) { function bindPickerChange(e) {
state.expressIndex = e.detail.value; state.expressIndex = e.detail.value;
} }
async function subRefund(e) { async function subRefund(e) {
let data = { let data = {
id: state.id, id: state.id,
logisticsId: state.expresses[state.expressIndex].id, logisticsId: state.expresses[state.expressIndex].id,
@ -62,134 +90,134 @@
title: '填写退货成功', title: '填写退货成功',
}); });
sheep.$router.go('/pages/order/aftersale/detail', { id: state.id }); sheep.$router.go('/pages/order/aftersale/detail', { id: state.id });
} }
// //
async function getExpressList() { async function getExpressList() {
const { code, data } = await DeliveryApi.getDeliveryExpressList(); const { code, data } = await DeliveryApi.getDeliveryExpressList();
if (code !== 0) { if (code !== 0) {
return; return;
} }
state.expresses = data; state.expresses = data;
} }
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;
// //
getExpressList(); getExpressList();
}) });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.apply-return { .apply-return {
padding: 20rpx 30rpx 70rpx 30rpx; padding: 20rpx 30rpx 70rpx 30rpx;
} }
.apply-return .list { .apply-return .list {
background-color: #fff; background-color: #fff;
margin-top: 18rpx; margin-top: 18rpx;
padding: 0 24rpx 70rpx 24rpx; padding: 0 24rpx 70rpx 24rpx;
} }
.apply-return .list .item { .apply-return .list .item {
min-height: 90rpx; min-height: 90rpx;
border-bottom: 1rpx solid #eee; border-bottom: 1rpx solid #eee;
font-size: 30rpx; font-size: 30rpx;
color: #333; color: #333;
} }
.apply-return .list .item .num { .apply-return .list .item .num {
color: #282828; color: #282828;
margin-left: 27rpx; margin-left: 27rpx;
// width: 227rpx; // width: 227rpx;
// text-align: right; // text-align: right;
} }
.apply-return .list .item .num .picker .reason { .apply-return .list .item .num .picker .reason {
width: 385rpx; width: 385rpx;
} }
.apply-return .list .item .num .picker .iconfont { .apply-return .list .item .num .picker .iconfont {
color: #666; color: #666;
font-size: 30rpx; font-size: 30rpx;
margin-top: 2rpx; margin-top: 2rpx;
} }
.apply-return .list .item.textarea { .apply-return .list .item.textarea {
padding: 24rpx 0; padding: 24rpx 0;
} }
.apply-return .list .item textarea { .apply-return .list .item textarea {
height: 100rpx; height: 100rpx;
font-size: 30rpx; font-size: 30rpx;
} }
.apply-return .list .item .placeholder { .apply-return .list .item .placeholder {
color: #bbb; color: #bbb;
} }
.apply-return .list .item .title { .apply-return .list .item .title {
height: 95rpx; height: 95rpx;
width: 100%; width: 100%;
} }
.apply-return .list .item .title .tip { .apply-return .list .item .title .tip {
font-size: 30rpx; font-size: 30rpx;
color: #bbb; color: #bbb;
} }
.apply-return .list .item .upload { .apply-return .list .item .upload {
padding-bottom: 36rpx; padding-bottom: 36rpx;
} }
.apply-return .list .item .upload .pictrue { .apply-return .list .item .upload .pictrue {
border-radius: 14rpx; border-radius: 14rpx;
margin: 22rpx 23rpx 0 0; margin: 22rpx 23rpx 0 0;
width: 156rpx; width: 156rpx;
height: 156rpx; height: 156rpx;
position: relative; position: relative;
font-size: 24rpx; font-size: 24rpx;
color: #bbb; color: #bbb;
} }
.apply-return .list .item .upload .pictrue:nth-of-type(4n) { .apply-return .list .item .upload .pictrue:nth-of-type(4n) {
margin-right: 0; margin-right: 0;
} }
.apply-return .list .item .upload .pictrue image { .apply-return .list .item .upload .pictrue image {
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius: 14rpx; border-radius: 14rpx;
} }
.apply-return .list .item .upload .pictrue .icon-guanbi1 { .apply-return .list .item .upload .pictrue .icon-guanbi1 {
position: absolute; position: absolute;
font-size: 45rpx; font-size: 45rpx;
top: -10rpx; top: -10rpx;
right: -10rpx; right: -10rpx;
} }
.apply-return .list .item .upload .pictrue .icon-icon25201 { .apply-return .list .item .upload .pictrue .icon-icon25201 {
color: #bfbfbf; color: #bfbfbf;
font-size: 50rpx; font-size: 50rpx;
} }
.apply-return .list .item .upload .pictrue:nth-last-child(1) { .apply-return .list .item .upload .pictrue:nth-last-child(1) {
border: 1rpx solid #ddd; border: 1rpx solid #ddd;
box-sizing: border-box; box-sizing: border-box;
} }
.apply-return .returnBnt { .apply-return .returnBnt {
font-size: 32rpx; font-size: 32rpx;
color: #fff; color: #fff;
width: 100%; width: 100%;
height: 86rpx; height: 86rpx;
border-radius: 50rpx; border-radius: 50rpx;
text-align: center; text-align: center;
line-height: 86rpx; line-height: 86rpx;
margin: 43rpx auto; margin: 43rpx auto;
} }
</style> </style>

View File

@ -221,7 +221,7 @@
pointStatus: false, // TODO pointStatus: false, // TODO
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;
@ -247,7 +247,7 @@
pointStatus: false, // TODO pointStatus: false, // TODO
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;

View File

@ -371,7 +371,7 @@
// //
function onComment(id) { function onComment(id) {
sheep.$router.go('/pages/goods/comment/add', { sheep.$router.go('/pages/goods/comment/add', {
id id,
}); });
} }

View File

@ -13,10 +13,10 @@
</uni-swiper-dot> </uni-swiper-dot>
<view class="log-card-msg"> <view class="log-card-msg">
<!-- TODO 芋艿优化点展示状态 --> <!-- TODO 芋艿优化点展示状态 -->
<!-- <view class="ss-flex ss-m-b-8">--> <!-- <view class="ss-flex ss-m-b-8">-->
<!-- <view>物流状态</view>--> <!-- <view>物流状态</view>-->
<!-- <view class="warning-color">{{ state.info.status_text }}</view>--> <!-- <view class="warning-color">{{ state.info.status_text }}</view>-->
<!-- </view>--> <!-- </view>-->
<view class="ss-m-b-8">快递单号{{ state.info.logisticsNo }}</view> <view class="ss-m-b-8">快递单号{{ state.info.logisticsNo }}</view>
<view>快递公司{{ state.info.logisticsName }}</view> <view>快递公司{{ state.info.logisticsName }}</view>
</view> </view>
@ -35,9 +35,9 @@
</view> </view>
<view class="log-content-msg"> <view class="log-content-msg">
<!-- TODO 芋艿优化点展示状态 --> <!-- TODO 芋艿优化点展示状态 -->
<!-- <view class="log-msg-title ss-m-b-20">--> <!-- <view class="log-msg-title ss-m-b-20">-->
<!-- {{ item.status_text }}--> <!-- {{ item.status_text }}-->
<!-- </view>--> <!-- </view>-->
<view class="log-msg-desc ss-m-b-16">{{ item.content }}</view> <view class="log-msg-desc ss-m-b-16">{{ item.content }}</view>
<view class="log-msg-date ss-m-b-40"> <view class="log-msg-date ss-m-b-40">
{{ sheep.$helper.timeFormat(item.time, 'yyyy-mm-dd hh:MM:ss') }} {{ sheep.$helper.timeFormat(item.time, 'yyyy-mm-dd hh:MM:ss') }}
@ -78,7 +78,7 @@
} }
async function getOrderDetail(id) { async function getOrderDetail(id) {
const { data } = await OrderApi.getOrder(id) const { data } = await OrderApi.getOrder(id);
state.info = data; state.info = data;
} }

View File

@ -1,243 +1,284 @@
<!-- 订单列表 --> <!-- 订单列表 -->
<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
</su-sticky> :list="tabMaps"
<s-empty v-if="state.pagination.total === 0" icon="/static/order-empty.png" text="暂无订单" /> :scrollable="false"
<view v-if="state.pagination.total > 0"> @change="onTabsChange"
<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" :current="state.currentTab"
:key="order.id" @tap="onOrderDetail(order.id)"> />
<view class="order-card-header ss-flex ss-col-center ss-row-between ss-p-x-20"> </su-sticky>
<view class="order-no">订单号{{ order.no }}</view> <s-empty v-if="state.pagination.total === 0" icon="/static/order-empty.png" text="暂无订单" />
<view class="order-state ss-font-26" :class="formatOrderColor(order)"> <view v-if="state.pagination.total > 0">
<view
class="bg-white order-list-card-box ss-r-10 ss-m-t-14 ss-m-20"
v-for="order in state.pagination.list"
:key="order.id"
@tap="onOrderDetail(order.id)"
>
<view class="order-card-header ss-flex ss-col-center ss-row-between ss-p-x-20">
<view class="order-no">订单号{{ order.no }}</view>
<view class="order-state ss-font-26" :class="formatOrderColor(order)">
{{ formatOrderStatus(order) }} {{ formatOrderStatus(order) }}
</view> </view>
</view> </view>
<view class="border-bottom" v-for="item in order.items" :key="item.id"> <view class="border-bottom" v-for="item in order.items" :key="item.id">
<s-goods-item <s-goods-item
:img="item.picUrl" :img="item.picUrl"
:title="item.spuName" :title="item.spuName"
:skuText="item.properties.map((property) => property.valueName).join(' ')" :skuText="item.properties.map((property) => property.valueName).join(' ')"
:price="item.price" :price="item.price"
:num="item.count" :num="item.count"
/> />
</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> <view class="discounts-money pay-color"> {{ fen2yuan(order.payPrice) }} </view>
</view> </view>
</view> </view>
<view class="order-card-footer ss-flex ss-col-center ss-p-x-20" <view
:class="order.buttons.length > 3 ? 'ss-row-between' : 'ss-row-right'"> class="order-card-footer ss-flex ss-col-center ss-p-x-20"
<view class="ss-flex ss-col-center"> :class="order.buttons.length > 3 ? 'ss-row-between' : 'ss-row-right'"
<button v-if="order.buttons.includes('combination')" class="tool-btn ss-reset-button" >
@tap.stop="onOrderGroupon(order)"> <view class="ss-flex ss-col-center">
<button
v-if="order.buttons.includes('combination')"
class="tool-btn ss-reset-button"
@tap.stop="onOrderGroupon(order)"
>
拼团详情 拼团详情
</button> </button>
<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"
</button> @tap.stop="onExpress(order.id)"
<button v-if="order.buttons.includes('cancel')" class="tool-btn ss-reset-button" >
@tap.stop="onCancel(order.id)"> 查看物流
取消订单 </button>
</button> <button
<button v-if="order.buttons.includes('comment')" class="tool-btn ss-reset-button" v-if="order.buttons.includes('cancel')"
@tap.stop="onComment(order.id)"> class="tool-btn ss-reset-button"
评价 @tap.stop="onCancel(order.id)"
</button> >
<button 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('comment')"
<button v-if="order.buttons.includes('pay')" class="tool-btn ss-reset-button ui-BG-Main-Gradient" class="tool-btn ss-reset-button"
@tap.stop="onPay(order.payOrderId)"> @tap.stop="onComment(order.id)"
继续支付 >
</button> 评价
</view> </button>
</view> <button
</view> v-if="order.buttons.includes('delete')"
</view> class="delete-btn ss-reset-button"
@tap.stop="onDelete(order.id)"
>
删除订单
</button>
<button
v-if="order.buttons.includes('pay')"
class="tool-btn ss-reset-button ui-BG-Main-Gradient"
@tap.stop="onPay(order.payOrderId)"
>
继续支付
</button>
</view>
</view>
</view>
</view>
<!-- 加载更多 --> <!-- 加载更多 -->
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{ <uni-load-more
v-if="state.pagination.total > 0"
:status="state.loadStatus"
:content-text="{
contentdown: '上拉加载更多', contentdown: '上拉加载更多',
}" @tap="loadMore" /> }"
</s-layout> @tap="loadMore"
/>
</s-layout>
</template> </template>
<script setup> <script setup>
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 { 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';
import { import { isEmpty } from 'lodash';
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';
// //
const state = reactive({ const state = reactive({
currentTab: 0, // tabMaps currentTab: 0, // tabMaps
pagination: { pagination: {
list: [], list: [],
total: 0, total: 0,
pageNo: 1, pageNo: 1,
pageSize: 5, pageSize: 5,
}, },
loadStatus: '' loadStatus: '',
}); });
const tabMaps = [{ const tabMaps = [
name: '全部' {
}, name: '全部',
{ },
name: '待付款', {
value: 0, name: '待付款',
}, value: 0,
{ },
name: '待发货', {
value: 10, name: '待发货',
}, value: 10,
{ },
name: '待收货', {
value: 20, name: '待收货',
}, value: 20,
{ },
name: '待评价', {
value: 30, name: '待评价',
}, value: 30,
]; },
];
// //
function onTabsChange(e) { function onTabsChange(e) {
if (state.currentTab === e.index) { if (state.currentTab === e.index) {
return; return;
} }
// //
resetPagination(state.pagination); resetPagination(state.pagination);
state.currentTab = e.index; state.currentTab = e.index;
getOrderList(); getOrderList();
} }
// //
function onOrderDetail(id) { function onOrderDetail(id) {
sheep.$router.go('/pages/order/detail', { sheep.$router.go('/pages/order/detail', {
id, id,
}); });
} }
// //
function onOrderGroupon(order) { function onOrderGroupon(order) {
sheep.$router.go('/pages/activity/groupon/detail', { sheep.$router.go('/pages/activity/groupon/detail', {
id: order.combinationRecordId, id: order.combinationRecordId,
}); });
} }
// //
function onPay(payOrderId) { function onPay(payOrderId) {
sheep.$router.go('/pages/pay/index', { sheep.$router.go('/pages/pay/index', {
id: payOrderId, id: payOrderId,
}); });
} }
// //
function onComment(id) { function onComment(id) {
sheep.$router.go('/pages/goods/comment/add', { sheep.$router.go('/pages/goods/comment/add', {
id, id,
}); });
} }
// TODO // TODO
async function onConfirm(order, ignore = false) { async function onConfirm(order, ignore = false) {
// //
// todo: // todo:
// 1.return // 1.return
// 2.mpConfirm,App.vueshow // 2.mpConfirm,App.vueshow
let isOpenBusinessView = true; let isOpenBusinessView = true;
if ( if (
sheep.$platform.name === 'WechatMiniProgram' && sheep.$platform.name === 'WechatMiniProgram' &&
!isEmpty(order.wechat_extra_data) && !isEmpty(order.wechat_extra_data) &&
isOpenBusinessView && isOpenBusinessView &&
!ignore !ignore
) { ) {
mpConfirm(order); mpConfirm(order);
return; return;
} }
// //
const { code } = await OrderApi.receiveOrder(order.id); const { code } = await OrderApi.receiveOrder(order.id);
if (code === 0) { if (code === 0) {
resetPagination(state.pagination); resetPagination(state.pagination);
await getOrderList(); await getOrderList();
} }
} }
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
// TODO // TODO
function mpConfirm(order) { function mpConfirm(order) {
if (!wx.openBusinessView) { if (!wx.openBusinessView) {
sheep.$helper.toast(`请升级微信版本`); sheep.$helper.toast(`请升级微信版本`);
return; return;
} }
wx.openBusinessView({ wx.openBusinessView({
businessType: 'weappOrderConfirm', businessType: 'weappOrderConfirm',
extraData: { extraData: {
merchant_id: '1481069012', merchant_id: '1481069012',
merchant_trade_no: order.wechat_extra_data.merchant_trade_no, merchant_trade_no: order.wechat_extra_data.merchant_trade_no,
transaction_id: order.wechat_extra_data.transaction_id, transaction_id: order.wechat_extra_data.transaction_id,
}, },
success(response) { success(response) {
console.log('success:', response); console.log('success:', response);
if (response.errMsg === 'openBusinessView:ok') { if (response.errMsg === 'openBusinessView:ok') {
if (response.extraData.status === 'success') { if (response.extraData.status === 'success') {
onConfirm(order, true); onConfirm(order, true);
} }
} }
}, },
fail(error) { fail(error) {
console.log('error:', error); console.log('error:', error);
}, },
complete(result) { complete(result) {
console.log('result:', result); console.log('result:', result);
}, },
}); });
} }
// #endif // #endif
// //
async function onExpress(id) { async function onExpress(id) {
sheep.$router.go('/pages/order/express/log', { sheep.$router.go('/pages/order/express/log', {
id, id,
}); });
} }
// //
async function onCancel(orderId) { async function onCancel(orderId) {
uni.showModal({ uni.showModal({
title: '提示', title: '提示',
content: '确定要取消订单吗?', content: '确定要取消订单吗?',
success: async function(res) { success: async function (res) {
if (!res.confirm) { if (!res.confirm) {
return; return;
} }
const { code } = await OrderApi.cancelOrder(orderId); const { code } = await OrderApi.cancelOrder(orderId);
if (code === 0) { if (code === 0) {
// //
@ -246,208 +287,209 @@
orderInfo.status = 40; orderInfo.status = 40;
handleOrderButtons(orderInfo); handleOrderButtons(orderInfo);
} }
}, },
}); });
} }
// //
function onDelete(orderId) { function onDelete(orderId) {
uni.showModal({ uni.showModal({
title: '提示', title: '提示',
content: '确定要删除订单吗?', content: '确定要删除订单吗?',
success: async function(res) { success: async function (res) {
if (res.confirm) { if (res.confirm) {
const { code } = await OrderApi.deleteOrder(orderId); const { code } = await OrderApi.deleteOrder(orderId);
if (code === 0) { if (code === 0) {
// //
let index = state.pagination.list.findIndex((order) => order.id === orderId); let index = state.pagination.list.findIndex((order) => order.id === orderId);
state.pagination.list.splice(index, 1); state.pagination.list.splice(index, 1);
} }
} }
}, },
}); });
} }
// //
async function getOrderList() { async function getOrderList() {
state.loadStatus = 'loading'; state.loadStatus = 'loading';
let { code, data } = await OrderApi.getOrderPage({ let { code, data } = await OrderApi.getOrderPage({
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';
} }
onLoad(async (options) => { onLoad(async (options) => {
if (options.type) { if (options.type) {
state.currentTab = options.type; state.currentTab = options.type;
} }
await getOrderList(); await getOrderList();
}); });
// //
function loadMore() { function loadMore() {
if (state.loadStatus === 'noMore') { if (state.loadStatus === 'noMore') {
return return;
} }
state.pagination.pageNo++; state.pagination.pageNo++;
getOrderList(); getOrderList();
} }
// //
onReachBottom(() => { onReachBottom(() => {
loadMore(); loadMore();
}); });
// //
onPullDownRefresh(() => { onPullDownRefresh(() => {
resetPagination(state.pagination); resetPagination(state.pagination);
getOrderList(); getOrderList();
setTimeout(function() { setTimeout(function () {
uni.stopPullDownRefresh(); uni.stopPullDownRefresh();
}, 800); }, 800);
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.score-img { .score-img {
width: 36rpx; width: 36rpx;
height: 36rpx; height: 36rpx;
margin: 0 4rpx; margin: 0 4rpx;
} }
.tool-btn { .tool-btn {
width: 160rpx; width: 160rpx;
height: 60rpx; height: 60rpx;
background: #f6f6f6; background: #f6f6f6;
font-size: 26rpx; font-size: 26rpx;
border-radius: 30rpx; border-radius: 30rpx;
margin-right: 10rpx; margin-right: 10rpx;
&:last-of-type { &:last-of-type {
margin-right: 0; margin-right: 0;
} }
} }
.delete-btn { .delete-btn {
width: 160rpx; width: 160rpx;
height: 56rpx; height: 56rpx;
color: #ff3000; color: #ff3000;
background: #fee; background: #fee;
border-radius: 28rpx; border-radius: 28rpx;
font-size: 26rpx; font-size: 26rpx;
margin-right: 10rpx; margin-right: 10rpx;
line-height: normal; line-height: normal;
&:last-of-type { &:last-of-type {
margin-right: 0; margin-right: 0;
} }
} }
.apply-btn { .apply-btn {
width: 140rpx; width: 140rpx;
height: 50rpx; height: 50rpx;
border-radius: 25rpx; border-radius: 25rpx;
font-size: 24rpx; font-size: 24rpx;
border: 2rpx solid #dcdcdc; border: 2rpx solid #dcdcdc;
line-height: normal; line-height: normal;
margin-left: 16rpx; margin-left: 16rpx;
} }
.swiper-box { .swiper-box {
flex: 1; flex: 1;
.swiper-item { .swiper-item {
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
} }
.order-list-card-box { .order-list-card-box {
.order-card-header { .order-card-header {
height: 80rpx; height: 80rpx;
.order-no { .order-no {
font-size: 26rpx; font-size: 26rpx;
font-weight: 500; font-weight: 500;
} }
.order-state {} .order-state {
} }
}
.pay-box { .pay-box {
.discounts-title { .discounts-title {
font-size: 24rpx; font-size: 24rpx;
line-height: normal; line-height: normal;
color: #999999; color: #999999;
} }
.discounts-money { .discounts-money {
font-size: 24rpx; font-size: 24rpx;
line-height: normal; line-height: normal;
color: #999; color: #999;
font-family: OPPOSANS; font-family: OPPOSANS;
} }
.pay-color { .pay-color {
color: #333; color: #333;
} }
} }
.order-card-footer { .order-card-footer {
height: 100rpx; height: 100rpx;
.more-item-box { .more-item-box {
padding: 20rpx; padding: 20rpx;
.more-item { .more-item {
height: 60rpx; height: 60rpx;
.title { .title {
font-size: 26rpx; font-size: 26rpx;
} }
} }
} }
.more-btn { .more-btn {
color: $dark-9; color: $dark-9;
font-size: 24rpx; font-size: 24rpx;
} }
.content { .content {
width: 154rpx; width: 154rpx;
color: #333333; color: #333333;
font-size: 26rpx; font-size: 26rpx;
font-weight: 500; font-weight: 500;
} }
} }
} }
:deep(.uni-tooltip-popup) { :deep(.uni-tooltip-popup) {
background: var(--ui-BG); background: var(--ui-BG);
} }
.warning-color { .warning-color {
color: #faad14; color: #faad14;
} }
.danger-color { .danger-color {
color: #ff3000; color: #ff3000;
} }
.success-color { .success-color {
color: #52c41a; color: #52c41a;
} }
.info-color { .info-color {
color: #999999; color: #999999;
} }
</style> </style>

View File

@ -135,12 +135,13 @@
// payOrder.status => payStatus // payOrder.status => payStatus
function checkPayStatus() { function checkPayStatus() {
if (state.orderInfo.status === 10 if (state.orderInfo.status === 10 || state.orderInfo.status === 20) {
|| state.orderInfo.status === 20 ) { // //
state.payStatus = 2; state.payStatus = 2;
return; return;
} }
if (state.orderInfo.status === 30) { // if (state.orderInfo.status === 30) {
//
state.payStatus = -1; state.payStatus = -1;
return; return;
} }
@ -169,17 +170,19 @@
// //
async function setPayMethods() { async function setPayMethods() {
const { data, code } = await PayChannelApi.getEnableChannelCodeList(state.orderInfo.appId) const { data, code } = await PayChannelApi.getEnableChannelCodeList(state.orderInfo.appId);
if (code !== 0) { if (code !== 0) {
return return;
} }
state.payMethods = getPayMethods(data) state.payMethods = getPayMethods(data);
} }
onLoad((options) => { onLoad((options) => {
if (sheep.$platform.name === 'WechatOfficialAccount' if (
&& sheep.$platform.os === 'ios' sheep.$platform.name === 'WechatOfficialAccount' &&
&& !sheep.$platform.landingPage.includes('pages/pay/index')) { sheep.$platform.os === 'ios' &&
!sheep.$platform.landingPage.includes('pages/pay/index')
) {
location.reload(); location.reload();
return; return;
} }
@ -208,7 +211,6 @@
position: relative; position: relative;
padding: 60rpx 20rpx 40rpx; padding: 60rpx 20rpx 40rpx;
.money-text { .money-text {
color: $red; color: $red;
font-size: 46rpx; font-size: 46rpx;

View File

@ -8,7 +8,7 @@
<view class="title">充值金额</view> <view class="title">充值金额</view>
<view class="num" :class="item.refundStatus === 10 ? 'danger-color' : 'success-color'"> <view class="num" :class="item.refundStatus === 10 ? 'danger-color' : 'success-color'">
{{ fen2yuan(item.payPrice) }} {{ fen2yuan(item.payPrice) }}
<text v-if="item.bonusPrice > 0">赠送 {{ fen2yuan(item.bonusPrice)}} </text> <text v-if="item.bonusPrice > 0">赠送 {{ fen2yuan(item.bonusPrice) }} </text>
</view> </view>
</view> </view>
<view class="status-box item ss-flex ss-col-center ss-row-between"> <view class="status-box item ss-flex ss-col-center ss-row-between">
@ -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>

View File

@ -1,259 +1,274 @@
<!-- 充值界面 --> <!-- 充值界面 -->
<template> <template>
<s-layout title="充值" class="withdraw-wrap" navbar="inner"> <s-layout title="充值" class="withdraw-wrap" navbar="inner">
<view class="wallet-num-box ss-flex ss-col-center ss-row-between" :style="[ <view
{ class="wallet-num-box ss-flex ss-col-center ss-row-between"
marginTop: '-' + Number(statusBarHeight + 88) + 'rpx', :style="[
paddingTop: Number(statusBarHeight + 108) + 'rpx', {
}, marginTop: '-' + Number(statusBarHeight + 88) + 'rpx',
]"> paddingTop: Number(statusBarHeight + 108) + 'rpx',
<view class=""> },
<view class="num-title">当前余额</view> ]"
<view class="wallet-num">{{ fen2yuan(userWallet.balance) }}</view> >
</view> <view class="">
<button class="ss-reset-button log-btn" @tap="sheep.$router.go('/pages/pay/recharge-log')"> <view class="num-title">当前余额</view>
<view class="wallet-num">{{ fen2yuan(userWallet.balance) }}</view>
</view>
<button class="ss-reset-button log-btn" @tap="sheep.$router.go('/pages/pay/recharge-log')">
充值记录 充值记录
</button> </button>
</view> </view>
<view class="recharge-box"> <view class="recharge-box">
<view class="recharge-card-box"> <view class="recharge-card-box">
<view class="input-label ss-m-b-50">充值金额</view> <view class="input-label ss-m-b-50">充值金额</view>
<view class="input-box ss-flex border-bottom ss-p-b-20"> <view class="input-box ss-flex border-bottom ss-p-b-20">
<view class="unit"></view> <view class="unit"></view>
<uni-easyinput v-model="state.recharge_money" type="digit" placeholder="请输入充值金额" <uni-easyinput
:inputBorder="false" /> v-model="state.recharge_money"
</view> type="digit"
<view class="face-value-box ss-flex ss-flex-wrap ss-m-y-40"> placeholder="请输入充值金额"
<button class="ss-reset-button face-value-btn" v-for="item in state.packageList" :key="item.money" :inputBorder="false"
:class="[{ 'btn-active': state.recharge_money === fen2yuan(item.payPrice) }]" />
@tap="onCard(item.payPrice)"> </view>
<text class="face-value-title">{{ fen2yuan(item.payPrice) }}</text> <view class="face-value-box ss-flex ss-flex-wrap ss-m-y-40">
<view v-if="item.bonusPrice" class="face-value-tag"> <button
{{ fen2yuan(item.bonusPrice) }} class="ss-reset-button face-value-btn"
v-for="item in state.packageList"
:key="item.money"
:class="[{ 'btn-active': state.recharge_money === fen2yuan(item.payPrice) }]"
@tap="onCard(item.payPrice)"
>
<text class="face-value-title">{{ fen2yuan(item.payPrice) }}</text>
<view v-if="item.bonusPrice" class="face-value-tag">
{{ fen2yuan(item.bonusPrice) }}
</view> </view>
</button> </button>
</view> </view>
<button class="ss-reset-button save-btn ui-BG-Main-Gradient ss-m-t-60 ui-Shadow-Main" @tap="onConfirm"> <button
确认充值 class="ss-reset-button save-btn ui-BG-Main-Gradient ss-m-t-60 ui-Shadow-Main"
</button> @tap="onConfirm"
</view> >
</view> 确认充值
</s-layout> </button>
</view>
</view>
</s-layout>
</template> </template>
<script setup> <script setup>
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 { fen2yuan } from '@/sheep/hooks/useGoods'; import { fen2yuan } from '@/sheep/hooks/useGoods';
import PayWalletApi from '@/sheep/api/pay/wallet'; import PayWalletApi from '@/sheep/api/pay/wallet';
const userWallet = computed(() => sheep.$store('user').userWallet); const userWallet = computed(() => sheep.$store('user').userWallet);
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2; const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
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 state = reactive({ const state = reactive({
recharge_money: '', // recharge_money: '', //
packageList: [], packageList: [],
}); });
// //
function onCard(e) { function onCard(e) {
state.recharge_money = fen2yuan(e); state.recharge_money = fen2yuan(e);
} }
// //
async function getRechargeTabs() { async function getRechargeTabs() {
const { code, data } = await PayWalletApi.getWalletRechargePackageList(); const { code, data } = await PayWalletApi.getWalletRechargePackageList();
if (code !== 0) { if (code !== 0) {
return; return;
} }
state.packageList = data; state.packageList = data;
} }
// //
async function onConfirm() { async function onConfirm() {
const { code, data } = await PayWalletApi.createWalletRecharge({ const { code, data } = await PayWalletApi.createWalletRecharge({
packageId: state.packageList.find((item) => fen2yuan(item.payPrice) === state.recharge_money)?.id, packageId: state.packageList.find((item) => fen2yuan(item.payPrice) === state.recharge_money)
payPrice: state.recharge_money * 100 ?.id,
}); payPrice: state.recharge_money * 100,
if (code !== 0) { });
return; if (code !== 0) {
} return;
}
// #ifdef MP // #ifdef MP
sheep.$platform.useProvider('wechat').subscribeMessage('money_change'); sheep.$platform.useProvider('wechat').subscribeMessage('money_change');
// #endif // #endif
sheep.$router.go('/pages/pay/index', { sheep.$router.go('/pages/pay/index', {
id: data.payOrderId, id: data.payOrderId,
orderType: 'recharge' orderType: 'recharge',
}); });
} }
onLoad(() => { onLoad(() => {
getRechargeTabs(); getRechargeTabs();
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep() { :deep() {
.uni-input-input { .uni-input-input {
font-family: OPPOSANS !important; font-family: OPPOSANS !important;
} }
} }
.wallet-num-box { .wallet-num-box {
padding: 0 40rpx 80rpx; padding: 0 40rpx 80rpx;
background: var(--ui-BG-Main) v-bind(headerBg) center/750rpx 100% no-repeat; background: var(--ui-BG-Main) v-bind(headerBg) center/750rpx 100% no-repeat;
border-radius: 0 0 5% 5%; border-radius: 0 0 5% 5%;
.num-title { .num-title {
font-size: 26rpx; font-size: 26rpx;
font-weight: 500; font-weight: 500;
color: $white; color: $white;
margin-bottom: 20rpx; margin-bottom: 20rpx;
} }
.wallet-num { .wallet-num {
font-size: 60rpx; font-size: 60rpx;
font-weight: 500; font-weight: 500;
color: $white; color: $white;
font-family: OPPOSANS; font-family: OPPOSANS;
} }
.log-btn { .log-btn {
width: 170rpx; width: 170rpx;
height: 60rpx; height: 60rpx;
line-height: 60rpx; line-height: 60rpx;
border: 1rpx solid $white; border: 1rpx solid $white;
border-radius: 30rpx; border-radius: 30rpx;
padding: 0; padding: 0;
font-size: 26rpx; font-size: 26rpx;
font-weight: 500; font-weight: 500;
color: $white; color: $white;
} }
} }
.recharge-box { .recharge-box {
position: relative; position: relative;
padding: 0 30rpx; padding: 0 30rpx;
margin-top: -60rpx; margin-top: -60rpx;
} }
.save-btn { .save-btn {
width: 620rpx; width: 620rpx;
height: 86rpx; height: 86rpx;
border-radius: 44rpx; border-radius: 44rpx;
font-size: 30rpx; font-size: 30rpx;
} }
.recharge-card-box { .recharge-card-box {
width: 690rpx; width: 690rpx;
background: var(--ui-BG); background: var(--ui-BG);
border-radius: 20rpx; border-radius: 20rpx;
padding: 30rpx; padding: 30rpx;
box-sizing: border-box; box-sizing: border-box;
.input-label { .input-label {
font-size: 30rpx; font-size: 30rpx;
font-weight: 500; font-weight: 500;
color: #333; color: #333;
} }
.unit { .unit {
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 48rpx; font-size: 48rpx;
font-weight: 500; font-weight: 500;
} }
.uni-easyinput__placeholder-class { .uni-easyinput__placeholder-class {
font-size: 30rpx; font-size: 30rpx;
height: 60rpx; height: 60rpx;
display: flex; display: flex;
align-items: center; align-items: center;
} }
:deep(.uni-easyinput__content-input) { :deep(.uni-easyinput__content-input) {
font-size: 48rpx; font-size: 48rpx;
} }
.face-value-btn { .face-value-btn {
width: 200rpx; width: 200rpx;
height: 144rpx; height: 144rpx;
border: 1px solid var(--ui-BG-Main); border: 1px solid var(--ui-BG-Main);
border-radius: 10rpx; border-radius: 10rpx;
position: relative; position: relative;
z-index: 1; z-index: 1;
margin-bottom: 15rpx; margin-bottom: 15rpx;
margin-right: 15rpx; margin-right: 15rpx;
&:nth-of-type(3n) { &:nth-of-type(3n) {
margin-right: 0; margin-right: 0;
} }
.face-value-title { .face-value-title {
font-size: 36rpx; font-size: 36rpx;
font-weight: 500; font-weight: 500;
color: var(--ui-BG-Main); color: var(--ui-BG-Main);
font-family: OPPOSANS; font-family: OPPOSANS;
&::after { &::after {
content: '元'; content: '元';
font-size: 24rpx; font-size: 24rpx;
margin-left: 6rpx; margin-left: 6rpx;
} }
} }
.face-value-tag { .face-value-tag {
position: absolute; position: absolute;
z-index: 2; z-index: 2;
height: 40rpx; height: 40rpx;
line-height: 40rpx; line-height: 40rpx;
background: var(--ui-BG-Main); background: var(--ui-BG-Main);
opacity: 0.8; opacity: 0.8;
border-radius: 10rpx 0 20rpx 0; border-radius: 10rpx 0 20rpx 0;
top: 0; top: 0;
left: -2rpx; left: -2rpx;
padding: 0 16rpx; padding: 0 16rpx;
font-size: 22rpx; font-size: 22rpx;
color: $white; color: $white;
font-family: OPPOSANS; font-family: OPPOSANS;
} }
&::before { &::before {
position: absolute; position: absolute;
content: ' '; content: ' ';
width: 100%; width: 100%;
height: 100%; height: 100%;
background: var(--ui-BG-Main); background: var(--ui-BG-Main);
opacity: 0.1; opacity: 0.1;
z-index: 0; z-index: 0;
left: 0; left: 0;
top: 0; top: 0;
} }
} }
.btn-active { .btn-active {
z-index: 1; z-index: 1;
&::before { &::before {
content: ''; content: '';
background: var(--ui-BG-Main); background: var(--ui-BG-Main);
opacity: 1; opacity: 1;
} }
.face-value-title { .face-value-title {
color: $white; color: $white;
position: relative; position: relative;
z-index: 1; z-index: 1;
font-family: OPPOSANS; font-family: OPPOSANS;
} }
.face-value-tag { .face-value-tag {
background: $white; background: $white;
color: var(--ui-BG-Main); color: var(--ui-BG-Main);
font-family: OPPOSANS; font-family: OPPOSANS;
} }
} }
} }
</style> </style>

View File

@ -53,7 +53,7 @@
if (true) { if (true) {
sheep.$router.go('/pages/public/richtext', { sheep.$router.go('/pages/public/richtext', {
title: '常见问题', title: '常见问题',
}) });
return; return;
} }
getFaqList(); getFaqList();

View File

@ -41,7 +41,6 @@
} }
getRichTextContent(options.id, options.title); getRichTextContent(options.id, options.title);
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -35,7 +35,7 @@
class="list-border" class="list-border"
@tap=" @tap="
sheep.$router.go('/pages/public/richtext', { sheep.$router.go('/pages/public/richtext', {
title: '关于我们' title: '关于我们',
}) })
" "
/> />
@ -59,7 +59,7 @@
class="tcp-text" class="tcp-text"
@tap=" @tap="
sheep.$router.go('/pages/public/richtext', { sheep.$router.go('/pages/public/richtext', {
title: '用户协议' title: '用户协议',
}) })
" "
> >
@ -70,7 +70,7 @@
class="tcp-text" class="tcp-text"
@tap=" @tap="
sheep.$router.go('/pages/public/richtext', { sheep.$router.go('/pages/public/richtext', {
title: '隐私协议' title: '隐私协议',
}) })
" "
> >

View File

@ -1,78 +1,118 @@
<!-- 收货地址的新增/编辑 --> <!-- 收货地址的新增/编辑 -->
<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"
<view class="bg-white form-box ss-p-x-30"> v-model="state.model"
<uni-forms-item name="name" label="收货人" class="form-item"> :rules="rules"
<uni-easyinput v-model="state.model.name" placeholder="请填写收货人姓名" :inputBorder="false" validateTrigger="bind"
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal" /> labelWidth="160"
</uni-forms-item> labelAlign="left"
border
:labelStyle="{ fontWeight: 'bold' }"
>
<view class="bg-white form-box ss-p-x-30">
<uni-forms-item name="name" label="收货人" class="form-item">
<uni-easyinput
v-model="state.model.name"
placeholder="请填写收货人姓名"
:inputBorder="false"
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
/>
</uni-forms-item>
<uni-forms-item name="mobile" label="手机号" class="form-item"> <uni-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"
</uni-easyinput> type="number"
</uni-forms-item> placeholder="请输入手机号"
<uni-forms-item name="areaName" label="省市区" @tap="state.showRegion = true" class="form-item"> :inputBorder="false"
<uni-easyinput v-model="state.model.areaName" disabled :inputBorder="false" placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
:styles="{ disableColor: '#fff', color: '#333' }" >
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal" </uni-easyinput>
placeholder="请选择省市区"> </uni-forms-item>
<template v-slot:right> <uni-forms-item
<uni-icons type="right" /> name="areaName"
</template> label="省市区"
</uni-easyinput> @tap="state.showRegion = true"
</uni-forms-item> class="form-item"
<uni-forms-item name="detailAddress" label="详细地址" :formItemStyle="{ alignItems: 'flex-start' }" >
:labelStyle="{ lineHeight: '5em' }" class="textarea-item"> <uni-easyinput
<uni-easyinput :inputBorder="false" type="textarea" v-model="state.model.detailAddress" v-model="state.model.areaName"
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal" disabled
placeholder="请输入详细地址" clearable /> :inputBorder="false"
</uni-forms-item> :styles="{ disableColor: '#fff', color: '#333' }"
</view> placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
<view class="ss-m-y-20 bg-white ss-p-x-30 ss-flex ss-row-between ss-col-center default-box"> placeholder="请选择省市区"
<view class="default-box-title"> 设为默认地址 </view> >
<su-switch style="transform: scale(0.8)" v-model="state.model.defaultStatus" /> <template v-slot:right>
</view> <uni-icons type="right" />
</uni-forms> </template>
<su-fixed bottom :opacity="false" bg="" placeholder :noFixed="false" :index="10"> </uni-easyinput>
<view class="footer-box ss-flex-col ss-row-between ss-p-20"> </uni-forms-item>
<view class="ss-m-b-20"> <uni-forms-item
name="detailAddress"
label="详细地址"
:formItemStyle="{ alignItems: 'flex-start' }"
:labelStyle="{ lineHeight: '5em' }"
class="textarea-item"
>
<uni-easyinput
:inputBorder="false"
type="textarea"
v-model="state.model.detailAddress"
placeholderStyle="color:#BBBBBB;font-size:30rpx;font-weight:400;line-height:normal"
placeholder="请输入详细地址"
clearable
/>
</uni-forms-item>
</view>
<view class="ss-m-y-20 bg-white ss-p-x-30 ss-flex ss-row-between ss-col-center default-box">
<view class="default-box-title"> 设为默认地址 </view>
<su-switch style="transform: scale(0.8)" v-model="state.model.defaultStatus" />
</view>
</uni-forms>
<su-fixed bottom :opacity="false" bg="" placeholder :noFixed="false" :index="10">
<view class="footer-box ss-flex-col ss-row-between ss-p-20">
<view class="ss-m-b-20">
<button class="ss-reset-button save-btn ui-Shadow-Main" @tap="onSave">保存</button> <button class="ss-reset-button save-btn ui-Shadow-Main" @tap="onSave">保存</button>
</view> </view>
<button v-if="state.model.id" class="ss-reset-button cancel-btn" @tap="onDelete"> <button v-if="state.model.id" class="ss-reset-button cancel-btn" @tap="onDelete">
删除 删除
</button> </button>
</view> </view>
</su-fixed> </su-fixed>
<!-- 省市区弹窗 --> <!-- 省市区弹窗 -->
<su-region-picker :show="state.showRegion" @cancel="state.showRegion = false" @confirm="onRegionConfirm" /> <su-region-picker
</s-layout> :show="state.showRegion"
@cancel="state.showRegion = false"
@confirm="onRegionConfirm"
/>
</s-layout>
</template> </template>
<script setup> <script setup>
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';
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';
const addressFormRef = ref(null); const addressFormRef = ref(null);
const state = reactive({ const state = reactive({
showRegion: false, showRegion: false,
model: { model: {
name: '', name: '',
mobile: '', mobile: '',
detailAddress: '', detailAddress: '',
defaultStatus: false, defaultStatus: false,
areaName: '', areaName: '',
}, },
rules: {}, rules: {},
}); });
const rules = { const rules = {
name: { name: {
@ -85,93 +125,99 @@
}, },
mobile, mobile,
detailAddress: { detailAddress: {
rules: [{ rules: [
required: true, {
errorMessage: '请输入详细地址', required: true,
}] errorMessage: '请输入详细地址',
},
],
}, },
areaName: { areaName: {
rules: [{ rules: [
required: true, {
errorMessage: '请选择您的位置' required: true,
}] 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;
}; };
// //
const getAreaData = () => { const getAreaData = () => {
if (_.isEmpty(uni.getStorageSync('areaData'))) { if (_.isEmpty(uni.getStorageSync('areaData'))) {
AreaApi.getAreaTree().then((res) => { AreaApi.getAreaTree().then((res) => {
if (res.code === 0) { if (res.code === 0) {
uni.setStorageSync('areaData', res.data); uni.setStorageSync('areaData', res.data);
} }
}); });
} }
}; };
// //
const onSave = async () => { const onSave = async () => {
// //
const validate = await unref(addressFormRef) const validate = await unref(addressFormRef)
.validate() .validate()
.catch((error) => { .catch((error) => {
console.log('error: ', error); console.log('error: ', error);
}); });
if (!validate) { if (!validate) {
return; return;
} }
// //
const formData = { const formData = {
...state.model ...state.model,
};
const { code } =
state.model.id > 0
? await AddressApi.updateAddress(formData)
: await AddressApi.createAddress(formData);
if (code === 0) {
sheep.$router.back();
} }
const {code } = state.model.id > 0 ? await AddressApi.updateAddress(formData) };
: await AddressApi.createAddress(formData);
if (code === 0) {
sheep.$router.back();
}
};
// //
const onDelete = () => { const onDelete = () => {
uni.showModal({ uni.showModal({
title: '提示', title: '提示',
content: '确认删除此收货地址吗?', content: '确认删除此收货地址吗?',
success: async function(res) { success: async function (res) {
if (!res.confirm) { if (!res.confirm) {
return; return;
} }
const { code } = await AddressApi.deleteAddress(state.model.id); const { code } = await AddressApi.deleteAddress(state.model.id);
if (code === 0) { if (code === 0) {
sheep.$router.back(); sheep.$router.back();
} }
}, },
}); });
}; };
onLoad(async (options) => { onLoad(async (options) => {
// //
getAreaData(); getAreaData();
// id // id
if (options.id) { if (options.id) {
let { code, data} = await AddressApi.getAddress(options.id); let { code, data } = await AddressApi.getAddress(options.id);
if (code !== 0) { if (code !== 0) {
return; return;
} }
state.model = data; state.model = data;
} }
// //
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,77 +227,79 @@
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,
name: data.consignee, name: data.consignee,
}; };
} }
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep() { :deep() {
.uni-forms-item__label .label-text { .uni-forms-item__label .label-text {
font-size: 28rpx !important; font-size: 28rpx !important;
color: #333333 !important; color: #333333 !important;
line-height: normal !important; line-height: normal !important;
} }
.uni-easyinput__content-input { .uni-easyinput__content-input {
font-size: 28rpx !important; font-size: 28rpx !important;
color: #333333 !important; color: #333333 !important;
line-height: normal !important; line-height: normal !important;
padding-left: 0 !important; padding-left: 0 !important;
} }
.uni-easyinput__content-textarea { .uni-easyinput__content-textarea {
font-size: 28rpx !important; font-size: 28rpx !important;
color: #333333 !important; color: #333333 !important;
line-height: normal !important; line-height: normal !important;
margin-top: 8rpx !important; margin-top: 8rpx !important;
} }
.uni-icons { .uni-icons {
font-size: 40rpx !important; font-size: 40rpx !important;
} }
.is-textarea-icon { .is-textarea-icon {
margin-top: 22rpx; margin-top: 22rpx;
} }
.is-disabled { .is-disabled {
color: #333333; color: #333333;
} }
} }
.default-box { .default-box {
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
height: 100rpx; height: 100rpx;
.default-box-title { .default-box-title {
font-size: 28rpx; font-size: 28rpx;
color: #333333; color: #333333;
line-height: normal; line-height: normal;
} }
} }
.footer-box { .footer-box {
.save-btn { .save-btn {
width: 710rpx; width: 710rpx;
height: 80rpx; height: 80rpx;
border-radius: 40rpx; border-radius: 40rpx;
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient)); background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
color: $white; color: $white;
} }
.cancel-btn { .cancel-btn {
width: 710rpx; width: 710rpx;
height: 80rpx; height: 80rpx;
border-radius: 40rpx; border-radius: 40rpx;
background: var(--ui-BG); background: var(--ui-BG);
} }
} }
</style> </style>

View File

@ -1,143 +1,156 @@
<!-- 收件地址列表 --> <!-- 收件地址列表 -->
<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
</view> v-for="item in state.list"
:key="item.id"
:item="item"
@tap="onSelect(item)"
/>
</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
@tap="importWechatAddress" v-if="['WechatMiniProgram', 'WechatOfficialAccount'].includes(sheep.$platform.name)"
class="border ss-reset-button sync-wxaddress ss-m-20 ss-flex ss-row-center ss-col-center"> @tap="importWechatAddress"
<text class="cicon-weixin ss-p-r-10" style="color: #09bb07; font-size: 40rpx"></text> class="border ss-reset-button sync-wxaddress ss-m-20 ss-flex ss-row-center ss-col-center"
导入微信地址 >
</button> <text class="cicon-weixin ss-p-r-10" style="color: #09bb07; font-size: 40rpx"></text>
<button class="add-btn ss-reset-button ui-Shadow-Main" 导入微信地址
@tap="sheep.$router.go('/pages/user/address/edit')"> </button>
新增收货地址 <button
</button> class="add-btn ss-reset-button ui-Shadow-Main"
</view> @tap="sheep.$router.go('/pages/user/address/edit')"
</su-fixed> >
<s-empty v-if="state.list.length === 0 && !state.loading" text="暂无收货地址" icon="/static/data-empty.png" /> 新增收货地址
</s-layout> </button>
</view>
</su-fixed>
<s-empty
v-if="state.list.length === 0 && !state.loading"
text="暂无收货地址"
icon="/static/data-empty.png"
/>
</s-layout>
</template> </template>
<script setup> <script setup>
import { reactive, onBeforeMount } from 'vue'; import { reactive, onBeforeMount } from 'vue';
import { onShow } from '@dcloudio/uni-app'; import { onShow } from '@dcloudio/uni-app';
import sheep from '@/sheep'; import sheep from '@/sheep';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
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,
}); });
// //
const onSelect = (addressInfo) => { const onSelect = (addressInfo) => {
uni.$emit('SELECT_ADDRESS', { uni.$emit('SELECT_ADDRESS', {
addressInfo, addressInfo,
}); });
sheep.$router.back(); sheep.$router.back();
}; };
// //
// TODO // TODO
function importWechatAddress() { function importWechatAddress() {
let wechatAddress = {}; let wechatAddress = {};
// #ifdef MP // #ifdef MP
uni.chooseAddress({ uni.chooseAddress({
success: (res) => { success: (res) => {
wechatAddress = { wechatAddress = {
consignee: res.userName, consignee: res.userName,
mobile: res.telNumber, mobile: res.telNumber,
province_name: res.provinceName, province_name: res.provinceName,
city_name: res.cityName, city_name: res.cityName,
district_name: res.countyName, district_name: res.countyName,
address: res.detailInfo, address: res.detailInfo,
region: '', region: '',
is_default: false, is_default: false,
}; };
if (!isEmpty(wechatAddress)) { if (!isEmpty(wechatAddress)) {
sheep.$router.go('/pages/user/address/edit', { sheep.$router.go('/pages/user/address/edit', {
data: JSON.stringify(wechatAddress), data: JSON.stringify(wechatAddress),
}); });
} }
}, },
fail: (err) => { fail: (err) => {
console.log('%cuni.chooseAddress,调用失败', 'color:green;background:yellow'); console.log('%cuni.chooseAddress,调用失败', 'color:green;background:yellow');
}, },
}); });
// #endif // #endif
// #ifdef H5 // #ifdef H5
sheep.$platform.useProvider('wechat').jssdk.openAddress({ sheep.$platform.useProvider('wechat').jssdk.openAddress({
success: (res) => { success: (res) => {
wechatAddress = { wechatAddress = {
consignee: res.userName, consignee: res.userName,
mobile: res.telNumber, mobile: res.telNumber,
province_name: res.provinceName, province_name: res.provinceName,
city_name: res.cityName, city_name: res.cityName,
district_name: res.countryName, district_name: res.countryName,
address: res.detailInfo, address: res.detailInfo,
region: '', region: '',
is_default: false, is_default: false,
}; };
if (!isEmpty(wechatAddress)) { if (!isEmpty(wechatAddress)) {
sheep.$router.go('/pages/user/address/edit', { sheep.$router.go('/pages/user/address/edit', {
data: JSON.stringify(wechatAddress), data: JSON.stringify(wechatAddress),
}); });
} }
}, },
}); });
// #endif // #endif
} }
onShow(async () => { onShow(async () => {
state.list = (await AddressApi.getAddressList()).data; state.list = (await AddressApi.getAddressList()).data;
state.loading = false; state.loading = false;
}); });
onBeforeMount(() => { onBeforeMount(() => {
if (!!uni.getStorageSync('areaData')) { if (!!uni.getStorageSync('areaData')) {
return; return;
} }
// //
AreaApi.getAreaTree().then((res) => { AreaApi.getAreaTree().then((res) => {
if (res.code === 0) { if (res.code === 0) {
uni.setStorageSync('areaData', res.data); uni.setStorageSync('areaData', res.data);
} }
}); });
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.footer-box { .footer-box {
.add-btn { .add-btn {
flex: 1; flex: 1;
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient)); background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
border-radius: 80rpx; border-radius: 80rpx;
font-size: 30rpx; font-size: 30rpx;
font-weight: 500; font-weight: 500;
line-height: 80rpx; line-height: 80rpx;
color: $white; color: $white;
position: relative; position: relative;
z-index: 1; z-index: 1;
} }
.sync-wxaddress { .sync-wxaddress {
flex: 1; flex: 1;
line-height: 80rpx; line-height: 80rpx;
background: $white; background: $white;
border-radius: 80rpx; border-radius: 80rpx;
font-size: 30rpx; font-size: 30rpx;
font-weight: 500; font-weight: 500;
color: $dark-6; color: $dark-6;
margin-right: 18rpx; margin-right: 18rpx;
} }
} }
</style> </style>

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>
@ -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-Shadow-Main': state.selectedSpuIdList.length > 0 'ui-BG-Main-Gradient': state.selectedSpuIdList.length > 0,
}]" 'ui-Shadow-Main': state.selectedSpuIdList.length > 0,
},
]"
@tap="onDelete" @tap="onDelete"
> >
删除足迹 删除足迹
@ -121,8 +123,8 @@
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';
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

@ -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">
@ -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);
@ -279,7 +278,7 @@
// //
async function onSubmit() { async function onSubmit() {
const { code } = await UserApi.updateUser({ const { code } = await UserApi.updateUser({
avatar: state.model.avatar, avatar: state.model.avatar,
nickname: state.model.nickname, nickname: state.model.nickname,
sex: state.model.sex, sex: state.model.sex,

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>
@ -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,19 +24,24 @@
<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
<button class="ss-reset-button date-btn"> v-model="state.date"
<text>{{ dateFilterText }}</text> type="daterange"
<text class="cicon-drop-down ss-seldate-icon"></text> @change="onChangeTime"
</button> :end="state.today"
</uni-datetime-picker> >
<button class="ss-reset-button date-btn">
<text>{{ dateFilterText }}</text>
<text class="cicon-drop-down ss-seldate-icon"></text>
</button>
</uni-datetime-picker>
<!-- TODO 芋艿优化 --> <!-- TODO 芋艿优化 -->
<!-- <view class="total-box">--> <!-- <view class="total-box">-->
<!-- <view class="ss-m-b-10">总收入{{ state.pagination.income }}</view>--> <!-- <view class="ss-m-b-10">总收入{{ state.pagination.income }}</view>-->
<!-- <view>总支出{{ -state.pagination.expense }}</view>--> <!-- <view>总支出{{ -state.pagination.expense }}</view>-->
<!-- </view>--> <!-- </view>-->
</view> </view>
<su-tabs <su-tabs
:list="tabMaps" :list="tabMaps"
@change="onChange" @change="onChange"
@ -274,4 +279,4 @@
} }
} }
} }
</style> </style>

View File

@ -15,8 +15,8 @@ const FileApi = {
name: 'file', name: 'file',
header: { header: {
// Accept: 'text/json', // Accept: 'text/json',
Accept : '*/*', Accept: '*/*',
'tenant-id' :'1', 'tenant-id': '1',
// Authorization: 'Bearer test247', // Authorization: 'Bearer test247',
}, },
success: (uploadFileRes) => { success: (uploadFileRes) => {

View File

@ -5,7 +5,7 @@ const AddressApi = {
getAddressList: () => { getAddressList: () => {
return request({ return request({
url: '/member/address/list', url: '/member/address/list',
method: 'GET' method: 'GET',
}); });
}, },
// 创建用户收件地址 // 创建用户收件地址
@ -16,7 +16,7 @@ const AddressApi = {
data, data,
custom: { custom: {
showSuccess: true, showSuccess: true,
successMsg: '保存成功' successMsg: '保存成功',
}, },
}); });
}, },
@ -28,7 +28,7 @@ const AddressApi = {
data, data,
custom: { custom: {
showSuccess: true, showSuccess: true,
successMsg: '更新成功' successMsg: '更新成功',
}, },
}); });
}, },
@ -37,7 +37,7 @@ const AddressApi = {
return request({ return request({
url: '/member/address/get', url: '/member/address/get',
method: 'GET', method: 'GET',
params: { id } params: { id },
}); });
}, },
// 删除用户收件地址 // 删除用户收件地址
@ -45,7 +45,24 @@ const AddressApi = {
return request({ return request({
url: '/member/address/delete', url: '/member/address/delete',
method: 'DELETE', method: 'DELETE',
params: { id } params: { id },
});
},
// 文章列表
textList: (id) => {
return request({
url: '/promotion/article/list',
method: 'GET',
params: { id },
});
},
// 文章列表详情
textListDetail: (id) => {
return request({
url: '/promotion/article/get',
method: 'GET',
params: { id },
}); });
}, },
}; };

View File

@ -56,7 +56,7 @@ const AuthUtil = {
url: '/member/auth/refresh-token', url: '/member/auth/refresh-token',
method: 'POST', method: 'POST',
params: { params: {
refreshToken refreshToken,
}, },
custom: { custom: {
loading: false, // 不用加载中 loading: false, // 不用加载中
@ -103,7 +103,7 @@ const AuthUtil = {
data: { data: {
phoneCode, phoneCode,
loginCode, loginCode,
state state,
}, },
custom: { custom: {
showSuccess: true, showSuccess: true,
@ -118,13 +118,13 @@ const AuthUtil = {
url: '/member/auth/create-weixin-jsapi-signature', url: '/member/auth/create-weixin-jsapi-signature',
method: 'POST', method: 'POST',
params: { params: {
url url,
}, },
custom: { custom: {
showError: false, showError: false,
showLoading: false, showLoading: false,
}, },
}) });
}, },
// //
}; };

View File

@ -4,7 +4,7 @@ const PointApi = {
// 获得用户积分记录分页 // 获得用户积分记录分页
getPointRecordPage: (params) => { getPointRecordPage: (params) => {
if (params.addStatus === undefined) { if (params.addStatus === undefined) {
delete params.addStatus delete params.addStatus;
} }
const queryString = Object.keys(params) const queryString = Object.keys(params)
.map((key) => encodeURIComponent(key) + '=' + params[key]) .map((key) => encodeURIComponent(key) + '=' + params[key])
@ -13,7 +13,7 @@ const PointApi = {
url: `/member/point/record/page?${queryString}`, url: `/member/point/record/page?${queryString}`,
method: 'GET', method: 'GET',
}); });
} },
}; };
export default PointApi; export default PointApi;

View File

@ -34,4 +34,4 @@ const SignInApi = {
}, },
}; };
export default SignInApi; export default SignInApi;

View File

@ -7,7 +7,7 @@ const SocialApi = {
url: '/member/social-user/get', url: '/member/social-user/get',
method: 'GET', method: 'GET',
params: { params: {
type type,
}, },
custom: { custom: {
showLoading: false, showLoading: false,
@ -22,7 +22,7 @@ const SocialApi = {
data: { data: {
type, type,
code, code,
state state,
}, },
custom: { custom: {
custom: { custom: {
@ -40,7 +40,7 @@ const SocialApi = {
method: 'DELETE', method: 'DELETE',
data: { data: {
type, type,
openid openid,
}, },
custom: { custom: {
showLoading: false, showLoading: false,
@ -51,4 +51,4 @@ const SocialApi = {
}, },
}; };
export default SocialApi; export default SocialApi;

View File

@ -21,7 +21,7 @@ const UserApi = {
custom: { custom: {
auth: true, auth: true,
showSuccess: true, showSuccess: true,
successMsg: '更新成功' successMsg: '更新成功',
}, },
}); });
}, },
@ -34,7 +34,7 @@ const UserApi = {
custom: { custom: {
loadingMsg: '验证中', loadingMsg: '验证中',
showSuccess: true, showSuccess: true,
successMsg: '修改成功' successMsg: '修改成功',
}, },
}); });
}, },
@ -44,12 +44,12 @@ const UserApi = {
url: '/member/user/update-mobile-by-weixin', url: '/member/user/update-mobile-by-weixin',
method: 'PUT', method: 'PUT',
data: { data: {
code code,
}, },
custom: { custom: {
showSuccess: true, showSuccess: true,
loadingMsg: '获取中', loadingMsg: '获取中',
successMsg: '修改成功' successMsg: '修改成功',
}, },
}); });
}, },
@ -62,7 +62,7 @@ const UserApi = {
custom: { custom: {
loadingMsg: '验证中', loadingMsg: '验证中',
showSuccess: true, showSuccess: true,
successMsg: '修改成功' successMsg: '修改成功',
}, },
}); });
}, },
@ -75,11 +75,10 @@ const UserApi = {
custom: { custom: {
loadingMsg: '验证中', loadingMsg: '验证中',
showSuccess: true, showSuccess: true,
successMsg: '修改成功' successMsg: '修改成功',
} },
}); });
}, },
}; };
export default UserApi; export default UserApi;

View File

@ -10,12 +10,12 @@ export default {
method: 'GET', method: 'GET',
params: { params: {
ids: ids.join(','), ids: ids.join(','),
} },
}), }),
getMpLink: () => getMpLink: () =>
request({ request({
url: 'app/mplive/getMpLink', url: 'app/mplive/getMpLink',
method: 'GET' method: 'GET',
}), }),
}, },
}; };

View File

@ -7,4 +7,4 @@ Object.keys(files).forEach((key) => {
}; };
}); });
export default api; export default api;

View File

@ -6,7 +6,7 @@ const PayChannelApi = {
return request({ return request({
url: '/pay/channel/get-enable-code-list', url: '/pay/channel/get-enable-code-list',
method: 'GET', method: 'GET',
params: { appId } params: { appId },
}); });
}, },
}; };

View File

@ -6,7 +6,7 @@ const PayOrderApi = {
return request({ return request({
url: '/pay/order/get', url: '/pay/order/get',
method: 'GET', method: 'GET',
params: { id } params: { id },
}); });
}, },
// 提交支付订单 // 提交支付订单
@ -14,9 +14,9 @@ const PayOrderApi = {
return request({ return request({
url: '/pay/order/submit', url: '/pay/order/submit',
method: 'POST', method: 'POST',
data data,
}); });
} },
}; };
export default PayOrderApi; export default PayOrderApi;

View File

@ -31,7 +31,7 @@ const SpuHistoryApi = {
method: 'GET', method: 'GET',
data, data,
custom: { custom: {
showLoading: false showLoading: false,
}, },
}); });
}, },

View File

@ -1,12 +1,12 @@
import request from '@/sheep/request'; import request from '@/sheep/request';
export default { export default {
// 获得文章详情 // 获得文章详情
getArticle: (id, title) => { getArticle: (id, title) => {
return request({ return request({
url: '/promotion/article/get', url: '/promotion/article/get',
method: 'GET', method: 'GET',
params: { id, title } params: { id, title },
}); });
} },
} };

View File

@ -47,9 +47,9 @@ const CombinationApi = {
// 获得我的拼团记录分页 // 获得我的拼团记录分页
getCombinationRecordPage: (params) => { getCombinationRecordPage: (params) => {
return request({ return request({
url: "/promotion/combination-record/page", url: '/promotion/combination-record/page',
method: 'GET', method: 'GET',
params params,
}); });
}, },

View File

@ -95,7 +95,7 @@ const CouponApi = {
showLoading: false, // 避免影响 settlementOrder 结算的结果 showLoading: false, // 避免影响 settlementOrder 结算的结果
}, },
}); });
} },
}; };
export default CouponApi; export default CouponApi;

View File

@ -16,7 +16,7 @@ const DiyApi = {
url: '/promotion/diy-template/get', url: '/promotion/diy-template/get',
method: 'GET', method: 'GET',
params: { params: {
id id,
}, },
custom: { custom: {
showError: false, showError: false,
@ -29,8 +29,8 @@ const DiyApi = {
url: '/promotion/diy-page/get', url: '/promotion/diy-page/get',
method: 'GET', method: 'GET',
params: { params: {
id id,
} },
}); });
}, },
}; };

View File

@ -8,7 +8,7 @@ const RewardActivityApi = {
method: 'GET', method: 'GET',
params: { id }, params: { id },
}); });
} },
}; };
export default RewardActivityApi; export default RewardActivityApi;

View File

@ -1,4 +1,4 @@
import request from "@/sheep/request"; import request from '@/sheep/request';
const SeckillApi = { const SeckillApi = {
// 获得秒杀时间段列表 // 获得秒杀时间段列表
@ -25,9 +25,9 @@ const SeckillApi = {
return request({ return request({
url: 'promotion/seckill-activity/get-detail', url: 'promotion/seckill-activity/get-detail',
method: 'GET', method: 'GET',
params: { id } params: { id },
}); });
} },
} };
export default SeckillApi; export default SeckillApi;

View File

@ -5,7 +5,7 @@ const AreaApi = {
getAreaTree: () => { getAreaTree: () => {
return request({ return request({
url: '/system/area/tree', url: '/system/area/tree',
method: 'GET' method: 'GET',
}); });
}, },
}; };

View File

@ -57,7 +57,7 @@ const AfterSaleApi = {
method: 'PUT', method: 'PUT',
data, data,
}); });
} },
}; };
export default AfterSaleApi; export default AfterSaleApi;

View File

@ -2,18 +2,18 @@ import request from '@/sheep/request';
const BrokerageApi = { const BrokerageApi = {
// 绑定分销用户 // 绑定分销用户
bindBrokerageUser: (data)=>{ bindBrokerageUser: (data) => {
return request({ return request({
url: '/trade/brokerage-user/bind', url: '/trade/brokerage-user/bind',
method: 'PUT', method: 'PUT',
data data,
}); });
}, },
// 获得个人分销信息 // 获得个人分销信息
getBrokerageUser: () => { getBrokerageUser: () => {
return request({ return request({
url: '/trade/brokerage-user/get', url: '/trade/brokerage-user/get',
method: 'GET' method: 'GET',
}); });
}, },
// 获得个人分销统计 // 获得个人分销统计
@ -24,12 +24,12 @@ const BrokerageApi = {
}); });
}, },
// 获得分销记录分页 // 获得分销记录分页
getBrokerageRecordPage: params => { getBrokerageRecordPage: (params) => {
if (params.status === undefined) { if (params.status === undefined) {
delete params.status delete params.status;
} }
const queryString = Object.keys(params) const queryString = Object.keys(params)
.map(key => encodeURIComponent(key) + '=' + params[key]) .map((key) => encodeURIComponent(key) + '=' + params[key])
.join('&'); .join('&');
return request({ return request({
url: `/trade/brokerage-record/page?${queryString}`, url: `/trade/brokerage-record/page?${queryString}`,
@ -37,7 +37,7 @@ const BrokerageApi = {
}); });
}, },
// 创建分销提现 // 创建分销提现
createBrokerageWithdraw: data => { createBrokerageWithdraw: (data) => {
return request({ return request({
url: '/trade/brokerage-withdraw/create', url: '/trade/brokerage-withdraw/create',
method: 'POST', method: 'POST',
@ -45,15 +45,15 @@ const BrokerageApi = {
}); });
}, },
// 获得商品的分销金额 // 获得商品的分销金额
getProductBrokeragePrice: spuId => { getProductBrokeragePrice: (spuId) => {
return request({ return request({
url: '/trade/brokerage-record/get-product-brokerage-price', url: '/trade/brokerage-record/get-product-brokerage-price',
method: 'GET', method: 'GET',
params: { spuId } params: { spuId },
}); });
}, },
// 获得分销用户排行(基于佣金) // 获得分销用户排行(基于佣金)
getRankByPrice: params => { getRankByPrice: (params) => {
const queryString = `times=${params.times[0]}&times=${params.times[1]}`; const queryString = `times=${params.times[0]}&times=${params.times[1]}`;
return request({ return request({
url: `/trade/brokerage-user/get-rank-by-price?${queryString}`, url: `/trade/brokerage-user/get-rank-by-price?${queryString}`,
@ -61,9 +61,9 @@ const BrokerageApi = {
}); });
}, },
// 获得分销用户排行分页(基于佣金) // 获得分销用户排行分页(基于佣金)
getBrokerageUserChildSummaryPageByPrice: params => { getBrokerageUserChildSummaryPageByPrice: (params) => {
const queryString = Object.keys(params) const queryString = Object.keys(params)
.map(key => encodeURIComponent(key) + '=' + params[key]) .map((key) => encodeURIComponent(key) + '=' + params[key])
.join('&'); .join('&');
return request({ return request({
url: `/trade/brokerage-user/rank-page-by-price?${queryString}`, url: `/trade/brokerage-user/rank-page-by-price?${queryString}`,
@ -71,9 +71,9 @@ const BrokerageApi = {
}); });
}, },
// 获得分销用户排行分页(基于用户量) // 获得分销用户排行分页(基于用户量)
getBrokerageUserRankPageByUserCount: params => { getBrokerageUserRankPageByUserCount: (params) => {
const queryString = Object.keys(params) const queryString = Object.keys(params)
.map(key => encodeURIComponent(key) + '=' + params[key]) .map((key) => encodeURIComponent(key) + '=' + params[key])
.join('&'); .join('&');
return request({ return request({
url: `/trade/brokerage-user/rank-page-by-user-count?${queryString}`, url: `/trade/brokerage-user/rank-page-by-user-count?${queryString}`,
@ -81,13 +81,13 @@ const BrokerageApi = {
}); });
}, },
// 获得下级分销统计分页 // 获得下级分销统计分页
getBrokerageUserChildSummaryPage: params => { getBrokerageUserChildSummaryPage: (params) => {
return request({ return request({
url: '/trade/brokerage-user/child-summary-page', url: '/trade/brokerage-user/child-summary-page',
method: 'GET', method: 'GET',
params, params,
}) });
} },
} };
export default BrokerageApi export default BrokerageApi;

View File

@ -9,21 +9,21 @@ const CartApi = {
custom: { custom: {
showSuccess: true, showSuccess: true,
successMsg: '已添加到购物车~', successMsg: '已添加到购物车~',
} },
}); });
}, },
updateCartCount: (data) => { updateCartCount: (data) => {
return request({ return request({
url: '/trade/cart/update-count', url: '/trade/cart/update-count',
method: 'PUT', method: 'PUT',
data: data data: data,
}); });
}, },
updateCartSelected: (data) => { updateCartSelected: (data) => {
return request({ return request({
url: '/trade/cart/update-selected', url: '/trade/cart/update-selected',
method: 'PUT', method: 'PUT',
data: data data: data,
}); });
}, },
deleteCart: (ids) => { deleteCart: (ids) => {
@ -31,8 +31,8 @@ const CartApi = {
url: '/trade/cart/delete', url: '/trade/cart/delete',
method: 'DELETE', method: 'DELETE',
params: { params: {
ids ids,
} },
}); });
}, },
getCartList: () => { getCartList: () => {
@ -47,4 +47,4 @@ const CartApi = {
}, },
}; };
export default CartApi; export default CartApi;

View File

@ -7,7 +7,7 @@ const DeliveryApi = {
url: `/trade/delivery/express/list`, url: `/trade/delivery/express/list`,
method: 'get', method: 'get',
}); });
} },
}; };
export default DeliveryApi; export default DeliveryApi;

View File

@ -43,7 +43,7 @@
const emits = defineEmits(['close']); const emits = defineEmits(['close']);
const state = reactive({ const state = reactive({
activityInfo: computed(() => props.modelValue), activityInfo: computed(() => props.modelValue),
activityMap: {} activityMap: {},
}); });
watch( watch(
@ -51,13 +51,13 @@
() => { () => {
// //
if (props.show) { if (props.show) {
state.activityInfo?.forEach(activity => { state.activityInfo?.forEach((activity) => {
RewardActivityApi.getRewardActivity(activity.id).then(res => { RewardActivityApi.getRewardActivity(activity.id).then((res) => {
if (res.code !== 0) { if (res.code !== 0) {
return; return;
} }
state.activityMap[activity.id] = res.data; state.activityMap[activity.id] = res.data;
}) });
}); });
} }
}, },

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>

View File

@ -89,7 +89,7 @@
// //
if (!props.agreeStatus) { if (!props.agreeStatus) {
emits('onConfirm', true) emits('onConfirm', true);
sheep.$helper.toast('请勾选同意'); sheep.$helper.toast('请勾选同意');
return; return;
} }

View File

@ -53,9 +53,7 @@
</uni-forms-item> </uni-forms-item>
</uni-forms> </uni-forms>
<button class="ss-reset-button type-btn" @tap="closeAuthModal"> <button class="ss-reset-button type-btn" @tap="closeAuthModal"> 取消修改 </button>
取消修改
</button>
</view> </view>
</template> </template>

View File

@ -110,7 +110,7 @@
return; return;
} }
// //
showAuthModal('accountLogin') showAuthModal('accountLogin');
}; };
</script> </script>

View File

@ -102,7 +102,7 @@
return; return;
} }
if (!props.agreeStatus) { if (!props.agreeStatus) {
emits('onConfirm', true) emits('onConfirm', true);
sheep.$helper.toast('请勾选同意'); sheep.$helper.toast('请勾选同意');
return; return;
} }

View File

@ -10,7 +10,11 @@
/> />
<!-- 2. 短信登录 smsLogin --> <!-- 2. 短信登录 smsLogin -->
<sms-login v-if="authType === 'smsLogin'" :agreeStatus="state.protocol" @onConfirm="onConfirm" /> <sms-login
v-if="authType === 'smsLogin'"
:agreeStatus="state.protocol"
@onConfirm="onConfirm"
/>
<!-- 3. 忘记密码 resetPassword--> <!-- 3. 忘记密码 resetPassword-->
<reset-password v-if="authType === 'resetPassword'" /> <reset-password v-if="authType === 'resetPassword'" />
@ -32,7 +36,11 @@
<!-- 7.1 微信小程序的快捷登录 --> <!-- 7.1 微信小程序的快捷登录 -->
<view v-if="sheep.$platform.name === 'WechatMiniProgram'" class="ss-flex register-box"> <view v-if="sheep.$platform.name === 'WechatMiniProgram'" class="ss-flex register-box">
<view class="register-title">还没有账号?</view> <view class="register-title">还没有账号?</view>
<button class="ss-reset-button login-btn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber"> <button
class="ss-reset-button login-btn"
open-type="getPhoneNumber"
@getphonenumber="getPhoneNumber"
>
快捷登录 快捷登录
</button> </button>
<view class="circle" /> <view class="circle" />
@ -81,17 +89,13 @@
/> />
<view class="agreement-text ss-flex ss-col-center ss-m-l-8"> <view class="agreement-text ss-flex ss-col-center ss-m-l-8">
我已阅读并遵守 我已阅读并遵守
<view class="tcp-text" @tap.stop="onProtocol('用户协议')"> <view class="tcp-text" @tap.stop="onProtocol('用户协议')"> 用户协议 </view>
用户协议
</view>
<view class="agreement-text"></view> <view class="agreement-text"></view>
<view class="tcp-text" @tap.stop="onProtocol('隐私协议')"> <view class="tcp-text" @tap.stop="onProtocol('隐私协议')"> 隐私协议 </view>
隐私协议
</view>
</view> </view>
</label> </label>
</view> </view>
<view class="safe-box"/> <view class="safe-box" />
</view> </view>
</su-popup> </su-popup>
</template> </template>

View File

@ -1,81 +1,152 @@
<template> <template>
<view> <view>
<!-- 基础组件搜索框 --> <!-- 基础组件搜索框 -->
<s-search-block v-if="type === 'SearchBar'" :data="data" :styles="styles" :navbar="false" /> <s-search-block v-if="type === 'SearchBar'" :data="data" :styles="styles" :navbar="false" />
<!-- 基础组件公告栏 --> <!-- 基础组件公告栏 -->
<s-notice-block v-if="type === 'NoticeBar'" :data="data" /> <s-notice-block v-if="type === 'NoticeBar'" :data="data" />
<!-- 基础组件菜单导航 --> <!-- 基础组件菜单导航 -->
<s-menu-button v-if="type === 'MenuSwiper'" :data="data" :styles="styles" /> <s-menu-button v-if="type === 'MenuSwiper'" :data="data" :styles="styles" />
<!-- 基础组件列表导航 --> <!-- 基础组件列表导航 -->
<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" />
<!-- 基础组件弹窗广告 --> <!-- 基础组件弹窗广告 -->
<s-popup-image v-if="type === 'Popover'" :data="data" /> <s-popup-image v-if="type === 'Popover'" :data="data" />
<!-- 基础组件悬浮按钮 --> <!-- 基础组件悬浮按钮 -->
<s-float-menu v-if="type === 'FloatingActionButton'" :data="data" /> <s-float-menu v-if="type === 'FloatingActionButton'" :data="data" />
<!-- 图文组件图片展示 --> <!-- 图文组件图片展示 -->
<s-image-block v-if="type === 'ImageBar'" :data="data" :styles="styles" /> <s-image-block v-if="type === 'ImageBar'" :data="data" :styles="styles" />
<!-- 图文组件图片轮播 --> <!-- 图文组件图片轮播 -->
<s-image-banner v-if="type === 'Carousel'" :data="data" :styles="styles" /> <s-image-banner v-if="type === 'Carousel'" :data="data" :styles="styles" />
<!-- 基础组件标题栏 --> <!-- 基础组件标题栏 -->
<s-title-block v-if="type === 'TitleBar'" :data="data" :styles="styles" /> <s-title-block v-if="type === 'TitleBar'" :data="data" :styles="styles" />
<!-- 图文组件广告魔方 --> <!-- 图文组件广告魔方 -->
<s-image-cube v-if="type === 'MagicCube'" :data="data" :styles="styles" /> <s-image-cube v-if="type === 'MagicCube'" :data="data" :styles="styles" />
<!-- 图文组件视频播放 --> <!-- 图文组件视频播放 -->
<s-video-block v-if="type === 'VideoPlayer'" :data="data" :styles="styles" /> <s-video-block v-if="type === 'VideoPlayer'" :data="data" :styles="styles" />
<!-- 基础组件分割线 --> <!-- 基础组件分割线 -->
<s-line-block v-if="type === 'Divider'" :data="data" /> <s-line-block v-if="type === 'Divider'" :data="data" />
<!-- 图文组件热区 --> <!-- 图文组件热区 -->
<s-hotzone-block v-if="type === 'HotZone'" :data="data" :styles="styles" /> <s-hotzone-block v-if="type === 'HotZone'" :data="data" :styles="styles" />
<!-- 商品组件商品卡片 --> <!-- 商品组件商品卡片 -->
<s-goods-card v-if="type === 'ProductCard'" :data="data" :styles="styles" /> <s-goods-card v-if="type === 'ProductCard'" :data="data" :styles="styles" />
<!-- 商品组件商品栏 --> <!-- 商品组件商品栏 -->
<s-goods-shelves v-if="type === 'ProductList'" :data="data" :styles="styles" /> <s-goods-shelves v-if="type === 'ProductList'" :data="data" :styles="styles" />
<!-- 营销组件拼团 --> <!-- 营销组件拼团 -->
<s-groupon-block v-if="type === 'PromotionCombination'" :data="data" :styles="styles" /> <s-groupon-block v-if="type === 'PromotionCombination'" :data="data" :styles="styles" />
<!-- 营销组件秒杀 --> <!-- 营销组件秒杀 -->
<s-seckill-block v-if="type === 'PromotionSeckill'" :data="data" :styles="styles" /> <s-seckill-block v-if="type === 'PromotionSeckill'" :data="data" :styles="styles" />
<!-- 营销组件小程序直播暂时没有这个功能 --> <!-- 营销组件小程序直播暂时没有这个功能 -->
<s-live-block v-if="type === 'MpLive'" :data="data" :styles="styles" /> <s-live-block v-if="type === 'MpLive'" :data="data" :styles="styles" />
<!-- 营销组件优惠券 --> <!-- 营销组件优惠券 -->
<s-coupon-block v-if="type === 'CouponCard'" :data="data" :styles="styles" /> <s-coupon-block v-if="type === 'CouponCard'" :data="data" :styles="styles" />
<!-- 营销组件文章 --> <!-- 营销组件文章 -->
<s-richtext-block v-if="type === 'PromotionArticle'" :data="data" :styles="styles" /> <!-- <s-richtext-block v-if="type === 'PromotionArticle'" :data="data" :styles="styles" /> -->
<view class="floxt" v-if="type === 'PromotionArticle'" >
<view class="addClass" v-for="(item, index) in state.model" @click="path(item.id)">
<view class="image">
<image
:src="item.picUrl"
alt="" />
</view>
<view class="text">
<view class="top">
{{item.title}}
</view>
<view class="bottom">
{{item.createTime}}
</view>
</view>
</view>
</view>
<!-- 用户组件用户卡片 --> <!-- 用户组件用户卡片 -->
<s-user-card v-if="type === 'UserCard'" /> <s-user-card v-if="type === 'UserCard'" />
<!-- 用户组件用户订单 --> <!-- 用户组件用户订单 -->
<s-order-card v-if="type === 'UserOrder'" :data="data" /> <s-order-card v-if="type === 'UserOrder'" :data="data" />
<!-- 用户组件用户资产 --> <!-- 用户组件用户资产 -->
<s-wallet-card v-if="type === 'UserWallet'" /> <s-wallet-card v-if="type === 'UserWallet'" />
<!-- 用户组件用户卡券 --> <!-- 用户组件用户卡券 -->
<s-coupon-card v-if="type === 'UserCoupon'" /> <s-coupon-card v-if="type === 'UserCoupon'" />
</view> </view>
</template> </template>
<script setup> <script setup>
/** import { ref, reactive, unref } from 'vue';
* 装修组件 - 组件集 import AddressApi from '@/sheep/api/member/address';
*/ const state = reactive({
const props = defineProps({ model: [],
type: { });
type: String,
default: '', const ff = async (id) => {
}, let { code, data } = await AddressApi.textList();
data: { state.model = data;
type: Object, }
default() {},
}, ff();
styles: { /**
type: Object, * 装修组件 - 组件集
default() {}, */
}, const props = defineProps({
}); type: {
function onSearch() {} type: String,
default: '',
},
data: {
type: Object,
default () {},
},
styles: {
type: Object,
default () {},
},
});
function path(id) {
// $u.route({url:'/pages/goods/index',params:{id:'14'}})
uni.navigateTo({
url: `/pages/mulu/mulu?id=${id}`
});
}
</script> </script>
<style></style> <style scoped lang="scss">
.floxt {
width: 100%;
.addClass {
background:white;
display: flex;
justify-content: space-between;
width: 100%;
margin:20rpx 0;
// padding: 40rpx;
// padding-right: 0;
// height: 200rpx;
.image {
width: 250rpx;
height: 156rpx;
margin-right: 18rpx;
padding:20rpx 20rpx;
image{
width: 100%;
height: 100%;
}
}
.text {
display: flex;
width: 100%;
// text-align: center;
padding:20rpx 20rpx;
flex:1;
flex-direction: column;
justify-content: space-between;
}
}
}
</style>

View File

@ -21,8 +21,7 @@
const elBackground = computed(() => { const elBackground = computed(() => {
if (props.styles) { if (props.styles) {
if (props.styles.bgType === 'color') if (props.styles.bgType === 'color') return { background: props.styles.bgColor };
return { background: props.styles.bgColor };
if (props.styles.bgType === 'img') if (props.styles.bgType === 'img')
return { return {
background: `url(${sheep.$url.cdn( background: `url(${sheep.$url.cdn(

View File

@ -1,173 +1,199 @@
<template> <template>
<view class="time" :style="justifyLeft"> <view class="time" :style="justifyLeft">
<text class="" v-if="tipText">{{ tipText }}</text> <text class="" v-if="tipText">{{ tipText }}</text>
<text class="styleAll p6" v-if="isDay === true" <text
:style="{background:bgColor.bgColor,color:bgColor.Color}">{{ day }}{{bgColor.isDay?'天':''}}</text> class="styleAll p6"
<text class="timeTxt" v-if="dayText" v-if="isDay === true"
:style="{width:bgColor.timeTxtwidth,color:bgColor.bgColor}">{{ dayText }}</text> :style="{ background: bgColor.bgColor, color: bgColor.Color }"
<text class="styleAll" :class='isCol?"timeCol":""' >{{ day }}{{ bgColor.isDay ? '天' : '' }}</text
:style="{background:bgColor.bgColor,color:bgColor.Color,width:bgColor.width}">{{ hour }}</text> >
<text class="timeTxt" v-if="hourText" :class='isCol?"whit":""' <text
:style="{width:bgColor.timeTxtwidth,color:bgColor.bgColor}">{{ hourText }}</text> class="timeTxt"
<text class="styleAll" :class='isCol?"timeCol":""' v-if="dayText"
:style="{background:bgColor.bgColor,color:bgColor.Color,width:bgColor.width}">{{ minute }}</text> :style="{ width: bgColor.timeTxtwidth, color: bgColor.bgColor }"
<text class="timeTxt" v-if="minuteText" :class='isCol?"whit":""' >{{ dayText }}</text
:style="{width:bgColor.timeTxtwidth,color:bgColor.bgColor}">{{ minuteText }}</text> >
<text class="styleAll" :class='isCol?"timeCol":""' <text
:style="{background:bgColor.bgColor,color:bgColor.Color,width:bgColor.width}">{{ second }}</text> class="styleAll"
<text class="timeTxt" v-if="secondText">{{ secondText }}</text> :class="isCol ? 'timeCol' : ''"
</view> :style="{ background: bgColor.bgColor, color: bgColor.Color, width: bgColor.width }"
>{{ hour }}</text
>
<text
class="timeTxt"
v-if="hourText"
:class="isCol ? 'whit' : ''"
:style="{ width: bgColor.timeTxtwidth, color: bgColor.bgColor }"
>{{ hourText }}</text
>
<text
class="styleAll"
:class="isCol ? 'timeCol' : ''"
:style="{ background: bgColor.bgColor, color: bgColor.Color, width: bgColor.width }"
>{{ minute }}</text
>
<text
class="timeTxt"
v-if="minuteText"
:class="isCol ? 'whit' : ''"
:style="{ width: bgColor.timeTxtwidth, color: bgColor.bgColor }"
>{{ minuteText }}</text
>
<text
class="styleAll"
:class="isCol ? 'timeCol' : ''"
:style="{ background: bgColor.bgColor, color: bgColor.Color, width: bgColor.width }"
>{{ second }}</text
>
<text class="timeTxt" v-if="secondText">{{ secondText }}</text>
</view>
</template> </template>
<script> <script>
export default { export default {
name: "countDown", name: 'countDown',
props: { props: {
justifyLeft: { justifyLeft: {
type: String, type: String,
default: "" default: '',
}, },
// //
tipText: { tipText: {
type: String, type: String,
default: "倒计时" default: '倒计时',
}, },
dayText: { dayText: {
type: String, type: String,
default: "天" default: '天',
}, },
hourText: { hourText: {
type: String, type: String,
default: "时" default: '时',
}, },
minuteText: { minuteText: {
type: String, type: String,
default: "分" default: '分',
}, },
secondText: { secondText: {
type: String, type: String,
default: "秒" default: '秒',
}, },
datatime: { datatime: {
type: Number, type: Number,
default: 0 default: 0,
}, },
isDay: { isDay: {
type: Boolean, type: Boolean,
default: true default: true,
}, },
isCol: { isCol: {
type: Boolean, type: Boolean,
default: false default: false,
}, },
bgColor: { bgColor: {
type: Object, type: Object,
default: null default: null,
} },
}, },
data: function() { data: function () {
return { return {
day: "00", day: '00',
hour: "00", hour: '00',
minute: "00", minute: '00',
second: "00" second: '00',
}; };
}, },
created: function() { created: function () {
this.show_time(); this.show_time();
}, },
mounted: function() {}, mounted: function () {},
methods: { methods: {
show_time: function() { show_time: function () {
let that = this; let that = this;
function runTime() { function runTime() {
// //
let intDiff = that.datatime - Date.parse(new Date()) / 1000; // let intDiff = that.datatime - Date.parse(new Date()) / 1000; //
let day = 0, let day = 0,
hour = 0, hour = 0,
minute = 0, minute = 0,
second = 0; second = 0;
if (intDiff > 0) { if (intDiff > 0) {
// //
if (that.isDay === true) { if (that.isDay === true) {
day = Math.floor(intDiff / (60 * 60 * 24)); day = Math.floor(intDiff / (60 * 60 * 24));
} else { } else {
day = 0; day = 0;
} }
hour = Math.floor(intDiff / (60 * 60)) - day * 24; hour = Math.floor(intDiff / (60 * 60)) - day * 24;
minute = Math.floor(intDiff / 60) - day * 24 * 60 - hour * 60; minute = Math.floor(intDiff / 60) - day * 24 * 60 - hour * 60;
second = second = Math.floor(intDiff) - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60;
Math.floor(intDiff) - if (hour <= 9) hour = '0' + hour;
day * 24 * 60 * 60 - if (minute <= 9) minute = '0' + minute;
hour * 60 * 60 - if (second <= 9) second = '0' + second;
minute * 60; that.day = day;
if (hour <= 9) hour = "0" + hour; that.hour = hour;
if (minute <= 9) minute = "0" + minute; that.minute = minute;
if (second <= 9) second = "0" + second; that.second = second;
that.day = day; } else {
that.hour = hour; that.day = '00';
that.minute = minute; that.hour = '00';
that.second = second; that.minute = '00';
} else { that.second = '00';
that.day = "00"; }
that.hour = "00"; }
that.minute = "00"; runTime();
that.second = "00"; setInterval(runTime, 1000);
} },
} },
runTime(); };
setInterval(runTime, 1000);
}
}
};
</script> </script>
<style scoped> <style scoped>
.p6 { .p6 {
padding: 0 8rpx; padding: 0 8rpx;
} }
.styleAll { .styleAll {
/* color: #fff; */ /* color: #fff; */
font-size: 24rpx; font-size: 24rpx;
height: 36rpx; height: 36rpx;
line-height: 36rpx; line-height: 36rpx;
border-radius: 6rpx; border-radius: 6rpx;
text-align: center; text-align: center;
/* padding: 0 6rpx; */ /* padding: 0 6rpx; */
} }
.timeTxt { .timeTxt {
text-align: center; text-align: center;
/* width: 16rpx; */ /* width: 16rpx; */
height: 36rpx; height: 36rpx;
line-height: 36rpx; line-height: 36rpx;
display: inline-block; display: inline-block;
} }
.whit { .whit {
color: #fff !important; color: #fff !important;
} }
.time { .time {
display: flex; display: flex;
justify-content: center; justify-content: center;
} }
.red { .red {
color: #fc4141; color: #fc4141;
margin: 0 4rpx; margin: 0 4rpx;
} }
.timeCol { .timeCol {
/* width: 40rpx; /* width: 40rpx;
height: 40rpx; height: 40rpx;
line-height: 40rpx; line-height: 40rpx;
text-align:center; text-align:center;
border-radius: 6px; border-radius: 6px;
background: #fff; background: #fff;
font-size: 24rpx; */ font-size: 24rpx; */
color: #E93323; color: #e93323;
} }
</style> </style>

View File

@ -47,8 +47,8 @@
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 { ref, onMounted } from 'vue';
import { CouponTemplateValidityTypeEnum, PromotionDiscountTypeEnum } from "@/sheep/util/const"; import { CouponTemplateValidityTypeEnum, PromotionDiscountTypeEnum } from '@/sheep/util/const';
import { floatToFixed2, formatDate } from "@/sheep/util"; import { floatToFixed2, formatDate } from '@/sheep/util';
const props = defineProps({ const props = defineProps({
data: { data: {
@ -61,7 +61,7 @@
}, },
}); });
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%`,
}; };
@ -72,36 +72,36 @@
// //
const formatCouponDiscountType = (coupon) => { const formatCouponDiscountType = (coupon) => {
if(coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) { if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
return 'reduce' return 'reduce';
} }
if(coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) { if (coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
return 'percent' return 'percent';
} }
return `未知【${coupon.discountType}` return `未知【${coupon.discountType}`;
} };
// //
const formatCouponDiscountValue = (coupon) => { const formatCouponDiscountValue = (coupon) => {
if(coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) { if (coupon.discountType === PromotionDiscountTypeEnum.PRICE.type) {
return floatToFixed2(coupon.discountPrice) return floatToFixed2(coupon.discountPrice);
} }
if(coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) { if (coupon.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
return coupon.discountPercent return coupon.discountPercent;
} }
return `未知【${coupon.discountType}` return `未知【${coupon.discountType}`;
} };
// //
const formatValidityType = (row) => { const formatValidityType = (row) => {
if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) { if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) {
return `${formatDate(row.validStartTime)}${formatDate(row.validEndTime)}` return `${formatDate(row.validStartTime)}${formatDate(row.validEndTime)}`;
} }
if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) { if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) {
return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用` return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`;
} }
return '未知【' + row.validityType + '】' return '未知【' + row.validityType + '】';
} };
const couponList = ref([]); const couponList = ref([]);
// //
@ -112,16 +112,16 @@
title: msg, title: msg,
icon: 'none', icon: 'none',
}); });
return return;
} }
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(() => {
getCouponTemplateList() getCouponTemplateList();
}); });
</script> </script>

View File

@ -1,79 +1,84 @@
<!-- 装修用户组件用户卡券 --> <!-- 装修用户组件用户卡券 -->
<template> <template>
<view class="ss-coupon-menu-wrap ss-flex ss-col-center"> <view class="ss-coupon-menu-wrap ss-flex ss-col-center">
<view class="menu-item ss-flex-col ss-row-center ss-col-center" v-for="item in props.list" :key="item.title" <view
@tap="sheep.$router.go(item.path, { type: item.type })" class="menu-item ss-flex-col ss-row-center ss-col-center"
:class="item.type === 'all' ? 'menu-wallet' : 'ss-flex-1'"> v-for="item in props.list"
<image class="item-icon" :src="sheep.$url.static(item.icon)" mode="aspectFit"></image> :key="item.title"
<view class="menu-title ss-m-t-28">{{ item.title }}</view> @tap="sheep.$router.go(item.path, { type: item.type })"
</view> :class="item.type === 'all' ? 'menu-wallet' : 'ss-flex-1'"
</view> >
<image class="item-icon" :src="sheep.$url.static(item.icon)" mode="aspectFit"></image>
<view class="menu-title ss-m-t-28">{{ item.title }}</view>
</view>
</view>
</template> </template>
<script setup> <script setup>
/** /**
* 装修组件 - 优惠券菜单 * 装修组件 - 优惠券菜单
*/ */
import sheep from '@/sheep'; import sheep from '@/sheep';
// //
const props = defineProps({ const props = defineProps({
list: { list: {
type: Array, type: Array,
default () { default() {
return [{ return [
title: '已领取', {
value: '0', title: '已领取',
icon: '/static/img/shop/order/nouse_coupon.png', value: '0',
path: '/pages/coupon/list', icon: '/static/img/shop/order/nouse_coupon.png',
type: 'geted', path: '/pages/coupon/list',
}, type: 'geted',
{ },
title: '已使用', {
value: '0', title: '已使用',
icon: '/static/img/shop/order/useend_coupon.png', value: '0',
path: '/pages/coupon/list', icon: '/static/img/shop/order/useend_coupon.png',
type: 'used', path: '/pages/coupon/list',
}, type: 'used',
{ },
title: '已失效', {
value: '0', title: '已失效',
icon: '/static/img/shop/order/out_coupon.png', value: '0',
path: '/pages/coupon/list', icon: '/static/img/shop/order/out_coupon.png',
type: 'expired', path: '/pages/coupon/list',
}, type: 'expired',
{ },
title: '领券中心', {
value: '0', title: '领券中心',
icon: '/static/img/shop/order/all_coupon.png', value: '0',
path: '/pages/coupon/list', icon: '/static/img/shop/order/all_coupon.png',
type: 'all', path: '/pages/coupon/list',
}, type: 'all',
]; },
}, ];
}, },
}); },
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.ss-coupon-menu-wrap { .ss-coupon-menu-wrap {
.menu-item { .menu-item {
height: 160rpx; height: 160rpx;
.menu-title { .menu-title {
font-size: 24rpx; font-size: 24rpx;
line-height: 24rpx; line-height: 24rpx;
color: #333333; color: #333333;
} }
.item-icon { .item-icon {
width: 44rpx; width: 44rpx;
height: 44rpx; height: 44rpx;
} }
} }
.menu-wallet { .menu-wallet {
width: 144rpx; width: 144rpx;
} }
} }
</style> </style>

View File

@ -52,7 +52,7 @@
const emits = defineEmits(['get', 'close']); const emits = defineEmits(['get', 'close']);
const state = reactive({ const state = reactive({
couponInfo: computed(() => props.modelValue) couponInfo: computed(() => props.modelValue),
}); });
// //

Some files were not shown because too many files have changed in this diff Show More