log.vue 8.83 KB
<template>
  <el-dialog
    v-model="showDialog"
    align-center
    class="invoice-dialog"
    destroy-on-close
    title="开票记录"
    width="560"
  >
    <!-- 头部装饰 -->
    <template #header="{ titleId, titleClass }">
      <div class="dialog-header">
        <div class="header-icon">
          <el-icon :size="24"><Ticket /></el-icon>
        </div>
        <div class="header-content">
          <h2 :id="titleId" :class="titleClass">开票记录</h2>
          <p class="header-subtitle">发票详细信息</p>
        </div>
      </div>
    </template>
    
    <!-- 主体内容 -->
    <div class="invoice-container">
      <!-- 发票卡片 -->
      <div class="invoice-card">
        <!--        &lt;!&ndash; 类型标识区 &ndash;&gt;-->
        <div :class="{ 'vat-type': form.invoiceStatus === '2' }" class="type-badge">
          <el-icon><Star /></el-icon>
          <span>{{ form.specialFlag === '2' ? '普通发票' : '增值税专用发票' }}</span>
        </div>

        <!-- 信息列表 -->
        <div class="info-list">
          <div class="info-row">
            <div class="info-label">
              <div class="label-icon">
                <el-icon><OfficeBuilding /></el-icon>
              </div>
              <span>发票抬头</span>
            </div>
            <div class="info-content">{{ form.invoiceBuyerName || '—' }}</div>
          </div>
          
          <div v-if="form.invoiceBuyerTaxno" class="info-row">
            <div class="info-label">
              <div class="label-icon">
                <el-icon><Key /></el-icon>
              </div>
              <span>纳税人识别号</span>
            </div>
            <div class="info-content taxno">{{ form.invoiceBuyerTaxno || '—' }}</div>
          </div>
          
          <div class="info-row">
            <div class="info-label">
              <div class="label-icon">
                <el-icon><Message /></el-icon>
              </div>
              <span>接收邮箱/号码</span>
            </div>
            <div class="info-content contact">{{ form.invoicePushPhone || '—' }}</div>
          </div>
          <div class="info-row">
            <div class="info-label">
              <div class="label-icon">
                <el-icon><Timer /></el-icon>
              </div>
              <span>开票时间</span>
            </div>
            <div class="info-content">{{ form.invoiceTime || '—' }}</div>
          </div>
          <div class="info-row">
            <div class="info-label">
              <div class="label-icon">
                <el-icon><money /></el-icon>
              </div>
              <span>开票金额</span>
            </div>
            <div class="info-content contact">¥{{ form.price || '—' }}</div>
          </div>
        </div>
        
        <!-- 分割装饰线 -->
        <div class="decorative-line" />
        <!--        <div class="footer-note">-->
        <!--          <el-icon><InfoFilled /></el-icon>-->
        <!--          <span>请仔细核对发票信息,一经开具无法修改</span>-->
        <!--        </div>-->
        
        <br>
        <br>
        <br>
      </div>
    </div>
    
    <!-- 底部按钮 -->
    <!--    <template #footer>-->
    <!--      <div class="dialog-footer">-->
    <!--        <el-button class="cancel-btn" @click="showDialog = false">-->
    <!--          <el-icon><Close /></el-icon>-->
    <!--          <span>取消</span>-->
    <!--        </el-button>-->
    <!--        <el-button type="primary" class="confirm-btn" @click="handlePrint">-->
    <!--          <el-icon><Printer /></el-icon>-->
    <!--          <span>打印发票</span>-->
    <!--        </el-button>-->
    <!--      </div>-->
    <!--    </template>-->
  </el-dialog>
</template>

<script setup>
import { ref } from 'vue'
import {
  Ticket,
  OfficeBuilding,
  Key,
  Message,
  Star,
  InfoFilled,
  Close,
  Printer
} from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'

const showDialog = ref(false)
const form = ref({})

const open = (row) => {
  showDialog.value = true
  form.value = row
}

const handlePrint = () => {
  ElMessage.success('正在生成发票,请稍候...')
  // 可在此实现打印逻辑
}

defineExpose({
  open
})
</script>

<style lang="scss" scoped>
.invoice-dialog {
  :deep(.el-dialog) {
    border-radius: 20px;
    overflow: hidden;
    box-shadow: 0 20px 35px -8px rgba(0, 0, 0, 0.15);
  }
  
  :deep(.el-dialog__body) {
    padding: 0;
  }
  
  :deep(.el-dialog__header) {
    display: none;
  }
  
  :deep(.el-dialog__footer) {
    padding: 20px 28px 28px;
    background: #fafbfc;
    border-top: 1px solid #f0f2f5;
  }
}

