feat(oa): 新增项目进度和进度步骤跟踪的API接口

添加项目进度管理和进度步骤跟踪的相关API接口,包括列表查询、详情获取、新增、修改、删除等功能
This commit is contained in:
砂糖
2025-11-07 17:18:33 +08:00
parent b569e4fef8
commit 08029c6406
9 changed files with 1115 additions and 63 deletions

View File

@@ -1,10 +1,5 @@
<template>
<view class="remaining-time" :class="computedClass">
<uni-icons
:type="isExpired ? 'clock' : 'time'"
:size="14"
class="icon"
></uni-icons>
<text class="text">{{ displayText }}</text>
</view>
</template>
@@ -13,53 +8,83 @@
export default {
name: 'RemainingTime',
props: {
// 截至日期(ISO格式'2025-12-31T23:59:59'
// 截至日期(支持多种格式或null
expireDate: {
type: String,
required: true,
type: [String, null], // 允许字符串或null
default: null, // 默认null
validator(value) {
// 验证日期格式有效性
// 允许null非null时检查是否能解析为有效日期
if (value === null) return true;
return !isNaN(Date.parse(value));
}
},
// 阈值天数(超过此值为绿色,否则红色)
// 阈值天数
thresholdDays: {
type: Number,
required: true,
default: 3,
default: 3,
validator(value) {
return value >= 0;
}
},
// 是否已完成
finished: {
type: Boolean,
default: false
}
},
computed: {
// 计算剩余天数(负数表示逾期)
// 计算剩余天数(处理null和无效日期)
remainingDays() {
// 如果无截止日期或日期无效返回null
if (!this.expireDate) return null;
const now = new Date();
const expire = new Date(this.expireDate);
// 无效日期处理
if (isNaN(expire.getTime())) return null;
const diffTime = expire - now;
// 转换为天数并四舍五入
return Math.round(diffTime / (1000 * 60 * 60 * 24));
},
// 是否已逾期
// 是否已逾期(仅在有有效日期时判断)
isExpired() {
return this.remainingDays < 0;
return this.remainingDays !== null && this.remainingDays < 0;
},
// 显示文本
// 显示文本(优先级:完成 > 无日期 > 逾期 > 剩余时间)
displayText() {
if (this.finished) {
return '已完成';
}
// 无截止日期的情况
if (this.remainingDays === null) {
return '无截止日期';
}
if (this.isExpired) {
return `已逾期 ${Math.abs(this.remainingDays)}`;
}
return `剩余 ${this.remainingDays}`;
},
// 计算样式类
computedClass() {
if (this.isExpired) {
return 'expired'; // 逾期状态
// 图标类型
getIconType() {
if (this.finished) {
return 'checkmark';
}
return this.remainingDays > this.thresholdDays
? 'normal' // 正常状态(超过阈值)
: 'warning'; // 警告状态(低于阈值)
if (this.remainingDays === null) {
return 'help'; // 无日期时显示帮助图标
}
return this.isExpired ? 'clock' : 'time';
},
// 样式类
computedClass() {
if (this.finished) {
return 'finished';
}
// 无截止日期的样式
if (this.remainingDays === null) {
return 'no-date';
}
if (this.isExpired) {
return 'expired';
}
return this.remainingDays > this.thresholdDays ? 'normal' : 'warning';
}
}
};
@@ -83,19 +108,30 @@ export default {
font-weight: 500;
}
/* 正常状态(超过阈值) */
/* 正常状态 */
.normal {
color: #00b42a; /* 绿色 */
color: #00b42a;
}
/* 警告状态(低于阈值) */
/* 警告状态 */
.warning {
color: #f53f3f; /* 红色 */
color: #f53f3f;
}
/* 逾期状态 */
.expired {
background-color: #fef0f0;
color: #f53f3f; /* 红色背景+红色文字 */
color: #f53f3f;
}
/* 完成状态 */
.finished {
background-color: #00b42a;
color: #ffffff;
}
/* 无截止日期状态 */
.no-date {
color: #888888; /* 灰色文字 */
}
</style>