my.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  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. </view>
  9. </view>
  10. <view class="user-info" v-else @click="goLogin">
  11. <image class="avatar" src="/static/avatar.png"></image>
  12. <view class="user-details">
  13. <text class="username">点击登录</text>
  14. <text class="user-id">登录后查看更多信息</text>
  15. </view>
  16. </view>
  17. <view class="menu-list">
  18. <view class="menu-item" v-for="(item, index) in menuItems" :key="index" @click="handleMenuClick(item)">
  19. <view class="menu-item-left">
  20. <text class="iconfont" :class="item.icon"></text>
  21. <text class="menu-text">{{ item.title }}</text>
  22. </view>
  23. <text class="iconfont icon-right"></text>
  24. </view>
  25. </view>
  26. <view class="logout-btn" @click="handleLogout" v-if="isLogin">
  27. <text>退出登录</text>
  28. </view>
  29. </view>
  30. </template>
  31. <script>
  32. export default {
  33. data() {
  34. return {
  35. isLogin: false,
  36. userInfo: {
  37. username: '',
  38. userId: '',
  39. avatar: ''
  40. },
  41. menuItems: [
  42. { title: '个人资料', icon: 'icon-user', action: 'profile' },
  43. // { title: '我的订单', icon: 'icon-order', action: 'orders' },
  44. // { title: '我的收藏', icon: 'icon-star', action: 'favorites' },
  45. { title: '设置', icon: 'icon-settings', action: 'settings' },
  46. { title: '帮助中心', icon: 'icon-help', action: 'help' }
  47. ]
  48. }
  49. },
  50. onShow() {
  51. // 每次显示页面时检查登录状态
  52. this.checkLoginStatus();
  53. },
  54. methods: {
  55. // 检查登录状态
  56. checkLoginStatus() {
  57. try {
  58. const token = uni.getStorageSync('token');
  59. const userInfo = uni.getStorageSync('userInfo');
  60. if (token && userInfo) {
  61. this.isLogin = true;
  62. this.userInfo = JSON.parse(userInfo);
  63. } else {
  64. this.isLogin = false;
  65. this.userInfo = {
  66. username: '',
  67. userId: '',
  68. avatar: ''
  69. };
  70. }
  71. } catch (e) {
  72. console.error('获取登录状态失败', e);
  73. this.isLogin = false;
  74. }
  75. },
  76. // 前往登录页
  77. goLogin() {
  78. // 显示登录方式选择
  79. uni.showActionSheet({
  80. itemList: ['账号密码登录', '微信登录'],
  81. success: (res) => {
  82. if (res.tapIndex === 0) {
  83. // 账号密码登录
  84. uni.navigateTo({
  85. url: '/pages/login/login'
  86. });
  87. } else if (res.tapIndex === 1) {
  88. // 微信登录
  89. this.wxLogin();
  90. }
  91. }
  92. });
  93. },
  94. // 微信登录
  95. wxLogin() {
  96. // 判断是否在微信环境中
  97. // #ifdef MP-WEIXIN
  98. uni.showLoading({
  99. title: '登录中...'
  100. });
  101. // 直接使用 uni.login 获取 code
  102. uni.login({
  103. provider: 'weixin',
  104. success: (loginRes) => {
  105. // 获取登录凭证成功后,直接请求后端
  106. this.wxLoginRequest(loginRes.code);
  107. // 如果需要用户头像和昵称,可以使用新的接口
  108. this.getUserProfileNew();
  109. },
  110. fail: (err) => {
  111. uni.hideLoading();
  112. uni.showToast({
  113. title: '微信登录失败',
  114. icon: 'none'
  115. });
  116. console.error('微信登录失败', err);
  117. }
  118. });
  119. // #endif
  120. // 非微信环境提示
  121. // #ifndef MP-WEIXIN
  122. uni.showToast({
  123. title: '请在微信环境中使用微信登录',
  124. icon: 'none'
  125. });
  126. // #endif
  127. },
  128. // 使用新的方式获取用户头像和昵称
  129. getUserProfileNew() {
  130. // 获取头像
  131. wx.getUserInfo({
  132. desc: '用于完善用户资料',
  133. success: (res) => {
  134. console.log('获取用户信息成功', res);
  135. // 可以在这里更新用户头像
  136. },
  137. fail: (err) => {
  138. console.error('获取用户信息失败', err);
  139. }
  140. });
  141. // 如果需要获取头像,可以使用 button 组件的开放能力
  142. // 在模板中添加:
  143. // <button open-type="chooseAvatar" @chooseavatar="onChooseAvatar">获取头像</button>
  144. },
  145. // 头像选择回调
  146. onChooseAvatar(e) {
  147. const { avatarUrl } = e.detail;
  148. // 这里可以将头像上传到服务器或进行其他处理
  149. console.log('用户选择的头像:', avatarUrl);
  150. },
  151. // 发送微信登录请求到服务器
  152. wxLoginRequest(code, userInfo = {}) {
  153. // 这里替换为您的实际接口地址
  154. uni.request({
  155. url: 'https://your-api-domain.com/api/wx/login',
  156. method: 'POST',
  157. data: {
  158. code: code,
  159. // 不再依赖 getUserProfile 获取的信息
  160. // 如果有用户选择的头像,可以在这里传递
  161. },
  162. success: (res) => {
  163. uni.hideLoading();
  164. if (res.data.code === 0) {
  165. // 登录成功,保存用户信息和token
  166. const userData = {
  167. username: res.data.data.username || '微信用户',
  168. userId: res.data.data.userId,
  169. avatar: res.data.data.avatar || '/static/avatar.png'
  170. };
  171. try {
  172. uni.setStorageSync('token', res.data.data.token);
  173. uni.setStorageSync('userInfo', JSON.stringify(userData));
  174. // 更新状态
  175. this.isLogin = true;
  176. this.userInfo = userData;
  177. uni.showToast({
  178. title: '登录成功',
  179. icon: 'success'
  180. });
  181. } catch (e) {
  182. console.error('保存登录信息失败', e);
  183. }
  184. } else {
  185. uni.showToast({
  186. title: res.data.msg || '登录失败',
  187. icon: 'none'
  188. });
  189. }
  190. },
  191. fail: (err) => {
  192. uni.hideLoading();
  193. uni.showToast({
  194. title: '网络请求失败',
  195. icon: 'none'
  196. });
  197. console.error('微信登录请求失败', err);
  198. }
  199. });
  200. },
  201. handleMenuClick(item) {
  202. // 检查是否需要登录
  203. const needLogin = ['profile', 'orders', 'favorites'];
  204. if (needLogin.includes(item.action) && !this.isLogin) {
  205. uni.showToast({
  206. title: '请先登录',
  207. icon: 'none'
  208. });
  209. setTimeout(() => {
  210. this.goLogin();
  211. }, 1500);
  212. return;
  213. }
  214. // 根据action跳转到对应页面
  215. switch(item.action) {
  216. case 'profile':
  217. uni.navigateTo({ url: '/pages/profile/profile' });
  218. break;
  219. case 'orders':
  220. uni.navigateTo({ url: '/pages/orders/orders' });
  221. break;
  222. case 'favorites':
  223. uni.navigateTo({ url: '/pages/favorites/favorites' });
  224. break;
  225. case 'settings':
  226. uni.navigateTo({ url: '/pages/settings/settings' });
  227. break;
  228. case 'help':
  229. uni.navigateTo({ url: '/pages/help/help' });
  230. break;
  231. default:
  232. uni.showToast({
  233. title: `点击了${item.title}`,
  234. icon: 'none'
  235. });
  236. }
  237. },
  238. handleLogout() {
  239. uni.showModal({
  240. title: '提示',
  241. content: '确定要退出登录吗?',
  242. success: (res) => {
  243. if (res.confirm) {
  244. // 清除登录信息
  245. try {
  246. uni.removeStorageSync('token');
  247. uni.removeStorageSync('userInfo');
  248. // 更新状态
  249. this.isLogin = false;
  250. this.userInfo = {
  251. username: '',
  252. userId: '',
  253. avatar: ''
  254. };
  255. uni.showToast({
  256. title: '已退出登录',
  257. icon: 'success'
  258. });
  259. } catch (e) {
  260. console.error('退出登录失败', e);
  261. uni.showToast({
  262. title: '退出登录失败',
  263. icon: 'none'
  264. });
  265. }
  266. }
  267. }
  268. });
  269. }
  270. }
  271. }
  272. </script>
  273. <style>
  274. .my-container {
  275. padding: 20rpx;
  276. background-color: #f5f5f5;
  277. min-height: 100vh;
  278. }
  279. .user-info {
  280. display: flex;
  281. align-items: center;
  282. background-color: #ffffff;
  283. padding: 30rpx;
  284. border-radius: 12rpx;
  285. margin-bottom: 20rpx;
  286. }
  287. .avatar {
  288. width: 120rpx;
  289. height: 120rpx;
  290. border-radius: 60rpx;
  291. margin-right: 20rpx;
  292. }
  293. .user-details {
  294. display: flex;
  295. flex-direction: column;
  296. }
  297. .username {
  298. font-size: 36rpx;
  299. font-weight: bold;
  300. margin-bottom: 10rpx;
  301. }
  302. .user-id {
  303. font-size: 24rpx;
  304. color: #999;
  305. }
  306. .menu-list {
  307. background-color: #ffffff;
  308. border-radius: 12rpx;
  309. margin-bottom: 20rpx;
  310. }
  311. .menu-item {
  312. display: flex;
  313. justify-content: space-between;
  314. align-items: center;
  315. padding: 30rpx;
  316. border-bottom: 1rpx solid #f5f5f5;
  317. }
  318. .menu-item:last-child {
  319. border-bottom: none;
  320. }
  321. .menu-item-left {
  322. display: flex;
  323. align-items: center;
  324. }
  325. .menu-text {
  326. margin-left: 20rpx;
  327. font-size: 28rpx;
  328. }
  329. .logout-btn {
  330. background-color: #ffffff;
  331. border-radius: 12rpx;
  332. padding: 30rpx;
  333. text-align: center;
  334. color: #ff0000;
  335. font-size: 32rpx;
  336. }
  337. /* 这里应该引入iconfont,但为了简化,我们先不添加 */
  338. .iconfont {
  339. font-size: 36rpx;
  340. color: #007AFF;
  341. }
  342. .icon-right {
  343. color: #cccccc;
  344. }
  345. </style>