倒计时组件

This commit is contained in:
浅念
2025-03-25 17:23:40 +08:00
parent f88048b876
commit a5d5ce4e7c
2 changed files with 229 additions and 0 deletions
+104
View File
@@ -0,0 +1,104 @@
<template>
<view class="countdown">
<view class="time green" v-if="!isend">
<image src="/static/image/gtime.png" mode=""></image>
<text v-if="showDays && timeObj.days > 0" >{{ timeObj.days }}{{$t('day')}} </text>
<text> {{ timeObj.hours | padZero }} : </text>
<text> {{ timeObj.minutes | padZero }} : </text>
<text> {{ timeObj.seconds | padZero }}</text>
</view>
<view class="time timered" v-else>
<image src="/static/image/redtime.png" mode=""></image>
<text>{{$t('timeout')}}</text>
</view>
</view>
</template>
<script>
export default {
props: {
// 倒计时总秒数
totalSeconds: {
type: Number,
required: true
},
// 是否显示天数
showDays: {
type: Boolean,
default: true
}
},
data() {
return {
timeObj: {
days: 0,
hours: 0,
minutes: 0,
seconds: 0
},
isend:false,
timer: null,
totalSeconds1:this.totalSeconds
}
},
filters: {
padZero(value) {
return value.toString().padStart(2, '0');
}
},
mounted() {
if(this.totalSeconds>0){
this.runCountdown();
}else{
this.isend=true
}
},
methods: {
runCountdown() {
this.updateTime(this.totalSeconds1);
this.timer = setInterval(() => {
if (this.totalSeconds1 <= 0) {
clearInterval(this.timer);
this.isend=true
this.$emit('end');
return;
}
this.totalSeconds1--;
this.updateTime(this.totalSeconds1);
}, 1000);
},
updateTime(seconds) {
this.timeObj.days = Math.floor(seconds / (24 * 3600));
const remaining = seconds % (24 * 3600);
this.timeObj.hours = Math.floor(remaining / 3600);
this.timeObj.minutes = Math.floor((remaining % 3600) / 60);
this.timeObj.seconds = remaining % 60;
}
},
beforeDestroy() {
clearInterval(this.timer);
}
}
</script>
<style lang="scss">
.countdown{
.time{
display: flex;
align-items: center;
text{
margin: 0px 2px;
}
}
image{
width: 18px;
height: 18px;
margin-right: 5px;
}
}
.green{
color: #27C89C;
}
.timered{
color: #FF4040;
}
</style>
+125
View File
@@ -0,0 +1,125 @@
<template>
<view>
<view class="text">
<view class="qx" @click="close('showarea') ">{{$t('cancel')}}</view>
<view class="qd" @click="arerfn">{{$t('confirm')}}</view>
</view>
<view class="popup-content">
<!-- 搜索框 -->
<u-input
v-model="searchKeyword"
:placeholder="$t('keyword')"
@input="handleSearch"
></u-input>
<!-- 选项列表 -->
<scroll-view scroll-y class="option-list">
<view
v-for="(item, index) in areaList"
:key="index"
class="option-item"
@click="handleSelect(item)"
:class="actives==item.id?'actives':''"
>
{{ item.name }}
</view>
<view v-if="filteredOptions.length === 0" class="no-data">
{{$t('noresults')}}
</view>
</scroll-view>
</view>
</view>
</template>
<script>
export default {
name:"select",
props: {
showarea: {
type: Boolean,
default: true
},
areaList:[],
},
data() {
return {
searchKeyword:'',
filteredOptions:'',
};
},
methods:{
// 搜索处理函数
handleSearch(){
if (this.searchKeyword) {
console.log(this.searchKeyword)
this.filteredOptions = this.areaList.filter((item) =>
item.name.includes(this.searchKeyword)
);
console.log(this.filteredOptions)
} else {
// 如果搜索框为空,显示全部数据
this.filteredOptions = this.areaList;
}
},
// 选择选项
handleSelect(item) {
this.selectedLabel = item.name; // 回显选中的值
// this.searchKeyword = item.name
this.actives = item.id
// this.showPicker = false; // 关闭弹窗
console.log("选中的值:", item.id);
console.log("选中的值:", item.name);
},
arerfn(){
this.showPicker = false; // 关闭弹窗
this.country_name = this.selectedLabel
this.userinfo.country_id = this.actives
},
close(val){
this[val] = false
},
}
}
</script>
<style lang="scss">
.actives{
background-color: #dfdfdf;
}
.text{
display: flex;
align-items: center;
justify-content: space-between;
line-height: 30px;
padding: 10px 15px 0px;
.qd{
color: #3471FF;
}
}
.popup-content {
padding: 20px;
background-color: #fff;
}
.option-list {
max-height: 400rpx;
margin-top: 20rpx;
}
.option-item {
padding: 20rpx;
border-bottom: 1rpx solid #eee;
}
.option-item:last-child {
border-bottom: none;
}
.no-data {
text-align: center;
padding: 20rpx;
color: #999;
}
</style>