<template>
    <div class="plan-page">
        <custom-header name="农事规划"></custom-header>
        <div class="plan-content">
            <div class="filter-wrap">
                <div class="season-tabs">
                    <div
                        v-for="s in seasons"
                        :key="s.value"
                        class="season-tab"
                        :class="{ active: s.value === activeSeason }"
                        @click="activeSeason = s.value"
                    >
                        {{ s.label }}
                    </div>
                </div>
                <div class="status-filter">
                    <div v-for="status in statusList" :key="status.value" class="status-item" :class="status.color">
                        <div class="status-dot"></div>
                        <span class="status-text">{{ status.label }}</span>
                    </div>
                </div>
            </div>

            <!-- 三行循环时间线 -->
            <div class="cycle-timeline-container">
                <div class="cycle-timeline">
                    <div
                        v-for="(row, rowIndex) in timelineRows"
                        :key="rowIndex"
                        class="cycle-row"
                        :class="{ 'odd-index': rowIndex % 2 === 1 }"
                    >
                        <div
                            v-for="(item, itemIndex) in row.items"
                            :key="itemIndex"
                            class="cycle-item"
                            @click="handleRowClick(item)"
                            :class="[item.type + '-item']"
                        >
                            <!-- 节气节点 -->
                            <template v-if="item.type === 'term'">
                                <!-- <div class="cycle-term-dot"></div> -->
                                <div class="cycle-term-label">{{ item.name || item.id }}</div>
                            </template>
                        </div>

                        <!-- 生育期名称（根据时间范围显示在对应行） -->
                        <div class="cycle-phenology-wrap" v-if="getPhenologyBarsForRow(rowIndex).length > 0">
                            <div
                                v-for="p in getPhenologyBarsForRow(rowIndex)"
                                :key="p.id"
                                class="cycle-label"
                                :class="p.color"
                                :style="
                                    isOddVisualRow(rowIndex)
                                        ? { right: p.left, width: p.width }
                                        : { left: p.left, width: p.width }
                                "
                            >
                                {{ p.name }}
                                <div v-if="p.arranges && p.arranges.length" class="arranges">
                                    <div v-for="a in p.arranges" :key="a.id" :class="['cycle-task-box', a.status]">
                                        <div class="cycle-task-text">{{ a.farmWorkName || a.name }}</div>
                                        <!-- 任务连接器 -->
                                        <div class="cycle-task-connector"></div>
                                        <div
                                            v-if="a.status === 'complete' || a.status === 'warning'"
                                            class="status-icon"
                                            :class="a.status"
                                        >
                                            <el-icon v-if="a.status === 'complete'" size="16" color="#1CA900"
                                                ><SuccessFilled
                                            /></el-icon>
                                            <el-icon v-else size="18" color="#FF953D"><WarnTriangleFilled /></el-icon>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <!-- 行连接器 -->
                        <div
                            v-if="rowIndex < timelineRows.length - 1"
                            class="cycle-connector"
                            :class="[
                                rowIndex % 2 === 1 ? 'middle-connector' : 'top-connector',
                                getConnectorColorClass(rowIndex),
                            ]"
                        >
                            <img v-if="isConnectorGray(rowIndex)" src="@/assets/img/monitor/defalut-arrow.png" alt="" />
                            <img v-else src="@/assets/img/monitor/arrow.png" alt="" />
                        </div>
                    </div>
                </div>
            </div>

            <div class="control-section">
                <div class="toggle-group">
                    <el-switch v-model="isDefaultEnabled" />
                    <span class="toggle-label">{{ isDefaultEnabled ? "默认" : "" }}发起农情需求</span>
                </div>
                <div class="add-button-group">
                    <div class="add-button button" @click="addNewTask">新增农事</div>
                    <div class="button" @click="manageTask">农事管理</div>
                </div>
            </div>
        </div>
    </div>
    <!-- 农事信息弹窗 -->
    <detail-dialog ref="detailDialogRef"></detail-dialog>
    <!-- 新增：激活上传弹窗 -->
    <active-upload-popup></active-upload-popup>
</template>

