From f26f29d84e0a68831a6af14dab3eec5500496d2e Mon Sep 17 00:00:00 2001 From: spring <2396852758@qq.com> Date: 星期三, 28 五月 2025 16:48:52 +0800 Subject: [PATCH] 初始化项目 --- uview-ui/components/u-popup/u-popup.vue | 456 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 456 insertions(+), 0 deletions(-) diff --git a/uview-ui/components/u-popup/u-popup.vue b/uview-ui/components/u-popup/u-popup.vue new file mode 100644 index 0000000..69c0ec8 --- /dev/null +++ b/uview-ui/components/u-popup/u-popup.vue @@ -0,0 +1,456 @@ +<template> + <view v-if="visibleSync" :style="[customStyle, { + zIndex: uZindex - 1 + }]" class="u-drawer" hover-stop-propagation> + <u-mask :duration="duration" :custom-style="maskCustomStyle" :maskClickAble="maskCloseAble" :z-index="uZindex - 2" :show="showDrawer && mask" @click="maskClick"></u-mask> + <view + class="u-drawer-content" + @tap="modeCenterClose(mode)" + :class="[ + safeAreaInsetBottom ? 'safe-area-inset-bottom' : '', + 'u-drawer-' + mode, + showDrawer ? 'u-drawer-content-visible' : '', + zoom && mode == 'center' ? 'u-animation-zoom' : '' + ]" + @touchmove.stop.prevent + @tap.stop.prevent + :style="[style]" + > + <view class="u-mode-center-box" @tap.stop.prevent @touchmove.stop.prevent v-if="mode == 'center'" :style="[centerStyle]"> + <u-icon + @click="close" + v-if="closeable" + class="u-close" + :class="['u-close--' + closeIconPos]" + :name="closeIcon" + :color="closeIconColor" + :size="closeIconSize" + ></u-icon> + <scroll-view class="u-drawer__scroll-view" scroll-y="true"> + <slot /> + </scroll-view> + </view> + <scroll-view class="u-drawer__scroll-view" scroll-y="true" v-else> + <slot /> + </scroll-view> + <view @tap="close" class="u-close" :class="['u-close--' + closeIconPos]"> + <u-icon + v-if="mode != 'center' && closeable" + :name="closeIcon" + :color="closeIconColor" + :size="closeIconSize" + ></u-icon> + </view> + </view> + </view> +</template> + +<script> +/** + * popup 寮圭獥 + * @description 寮瑰嚭灞傚鍣紝鐢ㄤ簬灞曠ず寮圭獥銆佷俊鎭彁绀虹瓑鍐呭锛屾敮鎸佷笂銆佷笅銆佸乏銆佸彸鍜屼腑閮ㄥ脊鍑恒�傜粍浠跺彧鎻愪緵瀹瑰櫒锛屽唴閮ㄥ唴瀹圭敱鐢ㄦ埛鑷畾涔� + * @tutorial https://www.uviewui.com/components/popup.html + * @property {String} mode 寮瑰嚭鏂瑰悜锛堥粯璁eft锛� + * @property {Boolean} mask 鏄惁鏄剧ず閬僵锛堥粯璁rue锛� + * @property {Stringr | Number} length mode=left | 瑙佸畼缃戣鏄庯紙榛樿auto锛� + * @property {Boolean} zoom 鏄惁寮�鍚缉鏀惧姩鐢伙紝鍙湪mode涓篶enter鏃舵湁鏁堬紙榛樿true锛� + * @property {Boolean} safe-area-inset-bottom 鏄惁寮�鍚簳閮ㄥ畨鍏ㄥ尯閫傞厤锛堥粯璁alse锛� + * @property {Boolean} mask-close-able 鐐瑰嚮閬僵鏄惁鍙互鍏抽棴寮瑰嚭灞傦紙榛樿true锛� + * @property {Object} custom-style 鐢ㄦ埛鑷畾涔夋牱寮� + * @property {Stringr | Number} negative-top 涓儴寮瑰嚭鏃讹紝寰�涓婂亸绉荤殑鍊� + * @property {Numberr | String} border-radius 寮圭獥鍦嗚鍊硷紙榛樿0锛� + * @property {Numberr | String} z-index 寮瑰嚭鍐呭鐨剒-index鍊硷紙榛樿1075锛� + * @property {Boolean} closeable 鏄惁鏄剧ず鍏抽棴鍥炬爣锛堥粯璁alse锛� + * @property {String} close-icon 鍏抽棴鍥炬爣鐨勫悕绉帮紝鍙兘uView鐨勫唴缃浘鏍� + * @property {String} close-icon-pos 鑷畾涔夊叧闂浘鏍囦綅缃紙榛樿top-right锛� + * @property {String} close-icon-color 鍏抽棴鍥炬爣鐨勯鑹诧紙榛樿#909399锛� + * @property {Number | String} close-icon-size 鍏抽棴鍥炬爣鐨勫ぇ灏忥紝鍗曚綅rpx锛堥粯璁�30锛� + * @event {Function} open 寮瑰嚭灞傛墦寮� + * @event {Function} close 寮瑰嚭灞傛敹璧� + * @example <u-popup v-model="show"><view>鍑烘筏娉ヨ�屼笉鏌擄紝婵竻娑熻�屼笉濡�</view></u-popup> + */ +export default { + name: 'u-popup', + props: { + /** + * 鏄剧ず鐘舵�� + */ + show: { + type: Boolean, + default: false + }, + /** + * 寮瑰嚭鏂瑰悜锛宭eft|right|top|bottom|center + */ + mode: { + type: String, + default: 'left' + }, + /** + * 鏄惁鏄剧ず閬僵 + */ + mask: { + type: Boolean, + default: true + }, + // 鎶藉眽鐨勫搴�(mode=left|right)锛屾垨鑰呴珮搴�(mode=top|bottom)锛屽崟浣峳px锛屾垨鑰�"auto" + // 鎴栬�呯櫨鍒嗘瘮"50%"锛岃〃绀虹敱鍐呭鎾戝紑楂樺害鎴栬�呭搴� + length: { + type: [Number, String], + default: 'auto' + }, + // 鏄惁寮�鍚缉鏀惧姩鐢伙紝鍙湪mode=center鏃舵湁鏁� + zoom: { + type: Boolean, + default: true + }, + // 鏄惁寮�鍚簳閮ㄥ畨鍏ㄥ尯閫傞厤锛屽紑鍚殑璇濓紝浼氬湪iPhoneX鏈哄瀷搴曢儴娣诲姞涓�瀹氱殑鍐呰竟璺� + safeAreaInsetBottom: { + type: Boolean, + default: false + }, + // 鏄惁鍙互閫氳繃鐐瑰嚮閬僵杩涜鍏抽棴 + maskCloseAble: { + type: Boolean, + default: true + }, + // 鐢ㄦ埛鑷畾涔夋牱寮� + customStyle: { + type: Object, + default() { + return {}; + } + }, + value: { + type: Boolean, + default: false + }, + // 姝や负鍐呴儴鍙傛暟锛屼笉鍦ㄦ枃妗e澶栦娇鐢紝涓轰簡瑙e喅Picker鍜宬eyboard绛夎瀺鍚堜簡寮圭獥鐨勭粍浠� + // 瀵箆-model鍙屽悜缁戝畾澶氬眰璋冪敤閫犳垚鎶ラ敊涓嶈兘淇敼props鍊肩殑闂 + popup: { + type: Boolean, + default: true + }, + // 鏄剧ず鏄剧ず寮圭獥鐨勫渾瑙掞紝鍗曚綅rpx + borderRadius: { + type: [Number, String], + default: 0 + }, + zIndex: { + type: [Number, String], + default: '' + }, + // 鏄惁鏄剧ず鍏抽棴鍥炬爣 + closeable: { + type: Boolean, + default: false + }, + // 鍏抽棴鍥炬爣鐨勫悕绉帮紝鍙兘uView鐨勫唴缃浘鏍� + closeIcon: { + type: String, + default: 'close' + }, + // 鑷畾涔夊叧闂浘鏍囦綅缃紝top-left涓哄乏涓婅锛宼op-right涓哄彸涓婅锛宐ottom-left涓哄乏涓嬭锛宐ottom-right涓哄彸涓嬭 + closeIconPos: { + type: String, + default: 'top-right' + }, + // 鍏抽棴鍥炬爣鐨勯鑹� + closeIconColor: { + type: String, + default: '#909399' + }, + // 鍏抽棴鍥炬爣鐨勫ぇ灏忥紝鍗曚綅rpx + closeIconSize: { + type: [String, Number], + default: '30' + }, + // 瀹藉害锛屽彧瀵瑰乏锛屽彸锛屼腑閮ㄥ脊鍑烘椂璧蜂綔鐢紝鍗曚綅rpx锛屾垨鑰�"auto" + // 鎴栬�呯櫨鍒嗘瘮"50%"锛岃〃绀虹敱鍐呭鎾戝紑楂樺害鎴栬�呭搴︼紝浼樺厛绾ч珮浜巐ength鍙傛暟 + width: { + type: String, + default: '' + }, + // 楂樺害锛屽彧瀵逛笂锛屼笅锛屼腑閮ㄥ脊鍑烘椂璧蜂綔鐢紝鍗曚綅rpx锛屾垨鑰�"auto" + // 鎴栬�呯櫨鍒嗘瘮"50%"锛岃〃绀虹敱鍐呭鎾戝紑楂樺害鎴栬�呭搴︼紝浼樺厛绾ч珮浜巐ength鍙傛暟 + height: { + type: String, + default: '' + }, + // 缁欎竴涓礋鐨刴argin-top锛屽線涓婂亸绉伙紝閬垮厤鍜岄敭鐩橀噸鍚堢殑鎯呭喌锛屼粎鍦╩ode=center鏃舵湁鏁� + negativeTop: { + type: [String, Number], + default: 0 + }, + // 閬僵鐨勬牱寮忥紝涓�鑸敤浜庝慨鏀归伄缃╃殑閫忔槑搴� + maskCustomStyle: { + type: Object, + default() { + return {} + } + }, + // 閬僵鎵撳紑鎴栨敹璧风殑鍔ㄧ敾杩囨浮鏃堕棿锛屽崟浣峬s + duration: { + type: [String, Number], + default: 250 + } + }, + data() { + return { + visibleSync: false, + showDrawer: false, + timer: null, + closeFromInner: false, // value鐨勫�兼敼鍙橈紝鏄彂鐢熷湪鍐呴儴杩樻槸澶栭儴 + }; + }, + computed: { + // 鏍规嵁mode鐨勪綅缃紝璁惧畾鍏跺脊绐楃殑瀹藉害(mode = left|right)锛屾垨鑰呴珮搴�(mode = top|bottom) + style() { + let style = {}; + // 濡傛灉鏄乏杈规垨鑰呬笂杈瑰脊鍑烘椂锛岄渶瑕佺粰translate璁剧疆涓鸿礋鍊硷紝鐢ㄤ簬闅愯棌 + if (this.mode == 'left' || this.mode == 'right') { + style = { + width: this.width ? this.getUnitValue(this.width) : this.getUnitValue(this.length), + height: '100%', + transform: `translate3D(${this.mode == 'left' ? '-100%' : '100%'},0px,0px)` + }; + } else if (this.mode == 'top' || this.mode == 'bottom') { + style = { + width: '100%', + height: this.height ? this.getUnitValue(this.height) : this.getUnitValue(this.length), + transform: `translate3D(0px,${this.mode == 'top' ? '-100%' : '100%'},0px)` + }; + } + style.zIndex = this.uZindex; + // 濡傛灉鐢ㄦ埛璁剧疆浜哹orderRadius鍊硷紝娣诲姞寮圭獥鐨勫渾瑙� + if (this.borderRadius) { + switch (this.mode) { + case 'left': + style.borderRadius = `0 ${this.borderRadius}rpx ${this.borderRadius}rpx 0`; + break; + case 'top': + style.borderRadius = `0 0 ${this.borderRadius}rpx ${this.borderRadius}rpx`; + break; + case 'right': + style.borderRadius = `${this.borderRadius}rpx 0 0 ${this.borderRadius}rpx`; + break; + case 'bottom': + style.borderRadius = `${this.borderRadius}rpx ${this.borderRadius}rpx 0 0`; + break; + default: + } + // 涓嶅姞鍙兘鍦嗚鏃犳晥 + style.overflow = 'hidden'; + } + if(this.duration) style.transition = `all ${this.duration / 1000}s linear`; + return style; + }, + // 涓儴寮圭獥鐨勭壒鏈夋牱寮� + centerStyle() { + let style = {}; + style.width = this.width ? this.getUnitValue(this.width) : this.getUnitValue(this.length); + // 涓儴寮瑰嚭鐨勬ā寮忥紝濡傛灉娌℃湁璁剧疆楂樺害锛屽氨鐢╝uto鍊硷紝鐢卞唴瀹规拺寮�楂樺害 + style.height = this.height ? this.getUnitValue(this.height) : 'auto'; + style.zIndex = this.uZindex; + style.marginTop = `-${this.$u.addUnit(this.negativeTop)}`; + if (this.borderRadius) { + style.borderRadius = `${this.borderRadius}rpx`; + // 涓嶅姞鍙兘鍦嗚鏃犳晥 + style.overflow = 'hidden'; + } + return style; + }, + // 璁$畻鏁寸悊鍚庣殑z-index鍊� + uZindex() { + return this.zIndex ? this.zIndex : this.$u.zIndex.popup; + } + }, + watch: { + value(val) { + if (val) { + this.open(); + } else if(!this.closeFromInner) { + this.close(); + } + this.closeFromInner = false; + } + }, + mounted() { + // 缁勪欢娓叉煋瀹屾垚鏃讹紝妫�鏌alue鏄惁涓簍rue锛屽鏋滄槸锛屽脊鍑簆opup + this.value && this.open(); + }, + methods: { + // 鍒ゆ柇浼犲叆鐨勫�硷紝鏄惁甯︽湁鍗曚綅锛屽鏋滄病鏈夛紝灏遍粯璁ょ敤rpx鍗曚綅 + getUnitValue(val) { + if(/(%|px|rpx|auto)$/.test(val)) return val; + else return val + 'rpx' + }, + // 閬僵琚偣鍑� + maskClick() { + this.close(); + }, + close() { + // 鏍囪鍏抽棴鏄唴閮ㄥ彂鐢熺殑锛屽惁鍒欎慨鏀逛簡value鍊硷紝瀵艰嚧watch涓value妫�娴嬶紝瀵艰嚧鍐嶆墽琛屼竴閬峜lose + // 閫犳垚@close浜嬩欢瑙﹀彂涓ゆ + this.closeFromInner = true; + this.change('showDrawer', 'visibleSync', false); + }, + // 涓儴寮瑰嚭鏃讹紝闇�瑕�.u-drawer-content灏嗗眳涓唴瀹癸紝姝ゅ厓绱犱細閾烘弧灞忓箷锛岀偣鍑婚渶瑕佸叧闂脊绐� + // 璁╁叾鍙湪mode=center鏃惰捣浣滅敤 + modeCenterClose(mode) { + if (mode != 'center' || !this.maskCloseAble) return; + this.close(); + }, + open() { + this.change('visibleSync', 'showDrawer', true); + }, + // 姝ゅ鐨勫師鐞嗘槸锛屽叧闂椂鍏堥�氳繃鍔ㄧ敾闅愯棌寮圭獥鍜岄伄缃╋紝鍐嶇Щ闄ゆ暣涓粍浠� + // 鎵撳紑鏃讹紝鍏堟覆鏌撶粍浠讹紝寤舵椂涓�瀹氭椂闂村啀璁╅伄缃╁拰寮圭獥鐨勫姩鐢昏捣浣滅敤 + change(param1, param2, status) { + // 濡傛灉this.popup涓篺alse锛屾剰鍛崇潃涓簆icker锛宎ctionsheet绛夌粍浠惰皟鐢ㄤ簡popup缁勪欢 + if (this.popup == true) { + this.$emit('input', status); + } + this[param1] = status; + if(status) { + // #ifdef H5 || MP + this.timer = setTimeout(() => { + this[param2] = status; + this.$emit(status ? 'open' : 'close'); + }, 50); + // #endif + // #ifndef H5 || MP + this.$nextTick(() => { + this[param2] = status; + this.$emit(status ? 'open' : 'close'); + }) + // #endif + } else { + this.timer = setTimeout(() => { + this[param2] = status; + this.$emit(status ? 'open' : 'close'); + }, this.duration); + } + } + } +}; +</script> + +<style scoped lang="scss"> +@import "../../libs/css/style.components.scss"; + +.u-drawer { + /* #ifndef APP-NVUE */ + display: block; + /* #endif */ + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + overflow: hidden; +} + +.u-drawer-content { + /* #ifndef APP-NVUE */ + display: block; + /* #endif */ + position: absolute; + z-index: 1003; + transition: all 0.25s linear; +} + +.u-drawer__scroll-view { + width: 100%; + height: 100%; +} + +.u-drawer-left { + top: 0; + bottom: 0; + left: 0; + background-color: #ffffff; +} + +.u-drawer-right { + right: 0; + top: 0; + bottom: 0; + background-color: #ffffff; +} + +.u-drawer-top { + top: 0; + left: 0; + right: 0; + background-color: #ffffff; +} + +.u-drawer-bottom { + bottom: 0; + left: 0; + right: 0; + background-color: #ffffff; +} + +.u-drawer-center { + @include vue-flex; + flex-direction: column; + bottom: 0; + left: 0; + right: 0; + top: 0; + justify-content: center; + align-items: center; + opacity: 0; + z-index: 99999; +} + +.u-mode-center-box { + min-width: 100rpx; + min-height: 100rpx; + /* #ifndef APP-NVUE */ + display: block; + /* #endif */ + position: relative; + background-color: #ffffff; +} + +.u-drawer-content-visible.u-drawer-center { + transform: scale(1); + opacity: 1; +} + +.u-animation-zoom { + transform: scale(1.15); +} + +.u-drawer-content-visible { + transform: translate3D(0px, 0px, 0px) !important; +} + +.u-close { + position: absolute; + z-index: 3; +} + +.u-close--top-left { + top: 30rpx; + left: 30rpx; +} + +.u-close--top-right { + top: 30rpx; + right: 30rpx; +} + +.u-close--bottom-left { + bottom: 30rpx; + left: 30rpx; +} + +.u-close--bottom-right { + right: 30rpx; + bottom: 30rpx; +} +</style> -- Gitblit v1.9.3