前言
Vue.js和ElementUI的结合使用已成为创建高效、美观和用户友好的Web应用的一种流行方式。特别是在处理复杂的用户界面和交互时,这种组合展现出其独特的优势。这篇博客旨在深入探讨如何利用Vue和ElementUI来构建一个实用的周数选择器。
周数选择器在很多类型的应用程序中都非常重要,尤其是在需要日期管理的系统中,如日历应用、项目管理工具或报告系统。正确地理解和计算周数对于确保数据的准确性和用户界面的一致性至关重要。然而,由于不同地区和标准对周的定义存在差异,开发这样的功能可能会带来挑战。
为了克服这些挑战并提供一个有效的解决方案,本博客首先从理论出发,详细介绍了周数的计算逻辑,特别是依据国际标准ISO 8601的定义。接着,我们深入到具体的代码实现,展示了如何在Vue和ElementUI框架下实现这一功能。
通过这篇博客,无论是对Vue和ElementUI初学者还是有经验的开发者,都能学到如何实现周数选择器这一具体功能,同时也能对如何在Vue中构建和管理复杂UI组件有更深入的理解。希望这篇博客能成为在Vue和ElementUI应用开发旅程中的宝贵资源。
一、周数的计算逻辑
在本章中,我们将探讨周数的计算逻辑,特别是以周一作为每周的起始日。
1.1 周数的定义
根据国际标准ISO 8601,一年的周数通常是从周一开始计算的。一周的第一天是周一,最后一天是周日。这种计算方式在欧洲和其他一些地区非常常见。
ISO 8601标准广泛应用于国际贸易、通信和其他领域,因为它提供了一种统一的日期和时间表示方法,有助于减少跨国交流中的混淆和误解。在开发支持多国用户的应用程序时,遵循这一标准尤为重要。
1.2 年初周数的确定
年初的周数计算较为特殊。如果1月1日恰好是周一,则该日即为第一周的开始。如果1月1日是周二至周日之间的任何一天,则该周属于上一年的最后一周,新的一年的第一周将从下一个周一开始。
具体来说,基于国际标准ISO 8601,一年中的第一周必须包含该年的1月4日。这实际上意味着如果1月1日至1月4日之间的任何一天是周一至周四,则这一周被视为当年的第一周。
- 包含1月4日的周为第一周:由于1月4日最晚只可能是一年中第一个星期四,因此保证了这一周至少有四天属于新的一年。这样做的目的是为了确保每年的第一周至少包括四天。
- 年初的周数处理:如果1月1日是周五、周六或周日,则该周被计为上一年的最后一周。因为在这种情况下,该周中大部分或所有天数都属于上一年。
1.3 周数的计算方法
二、Vue+ElementUI代码实现
2.1 计算周数
这个方法用于计算给定日期所在的周数。它是整个周数选择器功能的核心。
getWeekNumber (date) {
var yearStart = new Date(date.getFullYear(), 0, 1)
var januaryFirstDayOfWeek = yearStart.getDay() === 0 ? 6 : yearStart.getDay() - 1 // 将周日从0转换为7
var firstMonday = new Date(yearStart)
if (januaryFirstDayOfWeek <= 3) {
// 如果1月1日至1月4日之间为周一至周四,则该周为第一周
firstMonday.setDate(yearStart.getDate() - januaryFirstDayOfWeek)
} else {
// 否则,下周一为第一周的开始
firstMonday.setDate(yearStart.getDate() + 7 - januaryFirstDayOfWeek)
}
var dayCount = Math.ceil((date - firstMonday) / (24 * 3600 * 1000))
return Math.ceil(dayCount / 7)
},
2.2 获取周的日期范围
getWeekDateRange (date) {
// 计算当前日期是周几,ISO周从周一开始
var currentDay = date.getDay()
var distanceToMonday = currentDay === 0 ? 6 : currentDay - 1
// 计算当前周的周一和周日
var monday = new Date(date)
monday.setDate(date.getDate() - distanceToMonday)
var sunday = new Date(monday)
sunday.setDate(monday.getDate() + 6)
// 格式化日期为 yyyy-MM-dd
var format = (d) => d.toISOString().split('T')[0]
return [format(monday), format(sunday)]
},
2.3 根据周数获取日期范围
getWeekDateRangeByWeekNumber (weekNumber, year) {
var januaryFirst = new Date(year, 0, 1)
var januaryFirstDayOfWeek = januaryFirst.getDay() === 0 ? 6 : januaryFirst.getDay() - 1 // 将周日从0转换为7
var firstMonday = new Date(januaryFirst)
if (januaryFirstDayOfWeek <= 3) {
// 如果1月1日至1月4日之间为周一至周四,则该周为第一周
firstMonday.setDate(januaryFirst.getDate() - januaryFirstDayOfWeek + 1)
} else {
// 否则,下周一为第一周的开始
firstMonday.setDate(januaryFirst.getDate() + 8 - januaryFirstDayOfWeek)
}
var weekStart = new Date(firstMonday)
weekStart.setDate(firstMonday.getDate() + (weekNumber - 1) * 7)
var weekEnd = new Date(weekStart)
weekEnd.setDate(weekStart.getDate() + 6)
// 格式化日期为 yyyy-MM-dd
var format = (d) => d.toISOString().split('T')[0]
return [format(weekStart), format(weekEnd)]
}
这个方法根据给定的周数和年份,计算出那一周的起始和结束日期。
2.4 控件引用
在这个部分,我们将讨论如何在Vue应用中引入和使用一个自定义的WeekSelector
组件,这是一个周数选择控件。以下是控件的引用和初始化过程的解析。
2.4.1 控件引用代码分析
-
<WeekSelector v-else-if="column.searchType==='weekselector'" :model.sync="searchElement[column.prop]"></WeekSelector>
-
组件导入:
import WeekSelector from './WeekSelector'
-
components: { // 其他代码 WeekSelector }
2.4.2 初始化变量代码分析
初始化的主要作用是抑制Vue警告
[Vue warn]: Invalid prop: type check failed for prop "model". Expected Number with value 0, got String with value "".
this.tabInfo = this.tab
this.searchElement = this.searchModel
for (let column of this.tabInfo.searchFormat) {
if (column.searchType === 'weekselector') {
// 使用 Vue 的 $set 方法确保响应性
this.$set(this.searchElement, column.prop, -1)
}
}
- 这段代码用于初始化与
WeekSelector
组件相关的数据。 this.tabInfo
和this.searchElement
分别是对其他对象的引用,用于设置和获取搜索条件。- 循环遍历
this.tabInfo.searchFormat
中的每一列,对于类型为weekselector
的列,使用Vue的$set
方法来初始化this.searchElement
对象的相应属性。这里使用$set
是为了确保新增的属性是响应式的,这样当属性值发生变化时,Vue能够检测到并更新视图。
以上代码段展示了如何在Vue应用中引入、注册和初始化自定义组件WeekSelector
。这个组件的主要功能是作为一个周数选择器,用于提供用户界面上对周数的选择功能。通过这些步骤,可以确保WeekSelector
组件能够正确地被引用并且其状态的变化能够被Vue实例正确地管理和响应。
2.5 周数选择器完整代码
<template>
<div>
<el-row>
<el-col :span="6">
<el-input-number v-model="weekNumber"
:min="0"
:max="52"
label="周数" />
</el-col>
<el-col :span="18">
<el-form-item label="日期范围:">
<el-date-picker type="daterange"
id="dateRange"
range-separator="至"
style="width: 100%;"
size="mini"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd"
v-model="dateRange"
:readonly="true"></el-date-picker>
</el-form-item>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
create () {
this.weekNumber = this.model
},
data () {
return {
weekNumber: this.getWeekNumber(new Date()),
dateRange: this.getWeekDateRange(new Date())
}
},
methods: {
getWeekNumber (date) {
var yearStart = new Date(date.getFullYear(), 0, 1)
var januaryFirstDayOfWeek = yearStart.getDay() === 0 ? 6 : yearStart.getDay() - 1 // 将周日从0转换为7
var firstMonday = new Date(yearStart)
if (januaryFirstDayOfWeek <= 3) {
// 如果1月1日至1月4日之间为周一至周四,则该周为第一周
firstMonday.setDate(yearStart.getDate() - januaryFirstDayOfWeek)
} else {
// 否则,下周一为第一周的开始
firstMonday.setDate(yearStart.getDate() + 7 - januaryFirstDayOfWeek)
}
var dayCount = Math.ceil((date - firstMonday) / (24 * 3600 * 1000))
let weekNum = Math.ceil(dayCount / 7)
// 父级控件 v-model 绑定
this.$emit('update:model', weekNum)
return weekNum
},
getWeekDateRange (date) {
// 计算当前日期是周几,ISO周从周一开始
var currentDay = date.getDay()
var distanceToMonday = currentDay === 0 ? 6 : currentDay - 1
// 计算当前周的周一和周日
var monday = new Date(date)
monday.setDate(date.getDate() - distanceToMonday)
var sunday = new Date(monday)
sunday.setDate(monday.getDate() + 6)
// 格式化日期为 yyyy-MM-dd
var format = (d) => d.toISOString().split('T')[0]
return [format(monday), format(sunday)]
},
getWeekDateRangeByWeekNumber (weekNumber, year) {
if (weekNumber < 1) {
return null
}
var januaryFirst = new Date(year, 0, 1)
var januaryFirstDayOfWeek = januaryFirst.getDay() === 0 ? 6 : januaryFirst.getDay() - 1 // 将周日从0转换为7
var firstMonday = new Date(januaryFirst)
if (januaryFirstDayOfWeek <= 3) {
// 如果1月1日至1月4日之间为周一至周四,则该周为第一周
firstMonday.setDate(januaryFirst.getDate() - januaryFirstDayOfWeek + 1)
} else {
// 否则,下周一为第一周的开始
firstMonday.setDate(januaryFirst.getDate() + 8 - januaryFirstDayOfWeek)
}
var weekStart = new Date(firstMonday)
weekStart.setDate(firstMonday.getDate() + (weekNumber - 1) * 7)
var weekEnd = new Date(weekStart)
weekEnd.setDate(weekStart.getDate() + 6)
// 格式化日期为 yyyy-MM-dd
var format = (d) => d.toISOString().split('T')[0]
return [format(weekStart), format(weekEnd)]
}
},
props: {
model: {
type: Number,
required: true
}
},
watch: {
model (val) {
if (val.length <= 1 || val < 0) {
this.weekNumber = this.getWeekNumber(new Date())
this.dateRange = this.getWeekDateRange(new Date())
} else {
// 使用val作为周数
this.weekNumber = val
if (val > 0) {
this.dateRange = this.getWeekDateRangeByWeekNumber(val, new Date().getFullYear())
} else {
this.dateRange = null
}
}
},
weekNumber (newVal, oldVal) {
// 当周数改变时,更新日期范围
if (newVal !== oldVal) {
if (newVal > 0) {
this.dateRange = this.getWeekDateRangeByWeekNumber(newVal, new Date().getFullYear())
} else {
this.dateRange = null
}
}
// 父级控件 v-model 绑定
this.$emit('update:model', newVal)
}
}
}
</script>
<style lang="scss" scoped>
// 调整高度
.el-form-item {
height: 10px;
}
</style>
[
0
,
52
]
[0,52]
[0,52],当
el-input-number
=0时,则表示后端系统不使用周数选择器作为判断依据。也可以将el-input-number
的取值范围强制设为[
1
,
52
]
[1,52]
[1,52],用多选控件控制是否启用的判断。
2.getWeekNumber
方法中添加了this.$emit('update:model', weekNum)
,用于将初始化后的值返回给父控件。
3.getWeekDateRangeByWeekNumber
方法中添加了if (weekNumber < 1)
的判断,防止意外的输入值。
三、C#后端代码实现
了解上面原理之后,依样画葫芦,我们可以通过周数计算日期范围,用于查询后数据分析。
这里我们简单实现一下代码作为应用参考。
3.1 类实现
public class ReportWeekCalculator
{
public int ReportWeek { get; set; }
public int Year { get; set; }
public ReportWeekCalculator(int reportWeek, int year)
{
ReportWeek = reportWeek;
Year = year;
}
public (DateTime, DateTime) GetWeekDateRange()
{
// 获取指定年份的1月1日
DateTime januaryFirst = new DateTime(Year, 1, 1);
// 获取1月1日是周几(将周日从0转换为7)
int januaryFirstDayOfWeek = januaryFirst.DayOfWeek == DayOfWeek.Sunday ? 6 : (int)januaryFirst.DayOfWeek - 1;
// 计算第一周周一的日期
DateTime firstMonday;
if (januaryFirstDayOfWeek <= 3) // 如果1月1日是周一至周四
{
firstMonday = januaryFirst.AddDays(-januaryFirstDayOfWeek);
}
else // 如果1月1日是周五、周六或周日
{
firstMonday = januaryFirst.AddDays(7 - januaryFirstDayOfWeek);
}
// 计算目标周的开始日期
DateTime startOfWeek = firstMonday.AddDays((ReportWeek - 1) * 7);
// 计算目标周的结束日期
DateTime endOfWeek = startOfWeek.AddDays(6);
return (startOfWeek, endOfWeek);
}
}
使用示例
var calculator = new ReportWeekCalculator(47, 2023); // 假设需要计算2023年第47周的日期范围
var (startOfWeek, endOfWeek) = calculator.GetWeekDateRange();
Console.WriteLine($"Week {calculator.ReportWeek} of {calculator.Year} starts on {startOfWeek:yyyy-MM-dd} and ends on {endOfWeek:yyyy-MM-dd}");
3.1 静态方法实现
public class CommonFunc
{
public static (DateTime, DateTime) GetWeekDateRange(int ReportWeek)
{
// 获取当前年份
int year = DateTime.Now.Year;
// 获取指定年份的1月1日
DateTime januaryFirst = new DateTime(year, 1, 1);
// 获取1月1日是周几(将周日从0转换为7)
int januaryFirstDayOfWeek = januaryFirst.DayOfWeek == DayOfWeek.Sunday ? 6 : (int)januaryFirst.DayOfWeek - 1;
// 计算第一周周一的日期
DateTime firstMonday;
if (januaryFirstDayOfWeek <= 3) // 如果1月1日是周一至周四
{
firstMonday = januaryFirst.AddDays(-januaryFirstDayOfWeek);
}
else // 如果1月1日是周五、周六或周日
{
firstMonday = januaryFirst.AddDays(7 - januaryFirstDayOfWeek);
}
// 计算目标周的开始日期
DateTime startOfWeek = firstMonday.AddDays((ReportWeek - 1) * 7);
// 计算目标周的结束日期
DateTime endOfWeek = startOfWeek.AddDays(6);
return (startOfWeek, endOfWeek);
}
}
使用示例
(DateTime startDt, DateTime endDt) = CommonFunc.GetWeekDateRange(searchDto.ReportWeek);
注:endOfWeek
取的是周日的00:00:00
,如果需要日期筛选,需要加一天后用<
符号或者截取到日期字段用<=
符号比较。
参考代码片段:
(DateTime startDt, DateTime endDt) = CommonFunc.GetWeekDateRange(searchDto.ReportWeek);
endDt = endDt.AddDays(1); //加一天
expression = expression.And(p => p.CreateTime >= startDt);
expression = expression.And(p => p.CreateTime < endDt);
总结
本篇博客中,我们深入探讨了周数选择器的实现,从理论到实践,涵盖了周数的计算逻辑和具体的代码实现。
首先,我们讨论了周数的定义、确定年初的周数,以及周数的具体计算方法。这部分内容基于ISO 8601标准,为理解和计算周数提供了必要的理论基础。
随后,我们转向实际的代码实现,详细介绍了几个关键函数:计算周数(getWeekNumber
)、获取特定日期所在周的日期范围(getWeekDateRange
),以及根据周数和年份获取特定周的日期范围(getWeekDateRangeByWeekNumber
)。这些函数是构建周数选择器的核心,展示了如何在Vue和ElementUI环境中处理日期和时间。
进一步,我们分析了周数选择器控件在Vue中的引用方式,包括控件的引入、注册,以及相关变量的初始化。这不仅展示了组件化开发的便捷性,也体现了Vue响应式系统的强大。
最后,我们提供了周数选择器的完整代码,这为读者提供了一个实用的参考模板,可以直接应用于项目或作为学习实践。
整体而言,本博客不仅介绍了周数选择器的实现,更提供了一种结合Vue和ElementUI开发复杂UI组件的有效途径。这对于追求高效、可维护的前端开发来说,无疑是极有价值的。
原文地址:https://blog.csdn.net/qq_31463571/article/details/134629925
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_15745.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!