需求
已知数据
不同阶段的完成时间点(这里以三个阶段举例,依次为备货阶段,装配阶段,测试阶段)
计划的开始结束时间
要求实现功能
将当前日期处于哪个阶段用进度条展示出来
不同的阶段用不同的背景色显示
如果当前日期小于阶段计划完成时间点,需要将未完成时间点标记出来
最终效果图
核心思路
- 天数计算
- linear-gradient的应用:实现不同计划阶段不同颜色,及阶段时间点标记
代码实现
下面代码以vue为例
<template>
<div class="progress-div">
<div class="step-total" :style="{ background: getRule(record, 'style') }"></div>
<span>{{ getRule(record, 'percent') }} </span>
<span> {{ getRule(record, 'text') }}</span>
</div>
</template>
<script>
data(){
record: {
//这里的时间顺序一定是 计划开始时间<=备货截止日期<=装配截止日期<=测试截止日期<=计划结束时间
beginTime: '2024-04-01',
endTime: '2024-05-14',
//备货截止日期
stockEndTime: '2024-04-08',
//装配截止日期
assembleEndTime: '2024-04-27',
//测试截止日期
testEndTime: '2024-05-14'
}
},
methods:{
//工具方法用于计算两个日期天数差
getDaysBetween(date1, date2) {
const startDate = Date.parse(date1)
const endDate = Date.parse(date2)
if (startDate > endDate) {
return 0
}
if (startDate == endDate) {
return 1
}
const days = parseInt((endDate - startDate) / (24 * 60 * 60 * 1000))
return days
},
//通过style动态绑定更改背景色,这里还获取了百分比和当前状态文字,也可以不用switch直接返回一个对象
getRule(record, label) {
let bg = ''
let text = '未开始'
//总天数
const days = this.getDaysBetween(record.beginTime, record.endTime)
//备货天数
const stockDays = this.getDaysBetween(record.beginTime, record.stockEndTime)
//备货占比
const stockRate = parseInt((stockDays / days) * 100)
//装配天数
const assembleDays = this.getDaysBetween(record.beginTime, record.assembleEndTime)
//装备占比
const assembleRate = parseInt((assembleDays / days) * 100)
//测试天数
const testDays = this.getDaysBetween(record.beginTime, record.testEndTime)
//测试占比
const testRate = parseInt((testDays / days) * 100)
//当前过去几天
const currentDays = this.getDaysBetween(record.beginTime, new Date().toISOString().slice(0, 10).replace(/-/g, '-'))
//当天占比
const currentRate = parseInt((currentDays / days) * 100)
//全部完成
if (currentDays >= testDays) {
text = '已完成'
bg = `linear-gradient(to right, #e1eed9 0%, #e1eed9 ${stockRate}%,#a8d08d ${stockRate}%,#a8d08d ${assembleRate}%,#528135 ${assembleRate}%, #528135 ${testRate}%,#ddd ${testRate}%,#ddd 100%)`
}
//测试中
if (currentDays < testDays && currentDays >= assembleDays) {
text = '测试中'
bg = `linear-gradient(to right, #e1eed9 0%, #e1eed9 ${stockRate}%,#a8d08d ${stockRate}%,#a8d08d ${assembleRate}%,#528135 ${assembleRate}%, #528135 ${currentRate}%,#ddd ${currentRate}%,#ddd ${
testRate - 0.5
}%,#528135 ${testRate - 0.5}%,#528135 ${testRate}%,#ddd ${currentRate}%,#ddd 100%)`
}
//装配中
if (currentDays < assembleDays && currentDays >= stockDays) {
text = '装配中'
bg = `linear-gradient(to right, #e1eed9 0%, #e1eed9 ${stockRate}%,#a8d08d ${stockRate}%,#a8d08d ${currentRate}%,#ddd ${currentRate}%,#ddd ${
assembleRate - 0.5
}%,#a8d08d ${assembleRate - 0.5}%,#a8d08d ${assembleRate}%,#ddd ${assembleRate}%,#ddd ${
testRate - 0.5
}%,#528135 ${testRate - 0.5}%,#528135 ${testRate}%,#ddd ${testRate}%,#ddd 100%)`
}
//备货中
if (currentDays < stockDays && currentDays > 0) {
text = '备货中'
bg = `linear-gradient(to right, #e1eed9 0%, #e1eed9 ${currentRate}%,#ddd ${currentRate}%,#ddd ${
stockRate - 0.5
}%,#e1eed9 ${stockRate - 0.5}%,#e1eed9 ${stockRate}%,#ddd ${stockRate}%,#ddd ${assembleRate - 0.5}%,#a8d08d ${
assembleRate - 0.5
}%,#a8d08d ${assembleRate}%,#ddd ${assembleRate}%,#ddd ${testRate - 0.5}%,#528135 ${
testRate - 0.5
}%,#528135 ${testRate}%,#ddd ${testRate}%,#ddd 100%)`
}
//未开始
if (currentDays == 0) {
bg = `linear-gradient(to right, #ddd 0%, #ddd ${stockRate - 0.5}%,#e1eed9 ${
stockRate - 0.5
}%,#e1eed9 ${stockRate}%,#ddd ${stockRate}%,#ddd ${assembleRate - 0.5}%,#a8d08d ${
assembleRate - 0.5
}%,#a8d08d ${assembleRate}%,#ddd ${assembleRate}%,#ddd ${testRate - 0.5}%,#528135 ${
testRate - 0.5
}%,#528135 ${testRate}%,#ddd ${testRate}%,#ddd 100%)`
}
switch (label) {
case 'style':
return bg
case 'text':
return text
case 'percent':
return parseInt((currentDays / days) * 100) + '%'
}
}
<script>
<style lang="css">
.progress-div {
display: flex;
align-items: center;
width: 100%;
justify-content: space-between;
}
.step-total {
width: 200px;
border-radius: 10px;
height: 10px;
}
</style>