<!DOCTYPE html>
<html data-version="v2.0" lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<title>省胜优铺 轻商城</title>
<link rel="icon" type="image/svg+xml" href="/lib/favicon.svg">
<link rel="stylesheet" href="/lib/vant.css">
<script>
// ====== H5启动器：支持从URL参数注入token/page（小程序壳专用） ======
(function(){
  var p = new URLSearchParams(location.search);
  var t = p.get('token');
  var pg = p.get('page');
  if (t) { localStorage.setItem('token', t); }
  // 如果指定了初始页面，存到 sessionStorage，Vue初始化时读取
  if (pg) { sessionStorage.setItem('_initPage', pg); }
  if (p.get('product_id')) { sessionStorage.setItem('_initProductId', p.get('product_id')); }
})();
</script>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:-apple-system,'PingFang SC',sans-serif;background:#f5f3ff;font-size:14px;color:#1a1a2e}
[v-cloak]{display:none}
.primary{color:#7C3AED}
.page{min-height:100vh;padding-bottom:50px}
.page-enter{animation:pageIn .3s ease}
@keyframes pageIn{from{opacity:0;transform:translateX(20px)}to{opacity:1;transform:translateX(0)}}
.topbar{background:linear-gradient(135deg,#7C3AED,#A78BFA);padding:44px 12px 12px;color:#fff;display:flex;align-items:center;gap:10px}
.topbar .back{font-size:20px;cursor:pointer}
.topbar .title{flex:1;text-align:center;font-size:17px;font-weight:600}
.tabbar{position:fixed;bottom:0;left:0;right:0;height:50px;background:#fff;display:flex;border-top:1px solid #eee;z-index:1001}
.tabbar .tab{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;font-size:10px;color:#999;cursor:pointer;transition:color .2s}
.tabbar .tab.active{color:#7C3AED}
.tabbar .tab .icon{font-size:20px}
.card{background:#fff;border-radius:8px;margin:10px 12px;overflow:hidden}
.card-body{padding:12px}
.prod-list{display:flex;gap:10px;padding:0 12px;overflow-x:auto}
.prod-card{flex-shrink:0;width:130px;background:#fff;border-radius:8px;overflow:hidden}
.prod-card img{width:100%;height:130px;object-fit:cover;display:block;background:#f5f3ff}
.prod-card .info{padding:8px}
.prod-card .name{font-size:12px;line-height:1.3;height:31px;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.prod-card .price{font-size:15px;font-weight:700;color:#7C3AED;margin-top:4px}
.grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;padding:12px;text-align:center}
.grid-4 .item{padding:8px 0}
.grid-4 .item .icon{font-size:24px;margin-bottom:4px}
.grid-4 .item .label{font-size:12px;color:#666}
.img-placeholder{width:100%;height:130px;background:#f0f0f0;display:flex;align-items:center;justify-content:center;color:#ccc;font-size:24px}
.skeleton-home{padding:12px}
.skeleton-home .sk-row{display:flex;gap:10px;margin-bottom:16px}
.skeleton-home .sk-banner{height:140px;background:linear-gradient(90deg,#f0f0f0 25%,#e8e8e8 50%,#f0f0f0 75%);background-size:200% 100%;border-radius:8px;margin-bottom:16px;animation:shimmer 1.5s infinite}
.skeleton-home .sk-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-bottom:16px;padding:0 12px}
.skeleton-home .sk-grid-item{text-align:center}
.skeleton-home .sk-grid-item .sk-icon{width:32px;height:32px;border-radius:50%;background:#f0f0f0;margin:0 auto 6px;background:linear-gradient(90deg,#f0f0f0 25%,#e8e8e8 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}
.skeleton-home .sk-prod-title{width:120px;height:18px;border-radius:4px;background:linear-gradient(90deg,#f0f0f0 25%,#e8e8e8 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;margin-bottom:10px}
.skeleton-home .sk-prod-row{display:flex;gap:10px}
.skeleton-home .sk-prod-card{width:130px;border-radius:8px;overflow:hidden}
.skeleton-home .sk-prod-card .sk-img{height:130px;background:linear-gradient(90deg,#f0f0f0 25%,#e8e8e8 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}
.skeleton-home .sk-prod-card .sk-name{height:12px;background:#f0f0f0;margin:6px 8px;border-radius:4px;background:linear-gradient(90deg,#f0f0f0 25%,#e8e8e8 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}
.skeleton-home .sk-prod-card .sk-price{height:16px;width:60px;background:#f0f0f0;margin:4px 8px;border-radius:4px;background:linear-gradient(90deg,#f0f0f0 25%,#e8e8e8 50%,#f0f0f0 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}
@keyframes shimmer{0%{background-position:-200% 0}100%{background-position:200% 0}}
.review-summary{display:flex;align-items:center;gap:16px;padding:12px 0}
.review-summary .score{text-align:center}
.review-summary .score .num{font-size:36px;font-weight:700;color:#fa0}
.review-summary .score .label{font-size:12px;color:#999}
.review-tags{display:flex;gap:8px;flex-wrap:wrap;padding:8px 0}
.review-tags .tag{padding:4px 12px;border-radius:12px;font-size:12px;border:1px solid #ddd;cursor:pointer;transition:all .2s}
.review-tags .tag.active{background:#7C3AED;color:#fff;border-color:#7C3AED}
.review-item{padding:12px 0;border-bottom:1px solid #f0f0f0}
.review-item:last-child{border-bottom:none}
.review-item .header{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.review-item .header .avatar{width:28px;height:28px;border-radius:50%;background:#eee;display:flex;align-items:center;justify-content:center;font-size:12px;color:#999}
.review-item .header .nickname{font-size:13px;color:#333}
.review-item .header .time{font-size:11px;color:#999;margin-left:auto}
.review-item .content{font-size:13px;line-height:1.5;color:#333}
.review-item .images{display:flex;gap:6px;margin-top:6px;flex-wrap:wrap}
.review-item .images img{width:72px;height:72px;border-radius:4px;object-fit:cover;cursor:pointer;border:1px solid #eee}
.review-item .reply{margin-top:6px;padding:8px;background:#f8f8f8;border-radius:4px;font-size:12px;color:#666;line-height:1.5}
.review-item .reply .prefix{color:#7C3AED}
.review-item .actions{display:flex;gap:12px;margin-top:6px;font-size:12px;color:#999}
.review-item .actions span{cursor:pointer;display:flex;align-items:center;gap:2px}
.review-item .actions .liked{color:#e0245e}
.image-preview-overlay{position:fixed;inset:0;background:rgba(0,0,0,.9);z-index:2000;display:flex;align-items:center;justify-content:center}
.image-preview-overlay img{max-width:90%;max-height:90%;object-fit:contain}
.image-preview-overlay .close-btn{position:absolute;top:50px;right:20px;color:#fff;font-size:28px;cursor:pointer;z-index:2001}
.spec-popup{padding:20px;max-height:70vh;overflow-y:auto}
.spec-popup .spec-title{font-size:16px;font-weight:600;margin-bottom:12px}
.spec-popup .spec-section{margin-bottom:16px}
.spec-popup .spec-section .label{font-size:13px;color:#666;margin-bottom:8px}
.spec-popup .spec-options{display:flex;gap:8px;flex-wrap:wrap}
.spec-popup .spec-option{padding:6px 16px;border:1px solid #ddd;border-radius:16px;font-size:13px;cursor:pointer;transition:all .2s}
.spec-popup .spec-option.active{border-color:#7C3AED;color:#7C3AED;background:rgba(124,58,237,.06)}
.spec-popup .spec-option.disabled{opacity:.4;cursor:not-allowed}
.spec-popup .spec-bottom{display:flex;align-items:center;justify-content:space-between;padding-top:12px;border-top:1px solid #eee}
.spec-popup .spec-price{color:#7C3AED;font-size:20px;font-weight:700}
.address-item{padding:12px;border-bottom:1px solid #f0f0f0;cursor:pointer;transition:background .15s}
.address-item:last-child{border-bottom:none}
.address-item:hover{background:#f5f3ff}
.address-item .name{font-size:14px;font-weight:500}
.address-item .detail{font-size:12px;color:#666;margin-top:4px}
.address-item .selected-badge{float:right;color:#7C3AED;font-size:12px}
.coupon-item{padding:12px;border-bottom:1px solid #f0f0f0;cursor:pointer;transition:background .15s}
.coupon-item:last-child{border-bottom:none}
.coupon-item:hover{background:#f5f3ff}
.coupon-item .amount{color:#7C3AED;font-size:18px;font-weight:700}
.coupon-item .condition{font-size:12px;color:#999}
.coupon-item .expire{font-size:11px;color:#ccc;margin-top:2px}
.coupon-item .selected-badge{float:right;color:#7C3AED;font-size:12px}
.coupon-card{background:linear-gradient(135deg,#7C3AED,#A78BFA);border-radius:10px;padding:16px;margin:10px 12px;color:#fff;position:relative;overflow:hidden}
.coupon-card .cprice{font-size:32px;font-weight:800}
.coupon-card .cname{font-size:14px;margin-top:4px;opacity:.9}
.coupon-card .ccond{font-size:12px;margin-top:2px;opacity:.7}
.coupon-card .cexp{font-size:11px;margin-top:4px;opacity:.5}
.coupon-card .used{position:absolute;top:12px;right:12px;background:rgba(255,255,255,.2);padding:2px 10px;border-radius:10px;font-size:11px}
.coupon-empty{text-align:center;padding:60px 20px;color:#999}
.coupon-empty .icon{font-size:48px;margin-bottom:12px}
.coupon-empty .text{font-size:14px}
.cat-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:2px;padding:12px}
.cat-item{padding:16px 4px;text-align:center;border-radius:8px;cursor:pointer;transition:all .15s}
.cat-item:active{background:#f0e6ff}
.cat-item .cat-icon{width:44px;height:44px;border-radius:12px;background:linear-gradient(135deg,#7C3AED,#A78BFA);display:flex;align-items:center;justify-content:center;font-size:22px;margin:0 auto 6px;color:#fff}
.cat-item .cat-name{font-size:12px;color:#333}
.cat-prod-row{display:flex;gap:10px;padding:0 12px;overflow-x:auto}
.cat-prod-row .prod-card{flex-shrink:0;width:140px}
</style>
  <meta name="litemall-copyright" content="4c6974654d616c6c5f436f707972696768745f46554c4c5f45444954494f4e5f3037656566306534" />
</head>
<body>
<div id="app" v-cloak>
  <!-- ========== 首页 ========== -->
  <div class="page" v-show="page==='home'" :class="{'page-enter':page==='home'}">
    <!-- 首页骨架屏 -->
    <div class="skeleton-home" id="skel-loader">
      <div class="sk-banner"></div>
      <div class="sk-grid">
        <div class="sk-grid-item" v-for="i in 4" :key="i"><div class="sk-icon"></div></div>
      </div>
      <div class="sk-prod-title"></div>
      <div class="sk-prod-row">
        <div class="sk-prod-card" v-for="i in 3" :key="i">
          <div class="sk-img"></div>
          <div class="sk-name"></div>
          <div class="sk-price"></div>
        </div>
      </div>
    </div>
    <!-- 首页实际内容 -->
    <!-- 🔧 装修渲染层(v1.4.3): 授权版渲染装修模板, 否则走默认手写首页 -->
    <div id="decor-home" v-if="decor.enabled && page==='home'" class="decor-home"></div>
    <template v-if="!decor.enabled">
      <div style="background:linear-gradient(135deg,#7C3AED,#A78BFA);padding:44px 12px 16px;color:#fff">
        <div style="font-size:20px;font-weight:800;letter-spacing:-.5px">省胜优铺</div>
        <div style="margin-top:10px;background:rgba(255,255,255,.2);border-radius:20px;padding:8px 14px;font-size:13px;color:rgba(255,255,255,.7)">🔍 搜索商品</div>
      </div>
      <van-swipe :autoplay="3000" indicator-color="#7C3AED" style="margin:10px 12px;border-radius:8px;overflow:hidden">
        <van-swipe-item v-for="b in banners" :key="b.id">
          <van-image :src="b.image" style="width:100%;height:140px;object-fit:cover" lazy-load>
            <template v-slot:error><div class="img-placeholder" style="height:140px">📷</div></template>
          </van-image>
        </van-swipe-item>
        <van-swipe-item><div style="width:100%;height:140px;background:linear-gradient(135deg,#7C3AED,#A78BFA);display:flex;align-items:center;justify-content:center;color:#fff;font-size:18px;font-weight:600">省胜优铺 优选</div></van-swipe-item>
      </van-swipe>
      <div class="grid-4">
        <div class="item" v-for="e in entries" :key="e.l" @click="goEntryPage(e)"><div class="icon">{{e.i}}</div><div class="label">{{e.l}}</div></div>
      </div>
      <!-- 商品分类入口 -->
      <div style="padding:0 12px;margin:4px 0 6px">
        <div style="font-size:15px;font-weight:700">📂 全部分类</div>
        <div class="cat-grid">
          <div class="cat-item" v-for="c in categories.slice(0,8)" :key="c.id" @click="goCategory(c)">
            <div class="cat-icon">{{c.icon||'📦'}}</div>
            <div class="cat-name">{{c.name}}</div>
          </div>
        </div>
      </div>
      <div style="padding:0 12px;margin:10px 0">
        <div style="font-size:15px;font-weight:700">🔥 推荐商品</div>
        <div v-if="products.length===0" style="text-align:center;padding:20px;color:#999;font-size:13px">暂无商品</div>
        <div style="display:flex;gap:10px;overflow-x:auto;margin-top:8px;padding-bottom:8px" v-else>
          <div class="prod-card" v-for="p in products" :key="p.id" @click="goProduct(p.id)">
            <van-image :src="p.image" lazy-load>
              <template v-slot:error><div class="img-placeholder">📷</div></template>
            </van-image>
            <div class="info">
              <div class="name">{{p.name}}</div>
              <div class="price">¥{{formatPrice(p.price)}}</div>
            </div>
          </div>
        </div>
      </div>
    </template>
  </div>
  
  <!-- ========== 商品详情 ========== -->
  <div class="page" v-show="page==='product'" :class="{'page-enter':page==='product'}">
    <div class="topbar"><span class="back" @click="goBackHome">‹</span><span class="title">商品详情</span><span></span></div>
    <van-image :src="detail.image" style="width:100%;height:300px;object-fit:cover" lazy-load>
      <template v-slot:error><div class="img-placeholder" style="height:300px">📷</div></template>
    </van-image>
    <div class="card"><div class="card-body">
      <div style="font-size:16px;font-weight:600">{{detail.name}}</div>
      <div style="color:#7C3AED;font-size:22px;font-weight:700;margin-top:8px">¥{{formatPrice(detail.price)}}</div>
      <div style="color:#999;font-size:12px;margin-top:4px">库存: {{detail.stock||0}}件</div>
    </div></div>

    <!-- 商品评价区域 -->
    <div class="card" v-if="detail.id">
      <div class="card-body">
        <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px">
          <div style="font-size:15px;font-weight:600">商品评价</div>
          <span style="font-size:12px;color:#7C3AED;cursor:pointer" v-if="reviewList.length>3">查看全部 ›</span>
        </div>
        <!-- 评价统计 -->
        <div class="review-summary">
          <div class="score"><div class="num">{{reviewStats.avgScore||'--'}}</div><div class="label">综合评分</div></div>
          <div>
            <van-rate :model-value="Math.round(reviewStats.avgScore||0)" :size="14" color="#fa0" readonly />
            <div style="font-size:12px;color:#999;margin-top:2px">{{reviewStats.total||0}}条评价</div>
          </div>
        </div>
        <!-- 评价标签筛选 -->
        <div class="review-tags">
          <span class="tag" :class="{active:reviewFilter.tag==='all'}" @click="reviewFilter.tag='all'">全部({{reviewStats.total||0}})</span>
          <span class="tag" :class="{active:reviewFilter.tag==='good'}" @click="reviewFilter.tag='good'">好评({{reviewStats.good||0}})</span>
          <span class="tag" :class="{active:reviewFilter.tag==='neutral'}" @click="reviewFilter.tag='neutral'">中评({{reviewStats.neutral||0}})</span>
          <span class="tag" :class="{active:reviewFilter.tag==='bad'}" @click="reviewFilter.tag='bad'">差评({{reviewStats.bad||0}})</span>
          <span class="tag" :class="{active:reviewFilter.hasImage}" @click="reviewFilter.hasImage=!reviewFilter.hasImage">📷 有图</span>
        </div>
        <!-- 评价列表 -->
        <div v-if="filteredReviews.length===0" style="text-align:center;padding:20px;color:#999;font-size:13px">暂无评价</div>
        <div v-for="(rv,ri) in filteredReviews.slice(0,3)" :key="rv.id||ri" class="review-item">
          <div class="header">
            <div class="avatar">👤</div>
            <span class="nickname">{{rv.nickname||'匿名用户'}}</span>
            <span class="time">{{rv.created_at||''}}</span>
          </div>
          <div class="content">{{rv.content}}</div>
          <div class="images" v-if="rv.images&&rv.images.length">
            <img v-for="(img,ii) in rv.images.slice(0,6)" :key="ii" :src="img" @click="previewImage(rv.images,ii)">
          </div>
          <div class="reply" v-if="rv.reply">
            <span class="prefix">商家回复：</span>{{rv.reply}}
          </div>
          <div class="actions">
            <span :class="{liked:rv.liked}" @click="toggleReviewLike(rv)">{{rv.liked?'❤️':'🤍'}} {{rv.like_count||0}}</span>
          </div>
        </div>
        <div style="text-align:center;padding-top:8px" v-if="reviewList.length>3">
          <van-button plain size="small" round type="primary" @click="showAllReviews">查看全部 {{reviewList.length}} 条评价</van-button>
        </div>
      </div>
    </div>

    <!-- 底部操作栏 -->
    <div style="position:fixed;bottom:50px;left:0;right:0;display:flex;gap:10px;padding:10px 12px;background:#fff;border-top:1px solid #eee;z-index:100">
      <van-button round block plain type="primary" size="small" @click="showSpecSelector('cart')" :loading="cartLoading">加入购物车</van-button>
      <van-button round block type="primary" size="small" @click="showSpecSelector('buy')">立即购买</van-button>
    </div>
  </div>

  <!-- ========== 分类页 ========== -->
  <div class="page" v-show="page==='category'" :class="{'page-enter':page==='category'}">
    <div id="decor-category" v-if="decor.enabled && page==='category'" class="decor-home"></div>
    <div v-if="!decor.enabled || page!=='category'">
    <div class="topbar"><span class="back" @click="page='home'">‹</span><span class="title">全部分类</span><span></span></div>
    <div style="display:flex;min-height:calc(100vh - 100px)">
      <!-- 左侧分类列表 -->
      <div style="width:90px;background:#fafafa;overflow-y:auto;flex-shrink:0">
        <div v-for="(c,ci) in categories" :key="c.id"
             style="padding:14px 8px;text-align:center;font-size:13px;cursor:pointer;border-left:3px solid transparent;transition:all .15s"
             :style="{background:selectedCategoryIndex===ci?'#fff':'transparent',borderLeftColor:selectedCategoryIndex===ci?'#7C3AED':'transparent',color:selectedCategoryIndex===ci?'#7C3AED':'#666',fontWeight:selectedCategoryIndex===ci?'600':'400'}"
             @click="selectCategory(ci)">{{c.name}}</div>
      </div>
      <!-- 右侧商品 -->
      <div style="flex:1;overflow-y:auto;padding:10px">
        <div v-if="categoryProducts.length===0" style="text-align:center;padding:40px 0;color:#999;font-size:13px">该分类暂无商品</div>
        <div style="display:grid;grid-template-columns:repeat(2,1fr);gap:8px">
          <div v-for="p in categoryProducts" :key="p.id" class="prod-card" style="width:100%" @click="goProduct(p.id)">
            <van-image :src="p.image" style="width:100%;height:130px;object-fit:cover" lazy-load>
              <template v-slot:error><div class="img-placeholder" style="height:130px">📷</div></template>
            </van-image>
            <div class="info">
              <div class="name" style="height:auto;max-height:31px">{{p.name}}</div>
              <div class="price">¥{{formatPrice(p.price)}}</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  </div>

  <!-- 规格选择弹窗 -->
  <van-action-sheet v-model:show="specVisible" title="选择规格" :close-on-popstate="false">
    <div class="spec-popup">
      <div class="spec-section">
        <div class="label">选择规格</div>
        <div class="spec-options">
          <span class="spec-option" v-for="(spec,si) in specOptions" :key="si"
                :class="{active:selectedSpec===si,disabled:spec.disabled}"
                @click="!spec.disabled&&(selectedSpec=si)">{{spec.label}}</span>
        </div>
      </div>
      <div class="spec-section" v-if="detail.stock!==undefined">
        <div class="label">数量</div>
        <van-stepper v-model="specQuantity" min="1" :max="detail.stock||99" size="28" />
      </div>
      <div class="spec-bottom">
        <div class="spec-price">¥{{formatPrice(detail.price)}}</div>
        <van-button round type="primary" size="small" style="padding:0 24px" @click="confirmSpec" :loading="specConfirmLoading">确定</van-button>
      </div>
    </div>
  </van-action-sheet>
  
  <!-- ========== 购物车 ========== -->
  <div class="page" v-show="page==='cart'" :class="{'page-enter':page==='cart'}">
    <div id="decor-cart" v-if="decor.enabled && page==='cart'" class="decor-home"></div>
    <div v-if="!decor.enabled || page!=='cart'">
    <div class="topbar"><span></span><span class="title">购物车</span><span style="font-size:13px;cursor:pointer" @click="clearCart">清空</span></div>
    <div v-if="cart.length">
      <van-swipe-cell v-for="(c,i) in cart" :key="c.id||i">
        <div class="card" style="margin:6px 12px"><div class="card-body" style="display:flex;gap:10px;align-items:center">
          <van-checkbox v-model="c.selected" @change="calcCart" />
          <van-image :src="c.image" style="width:64px;height:64px;border-radius:4px;object-fit:cover;flex-shrink:0" lazy-load>
            <template v-slot:error><div class="img-placeholder" style="width:64px;height:64px;border-radius:4px;font-size:14px">📷</div></template>
          </van-image>
          <div style="flex:1;min-width:0"><div style="font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">{{c.name}}</div><div style="color:#7C3AED;font-weight:700;margin-top:4px">¥{{formatPrice(c.price)}}</div></div>
          <van-stepper v-model="c.quantity" min="1" :max="c.stock||99" size="26" @change="debouncedCartUpdate" />
        </div></div>
        <template v-slot:right>
          <van-button square type="danger" text="删除" style="height:100%;border-radius:0" @click="removeCartItem(i)" />
        </template>
      </van-swipe-cell>
      <!-- 底部结算栏 -->
      <div style="position:fixed;bottom:50px;left:0;right:0;padding:10px 12px;background:#fff;border-top:1px solid #eee;display:flex;align-items:center;justify-content:space-between;z-index:100">
        <div><van-checkbox v-model="cartAll" @change="toggleAll">全选</van-checkbox></div>
        <div style="display:flex;align-items:center;gap:10px">
          <span>合计: <b style="color:#7C3AED">¥{{formatPrice(cartTotal)}}</b></span>
          <van-button round type="primary" size="small" style="padding:0 20px" @click="checkout">结算({{cartSelectedCount}})</van-button>
        </div>
      </div>
    </div>
    <van-empty v-else description="购物车是空的">
      <van-button plain size="small" style="margin-top:12px" @click="page='home'">去逛逛</van-button>
    </van-empty>
  </div>
  </div>
  
  <!-- ========== 我的 ========== -->
  <div class="page" v-show="page==='user'" :class="{'page-enter':page==='user'}">
    <div id="decor-mine" v-if="decor.enabled && page==='user'" class="decor-home"></div>
    <div v-if="!decor.enabled || page!=='user'">
    <div style="background:linear-gradient(135deg,#7C3AED,#A78BFA);padding:44px 12px 24px;color:#fff;text-align:center">
      <div v-if="user.phone">👤 {{user.nickname||user.phone}}</div>
      <div v-else><van-button plain round size="small" style="color:#fff;border-color:rgba(255,255,255,.5)" @click="page='login'">去登录</van-button></div>
    </div>
    <div class="grid-4">
      <div class="item" @click="switchTab('orders')"><div class="icon">📄</div><div class="label">待付款</div></div>
      <div class="item" @click="switchTab('orders')"><div class="icon">📦</div><div class="label">待发货</div></div>
      <div class="item" @click="switchTab('orders')"><div class="icon">🚚</div><div class="label">待收货</div></div>
      <div class="item" @click="switchTab('orders')"><div class="icon">⭐</div><div class="label">已完成</div></div>
    </div>
    <div class="card"><div class="card-body">
      <van-cell is-link @click="switchTab('orders')">我的订单</van-cell>
      <van-cell is-link>我的地址</van-cell>
      <van-cell is-link>我的收藏</van-cell>
      <van-cell is-link @click="page='coupon-list'">我的优惠券</van-cell>
      <van-cell is-link @click="page='chat'">在线客服</van-cell>
    </div></div>
    <div class="card"><div class="card-body">
      <van-cell is-link @click="goPointsPage()">💎 我的积分 <span style="color:#7C3AED;font-weight:600">{{user.points||0}} 分</span></van-cell>
      <van-cell is-link @click="goEntryPage({p:'membership'})">👑 会员中心</van-cell>
      <van-cell is-link @click="goEntryPage({p:'distribution'})">📢 分销推广</van-cell>
      <van-cell is-link @click="goEntryPage({p:'exchange'})">🎁 积分兑换</van-cell>
      <van-cell is-link @click="goEntryPage({p:'recharge'})">💰 余额充值</van-cell>
      <van-cell is-link @click="goEntryPage({p:'browse-history'})">🕘 浏览足迹</van-cell>
      <van-cell is-link @click="goEntryPage({p:'aftersale'})">🔄 我的售后</van-cell>
    </div></div>
    <div style="padding:20px 12px"><van-button round block plain @click="logout" v-if="user.phone">退出登录</van-button></div>
  </div>
  </div>
  
  <!-- ========== 我的优惠券列表 ========== -->
  <div class="page" v-show="page==='coupon-list'" :class="{'page-enter':page==='coupon-list'}">
    <div class="topbar"><span class="back" @click="page='user'">‹</span><span class="title">我的优惠券</span><span></span></div>
    <div style="padding:4px 0">
      <div style="display:flex;justify-content:center;gap:8px;padding:12px;background:#fff">
        <span v-for="ct in couponTabs" :key="ct.key"
              style="padding:4px 16px;border-radius:14px;font-size:13px;cursor:pointer;transition:all .2s"
              :style="{background:couponTab===ct.key?'#7C3AED':'#f5f3ff',color:couponTab===ct.key?'#fff':'#7C3AED'}"
              @click="couponTab=ct.key;loadUserCoupons()">{{ct.label}}</span>
      </div>
      <div v-if="userCoupons.length===0" class="coupon-empty">
        <div class="icon">🎫</div>
        <div class="text">暂无优惠券</div>
      </div>
      <div v-for="cp in userCoupons" :key="cp.id" class="coupon-card" :style="{opacity:cp.status==='used'||cp.status==='expired'?'.5':'1'}">
        <div class="cprice">¥{{formatPrice(cp.amount)}}</div>
        <div class="cname">{{cp.name||'优惠券'}}</div>
        <div class="ccond">{{cp.condition_text||'无门槛'}}</div>
        <div class="cexp">有效期至: {{cp.expire_at||'长期有效'}}</div>
        <div class="used" v-if="cp.status==='used'">已使用</div>
        <div class="used" v-else-if="cp.status==='expired'" style="background:rgba(255,255,255,.15)">已过期</div>
      </div>
    </div>
  </div>

  <!-- ========== 我的积分 ========== -->
  <div class="page" v-show="page==='points'" :class="{'page-enter':page==='points'}">
    <div class="topbar"><span class="back" @click="page='user'">‹</span><span class="title">我的积分</span><span></span></div>
    <div style="background:linear-gradient(135deg,#7C3AED,#A78BFA);padding:32px 20px;color:#fff;text-align:center">
      <div style="font-size:13px;opacity:.9">当前积分</div>
      <div style="font-size:44px;font-weight:700;margin:6px 0">{{pointsData.balance||0}}</div>
      <div style="font-size:12px;opacity:.85">累计获得 {{pointsData.total||0}} 分 · 100积分抵1元 · 消费送积分</div>
    </div>
    <div style="padding:16px 12px">
      <div style="font-size:15px;font-weight:600;color:#333;margin-bottom:10px">积分明细</div>
      <div v-if="pointsLogs.length===0" style="text-align:center;color:#999;padding:40px 0">暂无积分记录</div>
      <div v-for="lg in pointsLogs" :key="lg.id" style="background:#fff;border-radius:8px;padding:12px;margin-bottom:8px;display:flex;justify-content:space-between;align-items:center">
        <div>
          <div style="font-size:14px;color:#333">{{pointsTypeText(lg.change_type)}}</div>
          <div style="font-size:12px;color:#999">{{lg.remark||lg.ref_no||''}}</div>
        </div>
        <div :style="{fontSize:'16px',fontWeight:'600',color:lg.change_amount<0?'#E74C3C':'#27AE60'}">{{lg.change_amount>0?'+':''}}{{lg.change_amount}}</div>
      </div>
    </div>
  </div>

  <!-- ========== 登录 ========== -->
  <div class="page" v-show="page==='login'" :class="{'page-enter':page==='login'}">
    <div class="topbar"><span class="back" @click="page='user'">‹</span><span class="title">登录</span><span></span></div>
    <div style="padding:30px 24px">
      <van-field v-model="loginForm.phone" label="手机号" placeholder="请输入手机号" clearable />
      <van-field v-model="loginForm.password" type="password" label="密码" placeholder="请输入密码" />
      <van-button round block type="primary" style="margin-top:24px;height:44px" @click="doLogin" :loading="loginLoading">登 录</van-button>
      <div style="text-align:center;margin-top:12px"><span style="color:#7C3AED;font-size:13px;cursor:pointer" @click="page='register'">没有账号？去注册</span></div>
    </div>
  </div>
  
  <!-- ========== 注册 ========== -->
  <div class="page" v-show="page==='register'" :class="{'page-enter':page==='register'}">
    <div class="topbar"><span class="back" @click="page='login'">‹</span><span class="title">注册</span><span></span></div>
    <div style="padding:30px 24px">
      <van-field v-model="regForm.phone" label="手机号" placeholder="请输入手机号" />
      <van-field v-model="regForm.password" type="password" label="密码" placeholder="至少6位" />
      <van-field v-model="regForm.nickname" label="昵称" placeholder="选填" />
      <van-button round block type="primary" style="margin-top:24px;height:44px" @click="doRegister" :loading="regLoading">注 册</van-button>
    </div>
  </div>
  
  <!-- ========== 订单列表 ========== -->
  <div class="page" v-show="page==='orders'" :class="{'page-enter':page==='orders'}">
    <div class="topbar"><span class="back" @click="page='user'">‹</span><span class="title">我的订单</span><span></span></div>
    <!-- 订单状态标签 -->
    <div style="display:flex;background:#fff;padding:8px 4px;border-bottom:1px solid #eee;overflow-x:auto">
      <span v-for="(s,sk) in orderStatusTabs" :key="sk"
            style="flex-shrink:0;padding:4px 14px;margin:0 4px;border-radius:14px;font-size:13px;cursor:pointer;transition:all .2s"
            :style="{background:orderTab===sk?'#7C3AED':'#f5f3ff',color:orderTab===sk?'#fff':'#7C3AED'}"
            @click="orderTab=sk;orderPage=1;loadOrders()">{{s}}</span>
    </div>
    <van-list v-model:loading="orderLoadingMore" :finished="orderFinished" finished-text="没有更多了" @load="loadOrders" :immediate-check="false">
      <div v-for="o in orderList" :key="o.order_no" class="card"><div class="card-body">
        <div style="display:flex;justify-content:space-between;font-size:12px;color:#999"><span>{{o.created_at}}</span><span :style="{color:o.status==='pending_pay'?'#e0245e':'#00B578'}">{{statusLabel(o.status)}}</span></div>
        <div v-for="i in o.items" :key="i.id" style="display:flex;gap:10px;margin-top:8px">
          <van-image :src="i.image" style="width:60px;height:60px;border-radius:4px;object-fit:cover;flex-shrink:0" lazy-load>
            <template v-slot:error><div class="img-placeholder" style="width:60px;height:60px;border-radius:4px;font-size:14px">📷</div></template>
          </van-image>
          <div style="flex:1;min-width:0"><div style="font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">{{i.product_name}}</div><div style="color:#999;font-size:12px;margin-top:4px">¥{{formatPrice(i.price)}} x {{i.quantity}}</div></div>
        </div>
        <div style="text-align:right;font-size:13px;margin-top:6px">实付: <b style="color:#7C3AED">¥{{formatPrice(o.pay_amount)}}</b></div>
        <!-- 订单操作按钮 -->
        <div style="display:flex;gap:8px;justify-content:flex-end;margin-top:8px">
          <van-button plain size="mini" round v-if="o.status==='pending_pay'" @click="payOrder(o)">去支付</van-button>
          <van-button plain size="mini" round v-if="o.status==='pending_ship'||o.status==='shipped'||o.status==='received'" @click="goAfterSaleApply(o)">申请售后</van-button>
          <van-button plain size="mini" round v-if="o.status==='received'" @click="goReview(o)">去评价</van-button>
          <van-button plain size="mini" round v-if="o.status==='received'||o.status==='completed'" @click="goFollowUp(o)">追评</van-button>
        </div>
      </div></div>
    </van-list>
    <van-empty v-if="!orderList.length && !orderLoading" description="暂无订单" />
  </div>
  
  <!-- ========== 结算 ========== -->
  <div class="page" v-show="page==='checkout'" :class="{'page-enter':page==='checkout'}">
    <div class="topbar"><span class="back" @click="page='cart'">‹</span><span class="title">确认订单</span><span></span></div>
    <!-- 收货地址 -->
    <div class="card" style="cursor:pointer" @click="showAddressSelector">
      <div class="card-body">
        <div v-if="selectedAddress" style="display:flex;align-items:flex-start;gap:8px">
          <div style="font-size:18px">📍</div>
          <div>
            <div style="font-size:14px;font-weight:500">{{selectedAddress.name}} {{selectedAddress.phone}}</div>
            <div style="font-size:12px;color:#666;margin-top:2px">{{selectedAddress.province}}{{selectedAddress.city}}{{selectedAddress.district}}{{selectedAddress.detail}}</div>
          </div>
          <div style="margin-left:auto;color:#ccc">›</div>
        </div>
        <div v-else style="color:#999;font-size:14px">请选择收货地址 ›</div>
      </div>
    </div>
    <!-- 商品列表 -->
    <div class="card"><div class="card-body">
      <div v-for="i in checkoutItems" :key="i.id" style="display:flex;gap:10px;margin-bottom:8px">
        <van-image :src="i.image" style="width:60px;height:60px;border-radius:4px;object-fit:cover;flex-shrink:0" lazy-load>
          <template v-slot:error><div class="img-placeholder" style="width:60px;height:60px;border-radius:4px;font-size:14px">📷</div></template>
        </van-image>
        <div style="flex:1;min-width:0"><div style="font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">{{i.name}}</div><div style="color:#7C3AED;font-weight:700;margin-top:4px">¥{{formatPrice(i.price)}} x {{i.quantity}}</div></div>
      </div>
    </div></div>
    <!-- 优惠券 -->
    <div class="card" style="cursor:pointer" @click="showCouponSelector">
      <div class="card-body" style="display:flex;justify-content:space-between;align-items:center">
        <span style="font-size:13px;color:#666">优惠券</span>
        <span v-if="selectedCoupon" style="color:#7C3AED;font-size:13px;font-weight:600">-¥{{formatPrice(selectedCoupon.amount)}}</span>
        <span v-else style="color:#999;font-size:13px">选择优惠券 ›</span>
      </div>
    </div>
    <!-- 提交按钮 -->
    <div style="padding:12px">
      <van-button round block type="primary" :loading="orderLoading" @click="submitOrder">
        提交订单 ¥{{formatPrice(checkoutTotal)}}
      </van-button>
    </div>
  </div>

  <!-- 地址选择弹窗 -->
  <van-popup v-model:show="addressPopup" position="bottom" round :style="{maxHeight:'60vh'}">
    <div style="padding:16px;font-size:16px;font-weight:600;border-bottom:1px solid #eee">选择收货地址</div>
    <div v-if="addressList.length===0" style="text-align:center;padding:30px;color:#999">暂无收货地址</div>
    <div v-for="(addr,ai) in addressList" :key="ai" class="address-item" @click="selectAddress(addr)">
      <div><span class="name">{{addr.name}}</span> <span style="color:#999;font-size:12px">{{addr.phone}}</span>
        <span class="selected-badge" v-if="selectedAddress===addr">✓</span>
      </div>
      <div class="detail">{{addr.province}}{{addr.city}}{{addr.district}}{{addr.detail}}</div>
    </div>
  </van-popup>

  <!-- 优惠券选择弹窗 -->
  <van-popup v-model:show="couponPopup" position="bottom" round :style="{maxHeight:'60vh'}">
    <div style="padding:16px;font-size:16px;font-weight:600;border-bottom:1px solid #eee">选择优惠券</div>
    <div v-if="couponList.length===0" style="text-align:center;padding:30px;color:#999">暂无可用优惠券</div>
    <div v-for="(cp,ci) in couponList" :key="ci" class="coupon-item" @click="selectCoupon(cp)">
      <div><span class="amount">¥{{formatPrice(cp.amount)}}</span>
        <span style="font-size:13px;margin-left:8px">{{cp.name}}</span>
        <span class="selected-badge" v-if="selectedCoupon===cp">✓</span>
      </div>
      <div class="condition">{{cp.condition||'无门槛'}}</div>
      <div class="expire" v-if="cp.expire_at">有效期至: {{cp.expire_at}}</div>
    </div>
  </van-popup>
  
  <!-- ========== AI客服 ========== -->
  <div class="page" v-show="page==='chat'" :class="{'page-enter':page==='chat'}">
    <div class="topbar"><span class="back" @click="page='user'">‹</span><span class="title">在线客服</span><span></span></div>
    <div style="padding:12px;background:#f5f3ff;min-height:calc(100vh - 110px)">
      <div v-if="chatMsgs.length===0" style="text-align:center;padding:40px 0;color:#999">开始咨询吧 👋</div>
      <div v-for="(m,i) in chatMsgs" :key="i" style="display:flex;margin-bottom:10px" :style="{justifyContent:m.role==='user'?'flex-end':'flex-start'}">
        <div style="max-width:75%;padding:8px 12px;border-radius:8px;font-size:14px;line-height:1.5" :style="{background:m.role==='user'?'#7C3AED':'#fff',color:m.role==='user'?'#fff':'#333'}">{{m.content}}</div>
      </div>
    </div>
    <div style="position:fixed;bottom:50px;left:0;right:0;padding:8px 12px;background:#fff;border-top:1px solid #eee;display:flex;gap:8px;z-index:100">
      <van-field v-model="chatInput" placeholder="输入问题..." style="flex:1" @keyup.enter="sendChat" />
      <van-button type="primary" round size="small" style="height:36px;padding:0 16px" @click="sendChat" :loading="chatLoading">发送</van-button>
    </div>
  </div>

  <!-- ========== 评价列表页（从订单进入） ========== -->
  <div class="page" v-show="page==='review-list'" :class="{'page-enter':page==='review-list'}">
    <div class="topbar"><span class="back" @click="page='orders'">‹</span><span class="title">商品评价</span><span></span></div>
    <div class="card" style="margin-top:0;border-radius:0">
      <div class="card-body" v-if="reviewTargetOrder">
        <div style="font-size:14px;font-weight:600;margin-bottom:8px">评价订单: {{reviewTargetOrder.order_no}}</div>
        <div v-for="i in reviewTargetOrder.items" :key="i.id" style="display:flex;gap:10px;align-items:center;margin-bottom:8px;padding-bottom:8px;border-bottom:1px solid #f0f0f0" v-if="!i._reviewed">
          <van-image :src="i.image" style="width:50px;height:50px;border-radius:4px;flex-shrink:0" lazy-load>
            <template v-slot:error><div class="img-placeholder" style="width:50px;height:50px;border-radius:4px;font-size:12px">📷</div></template>
          </van-image>
          <div style="flex:1;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">{{i.product_name}}</div>
          <van-button size="mini" round type="primary" @click="openReviewEditor(i)">评价</van-button>
        </div>
      </div>
    </div>
    <van-empty v-if="reviewTargetOrder&&reviewTargetOrder.items.every(i=>i._reviewed)" description="该订单商品已评价完毕" />
  </div>

  <!-- ========== 追评页 ========== -->
  <div class="page" v-show="page==='follow-up'" :class="{'page-enter':page==='follow-up'}">
    <div class="topbar"><span class="back" @click="page='orders'">‹</span><span class="title">追加评价</span><span></span></div>
    <div class="card" style="margin-top:0;border-radius:0">
      <div class="card-body">
        <div style="font-size:14px;font-weight:600;margin-bottom:8px">追评订单: {{followUpTarget?.order_no||''}}</div>
        <div v-if="followUpTarget">
          <div v-for="i in followUpTarget.items" :key="i.id" style="display:flex;gap:10px;align-items:flex-start;margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid #f0f0f0">
            <van-image :src="i.image" style="width:50px;height:50px;border-radius:4px;flex-shrink:0" lazy-load>
              <template v-slot:error><div class="img-placeholder" style="width:50px;height:50px;border-radius:4px;font-size:12px">📷</div></template>
            </van-image>
            <div style="flex:1">
              <div style="font-size:13px;font-weight:500">{{i.product_name}}</div>
              <van-field v-model="followUpContent" type="textarea" rows="3" placeholder="说说使用感受..." style="margin-top:6px" />
              <div style="display:flex;gap:8px;margin-top:6px">
                <div v-for="(_,fi) in followUpImages" :key="fi" style="width:60px;height:60px;border:1px dashed #ddd;border-radius:4px;display:flex;align-items:center;justify-content:center;color:#ccc;font-size:20px;cursor:pointer" @click="addFollowUpImage(fi)">+</div>
              </div>
            </div>
          </div>
          <van-button round block type="primary" style="margin-top:12px" @click="submitFollowUp" :loading="followUpLoading">提交追评</van-button>
        </div>
      </div>
    </div>
  </div>

  <!-- 评价编辑器弹窗 -->
  <van-popup v-model:show="reviewEditorVisible" position="bottom" round :style="{maxHeight:'70vh'}">
    <div style="padding:16px 16px 8px;font-size:16px;font-weight:600;border-bottom:1px solid #eee">评价商品</div>
    <div style="padding:16px">
      <div style="display:flex;align-items:center;gap:8px;margin-bottom:12px">
        <span style="font-size:13px;color:#666">评分:</span>
        <van-rate v-model="reviewForm.rating" :size="22" color="#fa0" void-color="#eee" />
      </div>
      <van-field v-model="reviewForm.content" type="textarea" rows="4" placeholder="分享您的使用体验..." />
      <div style="display:flex;gap:8px;margin-top:8px;flex-wrap:wrap">
        <div v-for="(_,fi) in reviewForm.images" :key="fi" style="width:64px;height:64px;border:1px dashed #ddd;border-radius:4px;display:flex;align-items:center;justify-content:center;color:#ccc;font-size:20px;cursor:relative;overflow:hidden">
          <input type="file" accept="image/*" style="opacity:0;position:absolute;width:100%;height:100%;cursor:pointer" @change="e=>handleReviewImageUpload(fi,e)" />
          <span>+</span>
        </div>
      </div>
      <van-button round block type="primary" style="margin-top:16px" @click="submitReview" :loading="reviewSubmitting">提交评价</van-button>
    </div>
  </van-popup>

  <!-- ========== 图片预览层 ========== -->
  <div class="image-preview-overlay" v-if="previewImages.length" @click="closePreview">
    <span class="close-btn" @click.stop="closePreview">✕</span>
    <img :src="previewImages[previewImageIndex]" @click.stop style="transition:transform .2s">
    <div style="position:absolute;bottom:60px;left:50%;transform:translateX(-50%);color:rgba(255,255,255,.7);font-size:14px">
      {{previewImageIndex+1}} / {{previewImages.length}}
    </div>
    <div style="position:absolute;bottom:80px;left:0;right:0;display:flex;justify-content:space-between;padding:0 20px">
      <span style="color:#fff;font-size:30px;cursor:pointer" @click.stop="prevImage" v-if="previewImages.length>1">‹</span>
      <span style="color:#fff;font-size:30px;cursor:pointer" @click.stop="nextImage" v-if="previewImages.length>1">›</span>
    </div>
  </div>
  
  <!-- ========== 限时秒杀（模块化） ========== -->
  <div class="page" v-show="page==='seckill'" :class="{'page-enter':page==='seckill'}">
    <div class="topbar"><span class="back" @click="goBackHome">‹</span><span class="title">限时秒杀</span><span></span></div>
    <div id="seckill-module-container"></div>
    <div id="promotion-module-container"></div>
  </div>

  <!-- ========== 每日签到（模块化） ========== -->
  <div class="page" v-show="page==='checkin'" :class="{'page-enter':page==='checkin'}">
    <div class="topbar"><span class="back" @click="page='user'">‹</span><span class="title">每日签到</span><span></span></div>
    <div id="checkin-module-container"></div>
  </div>

  <!-- ========== 我的售后（模块化） ========== -->
  <div class="page" v-show="page==='aftersale'" :class="{'page-enter':page==='aftersale'}">
    <div class="topbar"><span class="back" @click="page='user'">‹</span><span class="title">我的售后</span><span></span></div>
    <div id="aftersale-module-container"></div>
  </div>

  <!-- ========== 会员中心（模块化） ========== -->
  <div class="page" v-show="page==='membership'" :class="{'page-enter':page==='membership'}">
    <div class="topbar"><span class="back" @click="page='user'">‹</span><span class="title">会员中心</span><span></span></div>
    <div id="membership-module-container"></div>
  </div>

  <!-- ========== 分销中心（模块化） ========== -->
  <div class="page" v-show="page==='distribution'" :class="{'page-enter':page==='distribution'}">
    <div class="topbar"><span class="back" @click="page='user'">‹</span><span class="title">分销中心</span><span></span></div>
    <div id="distribution-module-container"></div>
  </div>

  <!-- ========== 积分商城（模块化） ========== -->
  <div class="page" v-show="page==='exchange'" :class="{'page-enter':page==='exchange'}">
    <div class="topbar"><span class="back" @click="page='user'">‹</span><span class="title">积分商城</span><span></span></div>
    <div id="exchange-module-container"></div>
  </div>

  <!-- ========== 余额充值（模块化） ========== -->
  <div class="page" v-show="page==='recharge'" :class="{'page-enter':page==='recharge'}">
    <div class="topbar"><span class="back" @click="page='user'">‹</span><span class="title">余额充值</span><span></span></div>
    <div id="recharge-module-container"></div>
  </div>

  <!-- ========== 拼团（模块化） ========== -->
  <div class="page" v-show="page==='group-buy'" :class="{'page-enter':page==='group-buy'}">
    <div class="topbar"><span class="back" @click="page='home'">‹</span><span class="title">拼团</span><span></span></div>
    <div id="group-buy-module-container"></div>
  </div>

  <!-- ========== 消息通知（模块化） ========== -->
  <div class="page" v-show="page==='notification'" :class="{'page-enter':page==='notification'}">
    <div class="topbar"><span class="back" @click="page='user'">‹</span><span class="title">消息通知</span><span></span></div>
    <div id="notification-module-container"></div>
  </div>

  <!-- ========== 浏览足迹（模块化） ========== -->
  <div class="page" v-show="page==='browse-history'" :class="{'page-enter':page==='browse-history'}">
    <div class="topbar"><span class="back" @click="page='user'">‹</span><span class="title">浏览足迹</span><span></span></div>
    <div id="browse-history-module-container"></div>
    <div id="ps-module-container" v-show="page==='presale'"></div>
    <div id="bargain-module-container" v-show="page==='bargain'"></div>
  </div>

</div>
  
  <!-- ========== 底部导航栏 ========== -->
  <div class="tabbar">
    <div class="tab" :class="{active:page==='home'}" @click="switchTab('home')"><div class="icon">🏠</div><div>首页</div></div>
    <div class="tab" :class="{active:page==='category'}" @click="switchTab('category')"><div class="icon">📂</div><div>分类</div></div>
    <div class="tab" :class="{active:page==='cart'}" @click="switchTab('cart')"><div class="icon">🛒</div><div>购物车</div></div>
    <div class="tab" :class="{active:page==='user'}" @click="switchTab('user')"><div class="icon">👤</div><div>我的</div></div>
  </div>
</div>

<script src="/lib/vue.global.prod.js"></script>
<script src="/lib/vant.min.js"></script>
<script src="/lib/axios.min.js"></script>
<script>/*** LiteMall 移动端商城 - 暮山紫版* Vue 3 + Vant 4 + Axios CDN 单页应用* 主题色: 暮山紫 #7C3AED / #A78BFA* 页面: 首页/分类/商品详情/购物车/订单/结算/评价/客服/优惠券/签到/秒杀*/const {createApp,ref,reactive,computed,onMounted,watch,nextTick}=Vue;const api=axios.create({baseURL:'/api',timeout:10000});function track(a,p,pid){try{if(window.__tDisable)return;var uid=(window.__tuidd||0);navigator.sendBeacon?navigator.sendBeacon('/api/track',JSON.stringify({action:a,page:p||page.value||'',product_id:pid||0,user_id:uid,source:'h5'})):axios.post('/api/track',{action:a,page:p||page.value||'',product_id:pid||0,user_id:uid,source:'h5'}).catch(function(){});}catch(e){}}api.interceptors.response.use(r=>r.data,e=>({code:500,message:e.message}));const app=createApp({setup(){const page=ref('home');const token=ref(localStorage.getItem('token')||'');try{var __tm=localStorage.getItem('user')||'';window.__tuidd=Number(JSON.parse(__tm||'{}').id)||0;}catch(e){window.__tuidd=0;}const homeLoading=ref(true); const banners=ref([]);const products=ref([]);const cart=ref([]);const cartAll=ref(false);const user=ref({});const pointsData=ref({balance:0,total:0});const pointsLogs=ref([]);const loginForm=reactive({phone:'',password:''});const loginLoading=ref(false);const regForm=reactive({phone:'',password:'',nickname:''});const regLoading=ref(false);const detail=ref({});const cartLoading=ref(false);const orderList=ref([]);const orderLoading=ref(false);const orderLoadingMore=ref(false); const orderFinished=ref(false); const orderPage=ref(1); const orderTab=ref('all'); const checkoutItems=ref([]);const checkoutTotal=ref(0);const chatInput=ref('');const chatMsgs=ref([]);const chatLoading=ref(false);const chatConvId=ref(null);const specVisible=ref(false);const specAction=ref('cart'); const specOptions=ref([{label:'标准版',disabled:false},{label:'豪华版',disabled:false},]);const selectedSpec=ref(0);const specQuantity=ref(1);const specConfirmLoading=ref(false);const addressPopup=ref(false);const couponPopup=ref(false);const addressList=ref([]);const selectedAddress=ref(null);const couponList=ref([]);const selectedCoupon=ref(null);const reviewList=ref([]);const reviewStats=ref({avgScore:0,total:0,good:0,neutral:0,bad:0});const reviewFilter=reactive({tag:'all',hasImage:false});const reviewVisible=ref(false); const previewImages=ref([]);const previewImageIndex=ref(0);const reviewEditorVisible=ref(false);const reviewForm=reactive({rating:5,content:'',images:[]});const reviewTargetItem=ref(null);const reviewSubmitting=ref(false);const reviewTargetOrder=ref(null);const followUpTarget=ref(null);const followUpContent=ref('');const followUpImages=ref(['','','']);const followUpLoading=ref(false);const categories=ref([]);const selectedCategoryIndex=ref(0);const categoryProducts=ref([]);const userCoupons=ref([]);const couponTab=ref('unused');const couponTabs=[{key:'unused',label:'未使用'},{key:'used',label:'已使用'},{key:'expired',label:'已过期'}];const entries=[{i:'🏷️',l:'促销中心',p:'promotion'},{i:'👑',l:'会员',p:'membership'},{i:'📢',l:'分销',p:'distribution'},{i:'⚡',l:'秒杀',p:'seckill'},{i:'📄',l:'优惠券',p:'coupon'},{i:'🤝',l:'拼团',p:'group-buy'},{i:'🚀',l:'预售',p:'presale'},{i:'🔪',l:'砍价',p:'bargain'},{i:'✅',l:'签到',p:'checkin'},{i:'🎁',l:'积分兑换',p:'exchange'},{i:'💰',l:'余额充值',p:'recharge'},{i:'🔔',l:'通知',p:'notification'},{i:'🕘',l:'足迹',p:'browse-history'}];
/* ==== 🔧 装修渲染(v1.4.3): 授权版渲染design模板组件, free版降级 ==== */
const decor=reactive({enabled:false,components:[],terminal:'h5',currentPage:'home',pages:{home:[],category:[],cart:[],user:[]}});
async function loadDecor(pg){var pg2=pg||decor.currentPage||'home';try{var r=await api.get('/design/render/h5',{params:{page:pg2}});if(r&&r.code===0&&r.data&&r.data.enabled&&(r.data.components||[]).length){decor.pages[pg2]=r.data.components||[];if(pg2===decor.currentPage){decor.enabled=true;decor.components=r.data.components||[];renderDecor();setTimeout(renderDecor,50);}}else{decor.pages[pg2]=[];if(pg2===decor.currentPage){decor.enabled=false;}}}catch(e){decor.pages[pg2]=[];if(pg2===decor.currentPage)decor.enabled=false;}}
function esc(s){return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');}
function renderDecor(){var pg=decor.currentPage||'home';var el=document.getElementById('decor-'+pg);if(!el||!decor.enabled)return;el.innerHTML=(decor.components||[]).map(function(c,i){var p=c.props||c.config||{};try{return renderDecorComp(c.type,c.key||('c'+i),p);}catch(e){return '';}}).join('');renderDecorAsync();startDecorCountdowns();setTimeout(startDecorCountdowns,300);}
function renderDecorAsync(){/* 异步: swiper banner + goodsList 商品 */
  var pg=decor.currentPage||'home';var el=document.getElementById('decor-'+pg);if(!el)return;
  decor.components.forEach(function(c,i){var p=c.props||c.config||{};
    if(c.type==='swiper'&&(!p.images||!p.images.length)){api.get('/banner/list').then(function(r){if(r&&r.code===0&&r.data&&r.data.length){p.images=r.data.map(function(b){return {url:b.image,link:''};});var html=renderDecorComp('swiper','b'+(i+1),p);var el2=document.querySelector('#decor-home .decor-swiper');if(!el2){el.innerHTML=decor.components.map(function(c2,i2){try{return renderDecorComp(c2.type,c2.key||('c'+i2),c2.props||c2.config||{});}catch(e){return '';}}).join('');}else{var wrap=el2.parentElement;var ne=document.createElement('div');ne.innerHTML=html;wrap.replaceChild(ne.firstChild,el2);}}}).catch(function(){});}
    if(c.type==='goodsList'){var gk=c.key||('c'+i);api.get('/product/list',{params:{pageSize:p.limit||6}}).then(function(r){if(r&&r.code===0&&r.data&&r.data.list&&r.data.list.length){var card=el.querySelector('.decor-goods-'+esc(gk));if(card){card.innerHTML=r.data.list.map(function(pr){return '<div class="prod-card" style="cursor:pointer" onclick="window.goProduct&&goProduct('+pr.id+')"><img src="'+esc(pr.image||'')+'" class="prod-img" alt=""><div class="prod-name">'+esc(pr.name||'')+'</div><div class="prod-price">¥'+esc((Number(pr.price)||0).toFixed(2))+'</div></div>';}).join('');}}}).catch(function(){});}
    if(c.type==='promotionList'){var pk2=c.key||('c'+i);var box=el.querySelector('.decor-promo-'+esc(pk2));if(!box)return;var ptype=box.getAttribute('data-type')||'all';var plimit=+(box.getAttribute('data-limit')||8);api.get('/marketing/promotion-center').then(function(r){if(!(r&&r.code===0&&r.data&&r.data.list)){box.innerHTML='<div style="text-align:center;color:#999;padding:20px 0;font-size:13px">暂无活动</div>';return;}var items=(r.data.list||[]).filter(function(it){return ptype==='all'||it.type===ptype;}).slice(0,plimit);if(!items.length){box.innerHTML='<div style="text-align:center;color:#999;padding:20px 0;font-size:13px">暂无活动</div>';return;}box.innerHTML=items.map(function(it){var tag=it.type==='seckill'?'秒杀':it.type==='groupon'?'拼团':it.type==='bargain'?'砍价':it.type==='presale'?'预售':'领券';var color=it.type==='seckill'?'#E74C3C':it.type==='groupon'?'#27AE60':it.type==='bargain'?'#FF7F50':it.type==='presale'?'#7C3AED':'#D4A045';if(it.type==='coupon'){return '<div class="promo-card" style="background:#fff;border-radius:8px;padding:10px 12px;display:flex;align-items:center;gap:10px;margin-bottom:8px"><span style="font-size:22px">🎫</span><div style="flex:1"><div style="font-size:13px;font-weight:600">'+esc(it.name||'')+'</div><div style="font-size:12px;color:#888">'+(it.claimed?'已领取':'满'+(it.min_amount||0)+'可用'+(it.value?'·减'+it.value+'元':''))+'</div></div><span style="font-size:11px;color:#fff;background:'+color+';padding:4px 10px;border-radius:12px">'+((it.claimed)?'已领':'领取')+'</span></div>';}return '<div class="promo-card" style="background:#fff;border-radius:8px;padding:10px 12px;display:flex;align-items:center;gap:10px;margin-bottom:8px;cursor:pointer" onclick="window.goEntryFromDecor&&goEntryFromDecor(\''+esc(it.link||'')+'\')"><div style="width:52px;height:52px;border-radius:6px;overflow:hidden;background:#f5f6fa;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:22px">'+(it.image?'<img src="'+esc(it.image)+'" style="width:100%;height:100%;object-fit:cover" alt="">':(it.type==='seckill'?'⚡':it.type==='groupon'?'🫂':it.type==='bargain'?'🔪':'🚀'))+'</div><div style="flex:1"><div style="font-size:13px;font-weight:600">'+esc(it.name||'')+'</div><div style="font-size:12px;color:#888">'+(it.type==='seckill'?'秒杀价':it.type==='groupon'?'拼团价':it.type==='bargain'?'砍到':'预售价')+' ¥'+esc((Number(it.price)||0).toFixed(2))+' <s style="color:#bbb">¥'+esc((Number(it.origin_price)||0).toFixed(2))+'</s></div></div><span style="font-size:11px;color:#fff;background:'+color+';padding:4px 10px;border-radius:12px">'+tag+'</span></div>';}).join('');}).catch(function(){if(box){box.innerHTML='<div style="text-align:center;color:#999;padding:20px 0;font-size:13px">活动加载失败</div>';}});}
    if(c.type==='waterfall'){var wfk=c.key||('c'+i);var wfEl=el.querySelector('.decor-waterfall-'+esc(wfk));if(!wfEl)return;var wfSrc=(p.source||'auto');var wfP={pageSize:p.count||6};if(wfSrc==='hot')wfP.sort='sales';else if(wfSrc==='new')wfP.sort='new';else if(wfSrc!=='all')wfP.is_recommend=1;api.get('/product/list',{params:wfP}).then(function(r){if(r&&r.code===0&&r.data&&r.data.list&&r.data.list.length){var prods=r.data.list.slice(0,(p.count||6));var ca='',cb='';prods.forEach(function(pr,ix){var card='<div style="background:#fff;border-radius:8px;overflow:hidden;margin-bottom:8px;cursor:pointer" onclick="window.goProduct&&goProduct('+pr.id+')"><img src="'+esc(pr.image||'')+'" style="width:100%;height:'+(90+((ix%3)*25))+'px;object-fit:cover;display:block" alt=""><div style="padding:6px"><div style="font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">'+esc(pr.name||'')+'</div>'+(p.showPrice!==false?'<div style="font-size:14px;color:#E17055;font-weight:700;margin-top:2px">¥'+esc((Number(pr.price)||0).toFixed(2))+'</div>':'')+(p.showSales!==false?'<div style="font-size:10px;color:#999">已售'+(pr.sales||0)+'件</div>':'')+'</div></div>';if(ix%2===0)ca+=card;else cb+=card;});var colA=wfEl.querySelector('.wf-col'),colB=wfEl.querySelector('.wf-col2');if(colA&&colB){colA.innerHTML=ca;colB.innerHTML=cb;}}}).catch(function(){});}
    if(c.type==='couponWall'){var cwk=c.key||('c'+i);var cwEl=el.querySelector('.decor-couponwall-'+esc(cwk));if(!cwEl)return;var cwN=+(p.count||4);var sc=p.showClaim!==false;api.get('/marketing/promotion-center',{headers:(function(){var t=localStorage.getItem('token');return t?{Authorization:'Bearer '+t}:{};})()}).then(function(r){if(!(r&&r.code===0&&r.data&&r.data.list)){var l=cwEl.querySelector('.cw-loading');if(l)l.innerHTML='暂无优惠券';return;}var cps=(r.data.list||[]).filter(function(it){return it.type==='coupon';}).slice(0,cwN);if(!cps.length){var l2=cwEl.querySelector('.cw-loading');if(l2)l2.innerHTML='暂无优惠券';return;}var hasTok=!!(localStorage.getItem('token'));cwEl.innerHTML=(p.title?'<div style="font-size:15px;font-weight:700;color:#333;margin-bottom:10px">'+esc(p.title)+'</div>':'')+cps.map(function(cp){var dis=cp.claimed?'已领取':'';var btn=cp.claimed?'<div style="background:rgba(255,255,255,.6);color:#fff;font-size:12px;border-radius:20px;padding:4px 12px">已领取</div>':(sc&&hasTok?'<div style="background:#fff;color:#EE6B2F;font-size:12px;font-weight:600;border-radius:20px;padding:4px 12px;cursor:pointer" onclick="window._claimCoupon&&_claimCoupon('+cp.id+',\''+esc(cp.name)+'\')">领取</div>':'<div style="background:rgba(255,255,255,.6);color:#fff;font-size:12px;border-radius:20px;padding:4px 12px">领取</div>');return '<div style="display:flex;align-items:center;background:linear-gradient(135deg,#EE6B2F,#F89B5B);border-radius:8px;overflow:hidden;padding:10px;margin-bottom:8px"><div style="width:70px;text-align:center;color:#fff;border-right:2px dashed rgba(255,255,255,.5);padding-right:6px"><div style="font-size:20px;font-weight:700">'+(cp.value?'¥'+cp.value:'礼')+'</div><div style="font-size:10px;opacity:.9">满'+(cp.min_amount||0)+'可用</div></div><div style="flex:1;padding:0 10px;color:#fff"><div style="font-size:14px;font-weight:600">'+esc(cp.name||'')+'</div><div style="font-size:10px;opacity:.8">'+(cp.valid_days?'有效期'+cp.valid_days+'天':'剩余'+cp.remained+'张')+'</div></div>'+btn+'</div>';}).join('');}).catch(function(){});}
    if(c.type==='categoryGrid'){var cgk=c.key||('c'+i);var cgEl=el.querySelector('.decor-categrid-'+esc(cgk));if(!cgEl)return;var cgCols=+(cgEl.getAttribute('data-cols')||4);api.get('/category/list').then(function(r){if(r&&r.code===0&&r.data&&r.data.length){var cats=r.data.slice(0,(p.limit||10));cgEl.innerHTML='<div style="display:grid;grid-template-columns:repeat('+cgCols+',1fr);gap:12px">'+cats.map(function(cg){return '<div style="text-align:center;cursor:pointer" onclick="window.goEntryFromDecor&&goEntryFromDecor(\'category\')"><div style="width:44px;height:44px;margin:0 auto;border-radius:14px;background:#f5f5f5;display:flex;align-items:center;justify-content:center;font-size:20px">'+(cg.icon||'📂')+'</div><div style="font-size:11px;color:#333;margin-top:4px">'+esc(cg.name||'')+'</div></div>';}).join('')+'</div>';}}).catch(function(){});}

  });
}

/* v1.8: 倒计时横幅实时更新 */
function startDecorCountdowns(){try{var boxes=document.querySelectorAll('[class*=decor-cdb-]');boxes.forEach&&boxes.forEach(function(bx){var endSt=bx.getAttribute('data-end');var endT=endSt?new Date(endSt).getTime():0;if(isNaN(endT))endT=0;var tick=function(){var clock=bx.querySelector('.cdb-clock');if(!clock){clearInterval(timer);return;}var diff=endT?Math.max(0,Math.floor((endT-Date.now())/1000)):0;if(!endT){clock.innerHTML='<span style="font-size:13px;opacity:.9">活动进行中</span>';return;}var d=Math.floor(diff/86400),h=Math.floor(diff%86400/3600),m=Math.floor(diff%3600/60),s2=diff%60;var pad=function(n){return (n<10?'0':'')+n;};var cells=clock.querySelectorAll('.cb');if(cells.length>=4){cells[0].textContent=pad(d);cells[1].textContent=pad(h);cells[2].textContent=pad(m);cells[3].textContent=pad(s2);}else{clock.innerHTML='<span class="cb" style="background:rgba(0,0,0,.35);border-radius:6px;padding:2px 6px">'+pad(d)+'</span><b>:</b><span class="cb" style="background:rgba(0,0,0,.35);border-radius:6px;padding:2px 6px">'+pad(h)+'</span><b>:</b><span class="cb" style="background:rgba(0,0,0,.35);border-radius:6px;padding:2px 6px">'+pad(m)+'</span><b>:</b><span class="cb" style="background:rgba(0,0,0,.35);border-radius:6px;padding:2px 6px">'+pad(s2)+'</span>';}};tick();var timer=setInterval(tick,1000);});}catch(e){}}
/* v1.8: 优惠券墙领取 */
window._claimCoupon=function(cid,name){if(!cid)return;var tk=localStorage.getItem('token');if(!tk){vant.showToast('请先登录');return;}api.post('/marketing/coupon/receive',{coupon_id:cid},{headers:{Authorization:'Bearer '+tk}}).then(function(r){if(r&&r.code===0){vant.showToast('领取成功');setTimeout(renderDecor,300);}else{vant.showToast((r&&r.message)||'领取失败');}}).catch(function(){vant.showToast('网络错误');});};

function renderDecorComp(type,key,p){
  p=p||{};
  var bg=p.bg||'#fff';
  var styleBase='box-sizing:border-box;';
  if(type==='swiper'){
    var imgs=p.images||[];if(!imgs.length)return '';
    var items=imgs.map(function(im){var url=(im&&(im.url||im.image))||'';var link=(im&&im.link)||p.link||'';var inner=url?'<img src="'+esc(url)+'" style="width:100%;height:'+(p.height||150)+'px;object-fit:cover;display:block" alt="">':'<div style="height:'+(p.height||150)+'px;background:#eee;display:flex;align-items:center;justify-content:center;color:#999">📷</div>';return link?'<a href="'+esc(link)+'">'+inner+'</a>':inner;}).join('');
    return '<div class="decor-swiper"><van-swipe :autoplay="'+(p.autoplay===false?0:(p.interval||3000))+'" indicator-color="#7C3AED" style="margin:8px 12px;border-radius:8px;overflow:hidden">'+imgs.map(function(im){var url=(im&&(im.url||im.image))||'';return '<van-swipe-item><div style="width:100%;height:'+(p.height||150)+'px">'+(url?'<img src="'+esc(url)+'" style="width:100%;height:100%;object-fit:cover" alt="">':'<div style="height:100%;background:linear-gradient(135deg,#7C3AED,#A78BFA);display:flex;align-items:center;justify-content:center;color:#fff">Banner</div>')+'</div></van-swipe-item>';}).join('')+'</van-swipe></div>';
  }
  if(type==='navGroup'||type==='grid'){
    var cols=p.columns||4;var its=p.items||[];var cells=its.map(function(it){var ic=it.icon||'🔘',tx=it.text||it.label||'',lk=it.link||'';return '<div class="item" style="cursor:pointer" onclick="goEntryFromDecor(\''+esc(lk)+'\')"><div class="icon">'+esc(ic)+'</div><div class="label">'+esc(tx)+'</div></div>';}).join('');
    return '<div class="grid-'+(cols>4?cols:4)+'" style="background:'+bg+';padding:6px 12px">'+cells+'</div>';
  }
  if(type==='goodsList'){return '<div class="decor-goods-'+esc(key)+'" style="background:'+bg+';padding:8px 12px"><div style="display:grid;grid-template-columns:repeat(2,1fr);gap:10px"><div class="prod-card">加载中...</div></div></div>';}
  if(type==='promotionList'){
    var pt=p.type||'all';var pl=+(p.limit||8);
    return '<div class="decor-promo-'+esc(key)+'" data-type="'+esc(pt)+'" data-limit="'+pl+'" style="background:'+bg+';padding:12px"><div style="display:flex;align-items:center;gap:8px;margin-bottom:10px"><span style="font-size:15px;font-weight:700;color:'+esc(p.textColor||'#E67E22')+'">'+esc(p.title||'今日热促')+'</span></div><div class="promo-loading" style="text-align:center;color:#999;font-size:13px;padding:20px 0">⏳ 正在加载活动...</div></div>';
  }
  if(type==='titleBar'){
    return '<div style="background:'+bg+';padding:10px 14px 6px;display:flex;align-items:center;justify-content:space-between"><span style="font-size:15px;font-weight:700">'+esc(p.title||'')+'</span>'+(p.link?'<span style="font-size:12px;color:#999">更多 ›</span>':'')+'</div>';
  }
  if(type==='noticeBar'){
    return '<div style="background:#fff8ec;padding:8px 12px;font-size:12px;color:#8a6d3b">📢 '+esc(p.text||'')+'</div>';
  }
  if(type==='searchBox'){
    return '<div style="padding:10px 12px;background:'+bg+'"><div style="background:#f5f5f5;border-radius:18px;padding:8px 14px;font-size:13px;color:#999">🔍 '+esc(p.placeholder||'搜索商品')+'</div></div>';
  }
  if(type==='imageAd'){
    var url=p.image||'';return '<div style="padding:8px 12px;background:'+bg+'">'+(url?'<img src="'+esc(url)+'" style="width:100%;border-radius:8px;display:block" alt="">':'')+'</div>';
  }
  if(type==='video'){
    return '<div style="padding:8px 12px;background:'+bg+(p.src?'"><video src="'+esc(p.src)+'" controls style="width:100%;border-radius:8px" '+(p.autoplay?'autoplay ':'')+'playsinline"></video>':'"">')+'</div>';
  }
  if(type==='space'||type==='spacer'){return '<div style="height:'+(p.height||10)+'px;background:'+bg+'"></div>';}
  if(type==='divider'){return '<div style="height:8px;background:#f5f5f5;margin:0"></div>';}
  // ============ v1.8 新增组件 ============
  if(type==='waterfall'){
    var wfCount=+(p.count||6);
    return '<div class="decor-waterfall-'+esc(key)+'" style="background:'+bg+';padding:8px 12px"><div style="display:flex;align-items:center;gap:8px;margin-bottom:10px"><span style="font-size:15px;font-weight:700;color:#333">'+esc(p.title||'人气瀑布流')+'</span></div><div style="display:flex;gap:8px;justify-content:space-between"><div style="width:calc(50% - 4px)" class="wf-col"><div style="background:#f5f5f5;border-radius:8px;text-align:center;color:#999;padding:30px 0">⏳ 加载中</div></div><div style="width:calc(50% - 4px);margin-top:18px" class="wf-col2"><div style="background:#f5f5f5;border-radius:8px;text-align:center;color:#999;padding:30px 0">⏳ 加载中</div></div></div></div>';
  }
  if(type==='couponWall'){
    return '<div class="decor-couponwall-'+esc(key)+'" style="background:'+bg+';padding:8px 12px"><div style="display:flex;align-items:center;gap:8px;margin-bottom:10px"><span style="font-size:15px;font-weight:700;color:#333">'+esc(p.title||'领券中心')+'</span></div><div class="cw-loading" style="text-align:center;color:#999;font-size:13px;padding:20px 0">⏳ 正在加载优惠券...</div></div>';
  }
  if(type==='noticeScroll'){
    var items=p.items||[];var txt=(items&&items[0])||'公告滚动内容';var dur=+(p.speed||30);
    return '<div style="display:flex;align-items:center;gap:6px;padding:8px 12px;font-size:12px;background:'+esc(p.bgColor||'#fff8ec')+';color:'+esc(p.textColor||'#8a6d3b')+'"><span style="flex-shrink:0">📢</span><div style="flex:1;overflow:hidden;white-space:nowrap"><span class="ns-track" style="display:inline-block;animation:nsScroll '+(dur>0?dur:30)+'s linear infinite">'+esc(txt)+'</span></div></div>';
  }
  if(type==='countdownBanner'){
    return '<div class="decor-cdb-'+esc(key)+'" data-end="'+esc(p.endTime||'')+'" onclick="'+(p.link?'window.goEntryFromDecor&&goEntryFromDecor(\''+esc(p.link)+'\')':'')+'" style="margin:8px 12px;border-radius:8px;padding:20px;color:#fff;text-align:center;background:'+(p.bgImage?'url('+esc(p.bgImage)+') center/cover':'')+';background-color:'+esc(p.bgColor||'#EE6B2F')+'"><div style="font-size:18px;font-weight:700">'+esc(p.title||'限时特惠')+'</div><div style="font-size:12px;opacity:.9;margin:4px 0 10px">'+esc(p.subtitle||'')+'</div><div class="cdb-clock" style="display:flex;align-items:center;justify-content:center;gap:4px;font-size:15px"><span class="cb" style="background:rgba(0,0,0,.35);border-radius:6px;padding:2px 6px">00</span><b>:</b><span class="cb" style="background:rgba(0,0,0,.35);border-radius:6px;padding:2px 6px">00</span><b>:</b><span class="cb" style="background:rgba(0,0,0,.35);border-radius:6px;padding:2px 6px">00</span><b>:</b><span class="cb" style="background:rgba(0,0,0,.35);border-radius:6px;padding:2px 6px">00</span></div></div>';
  }
  if(type==='categoryGrid'){
    var cgCols=p.columns||4;
    return '<div class="decor-categrid-'+esc(key)+'" data-cols="'+cgCols+'" style="background:'+bg+';padding:8px 12px"><div class="cg-loading" style="text-align:center;color:#999;font-size:13px;padding:20px 0">⏳ 正在加载分类...</div></div>';
  }
  return '';
}
window.goEntryFromDecor=function(link){if(!link)return;var page=switchTab;try{page(link.replace(/^\//,''));}catch(e){window.location.href=link;}};

const orderStatusTabs={all:'全部',pending_pay:'待付款',pending_ship:'待发货',shipped:'已发货',received:'已收货',completed:'已完成'};/*** 购物车总计（选中商品）*/const cartTotal=computed(()=>cart.value.filter(c=>c.selected).reduce((s,c)=>s+(+c.price||0)*(c.quantity||1),0));/*** 购物车选中商品数量*/const cartSelectedCount=computed(()=>cart.value.filter(c=>c.selected).length);/*** 筛选后的评价列表*/const filteredReviews=computed(()=>{let list=[...reviewList.value];if(reviewFilter.tag!=='all'){list=list.filter(r=>r.rating!==undefined&&(reviewFilter.tag==='good'?r.rating>=4:reviewFilter.tag==='neutral'?r.rating===3:r.rating<=2));}if(reviewFilter.hasImage){list=list.filter(r=>r.images&&r.images.length>0);}return list;});/*** 订单状态标签映射*/const statusLabel=s=>orderStatusTabs[s]||s;/*** 安全的价格格式化*/function formatPrice(price){const num=Number(price);return isNaN(num)||num===0?'0.00':num.toFixed(2);}/*** 防抖函数*/function debounce(fn,delay){let timer=null;return function(...args){if(timer)clearTimeout(timer);timer=setTimeout(()=>fn.apply(this,args),delay);};}const debouncedCartUpdate=debounce(function(){},300);/*** 统一页面切换*/function switchTab(target){page.value=target;track('visit',target);if(target==='home'||target==='category'||target==='cart'||target==='user'){var dp={home:'home',category:'category',cart:'cart',user:'mine'}[target]||'home';decor.currentPage=dp;if(!decor.pages[dp]||decor.pages[dp].length===0){decor.enabled=false;loadDecor(dp);}else{decor.enabled=true;decor.components=decor.pages[dp];renderDecor();setTimeout(renderDecor,50);}}if(target==='cart')loadCart();if(target==='orders')page.value='orders',orderPage.value=1,orderFinished.value=false,loadOrders();if(target==='category')loadCategories();var MM=window.MobileModules;if(MM){var modTargets={seckill:['seckill','#seckill-module-container'],checkin:['checkin','#checkin-module-container'],membership:['membership','#membership-module-container'],distribution:['distribution','#distribution-module-container'],exchange:['exchange','#exchange-module-container'],recharge:['recharge','#recharge-module-container'],'group-buy':['group-buy','#group-buy-module-container'],notification:['notification','#notification-module-container'],'browse-history':['browse-history','#browse-history-module-container'],'presale':['presale','#ps-module-container'],'bargain':['bargain','#bargain-module-container'],'promotion':['promotion','#promotion-module-container'],'aftersale':['aftersale','#aftersale-module-container']};if(modTargets[target]){var mt=modTargets[target];try{MM.load(mt[0],mt[1],{api:api,token:token.value,Vue:Vue,vant:vant,formatPrice:formatPrice,page:page,primaryColor:'#7C3AED',goProduct:goProduct,userId:(user.value&&user.value.id)||'',userPhone:(user.value&&user.value.phone)||'',userNickname:(user.value&&user.value.nickname)||''}).catch(function(e){console.error(e)});}catch(e){console.error(e)}}}if(target==='seckill'&&window.MobileModules){try{MobileModules.load('seckill','#seckill-module-container',{api:api,token:token.value,Vue:Vue,vant:vant,formatPrice:formatPrice,primaryColor:'#7C3AED'}).catch(function(e){console.error(e)});}catch(e){console.error(e)}}if(target==='checkin'&&window.MobileModules){try{MobileModules.load('checkin','#checkin-module-container',{api:api,token:token.value,Vue:Vue,vant:vant,formatPrice:formatPrice,page:page,primaryColor:'#7C3AED'}).catch(function(e){console.error(e)});}catch(e){console.error(e)}}}/*** 加载首页Banner*/async function loadBanners(){try{const r=await api.get('/banner/list');if(r.code===0)banners.value=r.data||[];}catch(e){}}/*** 加载首页推荐商品*/async function loadProducts(){try{const r=await api.get('/product/list',{params:{pageSize:10}});if(r.code===0)products.value=r.data.list||[];}catch(e){}}/*** 加载分类列表*/async function loadCategories(){try{const r=await api.get('/category/list');if(r.code===0){categories.value=r.data||[];if(categories.value.length)selectCategory(selectedCategoryIndex.value);}}catch(e){}}/*** 选择分类*/async function selectCategory(idx){selectedCategoryIndex.value=idx;const c=categories.value[idx];if(!c)return;try{const r=await api.get('/product/list',{params:{category_id:c.id,pageSize:50}});if(r.code===0)categoryProducts.value=r.data.list||[];else categoryProducts.value=[];}catch(e){categoryProducts.value=[];}}/*** 跳转到分类页*/function goCategory(c){page.value='category';selectedCategoryIndex.value=categories.value.indexOf(c);if(categories.value.length)selectCategory(selectedCategoryIndex.value);}/*** 加载我的优惠券*/async function loadUserCoupons(){if(!token.value)return;try{const r=await api.get('/coupon/user',{params:{status:couponTab.value},headers:{Authorization:'Bearer '+token.value}});if(r.code===0)userCoupons.value=r.data||[];else userCoupons.value=[];}catch(e){userCoupons.value=[];}}/*** 加载积分*/async function loadPoints(){if(!token.value)return;try{const rb=await api.get('/user/points',{headers:{Authorization:'Bearer '+token.value}});if(rb.code===0){pointsData.value={balance:rb.data.points||0,total:rb.data.total_points||0};}const rl=await api.get('/user/points/logs',{headers:{Authorization:'Bearer '+token.value}});if(rl.code===0)pointsLogs.value=rl.data.list||[];}catch(e){pointsLogs.value=[];}}/*** 积分类型文案*/function pointsTypeText(t){return ({sign:'每日签到',order_reward:'消费送积分',redeem:'积分兑换',deduct:'积分抵现',recharge:'充值赠送',admin:'后台调整',refund:'积分返还'})[t]||t;}function goPointsPage(){loadPoints();page.value='points';}/*** 加载购物车数据*/async function loadCart(){if(!token.value)return;try{const r=await api.get('/cart/list',{headers:{Authorization:'Bearer '+token.value}});if(r.code===0){cart.value=(r.data||[]).map(c=>({...c,selected:true}));calcCart();}}catch(e){}}/*** 计算全选状态*/function calcCart(){cartAll.value=cart.value.length>0&&cart.value.every(c=>c.selected);}/*** 切换全选*/function toggleAll(){cart.value.forEach(c=>c.selected=cartAll.value);}/*** 更新购物车*/async function updateCart(){}/*** 清空购物车*/async function clearCart(){if(!token.value)return;cart.value=[];await api.delete('/cart/clear',{headers:{Authorization:'Bearer '+token.value}}).catch(()=>{});}/*** 删除购物车单项*/async function removeCartItem(index){const item=cart.value[index];if(!item)return;try{await api.post('/cart/remove',{cart_id:item.id||item.cart_id},{headers:{Authorization:'Bearer '+token.value}});}catch(e){}cart.value.splice(index,1);calcCart();vant.showToast('已删除');}/*** 跳转到商品详情*/async function goProduct(id){page.value='product';track('product_view','product',id);detail.value={};reviewFilter.tag='all';reviewFilter.hasImage=false;try{const r=await api.get('/product/detail/'+id);if(r.code===0)detail.value=r.data;await loadReviews(id);}catch(e){}}/*** 从详情返回首页*/function goBackHome(){page.value='home';}

function goEntryPage(e){var needLogin=['distribution','exchange','recharge','notification','browse-history','membership','checkin','aftersale'];var MM=window.MobileModules;if(needLogin.indexOf(e.p)>-1&&!token.value){page.value='login';vant.showToast('请先登录');return;}if(MM){var conts={seckill:'#seckill-module-container',checkin:'#checkin-module-container',membership:'#membership-module-container',distribution:'#distribution-module-container',exchange:'#exchange-module-container',recharge:'#recharge-module-container','group-buy':'#group-buy-module-container',notification:'#notification-module-container','browse-history':'#browse-history-module-container','presale':'#ps-module-container','bargain':'#bargain-module-container','promotion':'#promotion-module-container','aftersale':'#aftersale-module-container'};if(conts[e.p]){page.value=e.p;try{MM.load(e.p,conts[e.p],{api:api,token:token.value,Vue:Vue,vant:vant,formatPrice:formatPrice,page:page,primaryColor:'#7C3AED',goProduct:goProduct,userId:(user.value&&user.value.id)||'',userPhone:(user.value&&user.value.phone)||'',userNickname:(user.value&&user.value.nickname)||''}).catch(function(){});}catch(e){}}return;}if(e.p==='seckill'){page.value='seckill';if(window.MobileModules)MobileModules.load('seckill','#seckill-module-container',{api:api,token:token.value,Vue:Vue,vant:vant,formatPrice:formatPrice,primaryColor:'#7C3AED'}).catch(function(){});}else if(e.p==='checkin'){page.value='checkin';if(window.MobileModules)MobileModules.load('checkin','#checkin-module-container',{api:api,token:token.value,Vue:Vue,vant:vant,formatPrice:formatPrice,page:page,primaryColor:'#7C3AED'}).catch(function(){});}else if(e.p==='coupon'){if(!token.value){page.value='login';vant.showToast('请先登录');return;}page.value='coupon-list';loadUserCoupons();}else if(e.p==='group-buy'){page.value='group-buy';if(window.MobileModules)MobileModules.load('group-buy','#group-buy-module-container',{api:api,token:token.value,Vue:Vue,vant:vant,formatPrice:formatPrice,page:page,primaryColor:'#7C3AED',goProduct:goProduct}).catch(function(){});}else{page.value='category';loadCategories();}return;}/*** 打开规格选择器*/function showSpecSelector(action){if(!token.value){page.value='login';return;}specAction.value=action;specQuantity.value=1;selectedSpec.value=0;if(detail.value.specs&&detail.value.specs.length){specOptions.value=detail.value.specs.map(s=>({label:s.name||s,disabled:false}));}specVisible.value=true;}/*** 确认规格选择*/async function confirmSpec(){specConfirmLoading.value=true;specVisible.value=false;const productId=detail.value.id;const qty=specQuantity.value;if(specAction.value==='cart'){await addCartItem(productId,qty);}else{await buyNowAction(productId,qty);}specConfirmLoading.value=false;}/*** 加入购物车*/async function addCartItem(productId,qty){cartLoading.value=true;try{const r=await api.post('/cart/add',{product_id:productId,quantity:qty||1,spec:specOptions.value[selectedSpec.value]?.label||''},{headers:{Authorization:'Bearer '+token.value}});if(r.code===0){vant.showToast('已加入购物车');}else{vant.showToast(r.message||'添加失败');}}catch(e){vant.showToast('添加失败');}cartLoading.value=false;}/*** 立即购买*/async function buyNowAction(productId,qty){try{const r=await api.post('/order/create',{items:[{product_id:productId,quantity:qty||1,spec:specOptions.value[selectedSpec.value]?.label||''}]},{headers:{Authorization:'Bearer '+token.value}});if(r.code===0){vant.showToast('下单成功');page.value='orders';orderPage.value=1;orderFinished.value=false;loadOrders();if(r.data&&r.data.pay_url){window.location.href=r.data.pay_url;}}else{vant.showToast(r.message||'下单失败');}}catch(e){vant.showToast('下单失败');}}async function addCart(){showSpecSelector('cart');}async function buyNow(){showSpecSelector('buy');}/*** 登录*/async function doLogin(){if(!loginForm.phone||!loginForm.password){vant.showToast('请填写完整信息');return;}loginLoading.value=true;try{const r=await api.post('/user/login',loginForm);if(r.code===0){token.value=r.data.token;localStorage.setItem('token',r.data.token);user.value=r.data.user||{};window.__tuidd=(r.data.user&&r.data.user.id)||0;page.value='home';loadCart();vant.showToast('登录成功');}else{vant.showToast(r.message||'登录失败');}}catch(e){vant.showToast('网络错误，请稍后重试');}loginLoading.value=false;}/*** 注册*/async function doRegister(){if(!regForm.phone||!regForm.password){vant.showToast('请填写完整');return;}if(regForm.password.length<6){vant.showToast('密码至少6位');return;}regLoading.value=true;try{const r=await api.post('/user/register',regForm);if(r.code===0){vant.showToast('注册成功');page.value='login';}else{vant.showToast(r.message||'注册失败');}}catch(e){vant.showToast('网络错误');}regLoading.value=false;}/*** 加载订单列表*/async function loadOrders(){if(!token.value){orderLoadingMore.value=false;orderFinished.value=true;return;}if(orderLoadingMore.value)return; orderLoadingMore.value=true;try{const params={page:orderPage.value,pageSize:10};if(orderTab.value!=='all')params.status=orderTab.value;const r=await api.get('/order/list',{params,headers:{Authorization:'Bearer '+token.value}});if(r.code===0){const list=r.data.list||[];if(orderPage.value===1){orderList.value=list;}else{orderList.value=[...orderList.value,...list];}orderFinished.value=list.length<10;if(!orderFinished.value)orderPage.value++;}else{orderFinished.value=true;}}catch(e){orderFinished.value=true;}orderLoadingMore.value=false;}/*** 去支付*/function payOrder(order){if(order.pay_url){window.location.href=order.pay_url;}else{vant.showToast('支付通道暂未开放');}}/*** 去评价*/function goReview(order){reviewTargetOrder.value=order;page.value='review-list';}/*** 去追评*/function goFollowUp(order){followUpTarget.value=order;followUpContent.value='';followUpImages.value=['','',''];page.value='follow-up';}/*** 申请售后(打开售后模块并弹申请框)*/function goAfterSaleApply(order){if(!order||!order.id){vant.showToast('订单无效');return;}page.value='aftersale';try{if(window.MobileModules){window.MobileModules.load('aftersale','#aftersale-module-container',{api:api,token:token.value,Vue:Vue,vant:vant,formatPrice:formatPrice,page:page,primaryColor:'#7C3AED',goProduct:goProduct}).then(function(){if(window.MobileModules&&window.__asApply){window.__asApply(order);}}).catch(function(){});}}catch(e){}}/*** 进入结算页*/async function checkout(){const items=cart.value.filter(c=>c.selected);if(!items.length){vant.showToast('请选择商品');return;}checkoutItems.value=items;checkoutTotal.value=cartTotal.value;selectedAddress.value=null;selectedCoupon.value=null;page.value='checkout';await loadAddressList();await loadCouponList();}/*** 加载收货地址列表*/async function loadAddressList(){try{const r=await api.get('/address/list',{headers:{Authorization:'Bearer '+token.value}});if(r.code===0)addressList.value=r.data||[];}catch(e){}}/*** 显示地址选择弹窗*/function showAddressSelector(){addressPopup.value=true;}/*** 选择地址*/function selectAddress(addr){selectedAddress.value=addr;addressPopup.value=false;}/*** 加载优惠券列表*/async function loadCouponList(){try{const r=await api.get('/coupon/list',{headers:{Authorization:'Bearer '+token.value}});if(r.code===0)couponList.value=r.data||[];}catch(e){}}/*** 显示优惠券选择弹窗*/function showCouponSelector(){couponPopup.value=true;}/*** 选择优惠券*/function selectCoupon(cp){if(selectedCoupon.value===cp){selectedCoupon.value=null;}else{selectedCoupon.value=cp;}couponPopup.value=false;const discount=selectedCoupon.value?Number(selectedCoupon.value.amount||0):0;checkoutTotal.value=Math.max(0,cartTotal.value-discount);}/*** 提交订单*/async function submitOrder(){if(!selectedAddress.value){vant.showDialog({title:'提示',message:'请选择收货地址'});return;}orderLoading.value=true;try{const items=checkoutItems.value.map(c=>({product_id:c.product_id||c.id,quantity:c.quantity||1}));const r=await api.post('/order/create',{items,address_id:selectedAddress.value.id,coupon_id:selectedCoupon.value?.id||null},{headers:{Authorization:'Bearer '+token.value}});if(r.code===0){vant.showToast('下单成功');cart.value=[];page.value='orders';orderPage.value=1;orderFinished.value=false;loadOrders();}else{vant.showToast(r.message||'下单失败');}}catch(e){vant.showToast('网络错误');}orderLoading.value=false;}/*** 发送客服消息*/async function sendChat(){const t=chatInput.value.trim();if(!t||chatLoading.value)return;chatInput.value='';chatMsgs.value.push({role:'user',content:t});chatLoading.value=true;try{if(!chatConvId.value){const cr=await api.post('/ai/conversation',{},{headers:{Authorization:'Bearer '+token.value}});if(cr.code===0)chatConvId.value=cr.data.id;}const r=await api.post('/ai/message',{conversation_id:chatConvId.value,content:t},{headers:{Authorization:'Bearer '+token.value}});if(r.code===0&&r.data.reply){chatMsgs.value.push({role:'assistant',content:r.data.reply});}}catch(e){chatMsgs.value.push({role:'assistant',content:'抱歉，我暂时无法回复，请稍后再试。'});}chatLoading.value=false;}/*** 加载商品评价*/async function loadReviews(productId){try{const r=await api.get('/review/list/'+productId);if(r.code===0){const data=r.data||{};reviewList.value=data.list||data.reviews||[];reviewStats.value=data.stats||{avgScore:calcAvgScore(reviewList.value),total:reviewList.value.length,good:reviewList.value.filter(r=>r.rating>=4).length,neutral:reviewList.value.filter(r=>r.rating===3).length,bad:reviewList.value.filter(r=>r.rating<=2).length};}}catch(e){}}/*** 计算评价平均分*/function calcAvgScore(list){if(!list||!list.length)return 0;const total=list.reduce((s,r)=>s+(r.rating||0),0);return Number((total/list.length).toFixed(1));}/*** 显示全部评价*/function showAllReviews(){vant.showToast('查看完整评价列表');}/*** 切换评价点赞*/async function toggleReviewLike(rv){try{const r=await api.post('/review/like',{review_id:rv.id},{headers:{Authorization:'Bearer '+token.value}});if(r.code===0){rv.liked=!rv.liked;rv.like_count=(rv.like_count||0)+(rv.liked?1:-1);}}catch(e){}}/*** 图片预览*/function previewImage(images,index){previewImages.value=images;previewImageIndex.value=index;}function closePreview(){previewImages.value=[];}function prevImage(){if(previewImageIndex.value>0)previewImageIndex.value--;}function nextImage(){if(previewImageIndex.value<previewImages.value.length-1)previewImageIndex.value++;}/*** 打开评价编辑器*/function openReviewEditor(item){reviewTargetItem.value=item;reviewForm.rating=5;reviewForm.content='';reviewForm.images=[];reviewEditorVisible.value=true;}/*** 处理评价图片上传*/function handleReviewImageUpload(idx,e){const file=e.target.files[0];if(!file)return;const reader=new FileReader();reader.onload=(ev)=>{reviewForm.images[idx]=ev.target.result;};reader.readAsDataURL(file);}/*** 提交评价*/async function submitReview(){if(!reviewForm.content.trim()){vant.showToast('请填写评价内容');return;}reviewSubmitting.value=true;try{const r=await api.post('/order/review',{order_no:reviewTargetOrder.value?.order_no,product_id:reviewTargetItem.value?.product_id||reviewTargetItem.value?.id,rating:reviewForm.rating,content:reviewForm.content,images:reviewForm.images.filter(Boolean)},{headers:{Authorization:'Bearer '+token.value}});if(r.code===0){vant.showToast('评价成功');reviewEditorVisible.value=false;if(reviewTargetItem.value)reviewTargetItem.value._reviewed=true;}else{vant.showToast(r.message||'评价提交失败');}}catch(e){vant.showToast('网络错误');}reviewSubmitting.value=false;}/*** 提交追评*/async function submitFollowUp(){if(!followUpContent.value.trim()){vant.showToast('请填写追评内容');return;}followUpLoading.value=true;try{const r=await api.post('/review/follow-up',{order_no:followUpTarget.value?.order_no,content:followUpContent.value,images:followUpImages.value.filter(Boolean)},{headers:{Authorization:'Bearer '+token.value}});if(r.code===0){vant.showToast('追评成功');page.value='orders';}else{vant.showToast(r.message||'提交失败');}}catch(e){vant.showToast('网络错误');}followUpLoading.value=false;}function addFollowUpImage(idx){vant.showToast('请选择图片');}/*** 退出登录*/function logout(){vant.showDialog({title:'提示',message:'确定退出登录吗？',showCancelButton:true,}).then((res)=>{if(res==='confirm'){token.value='';localStorage.removeItem('token');user.value={};page.value='home';vant.showToast('已退出');}});}onMounted(async ()=>{try{await Promise.all([loadBanners(),loadProducts(),loadDecor()]);}catch(e){}var sk=document.getElementById('skel-loader');if(sk)sk.style.display='none';if(token.value){loadCart();loadOrders();}loadCategories();/* 检查URL参数指定的初始页（小程序壳传入）*/var _ip=sessionStorage.getItem('_initPage');if(_ip){sessionStorage.removeItem('_initPage');var _ipid=sessionStorage.getItem('_initProductId');if(_ipid){sessionStorage.removeItem('_initProductId');goProduct(_ipid);}else{switchTab(_ip);}}/* 砍价分享深链: #/bargain?session_no=xxx */var _bh=(location.hash.match(/#\/bargain(\?.*)?/)||[])[0];if(_bh){page.value='bargain';if(window.MobileModules){var _bs=(new URLSearchParams(_bh.split('?')[1]||'')).get('session_no')||'';try{window.MobileModules.load('bargain','#bargain-module-container',{api:api,token:token.value,Vue:Vue,vant:vant,formatPrice:formatPrice,page:page,primaryColor:'#7C3AED',shareBase:'/mobile/',userId:(user.value&&user.value.id)||'',userPhone:(user.value&&user.value.phone)||'',userNickname:(user.value&&user.value.nickname)||'',sessionNo:_bs}).catch(function(e){console.error(e)});}catch(e){console.error(e)}}}else if((new URLSearchParams(location.search)).get('p')==='bargain'&&!['bargain'].includes(page.value)){switchTab('bargain');}});watch(page,function(nv){if(nv==='coupon-list'&&token.value)loadUserCoupons();});return{page,homeLoading,entries,banners,decor,products,cart,cartAll,cartTotal,cartSelectedCount,user,pointsData,pointsLogs,pointsTypeText,goPointsPage,loadPoints,token,loginForm,loginLoading,regForm,regLoading,detail,cartLoading,specVisible,specOptions,selectedSpec,specQuantity,specConfirmLoading,orderList,orderLoading,orderLoadingMore,orderFinished,orderTab,orderStatusTabs,checkoutItems,checkoutTotal,addressList,selectedAddress,addressPopup,couponList,selectedCoupon,couponPopup,chatInput,chatMsgs,chatLoading,reviewList,reviewStats,reviewFilter,filteredReviews,reviewEditorVisible,reviewForm,reviewTargetOrder,reviewTargetItem,reviewSubmitting,followUpTarget,followUpContent,followUpImages,followUpLoading,previewImages,previewImageIndex,switchTab,loadBanners,loadProducts,loadCart,calcCart,toggleAll,updateCart,clearCart,removeCartItem,goProduct,goBackHome,goEntryPage,addCart,buyNow,showSpecSelector,confirmSpec,doLogin,doRegister,logout,loadOrders,payOrder,goReview,goFollowUp,goAfterSaleApply,checkout,submitOrder,loadAddressList,showAddressSelector,selectAddress,loadCouponList,showCouponSelector,selectCoupon,sendChat,loadReviews,showAllReviews,toggleReviewLike,previewImage,closePreview,prevImage,nextImage,openReviewEditor,handleReviewImageUpload,submitReview,submitFollowUp,addFollowUpImage,formatPrice,statusLabel,categories,selectedCategoryIndex,categoryProducts,selectCategory,goCategory,loadCategories,userCoupons,couponTab,couponTabs,loadUserCoupons}}});app.use(vant).mount('#app');

// ====== 稳定性兜底 ======
setTimeout(function() {
  document.querySelectorAll('.loading, .skeleton-home, [class*=loading]').forEach(function(el) {
    if (getComputedStyle(el).display !== 'none') el.style.display = 'none';
  });
}, 10000);
window.addEventListener('error', function(e) { return true; });
window.addEventListener('unhandledrejection', function(e) { e.preventDefault(); });
</script>

<div class="lm-copyright" style="text-align:center;padding:16px 0;font-size:12px;color:#999;border-top:1px solid #eee;margin-top:20px;background:#fafafa;clear:both;">
  Powered By 省胜优铺商城 | 版权所有 &copy; 2026 保留一切权利 免费商用禁止移除版权
  <span class="lm-copyright-hash" style="display:none;">a1b2c3d4</span>
</div>
<script>(function(){function c(){var e=document.querySelector(".lm-copyright"),h=document.querySelector(".lm-copyright-hash");if(!e||!h)return;var t=e.textContent.trim().replace(/\s+/g,"");if(t.indexOf("省胜优铺商城")===-1||t.indexOf("免费商用禁止移除版权")===-1){var w=document.createElement("div");w.style.cssText="position:fixed;top:0;left:0;right:0;z-index:99999;background:#e0245e;color:#fff;text-align:center;padding:8px;font-size:13px;font-weight:600";w.textContent="系统版权信息异常，请重新安装正版授权";document.body.insertBefore(w,document.body.firstChild)}}document.readyState==="complete"?setTimeout(c,1e3):window.addEventListener("load",function(){setTimeout(c,1e3)});setInterval(c,3e4)})();</script>

<script>(function(){'use strict';var C={CHECK_INTERVAL:15000,b3:'#e0245e',WARN_FG:'#ffffff',b2:2147483647,KW:[String.fromCharCode(40847,34428,76,105,116,101,21830,22478),String.fromCharCode(20813,36153,21830,29992,31105,27490,31227,29256,26435)]};function T(){var e=document.querySelector('.lm-copyright'),h=document.querySelector('.lm-copyright-hash');if(!e||!h)return {t:true,r:'版权DOM已被移除'};var t=(e.textContent||e.innerText||'').replace(/\s+/g,'');for(var i=0;i<C.KW.length;i++){if(t.indexOf(C.KW[i])===-1)return {t:true,r:'版权文案被篡改: 缺少"'+C.KW[i]]+'"'};}if(h.textContent!=='a1b2c3d4')return {t:true,r:'版权校验码异常'};return {t:false};}var L=null,B=false;function S(r){if(L&&L.parentNode)L.parentNode.removeChild(L);L=document.createElement('div');L.id='lm-block';L.style.cssText='position:fixed;top:0;left:0;right:0;bottom:0;z-index:'+C.b2+';background:rgba(0,0,0,0.85);display:flex;flex-direction:column;align-items:center;justify-content:center;font-family:"PingFang SC","Microsoft YaHei",sans-serif';var ic=document.createElement('div');ic.textContent='⚠️';ic.style.cssText='font-size:64px;margin-bottom:16px;';L.appendChild(ic);var ti=document.createElement('div');ti.textContent='版权标识不可移除';ti.style.cssText='font-size:22px;font-weight:700;color:white;margin-bottom:12px;';L.appendChild(ti);var de=document.createElement('div');de.textContent='违规操作已记录，系统将限制核心功能使用';de.style.cssText='font-size:14px;color:rgba(255,255,255,0.8);margin-bottom:20px;text-align:center;line-height:1.6;padding:0 30px;';L.appendChild(de);var er=document.createElement('div');er.textContent='原因: '+(r||'版权信息异常');er.style.cssText='font-size:12px;color:rgba(255,255,255,0.5);margin-bottom:24px;';L.appendChild(er);var bw=document.createElement('div');bw.style.cssText='display:flex;gap:12px;';var bc=document.createElement('button');bc.textContent='我知道了';bc.style.cssText='padding:10px 32px;border:none;border-radius:24px;background:#e0245e;color:white;font-size:15px;cursor:pointer;font-weight:600';bc.onclick=function(){if(L&&L.parentNode){L.style.display='none';setTimeout(function(){S(r);},12*60*1000);}};bw.appendChild(bc);L.appendChild(bw);var gu=document.createElement('div');gu.textContent='请重新安装正版授权包覆盖';gu.style.cssText='font-size:12px;color:rgba(255,255,255,0.3);margin-top:24px;';L.appendChild(gu);document.body.appendChild(L);}function X(){var F=window.fetch;if(F){window.fetch=function(){var u=arguments[0]||'',s=typeof u==='string'?u:(u.url||'');if(s.indexOf('/api/order/create')!==-1||s.indexOf('/api/payment/create')!==-1||s.indexOf('/api/review/create')!==-1||s.indexOf('/api/review/follow-up')!==-1){console.warn('[LM]功能已禁用');return Promise.resolve(new Response(JSON.stringify({code:1,message:'系统版权异常，功能暂不可用'}),{status:200,headers:{'Content-Type':'application/json'}}));}return F.apply(this,arguments);};}var O=XMLHttpRequest.prototype.open;XMLHttpRequest.prototype.open=function(){var u=arguments[1]||'';if(u.indexOf('/api/order')!==-1||u.indexOf('/api/payment')!==-1||u.indexOf('/api/review')!==-1){this._lmB=true;}return O.apply(this,arguments);};var Q=XMLHttpRequest.prototype.send;XMLHttpRequest.prototype.send=function(){if(this._lmB){console.warn('[LM]请求被版权保护拦截');Object.defineProperty(this,'readyState',{value:4});Object.defineProperty(this,'status',{value:200});Object.defineProperty(this,'responseText',{value:JSON.stringify({code:1,message:'版权异常，功能暂不可用'})});if(this.onreadystatechange)this.onreadystatechange();if(this.onload)this.onload();return;}return Q.apply(this,arguments);};}var D=null;function M(){var r=T();if(r.t){B=true;S(r.r);X();return;}D=setInterval(function(){var r2=T();if(r2.t&&!B){B=true;clearInterval(D);S(r2.r);X();}},C.CHECK_INTERVAL);var CI=window.clearInterval;window.clearInterval=function(id){if(id===D){D=setInterval(function(){var r3=T();if(r3.t&&!B){B=true;S(r3.r);X();}},C.CHECK_INTERVAL);return;}return CI.apply(this,arguments);};}if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',M);else M();if(document.readyState!=='complete')window.addEventListener('load',function(){if(!D&&!B)M();});})();</script>
<script src="/lib/mobile-modules.js"></script>
</body>
</html>
