备货单 二手车添加vin 调整备货单显示 文件预览问题处理

This commit is contained in:
浅念
2025-11-11 17:27:07 +08:00
parent 963a95732b
commit 7638eaf80f
11 changed files with 103 additions and 43 deletions
+21 -10
View File
@@ -69,10 +69,11 @@
<ElTableColumn label="编号" width="60" align="center"> <ElTableColumn label="编号" width="60" align="center">
<template #default="scope">{{ scope.$index + 1 }}</template> <template #default="scope">{{ scope.$index + 1 }}</template>
</ElTableColumn> </ElTableColumn>
<ElTableColumn label="车型" min-width="160"> <ElTableColumn label="车型" min-width="160" align="center">
<template #default="scope"> <template #default="scope">
{{ scope.row.model_snapshot || scope.row.model || '—' }} <div>{{ scope.row.model_snapshot || scope.row.model || '—' }}</div>
<span v-if="scope.row.mileage > 0">({{ scope.row.mileage }}km)</span> <div v-if="scope.row.mileage > 0">里程:{{ scope.row.mileage }}km</div>
<div v-if="scope.row.vin && scope.row.vin != ''">VIN: {{ scope.row.vin }}</div>
</template> </template>
</ElTableColumn> </ElTableColumn>
<ElTableColumn label="数量/台" width="90" align="center"> <ElTableColumn label="数量/台" width="90" align="center">
@@ -287,12 +288,16 @@
orderData.declarant_name || orderData.declarant || '—' orderData.declarant_name || orderData.declarant || '—'
}}</span> }}</span>
</td> </td>
<td> <td v-if="orderData.is_final == 0">
<span class="info-label"> 预计发运日期:</span> <span class="info-label"> 预计发运日期:</span>
<span class="info-value">{{ <span class="info-value">{{
orderData.eta_ship_date || orderData.etaShipDate || '—' orderData.eta_ship_date || orderData.etaShipDate || '—'
}}</span> }}</span>
</td> </td>
<td v-else>
<span class="info-label"> 全款收齐日:</span>
<span class="info-value">{{ orderData.collect_all_date || '—' }}</span>
</td>
<td> <td>
<span class="info-label"> 出运方式:</span> <span class="info-label"> 出运方式:</span>
<span class="info-value">{{ <span class="info-value">{{
@@ -306,19 +311,25 @@
}}</span> }}</span>
</td> </td>
<td> <td>
<span class="info-label"> 贸易条款/清关目的港:</span> <span class="info-label"> 贸易条款:</span>
<span class="info-value" <span class="info-value">{{
>{{ orderData.trade_term_snapshot || orderData.tradeTerms || '—' }}/{{ orderData.trade_term_snapshot || orderData.tradeTerms || '—'
orderData.clearance_port_snapshot || '—' }}</span>
}}</span
>
</td> </td>
<td> <td>
<span class="info-label"> 清关目的港:</span>
<span class="info-value">{{ orderData.clearance_port_snapshot || '—' }}</span>
</td>
<td v-if="orderData.is_final == 0">
<span class="info-label"> 最迟到港时间:</span> <span class="info-label"> 最迟到港时间:</span>
<span class="info-value">{{ <span class="info-value">{{
orderData.latest_arrival_date || orderData.latestArrival || '—' orderData.latest_arrival_date || orderData.latestArrival || '—'
}}</span> }}</span>
</td> </td>
<td v-else>
<span class="info-label"> 提车日期:</span>
<span class="info-value">{{ orderData.pick_up_date || '—' }}</span>
</td>
</tr> </tr>
</table> </table>
</div> </div>
+60 -22
View File
@@ -49,23 +49,34 @@
<template v-else> <template v-else>
<!-- IMAGE --> <!-- IMAGE -->
<div v-if="fileType === 'image'" class="viewer-wrap"> <div v-if="fileType === 'image'" class="viewer-wrap" :key="`image-${currentFile.url}`">
<div class="viewer" :style="viewerStyle"> <div class="viewer" :style="viewerStyle">
<img :src="currentFile.url" @error="onError" @load="onLoadImage" /> <img
:src="currentFile.url"
:key="currentFile.url"
@error="onError"
@load="onLoadImage"
/>
</div> </div>
</div> </div>
<!-- PDF --> <!-- PDF -->
<div v-else-if="fileType === 'pdf'" class="viewer-wrap"> <div v-else-if="fileType === 'pdf'" class="viewer-wrap" :key="`pdf-${currentFile.url}`">
<div class="viewer" :style="viewerStyle"> <div class="viewer" :style="viewerStyle">
<!-- 使用 object / iframe 作为预览,支持大多数现代浏览器 --> <!-- 使用 object / iframe 作为预览,支持大多数现代浏览器 -->
<object <object
:key="`pdf-obj-${currentFile.url}`"
:data="appendPdfParams(currentFile.url)" :data="appendPdfParams(currentFile.url)"
type="application/pdf" type="application/pdf"
width="100%" width="100%"
height="100%" height="100%"
> >
<iframe :src="appendPdfParams(currentFile.url)" width="100%" height="100%"></iframe> <iframe
:key="`pdf-iframe-${currentFile.url}`"
:src="appendPdfParams(currentFile.url)"
width="100%"
height="100%"
></iframe>
<div class="fallback" <div class="fallback"
>无法在浏览器内预览 PDF。<a :href="currentFile.url" target="_blank" >无法在浏览器内预览 PDF。<a :href="currentFile.url" target="_blank"
>点击打开</a >点击打开</a
@@ -76,10 +87,15 @@
</div> </div>
<!-- OFFICE (Word, Excel, PPT) 使用微软 Office 在线查看器,仅当文件对外可访问时有效 --> <!-- OFFICE (Word, Excel, PPT) 使用微软 Office 在线查看器,仅当文件对外可访问时有效 -->
<div v-else-if="fileType === 'office'" class="viewer-wrap"> <div
v-else-if="fileType === 'office'"
class="viewer-wrap"
:key="`office-${currentFile.url}`"
>
<div class="viewer" :style="viewerStyle"> <div class="viewer" :style="viewerStyle">
<template v-if="isHttpUrl(currentFile.url)"> <template v-if="isHttpUrl(currentFile.url)">
<iframe <iframe
:key="`office-iframe-${currentFile.url}`"
:src="officeViewerUrl(currentFile.url)" :src="officeViewerUrl(currentFile.url)"
width="100%" width="100%"
height="100%" height="100%"
@@ -99,7 +115,7 @@
</div> </div>
<!-- 文本 / 代码 --> <!-- 文本 / 代码 -->
<div v-else-if="fileType === 'text'" class="viewer-wrap"> <div v-else-if="fileType === 'text'" class="viewer-wrap" :key="`text-${currentFile.url}`">
<div class="viewer text-viewer" :style="viewerStyle"> <div class="viewer text-viewer" :style="viewerStyle">
<pre v-if="textContent !== null">{{ textContent }}</pre> <pre v-if="textContent !== null">{{ textContent }}</pre>
<div v-else class="loading">正在加载文本内容...</div> <div v-else class="loading">正在加载文本内容...</div>
@@ -108,7 +124,7 @@
</div> </div>
<!-- 未知 --> <!-- 未知 -->
<div v-else class="viewer-wrap unknown-viewer"> <div v-else class="viewer-wrap unknown-viewer" :key="`unknown-${currentFile.url}`">
<div class="viewer" :style="viewerStyle"> <div class="viewer" :style="viewerStyle">
<div class="unknown"> <div class="unknown">
<p>无法在线预览此类型文件。</p> <p>无法在线预览此类型文件。</p>
@@ -159,6 +175,25 @@
const textContent = ref<string | null>(null) const textContent = ref<string | null>(null)
const textError = ref<string | null>(null) const textError = ref<string | null>(null)
// --- Computed ---
const currentFile = computed((): FileItem | null => {
if (props.files && props.files.length > 0) {
const idx = Math.min(Math.max(0, currentIndex.value), props.files.length - 1)
return props.files[idx]
}
return props.file ?? null
})
function resetViewState(clearText = true) {
zoom.value = 1
rotate.value = 0
if (clearText) {
textContent.value = null
textError.value = null
}
}
// --- Watchers ---
watch( watch(
() => props.modelValue, () => props.modelValue,
(v) => (visibleLocal.value = v) (v) => (visibleLocal.value = v)
@@ -188,31 +223,27 @@
loadTextIfNeeded() loadTextIfNeeded()
}) })
function resetViewState(clearText = true) { // 监听当前文件变化,确保文件切换时正确更新
zoom.value = 1 watch(
rotate.value = 0 () => currentFile.value?.url,
if (clearText) { (newUrl, oldUrl) => {
textContent.value = null if (newUrl !== oldUrl && newUrl) {
textError.value = null resetViewState()
loadTextIfNeeded()
}
} }
} )
const currentFile = computed((): FileItem | null => {
if (props.files && props.files.length > 0) {
const idx = Math.min(Math.max(0, currentIndex.value), props.files.length - 1)
return props.files[idx]
}
return props.file ?? null
})
const hasNext = computed( const hasNext = computed(
() => !!(props.files && currentIndex.value < (props.files?.length ?? 0) - 1) () => !!(props.files && currentIndex.value < (props.files?.length ?? 0) - 1)
) )
const hasPrev = computed(() => !!(props.files && currentIndex.value > 0)) const hasPrev = computed(() => !!(props.files && currentIndex.value > 0))
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function prevFile() { function prevFile() {
if (hasPrev.value) currentIndex.value -= 1 if (hasPrev.value) currentIndex.value -= 1
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function nextFile() { function nextFile() {
if (hasNext.value) currentIndex.value += 1 if (hasNext.value) currentIndex.value += 1
} }
@@ -292,23 +323,29 @@
} as Record<string, string> } as Record<string, string>
}) })
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function zoomIn() { function zoomIn() {
zoom.value = Math.min(zoom.value + 0.25, 4) zoom.value = Math.min(zoom.value + 0.25, 4)
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function zoomOut() { function zoomOut() {
zoom.value = Math.max(zoom.value - 0.25, 0.25) zoom.value = Math.max(zoom.value - 0.25, 0.25)
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function resetZoom() { function resetZoom() {
zoom.value = 1 zoom.value = 1
rotate.value = 0 rotate.value = 0
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function rotateLeft() { function rotateLeft() {
rotate.value = (rotate.value - 90) % 360 rotate.value = (rotate.value - 90) % 360
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function rotateRight() { function rotateRight() {
rotate.value = (rotate.value + 90) % 360 rotate.value = (rotate.value + 90) % 360
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function toggleFullscreen() { function toggleFullscreen() {
isFullscreen.value = !isFullscreen.value isFullscreen.value = !isFullscreen.value
} }
@@ -339,6 +376,7 @@
// 可以在这里获取自然尺寸进行布局优化 // 可以在这里获取自然尺寸进行布局优化
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function downloadCurrent() { function downloadCurrent() {
if (!currentFile.value) return if (!currentFile.value) return
// 打开下载链接(浏览器通常会下载) // 打开下载链接(浏览器通常会下载)
@@ -83,7 +83,7 @@
width="900px" width="900px"
class="purchase-dialog" class="purchase-dialog"
> >
<ElForm ref="formRef" :model="poForm" :rules="poRules" label-width="120px" class="form"> <ElForm ref="formRef" :model="poForm" :rules="poRules" label-width="90px" class="form">
<ElFormItem label="PI号" prop="pi_no"> <ElFormItem label="PI号" prop="pi_no">
<ElSelect v-model="poForm.pi_no" placeholder="请选择PI号" style="width: 100%"> <ElSelect v-model="poForm.pi_no" placeholder="请选择PI号" style="width: 100%">
<ElOption <ElOption
@@ -143,7 +143,7 @@
type="primary" type="primary"
@click="openVehiclePicker(gIdx)" @click="openVehiclePicker(gIdx)"
:disabled="!group.id" :disabled="!group.id"
>车辆</ElButton >修改</ElButton
> >
</template> </template>
<template v-else> <template v-else>
@@ -256,10 +256,10 @@
@selection-change="onVehicleSelectionChange" @selection-change="onVehicleSelectionChange"
style="width: 100%" style="width: 100%"
> >
<el-table-column type="selection" width="48" />
<el-table-column label="车辆" prop="model_snapshot" min-width="160" /> <el-table-column label="车辆" prop="model_snapshot" min-width="160" />
<el-table-column label="内饰" prop="color_exterior_snapshot" /> <el-table-column label="内饰" prop="color_exterior_snapshot" />
<el-table-column label="外饰" prop="color_interior_snapshot" /> <el-table-column label="外饰" prop="color_interior_snapshot" />
<el-table-column type="selection" width="48" />
</el-table> </el-table>
<template #footer> <template #footer>
<ElButton @click="vehiclePicker.visible = false">取消</ElButton> <ElButton @click="vehiclePicker.visible = false">取消</ElButton>
+1 -1
View File
@@ -375,7 +375,7 @@
// 获取订单详情成功 // 获取订单详情成功
const orderData: OrderData = res const orderData: OrderData = res
orderDialog.orderData = orderData orderDialog.orderData = orderData
orderDialog.title = '合塑实业-汽车事业部-备货单(客户下定)' orderDialog.title = '合塑实业-汽车事业部-备货单(终版)'
orderDialog.visible = true orderDialog.visible = true
} }
// router.push({ // router.push({
@@ -359,7 +359,7 @@
// 获取订单详情成功 // 获取订单详情成功
const orderData: OrderData = res const orderData: OrderData = res
orderDialog.orderData = orderData orderDialog.orderData = orderData
orderDialog.title = '合塑实业-汽车事业部-备货单(客户下定)' orderDialog.title = '合塑实业-汽车事业部-备货单(终版)'
orderDialog.visible = true orderDialog.visible = true
} }
} }
+8 -2
View File
@@ -523,8 +523,8 @@
</ElCol> </ElCol>
<ElCol :sm="12" :md="12" :lg="6" :xl="4"> <ElCol :sm="12" :md="12" :lg="6" :xl="4">
<ElFormItem label="报关价" label-width="85px"> <ElFormItem label="报关价" label-width="85px">
<ElInput <ElInput
v-model="item.clearance_price" v-model="item.clearance_price"
placeholder="正在计算报关价" placeholder="正在计算报关价"
@input="handleUserEdit(idx)" @input="handleUserEdit(idx)"
> >
@@ -542,6 +542,11 @@
<ElInput v-model="item.clearance_price_currency_snapshot" type="hidden" /> <ElInput v-model="item.clearance_price_currency_snapshot" type="hidden" />
</ElFormItem> </ElFormItem>
</ElCol> </ElCol>
<ElCol :sm="12" :md="12" :lg="6" :xl="4" v-if="(item.mileage ?? 0) > 0">
<ElFormItem label="车架号" label-width="85px">
<ElInput v-model="item.vin" placeholder="请输入车架号"></ElInput>
</ElFormItem>
</ElCol>
</ElRow> </ElRow>
<ElRow :gutter="12" class="item-row-wrap"> <ElRow :gutter="12" class="item-row-wrap">
<ElCol :sm="24" :md="24" :lg="24" :xl="24"> <ElCol :sm="24" :md="24" :lg="24" :xl="24">
@@ -1375,6 +1380,7 @@
.row-actions { .row-actions {
margin-left: 8px; margin-left: 8px;
cursor: pointer;
} }
/* 利润为负数时,输入文字变红(兼容 Element Plus disabled 样式) */ /* 利润为负数时,输入文字变红(兼容 Element Plus disabled 样式) */
+1 -1
View File
@@ -1,7 +1,7 @@
<template> <template>
<div class="stocking-add-page"> <div class="stocking-add-page">
<div class="header boxshadow"> <div class="header boxshadow">
<div class="title">合塑实业·汽车事业部-备货单(客户下定)</div> <div class="title">合塑实业·汽车事业部-终版备货单</div>
<div class="subtitle">业务员:{{ getUserInfo.user.name }}</div> <div class="subtitle">业务员:{{ getUserInfo.user.name }}</div>
</div> </div>
<div class="boxshadow"> <div class="boxshadow">
+1 -1
View File
@@ -1,7 +1,7 @@
<template> <template>
<div class="stocking-add-page"> <div class="stocking-add-page">
<div class="header boxshadow"> <div class="header boxshadow">
<div class="title">合塑实业·汽车事业部-备货单(客户下定)</div> <div class="title">合塑实业·汽车事业部-终版备货单</div>
<div class="subtitle">业务员:{{ getUserInfo.user.name }}</div> <div class="subtitle">业务员:{{ getUserInfo.user.name }}</div>
</div> </div>
<div class="boxshadow"> <div class="boxshadow">
+1 -1
View File
@@ -349,7 +349,7 @@
// 获取订单详情成功 // 获取订单详情成功
const orderData: OrderData = res const orderData: OrderData = res
orderDialog.orderData = orderData orderDialog.orderData = orderData
orderDialog.title = '合塑实业-汽车事业部-备货单(客户下定)' orderDialog.title = '合塑实业-汽车事业部-备货单(终版)'
orderDialog.visible = true orderDialog.visible = true
} }
} }
@@ -564,6 +564,11 @@
<ElInput v-model="item.clearance_price_currency_snapshot" type="hidden" /> <ElInput v-model="item.clearance_price_currency_snapshot" type="hidden" />
</ElFormItem> </ElFormItem>
</ElCol> </ElCol>
<ElCol :sm="12" :md="12" :lg="6" :xl="4" v-if="(item.mileage ?? 0) > 0">
<ElFormItem label="车架号" label-width="85px">
<ElInput v-model="item.vin" placeholder="请输入车架号"></ElInput>
</ElFormItem>
</ElCol>
</ElRow> </ElRow>
<ElRow :gutter="12" class="item-row-wrap"> <ElRow :gutter="12" class="item-row-wrap">
<ElCol :sm="24" :md="24" :lg="24" :xl="24"> <ElCol :sm="24" :md="24" :lg="24" :xl="24">
+1 -1
View File
@@ -422,7 +422,7 @@
// 获取订单详情成功 // 获取订单详情成功
const orderData: OrderData = res const orderData: OrderData = res
orderDialog.orderData = orderData orderDialog.orderData = orderData
orderDialog.title = '合塑实业-汽车事业部-备货单(客户下定)' orderDialog.title = '合塑实业-汽车事业部-备货单(终版)'
orderDialog.visible = true orderDialog.visible = true
} }
} }