129 lines
3.8 KiB
Vue
129 lines
3.8 KiB
Vue
|
|
<template>
|
|||
|
|
<view>
|
|||
|
|
<node-list v-for="(g, idx) in taskShowList" :key="g.id" :index="idx + 1" :last="idx === taskShowList.length - 1">
|
|||
|
|
<view class="group-head">
|
|||
|
|
<view class="group-title">{{ g.title }}</view>
|
|||
|
|
<view class="group-toggle" @click.stop="toggle(g.id)">
|
|||
|
|
<view class="toggle-text">{{ shrinkMap[g.id] ? '展开' : '收起' }}</view>
|
|||
|
|
<uni-icons class="toggle-icon" size="12" :type="shrinkMap[g.id] ? 'arrowup' : 'arrowdown'" color="#6b7280" />
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view v-if="!shrinkMap[g.id]" class="group-body">
|
|||
|
|
<plan-node-item v-for="(t, tIdx) in g.list" :key="String(t.taskId || tIdx)" :item="t" :classnames="tIdx ? 'mt-20' : ''" />
|
|||
|
|
</view>
|
|||
|
|
</node-list>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
import { computed, ref } from 'vue';
|
|||
|
|
import dayjs from 'dayjs';
|
|||
|
|
import nodeList from './node-list.vue';
|
|||
|
|
import planNodeItem from './plan-node-item.vue';
|
|||
|
|
|
|||
|
|
const props = defineProps({
|
|||
|
|
taskList: { type: Array, default: () => [] },
|
|||
|
|
planExecutionTime: { type: String, default: '' },
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const shrinkMap = ref({});
|
|||
|
|
|
|||
|
|
function toggle(id) {
|
|||
|
|
shrinkMap.value[id] = !shrinkMap.value[id];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function timeTypeTransform(timeType) {
|
|||
|
|
if (!timeType || timeType === 'day') return '天';
|
|||
|
|
if (timeType === 'week') return '周';
|
|||
|
|
if (timeType === 'month') return '月';
|
|||
|
|
if (timeType === 'year') return '年';
|
|||
|
|
return String(timeType);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function normalizedDays(taskTime, timeType) {
|
|||
|
|
const t = typeof taskTime === 'number' ? taskTime : 0;
|
|||
|
|
if (timeType === 'week') return t * 7;
|
|||
|
|
if (timeType === 'month') return t * 30;
|
|||
|
|
if (timeType === 'year') return t * 365;
|
|||
|
|
return t;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function dayTransform(baseDate, taskTime, timeType) {
|
|||
|
|
if (!baseDate) return '';
|
|||
|
|
if (!dayjs(baseDate).isValid()) return '';
|
|||
|
|
const t = typeof taskTime === 'number' ? taskTime : 0;
|
|||
|
|
const unit = ['day', 'week', 'month', 'year'].includes(String(timeType || '')) ? String(timeType) : 'day';
|
|||
|
|
return dayjs(baseDate).add(t, unit).format('YYYY-MM-DD');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const taskShowList = computed(() => {
|
|||
|
|
if (!Array.isArray(props.taskList) || props.taskList.length === 0) return [];
|
|||
|
|
|
|||
|
|
const grouped = props.taskList.reduce((acc, task) => {
|
|||
|
|
const obj = task && typeof task === 'object' ? task : {};
|
|||
|
|
const timeKey = normalizedDays(obj.taskTime, obj.timeType);
|
|||
|
|
const key = String(timeKey);
|
|||
|
|
if (!acc[key]) acc[key] = [];
|
|||
|
|
acc[key].push(obj);
|
|||
|
|
return acc;
|
|||
|
|
}, {});
|
|||
|
|
|
|||
|
|
const baseDate = props.planExecutionTime && dayjs(props.planExecutionTime).isValid() ? props.planExecutionTime : '';
|
|||
|
|
return Object.entries(grouped)
|
|||
|
|
.sort((a, b) => Number(a[0]) - Number(b[0]))
|
|||
|
|
.map(([key, list]) => {
|
|||
|
|
const first = list[0] || {};
|
|||
|
|
const taskTime = typeof first.taskTime === 'number' ? first.taskTime : 0;
|
|||
|
|
const unit = timeTypeTransform(first.timeType);
|
|||
|
|
const isToday = (first.timeType === 'day' || !first.timeType) && taskTime === 0;
|
|||
|
|
const offsetText = isToday ? '当天' : `${taskTime}${unit}`;
|
|||
|
|
const dateText = baseDate ? dayTransform(baseDate, taskTime, first.timeType) : '';
|
|||
|
|
return {
|
|||
|
|
id: key,
|
|||
|
|
title: `计划开始后: ${offsetText}${dateText ? `(${dateText})` : ''}`,
|
|||
|
|
list,
|
|||
|
|
};
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped>
|
|||
|
|
.group-head {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
padding: 24rpx 0 20rpx;
|
|||
|
|
}
|
|||
|
|
.group-title {
|
|||
|
|
flex: 1;
|
|||
|
|
min-width: 0;
|
|||
|
|
padding-left: 20rpx;
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #111827;
|
|||
|
|
overflow: hidden;
|
|||
|
|
text-overflow: ellipsis;
|
|||
|
|
white-space: nowrap;
|
|||
|
|
}
|
|||
|
|
.group-toggle {
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-left: 20rpx;
|
|||
|
|
}
|
|||
|
|
.toggle-text {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #6b7280;
|
|||
|
|
}
|
|||
|
|
.toggle-icon {
|
|||
|
|
margin-left: 10rpx;
|
|||
|
|
}
|
|||
|
|
.group-body {
|
|||
|
|
padding-bottom: 20rpx;
|
|||
|
|
}
|
|||
|
|
.mt-20 {
|
|||
|
|
margin-top: 20rpx;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
|