@@ -16,29 +16,27 @@
< view v-if = "receiptBatch && !result" class="work-card"><text class="card-title">待完成按箱签收</text><text class="business-code">{{ receiptBatch.returnNo }}</text><text class="hint">已确认 {{ receiptBatch.entries.filter(entry => entry.result).length }} / {{ receiptBatch.entries.length }} 箱。请继续本批签收,已确认的箱不会重新入库;本批内容暂不可修改。</text><button class="primary" :disabled="busy" @tap="confirmReceipt" > {{ busy ? ' 提交中 … ' : ' 继续本批签收 ' }} < / button > < / view >
< template v-if = "current && !result && !receiptBatch" >
< view class = "work-card" > < view class = "row-head" > < view > < text class = "business-code "> { { current . returnNo } } < / text > < text class = "meta-line" > { { startedBy === 'SKU' ? '通过 SKU 候选进入' : '通过退货单号进入' } } < / text > < / view > < text class = "status-pill" > { { statusLabel ( current . status ) } } < / text > < / view > < button class = "link-button" @tap ="clearCurrent" > 更换退货单 < / button > < / view >
< view class = "work-card receipt-order-card " > < view class = "row-head" > < text class = "card-title" > 退货单 < / text > < button class = "link-button" @tap ="clearCurrent "> 更换退货单 < / button > < / view > < view class = "receipt-order-line" > < text class = "business-code" > { { current . returnNo } } < / text > < text class = "status-pill" > { { statusLabel ( current . status ) } } < / text > < / view > < / view >
< view class = "work-card" >
< text class = "card-title" > 本次实物单元 < / text >
< text class = "hint" > 按现场收到的实物选择维度 , 托盘不是必填项 。 < / text >
< view class = "unit-tabs" > < button v-for = "item in unitOptions" :key="item.value" :class="['unit-tab', {active: unitType === item.value}]" @tap="selectUnitType(item.value)" > {{ item.label }} < / button > < / view >
< view v-if = "unitType === 'PARCEL'"><text class="field-label">包裹码/快递单号</text><ScanTargetInput name="unit" v-model="unitCode" label="包裹码/快递单号" placeholder="扫描快递面单" :active="activeTarget === 'unit'" @activate="activeTarget = 'unit'" @submit="acceptUnit" / > < / view >
< template v-else >
< text v-if = "unitType === 'PALLET'" class="scan-hint">托盘入库:扫描已有托盘或生成新托盘,沿用原托盘测量流程。</text><text v-else class="scan-hint" > 箱子可直接散装入库 , 也可扫描托盘直接打托 。 < / text >
< view > < text class = "field-label" > 托盘码 ( { { unitType === 'BOX' ? '选填' : '必填' } } ) < / text > < ScanTargetInput name = "pallet" v-model = "palletCode" label="托盘码" placeholder="扫描已有托盘或新托盘标签" :active="activeTarget === 'pallet'" @activate="activeTarget = 'pallet'" @submit="acceptPallet" /><text v-if="palletCheck" class="scan-hint">{{ palletCheck.empty ? '空托盘,可绑定当前退货单和 SKU' : `当前单托盘,已有 ${palletCheck.skuCodes.join('、')},共 ${palletCheck.quantity} 件` }} </text><button class="secondary pallet-generate" :disabled="busy" @tap="generatePallet" > 生成新托盘 ( 仅作载体 ) < / button > < / view >
< view v-if = "unitType === 'PALLET'" class="dimension-grid"><label><text>长 cm</text><input class="number-input" type="digit" v-model="palletLength" placeholder="长" /></label><label><text>宽 cm</text><input class="number-input" type="digit" v-model="palletWidth" placeholder="宽" /></label><label><text>高 cm</text><input class="number-input" type="digit" v-model="palletHeight" placeholder="高" /></label><label><text>重量 kg</text><input class="number-input" type="digit" v-model="palletWeight" placeholder="重量" /></label><view class="volume-box" > < text > 体积 < / text > < strong > { { palletVolume } } < / strong > < text > cm³ < / text > < / view > < / view >
< view > < text class = "field-label" > 托盘码 ( { { unitType === 'BOX' ? '选填' : '必填' } } ) < / text > < ScanTargetInput name = "pallet" v-model = "palletCode" label="托盘码" placeholder="扫描已有托盘或新托盘标签" :active="activeTarget === 'pallet'" @activate="activeTarget = 'pallet'" @submit="acceptPallet" /><text v-if="palletCheck" class="scan-hint">{{ palletCheck.empty ? '空托盘,可绑定当前退货单和 SKU' : `当前单托盘,已有 ${palletCheck.skuCodes.join('、')},共 ${palletCheck.quantity} 件` }}</text><button class="secondary pallet-generate" :disabled="busy" @tap="generatePallet" > 生成新托盘 < / button > < / view >
< view v-if = "unitType === 'PALLET'" class="dimension-grid"><label><text>托盘长(cm) </text><input class="number-input" type="digit" v-model="palletLength" /></label><label><view class="dimension-label"><text>托盘宽(cm) </text><text class="volume-text">体积 {{ palletVolume }} cm³</text></view><input class="number-input" type="digit" v-model="palletWidth" /></label><label><text>托盘高(cm) </text><input class="number-input" type="digit" v-model="palletHeight" /></label><label><text>托盘重量(kg) </text><input class="number-input" type="digit" v-model="palletWeight" / > < / label > < / view >
< view > < text class = "field-label" > 快递单号 ( 选填 ) < / text > < ScanTargetInput name = "tracking" v-model = "trackingNo" label="快递单号" placeholder="扫描快递面单" :active="activeTarget === 'tracking'" @activate="activeTarget = 'tracking'" @submit="acceptTracking" / > < / view >
< / template >
< / view >
< view class = "work-card" > < view class = "row-head" > < text class = "card-title" > { { unitType === 'PARCEL' ? '本次实收数量' : ( unitType === 'PALLET' ? '本托实收数量' : '逐箱实收数量' ) } } < / text > < button v-if = "unitType !== 'BOX'" class="link-button" @tap="fillRemaining">全部填入</button></view><view v-if="unitType === 'PALLET'" class="quantity-row"><text>本托箱数合计</text><strong class="auto-count">{{ palletBoxCount }}</strong></view><template v-if="unitType === 'BOX'"><view class="quantity-row"><text>本次箱数</text><input class="number-input" type="number" :value="boxRows.length" placeholder="箱数" @input="resizeBoxRows($event.detail.value)" /></view><view v-for="(box,index) in boxRows" :key="index" class="item-card"><text class="business-code">第 {{ index + 1 }} 箱</text><view v-for="item in selectedItems" :key="item.skuCode" class="quantity-row"><text>{{ item.skuCode }} · 数量</text><input class="number-input" type="number" :value="box.items[item.skuCode] || ''" placeholder="0" @input="setBoxQuantity(index, item.skuCode, $event.detail.value)" /></view></view></template><view v-else class="item-list"><view v-for="item in selectedItems" :key="item.skuCode" class="item-card"><view class="row-head"><view><text class="business-code">{{ item.skuCode }}</text><text class="meta-line">{{ item.productNameZh || '商品名称未填写' }}</text></view><text class="remaining-copy">剩余 {{ remaining(item) }}</text></view><view class="quantity-row"><text>数量</text><input class="number-input" type="number" :value="quantity(item.skuCode)" placeholder="0" @input="setQuantity(item, $event.detail.value)" /></view><view v-if="unitType === 'PALLET'" class="quantity-row"><text>此 SKU 箱数</text><input class="number-input" type="number" :value="boxCount(item.skuCode)" placeholder="0" @input="setBoxCount(item, $event.detail.value)" / > < / view > < / view > < / view > < / view >
< view class = "work-card" > < view class = "row-head" > < text class = "card-title" > { { unitType === 'PARCEL' ? '本次实收数量' : ( unitType === 'PALLET' ? '本托实收数量' : '逐箱实收数量' ) } } < / text > < button v-if = "unitType !== 'BOX'" class="link-button" @tap="fillRemaining">全部填入</button></view><view v-if="unitType === 'PALLET'" class="quantity-row"><text>本托箱数合计</text><strong class="auto-count">{{ palletBoxCount }}</strong></view><template v-if="unitType === 'BOX'"><view class="quantity-row"><text>本次箱数</text><input class="number-input" type="number" :value="boxRows.length" placeholder="箱数" @input="resizeBoxRows($event.detail.value)" /></view><view v-for="(box,index) in boxRows" :key="index" class="item-card"><text class="business-code">第 {{ index + 1 }} 箱</text><view v-for="item in selectedItems" :key="item.skuCode" class="quantity-row"><text>{{ item.skuCode }} · 数量</text><input class="number-input" type="number" :value="box.items[item.skuCode] || ''" placeholder="0" @input="setBoxQuantity(index, item.skuCode, $event.detail.value)" /></view></view></template><view v-else class="item-list receipt-sku-list "><view v-for="item in selectedItems" :key="item.skuCode" class="item-card"><view class="row-head"><view><text class="business-code">{{ item.skuCode }}</text><text class="meta-line">{{ item.productNameZh || '商品名称未填写' }}</text></view><text class="remaining-copy">剩余 {{ remaining(item) }}</text></view><view class="sku-quantity-fields"><view class="quantity-row"><text>数量</text><input class="number-input" type="number" :value="quantity(item.skuCode)" placeholder="0" @input="setQuantity(item, $event.detail.value)" /></view><view v-if="unitType === 'PALLET'" class="quantity-row"><text>SKU 箱数</text><input class="number-input" type="number" :value="boxCount(item.skuCode)" placeholder="0" @input="setBoxCount(item, $event.detail.value)" / > < / view > < / view > < / view > < / view > < / view >
< view class = "summary-bar" > < view > < text class = "summary-label" > 本托合计 < / text > < text class = "summary-value" > { { receiptQuantity } } < / text > < / view > < button class = "primary submit-button" : disabled = "!canConfirm || busy" @tap ="confirmReceipt" > {{ busy ? ' 提交中 … ' : ' 确认签收并入托 ' }} < / button > < / view >
< view class = "work-card" > < view class = "row-head" > < view > < text class = "card-title" > 退货打托照片 < / text > < text class = "hint" > 签收过程中可随时拍照 < / text > < / view > < text class = "status-pill" > { { photoFileIds . length } } / 20 张 < / text > < / view > < button class = "secondary" : disabled = "busy || photoFileIds.length >= 20" @tap ="choosePhoto" > 拍照或从相册选择 < / button > < view v-if = "photoFileIds.length" class="photo-grid"><view v-for="(fileId,index) in photoFileIds" :key="fileId" class="photo-tile"><image class="photo-thumbnail" :src="photoUrls[fileId]" mode="aspectFill" @tap="previewPhoto(fileId)" /><text class="photo-name">{{ photoNames[index] || '退货打托照片' }}</text><button class="link-button" :disabled="busy" @tap="removePhoto(index)" > 移除 < / button > < / view > < / view > < / view >
< button v-if = "current.status === 'PARTIALLY_RECEIVED'" class="secondary manual-complete" :disabled="busy" @tap="manualComplete" > 缺货手动完结 < / button >
< view v-if = "current.completedPallets?.length" class="work-card"><text class="card-title">本单已完成打托</text><view class="item-list"><view v-for="pallet in current.completedPallets" :key="pallet.palletCode" class="item-card"><text class="business-code">{{ pallet.palletCode }}</text><text class="meta-line">{{ pallet.skuCode }} · {{ pallet.quantity }} 件</text><text class="meta-line" > 签收批次 : {{ pallet.receiptBatchNo }} < / text > < / view > < / view > < / view >
< / template >
< view v-if = "result" class="success-box result-card"><text class="success-title">退货签收成功</text><view v-if="result.labels?.length"><view v-for="(label,index) in result.labels" :key="label.cartonMark" class="item-card"><text class="business-code">第 {{ index + 1 }} 箱 · {{ label.cartonMark }}</text><button class="secondary" @tap="printReturnCarton(label)">打印箱唛</button></view></view><view v-else-if="result.printableHtml" class="item-card"><text class="business-code">{{ result.unitType === 'PALLET' ? '托盘标签' : '箱唛' }} · {{ result.cartonMark }}</text><button class="secondary" @tap="printReturnCarton(result)">打印{{ result.unitType === 'PALLET' ? '托盘标签' : '箱唛' }}</button></view><text v-if="result.palletCode" class="result-carton">托盘:{{ result.palletCode }}</text><text class="meta-line">签收单:{{ result.receiptNo }}</text><text class="meta-line">计费批次:{{ result.receiptBatchNo }}</text><view class="metric-row"><view class="metric"><strong>{{ result.receivedQuantity }}/{{ result.expectedQuantity }}</strong><text>整单累计</text></view><view class="metric"><strong>{{ result.fullyMatched ? '已完成' : '签收中' }}</strong><text>退货单状态</text></view></view><button class="primary" @tap="nextReceipt " > 继续签收 < / button > < / view >
< view v-if = "result" class="success-box result-card"><text class="success-title">退货签收成功</text><view v-if="result.labels?.length"><view v-for="(label,index) in result.labels" :key="label.cartonMark" class="item-card"><text class="business-code">第 {{ index + 1 }} 箱 · {{ label.cartonMark }}</text><button class="secondary" @tap="printReturnCarton(label)">打印箱唛</button></view></view><view v-else-if="result.printableHtml" class="item-card"><text class="business-code">{{ result.unitType === 'PALLET' ? '托盘标签' : '箱唛' }} · {{ result.cartonMark }}</text><button class="secondary" @tap="printReturnCarton(result)">打印{{ result.unitType === 'PALLET' ? '托盘标签' : '箱唛' }}</button></view><text v-if="result.palletCode" class="result-carton">托盘:{{ result.palletCode }}</text><text class="meta-line">签收单:{{ result.receiptNo }}</text><text class="meta-line">计费批次:{{ result.receiptBatchNo }}</text><view class="metric-row"><view class="metric"><strong>{{ result.receivedQuantity }}/{{ result.expectedQuantity }}</strong><text>整单累计</text></view><view class="metric"><strong>{{ result.fullyMatched ? '已完成' : '签收中' }}</strong><text>退货单状态</text></view></view><button class="primary" :disabled="busy" @tap="nextReceipt">{{ result.continuationReturnNo ? (unitType === 'PALLET' ? '新增托盘,继续签收剩余货物' : '继续签收本单剩余货物') : '签收下一单' }}</button><button v-if="unitType === 'PALLET' && result.continuationReturnNo" class="secondary" :disabled="busy" @tap="continueScanning " > 继续签收 < / button > < / view >
< view v-if = "error" class="error-box" role="alert"><text class="error-title">{{ error.message }}</text><text v-if="error.code">错误码:{{ error.code }}</text><text v-if="error.requestId">requestId: {{ error.requestId }}</text><text v-if="error.traceId">traceId: {{ error.traceId }}</text><button v-if="current && !receiptBatch" class="secondary" :disabled="busy" @tap="reloadCurrent" > 刷新退货单 < / button > < / view >
< / view > < / scroll -view >
@@ -64,9 +62,9 @@
startedBy : { get ( ) { return warehouseWork . returnReceipt . startedBy } , set ( value ) { updateWarehouseWork ( 'returnReceipt' , { startedBy : value } ) } } ,
trackingNo : { get ( ) { return warehouseWork . returnReceipt . trackingNo } , set ( value ) { updateWarehouseWork ( 'returnReceipt' , { trackingNo : value } ) } } ,
palletCode : { get ( ) { return warehouseWork . returnReceipt . palletCode } , set ( value ) { updateWarehouseWork ( 'returnReceipt' , { palletCode : value } ) } } ,
selectedItems ( ) { return this . current ? . expectedItems ? . filter ( item => ! this . selectedSku || item . skuCode === this . selectedSku ) || [ ] } ,
selectedItems ( ) { return this . current ? . expectedItems || [ ] } ,
palletBoxCount ( ) { return this . selectedItems . reduce ( ( sum , item ) => sum + this . boxCount ( item . skuCode ) , 0 ) } ,
activeSkuCode ( ) { return this . selectedItems . length === 1 ? this . selectedItems [ 0 ] . skuCode : '' } ,
activeSkuCode ( ) { return this . selectedItems . find ( item => item . skuCode === this . selectedSku ) ? . skuCode || this . selectedItems [ 0 ] ? . skuCode || '' } ,
receiptQuantity ( ) { return this . unitType === 'BOX' ? this . boxRows . reduce ( ( sum , box ) => sum + Object . values ( box . items ) . reduce ( ( n , quantity ) => n + ( Number ( quantity ) || 0 ) , 0 ) , 0 ) : Object . values ( warehouseWork . returnReceipt . quantities || { } ) . reduce ( ( total , value ) => total + ( Number ( value ) || 0 ) , 0 ) } ,
canConfirm ( ) { if ( ! this . current || ! this . selectedItems . length || this . receiptQuantity <= 0 ) return false ; if ( this . unitType === 'BOX' ) return this . boxRows . length > 0 && this . boxRows . every ( box => Object . values ( box . items ) . some ( quantity => Number ( quantity ) > 0 ) ) && this . selectedItems . every ( item => this . boxRows . reduce ( ( sum , box ) => sum + ( Number ( box . items [ item . skuCode ] ) || 0 ) , 0 ) <= this . remaining ( item ) ) ; return ( this . unitType === 'PARCEL' ? this . unitCode . trim ( ) : this . palletCode . trim ( ) && this . palletCheck && Number ( this . palletLength ) > 0 && Number ( this . palletWidth ) > 0 && Number ( this . palletHeight ) > 0 && Number ( this . palletWeight ) > 0 && ( this . unitType !== 'PALLET' || this . palletBoxCount > 0 ) ) && this . selectedItems . every ( ( item ) => this . quantity ( item . skuCode ) <= this . remaining ( item ) && ( this . unitType !== 'PALLET' || this . quantity ( item . skuCode ) === 0 || this . boxCount ( item . skuCode ) > 0 ) ) ; } ,
unitLabel ( ) { return this . unitType === 'PALLET' ? '托盘码' : this . unitType === 'BOX' ? '箱号/箱唛' : '包裹码/快递单号' } ,
@@ -135,7 +133,7 @@
} ,
finishReceipt ( results ) {
const last = results [ results . length - 1 ]
this . result = { ... last , labels : results . filter ( item => item . unitType === 'BOX' && item . printableHtml ) . map ( item => ( { cartonMark : item . cartonMark , printableHtml : item . printableHtml } ) ) }
this . result = { ... last , continuationReturnNo : ! last . fullyMatched ? this . current ? . returnNo || '' : '' , labels : results . filter ( item => item . unitType === 'BOX' && item . printableHtml ) . map ( item => ( { cartonMark : item . cartonMark , printableHtml : item . printableHtml } ) ) }
resetWarehouseDomain ( 'returnReceipt' )
this . current = null
this . candidates = null
@@ -148,7 +146,27 @@
removePhoto ( index ) { const [ id ] = this . photoFileIds . splice ( index , 1 ) ; this . photoNames . splice ( index , 1 ) ; if ( id ) delete this . photoUrls [ id ] } ,
async reloadCurrent ( ) { if ( ! this . current ? . returnNo || this . busy ) return ; await this . openOrder ( this . current . returnNo , this . startedBy , false ) } ,
clearCurrent ( ) { if ( this . busy || this . receiptBatch ) return ; resetWarehouseDomain ( 'returnReceipt' ) ; this . current = null ; this . candidates = null ; this . error = null ; this . activeTarget = 'lookup' } ,
nextReceipt ( ) { this . result = null ; this . clearCurrent ( ) } ,
continueScanning ( ) {
if ( this . busy || this . receiptBatch ) return
this . clearCurrent ( )
this . result = null
this . entryMode = 'SKU' ; this . lookupCode = '' ; this . selectedSku = ''
this . palletCheck = null ; this . newPalletHtml = ''
this . palletLength = '' ; this . palletWidth = '' ; this . palletHeight = '' ; this . palletWeight = ''
this . unitCode = '' ; this . boxRows = [ { items : { } } ]
this . photoFileIds = [ ] ; this . photoNames = [ ] ; this . photoUrls = { }
} ,
async nextReceipt ( ) {
if ( this . busy ) return
const returnNo = this . result ? . continuationReturnNo
if ( ! returnNo ) { this . result = null ; this . clearCurrent ( ) ; return }
await this . run ( async ( ) => {
await this . openOrderValue ( returnNo , 'SKU' )
this . palletLength = '' ; this . palletWidth = '' ; this . palletHeight = '' ; this . palletWeight = ''
this . unitCode = '' ; this . boxRows = [ { items : { } } ] ; this . newPalletHtml = ''
this . result = null
} , '读取剩余待签收货物失败' )
} ,
async run ( work , fallback ) { if ( this . busy ) return ; this . busy = true ; this . error = null ; try { await work ( ) } catch ( error ) { this . setError ( error , fallback ) } finally { this . busy = false } } ,
setError ( error , fallback ) { this . error = { message : error ? . message || fallback , code : error ? . code , requestId : error ? . requestId , traceId : error ? . traceId } ; playErrorSound ( ) } ,
statusLabel ( value ) { return ( { PENDING _RECEIPT : '待签收' , PARTIALLY _RECEIVED : '签收中' , COMPLETED : '已完成' } ) [ value ] || value || '状态未知' }
@@ -158,6 +176,9 @@
< style scoped lang = "scss" >
@ import '../warehouse/operations.scss' ;
. dimension - grid label . dimension - label { display : flex ; align - items : center ; justify - content : space - between ; gap : 3 px ; margin - bottom : 3 px } . dimension - grid label . dimension - label > text { color : # 65768 b ; font - size : 10 px ; line - height : 14 px ; font - weight : 400 ; white - space : nowrap } . dimension - grid label . dimension - label > . volume - text { margin - left : auto ; color : # 135 ee8 ; font - size : 10 px }
. receipt - order - card { padding : 10 px 14 px ! important } . receipt - order - card . row - head { align - items : center ; margin - bottom : 5 px } . receipt - order - card . card - title { margin : 0 ; font - size : 12 px } . receipt - order - card . link - button { margin : 0 ; padding : 0 ; font - size : 11 px ; line - height : 24 px } . receipt - order - line { display : flex ; align - items : center ; gap : 8 px } . receipt - order - line . business - code { flex : 1 ; min - width : 0 ; font - size : 12 px ; line - height : 18 px ; white - space : nowrap ; overflow - x : auto ; word - break : normal } . receipt - order - line . status - pill { flex - shrink : 0 ; font - size : 10 px ; padding : 3 px 6 px }
. receipt - sku - list . item - card { padding : 10 px 12 px } . receipt - sku - list . row - head { align - items : flex - start ; gap : 8 px } . receipt - sku - list . row - head > view { flex : 1 ; min - width : 0 } . receipt - sku - list . business - code { font - size : 12 px ; line - height : 17 px ; word - break : break - all } . receipt - sku - list . meta - line { font - size : 10 px ; line - height : 15 px ; margin - top : 3 px } . receipt - sku - list . remaining - copy { flex - shrink : 0 ; white - space : nowrap ; font - size : 10 px } . sku - quantity - fields { display : flex ; gap : 14 px ; margin - top : 8 px } . sku - quantity - fields . quantity - row { flex : 1 ; min - width : 0 ; gap : 6 px ; margin : 0 ; justify - content : flex - start } . sku - quantity - fields . quantity - row > text { white - space : nowrap ; font - size : 10 px } . sku - quantity - fields . quantity - row . number - input { box - sizing : border - box ; width : 64 px ; height : 30 px ; min - height : 30 px ; padding : 0 5 px ; border - radius : 6 px ; font - size : 13 px }
. candidate - heading . card - title { margin - bottom : 0 } . candidate - card { width : 100 % ; text - align : left } . select - link { color : # 135 ee8 ; font - size : 12 px ; font - weight : 800 } . field - label { display : block ; margin : 13 px 0 6 px ; color : # 52667 e ; font - size : 11 px ; font - weight : 700 } . remaining - copy { color : # 135 ee8 ; font - size : 11 px } . quantity - row { display : flex ; align - items : center ; justify - content : space - between ; gap : 12 px ; margin - top : 10 px ; color : # 65768 b ; font - size : 11 px } . quantity - row . number - input { width : 112 px ; text - align : center } . summary - bar { position : sticky ; bottom : 0 ; z - index : 4 ; display : flex ; align - items : center ; gap : 12 px ; margin - top : 12 px ; padding : 11 px 13 px ; border : 1 px solid # d8e3f1 ; border - radius : 13 px ; background : # fff ; box - shadow : 0 5 px 20 px rgba ( 22 , 55 , 96 , .14 ) } . summary - bar > view { min - width : 70 px } . summary - label , . summary - value { display : block } . summary - label { color : # 728197 ; font - size : 10 px } . summary - value { color : # 135 ee8 ; font - size : 22 px ; font - weight : 800 } . submit - button { margin - top : 0 } . result - card { text - align : left } . result - carton { display : block ; margin : 9 px 0 ; color : # 135 ee8 ; font - size : 20 px ; font - weight : 800 ; word - break : break - all } . link - button { width : auto } . work - card > . link - button { margin - top : 8 px ; padding - left : 0 } . success - box . primary { margin - top : 14 px } . scan - hint { display : block ; margin - top : 9 px ; color : # 65768 b ; font - size : 11 px ; text - align : center }
. photo - grid { display : grid ; grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; gap : 10 px ; margin - top : 12 px } . photo - tile { min - width : 0 ; overflow : hidden ; border : 1 px solid # d7e1ef ; border - radius : 8 px } . photo - thumbnail { display : block ; width : 100 % ; height : 130 px ; background : # f1f4f8 } . photo - name { display : block ; padding : 6 px 8 px ; overflow : hidden ; white - space : nowrap ; text - overflow : ellipsis ; font - size : 12 px ; color : # 52647 c } . photo - tile . link - button { margin : 0 8 px 6 px }
. unit - tabs { display : flex ; gap : 8 px ; margin : 10 px 0 } . unit - tab { flex : 1 ! important ; min - width : 0 ! important ; height : 34 px ! important ; min - height : 34 px ! important ; margin : 0 ! important ; padding : 0 10 px ! important ; border : 1 px solid # d6e1ef ! important ; border - radius : 8 px ! important ; background : # f7f9fc ! important ; color : # 53677 f ! important ; font - size : 13 px ! important ; line - height : 34 px ! important } . unit - tab . active { border - color : # 135 ee8 ! important ; background : # eaf2ff ! important ; color : # 135 ee8 ! important ; font - weight : 700 }