<template>
  <div class="dashboard">
    <!-- 顶部导航 -->
    <header class="topbar">
      <button class="menu-btn" @click="sidebarOpen = !sidebarOpen">☰</button>
      <div class="brand">
        <img src="/src/assets/logo.png" alt="logo" />
        <!-- <span>销售数据平台</span> -->
      </div>
      <div class="user-dropdown" @click.stop="toggleUserMenu">
        <img :src="userInfo.avatar_pull" alt="avatar" class="avatar" />
        <i class="iconfont-sys iconsys-xiala" v-if="false"></i>
        <div v-if="showUserMenu" class="dropdown-menu" @click.stop>
          <div class="item" @click="openProfile">个人中心</div>
          <div class="item danger" @click="confirmLogout">退出登录</div>
        </div>
      </div>
    </header>

    <!-- 左侧导航 -->
    <aside :class="['sidebar', { open: sidebarOpen }]">
      <ul>
        <template v-for="(item, index) in menus" :key="item.id">
          <li
            @click.stop="toggleSubMenu(item, index)"
            :class="{ active: activeMenu === index }"
            class="parent-menu"
          >
            <span class="menu-content">
              <i class="iconfont-sys" v-html="item.icon" style="margin-right: 10px;"></i>
              {{ item.name }}
            </span>
            <i 
              v-if="item.children && item.children.length > 0" 
              class="arrow-icon"
              :class="{ expanded: expandedMenus.has(item.id) }"
            >▼</i>
          </li>
          <!-- 子菜单 -->
          <transition name="submenu">
            <ul v-if="item.children && item.children.length > 0 && expandedMenus.has(item.id)" class="submenu">
              <li 
                v-for="children in item.children" 
                :key="children.id"
                @click.stop="onNav(children.id, index, children.id)"
                :class="['submenu-item', { active: activeChildId === children.id }]"
              >
                {{ children.name }}
              </li>
            </ul>
          </transition>
        </template>
      </ul>
    </aside>
    <div v-if="sidebarOpen" class="drawer-overlay" @click="sidebarOpen = false"></div>

    <!-- 右侧内容 -->
    <main class="content">
      <!-- 看板 banner -->
      <div v-if="bannerImages.length" class="banner">
        <template v-if="bannerImages.length === 1">
          <img :src="bannerImages[0]" alt="banner" />
        </template>
        <template v-else>
          <el-carousel height="220px" indicator-position="outside" class="banner-carousel">
            <el-carousel-item v-for="(img, idx) in bannerImages" :key="`${img}-${idx}`">
              <img :src="img" alt="banner" />
            </el-carousel-item>
          </el-carousel>
        </template>
      </div>
      <template v-for="m in menus" :key="m.id">
        <!-- 父级 section -->
        <section :id="m.id" class="section" v-if="m.cards && m.cards.length > 0">
          <h3>{{ m.name }}</h3>
          <div class="title-block"></div>
          <div class="card-grid">
            <div class="card" v-for="(item, index) in m.cards" :key="index" @click="onCardClick(item)">
              <div class="icon">
                <img src="/src/assets/card-icon.png" alt="icon" />
              </div>
              <div class="info">
                <div class="title">{{ item.title }}</div>
                <div class="desc">{{ item.description }}</div>
              </div>
            </div>
          </div>
        </section>
        <!-- 子级 section -->
        <template v-for="children in m.processedChildren" :key="children.id">
          <section :id="children.id" class="section" v-if="children.cards && children.cards.length > 0">
            <h3>{{ children.parentName }} / {{ children.name }}</h3>
            <div class="title-block"></div>
            <div class="card-grid">
              <div class="card" v-for="(item, index) in children.cards" :key="index" @click="onCardClick(item)">
                <div class="icon">
                  <img src="/src/assets/card-icon.png" alt="icon" />
                </div>
                <div class="info">
                  <div class="title">{{ item.title }}</div>
                  <div class="desc">{{ item.description }}</div>
                </div>
              </div>
            </div>
          </section>
        </template>
      </template>
    </main>

    <!-- 修改资料弹窗 -->
    <div v-if="showProfile" class="modal-overlay" @click.self="showProfile = false">
      <div class="modal profile-modal">
        <!-- 顶部用户信息 -->
        <div class="profile-header">
          <div class="profile-avatar">
            <img :src="userInfo.avatar_pull" alt="avatar" />
          </div>
          <div class="profile-meta">
            <div class="profile-name">{{ userInfo.name }}</div>
            <div class="profile-sub">联系电话：{{ userInfo.mobile || '-' }}</div>
            <div class="profile-sub">编号：{{ userInfo.sn || '-' }}</div>
          </div>
        </div>

        <!-- 基本设置 -->
        <div class="profile-section">
          <div class="section-title">
            <span class="dot"></span>
            <span>基本设置</span>
          </div>
          <div class="section-body">
            <div class="row">
              <div class="col label">头像</div>
              <div class="col">
                <div class="avatar-edit">
                  <img :src="userInfo.avatar_pull" alt="avatar" class="avatar-lg" />
                  <input v-if="basicEditing" type="file" @change="uploadAvatar" />
                </div>
              </div>
            </div>
            <div class="row">
              <div class="col label">昵称</div>
              <div class="col">
                <input class="input" :disabled="!basicEditing" v-model="userInfo.nickname" placeholder="请输入昵称" />
              </div>
              <div class="col label">联系方式</div>
              <div class="col">
                <input class="input" :disabled="!basicEditing" v-model="userInfo.mobile" placeholder="请输入联系方式" />
              </div>
              <div class="col label">编号</div>
              <div class="col">
                <input class="input" disabled v-model="userInfo.sn" placeholder="请输入编号" />
              </div>
            </div>
            
          </div>
          <div class="actions">
            <button class="edit-btn" @click="saveProfile">{{ basicEditing ? '保存' : '编辑' }}</button>
          </div>
        </div>

        <!-- 更改密码 -->
        <div class="profile-section">
          <div class="section-title">
            <span class="dot"></span>
            <span>更改密码</span>
          </div>
          <div class="section-body">
            <div class="row">
              <div class="col label">当前密码</div>
              <div class="col">
                <input class="input" :type="pwdEditing ? 'password' : 'password'" :disabled="!pwdEditing" v-model="pwdForm.password" placeholder="请输入原始密码" />
              </div>
            </div>
            <div class="row">
              <div class="col label">新密码</div>
              <div class="col">
                <input class="input" :type="pwdEditing ? 'password' : 'password'" :disabled="!pwdEditing" v-model="pwdForm.password_new" placeholder="请输入新密码" />
              </div>
            </div>
            <div class="row">
              <div class="col label">确认新密码</div>
              <div class="col">
                <input class="input" :type="pwdEditing ? 'password' : 'password'" :disabled="!pwdEditing" v-model="pwdForm.confirm" placeholder="请输入确认密码" />
              </div>
            </div>
          </div>
          <div class="actions">
            <button class="edit-btn" @click="onResetPassword">{{ pwdEditing ? '保存' : '编辑' }}</button>
          </div>
        </div>

        <div class="modal-actions">
          <button class="btn ghost" @click="showProfile = false">关闭</button>
        </div>
      </div>
    </div>

    <!-- 退出登录确认 -->
    <div v-if="showLogoutConfirm" class="modal-overlay" @click.self="showLogoutConfirm = false">
      <div class="modal confirm-modal">
        <h3>确认退出登录？</h3>
        <p style="color:#666;margin-top:6px;">退出后需要重新登录才能进入系统。</p>
        <div class="modal-actions">
          <button class="btn ghost" @click="showLogoutConfirm = false">取消</button>
          <button class="btn primary" @click="doLogout">确认退出</button>
        </div>
      </div>
    </div>

    <!-- 图片预览 -->
    <div v-if="imagePreview.visible" class="image-preview-overlay" @click.self="closeImagePreview">
      <div class="image-preview-box">
        <div class="preview-header">
          <span>{{ imagePreview.title }}</span>
          <div class="preview-actions">
            <button class="preview-btn" @click="downloadCurrentImage" :disabled="!currentPreviewImage">下载图片</button>
            <button class="preview-btn" @click="prevImage" :disabled="imagePreview.images.length <= 1">上一张</button>
            <button class="preview-btn" @click="nextImage" :disabled="imagePreview.images.length <= 1">下一张</button>
            <button class="preview-btn" @click="closeImagePreview">关闭</button>
          </div>
        </div>
        <div class="preview-body">
          <img
            v-if="currentPreviewImage"
            :src="currentPreviewImage"
            :alt="imagePreview.title"
          />
        </div>
        <div class="preview-footer" v-if="imagePreview.images.length > 1">
          <div
            v-for="(thumb, idx) in imagePreview.images"
            :key="thumb"
            class="preview-thumb"
            :class="{ active: idx === imagePreview.currentIndex }"
            @click="imagePreview.currentIndex = idx"
          >
            <img :src="thumb" :alt="`thumbnail-${idx}`" />
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, computed } from "vue";
import { getMenus, getUser, updateUserInfo, resetPassword, uploadImage,getconfig } from "../api";
import { ElMessage } from 'element-plus'
const menus = ref([]);
const profile = ref({ username: "", password: "" });
const showProfile = ref(false);
const sidebarOpen = ref(false);
const basicEditing = ref(false);
const pwdEditing = ref(false);
const pwdForm = ref({ password: "", password_new: "", confirm: "" });
const showUserMenu = ref(false);
const showLogoutConfirm = ref(false);
const userInfo = ref({});
const activeChildId = ref(null);
const bannerImages = ref([]);
const imagePreview = ref({
  visible: false,
  images: [],
  currentIndex: 0,
  title: '',
  downloadImages: []
});
const currentPreviewImage = computed(() => imagePreview.value.images[imagePreview.value.currentIndex] || '');
const currentDownloadImage = computed(() => imagePreview.value.downloadImages[imagePreview.value.currentIndex] || '');

