Day.js是一个轻量级的JavaScript时间库,用于解析、验证、操作和格式化日期。它的API设计风格与Moment.js类似,但是它的体积更小,只有2KB,使得它在前端项目中非常受欢迎。Day.js支持链式操作,易于阅读和理解,同时它也是不可变的,这意味着Day.js对象操作后会返回一个新的Day.js实例。
效果大致如下:
在上述代码中,Day.js被用于处理日期和时间,主要体现在以下几个方面:
引入和配置
import dayjs from 'dayjs'
import isoWeek from 'dayjs/plugin/isoWeek'
dayjs.extend(isoWeek)
复制
这段代码首先引入了Day.js库,然后引入了isoWeek
插件。isoWeek
插件用于处理ISO周相关的操作。通过dayjs.extend(isoWeek)
来扩展Day.js,使其支持ISO周的相关功能。
获取当前日期的ISO周的开始日期
const getWeekStart = (date: string | null) => {
if (!date) return null
return dayjs(date).startOf('isoWeek').format('YYYY-MM-DD')
}
复制
getWeekStart
函数接受一个日期字符串作为参数,使用dayjs
将其转换为Day.js对象,然后调用startOf('isoWeek')
来获取该周的第一天(通常是周一),最后通过format('YYYY-MM-DD')
将日期格式化为年-月-日的格式。
计算一周内每一天的日期
const getWeekDays = () => {
const weekStart = getWeekStart(selectedWeek.value)
weekDays.value = days.map((day, index) => {
const date = new Date(weekStart)
date.setDate(date.getDate() + index)
return {
key: day,
label: `${dayLabels[day]}\n\n${date.getMonth() + 1}/${date.getDate()}`,
date: date.toISOString().split('T')[0]
}
})
}
复制
getWeekDays
函数计算选定周的每一天的日期,并将其存储在weekDays
响应式变量中。它首先获取周的开始日期,然后遍历每一天,通过new Date(weekStart)
创建一个日期对象,并使用setDate
方法加上索引值来获取该周的每一天的日期。
日期选择器的变化处理
const handleWeekChange = (value: any) => {
selectedWeek.value = value
fetchData(getWeekStart(selectedWeek.value), getDateAfterSevenDays(selectedWeek.value))
getWeekDays()
}
复制
handleWeekChange
函数作为日期选择器变化的事件处理函数,当用户选择一个新的周时,它会更新selectedWeek
的值,并调用fetchData
函数来获取新周的数据,同时调用getWeekDays
来更新周内每天的日期。
格式化日期
selectedWeek.value = dayjs().subtract(0, 'week').startOf('isoWeek').format('YYYY-MM-DD')
复制
这段代码用于设置默认选中的周为当前周。它使用dayjs()
获取当前日期的Day.js对象,然后通过subtract(0, 'week')
获取当前周,接着通过startOf('isoWeek')
获取周的开始日期,最后通过format('YYYY-MM-DD')
格式化日期。
Day.js的这些特性在上述代码中得到了广泛的应用,展示了如何使用Day.js来处理复杂的日期逻辑。它的轻量级和易用性使得它成为处理日期和时间的理想选择。
具体代码实现
<template>
<div class="pad20">
<el-date-picker
class="mb20"
v-if="weekDays.length"
v-model="selectedWeek"
type="week"
format="YYYY 第 ww 周"
placeholder="选择周"
:first-day-of-week="1"
@change="handleWeekChange"
/>
<el-table
v-if="weekDays && weekDays.length > 0"
:class="{ 'no-filter-icon': executorFilterOptions && executorFilterOptions.length == 0 }"
size="medium"
:header-cell-style="{ background: '#f5f7fa' }"
:data="processedData"
style="width: 100%"
>
<el-table-column
label="执行人"
width="120"
fixed
:filters="executorFilterOptions && executorFilterOptions.length ? executorFilterOptions : null"
:filter-method="filterExecutor"
>
<template #default="prop">
<router-link :to="`/planHour/${prop.row.executorId}`" class="cur-p">{{ prop.row.executorName }}</router-link>
</template>
</el-table-column>
<el-table-column label="总计工时" width="180" fixed prop="weekTotal" sortable>
<template #default="prop">
<el-progress
class="custom-progress-bar"
:color="customColorMethod(prop.row.weekTotal)"
:percentage="parseFloat(((prop.row.weekTotal / 40) * 100).toFixed(2))"
>
<span text>{{ prop.row.weekTotal }}</span>
</el-progress>
</template>
</el-table-column>
<el-table-column v-for="day in weekDays" :key="day.date" :label="day.label">
<template #default="scope">
{{ scope.row.weekData[day.key] }}
</template>
</el-table-column>
</el-table>
</div>
</template>
<script lang="ts" setup>
import { computed, onMounted, ref, reactive, toRefs } from 'vue'
import { xxxApi } from '@/apis'
import { useRouter } from 'vue-router'
import useMapStore from '@/compositions/mapStore'
import dayjs from 'dayjs'
import isoWeek from 'dayjs/plugin/isoWeek'
import 'dayjs/locale/zh-cn'
import { cbSuccess, cloneDeep, rules, checkTypeTemplate } from '@/utils'
import { Plan, Common } from '@/interfaces'
import useAdmq from '@/compositions/admq'
import { ElMessage } from 'element-plus'
import ESDialogVue from '@/components/ESDialog.vue'
const { user, isSys, isDba, isPA } = useMapStore()
const router = useRouter()
dayjs.extend(isoWeek)
const originalData = ref([])
const selectedWeek = ref(null)
const weekDays = ref([])
const state = reactive({
executor: {} as any,
taskTimeTotalList: [] as any,
planShow: false,
planInfo: {} as Plan,
team: Array<Common>(),
teams: [
{
executorId: undefined,
taskTime: undefined,
remarks: undefined
}
] as any,
newcoms: [],
canSave: true,
users: [],
copyId: undefined,
id: undefined,
executorId: undefined
})
const { planInfo, teams, planShow, newcoms } = toRefs(state)
const fetchData = async (start: string, end: string) => {
let _params = {
startDate: start,
endDate: end
}
let { data } = await xxxApi(_params)
if (Array.isArray(data)) originalData.value = data
}
const { formRef, onSubmit, operate, onconfirm } = useAdmq(fetchData)
const setType = (path: any) => {
router.push(path)
}
const executorFilterOptions = computed(() => {
const executors = new Set()
originalData.value.forEach(person => {
executors.add({ text: person.executorName, value: person.executorId })
})
return Array.from(executors)
})
const filterExecutor = (value: any, row: any) => {
return row.executorId === value
}
const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
const dayLabels = {
Mon: '周一',
Tue: '周二',
Wed: '周三',
Thu: '周四',
Fri: '周五',
Sat: '周六',
Sun: '周日'
} as any
const getWeekStart = (date: string | null) => {
if (!date) return null
return dayjs(date).startOf('isoWeek').format('YYYY-MM-DD')
}
function getDateAfterSevenDays(dateString: string) {
return dayjs(dateString).add(6, 'day').format('YYYY-MM-DD')
}
const processedData = computed(() => {
const weekStart = getWeekStart(selectedWeek.value)
if (!weekStart) return []
return originalData.value.map(person => {
const weekData = {} as any
let weekTotal = 0
days.forEach((day, index) => {
const date = new Date(weekStart)
date.setDate(date.getDate() + index)
const dateString = date.toISOString().split('T')[0]
const dayData = person.taskTimeTotalList.find((item: any) => item.date === dateString)
const hours = dayData ? dayData.hours : 0
weekData[day] = hours
weekTotal += hours
})
weekTotal = Number(weekTotal.toFixed(1))
return {
executorId: person.executorId,
executorName: person.executorName,
weekTotal,
weekData
}
})
})
const setDefaultWeek = () => {
selectedWeek.value = dayjs().subtract(0, 'week').startOf('isoWeek').format('YYYY-MM-DD')
if (selectedWeek.value) getWeekDays()
}
const getWeekDays = () => {
const weekStart = getWeekStart(selectedWeek.value)
weekDays.value = days.map((day, index) => {
const date = new Date(weekStart)
date.setDate(date.getDate() + index)
return {
key: day,
label: `${dayLabels[day]}\n\n${date.getMonth() + 1}/${date.getDate()}`,
date: date.toISOString().split('T')[0]
}
})
}
const handleWeekChange = (value: any) => {
selectedWeek.value = value
fetchData(getWeekStart(selectedWeek.value), getDateAfterSevenDays(selectedWeek.value))
getWeekDays()
}
const customColorMethod = (weekTotal: any) => {
let item = weekTotal
if (item >= 48) {
return '#2196F3'
} else if (item < 48 && item >= 40) {
return '#388E3C'
} else if (item < 40 && item >= 32) {
return '#67c23a'
} else if (item < 32 && item >= 20) {
return '#e6a23c'
} else if (item < 20) {
return '#f56c6c'
}
}
onMounted(() => {
setDefaultWeek()
fetchData(getWeekStart(selectedWeek.value), getDateAfterSevenDays(selectedWeek.value))
})
</script>
复制