mine.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <template>
  2. <view class="container">
  3. <view class="header">
  4. <!-- 语言切换按钮 -->
  5. <view class="language-switcher" @click="switchLanguage">
  6. <text class="language-icon">🌐</text>
  7. <text class="language-text">{{ currentLanguageName }}</text>
  8. </view>
  9. <view class="avatar">
  10. <image class="avatar-img" src="/static/default-avatar.png" mode="aspectFill"></image>
  11. </view>
  12. <text class="username">{{ userStore.nickname }}</text>
  13. </view>
  14. <view class="content">
  15. <view class="menu-list">
  16. <view class="menu-item" @click="handleMenuClick('profile')">
  17. <text class="menu-icon">👤</text>
  18. <text class="menu-text">{{ $t('mine.profile') }}</text>
  19. <text class="menu-arrow">›</text>
  20. </view>
  21. <view class="menu-item" @click="handleMenuClick('settings')">
  22. <text class="menu-icon">⚙️</text>
  23. <text class="menu-text">{{ $t('mine.settings') }}</text>
  24. <text class="menu-arrow">›</text>
  25. </view>
  26. <view class="menu-item" @click="handleMenuClick('about')">
  27. <text class="menu-icon">ℹ️</text>
  28. <text class="menu-text">{{ $t('mine.about') }}</text>
  29. <text class="menu-arrow">›</text>
  30. </view>
  31. </view>
  32. <view class="logout-section">
  33. <button class="logout-btn" @click="handleLogout">
  34. {{ $t('mine.logout') }}
  35. </button>
  36. </view>
  37. </view>
  38. </view>
  39. </template>
  40. <script setup>
  41. import { computed, watch } from 'vue'
  42. import { onShow } from '@dcloudio/uni-app'
  43. import { useI18n } from 'vue-i18n'
  44. import { useUserStore } from '@/store/index'
  45. import { useLocaleStore } from '@/store/locale'
  46. const { t, locale } = useI18n()
  47. const userStore = useUserStore()
  48. const localeStore = useLocaleStore()
  49. // 当前语言名称
  50. const currentLanguageName = computed(() => {
  51. return localeStore.getCurrentLocaleName()
  52. })
  53. // 设置页面标题
  54. const setPageTitle = () => {
  55. uni.setNavigationBarTitle({
  56. title: t('mine.title')
  57. })
  58. }
  59. // 页面显示时设置标题
  60. onShow(() => {
  61. setPageTitle()
  62. })
  63. // 监听语言变化,更新标题
  64. watch(locale, () => {
  65. setPageTitle()
  66. })
  67. // 切换语言
  68. const switchLanguage = () => {
  69. localeStore.toggleLocale()
  70. uni.showToast({
  71. title: t('common.language.switchSuccess'),
  72. icon: 'success',
  73. duration: 1500
  74. })
  75. }
  76. // 菜单点击
  77. const handleMenuClick = (type) => {
  78. uni.showToast({
  79. title: `${t('mine.' + type)}`,
  80. icon: 'none'
  81. })
  82. }
  83. // 退出登录
  84. const handleLogout = () => {
  85. uni.showModal({
  86. title: t('mine.confirmLogout'),
  87. content: t('mine.logoutMessage'),
  88. success: (res) => {
  89. if (res.confirm) {
  90. // 清除用户信息
  91. userStore.logout()
  92. uni.showToast({
  93. title: t('mine.logoutSuccess'),
  94. icon: 'success',
  95. duration: 1500
  96. })
  97. // 跳转到登录页
  98. setTimeout(() => {
  99. uni.reLaunch({
  100. url: '/pages/login/login'
  101. })
  102. }, 1500)
  103. }
  104. }
  105. })
  106. }
  107. </script>
  108. <style lang="scss" scoped>
  109. .container {
  110. min-height: 100vh;
  111. background-color: #f8f8f8;
  112. }
  113. .header {
  114. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  115. padding: 60rpx 40rpx 80rpx;
  116. text-align: center;
  117. position: relative;
  118. .language-switcher {
  119. position: absolute;
  120. top: 60rpx;
  121. right: 32rpx;
  122. display: flex;
  123. align-items: center;
  124. background: rgba(255, 255, 255, 0.25);
  125. backdrop-filter: blur(10rpx);
  126. border-radius: 40rpx;
  127. padding: 16rpx 28rpx;
  128. transition: all 0.3s;
  129. z-index: 10;
  130. box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
  131. &:active {
  132. transform: scale(0.95);
  133. background: rgba(255, 255, 255, 0.35);
  134. }
  135. .language-icon {
  136. font-size: 36rpx;
  137. margin-right: 8rpx;
  138. }
  139. .language-text {
  140. font-size: 28rpx;
  141. color: #ffffff;
  142. font-weight: 500;
  143. }
  144. }
  145. .avatar {
  146. width: 140rpx;
  147. height: 140rpx;
  148. margin: 0 auto 20rpx;
  149. border-radius: 50%;
  150. background-color: #ffffff;
  151. overflow: hidden;
  152. .avatar-img {
  153. width: 100%;
  154. height: 100%;
  155. }
  156. }
  157. .username {
  158. display: block;
  159. font-size: 32rpx;
  160. font-weight: bold;
  161. color: #ffffff;
  162. }
  163. }
  164. .content {
  165. margin-top: -40rpx;
  166. padding: 0 40rpx;
  167. .menu-list {
  168. background-color: #ffffff;
  169. border-radius: 20rpx;
  170. overflow: hidden;
  171. box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
  172. .menu-item {
  173. display: flex;
  174. align-items: center;
  175. padding: 30rpx 40rpx;
  176. border-bottom: 1rpx solid #f0f0f0;
  177. transition: background-color 0.3s;
  178. &:last-child {
  179. border-bottom: none;
  180. }
  181. &:active {
  182. background-color: #f5f5f5;
  183. }
  184. .menu-icon {
  185. font-size: 40rpx;
  186. margin-right: 24rpx;
  187. }
  188. .menu-text {
  189. flex: 1;
  190. font-size: 28rpx;
  191. color: #333333;
  192. }
  193. .menu-arrow {
  194. font-size: 48rpx;
  195. color: #cccccc;
  196. font-weight: 300;
  197. }
  198. }
  199. }
  200. .logout-section {
  201. margin-top: 40rpx;
  202. padding: 0 40rpx;
  203. .logout-btn {
  204. width: 100%;
  205. height: 88rpx;
  206. line-height: 88rpx;
  207. background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%);
  208. color: #ffffff;
  209. font-size: 32rpx;
  210. font-weight: bold;
  211. border-radius: 44rpx;
  212. border: none;
  213. box-shadow: 0 4rpx 20rpx rgba(238, 90, 111, 0.3);
  214. transition: all 0.3s;
  215. &:active {
  216. opacity: 0.8;
  217. transform: scale(0.98);
  218. }
  219. }
  220. }
  221. }
  222. </style>