as-select-item.vue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. <template>
  2. <view
  3. class="as-list-item"
  4. :class="{
  5. 'focus': focusValue == data[valueKey],
  6. 'disabled': disabled
  7. }">
  8. <view class="as-list-content" @tap="onClick">
  9. <view class="triangle-placeholder" v-if="hasChildren" >
  10. <view class="triangle-container" @tap.stop="toggle">
  11. <view class="triangle" :style="{'transform': open ? 'rotate(90deg)' : 'none'}"></view>
  12. </view>
  13. </view>
  14. <text style="margin-left: 5px;">{{data[labelKey]}}</text>
  15. </view>
  16. <view class="as-list-border"></view>
  17. <view v-if="hasChildren && open" class="as-list">
  18. <as-select-item
  19. v-for="item in data.children"
  20. :key="item[valueKey]"
  21. :data="item"
  22. :labelKey="labelKey"
  23. :valueKey="valueKey"
  24. :checkStrictly="checkStrictly"
  25. :disabled="item.disabled"
  26. @onSelect="onSelect">
  27. </as-select-item>
  28. </view>
  29. </view>
  30. </template>
  31. <script>
  32. import AsSelectItem from './as-select-item.vue';
  33. export default{
  34. name: 'AsSelectItem',
  35. props: {
  36. data: {
  37. type: Object,
  38. default: function() {
  39. return {}
  40. }
  41. },
  42. valueKey: {
  43. type: String,
  44. default: 'value'
  45. },
  46. labelKey: {
  47. type: String,
  48. default: 'label'
  49. },
  50. // 是否可以选择任意一级
  51. checkStrictly: {
  52. type: Boolean,
  53. default: false
  54. },
  55. disabled: {
  56. type: Boolean,
  57. default: false
  58. }
  59. },
  60. components: {
  61. AsSelectItem
  62. },
  63. data() {
  64. return {
  65. open: false,
  66. focusValue: null
  67. }
  68. },
  69. computed: {
  70. hasChildren: function(){
  71. return this.data.children && this.data.children.length
  72. }
  73. },
  74. methods: {
  75. onClick(){
  76. if(!this.disabled){
  77. this.focusValue = this.data[this.valueKey];
  78. setTimeout(()=> {
  79. this.focusValue = null;
  80. if(this.checkStrictly || !this.hasChildren){
  81. this.onSelect(this.data[this.valueKey]);
  82. }else{
  83. this.toggle();
  84. }
  85. }, 100)
  86. }
  87. },
  88. toggle(){
  89. this.open = !this.open;
  90. },
  91. onSelect(val){
  92. this.$emit('onSelect', val);
  93. }
  94. }
  95. }
  96. </script>
  97. <style lang="scss" scoped>
  98. $border-color: #e5e5e5;
  99. .as-list-item{
  100. color: #666;
  101. font-size: 26rpx;
  102. .triangle-container{
  103. // padding: 5px 8px;
  104. width: 52rpx;
  105. height: 52rpx;
  106. display: flex;
  107. justify-content: center;
  108. align-items: center;;
  109. }
  110. .triangle {
  111. border-left: 16rpx solid #c0c4cc;
  112. border-top: 12rpx solid transparent;
  113. border-bottom: 12rpx solid transparent;
  114. }
  115. .as-list-border{
  116. position: relative;
  117. margin-left: 15px;
  118. &:after {
  119. position: absolute;
  120. top: 0;
  121. right: 0;
  122. left: 0;
  123. height: 1px;
  124. content: "";
  125. -webkit-transform: scaleY(.5);
  126. transform: scaleY(.5);
  127. background-color: $border-color;
  128. }
  129. }
  130. .as-list-content{
  131. padding: 10px 15px;
  132. line-height: 30px;
  133. display: flex;
  134. align-items: center;
  135. }
  136. .as-list{
  137. padding-left: 20px;
  138. .as-list-content{
  139. position: relative;
  140. &::before{
  141. content: '';
  142. border-left: 1px dashed $border-color;
  143. height: 26px;
  144. width: 1px;
  145. position: absolute;
  146. left: 8px;
  147. top: 50%;
  148. margin-top: -13px;
  149. }
  150. &::after{
  151. content: '';
  152. border-bottom: 1px dashed $border-color;
  153. height: 1px;
  154. width: 8px;
  155. position: absolute;
  156. top: 50%;
  157. left: 9px;
  158. margin-top: -1px;
  159. }
  160. }
  161. }
  162. &.focus>.as-list-content{
  163. background: #f1f1f1;
  164. }
  165. &.disabled>.as-list-content{
  166. color: #c7c7c7;
  167. }
  168. }
  169. </style>