onMounted(async () => {
  try {
    const { data: bannerData } = await getconfig({ code: 'pc_banner' })
    const bannerStr = (bannerData?.value_pull || '').trim();
    bannerImages.value = bannerStr
      ? bannerStr
          .split(',')
          .map((url) => url.trim())
          .filter(Boolean)
      : [];
    const m = await getMenus();
    const res = m.data;
    // 处理数据结构，为父级和子级都准备 cards
    menus.value = res.map((section) => {
      // 处理父级的 nav_item
      const parentCards = (section.nav_item || []).map((c) =>
        typeof c === "string"
          ? { title: c, description: "" }
          : c
      );
      
      // 处理子级，为每个子级准备 cards 数据
      const processedChildren = (section.children || []).map((children) => {
        const childCards = (children.nav_item || []).map((c) =>
          typeof c === "string"
            ? { title: c, description: "" }
            : c
        );
        return {
          ...children,
          cards: childCards,
          parentName: section.name, // 保存父级名称，用于显示标题
        };
      });
      
      return {
        ...section,
        cards: parentCards,
        processedChildren: processedChildren, // 保存处理后的子级数据
      };
    });
    // 初始化展开当前激活的菜单项
    const activeItem = menus.value[activeMenu.value];
    if (activeItem && activeItem.children && activeItem.children.length > 0) {
      expandedMenus.value.add(activeItem.id);
    }
    const {data} = await getUser();
    userInfo.value = data.user;
  } catch (e) {
    console.error(e);
  }
});
// 下载文件
async function onCardClick(item){
  if (!item) return;
  const url_pull = item.url_pull;
  const type = item.type;
  if (type !== 'image' && !url_pull) return;
  if (type === 'link') {
    window.open(url_pull, '_blank');
    return;
  }

  if (type === 'image') {
    const images = getImageList(item);
    const downloadImages = getProxyList(item);
    if (!images.length) {
      ElMessage.warning('暂无可预览的图片');
      return;
    }
    imagePreview.value = {
      visible: true,
      images,
      currentIndex: 0,
      title: item.title || '图片预览',
      downloadImages: downloadImages.length ? downloadImages : images
    };
    return;
  }

  if (type === 'file') {
    try {
      // 对所有文件类型都使用 fetch 下载，确保真正的下载
      const response = await fetch(url_pull, {
        method: 'GET',
        headers: {
          Accept: '*/*'
        }
      })
      
      if (!response.ok) {
        throw new Error(`下载失败: ${response.status} ${response.statusText}`)
      }
      const blob = await response.blob()
      const url = window.URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.href = url
      link.download = item.title || 'download'
      link.style.display = 'none'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      window.URL.revokeObjectURL(url)
      
      ElMessage.success('下载成功')
    } catch (error) {
      console.error('下载失败:', error)
      const errorMessage = error instanceof Error ? error.message : '未知错误'
      ElMessage.error(`下载失败: ${errorMessage}`)
    }
    return;
  }
}

