style(admin): unify dialog layouts and dense readonly presentation
This commit is contained in:
@@ -182,7 +182,7 @@ function sourceSummary(sourceType: unknown, orderId: unknown, inboundId: unknown
|
||||
const type = sourceTypeDisplay(sourceType)
|
||||
return relations.length ? `${type} · ${relations.join('、')}` : type
|
||||
}
|
||||
function businessReference(row: ArapRow) {
|
||||
function businessReference(row: Pick<ArapRow, 'inboundCode' | 'containerNo' | 'sourceBusinessId'>) {
|
||||
const references = [row.inboundCode ? `入仓码 ${row.inboundCode}` : '', row.containerNo ? `柜次 ${row.containerNo}` : '']
|
||||
const businessId = row.sourceBusinessId.trim()
|
||||
if (businessId && ![row.inboundCode, row.containerNo].includes(businessId)) references.push(`业务单号 ${businessId}`)
|
||||
@@ -255,10 +255,10 @@ async function openReview(row: ArapRow) {
|
||||
selected.value = row
|
||||
const loaded = await loadDetail(row)
|
||||
if (!loaded) { detailOpen.value = true; return }
|
||||
Object.assign(reviewForm, { action: 'APPROVE', reason: '' }); reviewError.value = null; reviewOpen.value = true
|
||||
Object.assign(reviewForm, { action: 'APPROVE', reason: '' }); reviewError.value = null; mutationError.value = null; reviewOpen.value = true
|
||||
}
|
||||
async function submitReview() {
|
||||
if (!detail.value) return
|
||||
if (reviewSaving.value || !detail.value) return
|
||||
if (reviewForm.action === 'REJECT' && !reviewForm.reason.trim()) { ElMessage.warning('请填写驳回原因'); return }
|
||||
reviewSaving.value = true; reviewError.value = null
|
||||
try {
|
||||
@@ -277,7 +277,7 @@ async function openMutation(row: ArapRow, mode: 'EDIT' | 'ADJUST' | 'SUBMIT' | '
|
||||
}
|
||||
const loaded = await loadDetail(row)
|
||||
if (!loaded) { detailOpen.value = true; return }
|
||||
mutationMode.value = mode; Object.assign(mutationForm, { amount: loaded.amount, reason: '' }); mutationError.value = null; mutationOpen.value = true
|
||||
mutationMode.value = mode; Object.assign(mutationForm, { amount: loaded.amount, reason: '' }); mutationError.value = null; reviewError.value = null; mutationOpen.value = true
|
||||
}
|
||||
function sourceActions(row: ArapRow): RowActionItem[] {
|
||||
const available = row.status === 'AVAILABLE'
|
||||
@@ -301,7 +301,7 @@ function handleSourceAction(command: string, row: ArapRow) {
|
||||
else if (command === 'void') void openMutation(row, 'VOID')
|
||||
}
|
||||
async function submitMutation() {
|
||||
if (!detail.value) return
|
||||
if (mutationSaving.value || !detail.value) return
|
||||
if (!mutationForm.reason.trim()) { ElMessage.warning('请填写操作原因'); return }
|
||||
if ((mutationMode.value === 'EDIT' || mutationMode.value === 'ADJUST') && mutationForm.amount <= 0) { ElMessage.warning('金额必须大于 0'); return }
|
||||
mutationSaving.value = true; mutationError.value = null
|
||||
@@ -423,20 +423,54 @@ watch(() => [route.name, String(route.params.feeSourceId || '')], ([name, feeSou
|
||||
<template #header><div class="density-detail-header"><div class="density-detail-heading"><el-button link class="density-back" @click="closeDetail"><ArrowLeft :size="16" />返回客户应收应付</el-button><h1 class="density-detail-title">{{ selected?.documentNo || '费用来源详情' }}</h1><span class="finance-detail-context">{{ selected ? customerName(selected.customerId, selected.customerName) : '—' }}</span><StatusBadge v-if="detail" :status="statusLabel(detail.reviewStatus)" /></div><div class="finance-detail-actions"><el-button v-if="canEditSource && detail && selected && !isUpstreamSource(detail) && ['DRAFT','REJECTED'].includes(detail.reviewStatus)" @click="openMutation(selected, 'EDIT')"><Pencil :size="16" />编辑</el-button><el-button v-if="canEditSource && detail && selected && ['DRAFT','REJECTED'].includes(detail.reviewStatus)" @click="openMutation(selected, 'SUBMIT')"><Send :size="16" />提交审核</el-button><el-button v-if="canReviewSource && detail?.reviewStatus === 'PENDING' && selected" @click="openReview(selected)"><FileCheck2 :size="16" />审核</el-button></div></div></template>
|
||||
<template v-if="detail" #summary><dl class="density-detail-overview arap-metrics" aria-label="费用来源概览"><div class="arap-metric is-amount"><dt>结算金额</dt><dd>{{ money(detail.amount) }} <small>CNY</small></dd></div><div class="arap-metric"><dt>收付方向</dt><dd>{{ financeDirectionLabel(detail.direction) }}</dd></div><div class="arap-metric"><dt>来源状态</dt><dd>{{ sourceStatusDisplay(detail.sourceStatus) }}</dd></div><div class="arap-metric"><dt>审核状态</dt><dd>{{ statusLabel(detail.reviewStatus) }}</dd></div></dl></template>
|
||||
<LoadErrorState v-if="detailError" title="费用来源详情加载失败" :message="detailError.message" :loading="detailLoading" @retry="selected && loadDetail(selected)"><template #details><ApiErrorMeta :details="detailError" /></template></LoadErrorState>
|
||||
<template v-else-if="detail"><div class="arap-detail-grid"><FormSection class="arap-information density-form-section" title="单据信息" :bordered="false"><el-descriptions border :column="2" class="arap-detail density-descriptions"><el-descriptions-item label="客户">{{ customerName(detail.customerId, detail.customerName || selected?.customerName) }}</el-descriptions-item><el-descriptions-item label="费用项目">{{ displayFeeName(detail.feeItemName) }}</el-descriptions-item><el-descriptions-item label="来源类型">{{ sourceTypeDisplay(detail.sourceType) }}</el-descriptions-item><el-descriptions-item label="关联业务">{{ detail.inboundCode || detail.containerNo || detail.sourceBusinessId || '业务关联待补充' }}</el-descriptions-item><el-descriptions-item v-if="detail.direction === 'PAYABLE'" label="供应商">{{ detail.supplierName || '供应商待补充' }}</el-descriptions-item><el-descriptions-item label="业务日期">{{ formatBusinessDate(detail.businessDate) }}</el-descriptions-item><el-descriptions-item label="原币金额">{{ detail.originalCurrency }} {{ money(detail.originalAmount) }}</el-descriptions-item><el-descriptions-item label="折算汇率">{{ detail.exchangeRate }}<template v-if="detail.exchangeRateMonth">({{ detail.exchangeRateMonth }})</template></el-descriptions-item><el-descriptions-item v-if="detail.quantity != null" label="计费依据">{{ detail.quantity }} {{ detail.quantityUnit || '' }}<template v-if="detail.unitPrice != null"> × {{ detail.originalCurrency }} {{ detail.unitPrice }}</template></el-descriptions-item><el-descriptions-item v-if="detail.periodStart" label="计费期间">{{ detail.periodStart }} 至 {{ detail.periodEnd }}</el-descriptions-item></el-descriptions></FormSection><FormSection class="arap-settlement density-form-section" title="审核与结算" :bordered="false"><el-descriptions border :column="1" class="arap-detail density-descriptions"><el-descriptions-item label="费用状态">{{ sourceStatusDisplay(detail.sourceStatus) }}</el-descriptions-item><el-descriptions-item label="已生成对账单">{{ detail.statementGenerated ? '是' : '否' }}</el-descriptions-item><el-descriptions-item label="审核原因">{{ detail.reviewReason || '未填写' }}</el-descriptions-item></el-descriptions></FormSection></div><FormSection class="operation-log density-form-section" title="操作记录" :bordered="false"><DataTable :data="operationLogRows" :columns="operationLogColumns" row-key="rowKey" column-settings-mode="hide" empty-text="暂无操作记录"><template #occurredAt="{ row }">{{ formatDateTime(row.occurredAt) }}</template><template #action="{ row }">{{ financeOperationActionLabel(row.action) }}</template><template #operatorName="{ row }">{{ displayOperator(row.operatorName) }}</template><template #result="{ row }">{{ row.remark || financeOperationResultLabel(row.result) }}</template></DataTable></FormSection></template>
|
||||
<template v-else-if="detail"><div class="arap-detail-grid"><FormSection class="arap-information density-form-section" title="单据信息" :bordered="false"><el-descriptions border :column="2" class="arap-detail density-descriptions"><el-descriptions-item label="客户">{{ customerName(detail.customerId, detail.customerName || selected?.customerName) }}</el-descriptions-item><el-descriptions-item label="费用项目">{{ displayFeeName(detail.feeItemName) || '—' }}</el-descriptions-item><el-descriptions-item label="来源类型">{{ sourceTypeDisplay(detail.sourceType) }}</el-descriptions-item><el-descriptions-item label="关联业务">{{ detail.inboundCode || detail.containerNo || detail.sourceBusinessId || '业务关联待补充' }}</el-descriptions-item><el-descriptions-item v-if="detail.direction === 'PAYABLE'" label="供应商">{{ detail.supplierName || '供应商待补充' }}</el-descriptions-item><el-descriptions-item label="业务日期">{{ formatBusinessDate(detail.businessDate) }}</el-descriptions-item><el-descriptions-item label="原币金额">{{ detail.originalCurrency }} {{ money(detail.originalAmount) }}</el-descriptions-item><el-descriptions-item label="折算汇率">{{ detail.exchangeRate }}<template v-if="detail.exchangeRateMonth">({{ detail.exchangeRateMonth }})</template></el-descriptions-item><el-descriptions-item v-if="detail.quantity != null" label="计费依据">{{ detail.quantity }} {{ detail.quantityUnit || '' }}<template v-if="detail.unitPrice != null"> × {{ detail.originalCurrency }} {{ detail.unitPrice }}</template></el-descriptions-item><el-descriptions-item v-if="detail.periodStart" label="计费期间">{{ detail.periodStart }} 至 {{ detail.periodEnd }}</el-descriptions-item></el-descriptions></FormSection><FormSection class="arap-settlement density-form-section" title="审核与结算" :bordered="false"><el-descriptions border :column="1" class="arap-detail density-descriptions"><el-descriptions-item label="费用状态">{{ sourceStatusDisplay(detail.sourceStatus) }}</el-descriptions-item><el-descriptions-item label="已生成对账单">{{ detail.statementGenerated ? '是' : '否' }}</el-descriptions-item><el-descriptions-item label="审核原因">{{ detail.reviewReason || '未填写' }}</el-descriptions-item></el-descriptions></FormSection></div><FormSection class="operation-log density-form-section" title="操作记录" :bordered="false"><DataTable :data="operationLogRows" :columns="operationLogColumns" row-key="rowKey" column-settings-mode="hide" empty-text="暂无操作记录"><template #occurredAt="{ row }">{{ formatDateTime(row.occurredAt) }}</template><template #action="{ row }">{{ financeOperationActionLabel(row.action) }}</template><template #operatorName="{ row }">{{ displayOperator(row.operatorName) }}</template><template #result="{ row }">{{ row.remark || financeOperationResultLabel(row.result) }}</template></DataTable></FormSection></template>
|
||||
</DetailPageLayout>
|
||||
</section>
|
||||
</AdminPage>
|
||||
<AppDialog class="admin-density-dialog" v-model="reviewOpen" title="费用来源审核" confirm-text="提交审核" :confirm-loading="reviewSaving" @confirm="submitReview">
|
||||
<el-form class="density-form" label-position="top"><el-form-item label="审核结论"><el-segmented v-model="reviewForm.action" :options="[{ label: '通过', value: 'APPROVE' }, { label: '驳回', value: 'REJECT' }]" /></el-form-item><el-form-item :label="reviewForm.action === 'REJECT' ? '驳回原因' : '审核说明(可选)'"><el-input v-model="reviewForm.reason" type="textarea" :rows="3" maxlength="500" :placeholder="reviewForm.action === 'REJECT' ? '请填写驳回原因' : '请输入审核说明(可选)'" show-word-limit /></el-form-item></el-form>
|
||||
<AppDialog class="admin-density-dialog" v-model="reviewOpen" :title="`费用来源审核 · ${selected?.documentNo || '费用来源'}`" fullscreenable confirm-text="提交审核" :confirm-loading="reviewSaving" @confirm="submitReview">
|
||||
<div class="density-dialog-sections">
|
||||
<section v-if="detail" class="density-dialog-section" data-tone="source" aria-label="费用来源资料">
|
||||
<h3 class="density-dialog-section__title">费用来源</h3>
|
||||
<table class="density-table fee-dialog-facts"><tbody>
|
||||
<tr><th scope="row">客户</th><td colspan="3">{{ customerName(detail.customerId, detail.customerName || selected?.customerName) }}</td></tr>
|
||||
<tr><th scope="row">费用项目</th><td>{{ displayFeeName(detail.feeItemName) || '—' }}</td><th scope="row">金额(CNY)</th><td>{{ money(detail.amount) }}</td></tr>
|
||||
<tr><th scope="row">关联业务</th><td colspan="3">{{ businessReference(detail) }}</td></tr>
|
||||
<tr><th scope="row">收付方向</th><td>{{ financeDirectionLabel(detail.direction) }}</td><th scope="row">审核状态</th><td>{{ statusLabel(detail.reviewStatus) }}</td></tr>
|
||||
</tbody></table>
|
||||
</section>
|
||||
<section class="density-dialog-section" data-tone="work" aria-label="费用审核登记"><h3 class="density-dialog-section__title">审核登记</h3>
|
||||
<el-form class="density-form" label-position="left" label-width="110px" :disabled="reviewSaving"><table class="density-table density-table--editable"><tbody>
|
||||
<tr><td><el-form-item label="审核结论"><el-segmented v-model="reviewForm.action" :options="[{ label: '通过', value: 'APPROVE' }, { label: '驳回', value: 'REJECT' }]" /></el-form-item></td></tr>
|
||||
<tr><td><el-form-item :label="reviewForm.action === 'REJECT' ? '驳回原因' : '审核说明(可选)'" :required="reviewForm.action === 'REJECT'"><el-input v-model="reviewForm.reason" type="textarea" :rows="3" maxlength="500" :placeholder="reviewForm.action === 'REJECT' ? '请填写驳回原因' : '请输入审核说明(可选)'" show-word-limit /></el-form-item></td></tr>
|
||||
</tbody></table></el-form>
|
||||
</section>
|
||||
</div>
|
||||
</AppDialog>
|
||||
<AppDialog class="admin-density-dialog" v-model="mutationOpen" :title="mutationTitle" :confirm-text="mutationMode === 'VOID' ? '确认作废' : '确认'" :confirm-loading="mutationSaving" @confirm="submitMutation">
|
||||
<el-form class="density-form" label-position="top"><el-form-item v-if="mutationMode === 'EDIT' || mutationMode === 'ADJUST'" label="金额(CNY)"><el-input-number v-model="mutationForm.amount" :min="0.01" :precision="2" :controls="false" style="width:100%" placeholder="请输入调整金额" /></el-form-item><el-form-item label="操作原因"><el-input v-model="mutationForm.reason" type="textarea" :rows="3" maxlength="500" placeholder="请填写操作原因" show-word-limit /></el-form-item></el-form>
|
||||
<AppDialog class="admin-density-dialog" v-model="mutationOpen" :title="`${mutationTitle} · ${selected?.documentNo || '费用来源'}`" fullscreenable :confirm-type="mutationMode === 'VOID' ? 'danger' : 'primary'" :confirm-text="mutationMode === 'VOID' ? '确认作废' : '确认'" :confirm-loading="mutationSaving" @confirm="submitMutation">
|
||||
<div class="density-dialog-sections">
|
||||
<section v-if="detail" class="density-dialog-section" data-tone="source" aria-label="费用来源资料">
|
||||
<h3 class="density-dialog-section__title">费用来源</h3>
|
||||
<table class="density-table fee-dialog-facts"><tbody>
|
||||
<tr><th scope="row">客户</th><td colspan="3">{{ customerName(detail.customerId, detail.customerName || selected?.customerName) }}</td></tr>
|
||||
<tr><th scope="row">费用项目</th><td>{{ displayFeeName(detail.feeItemName) || '—' }}</td><th scope="row">金额(CNY)</th><td>{{ money(detail.amount) }}</td></tr>
|
||||
<tr><th scope="row">关联业务</th><td colspan="3">{{ businessReference(detail) }}</td></tr>
|
||||
<tr><th scope="row">收付方向</th><td>{{ financeDirectionLabel(detail.direction) }}</td><th scope="row">审核状态</th><td>{{ statusLabel(detail.reviewStatus) }}</td></tr>
|
||||
</tbody></table>
|
||||
</section>
|
||||
<section class="density-dialog-section" data-tone="work" aria-label="费用操作登记"><h3 class="density-dialog-section__title">{{ mutationTitle }}</h3>
|
||||
<el-form class="density-form" label-position="left" label-width="110px" :disabled="mutationSaving"><table class="density-table density-table--editable"><tbody>
|
||||
<tr v-if="mutationMode === 'EDIT' || mutationMode === 'ADJUST'"><td><el-form-item label="金额(CNY)" required><el-input-number v-model="mutationForm.amount" :min="0.01" :precision="2" :controls="false" placeholder="请输入调整金额" /></el-form-item></td></tr>
|
||||
<tr><td><el-form-item label="操作原因" required><el-input v-model="mutationForm.reason" type="textarea" :rows="3" maxlength="500" placeholder="请填写操作原因" show-word-limit /></el-form-item></td></tr>
|
||||
</tbody></table></el-form>
|
||||
</section>
|
||||
</div>
|
||||
</AppDialog>
|
||||
</AdminPage>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.fee-dialog-facts { table-layout: fixed; }
|
||||
.fee-dialog-facts th { width: var(--admin-label-width); }
|
||||
:deep(.danger-menu-item:not(.is-disabled)) { color: var(--el-color-danger); }
|
||||
.finance-arap-page {
|
||||
min-width: 0;
|
||||
|
||||
Reference in New Issue
Block a user