gui-select-menu.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <template>
  2. <view
  3. class="gui-select-menu-wrap">
  4. <!-- #ifndef APP-NVUE -->
  5. <view
  6. class="gui-masker"
  7. v-if="show"
  8. @tap.stop.prevent="close"
  9. @touchmove.stop.prevent="stopfun"
  10. :style="{zIndex:(zIndex-1)}" ></view>
  11. <!-- #endif -->
  12. <view
  13. class="gui-select-menu-title gui-flex gui-rows gui-nowrap gui-justify-content-center gui-align-items-center"
  14. @click.stop="showMenu"
  15. id="menuMain">
  16. <text
  17. class="gui-block gui-ellipsis gui-primary-text"
  18. :style="{
  19. fontSize:fontSize,
  20. }">{{itemsIn[currentIndex]}}</text>
  21. <text
  22. :style="{fontSize:fontSize}"
  23. class="gui-icons gui-select-menu-title-icon gui-block gui-primary-text"
  24. v-if="!show">&#xe603;</text>
  25. <text
  26. :style="{fontSize:fontSize}"
  27. class="gui-icons gui-select-menu-title-icon gui-block gui-primary-text"
  28. v-if="show">&#xe654;</text>
  29. </view>
  30. <view
  31. class="gui-select-menu"
  32. v-if="show"
  33. :style="{
  34. top : top +'px',
  35. zIndex:zIndex
  36. }"
  37. @tap.stop="close"
  38. @touchmove.stop.prevent="stopfun">
  39. <view style="marginTop:90rpx; height:0px;"></view>
  40. <view
  41. style="padding-bottom:10rpx;"
  42. @tap.stop="stopfun"
  43. class="gui-select-item gui-flex gui-rows gui-nowrap gui-align-items-center gui-bg-white gui-dark-bg-level-3"
  44. v-if="isInput">
  45. <view class="gui-select-input gui-flex1 gui-bg-gray gui-dark-bg-level-1">
  46. <input
  47. type="text"
  48. v-model="inputVal"
  49. style="margin:15rpx;"
  50. class="gui-form-input gui-flex1 gui-border-box"
  51. @confirm="addTag"
  52. @input="inputting"
  53. :placeholder="placeholder" />
  54. </view>
  55. <!-- 添加 -->
  56. <text
  57. class="gui-select-input-btn gui-block gui-primary-text"
  58. v-if="inputType == 'add'"
  59. @tap.stop="addTag">{{addBtnName}}</text>
  60. <!-- -->
  61. <text
  62. class="gui-select-input-btn gui-block gui-primary-text"
  63. v-else-if="inputType == 'search'"
  64. @tap.stop="addTag">搜索</text>
  65. </view>
  66. <scroll-view
  67. :scroll-y="true"
  68. :show-scrollbar="false"
  69. :style="{height:height, marginTop:'-2px'}"
  70. class="gui-select-menus gui-border-box gui-bg-white gui-dark-bg-level-3"
  71. :scroll-into-view="itemTo">
  72. <view
  73. class="gui-select-item gui-flex gui-rows gui-nowrap gui-align-items-center"
  74. v-for="(item, index) in itemsIn"
  75. :key="index"
  76. :data-index="index"
  77. @tap.stop="select"
  78. :style="{height:itemHeight}"
  79. :id="'items'+index">
  80. <text
  81. class="gui-selected-icon gui-icons gui-primary-color"
  82. :style="{fontSize:fontSize}"
  83. v-if="index == currentIndex">&#xe7f8;</text>
  84. <text
  85. class="gui-primary-text"
  86. :style="{fontSize:fontSize}">{{item}}</text>
  87. </view>
  88. <view
  89. style="height:25rpx;"
  90. class="gui-bg-white gui-dark-bg-level-3"></view>
  91. </scroll-view>
  92. </view>
  93. </view>
  94. </template>
  95. <script scoped>
  96. export default {
  97. name : "gui-select-menu",
  98. props : {
  99. items : { type : Array, default : function () { return [] } },
  100. selectIndex : { type : Number, default : 0},
  101. isH5header : { type : Boolean, default : true },
  102. fontSize : { type : String, default : '28rpx' },
  103. zIndex : { type : Number, default : 299 },
  104. isInput : { type : Boolean, default : false},
  105. placeholder : { type : String, default : "请输入自定义条件"},
  106. addBtnName : { type : String, default :"+ 添加"},
  107. height : { type : String, default : '500rpx'},
  108. itemHeight : { type : String, default : '88rpx'},
  109. inputType : { type : String, default : 'add' }
  110. },
  111. data() {
  112. return {
  113. currentIndex : 0,
  114. top : 0,
  115. showRes : [],
  116. inputVal : '',
  117. show : false,
  118. itemsIn : [],
  119. itemTo : ''
  120. }
  121. },
  122. watch:{
  123. selectIndex : function () {
  124. this.currentIndex = this.selectIndex;
  125. },
  126. items : function (val) {
  127. this.itemsIn = val;
  128. }
  129. },
  130. created : function () {
  131. this.currentIndex = this.selectIndex;
  132. this.itemsIn = this.items;
  133. },
  134. methods:{
  135. stopfun : function (e) {e.stopPropagation(); return ;},
  136. showMenu : function () {
  137. uni.createSelectorQuery().in(this).select('#menuMain').fields(
  138. {rect: true}, (res) => {
  139. this.top = res.top - 1;
  140. // #ifdef H5
  141. if(this.isH5header){
  142. this.top += 44;
  143. }
  144. // #endif
  145. this.show = true;
  146. this.$emit('showMenu');
  147. }
  148. ).exec();
  149. },
  150. close : function(){
  151. setTimeout(()=>{
  152. this.show = false;
  153. }, 100);
  154. this.$emit('close');
  155. },
  156. select : function(e){
  157. var index = Number(e.currentTarget.dataset.index);
  158. this.currentIndex = index;
  159. this.$emit('select', index, this.items[index]);
  160. this.close();
  161. },
  162. addTag : function () {
  163. if(this.inputVal == ''){return ;}
  164. if(this.inputType == 'add'){
  165. var newArr = JSON.stringify(this.itemsIn);
  166. newArr = JSON.parse(newArr);
  167. newArr.unshift(this.inputVal);
  168. this.itemsIn = [];
  169. this.itemsIn = newArr;
  170. this.$emit('submit', this.inputVal);
  171. this.inputVal = '';
  172. this.currentIndex = 0;
  173. this.close();
  174. }else{
  175. this.search();
  176. }
  177. },
  178. getSize : function(){
  179. return (this.itemsIn.length - 1);
  180. },
  181. setCurrentIndex : function (index) {
  182. this.currentIndex = index;
  183. },
  184. search : function(){
  185. var searchIndex = -1;
  186. for(var i = 0; i < this.itemsIn.length; i++){
  187. if(this.itemsIn[i].indexOf(this.inputVal) != -1){
  188. searchIndex = i;
  189. break;
  190. }
  191. }
  192. if(searchIndex != -1){
  193. this.itemTo = 'items' + searchIndex;
  194. }
  195. },
  196. inputting : function(){
  197. if(this.inputType == 'search'){
  198. this.search();
  199. }
  200. }
  201. },
  202. emits : ['showMenu', 'close', 'select', 'submit']
  203. }
  204. </script>
  205. <style scoped>
  206. .gui-masker{width:750rpx; position:fixed; left:0; top:250rpx; bottom:0; flex:1; background-color:rgba(0,0,0,0.3);}
  207. .gui-select-menu-title{height:100rpx;}
  208. .gui-select-menu-title-icon{margin-left:5px; margin-top:3px;}
  209. .gui-select-menu{position:fixed; width:750rpx; left:0; top:0;}
  210. .gui-select-menus{ height:300px;}
  211. .gui-select-item{padding:0 25rpx; height:88rpx;}
  212. .gui-selected-icon{margin-right:15rpx;}
  213. .gui-select-input{width:200rpx; padding:0 16rpx; border-radius:60rpx;}
  214. .gui-select-input-btn{width:100rpx; line-height:68rpx; height:68rpx; text-align:center; font-size:28rpx; border-radius:6rpx; margin-left:15rpx;}
  215. </style>