feat: 积分商城-供应商-对账-发票4
This commit is contained in:
@@ -1,23 +1,111 @@
|
||||
<template>
|
||||
<section class="page-card"><div class="page-title"><div><h2>{{ title }}</h2><p>{{ description }}</p></div></div><el-form :inline="true" class="query-form"><el-form-item label="供应商 ID"><el-input v-model="supplierId" placeholder="请输入供应商 ID" clearable /></el-form-item><el-form-item><el-button type="primary" :loading="loading" @click="loadRecords">查询</el-button><el-button @click="reset">重置</el-button></el-form-item></el-form><el-table v-loading="loading" :data="records" border><el-table-column prop="serviceOrderId" label="售后单号" min-width="170" /><el-table-column prop="serviceTypeText" label="售后类型" width="110" /><el-table-column prop="serviceStateText" label="状态" width="130" /><el-table-column prop="reason" label="原因" min-width="160" /><el-table-column prop="applyTime" label="申请时间" min-width="170" /><el-table-column label="操作" min-width="160" fixed="right"><template #default="{ row }"><el-button link type="primary" @click="openDetail(row)">详情</el-button><el-button v-if="scene === 'audit'" link type="success" @click="audit(row, 1)">通过</el-button><el-button v-if="scene === 'audit'" link type="danger" @click="audit(row, 2)">拒绝</el-button><el-button v-if="canReceive(row)" link type="success" @click="receive(row)">确认收货</el-button><el-button v-if="canShip(row)" link type="primary" @click="openShipDialog(row)">换货发货</el-button></template></el-table-column><template #empty><el-empty :image-size="80" description="暂无售后记录" /></template></el-table><el-dialog v-model="detailVisible" title="售后详情" width="620px"><pre class="detail-json">{{ JSON.stringify(detail, null, 2) }}</pre></el-dialog><el-dialog v-model="shipVisible" title="换货发货" width="460px"><el-form label-width="90px"><el-form-item label="快递公司"><el-input v-model="shipForm.logisticsCompany" /></el-form-item><el-form-item label="快递单号"><el-input v-model="shipForm.logisticsNo" /></el-form-item></el-form><template #footer><el-button @click="shipVisible = false">取消</el-button><el-button type="primary" @click="shipExchange">确认发货</el-button></template></el-dialog></section>
|
||||
<section class="page-card"><div class="page-title"><div><h2>{{ title }}</h2><p>{{ description }}</p></div></div><el-form :inline="true" class="query-form" @submit.prevent="loadRecords"><el-form-item label="售后单号"><el-input v-model="serviceOrderId" placeholder="请输入售后单号" clearable /></el-form-item><el-form-item><el-button type="primary" :loading="loading" @click="loadRecords">查询</el-button><el-button @click="reset">重置</el-button></el-form-item></el-form><div v-if="scene !== 'process'" v-loading="loading" class="audit-list">
|
||||
<article v-for="row in records" :key="row.serviceOrderId" class="audit-card">
|
||||
<header class="audit-card-header"><strong>{{ row.serviceOrderId }}</strong><el-tag type="warning">{{ row.serviceTypeText || '-' }}</el-tag></header>
|
||||
<div v-for="product in row.products || []" :key="product.id || product.sku" class="audit-product">
|
||||
<el-image :src="resolveImageUrl(product.image || '')" :preview-src-list="product.image ? [resolveImageUrl(product.image)] : []" preview-teleported fit="cover"><template #error><span class="image-empty">暂无图片</span></template></el-image>
|
||||
<div class="audit-product-info"><strong>{{ product.name }}</strong><span>{{ specText(product.sku) }}</span><b>¥{{ money(product.price) }}</b></div><span class="audit-quantity">×{{ product.number }}</span>
|
||||
</div>
|
||||
<div class="audit-summary"><dl><dt>原因</dt><dd>{{ row.reason || '-' }}</dd><dt>描述</dt><dd>{{ row.problemDescription || '-' }}</dd></dl><el-tag :type="row.isSigned === true ? 'success' : 'info'">{{ row.isSigned === true ? '已签收' : row.isSigned === false ? '未签收' : '签收状态未知' }}</el-tag></div>
|
||||
<div v-if="scene === 'audit'" class="after-sale-status"><el-tag :type="row.serviceState === 0 ? 'warning' : 'primary'">{{ currentStatusText(row) }}</el-tag></div>
|
||||
<div v-if="scene === 'history'" class="history-result"><span class="result-stamp" :class="{ approved: row.serviceState === 5, rejected: row.serviceState === 2 }">{{ historyResultText(row) }}</span></div>
|
||||
<footer class="audit-card-footer"><span>{{ row.applyTime || '-' }}</span><div><el-button @click="openDetail(row)">查看详情</el-button><el-button v-if="scene === 'audit' && row.serviceState === 0" type="danger" plain :disabled="auditing" @click="audit(row, 2)">拒绝</el-button><el-button v-if="scene === 'audit' && row.serviceState === 0" type="primary" :disabled="auditing" @click="audit(row, 1)">通过</el-button><el-button v-if="canReceive(row)" type="primary" :disabled="auditing" @click="receive(row)">确认收货</el-button><el-button v-if="canShip(row)" type="primary" :disabled="auditing" @click="openShipDialog(row)">换货发货</el-button></div></footer>
|
||||
</article>
|
||||
<el-empty v-if="!loading && !records.length" :description="scene === 'audit' ? '暂无待处理售后' : '暂无售后记录'" />
|
||||
</div><el-table v-else v-loading="loading" :data="records" border><el-table-column prop="serviceOrderId" label="售后单号" min-width="170" /><el-table-column prop="serviceTypeText" label="售后类型" width="110" /><el-table-column prop="serviceStateText" label="状态" width="130" /><el-table-column prop="reason" label="原因" min-width="160" /><el-table-column prop="applyTime" label="申请时间" min-width="170" /><el-table-column label="操作" min-width="160" fixed="right"><template #default="{ row }"><el-button link type="primary" @click="openDetail(row)">详情</el-button><el-button v-if="scene === 'audit'" link type="success" @click="audit(row, 1)">通过</el-button><el-button v-if="scene === 'audit'" link type="danger" @click="audit(row, 2)">拒绝</el-button><el-button v-if="canReceive(row)" link type="success" @click="receive(row)">确认收货</el-button><el-button v-if="canShip(row)" link type="primary" @click="openShipDialog(row)">换货发货</el-button></template></el-table-column><template #empty><el-empty :image-size="80" description="暂无售后记录" /></template></el-table><el-dialog v-model="detailVisible" title="售后详情" :width="scene !== 'process' ? '1080px' : '760px'">
|
||||
<div v-if="scene !== 'process' && detail.afterSale" class="audit-detail">
|
||||
<section class="audit-detail-section audit-progress"><span v-if="scene === 'history'" class="result-stamp detail-result-stamp" :class="{ approved: detail.afterSale.serviceState === 5, rejected: detail.afterSale.serviceState === 2 }" aria-label="处理结果">{{ historyResultText(detail.afterSale) }}</span><h3>售后进度</h3><el-steps align-center>
|
||||
<el-step title="提交申请" status="success"><template #description><p>用户提交售后申请</p><p>{{ detail.afterSale.applyTime || '-' }}</p></template></el-step>
|
||||
<el-step title="商家审核" :status="detail.afterSale.auditTime ? (detail.afterSale.auditStatus === 2 ? 'error' : 'success') : detail.afterSale.serviceState === 6 ? 'wait' : 'process'"><template #description><p>{{ detail.afterSale.auditRemark || (detail.afterSale.serviceState === 6 ? '申请已撤销' : '待商家审核') }}</p><p>{{ detail.afterSale.auditTime || '-' }}</p></template></el-step>
|
||||
<el-step v-if="detail.afterSale.isSigned && detail.afterSale.auditStatus === 1" title="商品寄回" :status="detail.afterSale.userShipTime ? 'success' : 'process'"><template #description><p>{{ detail.afterSale.userShipTime ? '用户已寄回商品' : '等待用户填写寄回物流' }}</p><p>{{ detail.afterSale.userShipTime || '-' }}</p></template></el-step>
|
||||
<el-step v-if="detail.afterSale.isSigned && detail.afterSale.auditStatus === 1" title="商家收货" :status="detail.afterSale.merchantReceiveTime ? 'success' : detail.afterSale.userShipTime ? 'process' : 'wait'"><template #description><p>{{ detail.afterSale.merchantReceiveTime ? '商家已确认收货' : '等待商家收到商品' }}</p><p>{{ detail.afterSale.merchantReceiveTime || '-' }}</p></template></el-step>
|
||||
<el-step :title="detail.afterSale.serviceState === 6 ? '已撤销' : detail.afterSale.serviceState === 2 ? '审核未通过' : '售后完成'" :status="detail.afterSale.serviceState === 5 ? 'success' : 'wait'"><template #description><p>{{ detail.afterSale.serviceState === 5 ? '售后已完成' : detail.afterSale.serviceState === 2 ? '审核未通过,售后已结束' : detail.afterSale.serviceState === 6 ? '用户已撤销售后申请' : '等待售后处理完成' }}</p><p>{{ detail.afterSale.finishTime || '-' }}</p></template></el-step>
|
||||
</el-steps></section>
|
||||
<section class="audit-detail-section"><h3>售后商品</h3><div v-for="product in detail.afterSale.products || []" :key="product.id || product.sku" class="audit-product"><el-image :src="resolveImageUrl(product.image || '')" :preview-src-list="product.image ? [resolveImageUrl(product.image)] : []" preview-teleported fit="cover"><template #error><span class="image-empty">暂无图片</span></template></el-image><div class="audit-product-info"><strong>{{ product.name }}</strong><span>{{ specText(product.sku) }}</span><b>¥{{ money(product.price) }}</b></div><span class="audit-quantity">×{{ product.number }}</span></div></section>
|
||||
<section class="audit-detail-section"><h3>售后信息</h3><el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="售后单号">{{ detail.afterSale.serviceOrderId }}</el-descriptions-item><el-descriptions-item label="子订单号">{{ detail.afterSale.orderNumberId || detail.afterSale.subOrderId || '-' }}</el-descriptions-item><el-descriptions-item label="售后类型"><el-tag type="warning">{{ detail.afterSale.serviceTypeText || '-' }}</el-tag></el-descriptions-item><el-descriptions-item label="签收状态"><el-tag :type="detail.afterSale.isSigned === true ? 'success' : 'info'">{{ detail.afterSale.isSigned === true ? '已签收' : detail.afterSale.isSigned === false ? '未签收' : '-' }}</el-tag></el-descriptions-item><el-descriptions-item label="当前状态"><el-tag>{{ currentStatusText(detail.afterSale) }}</el-tag></el-descriptions-item><el-descriptions-item v-if="detail.afterSale.userLogisticsNo" label="寄回物流">{{ detail.afterSale.userLogisticsCompany || '-' }} / {{ detail.afterSale.userLogisticsNo }}</el-descriptions-item><el-descriptions-item v-if="detail.afterSale.merchantReceiveTime" label="商家收货时间">{{ detail.afterSale.merchantReceiveTime }}</el-descriptions-item><el-descriptions-item v-if="detail.afterSale.merchantLogisticsNo" label="换货物流">{{ detail.afterSale.merchantLogisticsCompany || '-' }} / {{ detail.afterSale.merchantLogisticsNo }}</el-descriptions-item><el-descriptions-item label="售后原因">{{ detail.afterSale.reason || '-' }}</el-descriptions-item><el-descriptions-item label="问题描述">{{ detail.afterSale.problemDescription || '-' }}</el-descriptions-item><el-descriptions-item label="申请时间">{{ detail.afterSale.applyTime || '-' }}</el-descriptions-item>
|
||||
</el-descriptions><div v-if="detailImages.length" class="audit-evidence"><el-image v-for="url in detailImages" :key="url" :src="url" :preview-src-list="detailImages" preview-teleported fit="cover" /></div></section>
|
||||
</div><pre v-else class="detail-json">{{ JSON.stringify(detail, null, 2) }}</pre>
|
||||
<template #footer><el-button @click="detailVisible = false">关闭</el-button><template v-if="scene === 'audit' && detail.afterSale?.serviceState === 0"><el-button type="danger" plain :disabled="auditing" @click="audit(detail.afterSale, 2)">拒绝</el-button><el-button type="primary" :disabled="auditing" @click="audit(detail.afterSale, 1)">通过</el-button></template><el-button v-if="detail.afterSale && canReceive(detail.afterSale)" type="primary" :disabled="auditing" @click="receive(detail.afterSale)">确认收货</el-button><el-button v-if="detail.afterSale && canShip(detail.afterSale)" type="primary" :disabled="auditing" @click="openShipDialog(detail.afterSale)">换货发货</el-button></template>
|
||||
</el-dialog><el-dialog v-model="shipVisible" title="换货发货" width="460px" append-to-body><el-form label-width="90px"><el-form-item label="快递公司"><el-input v-model="shipForm.logisticsCompany" /></el-form-item><el-form-item label="快递单号"><el-input v-model="shipForm.logisticsNo" /></el-form-item></el-form><template #footer><el-button @click="shipVisible = false">取消</el-button><el-button type="primary" :loading="auditing" @click="shipExchange">确认发货</el-button></template></el-dialog></section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { postAdmin } from '@/api/admin'
|
||||
import { postAdmin, resolveImageUrl } from '@/api/admin'
|
||||
const props = defineProps<{ scene: 'audit' | 'process' | 'history'; title: string; description: string }>()
|
||||
type AfterSale = { serviceOrderId: string; serviceState?: number; serviceType?: number; isSigned?: boolean; serviceTypeText?: string; serviceStateText?: string; reason?: string; applyTime?: string }
|
||||
const supplierId = ref(''); const records = ref<AfterSale[]>([]); const loading = ref(false); const queried = ref(false); const detailVisible = ref(false); const detail = ref<unknown>({}); const shipVisible = ref(false); const current = ref<AfterSale>(); const shipForm = ref({ logisticsCompany: '', logisticsNo: '' })
|
||||
const loadRecords = async () => { if (!supplierId.value.trim()) return ElMessage.warning('请输入供应商 ID'); loading.value = true; try { const data = await postAdmin<{ afterSaleItems?: AfterSale[] }>('merchant-after-sale-list', { supplierId: supplierId.value.trim(), scene: props.scene }); records.value = data.afterSaleItems || []; queried.value = true } catch (error) { ElMessage.error(error instanceof Error ? error.message : '售后查询失败') } finally { loading.value = false } }
|
||||
const reset = () => { supplierId.value = ''; records.value = []; queried.value = false }
|
||||
const openDetail = async (row: AfterSale) => { try { detail.value = await postAdmin('merchant-after-sale-detail', { supplierId: supplierId.value.trim(), serviceOrderId: row.serviceOrderId }); detailVisible.value = true } catch (error) { ElMessage.error(error instanceof Error ? error.message : '售后详情查询失败') } }
|
||||
const audit = async (row: AfterSale, auditStatus: number) => { try { await ElMessageBox.confirm(auditStatus === 1 ? '确认通过该售后申请?' : '确认拒绝该售后申请?', '售后审核'); await postAdmin('merchant-after-sale-audit', { supplierId: supplierId.value.trim(), serviceOrderId: row.serviceOrderId, auditStatus, auditRemark: auditStatus === 1 ? '审核通过' : '商家拒绝' }); ElMessage.success('处理成功'); await loadRecords() } catch (error) { if (error !== 'cancel') ElMessage.error(error instanceof Error ? error.message : '处理失败') } }
|
||||
const canReceive = (row: AfterSale) => props.scene === 'process' && Number(row.serviceState) === 3
|
||||
const canShip = (row: AfterSale) => props.scene === 'process' && Number(row.serviceType) === 5 && (Number(row.serviceState) === 4 || (row.isSigned === false && Number(row.serviceState) === 1))
|
||||
const receive = async (row: AfterSale) => { try { await ElMessageBox.confirm('确认已收到寄回商品?', '售后处理'); await postAdmin('merchant-after-sale-receive', { supplierId: supplierId.value.trim(), serviceOrderId: row.serviceOrderId }); ElMessage.success('已确认收货'); await loadRecords() } catch (error) { if (error !== 'cancel') ElMessage.error(error instanceof Error ? error.message : '操作失败') } }
|
||||
type AfterSaleProduct = { id?: number; sku: string; name: string; number: number; price: string; image?: string }
|
||||
type AfterSale = { serviceOrderId: string; supplierId: string; serviceState?: number; logisticsState?: number; serviceType?: number; isSigned?: boolean; serviceTypeText?: string; serviceStateText?: string; reason?: string; applyTime?: string; problemDescription?: string; products?: AfterSaleProduct[]; subOrderId?: string; orderNumberId?: string; auditStatus?: number; auditTime?: string; auditRemark?: string; finishTime?: string; userLogisticsNo?: string; userLogisticsCompany?: string; merchantLogisticsNo?: string; merchantLogisticsCompany?: string; userShipTime?: string; merchantReceiveTime?: string; merchantShipTime?: string; images?: Array<string | { url?: string; previewUrl?: string; fileUrl?: string }> }
|
||||
const serviceOrderId = ref('')
|
||||
const auditing = ref(false)
|
||||
const currentStatusText = (row: AfterSale) => {
|
||||
if (row.serviceState === 1 && row.logisticsState === 1) return '审核通过,待用户寄回'
|
||||
if (row.serviceState === 3) return '用户已寄回,待商家收货'
|
||||
if (row.serviceState === 4 && row.serviceType === 5) return '商家已收货,待换货发货'
|
||||
if (row.serviceState === 1 && row.serviceType === 5 && row.isSigned === false) return '审核通过,待换货发货'
|
||||
return row.serviceStateText || '-'
|
||||
}
|
||||
const historyResultText = (row: AfterSale) => row.serviceState === 5 ? '审核通过' : row.serviceStateText || '-'
|
||||
const money = (value: string) => Number(value || 0).toFixed(2)
|
||||
const specText = (sku: string) => {
|
||||
const labels: Record<string, string> = { cream: '奶油白', blue: '雾霾蓝', orange: '暖橙色', standard: '标准款', plus: '升级款' }
|
||||
const parts = String(sku || '').split('-').slice(-2)
|
||||
return parts.some(part => labels[part]) ? parts.map(part => labels[part] || part).join(' | ') : '-'
|
||||
}
|
||||
const detailImages = computed(() => (detail.value.afterSale?.images || []).map(item => resolveImageUrl(typeof item === 'string' ? item : item.fileUrl || item.url || item.previewUrl || '')).filter(Boolean))
|
||||
const records = ref<AfterSale[]>([]); const loading = ref(false); const queried = ref(false); const detailVisible = ref(false); const detail = ref<{ afterSale?: AfterSale }>({}); const shipVisible = ref(false); const current = ref<AfterSale>(); const shipForm = ref({ logisticsCompany: '', logisticsNo: '' })
|
||||
const loadRecords = async () => { loading.value = true; try { const data = await postAdmin<{ afterSaleItems?: AfterSale[] }>('merchant-after-sale-list', { scene: props.scene, serviceOrderId: serviceOrderId.value.trim() }); records.value = data.afterSaleItems || []; queried.value = true } catch (error) { ElMessage.error(error instanceof Error ? error.message : '售后查询失败') } finally { loading.value = false } }
|
||||
const reset = () => { serviceOrderId.value = ''; return loadRecords() }
|
||||
const openDetail = async (row: AfterSale) => { try { detail.value = await postAdmin<{ afterSale: AfterSale }>('merchant-after-sale-detail', { supplierId: row.supplierId, serviceOrderId: row.serviceOrderId }); detailVisible.value = true } catch (error) { ElMessage.error(error instanceof Error ? error.message : '售后详情查询失败') } }
|
||||
const audit = async (row: AfterSale, auditStatus: number) => { if (auditing.value) return; auditing.value = true; try { await ElMessageBox.confirm(auditStatus === 1 ? '确认通过该售后申请?' : '确认拒绝该售后申请?', '售后审核'); await postAdmin('merchant-after-sale-audit', { supplierId: row.supplierId, serviceOrderId: row.serviceOrderId, auditStatus, auditRemark: auditStatus === 1 ? '审核通过' : '商家拒绝' }); ElMessage.success('处理成功'); detailVisible.value = false; await loadRecords() } catch (error) { if (error !== 'cancel' && error !== 'close') ElMessage.error(error instanceof Error ? error.message : '处理失败') } finally { auditing.value = false } }
|
||||
const canReceive = (row: AfterSale) => props.scene !== 'history' && Number(row.serviceState) === 3
|
||||
const canShip = (row: AfterSale) => props.scene !== 'history' && Number(row.serviceType) === 5 && (Number(row.serviceState) === 4 || (row.isSigned === false && Number(row.serviceState) === 1))
|
||||
const receive = async (row: AfterSale) => { if (auditing.value) return; auditing.value = true; try { await ElMessageBox.confirm('确认已收到寄回商品?', '售后处理'); await postAdmin('merchant-after-sale-receive', { supplierId: row.supplierId, serviceOrderId: row.serviceOrderId }); ElMessage.success('已确认收货'); await loadRecords(); if (detailVisible.value) await openDetail(row) } catch (error) { if (error !== 'cancel' && error !== 'close') ElMessage.error(error instanceof Error ? error.message : '操作失败') } finally { auditing.value = false } }
|
||||
const openShipDialog = (row: AfterSale) => { current.value = row; shipForm.value = { logisticsCompany: '', logisticsNo: '' }; shipVisible.value = true }
|
||||
const shipExchange = async () => { if (!current.value || !shipForm.value.logisticsCompany || !shipForm.value.logisticsNo) return ElMessage.warning('请填写完整发货信息'); try { await postAdmin('merchant-after-sale-ship', { supplierId: supplierId.value.trim(), serviceOrderId: current.value.serviceOrderId, ...shipForm.value }); ElMessage.success('换货已发货'); shipVisible.value = false; await loadRecords() } catch (error) { ElMessage.error(error instanceof Error ? error.message : '发货失败') } }
|
||||
const shipExchange = async () => { if (auditing.value) return; if (!current.value || !shipForm.value.logisticsCompany || !shipForm.value.logisticsNo) return ElMessage.warning('请填写完整发货信息'); auditing.value = true; try { await postAdmin('merchant-after-sale-ship', { supplierId: current.value.supplierId, serviceOrderId: current.value.serviceOrderId, ...shipForm.value }); ElMessage.success('换货已发货'); shipVisible.value = false; await loadRecords(); if (detailVisible.value) await openDetail(current.value) } catch (error) { ElMessage.error(error instanceof Error ? error.message : '发货失败') } finally { auditing.value = false } }
|
||||
onMounted(loadRecords)
|
||||
</script>
|
||||
|
||||
<style scoped>.detail-json { max-height: 420px; overflow: auto; padding: 12px; border-radius: 4px; background: #f5f7fa; white-space: pre-wrap; word-break: break-all; }</style>
|
||||
<style scoped>
|
||||
.after-sale-status { margin-top: 16px; }
|
||||
.audit-card-footer > div { display: flex; flex-wrap: wrap; gap: 8px; }
|
||||
.audit-card-footer > div .el-button { margin-left: 0; }
|
||||
.history-result { display: flex; justify-content: flex-end; margin-top: 16px; padding: 8px 6px; }
|
||||
.result-stamp { position: relative; display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; width: 112px; height: 56px; margin: 6px 0; border: 2px solid currentColor; border-radius: 50%; color: #909399; font-size: 16px; font-weight: 700; letter-spacing: 2px; line-height: 1; transform: rotate(-14deg); }
|
||||
.result-stamp::after { position: absolute; inset: 4px; border: 1px dashed currentColor; border-radius: 50%; content: ""; }
|
||||
.result-stamp.approved { color: #389e63; }
|
||||
.result-stamp.rejected { color: #d9534f; }
|
||||
.audit-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 390px), 1fr)); gap: 20px; }
|
||||
.audit-list > .el-empty { grid-column: 1 / -1; }
|
||||
.audit-card { padding: 20px; border: 1px solid #e9eef5; border-radius: 12px; background: #fff; }
|
||||
.audit-card-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 18px; }
|
||||
.audit-card-header strong { min-width: 0; overflow-wrap: anywhere; line-height: 22px; }
|
||||
.audit-card-header .el-tag { flex-shrink: 0; }
|
||||
.audit-product { display: flex; align-items: center; gap: 14px; margin-bottom: 16px; }
|
||||
.audit-product > .el-image { width: 72px; height: 72px; flex-shrink: 0; border-radius: 8px; }
|
||||
.audit-product-info { display: flex; flex: 1; min-width: 0; flex-direction: column; gap: 6px; }
|
||||
.audit-product-info strong { overflow-wrap: anywhere; }
|
||||
.audit-product-info span, .audit-card-footer > span { color: #8793a5; font-size: 12px; }
|
||||
.audit-product-info b { color: #ff6b35; }
|
||||
.audit-quantity { flex-shrink: 0; font-weight: 600; }
|
||||
.image-empty { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; background: #f5f7fa; color: #8793a5; font-size: 12px; }
|
||||
.audit-summary { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
|
||||
.audit-summary dl { display: grid; grid-template-columns: 36px minmax(0, 1fr); gap: 10px 12px; flex: 1; min-width: 0; margin: 0; font-size: 13px; }
|
||||
.audit-summary dt { color: #8793a5; }
|
||||
.audit-summary dd { margin: 0; overflow-wrap: anywhere; white-space: pre-wrap; }
|
||||
.audit-card-footer { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 14px; margin-top: 20px; padding-top: 16px; border-top: 1px solid #edf0f5; }
|
||||
.audit-detail { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); align-items: start; gap: 20px; }
|
||||
.audit-progress { position: relative; grid-column: 1 / -1; }
|
||||
.detail-result-stamp { position: absolute; z-index: 10; top: -18px; right: 8px; pointer-events: none; width: 128px; height: 128px; margin: 0; border-width: 3px; font-size: 20px; }
|
||||
.detail-result-stamp::after { inset: 7px; border-width: 2px; }
|
||||
.audit-detail-section { min-width: 0; padding: 20px; border: 1px solid #e9eef5; border-radius: 10px; }
|
||||
@media (max-width: 767px) { .audit-detail { grid-template-columns: minmax(0, 1fr); } }
|
||||
.audit-detail-section h3 { margin: 0 0 18px; font-size: 15px; }
|
||||
.audit-progress :deep(.el-step__description) { overflow-wrap: anywhere; }
|
||||
.audit-detail-section p { margin: 6px 0 0; color: #8793a5; font-size: 12px; }
|
||||
.audit-detail :deep(.el-descriptions__label) { width: 100px; white-space: nowrap; }
|
||||
.audit-detail :deep(.el-descriptions__content) { overflow-wrap: anywhere; white-space: pre-wrap; }
|
||||
.audit-evidence { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 16px; }
|
||||
.audit-evidence .el-image { width: 80px; height: 80px; border-radius: 6px; }
|
||||
.detail-json { max-height: 420px; overflow: auto; padding: 12px; border-radius: 4px; background: #f5f7fa; white-space: pre-wrap; word-break: break-all; }</style>
|
||||
|
||||
Reference in New Issue
Block a user