| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- <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>
|