依据文档修改

pull/27/head
落日晚风 2023-12-13 17:42:12 +08:00
parent 98baaab9bc
commit e71091cbb0
9 changed files with 1354 additions and 1310 deletions

View File

@ -33,7 +33,7 @@
// #endif // #endif
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
// //
console.log(options, 'options'); console.log(options, 'options');
// #endif // #endif

View File

@ -1,512 +1,532 @@
<!-- 页面 --> <!-- 页面 -->
<template> <template>
<s-layout title="签到有礼"> <s-layout title="签到有礼">
<view v-if="state.loading"></view> <view v-if="state.loading"></view>
<view class="sign-wrap" v-else-if="state.data && !state.loading"> <view class="sign-wrap" v-else-if="state.data && !state.loading">
<!-- 签到日历 --> <!-- 签到日历 -->
<view class="content-box calendar"> <view class="content-box calendar">
<view class="sign-everyday ss-flex ss-col-center ss-row-between ss-p-x-30"> <view class="sign-everyday ss-flex ss-col-center ss-row-between ss-p-x-30">
<text class="sign-everyday-title">签到日历</text> <text class="sign-everyday-title">签到日历</text>
<view class="sign-num-box"> <view class="sign-num-box">
已连续签到 已连续签到
<text class="sign-num">{{ state.continue_days }}</text> <text class="sign-num">{{ state.continue_days }}</text>
</view> </view>
</view> </view>
<!-- 切换年月 --> <!-- 切换年月 -->
<view class="bar ss-flex ss-col-center ss-row-center"> <view class="bar ss-flex ss-col-center ss-row-center">
<view class="previous" @tap="handleCalendar(0)"><text class="cicon-back"></text></view> <view class="previous" @tap="handleCalendar(0)"><text class="cicon-back"></text></view>
<view class="date ss-m-x-20">{{ state.cur_year || '--' }} {{ state.cur_month || '--' }} </view> <view class="date ss-m-x-20">{{ state.cur_year || '--' }} {{ state.cur_month || '--' }} </view>
<view class="next" @tap="handleCalendar(1)"><text class="cicon-forward"></text></view> <view class="next" @tap="handleCalendar(1)"><text class="cicon-forward"></text></view>
</view> </view>
<!-- 显示星期 --> <!-- 显示星期 -->
<view class="week ss-flex"> <view class="week ss-flex">
<view class="week-item ss-flex ss-row-center" v-for="(item, index) in state.weeks_ch" :key="index"> <view class="week-item ss-flex ss-row-center" v-for="(item, index) in state.weeks_ch" :key="index">
{{ item.title }} {{ item.title }}
</view> </view>
</view> </view>
<!-- 日历表 --> <!-- 日历表 -->
<view class="myDateTable"> <view class="myDateTable">
<view v-for="(item, j) in state.data.days" :key="j" class="dateCell ss-flex ss-row-center ss-col-center"> <view v-for="(item, j) in state.data.days" :key="j"
<!-- 空格 --> class="dateCell ss-flex ss-row-center ss-col-center">
<view class="ss-flex ss-row-center ss-col-center"> <!-- 空格 -->
<text :decode="true">&nbsp;&nbsp;</text> <view class="ss-flex ss-row-center ss-col-center">
</view> <text :decode="true">&nbsp;&nbsp;</text>
<view> </view>
<!-- 已签到日期 --> <view>
<view v-if="item.is_sign" class="is-sign ss-flex ss-row-center"> <!-- 已签到日期 -->
<view class="is-sign-num">{{ item.day < 10 ? '0' + item.day : item.day }}</view> <view v-if="item.is_sign" class="is-sign ss-flex ss-row-center">
<image class="is-sign-image" :src="sheep.$url.static('/static/img/shop/app/correct.png')"> <view class="is-sign-num">{{ item.day < 10 ? '0' + item.day : item.day }}</view>
</image> <image class="is-sign-image"
</view> :src="sheep.$url.static('/static/img/shop/app/correct.png')">
<!-- 未签到日期 --> </image>
<view class="is-sign ss-flex ss-row-center" v-if="item.is_replenish == 1" </view>
@tap="onShowRetroactive(item.date)"> <!-- 未签到日期 -->
<view class="cell-num">{{ item.day < 10 ? '0' + item.day : item.day }}</view> <view class="is-sign ss-flex ss-row-center" v-if="item.is_replenish == 1"
<text class="cicon-title"></text> @tap="onShowRetroactive(item.date)">
</view> <view class="cell-num">{{ item.day < 10 ? '0' + item.day : item.day }}</view>
<view class="is-sign ss-flex ss-row-center" v-if="item.is_replenish == 0 && !item.is_sign"> <text class="cicon-title"></text>
<view class="cell-num">{{ item.day < 10 ? '0' + item.day : item.day }}</view> </view>
</view> <view class="is-sign ss-flex ss-row-center" v-if="item.is_replenish == 0 && !item.is_sign">
</view> <view class="cell-num">{{ item.day < 10 ? '0' + item.day : item.day }}</view>
</view> </view>
</view>
</view>
<!-- 签到按钮 --> <!-- 签到按钮 -->
<view class="ss-flex ss-col-center ss-row-center sign-box ss-m-y-40"> <view class="ss-flex ss-col-center ss-row-center sign-box ss-m-y-40">
<button class="ss-reset-button sign-btn" v-if="state.isSign === 0" @tap="onSign"></button> <button class="ss-reset-button sign-btn" v-if="state.isSign === 0" @tap="onSign"></button>
<button class="ss-reset-button already-btn" v-if="state.isSign === 1" disabled>已签到</button> <button class="ss-reset-button already-btn" v-if="state.isSign === 1" disabled>已签到</button>
</view> </view>
</view> </view>
</view> </view>
<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"> <view class="activity-des">
1每日签到固定 {{ state.data.rules.everyday }} 积分 1每日签到固定 {{ state.data.rules.everyday }} 积分
<text v-if="state.data.rules.is_inc == '1'"> <text v-if="state.data.rules.is_inc == '1'">
次日递增奖励 {{ state.data.rules.inc_num }} 积分直到 次日递增奖励 {{ state.data.rules.inc_num }} 积分直到
{{ state.data.rules.until_day }} 天之后不再增加 {{ state.data.rules.until_day }} 天之后不再增加
</text> </text>
</view> </view>
<view class="activity-des" v-if="state.data.rules.discounts?.length > 0"> <view class="activity-des" v-if="state.data.rules.discounts?.length > 0">
2<text class="" v-for="i in state.data.rules.discounts" :key="i"> 2<text class="" v-for="i in state.data.rules.discounts" :key="i">
连续签到 {{ i.full }} 奖励 {{ i.value }} 积分 连续签到 {{ i.full }} 奖励 {{ i.value }} 积分
</text> </text>
</view> </view>
<view class="activity-des" v-if="state.data.rules.is_replenish == '1'"> <view class="activity-des" v-if="state.data.rules.is_replenish == '1'">
{{ state.data.rules.discounts?.length > 0 ? '3' : '2' }}用户在 {{ state.data.rules.discounts?.length > 0 ? '3' : '2' }}用户在
{{ state.data.rules.replenish_limit }} 天内可补签 {{ state.data.rules.replenish_limit }} 天内可补签
{{ state.data.rules.replenish_days }} 每次补签消耗 {{ state.data.rules.replenish_days }} 每次补签消耗
{{ state.data.rules.replenish_num }}积分 {{ state.data.rules.replenish_num }}积分
</view> </view>
</view> </view>
</view> </view>
<s-empty v-else-if="!state.data && !state.loading" icon="/static/data-empty.png" text="签到活动还未开始"> <s-empty v-else-if="!state.data && !state.loading" icon="/static/data-empty.png" text="签到活动还未开始">
</s-empty> </s-empty>
<su-popup :show="state.showModel" type="center" round="10" :isMaskClick="false"> <su-popup :show="state.showModel" type="center" round="10" :isMaskClick="false">
<view class="model-box ss-flex-col"> <view class="model-box ss-flex-col">
<view class="ss-m-t-56 ss-flex-col ss-col-center"> <view class="ss-m-t-56 ss-flex-col ss-col-center">
<text class="cicon-check-round"></text> <text class="cicon-check-round"></text>
<view class="score-title">{{ state.signin.score }}积分</view> <view class="score-title">{{ state.signin.score }}积分</view>
<view class="model-title ss-flex ss-col-center ss-m-t-22 ss-m-b-30"> <view class="model-title ss-flex ss-col-center ss-m-t-22 ss-m-b-30">
已连续打卡{{ state.continue_days }} 已连续打卡{{ state.continue_days }}
</view> </view>
</view> </view>
<view class="model-bg ss-flex-col ss-col-center ss-row-right"> <view class="model-bg ss-flex-col ss-col-center ss-row-right">
<view class="title ss-m-b-64">签到成功</view> <view class="title ss-m-b-64">签到成功</view>
<view class="ss-m-b-40"> <view class="ss-m-b-40">
<button class="ss-reset-button confirm-btn" @tap="onConfirm"></button> <button class="ss-reset-button confirm-btn" @tap="onConfirm"></button>
</view> </view>
</view> </view>
</view> </view>
</su-popup> </su-popup>
<su-popup :show="state.showRetroactive" type="center" round="10" :isMaskClick="false"> <su-popup :show="state.showRetroactive" type="center" round="10" :isMaskClick="false">
<view class="model-box ss-flex-col"> <view class="model-box ss-flex-col">
<view class="ss-m-t-56 ss-flex-col ss-col-center"> <view class="ss-m-t-56 ss-flex-col ss-col-center">
<text class="cicon-check-round"></text> <text class="cicon-check-round"></text>
<view class="score-title">消耗{{ state.data?.rules.replenish_num }}积分</view> <view class="score-title">消耗{{ state.data?.rules.replenish_num }}积分</view>
<view class="model-title ss-flex ss-col-center ss-m-t-22 ss-m-b-30"> <view class="model-title ss-flex ss-col-center ss-m-t-22 ss-m-b-30">
已连续打卡{{ state.continue_days }} 已连续打卡{{ state.continue_days }}
</view> </view>
</view> </view>
<view class="model-bg ss-flex-col ss-col-center ss-row-right"> <view class="model-bg ss-flex-col ss-col-center ss-row-right">
<view class="title ss-m-b-64">确认补签</view> <view class="title ss-m-b-64">确认补签</view>
<view class="ss-m-b-40 ss-flex"> <view class="ss-m-b-40 ss-flex">
<button class="ss-reset-button cancel-btn" @tap="state.showRetroactive = false">取消</button> <button class="ss-reset-button cancel-btn" @tap="state.showRetroactive = false">取消</button>
<button class="ss-reset-button confirm-btn" @tap="onRetroactive"></button> <button class="ss-reset-button confirm-btn" @tap="onRetroactive"></button>
</view> </view>
</view> </view>
</view> </view>
</su-popup> </su-popup>
</s-layout> </s-layout>
</template> </template>
<script setup> <script setup>
import sheep from '@/sheep'; import sheep from '@/sheep';
import { onLoad, onReady } from '@dcloudio/uni-app'; import {
import { computed, reactive } from 'vue'; onLoad,
onReady
} from '@dcloudio/uni-app';
import {
computed,
reactive
} from 'vue';
const headerBg = sheep.$url.css('/static/img/shop/app/sign.png'); const headerBg = sheep.$url.css('/static/img/shop/app/sign.png');
const state = reactive({ const state = reactive({
data: { data: {
days: [], // days: [], //
rules: {}, // rules: {}, //
}, },
cur_year: 0, // cur_year: 0, //
cur_month: 0, // cur_month: 0, //
cur_day: 0, // cur_day: 0, //
weeks_ch: [ weeks_ch: [{
{ title: '日',
title: '日', value: '0',
value: '0', },
}, {
{ title: '一',
title: '一', value: '1',
value: '1', },
}, {
{ title: '二',
title: '二', value: '2',
value: '2', },
}, {
{ title: '三',
title: '三', value: '3',
value: '3', },
}, {
{ title: '四',
title: '四', value: '4',
value: '4', },
}, {
{ title: '五',
title: '五', value: '5',
value: '5', },
}, {
{ title: '六',
title: '六', value: '6',
value: '6', },
}, ], //
], // showModel: false, //
showModel: false, // continue_days: 0, //
continue_days: 0, // signin: {}, //
signin: {}, // showRetroactive: false, //
showRetroactive: false, // date: '', //
date: '', // isSign: 0, //
isSign: 0, // loading: true,
loading: true, });
}); async function onSign() {
async function onSign() { //
const { error, data } = await sheep.$api.activity.signAdd(); const {
if (error === 0) { code: error,
state.showModel = true; data
state.signin = data; } = await sheep.$api.activity.signAdd();
// getData(); if (error === 0) {
} state.showModel = true;
} state.signin = data;
// getData();
}
}
function onShowRetroactive(e) { function onShowRetroactive(e) {
state.showRetroactive = true; state.showRetroactive = true;
state.date = e; state.date = e;
} }
// //
function onConfirm() { function onConfirm() {
state.showModel = false; state.showModel = false;
getData(); getData();
} }
// //
async function onRetroactive() { async function onRetroactive() {
const { error, data } = await sheep.$api.activity.replenish({ const {
date: state.date, error,
}); data
if (error === 0) { } = await sheep.$api.activity.replenish({
state.showRetroactive = false; date: state.date,
getData(); });
} if (error === 0) {
} state.showRetroactive = false;
getData();
}
}
async function getData(mouth) { async function getData(mouth) {
const { error, data } = await sheep.$api.activity.signList(mouth); const {
if (error === 0) { error,
state.data = data; data
} else { } = await sheep.$api.activity.signList(mouth);
state.data = null; //
} const ren = await sheep.$api.activity.getSummary();
state.loading = false; if (error === 0) {
if (state.data) { state.data = data;
state.data.days.forEach((i, index) => { } else {
if (index < i.week) { state.data = null;
index++; }
var obj = { state.loading = false;
day: null, if (state.data) {
is_sign: false, state.data.days.forEach((i, index) => {
}; if (index < i.week) {
state.data.days.unshift(obj); index++;
} var obj = {
if (index == 1) { day: null,
let arr = i.date.split('-'); is_sign: false,
state.cur_year = arr[0]; };
state.cur_month = arr[1]; state.data.days.unshift(obj);
} }
}); if (index == 1) {
if (state.data.days[0].day == null) { let arr = i.date.split('-');
state.data.days.forEach((i, index) => { state.cur_year = arr[0];
if (i.current == 'today') { state.cur_month = arr[1];
state.isSign = i.is_sign; }
} });
}); if (state.data.days[0].day == null) {
} state.data.days.forEach((i, index) => {
state.continue_days = data.continue_days; if (i.current == 'today') {
} state.isSign = i.is_sign;
} }
});
}
state.isSign = ren.data.todaySignIn ? 1 : 0;
state.continue_days = ren.data.continuousDay;
}
}
onReady(() => { onReady(() => {
getData(); getData();
}); });
// //
const handleCalendar = (type) => { const handleCalendar = (type) => {
const cur_year = parseInt(state.cur_year); const cur_year = parseInt(state.cur_year);
const cur_month = parseInt(state.cur_month); const cur_month = parseInt(state.cur_month);
var newMonth; var newMonth;
var newYear = cur_year; var newYear = cur_year;
if (type === 0) { if (type === 0) {
// //
newMonth = cur_month - 1; newMonth = cur_month - 1;
if (newMonth < 1) { if (newMonth < 1) {
newYear = cur_year - 1; newYear = cur_year - 1;
newMonth = 12; newMonth = 12;
} else if (newMonth < 10) { } else if (newMonth < 10) {
newMonth = '0' + newMonth; newMonth = '0' + newMonth;
} }
} else { } else {
newMonth = cur_month + 1; newMonth = cur_month + 1;
if (newMonth > 12) { if (newMonth > 12) {
newYear = cur_year + 1; newYear = cur_year + 1;
newMonth = 1; newMonth = 1;
} else if (newMonth < 10) { } else if (newMonth < 10) {
newMonth = '0' + newMonth; newMonth = '0' + newMonth;
} }
} }
getData({ getData({
month: newYear + '-' + newMonth, month: newYear + '-' + newMonth,
}); });
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.header-box { .header-box {
border-top: 2rpx solid rgba(#dfdfdf, 0.5); border-top: 2rpx solid rgba(#dfdfdf, 0.5);
} }
// //
.calendar { .calendar {
background: #fff; background: #fff;
.sign-everyday { .sign-everyday {
height: 100rpx; height: 100rpx;
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
border: 2rpx solid rgba(223, 223, 223, 0.4); border: 2rpx solid rgba(223, 223, 223, 0.4);
.sign-everyday-title { .sign-everyday-title {
font-size: 32rpx; font-size: 32rpx;
color: rgba(51, 51, 51, 1); color: rgba(51, 51, 51, 1);
font-weight: 500; font-weight: 500;
} }
.sign-num-box { .sign-num-box {
font-size: 26rpx; font-size: 26rpx;
font-weight: 500; font-weight: 500;
color: rgba(153, 153, 153, 1); color: rgba(153, 153, 153, 1);
.sign-num { .sign-num {
font-size: 30rpx; font-size: 30rpx;
font-weight: 600; font-weight: 600;
color: #ff6000; color: #ff6000;
padding: 0 10rpx; padding: 0 10rpx;
font-family: OPPOSANS; font-family: OPPOSANS;
} }
} }
} }
// //
.bar { .bar {
height: 100rpx; height: 100rpx;
.date { .date {
font-size: 30rpx; font-size: 30rpx;
font-family: OPPOSANS; font-family: OPPOSANS;
font-weight: 500; font-weight: 500;
color: #333333; color: #333333;
line-height: normal; line-height: normal;
} }
} }
.cicon-back { .cicon-back {
margin-top: 6rpx; margin-top: 6rpx;
font-size: 30rpx; font-size: 30rpx;
color: #c4c4c4; color: #c4c4c4;
line-height: normal; line-height: normal;
} }
.cicon-forward { .cicon-forward {
margin-top: 6rpx; margin-top: 6rpx;
font-size: 30rpx; font-size: 30rpx;
color: #c4c4c4; color: #c4c4c4;
line-height: normal; line-height: normal;
} }
// //
.week { .week {
.week-item { .week-item {
font-size: 24rpx; font-size: 24rpx;
font-weight: 500; font-weight: 500;
color: rgba(153, 153, 153, 1); color: rgba(153, 153, 153, 1);
flex: 1; flex: 1;
} }
} }
// //
.myDateTable { .myDateTable {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
.dateCell { .dateCell {
width: calc(750rpx / 7); width: calc(750rpx / 7);
height: 80rpx; height: 80rpx;
font-size: 26rpx; font-size: 26rpx;
font-weight: 400; font-weight: 400;
color: rgba(51, 51, 51, 1); color: rgba(51, 51, 51, 1);
} }
} }
} }
.is-sign { .is-sign {
width: 48rpx; width: 48rpx;
height: 48rpx; height: 48rpx;
position: relative; position: relative;
.is-sign-num { .is-sign-num {
font-size: 24rpx; font-size: 24rpx;
font-family: OPPOSANS; font-family: OPPOSANS;
font-weight: 500; font-weight: 500;
line-height: normal; line-height: normal;
} }
.is-sign-image { .is-sign-image {
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
width: 48rpx; width: 48rpx;
height: 48rpx; height: 48rpx;
} }
} }
.cell-num { .cell-num {
font-size: 24rpx; font-size: 24rpx;
font-family: OPPOSANS; font-family: OPPOSANS;
font-weight: 500; font-weight: 500;
color: #333333; color: #333333;
line-height: normal; line-height: normal;
} }
.cicon-title { .cicon-title {
position: absolute; position: absolute;
right: -10rpx; right: -10rpx;
top: -6rpx; top: -6rpx;
font-size: 20rpx; font-size: 20rpx;
color: red; color: red;
} }
// //
.sign-box { .sign-box {
height: 140rpx; height: 140rpx;
width: 100%; width: 100%;
.sign-btn { .sign-btn {
width: 710rpx; width: 710rpx;
height: 80rpx; height: 80rpx;
border-radius: 35rpx; border-radius: 35rpx;
font-size: 30rpx; font-size: 30rpx;
font-weight: 500; font-weight: 500;
box-shadow: 0 0.2em 0.5em rgba(#ff6000, 0.4); box-shadow: 0 0.2em 0.5em rgba(#ff6000, 0.4);
background: linear-gradient(90deg, #ff6000, #fe832a); background: linear-gradient(90deg, #ff6000, #fe832a);
color: #fff; color: #fff;
} }
.already-btn { .already-btn {
width: 710rpx; width: 710rpx;
height: 80rpx; height: 80rpx;
border-radius: 35rpx; border-radius: 35rpx;
font-size: 30rpx; font-size: 30rpx;
font-weight: 500; font-weight: 500;
} }
} }
.model-box { .model-box {
width: 520rpx; width: 520rpx;
// height: 590rpx; // height: 590rpx;
background: linear-gradient(177deg, #ff6000 0%, #fe832a 100%); background: linear-gradient(177deg, #ff6000 0%, #fe832a 100%);
// background: linear-gradient(177deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient)); // background: linear-gradient(177deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
border-radius: 10rpx; border-radius: 10rpx;
.cicon-check-round { .cicon-check-round {
font-size: 70rpx; font-size: 70rpx;
color: #fff; color: #fff;
} }
.score-title { .score-title {
font-size: 34rpx; font-size: 34rpx;
font-family: OPPOSANS; font-family: OPPOSANS;
font-weight: 500; font-weight: 500;
color: #fcff00; color: #fcff00;
} }
.model-title { .model-title {
font-size: 28rpx; font-size: 28rpx;
font-weight: 500; font-weight: 500;
color: #ffffff; color: #ffffff;
} }
.model-bg { .model-bg {
width: 520rpx; width: 520rpx;
height: 344rpx; height: 344rpx;
background-size: 100% 100%; background-size: 100% 100%;
background-image: v-bind(headerBg); background-image: v-bind(headerBg);
background-repeat: no-repeat; background-repeat: no-repeat;
border-radius: 0 0 10rpx 10rpx; border-radius: 0 0 10rpx 10rpx;
.title { .title {
font-size: 34rpx; font-size: 34rpx;
font-weight: bold; font-weight: bold;
// color: var(--ui-BG-Main); // color: var(--ui-BG-Main);
color: #ff6000; color: #ff6000;
} }
.subtitle { .subtitle {
font-size: 26rpx; font-size: 26rpx;
font-weight: 500; font-weight: 500;
color: #999999; color: #999999;
} }
.cancel-btn { .cancel-btn {
width: 220rpx; width: 220rpx;
height: 70rpx; height: 70rpx;
border: 2rpx solid #ff6000; border: 2rpx solid #ff6000;
border-radius: 35rpx; border-radius: 35rpx;
font-size: 28rpx; font-size: 28rpx;
font-weight: 500; font-weight: 500;
color: #ff6000; color: #ff6000;
line-height: normal; line-height: normal;
margin-right: 10rpx; margin-right: 10rpx;
} }
.confirm-btn { .confirm-btn {
width: 220rpx; width: 220rpx;
height: 70rpx; height: 70rpx;
background: linear-gradient(90deg, #ff6000, #fe832a); background: linear-gradient(90deg, #ff6000, #fe832a);
box-shadow: 0 0.2em 0.5em rgba(#ff6000, 0.4); box-shadow: 0 0.2em 0.5em rgba(#ff6000, 0.4);
border-radius: 35rpx; border-radius: 35rpx;
font-size: 28rpx; font-size: 28rpx;
font-weight: 500; font-weight: 500;
color: #ffffff; color: #ffffff;
line-height: normal; line-height: normal;
} }
} }
} }
// //
.activity-title { .activity-title {
font-size: 32rpx; font-size: 32rpx;
font-weight: 500; font-weight: 500;
color: #333333; color: #333333;
line-height: normal; line-height: normal;
} }
.activity-des { .activity-des {
font-size: 26rpx; font-size: 26rpx;
font-weight: 500; font-weight: 500;
color: #666666; color: #666666;
line-height: 40rpx; line-height: 40rpx;
} }
</style> </style>

View File

@ -13,7 +13,7 @@
<view class="detail-swiper-selector"> <view class="detail-swiper-selector">
<!-- 商品轮播图 --> <!-- 商品轮播图 -->
<su-swiper class="ss-m-b-14" isPreview :list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)" <su-swiper class="ss-m-b-14" isPreview :list="formatGoodsSwiper(state.goodsInfo.sliderPicUrls)"
dotStyle="tag" imageMode="widthFix" dotCur="bg-mask-40" :seizeHeight="750" /> dotStyle="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">
@ -31,16 +31,17 @@
</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">
<!-- 满减送/限时折扣活动的提示 TODO 芋艿promos 未写 --> <!-- 满减送/限时折扣活动的提示 TODO 芋艿promos 未写 -->
<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.goodsInfo.promos" :key="promos.id" @tap="onActivity"> <view class="tag ss-m-r-10" v-for="promos in state.goodsInfo.promos"
:key="promos.id" @tap="onActivity">
{{ promos.title }} {{ promos.title }}
</view> </view>
</view> </view>
</div> </div>
<!-- 优惠劵 --> <!-- 优惠劵 -->
<view class="get-coupon-box ss-flex ss-col-center ss-m-l-20" @tap="state.showModel = true" <view class="get-coupon-box ss-flex ss-col-center ss-m-l-20" @tap="state.showModel = true"
v-if="state.couponInfo.length"> v-if="state.couponInfo.length">
<view class="discounts-title ss-m-r-8">领券</view> <view class="discounts-title ss-m-r-8">领券</view>
@ -54,15 +55,15 @@
<!-- 功能卡片 --> <!-- 功能卡片 -->
<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 v-model="state.selectedSku.goods_sku_text" :sku="state.selectedSku"
@tap="state.showSelectSku = true" /> @tap="state.showSelectSku = true" />
<!-- TODO 芋艿可能暂时不考虑使用 --> <!-- TODO 芋艿可能暂时不考虑使用 -->
<detail-cell-service v-if="state.goodsInfo.service" v-model="state.goodsInfo.service" /> <detail-cell-service v-if="state.goodsInfo.service" v-model="state.goodsInfo.service" />
<detail-cell-params v-if="state.goodsInfo.params" v-model="state.goodsInfo.params" /> <detail-cell-params v-if="state.goodsInfo.params" v-model="state.goodsInfo.params" />
</view> </view>
<!-- 规格与数量弹框 --> <!-- 规格与数量弹框 -->
<s-select-sku :goodsInfo="state.goodsInfo" :show="state.showSelectSku" @addCart="onAddCart" <s-select-sku :goodsInfo="state.goodsInfo" :show="state.showSelectSku" @addCart="onAddCart"
@buy="onBuy" @change="onSkuChange" @close="state.showSelectSku = false" /> @buy="onBuy" @change="onSkuChange" @close="state.showSelectSku = false" />
</view> </view>
<!-- 评价 --> <!-- 评价 -->
@ -88,25 +89,35 @@
</view> </view>
</detail-tabbar> </detail-tabbar>
<!-- 优惠劵弹窗 --> <!-- 优惠劵弹窗 -->
<s-coupon-get v-model="state.couponInfo" :show="state.showModel" @close="state.showModel = false" <s-coupon-get v-model="state.couponInfo" :show="state.showModel" @close="state.showModel = false"
@get="onGet" /> @get="onGet" />
<!-- 满减送/限时折扣活动弹窗 --> <!-- 满减送/限时折扣活动弹窗 -->
<s-activity-pop v-model="state.activityInfo" :show="state.showActivityModel" <s-activity-pop v-model="state.activityInfo" :show="state.showActivityModel"
@close="state.showActivityModel = false" /> @close="state.showActivityModel = false" />
</block> </block>
</s-layout> </s-layout>
</view> </view>
</template> </template>
<script setup> <script setup>
import { reactive, computed } from 'vue'; import {
import { onLoad, onPageScroll } from '@dcloudio/uni-app'; reactive,
computed
} from 'vue';
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 { 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 detailCellService from './components/detail/detail-cell-service.vue'; import detailCellService from './components/detail/detail-cell-service.vue';
@ -116,7 +127,9 @@
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';
onPageScroll(() => {}); onPageScroll(() => {});
@ -130,7 +143,7 @@
couponInfo: [], // Coupon couponInfo: [], // Coupon
showActivityModel: false, // / Activity showActivityModel: false, // / Activity
activityInfo: [], // / Activity activityInfo: [], // / Activity
activityList: [], // // Activity activityList: [], // // Activity
}); });
// //
@ -179,7 +192,7 @@
} }
} }
// 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({
@ -193,8 +206,9 @@
}, { }, {
type: 'goods', // type: 'goods', //
title: state.goodsInfo.name, // title: state.goodsInfo.name, //
image: sheep.$url.cdn(state.goodsInfo.image), // // image: sheep.$url.cdn(state.goodsInfo.image), //
price: state.goodsInfo.price[0], // image: sheep.$url.cdn(state.goodsInfo.picUrl), //
price: state.goodsInfo.price, //
original_price: state.goodsInfo.original_price, // original_price: state.goodsInfo.original_price, //
}, ); }, );
}); });
@ -208,31 +222,31 @@
state.goodsId = options.id; state.goodsId = options.id;
// 1. // 1.
sheep.$api.goods.detail(state.goodsId).then((res) => { sheep.$api.goods.detail(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;
}); });
// 2. // 2.
CouponApi.getCouponTemplateList(state.goodsId,2, 10).then((res) => { CouponApi.getCouponTemplateList(state.goodsId, 2, 10).then((res) => {
if (res.code !== 0) { if (res.code !== 0) {
return; return;
} }
state.couponInfo = res.data; state.couponInfo = res.data;
}); });
// 3. // 3.
ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => { ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
if (res.code !== 0) { if (res.code !== 0) {
return; return;
} }
state.activityList = res.data; state.activityList = res.data;
}); });
}); });
</script> </script>

