You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

342 lines
12 KiB

  1. <template>
  2. <u-popup
  3. :show="show"
  4. mode="bottom"
  5. @close="closeHandler"
  6. :safeAreaInsetBottom="safeAreaInsetBottom"
  7. :round="round"
  8. >
  9. <view class="u-action-sheet">
  10. <!-- 顶部标题区域 -->
  11. <view
  12. class="u-action-sheet__header"
  13. v-if="title"
  14. >
  15. <text
  16. class="u-action-sheet__header__title u-line-1"
  17. :style="titleDynamicStyle"
  18. >{{title}}</text>
  19. <view
  20. class="u-action-sheet__header__icon-wrap"
  21. @tap.stop="cancel"
  22. >
  23. <up-icon
  24. name="close"
  25. size="17"
  26. :color="closeIconColor"
  27. bold
  28. ></up-icon>
  29. </view>
  30. </view>
  31. <!-- 描述信息 -->
  32. <text
  33. class="u-action-sheet__description"
  34. :style="[{
  35. marginTop: `${title && description ? 0 : '18px'}`
  36. }, descriptionDynamicStyle]"
  37. v-if="description"
  38. >{{description}}</text>
  39. <slot>
  40. <!-- 分割线 -->
  41. <u-line v-if="description" :color="dividerColor"></u-line>
  42. <!-- 操作项列表 -->
  43. <scroll-view scroll-y class="u-action-sheet__item-wrap" :style="{maxHeight: wrapMaxHeight}">
  44. <view :key="index" v-for="(item, index) in actions">
  45. <!-- #ifdef MP -->
  46. <button
  47. class="u-reset-button"
  48. :openType="item.openType"
  49. @getuserinfo="onGetUserInfo"
  50. @contact="onContact"
  51. @getphonenumber="onGetPhoneNumber"
  52. @error="onError"
  53. @launchapp="onLaunchApp"
  54. @opensetting="onOpenSetting"
  55. :lang="lang"
  56. :session-from="sessionFrom"
  57. :send-message-title="sendMessageTitle"
  58. :send-message-path="sendMessagePath"
  59. :send-message-img="sendMessageImg"
  60. :show-message-card="showMessageCard"
  61. :app-parameter="appParameter"
  62. @tap="selectHandler(index)"
  63. :hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''"
  64. >
  65. <!-- #endif -->
  66. <view
  67. class="u-action-sheet__item-wrap__item"
  68. @tap.stop="selectHandler(index)"
  69. :hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''"
  70. :hover-stay-time="150"
  71. :style="getItemHoverStyle(index)"
  72. >
  73. <template v-if="!item.loading">
  74. <text
  75. class="u-action-sheet__item-wrap__item__name"
  76. :style="[itemStyle(index)]"
  77. >{{ item[nameKey] }}</text>
  78. <text
  79. v-if="item[subnameKey]"
  80. class="u-action-sheet__item-wrap__item__subname"
  81. :style="[subnameStyle(index)]"
  82. >{{ item[subnameKey] }}</text>
  83. </template>
  84. <!-- 加载状态图标 -->
  85. <u-loading-icon
  86. v-else
  87. custom-class="van-action-sheet__loading"
  88. size="18"
  89. mode="circle"
  90. />
  91. </view>
  92. <!-- #ifdef MP -->
  93. </button>
  94. <!-- #endif -->
  95. <!-- 选项间分割线 -->
  96. <u-line v-if="index !== actions.length - 1" :color="dividerColor"></u-line>
  97. </view>
  98. </scroll-view>
  99. </slot>
  100. <!-- 取消按钮前的分割区域 -->
  101. <u-gap
  102. :bgColor="cancelGapColor"
  103. height="6"
  104. v-if="cancelText"
  105. ></u-gap>
  106. <!-- 取消按钮 -->
  107. <view class="u-action-sheet__item-wrap__item u-action-sheet__cancel"
  108. hover-class="u-action-sheet--hover" @tap="cancel" v-if="cancelText">
  109. <text
  110. @touchmove.stop.prevent
  111. :hover-stay-time="150"
  112. class="u-action-sheet__cancel-text"
  113. :style="cancelTextDynamicStyle"
  114. >{{cancelText}}</text>
  115. </view>
  116. </view>
  117. </u-popup>
  118. </template>
  119. <script>
  120. import { openType } from '../../libs/mixin/openType'
  121. import { buttonMixin } from '../../libs/mixin/button'
  122. import { props } from './props';
  123. import { mpMixin } from '../../libs/mixin/mpMixin';
  124. import { mixin } from '../../libs/mixin/mixin';
  125. import { addUnit } from '../../libs/function/index';
  126. /**
  127. * ActionSheet 操作菜单
  128. * @description 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheetAPI,配置更加灵活,所有平台都表现一致。
  129. * @tutorial https://uview-plus.jiangruyi.com/components/actionSheet.html
  130. *
  131. * @property {Boolean} show 操作菜单是否展示 (默认 false )
  132. * @property {String} title 操作菜单标题
  133. * @property {String} description 选项上方的描述信息
  134. * @property {Array<Object>} actions 按钮的文字数组,见官方文档示例
  135. * @property {String} cancelText 取消按钮的提示文字,不为空时显示按钮
  136. * @property {Boolean} closeOnClickAction 点击某个菜单项时是否关闭弹窗 (默认 true )
  137. * @property {Boolean} safeAreaInsetBottom 处理底部安全区 (默认 true )
  138. * @property {String} openType 小程序的打开方式 (contact | launchApp | getUserInfo | openSetting |getPhoneNumber |error )
  139. * @property {Boolean} closeOnClickOverlay 点击遮罩是否允许关闭 (默认 true )
  140. * @property {Number|String} round 圆角值,默认无圆角 (默认 0 )
  141. * @property {String} lang 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文
  142. * @property {String} sessionFrom 会话来源,openType="contact"时有效
  143. * @property {String} sendMessageTitle 会话内消息卡片标题,openType="contact"时有效
  144. * @property {String} sendMessagePath 会话内消息卡片点击跳转小程序路径,openType="contact"时有效
  145. * @property {String} sendMessageImg 会话内消息卡片图片,openType="contact"时有效
  146. * @property {Boolean} showMessageCard 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,openType="contact"时有效 (默认 false )
  147. * @property {String} appParameter 打开 APP 时,向 APP 传递的参数,openType=launchApp 时有效
  148. *
  149. * @event {Function} select 点击ActionSheet列表项时触发
  150. * @event {Function} close 点击取消按钮时触发
  151. * @event {Function} getuserinfo 用户点击该按钮时,会返回获取到的用户信息,回调的 detail 数据与 wx.getUserInfo 返回的一致,openType="getUserInfo"时有效
  152. * @event {Function} contact 客服消息回调,openType="contact"时有效
  153. * @event {Function} getphonenumber 获取用户手机号回调,openType="getPhoneNumber"时有效
  154. * @event {Function} error 当使用开放能力时,发生错误的回调,openType="error"时有效
  155. * @event {Function} launchapp 打开 APP 成功的回调,openType="launchApp"时有效
  156. * @event {Function} opensetting 在打开授权设置页后回调,openType="openSetting"时有效
  157. * @example <u-action-sheet :actions="list" :title="title" :show="show"></u-action-sheet>
  158. */
  159. export default {
  160. name: "u-action-sheet",
  161. // 一些props参数和methods方法,通过mixin混入,因为其他文件也会用到
  162. mixins: [openType, buttonMixin, mixin, props],
  163. data() {
  164. return {
  165. }
  166. },
  167. computed: {
  168. titleDynamicStyle() {
  169. return {
  170. color: this.upThemeVar('--up-main-color', '#303133')
  171. }
  172. },
  173. descriptionDynamicStyle() {
  174. return {
  175. color: this.upThemeVar('--up-tips-color', '#909193')
  176. }
  177. },
  178. closeIconColor() {
  179. return this.upThemeVar('--up-content-color', '#606266')
  180. },
  181. dividerColor() {
  182. return this.upThemeVar('--up-border-color', this.upThemeIsDark ? '#3a3a3c' : '#dadbde')
  183. },
  184. cancelGapColor() {
  185. return this.upThemeVar('--up-gap-bg-color', this.upThemeIsDark ? '#111111' : '#eaeaec')
  186. },
  187. cancelTextDynamicStyle() {
  188. return {
  189. color: this.upThemeVar('--up-main-color', '#303133')
  190. }
  191. },
  192. // 操作项目的样式
  193. itemStyle() {
  194. return (index) => {
  195. const style = {
  196. color: this.upThemeVar('--up-main-color', '#303133')
  197. };
  198. if (this.actions[index].color) style.color = this.actions[index].color
  199. if (this.actions[index].fontSize) style.fontSize = addUnit(this.actions[index].fontSize)
  200. // 选项被禁用的样式
  201. if (this.actions[index].disabled) style.color = this.upThemeVar('--up-light-color', '#c0c4cc')
  202. return style;
  203. }
  204. },
  205. subnameStyle() {
  206. return (index) => ({
  207. color: this.actions[index].disabled
  208. ? this.upThemeVar('--up-light-color', '#c0c4cc')
  209. : this.upThemeVar('--up-tips-color', '#909193')
  210. })
  211. }
  212. },
  213. emits: ["close", "select", "update:show"],
  214. methods: {
  215. // 关闭操作菜单事件处理
  216. closeHandler() {
  217. // 允许点击遮罩关闭时,才发出close事件
  218. if(this.closeOnClickOverlay) {
  219. this.$emit('update:show', false)
  220. this.$emit('close')
  221. }
  222. },
  223. // 点击取消按钮
  224. cancel() {
  225. this.$emit('update:show', false)
  226. this.$emit('close')
  227. },
  228. // 选择操作项处理
  229. selectHandler(index) {
  230. const item = this.actions[index]
  231. if (item && !item.disabled && !item.loading) {
  232. this.$emit('select', item)
  233. if (this.closeOnClickAction) {
  234. this.$emit('update:show', false)
  235. this.$emit('close')
  236. }
  237. }
  238. },
  239. // 动态处理Hover时候第一个item的圆角
  240. getItemHoverStyle(index) {
  241. if (index === 0 && this.round && !this.title && !this.description) {
  242. return {
  243. borderTopLeftRadius: `${this.round}px`,
  244. borderTopRightRadius: `${this.round}px`,
  245. }
  246. }
  247. return {}
  248. },
  249. }
  250. }
  251. </script>
  252. <style lang="scss" scoped>
  253. $u-action-sheet-reset-button-width:100% !default;
  254. $u-action-sheet-title-font-size: 16px !default;
  255. $u-action-sheet-title-padding: 12px 30px !default;
  256. $u-action-sheet-title-color: var(--up-main-color, #303133) !default;
  257. $u-action-sheet-header-icon-wrap-right:15px !default;
  258. $u-action-sheet-header-icon-wrap-top:15px !default;
  259. $u-action-sheet-description-font-size:13px !default;
  260. $u-action-sheet-description-color: var(--up-tips-color, #909193) !default;
  261. $u-action-sheet-description-margin: 18px 15px !default;
  262. $u-action-sheet-item-wrap-item-padding:17px !default;
  263. $u-action-sheet-item-wrap-name-font-size:16px !default;
  264. $u-action-sheet-item-wrap-subname-font-size:13px !default;
  265. $u-action-sheet-item-wrap-subname-color: var(--up-tips-color, #909193) !default;
  266. $u-action-sheet-item-wrap-subname-margin-top:10px !default;
  267. $u-action-sheet-cancel-text-font-size:16px !default;
  268. $u-action-sheet-cancel-text-color: var(--up-main-color, #303133) !default;
  269. $u-action-sheet-cancel-text-font-size:15px !default;
  270. $u-action-sheet-cancel-text-hover-background-color: var(--up-hover-bg-color, rgb(242, 243, 245)) !default;
  271. .u-reset-button {
  272. width: $u-action-sheet-reset-button-width;
  273. }
  274. .u-action-sheet {
  275. text-align: center;
  276. &__header {
  277. position: relative;
  278. padding: $u-action-sheet-title-padding;
  279. &__title {
  280. font-size: $u-action-sheet-title-font-size;
  281. color: $u-action-sheet-title-color;
  282. font-weight: bold;
  283. text-align: center;
  284. }
  285. &__icon-wrap {
  286. position: absolute;
  287. right: $u-action-sheet-header-icon-wrap-right;
  288. top: $u-action-sheet-header-icon-wrap-top;
  289. }
  290. }
  291. &__description {
  292. display: block;
  293. font-size: $u-action-sheet-description-font-size;
  294. color: $u-action-sheet-description-color;
  295. margin: $u-action-sheet-description-margin;
  296. text-align: center;
  297. }
  298. &__item-wrap {
  299. &__item {
  300. padding: $u-action-sheet-item-wrap-item-padding;
  301. @include flex;
  302. align-items: center;
  303. justify-content: center;
  304. flex-direction: column;
  305. &__name {
  306. font-size: $u-action-sheet-item-wrap-name-font-size;
  307. color: var(--up-main-color, #303133);
  308. text-align: center;
  309. }
  310. &__subname {
  311. font-size: $u-action-sheet-item-wrap-subname-font-size;
  312. color: $u-action-sheet-item-wrap-subname-color;
  313. margin-top: $u-action-sheet-item-wrap-subname-margin-top;
  314. text-align: center;
  315. }
  316. }
  317. }
  318. &__cancel-text {
  319. font-size: $u-action-sheet-cancel-text-font-size;
  320. color: $u-action-sheet-cancel-text-color;
  321. text-align: center;
  322. // padding: $u-action-sheet-cancel-text-font-size;
  323. }
  324. &--hover {
  325. background-color: $u-action-sheet-cancel-text-hover-background-color;
  326. }
  327. }
  328. </style>