<think>根据用户需求,我们需要在Vue2项目中实现一个功能:根据时间规则判断填报状态及得分,并在界面中用不同的颜色展示状态。
时间规则:
1. 按时填报:每月25号00:00点至下月6号24:00点,记满分(100分)
2. 补报:下月7号00:00点至20号24:00点,记半分(50分)
3. 不能填报:下月21号以后,记0分
4. 每月21号后绩效评估出上月考核结果
界面颜色规则:
- 蓝色:需要填报(待填报)
- 红色:填报完成后未交(注意:这里用户描述为“填报完成后红色为未交”,但逻辑上填报完成后应该不是未交,可能是用户笔误。根据上下文,我推测红色应该是已填报但未到截止时间(即未到21号)并且未提交的状态?但用户描述中并没有明确。我们需要仔细分析用户需求)
重新梳理用户关于颜色的描述:
- 蓝色:需要填报(待填报) -> 应该是还未填报的状态
- 红色:未交 -> 应该是填报了但未提交(或者未完成提交?)
- 浅绿色:迟交(补报阶段提交)
- 深绿色:按时(按时阶段提交)
但是用户说“填报完成后红色为未交”,这里可能有两种理解:
1. 用户可能指的是:一旦用户开始填报(即进入填报页面编辑),但尚未提交,此时显示为红色(未交)。
2. 或者,用户可能指的是在填报截止后(21号以后)显示为红色(未交)?但用户又说21号以后不能填报,所以21号以后应该就不能操作了。
另外,用户提到“每月21号后绩效评估出上月考核结果”,这意味着21号以后系统会给出上月的考核结果,此时填报已经截止(不能填报),应该只展示结果。
根据用户描述,我们可能需要考虑以下状态:
- 待填报(蓝色):当前时间在可以填报的时间段内(25号到下月20号),且用户还未开始填报。
- 按时提交(深绿色):在按时阶段(25号至下月6号)提交。
- 补报提交(浅绿色):在补报阶段(下月7号至20号)提交。
- 未提交(红色):在填报时间段内(25号至下月20号)已经开始填报(有保存记录)但未提交,或者超过补报时间(21号以后)未提交(记为0分)。
注意:用户需求中有一个点需要注意:填报完成后红色为未交。这里可能是指用户保存了填报内容但未提交,此时状态为“未交”(红色)。
因此,我们可能需要以下数据:
- 当前时间(用于判断时间段)
- 用户填报记录(包括保存时间、提交时间等)
由于用户没有给出具体的数据结构,我们假设每个月的填报数据包含以下字段(示例):
- `state`:填报状态(0: 未开始,1: 已保存未提交,2: 已提交)
- `submitTime`:提交时间(如果已提交)
- `saveTime`:最后保存时间(用于判断未提交时的时间点)
但是,我们还需要根据当前时间判断当前所处的填报阶段(按时、补报、已截止)以及应该显示的状态。
步骤:
1. 定义时间规则函数,根据当前时间和月份判断当前所处的阶段(按时、补报、不能填报)。
2. 根据当前时间和用户填报的记录(保存时间、提交时间等)确定状态(待填报、按时、补报、未交等)。
3. 根据状态设置对应的颜色。
由于用户需求中涉及跨月的时间判断,我们需要处理日期计算。
我们设计一个工具函数,用于判断给定时间(或当前时间)相对于指定月份的时间段。
假设我们要判断的时间是当前时间(也可以传入时间),以及要判断的月份(因为是上个月的考核,所以可能是判断上个月的数据)。
例如,当前是2024年7月10日,那么我们要判断的是2024年6月的填报状态(因为6月的填报时间段是6月25日到7月6日按时,7月7日到20日补报,7月21日截止)。
所以,关键点:我们要针对哪个月份进行判断?根据用户描述,每月21号后评估上月的考核结果,所以:
- 在25号到下月20号之间,填报的是当前月份的上个月的数据?还是当前月的数据?
用户需求中描述的时间段是“每月25号到下月6号”,这个时间段填报的是哪个月的数据?应该是上个月的数据。
例如:6月25日到7月6日填报的是6月份的数据(即上月),7月25日到8月6日填报的是7月份的数据(即当月?不对,应该是7月25日填报7月?但用户没说清楚)。
根据用户需求:每月21号后评估出上月考核结果,那么填报的应该是上个月的数据。所以填报时间段(25号到下月6号)是在下个月的7号之前填报上个月的数据。
因此,当我们判断状态时,需要知道是针对哪个月份(通常是上个月)的数据。
但是,在界面上,我们可能同时展示多个月份的数据?或者只展示当前需要填报的月份?用户需求中没有明确,我们假设是展示当前需要填报的状态(即最近的一个填报周期)。
为了简化,我们假设每个填报项对应一个月份(例如,每个月的填报项对应上个月的考核数据)。
因此,在组件中,我们可以为每个填报项(代表某个月份)计算状态。
具体实现:
1. 定义计算状态的函数(需要传入:填报项对应的月份,以及用户对该填报项的操作记录(保存时间、提交时间))
2. 根据当前时间,判断该填报项所处的阶段和状态。
步骤:
- 首先,计算填报项对应的月份(假设为targetMonth,格式为YYYY-MM)
- 那么该填报项的填报时间段为:
- 按时填报开始时间:targetMonth的下个月25号?不对,应该是targetMonth的当月25号开始,持续到下个月(即targetMonth+1个月)的6号24:00。
- 例如:targetMonth=2024-06,那么按时填报时间段:2024-06-25 00:00:00 到 2024-07-06 24:00:00
- 补报时间段:2024-07-07 00:00:00 到 2024-07-20 24:00:00
- 截止时间:2024-07-21 00:00:00
注意:这里targetMonth是填报项所针对的月份(即考核的月份),填报时间是下个月的25号开始(这里有点绕,用户说的是“每月25号”,指的是考核月份的下个月的25号?还是考核月份的当月25号?)
根据用户描述:“每月25号00:00点开始至下月6号24:00点”,这里的“每月”是指考核月份还是自然月?结合上下文,应该是考核月份的下一个月(因为25号已经是考核月份的下一个月了)。
例如:6月份的考核数据,填报时间是7月25日到8月6日?不对,这样跨度太大。实际上,6月份的考核数据填报时间应该是7月25日?这不太合理,因为6月刚过,7月1号就可以开始填报,为什么要等到7月25?
重新理解:用户可能指的是自然月,即:
- 1月25日00:00到2月6日24:00填报的是1月份的数据(1月的数据在1月25日就可以开始填报?但1月还没结束,所以不合理)。
因此,我推测:填报的是上个月的数据。例如:
- 2月25日00:00到3月6日24:00填报的是1月份的数据?这也不对,因为2月25日填报1月数据太晚了。
实际上,用户需求应该是:当月填报上月的数据。比如,7月份填报6月份的数据,那么填报时间应该是7月1日开始?但用户给的是25号开始。
这可能是因为业务需求,在25号才开始填报。所以,我们按照用户描述来实现。
因此,对于考核月份为YYYY-MM的数据:
- 按时填报开始时间:YYYY-MM-25 00:00:00 (注意:这里的YYYY-MM是考核月份的下一个月?还是考核月份?)
用户说“每月25号开始”,这个“每月”指的是考核月份的下一个月。例如:考核6月,那么填报开始时间是7月25日。
所以,考核月份为2024-06的数据:
- 按时填报时间段:2024-07-25 00:00:00 到 2024-08-06 24:00:00
- 补报时间段:2024-08-07 00:00:00 到 2024-08-20 24:00:00
- 截止时间:2024-08-21 00:00:00
但是这里有一个问题:7月25日才开始填报6月的数据,而7月25日已经是下一个月的下一个月了(6月、7月、8月)。这样跨度太大了,通常不会这样设计。
所以,我怀疑用户描述中的“每月25号”指的是考核月份当月的25号?比如,6月25日到7月6日填报6月的数据(此时6月还没结束,但25号以后可以填报当月的数据)。这样,6月25日到30日填报6月数据(当月),7月1日到6日填报6月数据(跨月)。
这样理解比较合理。因此,我们按照:
- 考核月份为YYYY-MM的数据,其填报时间段为:
- 按时填报:YYYY-MM-25 00:00:00 到 (YYYY-MM的下个月)-06 24:00:00
- 补报: (YYYY-MM的下个月)-07 00:00:00 到 (YYYY-MM的下个月)-20 24:00:00
- 21号以后不能填报。
例如:考核月份2024-06
- 按时填报:2024-06-25 00:00:00 到 2024-07-06 24:00:00
- 补报:2024-07-07 00:00:00 到 2024-07-20 24:00:00
- 2024-07-21 00:00:00以后不能填报。
这样,在6月25日到7月6日之间提交为按时,7月7日到20日提交为补报(迟交)。
因此,我们的函数需要计算某个考核月份(YYYY-MM)的填报时间段。
在Vue组件中,我们可以这样设计:
1. 定义计算状态的函数,它需要:
- 考核月份(month,字符串,格式为"YYYY-MM")
- 用户操作记录(对象,包含保存时间、提交时间、当前状态等)
2. 根据当前时间,首先判断当前时间在考核月份的时间段中所处的阶段(按时、补报、已截止、未开始?)
- 注意:未开始是指当前时间早于考核月份的25号00:00?但是用户需求中,填报是从25号开始,所以25号之前不能填报(不能填报,显示什么?用户需求没说,但根据规则,21号以后评估上月结果,所以25号之前可能是上个月的评估阶段?)
但是,我们这里针对的是当前考核月份(比如2024-06),那么:
- 在2024-06-25之前,这个考核月份的数据还不能填报(未开始),应该显示什么?用户需求可能要求提前展示(蓝色?待填报?但是时间没到,不能填报)。所以,我们可能需要根据当前时间判断是否在填报期内。
因此,我们分两个层面判断:
a. 填报项是否可操作(是否在填报期内)
b. 用户的操作状态(是否保存,是否提交)
3. 状态定义:
- 待填报(蓝色):当前时间在填报期内(按时或补报阶段)且用户未保存(或未开始填报)
- 已填报未提交(红色):当前时间在填报期内,用户保存了但未提交
- 按时提交(深绿色):在按时阶段提交
- 补报提交(浅绿色):在补报阶段提交
- 已截止未提交(红色?):在填报期截止后(21号以后)且未提交(记0分)
注意:用户需求中,21号以后不能填报,所以21号以后,如果未提交,则显示为未交(红色?)并且不能再操作。
另外,21号以后会出考核结果,所以可能还要显示分数(0分)。
4. 得分计算:
- 按时提交:100分
- 补报提交:50分
- 未提交:0分
得分可以在21号以后显示。
实现步骤:
第一步:编写工具函数,用于获取考核月份对应的三个关键时间点(按时开始、补报开始、截止)
输入:考核月份(字符串,如'2024-06')
输出:
onTimeStart: 按时填报开始时间(Date对象,当月25号00:00)
onTimeEnd: 按时填报结束时间(下月6号24:00,即下月7号00:00减1毫秒?或者直接设置时间为23:59:59.999)
lateStart: 补报开始时间(下月7号00:00)
lateEnd: 补报结束时间(下月20号24:00,即下月21号00:00减1毫秒)
deadline: 截止时间(下月21号00:00)
注意:由于涉及到月份的加减,我们可以使用moment.js或day.js,但为了减少依赖,也可以使用原生Date对象。
第二步:编写函数,根据当前时间和用户操作记录(保存时间、提交时间)返回状态和得分。
状态枚举:
- 'not_started': 未开始(在按时填报开始之前)
- 'on_time_fill': 按时填报期(未操作)
- 'late_fill': 补报期(未操作)
- 'draft': 已保存未提交(在填报期内)
- 'on_time_submitted': 按时提交
- 'late_submitted': 补报提交
- 'expired': 已截止(未提交)
第三步:根据状态,映射到颜色:
- not_started: 未开始,可能不显示或灰色(用户需求未提及,但根据需求,蓝色是待填报,所以未开始可能不属于待填报,我们暂时用灰色)
- on_time_fill, late_fill: 待填报 -> 蓝色
- draft: 已保存未提交 -> 红色
- on_time_submitted: 按时提交 -> 深绿色
- late_submitted: 补报提交 -> 浅绿色
- expired: 已截止未提交 -> 红色(用户需求:未交)
注意:用户需求中,填报完成后红色为未交,这里“填报完成”可能指的是保存了但未提交。所以红色对应draft状态(已保存未提交)和expired状态(已截止未提交)。但是用户描述中,红色是“填报完成后未交”,所以draft状态应该是红色,而expired状态也是未交,所以也是红色。
另外,在截止时间之前,如果用户保存了但未提交,在填报期内都是红色,一旦过了截止时间,即使保存了未提交也会变成expired(红色)。
第四步:在界面上,根据状态显示对应的颜色,并且得分可以在提交后立即显示(但用户需求是21号后评估结果,所以21号前也可以显示得分?用户需求是21号后出结果,所以21号前可能不显示得分?)
但是,用户需求中得分是根据提交时间确定的,所以提交后就可以知道得分(按时提交100,补报提交50)。所以,在提交后就可以显示得分,而21号后则是最终确定(未提交的0分也在21号后显示)。
因此,我们可以在用户提交后立即显示得分,未提交的在21号后显示0分。
代码实现:
由于用户使用Vue2,我们可以在methods或computed中实现。
假设我们有一个填报项的数据结构如下:
```javascript
reportItem: {
month: '2024-06', // 考核月份
saveTime: null, // 最后保存时间,Date对象或时间戳,如果没有保存则为null
submitTime: null, // 提交时间,Date对象或时间戳,如果没有提交则为null
// 其他字段...
}
```
然后,我们编写一个计算状态的函数:
```javascript
// 工具函数:计算考核月份的时间节点
function getTimeNodes(month) {
// 解析month,格式为'YYYY-MM'
const [year, monthStr] = month.split('-').map(Number);
// 当前考核月份的下个月
let nextYear = year;
let nextMonth = monthStr + 1;
if (nextMonth === 13) {
nextMonth = 1;
nextYear += 1;
}
// 按时填报开始时间:考核月份的25号00:00
const onTimeStart = new Date(year, monthStr - 1, 25, 0, 0, 0);
// 按时填报结束时间:下个月6号23:59:59.999
const onTimeEnd = new Date(nextYear, nextMonth - 1, 6, 23, 59, 59, 999);
// 补报开始时间:下个月7号00:00
const lateStart = new Date(nextYear, nextMonth - 1, 7, 0, 0, 0);
// 补报结束时间:下个月20号23:59:59.999
const lateEnd = new Date(nextYear, nextMonth - 1, 20, 23, 59, 59, 999);
// 截止时间(补报结束后):下个月21号00:00
const deadline = new Date(nextYear, nextMonth - 1, 21, 0, 0, 0);
return {
onTimeStart,
onTimeEnd,
lateStart,
lateEnd,
deadline
};
}
// 计算填报项的状态和得分
function calculateReportStatus(item, currentTime = new Date()) {
const { month, saveTime, submitTime } = item;
const timeNodes = getTimeNodes(month);
// 当前时间
const now = currentTime;
// 如果已经提交,则根据提交时间判断是按时还是补报
if (submitTime) {
const submit = new Date(submitTime);
if (submit >= timeNodes.onTimeStart && submit <= timeNodes.onTimeEnd) {
return { status: 'on_time_submitted', score: 100 };
} else if (submit >= timeNodes.lateStart && submit <= timeNodes.lateEnd) {
return { status: 'late_submitted', score: 50 };
}
// 如果提交时间不在填报期内(比如在25号之前提交?不可能,因为25号才开始),或者超过了补报时间,则认为是无效提交?但一般不会,所以这里不处理
}
// 未提交
// 判断当前时间所处的阶段
if (now < timeNodes.onTimeStart) {
// 未开始
return { status: 'not_started', score: 0 };
} else if (now >= timeNodes.onTimeStart && now <= timeNodes.onTimeEnd) {
// 按时填报期内
if (saveTime) {
// 保存过但未提交 -> 草稿状态(待提交)
return { status: 'draft', score: 0 }; // 得分0,因为未提交
} else {
// 未保存过,待填报
return { status: 'on_time_fill', score: 0 };
}
} else if (now >= timeNodes.lateStart && now <= timeNodes.lateEnd) {
// 补报期内
if (saveTime) {
return { status: 'draft', score: 0 };
} else {
return { status: 'late_fill', score: 0 };
}
} else if (now >= timeNodes.deadline) {
// 已截止
// 如果截止后还未提交,则状态为expired
return { status: 'expired', score: 0 };
}
// 如果当前时间在onTimeEnd和lateStart之间(即7号之前,但25号到下月6号是按时,7号开始补报,所以中间可能会有几个小时的空隙?)
// 实际上,按时结束是6号24:00(即7号00:00前一瞬),补报开始是7号00:00,所以不会有空隙。
// 同样,补报结束和截止时间也是连续的。
// 默认返回未开始
return { status: 'not_started', score: 0 };
}
```
然后,在Vue组件中,我们可以这样使用:
```javascript
computed: {
reportStatus() {
return calculateReportStatus(this.reportItem);
},
statusColor() {
const status = this.reportStatus.status;
const colorMap = {
not_started: 'grey',
on_time_fill: 'blue',
late_fill: 'blue',
draft: 'red',
on_time_submitted: 'darkgreen',
late_submitted: 'lightgreen',
expired: 'red'
};
return colorMap[status] || 'grey';
}
}
```
在模板中,我们可以根据状态和颜色来设置样式。
注意:用户需求中,蓝色为需要填报(即待填报状态:on_time_fill和late_fill),红色为未交(draft和expired),浅绿色为迟交(late_submitted),深绿色为按时(on_time_submitted)。
另外,关于得分,我们可以在界面上显示:
```html
<div :style="{ color: statusColor }">
状态:{{ reportStatus.status }}, 得分:{{ reportStatus.score }}
</div>
```
但是,用户需求中21号后评估结果,所以21号前对于未提交的我们不显示得分(显示0分?)或者不显示?用户需求没有明确,我们按照函数计算出的得分显示即可(未提交就是0分,提交了就有分数)。
注意:以上函数中,在截止时间之前,未提交的得分都是0,提交后就会显示对应得分。
但是,在截止时间之后,未提交的得分也是0。
所以,得分可以在任何时间显示(提交后立即显示得分,未提交的则一直显示0分,但用户可能希望在21号后才显示0分?)。如果需要,我们可以调整得分的显示逻辑:在21号之前,未提交的不显示得分(显示为'--'),21号后显示0分。
我们可以在计算状态时,增加一个属性来控制是否显示得分(或者单独写一个计算得分的函数,在21号后显示最终得分,21号前只显示已提交的得分)。
不过,用户需求的描述是“21号后绩效评估出上月考核结果”,所以21号后才会出结果。因此,21号前不显示未提交的得分(只显示已提交的得分),21号后显示所有得分(包括未提交的0分)。
修改计算状态的函数:
在返回的对象中增加一个属性`showScore`,表示是否显示得分(最终结果)。或者,我们可以根据状态和当前时间来决定显示什么。
为了简化,我们可以在calculateReportStatus函数中不改变得分,而在computed中根据状态和当前时间来判断显示什么得分。
例如:
```javascript
computed: {
displayScore() {
const status = this.reportStatus.status;
const score = this.reportStatus.score;
const timeNodes = getTimeNodes(this.reportItem.month);
const now = new Date();
// 如果当前时间在截止时间之后(21号后),则显示得分
if (now >= timeNodes.deadline) {
return score;
} else {
// 21号前,只有已提交的状态才显示得分,未提交的不显示
if (status === 'on_time_submitted' || status === 'late_submitted') {
return score;
} else {
return '--'; // 或者null,不显示
}
}
}
}
```
这样,在模板中用displayScore来显示得分。
注意:以上代码只是示例,实际应用中需要根据具体业务调整。
最后,由于用户的需求可能涉及多个填报项(每个月的),所以需要遍历多个填报项,每个填报项都进行状态和颜色的计算。
以上实现仅供参考,具体实现时可能需要根据实际数据结构调整。
由于代码较长,我们只展示关键部分。在Vue组件中,需要引入getTimeNodes和calculateReportStatus函数,可以在methods中定义,或者单独放在一个工具文件中。
相关问题:
1. 如何优化时间节点的计算,避免重复计算?
2. 如何处理时区问题?
3. 如何在没有保存时间的情况下判断用户是否开始填报(比如,用户可能没有保存,但有其他标记)?
4. 如何与后端API对接,保存和提交填报数据?
</think>根据您的需求,我将在Vue2中实现按时间规则判断填报状态及得分并展示不同状态颜色的功能。以下是完整的解决方案:
```vue
<template>
<div class="report-container">
<div
v-for="(item, index) in reportItems"
:key="index"
:class="['report-item', statusClass(item)]"
>
<div class="month">{{ item.month }}月考核</div>
<div class="status">状态: {{ getStatusText(item) }}</div>
<div class="score">得分: {{ calculateScore(item) }}</div>
<button
v-if="isEditable(item)"
@click="handleReport(item)"
>
{{ item.submitted ? "修改" : "填报" }}
</button>
<div v-else class="expired">已截止填报</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
reportItems: [
{ month: '2023-10', lastSave: null, submitted: false, submitTime: null },
{ month: '2023-11', lastSave: new Date(2023, 11, 15), submitted: false, submitTime: null },
{ month: '2023-12', lastSave: new Date(2023, 11, 28), submitted: true, submitTime: new Date(2023, 11, 30) },
]
};
},
methods: {
// 获取考核月份的时间节点
getTimeNodes(month) {
const [yearStr, monthStr] = month.split('-');
const year = parseInt(yearStr);
const monthNum = parseInt(monthStr);
// 按时填报时间段:当月25日00:00 - 下月6日24:00
const onTimeStart = new Date(year, monthNum - 1, 25);
const onTimeEnd = new Date(year, monthNum, 6, 23, 59, 59);
// 补报时间段:下月7日00:00 - 下月20日24:00
const lateStart = new Date(year, monthNum, 7);
const lateEnd = new Date(year, monthNum, 20, 23, 59, 59);
// 截止时间:下月21日00:00
const deadline = new Date(year, monthNum, 21);
return { onTimeStart, onTimeEnd, lateStart, lateEnd, deadline };
},
// 判断当前填报状态
getReportStatus(item) {
const now = new Date();
const nodes = this.getTimeNodes(item.month);
// 判断是否在填报时间段内
if (now >= nodes.onTimeStart && now <= nodes.onTimeEnd) {
return item.submitted ? 'on_time' : 'pending';
}
if (now >= nodes.lateStart && now <= nodes.lateEnd) {
return item.submitted ? 'late' : 'pending';
}
if (now > nodes.deadline) {
return item.submitted ? (item.submitTime <= nodes.onTimeEnd ? 'on_time' : 'late') : 'expired';
}
return 'not_started';
},
// 计算得分(满分100分)
calculateScore(item) {
const status = this.getReportStatus(item);
if (status === 'on_time') return 100;
if (status === 'late') return 50;
if (status === 'expired' && !item.submitted) return 0;
return '-';
},
// 获取状态文本
getStatusText(item) {
const status = this.getReportStatus(item);
const statusMap = {
pending: '待提交',
on_time: '按时提交',
late: '迟交',
expired: '未提交(已截止)',
not_started: '未开始'
};
return statusMap[status] || '未知状态';
},
// 判断是否可编辑
isEditable(item) {
const status = this.getReportStatus(item);
return status === 'pending' || status === 'on_time' || status === 'late';
},
// 状态对应的CSS类
statusClass(item) {
const status = this.getReportStatus(item);
return {
'pending': !item.submitted && this.isEditable(item),
'on-time': status === 'on_time',
'late': status === 'late',
'expired': status === 'expired'
};
},
// 处理填报操作
handleReport(item) {
if (item.submitted) {
// 修改已提交的报告
console.log(`修改${item.month}月报告`);
} else if (item.lastSave) {
// 提交保存过的报告
item.submitted = true;
item.submitTime = new Date();
console.log(`提交${item.month}月报告`);
} else {
// 新建报告
item.lastSave = new Date();
console.log(`新建${item.month}月报告`);
}
}
}
};
</script>
<style scoped>
.report-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
padding: 20px;
}
.report-item {
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
transition: all 0.3s ease;
}
/* 待填报状态(蓝色) */
.report-item.pending {
background-color: #e6f7ff;
border-color: #91d5ff;
}
/* 按时提交(深绿色) */
.report-item.on-time {
background-color: #f6ffed;
border-color: #b7eb8f;
}
/* 迟交(浅绿色) */
.report-item.late {
background-color: #f0fff3;
border-color: #95de64;
}
/* 未提交/已截止(红色) */
.report-item.expired {
background-color: #fff1f0;
border-color: #ffa39e;
}
.month {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
}
.status, .score {
margin: 8px 0;
}
button {
margin-top: 15px;
padding: 8px 16px;
background-color: #1890ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #40a9ff;
}
.expired {
margin-top: 15px;
color: #ff4d4f;
font-weight: bold;
}
</style>
```
### 功能说明
1. **时间规则实现**:
- 按时填报:每月25日00:00至下月6日24:00(如11月25日-12月6日)
- 补报:下月7日00:00至20日24:00(如12月7日-12月20日)
- 截止:下月21日00:00后不可填报(如12月21日)
2. **状态判断逻辑**:
- 蓝色(待填报):在填报期内未提交
- 深绿色(按时):在按时填报期内提交
- 浅绿色(迟交):在补报期内提交
- 红色(未交):截止后未提交
3. **得分计算**:
```javascript
calculateScore(item) {
const status = this.getReportStatus(item);
if (status === 'on_time') return 100; // 按时提交满分
if (status === 'late') return 50; // 补报半额
if (status === 'expired') return 0; // 截止未交0分
return '-'; // 其他情况不显示分数
}
```
4. **数据管理**:
- `lastSave`:最后保存时间
- `submitted`:是否已提交
- `submitTime`:提交时间(用于判断按时/迟交)
### 使用说明
1. **初始化数据**:
```javascript
reportItems: [
{ month: '2023-11', lastSave: null, submitted: false },
{ month: '2023-12', lastSave: new Date(2023, 11, 28), submitted: true }
]
```
2. **状态更新**:
- "填报"按钮:首次填写时保存草稿
- "提交"按钮:确认提交(状态变为按时/迟交)
- "修改"按钮:已提交的报告可修改
3. **绩效评估**:
- 每月21日后自动计算上月得分
- 截止后不可修改(显示"已截止填报")
### 注意事项
1. 日期处理使用JavaScript的`Date`对象,月份参数为0-11(0代表1月)
2. 实际项目中应添加完整的表单组件和API交互
3. 建议使用day.js或moment.js处理复杂日期计算
4. 截止判断使用`new Date(year, month, 21)`精确到下月21日00:00