274 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Vue
		
	
	
	
			
		
		
	
	
			274 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Vue
		
	
	
	
| <template>
 | |
|   <div
 | |
|     v-if="popupVisible"
 | |
|     class="region-select-overlay"
 | |
|     @click.self="handleClose"
 | |
|   >
 | |
|     <div class="region-select-popup">
 | |
|       <div class="popup-header">
 | |
|         <h3 class="popup-title">选择收益区域</h3>
 | |
|       </div>
 | |
|       <div class="popup-content">
 | |
|         <picker-view
 | |
|           v-if="popupVisible"
 | |
|           class="picker-view"
 | |
|           :indicator-style="indicatorStyle"
 | |
|           :value="pickerValue"
 | |
|           @change="handlePickerChange"
 | |
|         >
 | |
|           <picker-view-column>
 | |
|             <div v-for="p in provinces" :key="p.id" class="picker-item">
 | |
|               {{ p.name }}
 | |
|             </div>
 | |
|           </picker-view-column>
 | |
|           <picker-view-column>
 | |
|             <div v-for="c in cities" :key="c.id" class="picker-item">
 | |
|               {{ c.name }}
 | |
|             </div>
 | |
|           </picker-view-column>
 | |
|           <picker-view-column>
 | |
|             <div v-for="d in districts" :key="d.id" class="picker-item">
 | |
|               {{ d.name }}
 | |
|             </div>
 | |
|           </picker-view-column>
 | |
|         </picker-view>
 | |
|       </div>
 | |
|       <div class="popup-footer">
 | |
|         <button class="popup-btn popup-cancel" @click="handleClose">
 | |
|           取消
 | |
|         </button>
 | |
|         <button class="popup-btn popup-confirm" @click="handleConfirm">
 | |
|           确认
 | |
|         </button>
 | |
|       </div>
 | |
|     </div>
 | |
|   </div>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import { getRegionSelect, setRegion, getRegionAreaTree } from '@/config/mine.js'
 | |
| 
 | |
