Files
Smart-Farm/uniapp/uni-app/shop/pages/sign.vue
2025-12-22 17:13:05 +08:00

425 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="pages-mine" v-if="detail.id">
<uni-nav-bar :fixed="true" :shadow="false" :statusBar="true" color="#fff"
:backgroundColor="color == '#ffffff' ?``:primaryColor" leftIcon="icon-left" title="签到">
</uni-nav-bar>
<view class="sign-info abs">
<image mode="aspectFill" lazy-load class="common-bg sign abs" :src="cover"></image>
<view @tap="$util.goUrl({url:`/shop/pages/integral/list`})"
class="exchange-btn abs flex-center f-caption c-base">兑换好礼
</view>
<view class="integral-info abs flex-center flex-column c-base">
<view class="integral-num">{{detail.integral}}</view>
<image lazy-load class="integral-icon mt-sm" src="/static/image/shop/integral.png"></image>
<view class="f-icontext">我的积分</view>
</view>
<view class="count-info abs flex-center ml-md mr-md fill-base radius-24">
<view class="flex-center flex-column">
<view class="f-lg-title c-title text-bold">{{detail.sign_num}}</view>
<view class="f-caption c-caption">连续签到()</view>
</view>
<view class="flex-center flex-column">
<view class="f-lg-title c-title text-bold">{{detail.total_sign_num}}</view>
<view class="f-caption c-caption">累计签到()</view>
</view>
</view>
</view>
<view class="space-sign rel"></view>
<view class="sign-date-info fill-base mt-md ml-md mr-md radius-24">
<view class="flex-center pt-lg pb-lg">
<view class="flex-y-center f-paragraph">
<i @tap.stop="toChangeDate(-1)" class="iconfont icon-sanjiao pl-lg pr-lg rotate-180"></i>
<view class="month-text flex-center f-sm-title c-title text-bold"> {{detail.month}} </view>
<i @tap.stop="toChangeDate(1)" class="iconfont icon-sanjiao pl-lg pr-lg"></i>
</view>
</view>
<view class="day-info flex-warp">
<view class="day-item flex-center flex-column" v-for="(item,index) in weekList">
{{item}}
</view>
<view class="day-item flex-center flex-column" v-for="(item,index) in timeList">
</view>
<!-- status 0可签到1已签到2未在签到时间内 -->
<view @tap.stop="toChangeItem('dayInd',index)"
class="day-item flex-center flex-column f-title c-title radius"
:class="[{'sign':item.status == 1 },{'today':item.day_str == today || dayInd == index},{'register':item.day_str == detail.create_time}]"
:style="{color:item.day_str == today || item.day_str == detail.create_time || dayInd == index ? '#fff' : ''}"
v-for="(item,index) in detail.list" :key="index">
{{item.day_str == detail.create_time ? '注册' : item.day}}
</view>
</view>
<view class="flex-between pl-lg pr-lg pb-md f-paragraph c-title">
<view @tap="$refs.show_rule_item.open()" class="flex-center c-caption"><i
class="iconfont icon-wenhao mr-sm"></i>签到规则</view>
<view @tap="toChangeItem('is_sign', !is_sign)" class="flex-center">签到提醒<i class="iconfont ml-sm"
:class="[{'icon-switch c-caption':!is_sign},{'icon-switch-on':is_sign}]"
:style="{color:is_sign?primaryColor:''}"></i></view>
</view>
<view @tap="toSign" class="sign-btn flex-center f-title c-base radius">立即签到</view>
<view class="space-lg"></view>
</view>
<view class="mt-md ml-md mr-md pd-lg fill-base radius-24">
<view class="f-title c-title text-bold">积分纪录</view>
<block v-for="(item,index) in list.data" :key="index">
<view @tap.stop="goDetail(index)" class="integral-item flex-center mt-md radius-16">
<image lazy-load class="integral-img radius-16" src="/static/image/shop/integral.png"></image>
<view class="flex-1 ml-lg">
<view class="flex-1 flex-between">
<view>
<view class="f-paragraph c-title mt-sm mb-sm">{{item.create_date}} 签到赠送</view>
<view class="f-caption" style="color: #C7C7C7;">{{item.create_time_text}}</view>
</view>
<view class="flex-y-baseline f-caption" :style="{color:primaryColor}">+<view
class="f-lg-title">
{{item.integral}}
</view>
</view>
</view>
</view>
</view>
</block>
</view>
<load-more :noMore="list.current_page>=list.last_page&&list.data.length>0" :loading="loading" v-if="loading">
</load-more>
<abnor v-if="!loading&&list.data.length<=0&&list.current_page==1"></abnor>
<view class="space-footer"></view>
<uni-popup ref="show_rule_item">
<view class="popup-rule">
<view class="rule-info pd-lg fill-base radius-24">
<view class="flex-center f-title c-title text-bold">签到规则</view>
<view class="rule-text mt-lg f-paragraph">
<text decode="emsp" style="word-break:break-all;">{{detail.integral_text}}</text>
</view>
</view>
<i @tap="$refs.show_rule_item.close()" class="flex-center mt-lg iconfont icon-close c-base"></i>
</view>
</uni-popup>
</view>
</template>
<script>
import {
mapState,
mapActions,
} from "vuex"
export default {
components: {},
data() {
return {
options: {},
color: '#ffffff',
cover: 'https://lbqny.migugu.com/admin/farm/default_sign.png',
weekList: ['日', '一', '二', '三', '四', '五', '六'],
timeList: [],
today: '',
dayInd: -1,
is_sign: true,
detail: {},
param: {
page: 1,
},
list: {
data: []
},
loading: true,
lockTap: false
}
},
computed: mapState({
primaryColor: state => state.config.configInfo.primaryColor,
subColor: state => state.config.configInfo.subColor,
configInfo: state => state.config.configInfo,
userInfo: state => state.user.userInfo,
mineInfo: state => state.user.mineInfo,
}),
onLoad() {
this.$util.showLoading()
this.initIndex()
},
onPullDownRefresh() {
// #ifndef APP-PLUS
uni.showNavigationBarLoading()
// #endif
this.initRefresh()
uni.stopPullDownRefresh()
},
onReachBottom() {
if (this.list.current_page >= this.list.last_page || this.loading) return
this.param.page = this.param.page + 1
this.loading = true
this.getList()
},
onPageScroll(e) {
let color = e.scrollTop < 20 ? '#ffffff' : '#000000'
if (this.color == color) return
this.color = color
},
methods: {
...mapActions(['getConfigInfo', 'getUserInfo', 'getMineInfo', 'getAuthUserProfile']),
async initIndex(day = '') {
let today = this.$util.DateToUnix(this.$util.formatTime(new Date().getTime(),
'YY-M-D'))
this.today = today
day = day || this.$util.formatTime(today * 1000, 'YY-M-D')
let [detail] = await Promise.all([this.$api.shop.signinIndex({
day
}), this.getList()])
detail.id = 1
let {
list,
sign_notice,
create_time
} = detail
detail.create_time = this.$util.DateToUnix(this.$util.formatTime(create_time * 1000, 'YY-M-D'))
this.dayInd = list.findIndex(item => {
return item.day_str == today
})
let {
week,
day_str
} = list[0]
detail.month = this.$util.formatTime(day_str * 1000, 'YY年M月')
let timeList = []
if (week !== 0) {
for (let i = 0; i < week; i++) {
timeList.push({
id: 0
})
}
}
this.timeList = timeList
this.is_sign = sign_notice === 1
this.detail = detail
this.$util.hideAll()
},
initRefresh() {
this.param.page = 1
this.initIndex()
},
async getList() {
let {
list: oldList,
param,
} = this
let newList = await this.$api.shop.signinRecordList(param);
if (this.param.page == 1) {
this.list = newList
} else {
newList.data = oldList.data.concat(newList.data)
this.list = newList
}
this.loading = false
this.$util.hideAll()
},
toChangeDate(type) {
let {
list
} = this.detail
let one = 24 * 3600
let index = type === 1 ? list.length - 1 : 0
let {
day_str
} = list[index]
let day = this.$util.formatTime((day_str + one * type) * 1000, 'YY-M-D')
this.initIndex(day)
},
toChangeItem(key, val) {
if (key === 'dayInd') {
let {
status,
day_str
} = this.detail.list[val]
if (status) {
let {
create_time
} = this.detail
let msg = day_str < create_time ? `注册时间后才可签到` : `签到未开始`
this.$util.showToast({
title: status == 1 ? `已签到` : msg
})
return
}
}
this[key] = val
if (key === 'is_sign') {
this.$api.user.userUpdate({
sign_notice: val ? 1 : 0
})
}
},
async toSign() {
let {
dayInd,
} = this
let {
day_str: day
} = this.detail.list[dayInd]
if (this.lockTap) return;
this.lockTap = true;
this.$util.showLoading()
try {
await this.$api.shop.signin({
day
})
this.$util.showToast({
title: `签到成功`
})
this.lockTap = false
await this.initRefresh()
} catch (e) {
setTimeout(() => {
this.lockTap = false
this.$util.hideAll()
}, 2000)
}
}
}
}
</script>
<style lang="scss">
.pages-mine {
.sign-info {
width: 100%;
height: 579rpx;
top: 0;
left: 0;
z-index: 1;
.exchange-btn {
top: 167rpx;
right: 0;
width: 146rpx;
height: 53rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 100rpx 0 0 100rpx;
z-index: 2;
}
.integral-info {
width: 100%;
height: 217rpx;
top: 167rpx;
left: 0;
.integral-num {
font-size: 50rpx;
}
.integral-icon {
width: 32rpx;
height: 32rpx;
}
}
.count-info {
width: calc(100% - 40rpx);
height: 162rpx;
bottom: 0;
.flex-center {
width: 50%;
}
}
}
.space-sign {
width: 100%;
height: 579rpx;
top: 0;
z-index: -1;
}
.sign-date-info {
.month-text {
width: 300rpx;
}
.day-info {
margin: 0 5rpx;
.day-item {
width: 62rpx;
height: 62rpx;
margin: 10rpx 19rpx;
.f-title {
height: 36rpx;
}
}
.sign {
background: #EFEFEF;
}
.today {
background: linear-gradient(4deg, #39b54a 0%, #69D275 100%);
box-shadow: 0px 3px 11px 0px rgba(13, 143, 57, 0.34);
}
.register {
background: linear-gradient(4deg, #F3A664 0%, #FBE945 100%);
box-shadow: 0px 3px 11px 0px rgba(243,166,100, 0.34);
font-size: 24rpx;
}
}
.icon-wenhao {
font-size: 26rpx;
}
.icon-switch,
.icon-switch-on {
font-size: 70rpx;
}
.sign-btn {
width: 540rpx;
height: 72rpx;
margin: 0 auto;
background: linear-gradient(360deg, #39b54a 0%, #69D275 100%);
box-shadow: 0px 6rpx 17rpx 0px rgba(13, 143, 47, 0.3500);
}
}
.integral-item {
.integral-img {
width: 47rpx;
height: 47rpx;
}
}
.popup-rule {
width: 596rpx;
margin: 0 auto;
.rule-info {
margin-top: 10vh;
.rule-text {
color: #4A4A4A;
line-height: 1.4;
min-height: 100rpx;
max-height: 60vh;
overflow: auto;
}
}
.icon-close {
font-size: 70rpx;
}
}
}
</style>