index.vue 3.7 KB
<template>
  <view class="page">
    <view class="header-hero" :style="{ paddingTop: statusBarHeight + 'px' }">
      <view class="top-bar">
        <view class="top-left-empty" />
        <view class="top-center">
          <image class="header-logo" src="/static/logo_us.png" mode="aspectFit" />
        </view>
        <view class="top-right" @click="isMenuOpen = true">
          <AppIcon name="menu" size="sm" color="white" />
        </view>
      </view>
      <view class="hero-info">
        <text class="app-sub">{{ storeName }}</text>
        <LocationPicker />
      </view>
    </view>

    <view class="main">
      <view class="content">
        <view class="quick-actions">
          <view
            v-for="action in quickActions"
            :key="action.label"
            class="action-wrap"
            @click="navTo(action.path)"
          >
            <view class="action-card">
              <AppIcon :name="action.icon" size="md" color="white" />
            </view>
            <text class="action-label">{{ action.label }}</text>
          </view>
        </view>
      </view>
    </view>

    <SideMenu v-model="isMenuOpen" />
  </view>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import AppIcon from '../../components/AppIcon.vue'
import SideMenu from '../../components/SideMenu.vue'
import LocationPicker from '../../components/LocationPicker.vue'
import { getStatusBarHeight } from '../../utils/statusBar'

const { t } = useI18n()
const statusBarHeight = getStatusBarHeight()

const storeName = computed(() => uni.getStorageSync('storeName') || 'MedVantage')
const isMenuOpen = ref(false)

const quickActions = computed(() => [
  {
    label: t('Labeling'),
    icon: 'tag',
    path: '/pages/labels/labels',
  },
])

const navTo = (path: string) => {
  uni.navigateTo({ url: path })
}
</script>

<style scoped>
.page {
  min-height: 100vh;
  background: #f9fafb;
  box-sizing: border-box;
}

.header-hero {
  min-height: 260rpx;
  background: linear-gradient(135deg, var(--theme-primary), var(--theme-primary-dark));
  padding-left: 32rpx;
  padding-right: 32rpx;
  padding-bottom: 32rpx;
}

.top-bar {
  height: 96rpx;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.top-left-empty {
  width: 64rpx;
  height: 64rpx;
}

.top-right {
  width: 64rpx;
  height: 64rpx;
  border-radius: 999rpx;
  background: rgba(255, 255, 255, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
}

.top-center {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.header-logo {
  width: 300rpx;
  height: 80rpx;
  background: rgba(255, 255, 255, 0.92);
  border-radius: 12rpx;
  padding: 8rpx 12rpx;
  margin-bottom: 8rpx;
}

.hero-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 16rpx;
}

.app-sub {
  font-size: 26rpx;
  color: rgba(255, 255, 255, 0.9);
  margin-bottom: 12rpx;
}

.main {
  max-width: 960rpx;
  margin: 0 auto;
  padding: 48rpx 48rpx 64rpx;
}

.content {
  background: transparent;
}

.quick-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 40rpx;
}

.action-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20rpx;
  cursor: pointer;
}

.action-card {
  width: 120rpx;
  height: 120rpx;
  border-radius: 28rpx;
  background: var(--theme-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 6rpx 16rpx var(--theme-primary-shadow);
  transition: box-shadow 0.2s ease;
}

.action-card:active {
  box-shadow: 0 2rpx 8rpx var(--theme-primary-shadow-light);
}

.action-label {
  font-size: 28rpx;
  font-weight: 500;
  color: #111827;
  text-align: center;
}
</style>