addBankCard.vue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. <template>
  2. <view class="container">
  3. <!-- 导航栏 -->
  4. <view class="navbar">
  5. <view class="nav-left" @click="goBack">
  6. <text class="back-icon"><</text>
  7. </view>
  8. <view class="nav-title">添加银行卡</view>
  9. <view class="nav-right">
  10. <text class="more-icon">...</text>
  11. <text class="eye-icon">O</text>
  12. </view>
  13. </view>
  14. <!-- 表单区域 -->
  15. <scroll-view class="content" scroll-y>
  16. <view class="form-section">
  17. <view class="form-item">
  18. <view class="form-label">开户行</view>
  19. <picker mode="selector" :range="bankList" range-key="name" @change="onBankChange">
  20. <view class="form-input picker-input" :class="{ placeholder: !formData.bank }">
  21. {{ formData.bank || '请选择开户行' }}
  22. <text class="arrow-right">></text>
  23. </view>
  24. </picker>
  25. </view>
  26. <view class="divider"></view>
  27. <view class="form-item">
  28. <view class="form-label">支行</view>
  29. <picker mode="selector" :range="branchList" range-key="name" @change="onBranchChange">
  30. <view class="form-input picker-input" :class="{ placeholder: !formData.branch }">
  31. {{ formData.branch || '请选择支行' }}
  32. <text class="arrow-right">></text>
  33. </view>
  34. </picker>
  35. </view>
  36. <view class="divider"></view>
  37. <view class="form-item">
  38. <view class="form-label">银行卡号</view>
  39. <input
  40. class="form-input"
  41. v-model="formData.cardNumber"
  42. placeholder="请输入银行卡号"
  43. type="number"
  44. maxlength="19"
  45. placeholder-class="placeholder"
  46. />
  47. </view>
  48. </view>
  49. <!-- 注意事项 -->
  50. <view class="notes-section">
  51. <view class="notes-title">注意:</view>
  52. <view class="notes-item">1、只能绑定认证用户本人的银行卡;</view>
  53. <view class="notes-item">2、每次更换次数不得超过三次。</view>
  54. </view>
  55. </scroll-view>
  56. <!-- 底部按钮 -->
  57. <view class="bottom-bar">
  58. <view class="submit-btn" @click="handleSubmit">确认添加</view>
  59. </view>
  60. </view>
  61. </template>
  62. <script>
  63. import { addBankCard, getBankList, getBranchList } from '@/api-js/bankCard'
  64. export default {
  65. data() {
  66. return {
  67. formData: {
  68. bank: '',
  69. branch: '',
  70. cardNumber: ''
  71. },
  72. bankList: [],
  73. branchList: []
  74. }
  75. },
  76. onLoad() {
  77. this.loadBankList()
  78. },
  79. methods: {
  80. async loadBankList() {
  81. try {
  82. const res = await getBankList()
  83. if (res.code === 200 && res.data) {
  84. this.bankList = res.data
  85. } else {
  86. // 默认数据
  87. this.bankList = [
  88. { name: '中国工商银行', id: 1 },
  89. { name: '中国建设银行', id: 2 },
  90. { name: '中国银行', id: 3 },
  91. { name: '中国农业银行', id: 4 }
  92. ]
  93. }
  94. } catch (e) {
  95. console.error('加载银行列表失败', e)
  96. this.bankList = [
  97. { name: '中国工商银行', id: 1 },
  98. { name: '中国建设银行', id: 2 },
  99. { name: '中国银行', id: 3 },
  100. { name: '中国农业银行', id: 4 }
  101. ]
  102. }
  103. },
  104. async loadBranchList(bankId) {
  105. try {
  106. const res = await getBranchList({ bankId })
  107. if (res.code === 200 && res.data) {
  108. this.branchList = res.data
  109. } else {
  110. this.branchList = [
  111. { name: '北京支行', id: 1 },
  112. { name: '上海支行', id: 2 },
  113. { name: '广州支行', id: 3 }
  114. ]
  115. }
  116. } catch (e) {
  117. this.branchList = [
  118. { name: '北京支行', id: 1 },
  119. { name: '上海支行', id: 2 },
  120. { name: '广州支行', id: 3 }
  121. ]
  122. }
  123. },
  124. onBankChange(e) {
  125. const index = e.detail.value
  126. this.formData.bank = this.bankList[index].name
  127. this.formData.bankId = this.bankList[index].id
  128. this.formData.branch = '' // 清空支行选择
  129. if (this.formData.bankId) {
  130. this.loadBranchList(this.formData.bankId)
  131. }
  132. },
  133. onBranchChange(e) {
  134. const index = e.detail.value
  135. this.formData.branch = this.branchList[index].name
  136. this.formData.branchId = this.branchList[index].id
  137. },
  138. goBack() {
  139. uni.navigateBack()
  140. },
  141. async handleSubmit() {
  142. // 表单验证
  143. if (!this.formData.bank) {
  144. uni.showToast({
  145. icon: 'none',
  146. title: '请选择开户行'
  147. })
  148. return
  149. }
  150. if (!this.formData.branch) {
  151. uni.showToast({
  152. icon: 'none',
  153. title: '请选择支行'
  154. })
  155. return
  156. }
  157. if (!this.formData.cardNumber) {
  158. uni.showToast({
  159. icon: 'none',
  160. title: '请输入银行卡号'
  161. })
  162. return
  163. }
  164. // 银行卡号验证(简单验证)
  165. if (this.formData.cardNumber.length < 16) {
  166. uni.showToast({
  167. icon: 'none',
  168. title: '请输入正确的银行卡号'
  169. })
  170. return
  171. }
  172. try {
  173. uni.showLoading({ title: '添加中...' })
  174. const res = await addBankCard(this.formData)
  175. uni.hideLoading()
  176. if (res.code === 200) {
  177. uni.showToast({
  178. icon: 'success',
  179. title: '添加成功'
  180. })
  181. setTimeout(() => {
  182. uni.navigateBack()
  183. }, 1500)
  184. } else {
  185. uni.showToast({
  186. icon: 'none',
  187. title: res.msg || '添加失败'
  188. })
  189. }
  190. } catch (e) {
  191. uni.hideLoading()
  192. uni.showToast({
  193. icon: 'none',
  194. title: '添加失败'
  195. })
  196. }
  197. }
  198. }
  199. }
  200. </script>
  201. <style lang="scss" scoped>
  202. .container {
  203. min-height: 100vh;
  204. background: #f5f5f5;
  205. display: flex;
  206. flex-direction: column;
  207. }
  208. .navbar {
  209. display: flex;
  210. align-items: center;
  211. justify-content: space-between;
  212. padding: 20rpx 24rpx;
  213. background: #fff;
  214. border-bottom: 1rpx solid #f0f0f0;
  215. .nav-left {
  216. width: 60rpx;
  217. .back-icon {
  218. font-size: 36rpx;
  219. color: #333;
  220. font-weight: bold;
  221. }
  222. }
  223. .nav-title {
  224. flex: 1;
  225. text-align: center;
  226. font-size: 36rpx;
  227. font-weight: bold;
  228. color: #333;
  229. }
  230. .nav-right {
  231. display: flex;
  232. align-items: center;
  233. gap: 24rpx;
  234. width: 60rpx;
  235. justify-content: flex-end;
  236. .more-icon {
  237. font-size: 32rpx;
  238. color: #333;
  239. }
  240. .eye-icon {
  241. font-size: 32rpx;
  242. color: #333;
  243. }
  244. }
  245. }
  246. .content {
  247. flex: 1;
  248. padding-bottom: 140rpx;
  249. }
  250. .form-section {
  251. background: #fff;
  252. margin: 24rpx;
  253. border-radius: 16rpx;
  254. overflow: hidden;
  255. .form-item {
  256. display: flex;
  257. align-items: center;
  258. justify-content: space-between;
  259. padding: 32rpx 24rpx;
  260. min-height: 100rpx;
  261. .form-label {
  262. font-size: 28rpx;
  263. color: #333;
  264. font-weight: 500;
  265. width: 150rpx;
  266. }
  267. .form-input {
  268. flex: 1;
  269. font-size: 28rpx;
  270. color: #333;
  271. text-align: right;
  272. margin-left: 24rpx;
  273. &.placeholder {
  274. color: #C8C9CC;
  275. }
  276. &.picker-input {
  277. display: flex;
  278. align-items: center;
  279. justify-content: flex-end;
  280. .arrow-right {
  281. font-size: 32rpx;
  282. color: #999;
  283. margin-left: 8rpx;
  284. }
  285. }
  286. }
  287. }
  288. .divider {
  289. height: 1rpx;
  290. background: #EBEDF0;
  291. margin-left: 24rpx;
  292. }
  293. }
  294. .notes-section {
  295. background: #fff;
  296. border-radius: 16rpx;
  297. padding: 32rpx;
  298. margin: 0 24rpx 24rpx;
  299. .notes-title {
  300. font-size: 28rpx;
  301. font-weight: bold;
  302. color: #333;
  303. margin-bottom: 16rpx;
  304. }
  305. .notes-item {
  306. font-size: 26rpx;
  307. color: #666;
  308. line-height: 1.8;
  309. margin-bottom: 8rpx;
  310. &:last-child {
  311. margin-bottom: 0;
  312. }
  313. }
  314. }
  315. .bottom-bar {
  316. position: fixed;
  317. bottom: 0;
  318. left: 0;
  319. right: 0;
  320. background: #fff;
  321. padding: 24rpx;
  322. border-top: 1rpx solid #f0f0f0;
  323. z-index: 100;
  324. .submit-btn {
  325. width: 100%;
  326. height: 88rpx;
  327. background: #388BFF;
  328. border-radius: 44rpx;
  329. display: flex;
  330. align-items: center;
  331. justify-content: center;
  332. font-size: 32rpx;
  333. font-weight: bold;
  334. color: #fff;
  335. }
  336. }
  337. </style>