diff --git a/backend/src/main/java/com/designhub/entity/DemandType.java b/backend/src/main/java/com/designhub/entity/DemandType.java
index 7546343..fdda901 100644
--- a/backend/src/main/java/com/designhub/entity/DemandType.java
+++ b/backend/src/main/java/com/designhub/entity/DemandType.java
@@ -47,10 +47,10 @@ public class DemandType implements Serializable {
private Integer unitScoreInt;
/**
- * 预估工时(小时)
+ * 预估工时(小时,支持小数如0.05表示3分钟)
*/
@TableField("estimated_hours")
- private Integer estimatedHours;
+ private BigDecimal estimatedHours;
/**
* 类型描述
diff --git a/frontend/src/views/CreateTask.vue b/frontend/src/views/CreateTask.vue
index a7e1521..d63717b 100644
--- a/frontend/src/views/CreateTask.vue
+++ b/frontend/src/views/CreateTask.vue
@@ -15,6 +15,22 @@
管理员身份,无需积分即可发起任务
本次任务预估消耗: {{ estimatedScore }} 分
+
+
+
+
+ 累计时效:
+ {{ formattedEstimatedTime }}
+
+
+ 预计完成:
+ {{ estimatedDeadline }}
+
+
+
+ 按8小时/工作日计算,超过8小时按整天计算
+
+
@@ -884,6 +900,75 @@ const estimatedScore = computed(() => {
return totalScore
})
+// 计算累计时效(小时)
+const estimatedTotalHours = computed(() => {
+ let totalHours = 0
+
+ for (const item of formData.taskTypes) {
+ if (item.taskTypeId && item.quantity > 0) {
+ const selectedType = taskTypes.value.find(t => t.id === item.taskTypeId)
+ if (selectedType && selectedType.estimatedHours) {
+ totalHours += selectedType.estimatedHours * item.quantity
+ }
+ }
+ }
+
+ return totalHours
+})
+
+// 格式化时效显示
+const formattedEstimatedTime = computed(() => {
+ const hours = estimatedTotalHours.value
+ if (hours === 0) return '--'
+
+ if (hours < 1) {
+ return `${Math.round(hours * 60)}分钟`
+ } else if (hours < 24) {
+ const h = Math.floor(hours)
+ const m = Math.round((hours - h) * 60)
+ return m > 0 ? `${h}小时${m}分钟` : `${h}小时`
+ } else {
+ const days = Math.floor(hours / 24)
+ const remainHours = Math.round(hours % 24)
+ return remainHours > 0 ? `${days}天${remainHours}小时` : `${days}天`
+ }
+})
+
+// 计算预计完成时间(考虑8小时工作制)
+const estimatedDeadline = computed(() => {
+ const totalHours = estimatedTotalHours.value
+ if (totalHours === 0) return '--'
+
+ const now = new Date()
+ const WORK_HOURS_PER_DAY = 8 // 每天工作8小时
+
+ // 计算需要多少个工作日
+ let workDays = Math.floor(totalHours / WORK_HOURS_PER_DAY)
+ let remainingHours = totalHours % WORK_HOURS_PER_DAY
+
+ // 如果超过8小时,按24小时(1天)计算
+ if (totalHours > WORK_HOURS_PER_DAY) {
+ // 超过8小时的部分,每8小时算1个工作日,但日历上是24小时
+ const totalDays = Math.ceil(totalHours / WORK_HOURS_PER_DAY)
+ const deadline = new Date(now.getTime() + totalDays * 24 * 60 * 60 * 1000)
+ return formatDeadline(deadline)
+ } else {
+ // 8小时内,当天完成
+ const deadline = new Date(now.getTime() + totalHours * 60 * 60 * 1000)
+ return formatDeadline(deadline)
+ }
+})
+
+// 格式化截止时间
+const formatDeadline = (date: Date) => {
+ const year = date.getFullYear()
+ const month = String(date.getMonth() + 1).padStart(2, '0')
+ const day = String(date.getDate()).padStart(2, '0')
+ const hour = String(date.getHours()).padStart(2, '0')
+ const minute = String(date.getMinutes()).padStart(2, '0')
+ return `${year}-${month}-${day} ${hour}:${minute}`
+}
+
// 计算流水线分组
const pipelineGroups = computed(() => {
if (formData.taskTypes.length === 0) {
@@ -1621,6 +1706,44 @@ onUnmounted(() => {
strong {
color: $brand-primary;
+ }
+}
+
+.time-estimate {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: $space-md;
+ margin-top: $space-md;
+ padding: $space-md;
+ background: rgba(255, 255, 255, 0.03);
+ border-radius: $radius-small;
+ border: 1px solid rgba(255, 255, 255, 0.06);
+
+ .estimate-item {
+ display: flex;
+ align-items: center;
+ gap: $space-xs;
+
+ .estimate-label {
+ color: $text-tertiary;
+ font-size: $font-size-sm;
+ }
+
+ .estimate-value {
+ color: $brand-primary;
+ font-weight: 600;
+ font-size: $font-size-base;
+ }
+ }
+
+ .estimate-tip {
+ flex-basis: 100%;
+ display: flex;
+ align-items: center;
+ font-size: $font-size-xs;
+ color: $text-tertiary;
+ margin-top: $space-xs;
font-weight: $font-weight-semibold;
}
}
diff --git a/frontend/src/views/Settings.vue b/frontend/src/views/Settings.vue
index 8333387..fc19887 100644
--- a/frontend/src/views/Settings.vue
+++ b/frontend/src/views/Settings.vue
@@ -1265,14 +1265,19 @@
-
+
+
+
+ 时效会根据任务数量累计计算(如5个任务×0.05小时=0.25小时)
+