# Conflicts:
#	pages/goods/index.vue
#	pages/order/addressSelection.vue
#	pages/order/confirm.vue
#	sheep/components/s-goods-column/s-goods-column.vue
This commit is contained in:
YunaiV
2024-09-16 08:24:54 +08:00
72 changed files with 3179 additions and 1995 deletions
+44 -22
View File
@@ -181,11 +181,11 @@
</view>
</view>
<!-- TODO 芋艿这里暂时没接入 -->
<view v-if="state.data.goods">
<view v-if="!isEmpty(state.goodsInfo)">
<!-- 规格与数量弹框 -->
<s-select-groupon-sku
:show="state.showSelectSku"
:goodsInfo="state.data.goods"
:goodsInfo="state.goodsInfo"
:grouponAction="state.grouponAction"
:grouponNum="state.grouponNum"
@buy="onBuy"
@@ -193,6 +193,7 @@
@close="state.showSelectSku = false"
/>
</view>
</view>
<s-empty v-if="!state.data && !state.loading" icon="/static/goods-empty.png" />
@@ -203,25 +204,28 @@
import { computed, reactive } from 'vue';
import sheep from '@/sheep';
import { onLoad } from '@dcloudio/uni-app';
import { useDurationTime } from '@/sheep/hooks/useGoods';
import { fen2yuan, useDurationTime } from '@/sheep/hooks/useGoods';
import { showShareModal } from '@/sheep/hooks/useModal';
import { isEmpty } from 'lodash-es';
import CombinationApi from '@/sheep/api/promotion/combination';
import SpuApi from '@/sheep/api/product/spu';
const headerBg = sheep.$url.css('/static/img/shop/user/withdraw_bg.png');
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
const state = reactive({
data: {}, // 拼团详情
loading: true,
grouponAction: 'create',
showSelectSku: false,
grouponNum: 0,
number: 0,
activity: {},
goodsId: 0, // 商品ID
goodsInfo: {}, // 商品信息
showSelectSku: false, // 显示规格弹框
selectedSkuPrice: {}, // 选中的规格价格
activity: {}, // 团购活动
grouponId: 0, // 团购ID
grouponNum: 0, // 团购人数
grouponAction: 'create', // 团购操作
combinationHeadId: null, // 拼团团长编号
loading: true,
});
// todo 芋艿:分享要再接下
const shareInfo = computed(() => {
if (isEmpty(state.data)) return {};
return sheep.$platform.share.getShareInfo(
@@ -231,15 +235,14 @@
desc: state.data.goods?.subtitle,
params: {
page: '5',
query: state.data.id,
query: state.data.headRecord.id,
},
},
{
type: 'groupon', // 邀请拼团海报
title: state.data.headRecord.spuName, // 商品标题
image: sheep.$url.cdn(state.data.headRecord.picUrl), // 商品主图
price: state.data.goods?.price, // 商品价格
original_price: state.data.goods?.original_price, // 商品原价
price: fen2yuan(state.data.headRecord.combinationPrice), // 商品价格
},
);
});
@@ -251,33 +254,33 @@
});
}
// 去开团 TODO 芋艿:这里没接入
// 去开团
function onCreateGroupon() {
state.grouponAction = 'create';
state.grouponId = 0;
state.showSelectSku = true;
}
// 规格变更 TODO 芋艿:这里没接入
// 规格变更
function onSkuChange(e) {
state.selectedSkuPrice = e;
}
// 立即参团 TODO 芋艿:这里没接入
// 立即参团
function onJoinGroupon() {
state.grouponAction = 'join';
state.grouponId = state.data.activityId;
state.combinationHeadId = state.data.id;
state.grouponNum = state.data.num;
state.grouponId = state.data.headRecord.activityId;
state.combinationHeadId = state.data.headRecord.id;
state.grouponNum = state.data.headRecord.userSize;
state.showSelectSku = true;
}
// 立即购买 TODO 芋艿:这里没接入
// 立即购买
function onBuy(sku) {
sheep.$router.go('/pages/order/confirm', {
data: JSON.stringify({
order_type: 'goods',
combinationActivityId: state.data.activity.id,
combinationActivityId: state.activity.id,
combinationHeadId: state.combinationHeadId,
items: [
{
@@ -306,6 +309,25 @@
data.headRecord.activityId,
);
state.activity = activity;
state.grouponNum = activity.userSize;
// 加载商品信息
const { data: spu } = await SpuApi.getSpuDetail(activity.spuId);
state.goodsId = spu.id;
// 默认显示最低价
activity.products.forEach((product) => {
spu.price = Math.min(spu.price, product.combinationPrice); // 设置 SPU 的最低价格
});
state.goodsInfo = spu;
// 价格、库存使用活动的
spu.skus.forEach((sku) => {
const product = activity.products.find((product) => product.skuId === sku.id);
if (product) {
sku.price = product.combinationPrice;
} else {
// 找不到可能是没配置,则不能发起秒杀
sku.stock = 0;
}
});
} else {
state.data = null;
}
+2 -2
View File
@@ -62,7 +62,7 @@
</view>
</view>
<!-- 签到说明 TODO @科举这里改成已累计签到 -->
<!-- 签到说明 TODO @芋艿签到这里改成已累计签到改版接入 sheepjs -->
<view class="bg-white ss-m-t-16 ss-p-t-30 ss-p-b-60 ss-p-x-40">
<view class="activity-title ss-m-b-30">签到说明</view>
<view class="activity-des">1已累计签到{{state.signInfo.totalDay}}</view>
@@ -110,7 +110,7 @@
signInfo: {}, // 签到信息
signConfigList: [], // 签到配置列表
maxDay: 0, // 最大的签到天数
maxDay: 0, // 最大的签到天数
showModel: false, // 签到弹框
signResult: {}, // 签到结果
+5 -5
View File
@@ -7,7 +7,7 @@
@scrolltoupper="onScrollToUpper" @query="queryList">
<template #top>
<!-- 撑一下顶部导航 -->
<view style="height: 45px"></view>
<view :style="{ height: sys_navBar + 'px' }"></view>
</template>
<!-- style="transform: scaleY(-1)"必须写否则会导致列表倒置 -->
<!-- 注意不要直接在chat-item组件标签上设置style因为在微信小程序中是无效的请包一层view -->
@@ -33,7 +33,9 @@
import { reactive, ref } from 'vue';
import KeFuApi from '@/sheep/api/promotion/kefu';
import { isEmpty } from '@/sheep/helper/utils';
import sheep from '@/sheep';
const sys_navBar = sheep.$platform.navbar;
const messageList = ref([]); // 消息列表
const showNewMessageTip = ref(false); // 显示有新消息提示
const backToTopStyle = reactive({
@@ -67,7 +69,7 @@
};
/** 刷新消息列表 */
const refreshMessageList = (message = undefined) => {
if (queryParams.pageNo != 1 && message !== undefined) {
if (message !== undefined) {
showNewMessageTip.value = true;
// 追加数据
pagingRef.value.addChatRecordData([message], false);
@@ -87,8 +89,6 @@
return;
}
showNewMessageTip.value = false;
// 到底重置消息列表
refreshMessageList();
};
defineExpose({ getMessageList, refreshMessageList });
</script>
+35 -30
View File
@@ -4,12 +4,20 @@
<view class="message-item ss-flex-col scroll-item">
<view class="ss-flex ss-row-center ss-col-center">
<!-- 日期 -->
<view v-if="message.contentType !== KeFuMessageContentTypeEnum.SYSTEM && showTime(message, messageIndex)"
class="date-message">
<view
v-if="
message.contentType !== KeFuMessageContentTypeEnum.SYSTEM &&
showTime(message, messageIndex)
"
class="date-message"
>
{{ formatDate(message.createTime) }}
</view>
<!-- 系统消息 -->
<view v-if="message.contentType === KeFuMessageContentTypeEnum.SYSTEM" class="system-message">
<view
v-if="message.contentType === KeFuMessageContentTypeEnum.SYSTEM"
class="system-message"
>
{{ message.content }}
</view>
</view>
@@ -18,32 +26,35 @@
v-if="message.contentType !== KeFuMessageContentTypeEnum.SYSTEM"
class="ss-flex ss-col-top"
:class="[
message.senderType === UserTypeEnum.ADMIN
? `ss-row-left`
: message.senderType === UserTypeEnum.MEMBER
? `ss-row-right`
: '',
]"
message.senderType === UserTypeEnum.ADMIN
? `ss-row-left`
: message.senderType === UserTypeEnum.MEMBER
? `ss-row-right`
: '',
]"
>
<!-- 客服头像 -->
<image
v-show="message.senderType === UserTypeEnum.ADMIN"
class="chat-avatar ss-m-r-24"
:src="
sheep.$url.cdn(message.senderAvatar) ||
sheep.$url.static('/static/img/shop/chat/default.png')
"
sheep.$url.cdn(message.senderAvatar) ||
sheep.$url.static('/static/img/shop/chat/default.png')
"
mode="aspectFill"
></image>
<!-- 内容 -->
<template v-if="message.contentType === KeFuMessageContentTypeEnum.TEXT">
<view class="message-box" :class="{'admin': message.senderType === UserTypeEnum.ADMIN}">
<view class="message-box" :class="{ admin: message.senderType === UserTypeEnum.ADMIN }">
<mp-html :content="replaceEmoji(message.content)" />
</view>
</template>
<template v-if="message.contentType === KeFuMessageContentTypeEnum.IMAGE">
<view class="message-box" :class="{'admin': message.senderType === UserTypeEnum.ADMIN}"
:style="{ width: '200rpx' }">
<view
class="message-box"
:class="{ admin: message.senderType === UserTypeEnum.ADMIN }"
:style="{ width: '200rpx' }"
>
<su-image
class="message-img"
isPreview
@@ -59,29 +70,23 @@
<template v-if="message.contentType === KeFuMessageContentTypeEnum.PRODUCT">
<GoodsItem
:goodsData="getMessageContent(message)"
@tap="
sheep.$router.go('/pages/goods/index', {
id: getMessageContent(message).id,
})
"
@tap="sheep.$router.go('/pages/goods/index', { id: getMessageContent(message).spuId })"
/>
</template>
<template v-if="message.contentType === KeFuMessageContentTypeEnum.ORDER">
<OrderItem
:orderData="getMessageContent(message)"
@tap="
sheep.$router.go('/pages/order/detail', {
id: getMessageContent(message).id,
})
"
@tap="sheep.$router.go('/pages/order/detail', { id: getMessageContent(message).id })"
/>
</template>
<!-- user头像 -->
<image
v-if="message.senderType === UserTypeEnum.MEMBER"
class="chat-avatar ss-m-l-24"
:src="sheep.$url.cdn(message.senderAvatar) ||
sheep.$url.static('/static/img/shop/chat/default.png')"
:src="
sheep.$url.cdn(message.senderAvatar) ||
sheep.$url.static('/static/img/shop/chat/default.png')
"
mode="aspectFill"
>
</image>
@@ -104,7 +109,7 @@
// 消息
message: {
type: Object,
default: ()=>({}),
default: () => ({}),
},
// 消息索引
messageIndex: {
@@ -112,10 +117,10 @@
default: 0,
},
// 消息列表
messageList:{
messageList: {
type: Array,
default: () => [],
}
},
});
const getMessageContent = computed(() => (item) => JSON.parse(item.content)); // 解析消息内容
+125 -118
View File
@@ -1,138 +1,145 @@
<!-- 分销商菜单栏 -->
<template>
<view class="menu-box ss-flex-col">
<view class="header-box">
<image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title1.png')" />
<view class="ss-flex header-title">
<view class="title">功能专区</view>
<text class="cicon-forward"></text>
</view>
</view>
<view class="menu-list ss-flex ss-flex-wrap">
<view v-for="(item, index) in state.menuList" :key="index" class="item-box ss-flex-col ss-col-center"
@tap="sheep.$router.go(item.path)">
<image class="menu-icon ss-m-b-10" :src="sheep.$url.static(item.img)" mode="aspectFill"></image>
<view>{{ item.title }}</view>
</view>
</view>
</view>
<view class="menu-box ss-flex-col">
<view class="header-box">
<image class="header-bg" :src="sheep.$url.static('/static/img/shop/commission/title1.png')" />
<view class="ss-flex header-title">
<view class="title">功能专区</view>
<text class="cicon-forward"></text>
</view>
</view>
<view class="menu-list ss-flex ss-flex-wrap">
<view
v-for="(item, index) in state.menuList"
:key="index"
class="item-box ss-flex-col ss-col-center"
@tap="sheep.$router.go(item.path)"
>
<image
class="menu-icon ss-m-b-10"
:src="sheep.$url.static(item.img)"
mode="aspectFill"
></image>
<view>{{ item.title }}</view>
</view>
</view>
</view>
</template>
<script setup>
import sheep from '@/sheep';
import { reactive } from 'vue';
import sheep from '@/sheep';
import { reactive } from 'vue';
const state = reactive({
menuList: [{
img: '/static/img/shop/commission/commission_icon1.png',
title: '我的团队',
path: '/pages/commission/team',
},
{
img: '/static/img/shop/commission/commission_icon2.png',
title: '佣金明细',
path: '/pages/commission/wallet',
},
{
img: '/static/img/shop/commission/commission_icon3.png',
title: '分销订单',
path: '/pages/commission/order',
},
{
img: '/static/img/shop/commission/commission_icon4.png',
title: '推广商品',
path: '/pages/commission/goods',
},
// {
// img: '/static/img/shop/commission/commission_icon5.png',
// title: '我的资料',
// path: '/pages/commission/apply',
// isAgentFrom: true,
// },
// todo @芋艿:邀请海报需要登录后的个人数据
{
img: '/static/img/shop/commission/commission_icon7.png',
title: '邀请海报',
path: 'action:showShareModal',
},
// TODO @芋艿:缺少 icon
const state = reactive({
menuList: [
{
// img: '/static/img/shop/commission/commission_icon7.png',
title: '推广排行',
path: '/pages/commission/promoter',
},
img: '/static/img/shop/commission/commission_icon1.png',
title: '我的团队',
path: '/pages/commission/team',
},
{
// img: '/static/img/shop/commission/commission_icon7.png',
title: '佣金排行',
path: '/pages/commission/commission-ranking',
}
],
});
img: '/static/img/shop/commission/commission_icon2.png',
title: '佣金明细',
path: '/pages/commission/wallet',
},
{
img: '/static/img/shop/commission/commission_icon3.png',
title: '分销订单',
path: '/pages/commission/order',
},
{
img: '/static/img/shop/commission/commission_icon4.png',
title: '推广商品',
path: '/pages/commission/goods',
},
// {
// img: '/static/img/shop/commission/commission_icon5.png',
// title: '我的资料',
// path: '/pages/commission/apply',
// isAgentFrom: true,
// },
{
img: '/static/img/shop/commission/commission_icon7.png',
title: '邀请海报',
path: 'action:showShareModal',
},
{
img: '/static/img/shop/commission/commission_icon8.png',
title: '推广排行',
path: '/pages/commission/promoter',
},
{
img: '/static/img/shop/commission/commission_icon9.png',
title: '佣金排行',
path: '/pages/commission/commission-ranking',
},
],
});
</script>
<style lang="scss" scoped>
.menu-box {
margin: 0 auto;
width: 690rpx;
margin-bottom: 20rpx;
margin-top: 20rpx;
border-radius: 12rpx;
z-index: 3;
position: relative;
}
.menu-box {
margin: 0 auto;
width: 690rpx;
margin-bottom: 20rpx;
margin-top: 20rpx;
border-radius: 12rpx;
z-index: 3;
position: relative;
}
.header-box {
width: 690rpx;
height: 76rpx;
position: relative;
.header-box {
width: 690rpx;
height: 76rpx;
position: relative;
.header-bg {
width: 690rpx;
height: 76rpx;
}
.header-bg {
width: 690rpx;
height: 76rpx;
}
.header-title {
position: absolute;
left: 20rpx;
top: 24rpx;
}
.header-title {
position: absolute;
left: 20rpx;
top: 24rpx;
}
.title {
font-size: 28rpx;
font-weight: 500;
color: #ffffff;
line-height: 30rpx;
}
.title {
font-size: 28rpx;
font-weight: 500;
color: #ffffff;
line-height: 30rpx;
}
.cicon-forward {
font-size: 30rpx;
font-weight: 400;
color: #ffffff;
line-height: 30rpx;
}
}
.cicon-forward {
font-size: 30rpx;
font-weight: 400;
color: #ffffff;
line-height: 30rpx;
}
}
.menu-list {
padding: 50rpx 0 10rpx 0;
background: #fdfae9;
border-radius: 0 0 12rpx 12rpx;
}
.menu-list {
padding: 50rpx 0 10rpx 0;
background: #fdfae9;
border-radius: 0 0 12rpx 12rpx;
}
.item-box {
width: 25%;
margin-bottom: 40rpx;
}
.item-box {
width: 25%;
margin-bottom: 40rpx;
}
.menu-icon {
width: 68rpx;
height: 68rpx;
background: #ffffff;
border-radius: 50%;
}
.menu-icon {
width: 68rpx;
height: 68rpx;
background: #ffffff;
border-radius: 50%;
}
.menu-title {
font-size: 26rpx;
font-weight: 500;
color: #ffffff;
}
</style>
.menu-title {
font-size: 26rpx;
font-weight: 500;
color: #ffffff;
}
</style>
+1 -1
View File
@@ -76,7 +76,7 @@
shareInfo: {},
});
// TODO 芋艿:分享接入
// TODO @puhui999:【分享接入
function onShareGoods(goodsInfo) {
state.shareInfo = $share.getShareInfo(
{
+27 -6
View File
@@ -1,8 +1,29 @@
<!-- 页面 TODO 芋艿该页面的实现代码需要优化包括 js css以及相关的样式设计 -->
<template>
<s-layout title="我的团队" :class="state.scrollTop ? 'team-wrap' : ''" navbar="inner">
<view
class="header-box"
:style="[
{
marginTop: '-' + Number(statusBarHeight + 88) + 'rpx',
paddingTop: Number(statusBarHeight + 108) + 'rpx',
},
]"
>
<!-- 推广数据总览 -->
<view class="team-data-box ss-flex ss-col-center ss-row-between" style="width: 100%">
<view class="data-card" style="width: 100%">
<view class="total-item" style="width: 100%">
<view class="item-title" style="text-align: center">推广人数</view>
<view class="total-num" style="text-align: center">
{{ state.summary.firstBrokerageUserCount + state.summary.secondBrokerageUserCount || 0 }}
</view>
</view>
</view>
</view>
</view>
<view class="promoter-list">
<view
<!--<view
class="promoterHeader bg-color"
style="backgroundcolor: #e93323 !important; height: 218rpx; color: #fff"
>
@@ -21,9 +42,9 @@
</view>
<view class="iconfont icon-tuandui" />
</view>
</view>
<view style="padding: 0 30rpx">
<view class="nav acea-row row-around l1">
</view>-->
<view style="padding: 0 20rpx">
<view class="nav acea-row row-around l1" style="margin-top:20rpx;">
<view :class="state.level == 1 ? 'item on' : 'item'" @click="setType(1)">
一级({{ state.summary.firstBrokerageUserCount || 0 }})
</view>
@@ -152,7 +173,7 @@
</view>
</block>
<block v-if="state.pagination.list.length === 0">
<view style="text-align: center">暂无推广人数</view>
<view style="text-align: center;margin-top:30rpx;">暂无推广人数</view>
</block>
</view>
</view>
@@ -456,7 +477,7 @@
.promoter-list .nav .item.on {
border-bottom: 5rpx solid;
// $theme-color
color: red;
color: var(--ui-BG-Main);
// $theme-color
}
+48 -12
View File
@@ -15,7 +15,10 @@
<view class="num-title">可提现金额</view>
<view class="wallet-num">{{ fen2yuan(state.brokerageInfo.brokeragePrice) }}</view>
</view>
<button class="ss-reset-button log-btn" @tap="sheep.$router.go('/pages/commission/wallet', { type: 2 })">
<button
class="ss-reset-button log-btn"
@tap="sheep.$router.go('/pages/commission/wallet', { type: 2 })"
>
提现记录
</button>
</view>
@@ -98,12 +101,23 @@
v-show="state.accountInfo.type === '2'"
>
<view class="unit" />
<uni-easyinput
:inputBorder="false"
class="ss-flex-1 ss-p-l-10"
v-model="state.accountInfo.bankName"
placeholder="请输入提现银行"
/>
<!--银行改为下拉选择-->
<picker
@change="bankChange"
:value="state.bankListSelectedIndex"
:range="state.bankList"
range-key="label"
style="width: 100%"
>
<uni-easyinput
:inputBorder="false"
:value="state.accountInfo.bankName"
placeholder="请选择银行"
suffixIcon="right"
disabled
:styles="{ disableColor: '#fff', borderColor: '#fff', color: '#333!important' }"
/>
</picker>
</view>
<!-- 开户地址 -->
<view class="card-title" v-show="state.accountInfo.type === '2'">开户地址</view>
@@ -152,6 +166,7 @@
import { fen2yuan } from '@/sheep/hooks/useGoods';
import TradeConfigApi from '@/sheep/api/trade/config';
import BrokerageApi from '@/sheep/api/trade/brokerage';
import DictApi from '@/sheep/api/system/dict';
const headerBg = sheep.$url.css('/static/img/shop/user/withdraw_bg.png');
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
@@ -176,6 +191,8 @@
frozenDays: 0, // 冻结天数
minPrice: 0, // 最低提现金额
withdrawTypes: [], // 提现方式
bankList: [], // 银行字典数据
bankListSelectedIndex: '', // 选中银行 bankList 的 index
});
// 打开提现方式的弹窗
@@ -186,7 +203,7 @@
// 提交提现
const onConfirm = async () => {
// 参数校验
debugger;
//debugger;
if (
!state.accountInfo.price ||
state.accountInfo.price > state.brokerageInfo.price ||
@@ -215,12 +232,12 @@
confirmText: '查看记录',
success: (res) => {
if (res.confirm) {
sheep.$router.go('/pages/commission/wallet', { type: 2 })
sheep.$router.go('/pages/commission/wallet', { type: 2 });
return;
}
getBrokerageUser();
state.accountInfo = {};
}
},
});
};
@@ -245,10 +262,29 @@
}
}
// 获取提现银行配置字典
async function getDictDataListByType() {
let { code, data } = await DictApi.getDictDataListByType('brokerage_bank_name');
if (code !== 0) {
return;
}
if (data && data.length > 0) {
state.bankList = data;
}
}
// 银行选择
function bankChange(e) {
const value = e.detail.value;
state.bankListSelectedIndex = value;
state.accountInfo.bankName = state.bankList[value].label;
}
onBeforeMount(() => {
getWithdrawRules();
getBrokerageUser()
})
getBrokerageUser();
getDictDataListByType(); //获取银行字典数据
});
</script>
<style lang="scss" scoped>
-1
View File
@@ -107,7 +107,6 @@
},
];
// TODO yunai:
function onTabsChange(e) {
state.currentTab = e.index;
state.type = e.value;
+142 -97
View File
@@ -1,89 +1,130 @@
<!-- 评价 -->
<template>
<s-layout title="评价">
<view>
<view v-for="(item, index) in state.orderInfo.items" :key="item.id">
<view>
<view class="commont-from-wrap">
<!-- 评价商品 -->
<s-goods-item
<s-layout title="评价">
<view>
<view v-for="(item, index) in state.orderInfo.items" :key="item.id">
<view>
<view class="commont-from-wrap">
<!-- 评价商品 -->
<s-goods-item
:img="item.picUrl"
:title="item.spuName"
:skuText="item.properties.map((property) => property.valueName).join(' ')"
:price="item.payPrice"
:price="item.payPrice"
:num="item.count"
/>
</view>
</view>
<view class="form-item">
<!-- 评分 -->
<view class="star-box ss-flex ss-col-center">
<view class="star-title ss-m-r-40">商品质量</view>
<uni-rate v-model="state.commentList[index].descriptionScores" />
</view>
<view class="star-box ss-flex ss-col-center">
<view class="star-title ss-m-r-40">服务态度</view>
<uni-rate v-model="state.commentList[index].benefitScores" />
</view>
<!-- 评价 -->
<view class="area-box">
<uni-easyinput :inputBorder="false" type="textarea" maxlength="120" autoHeight
v-model="state.commentList[index].content"
placeholder="宝贝满足你的期待吗?说说你的使用心得,分享给想买的他们吧~" />
<!-- TODO 芋艿文件上传 -->
<view class="img-box">
<s-uploader v-model:url="state.commentList[index].images" fileMediatype="image"
limit="9" mode="grid" :imageStyles="{ width: '168rpx', height: '168rpx' }" />
</view>
</view>
</view>
</view>
</view>
</view>
<!-- TODO 芋艿是否匿名 -->
<su-fixed bottom placeholder>
<view class="foot_box ss-flex ss-row-center ss-col-center">
<button class="ss-reset-button post-btn ui-BG-Main-Gradient ui-Shadow-Main" @tap="onSubmit">
发布
</button>
</view>
</su-fixed>
</s-layout>
<view class="form-item">
<!-- 评分 -->
<view class="star-box ss-flex ss-col-center">
<view class="star-title ss-m-r-40">商品质量</view>
<uni-rate v-model="state.commentList[index].descriptionScores" />
</view>
<view class="star-box ss-flex ss-col-center">
<view class="star-title ss-m-r-40">服务态度</view>
<uni-rate v-model="state.commentList[index].benefitScores" />
</view>
<!-- 评价 -->
<view class="area-box">
<uni-easyinput
:inputBorder="false"
type="textarea"
maxlength="120"
autoHeight
v-model="state.commentList[index].content"
placeholder="宝贝满足你的期待吗?说说你的使用心得,分享给想买的他们吧~"
/>
<view class="img-box">
<s-uploader
v-model:url="state.commentList[index].images"
fileMediatype="image"
limit="9"
mode="grid"
:imageStyles="{ width: '168rpx', height: '168rpx' }"
@success="(payload) => uploadSuccess(payload, index)"
/>
</view>
</view>
<view class="checkbox-container">
<checkbox-group @change="(event) => toggleAnonymous(index, event)">
<label>
<checkbox value="anonymousChecked" />
匿名评论
</label>
</checkbox-group>
</view>
</view>
</view>
</view>
</view>
<su-fixed bottom placeholder>
<view class="foot_box ss-flex ss-row-center ss-col-center">
<button class="ss-reset-button post-btn ui-BG-Main-Gradient ui-Shadow-Main" @tap="onSubmit">
发布
</button>
</view>
</su-fixed>
</s-layout>
</template>
<script setup>
import sheep from '@/sheep';
import { onLoad } from '@dcloudio/uni-app';
import { reactive } from 'vue';
import sheep from '@/sheep';
import { onLoad } from '@dcloudio/uni-app';
import { reactive, ref } from 'vue';
import OrderApi from '@/sheep/api/trade/order';
const state = reactive({
orderInfo: {},
commentList: [],
id: null
});
const state = reactive({
orderInfo: {},
commentList: [],
id: null,
});
async function onSubmit() {
/**
* 切换是否匿名
*
* @param commentIndex 当前评论下标
* @param event 复选框事件
*/
function toggleAnonymous(commentIndex, event) {
state.commentList[commentIndex].anonymous = event.detail.value[0] === 'anonymousChecked';
}
/**
* 发布评论
*
* @returns {Promise<void>}
*/
async function onSubmit() {
// 顺序提交评论
for (const comment of state.commentList) {
await OrderApi.createOrderItemComment(comment);
}
// 都评论好,返回
sheep.$router.back();
}
}
onLoad(async (options) => {
/**
* 图片添加到表单
*
* @param payload 上传成功后的回调数据
* @param commentIndex 当前评论的下标
*/
function uploadSuccess(payload, commentIndex) {
state.commentList[commentIndex].picUrls = state.commentList[commentIndex].images;
}
onLoad(async (options) => {
if (!options.id) {
sheep.$helper.toast(`缺少订单信息,请检查`);
return
return;
}
state.id = options.id;
state.id = options.id;
const { code, data } = await OrderApi.getOrder(state.id);
const { code, data } = await OrderApi.getOrder(state.id);
if (code !== 0) {
sheep.$helper.toast('无待评价订单');
return
return;
}
// 处理评论
data.items.forEach((item) => {
@@ -93,53 +134,57 @@
descriptionScores: 5,
benefitScores: 5,
content: '',
picUrls: []
picUrls: [],
});
});
state.orderInfo = data;
});
});
</script>
<style lang="scss" scoped>
// 评价商品
.goods-card {
margin: 10rpx 0;
padding: 20rpx;
background: #fff;
}
// 评价商品
.goods-card {
margin: 10rpx 0;
padding: 20rpx;
background: #fff;
}
// 评论,选择图片
.form-item {
background: #fff;
// 评论,选择图片
.form-item {
background: #fff;
.star-box {
height: 100rpx;
padding: 0 25rpx;
}
.star-box {
height: 100rpx;
padding: 0 25rpx;
}
.star-title {
font-weight: 600;
}
}
.star-title {
font-weight: 600;
}
}
.area-box {
width: 690rpx;
min-height: 306rpx;
background: rgba(249, 250, 251, 1);
border-radius: 20rpx;
padding: 28rpx;
margin: auto;
.area-box {
width: 690rpx;
min-height: 306rpx;
background: rgba(249, 250, 251, 1);
border-radius: 20rpx;
padding: 28rpx;
margin: auto;
.img-box {
margin-top: 20rpx;
}
}
.img-box {
margin-top: 20rpx;
}
}
.post-btn {
width: 690rpx;
line-height: 80rpx;
border-radius: 40rpx;
color: rgba(#fff, 0.9);
margin-bottom: 20rpx;
}
</style>
.checkbox-container {
padding: 10rpx;
}
.post-btn {
width: 690rpx;
line-height: 80rpx;
border-radius: 40rpx;
color: rgba(#fff, 0.9);
margin-bottom: 20rpx;
}
</style>
+2 -1
View File
@@ -1,6 +1,6 @@
<!-- 商品评论的分页 -->
<template>
<s-layout title="全部评">
<s-layout title="全部评">
<su-tabs
:list="state.type"
:scrollable="false"
@@ -16,6 +16,7 @@
<s-empty v-if="state.pagination.total === 0" text="暂无数据" icon="/static/data-empty.png" />
<!-- 下拉 -->
<uni-load-more
icon-type="auto"
v-if="state.pagination.total > 0"
:status="state.loadStatus"
:content-text="{
@@ -2,7 +2,6 @@
<su-fixed bottom placeholder :val="44">
<view>
<view v-for="activity in props.activityList" :key="activity.id">
<!-- TODO 芋艿拼团 -->
<view
class="activity-box ss-p-x-38 ss-flex ss-row-between ss-col-center"
:class="activity.type === 1 ? 'seckill-box' : 'groupon-box'"
@@ -14,7 +13,6 @@
:src="sheep.$url.static('/static/img/shop/goods/seckill-icon.png')"
class="activity-icon"
/>
<!-- TODO 芋艿拼团 -->
<image
v-else-if="activity.type === 3"
:src="sheep.$url.static('/static/img/shop/goods/groupon-icon.png')"
@@ -33,7 +31,6 @@
<script setup>
import sheep from '@/sheep';
// TODO 芋艿:这里要迁移下;
const seckillBg = sheep.$url.css('/static/img/shop/goods/seckill-tip-bg.png');
const grouponBg = sheep.$url.css('/static/img/shop/goods/groupon-tip-bg.png');
+27 -9
View File
@@ -54,7 +54,7 @@
<view class="origin-price ss-flex ss-col-center" v-if="state.goodsInfo.price">
单买价:
<view class="origin-price-text">
{{ fen2yuan(state.goodsInfo.price) }}
{{ fen2yuan(state.goodsInfo.marketPrice) }}
</view>
</view>
</view>
@@ -80,7 +80,7 @@
<!-- 功能卡片 -->
<view class="detail-cell-card detail-card ss-flex-col">
<!-- 规格 -->
<detail-cell-sku :sku="state.selectedSkuPrice" @tap="state.showSelectSku = true" />
<detail-cell-sku :sku="state.selectedSku" @tap="state.showSelectSku = true" />
</view>
<!-- 参团列表 -->
@@ -104,7 +104,6 @@
<detail-content-card class="detail-content-selector" :content="state.goodsInfo.description" />
<!-- 商品tabbar -->
<!-- TODO: 已售罄、预热 判断 设计-->
<detail-tabbar v-model="state.goodsInfo">
<view class="buy-box ss-flex ss-col-center ss-p-r-20">
<button
@@ -125,7 +124,12 @@
:disabled="state.goodsInfo.stock === 0 || state.activity.status !== 0"
>
<view class="btn-price">{{
fen2yuan(state.activity.price || state.goodsInfo.price)
fen2yuan(
state.selectedSku.price * state.selectedSku.count ||
state.activity.price * state.selectedSku.count ||
state.goodsInfo.price * state.selectedSku.count ||
state.goodsInfo.price,
)
}}</view>
<view v-if="state.activity.startTime > new Date().getTime()">未开始</view>
<view v-else-if="state.activity.endTime <= new Date().getTime()">已结束</view>
@@ -168,7 +172,7 @@
goodsInfo: {}, // 商品信息
goodsSwiper: [], // 商品轮播图
showSelectSku: false, // 显示规格弹框
selectedSkuPrice: {}, // 选中的规格价格
selectedSku: {}, // 选中的规格属性
activity: {}, // 团购活动
grouponId: 0, // 团购ID
grouponNum: 0, // 团购人数
@@ -183,7 +187,7 @@
// 规格变更
function onSkuChange(e) {
state.selectedSkuPrice = e;
state.selectedSku = e;
}
function onSkuClose() {
@@ -199,6 +203,7 @@
/**
* 去参团
*
* @param record 团长的团购记录
*/
function onJoinGroupon(record) {
@@ -227,7 +232,6 @@
}
// 分享信息
// TODO @芋艿:分享的接入
const shareInfo = computed(() => {
if (isEmpty(state.activity)) return {};
return sheep.$platform.share.getShareInfo(
@@ -262,9 +266,23 @@
// 加载商品信息
const { data: spu } = await SpuApi.getSpuDetail(activity.spuId);
state.goodsId = spu.id;
activity.products.forEach((product) => {
spu.price = Math.min(spu.price, product.combinationPrice); // 设置 SPU 的最低价
// 默认显示最低价
spu.price = activity.products.reduce((min, product) => {
return Math.min(min, product.combinationPrice || Infinity);
}, Infinity);
// 价格、库存使用活动的
spu.skus.forEach((sku) => {
const product = activity.products.find((product) => product.skuId === sku.id);
if (product) {
sku.price = product.combinationPrice;
} else {
// 找不到可能是没配置,则不能发起秒杀
sku.stock = 0;
}
});
// 关闭骨架屏
state.skeletonLoading = false;
if (code === 0) {
+109 -262
View File
@@ -7,47 +7,30 @@
<!-- 骨架屏 -->
<detailSkeleton v-if="state.skeletonLoading" />
<!-- 下架/售罄提醒 -->
<s-empty v-else-if="state.goodsInfo === null" text="商品不存在或已下架" icon="/static/soldout-empty.png" showAction
actionText="再逛逛" actionUrl="/pages/goods/list" />
<s-empty
v-else-if="state.goodsInfo === null"
text="商品不存在或已下架"
icon="/static/soldout-empty.png"
showAction
actionText="再逛逛"
actionUrl="/pages/goods/list"
/>
<block v-else>
<view class="detail-swiper-selector">
<!-- 商品轮播图 -->
<su-swiper class="ss-m-b-14" isPreview :list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)"
otStyle="tag" imageMode="widthFix" dotCur="bg-mask-40" :seizeHeight="750" />
<!-- 限时折扣 -->
<view class="discount" v-if="setShow">
<image class="disImg" src="../../static/images/dis.png"></image>
<view class="discountCont">
<view class="disContT">
<view class="disContT1">
<view class="disContT1P">
{{fen2yuan(settleData.price)}}
</view>
<view class="disContT1End">
直降{{fen2yuan( state.goodsInfo.price - settleData.price)}}
</view>
</view>
<view class="disContT2">
限时折扣
</view>
</view>
<view class="disContB">
<view class="disContB1">
价格{{fen2yuan(state.goodsInfo.price)}} 剩余{{settleData.stock}}
</view>
<view class="disContB2">
距结束仅剩
<countDown :tipText="' '" :bgColor="bgColor" :dayText="':'" :hourText="':'"
:minuteText="':'" :secondText="' '" :datatime="settleData.endTime / 1000"
:isDay="false" />
</view>
</view>
</view>
</view>
<!-- 限时折扣 -->
<su-swiper
class="ss-m-b-14"
isPreview
:list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)"
otStyle="tag"
imageMode="widthFix"
dotCur="bg-mask-40"
:seizeHeight="750"
/>
<!-- 价格+标题 -->
<view class="title-card detail-card ss-p-y-40 ss-p-x-20">
<view class="ss-flex ss-row-between ss-col-center ss-m-b-26" v-if="!setShow">
<view class="ss-flex ss-row-between ss-col-center ss-m-b-26">
<view class="price-box ss-flex ss-col-bottom">
<view class="price-text ss-m-r-16">
{{ fen2yuan(state.selectedSku.price || state.goodsInfo.price) }}
@@ -64,16 +47,23 @@
<!-- 满减送/限时折扣活动的提示 -->
<div class="tag-content">
<view class="tag-box ss-flex">
<view class="tag ss-m-r-10" v-for="promos in state.activityInfo" :key="promos.id"
@tap="onActivity">
<view
class="tag ss-m-r-10"
v-for="promos in state.activityInfo"
:key="promos.id"
@tap="onActivity"
>
{{ promos.name }}
</view>
</view>
</div>
<!-- 优惠劵@tap="state.showModel = true" -->
<view class="get-coupon-box ss-flex ss-col-center ss-m-l-20" @tap="onActivity"
v-if="state.couponInfo.length">
<!-- 优惠劵 -->
<view
class="get-coupon-box ss-flex ss-col-center ss-m-l-20"
@tap="state.showModel = true"
v-if="state.couponInfo.length"
>
<view class="discounts-title ss-m-r-8">领券</view>
<text class="cicon-forward"></text>
</view>
@@ -84,30 +74,51 @@
<!-- 功能卡片 -->
<view class="detail-cell-card detail-card ss-flex-col">
<detail-cell-sku v-model="state.selectedSku.goods_sku_text" :sku="state.selectedSku"
@tap="state.showSelectSku = true" />
<detail-cell-sku
v-model="state.selectedSku.goods_sku_text"
:sku="state.selectedSku"
@tap="state.showSelectSku = true"
/>
</view>
<!-- 规格与数量弹框 -->
<s-select-sku :goodsInfo="state.goodsInfo" :show="state.showSelectSku" @addCart="onAddCart"
@buy="onBuy" @change="onSkuChange" @close="state.showSelectSku = false" />
<s-select-sku
:goodsInfo="state.goodsInfo"
:show="state.showSelectSku"
@addCart="onAddCart"
@buy="onBuy"
@change="onSkuChange"
@close="state.showSelectSku = false"
/>
</view>
<!-- 评价 -->
<detail-comment-card class="detail-comment-selector" :goodsId="state.goodsId" />
<!-- 详情 -->
<detail-content-card class="detail-content-selector" :content="state.goodsInfo.description" />
<detail-content-card
class="detail-content-selector"
:content="state.goodsInfo.description"
/>
<!-- 活动跳转拼团/秒杀/砍价活动 -->
<detail-activity-tip v-if="state.activityList.length > 0" :activity-list="state.activityList" />
<detail-activity-tip
v-if="state.activityList.length > 0"
:activity-list="state.activityList"
/>
<!-- 详情 tabbar -->
<detail-tabbar v-model="state.goodsInfo">
<view class="buy-box ss-flex ss-col-center ss-p-r-20" v-if="state.goodsInfo.stock > 0">
<button class="ss-reset-button add-btn ui-Shadow-Main" @tap="state.showSelectSku = true">
<button
class="ss-reset-button add-btn ui-Shadow-Main"
@tap="state.showSelectSku = true"
>
加入购物车
</button>
<button class="ss-reset-button buy-btn ui-Shadow-Main" @tap="state.showSelectSku = true">
<button
class="ss-reset-button buy-btn ui-Shadow-Main"
@tap="state.showSelectSku = true"
>
立即购买
</button>
</view>
@@ -117,38 +128,32 @@
</detail-tabbar>
<!-- 优惠劵弹窗 -->
<!-- <s-coupon-get v-model="state.couponInfo" :show="state.showModel" @close="state.showModel = false"
@get="onGet" /> -->
<s-coupon-get
v-model="state.couponInfo"
:show="state.showModel"
@close="state.showModel = false"
@get="onGet"
/>
<!-- 满减送/限时折扣活动弹窗 -->
<s-activity-pop v-model="state" :show="state.showActivityModel"
@close="state.showActivityModel = false" @get="onGet" />
<s-activity-pop
v-model="state.activityInfo"
:show="state.showActivityModel"
@close="state.showActivityModel = false"
/>
</block>
</s-layout>
</view>
</template>
<script setup>
import {
reactive,
computed,
ref
} from 'vue';
import {
onLoad,
onPageScroll
} from '@dcloudio/uni-app';
import { reactive, computed } from 'vue';
import { onLoad, onPageScroll } from '@dcloudio/uni-app';
import sheep from '@/sheep';
import CouponApi from '@/sheep/api/promotion/coupon';
import ActivityApi from '@/sheep/api/promotion/activity';
import FavoriteApi from '@/sheep/api/product/favorite';
import {
formatSales,
formatGoodsSwiper,
fen2yuan,
handList,
handListPrice
} from '@/sheep/hooks/useGoods';
import { formatSales, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods';
import detailNavbar from './components/detail/detail-navbar.vue';
import detailCellSku from './components/detail/detail-cell-sku.vue';
import detailTabbar from './components/detail/detail-tabbar.vue';
@@ -156,22 +161,11 @@
import detailCommentCard from './components/detail/detail-comment-card.vue';
import detailContentCard from './components/detail/detail-content-card.vue';
import detailActivityTip from './components/detail/detail-activity-tip.vue';
import {
isEmpty
} from 'lodash-es';
import { isEmpty } from 'lodash-es';
import SpuApi from '@/sheep/api/product/spu';
onPageScroll(() => {
});
import countDown from '@/sheep/components/countDown/index.vue'
onPageScroll(() => {});
const bgColor = {
'bgColor': '#E93323',
'Color': '#fff',
'width': '44rpx',
'timeTxtwidth': '16rpx',
'isDay': true
}
const isLogin = computed(() => sheep.$store('user').isLogin);
const state = reactive({
goodsId: 0,
@@ -182,19 +176,13 @@
showModel: false, // 是否展示 Coupon 优惠劵的弹窗
couponInfo: [], // 可领取的 Coupon 优惠劵的列表
showActivityModel: false, // 【满减送/限时折扣】是否展示 Activity 营销活动的弹窗
activityInfo: [], // 【满减送/限时折扣】可参与的 Activity 营销活动的列表
activityInfo: [], // 【满减送/限时折扣】可参与的 Activity 营销活动的列表 TODO 芋艿:正在接入中
activityList: [], // 【秒杀/拼团/砍价】可参与的 Activity 营销活动的列表
});
// 规格变更
function onSkuChange(e) {
if (e.type == 4) {
settleData.value = e
setShow.value = true
} else {
state.selectedSku = e;
setShow.value = false
}
state.selectedSku = e;
}
// 添加购物车
@@ -208,17 +196,19 @@
// 立即购买
function onBuy(e) {
if (!e.id) {
if (!state.selectedSku.id) {
sheep.$helper.toast('请选择商品规格');
return;
}
sheep.$router.go('/pages/order/confirm', {
data: JSON.stringify({
items: [{
skuId: e.id,
count: e.goods_num,
categoryId: state.goodsInfo.categoryId
}]
items: [
{
skuId: e.id,
count: e.goods_num,
categoryId: state.goodsInfo.categoryId,
},
],
}),
});
}
@@ -230,9 +220,7 @@
// 立即领取
async function onGet(id) {
const {
code
} = await CouponApi.takeCoupon(id);
const { code } = await CouponApi.takeCoupon(id);
if (code !== 0) {
return;
}
@@ -244,69 +232,35 @@
}, 1000);
}
// TODO 芋艿:待测试
const shareInfo = computed(() => {
if (isEmpty(state.goodsInfo)) return {};
return sheep.$platform.share.getShareInfo({
title: state.goodsInfo.name,
image: sheep.$url.cdn(state.goodsInfo.picUrl),
desc: state.goodsInfo.introduction,
params: {
page: '2',
query: state.goodsInfo.id,
return sheep.$platform.share.getShareInfo(
{
title: state.goodsInfo.name,
image: sheep.$url.cdn(state.goodsInfo.picUrl),
desc: state.goodsInfo.introduction,
params: {
page: '2',
query: state.goodsInfo.id,
},
},
}, {
type: 'goods', // 商品海报
title: state.goodsInfo.name, // 商品名称
image: sheep.$url.cdn(state.goodsInfo.picUrl), // 商品主图
price: fen2yuan(state.goodsInfo.price), // 商品价格
original_price: fen2yuan(state.goodsInfo.marketPrice), // 商品原价
});
{
type: 'goods', // 商品海报
title: state.goodsInfo.name, // 商品名称
image: sheep.$url.cdn(state.goodsInfo.picUrl), // 商品主图
price: fen2yuan(state.goodsInfo.price), // 商品价格
original_price: fen2yuan(state.goodsInfo.marketPrice), // 商品原价
},
);
});
async function getCoupon() {
const {
code,
data
} = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10);
const { code, data } = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10);
if (code === 0) {
state.couponInfo = data;
}
}
//获取结算信息
const setShow = ref(false)
const settleData = ref()
async function getSettlementByIds(ids) {
const { data } = await SpuApi.getSettlementProduct(ids);
settleData.value = handle(data)
state.goodsInfo.skus = handListPrice(state.goodsInfo.skus, data[0].skus)
}
//判断是否有限时折扣信息
function handle(array) {
let setList = {}
array.some(item => {
return item.skus.some(items => {
if (items.type === 4) {
setShow.value = true;
setList = items;
return true; // 返回true以结束some循环
}
return false; // 继续遍历
});
});
// 将库存信息加入
state.goodsInfo.skus.forEach(item => {
if (item.id == setList.skuId) {
setList.stock = item.stock
}
})
return setList
}
onLoad((options) => {
// 非法参数
if (!options.id) {
@@ -324,6 +278,7 @@
// 加载到商品
state.skeletonLoading = false;
state.goodsInfo = res.data;
// 加载是否收藏
if (isLogin.value) {
FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
@@ -338,24 +293,13 @@
// 2. 加载优惠劵信息
getCoupon();
// 3. 加载营销活动信息
// 3. 获得单个商品,进行中的拼团、秒杀、砍价活动信息
ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
if (res.code !== 0) {
return;
}
let activData = handList(res.data)
activData.forEach(activity => {
if ([1, 2, 3].includes(activity.type)) { // 情况一:拼团/秒杀/砍价
state.activityList.push(activity);
} else if (activity.type === 5) { // 情况二:满减送
state.activityInfo.push(activity);
} else { // 情况三:限时折扣 TODO 芋艿
// console.log('待实现!优先级不高');
}
})
state.activityList = res.data;
});
//获取结算信息
getSettlementByIds(state.goodsId)
});
</script>
@@ -504,101 +448,4 @@
color: #333333;
}
}
// 限时折扣
.discount {
width: 750rpx;
height: 100rpx;
// background-color: red;
overflow: hidden;
position: relative;
}
.disImg {
width: 750rpx;
height: 100rpx;
position: absolute;
top: 0;
z-index: -1;
}
.discountCont {
width: 680rpx;
height: 90rpx;
margin: 10rpx auto 0 auto;
// background-color: gold;
}
.disContT {
width: 680rpx;
height: 50rpx;
display: flex;
justify-content: space-between;
}
.disContT1 {
width: 400rpx;
height: 50rpx;
// background-color: green;
display: flex;
justify-content: flex-start;
align-items: center;
}
.disContT2 {
width: 200rpx;
height: 50rpx;
line-height: 50rpx;
// background-color: gold;
font-size: 30rpx;
text-align: end;
color: white;
font-weight: bolder;
font-style: oblique 20deg;
letter-spacing: .1rem;
}
.disContT1P {
color: white;
font-weight: bold;
font-size: 28rpx;
}
.disContT1End {
// width: 180rpx;
padding: 0 10rpx;
height: 30rpx;
line-height: 28rpx;
text-align: center;
font-weight: bold;
background-color: white;
color: #ff3000;
font-size: 23rpx;
border-radius: 20rpx;
margin-left: 10rpx;
}
.disContB {
width: 680rpx;
height: 40rpx;
display: flex;
justify-content: space-between;
font-size: 20rpx;
color: white;
align-items: center;
}
.disContB1 {
width: 300rpx;
height: 40rpx;
line-height: 40rpx;
}
.disContB2 {
width: 300rpx;
height: 40rpx;
line-height: 40rpx;
display: flex;
justify-content: flex-end;
}
</style>
</style>
+2 -6
View File
@@ -107,6 +107,7 @@
skuId: item.sku.id,
count: item.count,
cartId: item.id,
categoryId: item.spu.categoryId
})
goods_list.push({
// goods_id: item.goods_id,
@@ -124,12 +125,7 @@
}
sheep.$router.go('/pages/order/confirm', {
data: JSON.stringify({
// order_type: 'goods',
// goods_list,
items,
// from: 'cart',
deliveryType: 1,
pointStatus: false,
items
}),
});
}
+6 -5
View File
@@ -131,12 +131,13 @@
getGoodsList();
}
onLoad(async () => {
onLoad(async (params) => {
await getList();
// 如果是 first 风格,需要加载商品分页
if (state.style === 'first_one' || state.style === 'first_two') {
onMenu(0);
}
// 首页点击分类的处理:查找满足条件的分类
const foundCategory = state.categoryList.find(category => category.id === params.id);
// 如果找到则调用 onMenu 自动勾选相应分类,否则调用 onMenu(0) 勾选第一个分类
onMenu(foundCategory ? state.categoryList.indexOf(foundCategory) : 0);
});
onReachBottom(() => {
+64 -49
View File
@@ -1,52 +1,69 @@
<!-- 下单界面收货地址 or 自提门店的选择组件 -->
<template>
<view class="allAddress" :style="state.isPickUp ? '':'padding-top:10rpx;'">
<view class="allAddress" :style="state.isPickUp ? '' : 'padding-top:10rpx;'">
<view class="nav flex flex-wrap">
<view class="item font-color" :class="state.deliveryType === 1 ? 'on' : 'on2'"
@tap="switchDeliveryType(1)" v-if='state.isPickUp' />
<view class="item font-color" :class="state.deliveryType === 2 ? 'on' : 'on2'"
@tap="switchDeliveryType(2)" v-if='state.isPickUp' />
<view
class="item font-color"
:class="state.deliveryType === 1 ? 'on' : 'on2'"
@tap="switchDeliveryType(1)"
v-if="state.isPickUp"
/>
<view
class="item font-color"
:class="state.deliveryType === 2 ? 'on' : 'on2'"
@tap="switchDeliveryType(2)"
v-if="state.isPickUp"
/>
</view>
<!-- 情况一收货地址的选择 -->
<view class='address flex flex-wrap flex-center ss-row-between' @tap='onSelectAddress' v-if='state.deliveryType === 1'
:style="state.isPickUp ? '':'border-top-left-radius: 14rpx;border-top-right-radius: 14rpx;'">
<view class='addressCon' v-if="state.addressInfo.name">
<view class='name'>{{ state.addressInfo.name }}
<text class='phone'>{{ state.addressInfo.mobile }}</text>
<view
class="address flex flex-wrap flex-center ss-row-between"
@tap="onSelectAddress"
v-if="state.deliveryType === 1"
:style="state.isPickUp ? '' : 'border-top-left-radius: 14rpx;border-top-right-radius: 14rpx;'"
>
<view class="addressCon" v-if="state.addressInfo.name">
<view class="name"
>{{ state.addressInfo.name }}
<text class="phone">{{ state.addressInfo.mobile }}</text>
</view>
<view class="flex flex-wrap">
<text class='default font-color' v-if="state.addressInfo.defaultStatus">[默认]</text>
<text class="line2">{{ state.addressInfo.areaName }} {{ state.addressInfo.detailAddress }}</text>
<text class="default font-color" v-if="state.addressInfo.defaultStatus">[默认]</text>
<text class="line2"
>{{ state.addressInfo.areaName }} {{ state.addressInfo.detailAddress }}</text
>
</view>
</view>
<view class='addressCon' v-else>
<view class='setaddress'>设置收货地址</view>
<view class="addressCon" v-else>
<view class="setaddress">设置收货地址</view>
</view>
<view class='iconfont'>
<view class="iconfont">
<view class="ss-rest-button">
<text class="_icon-forward" />
</view>
</view>
</view>
<!-- 情况二门店的选择 -->
<view class='address flex flex-wrap flex-center ss-row-between' v-else @tap="onSelectAddress">
<view class='addressCon' v-if="state.pickUpInfo.name">
<view class='name'>{{ state.pickUpInfo.name }}
<text class='phone'>{{ state.pickUpInfo.phone }}</text>
<view class="address flex flex-wrap flex-center ss-row-between" v-else @tap="onSelectAddress">
<view class="addressCon" v-if="state.pickUpInfo.name">
<view class="name"
>{{ state.pickUpInfo.name }}
<text class="phone">{{ state.pickUpInfo.phone }}</text>
</view>
<view class="line1"> {{ state.pickUpInfo.areaName }}{{ ', ' + state.pickUpInfo.detailAddress }}
<view class="line1">
{{ state.pickUpInfo.areaName }}{{ ', ' + state.pickUpInfo.detailAddress }}
</view>
</view>
<view class='addressCon' v-else>
<view class='setaddress'>选择自提门店</view>
<view class="addressCon" v-else>
<view class="setaddress">选择自提门店</view>
</view>
<view class='iconfont'>
<view class="iconfont">
<view class="ss-rest-button">
<text class="_icon-forward" />
</view>
</view>
</view>
<view class='line'>
<view class="line">
<image :src="sheep.$url.static('/static/images/line.png', 'local')" />
</view>
</view>
@@ -61,13 +78,13 @@
modelValue: {
type: Object,
default() {},
}
},
});
const emits = defineEmits(['update:modelValue','change']);
const emits = defineEmits(['update:modelValue']);
// computed 解决父子组件双向数据同步
const state = computed({
get(){
get() {
return new Proxy(props.modelValue, {
set(obj, name, val) {
emits('update:modelValue', {
@@ -75,21 +92,21 @@
[name]: val,
});
return true;
}
})
},
});
},
set(val){
set(val) {
emits('update:modelValue', val);
}
})
},
});
// 选择地址
function onSelectAddress() {
let emitName = 'SELECT_ADDRESS'
let emitName = 'SELECT_ADDRESS';
let addressPage = '/pages/user/address/list?type=select';
if (state.value.deliveryType === 2){
emitName = 'SELECT_PICK_UP_INFO'
addressPage = '/pages/user/goods_details_store/index'
if (state.value.deliveryType === 2) {
emitName = 'SELECT_PICK_UP_INFO';
addressPage = '/pages/user/goods_details_store/index';
}
uni.$once(emitName, (e) => {
changeConsignee(e.addressInfo);
@@ -100,28 +117,26 @@
// 更改收货人地址&计算订单信息
async function changeConsignee(addressInfo = {}) {
if (!isEmpty(addressInfo)) {
if (state.value.deliveryType === 1){
if (state.value.deliveryType === 1) {
state.value.addressInfo = addressInfo;
}
if (state.value.deliveryType === 2){
if (state.value.deliveryType === 2) {
state.value.pickUpInfo = addressInfo;
}
emits('change')
}
}
// 收货方式切换
const switchDeliveryType = (type) =>{
const switchDeliveryType = (type) => {
state.value.deliveryType = type;
emits('change')
}
};
</script>
<style scoped lang="scss">
.allAddress .font-color{
color: #E93323!important
.allAddress .font-color {
color: #e93323 !important;
}
.line2{
.line2 {
width: 504rpx;
}
.textR {
@@ -204,7 +219,7 @@
.allAddress .nav .item.on::before {
position: absolute;
bottom: 0;
content: "快递配送";
content: '快递配送';
font-size: 28rpx;
display: block;
height: 0;
@@ -219,7 +234,7 @@
}
.allAddress .nav .item:nth-of-type(2).on::before {
content: "到店自提";
content: '到店自提';
border-width: 0 0 80rpx 20rpx;
border-radius: 36rpx 14rpx 0 0;
}
@@ -231,7 +246,7 @@
.allAddress .nav .item.on2::before {
position: absolute;
bottom: 0;
content: "到店自提";
content: '到店自提';
font-size: 28rpx;
display: block;
height: 0;
@@ -245,7 +260,7 @@
}
.allAddress .nav .item:nth-of-type(1).on2::before {
content: "快递配送";
content: '快递配送';
border-width: 0 60rpx 60rpx 0;
border-radius: 14rpx 36rpx 0 0;
}
+131 -78
View File
@@ -1,18 +1,30 @@
<template>
<s-layout title="确认订单">
<!-- 头部地址选择配送地址自提地址 -->
<AddressSelection v-model="addressState" @change="getOrderInfo()" />
<AddressSelection v-model="addressState" />
<!-- 商品信息 -->
<view class="order-card-box ss-m-b-14">
<s-goods-item v-for="item in state.orderInfo.items" :key="item.skuId" :img="item.picUrl"
:title="item.spuName" :skuText="item.properties.map((property) => property.valueName).join(' ')"
:price="item.price" :num="item.count" marginBottom="10" />
<s-goods-item
v-for="item in state.orderInfo.items"
:key="item.skuId"
:img="item.picUrl"
:title="item.spuName"
:skuText="item.properties.map((property) => property.valueName).join(' ')"
:price="item.price"
:num="item.count"
marginBottom="10"
/>
<view class="order-item ss-flex ss-col-center ss-row-between ss-p-x-20 bg-white ss-r-10">
<view class="item-title">订单备注</view>
<view class="ss-flex ss-col-center">
<uni-easyinput maxlength="20" placeholder="建议留言前先与商家沟通" v-model="state.orderPayload.remark"
:inputBorder="false" :clearable="false" />
<uni-easyinput
maxlength="20"
placeholder="建议留言前先与商家沟通"
v-model="state.orderPayload.remark"
:inputBorder="false"
:clearable="false"
/>
</view>
</view>
</view>
@@ -28,71 +40,121 @@
</text>
</view>
</view>
<view class="order-item ss-flex ss-col-center ss-row-between" v-if="state.orderInfo.type === 0">
<view
class="order-item ss-flex ss-col-center ss-row-between"
v-if="state.orderInfo.type === 0"
>
<view class="item-title">积分抵扣</view>
<view class="ss-flex ss-col-center">
{{ state.pointStatus ? '剩余积分' : '当前积分' }}
<image :src="sheep.$url.static('/static/img/shop/goods/score1.svg')" class="score-img" />
<image
:src="sheep.$url.static('/static/img/shop/goods/score1.svg')"
class="score-img"
/>
<text class="item-value ss-m-r-24">
{{ state.pointStatus ? state.orderInfo.totalPoint - state.orderInfo.usePoint : (state.orderInfo.totalPoint || 0) }}
{{
state.pointStatus
? state.orderInfo.totalPoint - state.orderInfo.usePoint
: state.orderInfo.totalPoint || 0
}}
</text>
<checkbox-group @change="changeIntegral">
<checkbox :checked='state.pointStatus'
:disabled="!state.orderInfo.totalPoint || state.orderInfo.totalPoint <= 0" />
<checkbox
:checked="state.pointStatus"
:disabled="!state.orderInfo.totalPoint || state.orderInfo.totalPoint <= 0"
/>
</checkbox-group>
</view>
</view>
<!-- 快递配置时信息的展示 -->
<view class="order-item ss-flex ss-col-center ss-row-between" v-if='addressState.deliveryType === 1'>
<view
class="order-item ss-flex ss-col-center ss-row-between"
v-if="addressState.deliveryType === 1"
>
<view class="item-title">运费</view>
<view class="ss-flex ss-col-center">
<text class="item-value ss-m-r-24" v-if="state.orderInfo.price.deliveryPrice > 0">
+{{ fen2yuan(state.orderInfo.price.deliveryPrice) }}
</text>
<view class='item-value ss-m-r-24' v-else>免运费</view>
<view class="item-value ss-m-r-24" v-else>免运费</view>
</view>
</view>
<!-- 门店自提时需要填写姓名和手机号 -->
<view class="order-item ss-flex ss-col-center ss-row-between" v-if='addressState.deliveryType === 2'>
<view
class="order-item ss-flex ss-col-center ss-row-between"
v-if="addressState.deliveryType === 2"
>
<view class="item-title">联系人</view>
<view class="ss-flex ss-col-center">
<uni-easyinput maxlength="20" placeholder="请填写您的联系姓名" v-model="addressState.receiverName"
:inputBorder="false" :clearable="false" />
<uni-easyinput
maxlength="20"
placeholder="请填写您的联系姓名"
v-model="addressState.receiverName"
:inputBorder="false"
:clearable="false"
/>
</view>
</view>
<view class="order-item ss-flex ss-col-center ss-row-between" v-if='addressState.deliveryType === 2'>
<view
class="order-item ss-flex ss-col-center ss-row-between"
v-if="addressState.deliveryType === 2"
>
<view class="item-title">联系电话</view>
<view class="ss-flex ss-col-center">
<uni-easyinput maxlength="20" placeholder="请填写您的联系电话" v-model="addressState.receiverMobile"
:inputBorder="false" :clearable="false" />
<uni-easyinput
maxlength="20"
placeholder="请填写您的联系电话"
v-model="addressState.receiverMobile"
:inputBorder="false"
:clearable="false"
/>
</view>
</view>
<!-- 优惠劵只有 type = 0 普通订单非拼团秒杀砍价才可以使用优惠劵 -->
<view class="order-item ss-flex ss-col-center ss-row-between" v-if="state.orderInfo.type === 0">
<view
class="order-item ss-flex ss-col-center ss-row-between"
v-if="state.orderInfo.type === 0"
>
<view class="item-title">优惠券</view>
<view class="ss-flex ss-col-center" @tap="state.showCoupon = true">
<text class="item-value text-red" v-if="state.orderPayload.couponId > 0">
-{{ fen2yuan(state.orderInfo.price.couponPrice) }}
</text>
<text class="item-value" :class="couponNumber > 0 ? 'text-red' : 'text-disabled'" v-else>
<text
class="item-value"
:class="
state.couponInfo.filter((coupon) => coupon.match).length > 0
? 'text-red'
: 'text-disabled'
"
v-else
>
{{
couponNumber > 0 ? couponNumber + ' 张可用' : '暂无可用优惠券'
state.couponInfo.filter((coupon) => coupon.match).length > 0
? state.couponInfo.filter((coupon) => coupon.match).length + ' 张可用'
: '暂无可用优惠券'
}}
</text>
<text class="_icon-forward item-icon" />
</view>
</view>
<view class="order-item ss-flex ss-col-center ss-row-between"
v-if="state.orderInfo.price.discountPrice > 0">
<view
class="order-item ss-flex ss-col-center ss-row-between"
v-if="state.orderInfo.price.discountPrice > 0"
>
<view class="item-title">活动优惠</view>
<view class="ss-flex ss-col-center" @tap="state.showDiscount = true">
<view class="ss-flex ss-col-center">
<!-- @tap="state.showDiscount = true" TODO puhui999折扣后续要把优惠信息打进去 -->
<text class="item-value text-red">
-{{ fen2yuan(state.orderInfo.price.discountPrice) }}
</text>
<text class="_icon-forward item-icon" />
</view>
</view>
<view class="order-item ss-flex ss-col-center ss-row-between" v-if="state.orderInfo.price.vipPrice > 0">
<view
class="order-item ss-flex ss-col-center ss-row-between"
v-if="state.orderInfo.price.vipPrice > 0"
>
<view class="item-title">会员优惠</view>
<view class="ss-flex ss-col-center">
<text class="item-value text-red">
@@ -111,11 +173,19 @@
</view>
<!-- 选择优惠券弹框 -->
<s-coupon-select v-model="state.couponInfo" :show="state.showCoupon" @confirm="onSelectCoupon"
@close="state.showCoupon = false" />
<s-coupon-select
v-model="state.couponInfo"
:show="state.showCoupon"
@confirm="onSelectCoupon"
@close="state.showCoupon = false"
/>
<!-- 满额折扣弹框 TODO 芋艿后续要把优惠信息打进去 -->
<s-discount-list v-model="state.orderInfo" :show="state.showDiscount" @close="state.showDiscount = false" />
<!-- 满额折扣弹框 TODO @puhui999折扣后续要把优惠信息打进去 -->
<s-discount-list
v-model="state.orderInfo"
:show="state.showDiscount"
@close="state.showDiscount = false"
/>
<!-- 底部 -->
<su-fixed bottom :opacity="false" bg="bg-white" placeholder :noFixed="false" :index="200">
@@ -125,7 +195,10 @@
{{ fen2yuan(state.orderInfo.price.payPrice) }}
</view>
</view>
<button class="ss-reset-button ui-BG-Main-Gradient ss-r-40 submit-btn ui-Shadow-Main" @tap="onConfirm">
<button
class="ss-reset-button ui-BG-Main-Gradient ss-r-40 submit-btn ui-Shadow-Main"
@tap="onConfirm"
>
提交订单
</button>
</view>
@@ -134,20 +207,13 @@
</template>
<script setup>
import {
reactive,
ref
} from 'vue';
import {
onLoad
} from '@dcloudio/uni-app';
import { reactive, ref, watch } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import AddressSelection from '@/pages/order/addressSelection.vue';
import sheep from '@/sheep';
import OrderApi from '@/sheep/api/trade/order';
import CouponApi from '@/sheep/api/promotion/coupon';
import {
fen2yuan
} from '@/sheep/hooks/useGoods';
import TradeConfigApi from '@/sheep/api/trade/config';
import { fen2yuan } from '@/sheep/hooks/useGoods';
const state = reactive({
orderPayload: {},
@@ -164,8 +230,8 @@
const addressState = ref({
addressInfo: {}, // 选择的收货地址
deliveryType: 1, // 收货方式 1 - 快递配送;2 - 门店自提
isPickUp: true, // 门店自提是否开启 TODO puhui999: 默认开启,看看后端有开关的话接入
deliveryType: 1, // 收货方式1-快递配送,2-门店自提
isPickUp: true, // 门店自提是否开启
pickUpInfo: {}, // 选择的自提门店信息
receiverName: '', // 收件人名称
receiverMobile: '', // 收件人手机
@@ -182,7 +248,7 @@
// 选择优惠券
async function onSelectCoupon(couponId) {
state.orderPayload.couponId = couponId || 0;
state.orderPayload.couponId = couponId;
await getOrderInfo();
state.showCoupon = false;
}
@@ -216,10 +282,7 @@
// 创建订单&跳转
async function submitOrder() {
const {
code,
data
} = await OrderApi.createOrder({
const { code, data } = await OrderApi.createOrder({
items: state.orderPayload.items,
couponId: state.orderPayload.couponId,
remark: state.orderPayload.remark,
@@ -250,10 +313,7 @@
// 检查库存 & 计算订单价格
async function getOrderInfo() {
// 计算价格
const {
data,
code
} = await OrderApi.settlementOrder({
const { data, code } = await OrderApi.settlementOrder({
items: state.orderPayload.items,
couponId: state.orderPayload.couponId,
deliveryType: addressState.value.deliveryType,
@@ -267,38 +327,16 @@
seckillActivityId: state.orderPayload.seckillActivityId,
});
if (code !== 0) {
setTimeout(() => {
uni.navigateBack({
delta: 1
})
}, 1500)
return;
}
state.orderInfo = data;
state.couponInfo = data.coupons;
// 设置收货地址
if (state.orderInfo.address) {
addressState.value.addressInfo = state.orderInfo.address;
}
}
// 获取可用优惠券
let couponNumber = ref(0)
async function getCoupons() {
const {
code,
data
} = await CouponApi.getMatchCouponList(
state.orderInfo.price.payPrice,
state.orderInfo.items.map((item) => item.spuId),
state.orderPayload.items.map((item) => item.skuId),
state.orderPayload.items.map((item) => item.categoryId),
);
if (code === 0) {
state.couponInfo = data;
couponNumber.value = state.couponInfo.filter(item => item.match).length;
}
}
onLoad(async (options) => {
if (!options.data) {
sheep.$helper.toast('参数不正确,请检查!');
@@ -306,7 +344,22 @@
}
state.orderPayload = JSON.parse(options.data);
await getOrderInfo();
await getCoupons();
// 获取交易配置
const { data, code } = await TradeConfigApi.getTradeConfig();
if (code === 0) {
addressState.value.isPickUp = data.deliveryPickUpEnabled;
}
});
// 使用 watch 监听地址和配送方式的变化
watch(addressState, async (newAddress, oldAddress) => {
// 如果收货地址或配送方式有变化,则重新计算价格
if (
newAddress.addressInfo.id !== oldAddress.addressInfo.id ||
newAddress.deliveryType !== oldAddress.deliveryType
) {
await getOrderInfo();
}
});
</script>
@@ -429,4 +482,4 @@
font-size: 36rpx;
color: #999999;
}
</style>
</style>
+30 -8
View File
@@ -45,9 +45,9 @@
</image>
<view class="ss-font-30">{{ formatOrderStatus(state.orderInfo) }}</view>
</view>
<view class="ss-font-26 ss-m-x-20 ss-m-b-70">{{
formatOrderStatusDescription(state.orderInfo)
}}</view>
<view class="ss-font-26 ss-m-x-20 ss-m-b-70">
{{ formatOrderStatusDescription(state.orderInfo) }}
</view>
</view>
<!-- 收货地址 -->
@@ -126,6 +126,9 @@
</view>
</view>
<!-- 自提核销 -->
<PickUpVerify :order-info="state.orderInfo" :systemStore="systemStore" ref="pickUpVerifyRef"></PickUpVerify>
<!-- 订单信息 -->
<view class="notice-box">
<view class="notice-box__content">
@@ -167,11 +170,14 @@
<text class="title">运费</text>
<text class="detail">¥{{ fen2yuan(state.orderInfo.deliveryPrice) }}</text>
</view>
<!-- TODO 芋艿:优惠劵抵扣、积分抵扣 -->
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.couponPrice > 0">
<text class="title">优惠劵金额</text>
<text class="detail">-¥{{ fen2yuan(state.orderInfo.couponPrice) }}</text>
</view>
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.pointPrice > 0">
<text class="title">积分抵扣</text>
<text class="detail">-¥{{ fen2yuan(state.orderInfo.pointPrice) }}</text>
</view>
<view class="notice-item ss-flex ss-row-between" v-if="state.orderInfo.discountPrice > 0">
<text class="title">活动优惠</text>
<text class="detail">¥{{ fen2yuan(state.orderInfo.discountPrice) }}</text>
@@ -251,7 +257,7 @@
<script setup>
import sheep from '@/sheep';
import { onLoad } from '@dcloudio/uni-app';
import { reactive } from 'vue';
import { reactive, ref } from 'vue';
import { isEmpty } from 'lodash-es';
import {
fen2yuan,
@@ -260,6 +266,8 @@
handleOrderButtons,
} from '@/sheep/hooks/useGoods';
import OrderApi from '@/sheep/api/trade/order';
import DeliveryApi from '@/sheep/api/trade/delivery';
import PickUpVerify from '@/pages/order/pickUpVerify.vue';
const statusBarHeight = sheep.$platform.device.statusBarHeight * 2;
const headerBg = sheep.$url.css('/static/img/shop/order/order_bg.png');
@@ -270,6 +278,9 @@
comeinType: '', // 进入订单详情的来源类型
});
// ========== 门店自提(核销) ==========
const systemStore = ref({}); // 门店信息
// 复制
const onCopy = () => {
sheep.$helper.copyText(state.orderInfo.no);
@@ -294,7 +305,7 @@
uni.showModal({
title: '提示',
content: '确定要取消订单吗?',
success: async function (res) {
success: async function(res) {
if (!res.confirm) {
return;
}
@@ -313,7 +324,7 @@
});
}
// 确认收货 TODO 芋艿:待测试
// 确认收货
async function onConfirm(orderId, ignore = false) {
// 需开启确认收货组件
// todo: 芋艿:待接入微信
@@ -366,6 +377,7 @@
},
});
}
// #endif
// 评价
@@ -375,6 +387,8 @@
});
}
const pickUpVerifyRef = ref();
async function getOrderDetail(id) {
// 对详情数据进行适配
let res;
@@ -389,6 +403,14 @@
if (res.code === 0) {
state.orderInfo = res.data;
handleOrderButtons(state.orderInfo);
// 配送方式:门店自提
if (res.data.pickUpStoreId) {
const { data } = await DeliveryApi.getDeliveryPickUpStore(res.data.pickUpStoreId);
systemStore.value = data || {};
}
if (state.orderInfo.deliveryType === 2 && state.orderInfo.payStatus) {
pickUpVerifyRef.value && pickUpVerifyRef.value.markCode(res.data.pickUpVerifyCode);
}
} else {
sheep.$router.back();
}
@@ -429,7 +451,7 @@
color: rgba(#fff, 0.9);
width: 100%;
background: v-bind(headerBg) no-repeat,
linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
background-size: 750rpx 100%;
box-sizing: border-box;
+2 -2
View File
@@ -12,7 +12,7 @@
</swiper>
</uni-swiper-dot>
<view class="log-card-msg">
<!-- TODO 芋艿优化点展示状态 -->
<!-- TODO 芋艿物流优化点展示状态 -->
<!-- <view class="ss-flex ss-m-b-8">-->
<!-- <view>物流状态</view>-->
<!-- <view class="warning-color">{{ state.info.status_text }}</view>-->
@@ -34,7 +34,7 @@
<view v-if="state.tracks.length - 1 !== index" class="line" />
</view>
<view class="log-content-msg">
<!-- TODO 芋艿优化点展示状态 -->
<!-- TODO 芋艿物流优化点展示状态 -->
<!-- <view class="log-msg-title ss-m-b-20">-->
<!-- {{ item.status_text }}-->
<!-- </view>-->
+261
View File
@@ -0,0 +1,261 @@
<template>
<view class='order-details'>
<!-- 自提商品核销 -->
<view v-if="orderInfo.deliveryType === 2 && orderInfo.payStatus" class="writeOff borRadius14">
<view class="title">核销信息</view>
<view class="grayBg flex-center">
<view class="pictrue">
<image
v-if="!!painterImageUrl"
:src="painterImageUrl"
:style="{width: `${state.qrcodeSize}px`, height: `${state.qrcodeSize}px`}"
:show-menu-by-longpress="true"
/>
</view>
</view>
<view class="gear">
<image :src="sheep.$url.static('/static/images/writeOff.png', 'local')"></image>
</view>
<view class="num">{{ orderInfo.pickUpVerifyCode }}</view>
<view class="rules">
<!-- TODO puhui999: 需要后端放回使用 receiveTime 即可 -->
<!-- <view class="item">-->
<!-- <view class="rulesTitle flex flex-wrap align-center">-->
<!-- 核销时间-->
<!-- </view>-->
<!-- <view class="info">-->
<!-- 每日-->
<!-- <text class="time">2020-2-+52</text>-->
<!-- </view>-->
<!-- </view>-->
<view class="item">
<view class="rulesTitle flex flex-wrap align-center">
<text class="iconfont icon-shuoming1"></text>
使用说明
</view>
<view class="info">可将二维码出示给店员扫描或提供数字核销码</view>
</view>
</view>
</view>
<view v-if="orderInfo.deliveryType === 2" class="map flex flex-wrap align-center ss-row-between borRadius14">
<view>自提地址信息</view>
<view class="place cart-color flex flex-wrap flex-center" @tap="showMaoLocation">
查看位置
</view>
</view>
<!-- 海报画板默认隐藏只用来生成海报生成方式为主动调用 -->
<l-painter
v-if="showPainter"
isCanvasToTempFilePath
pathType="url"
@success="setPainterImageUrl"
hidden
ref="painterRef"
/>
</view>
</template>
<script setup>
import sheep from '@/sheep';
import { reactive, ref } from 'vue';
const props = defineProps({
orderInfo: {
type: Object,
default() {},
},
systemStore:{
type: Object,
default() {},
}
});
const state = reactive({
qrcodeSize: 145
})
/**
* 打开地图
*/
const showMaoLocation = () => {
console.log(props.systemStore);
if (!props.systemStore.latitude || !props.systemStore.longitude) {
sheep.$helper.toast('缺少经纬度信息无法查看地图!');
return
}
uni.openLocation({
latitude: props.systemStore.latitude,
longitude: props.systemStore.longitude,
scale: 8,
name: props.systemStore.name,
address: props.systemStore.areaName + props.systemStore.detailAddress,
});
}
/**
* 拨打电话
*/
const makePhone = () => {
uni.makePhoneCall({
phoneNumber: props.systemStore.phone
})
}
const painterRef = ref(); // 海报画板
const painterImageUrl = ref(); // 海报 url
const showPainter = ref(true)
// 渲染海报
const renderPoster = async (poster) => {
await painterRef.value.render(poster);
};
// 获得生成的图片
const setPainterImageUrl = (path) => {
painterImageUrl.value = path;
showPainter.value = false
};
/**
* 生成核销二维码
*/
const markCode = (text) => {
renderPoster({
css: {
width: `${state.qrcodeSize}px`,
height: `${state.qrcodeSize}px`
},
views:[
{
type: 'qrcode',
text: text,
css: {
width: `${state.qrcodeSize}px`,
height: `${state.qrcodeSize}px`
}
}
]
})
}
defineExpose({
markCode
})
</script>
<style scoped lang="scss">
// TODO puhui999: 样式需要调整有 bug
.borRadius14 {
border-radius: 14rpx !important;
}
.cart-color {
color: #E93323 !important;
border: 1px solid #E93323 !important
}
.order-details{
border-radius: 10rpx;
margin: 0 20rpx 20rpx 20rpx;
}
.order-details .writeOff {
background-color: #fff;
margin-top: 15rpx;
padding-bottom: 50rpx;
}
.order-details .writeOff .title {
font-size: 30rpx;
color: #282828;
height: 87rpx;
border-bottom: 1px solid #f0f0f0;
padding: 0 24rpx;
line-height: 87rpx;
}
.order-details .writeOff .grayBg {
background-color: #f2f5f7;
width: 590rpx;
height: 384rpx;
border-radius: 20rpx 20rpx 0 0;
margin: 50rpx auto 0 auto;
padding-top: 55rpx;
}
.order-details .writeOff .grayBg .pictrue {
width: 290rpx;
height: 290rpx;
}
.order-details .writeOff .grayBg .pictrue image {
width: 100%;
height: 100%;
}
.order-details .writeOff .gear {
width: 590rpx;
height: 30rpx;
margin: 0 auto;
}
.order-details .writeOff .gear image {
width: 100%;
height: 100%;
}
.order-details .writeOff .num {
background-color: #f0c34c;
width: 590rpx;
height: 84rpx;
color: #282828;
font-size: 48rpx;
margin: 0 auto;
border-radius: 0 0 20rpx 20rpx;
text-align: center;
padding-top: 4rpx;
}
.order-details .writeOff .rules {
margin: 46rpx 30rpx 0 30rpx;
border-top: 1px solid #f0f0f0;
padding-top: 10rpx;
}
.order-details .writeOff .rules .item {
margin-top: 20rpx;
}
.order-details .writeOff .rules .item .rulesTitle {
font-size: 28rpx;
color: #282828;
}
.order-details .writeOff .rules .item .rulesTitle .iconfont {
font-size: 30rpx;
color: #333;
margin-right: 8rpx;
margin-top: 5rpx;
}
.order-details .writeOff .rules .item .info {
font-size: 28rpx;
color: #999;
margin-top: 7rpx;
}
.order-details .writeOff .rules .item .info .time {
margin-left: 20rpx;
}
.order-details .map {
height: 86rpx;
font-size: 30rpx;
color: #282828;
line-height: 86rpx;
border-bottom: 1px solid #f0f0f0;
margin-top: 15rpx;
background-color: #fff;
padding: 0 24rpx;
}
.order-details .map .place {
font-size: 26rpx;
width: 176rpx;
height: 50rpx;
border-radius: 25rpx;
line-height: 50rpx;
text-align: center;
}
</style>
+6
View File
@@ -174,6 +174,12 @@
return
}
state.payMethods = getPayMethods(data)
state.payMethods.find(item => {
if (item.value && !item.disabled) {
state.payment = item.value;
return true;
}
});
}
onLoad((options) => {
-1
View File
@@ -39,7 +39,6 @@
<button class="check-btn ss-reset-button" v-if="payResult === 'success'" @tap="onOrder">
查看订单
</button>
<!-- TODO 芋艿拼团接入 -->
<button
class="check-btn ss-reset-button"
v-if="payResult === 'success' && state.tradeOrder.type === 3"
+1 -1
View File
@@ -49,7 +49,7 @@
}
}
onLoad(() => {
// TODO 芋艿:目前简单做,使用营销文章,作为 faq
// TODO 芋艿:【文章】目前简单做,使用营销文章,作为 faq
if (true) {
sheep.$router.go('/pages/public/richtext', {
title: '常见问题',
+12 -3
View File
@@ -39,8 +39,8 @@
</template>
<script setup>
import { reactive, onBeforeMount } from 'vue';
import { onShow } from '@dcloudio/uni-app';
import { onBeforeMount, reactive } from 'vue';
import { onShow, onLoad } from '@dcloudio/uni-app';
import sheep from '@/sheep';
import { isEmpty } from 'lodash-es';
import AreaApi from '@/sheep/api/system/area';
@@ -49,10 +49,14 @@
const state = reactive({
list: [], // 地址列表
loading: true,
openType: '', // 页面打开类型
});
// 选择收货地址
const onSelect = (addressInfo) => {
if (state.openType !== 'select'){ // 不作为选择组件时阻断操作
return
}
uni.$emit('SELECT_ADDRESS', {
addressInfo,
});
@@ -60,7 +64,6 @@
};
// 导入微信地址
// TODO 芋艿:未测试
function importWechatAddress() {
let wechatAddress = {};
// #ifdef MP
@@ -110,6 +113,12 @@
// #endif
}
onLoad((option) => {
if (option.type) {
state.openType = option.type;
}
});
onShow(async () => {
state.list = (await AddressApi.getAddressList()).data;
state.loading = false;
+282
View File
@@ -0,0 +1,282 @@
<template>
<s-layout title="选择自提门店" :bgStyle="{ color: '#FFF' }">
<view class="storeBox" ref="container">
<view
class="storeBox-box"
v-for="(item, index) in state.storeList"
:key="index"
@tap="checked(item)"
>
<view class="store-img">
<image :src="item.logo" class="img" />
</view>
<view class="store-cent-left">
<view class="store-name">{{ item.name }}</view>
<view class="store-address line1">
{{ item.areaName }}{{ ', ' + item.detailAddress }}
</view>
</view>
<view class="row-right ss-flex-col ss-col-center">
<view>
<!-- #ifdef H5 -->
<a class="store-phone" :href="'tel:' + item.phone">
<view class="iconfont">
<view class="ss-rest-button">
<text class="_icon-forward" />
</view>
</view>
</a>
<!-- #endif -->
<!-- #ifdef MP -->
<view class="store-phone" @click="call(item.phone)">
<view class="iconfont">
<view class="ss-rest-button">
<text class="_icon-forward" />
</view>
</view>
</view>
<!-- #endif -->
</view>
<view class="store-distance ss-flex ss-row-center" @tap.stop="showMaoLocation(item)">
<text class="addressTxt" v-if="item.distance">
距离{{ item.distance.toFixed(2) }}千米
</text>
<text class="addressTxt" v-else>查看地图</text>
<view class="iconfont">
<view class="ss-rest-button">
<text class="_icon-forward" />
</view>
</view>
</view>
</view>
</view>
</view>
</s-layout>
</template>
<script setup>
import DeliveryApi from '@/sheep/api/trade/delivery';
import { onMounted, reactive } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import sheep from '@/sheep';
const LONGITUDE = 'user_longitude';
const LATITUDE = 'user_latitude';
const state = reactive({
loaded: false,
loading: false,
storeList: [],
system_store: {},
locationShow: false,
user_latitude: 0,
user_longitude: 0,
});
const call = (phone) => {
uni.makePhoneCall({
phoneNumber: phone,
});
};
const selfLocation = () => {
// #ifdef H5
const jsWxSdk = sheep.$platform.useProvider('wechat').jsWxSdk;
if (jsWxSdk.isWechat()) {
jsWxSdk.getLocation((res) => {
state.user_latitude = res.latitude;
state.user_longitude = res.longitude;
uni.setStorageSync(LATITUDE, res.latitude);
uni.setStorageSync(LONGITUDE, res.longitude);
getList();
});
} else {
// #endif
uni.getLocation({
type: 'gcj02',
success: (res) => {
try {
state.user_latitude = res.latitude;
state.user_longitude = res.longitude;
uni.setStorageSync(LATITUDE, res.latitude);
uni.setStorageSync(LONGITUDE, res.longitude);
} catch (e) {
console.error(e);
}
getList();
},
complete: () => {
getList();
},
});
// #ifdef H5
}
// #endif
};
const showMaoLocation = (e) => {
// #ifdef H5
const jsWxSdk = sheep.$platform.useProvider('wechat').jsWxSdk;
if (jsWxSdk.isWechat()) {
jsWxSdk.openLocation({
latitude: Number(e.latitude),
longitude: Number(e.longitude),
name: e.name,
address: `${e.areaName}-${e.detailAddress}`,
});
} else {
// #endif
uni.openLocation({
latitude: Number(e.latitude),
longitude: Number(e.longitude),
name: e.name,
address: `${e.areaName}-${e.detailAddress}`,
success: function () {
console.log('success');
},
});
// #ifdef H5
}
// #endif
};
/**
* 选中门店
*/
const checked = (addressInfo) => {
uni.$emit('SELECT_PICK_UP_INFO', {
addressInfo,
});
sheep.$router.back();
};
/**
* 获取门店列表数据
*/
const getList = async () => {
if (state.loading || state.loaded) {
return;
}
state.loading = true;
const { data, code } = await DeliveryApi.getDeliveryPickUpStoreList({
latitude: state.user_latitude,
longitude: state.user_longitude,
});
if (code !== 0) {
return;
}
state.loading = false;
state.storeList = data;
};
onMounted(() => {
if (state.user_latitude && state.user_longitude) {
getList();
} else {
selfLocation();
getList();
}
});
onLoad(() => {
try {
state.user_latitude = uni.getStorageSync(LATITUDE);
state.user_longitude = uni.getStorageSync(LONGITUDE);
} catch (e) {
console.error(e);
}
});
</script>
<style lang="scss" scoped>
.line1 {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.geoPage {
position: fixed;
width: 100%;
height: 100%;
top: 0;
z-index: 10000;
}
.storeBox {
width: 100%;
background-color: #fff;
padding: 0 30rpx;
}
.storeBox-box {
width: 100%;
height: auto;
display: flex;
align-items: center;
padding: 23rpx 0;
justify-content: space-between;
border-bottom: 1px solid #eee;
}
.store-cent {
display: flex;
align-items: center;
width: 80%;
}
.store-cent-left {
//width: 45%;
flex: 2;
}
.store-img {
flex: 1;
width: 120rpx;
height: 120rpx;
border-radius: 6rpx;
margin-right: 22rpx;
}
.store-img .img {
width: 100%;
height: 100%;
}
.store-name {
color: #282828;
font-size: 30rpx;
margin-bottom: 22rpx;
font-weight: 800;
}
.store-address {
color: #666666;
font-size: 24rpx;
}
.store-phone {
width: 50rpx;
height: 50rpx;
color: #fff;
border-radius: 50%;
display: block;
text-align: center;
line-height: 48rpx;
background-color: #e83323;
margin-bottom: 22rpx;
text-decoration: none;
}
.store-distance {
font-size: 22rpx;
color: #e83323;
}
.iconfont {
font-size: 20rpx;
}
.row-right {
flex: 2;
//display: flex;
//flex-direction: column;
//align-items: flex-end;
//width: 33.5%;
}
</style>
+1 -1
View File
@@ -36,7 +36,7 @@
</button>
</uni-datetime-picker>
<!-- TODO 芋艿优化 -->
<!-- TODO 芋艿钱包优化 -->
<!-- <view class="total-box">-->
<!-- <view class="ss-m-b-10">总收入{{ state.pagination.income }}</view>-->
<!-- <view>总支出{{ -state.pagination.expense }}</view>-->