addressChoose.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. <template>
  2. <div class="distpicker-address-wrapper">
  3. <template>
  4. <div class="return">
  5. <i class="fa fa-angle-left" @click="goBack"></i>
  6. 填写企业注册地址
  7. <span @click="goFinish">完成</span>
  8. </div>
  9. <div class="choose">
  10. <div class="form-group" @click="popupVisible = true">
  11. <label for="addr">选择地区</label>
  12. <input readonly
  13. id="addr"
  14. placeholder="地区信息"
  15. v-model="chooseAddress">
  16. <i class="fa fa-map-marker"></i>
  17. </div>
  18. <div class="form-group">
  19. <label for="addrs">详细信息</label>
  20. <textarea placeholder="街道、大厦、楼层信息"
  21. id="addrs"
  22. v-model="detailAddress"
  23. @blur="out"></textarea>
  24. </div>
  25. </div>
  26. </template>
  27. <mt-popup v-model="popupVisible" position="bottom" class="mint-popup">
  28. <template>
  29. <div class="handle">
  30. <span class="cancel" @click="cancel">取消</span>
  31. <span class="sure" @click="sure">完成</span>
  32. </div>
  33. <div :class="addressHeader">
  34. <ul>
  35. <li :class="{'active': tab === 1}" @click="resetProvince">{{ currentProvince && !staticPlaceholder ? currentProvince : placeholders.province }}</li>
  36. <template v-if="!onlyProvince">
  37. <li v-if="showCityTab" :class="{'active': tab === 2}" @click="resetCity">{{ currentCity && !staticPlaceholder ? currentCity : placeholders.city }}</li>
  38. <li v-if="showAreaTab && !hideArea" :class="{'active': tab === 3}">{{ currentArea && !staticPlaceholder ? currentArea : placeholders.area }}</li>
  39. </template>
  40. </ul>
  41. </div>
  42. <div :class="addressContainer">
  43. <ul v-if="tab === 1">
  44. <li v-for="(item, index) in provinces"
  45. :class="{'active': item === currentProvince}"
  46. @click="chooseProvince(item)"
  47. :key="index">
  48. {{ item }}
  49. </li>
  50. </ul>
  51. <template v-if="!onlyProvince">
  52. <ul v-if="tab === 2">
  53. <li v-for="(item, index) in cities"
  54. :class="{'active': item === currentCity}"
  55. @click="chooseCity(item)"
  56. :key="index">
  57. {{ item }}
  58. </li>
  59. </ul>
  60. <ul v-if="tab === 3 && !hideArea">
  61. <li v-for="(item, index) in areas"
  62. :class="{'active': item === currentArea}"
  63. @click="chooseArea(item)"
  64. :key="index">
  65. {{ item }}
  66. </li>
  67. </ul>
  68. </template>
  69. </div>
  70. </template>
  71. </mt-popup>
  72. </div>
  73. </template>
  74. <script>
  75. import DISTRICTS from './districts'
  76. const DEFAULT_CODE = 100000
  77. export default {
  78. name: 'v-distpicker',
  79. props: {
  80. province: { type: [String, Number], default: '' },
  81. city: { type: [String, Number], default: '' },
  82. area: { type: [String, Number], default: '' },
  83. type: { type: String, default: '' },
  84. hideArea: { type: Boolean, default: false },
  85. onlyProvince: { type: Boolean, default: false },
  86. staticPlaceholder: { type: Boolean, default: false },
  87. placeholders: {
  88. type: Object,
  89. default () {
  90. return {
  91. province: '省',
  92. city: '市',
  93. area: '区'
  94. }
  95. }
  96. },
  97. disabled: { type: Boolean, default: false },
  98. addressHeader: { type: String, default: 'address-header' },
  99. addressContainer: { type: String, default: 'address-container' },
  100. popAddress: {type: String},
  101. regStreet: {type: String},
  102. regProvince: {type: String},
  103. regCity: {type: String},
  104. regDistrict: {type: String}
  105. },
  106. data () {
  107. return {
  108. popupVisible: false,
  109. allAddress: '',
  110. detailAddress: '',
  111. chooseAddress: '',
  112. tab: 1,
  113. showCityTab: false,
  114. showAreaTab: false,
  115. provinces: [],
  116. cities: [],
  117. areas: [],
  118. currentProvince: this.determineType(this.province) || this.placeholders.province,
  119. currentCity: this.determineType(this.city) || this.placeholders.city,
  120. currentArea: this.determineType(this.area) || this.placeholders.area
  121. }
  122. },
  123. created () {
  124. this.chooseAddress = this.popAddress
  125. this.detailAddress = this.regStreet
  126. if (this.chooseAddress && this.detailAddress) {
  127. this.allAddress = this.chooseAddress + this.detailAddress
  128. }
  129. this.currentProvince = this.regProvince
  130. this.currentCity = this.regCity
  131. this.currentArea = this.regDistrict
  132. if (this.area && !this.hideArea && !this.onlyProvince) {
  133. this.tab = 3
  134. this.showCityTab = true
  135. this.showAreaTab = true
  136. this.areas = this.getDistricts(this.getAreaCode(this.determineType(this.city), this.area))
  137. } else if (this.city && this.hideArea && !this.onlyProvince) {
  138. this.tab = 2
  139. this.showCityTab = true
  140. this.cities = this.getDistricts(this.getAreaCode(this.determineType(this.province)))
  141. } else {
  142. this.provinces = this.getDistricts()
  143. }
  144. },
  145. watch: {
  146. currentProvince (vaule) {
  147. this.$emit('province', this.setData(vaule))
  148. if (this.onlyProvince) this.emit('selected')
  149. },
  150. currentCity (value) {
  151. this.$emit('city', this.setData(value, this.currentProvince))
  152. if (value !== this.placeholders.city && this.hideArea) this.emit('selected')
  153. },
  154. currentArea (value) {
  155. this.$emit('area', this.setData(value, this.currentProvince))
  156. if (value !== this.placeholders.area) this.emit('selected')
  157. },
  158. province (value) {
  159. this.currentProvince = this.province || this.placeholders.province
  160. this.cities = this.determineValue(this.currentProvince, this.placeholders.province)
  161. },
  162. city (value) {
  163. this.currentCity = this.city || this.placeholders.city
  164. this.areas = this.determineValue(this.currentCity, this.placeholders.city, this.currentProvince)
  165. },
  166. area (value) {
  167. this.currentArea = this.area || this.placeholders.area
  168. }
  169. },
  170. mounted () {
  171. this.$nextTick(() => {
  172. if (!this.regProvince && !this.regProvince && !this.regDistrict) {
  173. console.log('result', !this.regProvince && !this.regProvince && !this.regDistrict)
  174. } else {
  175. this.chooseProvince(this.regProvince)
  176. this.chooseCity(this.regCity)
  177. this.chooseArea(this.regDistrict)
  178. }
  179. })
  180. },
  181. methods: {
  182. // 取消选择地址
  183. cancel () {
  184. this.popupVisible = false
  185. this.allAddress = ''
  186. },
  187. // 完成选择地址
  188. sure () {
  189. if (this.currentProvince.length <= 1) {
  190. this.$toast({
  191. message: '请选择省、市、区',
  192. iconClass: 'el-icon-warning'
  193. })
  194. this.popupVisible = true
  195. } else if (this.currentCity.length <= 1) {
  196. this.$toast({
  197. message: '请选择省、市、区',
  198. iconClass: 'el-icon-warning'
  199. })
  200. this.popupVisible = true
  201. } else if (this.currentArea.length <= 1) {
  202. this.$toast({
  203. message: '请选择省、市、区',
  204. iconClass: 'el-icon-warning'
  205. })
  206. this.popupVisible = true
  207. } else {
  208. this.chooseAddress = this.currentProvince + this.currentCity + this.currentArea
  209. this.popupVisible = false
  210. }
  211. },
  212. // 监听textarea
  213. out () {
  214. if (!this.detailAddress) {
  215. this.$toast({
  216. message: '请输入详情地址',
  217. iconClass: 'el-icon-warning'
  218. })
  219. } else {
  220. let reg = /^(?=.*([\w\u4e00-\u9fa5]+)).*$/
  221. if (!reg.test(this.detailAddress)) {
  222. this.$toast({
  223. message: '请输入详情地址',
  224. iconClass: 'el-icon-warning'
  225. })
  226. }
  227. }
  228. },
  229. // 返回注册页面
  230. goBack () {
  231. if (this.chooseAddress && this.detailAddress) {
  232. this.allAddress = this.popAddress + this.regStreet
  233. this.$emit('getAddress', this.allAddress)
  234. this.$emit('getProvince', this.currentProvince)
  235. this.$emit('getCity', this.currentCity)
  236. this.$emit('getArea', this.currentArea)
  237. this.$emit('getDetailAddress', this.regStreet)
  238. this.$emit('getPopAddress', this.popAddress)
  239. } else if (this.chooseAddress && !this.detailAddress) {
  240. this.$emit('getAddress', '')
  241. this.$emit('getProvince', this.currentProvince)
  242. this.$emit('getCity', this.currentCity)
  243. this.$emit('getArea', this.currentArea)
  244. this.$emit('getDetailAddress', '')
  245. this.$emit('popAddress', this.chooseAddress)
  246. } else if (!this.chooseAddress && this.detailAddress) {
  247. this.$emit('getAddress', '')
  248. this.$emit('getProvince', '')
  249. this.$emit('getCity', '')
  250. this.$emit('getArea', '')
  251. this.$emit('getDetailAddress', this.detailAddress)
  252. this.$emit('popAddress', '')
  253. } else {
  254. this.$emit('getAddress', '')
  255. this.$emit('getProvince', '')
  256. this.$emit('getCity', '')
  257. this.$emit('getArea', '')
  258. this.$emit('getDetailAddress', '')
  259. this.$emit('popAddress', '')
  260. }
  261. this.$emit('showEvent', false)
  262. },
  263. goFinish () {
  264. if (!this.chooseAddress) {
  265. this.$toast({
  266. message: '请选择省、市、区',
  267. iconClass: 'el-icon-warning'
  268. })
  269. } else if (!this.detailAddress) {
  270. this.$toast({
  271. message: '请输入详情地址',
  272. iconClass: 'el-icon-warning'
  273. })
  274. } else {
  275. if (this.chooseAddress && this.detailAddress) {
  276. this.allAddress = this.chooseAddress + this.detailAddress
  277. }
  278. this.$emit('getAddress', this.allAddress)
  279. this.$emit('getProvince', this.currentProvince)
  280. this.$emit('getCity', this.currentCity)
  281. this.$emit('getArea', this.currentArea)
  282. this.$emit('getDetailAddress', this.detailAddress)
  283. this.$emit('getPopAddress', this.chooseAddress)
  284. this.$emit('showEvent', false)
  285. }
  286. },
  287. setData (value, check = '') {
  288. return {
  289. code: this.getAreaCode(value, check),
  290. value: value
  291. }
  292. },
  293. emit (name) {
  294. let data = {
  295. province: this.setData(this.currentProvince)
  296. }
  297. if (!this.onlyProvince) {
  298. this.$set(data, 'city', this.setData(this.currentCity))
  299. }
  300. if (!this.onlyProvince || this.hideArea) {
  301. this.$set(data, 'area', this.setData(this.currentArea))
  302. }
  303. this.$emit(name, data)
  304. },
  305. getCities () {
  306. this.currentCity = this.placeholders.city
  307. this.currentArea = this.placeholders.area
  308. this.cities = this.determineValue(this.currentProvince, this.placeholders.province)
  309. this.cleanList('areas')
  310. if (this.cities === null) {
  311. this.emit('selected')
  312. this.tab = 1
  313. this.showCityTab = false
  314. }
  315. },
  316. getAreas () {
  317. this.currentArea = this.placeholders.area
  318. this.areas = this.determineValue(this.currentCity, this.placeholders.city, this.currentProvince)
  319. if (this.areas === null) {
  320. this.emit('selected')
  321. this.tab = 2
  322. this.showAreaTab = false
  323. }
  324. },
  325. resetProvince () {
  326. this.tab = 1
  327. this.provinces = this.getDistricts()
  328. this.showCityTab = false
  329. this.showAreaTab = false
  330. },
  331. resetCity () {
  332. this.tab = 2
  333. this.showCityTab = true
  334. this.showAreaTab = false
  335. this.getCities()
  336. },
  337. chooseProvince (name) {
  338. this.currentProvince = name
  339. if (this.onlyProvince) return
  340. this.tab = 2
  341. this.showCityTab = true
  342. this.showAreaTab = false
  343. this.getCities()
  344. },
  345. chooseCity (name) {
  346. this.currentCity = name
  347. if (this.hideArea) return
  348. this.tab = 3
  349. this.showCityTab = true
  350. this.showAreaTab = true
  351. this.getAreas()
  352. },
  353. chooseArea (name) {
  354. this.currentArea = name
  355. },
  356. getAreaCode (name, check = '') {
  357. for (let x in DISTRICTS) {
  358. for (let y in DISTRICTS[x]) {
  359. if (name === DISTRICTS[x][y]) {
  360. if (check.length > 0) {
  361. if (y.slice(0, 2) !== this.getAreaCode(check).slice(0, 2)) {
  362. continue
  363. } else {
  364. return y
  365. }
  366. } else {
  367. return y
  368. }
  369. }
  370. }
  371. }
  372. },
  373. getCodeValue (code) {
  374. console.log(code)
  375. for (let x in DISTRICTS) {
  376. for (let y in DISTRICTS[x]) {
  377. if (code === parseInt(y)) {
  378. return DISTRICTS[x][y]
  379. }
  380. }
  381. }
  382. },
  383. getDistricts (code = DEFAULT_CODE) {
  384. return DISTRICTS[code] || []
  385. },
  386. determineValue (currentValue, placeholderValue, check = '') {
  387. if (currentValue === placeholderValue) {
  388. return []
  389. } else {
  390. return this.getDistricts(this.getAreaCode(currentValue, check))
  391. }
  392. },
  393. determineType (value) {
  394. if (typeof value === 'number') {
  395. return this.getCodeValue(value)
  396. }
  397. return value
  398. },
  399. cleanList (name) {
  400. this[name] = []
  401. }
  402. }
  403. }
  404. </script>
  405. <style lang="scss" scoped>
  406. .mint-toast.is-placemiddle {
  407. z-index: 1000;
  408. }
  409. .distpicker-address-wrapper {
  410. color: #9caebf;
  411. .handle {
  412. padding: .3rem;
  413. span{
  414. font-size: .28rem;
  415. color: #2d8cf0;
  416. }
  417. span.cancel{
  418. float: left;
  419. }
  420. span.sure{
  421. float: right;
  422. }
  423. }
  424. .return {
  425. padding: 0 .2rem;
  426. margin-bottom: .3rem;
  427. width: 100%;
  428. height: .9rem;
  429. line-height: .9rem;
  430. font-size: .28rem;
  431. text-align: center;
  432. color: #787878;
  433. background: #fff;
  434. overflow: hidden;
  435. i{
  436. float: left;
  437. font-size: .5rem;
  438. margin-top: .2rem;
  439. font-weight: bold;
  440. color: #000;
  441. }
  442. span{
  443. float: right;
  444. font-size: .3rem;
  445. color: #999;
  446. }
  447. }
  448. .choose{
  449. background: #fff;
  450. div.form-group {
  451. padding: 0 .2rem;
  452. position: relative;
  453. height: 1.5rem;
  454. overflow: hidden;
  455. &:first-child{
  456. height: 1rem;
  457. line-height: 1rem;
  458. border-bottom: 1px solid #ddd;
  459. }
  460. label{
  461. float: left;
  462. margin-right: .6rem;
  463. font-size: .3rem;
  464. font-weight: normal;
  465. color: #505050;
  466. }
  467. input{
  468. float: left;
  469. height: 1rem;
  470. color: #555;
  471. font-size: .28rem;
  472. border: none;
  473. }
  474. textarea {
  475. float: left;
  476. /*width: 4.6rem;*/
  477. height: 1.5rem;
  478. font-size: .28rem;
  479. color: #555;
  480. border: none;
  481. outline: none;
  482. resize:none
  483. }
  484. i{
  485. position: absolute;
  486. top: .3rem;
  487. right: .4rem;
  488. font-size: .4rem;
  489. color: #a0a0a0;
  490. }
  491. }
  492. }
  493. select {
  494. padding: .5rem .75rem;
  495. height: 40px;
  496. font-size: 1rem;
  497. line-height: 1.25;
  498. color: #464a4c;
  499. background-color: #fff;
  500. background-image: none;
  501. -webkit-background-clip: padding-box;
  502. background-clip: padding-box;
  503. border: 1px solid rgba(0,0,0,.15);
  504. border-radius: .25rem;
  505. -webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;
  506. transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;
  507. -o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
  508. transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
  509. transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;
  510. option {
  511. font-weight: normal;
  512. display: block;
  513. white-space: pre;
  514. min-height: 1.2em;
  515. padding: 0px 2px 1px;
  516. }
  517. }
  518. ul {
  519. margin: 0;
  520. padding: 0;
  521. li {
  522. list-style: none;
  523. }
  524. }
  525. .address-header {
  526. background-color: #fff;
  527. ul {
  528. display: flex;
  529. justify-content: space-around;
  530. align-items: stretch;
  531. li {
  532. display: inline-block;
  533. padding: 10px 10px 7px;
  534. color: #000;
  535. &.active {
  536. border-bottom: #52697f solid 3px;
  537. color: #52697f;
  538. font-weight: bold;
  539. }
  540. }
  541. }
  542. }
  543. .address-container {
  544. background-color: #fff;
  545. ul {
  546. height: 4.3rem;
  547. overflow-y: auto;
  548. li {
  549. color: #555;
  550. padding: 8px 10px;
  551. border-top: 1px solid #f6f6f6;
  552. &.active {
  553. color: #52697f;
  554. font-weight: bold;
  555. }
  556. }
  557. }
  558. }
  559. }
  560. </style>