<template>
  <div class="dashboard-page">
    <!-- 顶部：门店信息 + 待办提醒 + 会员搜索 -->
    <div class="top-bar">
      <div class="store-info">
        <div class="store-name">{{ currentStoreName }} · 工作台</div>
        <div class="store-subtitle">
          今日到店 · 开单，一眼总览
          <span class="schedule-link" @click.stop="$store.commit('SET_SCHEDULE_DIALOG', true)">打开排班</span>
        </div>
      </div>
      <div class="top-bar-right">
        <div class="calendar-entry" @click="companyCalendarVisible = true">
          <i class="el-icon-date calendar-entry-icon"></i>
          <span class="calendar-entry-text">公司日历</span>
        </div>
        <div class="member-search">
          <el-autocomplete v-model="memberKeyword" class="member-search-input"
            :fetch-suggestions="fetchMemberSuggestions" placeholder="手机号 / 姓名 / 会员卡号" prefix-icon="el-icon-search"
            value-key="displayText" :trigger-on-focus="true" popper-class="member-search-dropdown"
            @select="handleMemberSelect" @keyup.enter.native="handleFirstMatchOrFocus">
            <template slot-scope="{ item }">
              <div class="member-suggestion">
                <div class="suggestion-main">
                  <span class="suggestion-name">{{ item.khmc }}</span>
                  <span class="suggestion-level" :class="'level--' + (item.levelKey || 'default')">{{ item.level
                  }}</span>
                </div>
                <div class="suggestion-meta">
                  <span><i class="el-icon-phone"></i>{{ item.sjh }}</span>
                  <span v-if="item.dah"><i class="el-icon-postcard"></i>{{ item.dah }}</span>
                  <span><i class="el-icon-office-building"></i>{{ item.gsmdName }}</span>
                </div>
                <div class="suggestion-extra">
                  <span class="suggestion-row">
                    <span>最后到店：{{ item.lastVisit }}</span>
                    <span v-if="item.sleepDays > 0" class="suggestion-sleep">沉睡 {{ item.sleepDays }} 天</span>
                  </span>
                  <span class="suggestion-row">
                    <span>剩余权益：<b>¥{{ item.remainingAmount }}</b></span>
                    <span>累计消费：¥{{ item.totalConsume }}</span>
                  </span>
                </div>
              </div>
            </template>
          </el-autocomplete>
        </div>
      </div>
      <div class="top-meta">
        <div class="today-text">
          <span class="today-date">{{ todayLabel }}</span>
          <span class="today-clock">{{ currentTime }}</span>
        </div>
        <div class="top-actions">
          <!-- 全屏按钮 -->
          <el-tooltip :content="isFullscreen ? '退出全屏' : '全屏显示'" placement="bottom" effect="dark">
            <div class="action-btn" @click="toggleFullscreen">
              <i :class="isFullscreen ? 'el-icon-copy-document' : 'el-icon-full-screen'"></i>
            </div>
          </el-tooltip>
          <!-- 用户下拉菜单 -->
          <el-dropdown trigger="click" placement="bottom-end" @command="handleUserCommand">
            <div class="user-info user-info--clickable">
              <div class="user-avatar">{{ userInitial }}</div>
              <span class="user-name">{{ userName }}</span>
              <i class="el-icon-arrow-down user-arrow"></i>
            </div>
            <el-dropdown-menu slot="dropdown" class="user-dropdown-menu">
              <div class="dropdown-header">
                <div class="dropdown-avatar">{{ userInitial }}</div>
                <div class="dropdown-name">{{ userName }}</div>
                <div class="dropdown-role">门店员工</div>
              </div>
              <el-dropdown-item command="profile">
                <i class="el-icon-user"></i>个人信息
              </el-dropdown-item>
              <el-dropdown-item command="store" v-if="storeList.length > 1">
                <i class="el-icon-office-building"></i>切换门店
              </el-dropdown-item>
              <el-dropdown-item command="password">
                <i class="el-icon-lock"></i>修改密码
              </el-dropdown-item>
              <el-dropdown-item command="logout" divided class="dropdown-item--danger">
                <i class="el-icon-switch-button"></i>退出登录
              </el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </div>
      </div>
    </div>

    <div class="layout-grid" :class="{ 'layout-grid--reminder-open': reminderCenterOpen }">
      <!-- 左侧：概览 + 六大板块 -->
      <div class="left-column">
        <!-- 今日概览 -->
        <div class="overview-row" v-loading="overviewLoading">
          <el-row :gutter="16" class="overview-row-inner">
            <el-col
              v-for="item in overviewStats"
              :key="item.key"
              :span="24 / overviewStats.length"
            >
              <el-card
                shadow="hover"
                :class="['overview-card', 'overview-card--' + item.key]"
              >
                <div class="overview-card-inner">
                  <div class="overview-meta">
                    <span class="label">{{ item.label }}</span>
                    <span class="tag" v-if="item.tag">{{ item.tag }}</span>
                  </div>
                  <div class="overview-main">
                    <div class="overview-main-value">{{ item.today }}</div>
                  </div>
                  <div class="overview-secondary">
                    <span class="overview-secondary-label">本月</span>
                    <span class="overview-secondary-value">{{ item.month }}</span>
                  </div>
                </div>
              </el-card>
            </el-col>
          </el-row>
        </div>

        <!-- 月业绩进度 -->
        <div class="monthly-progress-bar">
          <div class="progress-header">
            <div class="progress-title">
              <i class="el-icon-data-analysis"></i>
              本月门店业绩进度
            </div>
            <div class="progress-meta">
              <span class="progress-percent">{{ monthlyPercent }}%</span>
              <span class="progress-done">{{ formatMoney(monthlyDone) }}</span>
              <span class="progress-sep">/</span>
              <span class="progress-target">目标 {{ formatMoney(monthlyTarget) }}</span>
            </div>
          </div>
          <div class="progress-track">
            <div class="progress-fill" :style="{ width: monthlyPercent + '%' }"></div>
          </div>
          <div class="progress-footer">
            <span>距月末还有 <b>{{ daysLeft }}</b> 天</span>
            <span>还需完成 <b>¥ {{ remainTarget }}</b></span>
          </div>
        </div>

        <!-- 业务板块：支持拖拽排序并本地记忆顺序 -->
        <div class="modules-grid">
          <draggable
            v-model="modules"
            tag="el-row"
            :component-data="{ props: { gutter: 16 } }"
            :options="moduleDragOptions"
            @end="onModuleDragEnd"
          >
            <el-col v-for="module in modules" :key="module.key" :span="8">
              <el-card
                shadow="hover"
                class="module-card module-card--draggable"
                :body-style="{ padding: '20px 20px 18px' }"
                @click.native="handleModuleCardClick($event, module)"
              >
                <div class="module-header">
                  <div class="module-title-wrap">
                    <div class="module-title">{{ module.title }}</div>
                    <div class="module-subtitle">{{ module.subtitle }}</div>
                  </div>
                  <div class="module-icon" :style="{ background: module.iconBg }">
                    <i :class="module.icon"></i>
                  </div>
                </div>
                <div v-if="!module.hideMetric" class="module-meta">
                  <div class="meta-value">{{ module.metricValue }}</div>
                  <div class="meta-label">{{ module.metricLabel }}</div>
                </div>
                <div class="module-actions-spacer"></div>
                <div class="module-actions">
                  <button
                    type="button"
                    class="primary-action"
                    @click.stop="handleModulePrimary(module)"
                  >
                    {{ module.primaryAction }}
                  </button>
                  <span
                    v-if="module.secondaryText"
                    class="secondary-text"
                    @click.stop="handleModuleSecondary(module)"
                  >
                    {{ module.secondaryText }}
                  </span>
                </div>
              </el-card>
            </el-col>
          </draggable>
        </div>
      </div>

      <!-- 提醒中心侧栏（我的待办 / 今日到店 / 生日提醒 / 沉睡提醒） -->
      <div class="reminder-center">
        <!-- 右侧窄栏入口 -->
        <div class="reminder-center-toggle">
          <div v-for="entry in reminderEntries" :key="entry.key"
            :class="['reminder-toggle-item', entry.key === 'todo' ? 'todo-entry' : '', { 'is-active': currentReminderType === entry.key && reminderCenterOpen }]"
            @click="handleReminderEntryClick(entry.key)">
            <!-- 提醒中心入口样式：图标在上、文字在下（角标显示数字） -->
            <el-badge
              :value="entry.count"
              :max="99"
              :hidden="entry.count === 0"
              class="reminder-badge"
            >
              <div :class="['entry-icon-wrap', 'entry-icon-wrap--' + entry.key]">
                <i :class="['entry-icon', entry.icon]"></i>
              </div>
            </el-badge>
            <span class="label-text">{{ entry.label }}</span>
          </div>
          <div v-if="reminderCenterOpen" class="reminder-toggle-close" @click.stop="toggleReminderCenter(false)">
            <i class="el-icon-arrow-right"></i>
          </div>
        </div>

        <!-- 侧栏主体 -->
        <transition name="reminder-center-slide" :css="reminderFirstRenderDone">
          <div v-if="reminderCenterOpen" class="reminder-center-panel">
            <el-card shadow="hover" class="today-card" :body-style="{ padding: '12px 14px 14px' }">
              <el-tabs v-model="todayTab" @tab-click="handleTodayTabClick">
                <el-tab-pane label="我的待办" name="todo">
                  <div v-if="todoList.length" class="timeline-list todo-list">
                    <div
                      v-for="item in todoList"
                      :key="item.key"
                      class="timeline-item todo-item"
                      @click="handleTodoClick(item)"
                    >
                      <div class="time todo-item__aside">
                        <span
                          class="todo-item__tag"
                          :class="{
                            'todo-item__tag--overdue': item.urgency === 'overdue',
                            'todo-item__tag--urgent': item.urgency === 'urgent'
                          }"
                        >{{ item.tag || '待办' }}</span>
                      </div>
                      <div class="content">
                        <div class="line-main todo-item__main">
                          <span class="name">{{ item.title }}</span>
                          <span v-if="item.dueTime" class="todo-item__due">{{ formatTodoDueLabel(item.dueTime) }}</span>
                        </div>
                        <div v-if="item.desc" class="line-sub todo-item__sub">
                          <span class="project">{{ item.desc }}</span>
                        </div>
                        <div class="todo-item__foot">
                          <button
                            type="button"
                            class="todo-action-btn todo-action-btn--primary"
                            @click.stop="handleTodoClick(item)"
                          >立即处理</button>
                          <span class="todo-action-divider" aria-hidden="true" />
                          <button type="button" class="todo-action-btn" @click.stop="handleTodoDismiss(item)">忽略</button>
                        </div>
                      </div>
                    </div>
                  </div>
                  <div v-else class="empty-tip">暂无待办事项</div>
                </el-tab-pane>
                <el-tab-pane label="今日到店" name="booking">
                  <div v-if="todayBooking.length" class="timeline-list">
                    <div v-for="item in todayBooking" :key="item.id" class="timeline-item">
                      <div class="time">{{ item.time }}</div>
                      <div class="content">
                        <div class="line-main">
                          <span class="name">{{ item.name }}</span>
                          <span class="mobile">{{ item.mobile }}</span>
                        </div>
                        <div class="line-sub">
                          <span class="project">
                            预约项目：{{ item.project }} · 预约时间：{{ item.date }} {{ item.timeRange }}
                          </span>
                          <div class="booking-actions">
                            <el-button
                              type="text"
                              size="mini"
                              class="booking-action-btn booking-action-btn--cancel"
                              @click.stop="handleCancelBooking(item)"
                            >
                              取消预约
                            </el-button>
                            <el-button
                              type="text"
                              size="mini"
                              class="booking-action-btn booking-action-btn--confirm"
                              @click.stop="handleConfirmConsume(item)"
                            >
                              确认消耗
                            </el-button>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                  <div v-else class="empty-tip">今日暂无预约记录</div>
                </el-tab-pane>
                <el-tab-pane label="生日提醒" name="birthday">
                  <div class="birthday-calendar">
                    <!-- 月份切换头 -->
                    <div class="cal-header">
                      <button class="cal-nav-btn" @click="prevBirthdayMonth"><i class="el-icon-arrow-left"></i></button>
                      <div class="cal-month-label">{{ birthdayYear }} 年 {{ birthdayMonth }} 月</div>
                      <button class="cal-nav-btn" @click="nextBirthdayMonth"><i
                          class="el-icon-arrow-right"></i></button>
                    </div>
                    <!-- 星期头 -->
                    <div class="cal-weekdays">
                      <div v-for="w in ['日', '一', '二', '三', '四', '五', '六']" :key="w" class="cal-weekday">{{ w }}</div>
                    </div>
                    <!-- 日期格子 -->
                    <div class="cal-grid">
                      <div v-for="(cell, idx) in calendarDays" :key="idx"
                        :class="['cal-cell', { 'cal-cell--empty': !cell.day, 'cal-cell--has-birthday': cell.members.length > 0, 'cal-cell--selected': cell.day === selectedBirthdayDay }]"
                        @click="cell.day && selectBirthdayDay(cell.day)">
                        <span v-if="cell.day" class="cal-day-num">{{ cell.day }}</span>
                        <div v-if="cell.members.length" class="cal-dots">
                          <span v-for="m in cell.members.slice(0, 3)" :key="m.id" class="cal-dot"
                            :style="{ background: levelDotColor(m.level) }"
                            :title="m.name + '（' + m.level + '）'"></span>
                        </div>
                      </div>
                    </div>
                    <!-- 生日会员列表 -->
                    <div class="cal-list-title" v-if="birthdayMonthData.length">
                      <span v-if="selectedBirthdayDay != null">{{ birthdayMonth }}月{{ selectedBirthdayDay }}日 · {{
                        birthdayDisplayList.length }} 位</span>
                      <span v-else>本月共 {{ birthdayMonthData.length }} 位会员生日</span>
                      <span v-if="selectedBirthdayDay != null" class="cal-list-reset"
                        @click="selectedBirthdayDay = null">查看全部</span>
                    </div>
                    <div v-if="birthdayDisplayList.length" class="timeline-list cal-member-list">
                      <div v-for="item in birthdayDisplayList" :key="item.id" class="birthday-item">
                        <div class="birthday-day-badge">
                          <i class="el-icon-present birthday-icon"></i>
                          <span class="birthday-day-text">{{ item.day }}日</span>
                        </div>
                        <div class="birthday-info">
                          <div class="birthday-name">
                            {{ item.name }}
                            <span class="birthday-level-tag" :style="levelTagStyle(item.level)">{{ item.level }}</span>
                          </div>
                          <div class="birthday-phone">{{ item.phone }}</div>
                          <div class="birthday-amount">累计消费 ¥{{ item.totalAmount }}</div>
                        </div>
                        <button class="quick-book-btn" @click="handleBirthdayCall(item)">发祝福</button>
                      </div>
                    </div>
                    <div v-else-if="birthdayMonthData.length && selectedBirthdayDay != null" class="empty-tip">{{
                      birthdayMonth }}月{{ selectedBirthdayDay }}日暂无会员生日</div>
                    <div v-else class="empty-tip">本月暂无会员生日</div>
                  </div>
                </el-tab-pane>
                <el-tab-pane label="沉睡提醒" name="sleeping">
                  <div v-if="sleepingMembers.length" class="timeline-list">
                    <div v-for="item in sleepingMembers" :key="item.id" class="sleeping-item">
                      <div class="sleeping-days">{{ item.days }}天</div>
                      <div class="sleeping-info">
                        <div class="sleeping-name">
                          {{ item.name }}
                          <span class="sleeping-level">{{ item.level }}</span>
                        </div>
                        <div class="sleeping-phone">{{ item.phone }}</div>
                        <div class="sleeping-last">最后到店：{{ item.lastVisit }} · 余额 ¥{{ item.balance }}</div>
                      </div>
                      <button class="quick-book-btn" @click="handleSleepingCall(item)">去沟通</button>
                    </div>
                  </div>
                  <div v-else class="empty-tip">暂无沉睡会员</div>
                </el-tab-pane>
              </el-tabs>
            </el-card>
          </div>
        </transition>
      </div>
    </div>
    <member-profile-dialog
      :visible.sync="memberDialogVisible"
      :member="activeMember || {}"
      @action="handleMemberAction"
    />
    <tuoke-lead-dialog :visible.sync="tuokeDialogVisible" @saved="loadTodayTuokeCount" />
    <booking-consume-dialog
      :visible.sync="bookingConsumeDialogVisible"
      @saved="handlePreConsumeBookingSaved"
    />
    <booking-dialog :visible.sync="bookingDialogVisible" :prefill="bookingPrefill" />
    <billing-dialog :visible.sync="billingDialogVisible" :prefill="billingPrefill" @submitted="loadTodayBillingCount" />
    <consume-dialog :visible.sync="consumeDialogVisible" :prefill="consumePrefill" @submitted="loadTodayConsumeCount" />
    <refund-dialog :visible.sync="refundDialogVisible" :prefill="refundPrefill" @submitted="loadTodayRefundCount" />
    <tuoke-list-dialog :visible.sync="tuokeListVisible" />
    <booking-calendar-dialog
      :visible.sync="bookingCalendarVisible"
      :current-store-id="currentStoreId"
      @convert-consume="handleBookingConvertConsume"
    />
    <billing-list-dialog :visible.sync="billingListVisible" :current-store-id="currentStoreId" />
    <consume-list-dialog :visible.sync="consumeListVisible" :current-store-id="currentStoreId" />
    <refund-list-dialog :visible.sync="refundListVisible" :current-store-id="currentStoreId" />
    <gold-triangle-dialog
      :visible.sync="goldTriangleDialogVisible"
      :current-store-id="currentStoreId"
      :current-store-name="currentStoreName"
    />
    <store-target-dialog
      :visible.sync="storeTargetDialogVisible"
      :current-store-id="currentStoreId"
      :current-store-name="currentStoreName"
      :month-value="storeTargetMonthValue"
    />
    <invite-add-dialog
      :visible.sync="contactDialogVisible"
      :customer="currentContactCustomer"
      @success="handleContactSuccess"
      @cancel="handleContactCancel"
    />
    <company-calendar-dialog :visible.sync="companyCalendarVisible" />
    <!-- 切换门店弹窗 -->
    <el-dialog :visible.sync="storeSwitchDialogVisible" width="420px" append-to-body custom-class="store-switch-dialog"
      :show-close="false">
      <div class="store-switch-inner">
        <div class="store-switch-header">
          <div class="store-switch-title">切换门店</div>
          <span class="store-switch-close" @click="storeSwitchDialogVisible = false"><i
              class="el-icon-close"></i></span>
        </div>
        <div class="store-switch-content">
          <div v-for="s in storeList" :key="s.id"
            :class="['store-switch-item', { 'store-switch-item--active': s.id === currentStoreId }]"
            @click="handleStoreSwitch(s)">
            <div class="store-switch-icon">
              <span>{{ (s.name || '').replace(/店$/, '')[0] || '店' }}</span>
            </div>
            <div class="store-switch-info">
              <div class="store-switch-name">
                {{ s.name }}
                <span v-if="s.id === currentStoreId" class="store-switch-badge">当前</span>
              </div>
              <div class="store-switch-addr" v-if="s.address">
                <i class="el-icon-location-outline"></i>{{ s.address }}
              </div>
            </div>
            <i v-if="s.id === currentStoreId" class="el-icon-check store-switch-check"></i>
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import request from '@/utils/request'
import {
  getStoreDashboardStatistics,
  getStoreDailyStatistics,
  getStorePerformanceCompletion
} from '@/api/storeDashboard'
import { getTkjlbList } from '@/api/lqTkjlb'
import { getKdKdjlbList } from '@/api/lqKdKdjlb'
import { getXhHyhkList } from '@/api/lqXhHyhk'
import { buildHksjRange } from '@/utils/consumeHelper'
import { getHytkHytkList } from '@/api/lqHytkHytk'
import { buildTksjRange } from '@/utils/refundHelper'
import { getYyjlList, cancelYyjl, startYyjlService } from '@/api/lqYyjl'
import { buildBillingKdrqRange } from '@/utils/billingHelper'
import { getStoreUserList } from '@/api/storeUser'
import { getAttendanceMonthReport } from '@/api/lqAttendanceRecord'
import {
  mapYyjlListRow,
  formatDateYMD,
  buildYysjTimestampRange,
  formatTodoDueLabel as formatTodoDueLabelText
} from '@/utils/appointmentHelper'
import { mapAttendanceDayToScheduleStatus } from '@/utils/scheduleHelper'
import draggable from 'vuedraggable'
import MemberProfileDialog from '@/components/MemberProfileDialog.vue'
import TuokeLeadDialog from '@/components/TuokeLeadDialog.vue'
import InviteAddDialog from '@/components/InviteAddDialog.vue'
import CompanyCalendarDialog from '@/components/CompanyCalendarDialog.vue'
import BookingDialog from '@/components/BookingDialog.vue'
import BookingConsumeDialog from '@/components/booking-consume-dialog.vue'
import BillingDialog from '@/components/BillingDialog.vue'
import ConsumeDialog from '@/components/ConsumeDialog.vue'
import RefundDialog from '@/components/RefundDialog.vue'
import TuokeListDialog from '@/components/TuokeListDialog.vue'
import BookingCalendarDialog from '@/components/BookingCalendarDialog.vue'
import BillingListDialog from '@/components/BillingListDialog.vue'
import ConsumeListDialog from '@/components/ConsumeListDialog.vue'
import RefundListDialog from '@/components/RefundListDialog.vue'
import GoldTriangleDialog from '@/components/GoldTriangleDialog.vue'
import StoreTargetDialog from '@/components/StoreTargetDialog.vue'
import { getKhxxList } from '@/api/lqKhxx'
import { getMyProfile } from '@/api/lqStoreAuth'
import { mapKhxxListToSuggestion } from '@/utils/memberProfileHelper'

