ActionSheet.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <template>
  2. <Popup
  3. v-bind="props"
  4. :closeable="showCancel"
  5. :closeIcon="false"
  6. :position="center ? 'center' : 'bottom'"
  7. :size="center ? themeContext.resolveThemeSize(centerWidth) : 'auto'"
  8. backgroundColor="transparent"
  9. @close="onCancelClick"
  10. >
  11. <slot name="content" :close="onCancelClick">
  12. <FlexCol :padding="innerPadding">
  13. <FlexCol :innerStyle="themeStyles.topView.value">
  14. <ActionSheetTitle :title="title" :description="description" />
  15. <scroll-view
  16. :scroll-y="true"
  17. :style="{
  18. ...themeStyles.topScroll.value,
  19. width: center ? themeContext.resolveThemeSize(centerWidth) : undefined,
  20. }"
  21. >
  22. <FlexCol position="relative">
  23. <ActionSheetItem
  24. v-for="(item, index) in props.actions"
  25. :key="item.name"
  26. :name="item.name"
  27. :bold="item.bold || themeContext.getVar('ActionSheetItemBold', false)"
  28. :color="themeContext.resolveThemeColor(item.color || props.textColor || themeContext.resolveThemeColor('ActionSheetItemColor', 'text.content'))"
  29. :subname="item.subname"
  30. :disabled="item.disabled"
  31. @click="onItemClick(item, index)"
  32. />
  33. </FlexCol>
  34. </scroll-view>
  35. </FlexCol>
  36. <FlexCol v-if="showCancel" position="relative" :innerStyle="themeStyles.viewCancel.value">
  37. <ActionSheetItem
  38. :name="props.cancelText || '取消'"
  39. :bold="themeContext.getVar('ActionSheetCancelBold', false)"
  40. :color="themeContext.resolveThemeColor(props.textColor || themeContext.resolveThemeColor('ActionSheetCancelColor', 'text.content'))"
  41. :subname="''"
  42. :disabled="false"
  43. @click="onCancelClick"
  44. />
  45. </FlexCol>
  46. </FlexCol>
  47. </slot>
  48. </Popup>
  49. </template>
  50. <script setup lang="ts">
  51. import { propGetThemeVar, useTheme } from '../theme/ThemeDefine';
  52. import { DynamicColor, DynamicSize, screenHeight } from '../theme/ThemeTools';
  53. import ActionSheetItem from './ActionSheetItem.vue';
  54. import ActionSheetTitle from './ActionSheetTitle.vue';
  55. import FlexCol from '../layout/FlexCol.vue';
  56. import Popup from './Popup.vue';
  57. import type { PopupProps } from './Popup.vue';
  58. import { computed } from 'vue';
  59. export interface ActionSheetProps extends Omit<PopupProps, 'onClose'|'position'|'closeable'|'position'|'size'> {
  60. /**
  61. * 是否显示动作面板
  62. * @default false
  63. */
  64. show: boolean;
  65. /**
  66. * 是否显示取消按扭
  67. * @default false
  68. */
  69. showCancel?: boolean;
  70. /**
  71. * 取消条目的文字
  72. */
  73. cancelText?: string;
  74. /**
  75. * 顶部标题
  76. */
  77. title?: string;
  78. /**
  79. * 选项上方的描述信息
  80. */
  81. description?: string;
  82. /**
  83. * 面板选项列表
  84. */
  85. actions?: ActionSheetItem[];
  86. /**
  87. * 是否在点击条目后自动关闭
  88. * @default false
  89. */
  90. autoClose?: boolean;
  91. /**
  92. * 是否在屏幕居中显示
  93. * @default false
  94. */
  95. center?: boolean;
  96. /**
  97. * 居中显示时的宽度
  98. */
  99. centerWidth?: string|number;
  100. /**
  101. * 条目文字颜色
  102. */
  103. textColor?: string;
  104. }
  105. export interface ActionSheetItem {
  106. /**
  107. * 标题
  108. */
  109. name: string;
  110. /**
  111. * 二级标题
  112. */
  113. subname?: string;
  114. /**
  115. * 选项文字颜色
  116. */
  117. color?: string;
  118. /**
  119. * 是否加粗当前选项
  120. */
  121. bold?: boolean;
  122. /**
  123. * 是否禁用当前选项
  124. */
  125. disabled?: boolean;
  126. }
  127. const emit = defineEmits([ 'close', 'select' ]);
  128. const props = withDefaults(defineProps<ActionSheetProps>(), {
  129. mask: true,
  130. safeArea: true,
  131. centerWidth: () => propGetThemeVar('ActionSheetCenterWidth', '600rpx'),
  132. });
  133. const innerPadding = computed(() => themeContext.getVar('ActionSheetInnerPadding', 20));
  134. const themeContext = useTheme();
  135. const themeStyles = themeContext.useThemeStyles({
  136. viewCancel: {
  137. backgroundColor: DynamicColor('ActionSheetCancelBackgroundColor', 'white'),
  138. borderRadius: DynamicSize('ActionSheetCancelBorderRadius', 22),
  139. marginTop: DynamicSize('ActionSheetCancelMarginTop', 20),
  140. overflow: 'hidden',
  141. },
  142. topScroll: {
  143. maxHeight: DynamicSize('ActionSheetMaxScrollHeight', (screenHeight - 200) + 'px'),
  144. },
  145. topView: {
  146. backgroundColor: DynamicColor('ActionSheetCancelBackgroundColor', 'white'),
  147. borderRadius: DynamicSize('ActionSheetCancelBorderRadius', 22),
  148. overflow: 'hidden',
  149. },
  150. });
  151. function onItemClick(item: ActionSheetItem, index: number) {
  152. emit('select', index, item.name);
  153. if (props.autoClose === true)
  154. onCancelClick();
  155. }
  156. function onCancelClick() {
  157. emit('close');
  158. }
  159. </script>