gui-select-menu.vue 6.8 KB

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