@@ -1,7 +1,7 @@
< script setup lang = "ts" >
import { computed , nextTick , onBeforeUnmount , onMounted , reactive , ref , watch , type Component } from 'vue'
import { ElMessage , ElMessageBox , type UploadFile } from 'element-plus'
import { ArrowLeft , Box , ChevronDown , ChevronUp , CircleCheck , Download , Eye , FileUp , GitBranch , History , Link2 , ListChecks , MoreHorizontal , PackageOpen , Printer , Ruler , Send , ShieldAlert , SlidersHorizontal , StickyNote , Undo2 , WalletCards } from '@lucide/vue'
import { ArrowLeft , ChevronDown , ChevronUp , CircleCheck , Download , Eye , FileUp , GitBranch , Link2 , MoreHorizontal , PackageOpen , Printer , Ruler , Send , ShieldAlert , SlidersHorizontal , StickyNote , Undo2 } from '@lucide/vue'
import { useRoute , useRouter } from 'vue-router'
import {
getPlatformUnifiedOrder ,
@@ -622,7 +622,7 @@ const queryFields = computed(() => showAdvancedFilters.value
const columns = computed < DataTableColumn [ ] > ( ( ) => [
// 业务表格保持操作列第一;批量选择列仅在有对应权限时紧随其后。
{ key : 'actions' , label : '操作' , width : 290 , fixed : 'left' , slotName : 'actions' } ,
{ key : 'actions' , label : '操作' , width : 260 , fixed : 'left' , slotName : 'actions' } ,
... ( can ( 'platform:order:approve' ) || can ( 'platform:firstleg:smart-loading:assign' ) || can ( 'platform:order:export' ) || can ( 'platform:firstleg:inbound:view' ) ? [ {
key : 'selection' , type : 'selection' , width : 48 , fixed : 'left' ,
selectable : ( ) => ! batchApprovalSaving . value && ! coLoadSaving . value && ! exportSubmitting . value ,
@@ -2199,7 +2199,7 @@ onBeforeUnmount(() => {
< template >
< AdminPage >
< section class = "business-page unified-orders-page" >
< AppDialog v-model = "feeConfirmOpen" title="编辑计费数据" confirm-text="确认并发送" :confirm-loading="confirmFeeSending || feeConfirmReferenceLoading" width="min(920px, 94vw)" :teleported="false" @confirm="executeConfirmAndSendFee" >
< AppDialog class = "order-density-dialog" v-model = "feeConfirmOpen" title="编辑计费数据" confirm-text="确认并发送" :confirm-loading="confirmFeeSending || feeConfirmReferenceLoading" width="min(920px, 94vw)" :teleported="false" @confirm="executeConfirmAndSendFee" >
< el -alert class = "fee-confirm-price-alert" title = "价格表单价仅作为参考;本次对客单价可人工修改,客户将一次确认计费量、单价和费用合计。" type = "info" :closable = "false" show -icon / >
< el-form label -position = " top " class = "fee-confirm-form" >
< el-form-item label = "入仓码" > < el-input : model -value = " detail ? .summary.inboundCode | | ' — ' " disabled / > < / el-form-item >
@@ -2219,7 +2219,7 @@ onBeforeUnmount(() => {
< el-table :data = "feeConfirmRows" border size = "small" >
< el-table-column prop = "source" label = "数据来源" / >
< el-table-column prop = "count" label = "件数" / >
< el-table-column label = "总毛重(T.K.GW)" > < template # default = "{ row }" > { { row . weight == null ? '—' : formatNumber ( row . weight , 2 ) } } < / template > < / el-table-column >
< el-table-column label = "总毛重(T.K.GW)" align = "right" > < template # default = "{ row }" > { { row . weight == null ? '—' : formatNumber ( row . weight , 2 ) } } < / template > < / el-table-column >
< el-table-column label = "总体积(m³)" > < template # default = "{ row }" > { { row . volume == null ? '—' : formatNumber ( row . volume , 4 ) } } < / template > < / el-table-column >
< el-table-column label = "总材积重" > < template # default = "{ row }" > { { row . volume == null ? '—' : formatNumber ( Number ( row . volume ) * 167 , 2 ) } } < / template > < / el-table-column >
< / el-table >
@@ -2229,7 +2229,6 @@ onBeforeUnmount(() => {
< header class = "order-detail-header" >
< div class = "order-detail-heading" >
< el-button link class = "back-button" @click ="fromMeasurementReview ? returnToMeasurementReviews() : closeDetail()" > < ArrowLeft :size = "16" / > { { fromMeasurementReview ? '返回测量审核列表' : '返回列表' } } < / el-button >
< span class = "order-mark" aria -hidden = " true " > < Box :size = "19" / > < / span >
< div class = "order-title" >
< h1 > { { detail ? . summary . inboundCode || '入仓码暂缺' } } < / h1 >
< / div >
@@ -2247,12 +2246,15 @@ onBeforeUnmount(() => {
< div v-else v-loading = "detailLoading" class="order-detail-content" >
< template v-if = "detail" >
< section class = "detail-overview" aria -label = " 订单概览 " >
< article > < span > 客户 < / span > < strong > { { customerName ( detail . summary ) } } < / strong > < small > { { detail . summary . channelName || '未配置渠道' } } < / small > < / article >
< article > < span > 总箱数 < / span > < strong > { { detail . summary . totalPackageCount ? ? '—' } } < small > 箱 < / small > < / strong > < small > { { detail . order . cargoes . length } } 条货品明细 < / small > < / article >
< article > < span > 实测毛重 < / span > < strong > { { formatNumber ( detail . summary . measurement ? . actualGrossWeightKg ) } } < small > kg < / small > < / strong > < small > { { measurementStatusLabel ( detail . summary . measurement ? . reviewStatus ) } } < / small > < / article >
< article > < span > 实测体积 < / span > < strong > { { formatNumber ( detail . summary . measurement ? . actualVolumeCbm , 3 ) } } < small > m³ < / small > < / strong > < small > 最近更新 { { formatDate ( detail . summary . updatedAt ) } } < / small > < / article >
< / section >
< dl class = "detail-overview" aria -label = " 订单概览 " >
< div > < dt > 客户 < / dt > < dd > { { customerName ( detail . summary ) } } < / dd > < / div >
< div > < dt > 渠道 < / dt > < dd > { { detail . summary . channelName || '未配置渠道' } } < / dd > < / div >
< div > < dt > 总箱数 < / dt > < dd > { { detail . summary . totalPackageCount ? ? '—' } } 箱 < small > ( { { detail . order . cargoes . length } } 条货品 ) < / small > < / dd > < / div >
< div > < dt > 实测毛重 < / dt > < dd > { { formatNumber ( detail . summary . measurement ? . actualGrossWeightKg ) } } kg < / dd > < / div >
< div > < dt > 实测体积 < / dt > < dd > { { formatNumber ( detail . summary . measurement ? . actualVolumeCbm , 3 ) } } m³ < / dd > < / div >
< div > < dt > 测量审核 < / dt > < dd > { { measurementStatusLabel ( detail . summary . measurement ? . reviewStatus ) } } < / dd > < / div >
< div > < dt > 最近更新 < / dt > < dd > { { formatDate ( detail . summary . updatedAt ) } } < / dd > < / div >
< / dl >
< div class = "detail-tabs" role = "tablist" aria -label = " 订单详情模块 " >
< button v-for = "tab in detailTabs" :id="`order-detail-tab-${tab.key}`" :key="tab.key" type="button" role="tab" :class="{ active: activeDetailTab === tab.key }" :aria-selected="activeDetailTab === tab.key" :aria-controls="`order-detail-panel-${tab.key}`" :tabindex="activeDetailTab === tab.key ? 0 : -1" @click="selectDetailTab(tab.key)"><component :is="tab.icon" :size="17" / > < span > { { tab . label } } < / span > < / button >
@@ -2260,17 +2262,16 @@ onBeforeUnmount(() => {
< section :id = "`order-detail-panel-${activeDetailTab}`" class = "detail-panel" role = "tabpanel" :aria-labelledby = "`order-detail-tab-${activeDetailTab}`" tabindex = "0" >
< template v-if = "activeDetailTab === 'basic'" >
< div class = "panel-title" > < div > < h2 > 订单基本信息 < / h2 > < p > { { detail . summary . inboundCode || '入仓码暂缺' } } < / p > < / div > < Box :size = "19" / > < / div >
< dl class = "order-info-grid" >
< div > < dt > 公司 < / dt > < dd > { { customerName ( detail . summary ) } } < / dd > < / div >
< div > < dt > 运输方式 < / dt > < dd > { { firstLegTransportModeLabel ( detail . order . order ? . transportMode ) } } < / dd > < / div >
< div > < dt > 当前状态 < / dt > < dd > < StatusBadge :status = "statusLabel(detail.summary.mainStatus)" / > < / dd > < / div >
< div > < dt > 内部订单状态 < / dt > < dd > { { orderStatusLabel ( detail . summary . internalOrderStatus || detail . summary . mainStatus ) } } < / dd > < / div >
< div > < dt > 平台收货仓 < / dt > < dd > { { detail . summary . receivingWarehouseName || '—' } } < / dd > < / div >
< div > < dt > 收货仓地址 < / dt > < dd > { { detail . order . order ? . receivingWarehouseAddress || '—' } } < / dd > < / div >
< div class = "wide" > < dt > 收货仓地址 < / dt > < dd > { { detail . order . order ? . receivingWarehouseAddress || '—' } } < / dd > < / div >
< div > < dt > 目的仓 < / dt > < dd > { { detail . summary . destinationWarehouseName || '—' } } < / dd > < / div >
< div > < dt > 目的国家 < / dt > < dd > { { detail . order . order ? . destinationCountryCode || '—' } } < / dd > < / div >
< div > < dt > 目的仓地址 < / dt > < dd > { { detail . summary . destinationAddress || '—' } } < / dd > < / div >
< div class = "wide" > < dt > 目的仓地址 < / dt > < dd > { { detail . summary . destinationAddress || '—' } } < / dd > < / div >
< div > < dt > 目的仓邮编 < / dt > < dd > { { detail . summary . destinationPostalCode || '—' } } < / dd > < / div >
< div > < dt > 目的仓联系人 < / dt > < dd > { { detail . summary . destinationContact || '—' } } < / dd > < / div >
< div > < dt > 目的仓联系人电话 < / dt > < dd > { { detail . summary . destinationContactPhone || '—' } } < / dd > < / div >
@@ -2324,30 +2325,29 @@ onBeforeUnmount(() => {
< / template >
< template v-else-if = "activeDetailTab === 'cargo'" >
< div class = "panel-title" > < div > < h2 > 货品信息 < / h2 > < p > 共 { { detail . order . cargoes . length } } 条 < / p > < / div > < el-button v-if = "canEditDeclaration" type="primary" size="small" @click="declarationEditorOpen = true" > 编辑客户申报资料 < / el -button > < / div >
< div class = "panel-title" > < p > 共 { { detail . order . cargoes . length } } 条货品 < / p > < el-button v-if = "canEditDeclaration" type="primary" size="small" @click="declarationEditorOpen = true" > 编辑客户申报资料 < / el -button > < / div >
< div class = "detail-table-wrap" >
< el-table :data = "detail.order.cargoes" border stripe empty -text = " 暂无货品信息 " >
< el-table-column prop = "itemNo" label = "#" width = "64" / >
< el-table-column label = "报关HS_CODE" min -width = " 130 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'hsCode' ) } } < / template > < / el-table-column >
< el-table-column label = "货品图片" width = "110" > < template # default = "{ row }" > < el-image v-if = "cargoImage(row as Record<string, unknown>)" :src="cargoImage(row as Record<string, unknown>)" fit="contain" class="cargo-image" / > < span v-else > — < / span > < / template > < / el -table -column >
< el-table-column label = "货品图片" width = "110" > < template # default = "{ row }" > < el-image v-if = "cargoImage(row as Record<string, unknown>)" :src="cargoImage(row as Record<string, unknown>)" :preview-src-list="[cargoImage(row as Record<string, unknown>)]" preview-teleported fit="contain" class="cargo-image" / > < span v-else > — < / span > < / template > < / el -table -column >
< el-table-column label = "SKU NO." min -width = " 150 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'skuNo' ) } } < / template > < / el-table-column >
< el-table-column label = "中文品名" min -width = " 170 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'cargoName' ) } } < / template > < / el-table-column >
< el-table-column label = "英文品名" min -width = " 170 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'cargoNameEn' ) } } < / template > < / el-table-column >
< el-table-column label = "清关HS_CODE" min -width = " 130 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'customsHsCode' ) } } < / template > < / el-table-column >
< el-table-column label = "箱规长(cm)" min -width = " 110 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'lengthCm' ) } } < / template > < / el-table-column >
< el-table-column label = "箱规宽(cm)" min -width = " 110 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'widthCm' ) } } < / template > < / el-table-column >
< el-table-column label = "箱规高(cm)" min -width = " 110 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'heightCm' ) } } < / template > < / el-table-column >
< el-table-column label = "箱规周长(cm)" min -width = " 120 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'circumferenceCm' ) } } < / template > < / el-table-column >
< el-table-column label = "每箱产品数量" min -width = " 130 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'unitsPerPackage' ) } } < / template > < / el-table-column >
< el-table-column label = "箱数" width = "90" > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'packageCount' ) } } < / template > < / el-table-column >
< el-table-column label = "总毛重(T.KGW)" min -width = " 140 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'grossWeightKg' ) } } < / template > < / el-table-column >
< el-table-column label = "总净重(T.KNW)" min -width = " 140 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'netWeightKg' ) } } < / template > < / el-table-column >
< el-table-column label = "箱规长(cm)" align = "right" min -width = " 110 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'lengthCm' ) } } < / template > < / el-table-column >
< el-table-column label = "箱规宽(cm)" align = "right" min -width = " 110 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'widthCm' ) } } < / template > < / el-table-column >
< el-table-column label = "箱规高(cm)" align = "right" min -width = " 110 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'heightCm' ) } } < / template > < / el-table-column >
< el-table-column label = "箱规周长(cm)" align = "right" min -width = " 120 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'circumferenceCm' ) } } < / template > < / el-table-column >
< el-table-column label = "每箱产品数量" align = "right" min -width = " 130 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'unitsPerPackage' ) } } < / template > < / el-table-column >
< el-table-column label = "箱数" align = "right" width = "90" > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'packageCount' ) } } < / template > < / el-table-column >
< el-table-column label = "总毛重(T.KGW)" align = "right" min -width = " 140 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'grossWeightKg' ) } } < / template > < / el-table-column >
< el-table-column label = "总净重(T.KNW)" align = "right" min -width = " 140 " > < template # default = "{ row }" > { { cargoValue ( row as Record < string , unknown > , 'netWeightKg' ) } } < / template > < / el-table-column >
< / el-table >
< / div >
< / template >
< template v-else-if = "activeDetailTab === 'fees'" >
< div class = "panel-title" > < div > < h2 > 费用信息 < / h2 > < p > 头程自动初算与其他人工费用在同一页维护 < / p > < / div > < WalletCards :size = "19" / > < / div >
< el -empty v-if = "!normalizedInboundId" description="订单尚未生成入库单,暂无入仓费用" :image-size="64" / >
< template v-else >
< dl class = "fee-overview" aria -label = " 费用汇总 " >
@@ -2375,13 +2375,18 @@ onBeforeUnmount(() => {
< / template >
< template v-else-if = "activeDetailTab === 'history'" >
< div class = "panel-title" > < div > < h2 > 状态历史 < / h2 > < p > 共 { { detail . timeline . length } } 条 < / p > < / div > < History :size = "19" / > < / div >
< el-empty v-if = "detail.timeline.length === 0" description="暂无状态历史" :image-size="64" / >
< ol v-else class = "history-list" aria -label = " 状态历史 " > < li v-for = "(item, index) in detail.timeline" :key="`${item.source || 'event'}-${item.occurredAt || index}`"><span class="history-marker" aria-hidden="true" /><div><div class="history-line"><strong>{{ historyActionLabel(item.action || item.eventType) }}</strong><StatusBadge :status="statusLabel(item.mainStatus)" /></div><p>{{ item.operatorName || '系统' }} · {{ formatDate(item.occurredAt) }}</p><p v-if="item.remark" class="history-remark "> {{ item.remark }} < / p > < / div > < / li > < / ol >
< div class = "panel-title" > < p > 共 { { detail . timeline . length } } 条记录 < / p > < / div >
< el-table :data = "detail.timeline" class = "history-table" border stripe empty -text = " 暂无状态历史 " aria -label = " 状态历史 " >
< el-table-column label = "时间" width = "172" > < template # default = "{ row } "> { { formatDate ( row . occurredAt ) } } < / template > < / el-table-column >
< el-table-column label = "事件" min -width = " 180 " > < template # default = "{ row }" > { { historyActionLabel ( row . action || row . eventType ) } } < / template > < / el-table-column >
< el-table-column label = "状态" width = "166" > < template # default = "{ row }" > < StatusBadge :status = "statusLabel(row.mainStatus)" / > < / template > < / el-table-column >
< el-table-column label = "操作人" min -width = " 160 " > < template # default = "{ row }" > { { row . operatorName || '系统' } } < / template > < / el-table-column >
< el-table-column label = "备注" min -width = " 300 " > < template # default = "{ row }" > { { row . remark || '—' } } < / template > < / el-table-column >
< / el-table >
< / template >
< template v-else-if = "activeDetailTab === 'fulfillment'" >
< div class = "panel-title" > < div > < h2 > 拆分履约 < / h2 > < p > 根单 、 已完成分片与当前余量 < / p > < / div > < ListChecks :size = "19" / > < / div >
< div class = "panel-title" > < p > 根单 、 已完成分片与当前余量 < / p > < / div >
< OrderFulfillmentTreePanel :tenant-id = "String(detail.summary.tenantId)" :order-id = "String(detail.summary.orderId)" :inbound-code = "detail.summary.inboundCode" / >
< section v-loading = "subsequentFulfillmentLoading" class="subsequent-fulfillment" aria-label="后续履约数据" >
< h3 > 后续履约数据 < / h3 >
@@ -2407,7 +2412,7 @@ onBeforeUnmount(() => {
< template v-else-if = "activeDetailTab === 'measurement'" >
< div class = "panel-title" >
< div > < h2 > 测量数据 < / h2 > < p > { { detail . summary . measurement ? . completedAt ? ` 完成于 ${ formatDate ( detail . summary . measurement . completedAt ) } ` : '尚未完成测量' } } < / p > < / div >
< p > { { detail . summary . measurement ? . completedAt ? ` 测量 完成于 ${ formatDate ( detail . summary . measurement . completedAt ) } ` : '尚未完成测量' } } < / p >
< div class = "measurement-title-actions" >
< el-button
v-if = "can('firstleg:inbound:confirm-send-fee')"
@@ -2426,17 +2431,17 @@ onBeforeUnmount(() => {
< / LoadErrorState >
< template v-else >
< section class = "measurement-section" >
< div class = "measurement-section-title" > < button type = "button" class = "measurement-section-toggle" :aria-expanded = "!measurementCollapsed.customer" @click ="toggleMeasurementSection('customer')" > < h3 > 一 、 客户下单数据 < / h3 > < span class = "measurement-section-summary" > < span > 总件数 : { { measurementTotals ( customerMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . volume , 6 ) } } < / span > < span > 总材积重 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . volumetric ) } } < / span > < span > 重量体积 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . weightVolume , 6 ) } } < / span > < / span > < ChevronUp v-if = "!measurementCollapsed.customer" :size="18" /><ChevronDown v-else :size="18" /></button><el-select class="measurement-section-mode" :model-value="measurementSectionModes.customer" aria-label="客户下单数据计算方式" @change="updateMeasurementSectionMode('customer', $event)"><el-option label="实测原尺寸(不调整)" value="ACTUAL" /><el-option label="箱规尺寸" value="ADD" /><el-option label="箱规系数" value="MULTIPLY" :disabled="multiplyModeDisabled" / > < / el-select > < / div >
< div class = "measurement-section-title" > < button type = "button" class = "measurement-section-toggle" :aria-expanded = "!measurementCollapsed.customer" @click ="toggleMeasurementSection('customer')" > < h3 > 一 、 客户下单数据 < / h3 > < span v-if = "measurementCollapsed.customer" class="measurement-section-summary"><span>总件数:{{ measurementTotals(customerMeasurementRows).count ?? '—' }}</span><span>总毛重:{{ formatNumber(measurementTotals(customerMeasurementRows).gross) }}</span><span>总体积:{{ formatNumber(measurementTotals(customerMeasurementRows).volume, 6) }}</span><span>总材积重:{{ formatNumber(measurementTotals(customerMeasurementRows).volumetric) }}</span><span>重量体积:{{ formatNumber(measurementTotals(customerMeasurementRows).weightVolume, 6) }}</span></span><ChevronUp v-if= "!measurementCollapsed.customer" :size="18" /><ChevronDown v-else :size="18" /></button><el-select class="measurement-section-mode" :model-value="measurementSectionModes.customer" aria-label="客户下单数据计算方式" @change="updateMeasurementSectionMode('customer', $event)"><el-option label="实测原尺寸(不调整)" value="ACTUAL" /><el-option label="箱规尺寸" value="ADD" /><el-option label="箱规系数" value="MULTIPLY" :disabled="multiplyModeDisabled" / > < / el-select > < / div >
< div v-if = "!measurementCollapsed.customer" >
< div class = "detail-table-wrap" > < el-table :data = "customerMeasurementRows" border stripe empty -text = " 暂无客户下单数据 " > < el-table-column v-for = "column in customerMeasurementColumns" :key="column.key" :label="column.label" :prop="column.key" min-width="120"><template #default="{ row }"><LineClampText v-if="column.key === 'remark'" :content="measurementValue(row as Record<string, unknown>, column.key)" / > < template v-else > {{ measurementValue ( row as Record < string , unknown > , column . key ) } } < / template > < / template > < / el-table-column > < / el-table > < / div >
< div class = "measurement-total" > < strong > 合计 < / strong > < span > 箱数 : { { measurementTotals ( customerMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . volume , 6 ) } } < / span > < span > 总材积 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . volumetric ) } } < / span > < / div >
< div class = "measurement-total" > < strong > 合计 < / strong > < span > 箱数 : { { measurementTotals ( customerMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . volume , 6 ) } } < / span > < span > 总材积重 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . volumetric ) } } < / span > < span > 重量体积 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . weightVolume , 6 ) } } < / span > < / div >
< / div >
< / section >
< section class = "measurement-section" >
< div class = "measurement-section-title" > < button type = "button" class = "measurement-section-toggle" :aria-expanded = "!measurementCollapsed.outer" @click ="toggleMeasurementSection('outer')" > < h3 > 二 、 外箱规数据 < / h3 > < span class = "measurement-section-summary" > < span > 总件数 : { { measurementTotals ( outerMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . volume , 6 ) } } < / span > < span > 总材积重 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . volumetric ) } } < / span > < span > 重量体积 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . weightVolume , 6 ) } } < / span > < / span > < ChevronUp v-if = "!measurementCollapsed.outer" :size="18" /><ChevronDown v-else :size="18" /></button><el-tooltip :content="measurementStrategyLockedHint" :disabled="measurementStrategyEditable"><span><el-select class="measurement-section-mode" :model-value="measurementSectionModes.outer" aria-label="外箱规数据计算方式" :loading="Boolean(measurementStrategySavingId)" :disabled="Boolean(measurementStrategySavingId) || !measurementStrategyEditable" @change="selectAndSaveOuterMeasurementMode($event)"><el-option label="实测原尺寸(不调整)" value="ACTUAL" /><el-option label="箱规尺寸" value="ADD" /><el-option label="箱规系数" value="MULTIPLY" :disabled="multiplyModeDisabled" / > < / el-select > < / span > < / el-tooltip > < / div >
< div class = "measurement-section-title" > < button type = "button" class = "measurement-section-toggle" :aria-expanded = "!measurementCollapsed.outer" @click ="toggleMeasurementSection('outer')" > < h3 > 二 、 外箱规数据 < / h3 > < span v-if = "measurementCollapsed.outer" class="measurement-section-summary"><span>总件数:{{ measurementTotals(outerMeasurementRows).count ?? '—' }}</span><span>总毛重:{{ formatNumber(measurementTotals(outerMeasurementRows).gross) }}</span><span>总体积:{{ formatNumber(measurementTotals(outerMeasurementRows).volume, 6) }}</span><span>总材积重:{{ formatNumber(measurementTotals(outerMeasurementRows).volumetric) }}</span><span>重量体积:{{ formatNumber(measurementTotals(outerMeasurementRows).weightVolume, 6) }}</span></span><ChevronUp v-if="!measurementCollapsed.outer" :size="18" /><ChevronDown v-else :size="18" / > < / button > < / div >
< div v-if = "!measurementCollapsed.outer" >
< div v-loading = "measurementLoading" class="detail-table-wrap"><el-table :data="outerMeasurementRows" border stripe empty-text="暂无外箱规数据"><el-table-column label="#" prop="itemNo" min-width="70" /><el-table-column v-for="column in outerColumns.filter((item) => item.key !== 'itemNo')" :key="column.key" :label="column.label" :prop="column.key" min-width="150"><template #default="{ row }"><LineClampText v-if="column.key === 'remark'" :content="measurementValue(row as Record<string, unknown>, column.key)" / > < template v-else > {{ measurementValue ( row as Record < string , unknown > , column . key ) } } < / template > < / template > < / el-table-column > < / el-table > < / div >
< div class = "measurement-total" > < strong > 合计 < / strong > < span > 箱数 : { { measurementTotals ( outerMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . volume , 6 ) } } < / span > < span > 总材积 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . volumetric ) } } < / span > < / div >
< div class = "measurement-total" > < strong > 合计 < / strong > < span > 箱数 : { { measurementTotals ( outerMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . volume , 6 ) } } < / span > < span > 总材积重 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . volumetric ) } } < / span > < span > 重量体积 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . weightVolume , 6 ) } } < / span > < / div >
< / div >
< / section >
< div class = "measurement-rule-selector" >
@@ -2449,10 +2454,13 @@ onBeforeUnmount(() => {
< span class = "measurement-rule-selector__hint" > { { measurementStrategyEditable ? '规则参数来源:客户管理' : measurementStrategyLockedHint } } < / span >
< / div >
< section class = "measurement-section" >
< div class = "measurement-section-title" > < button type = "button" class = "measurement-section-toggle" :aria-expanded = "!measurementCollapsed.actual" @click ="toggleMeasurementSection('actual')" > < h3 > 三 、 实际测量数据 < / h3 > < span class = "measurement-section-summary" > < span > 总件数 : { { measurementTotals ( actualMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . volume , 6 ) } } < / span > < span > 总材积重 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . volumetric ) } } < / span > < span > 重量体积 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . weightVolume , 6 ) } } < / span > < / span > < ChevronUp v-if = "!measurementCollapsed.actual" :size="18" /><ChevronDown v-else :size="18" /></button><el-select class="measurement-section-mode" :model-value="measurementSectionModes.actual" aria-label="实际测量数据计算方式" @change="updateMeasurementSectionMode('actual', $event)"><el-option label="实测原尺寸(不调整)" value="ACTUAL" /><el-option label="箱规尺寸" value="ADD" /><el-option label="箱规系数" value="MULTIPLY" :disabled="multiplyModeDisabled" / > < / el-select > < / div >
< div class = "measurement-section-title" > < button type = "button" class = "measurement-section-toggle" :aria-expanded = "!measurementCollapsed.actual" @click ="toggleMeasurementSection('actual')" > < h3 > 三 、 实际测量数据 < / h3 > < span v-if = "measurementCollapsed.actual" class="measurement-section-summary"><span>总件数:{{ measurementTotals(actualMeasurementRows).count ?? '—' }}</span><span>总毛重:{{ formatNumber(measurementTotals(actualMeasurementRows).gross) }}</span><span>总体积:{{ formatNumber(measurementTotals(actualMeasurementRows).volume, 6) }}</span><span>总材积重:{{ formatNumber(measurementTotals(actualMeasurementRows).volumetric) }}</span><span>重量体积:{{ formatNumber(measurementTotals(actualMeasurementRows).weightVolume, 6) }}</span></span><ChevronUp v-if= "!measurementCollapsed.actual" :size="18" /><ChevronDown v-else :size="18" /></button><el-select class="measurement-section-mode" :model-value="measurementSectionModes.actual" aria-label="实际测量数据计算方式" @change="updateMeasurementSectionMode('actual', $event)"><el-option label="实测原尺寸(不调整)" value="ACTUAL" /><el-option label="箱规尺寸" value="ADD" /><el-option label="箱规系数" value="MULTIPLY" :disabled="multiplyModeDisabled" / > < / el-select > < / div >
< div v-if = "!measurementCollapsed.actual" >
< div v-loading = "measurementLoading" class="detail-table-wrap" >
< el -table :data = "actualMeasurementRows" row -key = " id " border stripe empty -text = " 暂无实际测量数据 " >
< el-table-column v-if = "measurementStrategyEditable" label="操作" width="110" fixed="left" >
< template # default = "{ row }" > < el-button type = "primary" plain size = "small" : loading = "measurementOuterSavingId === String(row.id)" :disabled = "Boolean(measurementOuterSavingId)" @click ="saveWarehouseOuterDimensions(row as Record<string, unknown>)" > 保存外箱 < / el -button > < / template >
< / el-table-column >
< el-table-column label = "箱号" prop = "boxCode" min -width = " 190 " fixed = "left" show -overflow -tooltip >
< template # default = "{ row }" > < strong class = "measurement-box-code" > { { row . boxCode || '—' } } < / strong > < / template >
< / el-table-column >
@@ -2466,9 +2474,7 @@ onBeforeUnmount(() => {
< el-table-column label = "仓库修改外箱(高)" width = "190" align = "center" >
< template # default = "{ row }" > < el-input-number v-if = "measurementStrategyEditable" v-model="row.outerHeightCm" class="measurement-outer-dimension-input" aria-label="仓库修改外箱高" :min="0.001" :precision="3" :controls="false" placeholder="不修改" / > < template v-else > {{ formatNumber ( row.outerHeightCm ) }} < / template > < / template >
< / el -table -column >
< el-table-column v-if = "measurementStrategyEditable" label="仓库外箱操作" min-width="120" >
< template # default = "{ row }" > < el-button type = "primary" plain size = "small" : loading = "measurementOuterSavingId === String(row.id)" :disabled = "Boolean(measurementOuterSavingId)" @click ="saveWarehouseOuterDimensions(row as Record<string, unknown>)" > 保存外箱 < / el -button > < / template >
< / el-table-column >
< el-table-column v-for = "column in actualMeasuredColumns" :key="column.key" :label="column.label" :prop="column.key" min-width="120" >
< template # default = "{ row }" > < LineClampText v-if = "column.key === 'remark'" :content="measurementValue(row as Record<string, unknown>, column.key)" / > < template v-else > {{ measurementValue ( row as Record < string , unknown > , column . key ) } } < / template > < / template >
< / el-table-column >
@@ -2486,7 +2492,7 @@ onBeforeUnmount(() => {
< / el-table-column >
< / el-table >
< / div >
< div class = "measurement-total" > < strong > 合计 < / strong > < span > 箱数 : { { measurementTotals ( actualMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . volume , 6 ) } } < / span > < span > 总材积 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . volumetric ) } } < / span > < / div >
< div class = "measurement-total" > < strong > 合计 < / strong > < span > 箱数 : { { measurementTotals ( actualMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . volume , 6 ) } } < / span > < span > 总材积重 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . volumetric ) } } < / span > < span > 重量体积 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . weightVolume , 6 ) } } < / span > < / div >
< section class = "weight-evidence" aria -label = " 称重图片与服务端确认重量 " >
< div class = "weight-evidence__heading" >
< div > < h4 > 称重图片与确认重量 < / h4 > < p > 称重图片独立展示 ; 重量值直接采用服务端确认结果 。 < / p > < / div >
@@ -2510,7 +2516,7 @@ onBeforeUnmount(() => {
< / dl >
< / article >
< / div >
< el-empty v-else description = "暂无称重图片与确认结果" :image-size = "48" / >
< p v-else class = "compact-empty" > 暂无称重图片与确认结果 < / p >
< / section >
< / div >
< / section >
@@ -2537,7 +2543,7 @@ onBeforeUnmount(() => {
< / section >
< section class = "other-notes-section" aria -label = " 内部备注 " >
< div class = "panel-title" > < div > < h2 > 内部备注 < / h2 > < p > 仅平台内部可见 , 独立保存 < / p > < / div > < el-button v-if = "can('platform:order:note')" type="primary" size="small" @click="openNoteDialog()"><StickyNote :size="15" / > 添加备注 < / el-button > < / div >
< el-empty v-if = "detail.order.internalNotes.length === 0" description="暂无内部备注" :image-size="64" / >
< p v-if = "detail.order.internalNotes.length === 0" class="compact-empty" > 暂无内部备注 < / p >
< ul v-else class = "notes-list" aria -label = " 内部备注 " > < li v-for = "item in detail.order.internalNotes" :key="String(item.id)" > < p > { { item . content } } < / p > < span > 操作人 { { item . createdBy || '系统' } } · { { formatDate ( item . createdAt ) } } < / span > < / li > < / ul >
< / section >
< / template >
@@ -2680,7 +2686,7 @@ onBeforeUnmount(() => {
< / template >
< / ListPageLayout >
< SmartLoadingDialog v-model = "smartLoadingOpen" / >
< AppDialog v-model = "batchApprovalOpen" title="批量审核订单" confirm-text="确认批量审核" confirm-type="success" width="min(1100px, calc(100vw - 28px))" :loading="batchApprovalLoading" :confirm-loading="batchApprovalSaving" :confirm-disabled="batchApprovalLoading || !batchApprovalSelectedRows.length" destroy-on-close @confirm="batchApproveOrders" >
< AppDialog class = "order-density-dialog" v-model = "batchApprovalOpen" title="批量审核订单" confirm-text="确认批量审核" confirm-type="success" width="min(1100px, calc(100vw - 28px))" :loading="batchApprovalLoading" :confirm-loading="batchApprovalSaving" :confirm-disabled="batchApprovalLoading || !batchApprovalSelectedRows.length" destroy-on-close @confirm="batchApproveOrders" >
< el -alert title = "请逐票核对入仓码、客户、中文品名、渠道和目的仓;审核通过后订单进入待测量。" type = "info" :closable = "false" show -icon / >
< LoadErrorState v-if = "batchApprovalError" compact title="批量审核预览加载失败" :message="batchApprovalError.message" :loading="batchApprovalLoading" @retry="openBatchApproval"><template #details><ApiErrorMeta :details="batchApprovalError" / > < / template > < / LoadErrorState >
< template v-else >
@@ -2696,12 +2702,12 @@ onBeforeUnmount(() => {
< / el-table >
< / template >
< / AppDialog >
< AppDialog v-model = "coLoadCreateOpen" title="合柜报关" confirm-text="确认建组" :confirm-loading="coLoadSaving" :confirm-disabled="!canCreateCoLoadGroup" @confirm="createCoLoadGroup" >
< AppDialog class = "order-density-dialog" v-model = "coLoadCreateOpen" title="合柜报关" confirm-text="确认建组" :confirm-loading="coLoadSaving" :confirm-disabled="!canCreateCoLoadGroup" @confirm="createCoLoadGroup" >
< el -alert type = "warning" :closable = "false" show -icon : title = "`所选 ${selectedOrders.length} 票须属于同一国内仓、同一渠道,并全量进入同一柜;目的仓或目的港可以不同。资格由服务端按完整入仓片段校验。`" / >
< div class = "coload-selection" > < span v-for = "row in selectedOrders" :key="String(row.orderId)" > {{ row.inboundCode | | ' 待生成入仓码 ' }} < / span > < / div >
< div v-if = "coLoadError" class="coload-error" role="alert"><span>{{ coLoadError.message }}</span><ApiErrorMeta :details="coLoadError" / > < / div >
< / AppDialog >
< AppDialog v-model = "coLoadDetailOpen" title="同柜组成员" :show-confirm="false" cancel-text="关闭" width="min(720px, 94vw)" :loading="coLoadDetailLoading" :confirm-loading="coLoadCancelSaving" >
< AppDialog class = "order-density-dialog" v-model = "coLoadDetailOpen" title="同柜组成员" :show-confirm="false" cancel-text="关闭" width="min(720px, 94vw)" :loading="coLoadDetailLoading" :confirm-loading="coLoadCancelSaving" >
< LoadErrorState v-if = "coLoadDetailError" title="同柜组成员加载失败" :message="coLoadDetailError.message" :loading="coLoadDetailLoading" @retry="loadCoLoadDetail"><template #details><ApiErrorMeta :details="coLoadDetailError" / > < / template > < / LoadErrorState >
< template v-else-if = "coLoadDetailSummary" >
< div class = "coload-detail-summary" > < el-tag size = "small" : type = "coLoadDetailSummary.status === 'ACTIVE' ? 'warning' : 'info'" > { { coLoadGroupSummary ( coLoadDetailSummary ) } } < / el-tag > < span > { { coLoadDetailSummary . memberCount } } 个成员 < / span > < / div >
@@ -2728,17 +2734,24 @@ onBeforeUnmount(() => {
/ >
< / AppDrawer >
< AppDialog v-model = "noteOpen" title="添加内部备注" confirm-text="保存备注" :confirm-loading="noteSaving" @confirm="saveNote" >
< AppDialog class = "order-density-dialog" v-model = "noteOpen" title="添加内部备注" confirm-text="保存备注" :confirm-loading="noteSaving" @confirm="saveNote" >
< el -input v-model = "noteContent" type="textarea" :rows="5" maxlength="2000" show-word-limit placeholder="请输入仅平台内部可见的备注" aria-label="内部备注内容" / >
< / AppDialog >
< AppDialog v-model = "holdDialogOpen" :title="holdAction === 'HOLD' ? '确认扣货' : '确认解除扣货'" :confirm-text="holdAction === 'HOLD' ? '确认扣货' : '确认解除'" :confirm-type="holdAction === 'HOLD' ? 'danger' : 'primary'" :confirm-loading="holdSaving" :confirm-disabled="!holdReason.trim() || holdReason.trim().length > 1000" width="min(600px, calc(100vw - 28px))" destroy-on-close @confirm="submitHoldAction" >
< AppDialog class = "order-density-dialog" v-model = "holdDialogOpen" :title="holdAction === 'HOLD' ? '确认扣货' : '确认解除扣货'" :confirm-text="holdAction === 'HOLD' ? '确认扣货' : '确认解除'" :confirm-type="holdAction === 'HOLD' ? 'danger' : 'primary'" :confirm-loading="holdSaving" :confirm-disabled="!holdReason.trim() || holdReason.trim().length > 1000" width="min(600px, calc(100vw - 28px))" destroy-on-close @confirm="submitHoldAction" >
< el -alert : title = "holdAction === 'HOLD' ? '扣货后服务端将阻止后续实物履约操作。' : '解除后是否可继续履约仍以服务端状态为准。'" : type = "holdAction === 'HOLD' ? 'warning' : 'info'" :closable = "false" show -icon / >
< el-form label -position = " top " class = "hold-command-form" > < el-form-item : label = "holdAction === 'HOLD' ? '扣货原因' : '解除原因'" required > < el-input v-model = "holdReason" type="textarea" :rows="4" maxlength="1000" show-word-limit :placeholder="holdAction === 'HOLD' ? '请输入扣货原因' : '请输入解除扣货原因'" aria-label="扣货操作原因" /></el-form-item><el-form-item label="关联文件(选填)"><el-upload :key="holdEvidenceUploadKey" :auto-upload="false" :limit="1" accept=".txt,.pdf,.jpg,.jpeg,.png,text/plain,application/pdf,image/jpeg,image/png" :disabled="holdSaving" :on-change="selectHoldEvidenceFile" :on-remove="removeHoldEvidenceFile"><el-button :disabled="holdSaving"><FileUp :size="15" />选择文件</el-button><template #tip><div class="el-upload__tip">仅支持 TXT、PDF、JPG、PNG,单文件不超过 10MB;服务端将校验文件真实内容。</div></template></el-upload></el-form-item><LoadErrorState v-if="holdEvidenceError" compact title="关联文件处理失败" :message="holdEvidenceError.message" :show-retry="false"><template #details><ApiErrorMeta :details="holdEvidenceError" / > < / template > < / LoadErrorState > < / el-form >
< / AppDialog >
< AppDialog v-model = "approvalOpen" title="审核订单" confirm-text="审核通过" confirm-type="success" :confirm-loading="approvalSaving" destroy-on-close @confirm="approveOrder" @cancel="closeApproval" >
< el -alert title = "确认订单资料无误后审核通过,订单将进入待测量阶段。" type = "info" :closable = "false" show -icon / >
< AppDialog class = "order-density-dialog" v-model = "approvalOpen" title="审核订单" confirm-text="审核通过" confirm-type="success" :confirm-loading="approvalSaving" destroy-on-close @confirm="approveOrder" @cancel="closeApproval" >
< dl v-if = "approvalOrder" class="approval-facts" >
< div > < dt > 入仓码 < / dt > < dd > { { approvalOrder . inboundCode || '—' } } < / dd > < / div >
< div > < dt > 客户 < / dt > < dd > { { customerName ( approvalOrder ) } } < / dd > < / div >
< div > < dt > 渠道 < / dt > < dd > { { approvalOrder . channelName || '—' } } < / dd > < / div >
< div > < dt > 目的仓 < / dt > < dd > { { approvalOrder . destinationWarehouseName || '—' } } < / dd > < / div >
< div > < dt > 总箱数 < / dt > < dd > { { approvalOrder . totalPackageCount ? ? '—' } } 箱 < / dd > < / div >
< / dl >
< p class = "approval-hint" > 确认订单资料无误后审核通过 , 订单将进入待测量阶段 。 < / p >
< / AppDialog >
< OrderDeclarationEditorDialog
@@ -2749,6 +2762,7 @@ onBeforeUnmount(() => {
/ >
< AppDialog
class = "order-density-dialog"
v-model = "measurementPreviewOpen"
:title = "measurementPreviewTitle"
width = "min(920px, calc(100vw - 28px))"
@@ -2764,6 +2778,7 @@ onBeforeUnmount(() => {
< / AppDialog >
< InboundMeasurementDialog
class = "order-density-dialog order-measurement-dialog"
v-if = "measurementOrder?.inboundId"
v-model = "measurementDialogOpen"
:customer-id = "String(measurementOrder.tenantId)"
@@ -2780,21 +2795,46 @@ onBeforeUnmount(() => {
< / template >
< style scoped >
. unified - orders - page { min - width : 0 ; gap : 16 px ; }
. detail - overview > div { display : flex ; min - width : 0 ; align - items : baseline ; gap : 6 px ; }
. detail - overview dt { flex : 0 0 auto ; color : var ( -- cc - muted ) ; font - size : 12 px ; }
. detail - overview dd { min - width : 0 ; margin : 0 ; color : var ( -- cc - text ) ; font - size : 13 px ; overflow - wrap : anywhere ; font - variant - numeric : tabular - nums ; }
. detail - overview small { color : var ( -- cc - muted ) ; font - size : 12 px ; }
. detail - tabs button : focus - visible { outline : 2 px solid var ( -- cc - primary ) ; outline - offset : - 2 px ; }
. panel - title > div : first - child { display : flex ; align - items : baseline ; flex - wrap : wrap ; gap : 4 px 12 px ; }
. compact - empty { margin : 0 ; padding : 14 px 10 px ; color : var ( -- cc - muted ) ; text - align : center ; font - size : 13 px ; }
. approval - facts { margin : 0 ; border - top : 1 px solid var ( -- cc - border ) ; }
. approval - facts > div { display : grid ; grid - template - columns : 88 px minmax ( 0 , 1 fr ) ; gap : 12 px ; padding : 8 px 0 ; border - bottom : 1 px solid var ( -- cc - border ) ; }
. approval - facts dt { color : var ( -- cc - muted ) ; font - size : 12 px ; }
. approval - facts dd { min - width : 0 ; margin : 0 ; overflow - wrap : anywhere ; font - size : 13 px ; }
. approval - hint { margin : 12 px 0 0 ; color : # 475467 ; font - size : 13 px ; }
. detail - panel : deep ( . el - table ) { font - size : 13 px ; -- el - table - header - bg - color : # f8fafc ; }
. detail - panel : deep ( . el - table _ _cell ) { height : 36 px ; padding : 4 px 0 ; }
. detail - panel : deep ( . el - table . cell ) { line - height : 22 px ; overflow - wrap : anywhere ; }
. detail - panel : deep ( . el - table _ _empty - block ) { min - height : 44 px ; }
. detail - panel : deep ( . el - table _ _empty - text ) { line - height : 44 px ; }
. history - table : deep ( . cell ) { white - space : normal ; }
. measurement - section - title : has ( [ aria - expanded = "false" ] ) { border - bottom : 1 px solid var ( -- cc - border ) ; }
. fulfillment - facts + . fulfillment - facts { border - top : 0 ; }
@ media ( min - width : 961 px ) {
. table - card : deep ( . data - table _ _toolbar . is - compact ) { min - height : 44 px ; padding : 6 px 12 px ; }
. table - card : deep ( . data - table _ _pagination ) { min - height : 44 px ; padding : 6 px 12 px ; }
}
. unified - orders - page { min - width : 0 ; gap : 12 px ; -- cc - list - table - font - size : 13 px ; -- cc - list - query - font - size : 13 px ; -- cc - list - action - font - size : 13 px ; }
. page - intro { display : flex ; align - items : flex - start ; justify - content : space - between ; gap : 16 px ; margin - bottom : 16 px ; }
. page - intro h1 { margin : 0 ; color : var ( -- cc - text ) ; font - size : 22 px ; line - height : 1.35 ; }
. page - intro p { margin : 5 px 0 0 ; color : var ( -- cc - muted ) ; font - size : 13 px ; line - height : 1.6 ; }
. page - intro : deep ( . el - button ) { flex : 0 0 auto ; }
. orders - query - panel { overflow : hidden ; border : 1 px solid var ( -- cc - border ) ; border - radius : 8 px ; background : # fff ; }
. orders - query - panel { overflow : hidden ; border : 1 px solid var ( -- cc - border ) ; border - radius : 4 px ; background : # fff ; }
. status - tabs { display : flex ; max - width : 100 % ; overflow - x : auto ; margin - bottom : 0 ; border - bottom : 1 px solid # e5e7eb ; background : # f9fafb ; scrollbar - width : thin ; }
. status - tab { position : relative ; flex : 0 0 auto ; min - height : 44 px ; padding : 0 18 px ; border : 0 ; background : transparent ; color : var ( -- cc - muted ) ; font : inherit ; font - size : 14 px ; cursor : pointer ; }
. status - tab { position : relative ; flex : 0 0 auto ; min - height : 38 px ; padding : 0 16 px ; border : 0 ; background : transparent ; color : var ( -- cc - muted ) ; font : inherit ; font - size : 13 px ; cursor : pointer ; }
. status - tab : : after { position : absolute ; right : 12 px ; bottom : 0 ; left : 12 px ; height : 3 px ; background : transparent ; content : '' ; }
. status - tab : hover { color : var ( -- cc - primary ) ; background : # f6f9fd ; }
. status - tab : focus - visible { outline : 2 px solid var ( -- cc - primary ) ; outline - offset : - 2 px ; }
. status - tab . is - active { color : var ( -- cc - primary ) ; font - weight : 600 ; }
. status - tab . is - active : : after { background : var ( -- cc - primary ) ; }
. orders - query - toolbar { border : 0 ; }
. table - card { overflow : hidden ; }
. orders - query - toolbar { border : 0 ; padding : 10 px 12 px ; }
. table - card { overflow : hidden ; border - radius : 4 px ; box - shadow : none ; }
. coload - error { margin : 8 px 12 px ; padding : 8 px 10 px ; border : 1 px solid var ( -- el - color - danger - light - 5 ) ; border - radius : 4 px ; background : var ( -- el - color - danger - light - 9 ) ; color : var ( -- el - color - danger ) ; font - size : 12 px ; }
. coload - error : deep ( . api - error - meta ) { margin - top : 5 px ; }
. order - code - cell { display : grid ; justify - items : start ; gap : 4 px ; }
@@ -2814,20 +2854,20 @@ onBeforeUnmount(() => {
. coload - detail - table td span { color : var ( -- cc - muted ) ; }
. coload - detail - table : deep ( . el - button ) { min - height : 24 px ; padding : 2 px 0 ; }
. coload - toolbar - action { display : flex ; min - width : 0 ; align - items : center ; gap : 8 px ; }
. subsequent - fulfillment { min - height : 72 px ; margin - top : 16 px ; padding - top : 14 px ; border - top : 1 px solid var ( -- cc - border ) ; }
. subsequent - fulfillment h3 { margin : 0 0 10 px ; font - size : 15 px ; }
. fulfillment - facts { display : grid ; grid - template - columns : repeat ( 4 , minmax ( 0 , 1 fr ) ) ; margin : 0 0 10 px ; border : 1 px solid var ( -- cc - border ) ; border - radius : 6 px ; overflow : hidden ; }
. subsequent - fulfillment { margin - top : 12 px ; padding - top : 10 px ; border - top : 1 px solid var ( -- cc - border ) ; }
. subsequent - fulfillment h3 { margin : 0 0 8 px ; font - size : 14 px ; }
. fulfillment - facts { display : grid ; grid - template - columns : repeat ( 4 , minmax ( 0 , 1 fr ) ) ; margin : 0 ; border - top : 1 px solid var ( -- cc - border ) ; border - left : 1 px solid var ( -- cc - border ) ; overflow : hidden ; }
. batch - approval - summary { display : flex ; align - items : center ; justify - content : space - between ; gap : 16 px ; margin : 12 px 0 8 px ; color : var ( -- cc - muted ) ; font - size : 13 px ; white - space : nowrap ; }
. batch - approval - summary strong { color : var ( -- cc - text ) ; }
. batch - approval - table : deep ( . cell ) { overflow : hidden ; text - overflow : ellipsis ; white - space : nowrap ; }
. fulfillment - facts > div { min - width : 0 ; padding : 9 px 10 px ; border - right : 1 px solid var ( -- cc - border ) ; background : # fff ; }
. fulfillment - facts > div { display : flex ; align - items : baseline ; gap : 10 px ; min - width : 0 ; padding : 8 px 10 px ; border - right : 1 px solid var ( -- cc - border ) ; border - bottom : 1 px solid var ( -- cc - border ) ; background : # fff ; }
. fulfillment - facts > div . wide { grid - column : span 2 ; }
. fulfillment - facts dt { color : var ( -- cc - muted ) ; font - size : 12 px ; }
. fulfillment - facts dd { min - width : 0 ; margin : 4 px 0 0 ; overflow - wrap : anywhere ; font - size : 13 px ; }
. fulfillment - facts dt { flex : 0 0 auto ; color : var ( -- cc - muted ) ; font - size : 12 px ; }
. fulfillment - facts dd { min - width : 0 ; margin : 0 ; overflow - wrap : anywhere ; font - size : 13 px ; }
. fulfillment - empty { margin : 0 ; padding : 12 px ; border : 1 px dashed var ( -- cc - border ) ; border - radius : 6 px ; color : var ( -- cc - muted ) ; text - align : center ; }
. table - card : deep ( . el - table ) { -- el - table - border - color : # e5e7eb ; -- el - table - header - bg - color : # f9fafb ; -- el - table - row - hover - bg - color : # f3f7fb ; -- el - table - tr - bg - color : # fff ; color : # 374151 ; font - size : 12 px ; }
. table - card : deep ( . el - table th . el - table _ _cell ) { height : 42 px ; padding : 0 ; background : # f9fafb ; color : # 374151 ; font - size : 12 px ; font - weight : 600 ; }
. table - card : deep ( . el - table td . el - table _ _cell ) { min - height : 42 px ; padding : 9 px 0 ; }
. table - card : deep ( . el - table ) { -- el - table - border - color : # e5e7eb ; -- el - table - header - bg - color : # f9fafb ; -- el - table - row - hover - bg - color : # f3f7fb ; -- el - table - tr - bg - color : # fff ; color : # 374151 ; font - size : 13 px ; }
. table - card : deep ( . el - table th . el - table _ _cell ) { height : 36 px ; padding : 4 px 0 ; background : # f9fafb ; color : # 374151 ; font - size : 13 px ; font - weight : 600 ; }
. table - card : deep ( . el - table td . el - table _ _cell ) { height : 36 px ; padding : 4 px 0 ; }
. table - card : deep ( . el - table -- striped . el - table _ _body tr . el - table _ _row -- striped td . el - table _ _cell ) { background : # fcfcfd ; }
. table - card : deep ( . el - table _ _body tr : hover > td . el - table _ _cell ) { background : # f3f7fb ; }
. row - actions { display : flex ; align - items : center ; gap : 4 px ; white - space : nowrap ; }
@@ -2844,34 +2884,27 @@ onBeforeUnmount(() => {
. primary - cell { display : grid ; min - width : 0 ; gap : 4 px ; }
. primary - cell strong { overflow - wrap : anywhere ; }
. primary - cell span { color : var ( -- cc - muted ) ; font - size : 12 px ; overflow - wrap : anywhere ; }
. order - detail - header { display : flex ; min - width : 0 ; min - height : 42 px ; align - items : center ; justify - content : space - between ; gap : 16 px ; margin - bottom : 12 px ; }
. order - detail - header { display : flex ; min - width : 0 ; min - height : 40 px ; align - items : center ; justify - content : space - between ; gap : 12 px ; margin - bottom : 0 ; padding : 8 px 12 px ; border : 1 px solid var ( -- cc - border ) ; border - bottom : 0 ; border - radius : 4 px 4 px 0 0 ; background : # fff ; }
. order - detail - heading { display : flex ; min - width : 0 ; align - items : center ; gap : 10 px ; }
. back - button { flex : 0 0 auto ; padding : 0 ; }
. order - mark { display : grid ; width : 36 px ; height : 36 px ; flex : 0 0 36 px ; place - items : center ; border - radius : 7 px ; background : # 1 d2939 ; color : # fff ; }
. order - title { min - width : 0 ; }
. order - title h1 { margin : 0 ; overflow : hidden ; color : # 172033 ; font - size : 18 px ; line - height : 1.2 ; text - overflow : ellipsis ; white - space : nowrap ; }
. order - title p { margin : 2 px 0 0 ; color : var ( -- cc - muted ) ; font - size : 11 px ; }
. order - title h1 { margin : 0 ; color : # 172033 ; font - size : 16 px ; line - height : 1.5 ; overflow - wrap : anywhere ; }
. detail - header - actions { display : flex ; flex : 0 0 auto ; gap : 8 px ; }
. detail - header - actions : deep ( . el - button + . el - button ) { margin - left : 0 ; }
. detail - load - error { min - height : 280 px ; }
. order - detail - content { min - height : 520 px ; }
. detail - overview { display : grid ; grid - template - columns : repeat ( 4 , minmax ( 0 , 1 fr ) ) ; overflow : hidden ; margin - bottom : 16 px ; border : 1 px solid var ( -- cc - border ) ; border - radius : 8 px ; background : # fff ; }
. detail - overview article { min - width : 0 ; padding : 18 px 20 px ; border - right : 1 px solid var ( -- cc - border ) ; }
. detail - overview article : last - child { border - right : 0 ; }
. detail - overview article > span , . detail - overview article > small { display : block ; overflow : hidden ; color : var ( -- cc - muted ) ; font - size : 11 px ; text - overflow : ellipsis ; white - space : nowrap ; }
. detail - overview strong { display : block ; margin : 7 px 0 5 px ; overflow : hidden ; color : # 172033 ; font - size : 20 px ; line - height : 1.2 ; text - overflow : ellipsis ; white - space : nowrap ; }
. detail - overview strong small { margin - left : 5 px ; color : # 475467 ; font - size : 11 px ; }
. detail - tabs { display : flex ; overflow - x : auto ; overflow - y : hidden ; border : 1 px solid var ( -- cc - border ) ; border - bottom : 0 ; border - radius : 8 px 8 px 0 0 ; background : # fff ; scrollbar - width : thin ; }
. detail - tabs button { position : relative ; display : inline - flex ; min - width : max - content ; min - height : 56 px ; flex : 0 0 auto ; align - items : center ; justify - content : center ; gap : 7 px ; padding : 0 22 px ; border : 0 ; border - right : 1 px solid # edf0f4 ; background : transparent ; color : # 667085 ; font - weight : 650 ; cursor : pointer ; }
. order - detail - content { min - width : 0 ; }
. detail - overview { display : flex ; flex - wrap : wrap ; gap : 6 px 24 px ; margin : 0 ; padding : 8 px 12 px ; border : 1 px solid var ( -- cc - border ) ; border - top : 0 ; background : # fff ; }
. detail - tabs { display : flex ; overflow - x : auto ; overflow - y : hidden ; border : 1 px solid var ( -- cc - border ) ; border - block : 0 ; background : # fff ; scrollbar - width : thin ; }
. detail - tabs button { position : relative ; display : inline - flex ; min - width : max - content ; min - height : 38 px ; flex : 0 0 auto ; align - items : center ; justify - content : center ; gap : 6 px ; padding : 0 16 px ; border : 0 ; background : transparent ; color : # 475467 ; font - size : 13 px ; font - weight : 500 ; cursor : pointer ; }
. detail - tabs button : last - child { border - right : 0 ; }
. detail - tabs button : : after { position : absolute ; right : 14 px ; bottom : 0 ; left : 14 px ; height : 3 px ; background : transparent ; content : '' ; }
. detail - tabs button : : after { position : absolute ; right : 12 px ; bottom : 0 ; left : 12 px ; height : 2 px ; background : transparent ; content : '' ; }
. detail - tabs button : hover { background : # fafbff ; color : # 344054 ; }
. detail - tabs button . active { background : # f7f8ff ; color : var ( -- cc - primary ) ; }
. detail - tabs button . active { background : # f7f8ff ; color : var ( -- cc - primary ) ; font - weight : 600 ; }
. detail - tabs button . active : : after { background : var ( -- cc - primary ) ; }
. detail - panel { min - width : 0 ; min - height : 390 px ; padding : 16 px ; border : 1 px solid var ( -- cc - border ) ; border - radius : 0 0 8 px 8 px ; background : # fff ; }
. panel - title { display : flex ; align - items : flex - start ; justify - content : space - between ; gap : 16 px ; margin - bottom : 10 px ; padding - bottom : 8 px ; border - bottom : 1 px solid var ( -- cc - border ) ; }
. panel - title h2 { margin : 0 ; color : # 344054 ; font - size : 16 px ; }
. panel - title p { margin : 5 px 0 0 ; color : var ( -- cc - muted ) ; font - size : 11 px ; }
. detail - panel { min - width : 0 ; padding : 12 px ; border : 1 px solid var ( -- cc - border ) ; border - radius : 0 0 4 px 4 px ; background : # fff ; }
. panel - title { display : flex ; align - items : center ; justify - content : space - between ; gap : 12 px ; min - height : 28 px ; margin - bottom : 8 px ; }
. panel - title h2 { margin : 0 ; color : # 344054 ; font - size : 14 px ; font - weight : 600 ; }
. panel - title p { margin : 0 ; color : var ( -- cc - muted ) ; font - size : 12 px ; line - height : 1.5 ; }
. panel - title > svg { color : var ( -- cc - primary ) ; }
. measurement - title - actions { display : flex ; flex - wrap : wrap ; justify - content : flex - end ; gap : 8 px ; }
. measurement - title - actions : deep ( . el - button ) { margin - left : 0 ; }
@@ -2889,86 +2922,82 @@ onBeforeUnmount(() => {
. fee - confirm - price - summary dt { color : var ( -- cc - muted ) ; font - size : 11 px ; }
. fee - confirm - price - summary dd { margin : 4 px 0 0 ; color : var ( -- cc - text ) ; font - size : 13 px ; font - weight : 650 ; }
@ media ( max - width : 680 px ) { . fee - confirm - form { grid - template - columns : 1 fr ; } . fee - confirm - unit { right : 12 px ; } }
. fee - section - title { margin : 14 px 0 8 px ; color : # 344054 ; font - size : 13 px ; line - height : 1.4 ; }
. fee - overview { display : grid ; grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; margin : 8 px 0 0 ; border : 1 px solid var ( -- cc - border ) ; }
. fee - overview > div { display : grid ; grid - template - columns : auto 1 fr ; align - items : baseline ; gap : 4 px 12 px ; padding : 10 px 12 px ; }
. fee - section - title { margin : 12 px 0 8 px ; color : # 344054 ; font - size : 14 px ; line - height : 1.4 ; }
. fee - overview { display : grid ; grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; margin : 0 ; border : 1 px solid var ( -- cc - border ) ; }
. fee - overview > div { display : flex ; flex - wrap : wrap ; align - items : baseline ; gap : 4 px 12 px ; padding : 8 px 10 px ; }
. fee - overview > div + div { border - left : 1 px solid var ( -- cc - border ) ; }
. fee - overview dt , . fee - overview small { color : var ( -- cc - muted ) ; font - size : 11 px ; }
. fee - overview dd { margin : 0 ; font - size : 18 px ; font - weight : 700 ; text - align : right ; }
. fee - overview small { grid - column : 1 / - 1 ; }
. fee - section - title -- secondary { margin - top : 20 px ; padding - top : 14 px ; border - top : 1 px solid var ( -- cc - border ) ; }
. order - info - grid { display : grid ; grid - template - columns : repeat ( 3 , minmax ( 0 , 1 fr ) ) ; gap : 0 ; margin : 0 ; overflow : hidden ; border : 1 px solid # edf0f4 ; background : # fff ; }
. order - info - grid > div , . measurement - grid > div { display : flex ; min - width : 0 ; min - height : 38 px ; align - items : baseline ; gap : 8 px ; padding : 8 px 12 px ; border - right : 1 px solid # edf0f4 ; border - bottom : 1 px solid # edf0f4 ; background : # fff ; }
. fee - overview dt , . fee - overview small { color : var ( -- cc - muted ) ; font - size : 12 px ; }
. fee - overview dd { margin : 0 ; font - size : 16 px ; font - weight : 600 ; font - variant - numeric : tabular - nums ; }
. fee - overview small { margin - left : auto ; }
. fee - section - title -- secondary { margin - top : 12 px ; padding - top : 10 px ; border - top : 1 px solid var ( -- cc - border ) ; }
. order - info - grid { display : grid ; grid - template - columns : repeat ( 4 , minmax ( 0 , 1 fr ) ) ; gap : 0 ; margin : 0 ; overflow : hidden ; border - top : 1 px solid var ( -- cc - border ) ; border - left : 1 px solid var ( -- cc - border ) ; background : # fff ; }
. order - info - grid > div , . measurement - grid > div { display : grid ; grid - template - columns : 112 px minmax ( 0 , 1 fr ) ; min - width : 0 ; min - height : 36 px ; align - items : stretch ; gap : 0 ; border - right : 1 px solid var ( -- cc - border ) ; border - bottom : 1 px solid var ( -- cc - border ) ; background : # fff ; }
. order - info - grid > div . wide { grid - column : span 2 ; }
. order - info - grid dt , . measurement - grid dt { flex : 0 0 auto ; margin : 0 ; color : var ( -- cc - muted ) ; font - size : 11 px ; white - space : nowrap ; }
. order - info - grid dd , . measurement - grid dd { min - width : 0 ; margin : 0 ; color : # 25324 a ; font - size : 12 px ; font - weight : 650 ; line - height : 1.35 ; overflow - wrap : anywhere ; }
. order - info - grid dt , . measurement - grid dt { margin : 0 ; padding : 8 px ; color : # 667085 ; background : # f8fafc ; font - size : 12 px ; line - height : 20 px ; }
. order - info - grid dd , . measurement - grid dd { min - width : 0 ; margin : 0 ; padding : 8 px ; color : # 25324 a ; font - size : 13 px ; font - weight : 400 ; line - height : 20 px ; overflow - wrap : anywhere ; }
. detail - table - wrap { overflow - x : auto ; }
. detail - table - wrap : deep ( . el - table ) { min - width : 720 px ; -- el - table - header - bg - color : # f8fafc ; }
. cargo - image { width : 72 px ; height : 56 px ; border : 1 px solid var ( -- cc - border ) ; border - radius : 6 px ; background : # f8fafc ; }
. cargo - image { width : 40 px ; height : 32 px ; border : 1 px solid var ( -- cc - border ) ; border - radius : 2 px ; background : # f8fafc ; cursor : zoom - in ; }
. measurement - grid { display : grid ; grid - template - columns : repeat ( 4 , minmax ( 0 , 1 fr ) ) ; gap : 1 px ; margin : 0 ; border : 1 px solid var ( -- cc - border ) ; background : var ( -- cc - border ) ; }
. measurement - section { margin - top : 18 px ; }
. measurement - section - title { display : flex ; width : 100 % ; min - height : 48 px ; align - items : center ; gap : 12 px ; padding : 7 px 12 px ; border : 1 px solid var ( -- cc - border ) ; border - radius : 7 px 7 px 0 0 ; background : # f8fafc ; color : var ( -- cc - text ) ; }
. measurement - section { margin - top : 12 px ; }
. measurement - section - title { display : flex ; width : 100 % ; min - height : 36 px ; align - items : center ; gap : 12 px ; padding : 4 px 10 px ; border : 1 px solid var ( -- cc - border ) ; border - bottom : 0 ; background : # f8fafc ; color : var ( -- cc - text ) ; }
. measurement - section - title : hover { background : # f2f6fb ; }
. measurement - section - title h3 { flex : 0 0 auto ; margin : 0 ; color : var ( -- cc - text ) ; font - size : 14 px ; }
. measurement - section - summary { display : flex ; min - width : 0 ; flex : 1 ; align - items : center ; justify - content : flex - end ; gap : 18 px ; color : var ( -- cc - muted ) ; font - size : 12 px ; white - space : nowrap ; }
. measurement - section - toggle { display : flex ; min - width : 0 ; flex : 1 ; align - items : center ; gap : 16 px ; padding : 2 px ; border : 0 ; background : transparent ; color : inherit ; font : inherit ; text - align : left ; cursor : pointer ; }
. measurement - section - title h3 { flex : 0 0 auto ; margin : 0 ; color : var ( -- cc - text ) ; font - size : 13 px ; font - weight : 600 ; }
. measurement - section - summary { display : flex ; min - width : 0 ; flex : 1 ; flex - wrap : wrap ; align - items : center ; justify - content : flex - end ; gap : 4 px 16 px ; color : var ( -- cc - muted ) ; font - size : 12 px ; }
. measurement - section - toggle { display : flex ; min - width : 0 ; min - height : 28 px ; flex : 1 ; align - items : center ; gap : 16 px ; padding : 0 ; border : 0 ; background : transparent ; color : inherit ; font : inherit ; text - align : left ; cursor : pointer ; }
. measurement - section - toggle : focus - visible { outline : 2 px solid var ( -- cc - primary ) ; outline - offset : 2 px ; }
. measurement - section - toggle > svg { flex : 0 0 auto ; color : var ( -- cc - muted ) ; }
. measurement - section - toggle > svg { flex : 0 0 auto ; margin - left : auto ; color : var ( -- cc - muted ) ; }
. measurement - section - mode { flex : 0 0 190 px ; }
. measurement - section - title > . measurement - section - mode { display : none ; }
. measurement - rule - selector { display : flex ; align - items : center ; gap : 14 px ; margin : 8 px 0 12 px ; padding : 12 px 16 px ; border : 1 px solid var ( -- cc - border ) ; border - radius : 7 px ; background : # f8fafc ; }
. measurement - rule - selector { display : flex ; flex - wrap : wrap ; align - items : center ; gap : 10 px ; margin : 0 ; padding : 8 px 10 px ; border : 1 px solid var ( -- cc - border ) ; border - top : 0 ; background : # fff ; }
. measurement - rule - selector _ _label { color : var ( -- cc - text ) ; font - size : 12 px ; font - weight : 650 ; white - space : nowrap ; }
. measurement - rule - selector _ _control { width : 270 px ; }
. measurement - rule - selector _ _hint { color : var ( -- cc - muted ) ; font - size : 11 px ; }
. measurement - rule - selector _ _hint { color : var ( -- cc - muted ) ; font - size : 12 px ; }
. measurement - outer - dimension - input { width : 128 px ; max - width : 100 % ; }
. measurement - total { display : flex ; min - height : 42 px ; align - items : center ; justify - content : flex - end ; gap : 24 px ; padding : 9 px 14 px ; border : 1 px solid var ( -- cc - border ) ; background : # f8fafc ; color : var ( -- cc - muted ) ; font - size : 12 px ; }
. measurement - total { border - top : 0 ; border - radius : 0 0 7 px 7 px ; }
. measurement - total { display : flex ; min - height : 32 px ; flex - wrap : wrap ; align - items : center ; justify - content : flex - end ; gap : 4 px 20 px ; padding : 6 px 10 px ; border : 1 px solid var ( -- cc - border ) ; border - top : 0 ; background : # f8fafc ; color : # 475467 ; font - size : 12 px ; font - variant - numeric : tabular - nums ; }
. measurement - total strong { margin - right : auto ; color : var ( -- cc - text ) ; font - size : 13 px ; }
. weight - evidence { margin - top : 20 px ; padding : 16 px ; border : 1 px solid var ( -- cc - border ) ; border - radius : 8 px ; background : # fbfcfe ; }
. weight - evidence _ _heading { display : flex ; align - items : flex - start ; justify - content : space - between ; gap : 20 px ; margin - bottom : 14 px ; }
. weight - evidence { margin - top : 12 px ; padding : 10 px 0 0 ; border - top : 1 px solid var ( -- cc - border ) ; background : # fff ; }
. weight - evidence _ _heading { display : flex ; align - items : center ; justify - content : space - between ; gap : 16 px ; margin - bottom : 8 px ; }
. weight - evidence _ _heading h4 { margin : 0 ; color : var ( -- cc - text ) ; font - size : 14 px ; }
. weight - evidence _ _heading p { margin : 5 px 0 0 ; color : var ( -- cc - muted ) ; font - size : 12 px ; }
. weight - evidence _ _heading dl { margin : 0 ; text - align : right ; }
. weight - evidence _ _heading dt { color : var ( -- cc - muted ) ; font - size : 11 px ; }
. weight - evidence _ _heading dd { margin : 4 px 0 0 ; color : var ( -- cc - text ) ; font - size : 16 px ; font - weight : 700 ; }
. weight - evidence - grid { display : grid ; grid - template - columns : repeat ( auto - fill , minmax ( 220 px , 1 fr ) ) ; gap : 14 px ; }
. weight - evidence - card { min - width : 0 ; overflow : hidden ; border : 1 px solid var ( -- cc - border ) ; border - radius : 8 px ; background : # fff ; }
. weight - evidence - card > dl { display : grid ; gap : 7 px ; margin : 0 ; padding : 12 px ; }
. weight - evidence _ _heading dd { margin : 0 ; color : var ( -- cc - text ) ; font - size : 13 px ; font - weight : 600 ; }
. weight - evidence - grid { display : grid ; grid - template - columns : repeat ( auto - fill , minmax ( 280 px , 1 fr ) ) ; gap : 8 px ; }
. weight - evidence - card { display : grid ; grid - template - columns : 96 px minmax ( 0 , 1 fr ) ; align - items : center ; min - width : 0 ; padding : 8 px ; border : 1 px solid var ( -- cc - border ) ; background : # fff ; }
. weight - evidence - card > dl { display : grid ; gap : 4 px ; margin : 0 ; padding : 0 0 0 8 px ; }
. weight - evidence - card > dl > div { display : flex ; min - width : 0 ; justify - content : space - between ; gap : 12 px ; }
. weight - evidence - card dt { color : var ( -- cc - muted ) ; font - size : 11 px ; }
. weight - evidence - card dd { min - width : 0 ; margin : 0 ; color : var ( -- cc - text ) ; font - size : 12 px ; font - weight : 650 ; text - align : right ; overflow - wrap : anywhere ; }
. measurement - original - preview { display : block ; width : 100 % ; max - height : min ( 72 vh , 760 px ) ; object - fit : contain ; border - radius : 8 px ; background : # f2f4f7 ; }
. hold - section { padding - bottom : 18 px ; border - bottom : 1 px solid var ( -- cc - border ) ; }
. other - notes - section { padding - top : 18 px ; }
. hold - summary { display : flex ; align - items : flex - start ; justify - content : space - between ; gap : 20 px ; padding : 12 px 14 px ; border : 1 px solid var ( -- cc - border ) ; border - radius : 6 px ; background : # f8fafc ; }
. hold - summary dl { display : grid ; min - width : 0 ; flex : 1 ; grid - template - columns : 150 px minmax ( 280 px , 1 fr ) ; gap : 18 px ; margin : 0 ; }
. hold - summary dl > div { min - width : 0 ; }
. hold - summary dt { margin - bottom : 5 px ; color : var ( -- cc - muted ) ; font - size : 12 px ; }
. hold - section { padding - bottom : 12 px ; border - bottom : 1 px solid var ( -- cc - border ) ; }
. other - notes - section { padding - top : 10 px ; }
. hold - summary { display : flex ; align - items : center ; justify - content : space - between ; gap : 16 px ; padding : 8 px 10 px ; border : 1 px solid var ( -- cc - border ) ; background : # fff ; }
. hold - summary dl { display : grid ; min - width : 0 ; flex : 1 ; grid - template - columns : 210 px minmax ( 280 px , 1 fr ) ; gap : 12 px ; margin : 0 ; }
. hold - summary dl > div { display : flex ; align - items : baseline ; gap : 10 px ; min - width : 0 ; }
. hold - summary dt { flex : 0 0 auto ; margin : 0 ; color : var ( -- cc - muted ) ; font - size : 12 px ; }
. hold - summary dd { margin : 0 ; color : var ( -- cc - text ) ; font - size : 13 px ; overflow - wrap : anywhere ; }
. hold - actions { display : flex ; flex : 0 0 auto ; gap : 8 px ; }
. hold - actions : deep ( . el - button ) { margin - left : 0 ; }
. hold - block - reason { margin : 12 px 0 0 ; padding : 9 px 12 px ; border : 1 px solid var ( -- el - color - warning - light - 5 ) ; border - radius : 4 px ; background : var ( -- el - color - warning - light - 9 ) ; color : var ( -- el - color - warning - dark - 2 ) ; font - size : 12 px ; }
. hold - history - title { margin : 16 px 0 8 px ; color : # 344054 ; font - size : 14 px ; }
. hold - history - table { min - height : 90 px ; overflow - x : auto ; }
. hold - history - table { min - width : 0 ; overflow - x : auto ; }
. hold - command - form { margin - top : 16 px ; }
. hold - evidence - hint { margin : - 4 px 0 0 ; color : var ( -- cc - muted ) ; font - size : 12 px ; }
. history - list , . notes - list { display : grid ; gap : 0 ; margin : 0 ; padding : 0 ; list - style : none ; }
. history - list li { position : relative ; display : grid ; grid - template - columns : 16 px minmax ( 0 , 1 fr ) ; gap : 12 px ; padding - bottom : 20 px ; }
. history - list li : not ( : last - child ) : : after { position : absolute ; top : 15 px ; bottom : 0 ; left : 7 px ; width : 1 px ; background : var ( -- cc - border ) ; content : '' ; }
. history - marker { z - index : 1 ; width : 14 px ; height : 14 px ; margin - top : 3 px ; border : 3 px solid var ( -- cc - primary ) ; border - radius : 50 % ; background : # fff ; }
. history - line { display : flex ; align - items : center ; justify - content : space - between ; gap : 12 px ; }
. history - list strong { color : # 344054 ; font - size : 13 px ; }
. history - list p , . notes - list p { margin : 4 px 0 0 ; color : var ( -- cc - muted ) ; font - size : 12 px ; line - height : 1.55 ; overflow - wrap : anywhere ; }
. history - list . history - remark { margin - top : 8 px ; padding : 10 px 12 px ; background : # f8fafc ; color : # 475467 ; }
. notes - list { display : grid ; gap : 0 ; margin : 0 ; padding : 0 ; list - style : none ; }
. notes - list p { margin : 4 px 0 0 ; color : var ( -- cc - muted ) ; font - size : 12 px ; line - height : 1.55 ; overflow - wrap : anywhere ; }
. notes - list li { padding : 14 px 0 ; border - bottom : 1 px solid # edf0f4 ; }
. notes - list li : first - child { padding - top : 0 ; }
. notes - list li : last - child { padding - bottom : 0 ; border - bottom : 0 ; }
. notes - list li > p { margin : 0 ; color : var ( -- cc - text ) ; font - size : 13 px ; }
. notes - list span { display : block ; margin - top : 5 px ; color : var ( -- cc - muted ) ; font - size : 12 px ; }
@ media ( max - width : 960 px ) { . detail - overview { grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; } . detail - overview article : nth - child ( 2 ) { border - right : 0 ; } . detail - overview article : nth - child ( - n + 2 ) { border - bottom : 1 px solid var ( -- cc - border ) ; } . order - info - grid { grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; } . measurement - grid { grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; } }
@ media ( max - width : 720 px ) { . page - intro { align - items : stretch ; flex - direction : column ; } . page - intro : deep ( . el - button ) { width : 100 % ; min - height : 44 px ; } . status - tab { min - height : 46 px ; padding : 0 14 px ; } . table - actions : deep ( . el - button ) { width : 100 % ; min - height : 40 px ; } . row - actions { flex - wrap : wrap ; } . order - detail - header { align - items : stretch ; flex - direction : column ; } . order - detail - heading { display : grid ; grid - template - columns : auto 36 px minmax ( 0 , 1 fr ) auto ; } . detail - header - actions { display : grid ; grid - template - columns : 1 fr ; } . detail - header - actions : deep ( . el - button ) { min - height : 40 px ; } . detail - overview , . order - info - grid , . measurement - grid { grid - template - columns : 1 fr ; } . detail - overview article { border - right : 0 ; border - bottom : 1 px solid var ( -- cc - border ) ; } . detail - overview article : last - child { border - bottom : 0 ; } . order - info - grid > div . wide { grid - column : auto ; } . detail - tabs button { padding : 0 18 px ; } . detail - panel { padding : 16 px ; } . measurement - section - title { align - items : flex - start ; flex - wrap : wrap ; padding : 12 px ; } . measurement - section - summary { width : 100 % ; flex - basis : calc ( 100 % - 34 px ) ; flex - wrap : wrap ; justify - content : flex - start ; gap : 6 px 16 px ; white - space : normal ; } . measurement - section - title > svg { margin - left : auto ; } . measurement - total { flex - wrap : wrap ; justify - content : flex - start ; gap : 6 px 16 px ; } . measurement - total strong { width : 100 % ; } }
@ media ( max - width : 960 px ) { . detail - overview { grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; } . order - info - grid { grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; } . measurement - grid { grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; } }
@ media ( max - width : 720 px ) { . page - intro { align - items : stretch ; flex - direction : column ; } . page - intro : deep ( . el - button ) { width : 100 % ; min - height : 44 px ; } . status - tab { min - height : 46 px ; padding : 0 14 px ; } . table - actions : deep ( . el - button ) { width : 100 % ; min - height : 40 px ; } . row - actions { flex - wrap : wrap ; } . order - detail - header { align - items : stretch ; flex - direction : column ; } . order - detail - heading { flex - wrap : wrap ; } . detail - header - actions { display : grid ; grid - template - columns : 1 fr ; } . detail - header - actions : deep ( . el - button ) { min - height : 40 px ; } . order - info - grid , . measurement - grid { grid - template - columns : 1 fr ; } . order - info - grid > div . wide { grid - column : auto ; } . detail - tabs button { padding : 0 18 px ; } . detail - panel { padding : 16 px ; } . measurement - section - title { align - items : flex - start ; flex - wrap : wrap ; padding : 12 px ; } . measurement - section - summary { width : 100 % ; flex - basis : calc ( 100 % - 34 px ) ; flex - wrap : wrap ; justify - content : flex - start ; gap : 6 px 16 px ; white - space : normal ; } . measurement - section - title > svg { margin - left : auto ; } . measurement - total { flex - wrap : wrap ; justify - content : flex - start ; gap : 6 px 16 px ; } . measurement - total strong { width : 100 % ; } }
@ media ( max - width : 720 px ) { . weight - evidence _ _heading { flex - direction : column ; } . weight - evidence _ _heading dl { text - align : left ; } }
@ media ( max - width : 720 px ) { . fee - overview { grid - template - columns : 1 fr ; } . fee - overview > div + div { border - top : 1 px solid var ( -- cc - border ) ; border - left : 0 ; } }
@ media ( max - width : 720 px ) { . measurement - section - title { align - items : stretch ; flex - direction : column ; } . measurement - section - toggle { align - items : flex - start ; flex - wrap : wrap ; } . measurement - section - toggle > svg { margin - left : auto ; } . measurement - section - mode { width : 100 % ; flex - basis : auto ; } }
@ media ( max - width : 420 px ) { . order - detail - heading { grid - template - columns : auto minmax ( 0 , 1 fr ) auto ; } . order - mark { display : none ; } . weight - evidence { padding : 10 px ; } . weight - evidence - grid { grid - template - columns : 1 fr ; } }
@ media ( max - width : 420 px ) { . weight - evidence { padding : 10 px ; } . weight - evidence - grid { grid - template - columns : 1 fr ; } }
< / style >
< style src = "../styles/orderDensity.css" > < / style >