ykt-wxapp/components/manage-plan/plan-node-list.vue

129 lines
3.8 KiB
Vue
Raw Normal View History

2026-01-26 15:39:14 +08:00
<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>