| export default {
 | |
|   name: 'region-select',
 | |
|   data() {
 | |
|     return {
 | |
|       popupVisible: false,
 | |
|       areaTree: [],
 | |
|       provinces: [],
 | |
|       cities: [],
 | |
|       districts: [],
 | |
|       pickerValue: [0, 0, 0],
 | |
|       indicatorStyle: `height: 50px;`,
 | |
|     }
 | |
|   },
 | |
|   async created() {
 | |
|     try {
 | |
|       const res = await getRegionSelect()
 | |
|       if (
 | |
|         res.code === 200 &&
 | |
|         res.data &&
 | |
|         res.data.regionStatus === 0 &&
 | |
|         !res.data.province
 | |
|       ) {
 | |
|         this.open()
 | |
|       }
 | |
|     } catch (error) {
 | |
|       console.error('Failed to get region select info:', error)
 | |
|     }
 | |
|   },
 | |
|   methods: {
 | |
|     async open() {
 | |
|       return new Promise(async (resolve, reject) => {
 | |
|         if (this.areaTree?.length === 0) {
 | |
|           await this.loadAreaTree()
 | |
|         }
 | |
|         this.popupVisible = true
 | |
|         resolve()
 | |
|       })
 | |
|     },
 | |
|     async loadAreaTree() {
 | |
|       try {
 | |
|         const res = await getRegionAreaTree()
 | |
|         if (res.code === 200 && res.data) {
 | |
|           this.areaTree = res.data
 | |
|           this.provinces = this.areaTree
 | |
|           if (this.provinces.length > 0) {
 | |
|             this.cities = this.provinces[0].children || []
 | |
|             if (this.cities.length > 0) {
 | |
|               this.districts = this.cities[0].children || []
 | |
|             } else {
 | |
|               this.districts = []
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       } catch (error) {
 | |
|         console.error('Failed to load area tree:', error)
 | |
|       }
 | |
|     },
 | |
|     handlePickerChange(e) {
 | |
|       const [pIndex, cIndex] = e.detail.value
 | |
|       const oldPIndex = this.pickerValue[0]
 | |
|       const oldCIndex = this.pickerValue[1]
 | |
| 
 | |
|       this.pickerValue = e.detail.value
 | |
| 
 | |
|       if (pIndex !== oldPIndex) {
 | |
|         this.cities = this.provinces[pIndex]?.children || []
 | |
|         this.districts = this.cities[0]?.children || []
 | |
|       } else if (cIndex !== oldCIndex) {
 | |
|         this.districts = this.cities[cIndex]?.children || []
 | |
|       }
 | |
|     },
 | |
|     handleClose() {
 | |
|       this.popupVisible = false
 | |
|     },
 | |
|     async handleConfirm() {
 | |
|       const [pIndex, cIndex, dIndex] = this.pickerValue
 | |
|       const province = this.provinces[pIndex]
 | |
|       const city = this.cities[cIndex]
 | |
|       const district = this.districts[dIndex]
 | |
| 
 | |
|       if (!province || !city || !district) {
 | |
|         return
 | |
|       }
 | |
|       try {
 | |
|         const params = {
 | |
|           province: province.id,
 | |
|           city: city.id,
 | |
|           county: district.id,
 | |
|         }
 | |
|         const res = await setRegion(params)
 | |
|         if (res.code === 200) {
 | |
|           this.handleClose()
 | |
|           this.$emit('success')
 | |
|         } else {
 | |
|           throw new Error(res.message || 'Failed to set region')
 | |
|         }
 | |
|       } catch (error) {
 | |
|         console.error('Failed to set region:', error)
 | |
|       }
 | |
|     },
 | |
|   },
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <style scoped>
 | |
| .region-select-overlay {
 | |
|   position: fixed;
 | |
|   top: 0;
 | |
|   left: 0;
 | |
|   width: 100%;
 | |
|   height: 100%;
 | |
|   background-color: rgba(0, 0, 0, 0.5);
 | |
|   display: flex;
 | |
|   align-items: center;
 | |
|   justify-content: center;
 | |
|   z-index: 1000;
 | |
|   transition: opacity 0.3s ease;
 | |
| }
 | |
| 
 | |
| .region-select-popup {
 | |
|   width: 90%;
 | |
|   max-width: 680rpx;
 | |
|   background-color: white;
 | |
|   border-radius: 24rpx;
 | |
|   animation: scale-up 0.3s ease-out;
 | |
|   max-height: 80vh;
 | |
|   display: flex;
 | |
|   flex-direction: column;
 | |
|   overflow: hidden;
 | |
|   box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.1);
 | |
| }
 | |
| 
 | |
| .popup-header {
 | |
|   display: flex;
 | |
|   justify-content: center;
 | |
|   align-items: center;
 | |
|   padding: 30rpx;
 | |
|   border-bottom: 1rpx solid #f5f5f5;
 | |
|   flex-shrink: 0;
 | |
| }
 | |
| 
 | |
| .popup-title {
 | |
|   font-size: 32rpx;
 | |
|   font-weight: 600;
 | |
|   color: #1c1c1e;
 | |
|   margin: 0;
 | |
| }
 | |
| 
 | |
| .popup-btn {
 | |
|   border: none;
 | |
|   background: none;
 | |
|   cursor: pointer;
 | |
| }
 | |
| 
 | |
| .popup-content {
 | |
|   overflow: hidden;
 | |
|   flex-grow: 1;
 | |
| }
 | |
| 
 | |
| .picker-view {
 | |
|   width: 100%;
 | |
|   height: 500rpx;
 | |
| }
 | |
| 
 | |
| .picker-item {
 | |
|   display: flex;
 | |
|   align-items: center;
 | |
|   justify-content: center;
 | |
|   height: 50px;
 | |
|   font-size: 30rpx;
 | |
|   color: #666;
 | |
|   white-space: nowrap;
 | |
|   overflow: hidden;
 | |
|   text-overflow: ellipsis;
 | |
| }
 | |
| 
 | |
| .popup-footer {
 | |
|   display: flex;
 | |
|   flex-shrink: 0;
 | |
|   padding: 24rpx;
 | |
|   gap: 24rpx;
 | |
|   background-color: #f7f7f7;
 | |
|   border-top: 1rpx solid #efefef;
 | |
| }
 | |
| 
 | |
| .popup-footer .popup-btn {
 | |
|   flex: 1;
 | |
|   text-align: center;
 | |
|   padding: 14rpx 0;
 | |
|   font-size: 28rpx;
 | |
|   border-radius: 40rpx;
 | |
|   font-weight: 500;
 | |
|   transition:
 | |
|     transform 0.1s ease,
 | |
|     box-shadow 0.2s ease;
 | |
| }
 | |
| 
 | |
| .popup-footer .popup-btn:active {
 | |
|   transform: scale(0.97);
 | |
| }
 | |
| 
 | |
| .popup-footer .popup-cancel {
 | |
|   background-color: #eee;
 | |
|   color: #555;
 | |
| }
 | |
| 
 | |
| .popup-footer .popup-confirm {
 | |
|   background: linear-gradient(135deg, #007aff, #0056b3);
 | |
|   color: white;
 | |
|   box-shadow: 0 4rpx 12rpx rgba(0, 122, 255, 0.25);
 | |
| }
 | |
| 
 | |
| @keyframes scale-up {
 | |
|   from {
 | |
|     transform: scale(0.8);
 | |
|     opacity: 0;
 | |
|   }
 | |
|   to {
 | |
|     transform: scale(1);
 | |
|     opacity: 1;
 | |
|   }
 | |
| }
 | |
| </style>
 |