<script setup>
import { reactive, ref, onMounted, nextTick, onBeforeUnmount } from "vue";
import customHeader from "@/components/customHeader.vue";
import { useRouter, useRoute } from "vue-router";
import detailDialog from "@/components/detailDialog.vue";
import activeUploadPopup from "@/components/popup/activeUploadPopup.vue";
const router = useRouter();
const route = useRoute();

// 状态列表数据
const seasons = reactive([
    { value: "spring", label: "春季" },
    { value: "summer", label: "夏季" },
    { value: "autumn", label: "秋季" },
    { value: "winter", label: "冬季" },
]);
const activeSeason = ref("spring");

const statusList = reactive([
    { value: "pending", label: "待触发", color: "gray" },
    { value: "executing", label: "待完成", color: "blue" },
    { value: "completed", label: "已完成", color: "green" },
    { value: "expired", label: "已过期", color: "orange" },
]);

// 切换开关状态
const isDefaultEnabled = ref(true);

// 时间线行数据（由接口节气生成）
const timelineRows = reactive([]);

// 目标定位日期（当前生育期参考点）
const targetDate = new Date("2025-04-04T00:00:00");
// 每行“当前生育期”标记的位置样式（按行索引）
const phenologyPositions = ref({});

// 生育期条（按行分组）
const phenologyBarsByRow = ref([]);
// 每一行可视区域的实际像素宽度（用于将最小像素宽度换算为百分比）
const rowWidths = ref([]);
// 节气 id 到对象的索引，便于通过 id 查找节气日期
let solarTermIdToTerm = {};
// 接口返回的生育期数据
const phenologyList = ref([]);

// 安全日期解析（兼容 'YYYY-MM-DD HH:mm:ss' / 'YYYY/MM/DD HH:mm:ss'）
const parseDate = (val) => {
    if (!val) return null;
    if (val instanceof Date) return isNaN(val.getTime()) ? null : val;
    if (typeof val === "number") return new Date(val);
    if (typeof val === "string") {
        // 统一到可被 Safari 解析的格式
        const s = val.replace(/-/g, "/").replace("T", " ");
        const d = new Date(s);
        return isNaN(d.getTime()) ? null : d;
    }
    return null;
};

onMounted(() => {
    getFarmWorkPlan();
    window.addEventListener("resize", handleResize, { passive: true });
});
onBeforeUnmount(() => {
    window.removeEventListener("resize", handleResize);
});

const handleResize = () => {
    // 重新测量并基于最新宽度重算条目
    nextTick(() => {
        measureRowWidths();
        // 需要基于最新数据重算
        if (phenologyList.value && phenologyList.value.length && cachedValidSolarTerms.value) {
            groupPhenologyBarsByRow(phenologyList.value, cachedValidSolarTerms.value);
        }
    });
};

// 缓存已过滤/排序后的节气用于重复计算
const cachedValidSolarTerms = ref(null);

const getFarmWorkPlan = () => {
    const paramFarmId = Number(route.query.farmId) || undefined;
    VE_API.monitor
        .farmWorkPlan({ farmId: paramFarmId ?? 92844 }) // 优先使用路由传入的 farmId
        .then(({ data, code }) => {
            if (code === 0) {
                const solarTermsList = data.solarTermsList;
                // 仅保留 type === 1 的节气，按需要的顺序（示例：反转）
                // 取 type===1 的节气，并按日期降序排序（晚到早）
                const validSolarTerms = Array.isArray(solarTermsList)
                    ? solarTermsList
                          .filter((t) => t && t.type === 1 && t.createDate)
                          .sort((a, b) => {
                              const da = parseDate(a.createDate)?.getTime() ?? 0;
                              const db = parseDate(b.createDate)?.getTime() ?? 0;
                              return db - da;
                          })
                    : [];
                cachedValidSolarTerms.value = validSolarTerms;
                generateTimelineData(validSolarTerms);
                computeCurrentPhenologyPositions(validSolarTerms, targetDate);
                // 保存生育期数据并生成各行生育期条
                phenologyList.value = Array.isArray(data.phenologyList) ? data.phenologyList : [];
                // 生成 id->term 的索引
                solarTermIdToTerm = {};
                validSolarTerms.forEach((t) => {
                    if (t && (t.id || t.solarTermsId)) solarTermIdToTerm[t.id ?? t.solarTermsId] = t;
                });
                // 先等待 DOM 渲染完成后测量每行宽度，再据此计算最小可显示宽度
                nextTick(() => {
                    measureRowWidths();
                    groupPhenologyBarsByRow(phenologyList.value, validSolarTerms);
                });
            }
        })
        .catch((error) => {
            console.error("获取农事规划数据失败:", error);
        });
};