// 自定义头部
.dialog-header {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 24px 28px 16px;
  background: linear-gradient(135deg, #173ce2 0%, #3ea3eb 100%);
  
  .header-icon {
    width: 48px;
    height: 48px;
    background: rgba(255, 255, 255, 0.2);
    backdrop-filter: blur(10px);
    border-radius: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    
    .el-icon {
      color: white;
    }
  }
  
  .header-content {
    flex: 1;
    
    h2 {
      margin: 0 0 4px;
      color: white;
      font-size: 20px;
      font-weight: 600;
      letter-spacing: 0.5px;
    }
    
    .header-subtitle {
      margin: 0;
      color: rgba(255, 255, 255, 0.85);
      font-size: 13px;
    }
  }
}

// 主容器
.invoice-container {
  padding: 28px;
  background: #ffffff;
}

.invoice-card {
  position: relative;
  background: #ffffff;
  border-radius: 16px;
  border: 1px solid #eef2f6;
  transition: all 0.3s ease;
  
  .type-badge {
    position: absolute;
    top: -12px;
    right: 24px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 16px;
    background: linear-gradient(135deg, #6aaaf2 0%, #178cd7 100%);
    color: #fff;
    border-radius: 40px;
    font-size: 13px;
    font-weight: 600;
    border: 1px solid rgba(57, 125, 227, 0.2);
    
    .el-icon {
      font-size: 14px;
    }
    
    &.vat-type {
      background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
      color: #3b82f6;
      border-color: rgba(59, 130, 246, 0.2);
    }
  }
  
  .info-list {
    padding: 28px 24px 20px;
    
    .info-row {
      display: flex;
      align-items: flex-start;
      margin-bottom: 24px;
      padding-bottom: 20px;
      border-bottom: 1px dashed #f0f2f5;
      
      &:last-child {
        margin-bottom: 0;
        padding-bottom: 0;
        border-bottom: none;
      }
      
      .info-label {
        display: flex;
        align-items: center;
        gap: 10px;
        min-width: 140px;
        color: #5b6e8c;
        font-size: 14px;
        font-weight: 500;
        
        .label-icon {
          width: 32px;
          height: 32px;
          background: #f8fafc;
          border-radius: 10px;
          display: flex;
          align-items: center;
          justify-content: center;
          color: #173ce2;
          
          .el-icon {
            font-size: 16px;
          }
        }
      }
      
      .info-content {
        flex: 1;
        color: #1e293b;
        font-size: 15px;
        font-weight: 500;
        line-height: 32px;
        word-break: break-all;
        
        &.taxno {
          font-family: 'Monaco', 'Menlo', monospace;
          letter-spacing: 0.5px;
          color: #475569;
        }
        
        &.contact {
          color: #3b82f6;
        }
      }
    }
  }
  
  .decorative-line {
    height: 2px;
    //background: linear-gradient(90deg, #667eea 0%, #764ba2 50%, transparent 100%);
    background: linear-gradient(135deg, #173ce2 0%, #3ea3eb 50%,transparent 100%)
  }
  
  .footer-note {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 16px 24px;
    background: #fefce8;
    color: #ca8a04;
    font-size: 12px;
    border-radius: 0 0 16px 16px;
    
    .el-icon {
      font-size: 14px;
    }
  }
}

// 底部按钮样式
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  
  .cancel-btn,
  .confirm-btn {
    padding: 10px 24px;
    border-radius: 12px;
    font-weight: 500;
    transition: all 0.2s;
    
    .el-icon {
      margin-right: 6px;
    }
  }
  
  .cancel-btn {
    background: white;
    border-color: #e2e8f0;
    color: #64748b;
    
    &:hover {
      background: #f8fafc;
      border-color: #cbd5e1;
      color: #475569;
    }
  }
  
  .confirm-btn {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border: none;
    
    &:hover {
      transform: translateY(-1px);
      box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
    }
  }
}

// 响应式适配
@media (max-width: 640px) {
  .invoice-dialog :deep(.el-dialog) {
    width: 90%;
  }
  
  .invoice-container {
    padding: 20px;
  }
  
  .info-row {
    flex-direction: column;
    
    .info-label {
      margin-bottom: 8px;
    }
  }
}
</style>