展品维保小程序前端代码接口
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

279 lines
5.8 KiB

  1. <template>
  2. <view class="profile-page">
  3. <view class="profile-content">
  4. <!-- 头像上传区域 -->
  5. <view class="avatar-section">
  6. <!-- 基本资料标签 -->
  7. <view class="profile-label">
  8. <text class="label-text">基本资料</text>
  9. </view>
  10. <view class="avatar-container" @click="uploadAvatar">
  11. <image
  12. v-if="userInfo.headImage"
  13. :src="userInfo.headImage"
  14. class="avatar-image"
  15. mode="aspectFill"
  16. />
  17. <view v-else class="avatar-placeholder">
  18. <image src="@/static/待上传头像.png" class="placeholder-image" mode="aspectFit" />
  19. </view>
  20. </view>
  21. <text class="avatar-tip">点击更换头像</text>
  22. </view>
  23. <!-- 表单区域 -->
  24. <view class="form-section">
  25. <!-- 昵称 -->
  26. <view class="form-item">
  27. <text class="form-label">昵称</text>
  28. <uv-input
  29. v-model="userInfo.nickName"
  30. placeholder="请输入"
  31. border="none"
  32. class="form-input"
  33. ></uv-input>
  34. </view>
  35. <!-- 手机号 -->
  36. <view class="form-item">
  37. <text class="form-label">手机号</text>
  38. <uv-input
  39. v-model="userInfo.phone"
  40. placeholder="请输入"
  41. border="none"
  42. class="form-input"
  43. ></uv-input>
  44. </view>
  45. </view>
  46. <!-- 保存按钮 -->
  47. <view class="save-section">
  48. <uv-button
  49. type="primary"
  50. text="保存"
  51. @click="saveProfile"
  52. :custom-style="saveButtonStyle"
  53. ></uv-button>
  54. </view>
  55. </view>
  56. </view>
  57. </template>
  58. <script>
  59. export default {
  60. data() {
  61. return {
  62. userInfo: {
  63. headImage: '',
  64. nickName: '',
  65. phone: ''
  66. },
  67. saveButtonStyle: {
  68. backgroundColor: '#C70019',
  69. borderRadius: '41rpx',
  70. height: '94rpx',
  71. width: '594rpx',
  72. border: 'none'
  73. }
  74. }
  75. },
  76. methods: {
  77. // 返回上一页
  78. goBack() {
  79. uni.navigateBack()
  80. },
  81. // 上传头像
  82. async uploadAvatar() {
  83. try {
  84. const result = await this.$utils.chooseAndUpload()
  85. if (result && result.success) {
  86. console.log(result);
  87. this.userInfo.headImage = result.url
  88. }
  89. } catch (error) {
  90. console.error('头像上传失败:', error)
  91. uni.showToast({
  92. title: '头像上传失败',
  93. icon: 'error'
  94. })
  95. }
  96. },
  97. // 保存资料
  98. async saveProfile() {
  99. if (!this.userInfo.nickName.trim()) {
  100. uni.showToast({
  101. title: '请输入昵称',
  102. icon: 'none'
  103. })
  104. return
  105. }
  106. if (!this.userInfo.phone.trim()) {
  107. uni.showToast({
  108. title: '请输入手机号',
  109. icon: 'none'
  110. })
  111. return
  112. }
  113. // 简单的手机号验证
  114. const phoneReg = /^1[3-9]\d{9}$/
  115. if (!phoneReg.test(this.userInfo.phone)) {
  116. uni.showToast({
  117. title: '请输入正确的手机号',
  118. icon: 'none'
  119. })
  120. return
  121. }
  122. // TODO: 调用API保存用户信息
  123. const res = await this.$api.user.updateUser({
  124. headImage: this.userInfo.headImage,
  125. nickName: this.userInfo.nickName,
  126. phone: this.userInfo.phone
  127. })
  128. if (res.code === 200) {
  129. uni.showToast({
  130. title: '保存成功',
  131. icon: 'success'
  132. })
  133. // 延迟返回上一页
  134. setTimeout(() => {
  135. uni.navigateBack()
  136. }, 1500)
  137. }
  138. },
  139. // 获取个人信息
  140. async getProfile() {
  141. const res = await this.$api.user.queryUser()
  142. if (res.code === 200) {
  143. this.userInfo = res.result
  144. }
  145. }
  146. },
  147. onLoad() {
  148. this.getProfile()
  149. }
  150. }
  151. </script>
  152. <style lang="scss" scoped>
  153. .profile-page {
  154. min-height: 100vh;
  155. // background-color: #f5f5f5;
  156. }
  157. .profile-content {
  158. padding:45rpx 32rpx;
  159. }
  160. .avatar-section {
  161. display: flex;
  162. flex-direction: column;
  163. align-items: center;
  164. margin-bottom: 80rpx;
  165. position: relative;
  166. .profile-label {
  167. position: absolute;
  168. top: 0;
  169. left: 28rpx;
  170. z-index: 10;
  171. .label-text {
  172. font-size: 30rpx;
  173. // font-weight: bold;
  174. color: $primary-text-color;
  175. position: relative;
  176. &::before {
  177. content: '';
  178. position: absolute;
  179. left: -16rpx;
  180. top: 50%;
  181. transform: translateY(-50%);
  182. width: 9rpx;
  183. height: 33rpx;
  184. background-color: $primary-color;
  185. border-radius: 5rpx;
  186. }
  187. }
  188. }
  189. .avatar-container {
  190. width: 160rpx;
  191. height: 160rpx;
  192. border-radius: 50%;
  193. overflow: hidden;
  194. margin-bottom: 20rpx;
  195. margin-top: 66rpx;
  196. .avatar-image {
  197. width: 100%;
  198. height: 100%;
  199. }
  200. .avatar-placeholder {
  201. width: 100%;
  202. height: 100%;
  203. display: flex;
  204. align-items: center;
  205. justify-content: center;
  206. background-color: #f0f0f0;
  207. .placeholder-image {
  208. width: 80rpx;
  209. height: 80rpx;
  210. }
  211. }
  212. }
  213. .avatar-tip {
  214. font-size: 28rpx;
  215. color: $secondary-text-color;
  216. }
  217. }
  218. .form-section {
  219. // background-color: #fff;
  220. // border-radius: 16rpx;
  221. padding: 0 32rpx;
  222. margin-bottom: 500rpx;
  223. .form-item {
  224. display: flex;
  225. align-items: center;
  226. padding: 40rpx 0;
  227. border-bottom: 0.5rpx solid #f0f0f0;
  228. .form-label {
  229. font-size: 30rpx;
  230. color: $secondary-text-color;
  231. width: 120rpx;
  232. flex-shrink: 0;
  233. }
  234. .form-input {
  235. flex: 1;
  236. margin-left: 40rpx;
  237. }
  238. }
  239. }
  240. .save-section {
  241. display: flex;
  242. justify-content: center;
  243. }
  244. </style>