取消订单页面第一版本edit icon

创建者:
Kitty
Fork(复制)
下载
嵌入
BUG反馈
index.html
style.css
index.js
md
项目介绍.md
index.html
            
            <!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>退款取消订单</title>
  <style>
    :root {
      --bg: #fef8f8;
      --card-bg: #ffffff;
      --primary: #d32f2f;
      --primary-light: #ef5350;
      --primary-dark: #b71c1c;
      --accent: #ff5252;
      --text: #2c1818;
      --muted: #6e4b4b;
      --border: #f1d4d4;
      --shadow: rgba(211, 47, 47, 0.1);
      --success: #43a047;
      --warning: #ff9800;
      --radius-sm: 8px;
      --radius-md: 12px;
      --radius-lg: 16px;
    }
    
    * { 
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    
    html, body {
      height: 100%;
      margin: 0;
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "PingFang SC", "Microsoft YaHei", sans-serif;
      color: var(--text);
      background: linear-gradient(135deg, #fff8f8 0%, #ffecec 100%);
      line-height: 1.5;
    }
    
    .app {
      min-height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 16px;
    }
    
    .card {
      width: 100%;
      max-width: 1000px;
      background: var(--card-bg);
      border-radius: var(--radius-lg);
      box-shadow: 0 10px 40px var(--shadow);
      overflow: hidden;
      border: 1px solid var(--border);
    }
    
    .card-header {
      background: linear-gradient(90deg, var(--primary) 0%, var(--primary-light) 100%);
      color: white;
      padding: 20px 24px;
    }
    
    .card-title {
      font-size: 22px;
      font-weight: 700;
      display: flex;
      align-items: center;
      gap: 10px;
    }
    
    .card-title-icon {
      width: 24px;
      height: 24px;
      fill: white;
    }
    
    .card-subtitle {
      font-size: 14px;
      opacity: 0.9;
      margin-top: 4px;
    }
    
    .card-body {
      padding: 24px;
    }
    
    .section {
      margin-bottom: 28px;
    }
    
    .section-title {
      font-size: 17px;
      font-weight: 600;
      margin-bottom: 16px;
      color: var(--primary-dark);
      display: flex;
      align-items: center;
      gap: 8px;
    }
    
    .section-title::before {
      content: "";
      display: block;
      width: 4px;
      height: 16px;
      background-color: var(--primary);
      border-radius: 2px;
    }
    
    .policy-box {
      background: #fff9f9;
      border: 1px solid var(--border);
      border-radius: var(--radius-md);
      padding: 16px;
      margin-bottom: 24px;
      font-size: 14px;
      line-height: 1.6;
      color: var(--muted);
    }
    
    .form-grid {
      display: grid;
      grid-template-columns: 1fr;
      gap: 20px;
      margin-bottom: 24px;
    }
    
    @media (min-width: 768px) {
      .form-grid {
        grid-template-columns: repeat(2, 1fr);
      }
    }
    
    .form-field {
      display: flex;
      flex-direction: column;
      gap: 8px;
    }
    
    .form-label {
      font-size: 14px;
      font-weight: 500;
      color: var(--muted);
    }
    
    select, input, textarea {
      width: 100%;
      padding: 12px 16px;
      border: 1px solid var(--border);
      border-radius: var(--radius-md);
      font-size: 15px;
      background: #fffefe;
      transition: all 0.2s ease;
      color: var(--text);
    }
    
    select:focus, input:focus, textarea:focus {
      outline: none;
      border-color: var(--accent);
      box-shadow: 0 0 0 3px rgba(255, 82, 82, 0.2);
    }
    
    textarea {
      min-height: 100px;
      resize: vertical;
    }
    
    .products-grid {
      display: grid;
      grid-template-columns: 1fr;
      gap: 12px;
    }
    
    @media (min-width: 640px) {
      .products-grid {
        grid-template-columns: repeat(2, 1fr);
      }
    }
    
    .product-card {
      display: grid;
      grid-template-columns: auto 1fr auto;
      gap: 14px;
      align-items: center;
      border: 1px solid var(--border);
      border-radius: var(--radius-md);
      padding: 14px;
      background: #fffefe;
      transition: all 0.2s ease;
    }
    
    .product-card:hover {
      border-color: var(--accent);
      box-shadow: 0 4px 12px var(--shadow);
    }
    
    .product-image {
      width: 70px;
      height: 70px;
      object-fit: cover;
      border-radius: var(--radius-sm);
      border: 1px solid var(--border);
    }
    
    .product-info {
      display: flex;
      flex-direction: column;
      gap: 6px;
    }
    
    .product-name {
      font-weight: 600;
      font-size: 15px;
    }
    
    .product-sku {
      font-size: 12px;
      color: var(--muted);
    }
    
    .product-controls {
      display: flex;
      align-items: center;
      gap: 10px;
      flex-wrap: wrap;
    }
    
    .product-price {
      font-weight: 700;
      color: var(--primary-dark);
      font-size: 16px;
      text-align: right;
    }
    
    .checkbox-label {
      display: flex;
      align-items: center;
      gap: 6px;
      font-size: 14px;
      cursor: pointer;
    }
    
    .checkbox-label input[type="checkbox"] {
      width: 16px;
      height: 16px;
      accent-color: var(--primary);
    }
    
    .qty-input {
      width: 70px;
      padding: 6px 8px;
      text-align: center;
    }
    
    /* 金额汇总区域 */
    .amount-summary {
      background: #fff9f9;
      border: 1px solid var(--border);
      border-radius: var(--radius-md);
      padding: 20px;
      margin-top: 24px;
    }
    
    .amount-row {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 10px 0;
      border-bottom: 1px dashed var(--border);
    }
    
    .amount-row:last-child {
      border-bottom: none;
      padding-bottom: 0;
    }
    
    .amount-row.total-row {
      border-top: 2px solid var(--border);
      padding-top: 16px;
      margin-top: 8px;
    }
    
    .amount-label {
      font-size: 15px;
      color: var(--muted);
    }
    
    .amount-value {
      font-weight: 600;
      color: var(--text);
    }
    
    .total-amount {
      font-size: 24px;
      font-weight: 800;
      color: var(--primary-dark);
    }
    
    /* 附加费区域 */
    .fees-grid {
      display: grid;
      grid-template-columns: 1fr;
      gap: 12px;
    }
    
    @media (min-width: 640px) {
      .fees-grid {
        grid-template-columns: repeat(2, 1fr);
      }
    }
    
    .fee-item {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 14px;
      border: 1px solid var(--border);
      border-radius: var(--radius-md);
      background: #fffefe;
    }
    
    .fee-info {
      display: flex;
      flex-direction: column;
      gap: 4px;
    }
    
    .fee-name {
      font-weight: 500;
      font-size: 14px;
    }
    
    .fee-desc {
      font-size: 12px;
      color: var(--muted);
    }
    
    .fee-amount {
      display: flex;
      align-items: center;
      gap: 12px;
    }
    
    .fee-input {
      width: 100px;
      text-align: right;
    }
    
    /* 降价退款区域 */
    .price-drop-info {
      display: grid;
      grid-template-columns: 1fr;
      gap: 16px;
      background: #fff9f9;
      border: 1px solid var(--border);
      border-radius: var(--radius-md);
      padding: 20px;
    }
    
    @media (min-width: 640px) {
      .price-drop-info {
        grid-template-columns: repeat(3, 1fr);
      }
    }
    
    .price-drop-item {
      display: flex;
      flex-direction: column;
      align-items: center;
      text-align: center;
      gap: 8px;
      padding: 12px;
      background: white;
      border-radius: var(--radius-sm);
      border: 1px solid var(--border);
    }
    
    .price-drop-label {
      font-size: 14px;
      color: var(--muted);
    }
    
    .price-drop-value {
      font-weight: 700;
      font-size: 18px;
    }
    
    .price-drop-total {
      color: var(--primary-dark);
      font-size: 22px;
    }
    
    /* 图片上传区域 */
    .upload-area {
      border: 2px dashed var(--border);
      border-radius: var(--radius-md);
      padding: 20px;
      text-align: center;
      background: #fff9f9;
      cursor: pointer;
      transition: all 0.2s ease;
    }
    
    .upload-area:hover {
      border-color: var(--accent);
      background: #fff5f5;
    }
    
    .upload-icon {
      width: 48px;
      height: 48px;
      fill: var(--primary-light);
      margin-bottom: 12px;
    }
    
    .upload-text {
      font-size: 15px;
      color: var(--muted);
      margin-bottom: 8px;
    }
    
    .upload-hint {
      font-size: 13px;
      color: var(--muted);
    }
    
    .image-preview {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
      gap: 10px;
      margin-top: 16px;
    }
    
    .preview-image {
      width: 100%;
      height: 80px;
      object-fit: cover;
      border-radius: var(--radius-sm);
      border: 1px solid var(--border);
    }
    
    /* 按钮区域 */
    .action-buttons {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-top: 32px;
      padding-top: 20px;
      border-top: 1px solid var(--border);
      flex-wrap: wrap;
      gap: 16px;
    }
    
    .btn {
      padding: 14px 28px;
      border-radius: var(--radius-md);
      font-size: 16px;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.2s ease;
      border: none;
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
    }
    
    .btn-primary {
      background: linear-gradient(90deg, var(--primary) 0%, var(--primary-light) 100%);
      color: white;
      box-shadow: 0 4px 12px rgba(211, 47, 47, 0.3);
    }
    
    .btn-primary:hover {
      transform: translateY(-2px);
      box-shadow: 0 6px 16px rgba(211, 47, 47, 0.4);
    }
    
    .btn-primary:active {
      transform: translateY(0);
    }
    
    .btn-secondary {
      background: white;
      color: var(--text);
      border: 1px solid var(--border);
    }
    
    .btn-secondary:hover {
      background: #fff5f5;
      border-color: var(--accent);
    }
    
    .btn-icon {
      width: 18px;
      height: 18px;
    }
    
    .footer-note {
      font-size: 13px;
      color: var(--muted);
    }
    
    /* 隐藏元素 */
    .hidden {
      display: none !important;
    }
    
    .disabled {
      opacity: 0.6;
      pointer-events: none;
    }
    
    /* 状态指示器 */
    .status-badge {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 6px 12px;
      border-radius: 20px;
      font-size: 12px;
      font-weight: 500;
      background: rgba(211, 47, 47, 0.1);
      color: var(--primary-dark);
      border: 1px solid rgba(211, 47, 47, 0.2);
    }
    
    /* 响应式调整 */
    @media (max-width: 640px) {
      .card-body {
        padding: 16px;
      }
      
      .btn {
        padding: 12px 20px;
        width: 100%;
      }
      
      .action-buttons {
        flex-direction: column;
        align-items: stretch;
      }
      
      .product-controls {
        flex-direction: column;
        align-items: flex-start;
      }
    }
  </style>
</head>
<body>
  <div class="app">
    <div class="card">
      <div class="card-header">
        <div class="card-title">
          <svg class="card-title-icon" viewBox="0 0 24 24">
            <path d="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z" />
          </svg>
          退款取消订单
        </div>
        <div class="card-subtitle">请填写退款信息并提交申请,我们将在1-3个工作日内处理</div>
      </div>
      
      <div class="card-body">
        <!-- 退款政策提醒 -->
        <div class="policy-box">
          <strong>重要提示:</strong> 对于定制个性化产品,一旦开始生产,可能无法更改或取消。这包括根据订单中的规格定制的专业设计、成型和造型。如果您需要在生产过程中取消或修改订单,则定制费(也称为补货费)将收取,来抵消已产生的费用。
        </div>
        
        <!-- 基本信息 -->
        <div class="section">
          <div class="section-title">基本信息</div>
          <div class="form-grid">
            <div class="form-field">
              <label class="form-label">退款原因</label>
              <select id="reason">
                <option value="">请选择退款原因</option>
                <option value="vip_insurance">取消VIP/运费保险</option>
                <option value="price_drop">购买后降价</option>
                <option value="delay">生产或交期延误</option>
                <option value="wrong_info">订单信息错误(尺码/颜色/数量)</option>
                <option value="quality">品质问题 / 与描述不符</option>
                <option value="other">其他原因</option>
              </select>
            </div>
            
            <div class="form-field">
              <label class="form-label">联系邮箱</label>
              <input id="email" type="email" placeholder="[email protected]" />
            </div>
          </div>
        </div>
        
        <!-- 产品明细 -->
        <div class="section">
          <div class="section-title">产品明细</div>
          <div id="products" class="products-grid"></div>
        </div>
        
        <!-- 附加费区域(仅显示当选择VIP/运费保险时) -->
        <div id="fee-section" class="section hidden">
          <div class="section-title">附加费用</div>
          <div class="fees-grid">
            <div class="fee-item">
              <div class="fee-info">
                <div class="fee-name">VIP费用</div>
                <div class="fee-desc">会员专享服务</div>
              </div>
              <div class="fee-amount">
                <label class="checkbox-label">
                  <input type="checkbox" class="fee-check" data-key="vip" checked /> 退款
                </label>
                <input type="number" class="fee-input" data-key="vip" value="19.99" min="0" step="0.01" />
              </div>
            </div>
            
            <div class="fee-item">
              <div class="fee-info">
                <div class="fee-name">运费保险</div>
                <div class="fee-desc">物流运输保障</div>
              </div>
              <div class="fee-amount">
                <label class="checkbox-label">
                  <input type="checkbox" class="fee-check" data-key="insurance" checked /> 退款
                </label>
                <input type="number" class="fee-input" data-key="insurance" value="5.00" min="0" step="0.01" />
              </div>
            </div>
            
            <div class="fee-item">
              <div class="fee-info">
                <div class="fee-name">保修费用</div>
                <div class="fee-desc">延长保修服务</div>
              </div>
              <div class="fee-amount">
                <label class="checkbox-label">
                  <input type="checkbox" class="fee-check" data-key="warranty" /> 退款
                </label>
                <input type="number" class="fee-input" data-key="warranty" value="9.99" min="0" step="0.01" />
              </div>
            </div>
            
            <div class="fee-item">
              <div class="fee-info">
                <div class="fee-name">服务费</div>
                <div class="fee-desc">人工客服服务</div>
              </div>
              <div class="fee-amount">
                <label class="checkbox-label">
                  <input type="checkbox" class="fee-check" data-key="service" /> 退款
                </label>
                <input type="number" class="fee-input" data-key="service" value="3.00" min="0" step="0.01" />
              </div>
            </div>
          </div>
        </div>
        
        <!-- 降价退款信息(仅显示当选择降价时) -->
        <div id="price-drop" class="section hidden">
          <div class="section-title">降价退款详情</div>
          <div class="price-drop-info">
            <div class="price-drop-item">
              <div class="price-drop-label">原始订单金额</div>
              <div class="price-drop-value">¥<span id="pd-original">42.91</span></div>
            </div>
            
            <div class="price-drop-item">
              <div class="price-drop-label">定制费用</div>
              <div class="price-drop-value">¥<span id="pd-custom">8.99</span></div>
            </div>
            
            <div class="price-drop-item">
              <div class="price-drop-label">退款总额</div>
              <div class="price-drop-value price-drop-total">¥<span id="pd-refund">33.92</span></div>
            </div>
          </div>
        </div>
        
        <!-- 金额汇总区域 -->
        <div class="section">
          <div class="section-title">金额明细</div>
          <div class="amount-summary">
            <div class="amount-row">
              <span class="amount-label">商品合计</span>
              <span class="amount-value">¥<span id="subtotal">0.00</span></span>
            </div>
            
            <div class="amount-row">
              <span class="amount-label">附加费退款</span>
              <span class="amount-value">¥<span id="fee-total">0.00</span></span>
            </div>
            
            <div class="amount-row">
              <span class="amount-label">运费退款</span>
              <span class="amount-value">¥<span id="shipping-refund">0.00</span></span>
            </div>
            
            <div class="amount-row total-row">
              <span class="amount-label">退款总金额</span>
              <span class="amount-value total-amount">¥<span id="total">0.00</span></span>
            </div>
          </div>
        </div>
        
        <!-- 取消说明 -->
        <div class="section">
          <div class="section-title">取消说明</div>
          <div class="form-field">
            <label class="form-label">备注说明</label>
            <textarea id="note" placeholder="请补充取消和退款的原因或细节,以便我们更好地处理您的申请..."></textarea>
          </div>
          
          <div class="form-field">
            <label class="form-label">上传凭证(最多6张)</label>
            <div class="upload-area" id="upload-area">
              <svg class="upload-icon" viewBox="0 0 24 24">
                <path d="M14,13V17H10V13H7L12,8L17,13M19.35,10.03C18.67,6.59 15.64,4 12,4C9.11,4 6.6,5.64 5.35,8.03C2.34,8.36 0,10.9 0,14A6,6 0 0,0 6,20H19A5,5 0 0,0 24,15C24,12.36 21.95,10.22 19.35,10.03Z" />
              </svg>
              <div class="upload-text">点击或拖拽上传图片</div>
              <div class="upload-hint">支持 JPG、PNG 格式,每张不超过5MB</div>
              <input id="images" type="file" accept="image/*" multiple class="hidden" />
            </div>
            <div id="thumbs" class="image-preview"></div>
          </div>
        </div>
        
        <!-- 操作按钮 -->
        <div class="action-buttons">
          <div class="footer-note">
            <span class="status-badge">演示版本</span> 本页面为前端示例,不会提交到服务器
          </div>
          
          <div style="display: flex; gap: 12px; flex-wrap: wrap;">
            <button id="submit-btn" class="btn btn-primary">
              <svg class="btn-icon" viewBox="0 0 24 24">
                <path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z" fill="white"/>
              </svg>
              提交申请
            </button>
            <button id="cancel-btn" class="btn btn-secondary">
              <svg class="btn-icon" viewBox="0 0 24 24">
                <path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" fill="currentColor"/>
              </svg>
              取消
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>

  <script>
    // 示例产品数据
    const productsData = [
      { id: 'p1', name: '定制T恤(白色)', sku: 'TS-001-W', price: 129.00, img: 'https://picsum.photos/seed/t1/200/200' },
      { id: 'p2', name: '定制帽子(红色)', sku: 'CP-207-R', price: 89.00, img: 'https://picsum.photos/seed/cp/200/200' },
      { id: 'p3', name: 'LOGO贴纸包', sku: 'ST-511-M', price: 39.00, img: 'https://picsum.photos/seed/st/200/200' },
      { id: 'p4', name: '限定托特包', sku: 'TB-888-K', price: 159.00, img: 'https://picsum.photos/seed/tb/200/200' }
    ];

    const els = {
      reason: document.getElementById('reason'),
      email: document.getElementById('email'),
      products: document.getElementById('products'),
      subtotal: document.getElementById('subtotal'),
      feeTotal: document.getElementById('fee-total'),
      shippingRefund: document.getElementById('shipping-refund'),
      total: document.getElementById('total'),
      feeSection: document.getElementById('fee-section'),
      priceDrop: document.getElementById('price-drop'),
      note: document.getElementById('note'),
      images: document.getElementById('images'),
      thumbs: document.getElementById('thumbs'),
      uploadArea: document.getElementById('upload-area'),
      submitBtn: document.getElementById('submit-btn'),
      cancelBtn: document.getElementById('cancel-btn')
    };

    // 初始化页面
    function init() {
      renderProducts();
      bindEvents();
      calcTotals();
      
      // 设置默认邮箱
      els.email.value = '[email protected]';
      
      // 设置默认原因
      els.reason.value = 'price_drop';
      els.reason.dispatchEvent(new Event('change'));
    }

    // 渲染产品列表
    function renderProducts() {
      els.products.innerHTML = '';
      productsData.forEach(p => {
        const row = document.createElement('div');
        row.className = 'product-card';
        row.innerHTML = `
          <img src="${p.img}" alt="${p.name}" class="product-image" />
          <div class="product-info">
            <div class="product-name">${p.name}</div>
            <div class="product-sku">货号:${p.sku}</div>
            <div class="product-controls">
              <label class="checkbox-label">
                <input type="checkbox" class="pick" data-id="${p.id}" checked /> 申请退款
              </label>
              <div style="display: flex; align-items: center; gap: 6px;">
                <span style="font-size: 14px; color: var(--muted);">数量</span>
                <input type="number" class="qty-input" data-id="${p.id}" value="1" min="1" class="qty-input" />
              </div>
            </div>
          </div>
          <div class="product-price">¥${p.price.toFixed(2)}</div>
        `;
        els.products.appendChild(row);
      });
    }

    // 计算商品小计
    function getProductsSubtotal() {
      let sum = 0;
      const picks = Array.from(document.querySelectorAll('.pick'));
      picks.forEach(chk => {
        const id = chk.getAttribute('data-id');
        const prod = productsData.find(x => x.id === id);
        const qtyEl = document.querySelector('.qty-input[data-id="' + id + '"]');
        const qty = Math.max(1, parseInt(qtyEl.value || '1', 10));
        if (chk.checked) sum += prod.price * qty;
      });
      return sum;
    }

    // 计算附加费总额
    function getFeesTotal() {
      let sum = 0;
      const checks = Array.from(document.querySelectorAll('.fee-check'));
      checks.forEach(chk => {
        const key = chk.getAttribute('data-key');
        const input = document.querySelector('.fee-input[data-key="' + key + '"]');
        const val = parseFloat(input.value);
        if (chk.checked && !isNaN(val) && val > 0) sum += val;
      });
      return sum;
    }

    // 计算运费退款(模拟)
    function getShippingRefund() {
      const subtotal = getProductsSubtotal();
      // 假设订单满200免运费,否则收取15元运费
      return subtotal >= 200 ? 15.00 : 0.00;
    }

    // 计算总额并更新显示
    function calcTotals() {
      const reason = els.reason.value;
      const subtotal = getProductsSubtotal();
      const shippingRefund = getShippingRefund();
      
      let feeTotal = 0;
      let total = 0;

      // 根据退款原因显示不同内容
      if (reason === 'price_drop') {
        // 显示降价退款信息
        els.priceDrop.classList.remove('hidden');
        els.feeSection.classList.add('hidden');
        
        // 禁用产品选择
        els.products.classList.add('disabled');
        document.querySelectorAll('.pick, .qty-input').forEach(el => el.disabled = true);
        
        // 显示固定退款金额
        total = 33.92;
        els.subtotal.textContent = '0.00';
        els.feeTotal.textContent = '0.00';
        els.shippingRefund.textContent = '0.00';
      } else {
        // 隐藏降价退款信息
        els.priceDrop.classList.add('hidden');
        els.products.classList.remove('disabled');
        document.querySelectorAll('.pick, .qty-input').forEach(el => el.disabled = false);
        
        // 根据原因显示附加费区域
        if (reason === 'vip_insurance') {
          els.feeSection.classList.remove('hidden');
          feeTotal = getFeesTotal();
        } else {
          els.feeSection.classList.add('hidden');
        }
        
        // 计算总额
        total = subtotal + feeTotal + shippingRefund;
        els.subtotal.textContent = subtotal.toFixed(2);
        els.feeTotal.textContent = feeTotal.toFixed(2);
        els.shippingRefund.textContent = shippingRefund.toFixed(2);
      }
      
      // 更新总金额
      els.total.textContent = total.toFixed(2);
    }

    // 处理图片上传
    function handleImages() {
      const files = Array.from(els.images.files || []).slice(0, 6);
      els.thumbs.innerHTML = '';
      
      if (files.length === 0) return;
      
      files.forEach(f => {
        const reader = new FileReader();
        reader.onload = function(e) {
          const img = document.createElement('img');
          img.src = e.target.result;
          img.className = 'preview-image';
          img.alt = f.name;
          els.thumbs.appendChild(img);
        };
        reader.readAsDataURL(f);
      });
    }

    // 验证表单
    function validate() {
      const reason = (els.reason.value || '').trim();
      const email = (els.email.value || '').trim();
      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      const anyPicked = Array.from(document.querySelectorAll('.pick')).some(el => el.checked);
      
      if (!reason) {
        alert('请选择退款原因');
        els.reason.focus();
        return false;
      }
      
      if (!email || !emailRegex.test(email)) {
        alert('请输入有效的邮箱地址');
        els.email.focus();
        return false;
      }
      
      if (reason !== 'price_drop' && !anyPicked) {
        alert('请至少选择一个产品进行退款');
        return false;
      }
      
      return true;
    }

    // 提交表单
    function submit() {
      if (!validate()) return;
      
      const reason = els.reason.value;
      const payload = {
        reason,
        email: els.email.value,
        note: els.note.value,
        items: [],
        fees: {},
        totals: {
          subtotal: parseFloat(els.subtotal.textContent),
          feeTotal: parseFloat(els.feeTotal.textContent),
          shippingRefund: parseFloat(els.shippingRefund.textContent),
          total: parseFloat(els.total.textContent)
        }
      };
      
      if (reason === 'price_drop') {
        payload.priceDrop = {
          original: 42.91,
          custom: 8.99,
          refund: 33.92
        };
      } else {
        payload.items = Array.from(document.querySelectorAll('.pick'))
          .filter(el => el.checked)
          .map(el => {
            const id = el.getAttribute('data-id');
            const prod = productsData.find(x => x.id === id);
            const qtyEl = document.querySelector('.qty-input[data-id="' + id + '"]');
            const qty = Math.max(1, parseInt(qtyEl.value || '1', 10));
            return {
              id,
              name: prod.name,
              sku: prod.sku,
              price: prod.price,
              qty,
              total: prod.price * qty
            };
          });
        
        if (reason === 'vip_insurance') {
          Array.from(document.querySelectorAll('.fee-check')).forEach(chk => {
            const key = chk.getAttribute('data-key');
            const val = parseFloat(document.querySelector('.fee-input[data-key="' + key + '"]').value);
            payload.fees[key] = {
              checked: chk.checked,
              amount: isNaN(val) ? 0 : val
            };
          });
        }
      }
      
      // 在实际应用中,这里应该发送数据到服务器
      console.log('提交退款申请:', payload);
      
      // 显示成功提示
      alert('退款申请已提交成功!我们将在1-3个工作日内处理您的申请。\n\n(演示版本,数据不会实际提交)');
      
      // 重置表单
      setTimeout(() => {
        els.note.value = '';
        els.images.value = '';
        els.thumbs.innerHTML = '';
      }, 100);
    }

    // 取消操作
    function cancelPage() {
      if (confirm('确定要离开此页面吗?您填写的信息将不会被保存。')) {
        // 在实际应用中,这里应该返回上一页或关闭页面
        console.log('用户取消操作');
        // 模拟返回上一页
        window.history.back();
      }
    }

    // 绑定事件
    function bindEvents() {
      // 监听所有输入变化
      document.addEventListener('input', (e) => {
        if (
          e.target.classList.contains('pick') ||
          e.target.classList.contains('qty-input') ||
          e.target.classList.contains('fee-input') ||
          e.target.classList.contains('fee-check')
        ) {
          calcTotals();
        }
      });
      
      // 监听选择变化
      document.addEventListener('change', (e) => {
        if (
          e.target === els.reason ||
          e.target.classList.contains('pick') ||
          e.target.classList.contains('fee-check')
        ) {
          calcTotals();
        }
      });
      
      // 监听退款原因变化
      els.reason.addEventListener('change', calcTotals);
      
      // 图片上传事件
      els.uploadArea.addEventListener('click', () => els.images.click());
      els.uploadArea.addEventListener('dragover', (e) => {
        e.preventDefault();
        els.uploadArea.style.borderColor = 'var(--accent)';
        els.uploadArea.style.background = '#fff5f5';
      });
      els.uploadArea.addEventListener('dragleave', () => {
        els.uploadArea.style.borderColor = 'var(--border)';
        els.uploadArea.style.background = '#fff9f9';
      });
      els.uploadArea.addEventListener('drop', (e) => {
        e.preventDefault();
        els.uploadArea.style.borderColor = 'var(--border)';
        els.uploadArea.style.background = '#fff9f9';
        els.images.files = e.dataTransfer.files;
        handleImages();
      });
      els.images.addEventListener('change', handleImages);
      
      // 按钮事件
      els.submitBtn.addEventListener('click', submit);
      els.cancelBtn.addEventListener('click', cancelPage);
    }

    // 页面加载完成后初始化
    document.addEventListener('DOMContentLoaded', init);
  </script>
</body>
</html>
        
编辑器加载中
预览
控制台