cl-confirm.uvue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <template>
  2. <cl-popup
  3. v-model="visible"
  4. :pt="{
  5. className: '!rounded-[60rpx]'
  6. }"
  7. size="70%"
  8. :show-close="false"
  9. :show-header="false"
  10. :mask-closable="false"
  11. direction="center"
  12. @mask-close="onAction('close')"
  13. @closed="onClosed"
  14. >
  15. <view class="cl-confirm">
  16. <cl-text
  17. :pt="{
  18. className: parseClass(['cl-confirm__title text-lg text-center font-bold mb-2'])
  19. }"
  20. >{{ config.title }}</cl-text
  21. >
  22. <cl-text
  23. :pt="{
  24. className: parseClass(['cl-confirm__message text-md text-center mb-8'])
  25. }"
  26. >{{ config.message }}</cl-text
  27. >
  28. <view class="cl-confirm__actions">
  29. <cl-button
  30. v-if="config.showCancel"
  31. size="large"
  32. text
  33. rounded
  34. border
  35. type="info"
  36. :pt="{
  37. className: 'flex-1 h-[80rpx]'
  38. }"
  39. @tap="onAction('cancel')"
  40. >{{ config.cancelText }}</cl-button
  41. >
  42. <cl-button
  43. v-if="config.showConfirm"
  44. size="large"
  45. rounded
  46. :loading="loading"
  47. :pt="{
  48. className: 'flex-1 h-[80rpx]'
  49. }"
  50. @tap="onAction('confirm')"
  51. >{{ config.confirmText }}</cl-button
  52. >
  53. </view>
  54. </view>
  55. </cl-popup>
  56. </template>
  57. <script setup lang="ts">
  58. import { ref, reactive } from "vue";
  59. import type { ClConfirmAction, ClConfirmOptions } from "../../types";
  60. import { t } from "@/locale";
  61. import { parseClass } from "@/cool";
  62. // 控制弹窗显示/隐藏
  63. const visible = ref(false);
  64. // 控制弹窗是否关闭
  65. const closed = ref(true);
  66. // 确认弹窗配置项,包含标题、内容、按钮文本等
  67. const config = reactive<ClConfirmOptions>({
  68. title: "",
  69. message: ""
  70. });
  71. // 控制确认按钮loading状态
  72. const loading = ref(false);
  73. // 显示loading
  74. function showLoading() {
  75. loading.value = true;
  76. }
  77. // 隐藏loading
  78. function hideLoading() {
  79. loading.value = false;
  80. }
  81. // 关闭弹窗
  82. function close() {
  83. visible.value = false;
  84. }
  85. /**
  86. * 打开确认弹窗,并设置相关配置
  87. * @param options ClConfirmOptions 配置项
  88. */
  89. let timer: number = 0;
  90. function open(options: ClConfirmOptions) {
  91. const next = () => {
  92. // 清除之前的定时器
  93. clearTimeout(timer);
  94. // 设置弹窗状态为打开
  95. closed.value = false;
  96. // 显示弹窗
  97. visible.value = true;
  98. // 设置弹窗标题
  99. config.title = options.title;
  100. // 设置弹窗内容
  101. config.message = options.message;
  102. // 是否显示取消按钮,默认显示
  103. config.showCancel = options.showCancel ?? true;
  104. // 是否显示确认按钮,默认显示
  105. config.showConfirm = options.showConfirm ?? true;
  106. // 取消按钮文本,默认"取消"
  107. config.cancelText = options.cancelText ?? t("取消");
  108. // 确认按钮文本,默认"确定"
  109. config.confirmText = options.confirmText ?? t("确定");
  110. // 显示时长,默认0不自动关闭
  111. config.duration = options.duration ?? 0;
  112. // 回调函数
  113. config.callback = options.callback;
  114. // 关闭前钩子
  115. config.beforeClose = options.beforeClose;
  116. // 如果设置了显示时长且不为0,则启动自动关闭定时器
  117. if (config.duration != 0) {
  118. // 设置定时器,在指定时长后自动关闭弹窗
  119. // @ts-ignore
  120. timer = setTimeout(() => {
  121. // 调用关闭方法
  122. close();
  123. }, config.duration!);
  124. }
  125. };
  126. if (closed.value) {
  127. next();
  128. } else {
  129. setTimeout(() => {
  130. next();
  131. }, 360);
  132. }
  133. }
  134. // 弹窗关闭后,重置loading状态
  135. function onClosed() {
  136. hideLoading();
  137. closed.value = true;
  138. }
  139. /**
  140. * 处理用户操作(确认、取消、关闭)
  141. * @param action ClConfirmAction 操作类型
  142. */
  143. function onAction(action: ClConfirmAction) {
  144. // 如果没有beforeClose钩子,直接关闭并回调
  145. if (config.beforeClose == null) {
  146. visible.value = false;
  147. if (config.callback != null) {
  148. config.callback!(action);
  149. }
  150. } else {
  151. // 有beforeClose钩子时,传递操作方法
  152. config.beforeClose!(action, {
  153. close,
  154. showLoading,
  155. hideLoading
  156. });
  157. }
  158. }
  159. defineExpose({
  160. open,
  161. close
  162. });
  163. </script>
  164. <style lang="scss" scoped>
  165. .cl-confirm {
  166. @apply p-4;
  167. &__actions {
  168. @apply flex flex-row items-center justify-center;
  169. }
  170. }
  171. </style>