PlanPopupNew.vue 4 KB
<!--
 * @Date: 2026-02-08
 * @Description: 计划书弹窗容器组件(支持全局弹窗管理器)
-->
<template>
  <nut-popup
    :visible="visible"
    position="bottom"
    round
    :style="{ height: '90%' }"
    :close-on-click-overlay="true"
    :safe-area-inset-bottom="true"
    @update:visible="handleVisibleChange"
  >
    <div class="h-full flex flex-col bg-gray-50 overflow-hidden rounded-t-2xl">
      <!-- Header -->
      <div class="flex justify-between items-center px-5 py-4 bg-white border-b border-gray-100 flex-shrink-0">
        <span class="text-lg font-bold text-gray-900">{{ title }}</span>
        <div class="p-2 -mr-2" @click="handleClose">
          <IconFont name="close" size="16" color="#9CA3AF" />
        </div>
      </div>

      <!-- Scrollable Content -->
      <div class="flex-1 overflow-y-auto p-4">
        <div class="bg-white rounded-xl p-5 shadow-sm">
          <slot></slot>
        </div>
      </div>

      <!-- Footer Buttons -->
      <div
        v-show="showFooter"
        class="p-4 bg-white border-t border-gray-100 flex gap-3 flex-shrink-0 pb-safe"
      >
        <nut-button
          plain
          type="primary"
          class="flex-1 !h-[88rpx] !rounded-[16rpx] !text-[30rpx] !border-blue-600"
          @click="handleClose"
        >
          取消
        </nut-button>
        <nut-button
          type="primary"
          color="#2563EB"
          class="flex-1 !h-[88rpx] !rounded-[16rpx] !text-[30rpx]"
          @click="handleSubmit"
        >
          生成计划书
        </nut-button>
      </div>

    </div>
  </nut-popup>
</template>

<script setup>
/**
 * @description 录入计划书弹窗容器组件(支持全局弹窗管理器)
 * @description 自动监听子弹窗状态,隐藏/显示底部按钮
 * @param {boolean} visible - 控制弹窗显示隐藏
 * @param {string} title - 弹窗标题
 * @emits update:visible - 更新 visible 状态
 * @emits close - 关闭弹窗
 * @emits submit - 提交表单
 * @author Claude Code
 * @version 2.0.0 - 支持全局弹窗管理器
 */
import { ref, watch, onMounted, onUnmounted } from 'vue'
import IconFont from '@/components/IconFont.vue'
import { useParentPopup } from './PlanFields/GlobalPopupManager.js'

const props = defineProps({
  visible: {
    type: Boolean,
    default: false,
  },
  title: {
    type: String,
    default: '计划书',
  },
})

const emit = defineEmits(['update:visible', 'close', 'submit'])

/**
 * 底部按钮显示状态
 * @type {Ref<boolean>}
 */
const showFooter = ref(true)

/**
 * 使用父弹窗管理器
 */
const { registerFooterCallback, hasActiveChildPopup } = useParentPopup()

/**
 * 取消注册回调函数
 * @type {Function|null}
 */
let unregisterFooterCallback = null

/**
 * 组件挂载时注册回调
 */
onMounted(() => {
  // 注册回调,当子弹窗打开/关闭时自动隐藏/显示底部按钮
  unregisterFooterCallback = registerFooterCallback((shouldShowFooter) => {
    showFooter.value = shouldShowFooter
  })

  // 初始化时检查是否已有活动弹窗
  if (hasActiveChildPopup.value) {
    showFooter.value = false
  }
})

/**
 * 组件卸载时取消注册
 */
onUnmounted(() => {
  if (unregisterFooterCallback) {
    unregisterFooterCallback()
  }
})

/**
 * 监听全局弹窗状态变化
 * 当子弹窗打开/关闭时,自动隐藏/显示底部按钮
 */
watch(hasActiveChildPopup, (isActive) => {
  showFooter.value = !isActive
})

// 处理 visible 变化事件
const handleVisibleChange = (value) => {
  emit('update:visible', value)
  if (!value) {
    // 重置底部按钮显示状态
    showFooter.value = true
    emit('close')
  }
}

const handleClose = () => {
  emit('update:visible', false)
  emit('close')
}

const handleSubmit = () => {
  emit('submit')
}
</script>

<style lang="less">
:deep(.nut-popup) {
  border-top-left-radius: 16px;
  border-top-right-radius: 16px;
  background-color: #F9FAFB;
}

/* 适配底部安全区 */
.pb-safe {
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}
</style>