195 lines
4.0 KiB
Plaintext
195 lines
4.0 KiB
Plaintext
<template>
|
||
<cl-popup
|
||
v-model="visible"
|
||
:pt="{
|
||
className: '!rounded-[60rpx]'
|
||
}"
|
||
size="70%"
|
||
:show-close="false"
|
||
:show-header="false"
|
||
:mask-closable="false"
|
||
direction="center"
|
||
@mask-close="onAction('close')"
|
||
@closed="onClosed"
|
||
>
|
||
<view class="cl-confirm">
|
||
<cl-text
|
||
:pt="{
|
||
className: parseClass(['cl-confirm__title text-lg text-center font-bold mb-2'])
|
||
}"
|
||
>{{ config.title }}</cl-text
|
||
>
|
||
|
||
<cl-text
|
||
:pt="{
|
||
className: parseClass(['cl-confirm__message text-md text-center mb-8'])
|
||
}"
|
||
>{{ config.message }}</cl-text
|
||
>
|
||
|
||
<view class="cl-confirm__actions">
|
||
<cl-button
|
||
v-if="config.showCancel"
|
||
size="large"
|
||
text
|
||
rounded
|
||
border
|
||
type="info"
|
||
:pt="{
|
||
className: 'flex-1 h-[80rpx]'
|
||
}"
|
||
@tap="onAction('cancel')"
|
||
>{{ config.cancelText }}</cl-button
|
||
>
|
||
<cl-button
|
||
v-if="config.showConfirm"
|
||
size="large"
|
||
rounded
|
||
:loading="loading"
|
||
:pt="{
|
||
className: 'flex-1 h-[80rpx]'
|
||
}"
|
||
@tap="onAction('confirm')"
|
||
>{{ config.confirmText }}</cl-button
|
||
>
|
||
</view>
|
||
</view>
|
||
</cl-popup>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, reactive } from "vue";
|
||
import type { ClConfirmAction, ClConfirmOptions } from "../../types";
|
||
import { t } from "@/locale";
|
||
import { parseClass } from "@/cool";
|
||
|
||
// 控制弹窗显示/隐藏
|
||
const visible = ref(false);
|
||
|
||
// 控制弹窗是否关闭
|
||
const closed = ref(true);
|
||
|
||
// 确认弹窗配置项,包含标题、内容、按钮文本等
|
||
const config = reactive<ClConfirmOptions>({
|
||
title: "",
|
||
message: ""
|
||
});
|
||
|
||
// 控制确认按钮loading状态
|
||
const loading = ref(false);
|
||
|
||
// 显示loading
|
||
function showLoading() {
|
||
loading.value = true;
|
||
}
|
||
|
||
// 隐藏loading
|
||
function hideLoading() {
|
||
loading.value = false;
|
||
}
|
||
|
||
// 关闭弹窗
|
||
function close() {
|
||
visible.value = false;
|
||
}
|
||
|
||
/**
|
||
* 打开确认弹窗,并设置相关配置
|
||
* @param options ClConfirmOptions 配置项
|
||
*/
|
||
|
||
let timer: number = 0;
|
||
|
||
function open(options: ClConfirmOptions) {
|
||
const next = () => {
|
||
// 清除之前的定时器
|
||
clearTimeout(timer);
|
||
|
||
// 设置弹窗状态为打开
|
||
closed.value = false;
|
||
// 显示弹窗
|
||
visible.value = true;
|
||
|
||
// 设置弹窗标题
|
||
config.title = options.title;
|
||
// 设置弹窗内容
|
||
config.message = options.message;
|
||
// 是否显示取消按钮,默认显示
|
||
config.showCancel = options.showCancel ?? true;
|
||
// 是否显示确认按钮,默认显示
|
||
config.showConfirm = options.showConfirm ?? true;
|
||
// 取消按钮文本,默认"取消"
|
||
config.cancelText = options.cancelText ?? t("取消");
|
||
// 确认按钮文本,默认"确定"
|
||
config.confirmText = options.confirmText ?? t("确定");
|
||
// 显示时长,默认0不自动关闭
|
||
config.duration = options.duration ?? 0;
|
||
// 回调函数
|
||
config.callback = options.callback;
|
||
// 关闭前钩子
|
||
config.beforeClose = options.beforeClose;
|
||
|
||
// 如果设置了显示时长且不为0,则启动自动关闭定时器
|
||
if (config.duration != 0) {
|
||
// 设置定时器,在指定时长后自动关闭弹窗
|
||
// @ts-ignore
|
||
timer = setTimeout(() => {
|
||
// 调用关闭方法
|
||
close();
|
||
}, config.duration!);
|
||
}
|
||
};
|
||
|
||
if (closed.value) {
|
||
next();
|
||
} else {
|
||
setTimeout(() => {
|
||
next();
|
||
}, 360);
|
||
}
|
||
}
|
||
|
||
// 弹窗关闭后,重置loading状态
|
||
function onClosed() {
|
||
hideLoading();
|
||
closed.value = true;
|
||
}
|
||
|
||
/**
|
||
* 处理用户操作(确认、取消、关闭)
|
||
* @param action ClConfirmAction 操作类型
|
||
*/
|
||
function onAction(action: ClConfirmAction) {
|
||
// 如果没有beforeClose钩子,直接关闭并回调
|
||
if (config.beforeClose == null) {
|
||
visible.value = false;
|
||
|
||
if (config.callback != null) {
|
||
config.callback!(action);
|
||
}
|
||
} else {
|
||
// 有beforeClose钩子时,传递操作方法
|
||
config.beforeClose!(action, {
|
||
close,
|
||
showLoading,
|
||
hideLoading
|
||
});
|
||
}
|
||
}
|
||
|
||
defineExpose({
|
||
open,
|
||
close
|
||
});
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.cl-confirm {
|
||
@apply p-4;
|
||
|
||
&__actions {
|
||
@apply flex flex-row items-center justify-center;
|
||
}
|
||
}
|
||
</style>
|