const activeMenu = ref(0);
const expandedMenus = ref(new Set()); // 用于跟踪展开的菜单项
function onNav(id, index, childId = null) {
  activeMenu.value = index;
  activeChildId.value = childId;
  const el = document.getElementById(id);
  if (el) {
    const topbarHeight = 56;
    const mobileHeight = 44;
    const offset = window.innerWidth <= 768 ? mobileHeight : topbarHeight;
    const y = el.getBoundingClientRect().top + window.scrollY - offset;
    window.scrollTo({ top: y, behavior: "smooth" });
  }
  sidebarOpen.value = false;
}
// 处理父级菜单点击事件（展开/收起子菜单）
function toggleSubMenu(item, index) {
  // 设置选中状态并导航
  activeMenu.value = index;
  activeChildId.value = null;
  const el = document.getElementById(item.id);
  if (el) {
    const topbarHeight = 56;
    const mobileHeight = 44;
    const offset = window.innerWidth <= 768 ? mobileHeight : topbarHeight;
    const y = el.getBoundingClientRect().top + window.scrollY - offset;
    window.scrollTo({ top: y, behavior: "smooth" });
  }
  sidebarOpen.value = false;
  
  // 如果有子菜单，切换展开/收起状态（手风琴效果：同时只展开一个）
  if (item.children && item.children.length > 0) {
    if (expandedMenus.value.has(item.id)) {
      // 如果当前菜单已展开，则关闭它
      expandedMenus.value.delete(item.id);
    } else {
      // 如果当前菜单未展开，先关闭其他所有已展开的菜单，再展开当前菜单
      expandedMenus.value.clear();
      expandedMenus.value.add(item.id);
    }
  }
}

