s-pay-password.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. <template>
  2. <view class="paymentCodeBox" v-if="show">
  3. <view class="password-set-page">
  4. <view class="setPage">
  5. <view class="hint mb-30 height110 width100Percent ss-font-32 ss-color-222 ss-font-bold">
  6. {{ title }}
  7. <view class="imgClose" @click="onClose">
  8. <image src="@/static/icon/close.svg" style="width:50rpx;height:50rpx"></image>
  9. </view>
  10. </view>
  11. <view class="code">
  12. <view class="numFont">
  13. <view v-for="(item, index) in 6" :key="index">{{ password[index] && '●' || '' }}</view>
  14. </view>
  15. </view>
  16. <view class="keyboard">
  17. <button v-for="(item, index) in 9" :key="index" @click="key(index + 1)">
  18. <text>{{ index + 1 }}</text>
  19. </button>
  20. <button class="hide"></button>
  21. <button @click="key(0)">
  22. <text>0</text>
  23. </button>
  24. <button @click="del">
  25. <image src="@/static/icon/close.svg" mode="aspectFill"></image>
  26. </button>
  27. </view>
  28. </view>
  29. </view>
  30. </view>
  31. </template>
  32. <script setup>
  33. import { ref, computed } from 'vue'
  34. import sheep from '@/sheep'
  35. import { hidePayPassword } from '@/sheep/hooks/useModal'
  36. import UserApi from '@/sheep/api/member/user';
  37. const modalStore = sheep.$store('modal')
  38. const password = ref('')
  39. const show = computed(() => modalStore.payPassword.show)
  40. const title = computed(() => modalStore.payPassword.title)
  41. // 处理密码输入完成
  42. async function handleComplete(inputPassword) {
  43. const { type, step, callback, oldPassword, newPassword } = modalStore.payPassword
  44. if (type === 'input') {
  45. callback?.(inputPassword)
  46. hidePayPassword()
  47. } else if (type === 'change') {
  48. if (step === 1) {
  49. modalStore.$patch((state) => {
  50. state.payPassword.oldPassword = inputPassword
  51. state.payPassword.step = 2
  52. state.payPassword.title = '请输入新支付密码'
  53. })
  54. } else if (step === 2) {
  55. modalStore.$patch((state) => {
  56. state.payPassword.newPassword = inputPassword
  57. state.payPassword.step = 3
  58. state.payPassword.title = '请确认新支付密码'
  59. })
  60. } else if (step === 3) {
  61. if (inputPassword === newPassword) {
  62. try {
  63. const { code } = await UserApi.updatePayPassword({
  64. payPassword: inputPassword,
  65. oldPayPassword: oldPassword
  66. })
  67. if (code === 0) {
  68. uni.showToast({
  69. title: '修改成功',
  70. icon: 'success'
  71. })
  72. callback?.({ oldPassword, newPassword: inputPassword })
  73. }
  74. hidePayPassword()
  75. } catch (error) {
  76. uni.showToast({
  77. title: error.message || '修改失败',
  78. icon: 'none'
  79. })
  80. hidePayPassword()
  81. }
  82. } else {
  83. uni.showToast({
  84. title: '两次密码不一致',
  85. icon: 'none'
  86. })
  87. modalStore.$patch((state) => {
  88. state.payPassword.step = 2
  89. state.payPassword.title = '请输入新支付密码'
  90. })
  91. }
  92. }
  93. } else if (type === 'set') {
  94. if (step === 1) {
  95. modalStore.$patch((state) => {
  96. state.payPassword.newPassword = inputPassword
  97. state.payPassword.step = 2
  98. state.payPassword.title = '请确认支付密码'
  99. })
  100. } else if (step === 2) {
  101. if (inputPassword === newPassword) {
  102. try {
  103. const { code } = await UserApi.updatePayPassword({
  104. payPassword: inputPassword
  105. })
  106. if (code === 0) {
  107. uni.showToast({
  108. title: '设置成功',
  109. icon: 'success'
  110. })
  111. callback?.(inputPassword)
  112. }
  113. window.location.reload()
  114. hidePayPassword()
  115. } catch (error) {
  116. uni.showToast({
  117. title: error.message || '设置失败',
  118. icon: 'none'
  119. })
  120. hidePayPassword()
  121. }
  122. } else {
  123. uni.showToast({
  124. title: '两次密码不一致',
  125. icon: 'none'
  126. })
  127. modalStore.$patch((state) => {
  128. state.payPassword.step = 1
  129. state.payPassword.title = '设置支付密码'
  130. })
  131. }
  132. }
  133. }
  134. // 清空当前输入
  135. password.value = ''
  136. }
  137. // 输入数字
  138. function key(num) {
  139. if (password.value.length < 6) {
  140. password.value += num
  141. if (password.value.length === 6) {
  142. handleComplete(password.value)
  143. }
  144. }
  145. }
  146. // 删除数字
  147. function del() {
  148. if (password.value.length > 0) {
  149. password.value = password.value.substring(0, password.value.length - 1)
  150. }
  151. }
  152. // 关闭弹窗
  153. function onClose() {
  154. hidePayPassword()
  155. modalStore.payPassword.onCancel?.()
  156. }
  157. </script>
  158. <style lang="scss" scoped>
  159. .paymentCodeBox {
  160. width: 100%;
  161. height: 100vh;
  162. background: rgba(0, 0, 0, .5);
  163. position: fixed;
  164. top: 0;
  165. left: 0;
  166. z-index: 999;
  167. .password-set-page {
  168. position: fixed;
  169. bottom: 0;
  170. width: 100%;
  171. height: 100vh;
  172. overflow: hidden;
  173. z-index: 999999;
  174. .setPage {
  175. position: fixed;
  176. bottom: 0;
  177. width: 100%;
  178. background: #fff;
  179. border-radius: 20rpx 20rpx 0 0;
  180. .hint {
  181. line-height: 110rpx;
  182. position: relative;
  183. text-align: center;
  184. border-bottom: 1rpx solid #ECECEC;
  185. display: flex;
  186. justify-content: space-between;
  187. align-items: center;
  188. padding: 0 20rpx;
  189. .imgClose {
  190. display: flex;
  191. align-items: center;
  192. justify-content: center;
  193. }
  194. }
  195. }
  196. .code {
  197. margin: 30rpx 0;
  198. .numFont {
  199. display: flex;
  200. width: 690rpx;
  201. margin: 0 auto;
  202. view {
  203. flex: 1;
  204. height: 100rpx;
  205. border: 1rpx solid #D9D9D9;
  206. display: flex;
  207. align-items: center;
  208. justify-content: center;
  209. font-size: 60rpx;
  210. &:not(:last-child) {
  211. border-right: none;
  212. }
  213. }
  214. }
  215. }
  216. .slipBox {
  217. display: flex;
  218. justify-content: space-between;
  219. align-items: center;
  220. .goto {
  221. align-items: center;
  222. .imgBox {
  223. width: 9rpx;
  224. height: 16rpx;
  225. .img {
  226. width: 100%;
  227. height: 100%;
  228. }
  229. }
  230. }
  231. }
  232. .keyboard {
  233. width: 100%;
  234. background: #EEEEEE;
  235. display: flex;
  236. flex-wrap: wrap;
  237. padding-bottom: env(safe-area-inset-bottom);
  238. button {
  239. display: flex;
  240. align-items: center;
  241. justify-content: center;
  242. width: calc(100% / 3);
  243. height: 120rpx;
  244. background: #FFFFFF;
  245. border-radius: 0;
  246. margin: 1rpx 0 0 0;
  247. font-size: 50rpx;
  248. &.hide {
  249. background: #EEEEEE;
  250. }
  251. &:active:not(.hide) {
  252. background: #EEEEEE;
  253. }
  254. image {
  255. width: 52rpx;
  256. height: 38rpx;
  257. }
  258. }
  259. }
  260. }
  261. }
  262. </style>