2025-11-07 14:21:27 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view class="remaining-time" :class="computedClass">
|
|
|
|
|
|
<text class="text">{{ displayText }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
export default {
|
|
|
|
|
|
name: 'RemainingTime',
|
|
|
|
|
|
props: {
|
2025-11-07 17:18:33 +08:00
|
|
|
|
// 截至日期(支持多种格式或null)
|
2025-11-07 14:21:27 +08:00
|
|
|
|
expireDate: {
|
2025-11-07 17:18:33 +08:00
|
|
|
|
type: [String, null], // 允许字符串或null
|
|
|
|
|
|
default: null, // 默认null
|
2025-11-07 14:21:27 +08:00
|
|
|
|
validator(value) {
|
2025-11-07 17:18:33 +08:00
|
|
|
|
// 允许null,非null时检查是否能解析为有效日期
|
|
|
|
|
|
if (value === null) return true;
|
2025-11-07 14:21:27 +08:00
|
|
|
|
return !isNaN(Date.parse(value));
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-11-07 17:18:33 +08:00
|
|
|
|
// 阈值天数
|
2025-11-07 14:21:27 +08:00
|
|
|
|
thresholdDays: {
|
|
|
|
|
|
type: Number,
|
2025-11-07 17:18:33 +08:00
|
|
|
|
default: 3,
|
2025-11-07 14:21:27 +08:00
|
|
|
|
validator(value) {
|
|
|
|
|
|
return value >= 0;
|
|
|
|
|
|
}
|
2025-11-07 17:18:33 +08:00
|
|
|
|
},
|
|
|
|
|
|
// 是否已完成
|
|
|
|
|
|
finished: {
|
|
|
|
|
|
type: Boolean,
|
|
|
|
|
|
default: false
|
2025-11-07 14:21:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
computed: {
|
2025-11-07 17:18:33 +08:00
|
|
|
|
// 计算剩余天数(处理null和无效日期)
|
2025-11-07 14:21:27 +08:00
|
|
|
|
remainingDays() {
|
2025-11-07 17:18:33 +08:00
|
|
|
|
// 如果无截止日期或日期无效,返回null
|
|
|
|
|
|
if (!this.expireDate) return null;
|
2025-11-07 14:21:27 +08:00
|
|
|
|
const now = new Date();
|
|
|
|
|
|
const expire = new Date(this.expireDate);
|
2025-11-07 17:18:33 +08:00
|
|
|
|
// 无效日期处理
|
|
|
|
|
|
if (isNaN(expire.getTime())) return null;
|
2025-11-07 14:21:27 +08:00
|
|
|
|
const diffTime = expire - now;
|
|
|
|
|
|
return Math.round(diffTime / (1000 * 60 * 60 * 24));
|
|
|
|
|
|
},
|
2025-11-07 17:18:33 +08:00
|
|
|
|
// 是否已逾期(仅在有有效日期时判断)
|
2025-11-07 14:21:27 +08:00
|
|
|
|
isExpired() {
|
2025-11-07 17:18:33 +08:00
|
|
|
|
return this.remainingDays !== null && this.remainingDays < 0;
|
2025-11-07 14:21:27 +08:00
|
|
|
|
},
|
2025-11-07 17:18:33 +08:00
|
|
|
|
// 显示文本(优先级:完成 > 无日期 > 逾期 > 剩余时间)
|
2025-11-07 14:21:27 +08:00
|
|
|
|
displayText() {
|
2025-11-07 17:18:33 +08:00
|
|
|
|
if (this.finished) {
|
|
|
|
|
|
return '已完成';
|
|
|
|
|
|
}
|
|
|
|
|
|
// 无截止日期的情况
|
|
|
|
|
|
if (this.remainingDays === null) {
|
|
|
|
|
|
return '无截止日期';
|
|
|
|
|
|
}
|
2025-11-07 14:21:27 +08:00
|
|
|
|
if (this.isExpired) {
|
|
|
|
|
|
return `已逾期 ${Math.abs(this.remainingDays)} 天`;
|
|
|
|
|
|
}
|
|
|
|
|
|
return `剩余 ${this.remainingDays} 天`;
|
|
|
|
|
|
},
|
2025-11-07 17:18:33 +08:00
|
|
|
|
// 图标类型
|
|
|
|
|
|
getIconType() {
|
|
|
|
|
|
if (this.finished) {
|
|
|
|
|
|
return 'checkmark';
|
|
|
|
|
|
}
|
|
|
|
|
|
if (this.remainingDays === null) {
|
|
|
|
|
|
return 'help'; // 无日期时显示帮助图标
|
|
|
|
|
|
}
|
|
|
|
|
|
return this.isExpired ? 'clock' : 'time';
|
|
|
|
|
|
},
|
|
|
|
|
|
// 样式类
|
2025-11-07 14:21:27 +08:00
|
|
|
|
computedClass() {
|
2025-11-07 17:18:33 +08:00
|
|
|
|
if (this.finished) {
|
|
|
|
|
|
return 'finished';
|
|
|
|
|
|
}
|
|
|
|
|
|
// 无截止日期的样式
|
|
|
|
|
|
if (this.remainingDays === null) {
|
|
|
|
|
|
return 'no-date';
|
|
|
|
|
|
}
|
2025-11-07 14:21:27 +08:00
|
|
|
|
if (this.isExpired) {
|
2025-11-07 17:18:33 +08:00
|
|
|
|
return 'expired';
|
2025-11-07 14:21:27 +08:00
|
|
|
|
}
|
2025-11-07 17:18:33 +08:00
|
|
|
|
return this.remainingDays > this.thresholdDays ? 'normal' : 'warning';
|
2025-11-07 14:21:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.remaining-time {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 4rpx 12rpx;
|
|
|
|
|
|
border-radius: 20rpx;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
line-height: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.icon {
|
|
|
|
|
|
margin-right: 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.text {
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-07 17:18:33 +08:00
|
|
|
|
/* 正常状态 */
|
2025-11-07 14:21:27 +08:00
|
|
|
|
.normal {
|
2025-11-07 17:18:33 +08:00
|
|
|
|
color: #00b42a;
|
2025-11-07 14:21:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-07 17:18:33 +08:00
|
|
|
|
/* 警告状态 */
|
2025-11-07 14:21:27 +08:00
|
|
|
|
.warning {
|
2025-11-07 17:18:33 +08:00
|
|
|
|
color: #f53f3f;
|
2025-11-07 14:21:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 逾期状态 */
|
|
|
|
|
|
.expired {
|
|
|
|
|
|
background-color: #fef0f0;
|
2025-11-07 17:18:33 +08:00
|
|
|
|
color: #f53f3f;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 完成状态 */
|
|
|
|
|
|
.finished {
|
|
|
|
|
|
background-color: #00b42a;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 无截止日期状态 */
|
|
|
|
|
|
.no-date {
|
|
|
|
|
|
color: #888888; /* 灰色文字 */
|
2025-11-07 14:21:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
</style>
|