function getImageList(item = {}) {
  const candidates = [];
  if (Array.isArray(item.url_pull)) candidates.push(...item.url_pull);
  if (typeof item.url_pull === 'string') {
    candidates.push(...item.url_pull.split(','));
  }
  const unique = Array.from(
    new Set(
      candidates
        .map((url) => (typeof url === 'string' ? url.trim() : url?.url || ''))
        .filter(Boolean)
    )
  );
  return unique;
}

function getProxyList(item = {}) {
  const list = item.url_pull_proxy;
  if (!list) return [];
  if (Array.isArray(list)) {
    return list.map((url) => (typeof url === 'string' ? url.trim() : '')).filter(Boolean);
  }
  if (typeof list === 'string') {
    return list
      .split(',')
      .map((url) => url.trim())
      .filter(Boolean);
  }
  return [];
}

function closeImagePreview() {
  imagePreview.value.visible = false;
  imagePreview.value.images = [];
  imagePreview.value.currentIndex = 0;
  imagePreview.value.downloadImages = [];
}

function prevImage() {
  if (!imagePreview.value.images.length) return;
  imagePreview.value.currentIndex =
    (imagePreview.value.currentIndex - 1 + imagePreview.value.images.length) %
    imagePreview.value.images.length;
}

function nextImage() {
  if (!imagePreview.value.images.length) return;
  imagePreview.value.currentIndex =
    (imagePreview.value.currentIndex + 1) % imagePreview.value.images.length;
}