// 测量每一行生育期容器的实际宽度
const measureRowWidths = () => {
    const rows = document.querySelectorAll(".cycle-timeline .cycle-row");
    const widths = [];
    rows.forEach((rowEl, idx) => {
        const wrap = rowEl.querySelector(".cycle-phenology-wrap");
        widths[idx] = wrap ? wrap.offsetWidth : 0;
    });
    rowWidths.value = widths;
};

// 生成时间轴数据
const generateTimelineData = (solarTerms) => {
    // 清空
    timelineRows.splice(0, timelineRows.length);

    // 无数据则给一行示例
    if (!solarTerms || solarTerms.length === 0) {
        timelineRows.push({
            items: [
                { type: "task", status: "default", taskName: "梢期", taskDesc: "杀虫" },
                { type: "term", name: "节气" },
                { type: "task", status: "default", taskName: "梢期", taskDesc: "杀虫" },
                { type: "term", name: "节气" },
                { type: "task", status: "default", taskName: "梢期", taskDesc: "杀虫" },
                { type: "term", name: "节气" },
            ],
        });
        return;
    }

    const itemsPerRow = 6; // 任务/节气交替
    const termsPerRow = 3; // 每行3个节气
    const totalRows = Math.ceil(solarTerms.length / termsPerRow);

    for (let rowIndex = 0; rowIndex < totalRows; rowIndex++) {
        const rowItems = [];
        const startTermIndex = rowIndex * termsPerRow;

        for (let i = 0; i < itemsPerRow; i++) {
            if (i % 2 === 0) {
                // 任务位
                const taskData = getTaskDataForIndex(Math.floor(i / 2));
                rowItems.push({
                    type: "task",
                    status: taskData.status,
                    taskName: taskData.taskName,
                    taskDesc: taskData.taskDesc,
                    icon: taskData.icon,
                });
            } else {
                // 节气位
                const termIndex = startTermIndex + Math.floor(i / 2);
                if (termIndex < solarTerms.length) {
                    const term = solarTerms[termIndex] || {};
                    rowItems.push({
                        type: "term",
                        status: "default",
                        name: term.name || term.solarTermsName || term.termName || "节气",
                        id: term.id,
                        createDate: term.createDate,
                    });
                } else {
                    // 不足时补任务
                    rowItems.push({
                        type: "task",
                        status: "default",
                        taskName: "梢期",
                        taskDesc: "杀虫",
                    });
                }
            }
        }

        timelineRows.push({ items: rowItems });
    }
};

// 任务占位数据（可按需接后端）
const getTaskDataForIndex = (index) => {
    const defaultTasks = [
        { status: "default", taskName: "梢期", taskDesc: "杀虫" },
        { status: "active", taskName: "梢期", taskDesc: "营养" },
        { status: "complete", taskName: "梢期", taskDesc: "修剪", icon: { type: "complete" } },
        { status: "warning", taskName: "梢期", taskDesc: "施肥", icon: { type: "warning" } },
        { status: "normal", taskName: "梢期", taskDesc: "灌溉", icon: { type: "normal" } },
    ];
    return defaultTasks[index % defaultTasks.length];
};

