Prechádzať zdrojové kódy

Signed-off-by: 李妹妹 <1639016684@qq.com>

李妹妹 1 týždeň pred
rodič
commit
2fd4d2e21b
3 zmenil súbory, kde vykonal 606 pridanie a 128 odobranie
  1. 193 6
      pages_user/addBankCard.vue
  2. 222 117
      pages_user/certification.vue
  3. 191 5
      pages_user/editBankCard.vue

+ 193 - 6
pages_user/addBankCard.vue

@@ -5,12 +5,18 @@
 			<view class="form-section">
 				<view class="form-item">
 					<view class="form-label">开户行</view>
-					<input 
+					<!-- <input 
 						class="form-input" 
 						v-model="formData.bankName" 
 						placeholder="请输入开户行"
 						placeholder-class="text-placeholder"
-					/>
+					/> -->
+					<view style="flex:1" @click="openBankPicker">
+						<view class="form-input picker-input" :class="{ placeholder: !formData.bankName }">
+							{{ getBankLabel() || '请选择开户行' }}
+							<image class="w32 h32" src="/static/image/icon_my_more.png" mode=""></image>
+						</view>
+					</view>
 				</view>
 				<view class="divider"></view>
 				
@@ -45,7 +51,38 @@
 				<view class="notes-item">2、每次更换次数不得超过三次。</view>
 			</view>
 		</scroll-view>
-		
+		<!-- 银行搜索弹窗 -->
+		<view class="search-picker-popup" v-if="showBankPicker" @click="closeBankPicker">
+			<view class="popup-content" @click.stop>
+				<view class="popup-header">
+					<text class="popup-title">选择开户行</text>
+					<view class="popup-close" @click="closeBankPicker">×</view>
+				</view>
+				<view class="search-box">
+					<input 
+						class="search-input" 
+						v-model="bankSearchKeyword" 
+						placeholder="请输入银行名称搜索"
+						@blur="onBankSearch"
+					/>
+				</view>
+				<scroll-view class="search-list" scroll-y>
+					<view 
+						class="search-item" 
+						v-for="(item, index) in filteredBankList" 
+						:key="index"
+						:class="{ active: formData.bankName === item.label }"
+						@click="selectBank(item)"
+					>
+						<text>{{ item.label }}</text>
+						<text v-if="formData.bankName === item.label" class="check-icon">✓</text>
+					</view>
+					<view class="search-empty" v-if="filteredBankList.length === 0">
+						<text>暂无匹配结果</text>
+					</view>
+				</scroll-view>
+			</view>
+		</view>
 		<!-- 底部按钮 -->
 		<view class="bottom-bar">
 			<view class="submit-btn" @click="handleSubmit">确认添加</view>
@@ -54,6 +91,7 @@
 </template>
 
 <script>
+import {getBankTypeList} from '@/api/certification'
 import { addBankCard } from '@/api/bankCard'
 export default {
 	data() {
@@ -62,20 +100,67 @@ export default {
 				"bankBranch": "",
 				  "bankCardNo": "",
 				  "bankName": ""
-			}
+			},
+			showBankPicker: false,
+			bankSearchKeyword: '',
+			filteredBankList: []
 		}
 	},
