App.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. <template>
  2. <view>
  3. <slot></slot>
  4. </view>
  5. </template>
  6. <script setup>
  7. import { onLaunch } from '@dcloudio/uni-app'
  8. import { loadDicts } from './utils/dict.js'
  9. import { storage } from './utils/index.js'
  10. // 应用启动时执行
  11. onLaunch(() => {
  12. console.log('App launched')
  13. // 如果已有登录token,预加载字典数据
  14. if (storage.get('token')) {
  15. loadDicts()
  16. }
  17. })
  18. </script>
  19. <style lang="scss">
  20. /* 全局样式 — Soft UI Evolution */
  21. @import './uni.scss';
  22. page {
  23. font-family: $uni-font-family;
  24. font-size: $uni-font-size-base;
  25. line-height: $uni-line-height-base;
  26. color: $uni-text-color;
  27. background-color: $uni-page-bg-color;
  28. -webkit-font-smoothing: antialiased;
  29. -moz-osx-font-smoothing: grayscale;
  30. }
  31. /* ===== Global Keyframes ===== */
  32. @keyframes app-spin {
  33. to { transform: rotate(360deg); }
  34. }
  35. /* ===== Loading Spinner (unified CSS, replaces emoji 🔄) ===== */
  36. .loading-spinner {
  37. width: 64rpx;
  38. height: 64rpx;
  39. border: 4rpx solid rgba(198, 23, 30, 0.1);
  40. border-top-color: $uni-color-primary;
  41. border-radius: 50%;
  42. animation: app-spin 0.8s linear infinite;
  43. }
  44. /* ===== Loading State Container ===== */
  45. .loading-state {
  46. display: flex;
  47. flex-direction: column;
  48. align-items: center;
  49. justify-content: center;
  50. padding: 120rpx 0;
  51. }
  52. .loading-text {
  53. font-size: $uni-font-size-sm;
  54. color: $uni-text-color-light;
  55. margin-top: 20rpx;
  56. }
  57. /* ===== Empty State ===== */
  58. .empty-state {
  59. display: flex;
  60. flex-direction: column;
  61. align-items: center;
  62. justify-content: center;
  63. padding: 100rpx 0;
  64. }
  65. .empty-icon-wrapper {
  66. width: 120rpx;
  67. height: 120rpx;
  68. border-radius: 50%;
  69. background: #F5F5F5;
  70. display: flex;
  71. align-items: center;
  72. justify-content: center;
  73. margin-bottom: 24rpx;
  74. }
  75. .empty-text {
  76. font-size: 28rpx;
  77. color: $uni-text-color-light;
  78. margin-bottom: 32rpx;
  79. }
  80. .empty-refresh-btn {
  81. padding: 16rpx 48rpx;
  82. background: $uni-color-primary;
  83. color: #FFFFFF;
  84. border: none;
  85. border-radius: $uni-border-radius-sm;
  86. font-size: $uni-font-size-sm;
  87. font-weight: $uni-font-weight-medium;
  88. transition: all $uni-transition-duration-base $uni-transition-timing;
  89. }
  90. .empty-refresh-btn:active {
  91. transform: translateY(1px);
  92. }
  93. /* ===== Tab Bar ===== */
  94. .uni-tabbar {
  95. --tabbar-height: 50px;
  96. --tabbar-bg-color: #FFFFFF;
  97. --tabbar-border-color: #E0E0E0;
  98. --tabbar-item-active-color: #C6171E;
  99. --tabbar-item-color: #999999;
  100. --tabbar-item-font-size: 14px;
  101. --tabbar-item-icon-size: 24px;
  102. --tabbar-item-spacing: 4px;
  103. }
  104. .uni-tabbar__item:active {
  105. transform: scale(0.95);
  106. transition: transform $uni-transition-duration-fast $uni-transition-timing;
  107. }
  108. .uni-tabbar__item-icon { font-size: var(--tabbar-item-icon-size); }
  109. .uni-tabbar__item-text {
  110. font-size: var(--tabbar-item-font-size);
  111. margin-top: var(--tabbar-item-spacing);
  112. }
  113. /* ===== Flex Utilities ===== */
  114. .flex { display: flex; }
  115. .flex-center { display: flex; align-items: center; justify-content: center; }
  116. .flex-just-between { display: flex; align-items: center; justify-content: space-between; }
  117. .flex-column { display: flex; flex-direction: column; }
  118. /* ===== Container ===== */
  119. .container {
  120. width: 100%;
  121. padding: 0 $uni-spacing-base;
  122. }
  123. /* ===== Card (Soft UI Evolution standard) ===== */
  124. .card {
  125. background-color: $uni-card-bg-color;
  126. border-radius: $uni-border-radius-md;
  127. box-shadow: $uni-box-shadow-base;
  128. padding: $uni-spacing-base;
  129. transition: all $uni-transition-duration-base $uni-transition-timing;
  130. }
  131. .card:active {
  132. transform: translateY(-2px);
  133. box-shadow: $uni-box-shadow-lg;
  134. }
  135. /* ===== Buttons (Soft UI) ===== */
  136. .btn-primary {
  137. background-color: $uni-color-primary;
  138. color: #FFFFFF;
  139. border: none;
  140. border-radius: $uni-border-radius-sm;
  141. padding: 12px 24px;
  142. font-size: $uni-font-size-sm;
  143. font-weight: $uni-font-weight-semibold;
  144. box-shadow: $uni-box-shadow-sm;
  145. transition: all $uni-transition-duration-base $uni-transition-timing;
  146. }
  147. .btn-primary:active {
  148. transform: translateY(1px);
  149. box-shadow: none;
  150. }
  151. .btn-primary:disabled {
  152. opacity: 0.5;
  153. box-shadow: none;
  154. }
  155. .btn-secondary {
  156. background-color: $uni-bg-color;
  157. color: $uni-text-color;
  158. border: 1px solid $uni-border-color;
  159. border-radius: $uni-border-radius-sm;
  160. padding: 12px 24px;
  161. font-size: $uni-font-size-sm;
  162. font-weight: $uni-font-weight-medium;
  163. transition: all $uni-transition-duration-base $uni-transition-timing;
  164. }
  165. .btn-secondary:active {
  166. background-color: $uni-page-bg-color;
  167. }
  168. /* ===== Status Tags (pill shape) ===== */
  169. .status-tag {
  170. display: inline-flex;
  171. align-items: center;
  172. padding: 4px 12px;
  173. border-radius: $uni-border-radius-pill;
  174. font-size: $uni-font-size-xs;
  175. font-weight: $uni-font-weight-medium;
  176. }
  177. .status-tag-success {
  178. background-color: rgba(76, 175, 80, 0.1);
  179. color: $uni-color-success;
  180. }
  181. .status-tag-warning {
  182. background-color: rgba(255, 152, 0, 0.1);
  183. color: $uni-color-warning;
  184. }
  185. .status-tag-error {
  186. background-color: rgba(244, 67, 54, 0.1);
  187. color: $uni-color-error;
  188. }
  189. .status-tag-info {
  190. background-color: rgba(33, 150, 243, 0.1);
  191. color: $uni-color-info;
  192. }
  193. /* ===== Form Input (Soft UI standard) ===== */
  194. .input-field {
  195. width: 100%;
  196. padding: 16rpx 20rpx;
  197. background: $uni-page-bg-color;
  198. border: 2rpx solid $uni-border-color;
  199. border-radius: $uni-border-radius-sm;
  200. font-size: $uni-font-size-sm;
  201. color: $uni-text-color;
  202. transition: border-color $uni-transition-duration-base $uni-transition-timing,
  203. box-shadow $uni-transition-duration-base $uni-transition-timing;
  204. box-sizing: border-box;
  205. }
  206. .input-field:focus {
  207. border-color: $uni-color-primary;
  208. box-shadow: $uni-focus-ring;
  209. background: #FFFFFF;
  210. outline: none;
  211. }
  212. .input-field::placeholder {
  213. color: $uni-text-color-placeholder;
  214. }
  215. </style>