雙層彈框 - daniel-qa/Vue GitHub Wiki

雙層彈框

雙層彈框


  • 正確做法是:

你必須在按下第一層的「我已確認」按鈕時,呼叫 Promise 的 resolve()。

✅ 解法:把 langDialogHandlers 加回來!

const langDialogHandlers = ref({
  onConfirm: () => {},
  onCancel: () => {}
});

然後更新你 < el-dialog> 裡按鈕的事件:

<el-button type="danger" @click="langDialogHandlers.value.onConfirm()">
    我已確認,繼續發送
</el-button>

<el-button @click="langDialogHandlers.value.onCancel()">取消</el-button>

✅ 並在 waitForLangConfirm() 中註冊 handlers:

function waitForLangConfirm() {

  return new Promise((resolve, reject) => {

    sendLangDialogVisible.value = true;  // 叫出彈框

    langDialogHandlers.value = {
      onConfirm: () => {
        sendLangDialogVisible.value = false;
        resolve(); // 👈 關鍵!才能讓 await 繼續執行
      },
      onCancel: () => {
        sendLangDialogVisible.value = false;
        reject();  // 👈 取消時觸發 catch 區塊
      }
    };
  });
}
  • 最外層的呼叫
try {
    await waitForLangConfirm(); //  等使用者操作
    // 👇 使用者按「確認」,會從 resolve() 繼續往下走
    debugger;
    console.log("使用者確認了,開始發送");


    // 最後一次提醒 (多語系才檢查)
    try {
        await ElMessageBox.confirm(
            '最後確認,是否進行訊息發送',
            '提示',
            { type: 'error', confirmButtonText: '確定', cancelButtonText: '取消' }
        );
    } catch {
        // 使用者取消
        return;
    }

} catch {
    // 👇 使用者按「取消」,會從 reject() 進來這裡
    console.log("使用者取消了發送");
    return;  //返回
}

完整範例

<template>
    <div style="padding: 20px">
        <el-button type="primary" @click="handleSend">送出</el-button>

        <!-- 第一道自訂確認 Dialog -->
        <el-dialog v-model="langDialogVisible" title="語系訊息提醒" width="400">

            <p>此為語系訊息,可能產生較高費用。</p>
            <p style="color: #e6a23c;">請再次確認是否要發送?</p>

            <template #footer>
                <el-button @click="cancelLangConfirm">取消</el-button>
                <el-button type="primary" @click="confirmLangConfirm">我已確認</el-button>
            </template>

        </el-dialog>
    </div>
</template>

<script setup>
    import { ref } from 'vue'
    import { ElMessageBox, ElMessage } from 'element-plus'

    // 狀態
    const langDialogVisible = ref(false)
    let langDialogHandlers = {
        onConfirm: () => { },
        onCancel: () => { },
    }

    // 顯示第一層自訂 Dialog,回傳 Promise
    function waitForLangConfirm() {

        return new Promise((resolve, reject) => {

            langDialogVisible.value = true    // 這個會打開彈窗

            // 由於有 promise,會等到觸發函式時,才進行處理,不然會一直等待

            langDialogHandlers = {
                onConfirm: () => {
                    langDialogVisible.value = false
                    resolve()
                },
                onCancel: () => {
                    langDialogVisible.value = false
                    reject('使用者取消第一層')
                },
            }
        })
    }

    // Dialog 裡面的事件綁定
    function confirmLangConfirm() {
        langDialogHandlers.onConfirm()
    }

    function cancelLangConfirm() {
        langDialogHandlers.onCancel()
    }

    // 主流程:雙重確認
    async function handleSend() {
        try {
            await waitForLangConfirm()

            await ElMessageBox.confirm(
                '此為最終確認,確定要送出嗎?',
                '發送確認',
                {
                    type: 'warning',
                    confirmButtonText: '確定發送',
                    cancelButtonText: '取消',
                }
            )

            ElMessage.success('✅ 已送出!')
        } catch (err) {
            ElMessage.info('❌ 發送已取消')
        }
    }
</script>
⚠️ **GitHub.com Fallback** ⚠️