dashboard.vue 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <template>
  2. <div class="merchant-dashboard">
  3. <van-nav-bar
  4. :title="$t('merchant.dashboard.title')"
  5. left-arrow
  6. @click-left="goBack"
  7. />
  8. <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
  9. <div class="dashboard-content">
  10. <!-- 店铺信息 -->
  11. <div class="shop-card">
  12. <h3>{{ shopInfo.name || $t('merchant.dashboard.myShop') }}</h3>
  13. <van-tag :type="shopInfo.isOpen ? 'success' : 'default'">
  14. {{ shopInfo.isOpen ? $t('merchant.dashboard.operating') : $t('merchant.dashboard.resting') }}
  15. </van-tag>
  16. <p>{{ shopInfo.hours }}</p>
  17. </div>
  18. <!-- 今日数据 -->
  19. <div class="stats-section">
  20. <h4>{{ $t('merchant.dashboard.todayData') }}</h4>
  21. <van-grid :column-num="2" :border="false">
  22. <van-grid-item icon="gold-coin-o">
  23. <template #text>
  24. <div class="grid-value">¥{{ todayStats.revenue }}</div>
  25. <div class="grid-label">{{ $t('merchant.dashboard.todayRevenue') }}</div>
  26. </template>
  27. </van-grid-item>
  28. <van-grid-item icon="shopping-cart-o">
  29. <template #text>
  30. <div class="grid-value">{{ todayStats.orderCount }}</div>
  31. <div class="grid-label">{{ $t('merchant.dashboard.todayOrders') }}</div>
  32. </template>
  33. </van-grid-item>
  34. <van-grid-item icon="logistics">
  35. <template #text>
  36. <div class="grid-value">{{ todayStats.takeoutCount }}</div>
  37. <div class="grid-label">{{ $t('merchant.dashboard.todayTakeout') }}</div>
  38. </template>
  39. </van-grid-item>
  40. <van-grid-item icon="shop-o">
  41. <template #text>
  42. <div class="grid-value">{{ todayStats.dineInCount }}</div>
  43. <div class="grid-label">{{ $t('merchant.dashboard.todayDineIn') }}</div>
  44. </template>
  45. </van-grid-item>
  46. </van-grid>
  47. </div>
  48. <!-- 订单统计 -->
  49. <div class="order-stats-section">
  50. <h4>{{ $t('merchant.dashboard.orderStats') }}</h4>
  51. <div class="order-stats-grid">
  52. <div class="stat-card" @click="goToOrders('pending')">
  53. <div class="stat-count" style="color: #ff976a">{{ orderStats.pending }}</div>
  54. <div class="stat-name">{{ $t('merchant.dashboard.pending') }}</div>
  55. </div>
  56. <div class="stat-card" @click="goToOrders('preparing')">
  57. <div class="stat-count" style="color: #1989fa">{{ orderStats.preparing }}</div>
  58. <div class="stat-name">{{ $t('merchant.dashboard.preparing') }}</div>
  59. </div>
  60. <div class="stat-card" @click="goToOrders('delivering')">
  61. <div class="stat-count" style="color: #07c160">{{ orderStats.delivering }}</div>
  62. <div class="stat-name">{{ $t('merchant.dashboard.delivering') }}</div>
  63. </div>
  64. <div class="stat-card" @click="goToOrders('completed')">
  65. <div class="stat-count" style="color: #969799">{{ orderStats.completed }}</div>
  66. <div class="stat-name">{{ $t('merchant.dashboard.completed') }}</div>
  67. </div>
  68. </div>
  69. </div>
  70. <!-- 常用功能 -->
  71. <div class="menu-section">
  72. <h4>{{ $t('merchant.menu.commonFunctions') }}</h4>
  73. <van-grid :column-num="3" clickable>
  74. <van-grid-item icon="apps-o" :text="$t('merchant.menu.products')" @click="goToProducts" />
  75. <van-grid-item icon="label-o" :text="$t('merchant.menu.buffetPlans')" to="/merchant/buffet-plans" />
  76. <van-grid-item icon="setting-o" :text="$t('merchant.menu.settings')" />
  77. </van-grid>
  78. </div>
  79. </div>
  80. </van-pull-refresh>
  81. </div>
  82. </template>
  83. <script setup lang="ts">
  84. import { ref, computed, onMounted } from 'vue'
  85. import { useRouter } from 'vue-router'
  86. import { useI18n } from 'vue-i18n'
  87. import { showToast } from 'vant'
  88. import { useMerchantStore } from '@/store/modules/merchant'
  89. const { t } = useI18n()
  90. const router = useRouter()
  91. const merchantStore = useMerchantStore()
  92. const refreshing = ref(false)
  93. const shopInfo = computed(() => merchantStore.shopInfo)
  94. const todayStats = computed(() => merchantStore.todayStats)
  95. const orderStats = computed(() => merchantStore.orderStats)
  96. const loadData = async () => {
  97. try {
  98. await merchantStore.loadDashboardData()
  99. } catch (error) {
  100. showToast(t('merchant.dashboard.loadFailed'))
  101. }
  102. }
  103. const onRefresh = async () => {
  104. await loadData()
  105. refreshing.value = false
  106. showToast(t('common.refreshSuccess'))
  107. }
  108. const goBack = () => {
  109. router.push('/mine')
  110. }
  111. const goToOrders = (status: string) => {
  112. showToast(t('merchant.dashboard.orderManagementInDev'))
  113. }
  114. const goToProducts = () => {
  115. router.push('/merchant/products')
  116. }
  117. onMounted(() => {
  118. loadData()
  119. })
  120. </script>
  121. <style scoped lang="scss">
  122. .merchant-dashboard {
  123. min-height: 100vh;
  124. background: #f5f5f5;
  125. }
  126. .dashboard-content {
  127. padding: 15px;
  128. }
  129. .shop-card {
  130. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  131. border-radius: 12px;
  132. padding: 20px;
  133. color: #fff;
  134. margin-bottom: 15px;
  135. h3 {
  136. margin: 0 0 10px 0;
  137. font-size: 20px;
  138. }
  139. p {
  140. margin: 10px 0 0 0;
  141. font-size: 14px;
  142. opacity: 0.9;
  143. }
  144. }
  145. .stats-section,
  146. .order-stats-section,
  147. .menu-section {
  148. background: #fff;
  149. border-radius: 12px;
  150. padding: 15px;
  151. margin-bottom: 15px;
  152. h4 {
  153. margin: 0 0 15px 0;
  154. font-size: 16px;
  155. font-weight: 600;
  156. }
  157. }
  158. .grid-value {
  159. font-size: 24px;
  160. font-weight: bold;
  161. color: #323233;
  162. margin-bottom: 5px;
  163. }
  164. .grid-label {
  165. font-size: 12px;
  166. color: #969799;
  167. }
  168. .order-stats-grid {
  169. display: grid;
  170. grid-template-columns: repeat(4, 1fr);
  171. gap: 12px;
  172. }
  173. .stat-card {
  174. text-align: center;
  175. padding: 15px;
  176. background: #f7f8fa;
  177. border-radius: 8px;
  178. cursor: pointer;
  179. &:active {
  180. transform: scale(0.95);
  181. }
  182. .stat-count {
  183. font-size: 24px;
  184. font-weight: bold;
  185. margin-bottom: 5px;
  186. }
  187. .stat-name {
  188. font-size: 12px;
  189. color: #969799;
  190. }
  191. }
  192. </style>