editBankCard.vue 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  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="save-btn" @click="handleSave">保存</view>
  59. <view class="unbind-btn" @click="handleUnbind">解除绑定</view>
  60. </view>
  61. </view>
  62. </template>
  63. <script>
  64. import { updateBankCard, deleteBankCard, getBankCardDetail, getBankList, getBranchList } from '@/api-js/bankCard'
  65. export default {
  66. data() {
  67. return {
  68. cardId: '',
  69. formData: {
  70. bank: '',
  71. branch: '',
  72. cardNumber: ''
  73. },
  74. bankList: [],
  75. branchList: []
  76. }
  77. },
  78. onLoad(options) {
  79. if (options.id) {
  80. this.cardId = options.id
  81. this.loadBankCardDetail()
  82. }
  83. this.loadBankList()
  84. },
  85. methods: {
  86. async loadBankCardDetail() {
  87. try {
  88. uni.showLoading({ title: '加载中...' })
  89. const res = await getBankCardDetail({ id: this.cardId })
  90. uni.hideLoading()
  91. if (res.code === 200 && res.data) {
  92. this.formData = {
  93. bank: res.data.bankName || '',
  94. branch: res.data.branchName || '',
  95. cardNumber: res.data.cardNumber || ''
  96. }
  97. if (res.data.bankId) {
  98. this.loadBranchList(res.data.bankId)
  99. }
  100. }
  101. } catch (e) {
  102. uni.hideLoading()
  103. console.error('加载银行卡详情失败', e)
  104. }
  105. },
  106. async loadBankList() {
  107. try {
  108. const res = await getBankList()
  109. if (res.code === 200 && res.data) {
  110. this.bankList = res.data
  111. } else {
  112. this.bankList = [
  113. { name: '中国工商银行', id: 1 },
  114. { name: '中国建设银行', id: 2 },
  115. { name: '中国银行', id: 3 },
  116. { name: '中国农业银行', id: 4 }
  117. ]
  118. }
  119. } catch (e) {
  120. this.bankList = [
  121. { name: '中国工商银行', id: 1 },
  122. { name: '中国建设银行', id: 2 },
  123. { name: '中国银行', id: 3 },
  124. { name: '中国农业银行', id: 4 }
  125. ]
  126. }
  127. },
  128. async loadBranchList(bankId) {
  129. try {
  130. const res = await getBranchList({ bankId })
  131. if (res.code === 200 && res.data) {
  132. this.branchList = res.data
  133. } else {
  134. this.branchList = [
  135. { name: '北京支行', id: 1 },
  136. { name: '上海支行', id: 2 },
  137. { name: '广州支行', id: 3 }
  138. ]
  139. }
  140. } catch (e) {
  141. this.branchList = [
  142. { name: '北京支行', id: 1 },
  143. { name: '上海支行', id: 2 },
  144. { name: '广州支行', id: 3 }
  145. ]
  146. }
  147. },
  148. onBankChange(e) {
  149. const index = e.detail.value
  150. this.formData.bank = this.bankList[index].name
  151. this.formData.bankId = this.bankList[index].id
  152. this.formData.branch = ''
  153. if (this.formData.bankId) {
  154. this.loadBranchList(this.formData.bankId)
  155. }
  156. },
  157. onBranchChange(e) {
  158. const index = e.detail.value
  159. this.formData.branch = this.branchList[index].name
  160. this.formData.branchId = this.branchList[index].id
  161. },
  162. goBack() {
  163. uni.navigateBack()
  164. },
  165. async handleSave() {
  166. // 表单验证
  167. if (!this.formData.bank) {
  168. uni.showToast({
  169. icon: 'none',
  170. title: '请选择开户行'
  171. })
  172. return
  173. }
  174. if (!this.formData.branch) {
  175. uni.showToast({
  176. icon: 'none',
  177. title: '请选择支行'
  178. })
  179. return
  180. }
  181. if (!this.formData.cardNumber) {
  182. uni.showToast({
  183. icon: 'none',
  184. title: '请输入银行卡号'
  185. })
  186. return
  187. }
  188. if (this.formData.cardNumber.length < 16) {
  189. uni.showToast({
  190. icon: 'none',
  191. title: '请输入正确的银行卡号'
  192. })
  193. return
  194. }
  195. try {
  196. uni.showLoading({ title: '保存中...' })
  197. const res = await updateBankCard({
  198. id: this.cardId,
  199. ...this.formData
  200. })
  201. uni.hideLoading()
  202. if (res.code === 200) {
  203. uni.showToast({
  204. icon: 'success',
  205. title: '保存成功'
  206. })
  207. setTimeout(() => {
  208. uni.navigateBack()
  209. }, 1500)
  210. } else {
  211. uni.showToast({
  212. icon: 'none',
  213. title: res.msg || '保存失败'
  214. })
  215. }
  216. } catch (e) {
  217. uni.hideLoading()
  218. uni.showToast({
  219. icon: 'none',
  220. title: '保存失败'
  221. })
  222. }
  223. },
  224. handleUnbind() {
  225. uni.showModal({
  226. title: '提示',
  227. content: '确定要解除绑定该银行卡吗?',
  228. success: async (res) => {
  229. if (res.confirm) {
  230. try {
  231. uni.showLoading({ title: '解除绑定中...' })
  232. const result = await deleteBankCard({ id: this.cardId })
  233. uni.hideLoading()
  234. if (result.code === 200) {
  235. uni.showToast({
  236. icon: 'success',
  237. title: '解除绑定成功'
  238. })
  239. setTimeout(() => {
  240. uni.navigateBack()
  241. }, 1500)
  242. } else {
  243. uni.showToast({
  244. icon: 'none',
  245. title: result.msg || '解除绑定失败'
  246. })
  247. }
  248. } catch (e) {
  249. uni.hideLoading()
  250. uni.showToast({
  251. icon: 'none',
  252. title: '解除绑定失败'
  253. })
  254. }
  255. }
  256. }
  257. })
  258. }
  259. }
  260. }
  261. </script>
  262. <style lang="scss" scoped>
  263. .container {
  264. min-height: 100vh;
  265. background: #f5f5f5;
  266. display: flex;
  267. flex-direction: column;
  268. }
  269. .navbar {
  270. display: flex;
  271. align-items: center;
  272. justify-content: space-between;
  273. padding: 20rpx 24rpx;
  274. background: #fff;
  275. border-bottom: 1rpx solid #f0f0f0;
  276. .nav-left {
  277. width: 60rpx;
  278. .back-icon {
  279. font-size: 36rpx;
  280. color: #333;
  281. font-weight: bold;
  282. }
  283. }
  284. .nav-title {
  285. flex: 1;
  286. text-align: center;
  287. font-size: 36rpx;
  288. font-weight: bold;
  289. color: #333;
  290. }
  291. .nav-right {
  292. display: flex;
  293. align-items: center;
  294. gap: 24rpx;
  295. width: 60rpx;
  296. justify-content: flex-end;
  297. .more-icon {
  298. font-size: 32rpx;
  299. color: #333;
  300. }
  301. .eye-icon {
  302. font-size: 32rpx;
  303. color: #333;
  304. }
  305. }
  306. }
  307. .content {
  308. flex: 1;
  309. padding-bottom: 140rpx;
  310. }
  311. .form-section {
  312. background: #fff;
  313. margin: 24rpx;
  314. border-radius: 16rpx;
  315. overflow: hidden;
  316. .form-item {
  317. display: flex;
  318. align-items: center;
  319. justify-content: space-between;
  320. padding: 32rpx 24rpx;
  321. min-height: 100rpx;
  322. .form-label {
  323. font-size: 28rpx;
  324. color: #333;
  325. font-weight: 500;
  326. width: 150rpx;
  327. }
  328. .form-input {
  329. flex: 1;
  330. font-size: 28rpx;
  331. color: #333;
  332. text-align: right;
  333. margin-left: 24rpx;
  334. &.placeholder {
  335. color: #C8C9CC;
  336. }
  337. &.picker-input {
  338. display: flex;
  339. align-items: center;
  340. justify-content: flex-end;
  341. .arrow-right {
  342. font-size: 32rpx;
  343. color: #999;
  344. margin-left: 8rpx;
  345. }
  346. }
  347. }
  348. }
  349. .divider {
  350. height: 1rpx;
  351. background: #EBEDF0;
  352. margin-left: 24rpx;
  353. }
  354. }
  355. .notes-section {
  356. background: #fff;
  357. border-radius: 16rpx;
  358. padding: 32rpx;
  359. margin: 0 24rpx 24rpx;
  360. .notes-title {
  361. font-size: 28rpx;
  362. font-weight: bold;
  363. color: #333;
  364. margin-bottom: 16rpx;
  365. }
  366. .notes-item {
  367. font-size: 26rpx;
  368. color: #666;
  369. line-height: 1.8;
  370. margin-bottom: 8rpx;
  371. &:last-child {
  372. margin-bottom: 0;
  373. }
  374. }
  375. }
  376. .bottom-bar {
  377. position: fixed;
  378. bottom: 0;
  379. left: 0;
  380. right: 0;
  381. background: #fff;
  382. padding: 24rpx;
  383. border-top: 1rpx solid #f0f0f0;
  384. z-index: 100;
  385. display: flex;
  386. flex-direction: column;
  387. gap: 16rpx;
  388. .save-btn {
  389. width: 100%;
  390. height: 88rpx;
  391. background: #388BFF;
  392. border-radius: 44rpx;
  393. display: flex;
  394. align-items: center;
  395. justify-content: center;
  396. font-size: 32rpx;
  397. font-weight: bold;
  398. color: #fff;
  399. }
  400. .unbind-btn {
  401. width: 100%;
  402. height: 88rpx;
  403. display: flex;
  404. align-items: center;
  405. justify-content: center;
  406. font-size: 28rpx;
  407. color: #388BFF;
  408. }
  409. }
  410. </style>