my.vue 22 KB

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