export default {
  name: 'Dashboard',
  components: {
    MemberProfileDialog,
    TuokeLeadDialog,
    InviteAddDialog,
    CompanyCalendarDialog,
    BookingDialog,
    BookingConsumeDialog,
    BillingDialog,
    ConsumeDialog,
    RefundDialog,
    TuokeListDialog,
    BookingCalendarDialog,
    BillingListDialog,
    ConsumeListDialog,
    RefundListDialog,
    GoldTriangleDialog,
    StoreTargetDialog,
    draggable
  },
  data() {
    return {
      isFullscreen: false,
      currentTime: '',
      clockTimer: null,
      storeTargetDialogVisible: false,
      memberKeyword: '',
      memberDialogVisible: false,
      activeMember: null,
      contactDialogVisible: false,
      activeTodoId: '',
      currentContactCustomer: {},
      companyCalendarVisible: false,
      storeSwitchDialogVisible: false,
      currentStoreId: '',
      storeList: [],
      overviewLoading: false,
      monthlyDone: 0,
      monthlyTarget: 0,
      memberSuggestTimer: null,
      todayTab: 'todo',
      overviewStats: [
        { key: 'headCount', label: '人头数', today: 0, month: 0, tag: '客流' },
        { key: 'visitCount', label: '人次数', today: 0, month: 0, tag: '频次' },
        { key: 'projectCount', label: '项目数', today: 0, month: 0, tag: '项目' },
        { key: 'consumeAmount', label: '消耗金额', today: '¥0', month: '¥0', tag: '消耗' },
        { key: 'refundAmount', label: '退卡金额', today: '¥0', month: '¥0', tag: '退卡' }
      ],
      todoList: [],
      todoTotal: 0,
      todoLoading: false,
      todoCountData: { total: 0, followUp: 0, approval: 0, system: 0 },
      todoSourceFilter: '',
      modules: [
        {
          key: 'tuoke',
          title: '拓客管理',
          subtitle: '',
          icon: 'el-icon-connection',
          iconBg: 'linear-gradient(135deg, #6366f1, #a855f7)',
          metricValue: 0,
          metricLabel: '今日新增潜客',
          primaryAction: '新建拓客',
          secondaryText: '查看拓客数据'
        },
        {
          key: 'booking',
          title: '预约管理',
          subtitle: '',
          icon: 'el-icon-date',
          iconBg: 'linear-gradient(135deg, #f97316, #facc15)',
          metricValue: 0,
        metricLabel: '今日到店',
          primaryAction: '新建预约',
          secondaryText: '打开预约日历'
        },
        {
          key: 'order',
          title: '开单管理',
          subtitle: '',
          icon: 'el-icon-s-order',
          iconBg: 'linear-gradient(135deg, #3b82f6, #2563eb)',
          metricValue: 0,
          metricLabel: '今日开单',
          primaryAction: '新建开单',
          secondaryText: '查看开单记录'
        },
        {
          key: 'consume',
          title: '消耗管理',
          subtitle: '',
          icon: 'el-icon-magic-stick',
          iconBg: 'linear-gradient(135deg, #22c55e, #16a34a)',
          metricValue: 0,
          metricLabel: '今日消耗人次',
          primaryAction: '新建消耗',
          secondaryText: '查看消耗记录'
        },
        {
          key: 'refund',
          title: '退卡管理',
          subtitle: '',
          icon: 'el-icon-refresh-left',
          iconBg: 'linear-gradient(135deg, #f97316, #ef4444)',
          metricValue: 0,
          metricLabel: '今日退卡',
          primaryAction: '新建退卡',
          secondaryText: '查看退卡记录'
        },
        {
          key: 'schedule',
          title: '员工排班',
          subtitle: '',
          icon: 'el-icon-s-grid',
          iconBg: 'linear-gradient(135deg, #8b5cf6, #6366f1)',
          metricValue: 0,
          metricLabel: '在岗员工',
          primaryAction: '查看排班',
          secondaryText: ''
        },
        {
          key: 'goldTriangle',
          title: '金三角设置',
          subtitle: '',
          icon: 'el-icon-s-flag',
          iconBg: 'linear-gradient(135deg, #f59e0b, #d97706)',
          hideMetric: true,
          primaryAction: '金三角设置',
          secondaryText: ''
        },
        {
          key: 'storeTarget',
          title: '门店目标设置',
          subtitle: '',
          icon: 'el-icon-aim',
          iconBg: 'linear-gradient(135deg, #2563eb, #1d4ed8)',
          hideMetric: true,
          primaryAction: '设置目标',
          secondaryText: ''
        }
      ],
      moduleOrderStorageKey: 'store_dashboard_module_order',
      todayInvite: [],
      todayBooking: [],
      birthdayYear: new Date().getFullYear(),
      birthdayMonth: new Date().getMonth() + 1,
      selectedBirthdayDay: null,
      birthdayAllData: [
        { id: 'B001', name: '林晓薇', phone: '138****8801', level: 'A++', totalAmount: '38,600', month: 3, day: 5 },
        { id: 'B002', name: '陈美玲', phone: '139****2233', level: 'A+', totalAmount: '22,400', month: 3, day: 12 },
        { id: 'B003', name: '张芳芳', phone: '158****9901', level: 'A', totalAmount: '15,800', month: 3, day: 12 },
        { id: 'B004', name: '王晓燕', phone: '137****4456', level: 'A++', totalAmount: '45,200', month: 3, day: 18 },
        { id: 'B005', name: '李明珠', phone: '186****3322', level: 'B', totalAmount: '8,900', month: 3, day: 22 },
        { id: 'B006', name: '周丽', phone: '133****7788', level: 'A', totalAmount: '18,300', month: 3, day: 22 },
        { id: 'B007', name: '刘思雨', phone: '159****6678', level: 'C', totalAmount: '5,200', month: 3, day: 28 },
        { id: 'B008', name: '赵美华', phone: '181****2234', level: 'A+', totalAmount: '31,800', month: 4, day: 6 },
        { id: 'B009', name: '孙晴晴', phone: '135****8890', level: 'B', totalAmount: '11,200', month: 4, day: 15 },
        { id: 'B010', name: '钱雯雯', phone: '189****0012', level: 'D', totalAmount: '2,800', month: 4, day: 15 },
        { id: 'B011', name: '吴佳敏', phone: '136****5567', level: 'A++', totalAmount: '52,400', month: 5, day: 3 },
        { id: 'B012', name: '郑晓红', phone: '182****3345', level: 'A', totalAmount: '19,600', month: 5, day: 20 },
        { id: 'B013', name: '冯丽娟', phone: '155****7723', level: 'B', totalAmount: '7,300', month: 1, day: 8 },
        { id: 'B014', name: '蒋雪梅', phone: '177****6634', level: 'A+', totalAmount: '28,500', month: 2, day: 14 }
      ],
      sleepingMembers: [
        { id: 'S001', name: '周丽娟', days: 187, phone: '133****7788', level: 'A++', lastVisit: '2024-09-01', balance: '12,800' },
        { id: 'S002', name: '王晓燕', days: 95, phone: '137****4456', level: 'A+', lastVisit: '2024-12-01', balance: '8,500' },
        { id: 'S003', name: '刘倩', days: 63, phone: '159****3312', level: 'A', lastVisit: '2025-01-03', balance: '3,200' },
        { id: 'S004', name: '赵海燕', days: 60, phone: '186****0023', level: 'B', lastVisit: '2025-01-06', balance: '1,600' }
      ],
      tuokeDialogVisible: false,
      bookingDialogVisible: false,
      bookingPrefill: {
        name: '',
        phone: ''
      },
      bookingConsumeDialogVisible: false,
      billingDialogVisible: false,
      billingPrefill: {},
      consumeDialogVisible: false,
      consumePrefill: {},
      refundDialogVisible: false,
      refundPrefill: {},
      tuokeListVisible: false,
      bookingCalendarVisible: false,
      billingListVisible: false,
      consumeListVisible: false,
      refundListVisible: false,
      goldTriangleDialogVisible: false,
      // 提醒中心侧栏状态（今日预约 / 生日提醒 / 沉睡提醒）
      // reminderDefaultOpen 可作为默认展开/收起开关
      reminderDefaultOpen: false,
      reminderCenterOpen: false,
      // 提醒中心侧栏：首屏渲染完成后再启用滑动动画
      reminderFirstRenderDone: false,
      currentReminderType: 'booking'
    }
  },
  computed: {
    todayLabel() {
      const d = new Date()
      const year = d.getFullYear()
      const month = `${d.getMonth() + 1}`.padStart(2, '0')
      const day = `${d.getDate()}`.padStart(2, '0')
      return `${year}-${month}-${day}`
    },
    userName() {
      return (this.$store && this.$store.state && this.$store.state.user && this.$store.state.user.realName) || '门店前台'
    },
    userInitial() {
      return this.userName ? this.userName[0] : '店'
    },
    currentStoreName() {
      const info = this.$store.getters.storeInfo || {}
      if (info.storeName) return info.storeName
      const s = this.storeList.find(x => x.id === this.currentStoreId)
      return (s && s.name) || '当前门店'
    },
    monthlyPercent() {
      if (!this.monthlyTarget || this.monthlyTarget <= 0) return 0
      return Math.min(Math.round((this.monthlyDone / this.monthlyTarget) * 100), 100)
    },
    daysLeft() {
      const now = new Date()
      const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate()
      return lastDay - now.getDate()
    },
    remainTarget() {
      const remain = Math.max(this.monthlyTarget - this.monthlyDone, 0)
      return remain.toLocaleString()
    },
    birthdayMonthData() {
      return this.birthdayAllData.filter(m => m.month === this.birthdayMonth)
    },
    birthdayDisplayList() {
      const list = this.birthdayMonthData
      if (this.selectedBirthdayDay != null) {
        return list.filter(m => m.day === this.selectedBirthdayDay)
      }
      return list
    },
    calendarDays() {
      const year = this.birthdayYear
      const month = this.birthdayMonth
      const firstWeekday = new Date(year, month - 1, 1).getDay()
      const daysInMonth = new Date(year, month, 0).getDate()
      const days = []
      for (let i = 0; i < firstWeekday; i++) {
        days.push({ day: null, members: [] })
      }
      for (let d = 1; d <= daysInMonth; d++) {
        const members = this.birthdayAllData.filter(m => m.month === month && m.day === d)
        days.push({ day: d, members })
      }
      while (days.length % 7 !== 0) days.push({ day: null, members: [] })
      return days
    },
    moduleDragOptions() {
      return {
        animation: 200,
        ghostClass: 'module-card--ghost',
        chosenClass: 'module-card--chosen',
        handle: '.module-card--draggable'
      }
    },
    storeTargetMonthValue() {
      const now = new Date()
      const next = new Date(now.getFullYear(), now.getMonth() + 1, 1)
      return `${next.getFullYear()}${String(next.getMonth() + 1).padStart(2, '0')}`
    },
    // 提醒中心入口数据（用于窄栏徽标统计）
    reminderEntries() {
      const today = new Date()
      const month = today.getMonth() + 1
      const day = today.getDate()
      const birthdayTodayCount = this.birthdayAllData.filter(m => m.month === month && m.day === day).length
      return [
        {
          key: 'todo',
          label: '我的待办',
          count: this.todoCountData.total,
          icon: 'el-icon-warning-outline'
        },
        {
          key: 'booking',
          label: '今日到店',
          count: this.todayBooking.length,
          icon: 'el-icon-date'
        },
        {
          key: 'birthday',
          label: '生日提醒',
          count: birthdayTodayCount,
          icon: 'el-icon-present'
        },
        {
          key: 'sleeping',
          label: '沉睡提醒',
          count: this.sleepingMembers.length,
          icon: 'el-icon-moon'
        }
      ]
    }
  },
  mounted() {
    document.addEventListener('fullscreenchange', this.onFullscreenChange)
    this.startClock()
    this.bootstrapDashboard()
    window.addEventListener('store_pc_bookings_updated', this.loadTodayBooking)
    window.addEventListener('store_pc_billing_updated', this.loadTodayBillingCount)
    window.addEventListener('store_pc_consume_updated', this.loadTodayConsumeCount)
    window.addEventListener('store_pc_refund_updated', this.loadTodayRefundCount)

    // 提醒中心默认展开/收起与上次状态（可配置）
    const savedOpen = localStorage.getItem('store_reminder_open')
    const savedType = localStorage.getItem('store_reminder_type')
    const validTypes = ['todo', 'booking', 'birthday', 'sleeping']
    if (savedType && validTypes.includes(savedType)) {
      this.currentReminderType = savedType
      this.todayTab = savedType
    }
    if (savedOpen !== null) {
      this.reminderCenterOpen = savedOpen === '1'
    } else {
      this.reminderCenterOpen = this.reminderDefaultOpen
    }
    this.$nextTick(() => {
      this.reminderFirstRenderDone = true
    })
    this.applyModuleOrderFromStorage()
  },
  beforeDestroy() {
    document.removeEventListener('fullscreenchange', this.onFullscreenChange)
    window.removeEventListener('store_pc_bookings_updated', this.loadTodayBooking)
    window.removeEventListener('store_pc_billing_updated', this.loadTodayBillingCount)
    window.removeEventListener('store_pc_consume_updated', this.loadTodayConsumeCount)
    window.removeEventListener('store_pc_refund_updated', this.loadTodayRefundCount)
    clearInterval(this.clockTimer)
  },
  methods: {
    startClock() {
      const fmt = () => {
        const now = new Date()
        const h = String(now.getHours()).padStart(2, '0')
        const m = String(now.getMinutes()).padStart(2, '0')
        const s = String(now.getSeconds()).padStart(2, '0')
        this.currentTime = `${h}:${m}:${s}`
      }
      fmt()
      this.clockTimer = setInterval(fmt, 1000)
    },
    resolveStoreId() {
      if (this.currentStoreId) return this.currentStoreId
      const info = this.$store.getters.storeInfo || {}
      if (info.storeId) return info.storeId
      const cached = localStorage.getItem('store_current_store_id')
      if (cached) return cached
      const user = this.$store.state.user || {}
      return user.mdid || ''
    },
    applyStoreContext(storeId, storeName) {
      if (!storeId) return
      this.currentStoreId = storeId
      const name = storeName || '当前门店'
      const exists = this.storeList.some(s => s.id === storeId)
      if (!exists) {
        this.storeList = [{ id: storeId, name, address: '' }]
      } else {
        this.storeList = this.storeList.map(s =>
          s.id === storeId ? { ...s, name: name || s.name } : s
        )
      }
      localStorage.setItem('store_current_store_id', storeId)
    },
    async ensureStoreContext() {
      let storeId = this.resolveStoreId()
      let storeName = (this.$store.getters.storeInfo || {}).storeName || ''
      if (!storeId) {
        try {
          const res = await getMyProfile()
          const profile = res.data || {}
          if (profile.mdid) {
            storeId = profile.mdid
            storeName = profile.storeName || storeName
            this.$store.commit('SET_STORE', {
              storeId: profile.mdid,
              storeName: profile.storeName || '当前门店'
            })
          }
        } catch (e) {
          // 错误提示由 request 拦截器处理
        }
      }
      if (storeId) {
        this.applyStoreContext(storeId, storeName)
      }
      return storeId
    },
    async bootstrapDashboard() {
      const storeId = await this.ensureStoreContext()
      if (!storeId) {
        this.$message.warning('未获取到门店信息，请重新登录')
        return
      }
      this.tryOpenConsumeFromPrefillOnce()
      this.reloadAllDashboardData()
    },
    reloadAllDashboardData() {
      this.loadDashboardOverview()
      this.loadTodayTuokeCount()
      this.loadTodayBooking()
      this.loadTodayBillingCount()
      this.loadTodayConsumeCount()
      this.loadTodayRefundCount()
      this.loadScheduleOnDutyCount()
      this.loadTodoList()
      this.loadTodoCount()
    },
    formatTodoDueLabel(dt) {
      return formatTodoDueLabelText(dt)
    },
    getStatisticsMonth() {
      const d = new Date()
      return `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, '0')}`
    },
    pickField(obj, ...keys) {
      if (!obj) return undefined
      for (let i = 0; i < keys.length; i++) {
        const k = keys[i]
        if (obj[k] !== undefined && obj[k] !== null) return obj[k]
      }
      return undefined
    },
    pickStoreRow(list, storeId) {
      if (!Array.isArray(list) || !storeId) return {}
      return list.find(x => this.pickField(x, 'storeId', 'StoreId') === storeId) || {}
    },
    formatMoney(val) {
      const n = Number(val) || 0
      return `¥${n.toLocaleString('zh-CN', { maximumFractionDigits: 0, minimumFractionDigits: 0 })}`
    },
    formatCount(val) {
      const n = Number(val) || 0
      return Math.round(n).toLocaleString('zh-CN')
    },
    patchOverviewStat(key, today, month) {
      const idx = this.overviewStats.findIndex(x => x.key === key)
      if (idx < 0) return
      const row = { ...this.overviewStats[idx], today, month }
      this.$set(this.overviewStats, idx, row)
    },
    async loadDashboardOverview() {
      const storeId = this.resolveStoreId()
      if (!storeId) return
      this.overviewLoading = true
      const today = this.todayLabel
      try {
        const [monthRes, dailyRes, todayRefundRes] = await Promise.all([
          getStoreDashboardStatistics({
            storeId,
            statisticsMonth: this.getStatisticsMonth()
          }),
          getStoreDailyStatistics({
            startTime: today,
            endTime: today,
            storeIds: [storeId]
          }),
          getStorePerformanceCompletion({
            startTime: today,
            endTime: today,
            storeIds: [storeId]
          })
        ])
        const monthData = monthRes.data || {}
        const dailyRow = this.pickStoreRow(dailyRes.data, storeId)
        const refundRow = this.pickStoreRow(todayRefundRes.data, storeId)

        const monthHead = this.pickField(monthData, 'headCount', 'HeadCount') || 0
        const monthPerson = this.pickField(monthData, 'personCount', 'PersonCount') || 0
        const monthProject = this.pickField(monthData, 'projectCount', 'ProjectCount') || 0
        const monthConsume = this.pickField(monthData, 'consumePerformance', 'ConsumePerformance') || 0
        const monthRefund = this.pickField(monthData, 'refundAmount', 'RefundAmount') || 0

        const todayHead = this.pickField(dailyRow, 'headCount', 'HeadCount') || 0
        const todayPerson = this.pickField(dailyRow, 'personCount', 'PersonCount') || 0
        const todayProject = this.pickField(dailyRow, 'projectCount', 'ProjectCount') || 0
        const todayConsume = this.pickField(dailyRow, 'consumePerformance', 'ConsumePerformance') || 0
        const todayRefund = this.pickField(refundRow, 'refundPerformance', 'RefundPerformance') || 0

        this.monthlyDone = Number(monthConsume) || 0
        this.monthlyTarget = Number(this.pickField(monthData, 'targetPerformance', 'TargetPerformance') || 0) || 0

        this.patchOverviewStat('headCount', this.formatCount(todayHead), this.formatCount(monthHead))
        this.patchOverviewStat('visitCount', this.formatCount(todayPerson), this.formatCount(monthPerson))
        this.patchOverviewStat('projectCount', this.formatCount(todayProject), this.formatCount(monthProject))
        this.patchOverviewStat('consumeAmount', this.formatMoney(todayConsume), this.formatMoney(monthConsume))
        this.patchOverviewStat('refundAmount', this.formatMoney(todayRefund), this.formatMoney(monthRefund))
      } catch (e) {
        // 错误提示由 request 拦截器处理
      } finally {
        this.overviewLoading = false
      }
    },
    updateModuleMetric(moduleKey, value) {
      const idx = this.modules.findIndex(m => m.key === moduleKey)
      if (idx >= 0) {
        this.$set(this.modules[idx], 'metricValue', value)
      }
    },
    /** 员工排班卡片：今日在岗健康师（门店启用人员 − 今日全天请假/休息） */
    async loadScheduleOnDutyCount() {
      const storeId = this.currentStoreId || (this.$store.getters.storeInfo || {}).storeId
      if (!storeId) {
        this.updateModuleMetric('schedule', 0)
        return
      }
      try {
        const res = await getStoreUserList({
          mdid: storeId,
          gw: '健康师',
          currentPage: 1,
          pageSize: 500
        })
        const list = (res.data?.list || []).filter(u => {
          if (!u || !u.id) return false
          const en = u.enabledMark
          return en === undefined || en === null || en === 1 || en === '1'
        })
        if (!list.length) {
          this.updateModuleMetric('schedule', 0)
          return
        }
        const empIds = new Set(list.map(u => u.id))
        const today = formatDateYMD(new Date())
        const month = today.slice(0, 7)
        const offDutyIds = new Set()
        try {
          const attRes = await getAttendanceMonthReport({
            Month: month,
            currentPage: 1,
            pageSize: 1000
          })
          ;(attRes.data?.list || []).forEach(emp => {
            if (!emp || !emp.userId || !empIds.has(emp.userId)) return
            if (emp.storeId && emp.storeId !== storeId) return
            const day = (emp.dayRecords || []).find(d => d && d.date === today)
            if (!day) return
            const st = mapAttendanceDayToScheduleStatus(day)
            if (st.type === 'leave' || st.type === 'vacation') {
              offDutyIds.add(emp.userId)
            }
          })
        } catch (e) {
          /* 考勤未接入时仅统计门店健康师人数 */
        }
        const onDuty = list.filter(u => !offDutyIds.has(u.id)).length
        this.updateModuleMetric('schedule', onDuty)
      } catch (e) {
        this.updateModuleMetric('schedule', 0)
      }
    },
    async loadTodayBooking() {
      const storeId = this.currentStoreId || (this.$store.getters.storeInfo || {}).storeId
      if (!storeId) return
      const now = new Date()
      const dayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0)
      const dayEnd = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59, 999)
      try {
        const res = await getYyjlList({
          djmd: storeId,
          currentPage: 1,
          pageSize: 200,
          sort: 'asc',
          yysj: buildYysjTimestampRange(dayStart, dayEnd)
        })
        const rows = (res.data?.list || []).map(mapYyjlListRow)
        this.todayBooking = rows
          .filter(r => r.status !== 'cancelled')
          .map(r => ({
            id: r.id,
            time: r.startTime || '',
            date: r.date,
            timeRange: r.timeRange || `${r.startTime}-${r.endTime}`,
            name: r.memberName,
            mobile: r.mobile || '',
            project: r.project,
            staffName: r.staffName,
            status: r.status,
            statusText: r.fStatus || r.status,
            fStatus: r.fStatus,
            memberId: r.memberId
          }))
        this.updateModuleMetric('booking', this.todayBooking.length)
      } catch (e) {
        this.todayBooking = []
        this.updateModuleMetric('booking', 0)
      }
    },
    async loadTodayTuokeCount() {
      const storeId = this.currentStoreId || (this.$store.getters.storeInfo || {}).storeId
      if (!storeId) return
      const start = new Date()
      start.setHours(0, 0, 0, 0)
      const end = new Date()
      end.setHours(23, 59, 59, 999)
      try {
        const res = await getTkjlbList({
          currentPage: 1,
          pageSize: 1,
          sort: 'desc',
          storeId,
          expansionTime: `${start.getTime()},${end.getTime()}`
        })
        const count = res.data?.pagination?.total || 0
        this.updateModuleMetric('tuoke', count)
      } catch (e) {
        this.updateModuleMetric('tuoke', 0)
      }
    },
    /** 开单管理卡片：今日本店有效开单数 */
    async loadTodayBillingCount() {
      const storeId = this.currentStoreId || (this.$store.getters.storeInfo || {}).storeId
      if (!storeId) {
        this.updateModuleMetric('order', 0)
        return
      }
      const now = new Date()
      const dayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0)
      const dayEnd = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59, 999)
      const kdrq = buildBillingKdrqRange([dayStart.getTime(), dayEnd.getTime()])
      try {
        const res = await getKdKdjlbList({
          currentPage: 1,
          pageSize: 1,
          sort: 'desc',
          djmd: storeId,
          kdrq,
          isEffective: 1
        })
        const count = res.data?.pagination?.total || 0
        this.updateModuleMetric('order', count)
      } catch (e) {
        this.updateModuleMetric('order', 0)
      }
    },
    /** 消耗管理卡片：今日本店有效耗卡数 */
    async loadTodayConsumeCount() {
      const storeId = this.currentStoreId || (this.$store.getters.storeInfo || {}).storeId
      if (!storeId) {
        this.updateModuleMetric('consume', 0)
        return
      }
      const now = new Date()
      const dayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0)
      const dayEnd = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59, 999)
      const hksj = buildHksjRange([dayStart.getTime(), dayEnd.getTime()])
      try {
        const res = await getXhHyhkList({
          currentPage: 1,
          pageSize: 1,
          sort: 'desc',
          md: storeId,
          hksj,
          isEffective: 1
        })
        const count = res.data?.pagination?.total || 0
        this.updateModuleMetric('consume', count)
      } catch (e) {
        this.updateModuleMetric('consume', 0)
      }
    },
    /** 退卡管理卡片：今日本店有效退卡数 */
    async loadTodayRefundCount() {
      const storeId = this.currentStoreId || (this.$store.getters.storeInfo || {}).storeId
      if (!storeId) {
        this.updateModuleMetric('refund', 0)
        return
      }
      const now = new Date()
      const dayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0)
      const dayEnd = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59, 999)
      const tksj = buildTksjRange([dayStart.getTime(), dayEnd.getTime()])
      try {
        const res = await getHytkHytkList({
          currentPage: 1,
          pageSize: 1,
          sort: 'desc',
          md: storeId,
          tksj,
          isEffective: 1
        })
        const count = res.data?.pagination?.total || 0
        this.updateModuleMetric('refund', count)
      } catch (e) {
        this.updateModuleMetric('refund', 0)
      }
    },
    tryOpenConsumeFromPrefillOnce() {
      const key = 'store_pc_consume_prefill_once'
      let raw = null
      try {
        raw = localStorage.getItem(key)
      } catch (e) {
        raw = null
      }
      if (!raw) return
      try {
        const obj = JSON.parse(raw)
        if (!obj || typeof obj !== 'object') return
        this.consumePrefill = obj
        this.$nextTick(() => {
          this.consumeDialogVisible = true
        })
      } catch (e) {
        // ignore
      } finally {
        try { localStorage.removeItem(key) } catch (e) {}
      }
    },
    toggleFullscreen() {
      if (!document.fullscreenElement) {
        document.documentElement.requestFullscreen().catch(() => { })
      } else {
        document.exitFullscreen().catch(() => { })
      }
    },
    onFullscreenChange() {
      this.isFullscreen = !!document.fullscreenElement
    },
    applyModuleOrderFromStorage() {
      try {
        const cached = window.localStorage.getItem(this.moduleOrderStorageKey)
        if (!cached) return
        const orderKeys = JSON.parse(cached)
        if (!Array.isArray(orderKeys) || !orderKeys.length) return

        const map = this.modules.reduce((acc, item) => {
          acc[item.key] = item
          return acc
        }, {})

        const ordered = []
        orderKeys.forEach(key => {
          if (map[key]) {
            ordered.push(map[key])
            delete map[key]
          }
        })

        Object.keys(map).forEach(key => {
          ordered.push(map[key])
        })

        this.modules = ordered
      } catch (e) {
        // ignore parse errors
      }
    },
    onModuleDragEnd() {
      const orderKeys = this.modules.map(item => item.key)
      window.localStorage.setItem(this.moduleOrderStorageKey, JSON.stringify(orderKeys))
    },
    handleUserCommand(cmd) {
      if (cmd === 'store') {
        this.storeSwitchDialogVisible = true
      } else if (cmd === 'logout') {
        this.$confirm('确定要退出登录吗？', '退出确认', {
          confirmButtonText: '退出',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.$store.commit('LOGOUT')
          this.$router.push('/login')
        }).catch(() => { })
      } else if (cmd === 'profile') {
        this.$message.info('个人信息功能开发中')
      } else if (cmd === 'password') {
        this.$message.info('修改密码功能开发中')
      }
    },
    handleModulePrimary(module) {
      if (module.key === 'tuoke') {
        this.tuokeDialogVisible = true
        return
      }
      if (module.key === 'booking') {
        this.bookingConsumeDialogVisible = true
        return
      }
      if (module.key === 'order') {
        this.billingPrefill = {}
        this.billingDialogVisible = true
        return
      }
      if (module.key === 'consume') {
        this.consumePrefill = {}
        this.consumeDialogVisible = true
        return
      }
      if (module.key === 'refund') {
        this.refundPrefill = {}
        this.refundDialogVisible = true
        return
      }
      if (module.key === 'schedule') {
        this.$store.commit('SET_SCHEDULE_DIALOG', true)
        return
      }
      if (module.key === 'goldTriangle') {
        this.goldTriangleDialogVisible = true
        return
      }
      if (module.key === 'storeTarget') {
        this.storeTargetDialogVisible = true
        return
      }
    },
    handleReminderClick(action) {
      if (action === 'goldTriangle') {
        this.goldTriangleDialogVisible = true
      } else if (action === 'storeTarget') {
        this.storeTargetDialogVisible = true
      }
    },
    async searchMembersByKeyword(keyword) {
      const kw = (keyword || '').trim()
      if (!kw) return []
      try {
        const res = await getKhxxList({
          currentPage: 1,
          pageSize: 20,
          keyWord: kw
        })
        const list = res.data?.list || []
        return list.map(mapKhxxListToSuggestion)
      } catch (e) {
        return []
      }
    },
    fetchMemberSuggestions(queryString, cb) {
      const keyword = (queryString || '').trim()
      if (this.memberSuggestTimer) clearTimeout(this.memberSuggestTimer)
      if (!keyword) {
        cb([])
        return
      }
      this.memberSuggestTimer = setTimeout(async () => {
        const list = await this.searchMembersByKeyword(keyword)
        cb(list)
      }, 300)
    },
    openMemberProfile(item) {
      if (!item || !item.id) return
      this.activeMember = {
        id: item.id,
        khmc: item.khmc || '',
        sjh: item.sjh || '',
        dah: item.dah || ''
      }
      this.memberDialogVisible = true
      this.memberKeyword = ''
    },
    handleMemberSelect(item) {
      this.openMemberProfile(item)
    },
    async handleFirstMatchOrFocus() {
      const keyword = (this.memberKeyword || '').trim()
      if (!keyword) return
      const list = await this.searchMembersByKeyword(keyword)
      if (list.length === 1) {
        this.openMemberProfile(list[0])
      } else if (list.length > 1) {
        this.$message.info('请从下拉列表中选择会员')
      } else {
        this.$message.warning('未找到匹配的会员')
      }
    },
    async handleMemberSearch() {
      const keyword = (this.memberKeyword || '').trim()
      if (!keyword) return
      const list = await this.searchMembersByKeyword(keyword)
      if (list.length === 1) {
        this.openMemberProfile(list[0])
      } else if (list.length > 1) {
        this.$message.info('匹配到多位会员，请从下拉列表中选择')
      } else {
        this.$message.warning('未找到匹配的会员')
      }
    },
    handleMemberAction(payload) {
      if (!payload || !payload.type) return
      const { type } = payload
      if (type === 'invite') {
        this.activeTodoId = ''
        if (this.activeMember) {
          this.currentContactCustomer = {
            id: this.activeMember.id || '',
            name: this.activeMember.khmc || '',
            phone: this.activeMember.sjh || ''
          }
        } else {
          this.currentContactCustomer = {}
        }
        this.contactDialogVisible = true
        return
      }
      if (!this.activeMember) return
      const memberId = this.activeMember.id || ''
      const memberName = this.activeMember.khmc || ''
      const mobile = this.activeMember.sjh || ''
      if (type === 'refund') {
        this.refundPrefill = { memberId, memberName, mobile }
        this.refundDialogVisible = true
        return
      }
      if (type === 'billing') {
        this.billingPrefill = { memberId, memberName, name: memberName, mobile }
        this.billingDialogVisible = true
        return
      }
      if (type === 'consume') {
        this.consumePrefill = { memberId, memberName, mobile, phone: mobile }
        this.consumeDialogVisible = true
        return
      }
      if (type === 'booking') {
        this.bookingPrefill = { name: memberName, phone: mobile }
        this.bookingDialogVisible = true
      }
    },
    handleQuickBooking(item) {
      this.bookingPrefill = {
        name: item.name,
        phone: item.mobile
      }
      this.bookingDialogVisible = true
    },
    handlePreConsumeBookingSaved() {
      this.bookingConsumeDialogVisible = false
      this.loadTodayBooking()
      this.$message.success('预约已保存')
    },
    handleBookingConvertConsume(payload) {
      if (!payload) return
      this.consumePrefill = {
        appointmentId: payload.appointmentId,
        memberId: payload.memberId,
        name: payload.memberName
      }
      this.consumeDialogVisible = true
    },
    handleQuickBilling(item) {
      this.billingPrefill = {
        name: item.name,
        memberId: item.memberId || '',
        memberName: item.name,
        mobile: item.mobile,
        appointmentId: item.id || '',
        fromBooking: true,
        bookingProject: item.project,
        bookingDate: item.date,
        bookingTimeRange: item.timeRange,
        bookingStaff: item.staffName
      }
      this.billingDialogVisible = true
    },
    handleStoreSwitch(store) {
      if (store.id === this.currentStoreId) {
        this.storeSwitchDialogVisible = false
        return
      }
      this.currentStoreId = store.id
      localStorage.setItem('store_current_store_id', store.id)
      this.$store.commit('SET_STORE', {
        storeId: store.id,
        storeName: store.name
      })
      this.storeSwitchDialogVisible = false
      this.$message.success(`已切换到 ${store.name}`)
      this.reloadAllDashboardData()
    },
    handleBirthdayCall(item) {
      this.$message.success(`已为 ${item.name} 发送生日祝福短信`)
    },
    handleSleepingCall(item) {
      this.activeTodoId = ''
      this.currentContactCustomer = {
        id: item.id || '',
        name: item.name || '',
        phone: item.phone || ''
      }
      this.contactDialogVisible = true
    },
    handleContactCancel() {
      this.activeTodoId = ''
    },
    handleContactSuccess() {
      const todoId = this.activeTodoId
      this.activeTodoId = ''
      const afterRefresh = () => {
        this.loadTodoList()
        this.loadTodoCount()
      }
      if (todoId) {
        request({
          url: '/api/Extend/LqTodo/Handle/' + todoId,
          method: 'POST'
        }).then(() => {
          this.$message.success('沟通记录已添加，待办已完成')
          afterRefresh()
        }).catch(() => {
          this.$message.success('沟通记录已添加')
          afterRefresh()
        })
      } else {
        this.$message.success('沟通记录已添加')
        afterRefresh()
      }
    },
    handleCancelBooking(item) {
      if (!item || !item.id) return
      this.$confirm(`确定要取消「${item.name}」在 ${item.date} ${item.timeRange} 的预约吗？`, '取消预约确认', {
        confirmButtonText: '确定',
        cancelButtonText: '再想想',
        type: 'warning'
      }).then(async () => {
        await cancelYyjl(item.id, '')
        this.$message.success('预约已取消')
        this.loadTodayBooking()
      }).catch(() => {})
    },
    handleConfirmConsume(item) {
      if (!item || !item.id) return
      this.$confirm(`确认为「${item.name}」开始服务吗？`, '开始服务', {
        confirmButtonText: '确定',
        cancelButtonText: '再想想',
        type: 'info'
      }).then(async () => {
        await startYyjlService(item.id)
        this.$message.success('已开始服务')
        this.loadTodayBooking()
      }).catch(() => {})
    },
    handleTodoClick(item) {
      if (!item) return
      const handleType = item.handleType || 'dialog'
      const handlePath = item.handlePath || ''
      let params = {}
      try {
        params = item.handleParam ? JSON.parse(item.handleParam) : {}
      } catch (e) {
        params = {}
      }

      if (handleType === 'dialog') {
        if (handlePath === 'contactDialog') {
          this.activeTodoId = item.id || ''
          this.currentContactCustomer = {
            id: params.customerId || '',
            name: params.customerName || '',
            phone: params.customerPhone || params.phone || ''
          }
          this.contactDialogVisible = true
          return
        }
        if (handlePath === 'goldTriangleDialog') {
          this.goldTriangleDialogVisible = true
          return
        }
        if (handlePath === 'storeTargetDialog') {
          this.storeTargetDialogVisible = true
          return
        }
      } else if (handleType === 'page') {
        this.$router.push({ path: handlePath, query: params })
        return
      }
      // 无明确处理入口时再标记完成（避免点击跟进待办即消失）
      this.handleTodoDone(item)
    },
    loadTodoList() {
      this.todoLoading = true
      const params = {
        currentPage: 1,
        pageSize: 50,
        status: 0
      }
      if (this.todoSourceFilter) {
        params.source = this.todoSourceFilter
      }
      request({
        url: '/api/Extend/LqTodo/MyTodoList',
        method: 'GET',
        data: params
      }).then(res => {
        const data = res.data || {}
        const list = data.list || data.List || []
        this.todoList = list.map(item => ({
          ...item,
          key: item.id
        }))
        const pagination = data.pagination || data.Pagination || {}
        this.todoTotal = pagination.total != null ? pagination.total : list.length
        this.todoLoading = false
      }).catch(() => {
        this.todoList = []
        this.todoTotal = 0
        this.todoLoading = false
      })
    },
    loadTodoCount() {
      request({
        url: '/api/Extend/LqTodo/TodoCount',
        method: 'GET'
      }).then(res => {
        this.todoCountData = res.data || { total: 0, followUp: 0, approval: 0, system: 0 }
      })
    },
    handleTodoDone(item) {
      request({
        url: '/api/Extend/LqTodo/Handle/' + item.id,
        method: 'POST'
      }).then(() => {
        this.$message.success('已处理')
        this.loadTodoList()
        this.loadTodoCount()
      })
    },
    handleTodoDismiss(item) {
      request({
        url: '/api/Extend/LqTodo/Dismiss/' + item.id,
        method: 'POST'
      }).then(() => {
        this.$message.success('已忽略')
        this.loadTodoList()
        this.loadTodoCount()
      })
    },
    selectBirthdayDay(day) {
      this.selectedBirthdayDay = this.selectedBirthdayDay === day ? null : day
    },
    prevBirthdayMonth() {
      this.selectedBirthdayDay = null
      if (this.birthdayMonth === 1) {
        this.birthdayMonth = 12
        this.birthdayYear--
      } else {
        this.birthdayMonth--
      }
    },
    nextBirthdayMonth() {
      this.selectedBirthdayDay = null
      if (this.birthdayMonth === 12) {
        this.birthdayMonth = 1
        this.birthdayYear++
      } else {
        this.birthdayMonth++
      }
    },
    levelDotColor(level) {
      const map = { 'A++': '#ef4444', 'A+': '#f59e0b', 'A': '#d97706', 'B': '#22c55e', 'C': '#3b82f6', 'D': '#94a3b8' }
      return map[level] || '#94a3b8'
    },
    levelTagStyle(level) {
      const map = {
        'A++': 'background: linear-gradient(135deg, #ef4444, #dc2626); color: #fff;',
        'A+': 'background: linear-gradient(135deg, #f59e0b, #d97706); color: #fff;',
        'A': 'background: rgba(245,158,11,0.12); color: #d97706; border: 1px solid rgba(245,158,11,0.25);',
        'B': 'background: rgba(34,197,94,0.12); color: #16a34a; border: 1px solid rgba(34,197,94,0.25);',
        'C': 'background: rgba(59,130,246,0.12); color: #2563eb; border: 1px solid rgba(59,130,246,0.25);',
        'D': 'background: #e5e7eb; color: #6b7280;'
      }
      return map[level] || map['D']
    },
    handleModuleCardClick(ev, module) {
      const target = ev && ev.target
      if (target && target.closest && target.closest('.primary-action')) {
        this.handleModulePrimary(module)
      } else {
        this.handleModuleSecondary(module)
      }
    },
    handleModuleSecondary(module) {
      if (module.key === 'goldTriangle') {
        this.goldTriangleDialogVisible = true
        return
      }
      if (module.key === 'schedule') {
        this.$store.commit('SET_SCHEDULE_DIALOG', true)
        return
      }
      const map = {
        tuoke: 'tuokeListVisible',
        booking: 'bookingCalendarVisible',
        order: 'billingListVisible',
        consume: 'consumeListVisible',
        refund: 'refundListVisible'
      }
      const key = map[module.key]
      if (key) this[key] = true
    },
    // 提醒中心侧栏：入口点击
    handleReminderEntryClick(type) {
      if (this.reminderCenterOpen && this.currentReminderType === type) {
        this.reminderCenterOpen = false
        localStorage.setItem('store_reminder_open', '0')
        return
      }
      this.currentReminderType = type
      this.todayTab = type
      this.reminderCenterOpen = true
      localStorage.setItem('store_reminder_open', '1')
      localStorage.setItem('store_reminder_type', this.currentReminderType)
    },
    // 提醒中心侧栏：面板显隐
    toggleReminderCenter(open) {
      this.reminderCenterOpen = open
      localStorage.setItem('store_reminder_open', open ? '1' : '0')
    },
    // 提醒中心侧栏：Tab 切换时同步当前类型
    handleTodayTabClick(tab) {
      this.currentReminderType = tab.name
      localStorage.setItem('store_reminder_type', this.currentReminderType)
    }
  }
}
</script>