async function downloadImage(url, filename = 'image') {
  try {
    if (!url) throw new Error('无效的下载地址');
    const link = document.createElement('a');
    link.href = url;
    link.download = filename || 'download';
    link.target = '_blank';
    link.style.display = 'none';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    ElMessage.success('图片已开始下载');
  } catch (error) {
    console.error('下载图片失败:', error);
    ElMessage.error('下载图片失败');
  }
}

function downloadCurrentImage() {
  const img = currentDownloadImage.value || currentPreviewImage.value;
  if (!img) {
    ElMessage.warning('暂无可下载图片');
    return;
  }
  downloadImage(img, imagePreview.value.title || 'image');
}

async function uploadAvatar(e){
  const file = e.target.files[0];
  const formData = new FormData();
  formData.append('image', file);
  formData.append('scene', 'user');
  const { data } = await uploadImage(formData);
  if (data) {
    userInfo.value.avatar = data.href;
    userInfo.value.avatar_pull = data.url;
  }
}
async function saveProfile(){
  basicEditing.value = !basicEditing.value;
  if(basicEditing.value) return;
  try {
    const { data } = await updateUserInfo(userInfo.value);
  } catch (e) {
    console.error('保存用户信息失败', e);
  } finally {
    basicEditing.value = false;
  }
}
async function onResetPassword(){
  pwdEditing.value = !pwdEditing.value;
  if(pwdEditing.value) return;
  if(pwdForm.value.password_new !== pwdForm.value.confirm){
    alert('新密码和确认密码不一致');
    return;
  }
  try {
    const { message } = await resetPassword(pwdForm.value);
    alert(message);
  } catch (e) {
    alert(e?.response?.data?.message || '重置密码失败');
  }
}
function toggleUserMenu(){
  showUserMenu.value = !showUserMenu.value;
}
async function openProfile(){
  showUserMenu.value = false;
  try {
    const { data } = await getUser();
    if (data.user) {
      userInfo.value = data.user;
      profile.value.nickname = data.user.nickname || data.user.name || '';
      profile.value.phone = data.user.phone || '';
      profile.value.code = data.user.code || data.user.id || '';
    }
  } catch (e) {
    console.error('获取用户信息失败', e);
  } finally {
    showProfile.value = true;
  }
}
function confirmLogout(){
  showUserMenu.value = false;
  showLogoutConfirm.value = true;
}
function doLogout(){
  // 清空本地缓存并跳转登录
  localStorage.clear();
  window.location.href = '/login';
}

window.addEventListener('click', () => { showUserMenu.value = false; });
</script>

