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-select/u-select.vue | 424 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 424 insertions(+), 0 deletions(-) diff --git a/uview-ui/components/u-select/u-select.vue b/uview-ui/components/u-select/u-select.vue new file mode 100644 index 0000000..3a8b0bd --- /dev/null +++ b/uview-ui/components/u-select/u-select.vue @@ -0,0 +1,424 @@ +<template> + <view class="u-select"> + <!-- <view class="u-select__action" :class="{ + 'u-select--border': border + }" @tap.stop="selectHandler"> + <view class="u-select__action__icon" :class="{ + 'u-select__action__icon--reverse': value == true + }"> + <u-icon name="arrow-down-fill" size="26" color="#c0c4cc"></u-icon> + </view> + </view> --> + <u-popup :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto" :safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex"> + <view class="u-select"> + <view class="u-select__header" @touchmove.stop.prevent=""> + <view + class="u-select__header__cancel u-select__header__btn" + :style="{ color: cancelColor }" + hover-class="u-hover-class" + :hover-stay-time="150" + @tap="getResult('cancel')" + > + {{cancelText}} + </view> + <view class="u-select__header__title"> + {{title}} + </view> + <view + class="u-select__header__confirm u-select__header__btn" + :style="{ color: moving ? cancelColor : confirmColor }" + hover-class="u-hover-class" + :hover-stay-time="150" + @touchmove.stop="" + @tap.stop="getResult('confirm')" + > + {{confirmText}} + </view> + </view> + <view class="u-select__body"> + <picker-view @change="columnChange" class="u-select__body__picker-view" :value="defaultSelector" @pickstart="pickstart" @pickend="pickend"> + <picker-view-column v-for="(item, index) in columnData" :key="index"> + <view class="u-select__body__picker-view__item" v-for="(item1, index1) in item" :key="index1"> + <view class="u-line-1">{{ item1[labelName] }}</view> + </view> + </picker-view-column> + </picker-view> + </view> + </view> + </u-popup> + </view> +</template> + +<script> + /** + * select 鍒楅�夋嫨鍣� + * @description 姝ら�夋嫨鍣ㄧ敤浜庡崟鍒楋紝澶氬垪锛屽鍒楄仈鍔ㄧ殑閫夋嫨鍦烘櫙銆�(浠�1.3.0鐗堟湰璧凤紝涓嶅缓璁娇鐢≒icker缁勪欢鐨勫崟鍒楀拰澶氬垪妯″紡锛孲elect缁勪欢鏄笓闂ㄤ负鍒楅�夋嫨鑰屾瀯閫犵殑缁勪欢锛屾洿绠�鍗曟槗鐢ㄣ��) + * @tutorial http://uviewui.com/components/select.html + * @property {String} mode 妯″紡閫夋嫨锛�"single-column"-鍗曞垪妯″紡锛�"mutil-column"-澶氬垪妯″紡锛�"mutil-column-auto"-澶氬垪鑱斿姩妯″紡 + * @property {Array} list 鍒楁暟鎹紝鏁扮粍褰㈠紡锛岃瀹樼綉璇存槑 + * @property {Boolean} v-model 甯冨皵鍊煎彉閲忥紝鐢ㄤ簬鎺у埗閫夋嫨鍣ㄧ殑寮瑰嚭涓庢敹璧� + * @property {Boolean} safe-area-inset-bottom 鏄惁寮�鍚簳閮ㄥ畨鍏ㄥ尯閫傞厤(榛樿false) + * @property {String} cancel-color 鍙栨秷鎸夐挳鐨勯鑹诧紙榛樿#606266锛� + * @property {String} confirm-color 纭鎸夐挳鐨勯鑹�(榛樿#497bff) + * @property {String} confirm-text 纭鎸夐挳鐨勬枃瀛� + * @property {String} cancel-text 鍙栨秷鎸夐挳鐨勬枃瀛� + * @property {String} default-value 鎻愪緵鐨勯粯璁ら�変腑鐨勪笅鏍囷紝瑙佸畼缃戣鏄� + * @property {Boolean} mask-close-able 鏄惁鍏佽閫氳繃鐐瑰嚮閬僵鍏抽棴Picker(榛樿true) + * @property {String Number} z-index 寮瑰嚭鏃剁殑z-index鍊�(榛樿10075) + * @property {String} value-name 鑷畾涔塴ist鏁版嵁鐨剉alue灞炴�у悕 1.3.6 + * @property {String} label-name 鑷畾涔塴ist鏁版嵁鐨刲abel灞炴�у悕 1.3.6 + * @property {String} child-name 鑷畾涔塴ist鏁版嵁鐨刢hildren灞炴�у悕锛屽彧瀵瑰鍒楄仈鍔ㄦā寮忔湁鏁� 1.3.7 + * @event {Function} confirm 鐐瑰嚮纭畾鎸夐挳锛岃繑鍥炲綋鍓嶉�夋嫨鐨勫�� + * @example <u-select v-model="show" :list="list"></u-select> + */ + +export default { + props: { + // 鍒楁暟鎹� + list: { + type: Array, + default() { + return []; + } + }, + // 鏄惁鏄剧ず杈规 + border: { + type: Boolean, + default: true + }, + // 閫氳繃鍙屽悜缁戝畾鎺у埗缁勪欢鐨勫脊鍑轰笌鏀惰捣 + value: { + type: Boolean, + default: false + }, + // "鍙栨秷"鎸夐挳鐨勯鑹� + cancelColor: { + type: String, + default: '#606266' + }, + // "纭畾"鎸夐挳鐨勯鑹� + confirmColor: { + type: String, + default: '#497bff' + }, + // 寮瑰嚭鐨剒-index鍊� + zIndex: { + type: [String, Number], + default: 0 + }, + safeAreaInsetBottom: { + type: Boolean, + default: false + }, + // 鏄惁鍏佽閫氳繃鐐瑰嚮閬僵鍏抽棴Picker + maskCloseAble: { + type: Boolean, + default: true + }, + // 鎻愪緵鐨勯粯璁ら�変腑鐨勪笅鏍� + defaultValue: { + type: Array, + default() { + return [0]; + } + }, + // 妯″紡閫夋嫨锛宻ingle-column-鍗曞垪锛宮util-column-澶氬垪锛宮util-column-auto-澶氬垪鑱斿姩 + mode: { + type: String, + default: 'single-column' + }, + // 鑷畾涔塿alue灞炴�у悕 + valueName: { + type: String, + default: 'value' + }, + // 鑷畾涔塴abel灞炴�у悕 + labelName: { + type: String, + default: 'label' + }, + // 鑷畾涔夊鍒楄仈鍔ㄦā寮忕殑children灞炴�у悕 + childName: { + type: String, + default: 'children' + }, + // 椤堕儴鏍囬 + title: { + type: String, + default: '' + }, + // 鍙栨秷鎸夐挳鐨勬枃瀛� + cancelText: { + type: String, + default: '鍙栨秷' + }, + // 纭鎸夐挳鐨勬枃瀛� + confirmText: { + type: String, + default: '纭' + } + }, + data() { + return { + // 鐢ㄤ簬鍒楁敼鍙樻椂锛屼繚瀛樺綋鍓嶇殑绱㈠紩锛屼笅涓�娆″彉鍖栨椂姣旇緝寰楀嚭鏄摢涓�鍒楀彂鐢熶簡鍙樺寲 + defaultSelector: [0], + // picker-view鐨勬暟鎹� + columnData: [], + // 姣忔闃熷垪鍙戠敓鍙樺寲鏃讹紝淇濆瓨閫夋嫨鐨勭粨鏋� + selectValue: [], + // 涓婁竴娆″垪鍙樺寲鏃剁殑index + lastSelectIndex: [], + // 鍒楁暟 + columnNum: 0, + // 鍒楁槸鍚﹁繕鍦ㄦ粦鍔ㄤ腑锛屽井淇″皬绋嬪簭濡傛灉鍦ㄦ粦鍔ㄤ腑灏辩偣纭畾锛岀粨鏋滃彲鑳戒笉鍑嗙‘ + moving: false + }; + }, + watch: { + // 鍦╯elect寮硅捣鐨勬椂鍊欙紝閲嶆柊鍒濆鍖栨墍鏈夋暟鎹� + value: { + immediate: true, + handler(val) { + if(val) setTimeout(() => this.init(), 10); + } + }, + }, + computed: { + uZIndex() { + // 濡傛灉鐢ㄦ埛鏈変紶閫抸-index鍊硷紝浼樺厛浣跨敤 + return this.zIndex ? this.zIndex : this.$u.zIndex.popup; + }, + }, + methods: { + // 鏍囪瘑婊戝姩寮�濮嬶紝鍙湁寰俊灏忕▼搴忔墠鏈夎繖鏍风殑浜嬩欢 + pickstart() { + // #ifdef MP-WEIXIN + this.moving = true; + // #endif + }, + // 鏍囪瘑婊戝姩缁撴潫 + pickend() { + // #ifdef MP-WEIXIN + this.moving = false; + // #endif + }, + init() { + // 濡傛灉娌℃湁鏁版嵁鐨勬椂鍊欏澶勬姤鏈畾涔� ThinkGem + if (!this.list || this.list.length == 0){ + return + } + this.setColumnNum(); + this.setDefaultSelector(); + this.setColumnData(); + this.setSelectValue(); + }, + // 鑾峰彇榛樿閫変腑鍒椾笅鏍� + setDefaultSelector() { + // 濡傛灉娌℃湁浼犲叆榛樿閫変腑鐨勫�硷紝鐢熸垚闀垮害涓篶olumnNum锛岀敤0濉厖鐨勬暟缁� + this.defaultSelector = this.defaultValue.length == this.columnNum ? this.defaultValue : Array(this.columnNum).fill(0); + this.lastSelectIndex = this.$u.deepClone(this.defaultSelector); + }, + // 璁$畻鍒楁暟 + setColumnNum() { + // 鍗曞垪鐨勫垪鏁颁负1 + if(this.mode == 'single-column') this.columnNum = 1; + // 澶氬垪鏃讹紝this.list鏁扮粍闀垮害灏辨槸鍒楁暟 + else if(this.mode == 'mutil-column') this.columnNum = this.list.length; + // 澶氬垪鑱斿姩鏃讹紝閫氳繃鍘嗛亶this.list鐨勭涓�涓厓绱狅紝寰楀嚭鏈夊灏戝垪 + else if(this.mode == 'mutil-column-auto') { + let num = 1; + let column = this.list; + // 鍙鏈夊厓绱犲苟涓旂涓�涓厓绱犳湁children灞炴�э紝缁х画鍘嗛亶 + while(column[0] && column[0][this.childName]) { // 澧炲姞 column[0] 鍒ゆ柇锛屽鏋滄病鏈夋暟鎹殑鏃跺�欎細鎶� undefined ThinkGem + column = column[0] ? column[0][this.childName] : {}; + num ++; + } + this.columnNum = num; + } + }, + // 鑾峰彇闇�瑕佸睍绀哄湪picker涓殑鍒楁暟鎹� + setColumnData() { + let data = []; + this.selectValue = []; + if(this.mode == 'mutil-column-auto') { + // 鑾峰緱鎵�鏈夋暟鎹腑鐨勭涓�涓厓绱� + let column = this.list[this.defaultSelector.length ? this.defaultSelector[0] : 0]; + // 閫氳繃寰幆鎵�鏈夌殑鍒楁暟锛屽啀鏍规嵁璁惧畾鍒楃殑鏁扮粍锛屽緱鍑哄綋鍓嶉渶瑕佹覆鏌撶殑鏁翠釜鍒楁暟缁� + for (let i = 0; i < this.columnNum; i++) { + // 绗竴鍒楅粯璁や负鏁翠釜list鏁扮粍 + if (i == 0) { + data[i] = this.list; + column = column[this.childName]; + } else { + // 澶т簬绗竴鍒楁椂锛屽垽鏂槸鍚︽湁榛樿閫変腑鐨勶紝濡傛灉娌℃湁灏辩敤璇ュ垪鐨勭涓�椤� + data[i] = column; + column = column[this.defaultSelector[i]][this.childName]; + } + } + } else if(this.mode == 'single-column') { + data[0] = this.list; + } else { + data = this.list; + } + this.columnData = data; + }, + // 鑾峰彇榛樿閫変腑鐨勫�硷紝濡傛灉娌℃湁璁剧疆defaultValue锛屽氨榛樿閫変腑姣忓垪鐨勭涓�涓� + setSelectValue() { + let tmp = null; + for(let i = 0; i < this.columnNum; i++) { + tmp = this.columnData[i][this.defaultSelector[i]]; + let data = { + value: tmp ? tmp[this.valueName] : null, + label: tmp ? tmp[this.labelName] : null + }; + // 鍒ゆ柇鏄惁瀛樺湪棰濆鐨勫弬鏁帮紝濡傛灉瀛樺湪锛屽氨杩斿洖 + if(tmp && tmp.extra) data.extra = tmp.extra; + this.selectValue.push(data) + } + }, + // 鍒楅�夐」 + columnChange(e) { + let index = null; + let columnIndex = e.detail.value; + // 鐢变簬鍚庨潰鏄渶瑕乸ush杩涙暟缁勭殑锛屾墍浠ラ渶瑕佸厛娓呯┖鏁扮粍 + this.selectValue = []; + if(this.mode == 'mutil-column-auto') { + // 瀵规瘮鍓嶅悗涓や釜鏁扮粍锛屽鎵惧彉鏇寸殑鏄摢涓�鍒楋紝濡傛灉鏌愪竴涓厓绱犱笉鍚岋紝鍗冲彲鍒ゅ畾璇ュ垪鍙戠敓浜嗗彉鍖� + this.lastSelectIndex.map((val, idx) => { + if (val != columnIndex[idx]) index = idx; + }); + this.defaultSelector = columnIndex; + for (let i = index + 1; i < this.columnNum; i++) { + // 褰撳墠鍙樺寲鍒楃殑涓嬩竴鍒楃殑鏁版嵁锛岄渶瑕佽幏鍙栦笂涓�鍒楃殑鏁版嵁锛屽悓鏃堕渶瑕佹寚瀹氭槸涓婁竴鍒楃殑绗嚑涓殑children锛屽啀寰�鍚庣殑 + // 榛樿鏄槦鍒楃殑绗竴涓负榛樿閫夐」 + this.columnData[i] = this.columnData[i - 1][i - 1 == index ? columnIndex[index] : 0][this.childName]; + // 鏀瑰彉鐨勫垪涔嬪悗鐨勬墍鏈夊垪锛岄粯璁ら�変腑绗竴涓� + this.defaultSelector[i] = 0; + } + // 鍦ㄥ巻閬嶇殑杩囩▼涓紝鍙兘鐢变簬涓婁竴姝ヤ慨鏀箃his.columnData锛屽鑷翠骇鐢熻繛閿佸弽搴旓紝绋嬪簭瑙﹀彂columnChange锛屼細鏈夊娆¤皟鐢� + // 鍙湁鍦ㄦ渶鍚庝竴娆℃暟鎹ǔ瀹氬悗鐨勭粨鏋滄槸姝g‘鐨勶紝姝ゅ墠鐨勫巻閬嶄腑锛屽彲鑳戒細浜х敓undefined锛屾晠闇�瑕佸垽鏂� + columnIndex.map((item, index) => { + if (!this.columnData[index]){ + return; // 濡傛灉鍒楁爲涓嶅浐瀹氾紝浼氭姤绌� ThinkGem + } + let data = this.columnData[index][columnIndex[index]]; + let tmp = { + value: data ? data[this.valueName] : null, + label: data ? data[this.labelName] : null, + }; + // 鍒ゆ柇鏄惁鏈夐渶瑕侀澶栨惡甯︾殑鍙傛暟 + if(data && data.extra !== undefined) tmp.extra = data.extra; + this.selectValue.push(tmp); + + }) + // 淇濆瓨杩欎竴娆$殑缁撴灉锛岀敤浜庝笅娆″垪鍙戠敓鍙樺寲鏃朵綔姣旇緝 + this.lastSelectIndex = columnIndex; + } else if(this.mode == 'single-column') { + let data = this.columnData[0][columnIndex[0]]; + // 鍒濆榛樿閫変腑鍊� + let tmp = { + value: data ? data[this.valueName] : null, + label: data ? data[this.labelName] : null, + }; + // 鍒ゆ柇鏄惁鏈夐渶瑕侀澶栨惡甯︾殑鍙傛暟 + if(data && data.extra !== undefined) tmp.extra = data.extra; + this.selectValue.push(tmp); + } else if(this.mode == 'mutil-column') { + // 鍒濆榛樿閫変腑鍊� + columnIndex.map((item, index) => { + let data = this.columnData[index][columnIndex[index]]; + // 鍒濆榛樿閫変腑鍊� + let tmp = { + value: data ? data[this.valueName] : null, + label: data ? data[this.labelName] : null, + }; + // 鍒ゆ柇鏄惁鏈夐渶瑕侀澶栨惡甯︾殑鍙傛暟 + if(data && data.extra !== undefined) tmp.extra = data.extra; + this.selectValue.push(tmp); + }) + } + }, + close() { + this.$emit('input', false); + }, + // 鐐瑰嚮纭畾鎴栬�呭彇娑� + getResult(event = null) { + // #ifdef MP-WEIXIN + if (this.moving) return; + // #endif + if (event) this.$emit(event, this.selectValue, this.defaultSelector); + this.close(); + }, + selectHandler() { + this.$emit('click'); + } + } +}; +</script> + +<style scoped lang="scss"> +@import "../../libs/css/style.components.scss"; + +.u-select { + + &__action { + position: relative; + line-height: $u-form-item-height; + height: $u-form-item-height; + + &__icon { + position: absolute; + right: 20rpx; + top: 50%; + transition: transform .4s; + transform: translateY(-50%); + z-index: 1; + + &--reverse { + transform: rotate(-180deg) translateY(50%); + } + } + } + + &__hader { + &__title { + color: $u-content-color; + } + } + + &--border { + border-radius: 6rpx; + border-radius: 4px; + border: 1px solid $u-form-item-border-color; + } + + &__header { + @include vue-flex; + align-items: center; + justify-content: space-between; + height: 80rpx; + padding: 0 40rpx; + } + + &__body { + width: 100%; + height: 500rpx; + overflow: hidden; + background-color: #fff; + + &__picker-view { + height: 100%; + box-sizing: border-box; + + &__item { + @include vue-flex; + align-items: center; + justify-content: center; + font-size: 32rpx; + color: $u-main-color; + padding: 0 8rpx; + } + } + } +} +</style> -- Gitblit v1.9.3