-	onLoad() {},
+	onLoad() {
+		this.loadBankList()
+	},
 	methods: {
 		goBack() {
 			uni.navigateBack()
 		},
+		getBankLabel() {
+			return this.formData.bankName || ''
+		},
+		openBankPicker() {
+			this.showBankPicker = true
+			this.bankSearchKeyword = ''
+		},
+		openBankPicker() {
+			this.showBankPicker = true
+			this.bankSearchKeyword = ''
+		},
+		closeBankPicker() {
+			this.showBankPicker = false
+		},
+		async onBankSearch() {
+			const keyword = this.bankSearchKeyword.trim()
+			this.loadBankList(keyword)
+		},
+		selectBank(item) {
+			this.formData.bankName = item.label
+			this.closeBankPicker()
+		},
+		// 加载银行列表
+		async loadBankList(keyword) {
+			const params = {}
+			   // 如果传入了关键词,就用传入的
+			   if (keyword) {
+			     params.bankName = keyword.trim()
+			   }
+		  try {
+		    const res = await getBankTypeList(params)
+		    if (res.code === 200) {
+		      const arr = res.data
+		      this.filteredBankList = arr.map(item => ({
+		        label: item.bankName,
+		        value: item.id
+		      })).filter(opt => opt.label)
+		    }
+		  } catch (err) {
+		    console.log('银行类型加载失败', err)
+		  }
+		},
 		async handleSubmit() {
 			// 表单验证
 			if (!this.formData.bankName || !this.formData.bankName.trim()) {
 				uni.showToast({
 					icon: 'none',
-					title: '请输入开户行'
+					title: '请选择开户行'
 				})
 				return
 			}
@@ -289,6 +374,108 @@ export default {
 		color: #fff;
 	}
 }
+.search-picker-popup {
+	position: fixed;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	background: rgba(0, 0, 0, 0.5);
+	z-index: 1000;
+	display: flex;
+	align-items: flex-end;
+	
+	.popup-content {
+		width: 100%;
+	    height: 80vh;
+		background: #fff;
+		border-radius: 24rpx 24rpx 0 0;
+		display: flex;
+		flex-direction: column;
+	}
+	
+	.popup-header {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		padding: 32rpx;
+		border-bottom: 1rpx solid #f0f0f0;
+		
+		.popup-title {
+			font-size: 32rpx;
+			font-weight: bold;
+			color: #333;
+		}
+		
+		.popup-close {
+			font-size: 48rpx;
+			color: #999;
+			line-height: 1;
+		}
+	}
+	
+	.search-box {
+		padding: 24rpx 32rpx;
+		
+		.search-input {
+			//width: 100%;
+			height: 72rpx;
+			background: #f5f5f5;
+			border-radius: 36rpx;
+			padding: 0 32rpx;
+			font-size: 28rpx;
+		}
+	}
+	
+	.search-list {
+		flex: 1;
+		height: 60%;
+		padding: 0 32rpx 40rpx;
+		box-sizing: border-box;
+		.search-item {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			padding: 28rpx 0;
+			border-bottom: 1rpx solid #f5f5f5;
+			
+			&:last-child {
+				border-bottom: none;
+			}
+			
+			&.active {
+				color: #388BFF;
+				
+				text {
+					color: #388BFF;
+				}
+			}
+			
+			.check-icon {
+				color: #388BFF;
+				font-size: 32rpx;
+				font-weight: bold;
+			}
+			
+			text {
+				font-size: 28rpx;
+				color: #333;
+			}
+		}
+		
+		.search-empty {
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			padding: 60rpx 0;
+			
+			text {
+				font-size: 28rpx;
+				color: #999;
+			}
+		}
+	}
+}
 </style>
 
 

+ 222 - 117
pages_user/certification.vue

@@ -79,19 +79,12 @@
 						<text class="required">*</text>
 						<text>科室</text>
 					</view>
-					<picker
-					style="flex:1"
-						mode="selector"
-						:range="departmentList"
-						range-key="label"
-						:value="getDepartmentIndex()"
-						@change="onDepartmentChange"
-					>
+					<view style="flex:1" @click="openDepartmentPicker">
 						<view class="form-input picker-input" :class="{ placeholder: !formData.department }">
 							{{ getDepartmentLabel() || '请选择科室' }}
 							<image class="w32 h32" src="/static/image/icon_my_more.png" mode=""></image>
 						</view>
-					</picker>
+					</view>
 				</view>
 				
 				<view class="form-item">
@@ -191,19 +184,12 @@
 						<text class="required">*</text>
 						<text>开户行</text>
 					</view>
-					<picker
-					style="flex:1"
-						mode="selector"
-						:range="bankList"
-						range-key="label"
-						:value="getBankIndex()"
-						@change="onBankChange"
-					>
+					<view style="flex:1" @click="openBankPicker">
 						<view class="form-input picker-input" :class="{ placeholder: !formData.bankName }">
 							{{ getBankLabel() || '请选择开户行' }}
 							<image class="w32 h32" src="/static/image/icon_my_more.png" mode=""></image>
 						</view>
-					</picker>
+					</view>
 				</view>
 				
 				<view class="form-item">
@@ -245,7 +231,7 @@
 						class="search-input" 
 						v-model="institutionSearchKeyword" 
 						placeholder="请输入机构名称搜索"
-						@input="onInstitutionSearch"
+						@blur="onInstitutionSearch"
 					/>
 				</view>
 				<scroll-view class="search-list" scroll-y>
@@ -266,6 +252,72 @@
 			</view>
 		</view>
 		
+		<!-- 科室搜索弹窗 -->
+		<view class="search-picker-popup" v-if="showDepartmentPicker" @click="closeDepartmentPicker">
+			<view class="popup-content" @click.stop>
+				<view class="popup-header">
+					<text class="popup-title">选择科室</text>
+					<view class="popup-close" @click="closeDepartmentPicker">×</view>
+				</view>
+				<view class="search-box">
+					<input 
+						class="search-input" 
+						v-model="departmentSearchKeyword" 
+						placeholder="请输入科室名称搜索"
+						@blur="onDepartmentSearch"
+					/>
+				</view>
+				<scroll-view class="search-list" scroll-y>
+					<view 
+						class="search-item" 
+						v-for="(item, index) in filteredDepartmentList" 
+						:key="index"
+						:class="{ active: formData.department === item.label }"
+						@click="selectDepartment(item)"
+					>
+						<text>{{ item.label }}</text>
+						<text v-if="formData.department === item.label" class="check-icon">✓</text>
+					</view>
+					<view class="search-empty" v-if="filteredDepartmentList.length === 0">
+						<text>暂无匹配结果</text>
+					</view>
+				</scroll-view>
+			</view>
+		</view>
+		
+		<!-- 银行搜索弹窗 -->
+		<view class="search-picker-popup" v-if="showBankPicker" @click="closeBankPicker">
+			<view class="popup-content" @click.stop>
+				<view class="popup-header">
+					<text class="popup-title">选择开户行</text>
+					<view class="popup-close" @click="closeBankPicker">×</view>
+				</view>
+				<view class="search-box">
+					<input 
+						class="search-input" 
+						v-model="bankSearchKeyword" 
+						placeholder="请输入银行名称搜索"
+						@blur="onBankSearch"
+					/>
+				</view>
+				<scroll-view class="search-list" scroll-y>
+					<view 
+						class="search-item" 
+						v-for="(item, index) in filteredBankList" 
+						:key="index"
+						:class="{ active: formData.bankName === item.label }"
+						@click="selectBank(item)"
+					>
+						<text>{{ item.label }}</text>
+						<text v-if="formData.bankName === item.label" class="check-icon">✓</text>
+					</view>
+					<view class="search-empty" v-if="filteredBankList.length === 0">
+						<text>暂无匹配结果</text>
+					</view>
+				</scroll-view>
+			</view>
+		</view>
+		
 		<!-- 底部操作栏 -->
 		<view class="bottom-bar">
 		
@@ -320,14 +372,17 @@ export default {
 				practiceCertificate: [],
 				titleCertificate: []
 			},
-			institutionList: [],
-			departmentList: [],
-			bankList: [],
 			titleList: [],
 			accountIdentityOptions: [],
 			showInstitutionPicker: false,
 			institutionSearchKeyword: '',
 			filteredInstitutionList: [],
+			showDepartmentPicker: false,
+			departmentSearchKeyword: '',
+			filteredDepartmentList: [],
+			showBankPicker: false,
+			bankSearchKeyword: '',
+			filteredBankList: [],
 		}
 	},
 	onLoad(options) {
@@ -336,7 +391,20 @@ export default {
 		if (options.rejectionInfo) {
 			this.rejectionInfo = decodeURIComponent(options.rejectionInfo)
 		}
-		this.loadData()
+		this.loadIdentityType()
+		    
+		    // 2. 银行类型(单独请求)
+		   this.loadBankList()
+		    
+		    // 3. 医院列表(单独请求)
+		   this.loadInstitutionList()
+		    
+		    // 4. 科室列表(单独请求)
+		   this.loadDepartmentList()
+		    
+		    // 5. 职称列表(单独请求)
+		    this.loadTitleList()
+		//this.loadData()
 	},
 	methods: {
 		extractArray(data) {
@@ -353,10 +421,10 @@ export default {
 			return candidates.find(Array.isArray) || []
 		},
 		getAccountIdentityLabel() {
-			return this.formData.accountType || ''
+			return this.formData.accountType|| ''
 		},
 		getAccountIdentityIndex() {
-			if (!this.formData.accountType) return 0
+			if (!this.formData.accountType) return ''
 			const idx = this.accountIdentityOptions.findIndex(opt => opt.label === this.formData.accountType)
 			return idx >= 0 ? idx : 0
 		},
@@ -366,19 +434,9 @@ export default {
 		getDepartmentLabel() {
 			return this.formData.department || ''
 		},
-		getDepartmentIndex() {
-			if (!this.formData.department) return 0
-			const idx = this.departmentList.findIndex(opt => opt.label === this.formData.department)
-			return idx >= 0 ? idx : 0
-		},
 		getBankLabel() {
 			return this.formData.bankName || ''
 		},
-		getBankIndex() {
-			if (!this.formData.bankName) return 0
-			const idx = this.bankList.findIndex(opt => opt.label === this.formData.bankName)
-			return idx >= 0 ? idx : 0
-		},
 		getTitleLabel() {
 			return this.formData.jobTitle || ''
 		},
@@ -387,62 +445,99 @@ export default {
 			const idx = this.titleList.findIndex(opt => opt.label === this.formData.jobTitle)
 			return idx >= 0 ? idx : 0
 		},
-		async loadData() {
-			try {
-				uni.showLoading({ title: '加载中...' })
-				const [identityRes, bankRes, instRes, departRes, titleRes] = await Promise.all([
-					identityType({ dictType: 'doctor_account_identity_type' }).catch(() => ({ code: 0 })),
-					getBankTypeList().catch(() => ({ code: 0 })),
-					getHospitalList().catch(() => ({ code: 0 })),
-					getDeptData().catch(() => ({ code: 0 })),
-					identityType({ dictType: 'hospital_title' }).catch(() => ({ code: 0 })),
-				])
-
-				if (identityRes.code === 200) {
-					const arr = this.extractArray(identityRes.data)
-					this.accountIdentityOptions = arr.map(item => ({
-						label: item.dictLabel || '',
-						value: item.dictValue
-					})).filter(opt => opt.label)
-				}
-
-				if (bankRes.code === 200) {
-					const arr = this.extractArray(bankRes.data)
-					this.bankList = arr.map(item => ({
-						label: item.bankName || '',
-						value: item.id
-					})).filter(opt => opt.label)
-				}
-
-				if (instRes.code === 200) {
-					const arr = this.extractArray(instRes.data)
-					this.institutionList = arr.map(item => ({
-						label: item.hospitalName || '',
-						value: item.id
-					})).filter(opt => opt.label)
-				}
-
-				if (departRes.code === 200) {
-					const arr = this.extractArray(departRes.data)
-					this.departmentList = arr.map(item => ({
-						label: item.departmentName || '',
-						value: item.id
-					})).filter(opt => opt.label)
-				}
-
-				if (titleRes.code === 200) {
-					const arr = this.extractArray(titleRes.data)
-					this.titleList = arr.map(item => ({
-						label: item.dictLabel || '',
-						value: item.dictValue
-					})).filter(opt => opt.label)
-				}
-
-				uni.hideLoading()
-			} catch (e) {
-				uni.hideLoading()
-				console.error('加载数据失败', e)
-			}
+		// 加载身份类型
+		async loadIdentityType() {
+		  try {
+		    const res = await identityType({ dictType: 'doctor_account_identity_type' })
+		    if (res.code === 200) {
+		      const arr = this.extractArray(res.data)
+		      this.accountIdentityOptions = arr.map(item => ({
+		        label: item.dictLabel || '',
+		        value: item.dictValue
+		      })).filter(opt => opt.label)
+		    }
+		  } catch (err) {
+		    console.log('身份类型加载失败', err)
+		  }
+		},
+		
+		// 加载银行列表
+		async loadBankList(keyword) {
+			const params = {}
+			   // 如果传入了关键词,就用传入的
+			   if (keyword) {
+			     params.bankName = keyword.trim()
+			   }
+		  try {
+		    const res = await getBankTypeList(params)
+		    if (res.code === 200) {
+		      const arr = res.data
+		      this.filteredBankList = arr.map(item => ({
+		        label: item.bankName,
+		        value: item.id
+		      })).filter(opt => opt.label)
+		    }
+		  } catch (err) {
+		    console.log('银行类型加载失败', err)
+		  }
+		},
+		
+		// 加载医院/机构列表
+		async loadInstitutionList(keyword) {
+			 const params = {}
+			    // 如果传入了关键词,就用传入的
+			    if (keyword) {
+			      params.hospitalName = keyword.trim()
+			    }
+		  try {
+		    const res = await getHospitalList(params)
+		    if (res.code == 200) {
+		      const arr = res.data
+		      this.filteredInstitutionList = arr.map(item => ({
+		        label: item.hospitalName,
+		        value: item.id
+		      })).filter(opt => opt.label)
+		    }
+		  } catch (err) {
+		    console.log('医院列表加载失败', err)
+		  }
+		},
+		
+		// 加载科室列表
+		async loadDepartmentList(keyword) {
+			const params = {}
+			   // 如果传入了关键词,就用传入的
+			   if (keyword) {
+			     params.departmentName = keyword.trim()
+			   }
+		  try {
+		    const res = await getDeptData(params)
+		    if (res.code === 200) {
+		      const arr = res.data
+		      this.filteredDepartmentList = arr.map(item => ({
+		        label: item.departmentName,
+		        value: item.id
+		      })).filter(opt => opt.label)
+		    }
+		  } catch (err) {
+		    console.log('科室列表加载失败', err)
+		  }
+		},
+		
+		// 加载职称列表
+		async loadTitleList() {
+		  try {
+		    const res = await identityType({ dictType: 'hospital_title' })
+		    if (res.code === 200) {
+		      const arr = this.extractArray(res.data)
+		      this.titleList = arr.map(item => ({
+		        label: item.dictLabel || '',
+		        value: item.dictValue
+		      })).filter(opt => opt.label)
+		    }
+		  } catch (err) {
+		    console.log('职称列表加载失败', err)
+		  }
 		},
 		onAccountIdentityChange(e) {
 			const selected = this.accountIdentityOptions[e.detail.value]
@@ -453,36 +548,47 @@ export default {
 		openInstitutionPicker() {
 			this.showInstitutionPicker = true
 			this.institutionSearchKeyword = ''
-			this.filteredInstitutionList = this.institutionList
 		},
 		closeInstitutionPicker() {
 			this.showInstitutionPicker = false
 		},
-		onInstitutionSearch() {
-			const keyword = this.institutionSearchKeyword.trim().toLowerCase()
-			if (!keyword) {
-				this.filteredInstitutionList = this.institutionList
-			} else {
-				this.filteredInstitutionList = this.institutionList.filter(item => 
-					item.label.toLowerCase().includes(keyword)
-				)
-			}
+		async onInstitutionSearch() {
+			const keyword = this.institutionSearchKeyword.trim()
+			this.loadInstitutionList(keyword)
 		},
 		selectInstitution(item) {
 			this.formData.institution = item.label
 			this.closeInstitutionPicker()
 		},
-		onDepartmentChange(e) {
-			const selected = this.departmentList[e.detail.value]
-			if (selected) {
-				this.formData.department = selected.label
-			}
+		openDepartmentPicker() {
+			this.showDepartmentPicker = true
+			this.departmentSearchKeyword = ''
 		},
-		onBankChange(e) {
-			const selected = this.bankList[e.detail.value]
-			if (selected) {
-				this.formData.bankName = selected.label
-			}
+		closeDepartmentPicker() {
+			this.showDepartmentPicker = false
+		},
+		async onDepartmentSearch() {
+			const keyword = this.departmentSearchKeyword.trim()
+			this.loadDepartmentList(keyword)
+		},
+		selectDepartment(item) {
+			this.formData.department = item.label
+			this.closeDepartmentPicker()
+		},
+		openBankPicker() {
+			this.showBankPicker = true
+			this.bankSearchKeyword = ''
+		},
+		closeBankPicker() {
+			this.showBankPicker = false
+		},
+		async onBankSearch() {
+			const keyword = this.bankSearchKeyword.trim()
+			this.loadBankList(keyword)
+		},
+		selectBank(item) {
+			this.formData.bankName = item.label
+			this.closeBankPicker()
 		},
 		onTitleChange(e) {
 			const selected = this.titleList[e.detail.value]
@@ -668,7 +774,6 @@ export default {
 					bankCardNo: this.formData.bankCardNo,
 					bankName: this.formData.bankName,
 					companyId: this.formData.companyId,
-					companyName: this.formData.institution,
 					department: this.formData.department,
 					doctorName: this.formData.doctorName,
 					idCard: this.formData.idCard,
@@ -1047,7 +1152,7 @@ export default {
 	
 	.popup-content {
 		width: 100%;
-		max-height: 80vh;
+	    height: 80vh;
 		background: #fff;
 		border-radius: 24rpx 24rpx 0 0;
 		display: flex;
@@ -1078,7 +1183,7 @@ export default {
 		padding: 24rpx 32rpx;
 		
 		.search-input {
-			width: 100%;
+			//width: 100%;
 			height: 72rpx;
 			background: #f5f5f5;
 			border-radius: 36rpx;
@@ -1089,9 +1194,9 @@ export default {
 	
 	.search-list {
 		flex: 1;
-		max-height: 60vh;
-		padding: 0 32rpx;
-		
+		height: 60%;
+		padding: 0 32rpx 40rpx;
+		box-sizing: border-box;
 		.search-item {
 			display: flex;
 			align-items: center;

+ 191 - 5
pages_user/editBankCard.vue

@@ -5,12 +5,18 @@
 			<view class="form-section">
 				<view class="form-item">
 					<view class="form-label">开户行</view>
-					<input 
+					<!-- <input 
 						class="form-input" 
 						v-model="formData.bankName" 
 						placeholder="请输入开户行"
 						placeholder-class="text-placeholder"
-					/>
+					/> -->
+					<view style="flex:1" @click="openBankPicker">
+						<view class="form-input picker-input" :class="{ placeholder: !formData.bankName }">
+							{{ getBankLabel() || '请选择开户行' }}
+							<image class="w32 h32" src="/static/image/icon_my_more.png" mode=""></image>
+						</view>
+					</view>
 				</view>
 				<view class="divider"></view>
 				
@@ -48,7 +54,38 @@
 				<view class="notes-item">2、每次更换次数不得超过三次。</view>
 			</view>
 		</scroll-view>
-		
+		<!-- 银行搜索弹窗 -->
+		<view class="search-picker-popup" v-if="showBankPicker" @click="closeBankPicker">
+			<view class="popup-content" @click.stop>
+				<view class="popup-header">
+					<text class="popup-title">选择开户行</text>
+					<view class="popup-close" @click="closeBankPicker">×</view>
+				</view>
+				<view class="search-box">
+					<input 
+						class="search-input" 
+						v-model="bankSearchKeyword" 
+						placeholder="请输入银行名称搜索"
+						@blur="onBankSearch"
+					/>
+				</view>
+				<scroll-view class="search-list" scroll-y>
+					<view 
+						class="search-item" 
+						v-for="(item, index) in filteredBankList" 
+						:key="index"
+						:class="{ active: formData.bankName === item.label }"
+						@click="selectBank(item)"
+					>
+						<text>{{ item.label }}</text>
+						<text v-if="formData.bankName === item.label" class="check-icon">✓</text>
+					</view>
+					<view class="search-empty" v-if="filteredBankList.length === 0">
+						<text>暂无匹配结果</text>
+					</view>
+				</scroll-view>
+			</view>
+		</view>
 		<!-- 底部按钮 -->
 		<view class="bottom-bar">
 			<view class="save-btn" @click="handleSave">保存</view>
@@ -58,6 +95,7 @@
 </template>
 
 <script>
+import {getBankTypeList} from '@/api/certification'
 import { addBankCard, deleteBankCard, getBankCardInfo } from '@/api/bankCard'
 export default {
 	data() {
@@ -68,7 +106,10 @@ export default {
 				"bankBranch": "",
 				  "bankCardNo": "",
 				  "bankName": ""
-			}
+			},
+			showBankPicker: false,
+			bankSearchKeyword: '',
+			filteredBankList: []
 		}
 	},
 	onLoad(options) {
@@ -77,8 +118,51 @@ export default {
 			
 		// }
 		this.loadBankCardDetail()
+		this.loadBankList()
 	},
 	methods: {
+		getBankLabel() {
+			return this.formData.bankName || ''
+		},
+		openBankPicker() {
+			this.showBankPicker = true
+			this.bankSearchKeyword = ''
+		},
+		openBankPicker() {
+			this.showBankPicker = true
+			this.bankSearchKeyword = ''
+		},
+		closeBankPicker() {
+			this.showBankPicker = false
+		},
+		async onBankSearch() {
+			const keyword = this.bankSearchKeyword.trim()
+			this.loadBankList(keyword)
+		},
+		selectBank(item) {
+			this.formData.bankName = item.label
+			this.closeBankPicker()
+		},
+		// 加载银行列表
+		async loadBankList(keyword) {
+			const params = {}
+			   // 如果传入了关键词,就用传入的
+			   if (keyword) {
+			     params.bankName = keyword.trim()
+			   }
+		  try {
+		    const res = await getBankTypeList(params)
+		    if (res.code === 200) {
+		      const arr = res.data
+		      this.filteredBankList = arr.map(item => ({
+		        label: item.bankName,
+		        value: item.id
+		      })).filter(opt => opt.label)
+		    }
+		  } catch (err) {
+		    console.log('银行类型加载失败', err)
+		  }
+		},
 		formatBankCard(cardNo) {
 		     if (!cardNo || cardNo.length < 8) return cardNo;
 		     const prefix = cardNo.substring(0, 4);
@@ -126,7 +210,7 @@ export default {
 			if (!this.formData.bankName || !this.formData.bankName.trim()) {
 				uni.showToast({
 					icon: 'none',
-					title: '请输入开户行'
+					title: '请选择开户行'
 				})
 				return
 			}
@@ -398,6 +482,108 @@ export default {
 		font-size: 32rpx;
 	}
 }
+.search-picker-popup {
+	position: fixed;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	background: rgba(0, 0, 0, 0.5);
+	z-index: 1000;
+	display: flex;
+	align-items: flex-end;
+	
+	.popup-content {
+		width: 100%;
+	    height: 80vh;
+		background: #fff;
+		border-radius: 24rpx 24rpx 0 0;
+		display: flex;
+		flex-direction: column;
+	}
+	
+	.popup-header {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		padding: 32rpx;
+		border-bottom: 1rpx solid #f0f0f0;
+		
+		.popup-title {
+			font-size: 32rpx;
+			font-weight: bold;
+			color: #333;
+		}
+		
+		.popup-close {
+			font-size: 48rpx;
+			color: #999;
+			line-height: 1;
+		}
+	}
+	
+	.search-box {
+		padding: 24rpx 32rpx;
+		
+		.search-input {
+			//width: 100%;
+			height: 72rpx;
+			background: #f5f5f5;
+			border-radius: 36rpx;
+			padding: 0 32rpx;
+			font-size: 28rpx;
+		}
+	}
+	
+	.search-list {
+		flex: 1;
+		height: 60%;
+		padding: 0 32rpx 40rpx;
+		box-sizing: border-box;
+		.search-item {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			padding: 28rpx 0;
+			border-bottom: 1rpx solid #f5f5f5;
+			
+			&:last-child {
+				border-bottom: none;
+			}
+			
+			&.active {
+				color: #388BFF;
+				
+				text {
+					color: #388BFF;
+				}
+			}
+			
+			.check-icon {
+				color: #388BFF;
+				font-size: 32rpx;
+				font-weight: bold;
+			}
+			
+			text {
+				font-size: 28rpx;
+				color: #333;
+			}
+		}
+		
+		.search-empty {
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			padding: 60rpx 0;
+			
+			text {
+				font-size: 28rpx;
+				color: #999;
+			}
+		}
+	}
+}
 </style>