<style lang="scss" scoped>
.dashboard-page {
  height: 100%;
  padding: 24px 20px 24px 28px;
  background: radial-gradient(circle at 10% 20%, #eef2ff 0, #eef2ff 26%, #fdf2ff 60%, #fff7ed 100%);
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative;
}

.top-bar-right {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

/* 顶部我的待办样式已移动到右侧工具栏 */

.top-bar {
  display: grid;
  grid-template-columns: minmax(200px, 1fr) minmax(360px, 520px) auto;
  align-items: center;
  gap: 20px;
  margin-bottom: 24px;
}

.member-search {
  flex: 1;
  min-width: 200px;
  max-width: 420px;
}

.calendar-entry {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  border-radius: 999px;
  background: linear-gradient(135deg, #e0f2fe, #ddd6fe);
  border: 1px solid rgba(129, 140, 248, 0.55);
  color: #1d4ed8;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(79, 70, 229, 0.28);
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}

.calendar-entry-icon {
  font-size: 16px;
}

.calendar-entry-text {
  white-space: nowrap;
}

.calendar-entry:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 20px rgba(79, 70, 229, 0.35);
}

@media (max-width: 1024px) {
  .top-bar-right {
    flex-wrap: wrap;
  }
}

.store-info {
  .store-name {
    font-size: 22px;
    font-weight: 600;
    color: #111827;
    letter-spacing: 0.5px;
  }

  .store-subtitle {
    margin-top: 4px;
    font-size: 14px;
    color: #5b6b7a;

    .schedule-link {
      margin-left: 12px;
      color: #6366f1;
      cursor: pointer;
      font-weight: 500;

      &:hover {
        text-decoration: underline;
      }
    }
  }
}

/* 会员搜索下拉项 */
.member-suggestion {
  padding: 2px 0;
}

.suggestion-main {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.suggestion-name {
  font-size: 14px;
  font-weight: 600;
  color: #111827;
}

.suggestion-level {
  font-size: 11px;
  padding: 1px 8px;
  border-radius: 999px;
  font-weight: 600;
  flex-shrink: 0;
}

.suggestion-level.level--aplusplus {
  background: linear-gradient(135deg, #ef4444, #dc2626);
  color: #fff;
}

.suggestion-level.level--aplus {
  background: linear-gradient(135deg, #f59e0b, #d97706);
  color: #fff;
}

.suggestion-level.level--a {
  background: rgba(245, 158, 11, 0.12);
  color: #d97706;
  border: 1px solid rgba(245, 158, 11, 0.25);
}

.suggestion-level.level--b {
  background: rgba(34, 197, 94, 0.12);
  color: #16a34a;
  border: 1px solid rgba(34, 197, 94, 0.25);
}

.suggestion-level.level--c {
  background: rgba(59, 130, 246, 0.12);
  color: #2563eb;
  border: 1px solid rgba(59, 130, 246, 0.25);
}

.suggestion-level.level--d {
  background: #e5e7eb;
  color: #6b7280;
}

.suggestion-level.level--default {
  background: #e5e7eb;
  color: #6b7280;
}

.suggestion-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 12px;
  color: #64748b;
}

.suggestion-meta span {
  display: flex;
  align-items: center;
  gap: 4px;
}

.suggestion-meta i {
  font-size: 12px;
  color: #94a3b8;
}

.suggestion-extra {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px dashed #e2e8f0;
  font-size: 11px;
  color: #94a3b8;
}

.suggestion-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 2px;
}

.suggestion-row b {
  color: #6366f1;
  font-weight: 600;
}

.suggestion-sleep {
  color: #f97316;
  font-weight: 500;
}

.member-search-input {
  width: 100%;

  ::v-deep .el-input__inner {
    border-radius: 999px;
    padding-left: 40px;
    height: 40px;
    line-height: 40px;
    font-size: 14px;
  }
}

.top-meta {
  display: flex;
  align-items: center;
  gap: 12px;
  justify-content: flex-end;
}

.today-text {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.4;
}

.today-date {
  font-size: 12px;
  color: #9ca3af;
}

.today-clock {
  font-size: 18px;
  font-weight: 600;
  color: #1e293b;
  letter-spacing: 1px;
  font-variant-numeric: tabular-nums;
}

.top-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.action-btn {
  width: 34px;
  height: 34px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  background: rgba(241, 245, 249, 0.9);
  border: 1px solid rgba(226, 232, 240, 0.8);
  color: #64748b;
  font-size: 16px;
  transition: all 0.2s ease;

  &:hover {
    background: rgba(99, 102, 241, 0.08);
    border-color: rgba(99, 102, 241, 0.25);
    color: #4f46e5;
  }
}

.user-info {
  display: flex;
  align-items: center;
  gap: 8px;
}

.user-info--clickable {
  cursor: pointer;
  padding: 4px 10px 4px 4px;
  border-radius: 999px;
  border: 1px solid rgba(226, 232, 240, 0.8);
  background: rgba(241, 245, 249, 0.9);
  transition: all 0.2s ease;

  &:hover {
    background: rgba(99, 102, 241, 0.06);
    border-color: rgba(99, 102, 241, 0.2);
  }
}

.user-avatar {
  width: 36px;
  height: 36px;
  border-radius: 999px;
  background: linear-gradient(135deg, #6366f1, #22c55e);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  font-weight: 600;
  flex-shrink: 0;
}

.user-name {
  font-size: 14px;
  color: #374151;
  font-weight: 500;
}

.user-arrow {
  font-size: 12px;
  color: #94a3b8;
  margin-left: 2px;
  transition: transform 0.2s;
}

/* 下拉菜单全局样式（非 scoped，用 ::v-deep 穿透） */
::v-deep .user-dropdown-menu {
  padding: 6px 0;
  border-radius: 14px !important;
  border: 1px solid rgba(226, 232, 240, 0.9) !important;
  box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12), 0 0 0 0.5px rgba(148, 163, 184, 0.2) !important;
  min-width: 180px;
  overflow: hidden;
}

::v-deep .user-dropdown-menu .el-dropdown-menu__item {
  font-size: 14px;
  color: #374151;
  padding: 9px 18px;
  display: flex;
  align-items: center;
  gap: 8px;
  line-height: 1.4;

  &:hover {
    background: rgba(99, 102, 241, 0.06);
    color: #4f46e5;
  }

  i {
    font-size: 15px;
  }
}

::v-deep .user-dropdown-menu .dropdown-item--danger {
  color: #ef4444 !important;

  &:hover {
    background: rgba(239, 68, 68, 0.06) !important;
    color: #dc2626 !important;
  }
}

::v-deep .user-dropdown-menu .el-dropdown-menu__item--divided {
  border-top: 1px solid #f1f5f9;
  margin-top: 4px;
  padding-top: 9px;
}

.dropdown-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 16px 18px 12px;
  border-bottom: 1px solid #f1f5f9;
  margin-bottom: 4px;
}

.dropdown-avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: linear-gradient(135deg, #6366f1, #22c55e);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  font-weight: 600;
  margin-bottom: 8px;
}

.dropdown-name {
  font-size: 15px;
  font-weight: 600;
  color: #0f172a;
  margin-bottom: 2px;
}

.dropdown-role {
  font-size: 12px;
  color: #94a3b8;
}

.layout-grid {
  display: grid;
  /* 收起时：主内容更宽，右侧只保留竖向按钮条宽度（约 88px + 间距） */
  grid-template-columns: minmax(0, 1fr) 108px;
  gap: 20px;
  flex: 1;
  min-height: 0;
  align-items: stretch;
  transition: grid-template-columns 0.25s ease-out;
}

.layout-grid--reminder-open {
  /* 展开时：主内容略窄，为竖向条 + 面板预留宽度 */
  grid-template-columns: minmax(0, 1fr) 520px;
}

.left-column {
  display: flex;
  flex-direction: column;
  gap: 20px;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(148, 163, 184, 0.3) transparent;

  &::-webkit-scrollbar {
    width: 4px;
  }

  &::-webkit-scrollbar-thumb {
    background: rgba(148, 163, 184, 0.3);
    border-radius: 2px;
  }
}

.modules-grid {
  margin-top: 4px;
}

.modules-grid .el-col {
  margin-bottom: 18px;
}

.overview-row {
  .overview-card {
    border-radius: 16px;
    border: none;
    background: #ffffff;
    box-shadow: 0 8px 20px rgba(15, 23, 42, 0.06);
  }
}

.overview-row-inner {
  display: flex;
}

.overview-row-inner > .el-col {
  flex: 1 1 0;
  max-width: none;
}

.overview-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;

  .label {
    font-size: 14px;
    color: #6b7280;
  }

  .tag {
    font-size: 12px;
    padding: 2px 8px;
    border-radius: 999px;
    background: #eff6ff;
    color: #2563eb;
  }
}

.overview-value {
  font-size: 18px;
  font-weight: 600;
  color: #111827;
  display: flex;
  align-items: baseline;
  gap: 4px;
}

.overview-sub {
  margin-top: 4px;
  font-size: 13px;
  color: #9ca3af;
  display: flex;
  align-items: baseline;
  gap: 4px;
}

.overview-card-inner {
  display: flex;
  flex-direction: column;
  row-gap: 6px;
}

.overview-main {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.overview-main-value {
  font-size: 26px;
  font-weight: 700;
  color: #0f172a;
}

.overview-secondary {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 13px;
  color: #6b7280;
}

.overview-secondary-label {
  padding: 0 6px;
  border-radius: 999px;
  background: #f3f4f6;
  font-size: 11px;
}

.overview-secondary-value {
  font-size: 14px;
  font-weight: 500;
  color: #374151;
}

/* 顶部统计：不同指标的内部色彩区分（保持白底统一） */
.overview-card--headCount {
  .overview-main-value {
    color: #1d4ed8;
  }
}

.overview-card--visitCount {
  .overview-main-value {
    color: #4f46e5;
  }
}

.overview-card--projectCount {
  .overview-main-value {
    color: #be185d;
  }
}

.overview-card--consumeAmount {
  .overview-main-value {
    color: #047857;
  }
}

.overview-card--refundAmount {
  .overview-main-value {
    color: #c2410c;
  }
}

.modules-grid .module-card {
  border-radius: 18px;
  border: none;
  box-shadow: 0 10px 28px rgba(15, 23, 42, 0.08);
  cursor: pointer;
  transition: transform 0.15s ease-out, box-shadow 0.15s ease-out;
}

.modules-grid .module-card ::v-deep .el-card__body {
  height: 132px;
  min-height: 132px;
  max-height: 132px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.module-actions-spacer {
  flex: 1;
  min-height: 2px;
}

.modules-grid .module-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 16px 36px rgba(15, 23, 42, 0.12);
}

.module-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 4px;
  flex-shrink: 0;
}

.module-title-wrap {
  .module-title {
    font-size: 15px;
    font-weight: 600;
    color: #111827;
  }

  .module-subtitle {
    margin-top: 1px;
    font-size: 11px;
    color: #6b7280;
  }
}

.module-icon {
  width: 32px;
  height: 32px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;

  i {
    font-size: 18px;
  }
}

.module-meta {
  margin-top: 2px;
  flex-shrink: 0;

  .meta-value {
    font-size: 16px;
    font-weight: 600;
    color: #111827;
    line-height: 1.2;
  }

  .meta-label {
    margin-top: 1px;
    font-size: 10px;
    color: #9ca3af;
  }
}

.module-actions {
  margin-top: 4px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  flex-shrink: 0;

  .primary-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 88px;
    height: 28px;
    padding: 0 12px;
    font-size: 13px;
    border: none;
    border-radius: 999px;
    background: #2563eb;
    color: #ffffff;
    font-size: 14px;
    font-weight: 500;
    box-shadow: 0 4px 10px rgba(37, 99, 235, 0.35);
    cursor: pointer;
    transition: background 0.15s, box-shadow 0.15s;

    &:hover {
      background: #1d4ed8;
      box-shadow: 0 4px 12px rgba(37, 99, 235, 0.45);
    }
  }

  .tertiary-action {
    font-size: 13px;
    color: #2563eb;
    cursor: pointer;
    font-weight: 500;
    transition: color 0.15s;

    &:hover {
      color: #1d4ed8;
      text-decoration: underline;
    }
  }

  .secondary-text {
    font-size: 13px;
    color: #9ca3af;
    cursor: pointer;
    transition: color 0.15s;
    margin-left: auto;

    &:hover {
      color: #2563eb;
    }
  }
}