// 计算“当前生育期”在各行的定位（只在包含目标日期的那一行显示）
const computeCurrentPhenologyPositions = (solarTerms, date) => {
    phenologyPositions.value = {};
    if (!Array.isArray(solarTerms) || solarTerms.length === 0 || !(date instanceof Date)) return;

    const termsPerRow = 3;
    const totalRows = Math.ceil(solarTerms.length / termsPerRow);

    // 1) 找到最接近目标日期的节气（按时间升序）
    const termsAsc = solarTerms
        .filter((t) => t && t.createDate)
        .slice()
        .sort((a, b) => (parseDate(a.createDate)?.getTime() ?? 0) - (parseDate(b.createDate)?.getTime() ?? 0));
    if (termsAsc.length === 0) return;

    const targetMs = date.getTime();
    let nearest = termsAsc[0];
    let bestDiff = Math.abs((parseDate(nearest.createDate)?.getTime() ?? 0) - targetMs);
    for (let i = 1; i < termsAsc.length; i++) {
        const ms = parseDate(termsAsc[i].createDate)?.getTime() ?? 0;
        const diff = Math.abs(ms - targetMs);
        if (diff < bestDiff) {
            bestDiff = diff;
            nearest = termsAsc[i];
        }
    }

    // 2) 将该节气映射回当前（降序）数组中的索引与行
    const nearestIdxDesc = solarTerms.findIndex((t) => t && nearest && t.id === nearest.id);
    const rowIndex = Math.max(0, Math.floor(nearestIdxDesc / termsPerRow));

    const startIdx = rowIndex * termsPerRow;
    const endIdx = Math.min(startIdx + termsPerRow - 1, solarTerms.length - 1);
    if (startIdx > endIdx) return;

    const rowTerms = solarTerms.slice(startIdx, endIdx + 1);
    // 视觉顺序用于方向（偶数行正向，奇数行反向），但时间范围应取该行真实最早/最晚
    const rowDates = rowTerms
        .map((t) => parseDate(t?.createDate))
        .filter((d) => d && !isNaN(d.getTime()))
        .map((d) => d.getTime());
    if (rowDates.length === 0) return;
    const minMs = Math.min(...rowDates);
    const maxMs = Math.max(...rowDates);
    const rowStart = new Date(minMs);
    const rowEnd = new Date(maxMs);

    // 3) 若目标日期不在该行范围内，则就近夹到边界（避免跨行导致丢失）
    let anchorMs = targetMs;
    if (anchorMs < minMs) anchorMs = minMs;
    if (anchorMs > maxMs) anchorMs = maxMs;

    // 4) 计算在该行范围内的比例
    const total = Math.max(1, maxMs - minMs);
    const ratio = Math.max(0, Math.min(1, (anchorMs - minMs) / total));
    const percent = `${(ratio * 100).toFixed(2)}%`;

    // 5) 偶数行用 left，奇数行用 right，与 Z 字方向一致
    if (rowIndex % 2 === 1) {
        phenologyPositions.value[rowIndex] = { right: percent };
    } else {
        phenologyPositions.value[rowIndex] = { left: percent };
    }
};
// moved above with other refs

