cl-confirm.uvue 3.9 KB

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