View File

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

View File

@ -1,250 +1,268 @@
<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" :style="[
{ {
marginTop: '-' + Number(statusBarHeight + 88) + 'rpx', marginTop: '-' + Number(statusBarHeight + 88) + 'rpx',
paddingTop: Number(statusBarHeight + 108) + 'rpx', paddingTop: Number(statusBarHeight + 108) + 'rpx',
}, },
]"> ]">
<view class=""> <view class="">
<view class="num-title">当前余额</view> <view class="num-title">当前余额</view>
<view class="wallet-num">{{ userInfo.money }}</view> <view class="wallet-num">{{ userInfo.money }}</view>
</view> </view>
<button class="ss-reset-button log-btn" @tap="sheep.$router.go('/pages/pay/recharge-log')"></button> <button class="ss-reset-button log-btn" @tap="sheep.$router.go('/pages/pay/recharge-log')"></button>
</view> </view>
<view class="recharge-box"> <view class="recharge-box">
<view class="recharge-card-box" v-if="state.data.status"> <view class="recharge-card-box" v-if="state.data.status">
<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" v-if="state.data.custom_status"> <view class="input-box ss-flex border-bottom ss-p-b-20" v-if="state.data.custom_status">
<view class="unit"></view> <view class="unit"></view>
<uni-easyinput v-model="state.recharge_money" type="digit" placeholder="请输入充值金额" :inputBorder="false"> <uni-easyinput v-model="state.recharge_money" type="digit" placeholder="请输入充值金额"
</uni-easyinput> :inputBorder="false">
</view> </uni-easyinput>
<view class="face-value-box ss-flex ss-flex-wrap ss-m-y-40"> </view>
<button class="ss-reset-button face-value-btn" v-for="item in state.faceValueList" :key="item.money" <view class="face-value-box ss-flex ss-flex-wrap ss-m-y-40">
:class="[{ 'btn-active': state.recharge_money == parseFloat(item.money) }]" @tap="onCard(item.money)"> <button class="ss-reset-button face-value-btn" v-for="item in state.faceValueList" :key="item.money"
<text class="face-value-title">{{ item.money }}</text> :class="[{ 'btn-active': state.recharge_money == parseFloat(item.money) }]"
<view v-if="item.gift" class="face-value-tag"> @tap="onCard(item.payPrice/100)">
{{ item.gift }}{{ state.data.gift_type == 'money' ? '元' : '积分' }}</view> <text class="face-value-title">{{ item.payPrice/100 }}</text>
</button> <view v-if="item.bonusPrice" class="face-value-tag">
</view> {{ item.bonusPrice/100 }}{{ state.data.gift_type == 'money' ? '元' : '积分' }}</view>
<button class="ss-reset-button save-btn ui-BG-Main-Gradient ss-m-t-60 ui-Shadow-Main" @tap="onConfirm"> </button>
确认充值 </view>
</button> <button class="ss-reset-button save-btn ui-BG-Main-Gradient ss-m-t-60 ui-Shadow-Main" @tap="onConfirm">
</view> 确认充值
<view class="" v-if="state.data.status === 0"> </view> </button>
</view> </view>
</s-layout> <view class="" v-if="state.data.status === 0"> </view>
</view>
</s-layout>
</template> </template>
<script setup> <script setup>
import { computed, reactive } from 'vue'; import {
import sheep from '@/sheep'; computed,
import { onLoad } from '@dcloudio/uni-app'; reactive
} from 'vue';
import sheep from '@/sheep';
import {
onLoad
} from '@dcloudio/uni-app';
const userInfo = computed(() => sheep.$store('user').userInfo); const userInfo = computed(() => sheep.$store('user').userInfo);
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: '',
data: {}, data: {},
faceValueList: [], faceValueList: [],
}); });
// //
function onCard(e) { function onCard(e) {
state.recharge_money = e; state.recharge_money = e;
} }
async function getRechargeTabs() { async function getRechargeTabs() {
const res = await sheep.$api.trade.rechargeRules(); const res = await sheep.$api.trade.rechargeRules();
if (res.error === 0) { const res2 = await sheep.$api.trade.rechargeRules2();
state.data = res.data; if (res.error === 0) {
state.data.status = res.data.status; state.data = res.data;
state.faceValueList = res.data.quick_amounts; state.data.status = res.data.status;
} console.log(res);
} console.log(res2);
// state.faceValueList = res.data.quick_amounts;
state.faceValueList = res2.data;
}
}
function onChange(e) { function onChange(e) {
state.data.gift_type = e.detail.value; state.data.gift_type = e.detail.value;
} }
async function onConfirm() { async function onConfirm() {
const { error, data } = await sheep.$api.trade.recharge({ const {
recharge_money: state.recharge_money, code,
}); data
if (error === 0) { } = await sheep.$api.trade.recharge({
// #ifdef MP packageId: 0,
sheep.$platform.useProvider('wechat').subscribeMessage('money_change'); payPrice: state.recharge_money * 100
// #endif });
sheep.$router.go('/pages/pay/index', { orderSN: data.order_sn, type: 'recharge' }); if (code === 0) {
} // #ifdef MP
} sheep.$platform.useProvider('wechat').subscribeMessage('money_change');
onLoad(() => { // #endif
getRechargeTabs(); sheep.$router.go('/pages/pay/index', {
}); orderSN: data.order_sn,
type: 'recharge'
});
}
}
onLoad(() => {
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

@ -101,6 +101,7 @@
}, },
); );
const onRegionConfirm = (e) => { const onRegionConfirm = (e) => {
console.log(e);
state.model = { state.model = {
...state.model, ...state.model,
...e, ...e,
@ -186,7 +187,13 @@
if (options.data) { if (options.data) {
let data = JSON.parse(options.data); let data = JSON.parse(options.data);
console.log(data) const areaData = uni.getStorageSync('areaData');
let provinceArr = areaData.filter(item => item.name == data.province_name);
data.province_id = provinceArr[0].id;
let provinceArr2 = provinceArr[0].children.filter(item => item.name == data.city_name);
data.city_id = provinceArr2[0].id;
let provinceArr3 = provinceArr2[0].children.filter(item => item.name == data.district_name);
data.district_id = provinceArr3[0].id;
state.model = { state.model = {
...state.model, ...state.model,
...data, ...data,

View File

@ -1,43 +1,54 @@
import request from '@/sheep/request'; import request from '@/sheep/request';
export default { export default {
myGroupon: (params) => myGroupon: (params) =>
request({ request({
url: 'activity/groupon/myGroupons', url: 'activity/groupon/myGroupons',
method: 'GET', method: 'GET',
params, params,
}), }),
getGrouponList: (params) => getGrouponList: (params) =>
request({ request({
url: 'activity/groupon', url: 'activity/groupon',
method: 'GET', method: 'GET',
params, params,
}), }),
grouponDetail: (id) => grouponDetail: (id) =>
request({ request({
url: 'activity/groupon/' + id, url: 'activity/groupon/' + id,
method: 'GET', method: 'GET',
}), }),
signList: (params) => signList: (params) =>
request({ request({
url: 'activity/signin', url: 'activity/signin',
method: 'GET', method: 'GET',
params, params,
}), }),
signAdd: () => signAdd: () =>
request({ request({
url: 'activity/signin', url: '/app-api/member/sign-in/record/create',
method: 'POST', method: 'POST',
}), }),
replenish: (data) => // signAdd: () =>
request({ // request({
url: 'activity/signin/replenish', // url: 'activity/signin',
method: 'POST', // method: 'POST',
data, // }),
}), replenish: (data) =>
activity: (id) => request({
request({ url: 'activity/signin/replenish',
url: 'activity/activity/' + id, method: 'POST',
method: 'GET', data,
}), }),
}; activity: (id) =>
request({
url: 'activity/activity/' + id,
method: 'GET',
}),
getSummary: () =>
request({
url: '/app-api/member/sign-in/record/get-summary',
method: 'GET',
}),
};

View File

@ -1,37 +1,46 @@
import request from '@/sheep/request'; import request from '@/sheep/request';
export default { export default {
order: (id) => order: (id) =>
request({ request({
url: 'trade/order/' + id, url: 'trade/order/' + id,
method: 'GET', method: 'GET',
custom: { custom: {
showLoading: false, showLoading: false,
}, },
}), }),
orderLog: (params) => orderLog: (params) =>
request({ request({
url: 'trade/order', url: 'trade/order',
method: 'GET', method: 'GET',
params, params,
custom: { custom: {
showLoading: false, showLoading: false,
}, },
}), }),
rechargeRules: () => rechargeRules: () =>
request({ request({
url: 'trade/order/rechargeRules', url: 'trade/order/rechargeRules',
method: 'GET', method: 'GET',
custom: { custom: {
showError: false, showError: false,
showLoading: false, showLoading: false,
}, },
}), }),
recharge: (data) => rechargeRules2: () =>
request({ request({
url: 'trade/order/recharge', url: '/app-api/pay/wallet-recharge-package/list',
method: 'POST', method: 'GET',
data, custom: {
}), showError: false,
}; showLoading: false,
},
}),
recharge: (data) =>
request({
url: '/app-api/pay/wallet-recharge/create',
method: 'POST',
data,
}),
};

View File

@ -1,19 +1,16 @@
<template> <template>
<!-- 分享弹框 --> <!-- 分享弹框 -->
<view> <view>
<su-popup :show="state.showShareGuide" :showClose="false" @close="onCloseGuide"></su-popup> <su-popup :show="state.showShareGuide" :showClose="false" @close="onCloseGuide"></su-popup>
<view v-if="state.showShareGuide" class="guide-wrap"> <view v-if="state.showShareGuide" class="guide-wrap">
<image <image class="guide-image" :src="sheep.$url.static('/static/img/shop/share/share_guide.png')"></image>
class="guide-image" </view>
:src="sheep.$url.static('/static/img/shop/share/share_guide.png')"
></image>
</view>
<su-popup :show="show" round="10" :showClose="false" @close="closeShareModal"> <su-popup :show="show" round="10" :showClose="false" @close="closeShareModal">
<!-- 分享tools --> <!-- 分享tools -->
<view class="share-box"> <view class="share-box">
<view class="share-list-box ss-flex"> <view class="share-list-box ss-flex">
<button <!-- <button
v-if="shareConfig.methods.includes('forward')" v-if="shareConfig.methods.includes('forward')"
class="share-item share-btn ss-flex-col ss-col-center" class="share-item share-btn ss-flex-col ss-col-center"
open-type="share" open-type="share"
@ -25,20 +22,14 @@
mode="" mode=""
></image> ></image>
<text class="share-title">微信好友</text> <text class="share-title">微信好友</text>
</button> </button> -->
<button <button v-if="shareConfig.methods.includes('poster')"
v-if="shareConfig.methods.includes('poster')" class="share-item share-btn ss-flex-col ss-col-center" @tap="onShareByPoster">
class="share-item share-btn ss-flex-col ss-col-center" <image class="share-img" :src="sheep.$url.static('/static/img/shop/share/share_poster.png')"
@tap="onShareByPoster" mode=""></image>
> <text class="share-title">生成海报</text>
<image </button>
class="share-img" <!--
:src="sheep.$url.static('/static/img/shop/share/share_poster.png')"
mode=""
></image>
<text class="share-title">生成海报</text>
</button>
<button <button
v-if="shareConfig.methods.includes('link')" v-if="shareConfig.methods.includes('link')"
class="share-item share-btn ss-flex-col ss-col-center" class="share-item share-btn ss-flex-col ss-col-center"
@ -50,152 +41,157 @@
mode="" mode=""
></image> ></image>
<text class="share-title">复制链接</text> <text class="share-title">复制链接</text>
</button> </button> -->
</view> </view>
<view class="share-foot ss-flex ss-row-center ss-col-center" @tap="closeShareModal"> <view class="share-foot ss-flex ss-row-center ss-col-center" @tap="closeShareModal">
取消 取消
</view> </view>
</view> </view>
</su-popup> </su-popup>
<!-- 分享海报 --> <!-- 分享海报 -->
<canvas-poster <canvas-poster ref="SharePosterRef" :show="state.showPosterModal" :shareInfo="shareInfo"
ref="SharePosterRef" @close="state.showPosterModal = false" />
:show="state.showPosterModal" </view>
:shareInfo="shareInfo"
@close="state.showPosterModal = false"
/>
</view>
</template> </template>
<script setup> <script setup>
/** /**
* 分享弹窗 * 分享弹窗
*/ */
import { ref, unref, reactive, computed } from 'vue'; import {
import sheep from '@/sheep'; ref,
import canvasPoster from './canvas-poster/index.vue'; unref,
import { showShareModal, closeShareModal, showAuthModal } from '@/sheep/hooks/useModal'; reactive,
computed
} from 'vue';
import sheep from '@/sheep';
import canvasPoster from './canvas-poster/index.vue';
import {
showShareModal,
closeShareModal,
showAuthModal
} from '@/sheep/hooks/useModal';
const show = computed(() => sheep.$store('modal').share); const show = computed(() => sheep.$store('modal').share);
const shareConfig = computed(() => sheep.$store('app').platform.share); const shareConfig = computed(() => sheep.$store('app').platform.share);
const SharePosterRef = ref(''); const SharePosterRef = ref('');
const props = defineProps({ const props = defineProps({
shareInfo: { shareInfo: {
type: Object, type: Object,
default() {}, default () {},
}, },
}); });
const state = reactive({ const state = reactive({
showShareGuide: false, //H5 showShareGuide: false, //H5
showPosterModal: false, // showPosterModal: false, //
}); });
// //
const onShareByPoster = () => { const onShareByPoster = () => {
closeShareModal(); closeShareModal();
if (!sheep.$store('user').isLogin) { if (!sheep.$store('user').isLogin) {
showAuthModal(); showAuthModal();
return; return;
} }
unref(SharePosterRef).getPoster(); unref(SharePosterRef).getPoster();
state.showPosterModal = true; state.showPosterModal = true;
}; };
// //
const onShareByForward = () => { const onShareByForward = () => {
closeShareModal(); closeShareModal();
// #ifdef H5 // #ifdef H5
if (['WechatOfficialAccount', 'H5'].includes(sheep.$platform.name)) { if (['WechatOfficialAccount', 'H5'].includes(sheep.$platform.name)) {
state.showShareGuide = true; state.showShareGuide = true;
return; return;
} }
// #endif // #endif
// #ifdef APP-PLUS // #ifdef APP-PLUS
uni.share({ uni.share({
provider: 'weixin', provider: 'weixin',
scene: 'WXSceneSession', scene: 'WXSceneSession',
type: 0, type: 0,
href: props.shareInfo.link, href: props.shareInfo.link,
title: props.shareInfo.title, title: props.shareInfo.title,
summary: props.shareInfo.desc, summary: props.shareInfo.desc,
imageUrl: props.shareInfo.image, imageUrl: props.shareInfo.image,
success: (res) => { success: (res) => {
console.log('success:' + JSON.stringify(res)); console.log('success:' + JSON.stringify(res));
}, },
fail: (err) => { fail: (err) => {
console.log('fail:' + JSON.stringify(err)); console.log('fail:' + JSON.stringify(err));
}, },
}); });
// #endif // #endif
}; };
// //
const onShareByCopyLink = () => { const onShareByCopyLink = () => {
sheep.$helper.copyText(props.shareInfo.link); sheep.$helper.copyText(props.shareInfo.link);
closeShareModal(); closeShareModal();
}; };
function onCloseGuide() { function onCloseGuide() {
state.showShareGuide = false; state.showShareGuide = false;
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.guide-image { .guide-image {
right: 30rpx; right: 30rpx;
top: 0; top: 0;
position: fixed; position: fixed;
width: 580rpx; width: 580rpx;
height: 430rpx; height: 430rpx;
z-index: 10080; z-index: 10080;
} }
// tool // tool
.share-box { .share-box {
background: $white; background: $white;
width: 750rpx; width: 750rpx;
border-radius: 30rpx 30rpx 0 0; border-radius: 30rpx 30rpx 0 0;
padding-top: 30rpx; padding-top: 30rpx;
.share-foot { .share-foot {
font-size: 24rpx; font-size: 24rpx;
color: $gray-b; color: $gray-b;
height: 80rpx; height: 80rpx;
border-top: 1rpx solid $gray-e; border-top: 1rpx solid $gray-e;
} }
.share-list-box { .share-list-box {
.share-btn { .share-btn {
background: none; background: none;
border: none; border: none;
line-height: 1; line-height: 1;
padding: 0; padding: 0;
&::after { &::after {
border: none; border: none;
} }
} }
.share-item { .share-item {
flex: 1; flex: 1;
padding-bottom: 20rpx; padding-bottom: 20rpx;
.share-img { .share-img {
width: 70rpx; width: 70rpx;
height: 70rpx; height: 70rpx;
background: $gray-f; background: $gray-f;
border-radius: 50%; border-radius: 50%;
margin-bottom: 20rpx; margin-bottom: 20rpx;
} }
.share-title { .share-title {
font-size: 24rpx; font-size: 24rpx;
color: $dark-6; color: $dark-6;
} }
} }
} }
} }
</style> </style>