/* 提醒中心侧栏 - 容器 */
.reminder-center {
  position: relative;
  display: flex;
  flex-direction: row-reverse;
  align-items: stretch;
}

/* 提醒中心侧栏 - 窄栏入口 */
.reminder-center-toggle {
  width: 88px;
  background: #ffffff;
  border-radius: 18px;
  box-shadow: 0 10px 28px rgba(15, 23, 42, 0.18);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  padding: 10px 4px;
  gap: 6px;
  pointer-events: auto;
  /* 固定宽度，避免在列宽动画时被压缩 */
  flex: 0 0 88px;
  position: relative;
  z-index: 2;
  /* 高度跟随列一起拉满 */
  height: 100%;
}

/* 我的待办入口样式复用提醒入口，无需额外样式 */

.reminder-toggle-item {
  width: 100%;
  border-radius: 12px;
  padding: 8px 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  cursor: pointer;
  transition: background 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.reminder-toggle-item .label-text {
  font-size: 12px;
  color: #4b5563;
  letter-spacing: 0.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: center;
  width: 100%;
}

.entry-icon-wrap {
  width: 40px;
  height: 40px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #e5edff, #e0f2fe);
  box-shadow: 0 6px 14px rgba(15, 23, 42, 0.2);
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}

.entry-icon-wrap .entry-icon {
  font-size: 18px;
  color: #ffffff;
}

/* 提醒中心入口样式：不同类型入口渐变色 */
.entry-icon-wrap--invite {
  background: linear-gradient(135deg, #0ea5e9, #22c55e);
}

.entry-icon-wrap--booking {
  background: linear-gradient(135deg, #f97316, #facc15);
}

.entry-icon-wrap--birthday {
  background: linear-gradient(135deg, #ec4899, #8b5cf6);
}

.entry-icon-wrap--sleeping {
  background: linear-gradient(135deg, #6366f1, #0ea5e9);
}

/* 我的待办图标底色：橙粉渐变，区分其他入口 */
.entry-icon-wrap--todo {
  background: linear-gradient(135deg, #f97316, #ec4899);
}

.reminder-badge {
  display: inline-block;
}

.reminder-toggle-item .reminder-badge {
  /* 提醒中心入口样式：数字角标位置微调贴近图标右上角 */
  ::v-deep .el-badge__content {
    background-color: #ef4444;
    border: none;
    box-shadow: 0 0 0 1px #fee2e2;
    right: 2px;
    top: 2px;
    padding: 0 4px;
    height: 16px;
    line-height: 16px;
    font-size: 11px;
  }
}

.entry-icon {
  flex-shrink: 0;
}

.reminder-toggle-item.is-active {
  background: linear-gradient(180deg, rgba(59, 130, 246, 0.06), rgba(59, 130, 246, 0.10));
}

.reminder-toggle-item.is-active .label-text {
  color: #1d4ed8;
  font-weight: 600;
}

.reminder-toggle-item.is-active .entry-icon-wrap {
  /* 点击后仅轻微高亮，不再增加额外阴影 */
  box-shadow: 0 6px 14px rgba(37, 99, 235, 0.35);
}

.reminder-toggle-close {
  margin-top: 4px;
  width: 26px;
  height: 26px;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.04);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: #6b7280;
  transition: background 0.15s ease, color 0.15s ease;
}

.reminder-toggle-close:hover {
  background: rgba(59, 130, 246, 0.16);
  color: #1d4ed8;
}

/* 提醒中心侧栏 - 主体卡片（右侧有间距滑出） */
.reminder-center-panel {
  width: 400px;
  /* 与右侧竖向按钮条留出间距 */
  margin-right: 20px;
  pointer-events: auto;
  display: flex;
  /* 固定宽度，由外层 grid 列宽承担动画 */
  flex: 0 0 400px;
  position: relative;
  z-index: 1;
}

/* 提醒面板布局：独立四角圆角卡片 */
.reminder-center-panel .today-card {
  border-radius: 18px;
  border: none;
  box-shadow: 0 10px 28px rgba(15, 23, 42, 0.18);
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.reminder-center-panel .today-card ::v-deep .el-card__body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.reminder-center-panel .today-card ::v-deep .el-tabs {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.reminder-center-panel .today-card ::v-deep .el-tabs__header {
  margin: 0 0 10px;
}

.reminder-center-panel .today-card ::v-deep .el-tabs__nav-wrap::after {
  height: 1px;
  background-color: #e5e7eb;
}

.reminder-center-panel .today-card ::v-deep .el-tabs__item {
  height: 34px;
  line-height: 34px;
  padding: 0 10px;
  font-size: 13px;
  color: #6b7280;
}

.reminder-center-panel .today-card ::v-deep .el-tabs__item.is-active {
  color: #2563eb;
  font-weight: 600;
}

.reminder-center-panel .today-card ::v-deep .el-tabs__active-bar {
  height: 2px;
  border-radius: 2px;
}

.reminder-center-panel .today-card ::v-deep .el-tabs__content {
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

.reminder-center-panel .today-card ::v-deep .el-tab-pane {
  height: 100%;
  display: flex;
  flex-direction: column;
}

/* 提醒中心侧栏 - 进出场动画 */
.reminder-center-slide-enter-active,
.reminder-center-slide-leave-active {
  transition: transform 0.25s ease;
}

.reminder-center-slide-enter,
.reminder-center-slide-leave-to {
  transform: translateX(100%);
}

.reminder-center-slide-enter-to,
.reminder-center-slide-leave {
  transform: translateX(0);
}

.timeline-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(148, 163, 184, 0.3) transparent;

  &::-webkit-scrollbar {
    width: 4px;
  }

  &::-webkit-scrollbar-thumb {
    background: rgba(148, 163, 184, 0.3);
    border-radius: 2px;
  }
}

.timeline-item {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  column-gap: 8px;
  padding: 8px 0;
  font-size: 13px;
}

.timeline-item+.timeline-item {
  border-top: 1px dashed #e5e7eb;
}

/* 我的待办：与「今日到店」同构时间轴，操作区独立一行 */
.todo-list .todo-item {
  cursor: pointer;
  padding: 10px 0;
  align-items: flex-start;
}

.todo-list .todo-item + .todo-item {
  border-top: 1px dashed #e5e7eb;
}

.todo-item__aside {
  padding-top: 2px;
  color: inherit;
}

.todo-item__tag {
  display: inline-block;
  font-size: 11px;
  line-height: 1.25;
  padding: 3px 6px;
  border-radius: 4px;
  background: #eff6ff;
  color: #2563eb;
  font-weight: 500;
  word-break: break-all;
}

.todo-item__tag--overdue {
  background: #fef2f2;
  color: #dc2626;
}

.todo-item__tag--urgent {
  background: #fffbeb;
  color: #d97706;
}

.todo-item__main {
  align-items: baseline;
  flex-wrap: wrap;
  white-space: normal;
  gap: 2px 8px;

  .name {
    flex: 1 1 auto;
    min-width: 0;
    white-space: normal;
    line-height: 1.4;
  }
}

.todo-item__due {
  flex: 0 1 auto;
  font-size: 11px;
  font-weight: 400;
  color: #94a3b8;
  line-height: 1.35;
}

.todo-item__sub {
  display: block;
  margin-top: 4px;

  .project {
    white-space: normal;
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
}

.todo-item__foot {
  margin-top: 8px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

.todo-action-btn {
  border: none;
  background: transparent;
  padding: 0;
  font-size: 12px;
  line-height: 1.4;
  color: #94a3b8;
  cursor: pointer;
  transition: color 0.15s ease;

  &:hover {
    color: #2563eb;
  }
}

.todo-action-btn--primary {
  color: #2563eb;
  font-weight: 500;

  &:hover {
    color: #1d4ed8;
  }
}

.todo-action-divider {
  width: 1px;
  height: 12px;
  margin: 0 10px;
  background: #e2e8f0;
  flex-shrink: 0;
}

.timeline-item .time {
  color: #6b7280;
  padding-top: 2px;
}

.timeline-item .content {
  .line-main {
    display: flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;

    .name {
      color: #111827;
      font-weight: 600;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .mobile {
      color: #6b7280;
      flex-shrink: 0;
    }
  }

  .line-sub {
    margin-top: 2px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;

    .project {
      color: #6b7280;
      flex: 1;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
}

.booking-actions {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}

.booking-action-btn {
  padding: 0 4px;
  font-size: 12px;
}

.booking-action-btn--cancel {
  color: #f97316;
}

.booking-action-btn--confirm {
  color: #16a34a;
}

.quick-book-btn {
  flex-shrink: 0;
  border: none;
  border-radius: 999px;
  padding: 0 14px;
  height: 30px;
  line-height: 30px;
  font-size: 13px;
  background: #2563eb;
  color: #ffffff;
  box-shadow: 0 3px 8px rgba(37, 99, 235, 0.3);
  cursor: pointer;
}

.quick-book-btn:hover {
  background: #1d4ed8;
}

.quick-order-btn {
  flex-shrink: 0;
  border: none;
  border-radius: 999px;
  padding: 0 14px;
  height: 30px;
  line-height: 30px;
  font-size: 13px;
  background: #f97316;
  color: #ffffff;
  box-shadow: 0 3px 8px rgba(248, 113, 22, 0.3);
  cursor: pointer;
}

.quick-order-btn:hover {
  background: #ea580c;
}

.status {
  font-size: 11px;
  padding: 1px 8px;
  border-radius: 999px;
}

.status--pending {
  background: #fef3c7;
  color: #92400e;
}

.status--done {
  background: #dcfce7;
  color: #166534;
}

.status--cancel {
  background: #fee2e2;
  color: #b91c1c;
}

.urgency-overdue {
  color: #ef4444 !important;
  font-weight: 600;
}

.urgency-urgent {
  color: #f59e0b !important;
  font-weight: 600;
}

.empty-tip {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  font-size: 13px;
  color: #9ca3af;
}

.monthly-progress-bar {
  background: #fff;
  border-radius: 16px;
  padding: 16px 20px;
  box-shadow: 0 4px 16px rgba(15, 23, 42, 0.06);
  border: 1px solid rgba(226, 232, 240, 0.6);
}

.progress-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.progress-title {
  font-size: 14px;
  font-weight: 600;
  color: #374151;
  display: flex;
  align-items: center;
  gap: 6px;

  i {
    color: #6366f1;
    font-size: 15px;
  }
}

.progress-meta {
  font-size: 13px;
  display: flex;
  align-items: baseline;
  gap: 4px;
}

.progress-done {
  font-size: 18px;
  font-weight: 700;
  color: #6366f1;
}

.progress-sep {
  color: #cbd5e1;
}

.progress-target {
  color: #94a3b8;
}

.progress-track {
  height: 10px;
  background: #f1f5f9;
  border-radius: 999px;
  position: relative;
  overflow: hidden;
  margin-bottom: 8px;
}

.progress-fill {
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, #6366f1, #a855f7);
  transition: width 0.6s ease;
  box-shadow: 0 2px 8px rgba(99, 102, 241, 0.3);
}

.progress-percent {
  font-size: 18px;
  font-weight: 700;
  color: #6366f1;
  margin-right: 8px;
}

.progress-footer {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: #94a3b8;

  b {
    color: #374151;
    font-weight: 600;
  }
}

/* 生日日历 */
.birthday-calendar {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.cal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
  flex-shrink: 0;
}

.cal-month-label {
  font-size: 14px;
  font-weight: 600;
  color: #1e293b;
}

.cal-nav-btn {
  border: none;
  background: rgba(241, 245, 249, 0.9);
  border-radius: 6px;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: #64748b;
  font-size: 13px;
  transition: all 0.2s;

  &:hover {
    background: rgba(99, 102, 241, 0.08);
    color: #4f46e5;
  }
}

.cal-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  margin-bottom: 4px;
  flex-shrink: 0;
}

.cal-weekday {
  text-align: center;
  font-size: 11px;
  color: #94a3b8;
  padding: 2px 0;
}

.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  flex-shrink: 0;
  margin-bottom: 10px;
}

.cal-cell {
  min-height: 34px;
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 3px 2px;
  transition: background 0.15s;

  &--empty {
    background: transparent;
  }

  &:not(.cal-cell--empty) {
    cursor: pointer;
  }

  &--has-birthday {
    background: rgba(99, 102, 241, 0.04);
  }

  &--selected {
    background: rgba(99, 102, 241, 0.15);
    box-shadow: 0 0 0 1px rgba(99, 102, 241, 0.3);
  }
}

.cal-day-num {
  font-size: 12px;
  color: #374151;
  line-height: 1.4;
}

.cal-dots {
  display: flex;
  gap: 2px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 2px;
}

.cal-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  display: inline-block;
}

.cal-list-title {
  font-size: 12px;
  color: #94a3b8;
  margin-bottom: 6px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 8px;
}

.cal-list-reset {
  color: #6366f1;
  cursor: pointer;
  font-weight: 500;

  &:hover {
    text-decoration: underline;
  }
}

.cal-member-list {
  flex: 1;
}

/* 生日列表项 */
.birthday-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid #f1f5f9;

  &:last-child {
    border-bottom: none;
  }
}

.sleeping-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid #f1f5f9;

  &:last-child {
    border-bottom: none;
  }
}

.birthday-day-badge {
  width: 40px;
  height: 36px;
  border-radius: 8px;
  background: rgba(99, 102, 241, 0.08);
  color: #6366f1;
  font-size: 12px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  text-align: center;
  flex-direction: column;
}

.birthday-icon {
  font-size: 14px;
  margin-bottom: 2px;
}

.birthday-day-text {
  line-height: 1;
}

.birthday-info,
.sleeping-info {
  flex: 1;
  min-width: 0;
}

.birthday-name,
.sleeping-name {
  font-size: 13px;
  font-weight: 600;
  color: #111827;
  display: flex;
  align-items: center;
  gap: 6px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.birthday-level-tag {
  font-size: 11px;
  padding: 1px 8px;
  border-radius: 999px;
  font-weight: 600;
  flex-shrink: 0;
}

.birthday-phone,
.sleeping-phone {
  font-size: 12px;
  color: #94a3b8;
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.birthday-amount,
.sleeping-last {
  font-size: 11px;
  color: #64748b;
  margin-top: 1px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sleeping-days {
  width: 42px;
  height: 42px;
  border-radius: 10px;
  background: linear-gradient(135deg, rgba(239, 68, 68, 0.1), rgba(249, 115, 22, 0.1));
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
  color: #ef4444;
  flex-shrink: 0;
  text-align: center;
  line-height: 1.2;
  white-space: nowrap;
}

.sleeping-level {
  font-size: 11px;
  background: rgba(99, 102, 241, 0.1);
  color: #6366f1;
  border-radius: 999px;
  padding: 1px 8px;
  font-weight: 500;
}

@media (max-width: 1024px) {
  .layout-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 768px) {
  .dashboard-page {
    padding: 16px;
  }

  .top-bar {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 12px;
  }

  .layout-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}
</style>

<style lang="scss">
/* 会员搜索下拉（popper 在 body，需全局样式） */
.member-search-dropdown {
  min-width: 420px !important;
  max-height: 360px;

  .el-autocomplete-suggestion__list li {
    padding: 10px 14px;
    line-height: 1.4;
  }
}

/* 切换门店弹窗 - 与 ListDialog 风格一致 */
.store-switch-dialog {
  border-radius: 20px !important;
  padding: 0 !important;
  background: radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.96) 0, rgba(248, 250, 252, 0.98) 40%, rgba(241, 245, 249, 0.98) 100%) !important;
  box-shadow: 0 24px 48px rgba(15, 23, 42, 0.18), 0 0 0 1px rgba(255, 255, 255, 0.9) !important;
  backdrop-filter: blur(22px);
  -webkit-backdrop-filter: blur(22px);
}

.store-switch-dialog .el-dialog__header {
  display: none;
}

.store-switch-dialog .el-dialog__body {
  padding: 0;
}

.store-switch-inner {
  display: flex;
  flex-direction: column;
  max-height: 75vh;
}

.store-switch-header {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 18px 22px 0;
  padding: 10px 14px;
  border-radius: 14px;
  background: rgba(219, 234, 254, 0.96);
}

.store-switch-title {
  font-size: 17px;
  font-weight: 600;
  color: #0f172a;
}

.store-switch-close {
  cursor: pointer;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  color: #64748b;
  transition: all 0.15s;

  &:hover {
    background: rgba(0, 0, 0, 0.06);
    color: #0f172a;
  }
}

.store-switch-content {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 16px 22px 22px;
}

.store-switch-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 10px;
  cursor: pointer;
  transition: all 0.2s;
  border: 1px solid transparent;
  margin-bottom: 8px;

  &:last-child {
    margin-bottom: 0;
  }

  &:hover {
    background: rgba(99, 102, 241, 0.06);
    border-color: rgba(99, 102, 241, 0.2);
  }

  &--active {
    background: rgba(219, 234, 254, 0.5);
    border-color: rgba(59, 130, 246, 0.3);
  }
}

.store-switch-icon {
  width: 36px;
  height: 36px;
  border-radius: 8px;
  background: linear-gradient(135deg, #6366f1, #a855f7);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 700;
  flex-shrink: 0;
  letter-spacing: 0.5px;
}

.store-switch-item--active .store-switch-icon {
  background: linear-gradient(135deg, #4f46e5, #7c3aed);
}

.store-switch-info {
  flex: 1;
  min-width: 0;
}

.store-switch-name {
  font-size: 14px;
  font-weight: 600;
  color: #111827;
  display: flex;
  align-items: center;
  gap: 6px;
  line-height: 1.4;
}

.store-switch-badge {
  font-size: 10px;
  padding: 2px 6px;
  border-radius: 4px;
  background: #22c55e;
  color: #fff;
  font-weight: 600;
}

.store-switch-addr {
  font-size: 12px;
  color: #64748b;
  margin-top: 4px;
  display: flex;
  align-items: flex-start;
  gap: 4px;
  line-height: 1.5;

  i {
    font-size: 12px;
    color: #94a3b8;
    margin-top: 1px;
    flex-shrink: 0;
  }
}

.store-switch-check {
  font-size: 16px;
  color: #22c55e;
  flex-shrink: 0;
}
</style>