// 将生育期条按行计算定位与宽度
const groupPhenologyBarsByRow = (phenologyList, solarTerms) => {
    phenologyBarsByRow.value = [];
    if (
        !Array.isArray(phenologyList) ||
        phenologyList.length === 0 ||
        !Array.isArray(solarTerms) ||
        solarTerms.length === 0
    ) {
        return;
    }

    const termsPerRow = 3;
    const totalRows = Math.ceil(solarTerms.length / termsPerRow);

    // 行范围：使用该行包含的节气最早/最晚时间（按真实时间线性映射）
    const rowRanges = [];
    for (let rowIndex = 0; rowIndex < totalRows; rowIndex++) {
        const startIdx = rowIndex * termsPerRow;
        const endIdx = Math.min(startIdx + termsPerRow - 1, solarTerms.length - 1);
        const rowTerms = solarTerms.slice(startIdx, endIdx + 1);
        const rowDates = rowTerms
            .map((t) => parseDate(t?.createDate))
            .filter((d) => d && !isNaN(d.getTime()))
            .map((d) => d.getTime());
        if (rowDates.length === 0) continue;
        const minMs = Math.min(...rowDates);
        const maxMs = Math.max(...rowDates);
        const rowStart = new Date(minMs);
        const rowEnd = new Date(maxMs);
        const totalMs = Math.max(1, rowEnd.getTime() - rowStart.getTime());
        rowRanges.push({ rowIndex, rowStart, rowEnd, totalMs });
        phenologyBarsByRow.value[rowIndex] = [];
    }

    // 中点归属法：每条生育期归属到中点所在的行；在行内按 Z 字方向计算 left/right 与 width
    phenologyList.forEach((p, pIndex) => {
        const list = Array.isArray(p?.reproductiveList) ? p.reproductiveList : [];
        const baseColorClass = pIndex % 2 === 0 ? "blue" : "orange";
        list.forEach((r) => {
            // 优先使用节气 id 对应的节气日期
            let sTermDate = null;
            let eTermDate = null;
            if (r?.startSolarTermId && solarTermIdToTerm[r.startSolarTermId]?.createDate) {
                sTermDate = parseDate(solarTermIdToTerm[r.startSolarTermId].createDate);
            }
            if (r?.endSolarTermId && solarTermIdToTerm[r.endSolarTermId]?.createDate) {
                eTermDate = parseDate(solarTermIdToTerm[r.endSolarTermId].createDate);
            }

            const s = sTermDate || parseDate(r?.startDate);
            const e = eTermDate || parseDate(r?.endDate);
            if (!s || !e) return;
            const start = new Date(Math.min(s.getTime(), e.getTime()));
            const end = new Date(Math.max(s.getTime(), e.getTime()));
            if (end < start) return;
            const mid = new Date(start.getTime() + (end.getTime() - start.getTime()) / 2);

            // 找到中点所在行；若不在任何行，则归最近行
            let target = rowRanges.find(({ rowStart, rowEnd }) => mid >= rowStart && mid <= rowEnd);
            if (!target) {
                target = rowRanges.reduce((best, curr) => {
                    const dist =
                        mid < curr.rowStart
                            ? curr.rowStart.getTime() - mid.getTime()
                            : mid.getTime() - curr.rowEnd.getTime();
                    if (!best || dist < best.dist) return { dist, curr };
                    return best;
                }, null)?.curr;
            }
            if (!target) return;

            // 位置：基于真实的 startDate（不截断），确保相邻条的间距 = (后一个startDate - 前一个endDate) 的时间差映射
            const startRatio = (start.getTime() - target.rowStart.getTime()) / target.totalMs;

            // 宽度：基于真实的 endDate - startDate 的时间差
            const actualDuration = end.getTime() - start.getTime();
            const widthRatio = actualDuration / target.totalMs;

            // 限制到行范围内
            const leftRatio = Math.max(0, Math.min(1, startRatio));
            const rightRatio = Math.max(0, Math.min(1, (end.getTime() - target.rowStart.getTime()) / target.totalMs));
            let clampedWidthRatio = Math.max(0.001, Math.min(widthRatio, rightRatio - leftRatio));

            // 强制最小显示宽度：若换算到像素后小于 CSS 中的 min-width:22px，则使用最小可见宽度
            const MIN_LABEL_PX = 22; // 与样式 .cycle-label 的最小宽度保持一致
            const rowWidthPx = rowWidths.value?.[target.rowIndex] || 0;
            let leftPercent = leftRatio * 100;
            let widthPercent = clampedWidthRatio * 100;
            if (rowWidthPx > 0) {
                const minPercent = (MIN_LABEL_PX / rowWidthPx) * 100;
                if (widthPercent < minPercent) {
                    widthPercent = minPercent;
                }
                // 若越界则左移以保证完全可见
                if (leftPercent + widthPercent > 100) {
                    leftPercent = Math.max(0, 100 - widthPercent);
                }
                // 回填为比例供后续使用
                clampedWidthRatio = widthPercent / 100;
            } else {
                // 无法测量时，保底给一个不至于 0 的最小显示比例（以 360px 近似，22px/360≈6.1%）
                if (widthPercent < 6.2) {
                    widthPercent = 6.2;
                    if (leftPercent + widthPercent > 100) leftPercent = Math.max(0, 100 - widthPercent);
                    clampedWidthRatio = widthPercent / 100;
                }
            }

            const isFuture = start.getTime() > Date.now();
            const colorToUse = isFuture ? "" : baseColorClass;
            // 组装农事安排：按 reproductiveId 归属到当前生育期
            const arrangeList = Array.isArray(r.farmWorkArrangeList)
                ? r.farmWorkArrangeList.filter((fw) => !fw.reproductiveId || fw.reproductiveId === r.id)
                : [];
            const arrangeItems = arrangeList.map((fw) => {
                let status = "default";
                const t = fw.farmWorkType;
                if (t == null || t === 0) {
                    status = "default";
                } else if (t >= 1 && t <= 4) {
                    status = "normal";
                } else if (t === 5) {
                    status = "complete";
                } else if (t === 6) {
                    status = "warning";
                }
                return {
                    id: fw.id,
                    name: fw.farmWorkName,
                    status,
                };
            });

            // // 附加两条测试数据：已完成、已过期
            // arrangeItems.push(
            //     { id: `${r.id}-test-complete`, name: "测试完成", status: "complete" },
            //     { id: `${r.id}-test-warning`, name: "测试过期", status: "warning" }
            // );

            phenologyBarsByRow.value[target.rowIndex].push({
                id: r.id || `${p.id || "p"}-${start.getTime()}-${end.getTime()}`,
                name: r.name && r.name.trim() ? r.name.trim() : r.phenologyName || "生育期",
                left: `${leftPercent.toFixed(4)}%`,
                width: `${(clampedWidthRatio * 100).toFixed(4)}%`,
                startTime: start.getTime(), // 用于排序，确保相邻条的顺序正确
                color: colorToUse,
                arranges: arrangeItems,
            });
        });
    });

    // 每行内部按 startTime 排序，确保相邻条的间距正确反映时间差
    phenologyBarsByRow.value.forEach((rowBars) => {
        rowBars.sort((a, b) => (a.startTime || 0) - (b.startTime || 0));
    });
};

