index.uvue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <template>
  2. <view class="form-page">
  3. <!-- 可滚动内容区域 -->
  4. <scroll-view class="form-scroll" scroll-y="true">
  5. <view class="form-container">
  6. <form-item label="密码" :required="formConfig.oldPassword.required" :error="formConfig.oldPassword.error">
  7. <l-input
  8. :type="showPassword ? 'text' : 'password'"
  9. class="form-input"
  10. v-model="formData.oldPassword"
  11. placeholder="请输入密码"
  12. :maxlength="100"
  13. :bordered="false"
  14. placeholderStyle="font-size: 14px;"
  15. />
  16. <image class="eye-icon" :src="showPassword ? '/static/images/login/4.png' : '/static/images/login/3.png'" mode="aspectFit" @click="handleTogglePassword"></image>
  17. </form-item>
  18. <form-item label="新密码" :required="formConfig.newPassword.required" :error="formConfig.newPassword.error">
  19. <l-input
  20. :type="showNewPassword ? 'text' : 'password'"
  21. class="form-input"
  22. v-model="formData.newPassword"
  23. placeholder="请输入新密码"
  24. :maxlength="100"
  25. :bordered="false"
  26. placeholderStyle="font-size: 14px;"
  27. />
  28. <image class="eye-icon" :src="showNewPassword ? '/static/images/login/4.png' : '/static/images/login/3.png'" mode="aspectFit" @click="handleToggleNewPassword"></image>
  29. </form-item>
  30. <form-item label="确认密码" :required="formConfig.confirmPassword.required" :error="formConfig.confirmPassword.error">
  31. <l-input
  32. :type="showConfirmPassword ? 'text' : 'password'"
  33. class="form-input"
  34. v-model="formData.confirmPassword"
  35. placeholder="请输入密码"
  36. :maxlength="100"
  37. :bordered="false"
  38. placeholderStyle="font-size: 14px;"
  39. />
  40. <image class="eye-icon" :src="showConfirmPassword ? '/static/images/login/4.png' : '/static/images/login/3.png'" mode="aspectFit" @click="handleToggleConfirmPassword"></image>
  41. </form-item>
  42. </view>
  43. </scroll-view>
  44. <!-- 固定底部按钮 -->
  45. <view class="footer">
  46. <button class="submit-btn" :disabled="submitting" @click="handleSubmit">
  47. <text class="submit-btn-text">{{ submitting ? "提交中..." : "提交" }}</text>
  48. </button>
  49. </view>
  50. </view>
  51. </template>
  52. <script setup lang="uts">
  53. import { ref } from 'vue'
  54. import { updatePassword } from '../../../api/user/info'
  55. const showPassword = ref<boolean>(false)
  56. const showNewPassword = ref<boolean>(false)
  57. const showConfirmPassword = ref<boolean>(false)
  58. // 表单 label 宽度统一配置
  59. const labelWidth = '140rpx'
  60. // 切换密码显示/隐藏
  61. const handleTogglePassword = (): void => {
  62. showPassword.value = !showPassword.value
  63. }
  64. // 切换密码显示/隐藏
  65. const handleToggleNewPassword = (): void => {
  66. showNewPassword.value = !showNewPassword.value
  67. }
  68. // 切换密码显示/隐藏
  69. const handleToggleConfirmPassword = (): void => {
  70. showConfirmPassword.value = !showConfirmPassword.value
  71. }
  72. // 表单数据类型
  73. type FormDataType = {
  74. oldPassword: string
  75. newPassword: string
  76. confirmPassword: string
  77. }
  78. // 表单数据
  79. const formData = ref<FormDataType>({
  80. oldPassword: '',
  81. newPassword: '',
  82. confirmPassword: ''
  83. })
  84. const submitting = ref<boolean>(false)
  85. // 表单字段配置类型
  86. type FormFieldConfig = {
  87. required: boolean
  88. error: string
  89. errorMsg: string
  90. errorValid: string
  91. }
  92. // 表单字段配置
  93. type FormFieldsConfig = {
  94. oldPassword: FormFieldConfig
  95. newPassword: FormFieldConfig
  96. confirmPassword: FormFieldConfig
  97. }
  98. // 表单配置
  99. const formConfig = ref<FormFieldsConfig>({
  100. oldPassword: {
  101. required: true,
  102. error: '',
  103. errorMsg: '请输入密码',
  104. errorValid: ''
  105. },
  106. newPassword: {
  107. required: true,
  108. error: '',
  109. errorMsg: '请输入新密码',
  110. errorValid: "2次密码不一样"
  111. },
  112. confirmPassword: {
  113. required: true,
  114. error: '',
  115. errorMsg: '请输入确认密码',
  116. errorValid: ''
  117. }
  118. })
  119. // 清空所有错误信息
  120. const clearErrors = (): void => {
  121. formConfig.value.oldPassword.error = ''
  122. formConfig.value.newPassword.error = ''
  123. formConfig.value.confirmPassword.error = ''
  124. }
  125. // 表单验证
  126. const validateForm = (): boolean => {
  127. // 清空之前的错误信息
  128. clearErrors()
  129. let isValid = true
  130. if (formConfig.value.oldPassword.required && formData.value.oldPassword.length == 0) {
  131. formConfig.value.oldPassword.error = formConfig.value.oldPassword.errorMsg
  132. isValid = false
  133. }
  134. if (formConfig.value.newPassword.required && formData.value.newPassword.length == 0) {
  135. formConfig.value.newPassword.error = formConfig.value.newPassword.errorMsg
  136. isValid = false
  137. }
  138. if (formConfig.value.confirmPassword.required && formData.value.confirmPassword.length == 0) {
  139. formConfig.value.confirmPassword.error = formConfig.value.confirmPassword.errorMsg
  140. isValid = false
  141. }
  142. if (formData.value.confirmPassword != formData.value.newPassword) {
  143. formConfig.value.newPassword.error = formConfig.value.newPassword.errorValid
  144. isValid = false
  145. }
  146. return isValid
  147. }
  148. // 提交表单
  149. const handleSubmit = async (): Promise<void> => {
  150. if (!validateForm()) {
  151. return
  152. }
  153. try {
  154. submitting.value = true
  155. // 打印表单数据
  156. console.log('表单数据:', formData.value)
  157. // 模拟提交
  158. await updatePassword(formData.value.oldPassword, formData.value.newPassword);
  159. uni.showToast({
  160. title: '提交成功',
  161. icon: 'success'
  162. })
  163. setTimeout(() => {
  164. uni.navigateBack()
  165. }, 800)
  166. } catch (e: any) {
  167. uni.showToast({
  168. title: e.message ?? '提交失败',
  169. icon: 'none'
  170. })
  171. } finally {
  172. submitting.value = false
  173. }
  174. }
  175. </script>
  176. <style lang="scss">
  177. @import "@/static/css/form.scss";
  178. .form-page {
  179. flex: 1;
  180. background-color: #e8f0f9;
  181. flex-direction: column;
  182. .form-scroll {
  183. flex: 1;
  184. padding: 30rpx;
  185. padding-bottom: 20rpx;
  186. .form-container {
  187. background-color: #ffffff;
  188. border-radius: 16rpx;
  189. padding: 30rpx;
  190. }
  191. }
  192. .footer {
  193. padding: 20rpx 30rpx;
  194. padding-bottom: 40rpx;
  195. .submit-btn {
  196. width: 100%;
  197. height: 88rpx;
  198. background-color: #007aff;
  199. border-radius: 12rpx;
  200. color: #ffffff !important;
  201. &:disabled {
  202. background-color: #cccccc;
  203. }
  204. .submit-btn-text {
  205. font-size: 32rpx;
  206. color: #ffffff !important;
  207. font-weight: bold;
  208. }
  209. }
  210. }
  211. }
  212. .eye-icon {
  213. position: absolute;
  214. right: 30rpx;
  215. top: 50%;
  216. transform: translateY(-50%);
  217. width: 40rpx;
  218. height: 40rpx;
  219. }
  220. </style>