351 lines
24 KiB
Vue
351 lines
24 KiB
Vue
<script setup lang="ts">
|
||
import { ref, watch } from 'vue'
|
||
import { ElMessage } from 'element-plus'
|
||
import { CircleAlert, Clock3, PackageCheck, RefreshCw, TriangleAlert } from '@lucide/vue'
|
||
import { confirmMerchantInboundFee } from '@/modules/first-leg/api/inboundBilling'
|
||
import type { MerchantInboundBilling } from '@/modules/first-leg/types/inboundBilling'
|
||
import {
|
||
formatConversionPrecision,
|
||
formatInboundDateTime,
|
||
formatInboundMeasure,
|
||
formatInboundMoney,
|
||
formatInboundNumber,
|
||
getCalculationRuleLabel,
|
||
getChargeModeLabel,
|
||
getTaxModeLabel,
|
||
} from '@/modules/first-leg/utils/inboundBilling'
|
||
|
||
const props = withDefaults(defineProps<{
|
||
data?: MerchantInboundBilling | null
|
||
loading?: boolean
|
||
unavailable?: boolean
|
||
unavailableMessage?: string
|
||
error?: string
|
||
autoOpen?: boolean
|
||
dialogOnly?: boolean
|
||
canConfirm?: boolean
|
||
}>(), {
|
||
data: null,
|
||
loading: false,
|
||
unavailable: false,
|
||
unavailableMessage: '还未测量推送',
|
||
error: '',
|
||
autoOpen: false,
|
||
dialogOnly: false,
|
||
canConfirm: false,
|
||
})
|
||
|
||
const emit = defineEmits<{
|
||
retry: []
|
||
confirmed: []
|
||
closed: []
|
||
}>()
|
||
|
||
const feeDialogOpen = ref(false)
|
||
const confirming = ref(false)
|
||
watch(() => props.autoOpen, (autoOpen) => {
|
||
if (autoOpen) feeDialogOpen.value = true
|
||
}, { immediate: true })
|
||
|
||
async function confirmFee() {
|
||
const fee = props.data?.latestFee
|
||
const orderId = props.data?.inbound.summary.orderId
|
||
if (!fee || !orderId || !props.canConfirm || confirming.value) return
|
||
if (fee.customerConfirmationStatus === 'CONFIRMED') {
|
||
ElMessage.info('当前费用已经确认,无需重复操作')
|
||
return
|
||
}
|
||
confirming.value = true
|
||
try {
|
||
await confirmMerchantInboundFee(orderId, fee.feeVersion)
|
||
ElMessage.success('费用确认成功,当前费用已锁定')
|
||
feeDialogOpen.value = false
|
||
emit('confirmed')
|
||
} catch (error) {
|
||
ElMessage.error(error instanceof Error ? error.message : '费用确认失败,请刷新后重试')
|
||
} finally {
|
||
confirming.value = false
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<section v-if="!props.dialogOnly" class="inbound-billing-panel" aria-labelledby="inbound-billing-title">
|
||
<header class="inbound-billing-heading">
|
||
<h3 id="inbound-billing-title">入库与费用</h3>
|
||
<div v-if="props.data" class="inbound-billing-actions">
|
||
<el-tag :type="props.data.latestFee.customerConfirmationStatus === 'CONFIRMED' ? 'success' : 'warning'" effect="light">
|
||
{{ props.data.latestFee.customerConfirmationStatus === 'CONFIRMED' ? '客户已确认 · 费用已锁定' : '费用已发布 · 待确认' }}
|
||
</el-tag>
|
||
<el-button v-if="props.data.latestFee.customerConfirmationStatus !== 'CONFIRMED' && props.canConfirm" type="primary" @click="feeDialogOpen = true">确认计费重</el-button>
|
||
<el-button v-else plain @click="feeDialogOpen = true">查看费用</el-button>
|
||
</div>
|
||
</header>
|
||
|
||
<div v-if="props.loading" class="inbound-billing-loading" aria-live="polite" aria-busy="true">
|
||
<el-skeleton :rows="4" animated />
|
||
<span class="sr-only">正在加载入库与费用结果</span>
|
||
</div>
|
||
|
||
<div v-else-if="props.error" class="inbound-billing-state is-error" role="alert">
|
||
<TriangleAlert :size="22" />
|
||
<div>
|
||
<strong>入库与费用加载失败</strong>
|
||
<span>{{ props.error }}</span>
|
||
</div>
|
||
<el-button @click="$emit('retry')"><RefreshCw :size="15" />重新加载</el-button>
|
||
</div>
|
||
|
||
<div v-else-if="props.unavailable || !props.data" class="inbound-billing-state is-pending" role="status">
|
||
<Clock3 :size="22" />
|
||
<div>
|
||
<strong>{{ props.unavailableMessage }}</strong>
|
||
<span>平台完成测量审核并确认推送费用后,将在这里展示测量与计费结果。</span>
|
||
</div>
|
||
</div>
|
||
|
||
<template v-else>
|
||
<dl class="inbound-overview">
|
||
<div><dt>入仓码</dt><dd>{{ props.data.inbound.summary.inboundCode }}</dd></div>
|
||
<div><dt>入库完成</dt><dd>{{ formatInboundDateTime(props.data.inbound.summary.inboundedAt) }}</dd></div>
|
||
<div><dt>平台收货仓</dt><dd>{{ props.data.inbound.summary.warehouseName || '-' }}</dd></div>
|
||
<div><dt>目的仓</dt><dd>{{ props.data.inbound.summary.destinationCode || props.data.inbound.summary.destinationName || '-' }}</dd></div>
|
||
</dl>
|
||
|
||
<div class="inbound-result-section">
|
||
<div class="inbound-section-title"><h4>测量数据</h4><el-tag size="small" type="warning" effect="light">后台推送</el-tag></div>
|
||
<dl class="inbound-measurements">
|
||
<div><dt>实际箱数</dt><dd>{{ formatInboundNumber(props.data.inbound.summary.totalPackageCount, 0) }}</dd></div>
|
||
<div><dt>实际毛重</dt><dd>{{ formatInboundMeasure(props.data.inbound.summary.actualGrossWeightKg, 'kg') }}</dd></div>
|
||
<div><dt>实际净重</dt><dd>{{ formatInboundMeasure(props.data.inbound.summary.actualNetWeightKg, 'kg') }}</dd></div>
|
||
<div><dt>实测体积</dt><dd>{{ formatInboundMeasure(props.data.inbound.summary.actualVolumeCbm, 'm³') }}</dd></div>
|
||
<div><dt>材积重</dt><dd>{{ formatInboundMeasure(props.data.inbound.summary.volumeWeightKg, 'kg') }}</dd></div>
|
||
<div><dt>测量完成</dt><dd>{{ formatInboundDateTime(props.data.inbound.summary.measureCompletedAt) }}</dd></div>
|
||
</dl>
|
||
<el-table v-if="props.data.measurementItems.length" class="measurement-detail-table" :data="props.data.measurementItems" border size="small">
|
||
<el-table-column type="index" label="#" width="54" />
|
||
<el-table-column prop="lengthCm" label="箱规长(cm)" min-width="105" />
|
||
<el-table-column prop="widthCm" label="箱规宽(cm)" min-width="105" />
|
||
<el-table-column prop="heightCm" label="箱规高(cm)" min-width="105" />
|
||
<el-table-column prop="packageCount" label="箱数" min-width="76" />
|
||
<el-table-column label="每箱体积" min-width="105"><template #default="{ row }">{{ formatInboundMeasure(row.unitVolumeCbm, 'm³') }}</template></el-table-column>
|
||
<el-table-column label="总体积" min-width="105"><template #default="{ row }">{{ formatInboundMeasure(row.totalVolumeCbm, 'm³') }}</template></el-table-column>
|
||
<el-table-column label="总材积重" min-width="105"><template #default="{ row }">{{ formatInboundMeasure(row.volumeWeightKg, 'kg') }}</template></el-table-column>
|
||
<el-table-column label="箱规规则" min-width="170"><template #default="{ row }">{{ getCalculationRuleLabel(row.calculationRuleVersion) }}</template></el-table-column>
|
||
<el-table-column prop="boxSpecification" label="备注" min-width="130" />
|
||
</el-table>
|
||
</div>
|
||
|
||
<div class="inbound-result-section">
|
||
<div class="inbound-section-title">
|
||
<h4>托盘与库位</h4>
|
||
<span>{{ props.data.inbound.palletLocations.length }} 个托盘</span>
|
||
</div>
|
||
<div v-if="props.data.inbound.palletLocations.length" class="pallet-location-list">
|
||
<article v-for="item in props.data.inbound.palletLocations" :key="`${item.palletId}-${item.locationId}`">
|
||
<PackageCheck :size="18" />
|
||
<div class="pallet-location-main">
|
||
<strong>{{ item.palletCode }}</strong>
|
||
<span>库位 {{ item.locationCode }}</span>
|
||
</div>
|
||
<div class="pallet-location-quantity">
|
||
<span>{{ formatInboundMeasure(item.allocatedVolumeCbm, 'm³') }}</span>
|
||
<span>{{ formatInboundNumber(item.allocatedPackageCount, 0) }} 箱</span>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
<p v-else class="inbound-inline-empty">暂无托盘和库位明细</p>
|
||
</div>
|
||
|
||
<div class="inbound-result-section fee-result">
|
||
<div class="inbound-section-title">
|
||
<h4>费用结果</h4>
|
||
<span>{{ props.data.latestFee.feeNo }} · 第 {{ props.data.latestFee.feeVersion }} 版</span>
|
||
</div>
|
||
<dl class="fee-calculation-grid">
|
||
<div><dt>计费方式</dt><dd>{{ getChargeModeLabel(props.data.latestFee.chargeMode) }} · {{ getTaxModeLabel(props.data.latestFee.taxMode) }}</dd></div>
|
||
<div>
|
||
<dt>换算与精度</dt>
|
||
<dd>{{ formatConversionPrecision(
|
||
props.data.latestFee.conversionFactor,
|
||
props.data.latestFee.roundingScale,
|
||
props.data.latestFee.roundingMode,
|
||
) }}</dd>
|
||
</div>
|
||
<div><dt>实际重量</dt><dd>{{ formatInboundMeasure(props.data.latestFee.actualWeightKg, 'kg') }}</dd></div>
|
||
<div><dt>实际体积</dt><dd>{{ formatInboundMeasure(props.data.latestFee.actualVolumeCbm, 'm³') }}</dd></div>
|
||
<div><dt>体积重量</dt><dd>{{ formatInboundMeasure(props.data.latestFee.convertedQuantity, props.data.latestFee.chargeUnit) }}</dd></div>
|
||
<div><dt>最终计费量</dt><dd>{{ formatInboundMeasure(props.data.latestFee.chargeableQuantity, props.data.latestFee.chargeUnit) }}</dd></div>
|
||
<div><dt>单价</dt><dd>{{ formatInboundMoney(props.data.latestFee.unitPrice, props.data.latestFee.currency) }} / {{ props.data.latestFee.chargeUnit }}</dd></div>
|
||
<div><dt>基础费用</dt><dd>{{ formatInboundMoney(props.data.latestFee.subtotalAmount, props.data.latestFee.currency) }}</dd></div>
|
||
<div><dt>附加费用</dt><dd>{{ formatInboundMoney(props.data.latestFee.additionalAmount, props.data.latestFee.currency) }}</dd></div>
|
||
</dl>
|
||
<div class="fee-total">
|
||
<div>
|
||
<span>费用合计</span>
|
||
<small>{{ props.data.latestFee.ruleCode }} v{{ props.data.latestFee.chargeRuleVersion }} · {{ props.data.latestFee.rateCode }} v{{ props.data.latestFee.carrierRateVersion }}</small>
|
||
</div>
|
||
<strong>{{ formatInboundMoney(props.data.latestFee.totalAmount, props.data.latestFee.currency) }}</strong>
|
||
</div>
|
||
<p class="fee-sent-time">发布于 {{ formatInboundDateTime(props.data.latestFee.sentAt) }}</p>
|
||
</div>
|
||
|
||
<div v-if="props.data.inbound.publicRemark" class="inbound-public-remark">
|
||
<strong>平台备注</strong>
|
||
<p>{{ props.data.inbound.publicRemark }}</p>
|
||
</div>
|
||
</template>
|
||
|
||
</section>
|
||
|
||
<el-dialog v-model="feeDialogOpen" class="billing-confirm-dialog" title="确认计费重" width="min(1180px, calc(100vw - 40px))" append-to-body @closed="emit('closed')">
|
||
<div v-if="props.loading" class="inbound-billing-loading" aria-live="polite" aria-busy="true">
|
||
<el-skeleton :rows="4" animated />
|
||
<span class="sr-only">正在加载费用</span>
|
||
</div>
|
||
<div v-else-if="props.error" class="inbound-billing-state is-error" role="alert">
|
||
<TriangleAlert :size="22" />
|
||
<div><strong>费用加载失败</strong><span>{{ props.error }}</span></div>
|
||
<el-button @click="$emit('retry')"><RefreshCw :size="15" />重新加载</el-button>
|
||
</div>
|
||
<div v-else-if="props.unavailable || !props.data" class="inbound-billing-state is-pending" role="status">
|
||
<Clock3 :size="22" />
|
||
<div><strong>{{ props.unavailableMessage }}</strong><span>平台推送费用后,可在这里核对并确认。</span></div>
|
||
</div>
|
||
<template v-else>
|
||
<dl class="fee-dialog-summary" aria-label="计费汇总">
|
||
<div><dt>计算重</dt><dd>{{ formatInboundMeasure(props.data.billingBasis.chargeableWeightKg, 'kg') }}</dd></div>
|
||
<div><dt>单价</dt><dd>{{ formatInboundMoney(props.data.latestFee.unitPrice, props.data.latestFee.currency) }} / {{ props.data.latestFee.chargeUnit.toUpperCase() }}</dd></div>
|
||
<div><dt>总金额</dt><dd>{{ formatInboundMoney(props.data.latestFee.totalAmount, props.data.latestFee.currency) }}</dd></div>
|
||
</dl>
|
||
<el-table class="measurement-detail-table fee-dialog-table" :data="props.data.measurementItems" border empty-text="暂无箱规测量明细">
|
||
<el-table-column type="index" label="#" width="54" />
|
||
<el-table-column prop="lengthCm" label="箱规长(cm)" min-width="105" />
|
||
<el-table-column prop="widthCm" label="箱规宽(cm)" min-width="105" />
|
||
<el-table-column prop="heightCm" label="箱规高(cm)" min-width="105" />
|
||
<el-table-column prop="packageCount" label="箱数" min-width="76" />
|
||
<el-table-column label="每箱体积" min-width="105"><template #default="{ row }">{{ formatInboundMeasure(row.unitVolumeCbm, 'm³') }}</template></el-table-column>
|
||
<el-table-column label="总体积" min-width="105"><template #default="{ row }">{{ formatInboundMeasure(row.totalVolumeCbm, 'm³') }}</template></el-table-column>
|
||
<el-table-column label="总材积重" min-width="105"><template #default="{ row }">{{ formatInboundMeasure(row.volumeWeightKg, 'kg') }}</template></el-table-column>
|
||
<el-table-column label="箱规规则" min-width="170"><template #default="{ row }">{{ getCalculationRuleLabel(row.calculationRuleVersion) }}</template></el-table-column>
|
||
<el-table-column prop="boxSpecification" label="备注" min-width="130" />
|
||
</el-table>
|
||
<div class="fee-confirm-notice" :class="{ 'is-confirmed': props.data.latestFee.customerConfirmationStatus === 'CONFIRMED' }" role="status">
|
||
<CircleAlert :size="21" aria-hidden="true" />
|
||
<span v-if="props.data.latestFee.customerConfirmationStatus === 'CONFIRMED'">客户已于 {{ formatInboundDateTime(props.data.latestFee.customerConfirmedAt) }} 确认,费用已锁定,不允许修改。</span>
|
||
<span v-else>请核对计算重、单价和总金额。确认后当前费用版本将锁定。</span>
|
||
</div>
|
||
</template>
|
||
<template #footer>
|
||
<el-button @click="feeDialogOpen = false">关闭</el-button>
|
||
<el-button v-if="props.data?.latestFee.customerConfirmationStatus !== 'CONFIRMED' && props.canConfirm" type="primary" :loading="confirming" @click="confirmFee">确认计费量和费用</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.inbound-billing-panel { margin-top: 14px; }
|
||
.inbound-billing-heading, .inbound-section-title, .fee-total { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
|
||
.inbound-billing-actions { display: flex; align-items: center; gap: 10px; }
|
||
.inbound-billing-heading h3, .inbound-result-section h4 { margin: 0; color: var(--navy); }
|
||
.inbound-billing-heading h3 { font-size: 13px; }
|
||
.inbound-result-section h4 { font-size: 13px; }
|
||
.inbound-billing-loading { min-height: 180px; padding: 18px 0; }
|
||
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
|
||
.inbound-billing-state { display: grid; min-height: 48px; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 10px; margin-top: 8px; padding: 8px 10px; border: 1px dashed #cbd5da; }
|
||
.inbound-billing-state > svg { color: var(--primary); }
|
||
.inbound-billing-state > div { display: flex; min-width: 0; flex-direction: column; gap: 4px; }
|
||
.inbound-billing-state strong { color: var(--navy); font-size: 13px; }
|
||
.inbound-billing-state span { overflow-wrap: anywhere; color: var(--muted); font-size: 11px; line-height: 1.55; }
|
||
.inbound-billing-state.is-error { border-style: solid; border-color: #e8c5bd; background: #fff8f6; }
|
||
.inbound-billing-state.is-error > svg { color: #b5472f; }
|
||
.inbound-overview { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); margin: 12px 0 0; border: 1px solid var(--border); }
|
||
.inbound-overview > div { min-width: 0; padding: 13px; border-bottom: 1px solid var(--border); }
|
||
.inbound-overview > div:nth-child(odd) { border-right: 1px solid var(--border); }
|
||
.inbound-overview > div:nth-last-child(-n + 2) { border-bottom: 0; }
|
||
.inbound-overview dt, .inbound-measurements dt, .fee-calculation-grid dt { color: var(--muted); font-size: 10px; }
|
||
.inbound-overview dd, .inbound-measurements dd, .fee-calculation-grid dd { margin: 5px 0 0; overflow-wrap: anywhere; color: var(--navy); font-size: 12px; font-weight: 650; }
|
||
.inbound-result-section { margin-top: 18px; }
|
||
.inbound-section-title > span { color: var(--muted); font-size: 10px; text-align: right; }
|
||
.inbound-measurements { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin: 10px 0 0; background: #f6f8f8; }
|
||
.inbound-measurements > div { min-width: 0; padding: 12px; }
|
||
.measurement-detail-table { margin-top: 12px; }
|
||
.fee-dialog-summary { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:12px; margin:0; }
|
||
.fee-dialog-summary > div { position:relative; min-width:0; overflow:hidden; padding:13px 17px; border:1px solid #e4e8f2; border-radius:11px; background:linear-gradient(145deg,#fff,#f8f9fc); box-shadow:0 5px 16px rgba(51,65,85,.04); }
|
||
.fee-dialog-summary > div::before { position:absolute; inset:0 auto 0 0; width:4px; background:#a7b4ef; content:''; }
|
||
.fee-dialog-summary > div:nth-child(2)::before { background:#7d91eb; }
|
||
.fee-dialog-summary > div:nth-child(3) { border-color:#cdd7ff; background:linear-gradient(145deg,#f8faff,#eef2ff); box-shadow:0 8px 22px rgba(82,110,232,.09); }
|
||
.fee-dialog-summary > div:nth-child(3)::before { background:#526ee8; }
|
||
.fee-dialog-summary dt { margin:0 0 3px; color:#7b8494; font-size:13px; font-weight:500; }
|
||
.fee-dialog-summary dd { margin:0; overflow-wrap:anywhere; color:#283246; font-size:20px; font-weight:700; font-variant-numeric:tabular-nums; letter-spacing:0; }
|
||
.fee-dialog-summary > div:nth-child(3) dt { color:#6578c5; }
|
||
.fee-dialog-summary > div:nth-child(3) dd { color:#405fd8; font-size:22px; }
|
||
.fee-dialog-table { margin-top:16px; overflow:hidden; border-radius:10px; box-shadow:0 5px 18px rgba(51,65,85,.04); }
|
||
.fee-dialog-table :deep(.el-table__header th.el-table__cell) { height:42px; padding:9px 0; background:linear-gradient(180deg,#f8f9fc,#f3f5f9); color:#697386; font-size:13px; font-weight:650; }
|
||
.fee-dialog-table :deep(.el-table__body td.el-table__cell) { height:82px; padding:9px 0; color:#515a6c; font-size:14px; font-variant-numeric:tabular-nums; }
|
||
.fee-dialog-table :deep(.el-table__body td:nth-child(7)), .fee-dialog-table :deep(.el-table__body td:nth-child(8)) { color:#34466b; font-weight:650; }
|
||
.fee-dialog-table :deep(.cell) { line-height:1.6; }
|
||
.fee-confirm-notice { display:flex; align-items:center; gap:10px; margin-top:14px; padding:10px 14px; border:1px solid #f5dfba; border-radius:9px; background:linear-gradient(90deg,#fff9ef,#fffaf2); color:#c6790c; font-size:14px; font-weight:500; }
|
||
.fee-confirm-notice > svg { flex:0 0 auto; fill:#eda332; color:#fff; filter:drop-shadow(0 2px 3px rgba(233,154,37,.25)); }
|
||
.fee-confirm-notice.is-confirmed { border-color:#b7dfc2; background:#f1faf3; color:#2d8a46; }
|
||
.fee-confirm-notice.is-confirmed > svg { fill:#4eae67; }
|
||
.pallet-location-list { margin-top: 9px; border-top: 1px solid var(--border); }
|
||
.pallet-location-list article { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 11px; padding: 12px 0; border-bottom: 1px solid var(--border); }
|
||
.pallet-location-list article > svg { color: var(--primary); }
|
||
.pallet-location-main, .pallet-location-quantity { display: flex; min-width: 0; flex-direction: column; gap: 3px; }
|
||
.pallet-location-main strong { overflow-wrap: anywhere; color: var(--navy); font-size: 12px; }
|
||
.pallet-location-main span, .pallet-location-quantity span { color: var(--muted); font-size: 10px; }
|
||
.pallet-location-quantity { align-items: flex-end; }
|
||
.inbound-inline-empty { margin: 9px 0 0; padding: 14px; background: #f6f8f8; color: var(--muted); font-size: 11px; text-align: center; }
|
||
.fee-result { padding-top: 18px; border-top: 1px solid var(--border); }
|
||
.fee-calculation-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin: 10px 0 0; border: 1px solid var(--border); }
|
||
.fee-calculation-grid > div { min-width: 0; padding: 11px 12px; border-bottom: 1px solid var(--border); }
|
||
.fee-calculation-grid > div:not(:nth-child(3n)) { border-right: 1px solid var(--border); }
|
||
.fee-calculation-grid > div:nth-last-child(-n + 3) { border-bottom: 0; }
|
||
.fee-total { padding: 15px 0 0; }
|
||
.fee-total > div { display: flex; min-width: 0; flex-direction: column; gap: 4px; }
|
||
.fee-total span { color: var(--navy); font-size: 12px; font-weight: 650; }
|
||
.fee-total small, .fee-sent-time { color: var(--muted); font-size: 10px; }
|
||
.fee-total strong { flex: 0 0 auto; color: var(--primary); font-size: 21px; }
|
||
.fee-sent-time { margin: 5px 0 0; text-align: right; }
|
||
.inbound-public-remark { margin-top: 16px; padding: 13px 14px; background: #f2f7f6; }
|
||
.inbound-public-remark strong { color: var(--navy); font-size: 11px; }
|
||
.inbound-public-remark p { margin: 5px 0 0; overflow-wrap: anywhere; color: var(--muted); font-size: 11px; line-height: 1.55; white-space: pre-wrap; }
|
||
|
||
:global(.billing-confirm-dialog) { max-height:calc(100vh - 40px); overflow:hidden; border-radius:14px; box-shadow:0 28px 90px rgba(17,24,39,.33); }
|
||
:global(.billing-confirm-dialog .el-dialog__header) { display:flex; align-items:center; min-height:66px; margin:0; padding:16px 22px 14px; border-bottom:1px solid #edf0f5; }
|
||
:global(.billing-confirm-dialog .el-dialog__title) { color:#252b38; font-size:22px; font-weight:700; line-height:1.4; letter-spacing:0; }
|
||
:global(.billing-confirm-dialog .el-dialog__headerbtn) { top:14px; right:20px; width:36px; height:36px; border-radius:50%; background:#f5f6f9; }
|
||
:global(.billing-confirm-dialog .el-dialog__headerbtn:hover) { background:#e9edfa; }
|
||
:global(.billing-confirm-dialog .el-dialog__headerbtn .el-dialog__close) { color:#8b92a0; font-size:22px; }
|
||
:global(.billing-confirm-dialog .el-dialog__body) { max-height:calc(100vh - 174px); overflow:auto; padding:18px 22px; }
|
||
:global(.billing-confirm-dialog .el-dialog__footer) { padding:14px 22px 16px; border-top:1px solid #edf0f5; }
|
||
:global(.billing-confirm-dialog .el-dialog__footer .el-button) { min-height:40px; padding:0 20px; border-radius:8px; font-size:14px; font-weight:650; }
|
||
:global(.billing-confirm-dialog .el-dialog__footer .el-button--primary) { min-width:168px; border-color:#526ee8; background:linear-gradient(135deg,#647fec,#526ee8); box-shadow:0 7px 16px rgba(82,110,232,.17); }
|
||
|
||
@media (max-width: 720px) {
|
||
.fee-dialog-summary { grid-template-columns: 1fr; gap: 8px; }
|
||
.fee-dialog-summary dd, .fee-dialog-summary > div:nth-child(3) dd { font-size: 18px; }
|
||
:global(.billing-confirm-dialog) { width:calc(100vw - 16px) !important; max-height:calc(100vh - 16px); }
|
||
:global(.billing-confirm-dialog .el-dialog__header) { padding:14px 16px 11px; }
|
||
:global(.billing-confirm-dialog .el-dialog__title) { font-size:19px; }
|
||
:global(.billing-confirm-dialog .el-dialog__body) { max-height:calc(100vh - 145px); padding:14px 16px; }
|
||
:global(.billing-confirm-dialog .el-dialog__footer) { padding:12px 16px; }
|
||
:global(.billing-confirm-dialog .el-dialog__footer .el-button) { min-height:38px; padding:0 14px; font-size:13px; }
|
||
.inbound-billing-state { grid-template-columns: auto minmax(0, 1fr); }
|
||
.inbound-billing-state .el-button { grid-column: 1 / -1; width: 100%; min-height: 44px; }
|
||
.inbound-overview, .inbound-measurements, .fee-calculation-grid { grid-template-columns: 1fr; }
|
||
.inbound-overview > div, .inbound-overview > div:nth-child(odd), .fee-calculation-grid > div, .fee-calculation-grid > div:not(:nth-child(3n)) { border-right: 0; border-bottom: 1px solid var(--border); }
|
||
.inbound-overview > div:last-child, .fee-calculation-grid > div:last-child { border-bottom: 0; }
|
||
.pallet-location-list article { grid-template-columns: auto minmax(0, 1fr); }
|
||
.pallet-location-quantity { grid-column: 2; align-items: flex-start; flex-direction: row; flex-wrap: wrap; gap: 8px; }
|
||
}
|
||
|
||
@media (max-width: 360px) {
|
||
.inbound-billing-heading { align-items: flex-start; flex-direction: column; }
|
||
.fee-total { align-items: flex-start; flex-direction: column; }
|
||
.fee-total strong { font-size: 19px; }
|
||
.fee-sent-time { text-align: left; }
|
||
}
|
||
</style>
|