// 获取指定行的生育期条
const getPhenologyBarsForRow = (rowIndex) => {
    return phenologyBarsByRow.value[rowIndex] || [];
};

// 视觉奇偶：自下而上计算奇偶（与 UI Z 字一致）
const isOddVisualRow = (rowIndex) => {
    const total = timelineRows.length;
    if (total <= 0) return rowIndex % 2 === 1;
    const visualIndex = total - 1 - rowIndex;
    return visualIndex % 2 === 1;
};

// 新增农事
const addNewTask = () => {
    router.push({
        path: "/modify_work",
        query: { data: JSON.stringify(["生长异常"]), gardenId: 766, isAdd: true },
    });
};

const manageTask = () => {
    router.push({
        path: "/agri_services_manage",
        query: {
            type: "manage",
        },
    });
};

const detailDialogRef = ref(null);

const handleRowClick = (item) => {
    if (item.status === "complete") {
        router.push({
            path: "/review_work",
            query: {
                id: item.id,
            },
        });
    } else if (item.type !== "term" && item.status === "default") {
        detailDialogRef.value.showDialog();
    } else if (item.status === "warning" || item.status === "normal") {
        router.push({
            path: "/completed_work",
            query: {
                id: item.id,
                status: item.status,
            },
        });
        // router.push({
        //     path: "/services_agri",
        //     query: {
        //         id: item.id,
        //         status: item.status,
        //     },
        // });
    }
};

// 行连接器颜色：若后续生育期未开始则灰色，否则保持其颜色（蓝/橙）
const getConnectorColorClass = (rowIndex) => {
    const nextIndex = rowIndex + 1;
    const bars = getPhenologyBarsForRow(nextIndex);
    if (!bars || bars.length === 0) return "";

    const nextIsOddIndex = nextIndex % 2 === 1; // 奇数行为左侧连接器

    const parsePercent = (val) => {
        if (typeof val !== "string") return 0;
        const n = parseFloat(val.replace("%", ""));
        return isNaN(n) ? 0 : n;
    };

    let target = bars[0];
    if (nextIsOddIndex) {
        // 左侧：选最靠左的条
        target = bars.reduce((best, cur) => (parsePercent(cur.left) < parsePercent(best.left) ? cur : best), bars[0]);
    } else {
        // 右侧：选最靠右的条（left + width 最大）
        const score = (b) => parsePercent(b.left) + parsePercent(b.width);
        target = bars.reduce((best, cur) => (score(cur) > score(best) ? cur : best), bars[0]);
    }

    // 未来（未开始）时，color 为空串；过去/当前一律显示蓝色
    const hasStarted = !!target?.color;
    return hasStarted ? "" : "connector-gray";
};

// 行连接器是否为灰色（用于切换箭头图片）
const isConnectorGray = (rowIndex) => getConnectorColorClass(rowIndex) === "connector-gray";
</script>

