国外MOSE官网
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.

347 lines
7.0 KiB

2 days ago
19 hours ago
2 days ago
19 hours ago
2 days ago
19 hours ago
2 days ago
19 hours ago
2 days ago
19 hours ago
2 days ago
19 hours ago
2 days ago
19 hours ago
2 days ago
19 hours ago
2 days ago
19 hours ago
2 days ago
19 hours ago
2 days ago
19 hours ago
2 days ago
19 hours ago
2 days ago
19 hours ago
2 days ago
19 hours ago
2 days ago
  1. <template>
  2. <view class="profile-container">
  3. <!-- 基本资料 -->
  4. <view class="section">
  5. <view class="section-title">
  6. <!-- 小竖线 -->
  7. <view class="vertical-line"></view>
  8. <view>
  9. <text class="title-text">基本资料</text>
  10. </view>
  11. </view>
  12. <!-- 头像 -->
  13. <view class="avatar-section">
  14. <button
  15. class="avatar-button"
  16. open-type="chooseAvatar"
  17. @chooseavatar="onChooseAvatar"
  18. >
  19. <image
  20. class="avatar"
  21. :src="userInfo.headImage || '/static/待上传头像.png'"
  22. mode="aspectFill"
  23. ></image>
  24. </button>
  25. <text class="avatar-tip">点击更换头像</text>
  26. </view>
  27. <!-- 昵称 -->
  28. <view class="info-item">
  29. <text class="label">昵称</text>
  30. <view class="value-container">
  31. <input
  32. class="nickname-input"
  33. v-model="userInfo.nickName"
  34. placeholder="请输入"
  35. type="nickname"
  36. @blur="onNicknameBlur"
  37. />
  38. </view>
  39. </view>
  40. <!-- 手机号 -->
  41. <view class="info-item">
  42. <text class="label">手机号</text>
  43. <view class="value-container">
  44. <input
  45. class="phone-input"
  46. v-model="userInfo.phone"
  47. placeholder="请输入"
  48. type="number"
  49. maxlength="11"
  50. />
  51. </view>
  52. </view>
  53. </view>
  54. <!-- 保存按钮 -->
  55. <view class="save-section">
  56. <button class="save-button" @click="saveProfile">
  57. 保存
  58. </button>
  59. </view>
  60. </view>
  61. </template>
  62. <script>
  63. export default {
  64. name: 'MyProfile',
  65. data() {
  66. return {
  67. userInfo: {
  68. headImage: '',
  69. nickName: '',
  70. phone: ''
  71. }
  72. }
  73. },
  74. onLoad() {
  75. // this.loadUserProfile();
  76. },
  77. methods: {
  78. // 返回上一页
  79. goBack() {
  80. uni.navigateBack();
  81. },
  82. // 加载用户资料
  83. // loadUserProfile() {
  84. // // 从本地存储获取用户资料
  85. // const storedUserInfo = uni.getStorageSync('userInfo');
  86. // if (storedUserInfo) {
  87. // this.userInfo = { ...this.userInfo, ...storedUserInfo };
  88. // }
  89. // },
  90. // 选择微信头像
  91. async onChooseAvatar(e) {
  92. console.log('选择头像回调', e);
  93. if (e.detail.avatarUrl) {
  94. this.userInfo.headImage = e.detail.avatarUrl;
  95. // console.log('头像设置成功', e.detail.avatarUrl);
  96. const file = {
  97. path: e.detail.avatarUrl
  98. }
  99. const res = await this.$utils.uploadImage(file)
  100. this.userInfo.headImage = res.url
  101. uni.showToast({
  102. title: '头像更新成功',
  103. icon: 'success'
  104. });
  105. } else {
  106. uni.showToast({
  107. title: '头像选择失败',
  108. icon: 'none'
  109. });
  110. }
  111. },
  112. // 昵称输入失焦验证
  113. onNicknameBlur() {
  114. if (!this.userInfo.nickName.trim()) {
  115. uni.showToast({
  116. title: '请输入昵称',
  117. icon: 'none'
  118. });
  119. }
  120. },
  121. // 保存资料
  122. async saveProfile() {
  123. // 验证昵称
  124. if (!this.userInfo.nickName.trim()) {
  125. uni.showToast({
  126. title: '请输入昵称',
  127. icon: 'none'
  128. });
  129. return;
  130. }
  131. // 验证手机号(如果填写了)
  132. if (this.userInfo.phone && !/^1[3-9]\d{9}$/.test(this.userInfo.phone)) {
  133. uni.showToast({
  134. title: '请输入正确的手机号',
  135. icon: 'none'
  136. });
  137. return;
  138. }
  139. const res = await this.$api.user.updateUser({
  140. nickName: this.userInfo.nickName,
  141. phone: this.userInfo.phone,
  142. headImage: this.userInfo.headImage
  143. })
  144. if (res.code === 200) {
  145. uni.showToast({
  146. title: `${res.message}`,
  147. icon: 'success'
  148. });
  149. setTimeout(() => {
  150. uni.navigateBack()
  151. }, 1000);
  152. }
  153. },
  154. // 获取个人信息
  155. async getUserInfo() {
  156. const res = await this.$api.user.queryUser()
  157. this.userInfo = res.result
  158. }
  159. },
  160. onShow() {
  161. this.getUserInfo();
  162. }
  163. }
  164. </script>
  165. <style lang="scss" scoped>
  166. .profile-container {
  167. min-height: 100vh;
  168. background-color: #f5f5f5;
  169. }
  170. .vertical-line {
  171. width: 9rpx;
  172. height: 33rpx;
  173. background-color: #1488DB;
  174. margin-right: 20rpx;
  175. }
  176. // 自定义导航栏
  177. .custom-navbar {
  178. background: linear-gradient(90deg, #1488db 0%, #1488db 100%);
  179. padding-top: var(--status-bar-height, 44rpx);
  180. .navbar-content {
  181. height: 88rpx;
  182. display: flex;
  183. align-items: center;
  184. justify-content: space-between;
  185. padding: 0 30rpx;
  186. .navbar-left {
  187. .back-icon {
  188. font-size: 40rpx;
  189. color: #ffffff;
  190. font-weight: bold;
  191. }
  192. }
  193. .navbar-title {
  194. font-size: 36rpx;
  195. color: #ffffff;
  196. font-weight: 500;
  197. }
  198. .navbar-right {
  199. display: flex;
  200. gap: 20rpx;
  201. .more-icon,
  202. .settings-icon {
  203. font-size: 32rpx;
  204. color: #ffffff;
  205. }
  206. }
  207. }
  208. }
  209. .section {
  210. margin: 20rpx;
  211. background-color: #ffffff;
  212. border-radius: 20rpx;
  213. overflow: hidden;
  214. .section-title {
  215. display: flex;
  216. align-items: center;
  217. padding: 30rpx;
  218. border-bottom: 1rpx solid #f0f0f0;
  219. .title-text {
  220. font-size: 32rpx;
  221. font-weight: 500;
  222. color: #333333;
  223. }
  224. }
  225. }
  226. .avatar-section {
  227. display: flex;
  228. flex-direction: column;
  229. align-items: center;
  230. padding: 40rpx 30rpx;
  231. border-bottom: 1rpx solid #f0f0f0;
  232. .avatar-button {
  233. padding: 0;
  234. margin: 0;
  235. background: transparent;
  236. border: none;
  237. outline: none;
  238. margin-bottom: 20rpx;
  239. &::after {
  240. border: none;
  241. }
  242. .avatar {
  243. width: 160rpx;
  244. height: 160rpx;
  245. border-radius: 80rpx;
  246. border: 4rpx dashed #cccccc;
  247. }
  248. }
  249. .avatar-tip {
  250. font-size: 26rpx;
  251. color: #999999;
  252. }
  253. }
  254. .info-item {
  255. display: flex;
  256. align-items: center;
  257. justify-content: space-between;
  258. padding: 30rpx;
  259. border-bottom: 1rpx solid #f0f0f0;
  260. &:last-child {
  261. border-bottom: none;
  262. }
  263. .label {
  264. font-size: 30rpx;
  265. color: #333333;
  266. font-weight: 500;
  267. width: 120rpx;
  268. }
  269. .value-container {
  270. flex: 1;
  271. display: flex;
  272. align-items: center;
  273. justify-content: flex-end;
  274. .nickname-input,
  275. .phone-input {
  276. width: 100%;
  277. text-align: right;
  278. font-size: 30rpx;
  279. color: #666666;
  280. border: none;
  281. outline: none;
  282. background: transparent;
  283. &::placeholder {
  284. color: #cccccc;
  285. }
  286. }
  287. }
  288. }
  289. .save-section {
  290. padding: 40rpx 20rpx;
  291. .save-button {
  292. width: 100%;
  293. height: 88rpx;
  294. background-color: #1488db;
  295. border-radius: 44rpx;
  296. border: none;
  297. outline: none;
  298. font-size: 32rpx;
  299. font-weight: 500;
  300. color: #ffffff;
  301. display: flex;
  302. align-items: center;
  303. justify-content: center;
  304. &::after {
  305. border: none;
  306. }
  307. }
  308. }
  309. </style>