style(admin): unify dialog layouts and dense readonly presentation
This commit is contained in:
@@ -21,7 +21,7 @@ const submitExport = useExportTask()
|
||||
const access = useAccessPreviewStore()
|
||||
const rows = ref<OverseasWarehouseQuote[]>([]), total = ref(0), page = ref(1), pageSize = ref(20), loading = ref(false), saving = ref(false), exporting = ref(false)
|
||||
const error = ref<ApiErrorDetails | null>(null), options = ref<PartnerWarehouseOption[]>([]), detail = ref<OverseasWarehouseQuoteDetail | null>(null)
|
||||
const detailOpen = ref(false), editorOpen = ref(false), editingId = ref('')
|
||||
const detailOpen = ref(false), editorOpen = ref(false), editingId = ref(''), editingWarehouse = ref('')
|
||||
const filters = ref<QueryModel>({ keyword: '', warehouseId: '', providerName: '', currency: '', status: '' })
|
||||
const fields = ref<QueryField[]>([])
|
||||
function syncFields() { fields.value = [
|
||||
@@ -46,11 +46,11 @@ async function load(){ loading.value=true;error.value=null;try{const r=await lis
|
||||
async function loadOptions(){ try{options.value=await listQuoteWarehouseOptions();syncFields()}catch(e){ElMessage.error(masterDataErrorMessage(e,'合作仓候选加载失败'))} }
|
||||
function search(){ if(page.value===1) void load(); else page.value=1 }
|
||||
async function openDetail(row:OverseasWarehouseQuote){ try{detail.value=await getQuote(row.id);detailOpen.value=true}catch(e){ElMessage.error(masterDataErrorMessage(e,'报价详情加载失败'))} }
|
||||
function fill(d:OverseasWarehouseQuoteDetail){const s=d.summary;Object.assign(form,{name:s.name,warehouseId:s.warehouseId,providerName:s.providerName,currency:s.currency,effectiveStart:s.effectiveStart,effectiveEnd:s.effectiveEnd,versionCode:s.versionCode,remark:s.remark||'',recordVersion:s.recordVersion,warehouseFees:d.warehouseFees.map(v=>({...v})),transitPrices:d.transitPrices.map(v=>({...v}))})}
|
||||
function fill(d:OverseasWarehouseQuoteDetail){const s=d.summary;editingWarehouse.value=[s.warehouseName,s.warehouseCode].filter(Boolean).join(' · ')||'—';Object.assign(form,{name:s.name,warehouseId:s.warehouseId,providerName:s.providerName,currency:s.currency,effectiveStart:s.effectiveStart,effectiveEnd:s.effectiveEnd,versionCode:s.versionCode,remark:s.remark||'',recordVersion:s.recordVersion,warehouseFees:d.warehouseFees.map(v=>({...v})),transitPrices:d.transitPrices.map(v=>({...v}))})}
|
||||
async function openCreate(){editingId.value='';resetForm();if(!options.value.length)await loadOptions();editorOpen.value=true}
|
||||
async function openEdit(row:OverseasWarehouseQuote){try{const d=await getQuote(row.id);editingId.value=row.id;fill(d);editorOpen.value=true}catch(e){ElMessage.error(masterDataErrorMessage(e,'报价详情加载失败'))}}
|
||||
async function save(){if(!form.name||!form.warehouseId||!form.providerName||!form.effectiveStart||!form.effectiveEnd||!form.warehouseFees.length){ElMessage.warning('请完整填写报价必填信息');return} if(form.effectiveEnd<form.effectiveStart){ElMessage.warning('失效日期不能早于生效日期');return} saving.value=true;try{const common={name:form.name,providerName:form.providerName,currency:form.currency as 'USD'|'CNY',effectiveStart:form.effectiveStart,effectiveEnd:form.effectiveEnd,warehouseFees:form.warehouseFees,transitPrices:form.transitPrices,remark:form.remark||null};if(editingId.value)await updateQuote(editingId.value,{...common,recordVersion:form.recordVersion});else await createQuote({...common,warehouseId:form.warehouseId,versionCode:form.versionCode});ElMessage.success(editingId.value?'报价已更新':'报价已创建');editorOpen.value=false;await load()}catch(e){ElMessage.error(masterDataErrorMessage(e,'报价保存失败'))}finally{saving.value=false}}
|
||||
async function toggle(row:OverseasWarehouseQuote){const next:MasterDataStatus=row.status==='ACTIVE'?'INACTIVE':'ACTIVE';try{await ElMessageBox.confirm(`确认${next==='ACTIVE'?'启用':'停用'}“${row.name}”吗?`,'报价状态',{customClass:'admin-density-confirm',type:'warning'});await changeQuoteStatus(row.id,next,row.recordVersion);ElMessage.success('报价状态已更新');await load()}catch(e){if(e!=='cancel'&&e!=='close')ElMessage.error(masterDataErrorMessage(e,'报价状态更新失败'))}}
|
||||
async function toggle(row:OverseasWarehouseQuote){const next:MasterDataStatus=row.status==='ACTIVE'?'INACTIVE':'ACTIVE';try{await ElMessageBox.confirm(`确认${next==='ACTIVE'?'启用':'停用'}“${row.name}”吗?`,`${next==='ACTIVE'?'启用':'停用'}海外仓报价 · ${row.name.trim() || '—'}`,{customClass:'admin-density-confirm',type:'warning'});await changeQuoteStatus(row.id,next,row.recordVersion);ElMessage.success('报价状态已更新');await load()}catch(e){if(e!=='cancel'&&e!=='close')ElMessage.error(masterDataErrorMessage(e,'报价状态更新失败'))}}
|
||||
async function exportCsv(){exporting.value=true;try{const {page:_,size:__,...q}=params();await submitExport('OVERSEAS_QUOTE_LIST', '海外报价', q)}catch(e){ElMessage.error(masterDataErrorMessage(e,'报价导出失败'))}finally{exporting.value=false}}
|
||||
watch([page,pageSize],load);onMounted(()=>{void Promise.all([load(),loadOptions()])})
|
||||
</script>
|
||||
@@ -67,7 +67,58 @@ watch([page,pageSize],load);onMounted(()=>{void Promise.all([load(),loadOptions(
|
||||
<template #actions="{row}"><div class="density-actions row-actions admin-text-actions"><el-button data-tone="neutral" class="density-action" @click="openDetail(row as OverseasWarehouseQuote)">详情</el-button><el-button data-tone="neutral" class="density-action" v-if="access.can(permission.quoteEdit)" @click="openEdit(row as OverseasWarehouseQuote)">编辑</el-button><el-button class="density-action" v-if="access.can(permission.quoteStatus)" :data-tone="(row as OverseasWarehouseQuote).status==='ACTIVE'?'danger':'success'" @click="toggle(row as OverseasWarehouseQuote)">{{(row as OverseasWarehouseQuote).status==='ACTIVE'?'停用':'启用'}}</el-button></div></template>
|
||||
<template #status="{row}"><el-tag :type="(row as OverseasWarehouseQuote).status==='ACTIVE'?'success':'info'">{{(row as OverseasWarehouseQuote).status==='ACTIVE'?'启用':'停用'}}</el-tag></template>
|
||||
</DataTable></section>
|
||||
<AppDialog class="admin-density-dialog" v-model="detailOpen" title="海外仓报价详情" width="min(980px, calc(100vw - 28px))" :show-confirm="false"><dl v-if="detail" class="detail-grid density-fields"><div v-for="item in [['报价名称',detail.summary.name],['海外仓',detail.summary.warehouseName],['服务商',detail.summary.providerName],['币种',detail.summary.currency],['生效日期',detail.summary.effectiveStart],['失效日期',detail.summary.effectiveEnd],['版本',detail.summary.versionCode],['状态',detail.summary.status]]" :key="item[0]"><dt>{{item[0]}}</dt><dd>{{item[1]}}</dd></div></dl><h3>仓储作业费用</h3><el-table :data="detail?.warehouseFees||[]" border><el-table-column prop="item" label="费用项目"/><el-table-column prop="billingUnit" label="计费单位"/><el-table-column prop="unitPrice" label="单价"/><el-table-column prop="minimumCharge" label="最低收费"/><el-table-column prop="remark" label="备注"/></el-table><h3>中转派送价格</h3><el-table :data="detail?.transitPrices||[]" border><el-table-column prop="fbaWarehouseCode" label="目的FBA仓"/><el-table-column prop="deliveryMethod" label="车型/提货方式"/><el-table-column prop="estimatedMiles" label="预估迈数"/><el-table-column prop="price" label="报价"/><el-table-column prop="minimumCharge" label="最低收费"/></el-table></AppDialog>
|
||||
<AppDialog class="admin-density-dialog" v-model="editorOpen" :title="editingId?'编辑海外仓报价':'新增海外仓报价'" width="min(1180px, calc(100vw - 28px))" :confirm-loading="saving" confirm-text="保存报价" @confirm="save"><el-form class="density-form" label-position="top"><div class="form-grid"><el-form-item label="报价名称"><el-input v-model="form.name" placeholder="请输入报价名称" /></el-form-item><el-form-item label="海外仓"><el-select v-model="form.warehouseId" :disabled="!!editingId"><el-option v-for="o in options" :key="o.warehouseId" :label="`${o.warehouseName} · ${o.warehouseCode}`" :value="o.warehouseId"/></el-select></el-form-item><el-form-item label="服务商"><el-input v-model="form.providerName" placeholder="请输入服务商名称" /></el-form-item><el-form-item label="币种"><el-select v-model="form.currency"><el-option label="USD" value="USD"/><el-option label="CNY" value="CNY"/></el-select></el-form-item><el-form-item label="生效日期"><el-date-picker v-model="form.effectiveStart" type="date" value-format="YYYY-MM-DD"/></el-form-item><el-form-item label="失效日期"><el-date-picker v-model="form.effectiveEnd" type="date" value-format="YYYY-MM-DD"/></el-form-item><el-form-item label="报价版本"><el-input v-model="form.versionCode" :disabled="!!editingId" placeholder="请输入版本号" /></el-form-item><el-form-item label="备注"><el-input v-model="form.remark" placeholder="请输入备注(选填)" /></el-form-item></div><h3>仓储作业费用 <el-button @click="form.warehouseFees.push({item:'',billingUnit:'',unitPrice:0,minimumCharge:null,remark:null})">+ 添加费用</el-button></h3><div v-for="(f,i) in form.warehouseFees" :key="i" class="line-grid"><el-input v-model="f.item" placeholder="请输入费用项目"/><el-input v-model="f.billingUnit" placeholder="请输入计费单位"/><el-input-number v-model="f.unitPrice" :min="0" placeholder="请输入单价" /><el-input-number v-model="f.minimumCharge" :min="0" placeholder="请输入最低收费" /><el-button data-tone="danger" class="density-action" @click="form.warehouseFees.splice(i,1)">删除</el-button></div><h3>中转派送价格 <el-button @click="form.transitPrices.push({fbaWarehouseCode:'',deliveryMethod:'',estimatedMiles:null,price:0,minimumCharge:null,remark:null})">+ 添加派送价格</el-button></h3><div v-for="(t,i) in form.transitPrices" :key="i" class="line-grid"><el-input v-model="t.fbaWarehouseCode" placeholder="请输入目的 FBA 仓"/><el-input v-model="t.deliveryMethod" placeholder="请输入车型或提货方式"/><el-input-number v-model="t.price" :min="0" placeholder="请输入报价" /><el-input-number v-model="t.minimumCharge" :min="0" placeholder="请输入最低收费" /><el-button data-tone="danger" class="density-action" @click="form.transitPrices.splice(i,1)">删除</el-button></div></el-form></AppDialog>
|
||||
<AppDialog class="admin-density-dialog" v-model="detailOpen" :title="detail?.summary.name?.trim() ? `海外仓报价详情 · ${detail.summary.name.trim()}` : '海外仓报价详情'" width="min(980px, calc(100vw - 28px))" fullscreenable :show-confirm="false">
|
||||
<div v-if="detail" class="density-dialog-sections">
|
||||
<section class="density-dialog-section" data-tone="summary" aria-label="报价摘要">
|
||||
<h3 class="density-dialog-section__title">报价信息</h3>
|
||||
<dl class="detail-grid density-fields"><div v-for="item in [['报价名称',detail.summary.name],['海外仓',detail.summary.warehouseName],['服务商',detail.summary.providerName],['币种',detail.summary.currency],['生效日期',detail.summary.effectiveStart],['失效日期',detail.summary.effectiveEnd],['版本',detail.summary.versionCode],['状态',detail.summary.status === 'ACTIVE' ? '启用' : '停用']]" :key="item[0] || ''"><dt>{{item[0]}}</dt><dd>{{item[1] || '—'}}</dd></div></dl>
|
||||
</section>
|
||||
<section class="density-dialog-section" data-tone="source" aria-label="仓储作业费用">
|
||||
<h3 class="density-dialog-section__title">仓储作业费用</h3>
|
||||
<el-table :data="detail.warehouseFees" border empty-text="暂无仓储作业费用"><el-table-column prop="item" label="费用项目" min-width="150"/><el-table-column prop="billingUnit" label="计费单位" width="100"/><el-table-column prop="unitPrice" label="单价" min-width="100"/><el-table-column label="最低收费" min-width="100"><template #default="{row}">{{row.minimumCharge ?? '—'}}</template></el-table-column><el-table-column label="备注" min-width="150"><template #default="{row}">{{row.remark || '—'}}</template></el-table-column></el-table>
|
||||
</section>
|
||||
<section class="density-dialog-section" data-tone="source" aria-label="中转派送价格">
|
||||
<h3 class="density-dialog-section__title">中转派送价格</h3>
|
||||
<el-table :data="detail.transitPrices" border empty-text="暂无中转派送价格"><el-table-column prop="fbaWarehouseCode" label="目的FBA仓" min-width="120"/><el-table-column prop="deliveryMethod" label="车型/提货方式" min-width="160"/><el-table-column label="预估迈数" min-width="100"><template #default="{row}">{{row.estimatedMiles ?? '—'}}</template></el-table-column><el-table-column prop="price" label="报价" min-width="100"/><el-table-column label="最低收费" min-width="100"><template #default="{row}">{{row.minimumCharge ?? '—'}}</template></el-table-column></el-table>
|
||||
</section>
|
||||
</div>
|
||||
</AppDialog>
|
||||
<AppDialog class="admin-density-dialog" v-model="editorOpen" :title="editingId ? `编辑海外仓报价 · ${form.name.trim() || '—'}` : '新增海外仓报价'" width="min(1180px, calc(100vw - 28px))" fullscreenable :confirm-loading="saving" confirm-text="保存报价" @confirm="save">
|
||||
<el-form class="density-form density-dialog-sections" label-position="left" label-width="90px" :disabled="saving">
|
||||
<section class="density-dialog-section" data-tone="work" aria-label="报价基础信息">
|
||||
<h3 class="density-dialog-section__title">基础信息</h3>
|
||||
<table class="density-table density-table--editable quote-basics-table"><tbody>
|
||||
<tr><td><el-form-item label="报价名称"><el-input v-model="form.name" placeholder="请输入报价名称" /></el-form-item></td><td><el-form-item label="海外仓"><span v-if="editingId">{{ editingWarehouse }}</span><el-select v-else v-model="form.warehouseId"><el-option v-for="o in options" :key="o.warehouseId" :label="`${o.warehouseName} · ${o.warehouseCode}`" :value="o.warehouseId"/></el-select></el-form-item></td></tr>
|
||||
<tr><td><el-form-item label="服务商"><el-input v-model="form.providerName" placeholder="请输入服务商名称" /></el-form-item></td><td><el-form-item label="币种"><el-select v-model="form.currency"><el-option label="USD" value="USD"/><el-option label="CNY" value="CNY"/></el-select></el-form-item></td></tr>
|
||||
<tr><td><el-form-item label="生效日期"><el-date-picker v-model="form.effectiveStart" type="date" value-format="YYYY-MM-DD"/></el-form-item></td><td><el-form-item label="失效日期"><el-date-picker v-model="form.effectiveEnd" type="date" value-format="YYYY-MM-DD"/></el-form-item></td></tr>
|
||||
<tr><td><el-form-item label="报价版本"><span v-if="editingId">{{form.versionCode || '—'}}</span><el-input v-else v-model="form.versionCode" placeholder="请输入版本号" /></el-form-item></td><td><el-form-item label="备注"><el-input v-model="form.remark" placeholder="请输入备注(选填)" /></el-form-item></td></tr>
|
||||
</tbody></table>
|
||||
</section>
|
||||
<section class="density-dialog-section" data-tone="work" aria-label="编辑仓储作业费用">
|
||||
<h3 class="density-dialog-section__title quote-section-heading">仓储作业费用 <el-button @click="form.warehouseFees.push({item:'',billingUnit:'',unitPrice:0,minimumCharge:null,remark:null})">+ 添加费用</el-button></h3>
|
||||
<div class="quote-lines-scroll"><table class="density-table density-table--editable quote-lines-table"><thead><tr><th scope="col">操作</th><th scope="col">费用项目</th><th scope="col">计费单位</th><th scope="col">单价</th><th scope="col">最低收费</th></tr></thead><tbody>
|
||||
<tr v-for="(f,i) in form.warehouseFees" :key="i"><td><el-button data-tone="danger" class="density-action" :aria-label="`删除第${i+1}项费用`" @click="form.warehouseFees.splice(i,1)">删除</el-button></td><td><el-input v-model="f.item" :aria-label="`第${i+1}项费用项目`" placeholder="请输入费用项目"/></td><td><el-input v-model="f.billingUnit" :aria-label="`第${i+1}项计费单位`" placeholder="请输入计费单位"/></td><td><el-input-number v-model="f.unitPrice" :aria-label="`第${i+1}项费用单价`" :min="0" placeholder="请输入单价" /></td><td><el-input-number v-model="f.minimumCharge" :aria-label="`第${i+1}项费用最低收费`" :min="0" placeholder="请输入最低收费" /></td></tr>
|
||||
<tr v-if="!form.warehouseFees.length"><td colspan="5">暂无仓储作业费用</td></tr>
|
||||
</tbody></table></div>
|
||||
</section>
|
||||
<section class="density-dialog-section" data-tone="work" aria-label="编辑中转派送价格">
|
||||
<h3 class="density-dialog-section__title quote-section-heading">中转派送价格 <el-button @click="form.transitPrices.push({fbaWarehouseCode:'',deliveryMethod:'',estimatedMiles:null,price:0,minimumCharge:null,remark:null})">+ 添加派送价格</el-button></h3>
|
||||
<div class="quote-lines-scroll"><table class="density-table density-table--editable quote-lines-table"><thead><tr><th scope="col">操作</th><th scope="col">目的FBA仓</th><th scope="col">车型/提货方式</th><th scope="col">报价</th><th scope="col">最低收费</th></tr></thead><tbody>
|
||||
<tr v-for="(t,i) in form.transitPrices" :key="i"><td><el-button data-tone="danger" class="density-action" :aria-label="`删除第${i+1}项派送价格`" @click="form.transitPrices.splice(i,1)">删除</el-button></td><td><el-input v-model="t.fbaWarehouseCode" :aria-label="`第${i+1}项目的FBA仓`" placeholder="请输入目的 FBA 仓"/></td><td><el-input v-model="t.deliveryMethod" :aria-label="`第${i+1}项车型或提货方式`" placeholder="请输入车型或提货方式"/></td><td><el-input-number v-model="t.price" :aria-label="`第${i+1}项派送报价`" :min="0" placeholder="请输入报价" /></td><td><el-input-number v-model="t.minimumCharge" :aria-label="`第${i+1}项派送最低收费`" :min="0" placeholder="请输入最低收费" /></td></tr>
|
||||
<tr v-if="!form.transitPrices.length"><td colspan="5">暂无中转派送价格</td></tr>
|
||||
</tbody></table></div>
|
||||
</section>
|
||||
</el-form>
|
||||
</AppDialog>
|
||||
</ListPageLayout></AdminPage></template>
|
||||
<style scoped>.detail-grid.density-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }.table-panel{min-width:0;overflow:hidden}.form-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--admin-space-5) var(--admin-space-6)}.line-grid{display:grid;grid-template-columns:2fr 1.2fr 1fr 1fr auto;gap:var(--admin-space-3);margin:var(--admin-space-3) 0}h3{margin:var(--admin-space-6) 0 var(--admin-space-4);font-size:var(--admin-font-body)}</style>
|
||||
<style scoped>
|
||||
.detail-grid.density-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.quote-basics-table { table-layout: fixed; }
|
||||
.quote-basics-table td { width: 50%; }
|
||||
.quote-section-heading { justify-content: space-between; }
|
||||
.quote-lines-scroll { overflow-x: auto; }
|
||||
.quote-lines-table { table-layout: fixed; min-width: 760px; }
|
||||
.quote-lines-table th:first-child { width: 70px; }
|
||||
.quote-lines-table th:nth-child(2) { width: 25%; }
|
||||
@media (max-width: 600px) { .quote-basics-table tr { display: grid; } .quote-basics-table td { width: auto; } }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user