cycle-selection.vue 7.35 KB
<template>
  <div class="cycle-selection-page">
    <van-config-provider :theme-vars="themeVars">
      <div class="cycle-popup">
        <div class="popup-header">
          <h3>选择周期</h3>
          <p>{{ cycle_note }}</p>
        </div>
        <div class="popup-content">
          <van-radio-group v-model="selectedCycle">
            <div v-for="cycle in cycleList" :key="cycle.id" class="cycle-item">
              <van-radio :name="cycle.id">
                <div class="cycle-info">
                  <div class="cycle-title">{{ cycle.title }}</div>
                  <div class="cycle-time">
                    <div v-if="cycle.start_date">活动开始时间: {{ cycle.start_date }}</div>
                    <div v-if="cycle.end_date">活动结束时间: {{ cycle.end_date }}</div>
                    <div v-if="cycle.reg_begin_time">报名开始时间: {{ cycle.reg_begin_time }}</div>
                    <div v-if="cycle.reg_end_time">报名结束时间: {{ cycle.reg_end_time }}</div>
                    <div v-if="cycle.description">说明: {{ cycle.description }}</div>
                  </div>
                </div>
              </van-radio>
            </div>
          </van-radio-group>
        </div>
        <div class="popup-footer">
          <van-button type="primary" class="confirm-btn" @click="confirmCycleSelection" :disabled="!selectedCycle">
            确认选择
          </van-button>
        </div>
      </div>
    </van-config-provider>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import { getCycleListAPI } from '@/api/cycle';
import { styleColor } from '@/constant.js';
import { showConfirmDialog } from 'vant';
import Cookies from 'js-cookie';

const $router = useRouter();
const $route = useRoute();

// 主题配置
const themeVars = {
  // 主色调配置
  radioCheckedIconColor: styleColor.baseColor,
  buttonPrimaryBackground: styleColor.baseColor,
  buttonPrimaryBorderColor: styleColor.baseColor,
};

// 周期选择相关变量
const cycleList = ref([]);
const selectedCycle = ref('');
const cycle_note = ref('');

/**
 * 动态计算弹窗内容区域高度
 */
const calculatePopupContentHeight = () => {
  nextTick(() => {
    const popupElement = document.querySelector('.cycle-popup');
    const headerElement = document.querySelector('.popup-header');
    const footerElement = document.querySelector('.popup-footer');
    const contentElement = document.querySelector('.popup-content');

    if (popupElement && headerElement && footerElement && contentElement) {
      const popupHeight = popupElement.offsetHeight;
      const headerHeight = headerElement.offsetHeight;
      const footerHeight = footerElement.offsetHeight;
      const padding = 100; // 上下padding和margin的总和

      const contentHeight = popupHeight - headerHeight - footerHeight - padding;
      contentElement.style.height = `${contentHeight}px`;
    }
  });
};

/**
 * 获取周期列表
 * @param {string} form_code 表单唯一标识
 */
const getCycleList = async (form_code) => {
  try {
    const { data } = await getCycleListAPI({ form_code });
    if (data.is_cycle) {
      if (!data.cycle_list || data.cycle_list.length === 0) {
        // 如果is_cycle是true但cycle_list为空,跳转到停用页面
        $router.push("/stop?status=disable");
        return;
      }
      // 设置周期列表
      cycleList.value = data.cycle_list;
      cycle_note.value = data.cycle_note;
      // 计算高度
      calculatePopupContentHeight();
    } else {
      // 如果不需要周期选择,检查未完成表单后跳转到目标页面
      const targetRoute = sessionStorage.getItem('cycle_target_route');
      if (targetRoute) {
        sessionStorage.removeItem('cycle_target_route');
        const route = JSON.parse(targetRoute);
        // 检查是否需要显示未完成表单弹框
        checkUnfinishedForm(route);
      } else {
        $router.replace('/');
      }
    }
  } catch (error) {
    console.error('获取周期列表失败:', error);
  }
};

/**
 * 确认选择周期
 */
const confirmCycleSelection = () => {
  if (selectedCycle.value) {
    // 获取目标路由
    const targetRoute = sessionStorage.getItem('cycle_target_route');
    if (targetRoute) {
      const route = JSON.parse(targetRoute);
      // 添加周期参数
      route.query = {
        ...route.query,
        x_cycle: selectedCycle.value,
        cycle_selected: '1'
      };
      // 清除临时存储
      sessionStorage.removeItem('cycle_target_route');

      // 检查是否需要显示未完成表单弹框
      checkUnfinishedForm(route);
    } else {
      // 如果没有目标路由,跳转到首页
      $router.replace({
        path: '/',
        query: {
          x_cycle: selectedCycle.value,
          cycle_selected: '1'
        }
      });
    }
  }
};

/**
 * 检查未完成的表单信息
 * @param {Object} route 目标路由对象
 */
const checkUnfinishedForm = (route) => {
  // 只在新增状态时检查
  if (route.query.page_type === 'add' || route.query.page_type === undefined) {
    const existingCookie = Cookies.get(route.query.code);
    if (existingCookie && route.query.force_back !== '1') {
      // 显示确认对话框
      showConfirmDialog({
        title: '温馨提示',
        message: '您还未完成的表单,是否继续?',
        confirmButtonColor: styleColor.baseColor,
        cancelButtonText: '删除',
        closeOnPopstate: false,
      })
        .then(() => {
          // 用户选择继续,跳转到目标页面
          $router.replace(route);
        })
        .catch(() => {
          // 用户选择删除,清除cookie后跳转
          Cookies.remove(route.query.code);
          $router.replace(route);
        });
    } else {
      // 没有未完成的表单,直接跳转
      $router.replace(route);
    }
  } else {
    // 不是新增状态,直接跳转
    $router.replace(route);
  }
};

onMounted(() => {
  const form_code = $route.query.code;
  if (form_code) {
    getCycleList(form_code);
  } else {
    console.error('缺少表单代码参数');
    $router.replace('/');
  }
});
</script>

<style lang="less" scoped>
.cycle-selection-page {
  width: 100vw;
  height: 100vh;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
}

.cycle-popup {
  width: 100%;
  max-width: 500px;
  height: 70vh;
  background: white;
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.popup-header {
  padding: 20px;
  text-align: center;
  border-bottom: 1px solid #eee;
  flex-shrink: 0;

  h3 {
    margin: 0;
    font-size: 18px;
    font-weight: 600;
    color: #333;
  }
}

.popup-content {
  flex: 1;
  overflow-y: auto;
  padding: 0 20px;
  min-height: 0;
}

.cycle-item {
  padding: 15px 0;
  border-bottom: 1px solid #f5f5f5;

  &:last-child {
    border-bottom: none;
  }
}

.cycle-info {
  margin-left: 10px;
}

.cycle-title {
  font-size: 16px;
  font-weight: 500;
  color: #333;
  margin-bottom: 8px;
}

.cycle-time {
  font-size: 14px;
  color: #666;
  line-height: 1.5;

  div {
    margin-bottom: 4px;

    &:last-child {
      margin-bottom: 0;
    }
  }
}

.popup-footer {
  padding: 20px;
  border-top: 1px solid #eee;
  flex-shrink: 0;
}

.confirm-btn {
  width: 100%;
  height: 44px;
  border-radius: 8px;
  font-size: 16px;
  font-weight: 500;
}
</style>