国外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.

348 lines
6.9 KiB

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.avatar || '/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. avatar: '',
  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. onChooseAvatar(e) {
  92. console.log('选择头像回调', e);
  93. if (e.detail.avatarUrl) {
  94. this.userInfo.avatar = e.detail.avatarUrl;
  95. console.log('头像设置成功', e.detail.avatarUrl);
  96. uni.showToast({
  97. title: '头像更新成功',
  98. icon: 'success'
  99. });
  100. } else {
  101. uni.showToast({
  102. title: '头像选择失败',
  103. icon: 'none'
  104. });
  105. }
  106. },
  107. // 昵称输入失焦验证
  108. onNicknameBlur() {
  109. if (!this.userInfo.nickname.trim()) {
  110. uni.showToast({
  111. title: '请输入昵称',
  112. icon: 'none'
  113. });
  114. }
  115. },
  116. // 保存资料
  117. async saveProfile() {
  118. // 验证昵称
  119. if (!this.userInfo.nickname.trim()) {
  120. uni.showToast({
  121. title: '请输入昵称',
  122. icon: 'none'
  123. });
  124. return;
  125. }
  126. // 验证手机号(如果填写了)
  127. if (this.userInfo.phone && !/^1[3-9]\d{9}$/.test(this.userInfo.phone)) {
  128. uni.showToast({
  129. title: '请输入正确的手机号',
  130. icon: 'none'
  131. });
  132. return;
  133. }
  134. try {
  135. uni.showLoading({
  136. title: '保存中...'
  137. });
  138. // 保存到本地存储
  139. uni.setStorageSync('userInfo', this.userInfo);
  140. // 模拟API调用
  141. await new Promise(resolve => setTimeout(resolve, 1000));
  142. uni.hideLoading();
  143. uni.showToast({
  144. title: '保存成功',
  145. icon: 'success'
  146. });
  147. // 返回上一页
  148. setTimeout(() => {
  149. uni.navigateBack();
  150. }, 1500);
  151. } catch (error) {
  152. uni.hideLoading();
  153. console.error('保存失败:', error);
  154. uni.showToast({
  155. title: '保存失败',
  156. icon: 'none'
  157. });
  158. }
  159. }
  160. }
  161. }
  162. </script>
  163. <style lang="scss" scoped>
  164. .profile-container {
  165. min-height: 100vh;
  166. background-color: #f5f5f5;
  167. }
  168. .vertical-line {
  169. width: 9rpx;
  170. height: 33rpx;
  171. background-color: #1488DB;
  172. margin-right: 20rpx;
  173. }
  174. // 自定义导航栏
  175. .custom-navbar {
  176. background: linear-gradient(90deg, #1488db 0%, #1488db 100%);
  177. padding-top: var(--status-bar-height, 44rpx);
  178. .navbar-content {
  179. height: 88rpx;
  180. display: flex;
  181. align-items: center;
  182. justify-content: space-between;
  183. padding: 0 30rpx;
  184. .navbar-left {
  185. .back-icon {
  186. font-size: 40rpx;
  187. color: #ffffff;
  188. font-weight: bold;
  189. }
  190. }
  191. .navbar-title {
  192. font-size: 36rpx;
  193. color: #ffffff;
  194. font-weight: 500;
  195. }
  196. .navbar-right {
  197. display: flex;
  198. gap: 20rpx;
  199. .more-icon,
  200. .settings-icon {
  201. font-size: 32rpx;
  202. color: #ffffff;
  203. }
  204. }
  205. }
  206. }
  207. .section {
  208. margin: 20rpx;
  209. background-color: #ffffff;
  210. border-radius: 20rpx;
  211. overflow: hidden;
  212. .section-title {
  213. display: flex;
  214. align-items: center;
  215. padding: 30rpx;
  216. border-bottom: 1rpx solid #f0f0f0;
  217. .title-text {
  218. font-size: 32rpx;
  219. font-weight: 500;
  220. color: #333333;
  221. }
  222. }
  223. }
  224. .avatar-section {
  225. display: flex;
  226. flex-direction: column;
  227. align-items: center;
  228. padding: 40rpx 30rpx;
  229. border-bottom: 1rpx solid #f0f0f0;
  230. .avatar-button {
  231. padding: 0;
  232. margin: 0;
  233. background: transparent;
  234. border: none;
  235. outline: none;
  236. margin-bottom: 20rpx;
  237. &::after {
  238. border: none;
  239. }
  240. .avatar {
  241. width: 160rpx;
  242. height: 160rpx;
  243. border-radius: 80rpx;
  244. border: 4rpx dashed #cccccc;
  245. }
  246. }
  247. .avatar-tip {
  248. font-size: 26rpx;
  249. color: #999999;
  250. }
  251. }
  252. .info-item {
  253. display: flex;
  254. align-items: center;
  255. justify-content: space-between;
  256. padding: 30rpx;
  257. border-bottom: 1rpx solid #f0f0f0;
  258. &:last-child {
  259. border-bottom: none;
  260. }
  261. .label {
  262. font-size: 30rpx;
  263. color: #333333;
  264. font-weight: 500;
  265. width: 120rpx;
  266. }
  267. .value-container {
  268. flex: 1;
  269. display: flex;
  270. align-items: center;
  271. justify-content: flex-end;
  272. .nickname-input,
  273. .phone-input {
  274. width: 100%;
  275. text-align: right;
  276. font-size: 30rpx;
  277. color: #666666;
  278. border: none;
  279. outline: none;
  280. background: transparent;
  281. &::placeholder {
  282. color: #cccccc;
  283. }
  284. }
  285. }
  286. }
  287. .save-section {
  288. padding: 40rpx 20rpx;
  289. .save-button {
  290. width: 100%;
  291. height: 88rpx;
  292. background-color: #1488db;
  293. border-radius: 44rpx;
  294. border: none;
  295. outline: none;
  296. font-size: 32rpx;
  297. font-weight: 500;
  298. color: #ffffff;
  299. display: flex;
  300. align-items: center;
  301. justify-content: center;
  302. &::after {
  303. border: none;
  304. }
  305. }
  306. }
  307. </style>