<style scoped>
.dashboard {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* 顶部导航 */
.topbar {
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  background: #fff;
  /* color: #fff; */
  position: sticky;
  top: 0;
  z-index: 50;
}
.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
}
.brand img {
  height: 22px;
}
.menu-btn {
  display: none;
  background: none;
  border: none;
  color: #fff;
  font-size: 20px;
  cursor: pointer;
}
.user-dropdown img.avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  cursor: pointer;
}
.user-dropdown{ position:relative; }
.user-dropdown .dropdown-menu{
  position:absolute; right:0; top:46px; width:140px; background:#fff; border:1px solid #e5e7eb; border-radius:8px; box-shadow:0 10px 30px rgba(0,0,0,.08); z-index:120;
}
.user-dropdown .dropdown-menu .item{ padding:10px 12px; cursor:pointer; font-size:14px; color:#333; }
.user-dropdown .dropdown-menu .item:hover{ background:#f6fbfb; color:#009999; }
.user-dropdown .dropdown-menu .item.danger{ color:#e35d5d; }

/* 左侧导航 */
.sidebar {
  width: 220px;
  background: #fff;
  padding: 12px 0;
  position: fixed;
  left: 0;
  top: 56px;
  bottom: 0;
  overflow-y: auto;
  border-right: 1px solid #e5e7eb;
}
.sidebar ul {
  list-style: none;
  padding: 0;
  margin: 0;
}
.sidebar li {
  padding: 10px 18px;
  cursor: pointer;
  color: #333;
  font-size: 14px;
  border-left: 3px solid transparent;
  transition: all 0.2s;
}
.sidebar li:hover {
  background: #eef6f6;
  color: #009999;
}
.sidebar li.active {
  background: rgba(0, 153, 153, 0.09);
  border-left: 3px solid #009999;
  color: #009999;
  font-weight: 600;
}
.parent-menu {
  display: flex;
  justify-content: space-between;
  align-items: center;
  position: relative;
}

.menu-content {
  flex: 1;
  display: flex;
  align-items: center;
}

.arrow-icon {
  font-size: 10px;
  color: #999;
  transition: transform 0.3s ease;
  transform: rotate(-90deg);
  margin-left: 8px;
}

.arrow-icon.expanded {
  transform: rotate(0deg);
}

.submenu {
  list-style: none;
  padding: 0;
  margin: 0;
  background: #f8f9fa;
  overflow: hidden;
}

.sidebar  .submenu-item {
  padding: 8px 18px 8px 48px;
  cursor: pointer;
  color: #666;
  font-size: 13px;
  transition: all 0.2s;
  border-left: 3px solid transparent;
}

.sidebar  .submenu-item:hover,
.sidebar  .submenu-item.active {
  background: #eef6f6;
  color: #009999;
  border-left-color: #009999;
}

/* 子菜单展开/收起动画 */
.submenu-enter-active,
.submenu-leave-active {
  transition: all 0.3s ease;
  max-height: 500px;
}

.submenu-enter-from,
.submenu-leave-to {
  max-height: 0;
  opacity: 0;
}
/* 内容区 */
.content {
  margin-left: 220px;
  padding: 24px;
  background: #f5f6f9;
  min-height: 100vh;
}

/* section 标题 */
.section h3 {
  font-size: 16px;
  font-weight: 600;
  color: #222;
  margin: 20px 0 16px;
  /* border-left: 4px solid #0f7c72; */
  padding-left: 8px;
}

.title-block {
  width: 40px;
  height: 8px;
  background: #14C9C9;
  margin-bottom: 16px;
  margin-top: -25px;
  margin-left: 10px;
}

/* 卡片网格 */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 16px;
}
.card {
  background: #fff;
  padding: 16px;
  border-radius: 10px;
  box-shadow: 0 4px 10px rgba(14, 42, 51, 0.06);
  display: flex;
  align-items: center;
  gap: 12px;
  transition: box-shadow 0.2s;
  cursor: pointer;
}
.card:hover {
  box-shadow: 0 6px 16px rgba(14, 42, 51, 0.12);
}
.card .icon img {
  width: 36px;
  height: 36px;
}
.card .info .title {
  font-size: 14px;
  font-weight: 600;
  color: #222;
}
.card .info .desc {
  font-size: 12px;
  color: #666;
  margin-top: 4px;
}

/* 弹窗 */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 200;
}
.modal {
  background: #fff;
  padding: 18px;
  width: 340px;
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
}
.profile-modal{ width: 920px; max-width: 96vw; }
.profile-header{ display:flex; align-items:center; gap:16px; padding:14px; background:linear-gradient(90deg,#f3fbfb,#ffffff); border-radius:8px; margin-bottom:16px; }
.profile-avatar img{ width:56px; height:56px; border-radius:50%; }
.profile-meta{ display:flex; flex-direction:column; gap:4px; }
.profile-name{ font-size:16px; font-weight:700; color:#222; }
.profile-sub{ font-size:12px; color:#666; }

.profile-section{ background:#fff; border:1px solid #eef2f2; border-radius:8px; padding:12px 14px; margin:16px 0; }
.section-title{ display:flex; align-items:center;margin-bottom:10px; }
.section-title .dot{ width:6px; height:16px; background:#14C9C9; border-radius:3px; display:inline-block; margin-right:8px; }
.section-title > span:first-child{ margin-right:8px; }
.edit-btn{ border:1px solid #14C9C9; color:#14C9C9; background:#ecfafa; border-radius:6px; padding:6px 12px; cursor:pointer; }
.section-body{ padding:4px 0; }
.row{ display:grid; grid-template-columns: 80px 1fr 80px 1fr 80px 1fr; gap:12px; align-items:center; padding:8px 0; }
.row + .row{ border-top:1px dashed #eef2f2; }
.col.label{ color:#666; font-size:13px; }
.input{ width:100%; height:36px; border:1px solid #e5e7eb; border-radius:6px; padding:0 10px; background:#fafafa; }
.avatar-lg{ width:64px; height:64px; border-radius:50%; }
.avatar-edit{ display:flex; align-items:center; gap:10px; }

.modal-actions{ display:flex; justify-content:flex-end; gap:8px; margin-top:8px; }
.btn{ padding:8px 14px; border-radius:8px; border:1px solid transparent; cursor:pointer; }
.btn.ghost{ background:#fff; border-color:#e5e7eb; }
.btn.primary{ background:#14C9C9; color:#fff; }
.modal label {
  display: block;
  margin-top: 8px;
  color: #555;
}

.image-preview-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 250;
  padding: 20px;
}

.image-preview-box {
  background: #fff;
  border-radius: 12px;
  width: min(900px, 96vw);
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.preview-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 18px;
  border-bottom: 1px solid #f0f0f0;
  font-weight: 600;
}

.preview-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  font-size: 12px;
  color: #666;
}

.preview-hint {
  margin-right: 12px;
  color: #999;
}

.preview-btn {
  border: 1px solid #ccc;
  background: #fff;
  padding: 4px 12px;
  border-radius: 4px;
  cursor: pointer;
}

.preview-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.preview-body {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #000;
  padding: 16px;
}

.preview-body img {
  max-width: 100%;
  max-height: 70vh;
  object-fit: contain;
  border-radius: 8px;
}

.preview-footer {
  display: flex;
  gap: 8px;
  padding: 10px 16px;
  overflow-x: auto;
  background: #fafafa;
}

.preview-thumb {
  width: 60px;
  height: 60px;
  border: 2px solid transparent;
  border-radius: 6px;
  overflow: hidden;
  cursor: pointer;
}

.preview-thumb.active {
  border-color: #14C9C9;
}

.preview-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 12px;
}

.banner {
  margin-bottom: 24px;
  border-radius: 12px;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.06);
}

.banner img { 
  width: 100%;
  height: 220px;
  object-fit: cover;
  display: block;
}

:deep(.banner-carousel .el-carousel__container) {
  height: 220px !important;
}

/* 移动端适配 */
.drawer-overlay {
  display: none;
}
@media (max-width: 768px) {
  .menu-btn {
    display: block;
  }
  .sidebar {
    left: -260px;
    transition: left 0.28s;
    top: 44px;
    width: 200px;
    z-index: 60;
  }
  .sidebar.open {
    left: 0;
  }
  .drawer-overlay {
    display: block;
    position: fixed;
    inset: 44px 0 0 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 50;
  }
  .content {
    margin-left: 0;
    padding: 16px;
    margin-top: 56px;
  }
  .topbar {
    height: 44px;
    padding: 0 12px;
  }
  .brand span {
    display: none;
  }
  .modal {
    width: 90%;
  }
}
</style>
