my.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. <template>
  2. <view class="my-container">
  3. <view class="user-info" v-if="isLogin">
  4. <image class="avatar" :src="userInfo.avatar || '/static/avatar.png'"></image>
  5. <view class="user-details">
  6. <text class="username">{{ userInfo.username }}</text>
  7. <!-- <text class="user-id">ID: {{ userInfo.userId }}</text> -->
  8. <text class="user-phone" v-if="userInfo.phone">手机: {{ formatPhone(userInfo.phone) }}</text>
  9. </view>
  10. </view>
  11. <view class="user-info" v-else @click="goLogin">
  12. <image class="avatar" src="/static/avatar.png"></image>
  13. <view class="user-details">
  14. <text class="username">点击登录</text>
  15. <text class="user-id">登录后查看更多信息</text>
  16. </view>
  17. </view>
  18. <view class="menu-list">
  19. <view class="menu-item" v-for="(item, index) in menuItems" :key="index" @click="handleMenuClick(item)">
  20. <view class="menu-item-left">
  21. <text class="iconfont" :class="item.icon"></text>
  22. <text class="menu-text">{{ item.title }}</text>
  23. </view>
  24. <text class="iconfont icon-right"></text>
  25. </view>
  26. </view>
  27. <view class="logout-btn" @click="handleLogout" v-if="isLogin">
  28. <text>退出登录</text>
  29. </view>
  30. <!-- 添加一个隐藏的授权按钮,在需要时显示 -->
  31. <view class="auth-modal" v-if="showAuthModal">
  32. <view class="auth-content">
  33. <text class="auth-title">微信授权登录</text>
  34. <text class="auth-desc">请授权获取您的微信头像和昵称</text>
  35. <button class="auth-btn" @tap="getUserProfile">确认授权</button>
  36. <button class="auth-cancel" @tap="cancelAuth">取消</button>
  37. </view>
  38. </view>
  39. <!-- 添加获取手机号按钮 -->
  40. <!-- <button
  41. v-if="isLogin && !userInfo.phone"
  42. open-type="getPhoneNumber"
  43. @getphonenumber="getPhoneNumber"
  44. class="get-phone-btn">
  45. 绑定手机号
  46. </button> -->
  47. <!-- <button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号</button> -->
  48. </view>
  49. </template>
  50. <script>
  51. // 直接导入所有需要的 API 函数
  52. import { log } from 'util';
  53. import { wxLogin, getUserInfo, getUserPhoneNumber, logout } from '../../api/user.js';
  54. export default {
  55. data() {
  56. return {
  57. isLogin: false,
  58. userInfo: {
  59. username: '',
  60. userId: '',
  61. avatar: ''
  62. },
  63. menuItems: [
  64. { title: '个人资料', icon: 'icon-user', action: 'profile' },
  65. { title:'上传简历',icon:'',action:'uploadResume'},
  66. // { title: '我的订单', icon: 'icon-order', action: 'orders' },
  67. // { title: '我的收藏', icon: 'icon-star', action: 'favorites' },
  68. { title: '设置', icon: 'icon-settings', action: 'settings' },
  69. { title: '帮助中心', icon: 'icon-help', action: 'help' }
  70. ],
  71. showAuthModal: false,
  72. wxLoginCode: '' // 存储微信登录code
  73. }
  74. },
  75. onLoad() {
  76. // 每次显示页面时检查登录状态
  77. //this.checkLogin();
  78. },
  79. onShow() {
  80. // 每次显示页面时检查登录状态
  81. this.checkLoginStatus();
  82. },
  83. methods: {
  84. checkLogin() {
  85. const userInfo = uni.getStorageSync('userInfo');
  86. if (!userInfo) {
  87. // 未登录时跳转到身份验证登录页面
  88. uni.reLaunch({
  89. url: '/pages/login/login',
  90. success: () => {
  91. console.log('跳转到身份验证登录页面成功');
  92. },
  93. fail: (err) => {
  94. console.error('跳转到身份验证登录页面失败:', err);
  95. uni.showToast({
  96. title: '跳转失败,请重试',
  97. icon: 'none'
  98. });
  99. }
  100. });
  101. return false;
  102. }
  103. try {
  104. const parsedUserInfo = JSON.parse(userInfo);
  105. if (!parsedUserInfo.openid) {
  106. // 没有openid时跳转到身份验证登录页面
  107. uni.navigateTo({
  108. url: '/pages/login/login'
  109. });
  110. return false;
  111. }
  112. return true;
  113. } catch (e) {
  114. console.error('解析用户信息失败:', e);
  115. uni.removeStorageSync('userInfo');
  116. uni.navigateTo({
  117. url: '/pages/login/login'
  118. });
  119. return false;
  120. }
  121. },
  122. // 检查登录状态
  123. checkLoginStatus() {
  124. try {
  125. const token = uni.getStorageSync('token');
  126. const userInfoStr = uni.getStorageSync('userInfo');
  127. if (token && userInfoStr) {
  128. const userInfo = JSON.parse(userInfoStr);
  129. // 检查登录是否过期(可选:如果需要登录有效期)
  130. const loginTime = userInfo.loginTime || 0;
  131. const currentTime = new Date().getTime();
  132. const loginExpireTime = 7 * 24 * 60 * 60 * 1000; // 例如7天过期
  133. if (currentTime - loginTime > loginExpireTime) {
  134. console.log('登录已过期,需要重新登录');
  135. this.handleLogout(false); // 静默登出,不显示提示
  136. return;
  137. }
  138. // 设置登录状态
  139. this.isLogin = true;
  140. this.userInfo = userInfo;
  141. // 可选:每次打开页面时刷新用户信息
  142. this.fetchUserDetail();
  143. } else {
  144. // 未登录状态
  145. this.isLogin = false;
  146. this.userInfo = {
  147. username: '',
  148. userId: '',
  149. avatar: '',
  150. phone: ''
  151. };
  152. }
  153. } catch (e) {
  154. console.error('获取登录状态失败', e);
  155. this.isLogin = false;
  156. }
  157. },
  158. // 前往登录页
  159. goLogin() {
  160. // 直接跳转到登录页面,不显示选择对话框
  161. uni.navigateTo({
  162. url: '/pages/login/login'
  163. });
  164. // 如果您想保留选择功能,可以取消注释下面的代码
  165. /*
  166. // 显示登录方式选择
  167. uni.showActionSheet({
  168. itemList: ['账号密码登录', '微信登录'],
  169. success: (res) => {
  170. if (res.tapIndex === 0) {
  171. // 账号密码登录
  172. uni.navigateTo({
  173. url: '/pages/login/login'
  174. });
  175. } else if (res.tapIndex === 1) {
  176. // 微信登录
  177. this.wxLogin();
  178. }
  179. }
  180. });
  181. */
  182. },
  183. // 微信登录
  184. wxLogin() {
  185. // #ifdef MP-WEIXIN
  186. this.getWxLoginCode();
  187. // #endif
  188. // #ifndef MP-WEIXIN
  189. uni.showToast({
  190. title: '请在微信环境中使用微信登录',
  191. icon: 'none'
  192. });
  193. // #endif
  194. },
  195. // 获取微信登录 code
  196. getWxLoginCode() {
  197. uni.showLoading({ title: '登录中...' });
  198. // 调用uni.login获取临时code
  199. uni.login({
  200. provider: 'weixin',
  201. success: (loginRes) => {
  202. console.log('获取微信登录code成功:', loginRes.code);
  203. // 保存code,并显示授权弹窗
  204. this.wxLoginCode = loginRes.code;
  205. uni.hideLoading();
  206. this.showAuthModal = true;
  207. },
  208. fail: (err) => {
  209. uni.hideLoading();
  210. console.error('获取微信登录code失败:', err);
  211. uni.showToast({
  212. title: '微信登录失败',
  213. icon: 'none'
  214. });
  215. }
  216. });
  217. },
  218. // 用户点击授权按钮时调用
  219. getUserProfile() {
  220. // 这个方法直接绑定到按钮的点击事件
  221. wx.getUserProfile({
  222. desc: '用于完善用户资料',
  223. success: (profileRes) => {
  224. console.log('获取用户信息成功:', profileRes);
  225. // 准备完整的登录参数
  226. const loginParams = {
  227. code: this.wxLoginCode,
  228. userInfo: profileRes.userInfo,
  229. signature: profileRes.signature,
  230. rawData: profileRes.rawData,
  231. encryptedData: profileRes.encryptedData,
  232. iv: profileRes.iv
  233. };
  234. // 隐藏授权弹窗
  235. this.showAuthModal = false;
  236. // 发送登录请求
  237. this.wxLoginRequest(loginParams);
  238. },
  239. fail: (err) => {
  240. console.error('获取用户信息失败:', err);
  241. this.showAuthModal = false;
  242. // 如果用户拒绝授权,仍然可以使用code登录,但没有用户信息
  243. this.wxLoginRequest({
  244. code: this.wxLoginCode,
  245. userInfo: {
  246. nickName: '微信用户',
  247. avatarUrl: '',
  248. gender: 0,
  249. province: '',
  250. city: '',
  251. country: ''
  252. }
  253. });
  254. }
  255. });
  256. },
  257. // 取消授权
  258. cancelAuth() {
  259. this.showAuthModal = false;
  260. // 使用code进行静默登录
  261. this.wxLoginRequest({
  262. code: this.wxLoginCode,
  263. userInfo: {
  264. nickName: '微信用户',
  265. avatarUrl: '',
  266. gender: 0,
  267. province: '',
  268. city: '',
  269. country: ''
  270. }
  271. });
  272. },
  273. // 头像选择回调
  274. onChooseAvatar(e) {
  275. const { avatarUrl } = e.detail;
  276. // 这里可以将头像上传到服务器或进行其他处理
  277. console.log('用户选择的头像:', avatarUrl);
  278. },
  279. // 发送微信登录请求并处理结果
  280. async wxLoginRequest(loginParams) {
  281. try {
  282. uni.showLoading({ title: '登录中...' });
  283. console.log('发送登录请求,参数:', loginParams);
  284. // 发送登录请求
  285. const data = await wxLogin(loginParams);
  286. console.log('登录成功,返回数据:', data);
  287. // 构建用户信息对象
  288. const userData = this.buildUserData(data, loginParams);
  289. // 保存登录状态
  290. this.saveLoginState(data, userData);
  291. // 步骤6: 获取用户详细信息 - 如果需要的话
  292. if (userData.userId) {
  293. this.fetchUserDetail();
  294. } else {
  295. console.log('无法获取用户ID,跳过获取详细信息');
  296. }
  297. // 检查是否需要获取手机号
  298. if (!userData.phone) {
  299. console.log('用户未绑定手机号,可以提示用户绑定');
  300. // 这里可以显示提示或自动弹出获取手机号的按钮
  301. }
  302. } catch (error) {
  303. this.handleLoginError(error, loginParams);
  304. }
  305. },
  306. /**
  307. * 构建用户数据对象
  308. * @param {Object} data - 后端返回的数据
  309. * @param {Object} loginParams - 登录参数
  310. * @returns {Object} - 构建的用户数据
  311. */
  312. buildUserData(data, loginParams) {
  313. console.log('构建用户数据,服务器返回:', data);
  314. // 处理不同的返回格式
  315. let userData = {
  316. // 用户基本信息 - 优先使用服务器返回的数据
  317. username: data.username || data.nickName ||
  318. (loginParams.userInfo ? loginParams.userInfo.nickName : '微信用户'),
  319. // 用户ID可能在不同字段
  320. userId: data.userId || data.user_id || data.id || data.openid || '',
  321. // 头像可能在不同字段
  322. avatar: data.avatar || data.avatarUrl ||
  323. (loginParams.userInfo ? loginParams.userInfo.avatarUrl : '/static/avatar.png'),
  324. // 用户详细信息
  325. phone: data.phone || data.mobile || '',
  326. gender: data.gender || (loginParams.userInfo ? loginParams.userInfo.gender : 0),
  327. // 微信相关信息
  328. openid: data.openid || '',
  329. unionid: data.unionid || '',
  330. session_key: data.session_key || '',
  331. // 是否新用户
  332. is_new_user: data.is_new_user || false,
  333. // 登录时间
  334. loginTime: new Date().getTime()
  335. };
  336. console.log('构建的用户数据:', userData);
  337. return userData;
  338. },
  339. /**
  340. * 保存登录状态和用户信息
  341. * @param {Object} data - 后端返回的数据
  342. * @param {Object} userData - 构建的用户数据
  343. */
  344. saveLoginState(data, userData) {
  345. // 保存token - 可能在不同字段
  346. const token = data.token || data.session_key || '';
  347. if (token) {
  348. uni.setStorageSync('token', token);
  349. console.log('Token已保存:', token);
  350. }
  351. // 保存用户信息
  352. uni.setStorageSync('userInfo', JSON.stringify(userData));
  353. console.log('用户信息已保存');
  354. // 更新页面状态
  355. this.isLogin = true;
  356. this.userInfo = userData;
  357. // 显示成功提示
  358. uni.hideLoading();
  359. uni.showToast({
  360. title: '登录成功',
  361. icon: 'success'
  362. });
  363. },
  364. /**
  365. * 处理登录错误
  366. * @param {Error} error - 错误对象
  367. * @param {Object} loginParams - 登录参数
  368. */
  369. handleLoginError(error, loginParams) {
  370. uni.hideLoading();
  371. // 检查是否是 code 无效错误
  372. if (error.message && (
  373. error.message.includes('code无效') ||
  374. error.message.includes('已过期') ||
  375. error.message.includes('已被使用') ||
  376. error.status === 999)) {
  377. console.error('微信登录code无效,重新获取:', error);
  378. uni.showToast({
  379. title: 'code已过期,请重试',
  380. icon: 'none',
  381. duration: 2000
  382. });
  383. // 延迟一下再重新获取code,避免频繁调用
  384. setTimeout(() => {
  385. this.getWxLoginCode();
  386. }, 1000);
  387. return;
  388. }
  389. // 其他错误处理保持不变
  390. if (error.code === 10001) {
  391. // 微信未绑定账号,跳转到绑定页面
  392. uni.navigateTo({
  393. url: '/pages/bind/bind?code=' + (loginParams.code || '')
  394. });
  395. } else if (error.message && error.message.includes('CSRF')) {
  396. // CSRF 错误处理
  397. console.error('CSRF验证失败:', error);
  398. uni.showToast({
  399. title: 'CSRF验证失败,请刷新页面重试',
  400. icon: 'none',
  401. duration: 2000
  402. });
  403. setTimeout(() => this.refreshCSRFToken(), 2000);
  404. } else {
  405. // 其他错误
  406. console.error('微信登录失败:', error);
  407. uni.showToast({
  408. title: error.message || '登录失败',
  409. icon: 'none'
  410. });
  411. }
  412. },
  413. /**
  414. * 获取用户详细信息
  415. * 步骤6: 获取并更新用户详细信息
  416. */
  417. async fetchUserDetail() {
  418. try {
  419. if (!this.isLogin) return;
  420. // 获取用户ID
  421. const userId = this.userInfo.userId;
  422. // 调用获取用户详情API
  423. const userDetail = await getUserInfo(userId,JSON.parse(uni.getStorageSync('userInfo')).openid);
  424. console.log('获取用户详细信息成功:', userDetail);
  425. if (userDetail) {
  426. // 更新用户信息
  427. this.updateUserInfo(userDetail);
  428. }
  429. } catch (error) {
  430. console.error('获取用户详细信息失败:', error);
  431. }
  432. },
  433. /**
  434. * 更新用户信息
  435. * @param {Object} userDetail - 用户详细信息
  436. */
  437. updateUserInfo(userDetail) {
  438. // 合并现有信息和新获取的详细信息
  439. const updatedUserInfo = {
  440. ...this.userInfo,
  441. // 更新基本信息
  442. username: userDetail.username || userDetail.nickName || this.userInfo.username,
  443. avatar: userDetail.avatar || userDetail.avatarUrl || this.userInfo.avatar,
  444. phone: userDetail.phone || userDetail.mobile || this.userInfo.phone,
  445. // 更新详细信息
  446. email: userDetail.email || '',
  447. address: userDetail.address || '',
  448. birthday: userDetail.birthday || '',
  449. // 其他字段
  450. ...userDetail
  451. };
  452. // 更新状态和存储
  453. this.userInfo = updatedUserInfo;
  454. uni.setStorageSync('userInfo', JSON.stringify(updatedUserInfo));
  455. console.log('用户详细信息已更新');
  456. },
  457. /**
  458. * 获取用户手机号
  459. * @param {Object} e - 事件对象
  460. */
  461. getPhoneNumber(e) {
  462.   if (e.detail.code) {
  463.     // 立即发送到后端,不缓存,不复用
  464.     wx.request({
  465.       url: 'http:192.168.66.187:8083/wechat/getUserPhoneNumber',
  466.       method: 'POST',
  467.       data: {
  468.         code: e.detail.code,  // 刚获取的新code
  469.         openid: this.data.openid
  470.       }
  471.     })
  472.   }
  473. },
  474. /* async getPhoneNumber(e) {
  475. console.log('获取手机号事件:', e);
  476. // 检查是否成功获取
  477. if (e.detail.errMsg !== 'getPhoneNumber:ok') {
  478. console.error('用户拒绝授权手机号');
  479. uni.showToast({
  480. title: '获取手机号失败',
  481. icon: 'none'
  482. });
  483. return;
  484. }
  485. try {
  486. uni.showLoading({ title: '获取手机号中...' });
  487. // 每次都重新获取最新的登录code
  488. const loginResult = await new Promise((resolve, reject) => {
  489. uni.login({
  490. provider: 'weixin',
  491. success: (res) => resolve(res),
  492. fail: (err) => reject(err)
  493. });
  494. });
  495. if (!loginResult || !loginResult.code) {
  496. throw new Error('获取微信登录凭证失败');
  497. }
  498. console.log('成功获取新的登录code:', loginResult.code);
  499. // 获取存储的用户信息
  500. const userInfoStr = uni.getStorageSync('userInfo');
  501. if (!userInfoStr) {
  502. throw new Error('用户信息不存在,请重新登录');
  503. }
  504. const userInfo = JSON.parse(userInfoStr);
  505. // 准备请求参数
  506. const params = {
  507. code: loginResult.code,
  508. encryptedData: e.detail.encryptedData,
  509. iv: e.detail.iv,
  510. openid: userInfo.openid
  511. };
  512. console.log('获取手机号请求参数:', params);
  513. // 调用获取手机号API
  514. const phoneData = await getUserPhoneNumber(params);
  515. console.log('获取手机号成功:', phoneData);
  516. // 更新用户信息
  517. if (phoneData && phoneData.phoneNumber) {
  518. const updatedUserInfo = {
  519. ...this.userInfo,
  520. phone: phoneData.phoneNumber
  521. };
  522. // 更新状态和存储
  523. this.userInfo = updatedUserInfo;
  524. uni.setStorageSync('userInfo', JSON.stringify(updatedUserInfo));
  525. uni.showToast({
  526. title: '手机号绑定成功',
  527. icon: 'success'
  528. });
  529. } else {
  530. throw new Error('未能获取到手机号');
  531. }
  532. } catch (error) {
  533. console.error('获取手机号失败:', error);
  534. uni.showToast({
  535. title: error.message || '获取手机号失败',
  536. icon: 'none'
  537. });
  538. } finally {
  539. uni.hideLoading();
  540. }
  541. }, */
  542. // 添加刷新 CSRF token 的方法
  543. refreshCSRFToken() {
  544. // 这里实现获取新的 CSRF token 的逻辑
  545. // 可能需要调用特定的 API 或刷新页面
  546. uni.request({
  547. url: 'your-api-endpoint/csrf-token', // 替换为获取 CSRF token 的 API
  548. method: 'GET',
  549. success: (res) => {
  550. if (res.data && res.data.csrfToken) {
  551. uni.setStorageSync('csrfToken', res.data.csrfToken);
  552. console.log('CSRF token 已刷新');
  553. }
  554. },
  555. fail: (err) => {
  556. console.error('获取 CSRF token 失败', err);
  557. }
  558. });
  559. },
  560. handleMenuClick(item) {
  561. // 检查是否需要登录
  562. const needLogin = ['profile', 'orders', 'favorites'];
  563. if (needLogin.includes(item.action) && !this.isLogin) {
  564. uni.showToast({
  565. title: '请先登录',
  566. icon: 'none'
  567. });
  568. setTimeout(() => {
  569. this.goLogin();
  570. }, 1500);
  571. return;
  572. }
  573. // 根据action跳转到对应页面
  574. switch(item.action) {
  575. case 'profile':
  576. uni.navigateTo({ url: '/pages/profile/profile' });
  577. break;
  578. case 'orders':
  579. uni.navigateTo({ url: '/pages/orders/orders' });
  580. break;
  581. case 'favorites':
  582. uni.navigateTo({ url: '/pages/favorites/favorites' });
  583. break;
  584. case 'settings':
  585. uni.navigateTo({ url: '/pages/settings/settings' });
  586. break;
  587. case 'help':
  588. uni.navigateTo({ url: '/pages/help/help' });
  589. break;
  590. case 'uploadResume':
  591. uni.navigateTo({url:'/pages/uploadResume/uploadResume'})
  592. break;
  593. default:
  594. uni.showToast({
  595. title: `点击了${item.title}`,
  596. icon: 'none'
  597. });
  598. }
  599. },
  600. // 处理退出登录 - 增强版
  601. handleLogout(showConfirm = true) {
  602. const doLogout = () => {
  603. // 调用登出 API
  604. logout().then(() => {
  605. // 清除登录信息
  606. try {
  607. uni.removeStorageSync('token');
  608. uni.removeStorageSync('userInfo');
  609. // 更新状态
  610. this.isLogin = false;
  611. this.userInfo = {
  612. username: '',
  613. userId: '',
  614. avatar: '',
  615. phone: ''
  616. };
  617. // 显示提示(如果需要)
  618. if (showConfirm) {
  619. uni.showToast({
  620. title: '已退出登录',
  621. icon: 'success'
  622. });
  623. }
  624. } catch (e) {
  625. console.error('退出登录失败', e);
  626. if (showConfirm) {
  627. uni.showToast({
  628. title: '退出登录失败',
  629. icon: 'none'
  630. });
  631. }
  632. }
  633. }).catch(err => {
  634. console.error('退出登录请求失败', err);
  635. // 即使 API 请求失败,也清除本地登录状态
  636. uni.removeStorageSync('token');
  637. uni.removeStorageSync('userInfo');
  638. this.isLogin = false;
  639. if (showConfirm) {
  640. /* uni.showToast({
  641. title: err.message || '退出登录失败',
  642. icon: 'none'
  643. }); */
  644. }
  645. });
  646. };
  647. // 是否需要显示确认对话框
  648. if (showConfirm) {
  649. uni.showModal({
  650. title: '提示',
  651. content: '确定要退出登录吗?',
  652. success: (res) => {
  653. if (res.confirm) {
  654. doLogout();
  655. }
  656. }
  657. });
  658. } else {
  659. // 直接登出,不显示确认
  660. doLogout();
  661. }
  662. },
  663. // 格式化手机号,例如:188****8888
  664. formatPhone(phone) {
  665. if (!phone || phone.length < 11) return phone;
  666. return phone.substring(0, 3) + '****' + phone.substring(7);
  667. }
  668. }
  669. }
  670. </script>
  671. <style>
  672. .my-container {
  673. padding: 20rpx;
  674. background-color: #f5f5f5;
  675. min-height: 100vh;
  676. }
  677. .user-info {
  678. display: flex;
  679. align-items: center;
  680. background-color: #ffffff;
  681. padding: 30rpx;
  682. border-radius: 12rpx;
  683. margin-bottom: 20rpx;
  684. }
  685. .avatar {
  686. width: 120rpx;
  687. height: 120rpx;
  688. border-radius: 60rpx;
  689. margin-right: 20rpx;
  690. }
  691. .user-details {
  692. display: flex;
  693. flex-direction: column;
  694. }
  695. .username {
  696. font-size: 36rpx;
  697. font-weight: bold;
  698. margin-bottom: 10rpx;
  699. }
  700. .user-id {
  701. font-size: 24rpx;
  702. color: #999;
  703. }
  704. .user-phone {
  705. font-size: 24rpx;
  706. color: #666;
  707. margin-top: 6rpx;
  708. }
  709. .menu-list {
  710. background-color: #ffffff;
  711. border-radius: 12rpx;
  712. margin-bottom: 20rpx;
  713. }
  714. .menu-item {
  715. display: flex;
  716. justify-content: space-between;
  717. align-items: center;
  718. padding: 30rpx;
  719. border-bottom: 1rpx solid #f5f5f5;
  720. }
  721. .menu-item:last-child {
  722. border-bottom: none;
  723. }
  724. .menu-item-left {
  725. display: flex;
  726. align-items: center;
  727. }
  728. .menu-text {
  729. margin-left: 20rpx;
  730. font-size: 28rpx;
  731. }
  732. .logout-btn {
  733. background-color: #ffffff;
  734. border-radius: 12rpx;
  735. padding: 30rpx;
  736. text-align: center;
  737. color: #ff0000;
  738. font-size: 32rpx;
  739. }
  740. /* 这里应该引入iconfont,但为了简化,我们先不添加 */
  741. .iconfont {
  742. font-size: 36rpx;
  743. color: #007AFF;
  744. }
  745. .icon-right {
  746. color: #cccccc;
  747. }
  748. /* 授权弹窗样式 */
  749. .auth-modal {
  750. position: fixed;
  751. top: 0;
  752. left: 0;
  753. right: 0;
  754. bottom: 0;
  755. background-color: rgba(0, 0, 0, 0.5);
  756. display: flex;
  757. justify-content: center;
  758. align-items: center;
  759. z-index: 999;
  760. }
  761. .auth-content {
  762. width: 80%;
  763. background-color: #fff;
  764. border-radius: 12rpx;
  765. padding: 40rpx;
  766. display: flex;
  767. flex-direction: column;
  768. align-items: center;
  769. }
  770. .auth-title {
  771. font-size: 36rpx;
  772. font-weight: bold;
  773. margin-bottom: 20rpx;
  774. }
  775. .auth-desc {
  776. font-size: 28rpx;
  777. color: #666;
  778. margin-bottom: 40rpx;
  779. text-align: center;
  780. }
  781. .auth-btn {
  782. width: 100%;
  783. height: 80rpx;
  784. line-height: 80rpx;
  785. background-color: #07c160;
  786. color: #fff;
  787. border-radius: 8rpx;
  788. margin-bottom: 20rpx;
  789. }
  790. .auth-cancel {
  791. width: 100%;
  792. height: 80rpx;
  793. line-height: 80rpx;
  794. background-color: #f5f5f5;
  795. color: #333;
  796. border-radius: 8rpx;
  797. }
  798. /* 添加获取手机号按钮样式 */
  799. .get-phone-btn {
  800. margin-top: 20rpx;
  801. background-color: #07c160;
  802. color: #fff;
  803. border-radius: 8rpx;
  804. font-size: 28rpx;
  805. padding: 16rpx 0;
  806. }
  807. </style>