<style scoped lang="scss">
.plan-page {
    width: 100%;
    height: 100vh;
    background: #fff;
    .plan-content {
        .filter-wrap {
            background: #fff;
            padding: 13px 12px;
            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
            border-radius: 0 0 20px 20px;
            .status-filter {
                background: #fff;
                padding: 3px 17px;
                display: flex;
                align-items: center;
                gap: 16px;
                font-size: 12px;

                .status-item {
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    gap: 6px;
                    flex: 1;
                    &.gray {
                        color: #c4c6c9;
                        .status-dot {
                            background-color: #c4c6c9;
                        }
                    }

                    &.blue {
                        color: #2199f8;
                        .status-dot {
                            background-color: #2199f8;
                        }
                    }

                    &.green {
                        color: #1ca900;
                        .status-dot {
                            background-color: #1ca900;
                        }
                    }

                    &.orange {
                        color: #ff953d;
                        .status-dot {
                            background-color: #ff953d;
                        }
                    }
                    .status-dot {
                        width: 6px;
                        height: 6px;
                        border-radius: 50%;
                    }
                }
            }

            .season-tabs {
                display: flex;
                gap: 8px;
                margin-bottom: 12px;
                .season-tab {
                    flex: 1;
                    padding: 7px;
                    text-align: center;
                    background: #f3f3f3;
                    color: #898a8a;
                    border-radius: 3px;
                    border: 1px solid transparent;
                    font-size: 12px;
                }
                .season-tab.active {
                    background: #ffffff;
                    color: #2199f8;
                    border-color: #2199f8;
                }
            }
        }

        // 循环时间线样式
        .cycle-timeline-container {
            padding: 35px 15px 25px;
            height: calc(100vh - 135px - 69px - 60px);
            overflow-y: auto;
            overflow-x: hidden;
            .cycle-timeline {
                position: relative;
                .cycle-row {
                    position: relative;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    margin-bottom: 60px;
                    padding-right: 30px;
                    &.odd-index {
                        padding: 0;
                        padding-left: 30px;
                        flex-direction: row-reverse;
                        .cycle-phenology-wrap {
                            left: 6px;
                            width: calc(100% - 13px);
                        }
                    }

                    &:last-child {
                        margin-bottom: 0;
                        .cycle-phenology-wrap {
                            left: 20px;
                            width: calc(100% - 10px);
                        }
                    }

                    // 水平时间线
                    &::before {
                        content: "";
                        position: absolute;
                        top: 0;
                        left: 6px;
                        right: 6px;
                        height: 5px;
                        border-left: 2px solid #fff;
                        border-right: 2px solid #fff;
                        background: #e8e8e8;
                        transform: translateY(-50%);
                        z-index: 1;
                    }

                    .cycle-item {
                        position: relative;
                        z-index: 2;
                        top: 12px;

                        &.term-item {
                            display: flex;
                            flex-direction: column;
                            align-items: center;
                            top: -11px;

                            .cycle-term-dot {
                                width: 6px;
                                height: 6px;
                                background: #c7c7c7;
                                border-radius: 50%;
                                margin-bottom: 4px;
                            }

                            .cycle-term-label {
                                font-size: 11px;
                                color: #c7c7c7;
                                margin-top: 16px;
                            }

                            &.active {
                                .cycle-term-dot {
                                    background: #858383;
                                }
                                .cycle-term-label {
                                    color: #858383;
                                }
                            }
                        }
                    }

                    .cycle-phenology-wrap {
                        position: absolute;
                        top: -23px;
                        left: 6px;
                        width: calc(100% - 10px);
                        z-index: 3;
                        height: 100px;
                        overflow: hidden;
                        .cycle-label {
                            position: absolute;
                            color: #4e4e4e;
                            font-size: 12px;
                            min-width: 24px;
                            height: 20px;
                            line-height: 20px;
                            text-align: center;
                            background: rgba(180, 182, 183, 0.1);
                            border-bottom: 6px solid #e8e8e8;
                        }
                        .cycle-label + .cycle-label {
                            border-right: 1px solid #fff;
                        }
                        .cycle-label.blue {
                            color: #2199f8;
                            background: rgba(33, 153, 248, 0.1);
                            border-bottom-color: #2199f8;
                        }
                        .cycle-label.orange {
                            color: #ff953d;
                            background: #fff2e7;
                            border-bottom-color: #ff953d;
                        }
                        .arranges {
                            display: flex;
                            gap: 8px;
                            padding-top: 26px;
                            justify-content: center;
                            flex-wrap: nowrap;
                            // 使用与任务框一致的视觉风格
                            .cycle-task-box {
                                border: 1px solid rgba(199, 199, 199, 0.5);
                                border-radius: 2px;
                                width: 36px;
                                height: 36px;
                                min-width: 36px;
                                line-height: 15px;
                                font-size: 12px;
                                box-sizing: border-box;
                                padding: 2px 0;
                                text-align: center;
                                position: relative;
                                color: #c7c7c7;
                                .status-icon {
                                    position: absolute;
                                    bottom: -10px;
                                    right: -10px;
                                }
                            }

                            .cycle-task-connector {
                                position: absolute;
                                top: -4px;
                                left: 50%;
                                transform: translateX(-50%);
                                width: 0;
                                height: 0;
                                border-left: 4px solid transparent;
                                border-right: 4px solid transparent;
                                border-bottom: 4px solid #dde1e7;
                            }

                            .cycle-task-box.warning {
                                border-color: #ff953d;
                            }
                            .cycle-task-box.warning .cycle-task-text {
                                color: #ff953d;
                            }
                            .cycle-task-box.warning + .cycle-task-connector,
                            .cycle-task-box.warning .cycle-task-connector {
                                border-bottom-color: #ff953d;
                            }

                            .cycle-task-box.complete {
                                border-color: #1ca900;
                            }
                            .cycle-task-box.complete .cycle-task-text {
                                color: #1ca900;
                            }
                            .cycle-task-box.complete + .cycle-task-connector,
                            .cycle-task-box.complete .cycle-task-connector {
                                border-bottom-color: #1ca900;
                            }

                            .cycle-task-box.normal {
                                border-color: #2199f8;
                            }
                            .cycle-task-box.normal .cycle-task-text {
                                color: #2199f8;
                            }
                            .cycle-task-box.normal + .cycle-task-connector,
                            .cycle-task-box.normal .cycle-task-connector {
                                border-bottom-color: #2199f8;
                            }
                        }
                    }

                    .cycle-connector {
                        position: absolute;
                        right: 0;
                        top: 45.5px;
                        transform: translateY(-50%);
                        width: 2px;
                        height: 87px;
                        border: 5px solid #9dcaf7;
                        border-left: none;
                        background: transparent;
                        img{
                            width: 13px;
                            height: 13px;
                            position: absolute;
                            top: 50%;
                            transform: translateY(-50%);
                            left: -8px;
                            z-index: 1;
                        }

                        &.top-connector {
                            border-top-right-radius: 5px;
                            border-bottom-right-radius: 5px;
                            img{
                                left: -2px;
                            }
                        }

                        &.middle-connector {
                            border-top-left-radius: 5px;
                            border-bottom-left-radius: 5px;
                            left: 0;
                            border-right: none;
                            border-left: 5px solid #9dcaf7;
                        }

                        // 动态颜色
                        &.connector-gray {
                            border-color: #c4c6c9;
                        }
                        &.connector-gray.middle-connector {
                            border-left-color: #c4c6c9;
                        }
                    }
                }
            }
        }

        // 控制区域样式
        .control-section {
            position: fixed;
            width: 100%;
            left: 0;
            box-sizing: border-box;
            bottom: 0px;
            background: #fff;
            padding: 16px 12px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            border-top: 1px solid #f0f0f0;

            .toggle-group {
                display: flex;
                align-items: center;
                gap: 8px;

                .toggle-label {
                    font-size: 13px;
                    color: #141414;
                }
            }

            .add-button-group {
                display: flex;
                align-items: center;
                gap: 8px;
                .button {
                    color: #2199f8;
                    border-radius: 25px;
                    padding: 9px 15px;
                    border: 1px solid #2199f8;
                }
                .add-button {
                    background: linear-gradient(120deg, #76c3ff 0%, #2199f8 100%);
                    color: white;
                    border: 1px solid transparent;
                }
            }
        }
    }
}
</style>
