Country.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. <template>
  2. <div class="filterInfo" :class="`filter--${size}`">
  3. <block v-if="size === 'big'">
  4. <h3 class="filterInfoTitle">国家和地区</h3>
  5. </block>
  6. <div class="filter-btn" :class="{ noChoose: !valueInfo }" @click="show">
  7. <h3 class="fontNormal">{{ valueInfo ? $t(valueInfo.label) : size === 'big' ? '请选择' : '地区' }}</h3>
  8. <van-icon v-if="size === 'big'" color="#CBCFDB" :size="18" name="arrow" />
  9. <van-icon
  10. v-if="size === 'small'"
  11. :color="valueInfo ? $colors.warn : '#878D99'"
  12. :size="10"
  13. name="arrow-down"
  14. />
  15. </div>
  16. <van-popup :show="showPopup" round position="bottom" custom-style="height: 300px" @close="showPopup = false">
  17. <div class="bar">
  18. <div class="left-icon">
  19. <van-icon v-if="headerInfo" color="#5E636D" @click="back" :size="18" name="arrow-left" />
  20. </div>
  21. <h3>国家地区</h3>
  22. <van-icon color="#5E636D" :size="18" name="cross" @click="showPopup = false" />
  23. </div>
  24. <van-cell-group :border="false">
  25. <van-cell
  26. @click="backChoose(headerInfo.value)"
  27. v-if="headerInfo"
  28. :border="false"
  29. :custom-class="chooseId === headerInfo.value ? 'active' : ''"
  30. >
  31. <h3 class="fontNormal" slot="title">全部{{ $t(headerInfo.label) }}地区</h3>
  32. <van-icon
  33. v-if="chooseId === headerInfo.value"
  34. slot="right-icon"
  35. :size="18"
  36. :color="$colors.warn"
  37. name="success"
  38. />
  39. </van-cell>
  40. <block v-for="item in showList" :key="item.value">
  41. <van-cell
  42. @click="chooseList(item)"
  43. :border="false"
  44. :custom-class="chooseId === item.value ? 'active' : ''"
  45. >
  46. <h3 class="fontNormal" slot="title">{{ $t(item.label) }}</h3>
  47. <van-icon
  48. v-if="chooseId === item.value"
  49. slot="right-icon"
  50. :size="18"
  51. :color="$colors.warn"
  52. name="success"
  53. />
  54. </van-cell>
  55. </block>
  56. </van-cell-group>
  57. </van-popup>
  58. </div>
  59. </template>
  60. <script>
  61. import { getArray } from '../../utils/commont';
  62. import { mapState } from 'vuex';
  63. export default {
  64. props: {
  65. value: {
  66. type: [Number, String],
  67. default: 0
  68. },
  69. size: {
  70. type: String,
  71. default: 'big'
  72. }
  73. },
  74. data() {
  75. return {
  76. showPopup: false,
  77. list: [],
  78. chooseId: 0,
  79. main: null
  80. };
  81. },
  82. computed: {
  83. ...mapState(['areaList']),
  84. showList() {
  85. const list = [...this.list];
  86. if (this.isLeaf) {
  87. return list.filter(item => {
  88. return item.parent === this.chooseInfo.parent && item.value !== this.chooseInfo.parent;
  89. });
  90. } else if (this.chooseId) {
  91. return list.filter(item => {
  92. return item.parent === this.chooseId && item.value !== this.chooseId;
  93. });
  94. } else {
  95. return list.filter(item => {
  96. return !item.parent;
  97. });
  98. }
  99. },
  100. isLeaf() {
  101. if (this.chooseInfo && !this.chooseInfo.children) {
  102. return true;
  103. }
  104. return false;
  105. },
  106. chooseInfo() {
  107. const list = [...this.list];
  108. return list.find(item => {
  109. return item.value === this.chooseId;
  110. });
  111. },
  112. valueInfo() {
  113. const list = [...this.list];
  114. return list.find(item => {
  115. return item.value === this.value;
  116. });
  117. },
  118. headerInfo() {
  119. if (this.isLeaf) {
  120. const list = [...this.list];
  121. return list.find(item => {
  122. return item.value === this.chooseInfo.parent;
  123. });
  124. } else {
  125. return this.chooseInfo;
  126. }
  127. }
  128. },
  129. mounted() {
  130. console.log(this.areaList);
  131. this.list = getArray(this.areaList, '', 2).flat(Infinity);
  132. },
  133. methods: {
  134. chooseList(info) {
  135. if (info.children && info.children.length > 0) {
  136. this.chooseId = info.value;
  137. } else {
  138. this.chooseId = info.value;
  139. this.backChoose();
  140. }
  141. },
  142. back() {
  143. if (this.headerInfo) {
  144. this.chooseId = this.headerInfo.parent || 0;
  145. }
  146. },
  147. backChoose(value) {
  148. this.$emit('input', value || this.chooseId || '');
  149. this.showPopup = false;
  150. },
  151. show() {
  152. console.log(this.valueInfo);
  153. this.chooseId = this.value || 0;
  154. this.showPopup = true;
  155. },
  156. clear() {
  157. this.chooseId = 0;
  158. this.backChoose();
  159. }
  160. }
  161. };
  162. </script>
  163. <style lang="less">
  164. .van-popup {
  165. .bar {
  166. position: sticky;
  167. top: 0;
  168. height: 48px;
  169. background: #ffffff;
  170. display: flex;
  171. align-items: center;
  172. padding: 0 16px;
  173. margin-bottom: 6px;
  174. z-index: 20;
  175. .left-icon {
  176. width: 18px;
  177. }
  178. h3 {
  179. flex-grow: 1;
  180. text-align: center;
  181. padding: 0 10px;
  182. }
  183. }
  184. .van-cell {
  185. padding: 12px 40px;
  186. &.active {
  187. h3 {
  188. color: @warn;
  189. }
  190. }
  191. }
  192. }
  193. .filterInfo {
  194. &.filter--big {
  195. padding: 0 16px 20px;
  196. .filter-btn {
  197. height: 44px;
  198. padding: 0 16px;
  199. h3 {
  200. padding-right: 10px;
  201. }
  202. &.noChoose {
  203. h3 {
  204. color: #bcc1cc;
  205. }
  206. }
  207. }
  208. }
  209. &.filter--small {
  210. .filter-btn {
  211. height: 28px;
  212. padding: 0 5px 0 10px;
  213. background-color: #fff4e5;
  214. h3 {
  215. font-size: 12px;
  216. color: @warn;
  217. padding-right: 2px;
  218. }
  219. &.noChoose {
  220. background: #f2f3f5;
  221. h3 {
  222. color: #878d99;
  223. }
  224. }
  225. }
  226. }
  227. h4 {
  228. padding: 14px 0;
  229. }
  230. .filter-btn {
  231. background: #f5f7fa;
  232. border-radius: 4px;
  233. display: flex;
  234. align-items: center;
  235. h3 {
  236. flex-grow: 1;
  237. }
  238. }
  239. }
  240. </style>