10.17沟通调整
计划收款信息增加复制操作 上传合同调整为:上传合同、上传PI、上传水单(均为必传,且支持多文件操作与下载)
This commit is contained in:
@@ -0,0 +1,274 @@
|
|||||||
|
<template>
|
||||||
|
<div class="multi-file-upload">
|
||||||
|
<!-- 上传按钮 -->
|
||||||
|
<el-upload
|
||||||
|
class="upload-box"
|
||||||
|
:action="actionImageUplode"
|
||||||
|
:headers="uploadHeaders"
|
||||||
|
:show-file-list="false"
|
||||||
|
:on-success="handleUpload"
|
||||||
|
:before-upload="beforeUpload"
|
||||||
|
multiple
|
||||||
|
:accept="accept"
|
||||||
|
>
|
||||||
|
<div class="upload-trigger">
|
||||||
|
<img class="upload-icon" :src="iconSrc" />
|
||||||
|
<div class="upload-text">
|
||||||
|
<span>{{ uploadText }}</span>
|
||||||
|
<span v-if="showHint" class="upload-hint">{{ hintText }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-upload>
|
||||||
|
|
||||||
|
<!-- 文件列表显示 -->
|
||||||
|
<div v-if="fileList.length > 0" class="files-list">
|
||||||
|
<div v-for="(file, index) in fileList" :key="index" class="file-item">
|
||||||
|
<div class="file-info">
|
||||||
|
<img v-if="isImageFile(file)" :src="file.url" class="file-preview-image" />
|
||||||
|
<div v-else class="file-icon">
|
||||||
|
<i class="el-icon-document"></i>
|
||||||
|
</div>
|
||||||
|
<span class="file-name">{{ file.name }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="file-actions">
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
@click="downloadFile(file)"
|
||||||
|
icon="el-icon-download"
|
||||||
|
>
|
||||||
|
下载
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
@click="removeFile(index)"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
style="color: #f56c6c"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="MultiFileUpload">
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { useUploadHeaders } from '@/composables/useUploadHeaders'
|
||||||
|
const actionImageUplode = `${import.meta.env.VITE_API_URL}/ticket/upload?scene=stock_orders`
|
||||||
|
const { uploadHeaders } = useUploadHeaders()
|
||||||
|
interface FileItem {
|
||||||
|
name: string
|
||||||
|
url: string
|
||||||
|
file_name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
modelValue: FileItem[]
|
||||||
|
uploadText?: string
|
||||||
|
hintText?: string
|
||||||
|
showHint?: boolean
|
||||||
|
iconSrc?: string
|
||||||
|
accept?: string
|
||||||
|
maxSize?: number // MB
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'update:modelValue', value: FileItem[]): void
|
||||||
|
(e: 'change', value: FileItem[]): void
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
uploadText: '点击上传文件',
|
||||||
|
hintText: '支持多个文件上传',
|
||||||
|
showHint: true,
|
||||||
|
iconSrc: '/src/assets/img/crm/contract.png',
|
||||||
|
accept: '.jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt',
|
||||||
|
maxSize: 10
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>()
|
||||||
|
|
||||||
|
const fileList = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set: (value) => {
|
||||||
|
emit('update:modelValue', value)
|
||||||
|
emit('change', value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const isImageFile = (file: FileItem) => {
|
||||||
|
const stripQuery = (s?: string) => (s ? s.split('?')[0] : '')
|
||||||
|
const byExt = (s?: string) => /\.(jpg|jpeg|png|gif|webp|bmp|svg)$/i.test(stripQuery(s || ''))
|
||||||
|
// Prefer extension checks on url, then file_name, then name
|
||||||
|
if (byExt(file.url)) return true
|
||||||
|
if (byExt(file.file_name)) return true
|
||||||
|
if (byExt(file.name)) return true
|
||||||
|
// Fallback: some backends may return mime in file_name like 'image/jpeg'
|
||||||
|
return (file.file_name || '').toLowerCase().startsWith('image/')
|
||||||
|
}
|
||||||
|
|
||||||
|
const beforeUpload = (file: File) => {
|
||||||
|
const isValidType = new RegExp(props.accept.replace(/\./g, '\\.').replace(/,/g, '|'), 'i').test(file.name)
|
||||||
|
if (!isValidType) {
|
||||||
|
ElMessage.error(`只能上传${props.accept}格式的文件!`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const isLtMaxSize = file.size / 1024 / 1024 < props.maxSize
|
||||||
|
if (!isLtMaxSize) {
|
||||||
|
ElMessage.error(`文件大小不能超过 ${props.maxSize}MB!`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleUpload = (response: any) => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
const fileInfo: FileItem = {
|
||||||
|
name: response.data.original_name || '文件',
|
||||||
|
url: response.data.file_url,
|
||||||
|
file_name: response.data.file_name
|
||||||
|
}
|
||||||
|
const newFileList = [...fileList.value, fileInfo]
|
||||||
|
fileList.value = newFileList
|
||||||
|
ElMessage.success('文件上传成功!')
|
||||||
|
} else {
|
||||||
|
ElMessage.error(response.message || '文件上传失败!')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeFile = (index: number) => {
|
||||||
|
const newFileList = [...fileList.value]
|
||||||
|
newFileList.splice(index, 1)
|
||||||
|
fileList.value = newFileList
|
||||||
|
ElMessage.success('文件已删除')
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadFile = (file: FileItem) => {
|
||||||
|
// 创建下载链接
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = file.url
|
||||||
|
link.download = file.name
|
||||||
|
link.target = '_blank'
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出组件
|
||||||
|
defineExpose({})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.multi-file-upload {
|
||||||
|
.upload-box {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-trigger {
|
||||||
|
width: 100%;
|
||||||
|
height: 120px;
|
||||||
|
// border: 2px dashed #d9d9d9;
|
||||||
|
// border-radius: 6px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s;
|
||||||
|
// background: #fafafa;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #409eff;
|
||||||
|
background: #f0f9ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-icon {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-text {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-hint {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文件列表样式
|
||||||
|
.files-list {
|
||||||
|
margin: 16px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 12px;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
background: #fafafa;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #f0f9ff;
|
||||||
|
border-color: #409eff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview-image {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-icon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background: #f5f7fa;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-right: 12px;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-name {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -24,7 +24,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
interface ApprovalRecordItem {
|
interface ApprovalRecordItem {
|
||||||
name?: string
|
name?: string
|
||||||
role?: string
|
role?: string
|
||||||
@@ -36,7 +38,15 @@
|
|||||||
comment?: string
|
comment?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProps<{ records: ApprovalRecordItem[] }>()
|
export default defineComponent({
|
||||||
|
name: 'ApprovalTimeline',
|
||||||
|
props: {
|
||||||
|
records: {
|
||||||
|
type: Array as () => ApprovalRecordItem[],
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -0,0 +1,311 @@
|
|||||||
|
<template>
|
||||||
|
<div class="file-preview-container">
|
||||||
|
<div class="form-title">
|
||||||
|
<span class="title">{{ title }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="file-preview">
|
||||||
|
<div v-if="files.length > 0" class="files-list">
|
||||||
|
<div v-for="(file, index) in files" :key="index" class="file-item">
|
||||||
|
<div v-if="isImageFile(file)" class="image-preview">
|
||||||
|
<img
|
||||||
|
:src="file.url"
|
||||||
|
:alt="file.name"
|
||||||
|
class="preview-image"
|
||||||
|
@click="previewImage(file)"
|
||||||
|
/>
|
||||||
|
<div class="file-info">
|
||||||
|
<span class="file-name">{{ file.name }}</span>
|
||||||
|
<div class="file-actions">
|
||||||
|
<!-- <el-button type="text" size="small" @click="previewImage(file)">预览</el-button> -->
|
||||||
|
<el-button type="primary" size="small" @click="downloadFile(file)">下载</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="document-preview">
|
||||||
|
<div class="file-icon">
|
||||||
|
<i class="iconfont-sys"></i>
|
||||||
|
</div>
|
||||||
|
<div class="file-info">
|
||||||
|
<span class="file-name">{{ file.name }}</span>
|
||||||
|
<el-button type="primary" size="small" @click="downloadFile(file)">下载</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="no-file">
|
||||||
|
<i class="iconfont-sys"></i>
|
||||||
|
<span>{{ emptyText }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
|
interface FileItem {
|
||||||
|
name: string
|
||||||
|
url: string
|
||||||
|
file_name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'FilePreview',
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
type: Array as () => FileItem[],
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
emptyText: {
|
||||||
|
type: String,
|
||||||
|
default: '暂无文件'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
// 判断是否为图片文件
|
||||||
|
const isImageFile = (file: FileItem) => {
|
||||||
|
// 检查文件名
|
||||||
|
if (file.name && /\.(jpg|jpeg|png|gif|webp|bmp|svg)$/i.test(file.name)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查file_name字段
|
||||||
|
if (file.file_name && file.file_name.startsWith('image/')) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查URL中的文件扩展名(去除查询参数)
|
||||||
|
if (file.url) {
|
||||||
|
const urlWithoutParams = file.url.split('?')[0] // 移除查询参数
|
||||||
|
if (/\.(jpg|jpeg|png|gif|webp|bmp|svg)$/i.test(urlWithoutParams)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预览图片
|
||||||
|
const previewImage = (file: FileItem) => {
|
||||||
|
// 创建图片预览弹窗
|
||||||
|
const imagePreview = document.createElement('div')
|
||||||
|
imagePreview.style.cssText = `
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 9999;
|
||||||
|
cursor: pointer;
|
||||||
|
`
|
||||||
|
|
||||||
|
const image = document.createElement('img')
|
||||||
|
image.src = file.url
|
||||||
|
image.alt = file.name
|
||||||
|
image.style.cssText = `
|
||||||
|
max-width: 90%;
|
||||||
|
max-height: 90%;
|
||||||
|
object-fit: contain;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
||||||
|
`
|
||||||
|
|
||||||
|
const closeBtn = document.createElement('div')
|
||||||
|
closeBtn.innerHTML = '×'
|
||||||
|
closeBtn.style.cssText = `
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: 30px;
|
||||||
|
color: white;
|
||||||
|
font-size: 30px;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 10000;
|
||||||
|
`
|
||||||
|
imagePreview.appendChild(image)
|
||||||
|
imagePreview.appendChild(closeBtn)
|
||||||
|
document.body.appendChild(imagePreview)
|
||||||
|
// 点击关闭
|
||||||
|
const closePreview = () => {
|
||||||
|
document.body.removeChild(imagePreview)
|
||||||
|
}
|
||||||
|
imagePreview.addEventListener('click', closePreview)
|
||||||
|
closeBtn.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
closePreview()
|
||||||
|
})
|
||||||
|
// ESC键关闭
|
||||||
|
const handleKeydown = (e: KeyboardEvent) => {
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
closePreview()
|
||||||
|
document.removeEventListener('keydown', handleKeydown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.addEventListener('keydown', handleKeydown)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载文件
|
||||||
|
const downloadFile = async (file: FileItem) => {
|
||||||
|
try {
|
||||||
|
// 对所有文件类型都使用 fetch 下载,确保真正的下载
|
||||||
|
const response = await fetch(file.url, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
Accept: '*/*'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`下载失败: ${response.status} ${response.statusText}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const blob = await response.blob()
|
||||||
|
const url = window.URL.createObjectURL(blob)
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = url
|
||||||
|
link.download = file.name || file.file_name || 'download'
|
||||||
|
link.style.display = 'none'
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
window.URL.revokeObjectURL(url)
|
||||||
|
|
||||||
|
ElMessage.success('下载成功')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('下载失败:', error)
|
||||||
|
const errorMessage = error instanceof Error ? error.message : '未知错误'
|
||||||
|
ElMessage.error(`下载失败: ${errorMessage}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
isImageFile,
|
||||||
|
previewImage,
|
||||||
|
downloadFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.file-preview-container {
|
||||||
|
.form-title {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #222;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-file {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
color: #999;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-file i {
|
||||||
|
font-size: 48px;
|
||||||
|
color: #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.files-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-item {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-width: 200px;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 120px;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-preview {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image {
|
||||||
|
flex: 1;
|
||||||
|
max-height: 70px;
|
||||||
|
object-fit: cover;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.document-preview {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-icon {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-icon i {
|
||||||
|
font-size: 48px;
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info {
|
||||||
|
padding: 8px;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-name {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #606266;
|
||||||
|
text-align: center;
|
||||||
|
word-break: break-all;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -60,9 +60,9 @@
|
|||||||
<template #default>
|
<template #default>
|
||||||
<ElTableColumn type="expand" width="30">
|
<ElTableColumn type="expand" width="30">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div style="padding: 6px">
|
<div style="padding: 6px;display: flex">
|
||||||
<strong>备注:</strong>
|
<div><strong>备注:</strong></div>
|
||||||
<span>{{ scope.row.remark || '暂无备注' }}</span>
|
<div><span v-html="scope.row.remark || '暂无备注'"></span></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
@@ -78,14 +78,17 @@
|
|||||||
<ElTableColumn label="数量/台" width="90" align="center">
|
<ElTableColumn label="数量/台" width="90" align="center">
|
||||||
<template #default="scope">{{ scope.row.num ?? scope.row.quantity ?? 1 }}</template>
|
<template #default="scope">{{ scope.row.num ?? scope.row.quantity ?? 1 }}</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
<ElTableColumn label="颜色/外" align="center" prop="color_exterior_snapshot" />
|
<ElTableColumn label="颜色" min-width="120"align="center">
|
||||||
<ElTableColumn
|
<template #default="scope">
|
||||||
label="内饰"
|
<div>
|
||||||
min-width="120"
|
外饰:{{ scope.row.color_exterior_snapshot || '—' }}
|
||||||
align="center"
|
</div>
|
||||||
prop="color_interior_snapshot"
|
<div>
|
||||||
/>
|
内饰:{{ scope.row.color_interior_snapshot || '—' }}
|
||||||
<ElTableColumn label="改装" min-width="120" align="center" prop="modify" />
|
</div>
|
||||||
|
</template>
|
||||||
|
</ElTableColumn>
|
||||||
|
<!-- <ElTableColumn label="改装" min-width="120" align="center" prop="modify" /> -->
|
||||||
<ElTableColumn label="官方指导价/二手挂牌价" min-width="175" align="center">
|
<ElTableColumn label="官方指导价/二手挂牌价" min-width="175" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span v-if="scope.row.mileage > 0">
|
<span v-if="scope.row.mileage > 0">
|
||||||
@@ -142,6 +145,14 @@
|
|||||||
'—'
|
'—'
|
||||||
}}</template>
|
}}</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
|
<ElTableColumn label="配件费" min-width="120" align="center">
|
||||||
|
<template #default="scope">{{
|
||||||
|
scope.row.accessory_price?.currency_info ||
|
||||||
|
scope.row.accessory_price?.amount ||
|
||||||
|
scope.row.discount ||
|
||||||
|
'—'
|
||||||
|
}}</template>
|
||||||
|
</ElTableColumn>
|
||||||
<ElTableColumn label="FOB运费" min-width="120" align="center">
|
<ElTableColumn label="FOB运费" min-width="120" align="center">
|
||||||
<template #default="scope">{{
|
<template #default="scope">{{
|
||||||
scope.row.fob_transport_fee?.currency_info ||
|
scope.row.fob_transport_fee?.currency_info ||
|
||||||
@@ -174,6 +185,14 @@
|
|||||||
'—'
|
'—'
|
||||||
}}</template>
|
}}</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
|
<ElTableColumn label="挂账" min-width="120" align="center">
|
||||||
|
<template #default="scope">{{
|
||||||
|
scope.row.retention_price?.currency_info ||
|
||||||
|
scope.row.retention_price?.amount ||
|
||||||
|
scope.row.discount ||
|
||||||
|
'—'
|
||||||
|
}}</template>
|
||||||
|
</ElTableColumn>
|
||||||
<ElTableColumn label="购置税" min-width="120" align="center">
|
<ElTableColumn label="购置税" min-width="120" align="center">
|
||||||
<template #default="scope">{{
|
<template #default="scope">{{
|
||||||
scope.row.purchase_tax?.currency_info ||
|
scope.row.purchase_tax?.currency_info ||
|
||||||
@@ -186,11 +205,17 @@
|
|||||||
<template #default="scope">{{
|
<template #default="scope">{{
|
||||||
scope.row.tax_refund?.currency_info ||
|
scope.row.tax_refund?.currency_info ||
|
||||||
scope.row.tax_refund?.amount ||
|
scope.row.tax_refund?.amount ||
|
||||||
scope.row.discount ||
|
|
||||||
'—'
|
'—'
|
||||||
}}</template>
|
}}</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
<ElTableColumn label="单价" min-width="120" align="center">
|
<ElTableColumn label="车价" min-width="120" align="center">
|
||||||
|
<template #default="scope">{{
|
||||||
|
scope.row.car_price?.currency_info ||
|
||||||
|
scope.row.car_price?.amount ||
|
||||||
|
'—'
|
||||||
|
}}</template>
|
||||||
|
</ElTableColumn>
|
||||||
|
<ElTableColumn label="收款价" min-width="120" align="center">
|
||||||
<template #default="scope">{{
|
<template #default="scope">{{
|
||||||
scope.row.unit_price?.currency_info ||
|
scope.row.unit_price?.currency_info ||
|
||||||
scope.row.unit_price?.amount ||
|
scope.row.unit_price?.amount ||
|
||||||
@@ -233,11 +258,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="summary-item">
|
<div class="summary-item">
|
||||||
<span class="label">合计到岸价:</span>
|
<span class="label">合计到岸价:</span>
|
||||||
<span class="value"
|
<span class="value"> {{ orderData.cif_total?.currency_info || '—' }}</span>
|
||||||
>${{
|
|
||||||
formatPrice(Number(orderData.cif_total_amount?.amount ?? orderData.totalCif ?? 0))
|
|
||||||
}}</span
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="summary-item">
|
<div class="summary-item">
|
||||||
<span class="label">利润:</span>
|
<span class="label">利润:</span>
|
||||||
@@ -355,7 +376,7 @@
|
|||||||
currency: p.currency_name_snapshot || '—',
|
currency: p.currency_name_snapshot || '—',
|
||||||
account: p.account_name_snapshot || '—',
|
account: p.account_name_snapshot || '—',
|
||||||
remitter: p.remitter_name || '—',
|
remitter: p.remitter_name || '—',
|
||||||
amount: `$${formatPrice(Number(p.amount || 0))}`
|
amount: p.amount || '—'
|
||||||
}))
|
}))
|
||||||
: (props.orderData as any).payments || []
|
: (props.orderData as any).payments || []
|
||||||
if (!list.length) return []
|
if (!list.length) return []
|
||||||
|
|||||||
@@ -0,0 +1,219 @@
|
|||||||
|
<template>
|
||||||
|
<div class="print-preview-container">
|
||||||
|
<div class="preview-header">
|
||||||
|
<div class="header-actions">
|
||||||
|
<el-button @click="download" v-if="showDownload">下载</el-button>
|
||||||
|
<el-button @click="print" type="primary">打印</el-button>
|
||||||
|
<el-button @click="close">关闭</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="preview-content">
|
||||||
|
<div
|
||||||
|
v-if="pdf.images.length"
|
||||||
|
class="images-container"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-for="(img, idx) in pdf.images"
|
||||||
|
:key="idx"
|
||||||
|
:src="img"
|
||||||
|
class="preview-image"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<iframe
|
||||||
|
v-else-if="pdf.blobUrl || pdf.url"
|
||||||
|
ref="frameRef"
|
||||||
|
:src="pdf.blobUrl || pdf.url"
|
||||||
|
class="preview-iframe"
|
||||||
|
@load="onIframeLoad"
|
||||||
|
@error="onIframeError"
|
||||||
|
/>
|
||||||
|
<div v-else class="no-content">
|
||||||
|
<p>没有可预览的内容</p>
|
||||||
|
<p>传入的 PDF URL: {{ pdfUrl }}</p>
|
||||||
|
<p>PDF Object URL: {{ pdf.url }}</p>
|
||||||
|
<p>PDF Blob URL: {{ pdf.blobUrl }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, watch } from 'vue'
|
||||||
|
import { usePdfPreview } from '@/composables/usePdfPreview'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'PrintPreview',
|
||||||
|
props: {
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
showDownload: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
pdfUrl: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emits: ['close'],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
// 使用公共的 usePdfPreview
|
||||||
|
const { pdf, frameRef, openWithResponse, download, print, preparePreview, prepareImages } = usePdfPreview()
|
||||||
|
|
||||||
|
// 监听 visible 变化,当显示时加载 PDF
|
||||||
|
watch(() => props.visible, (newVisible) => {
|
||||||
|
console.log('PrintPreview visible 变化:', newVisible)
|
||||||
|
if (newVisible && props.pdfUrl) {
|
||||||
|
// 构造响应对象,模拟 API 返回格式
|
||||||
|
const response = {
|
||||||
|
url: props.pdfUrl,
|
||||||
|
file_url: props.pdfUrl,
|
||||||
|
file_url_full: props.pdfUrl
|
||||||
|
}
|
||||||
|
openWithResponse(response)
|
||||||
|
console.log('PrintPreview 设置 PDF URL:', props.pdfUrl)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听 pdfUrl 变化
|
||||||
|
watch(() => props.pdfUrl, (newUrl) => {
|
||||||
|
console.log('PrintPreview pdfUrl 变化:', newUrl)
|
||||||
|
if (newUrl) {
|
||||||
|
// 构造响应对象,模拟 API 返回格式
|
||||||
|
const response = {
|
||||||
|
url: newUrl,
|
||||||
|
file_url: newUrl,
|
||||||
|
file_url_full: newUrl
|
||||||
|
}
|
||||||
|
openWithResponse(response)
|
||||||
|
console.log('PrintPreview 更新 PDF URL:', newUrl)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
emit('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
// iframe 加载事件
|
||||||
|
const onIframeLoad = () => {
|
||||||
|
console.log('iframe 加载完成')
|
||||||
|
}
|
||||||
|
|
||||||
|
// iframe 错误事件
|
||||||
|
const onIframeError = (error: any) => {
|
||||||
|
console.error('iframe 加载错误:', error)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
frameRef,
|
||||||
|
pdf,
|
||||||
|
download,
|
||||||
|
print,
|
||||||
|
close,
|
||||||
|
onIframeLoad,
|
||||||
|
onIframeError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.print-preview-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
max-height: 80vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-header {
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-bottom: 1px solid #e4e7ed;
|
||||||
|
background: #fafafa;
|
||||||
|
border-radius: 6px 6px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-content {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.images-container {
|
||||||
|
overflow: auto;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 8px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-iframe {
|
||||||
|
flex: 1;
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-content {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
color: #666;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打印样式
|
||||||
|
@media print {
|
||||||
|
.print-preview-container {
|
||||||
|
max-height: none;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-header {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-content {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.images-container {
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image {
|
||||||
|
margin-bottom: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-iframe {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
+395
-127
@@ -33,13 +33,17 @@ export interface BaseForm {
|
|||||||
contract_exchange_rate: string
|
contract_exchange_rate: string
|
||||||
settlement_currency: string
|
settlement_currency: string
|
||||||
remark: string
|
remark: string
|
||||||
total_cif: number | undefined
|
cif_total: number | undefined
|
||||||
total_cif_currency: string
|
cif_total_currency: string
|
||||||
total_cif_currency_snapshot: string
|
cif_total_currency_snapshot: string
|
||||||
is_final: string
|
is_final: string
|
||||||
object_id: string | number
|
object_id: string | number
|
||||||
contract: string
|
contract: string[]
|
||||||
contract_url?: string
|
contract_url?: string[]
|
||||||
|
pi_doc: string[]
|
||||||
|
pi_doc_url?: string[]
|
||||||
|
transaction_slip: string[]
|
||||||
|
transaction_slip_url?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ItemRow {
|
export interface ItemRow {
|
||||||
@@ -105,11 +109,22 @@ export interface ItemRow {
|
|||||||
discount_currency_snapshot: string
|
discount_currency_snapshot: string
|
||||||
contract_rate?: number | undefined
|
contract_rate?: number | undefined
|
||||||
profit: number | undefined
|
profit: number | undefined
|
||||||
|
profit_currency: string
|
||||||
|
profit_currency_snapshot: string
|
||||||
profit_type_snapshot?: string
|
profit_type_snapshot?: string
|
||||||
modify_ids: string[]
|
modify_ids: string[]
|
||||||
modify_list: Array<{ option_id: string; option_name_snapshot: string }>
|
modify_list: Array<{ option_id: string; option_name_snapshot: string }>
|
||||||
modify_fee_currency: string
|
modify_fee_currency: string
|
||||||
modify_fee_currency_snapshot: string
|
modify_fee_currency_snapshot: string
|
||||||
|
accessory_price: number | undefined
|
||||||
|
accessory_price_currency: string
|
||||||
|
accessory_price_currency_snapshot: string
|
||||||
|
retention_price: number | undefined
|
||||||
|
retention_price_currency: string
|
||||||
|
retention_price_currency_snapshot: string
|
||||||
|
car_price: number | undefined
|
||||||
|
car_price_currency: string
|
||||||
|
car_price_currency_snapshot: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PaymentItem {
|
export interface PaymentItem {
|
||||||
@@ -138,6 +153,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
const actionImageUplode = `${import.meta.env.VITE_API_URL}/ticket/upload?scene=stock_orders`
|
const actionImageUplode = `${import.meta.env.VITE_API_URL}/ticket/upload?scene=stock_orders`
|
||||||
// 回显填充抑制标记:为 true 时不触发自动计算覆盖接口值
|
// 回显填充抑制标记:为 true 时不触发自动计算覆盖接口值
|
||||||
const isPopulating = ref(false)
|
const isPopulating = ref(false)
|
||||||
|
const userEditing = ref<Set<number>>(new Set()) // 跟踪用户正在编辑的行
|
||||||
|
|
||||||
// 选项数据
|
// 选项数据
|
||||||
const channelOptions = ref<any>()
|
const channelOptions = ref<any>()
|
||||||
@@ -177,15 +193,19 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
clearance_port_snapshot: '',
|
clearance_port_snapshot: '',
|
||||||
latest_arrival_date: '',
|
latest_arrival_date: '',
|
||||||
contract_exchange_rate: '',
|
contract_exchange_rate: '',
|
||||||
settlement_currency: 'CNY',
|
settlement_currency: 'USD',
|
||||||
remark: '',
|
remark: '',
|
||||||
total_cif: undefined,
|
cif_total: undefined,
|
||||||
total_cif_currency: 'CNY',
|
cif_total_currency: 'USD',
|
||||||
total_cif_currency_snapshot: '',
|
cif_total_currency_snapshot: '',
|
||||||
is_final: isFinal ? '1' : '0',
|
is_final: isFinal ? '1' : '0',
|
||||||
object_id: stockingId || '0',
|
object_id: stockingId || '0',
|
||||||
contract: '',
|
contract: [],
|
||||||
contract_url: '',
|
contract_url: [],
|
||||||
|
pi_doc: [],
|
||||||
|
pi_doc_url: [],
|
||||||
|
transaction_slip: [],
|
||||||
|
transaction_slip_url: [],
|
||||||
pick_up_date: '',
|
pick_up_date: '',
|
||||||
collect_all_date: ''
|
collect_all_date: ''
|
||||||
})
|
})
|
||||||
@@ -197,11 +217,11 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
_echo_vin: false,
|
_echo_vin: false,
|
||||||
mileage: 0,
|
mileage: 0,
|
||||||
listing_price: undefined,
|
listing_price: undefined,
|
||||||
listing_price_currency: 'CNY',
|
listing_price_currency: 'USD',
|
||||||
listing_price_currency_snapshot: '人民币',
|
listing_price_currency_snapshot: '美元',
|
||||||
reduction_price: undefined,
|
reduction_price: undefined,
|
||||||
reduction_price_currency: 'CNY',
|
reduction_price_currency: 'USD',
|
||||||
reduction_price_currency_snapshot: '人民币',
|
reduction_price_currency_snapshot: '美元',
|
||||||
color_interior_code: '',
|
color_interior_code: '',
|
||||||
color_interior_snapshot: '',
|
color_interior_snapshot: '',
|
||||||
color_exterior_code: '',
|
color_exterior_code: '',
|
||||||
@@ -212,51 +232,62 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
port_misc_fee: '',
|
port_misc_fee: '',
|
||||||
remark: '',
|
remark: '',
|
||||||
ocean_freight: '',
|
ocean_freight: '',
|
||||||
ocean_freight_currency: 'CNY',
|
ocean_freight_currency: 'USD',
|
||||||
ocean_freight_currency_snapshot: '人民币',
|
ocean_freight_currency_snapshot: '美元',
|
||||||
commission: '',
|
commission: '',
|
||||||
commission_currency: 'CNY',
|
commission_currency: 'USD',
|
||||||
commission_currency_snapshot: '人民币',
|
commission_currency_snapshot: '美元',
|
||||||
purchase_tax: '',
|
purchase_tax: '',
|
||||||
purchase_tax_currency: 'CNY',
|
purchase_tax_currency: 'USD',
|
||||||
purchase_tax_currency_snapshot: '人民币',
|
purchase_tax_currency_snapshot: '美元',
|
||||||
tax_refund: '',
|
tax_refund: '',
|
||||||
tax_refund_currency: 'CNY',
|
tax_refund_currency: 'CNY',
|
||||||
tax_refund_currency_snapshot: '人民币',
|
tax_refund_currency_snapshot: '人民币',
|
||||||
clearance_price: undefined,
|
clearance_price: undefined,
|
||||||
clearance_price_currency: 'CNY',
|
clearance_price_currency: 'USD',
|
||||||
clearance_price_currency_snapshot: '人民币',
|
clearance_price_currency_snapshot: '美元',
|
||||||
retrofit_fee: '',
|
retrofit_fee: '',
|
||||||
total_price: undefined,
|
total_price: undefined,
|
||||||
official_price: undefined,
|
official_price: undefined,
|
||||||
discount_price: undefined,
|
discount_price: undefined,
|
||||||
fob_fee: undefined,
|
fob_fee: undefined,
|
||||||
fob_fee_currency: 'CNY',
|
fob_fee_currency: 'USD',
|
||||||
fob_fee_currency_snapshot: '人民币',
|
fob_fee_currency_snapshot: '美元',
|
||||||
helper_fee: undefined,
|
helper_fee: undefined,
|
||||||
helper_fee_currency: 'CNY',
|
helper_fee_currency: 'USD',
|
||||||
helper_fee_currency_snapshot: '人民币',
|
helper_fee_currency_snapshot: '美元',
|
||||||
domestic_freight: undefined,
|
domestic_freight: undefined,
|
||||||
domestic_freight_currency: 'CNY',
|
domestic_freight_currency: 'USD',
|
||||||
domestic_freight_currency_snapshot: '人民币',
|
domestic_freight_currency_snapshot: '美元',
|
||||||
port_fee: undefined,
|
port_fee: undefined,
|
||||||
port_fee_currency: 'CNY',
|
port_fee_currency: 'USD',
|
||||||
port_fee_currency_snapshot: '人民币',
|
port_fee_currency_snapshot: '美元',
|
||||||
unit_price_currency: 'CNY',
|
unit_price_currency: 'USD',
|
||||||
unit_price_currency_snapshot: '人民币',
|
unit_price_currency_snapshot: '美元',
|
||||||
total_price_currency: 'CNY',
|
total_price_currency: 'USD',
|
||||||
total_price_currency_snapshot: '人民币',
|
total_price_currency_snapshot: '美元',
|
||||||
guide_price_currency: 'CNY',
|
guide_price_currency: 'USD',
|
||||||
guide_price_currency_snapshot: '人民币',
|
guide_price_currency_snapshot: '美元',
|
||||||
discount: undefined,
|
discount: undefined,
|
||||||
discount_currency: 'CNY',
|
discount_currency: 'USD',
|
||||||
discount_currency_snapshot: '人民币',
|
discount_currency_snapshot: '美元',
|
||||||
contract_rate: 7.16,
|
contract_rate: 7.16,
|
||||||
profit: undefined,
|
profit: undefined,
|
||||||
|
profit_currency: 'CNY',
|
||||||
|
profit_currency_snapshot: '人民币',
|
||||||
modify_ids: [],
|
modify_ids: [],
|
||||||
modify_list: [],
|
modify_list: [],
|
||||||
modify_fee_currency: 'CNY',
|
modify_fee_currency: 'USD',
|
||||||
modify_fee_currency_snapshot: '人民币'
|
modify_fee_currency_snapshot: '美元',
|
||||||
|
accessory_price: undefined,
|
||||||
|
accessory_price_currency: 'USD',
|
||||||
|
accessory_price_currency_snapshot: '美元',
|
||||||
|
retention_price: undefined,
|
||||||
|
retention_price_currency: 'USD',
|
||||||
|
retention_price_currency_snapshot: '美元',
|
||||||
|
car_price: undefined,
|
||||||
|
car_price_currency: 'USD',
|
||||||
|
car_price_currency_snapshot: '美元'
|
||||||
})
|
})
|
||||||
|
|
||||||
// 创建新的收款项
|
// 创建新的收款项
|
||||||
@@ -264,8 +295,8 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
remit_country_id: '',
|
remit_country_id: '',
|
||||||
remit_country_name_snapshot: '',
|
remit_country_name_snapshot: '',
|
||||||
remit_date: '',
|
remit_date: '',
|
||||||
currency_code: 'CNY',
|
currency_code: 'USD',
|
||||||
currency_name_snapshot: '人民币',
|
currency_name_snapshot: '美元',
|
||||||
account_id: '',
|
account_id: '',
|
||||||
account_name_snapshot: '',
|
account_name_snapshot: '',
|
||||||
remitter_name: '',
|
remitter_name: '',
|
||||||
@@ -274,7 +305,9 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
|
|
||||||
const items = ref<ItemRow[]>([newItem()])
|
const items = ref<ItemRow[]>([newItem()])
|
||||||
const paymentItems = ref<PaymentItem[]>([newPaymentItem()])
|
const paymentItems = ref<PaymentItem[]>([newPaymentItem()])
|
||||||
const contractFile = ref<{ name: string; url: string; file_name: string } | null>(null)
|
const contractFiles = ref<{ name: string; url: string; file_name: string }[]>([])
|
||||||
|
const piFiles = ref<{ name: string; url: string; file_name: string }[]>([])
|
||||||
|
const waterBillFiles = ref<{ name: string; url: string; file_name: string }[]>([])
|
||||||
|
|
||||||
// 弹框状态
|
// 弹框状态
|
||||||
const customerDialog = reactive<DialogState>({
|
const customerDialog = reactive<DialogState>({
|
||||||
@@ -439,8 +472,9 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
return (val * rateFrom) / rateTo
|
return (val * rateFrom) / rateTo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 利润=收款价-官方指导价/二手挂牌价+优惠-手续费-改装费-配件费-fob运费-港杂-海运-佣金-挂账-购置税+预估退税
|
||||||
const calcProfit = (it: any): number => {
|
const calcProfit = (it: any): number => {
|
||||||
const targetCurrency = baseForm.settlement_currency || 'USD'
|
const targetCurrency = 'CNY' // 固定使用人民币
|
||||||
const unit = convertCurrency(it.unit_price, it.unit_price_currency, targetCurrency)
|
const unit = convertCurrency(it.unit_price, it.unit_price_currency, targetCurrency)
|
||||||
const retrofit = convertCurrency(
|
const retrofit = convertCurrency(
|
||||||
it.retrofit_fee,
|
it.retrofit_fee,
|
||||||
@@ -482,6 +516,18 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
(it as any).tax_refund_currency,
|
(it as any).tax_refund_currency,
|
||||||
targetCurrency
|
targetCurrency
|
||||||
)
|
)
|
||||||
|
//挂账
|
||||||
|
const retention = convertCurrency(
|
||||||
|
it.retention_price ?? (it as any).retention_price,
|
||||||
|
(it as any).retention_price_currency,
|
||||||
|
targetCurrency
|
||||||
|
)
|
||||||
|
//配件
|
||||||
|
const accessory = convertCurrency(
|
||||||
|
it.accessory_price ?? (it as any).accessory_price,
|
||||||
|
(it as any).accessory_price_currency,
|
||||||
|
targetCurrency
|
||||||
|
)
|
||||||
const mileageVal = Number(it.mileage ?? 0)
|
const mileageVal = Number(it.mileage ?? 0)
|
||||||
if (mileageVal > 0) {
|
if (mileageVal > 0) {
|
||||||
// 二手车:用挂牌价与二手减价替代官方指导价与优惠
|
// 二手车:用挂牌价与二手减价替代官方指导价与优惠
|
||||||
@@ -497,7 +543,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
unit -
|
unit -
|
||||||
(retrofit + fob + listing + handling + port + ocean + commission + purchaseTax) +
|
(retrofit + fob + listing + handling + port + ocean + commission + purchaseTax + retention + accessory) +
|
||||||
taxRefund +
|
taxRefund +
|
||||||
reduction
|
reduction
|
||||||
)
|
)
|
||||||
@@ -516,27 +562,29 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
unit -
|
unit -
|
||||||
(retrofit + fob + guide + handling + port + ocean + commission + purchaseTax) +
|
(retrofit + fob + guide + handling + port + ocean + commission + purchaseTax + retention + accessory) +
|
||||||
taxRefund +
|
taxRefund +
|
||||||
discount
|
discount
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 计算报关价 = 收款价 - 挂账
|
||||||
const calcClearanceFee = (it: any): number => {
|
const calcClearanceFee = (it: any): number => {
|
||||||
const targetCurrency = it.clearance_price_currency || baseForm.settlement_currency || 'USD'
|
const targetCurrency = it.clearance_price_currency || baseForm.settlement_currency || 'USD'
|
||||||
const unit = convertCurrency(it.unit_price, it.unit_price_currency, targetCurrency)
|
const unit = convertCurrency(it.unit_price, it.unit_price_currency, targetCurrency)
|
||||||
const commission = convertCurrency(
|
const retention = convertCurrency(
|
||||||
it.commission ?? (it as any).commission,
|
it.retention_price ?? (it as any).retention_price,
|
||||||
(it as any).commission_currency,
|
(it as any).retention_price_currency,
|
||||||
targetCurrency
|
targetCurrency
|
||||||
)
|
)
|
||||||
return unit - commission
|
return unit - retention
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 计算预估退税额 = (官方价 - 折扣价) * 11.5% (固定人民币)
|
||||||
const calcTaxRefund = (it: any): number => {
|
const calcTaxRefund = (it: any): number => {
|
||||||
const mileageVal = Number(it.mileage ?? 0)
|
const mileageVal = Number(it.mileage ?? 0)
|
||||||
if (mileageVal > 0) return 0
|
if (mileageVal > 0) return 0
|
||||||
const targetCurrency = baseForm.settlement_currency || 'USD'
|
const targetCurrency = 'CNY' // 固定使用人民币
|
||||||
const official = convertCurrency(
|
const official = convertCurrency(
|
||||||
it.official_price ?? (it as any).guide_price,
|
it.official_price ?? (it as any).guide_price,
|
||||||
(it as any).guide_price_currency,
|
(it as any).guide_price_currency,
|
||||||
@@ -552,6 +600,32 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
return refund < 0 ? 0 : refund
|
return refund < 0 ? 0 : refund
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 计算车价:车价 = 报关价 - FOB运费 - 港杂费 - 海运费
|
||||||
|
const calcCarPrice = (it: any): number => {
|
||||||
|
const targetCurrency = it.car_price_currency || baseForm.settlement_currency || 'USD'
|
||||||
|
const clearance = convertCurrency(
|
||||||
|
it.clearance_price ?? (it as any).clearance_price,
|
||||||
|
(it as any).clearance_price_currency,
|
||||||
|
targetCurrency
|
||||||
|
)
|
||||||
|
const fob = convertCurrency(
|
||||||
|
it.fob_transport_fee ?? (it as any).fob_fee,
|
||||||
|
(it as any).fob_fee_currency,
|
||||||
|
targetCurrency
|
||||||
|
)
|
||||||
|
const port = convertCurrency(
|
||||||
|
it.port_misc_fee ?? (it as any).port_fee,
|
||||||
|
(it as any).port_fee_currency,
|
||||||
|
targetCurrency
|
||||||
|
)
|
||||||
|
const ocean = convertCurrency(
|
||||||
|
it.ocean_freight ?? (it as any).ocean_freight,
|
||||||
|
(it as any).ocean_freight_currency,
|
||||||
|
targetCurrency
|
||||||
|
)
|
||||||
|
return clearance - fob - port - ocean
|
||||||
|
}
|
||||||
|
|
||||||
// 合同文件相关方法
|
// 合同文件相关方法
|
||||||
const isImageFile = (file: { name: string; url: string; file_name: string }) => {
|
const isImageFile = (file: { name: string; url: string; file_name: string }) => {
|
||||||
return /\.(jpg|jpeg|png|gif)$/i.test(file.name) || file.file_name.startsWith('image/')
|
return /\.(jpg|jpeg|png|gif)$/i.test(file.name) || file.file_name.startsWith('image/')
|
||||||
@@ -578,20 +652,69 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
url: response.data.file_url,
|
url: response.data.file_url,
|
||||||
file_name: response.data.file_name
|
file_name: response.data.file_name
|
||||||
}
|
}
|
||||||
contractFile.value = fileInfo
|
contractFiles.value.push(fileInfo)
|
||||||
baseForm.contract = response.data.file_name
|
// 更新合同字段为文件名数组
|
||||||
|
baseForm.contract = contractFiles.value.map((file) => file.file_name)
|
||||||
ElMessage.success('合同上传成功!')
|
ElMessage.success('合同上传成功!')
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(response.message || '合同上传失败!')
|
ElMessage.error(response.message || '合同上传失败!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeContractFile = () => {
|
const removeContractFile = (index: number) => {
|
||||||
contractFile.value = null
|
contractFiles.value.splice(index, 1)
|
||||||
baseForm.contract = ''
|
// 更新合同字段为文件名数组
|
||||||
|
baseForm.contract = contractFiles.value.map((file) => file.file_name)
|
||||||
ElMessage.success('合同文件已删除')
|
ElMessage.success('合同文件已删除')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const downloadContractFile = (file: { name: string; url: string; file_name: string }) => {
|
||||||
|
// 创建下载链接
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = file.url
|
||||||
|
link.download = file.name
|
||||||
|
link.target = '_blank'
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PI文件处理方法
|
||||||
|
const removePiFile = (index: number) => {
|
||||||
|
piFiles.value.splice(index, 1)
|
||||||
|
// 更新PI字段为文件名数组
|
||||||
|
baseForm.pi_doc = piFiles.value.map((file) => file.file_name)
|
||||||
|
ElMessage.success('PI文件已删除')
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadPiFile = (file: { name: string; url: string; file_name: string }) => {
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = file.url
|
||||||
|
link.download = file.name
|
||||||
|
link.target = '_blank'
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 水单文件处理方法
|
||||||
|
const removeWaterBillFile = (index: number) => {
|
||||||
|
waterBillFiles.value.splice(index, 1)
|
||||||
|
// 更新水单字段为文件名数组
|
||||||
|
baseForm.transaction_slip = waterBillFiles.value.map((file) => file.file_name)
|
||||||
|
ElMessage.success('水单文件已删除')
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadWaterBillFile = (file: { name: string; url: string; file_name: string }) => {
|
||||||
|
const link = document.createElement('a')
|
||||||
|
link.href = file.url
|
||||||
|
link.download = file.name
|
||||||
|
link.target = '_blank'
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
document.body.removeChild(link)
|
||||||
|
}
|
||||||
|
|
||||||
// 订单项操作方法
|
// 订单项操作方法
|
||||||
const copyRow = (idx: number) => {
|
const copyRow = (idx: number) => {
|
||||||
const copied = JSON.parse(JSON.stringify(items.value[idx])) as ItemRow
|
const copied = JSON.parse(JSON.stringify(items.value[idx])) as ItemRow
|
||||||
@@ -617,6 +740,15 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const copyPaymentItem = (idx: number) => {
|
||||||
|
const originalItem = paymentItems.value[idx]
|
||||||
|
if (originalItem) {
|
||||||
|
const copiedItem = { ...originalItem }
|
||||||
|
// 完全复制所有字段,包括汇款人和汇款日期
|
||||||
|
paymentItems.value.splice(idx + 1, 0, copiedItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 客户选择相关方法
|
// 客户选择相关方法
|
||||||
const openCustomerDialog = () => {
|
const openCustomerDialog = () => {
|
||||||
customerDialog.visible = true
|
customerDialog.visible = true
|
||||||
@@ -701,7 +833,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
if (idx !== undefined && idx >= 0 && idx < items.value.length) {
|
if (idx !== undefined && idx >= 0 && idx < items.value.length) {
|
||||||
const target = items.value[idx]
|
const target = items.value[idx]
|
||||||
target.sku_id = row.id || ''
|
target.sku_id = row.id || ''
|
||||||
target.model_snapshot = row.model_name || row.name || ''
|
target.model_snapshot = row.brand_name + ' ' + row.series_name + ' ' + row.model_name
|
||||||
target.color_exterior_code = row.color_exterior_code || ''
|
target.color_exterior_code = row.color_exterior_code || ''
|
||||||
target.color_exterior_snapshot = row.color_exterior_text || ''
|
target.color_exterior_snapshot = row.color_exterior_text || ''
|
||||||
target.color_interior_code = row.color_interior_code || ''
|
target.color_interior_code = row.color_interior_code || ''
|
||||||
@@ -722,7 +854,10 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
baseForm.pick_up_date = res.pick_up_date || ''
|
baseForm.pick_up_date = res.pick_up_date || ''
|
||||||
baseForm.collect_all_date = res.collect_all_date || ''
|
baseForm.collect_all_date = res.collect_all_date || ''
|
||||||
baseForm.pi_no = res.pi_no || ''
|
baseForm.pi_no = res.pi_no || ''
|
||||||
baseForm.contract = res.contract || ''
|
// 合同字段兼容字符串或数组
|
||||||
|
baseForm.contract = Array.isArray(res.contract)
|
||||||
|
? res.contract
|
||||||
|
: (res.contract ? String(res.contract).split(',') : [])
|
||||||
baseForm.biz_date = res.biz_date || ''
|
baseForm.biz_date = res.biz_date || ''
|
||||||
baseForm.clearance_country_id = res.clearance_country_id || ''
|
baseForm.clearance_country_id = res.clearance_country_id || ''
|
||||||
baseForm.clearance_country_snapshot = res.clearance_country_snapshot || ''
|
baseForm.clearance_country_snapshot = res.clearance_country_snapshot || ''
|
||||||
@@ -744,14 +879,11 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
baseForm.clearance_port_snapshot = res.clearance_port_snapshot || ''
|
baseForm.clearance_port_snapshot = res.clearance_port_snapshot || ''
|
||||||
baseForm.latest_arrival_date = res.latest_arrival_date || ''
|
baseForm.latest_arrival_date = res.latest_arrival_date || ''
|
||||||
baseForm.remark = res.remark || ''
|
baseForm.remark = res.remark || ''
|
||||||
baseForm.settlement_currency = res.settlement_currency || 'CNY'
|
baseForm.settlement_currency = res.settlement_currency || 'USD'
|
||||||
// 合计与汇率
|
// 合计与汇率
|
||||||
baseForm.total_cif = res.cif_total_amount.amount
|
baseForm.cif_total = res.cif_total.amount ? Number(res.cif_total.amount) : undefined
|
||||||
? Number(res.cif_total_amount.amount)
|
baseForm.cif_total_currency = res.cif_total.currency || 'USD'
|
||||||
: undefined
|
baseForm.contract_exchange_rate = res.contract_exchange_rate
|
||||||
baseForm.total_cif_currency = res.settlement_currency || baseForm.total_cif_currency
|
|
||||||
baseForm.contract_exchange_rate =
|
|
||||||
res.contract_exchange_rate || getCurrencyRate(baseForm.total_cif_currency)
|
|
||||||
// 明细
|
// 明细
|
||||||
const list = Array.isArray(res.veh_list) ? res.veh_list : []
|
const list = Array.isArray(res.veh_list) ? res.veh_list : []
|
||||||
items.value = list.map((it: any) => ({
|
items.value = list.map((it: any) => ({
|
||||||
@@ -761,10 +893,10 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
mileage: it.mileage ?? 0,
|
mileage: it.mileage ?? 0,
|
||||||
model_snapshot: it.model_snapshot || '',
|
model_snapshot: it.model_snapshot || '',
|
||||||
listing_price: it.listing_price?.amount ? Number(it.listing_price.amount) : undefined,
|
listing_price: it.listing_price?.amount ? Number(it.listing_price.amount) : undefined,
|
||||||
listing_price_currency: it.listing_price?.currency || 'CNY',
|
listing_price_currency: it.listing_price?.currency || 'USD',
|
||||||
listing_price_currency_snapshot: '',
|
listing_price_currency_snapshot: '',
|
||||||
reduction_price: it.reduction_price?.amount ? Number(it.reduction_price.amount) : undefined,
|
reduction_price: it.reduction_price?.amount ? Number(it.reduction_price.amount) : undefined,
|
||||||
reduction_price_currency: it.reduction_price?.currency || 'CNY',
|
reduction_price_currency: it.reduction_price?.currency || 'USD',
|
||||||
reduction_price_currency_snapshot: '',
|
reduction_price_currency_snapshot: '',
|
||||||
color_interior_code: it.color_interior_code || '',
|
color_interior_code: it.color_interior_code || '',
|
||||||
color_interior_snapshot: it.color_interior_snapshot || '',
|
color_interior_snapshot: it.color_interior_snapshot || '',
|
||||||
@@ -778,38 +910,38 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
port_misc_fee: it.port_misc_fee?.amount ?? '',
|
port_misc_fee: it.port_misc_fee?.amount ?? '',
|
||||||
remark: it.remark || '',
|
remark: it.remark || '',
|
||||||
ocean_freight: it.ocean_freight?.amount ?? '',
|
ocean_freight: it.ocean_freight?.amount ?? '',
|
||||||
ocean_freight_currency: it.ocean_freight?.currency || 'CNY',
|
ocean_freight_currency: it.ocean_freight?.currency || 'USD',
|
||||||
ocean_freight_currency_snapshot: '',
|
ocean_freight_currency_snapshot: '',
|
||||||
commission: it.commission?.amount ?? '',
|
commission: it.commission?.amount ?? '',
|
||||||
commission_currency: it.commission?.currency || 'CNY',
|
commission_currency: it.commission?.currency || 'USD',
|
||||||
commission_currency_snapshot: '',
|
commission_currency_snapshot: '',
|
||||||
purchase_tax: it.purchase_tax?.amount ?? '',
|
purchase_tax: it.purchase_tax?.amount ?? '',
|
||||||
purchase_tax_currency: it.purchase_tax?.currency || 'CNY',
|
purchase_tax_currency: it.purchase_tax?.currency || 'USD',
|
||||||
purchase_tax_currency_snapshot: '',
|
purchase_tax_currency_snapshot: '',
|
||||||
retrofit_fee: it.retrofit_fee?.amount ?? '',
|
retrofit_fee: it.retrofit_fee?.amount ?? '',
|
||||||
total_price: it.total_price?.amount ? Number(it.total_price.amount) : undefined,
|
total_price: it.total_price?.amount ? Number(it.total_price.amount) : undefined,
|
||||||
official_price: it.official_price?.amount ? Number(it.official_price.amount) : undefined,
|
official_price: it.official_price?.amount ? Number(it.official_price.amount) : undefined,
|
||||||
discount_price: it.discount_price?.amount ? Number(it.discount_price.amount) : undefined,
|
discount_price: it.discount_price?.amount ? Number(it.discount_price.amount) : undefined,
|
||||||
fob_fee: undefined,
|
fob_fee: undefined,
|
||||||
fob_fee_currency: it.fob_transport_fee?.currency || 'CNY',
|
fob_fee_currency: it.fob_transport_fee?.currency || 'USD',
|
||||||
fob_fee_currency_snapshot: '',
|
fob_fee_currency_snapshot: '',
|
||||||
helper_fee: undefined,
|
helper_fee: undefined,
|
||||||
helper_fee_currency: it.handling_fee?.currency || 'CNY',
|
helper_fee_currency: it.handling_fee?.currency || 'USD',
|
||||||
helper_fee_currency_snapshot: '',
|
helper_fee_currency_snapshot: '',
|
||||||
domestic_freight: undefined,
|
domestic_freight: undefined,
|
||||||
domestic_freight_currency: it.domestic_freight?.currency || 'CNY',
|
domestic_freight_currency: it.domestic_freight?.currency || 'USD',
|
||||||
domestic_freight_currency_snapshot: '',
|
domestic_freight_currency_snapshot: '',
|
||||||
port_fee: undefined,
|
port_fee: undefined,
|
||||||
port_fee_currency: it.port_misc_fee?.currency || 'CNY',
|
port_fee_currency: it.port_misc_fee?.currency || 'USD',
|
||||||
port_fee_currency_snapshot: '',
|
port_fee_currency_snapshot: '',
|
||||||
unit_price_currency: it.unit_price?.currency || 'CNY',
|
unit_price_currency: it.unit_price?.currency || 'USD',
|
||||||
unit_price_currency_snapshot: '',
|
unit_price_currency_snapshot: '',
|
||||||
total_price_currency: it.total_price?.currency || 'CNY',
|
total_price_currency: it.total_price?.currency || 'USD',
|
||||||
total_price_currency_snapshot: '',
|
total_price_currency_snapshot: '',
|
||||||
guide_price_currency: it.official_price?.currency || 'CNY',
|
guide_price_currency: it.official_price?.currency || 'USD',
|
||||||
guide_price_currency_snapshot: '',
|
guide_price_currency_snapshot: '',
|
||||||
discount: undefined,
|
discount: undefined,
|
||||||
discount_currency: it.discount_price?.currency || 'CNY',
|
discount_currency: it.discount_price?.currency || 'USD',
|
||||||
discount_currency_snapshot: '',
|
discount_currency_snapshot: '',
|
||||||
contract_rate: baseForm.contract_exchange_rate
|
contract_rate: baseForm.contract_exchange_rate
|
||||||
? Number(baseForm.contract_exchange_rate)
|
? Number(baseForm.contract_exchange_rate)
|
||||||
@@ -817,7 +949,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
profit: it.profit?.amount ? Number(it.profit.amount) : undefined,
|
profit: it.profit?.amount ? Number(it.profit.amount) : undefined,
|
||||||
profit_type_snapshot: '',
|
profit_type_snapshot: '',
|
||||||
clearance_price: it.clearance_price?.amount ? Number(it.clearance_price.amount) : undefined,
|
clearance_price: it.clearance_price?.amount ? Number(it.clearance_price.amount) : undefined,
|
||||||
clearance_price_currency: it.clearance_price?.currency || 'CNY',
|
clearance_price_currency: it.clearance_price?.currency || 'USD',
|
||||||
clearance_price_currency_snapshot: '',
|
clearance_price_currency_snapshot: '',
|
||||||
modify_ids: Array.isArray(it.modify_list)
|
modify_ids: Array.isArray(it.modify_list)
|
||||||
? it.modify_list.map((m: any) => Number(m.option_id))
|
? it.modify_list.map((m: any) => Number(m.option_id))
|
||||||
@@ -828,11 +960,20 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
option_name_snapshot: m.option_name_snapshot
|
option_name_snapshot: m.option_name_snapshot
|
||||||
}))
|
}))
|
||||||
: [],
|
: [],
|
||||||
modify_fee_currency: it.retrofit_fee?.currency || 'CNY',
|
modify_fee_currency: it.retrofit_fee?.currency || 'USD',
|
||||||
modify_fee_currency_snapshot: '',
|
modify_fee_currency_snapshot: '',
|
||||||
tax_refund: it.tax_refund?.amount ?? '',
|
tax_refund: it.tax_refund?.amount ?? '',
|
||||||
tax_refund_currency: it.tax_refund?.currency || 'CNY',
|
tax_refund_currency: it.tax_refund?.currency || 'USD',
|
||||||
tax_refund_currency_snapshot: ''
|
tax_refund_currency_snapshot: '',
|
||||||
|
accessory_price: it.accessory_price?.amount ? Number(it.accessory_price.amount) : undefined,
|
||||||
|
accessory_price_currency: it.accessory_price?.currency || 'USD',
|
||||||
|
accessory_price_currency_snapshot: '',
|
||||||
|
retention_price: it.retention_price?.amount ? Number(it.retention_price.amount) : undefined,
|
||||||
|
retention_price_currency: it.retention_price?.currency || 'USD',
|
||||||
|
retention_price_currency_snapshot: '',
|
||||||
|
car_price: it.car_price?.amount ? Number(it.car_price.amount) : undefined,
|
||||||
|
car_price_currency: it.car_price?.currency || 'USD',
|
||||||
|
car_price_currency_snapshot: ''
|
||||||
}))
|
}))
|
||||||
// 计划收款
|
// 计划收款
|
||||||
const pays = Array.isArray(res.account_list) ? res.account_list : []
|
const pays = Array.isArray(res.account_list) ? res.account_list : []
|
||||||
@@ -847,13 +988,55 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
remitter_name: p.remitter_name || '',
|
remitter_name: p.remitter_name || '',
|
||||||
amount: p.amount ? Number(p.amount) : undefined
|
amount: p.amount ? Number(p.amount) : undefined
|
||||||
}))
|
}))
|
||||||
// 合同文件回显
|
// 合同文件回显(兼容数组与逗号字符串)
|
||||||
if (res.contract) {
|
if (res.contract) {
|
||||||
contractFile.value = {
|
const contractNamesArr: string[] = Array.isArray(res.contract)
|
||||||
name: '合同文件',
|
? res.contract
|
||||||
url: res.contract_url || res.contract,
|
: String(res.contract).split(',')
|
||||||
file_name: res.contract
|
const contractUrlsArr: string[] = Array.isArray(res.contract_url)
|
||||||
}
|
? (res.contract_url as string[])
|
||||||
|
: (res.contract_url ? String(res.contract_url).split(',') : [])
|
||||||
|
baseForm.contract = contractNamesArr
|
||||||
|
baseForm.contract_url = contractUrlsArr
|
||||||
|
contractFiles.value = contractNamesArr.map((fileName: string, index: number) => ({
|
||||||
|
name: fileName,
|
||||||
|
url: contractUrlsArr[index] || fileName,
|
||||||
|
file_name: fileName
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PI文件回显(兼容数组与逗号字符串)
|
||||||
|
if (res.pi_doc) {
|
||||||
|
const piNamesArr: string[] = Array.isArray(res.pi_doc)
|
||||||
|
? res.pi_doc
|
||||||
|
: String(res.pi_doc).split(',')
|
||||||
|
const piUrlsArr: string[] = Array.isArray(res.pi_doc_url)
|
||||||
|
? (res.pi_doc_url as string[])
|
||||||
|
: (res.pi_doc_url ? String(res.pi_doc_url).split(',') : [])
|
||||||
|
baseForm.pi_doc = piNamesArr
|
||||||
|
baseForm.pi_doc_url = piUrlsArr
|
||||||
|
piFiles.value = piNamesArr.map((fileName: string, index: number) => ({
|
||||||
|
name: fileName,
|
||||||
|
url: piUrlsArr[index] || fileName,
|
||||||
|
file_name: fileName
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 水单文件回显(兼容数组与逗号字符串)
|
||||||
|
if (res.transaction_slip) {
|
||||||
|
const slipNamesArr: string[] = Array.isArray(res.transaction_slip)
|
||||||
|
? res.transaction_slip
|
||||||
|
: String(res.transaction_slip).split(',')
|
||||||
|
const slipUrlsArr: string[] = Array.isArray(res.transaction_slip_url)
|
||||||
|
? (res.transaction_slip_url as string[])
|
||||||
|
: (res.transaction_slip_url ? String(res.transaction_slip_url).split(',') : [])
|
||||||
|
baseForm.transaction_slip = slipNamesArr
|
||||||
|
baseForm.transaction_slip_url = slipUrlsArr
|
||||||
|
waterBillFiles.value = slipNamesArr.map((fileName: string, index: number) => ({
|
||||||
|
name: fileName,
|
||||||
|
url: slipUrlsArr[index] || fileName,
|
||||||
|
file_name: fileName
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
// 等待本轮变更完成后,再恢复自动计算
|
// 等待本轮变更完成后,再恢复自动计算
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@@ -865,6 +1048,18 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
const handleSubmit = async (type: number, edit?: string, isfinal?: string) => {
|
const handleSubmit = async (type: number, edit?: string, isfinal?: string) => {
|
||||||
// 提交校验:最终提交且为提交动作时(type=1),必须填写 VIN
|
// 提交校验:最终提交且为提交动作时(type=1),必须填写 VIN
|
||||||
const isFinalFlag = isfinal === '1' || (isfinal as any) === true
|
const isFinalFlag = isfinal === '1' || (isfinal as any) === true
|
||||||
|
if(type === 1&&baseForm.contract.length == 0){
|
||||||
|
ElMessage.error('请上传合同文件')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(type === 1&&baseForm.pi_doc.length == 0){
|
||||||
|
ElMessage.error('请上传pi文件')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(type === 1&& baseForm.transaction_slip.length == 0){
|
||||||
|
ElMessage.error('请上传水单文件')
|
||||||
|
return
|
||||||
|
}
|
||||||
if (isFinalFlag && type === 1) {
|
if (isFinalFlag && type === 1) {
|
||||||
// const hasEmptyVin = (items.value || []).some((it) => !it.vin || String(it.vin).trim() === '')
|
// const hasEmptyVin = (items.value || []).some((it) => !it.vin || String(it.vin).trim() === '')
|
||||||
// if (hasEmptyVin) {
|
// if (hasEmptyVin) {
|
||||||
@@ -898,7 +1093,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
commission: wrapMoney(it.commission, (it as any).commission_currency, '佣金'),
|
commission: wrapMoney(it.commission, (it as any).commission_currency, '佣金'),
|
||||||
purchase_tax: wrapMoney(it.purchase_tax, (it as any).purchase_tax_currency, '购置税'),
|
purchase_tax: wrapMoney(it.purchase_tax, (it as any).purchase_tax_currency, '购置税'),
|
||||||
// tax_refund: wrapMoney(it.tax_refund, (it as any).tax_refund_currency, '退税'),
|
// tax_refund: wrapMoney(it.tax_refund, (it as any).tax_refund_currency, '退税'),
|
||||||
tax_refund: wrapMoney(it.tax_refund, baseForm.settlement_currency, '退税'),
|
tax_refund: wrapMoney(it.tax_refund, 'CNY', '退税'),
|
||||||
retrofit_fee: wrapMoney((it as any).retrofit_fee, (it as any).modify_fee_currency, '改装费'),
|
retrofit_fee: wrapMoney((it as any).retrofit_fee, (it as any).modify_fee_currency, '改装费'),
|
||||||
modify_list: it.modify_list,
|
modify_list: it.modify_list,
|
||||||
// total_price: wrapMoney(it.total_price, (it as any).total_price_currency, '总价'),
|
// total_price: wrapMoney(it.total_price, (it as any).total_price_currency, '总价'),
|
||||||
@@ -913,22 +1108,37 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
(it as any).discount_currency,
|
(it as any).discount_currency,
|
||||||
'优惠额'
|
'优惠额'
|
||||||
),
|
),
|
||||||
profit: wrapMoney(it.profit, baseForm.settlement_currency, '利润'),
|
profit: wrapMoney(it.profit, 'CNY', '利润'),
|
||||||
listing_price: wrapMoney(it.listing_price, (it as any).listing_price_currency, '挂牌价'),
|
listing_price: wrapMoney(it.listing_price, (it as any).listing_price_currency, '挂牌价'),
|
||||||
reduction_price: wrapMoney(
|
reduction_price: wrapMoney(
|
||||||
it.reduction_price,
|
it.reduction_price,
|
||||||
(it as any).reduction_price_currency,
|
(it as any).reduction_price_currency,
|
||||||
'二手减价'
|
'二手减价'
|
||||||
),
|
),
|
||||||
clearance_price: wrapMoney(it.clearance_price, (it as any).clearance_price_currency, '报关价')
|
clearance_price: wrapMoney(
|
||||||
|
it.clearance_price,
|
||||||
|
(it as any).clearance_price_currency,
|
||||||
|
'报关价'
|
||||||
|
),
|
||||||
|
accessory_price: wrapMoney(
|
||||||
|
it.accessory_price,
|
||||||
|
(it as any).accessory_price_currency,
|
||||||
|
'配件价'
|
||||||
|
),
|
||||||
|
retention_price: wrapMoney(it.retention_price, (it as any).retention_price_currency, '挂账'),
|
||||||
|
car_price: wrapMoney(it.car_price, (it as any).car_price_currency, '车价')
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// 从提交参数中移除 settlement_currency
|
// 从提交参数中移除 settlement_currency
|
||||||
const baseFormWithoutCur = { ...(baseForm as any) }
|
const baseFormWithoutCur = { ...(baseForm as any) }
|
||||||
delete (baseFormWithoutCur as any).total_cif
|
baseFormWithoutCur.cif_total = wrapMoney(baseFormWithoutCur.cif_total, baseFormWithoutCur.cif_total_currency, '合计')
|
||||||
delete (baseFormWithoutCur as any).total_cif_currency
|
|
||||||
delete (baseFormWithoutCur as any).total_cif_currency_snapshot
|
// delete (baseFormWithoutCur as any).cif_total
|
||||||
|
delete (baseFormWithoutCur as any).cif_total_currency
|
||||||
|
delete (baseFormWithoutCur as any).cif_total_currency_snapshot
|
||||||
delete (baseFormWithoutCur as any).contract_url
|
delete (baseFormWithoutCur as any).contract_url
|
||||||
|
delete (baseFormWithoutCur as any).pi_doc_url
|
||||||
|
delete (baseFormWithoutCur as any).transaction_slip_url
|
||||||
const payload = {
|
const payload = {
|
||||||
...baseFormWithoutCur,
|
...baseFormWithoutCur,
|
||||||
veh_list: mappedItems,
|
veh_list: mappedItems,
|
||||||
@@ -970,26 +1180,26 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
if (typeof validateContractRate === 'function') {
|
if (typeof validateContractRate === 'function') {
|
||||||
validateContractRate()
|
validateContractRate()
|
||||||
}
|
}
|
||||||
// 结算币种变化时,按新币种重算所有行利润
|
// // 结算币种变化时,按新币种重算所有行利润
|
||||||
;(items.value || []).forEach((it: any, index: number) => {
|
// ;(items.value || []).forEach((it: any, index: number) => {
|
||||||
const profit = calcProfit(it)
|
// const profit = calcProfit(it)
|
||||||
if (items.value[index])
|
// if (items.value[index])
|
||||||
items.value[index].profit = isNaN(profit) ? 0 : Number(profit.toFixed(2))
|
// items.value[index].profit = isNaN(profit) ? 0 : Number(profit.toFixed(2))
|
||||||
const clearance = calcClearanceFee(it)
|
// const clearance = calcClearanceFee(it)
|
||||||
if (items.value[index]) {
|
// if (items.value[index]) {
|
||||||
items.value[index].clearance_price = isNaN(clearance) ? 0 : Number(clearance.toFixed(2))
|
// items.value[index].clearance_price = isNaN(clearance) ? 0 : Number(clearance.toFixed(2))
|
||||||
// 确保报关价货币单位与计算结果一致
|
// // 确保报关价货币单位与计算结果一致
|
||||||
if (items.value[index]) {
|
// if (items.value[index]) {
|
||||||
;(items.value[index] as any).clearance_price_currency =
|
// ;(items.value[index] as any).clearance_price_currency =
|
||||||
it.clearance_price_currency || baseForm.settlement_currency || 'USD'
|
// it.clearance_price_currency || baseForm.settlement_currency || 'USD'
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
const refund = calcTaxRefund(it)
|
// const refund = calcTaxRefund(it)
|
||||||
if (items.value[index]) {
|
// if (items.value[index]) {
|
||||||
items.value[index].tax_refund = isNaN(refund) ? 0 : (Number(refund.toFixed(2)) as any)
|
// items.value[index].tax_refund = isNaN(refund) ? 0 : (Number(refund.toFixed(2)) as any)
|
||||||
;(items.value[index] as any).tax_refund_currency = baseForm.settlement_currency || 'USD'
|
// ;(items.value[index] as any).tax_refund_currency = baseForm.settlement_currency || 'USD'
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -1010,9 +1220,15 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
(val) => {
|
(val) => {
|
||||||
if (isPopulating.value) return
|
if (isPopulating.value) return
|
||||||
val.forEach((it: any, index: number) => {
|
val.forEach((it: any, index: number) => {
|
||||||
|
// 跳过用户正在编辑的行
|
||||||
|
if (userEditing.value.has(index)) return
|
||||||
const profit = calcProfit(it)
|
const profit = calcProfit(it)
|
||||||
if (items.value[index])
|
if (items.value[index]) {
|
||||||
items.value[index].profit = isNaN(profit) ? 0 : Number(profit.toFixed(2))
|
items.value[index].profit = isNaN(profit) ? 0 : Number(profit.toFixed(2))
|
||||||
|
;(items.value[index] as any).profit_currency = 'CNY'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动计算报关价
|
||||||
const clearance = calcClearanceFee(it)
|
const clearance = calcClearanceFee(it)
|
||||||
if (items.value[index]) {
|
if (items.value[index]) {
|
||||||
items.value[index].clearance_price = isNaN(clearance) ? 0 : Number(clearance.toFixed(2))
|
items.value[index].clearance_price = isNaN(clearance) ? 0 : Number(clearance.toFixed(2))
|
||||||
@@ -1022,31 +1238,74 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
it.clearance_price_currency || baseForm.settlement_currency || 'USD'
|
it.clearance_price_currency || baseForm.settlement_currency || 'USD'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 自动计算预估退税额
|
||||||
const refund = calcTaxRefund(it)
|
const refund = calcTaxRefund(it)
|
||||||
if (items.value[index]) {
|
if (items.value[index]) {
|
||||||
items.value[index].tax_refund = isNaN(refund) ? 0 : (Number(refund.toFixed(2)) as any)
|
items.value[index].tax_refund = isNaN(refund) ? '0' : String(Number(refund.toFixed(2)))
|
||||||
;(items.value[index] as any).tax_refund_currency = baseForm.settlement_currency || 'USD'
|
;(items.value[index] as any).tax_refund_currency = 'CNY'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动计算车价
|
||||||
|
const carPrice = calcCarPrice(it)
|
||||||
|
if (items.value[index]) {
|
||||||
|
items.value[index].car_price = isNaN(carPrice) ? 0 : Number(carPrice.toFixed(2))
|
||||||
|
;(items.value[index] as any).car_price_currency =
|
||||||
|
it.car_price_currency || baseForm.settlement_currency || 'USD'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// 合计到岸价 = 所有单价相加
|
// 合计到岸价 = 所有报关价相加
|
||||||
const sum = (val || []).reduce((acc: number, cur: any) => {
|
const sum = (val || []).reduce((acc: number, cur: any) => {
|
||||||
const n =
|
const n =
|
||||||
cur?.unit_price === undefined || cur?.unit_price === null || cur?.unit_price === ''
|
cur?.clearance_price === undefined ||
|
||||||
|
cur?.clearance_price === null ||
|
||||||
|
cur?.clearance_price === ''
|
||||||
? 0
|
? 0
|
||||||
: Number(cur.unit_price)
|
: Number(cur.clearance_price)
|
||||||
return acc + (isNaN(n) ? 0 : n)
|
return acc + (isNaN(n) ? 0 : n)
|
||||||
}, 0)
|
}, 0)
|
||||||
baseForm.total_cif = Number(sum.toFixed(2))
|
baseForm.cif_total = Number(sum.toFixed(2))
|
||||||
|
|
||||||
// 同步合计币种为第一行单价币种(若有)
|
// 同步合计币种为第一行报关价币种(若有)
|
||||||
if (items.value.length > 0) {
|
if (items.value.length > 0) {
|
||||||
const c = items.value[0]?.unit_price_currency
|
const c = items.value[0]?.clearance_price_currency
|
||||||
if (c) baseForm.total_cif_currency = c
|
if (c) baseForm.cif_total_currency = c
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ deep: true }
|
{ deep: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 监听车价货币单位变化,重新计算车价并更新货币名称快照
|
||||||
|
watch(
|
||||||
|
() => items.value.map((item: any) => item.car_price_currency),
|
||||||
|
(newCurrencies, oldCurrencies) => {
|
||||||
|
if (isPopulating.value) return
|
||||||
|
newCurrencies.forEach((currency: string, index: number) => {
|
||||||
|
if (currency && currency !== oldCurrencies?.[index]) {
|
||||||
|
const found = (currencyOptions.value || []).find((x: any) => x.currency_code === currency)
|
||||||
|
if (found && items.value[index]) {
|
||||||
|
;(items.value[index] as any).car_price_currency_snapshot = found.currency_name
|
||||||
|
// 重新计算车价
|
||||||
|
const carPrice = calcCarPrice(items.value[index])
|
||||||
|
items.value[index].car_price = isNaN(carPrice) ? 0 : Number(carPrice.toFixed(2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
// 处理用户编辑状态的方法
|
||||||
|
const handleUserEdit = (index: number) => {
|
||||||
|
// 标记用户正在编辑这一行
|
||||||
|
userEditing.value.add(index)
|
||||||
|
|
||||||
|
// 延迟清除编辑状态,给用户时间完成输入
|
||||||
|
setTimeout(() => {
|
||||||
|
userEditing.value.delete(index)
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化方法
|
// 初始化方法
|
||||||
const initializeForm = async () => {
|
const initializeForm = async () => {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
@@ -1062,7 +1321,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
])
|
])
|
||||||
|
|
||||||
// 设置默认汇率
|
// 设置默认汇率
|
||||||
baseForm.contract_exchange_rate = getCurrencyRate('CNY')
|
baseForm.contract_exchange_rate = getCurrencyRate('USD')
|
||||||
|
|
||||||
// 设置预计发送日默认为当天
|
// 设置预计发送日默认为当天
|
||||||
const today = new Date()
|
const today = new Date()
|
||||||
@@ -1077,7 +1336,9 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
baseForm,
|
baseForm,
|
||||||
items,
|
items,
|
||||||
paymentItems,
|
paymentItems,
|
||||||
contractFile,
|
contractFiles,
|
||||||
|
piFiles,
|
||||||
|
waterBillFiles,
|
||||||
customerDialog,
|
customerDialog,
|
||||||
vehicleDialog,
|
vehicleDialog,
|
||||||
|
|
||||||
@@ -1109,12 +1370,18 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
calcProfit,
|
calcProfit,
|
||||||
calcClearanceFee,
|
calcClearanceFee,
|
||||||
calcTaxRefund,
|
calcTaxRefund,
|
||||||
|
handleUserEdit,
|
||||||
|
|
||||||
// 合同文件方法
|
// 合同文件方法
|
||||||
isImageFile,
|
isImageFile,
|
||||||
beforeContractUpload,
|
beforeContractUpload,
|
||||||
handleContractUpload,
|
handleContractUpload,
|
||||||
removeContractFile,
|
removeContractFile,
|
||||||
|
downloadContractFile,
|
||||||
|
removePiFile,
|
||||||
|
downloadPiFile,
|
||||||
|
removeWaterBillFile,
|
||||||
|
downloadWaterBillFile,
|
||||||
|
|
||||||
// 订单项方法
|
// 订单项方法
|
||||||
copyRow,
|
copyRow,
|
||||||
@@ -1125,6 +1392,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
|||||||
// 收款项方法
|
// 收款项方法
|
||||||
addPaymentItem,
|
addPaymentItem,
|
||||||
removePaymentItem,
|
removePaymentItem,
|
||||||
|
copyPaymentItem,
|
||||||
newPaymentItem,
|
newPaymentItem,
|
||||||
|
|
||||||
// 客户选择方法
|
// 客户选择方法
|
||||||
|
|||||||
@@ -11,4 +11,4 @@ export function useUploadHeaders() {
|
|||||||
'Fdesk-Auth-Token': 'Bearer ' + userStore.accessToken
|
'Fdesk-Auth-Token': 'Bearer ' + userStore.accessToken
|
||||||
}))
|
}))
|
||||||
return { uploadHeaders }
|
return { uploadHeaders }
|
||||||
}
|
}
|
||||||
@@ -153,8 +153,8 @@
|
|||||||
channel: '',
|
channel: '',
|
||||||
customer_name: '',
|
customer_name: '',
|
||||||
client_country: '',
|
client_country: '',
|
||||||
total_cif: '',
|
cif_total: '',
|
||||||
total_cif_currency: '',
|
cif_total_currency: '',
|
||||||
contract_rate: ''
|
contract_rate: ''
|
||||||
})
|
})
|
||||||
const items = ref<any[]>([])
|
const items = ref<any[]>([])
|
||||||
|
|||||||
@@ -83,44 +83,19 @@
|
|||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
>
|
>
|
||||||
<OrderDetailContent :orderData="orderDialog.orderData" />
|
<OrderDetailContent :orderData="orderDialog.orderData" />
|
||||||
|
<!-- 合同文件 -->
|
||||||
<div class="boxshadow">
|
<div class="boxshadow">
|
||||||
<div class="form-title">
|
<FilePreview title="合同文件" :files="contractFiles" empty-text="暂无合同文件" />
|
||||||
<!-- <span class="border"></span> -->
|
</div>
|
||||||
<span class="title">合同</span>
|
|
||||||
</div>
|
<!-- PI文件 -->
|
||||||
<div class="file-preview">
|
<div class="boxshadow">
|
||||||
<div v-if="contractFile" class="contract-file">
|
<FilePreview title="PI文件" :files="piFiles" empty-text="暂无PI文件" />
|
||||||
<div v-if="isImageFile(contractFile)" class="image-preview">
|
</div>
|
||||||
<img
|
|
||||||
:src="contractFile.url"
|
<!-- 水单文件 -->
|
||||||
:alt="contractFile.name"
|
<div class="boxshadow">
|
||||||
class="preview-image"
|
<FilePreview title="水单文件" :files="waterBillFiles" empty-text="暂无水单文件" />
|
||||||
@click="previewImage(contractFile)"
|
|
||||||
/>
|
|
||||||
<div class="file-info">
|
|
||||||
<span class="file-name">{{ contractFile.name }}</span>
|
|
||||||
<el-button type="text" size="small" @click="previewImage(contractFile)">
|
|
||||||
预览
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="document-preview">
|
|
||||||
<div class="file-icon">
|
|
||||||
<i class="iconfont-sys"></i>
|
|
||||||
</div>
|
|
||||||
<div class="file-info">
|
|
||||||
<span class="file-name">{{ contractFile.name }}</span>
|
|
||||||
<el-button type="primary" size="small" @click="downloadFile(contractFile)">
|
|
||||||
下载
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="no-file">
|
|
||||||
<i class="iconfont-sys"></i>
|
|
||||||
<span>暂无合同文件</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div style="display: flex; justify-content: flex-end; gap: 8px">
|
<div style="display: flex; justify-content: flex-end; gap: 8px">
|
||||||
@@ -138,7 +113,7 @@
|
|||||||
>
|
>
|
||||||
<div style="max-height: 70vh; display: flex; flex-direction: column; gap: 12px">
|
<div style="max-height: 70vh; display: flex; flex-direction: column; gap: 12px">
|
||||||
<div style="display: flex; justify-content: flex-end; gap: 8px">
|
<div style="display: flex; justify-content: flex-end; gap: 8px">
|
||||||
<el-button @click="download">下载</el-button>
|
<el-button @click="download" v-if="isFinites">下载</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="pdf.images.length"
|
v-if="pdf.images.length"
|
||||||
@@ -184,8 +159,10 @@
|
|||||||
import ApprovalTimeline from '@/components/custom/ApprovalTimeline.vue'
|
import ApprovalTimeline from '@/components/custom/ApprovalTimeline.vue'
|
||||||
import type { OrderData } from '@/composables/useOrderDetailDialog'
|
import type { OrderData } from '@/composables/useOrderDetailDialog'
|
||||||
import { usePdfPreview } from '@/composables/usePdfPreview'
|
import { usePdfPreview } from '@/composables/usePdfPreview'
|
||||||
|
import FilePreview from '@/components/custom/FilePreview.vue'
|
||||||
const timelineDialogVisible = ref(false)
|
const timelineDialogVisible = ref(false)
|
||||||
const approvalRecords = ref<any[]>([])
|
const approvalRecords = ref<any[]>([])
|
||||||
|
const isFinites = ref(false)
|
||||||
// PDF 预览/打印(公共)
|
// PDF 预览/打印(公共)
|
||||||
const { pdf, frameRef, openWithResponse, download, print, preparePreview, prepareImages } = usePdfPreview()
|
const { pdf, frameRef, openWithResponse, download, print, preparePreview, prepareImages } = usePdfPreview()
|
||||||
defineOptions({ name: 'AdminFinalListPage' })
|
defineOptions({ name: 'AdminFinalListPage' })
|
||||||
@@ -248,6 +225,11 @@
|
|||||||
}
|
}
|
||||||
//打印
|
//打印
|
||||||
const printfn = (row: any) => {
|
const printfn = (row: any) => {
|
||||||
|
if (row.approval_status == 2) {
|
||||||
|
isFinites.value = true
|
||||||
|
} else {
|
||||||
|
isFinites.value = false
|
||||||
|
}
|
||||||
manageService
|
manageService
|
||||||
.printStock({ id: row.id })
|
.printStock({ id: row.id })
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
@@ -261,16 +243,42 @@
|
|||||||
console.log(err)
|
console.log(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 文件数据
|
||||||
|
const contractFiles = ref<Array<{ name: string; url: string; file_name: string }>>([])
|
||||||
|
const piFiles = ref<Array<{ name: string; url: string; file_name: string }>>([])
|
||||||
|
const waterBillFiles = ref<Array<{ name: string; url: string; file_name: string }>>([])
|
||||||
|
|
||||||
const contractFile = ref<{ name: string; url: string; file_name: string } | null>(null)
|
// 处理文件数据
|
||||||
|
const processFiles = (files: any[], type: string) => {
|
||||||
|
if (!files || !Array.isArray(files)) return []
|
||||||
|
return files.map((file: any) => ({
|
||||||
|
name: `${type}文件`,
|
||||||
|
url: file.file_full_url || file.file_url,
|
||||||
|
file_name: file.file_url
|
||||||
|
}))
|
||||||
|
}
|
||||||
const handleView1 = async (row: any) => {
|
const handleView1 = async (row: any) => {
|
||||||
const res = await manageService.checkStock({ id: row.object_id })
|
const res = await manageService.checkStock({ id: row.object_id })
|
||||||
if (res?.contract) {
|
// 处理合同文件
|
||||||
contractFile.value = {
|
const file_list = res?.file_list
|
||||||
name: '合同文件',
|
if (file_list?.contract) {
|
||||||
url: res.contract_url || res.contract,
|
contractFiles.value = processFiles(file_list.contract, '合同')
|
||||||
file_name: res.contract
|
} else {
|
||||||
}
|
contractFiles.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理PI文件
|
||||||
|
if (file_list?.pi_doc) {
|
||||||
|
piFiles.value = processFiles(file_list.pi_doc, 'PI')
|
||||||
|
} else {
|
||||||
|
piFiles.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理水单文件
|
||||||
|
if (file_list?.transaction_slip) {
|
||||||
|
waterBillFiles.value = processFiles(file_list.transaction_slip, '水单')
|
||||||
|
} else {
|
||||||
|
waterBillFiles.value = []
|
||||||
}
|
}
|
||||||
if (res) {
|
if (res) {
|
||||||
// 获取订单详情成功
|
// 获取订单详情成功
|
||||||
|
|||||||
@@ -177,8 +177,8 @@
|
|||||||
<ElRow :gutter="12">
|
<ElRow :gutter="12">
|
||||||
<ElCol :span="6">
|
<ElCol :span="6">
|
||||||
<ElFormItem label="合计到岸价" label-width="85px">
|
<ElFormItem label="合计到岸价" label-width="85px">
|
||||||
<ElInput v-model="base.total_cif" disabled>
|
<ElInput v-model="base.cif_total" disabled>
|
||||||
<template #append>{{ base.total_cif_currency }}</template>
|
<template #append>{{ base.cif_total_currency }}</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
@@ -332,8 +332,8 @@
|
|||||||
channel: '',
|
channel: '',
|
||||||
customer_name: '',
|
customer_name: '',
|
||||||
client_country: '',
|
client_country: '',
|
||||||
total_cif: '',
|
cif_total: '',
|
||||||
total_cif_currency: '',
|
cif_total_currency: '',
|
||||||
contract_rate: ''
|
contract_rate: ''
|
||||||
})
|
})
|
||||||
const items = ref<any[]>([])
|
const items = ref<any[]>([])
|
||||||
@@ -429,8 +429,8 @@
|
|||||||
)
|
)
|
||||||
ship.latest_arrival = res?.latest_arrival_date || ''
|
ship.latest_arrival = res?.latest_arrival_date || ''
|
||||||
// 合计与汇率
|
// 合计与汇率
|
||||||
base.total_cif = res?.cif_total_amount?.amount ?? ''
|
base.cif_total = res?.cif_total_amount?.amount ?? ''
|
||||||
base.total_cif_currency = res?.cif_total_amount?.currency || ''
|
base.cif_total_currency = res?.cif_total_amount?.currency || ''
|
||||||
base.contract_rate = res?.contract_exchange_rate || res?.contract_rate || ''
|
base.contract_rate = res?.contract_exchange_rate || res?.contract_rate || ''
|
||||||
// 计划收款(全部展示)
|
// 计划收款(全部展示)
|
||||||
payments.value = (Array.isArray(res?.account_list) ? res.account_list : []).map((p: any) => ({
|
payments.value = (Array.isArray(res?.account_list) ? res.account_list : []).map((p: any) => ({
|
||||||
|
|||||||
@@ -172,8 +172,8 @@
|
|||||||
<ElRow :gutter="12">
|
<ElRow :gutter="12">
|
||||||
<ElCol :span="6">
|
<ElCol :span="6">
|
||||||
<ElFormItem label="合计到岸价" label-width="85px">
|
<ElFormItem label="合计到岸价" label-width="85px">
|
||||||
<ElInput v-model="base.total_cif" disabled>
|
<ElInput v-model="base.cif_total" disabled>
|
||||||
<template #append>{{ base.total_cif_currency }}</template>
|
<template #append>{{ base.cif_total_currency }}</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
@@ -327,8 +327,8 @@
|
|||||||
channel: '',
|
channel: '',
|
||||||
customer_name: '',
|
customer_name: '',
|
||||||
client_country: '',
|
client_country: '',
|
||||||
total_cif: '',
|
cif_total: '',
|
||||||
total_cif_currency: '',
|
cif_total_currency: '',
|
||||||
contract_rate: ''
|
contract_rate: ''
|
||||||
})
|
})
|
||||||
const items = ref<any[]>([])
|
const items = ref<any[]>([])
|
||||||
@@ -421,8 +421,8 @@
|
|||||||
)
|
)
|
||||||
ship.latest_arrival = res?.latest_arrival_date || ''
|
ship.latest_arrival = res?.latest_arrival_date || ''
|
||||||
// 合计与汇率
|
// 合计与汇率
|
||||||
base.total_cif = res?.cif_total_amount?.amount ?? ''
|
base.cif_total = res?.cif_total_amount?.amount ?? ''
|
||||||
base.total_cif_currency = res?.cif_total_amount?.currency || ''
|
base.cif_total_currency = res?.cif_total_amount?.currency || ''
|
||||||
base.contract_rate = res?.contract_exchange_rate || res?.contract_rate || ''
|
base.contract_rate = res?.contract_exchange_rate || res?.contract_rate || ''
|
||||||
// 计划收款(全部展示)
|
// 计划收款(全部展示)
|
||||||
payments.value = (Array.isArray(res?.account_list) ? res.account_list : []).map((p: any) => ({
|
payments.value = (Array.isArray(res?.account_list) ? res.account_list : []).map((p: any) => ({
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
type="success"
|
type="success"
|
||||||
underline="never"
|
underline="never"
|
||||||
@click="handleView(scope.row)"
|
@click="handleView(scope.row)"
|
||||||
style="margin-right: 8px"
|
style="margin-right: 8px;color: #333333;"
|
||||||
>
|
>
|
||||||
<i class="iconfont-sys"></i> 查看
|
<i class="iconfont-sys"></i> 查看
|
||||||
</el-link>
|
</el-link>
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
>
|
>
|
||||||
<div style="max-height: 70vh; display: flex; flex-direction: column; gap: 12px">
|
<div style="max-height: 70vh; display: flex; flex-direction: column; gap: 12px">
|
||||||
<div style="display: flex; justify-content: flex-end; gap: 8px;">
|
<div style="display: flex; justify-content: flex-end; gap: 8px;">
|
||||||
<el-button @click="download">下载</el-button>
|
<el-button @click="download" v-if="isFinites">下载</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="pdf.images.length"
|
v-if="pdf.images.length"
|
||||||
@@ -129,44 +129,19 @@
|
|||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
>
|
>
|
||||||
<OrderDetailContent :orderData="orderDialog.orderData" />
|
<OrderDetailContent :orderData="orderDialog.orderData" />
|
||||||
|
<!-- 合同文件 -->
|
||||||
<div class="boxshadow">
|
<div class="boxshadow">
|
||||||
<div class="form-title">
|
<FilePreview title="合同文件" :files="contractFiles" empty-text="暂无合同文件" />
|
||||||
<!-- <span class="border"></span> -->
|
</div>
|
||||||
<span class="title">合同</span>
|
|
||||||
</div>
|
<!-- PI文件 -->
|
||||||
<div class="file-preview">
|
<div class="boxshadow">
|
||||||
<div v-if="contractFile" class="contract-file">
|
<FilePreview title="PI文件" :files="piFiles" empty-text="暂无PI文件" />
|
||||||
<div v-if="isImageFile(contractFile)" class="image-preview">
|
</div>
|
||||||
<img
|
|
||||||
:src="contractFile.url"
|
<!-- 水单文件 -->
|
||||||
:alt="contractFile.name"
|
<div class="boxshadow">
|
||||||
class="preview-image"
|
<FilePreview title="水单文件" :files="waterBillFiles" empty-text="暂无水单文件" />
|
||||||
@click="previewImage(contractFile)"
|
|
||||||
/>
|
|
||||||
<div class="file-info">
|
|
||||||
<span class="file-name">{{ contractFile.name }}</span>
|
|
||||||
<el-button type="text" size="small" @click="previewImage(contractFile)">
|
|
||||||
预览
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="document-preview">
|
|
||||||
<div class="file-icon">
|
|
||||||
<i class="iconfont-sys"></i>
|
|
||||||
</div>
|
|
||||||
<div class="file-info">
|
|
||||||
<span class="file-name">{{ contractFile.name }}</span>
|
|
||||||
<el-button type="primary" size="small" @click="downloadFile(contractFile)">
|
|
||||||
下载
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="no-file">
|
|
||||||
<i class="iconfont-sys"></i>
|
|
||||||
<span>暂无合同文件</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div style="display: flex; justify-content: flex-end; gap: 8px">
|
<div style="display: flex; justify-content: flex-end; gap: 8px">
|
||||||
@@ -196,8 +171,10 @@
|
|||||||
import OrderDetailContent from '@/components/custom/OrderDetailContent.vue'
|
import OrderDetailContent from '@/components/custom/OrderDetailContent.vue'
|
||||||
import ApprovalTimeline from '@/components/custom/ApprovalTimeline.vue'
|
import ApprovalTimeline from '@/components/custom/ApprovalTimeline.vue'
|
||||||
import type { OrderData } from '@/composables/useOrderDetailDialog'
|
import type { OrderData } from '@/composables/useOrderDetailDialog'
|
||||||
|
import FilePreview from '@/components/custom/FilePreview.vue'
|
||||||
const timelineDialogVisible = ref(false)
|
const timelineDialogVisible = ref(false)
|
||||||
const approvalRecords = ref<any[]>([])
|
const approvalRecords = ref<any[]>([])
|
||||||
|
const isFinites = ref(false)
|
||||||
defineOptions({ name: 'StockingListAdmin' })
|
defineOptions({ name: 'StockingListAdmin' })
|
||||||
// import { useAuth } from '@/composables/useAuth'
|
// import { useAuth } from '@/composables/useAuth'
|
||||||
// const { hasAuth } = useAuth()
|
// const { hasAuth } = useAuth()
|
||||||
@@ -260,18 +237,48 @@
|
|||||||
getList()
|
getList()
|
||||||
}
|
}
|
||||||
|
|
||||||
const contractFile = ref<{ name: string; url: string; file_name: string } | null>(null)
|
// 文件数据
|
||||||
|
const contractFiles = ref<Array<{ name: string; url: string; file_name: string }>>([])
|
||||||
|
const piFiles = ref<Array<{ name: string; url: string; file_name: string }>>([])
|
||||||
|
const waterBillFiles = ref<Array<{ name: string; url: string; file_name: string }>>([])
|
||||||
|
|
||||||
|
// 处理文件数据
|
||||||
|
const processFiles = (files: any[], type: string) => {
|
||||||
|
if (!files || !Array.isArray(files)) return []
|
||||||
|
return files.map((file: any) => ({
|
||||||
|
name: `${type}文件`,
|
||||||
|
url: file.file_full_url || file.file_url,
|
||||||
|
file_name: file.file_url
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
const handleView = async (row: any) => {
|
const handleView = async (row: any) => {
|
||||||
try {
|
try {
|
||||||
// 获取订单详情数据
|
// 获取订单详情数据
|
||||||
const res = await manageService.checkStock({ id: row.id })
|
const res = await manageService.checkStock({ id: row.id })
|
||||||
if (res?.contract) {
|
|
||||||
contractFile.value = {
|
// 处理合同文件
|
||||||
name: '合同文件',
|
const file_list = res?.file_list
|
||||||
url: res.contract_url || res.contract,
|
if (file_list?.contract) {
|
||||||
file_name: res.contract
|
contractFiles.value = processFiles(file_list.contract, '合同')
|
||||||
}
|
} else {
|
||||||
|
contractFiles.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理PI文件
|
||||||
|
if (file_list?.pi_doc) {
|
||||||
|
piFiles.value = processFiles(file_list.pi_doc, 'PI')
|
||||||
|
} else {
|
||||||
|
piFiles.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理水单文件
|
||||||
|
if (file_list?.transaction_slip) {
|
||||||
|
waterBillFiles.value = processFiles(file_list.transaction_slip, '水单')
|
||||||
|
} else {
|
||||||
|
waterBillFiles.value = []
|
||||||
|
}
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
// 转换数据格式以适配 OrderDetailDialog
|
// 转换数据格式以适配 OrderDetailDialog
|
||||||
const orderData: OrderData = res
|
const orderData: OrderData = res
|
||||||
@@ -284,21 +291,33 @@
|
|||||||
console.error('获取订单详情失败:', error)
|
console.error('获取订单详情失败:', error)
|
||||||
ElMessage.error('获取订单详情失败')
|
ElMessage.error('获取订单详情失败')
|
||||||
}
|
}
|
||||||
// router.push({
|
|
||||||
// path: '/admin/stock/show_admin',
|
|
||||||
// query: { id: row.id } // 可带客户名等参数
|
|
||||||
// })
|
|
||||||
// TODO: 跳转或弹窗查看备货单
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleView1 = async (row: any) => {
|
const handleView1 = async (row: any) => {
|
||||||
const res = await manageService.checkStock({ id: row.object_id })
|
const res = await manageService.checkStock({ id: row.object_id })
|
||||||
if (res?.contract) {
|
|
||||||
contractFile.value = {
|
// 处理合同文件
|
||||||
name: '合同文件',
|
const file_list = res?.file_list
|
||||||
url: res.contract_url || res.contract,
|
if (file_list?.contract) {
|
||||||
file_name: res.contract
|
contractFiles.value = processFiles(file_list.contract, '合同')
|
||||||
}
|
} else {
|
||||||
|
contractFiles.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理PI文件
|
||||||
|
if (file_list?.pi_doc) {
|
||||||
|
piFiles.value = processFiles(file_list.pi_doc, 'PI')
|
||||||
|
} else {
|
||||||
|
piFiles.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理水单文件
|
||||||
|
if (file_list?.transaction_slip) {
|
||||||
|
waterBillFiles.value = processFiles(file_list.transaction_slip, '水单')
|
||||||
|
} else {
|
||||||
|
waterBillFiles.value = []
|
||||||
|
}
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
// 获取订单详情成功
|
// 获取订单详情成功
|
||||||
const orderData: OrderData = res
|
const orderData: OrderData = res
|
||||||
@@ -306,12 +325,6 @@
|
|||||||
orderDialog.title = '合塑实业-汽车事业部-备货单(客户下定)'
|
orderDialog.title = '合塑实业-汽车事业部-备货单(客户下定)'
|
||||||
orderDialog.visible = true
|
orderDialog.visible = true
|
||||||
}
|
}
|
||||||
// router.push({
|
|
||||||
// path: '/admin/stock/final_show_admin',
|
|
||||||
// query: { id: row.object_id } // 可带客户名等参数
|
|
||||||
// })
|
|
||||||
// router.push('/crmpc/stocking/final_show')
|
|
||||||
// TODO: 跳转或弹窗查看备货单
|
|
||||||
}
|
}
|
||||||
// 判断是否为图片文件
|
// 判断是否为图片文件
|
||||||
const isImageFile = (file: { name: string; url: string; file_name: string }) => {
|
const isImageFile = (file: { name: string; url: string; file_name: string }) => {
|
||||||
@@ -419,6 +432,11 @@
|
|||||||
}
|
}
|
||||||
//打印
|
//打印
|
||||||
const printfn = (row: any) => {
|
const printfn = (row: any) => {
|
||||||
|
if (row.approval_status == 2) {
|
||||||
|
isFinites.value = true
|
||||||
|
} else {
|
||||||
|
isFinites.value = false
|
||||||
|
}
|
||||||
manageService
|
manageService
|
||||||
.printStock({ id: row.id })
|
.printStock({ id: row.id })
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
@@ -506,5 +524,86 @@
|
|||||||
font-size: 48px;
|
font-size: 48px;
|
||||||
color: #ddd;
|
color: #ddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.files-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-item {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-width: 200px;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 120px;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #fafafa;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-preview {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image {
|
||||||
|
flex: 1;
|
||||||
|
max-height: 80px;
|
||||||
|
object-fit: cover;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.document-preview {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-icon {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-icon i {
|
||||||
|
font-size: 48px;
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info {
|
||||||
|
padding: 8px;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-name {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #606266;
|
||||||
|
text-align: center;
|
||||||
|
word-break: break-all;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -136,7 +136,7 @@
|
|||||||
v-model="item.color_exterior_snapshot"
|
v-model="item.color_exterior_snapshot"
|
||||||
filterable
|
filterable
|
||||||
placeholder="请选择内容"
|
placeholder="请选择内容"
|
||||||
@change="(val) => (item.color_exterior_code = (wcolorOptions || []).find((x: any) => x.color_text === val)?.color_code || '')"
|
@change="(val) => (item.color_exterior_code = (wcolorOptions || []).find((x) => x.color_text === val)?.color_code || '')"
|
||||||
>
|
>
|
||||||
<ElOption
|
<ElOption
|
||||||
v-for="item in wcolorOptions"
|
v-for="item in wcolorOptions"
|
||||||
@@ -157,7 +157,7 @@
|
|||||||
@change="
|
@change="
|
||||||
(val) =>
|
(val) =>
|
||||||
(item.color_interior_code =
|
(item.color_interior_code =
|
||||||
(ncolorOptions || []).find((x: any) => x.color_text === val)?.color_code ||
|
(ncolorOptions || []).find((x) => x.color_text === val)?.color_code ||
|
||||||
'')
|
'')
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
@@ -171,7 +171,7 @@
|
|||||||
<ElInput v-model="item.color_interior_code" type="hidden" />
|
<ElInput v-model="item.color_interior_code" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</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">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="item.modify_ids"
|
v-model="item.modify_ids"
|
||||||
@@ -188,7 +188,7 @@
|
|||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</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 v-model="item.mileage" placeholder="请输入里程" />
|
<ElInput v-model="item.mileage" placeholder="请输入里程" />
|
||||||
@@ -264,6 +264,23 @@
|
|||||||
<ElInput v-model="item.reduction_price_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.reduction_price_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
|
<ElFormItem label="收款价" label-width="85px" :prop="`items.${idx}.unit_price`" required>
|
||||||
|
<ElInput v-model="item.unit_price" placeholder="请输入收款价">
|
||||||
|
<template #suffix>
|
||||||
|
<ElSelect v-model="item.unit_price_currency" style="width: 74px">
|
||||||
|
<ElOption
|
||||||
|
v-for="c in currencyOptions"
|
||||||
|
:key="c.currency_code"
|
||||||
|
:label="c.currency_name"
|
||||||
|
:value="c.currency_code"
|
||||||
|
/>
|
||||||
|
</ElSelect>
|
||||||
|
</template>
|
||||||
|
</ElInput>
|
||||||
|
<ElInput v-model="item.unit_price_currency_snapshot" type="hidden" />
|
||||||
|
</ElFormItem>
|
||||||
|
</ElCol>
|
||||||
</ElRow>
|
</ElRow>
|
||||||
<ElRow :gutter="12" class="item-row-wrap">
|
<ElRow :gutter="12" class="item-row-wrap">
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
@@ -300,6 +317,23 @@
|
|||||||
<ElInput v-model="item.modify_fee_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.modify_fee_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
|
<ElFormItem label="配件费" label-width="85px">
|
||||||
|
<ElInput v-model="item.accessory_price" placeholder="请输入配件费">
|
||||||
|
<template #suffix>
|
||||||
|
<ElSelect v-model="item.accessory_price_currency" style="width: 74px">
|
||||||
|
<ElOption
|
||||||
|
v-for="c in currencyOptions"
|
||||||
|
:key="c.currency_code"
|
||||||
|
:label="c.currency_name"
|
||||||
|
:value="c.currency_code"
|
||||||
|
/>
|
||||||
|
</ElSelect>
|
||||||
|
</template>
|
||||||
|
</ElInput>
|
||||||
|
<ElInput v-model="item.accessory_price_currency_snapshot" type="hidden" />
|
||||||
|
</ElFormItem>
|
||||||
|
</ElCol>
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
<ElFormItem label="FOB段运费" label-width="85px">
|
<ElFormItem label="FOB段运费" label-width="85px">
|
||||||
<ElInput v-model="item.fob_transport_fee" placeholder="请输入FOB段运费">
|
<ElInput v-model="item.fob_transport_fee" placeholder="请输入FOB段运费">
|
||||||
@@ -368,6 +402,23 @@
|
|||||||
<ElInput v-model="item.commission_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.commission_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
|
<ElFormItem label="挂账" label-width="85px">
|
||||||
|
<ElInput v-model="item.retention_price" placeholder="请输入挂账">
|
||||||
|
<template #suffix>
|
||||||
|
<ElSelect v-model="item.retention_price_currency" style="width: 74px">
|
||||||
|
<ElOption
|
||||||
|
v-for="c in currencyOptions"
|
||||||
|
:key="c.currency_code"
|
||||||
|
:label="c.currency_name"
|
||||||
|
:value="c.currency_code"
|
||||||
|
/>
|
||||||
|
</ElSelect>
|
||||||
|
</template>
|
||||||
|
</ElInput>
|
||||||
|
<ElInput v-model="item.retention_price_currency_snapshot" type="hidden" />
|
||||||
|
</ElFormItem>
|
||||||
|
</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 v-model="item.purchase_tax" placeholder="请输入购置税">
|
<ElInput v-model="item.purchase_tax" placeholder="请输入购置税">
|
||||||
@@ -387,24 +438,13 @@
|
|||||||
</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 v-model="item.tax_refund" placeholder="请输入预估退税额">
|
<ElInput
|
||||||
<!-- <template #suffix>
|
v-model="item.tax_refund"
|
||||||
<ElSelect v-model="item.tax_refund_currency" style="width: 74px">
|
placeholder="正在计算预估退税额"
|
||||||
<ElOption
|
@input="handleUserEdit(idx)"
|
||||||
v-for="c in currencyOptions"
|
>
|
||||||
:key="c.currency_code"
|
|
||||||
:label="c.currency_name"
|
|
||||||
:value="c.currency_code"
|
|
||||||
/>
|
|
||||||
</ElSelect>
|
|
||||||
</template> -->
|
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span style="font-size: 11px">
|
<span style="font-size: 11px">人民币</span>
|
||||||
{{
|
|
||||||
((currencyOptions || []).find((c: any) => c.currency_code === baseForm.settlement_currency)?.currency_name) ||
|
|
||||||
baseForm.settlement_currency
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
</template>
|
</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
<ElInput v-model="item.tax_refund_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.tax_refund_currency_snapshot" type="hidden" />
|
||||||
@@ -413,10 +453,14 @@
|
|||||||
</ElRow>
|
</ElRow>
|
||||||
<ElRow :gutter="12" class="item-row-wrap">
|
<ElRow :gutter="12" class="item-row-wrap">
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
<ElFormItem label="成交价" label-width="85px" :prop="`items.${idx}.unit_price`" required>
|
<ElFormItem label="车价" label-width="85px">
|
||||||
<ElInput v-model="item.unit_price" placeholder="请输入成交价">
|
<ElInput
|
||||||
|
v-model="item.car_price"
|
||||||
|
placeholder="正在计算车价"
|
||||||
|
@input="handleUserEdit(idx)"
|
||||||
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<ElSelect v-model="item.unit_price_currency" style="width: 74px">
|
<ElSelect v-model="item.car_price_currency" style="width: 74px">
|
||||||
<ElOption
|
<ElOption
|
||||||
v-for="c in currencyOptions"
|
v-for="c in currencyOptions"
|
||||||
:key="c.currency_code"
|
:key="c.currency_code"
|
||||||
@@ -426,7 +470,7 @@
|
|||||||
</ElSelect>
|
</ElSelect>
|
||||||
</template>
|
</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
<ElInput v-model="item.unit_price_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.car_price_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
<!-- <ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
<!-- <ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
@@ -455,22 +499,17 @@
|
|||||||
disabled
|
disabled
|
||||||
>
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span style="font-size: 11px">
|
<span style="font-size: 11px">人民币</span>
|
||||||
{{
|
|
||||||
((currencyOptions || []).find((c: any) => c.currency_code === baseForm.settlement_currency)?.currency_name) ||
|
|
||||||
baseForm.settlement_currency
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
</template>
|
</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</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="正在计算报关价"
|
||||||
:class="Number(item.clearance_price) < 0 ? 'customs-fee-negative' : ''"
|
@input="handleUserEdit(idx)"
|
||||||
>
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<ElSelect v-model="item.clearance_price_currency" style="width: 74px">
|
<ElSelect v-model="item.clearance_price_currency" style="width: 74px">
|
||||||
@@ -522,9 +561,9 @@
|
|||||||
<ElRow :gutter="12">
|
<ElRow :gutter="12">
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
||||||
<ElFormItem label="合计到岸价" label-width="105px">
|
<ElFormItem label="合计到岸价" label-width="105px">
|
||||||
<ElInput v-model="baseForm.total_cif" placeholder="请输入合计到岸价">
|
<ElInput v-model="baseForm.cif_total" placeholder="请输入合计到岸价">
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<ElSelect v-model="baseForm.total_cif_currency" style="width: 74px">
|
<ElSelect v-model="baseForm.cif_total_currency" style="width: 74px">
|
||||||
<ElOption
|
<ElOption
|
||||||
v-for="c in currencyOptions"
|
v-for="c in currencyOptions"
|
||||||
:key="c.currency_code"
|
:key="c.currency_code"
|
||||||
@@ -534,7 +573,7 @@
|
|||||||
</ElSelect>
|
</ElSelect>
|
||||||
</template>
|
</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
<ElInput v-model="baseForm.total_cif_currency_snapshot" type="hidden" />
|
<ElInput v-model="baseForm.cif_total_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
||||||
@@ -543,7 +582,7 @@
|
|||||||
<template #suffix>
|
<template #suffix>
|
||||||
<ElSelect v-model="baseForm.settlement_currency" style="width: 74px">
|
<ElSelect v-model="baseForm.settlement_currency" style="width: 74px">
|
||||||
<ElOption
|
<ElOption
|
||||||
@change="(val) =>(baseForm.contract_exchange_rate =(currencyOptions || []).find((x: any) => x.currency_code === val)?.exchange_rate || '') "
|
@change="(val) => (baseForm.contract_exchange_rate = (currencyOptions || []).find((x: any) => x.currency_code === val)?.exchange_rate || '')"
|
||||||
v-for="c in currencyOptions"
|
v-for="c in currencyOptions"
|
||||||
:key="c.currency_code"
|
:key="c.currency_code"
|
||||||
:label="c.currency_name"
|
:label="c.currency_name"
|
||||||
@@ -611,7 +650,7 @@
|
|||||||
@change="
|
@change="
|
||||||
(val) =>
|
(val) =>
|
||||||
(baseForm.shipping_method_snapshot =
|
(baseForm.shipping_method_snapshot =
|
||||||
(transportOptions || []).find((x: any) => x.item_value === val)?.item_label ||
|
(transportOptions || []).find((x) => x.item_value === val)?.item_label ||
|
||||||
'')
|
'')
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
@@ -633,7 +672,7 @@
|
|||||||
@change="
|
@change="
|
||||||
(val) =>
|
(val) =>
|
||||||
(baseForm.trade_term_snapshot =
|
(baseForm.trade_term_snapshot =
|
||||||
(trade_termsOptions || []).find((x: any) => x.id === val)?.item_label || '')
|
(trade_termsOptions || []).find((x) => x.id === val)?.item_label || '')
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<ElOption
|
<ElOption
|
||||||
@@ -785,6 +824,14 @@
|
|||||||
</ElRow>
|
</ElRow>
|
||||||
<ElRow :gutter="12">
|
<ElRow :gutter="12">
|
||||||
<ElCol :span="24" style="text-align: right">
|
<ElCol :span="24" style="text-align: right">
|
||||||
|
<ElButton type="success" size="small" @click="copyPaymentItem(idx)">复制</ElButton>
|
||||||
|
<ElButton
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
@click="addPaymentItem"
|
||||||
|
v-if="idx === paymentItems.length - 1"
|
||||||
|
>添加</ElButton
|
||||||
|
>
|
||||||
<ElButton
|
<ElButton
|
||||||
type="danger"
|
type="danger"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -792,13 +839,6 @@
|
|||||||
:disabled="paymentItems.length === 1"
|
:disabled="paymentItems.length === 1"
|
||||||
>删除</ElButton
|
>删除</ElButton
|
||||||
>
|
>
|
||||||
<ElButton
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
@click="addPaymentItem"
|
|
||||||
v-if="idx === paymentItems.length - 1"
|
|
||||||
>添加收款信息</ElButton
|
|
||||||
>
|
|
||||||
</ElCol>
|
</ElCol>
|
||||||
</ElRow>
|
</ElRow>
|
||||||
</ElForm>
|
</ElForm>
|
||||||
@@ -812,26 +852,44 @@
|
|||||||
<span class="border"></span>
|
<span class="border"></span>
|
||||||
<span class="title">上传合同</span>
|
<span class="title">上传合同</span>
|
||||||
</div>
|
</div>
|
||||||
<el-upload
|
<MultiFileUpload
|
||||||
class="upload-box"
|
v-model="contractFiles"
|
||||||
:action="actionImageUplode"
|
upload-text="点击上传"
|
||||||
:headers="uploadHeaders"
|
hint-text="支持多文件上传"
|
||||||
:show-file-list="false"
|
:icon-src="contractIcon"
|
||||||
:on-success="handleContractUpload"
|
|
||||||
:before-upload="beforeContractUpload"
|
|
||||||
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
||||||
>
|
@change="(files) => (baseForm.contract = files.map((f) => f.file_name))"
|
||||||
<div class="qrcode-upload-box">
|
/>
|
||||||
<img v-if="!contractFile" class="avatar" src="@/assets/img/crm/contract.png" />
|
</div>
|
||||||
<div v-else class="file-preview">
|
<!-- 上传PI -->
|
||||||
<img v-if="isImageFile(contractFile)" :src="contractFile.url" class="preview-image" />
|
<div class="boxshadow">
|
||||||
<div v-else class="file-icon">
|
<div class="form-title">
|
||||||
<i class="el-icon-document"></i>
|
<span class="border"></span>
|
||||||
<span class="file-name">{{ contractFile.name }}</span>
|
<span class="title">上传PI</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<MultiFileUpload
|
||||||
</div>
|
v-model="piFiles"
|
||||||
</el-upload>
|
upload-text="点击上传"
|
||||||
|
hint-text="支持多文件上传"
|
||||||
|
:icon-src="contractIcon"
|
||||||
|
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
||||||
|
@change="(files) => (baseForm.pi_doc = files.map((f) => f.file_name))"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<!-- 上传水单 -->
|
||||||
|
<div class="boxshadow">
|
||||||
|
<div class="form-title">
|
||||||
|
<span class="border"></span>
|
||||||
|
<span class="title">上传水单</span>
|
||||||
|
</div>
|
||||||
|
<MultiFileUpload
|
||||||
|
v-model="waterBillFiles"
|
||||||
|
upload-text="点击上传"
|
||||||
|
hint-text="支持多文件上传"
|
||||||
|
:icon-src="contractIcon"
|
||||||
|
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
||||||
|
@change="(files) => (baseForm.transaction_slip = files.map((f) => f.file_name))"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-card">
|
<div class="form-card">
|
||||||
<!-- 底部信息 -->
|
<!-- 底部信息 -->
|
||||||
@@ -965,6 +1023,8 @@
|
|||||||
import { CrmService } from '@/api/crmApi'
|
import { CrmService } from '@/api/crmApi'
|
||||||
import { useStockingForm } from '@/composables/useStockingForm'
|
import { useStockingForm } from '@/composables/useStockingForm'
|
||||||
import { onMounted, ref, computed } from 'vue'
|
import { onMounted, ref, computed } from 'vue'
|
||||||
|
import MultiFileUpload from '@/components/core/forms/MultiFileUpload.vue'
|
||||||
|
import contractIcon from '@/assets/img/crm/contract.png'
|
||||||
|
|
||||||
defineOptions({ name: 'CrmStockingAdd' }) // 定义组件名称,用于 KeepAlive 缓存控制
|
defineOptions({ name: 'CrmStockingAdd' }) // 定义组件名称,用于 KeepAlive 缓存控制
|
||||||
|
|
||||||
@@ -1010,7 +1070,7 @@
|
|||||||
{ required: true, message: '请输入二手挂牌价', trigger: 'blur' }
|
{ required: true, message: '请输入二手挂牌价', trigger: 'blur' }
|
||||||
]
|
]
|
||||||
rules[`items.${idx}.unit_price`] = [
|
rules[`items.${idx}.unit_price`] = [
|
||||||
{ required: true, message: '请输入成交价', trigger: 'blur' }
|
{ required: true, message: '请输入收款价', trigger: 'blur' }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
return rules
|
return rules
|
||||||
@@ -1039,7 +1099,9 @@
|
|||||||
baseForm,
|
baseForm,
|
||||||
items,
|
items,
|
||||||
paymentItems,
|
paymentItems,
|
||||||
contractFile,
|
contractFiles,
|
||||||
|
piFiles,
|
||||||
|
waterBillFiles,
|
||||||
customerDialog,
|
customerDialog,
|
||||||
vehicleDialog,
|
vehicleDialog,
|
||||||
|
|
||||||
@@ -1058,8 +1120,6 @@
|
|||||||
trade_termsOptions,
|
trade_termsOptions,
|
||||||
|
|
||||||
// 上传相关
|
// 上传相关
|
||||||
actionImageUplode,
|
|
||||||
uploadHeaders,
|
|
||||||
|
|
||||||
// 方法
|
// 方法
|
||||||
initializeForm,
|
initializeForm,
|
||||||
@@ -1069,12 +1129,8 @@
|
|||||||
validateContractRate,
|
validateContractRate,
|
||||||
wrapMoney,
|
wrapMoney,
|
||||||
calcProfit,
|
calcProfit,
|
||||||
|
handleUserEdit,
|
||||||
|
|
||||||
// 合同文件方法
|
|
||||||
isImageFile,
|
|
||||||
beforeContractUpload,
|
|
||||||
handleContractUpload,
|
|
||||||
removeContractFile,
|
|
||||||
|
|
||||||
// 订单项方法
|
// 订单项方法
|
||||||
copyRow,
|
copyRow,
|
||||||
@@ -1084,6 +1140,7 @@
|
|||||||
// 收款项方法
|
// 收款项方法
|
||||||
addPaymentItem,
|
addPaymentItem,
|
||||||
removePaymentItem,
|
removePaymentItem,
|
||||||
|
copyPaymentItem,
|
||||||
|
|
||||||
// 客户选择方法
|
// 客户选择方法
|
||||||
openCustomerDialog,
|
openCustomerDialog,
|
||||||
@@ -1261,6 +1318,7 @@
|
|||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-input__suffix .el-select .el-select__wrapper) {
|
:deep(.el-input__suffix .el-select .el-select__wrapper) {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
|||||||
@@ -189,7 +189,7 @@
|
|||||||
<ElInput v-model="item.color_interior_code" type="hidden" />
|
<ElInput v-model="item.color_interior_code" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</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">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="item.modify_ids"
|
v-model="item.modify_ids"
|
||||||
@@ -211,7 +211,7 @@
|
|||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</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 v-model="item.mileage" placeholder="请输入里程" />
|
<ElInput v-model="item.mileage" placeholder="请输入里程" />
|
||||||
@@ -287,6 +287,23 @@
|
|||||||
<ElInput v-model="item.reduction_price_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.reduction_price_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
|
<ElFormItem label="收款价" label-width="85px" :prop="'items.' + idx + '.unit_price'" required>
|
||||||
|
<ElInput v-model="item.unit_price" placeholder="请输入收款价">
|
||||||
|
<template #suffix>
|
||||||
|
<ElSelect v-model="item.unit_price_currency" style="width: 64px">
|
||||||
|
<ElOption
|
||||||
|
v-for="c in currencyOptions"
|
||||||
|
:key="c.currency_code"
|
||||||
|
:label="c.currency_name"
|
||||||
|
:value="c.currency_code"
|
||||||
|
/>
|
||||||
|
</ElSelect>
|
||||||
|
</template>
|
||||||
|
</ElInput>
|
||||||
|
<ElInput v-model="item.unit_price_currency_snapshot" type="hidden" />
|
||||||
|
</ElFormItem>
|
||||||
|
</ElCol>
|
||||||
</ElRow>
|
</ElRow>
|
||||||
<ElRow :gutter="12" class="item-row-wrap">
|
<ElRow :gutter="12" class="item-row-wrap">
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
@@ -323,6 +340,23 @@
|
|||||||
<ElInput v-model="item.modify_fee_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.modify_fee_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
|
<ElFormItem label="配件费" label-width="85px">
|
||||||
|
<ElInput v-model="item.accessory_price" placeholder="请输入配件费">
|
||||||
|
<template #suffix>
|
||||||
|
<ElSelect v-model="item.accessory_price_currency" style="width: 74px">
|
||||||
|
<ElOption
|
||||||
|
v-for="c in currencyOptions"
|
||||||
|
:key="c.currency_code"
|
||||||
|
:label="c.currency_name"
|
||||||
|
:value="c.currency_code"
|
||||||
|
/>
|
||||||
|
</ElSelect>
|
||||||
|
</template>
|
||||||
|
</ElInput>
|
||||||
|
<ElInput v-model="item.accessory_price_currency_snapshot" type="hidden" />
|
||||||
|
</ElFormItem>
|
||||||
|
</ElCol>
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
<ElFormItem label="FOB段运费" label-width="85px">
|
<ElFormItem label="FOB段运费" label-width="85px">
|
||||||
<ElInput v-model="item.fob_transport_fee" placeholder="请输入FOB段运费">
|
<ElInput v-model="item.fob_transport_fee" placeholder="请输入FOB段运费">
|
||||||
@@ -391,6 +425,23 @@
|
|||||||
<ElInput v-model="item.commission_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.commission_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
|
<ElFormItem label="挂账" label-width="85px">
|
||||||
|
<ElInput v-model="item.retention_price" placeholder="请输入挂账">
|
||||||
|
<template #suffix>
|
||||||
|
<ElSelect v-model="item.retention_price_currency" style="width: 74px">
|
||||||
|
<ElOption
|
||||||
|
v-for="c in currencyOptions"
|
||||||
|
:key="c.currency_code"
|
||||||
|
:label="c.currency_name"
|
||||||
|
:value="c.currency_code"
|
||||||
|
/>
|
||||||
|
</ElSelect>
|
||||||
|
</template>
|
||||||
|
</ElInput>
|
||||||
|
<ElInput v-model="item.retention_price_currency_snapshot" type="hidden" />
|
||||||
|
</ElFormItem>
|
||||||
|
</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 v-model="item.purchase_tax" placeholder="请输入购置税">
|
<ElInput v-model="item.purchase_tax" placeholder="请输入购置税">
|
||||||
@@ -410,24 +461,13 @@
|
|||||||
</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 v-model="item.tax_refund" placeholder="请输入预估退税额">
|
<ElInput
|
||||||
<!-- <template #suffix>
|
v-model="item.tax_refund"
|
||||||
<ElSelect v-model="item.tax_refund_currency" style="width: 64px">
|
placeholder="正在计算预估退税额"
|
||||||
<ElOption
|
@input="handleUserEdit(idx)"
|
||||||
v-for="c in currencyOptions"
|
>
|
||||||
:key="c.currency_code"
|
|
||||||
:label="c.currency_name"
|
|
||||||
:value="c.currency_code"
|
|
||||||
/>
|
|
||||||
</ElSelect>
|
|
||||||
</template> -->
|
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span style="font-size: 11px">
|
<span style="font-size: 11px">人民币</span>
|
||||||
{{
|
|
||||||
((currencyOptions || []).find((c: any) => c.currency_code === baseForm.settlement_currency)?.currency_name) ||
|
|
||||||
baseForm.settlement_currency
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
</template>
|
</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
<ElInput v-model="item.tax_refund_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.tax_refund_currency_snapshot" type="hidden" />
|
||||||
@@ -436,10 +476,14 @@
|
|||||||
</ElRow>
|
</ElRow>
|
||||||
<ElRow :gutter="12" class="item-row-wrap">
|
<ElRow :gutter="12" class="item-row-wrap">
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
<ElFormItem label="成交价" label-width="85px" :prop="'items.' + idx + '.unit_price'" required>
|
<ElFormItem label="车价" label-width="85px">
|
||||||
<ElInput v-model="item.unit_price" placeholder="请输入成交价">
|
<ElInput
|
||||||
|
v-model="item.car_price"
|
||||||
|
placeholder="正在计算车价"
|
||||||
|
@input="handleUserEdit(idx)"
|
||||||
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<ElSelect v-model="item.unit_price_currency" style="width: 64px">
|
<ElSelect v-model="item.car_price_currency" style="width: 74px">
|
||||||
<ElOption
|
<ElOption
|
||||||
v-for="c in currencyOptions"
|
v-for="c in currencyOptions"
|
||||||
:key="c.currency_code"
|
:key="c.currency_code"
|
||||||
@@ -449,7 +493,7 @@
|
|||||||
</ElSelect>
|
</ElSelect>
|
||||||
</template>
|
</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
<ElInput v-model="item.unit_price_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.car_price_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
<!-- <ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
<!-- <ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
@@ -478,12 +522,7 @@
|
|||||||
disabled
|
disabled
|
||||||
>
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span style="font-size: 11px">
|
<span style="font-size: 11px">人民币</span>
|
||||||
{{
|
|
||||||
((currencyOptions || []).find((c: any) => c.currency_code === baseForm.settlement_currency)?.currency_name) ||
|
|
||||||
baseForm.settlement_currency
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
</template>
|
</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
@@ -526,9 +565,9 @@
|
|||||||
<ElRow :gutter="12">
|
<ElRow :gutter="12">
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
||||||
<ElFormItem label="合计到岸价" label-width="105px">
|
<ElFormItem label="合计到岸价" label-width="105px">
|
||||||
<ElInput v-model.number="baseForm.total_cif" placeholder="请输入合计到岸价">
|
<ElInput v-model.number="baseForm.cif_total" placeholder="请输入合计到岸价">
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<ElSelect v-model="baseForm.total_cif_currency" style="width: 64px">
|
<ElSelect v-model="baseForm.cif_total_currency" style="width: 64px">
|
||||||
<ElOption
|
<ElOption
|
||||||
v-for="c in currencyOptions"
|
v-for="c in currencyOptions"
|
||||||
:key="c.currency_code"
|
:key="c.currency_code"
|
||||||
@@ -539,7 +578,7 @@
|
|||||||
</ElSelect>
|
</ElSelect>
|
||||||
</template>
|
</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
<ElInput v-model="baseForm.total_cif_currency_snapshot" type="hidden" />
|
<ElInput v-model="baseForm.cif_total_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
||||||
@@ -798,35 +837,52 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 上传合同 -->
|
<!-- 上传合同 -->
|
||||||
|
<!-- 上传合同 -->
|
||||||
<div class="boxshadow">
|
<div class="boxshadow">
|
||||||
<div class="form-title">
|
<div class="form-title">
|
||||||
<span class="border"></span>
|
<span class="border"></span>
|
||||||
<span class="title">上传合同</span>
|
<span class="title">上传合同</span>
|
||||||
</div>
|
</div>
|
||||||
<el-upload
|
<MultiFileUpload
|
||||||
class="upload-box"
|
v-model="contractFiles"
|
||||||
:action="actionImageUplode"
|
upload-text="点击上传"
|
||||||
:headers="uploadHeaders"
|
hint-text="支持多文件上传"
|
||||||
:show-file-list="false"
|
:icon-src="contractIcon"
|
||||||
:on-success="handleContractUpload"
|
|
||||||
:before-upload="beforeContractUpload"
|
|
||||||
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
||||||
>
|
@change="(files) => (baseForm.contract = files.map((f) => f.file_name))"
|
||||||
<div class="qrcode-upload-box">
|
/>
|
||||||
<input type="hidden" v-model="baseForm.contract" />
|
</div>
|
||||||
<img v-if="!contractFile" class="avatar" src="@/assets/img/crm/contract.png" />
|
|
||||||
<div v-else class="file-preview">
|
<!-- 上传PI -->
|
||||||
<img v-if="isImageFile(contractFile)" :src="contractFile.url" class="preview-image" />
|
<div class="boxshadow">
|
||||||
<div v-else class="file-icon">
|
<div class="form-title">
|
||||||
<i class="iconfont-sys"></i>
|
<span class="border"></span>
|
||||||
<span class="file-name">{{ contractFile.name }}</span>
|
<span class="title">上传PI</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="file-actions">
|
<MultiFileUpload
|
||||||
<el-button type="text" size="small" @click.stop="removeContractFile">删除</el-button>
|
v-model="piFiles"
|
||||||
</div>
|
upload-text="点击上传"
|
||||||
</div>
|
hint-text="支持多文件上传"
|
||||||
</div>
|
:icon-src="contractIcon"
|
||||||
</el-upload>
|
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
||||||
|
@change="(files) => (baseForm.pi_doc = files.map((f) => f.file_name))"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 上传水单 -->
|
||||||
|
<div class="boxshadow">
|
||||||
|
<div class="form-title">
|
||||||
|
<span class="border"></span>
|
||||||
|
<span class="title">上传水单</span>
|
||||||
|
</div>
|
||||||
|
<MultiFileUpload
|
||||||
|
v-model="waterBillFiles"
|
||||||
|
upload-text="点击上传"
|
||||||
|
hint-text="支持多文件上传"
|
||||||
|
:icon-src="contractIcon"
|
||||||
|
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
||||||
|
@change="(files) => (baseForm.transaction_slip = files.map((f) => f.file_name))"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-card">
|
<div class="form-card">
|
||||||
<!-- 底部信息 -->
|
<!-- 底部信息 -->
|
||||||
@@ -960,6 +1016,8 @@
|
|||||||
import { useUserStore } from '@/store/modules/user'
|
import { useUserStore } from '@/store/modules/user'
|
||||||
import { useStockingForm } from '@/composables/useStockingForm'
|
import { useStockingForm } from '@/composables/useStockingForm'
|
||||||
import { onMounted, ref, computed } from 'vue'
|
import { onMounted, ref, computed } from 'vue'
|
||||||
|
import MultiFileUpload from '@/components/core/forms/MultiFileUpload.vue'
|
||||||
|
import contractIcon from '@/assets/img/crm/contract.png'
|
||||||
|
|
||||||
defineOptions({ name: 'CrmStockingFinalAdd' }) // 定义组件名称,用于 KeepAlive 缓存控制
|
defineOptions({ name: 'CrmStockingFinalAdd' }) // 定义组件名称,用于 KeepAlive 缓存控制
|
||||||
|
|
||||||
@@ -1000,7 +1058,7 @@
|
|||||||
{ required: true, message: '请输入二手挂牌价', trigger: 'blur' }
|
{ required: true, message: '请输入二手挂牌价', trigger: 'blur' }
|
||||||
]
|
]
|
||||||
rules[`items.${idx}.unit_price`] = [
|
rules[`items.${idx}.unit_price`] = [
|
||||||
{ required: true, message: '请输入成交价', trigger: 'blur' }
|
{ required: true, message: '请输入收款价', trigger: 'blur' }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
return rules
|
return rules
|
||||||
@@ -1029,7 +1087,9 @@
|
|||||||
baseForm,
|
baseForm,
|
||||||
items,
|
items,
|
||||||
paymentItems,
|
paymentItems,
|
||||||
contractFile,
|
contractFiles,
|
||||||
|
piFiles,
|
||||||
|
waterBillFiles,
|
||||||
customerDialog,
|
customerDialog,
|
||||||
vehicleDialog,
|
vehicleDialog,
|
||||||
// 选项数据
|
// 选项数据
|
||||||
@@ -1056,6 +1116,7 @@
|
|||||||
beforeContractUpload,
|
beforeContractUpload,
|
||||||
handleContractUpload,
|
handleContractUpload,
|
||||||
removeContractFile,
|
removeContractFile,
|
||||||
|
handleUserEdit,
|
||||||
// // 订单项方法
|
// // 订单项方法
|
||||||
// copyRow,
|
// copyRow,
|
||||||
// addRowAfter,
|
// addRowAfter,
|
||||||
@@ -1209,6 +1270,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-image {
|
.preview-image {
|
||||||
|
|||||||
@@ -515,11 +515,11 @@
|
|||||||
</ElRow>
|
</ElRow>
|
||||||
<ElRow :gutter="12" class="item-row-wrap">
|
<ElRow :gutter="12" class="item-row-wrap">
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
||||||
<ElFormItem label="成交价" label-width="95px" :prop="'items.' + idx + '.unit_price'" required>
|
<ElFormItem label="收款价" label-width="95px" :prop="'items.' + idx + '.unit_price'" required>
|
||||||
<ElInput
|
<ElInput
|
||||||
:disabled="item._echo_vin === true"
|
:disabled="item._echo_vin === true"
|
||||||
v-model="item.unit_price"
|
v-model="item.unit_price"
|
||||||
placeholder="请输入成交价"
|
placeholder="请输入收款价"
|
||||||
>
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<ElSelect
|
<ElSelect
|
||||||
@@ -622,9 +622,9 @@
|
|||||||
<ElRow :gutter="12">
|
<ElRow :gutter="12">
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
||||||
<ElFormItem label="合计到岸价" label-width="105px">
|
<ElFormItem label="合计到岸价" label-width="105px">
|
||||||
<ElInput v-model.number="baseForm.total_cif" placeholder="请输入合计到岸价">
|
<ElInput v-model.number="baseForm.cif_total" placeholder="请输入合计到岸价">
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<ElSelect v-model="baseForm.total_cif_currency" style="width: 64px">
|
<ElSelect v-model="baseForm.cif_total_currency" style="width: 64px">
|
||||||
<ElOption
|
<ElOption
|
||||||
v-for="c in currencyOptions"
|
v-for="c in currencyOptions"
|
||||||
:key="c.currency_code"
|
:key="c.currency_code"
|
||||||
@@ -634,7 +634,7 @@
|
|||||||
</ElSelect>
|
</ElSelect>
|
||||||
</template>
|
</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
<ElInput v-model="baseForm.total_cif_currency_snapshot" type="hidden" />
|
<ElInput v-model="baseForm.cif_total_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
||||||
@@ -898,30 +898,46 @@
|
|||||||
<span class="border"></span>
|
<span class="border"></span>
|
||||||
<span class="title">上传合同</span>
|
<span class="title">上传合同</span>
|
||||||
</div>
|
</div>
|
||||||
<el-upload
|
<MultiFileUpload
|
||||||
class="upload-box"
|
v-model="contractFiles"
|
||||||
:action="actionImageUplode"
|
upload-text="点击上传"
|
||||||
:headers="uploadHeaders"
|
hint-text="支持多文件上传"
|
||||||
:show-file-list="false"
|
:icon-src="contractIcon"
|
||||||
:on-success="handleContractUpload"
|
|
||||||
:before-upload="beforeContractUpload"
|
|
||||||
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
||||||
>
|
@change="(files) => (baseForm.contract = files.map((f) => f.file_name))"
|
||||||
<div class="qrcode-upload-box">
|
/>
|
||||||
<input type="hidden" v-model="baseForm.contract"/>
|
</div>
|
||||||
<img v-if="!contractFile" class="avatar" src="@/assets/img/crm/contract.png" />
|
|
||||||
<div v-else class="file-preview">
|
<!-- 上传PI -->
|
||||||
<img v-if="isImageFile(contractFile)" :src="contractFile.url" class="preview-image" />
|
<div class="boxshadow">
|
||||||
<div v-else class="file-icon">
|
<div class="form-title">
|
||||||
<i class="iconfont-sys"></i>
|
<span class="border"></span>
|
||||||
<span class="file-name">{{ contractFile.name }}</span>
|
<span class="title">上传PI</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="file-actions">
|
<MultiFileUpload
|
||||||
<el-button type="text" size="small" @click.stop="removeContractFile">删除</el-button>
|
v-model="piFiles"
|
||||||
</div>
|
upload-text="点击上传"
|
||||||
</div>
|
hint-text="支持多文件上传"
|
||||||
</div>
|
:icon-src="contractIcon"
|
||||||
</el-upload>
|
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
||||||
|
@change="(files) => (baseForm.pi_doc = files.map((f) => f.file_name))"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 上传水单 -->
|
||||||
|
<div class="boxshadow">
|
||||||
|
<div class="form-title">
|
||||||
|
<span class="border"></span>
|
||||||
|
<span class="title">上传水单</span>
|
||||||
|
</div>
|
||||||
|
<MultiFileUpload
|
||||||
|
v-model="waterBillFiles"
|
||||||
|
upload-text="点击上传"
|
||||||
|
hint-text="支持多文件上传"
|
||||||
|
:icon-src="contractIcon"
|
||||||
|
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
||||||
|
@change="(files) => (baseForm.transaction_slip = files.map((f) => f.file_name))"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-card">
|
<div class="form-card">
|
||||||
<!-- 底部信息 -->
|
<!-- 底部信息 -->
|
||||||
@@ -1047,6 +1063,8 @@
|
|||||||
import { useUserStore } from '@/store/modules/user'
|
import { useUserStore } from '@/store/modules/user'
|
||||||
import { useStockingForm } from '@/composables/useStockingForm'
|
import { useStockingForm } from '@/composables/useStockingForm'
|
||||||
import { onMounted, ref, computed } from 'vue'
|
import { onMounted, ref, computed } from 'vue'
|
||||||
|
import MultiFileUpload from '@/components/core/forms/MultiFileUpload.vue'
|
||||||
|
import contractIcon from '@/assets/img/crm/contract.png'
|
||||||
defineOptions({ name: 'CrmStockingEdit' })
|
defineOptions({ name: 'CrmStockingEdit' })
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const stocking_id = route.query.id
|
const stocking_id = route.query.id
|
||||||
@@ -1083,7 +1101,7 @@
|
|||||||
{ required: true, message: '请输入二手挂牌价', trigger: 'blur' }
|
{ required: true, message: '请输入二手挂牌价', trigger: 'blur' }
|
||||||
]
|
]
|
||||||
rules[`items.${idx}.unit_price`] = [
|
rules[`items.${idx}.unit_price`] = [
|
||||||
{ required: true, message: '请输入成交价', trigger: 'blur' }
|
{ required: true, message: '请输入收款价', trigger: 'blur' }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
return rules
|
return rules
|
||||||
@@ -1112,7 +1130,9 @@
|
|||||||
baseForm,
|
baseForm,
|
||||||
items,
|
items,
|
||||||
paymentItems,
|
paymentItems,
|
||||||
contractFile,
|
contractFiles,
|
||||||
|
piFiles,
|
||||||
|
waterBillFiles,
|
||||||
customerDialog,
|
customerDialog,
|
||||||
vehicleDialog,
|
vehicleDialog,
|
||||||
// 选项数据
|
// 选项数据
|
||||||
@@ -1141,6 +1161,7 @@
|
|||||||
validateContractRate,
|
validateContractRate,
|
||||||
wrapMoney,
|
wrapMoney,
|
||||||
calcProfit,
|
calcProfit,
|
||||||
|
handleUserEdit,
|
||||||
|
|
||||||
// 合同文件方法
|
// 合同文件方法
|
||||||
isImageFile,
|
isImageFile,
|
||||||
@@ -1306,6 +1327,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-image {
|
.preview-image {
|
||||||
|
|||||||
@@ -101,44 +101,19 @@
|
|||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
>
|
>
|
||||||
<OrderDetailContent :orderData="orderDialog.orderData" />
|
<OrderDetailContent :orderData="orderDialog.orderData" />
|
||||||
|
<!-- 合同文件 -->
|
||||||
<div class="boxshadow">
|
<div class="boxshadow">
|
||||||
<div class="form-title">
|
<FilePreview title="合同文件" :files="contractFiles" empty-text="暂无合同文件" />
|
||||||
<!-- <span class="border"></span> -->
|
</div>
|
||||||
<span class="title">合同</span>
|
|
||||||
</div>
|
<!-- PI文件 -->
|
||||||
<div class="file-preview">
|
<div class="boxshadow">
|
||||||
<div v-if="contractFile" class="contract-file">
|
<FilePreview title="PI文件" :files="piFiles" empty-text="暂无PI文件" />
|
||||||
<div v-if="isImageFile(contractFile)" class="image-preview">
|
</div>
|
||||||
<img
|
|
||||||
:src="contractFile.url"
|
<!-- 水单文件 -->
|
||||||
:alt="contractFile.name"
|
<div class="boxshadow">
|
||||||
class="preview-image"
|
<FilePreview title="水单文件" :files="waterBillFiles" empty-text="暂无水单文件" />
|
||||||
@click="previewImage(contractFile)"
|
|
||||||
/>
|
|
||||||
<div class="file-info">
|
|
||||||
<span class="file-name">{{ contractFile.name }}</span>
|
|
||||||
<el-button type="text" size="small" @click="previewImage(contractFile)">
|
|
||||||
预览
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="document-preview">
|
|
||||||
<div class="file-icon">
|
|
||||||
<i class="iconfont-sys"></i>
|
|
||||||
</div>
|
|
||||||
<div class="file-info">
|
|
||||||
<span class="file-name">{{ contractFile.name }}</span>
|
|
||||||
<el-button type="primary" size="small" @click="downloadFile(contractFile)">
|
|
||||||
下载
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="no-file">
|
|
||||||
<i class="iconfont-sys"></i>
|
|
||||||
<span>暂无合同文件</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div style="display: flex; justify-content: flex-end; gap: 8px">
|
<div style="display: flex; justify-content: flex-end; gap: 8px">
|
||||||
@@ -156,7 +131,7 @@
|
|||||||
>
|
>
|
||||||
<div style="max-height: 70vh; display: flex; flex-direction: column; gap: 12px">
|
<div style="max-height: 70vh; display: flex; flex-direction: column; gap: 12px">
|
||||||
<div style="display: flex; justify-content: flex-end; gap: 8px">
|
<div style="display: flex; justify-content: flex-end; gap: 8px">
|
||||||
<el-button @click="download">下载</el-button>
|
<el-button @click="download" v-if="isFinites">下载</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="pdf.images.length"
|
v-if="pdf.images.length"
|
||||||
@@ -202,7 +177,9 @@
|
|||||||
import type { OrderData } from '@/composables/useOrderDetailDialog'
|
import type { OrderData } from '@/composables/useOrderDetailDialog'
|
||||||
import ApprovalTimeline from '@/components/custom/ApprovalTimeline.vue'
|
import ApprovalTimeline from '@/components/custom/ApprovalTimeline.vue'
|
||||||
import { manageService } from '@/api/adminApi'
|
import { manageService } from '@/api/adminApi'
|
||||||
|
import FilePreview from '@/components/custom/FilePreview.vue'
|
||||||
const timelineDialogVisible = ref(false)
|
const timelineDialogVisible = ref(false)
|
||||||
|
const isFinites = ref(false)
|
||||||
const approvalRecords = ref<any[]>([])
|
const approvalRecords = ref<any[]>([])
|
||||||
defineOptions({ name: 'CrmFinalList' })
|
defineOptions({ name: 'CrmFinalList' })
|
||||||
// 订单详情弹窗
|
// 订单详情弹窗
|
||||||
@@ -304,6 +281,11 @@
|
|||||||
usePdfPreview()
|
usePdfPreview()
|
||||||
//打印
|
//打印
|
||||||
const printfn = (row: any) => {
|
const printfn = (row: any) => {
|
||||||
|
if (row.approval_status == 2) {
|
||||||
|
isFinites.value = true
|
||||||
|
} else {
|
||||||
|
isFinites.value = false
|
||||||
|
}
|
||||||
CrmService.printStock({ id: row.id })
|
CrmService.printStock({ id: row.id })
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
openWithResponse(res)
|
openWithResponse(res)
|
||||||
@@ -316,16 +298,46 @@
|
|||||||
console.log(err)
|
console.log(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const contractFile = ref<{ name: string; url: string; file_name: string } | null>(null)
|
// 文件数据
|
||||||
|
const contractFiles = ref<Array<{ name: string; url: string; file_name: string }>>([])
|
||||||
|
const piFiles = ref<Array<{ name: string; url: string; file_name: string }>>([])
|
||||||
|
const waterBillFiles = ref<Array<{ name: string; url: string; file_name: string }>>([])
|
||||||
|
|
||||||
|
// 处理文件数据
|
||||||
|
const processFiles = (files: any[], type: string) => {
|
||||||
|
if (!files || !Array.isArray(files)) return []
|
||||||
|
return files.map((file: any) => ({
|
||||||
|
name: `${type}文件`,
|
||||||
|
url: file.file_full_url || file.file_url,
|
||||||
|
file_name: file.file_url
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
const handleView1 = async (row: any) => {
|
const handleView1 = async (row: any) => {
|
||||||
const res = await CrmService.checkStock({ id: row.id })
|
const res = await CrmService.checkStock({ id: row.id })
|
||||||
if (res?.contract) {
|
|
||||||
contractFile.value = {
|
// 处理合同文件
|
||||||
name: '合同文件',
|
const file_list = res?.file_list
|
||||||
url: res.contract_url || res.contract,
|
if (file_list?.contract) {
|
||||||
file_name: res.contract
|
contractFiles.value = processFiles(file_list.contract, '合同')
|
||||||
}
|
} else {
|
||||||
|
contractFiles.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理PI文件
|
||||||
|
if (file_list?.pi_doc) {
|
||||||
|
piFiles.value = processFiles(file_list.pi_doc, 'PI')
|
||||||
|
} else {
|
||||||
|
piFiles.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理水单文件
|
||||||
|
if (file_list?.transaction_slip) {
|
||||||
|
waterBillFiles.value = processFiles(file_list.transaction_slip, '水单')
|
||||||
|
} else {
|
||||||
|
waterBillFiles.value = []
|
||||||
|
}
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
// 获取订单详情成功
|
// 获取订单详情成功
|
||||||
const orderData: OrderData = res
|
const orderData: OrderData = res
|
||||||
@@ -333,122 +345,6 @@
|
|||||||
orderDialog.title = '合塑实业-汽车事业部-备货单(客户下定)'
|
orderDialog.title = '合塑实业-汽车事业部-备货单(客户下定)'
|
||||||
orderDialog.visible = true
|
orderDialog.visible = true
|
||||||
}
|
}
|
||||||
// router.push({
|
|
||||||
// path: '/crmpc/stocking/final_show',
|
|
||||||
// query: { id: row.object_id } // 可带客户名等参数
|
|
||||||
// })
|
|
||||||
// router.push('/crmpc/stocking/final_show')
|
|
||||||
// TODO: 跳转或弹窗查看备货单
|
|
||||||
}
|
|
||||||
// const handleView1 = (row: any) => {
|
|
||||||
// router.push({
|
|
||||||
// path: '/crmpc/stocking/final_show',
|
|
||||||
// query: { id: row.id } // 可带客户名等参数
|
|
||||||
// })
|
|
||||||
// // TODO: 跳转或弹窗查看备货单
|
|
||||||
// }
|
|
||||||
// 判断是否为图片文件
|
|
||||||
const isImageFile = (file: { name: string; url: string; file_name: string }) => {
|
|
||||||
// 检查文件名
|
|
||||||
if (file.name && /\.(jpg|jpeg|png|gif|webp)$/i.test(file.name)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查file_name字段
|
|
||||||
if (file.file_name && file.file_name.startsWith('image/')) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查URL中的文件扩展名(去除查询参数)
|
|
||||||
if (file.url) {
|
|
||||||
const urlWithoutParams = file.url.split('?')[0] // 移除查询参数
|
|
||||||
if (/\.(jpg|jpeg|png|gif|webp)$/i.test(urlWithoutParams)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 预览图片
|
|
||||||
const previewImage = (file: { name: string; url: string; file_name: string }) => {
|
|
||||||
// 创建图片预览弹窗
|
|
||||||
const imagePreview = document.createElement('div')
|
|
||||||
imagePreview.style.cssText = `
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: rgba(0, 0, 0, 0.8);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 9999;
|
|
||||||
cursor: pointer;
|
|
||||||
`
|
|
||||||
|
|
||||||
const image = document.createElement('img')
|
|
||||||
image.src = file.url
|
|
||||||
image.alt = file.name
|
|
||||||
image.style.cssText = `
|
|
||||||
max-width: 90%;
|
|
||||||
max-height: 90%;
|
|
||||||
object-fit: contain;
|
|
||||||
border-radius: 4px;
|
|
||||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
|
||||||
`
|
|
||||||
|
|
||||||
const closeBtn = document.createElement('div')
|
|
||||||
closeBtn.innerHTML = '×'
|
|
||||||
closeBtn.style.cssText = `
|
|
||||||
position: absolute;
|
|
||||||
top: 20px;
|
|
||||||
right: 30px;
|
|
||||||
color: white;
|
|
||||||
font-size: 30px;
|
|
||||||
cursor: pointer;
|
|
||||||
z-index: 10000;
|
|
||||||
`
|
|
||||||
|
|
||||||
imagePreview.appendChild(image)
|
|
||||||
imagePreview.appendChild(closeBtn)
|
|
||||||
document.body.appendChild(imagePreview)
|
|
||||||
|
|
||||||
// 点击关闭
|
|
||||||
const closePreview = () => {
|
|
||||||
document.body.removeChild(imagePreview)
|
|
||||||
}
|
|
||||||
|
|
||||||
imagePreview.addEventListener('click', closePreview)
|
|
||||||
closeBtn.addEventListener('click', (e) => {
|
|
||||||
e.stopPropagation()
|
|
||||||
closePreview()
|
|
||||||
})
|
|
||||||
|
|
||||||
// ESC键关闭
|
|
||||||
const handleKeydown = (e: KeyboardEvent) => {
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
closePreview()
|
|
||||||
document.removeEventListener('keydown', handleKeydown)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
document.addEventListener('keydown', handleKeydown)
|
|
||||||
}
|
|
||||||
// 下载文件
|
|
||||||
const downloadFile = (file: { name: string; url: string; file_name: string }) => {
|
|
||||||
try {
|
|
||||||
const link = document.createElement('a')
|
|
||||||
link.href = file.url
|
|
||||||
link.download = file.name
|
|
||||||
link.target = '_blank'
|
|
||||||
document.body.appendChild(link)
|
|
||||||
link.click()
|
|
||||||
document.body.removeChild(link)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('下载失败:', error)
|
|
||||||
ElMessage.error('下载失败,请稍后重试')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -509,4 +405,85 @@
|
|||||||
font-size: 48px;
|
font-size: 48px;
|
||||||
color: #ddd;
|
color: #ddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.files-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-item {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-width: 200px;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-preview {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 120px;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #fafafa;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-preview {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image {
|
||||||
|
flex: 1;
|
||||||
|
max-height: 80px;
|
||||||
|
object-fit: cover;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.document-preview {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-icon {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-icon i {
|
||||||
|
font-size: 48px;
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-info {
|
||||||
|
padding: 8px;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-name {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #606266;
|
||||||
|
text-align: center;
|
||||||
|
word-break: break-all;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -177,8 +177,8 @@
|
|||||||
<ElRow :gutter="12">
|
<ElRow :gutter="12">
|
||||||
<ElCol :span="6">
|
<ElCol :span="6">
|
||||||
<ElFormItem label="合计到岸价" label-width="85px">
|
<ElFormItem label="合计到岸价" label-width="85px">
|
||||||
<ElInput v-model="base.total_cif" disabled>
|
<ElInput v-model="base.cif_total" disabled>
|
||||||
<template #append>{{ base.total_cif_currency }}</template>
|
<template #append>{{ base.cif_total_currency }}</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
@@ -338,8 +338,8 @@
|
|||||||
channel: '',
|
channel: '',
|
||||||
customer_name: '',
|
customer_name: '',
|
||||||
client_country: '',
|
client_country: '',
|
||||||
total_cif: '',
|
cif_total: '',
|
||||||
total_cif_currency: '',
|
cif_total_currency: '',
|
||||||
contract_rate: ''
|
contract_rate: ''
|
||||||
})
|
})
|
||||||
const items = ref<any[]>([])
|
const items = ref<any[]>([])
|
||||||
@@ -440,8 +440,8 @@
|
|||||||
)
|
)
|
||||||
ship.latest_arrival = res?.latest_arrival_date || ''
|
ship.latest_arrival = res?.latest_arrival_date || ''
|
||||||
// 合计与汇率
|
// 合计与汇率
|
||||||
base.total_cif = res?.cif_total_amount?.amount ?? ''
|
base.cif_total = res?.cif_total_amount?.amount ?? ''
|
||||||
base.total_cif_currency = res?.cif_total_amount?.currency || ''
|
base.cif_total_currency = res?.cif_total_amount?.currency || ''
|
||||||
base.contract_rate = res?.contract_exchange_rate || res?.contract_rate || ''
|
base.contract_rate = res?.contract_exchange_rate || res?.contract_rate || ''
|
||||||
// 计划收款(全部展示)
|
// 计划收款(全部展示)
|
||||||
payments.value = (Array.isArray(res?.account_list) ? res.account_list : []).map((p: any) => ({
|
payments.value = (Array.isArray(res?.account_list) ? res.account_list : []).map((p: any) => ({
|
||||||
|
|||||||
@@ -172,8 +172,8 @@
|
|||||||
<ElRow :gutter="12">
|
<ElRow :gutter="12">
|
||||||
<ElCol :span="6">
|
<ElCol :span="6">
|
||||||
<ElFormItem label="合计到岸价" label-width="85px">
|
<ElFormItem label="合计到岸价" label-width="85px">
|
||||||
<ElInput v-model="base.total_cif" disabled>
|
<ElInput v-model="base.cif_total" disabled>
|
||||||
<template #append>{{ base.total_cif_currency }}</template>
|
<template #append>{{ base.cif_total_currency }}</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
@@ -333,8 +333,8 @@
|
|||||||
channel: '',
|
channel: '',
|
||||||
customer_name: '',
|
customer_name: '',
|
||||||
client_country: '',
|
client_country: '',
|
||||||
total_cif: '',
|
cif_total: '',
|
||||||
total_cif_currency: '',
|
cif_total_currency: '',
|
||||||
contract_rate: ''
|
contract_rate: ''
|
||||||
})
|
})
|
||||||
const items = ref<any[]>([])
|
const items = ref<any[]>([])
|
||||||
@@ -427,8 +427,8 @@
|
|||||||
)
|
)
|
||||||
ship.latest_arrival = res?.latest_arrival_date || ''
|
ship.latest_arrival = res?.latest_arrival_date || ''
|
||||||
// 合计与汇率
|
// 合计与汇率
|
||||||
base.total_cif = res?.cif_total_amount?.amount ?? ''
|
base.cif_total = res?.cif_total_amount?.amount ?? ''
|
||||||
base.total_cif_currency = res?.cif_total_amount?.currency || ''
|
base.cif_total_currency = res?.cif_total_amount?.currency || ''
|
||||||
base.contract_rate = res?.contract_exchange_rate || res?.contract_rate || ''
|
base.contract_rate = res?.contract_exchange_rate || res?.contract_rate || ''
|
||||||
// 计划收款(全部展示)
|
// 计划收款(全部展示)
|
||||||
payments.value = (Array.isArray(res?.account_list) ? res.account_list : []).map((p: any) => ({
|
payments.value = (Array.isArray(res?.account_list) ? res.account_list : []).map((p: any) => ({
|
||||||
|
|||||||
@@ -188,7 +188,7 @@
|
|||||||
<ElInput v-model="item.color_interior_code" type="hidden" />
|
<ElInput v-model="item.color_interior_code" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
<!-- <ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
<ElFormItem label="改装" label-width="95px">
|
<ElFormItem label="改装" label-width="95px">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="item.modify_ids"
|
v-model="item.modify_ids"
|
||||||
@@ -210,7 +210,7 @@
|
|||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol> -->
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
||||||
<ElFormItem label="里程" label-width="95px">
|
<ElFormItem label="里程" label-width="95px">
|
||||||
<ElInput v-model="item.mileage" placeholder="请输入里程" />
|
<ElInput v-model="item.mileage" placeholder="请输入里程" />
|
||||||
@@ -286,6 +286,23 @@
|
|||||||
<ElInput v-model="item.reduction_price_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.reduction_price_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
|
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
||||||
|
<ElFormItem label="收款价" label-width="95px" :prop="'items.' + idx + '.unit_price'" required>
|
||||||
|
<ElInput v-model="item.unit_price" placeholder="请输入收款价">
|
||||||
|
<template #suffix>
|
||||||
|
<ElSelect v-model="item.unit_price_currency" style="width: 64px">
|
||||||
|
<ElOption
|
||||||
|
v-for="c in currencyOptions"
|
||||||
|
:key="c.currency_code"
|
||||||
|
:label="c.currency_name"
|
||||||
|
:value="c.currency_code"
|
||||||
|
/>
|
||||||
|
</ElSelect>
|
||||||
|
</template>
|
||||||
|
</ElInput>
|
||||||
|
<ElInput v-model="item.unit_price_currency_snapshot" type="hidden" />
|
||||||
|
</ElFormItem>
|
||||||
|
</ElCol>
|
||||||
</ElRow>
|
</ElRow>
|
||||||
<ElRow :gutter="12" class="item-row-wrap">
|
<ElRow :gutter="12" class="item-row-wrap">
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
||||||
@@ -322,6 +339,23 @@
|
|||||||
<ElInput v-model="item.modify_fee_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.modify_fee_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
|
<ElFormItem label="配件费" label-width="85px">
|
||||||
|
<ElInput v-model="item.accessory_price" placeholder="请输入配件费">
|
||||||
|
<template #suffix>
|
||||||
|
<ElSelect v-model="item.accessory_price_currency" style="width: 74px">
|
||||||
|
<ElOption
|
||||||
|
v-for="c in currencyOptions"
|
||||||
|
:key="c.currency_code"
|
||||||
|
:label="c.currency_name"
|
||||||
|
:value="c.currency_code"
|
||||||
|
/>
|
||||||
|
</ElSelect>
|
||||||
|
</template>
|
||||||
|
</ElInput>
|
||||||
|
<ElInput v-model="item.accessory_price_currency_snapshot" type="hidden" />
|
||||||
|
</ElFormItem>
|
||||||
|
</ElCol>
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
||||||
<ElFormItem label="FOB段运费" label-width="95px">
|
<ElFormItem label="FOB段运费" label-width="95px">
|
||||||
<ElInput v-model="item.fob_transport_fee" placeholder="请输入FOB段运费">
|
<ElInput v-model="item.fob_transport_fee" placeholder="请输入FOB段运费">
|
||||||
@@ -390,6 +424,23 @@
|
|||||||
<ElInput v-model="item.commission_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.commission_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
|
<ElFormItem label="挂账" label-width="85px">
|
||||||
|
<ElInput v-model="item.retention_price" placeholder="请输入挂账">
|
||||||
|
<template #suffix>
|
||||||
|
<ElSelect v-model="item.retention_price_currency" style="width: 74px">
|
||||||
|
<ElOption
|
||||||
|
v-for="c in currencyOptions"
|
||||||
|
:key="c.currency_code"
|
||||||
|
:label="c.currency_name"
|
||||||
|
:value="c.currency_code"
|
||||||
|
/>
|
||||||
|
</ElSelect>
|
||||||
|
</template>
|
||||||
|
</ElInput>
|
||||||
|
<ElInput v-model="item.retention_price_currency_snapshot" type="hidden" />
|
||||||
|
</ElFormItem>
|
||||||
|
</ElCol>
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
<ElFormItem label="购置税" label-width="95px">
|
<ElFormItem label="购置税" label-width="95px">
|
||||||
<ElInput v-model="item.purchase_tax" placeholder="请输入购置税">
|
<ElInput v-model="item.purchase_tax" placeholder="请输入购置税">
|
||||||
@@ -408,25 +459,14 @@
|
|||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
<ElFormItem label="预估退税额" label-width="95px">
|
<ElFormItem label="预估退税额" label-width="85px">
|
||||||
<ElInput v-model="item.tax_refund" placeholder="请输入预估退税额">
|
<ElInput
|
||||||
<!-- <template #suffix>
|
v-model="item.tax_refund"
|
||||||
<ElSelect v-model="item.tax_refund_currency" style="width: 64px">
|
placeholder="正在计算预估退税额"
|
||||||
<ElOption
|
@input="handleUserEdit(idx)"
|
||||||
v-for="c in currencyOptions"
|
>
|
||||||
:key="c.currency_code"
|
|
||||||
:label="c.currency_name"
|
|
||||||
:value="c.currency_code"
|
|
||||||
/>
|
|
||||||
</ElSelect>
|
|
||||||
</template> -->
|
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span style="font-size: 11px">
|
<span style="font-size: 11px">人民币</span>
|
||||||
{{
|
|
||||||
((currencyOptions || []).find((c: any) => c.currency_code === baseForm.settlement_currency)?.currency_name) ||
|
|
||||||
baseForm.settlement_currency
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
</template>
|
</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
<ElInput v-model="item.tax_refund_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.tax_refund_currency_snapshot" type="hidden" />
|
||||||
@@ -434,11 +474,15 @@
|
|||||||
</ElCol>
|
</ElCol>
|
||||||
</ElRow>
|
</ElRow>
|
||||||
<ElRow :gutter="12" class="item-row-wrap">
|
<ElRow :gutter="12" class="item-row-wrap">
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="4">
|
||||||
<ElFormItem label="成交价" label-width="95px" :prop="'items.' + idx + '.unit_price'" required>
|
<ElFormItem label="车价" label-width="85px">
|
||||||
<ElInput v-model="item.unit_price" placeholder="请输入成交价">
|
<ElInput
|
||||||
|
v-model="item.car_price"
|
||||||
|
placeholder="正在计算车价"
|
||||||
|
@input="handleUserEdit(idx)"
|
||||||
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<ElSelect v-model="item.unit_price_currency" style="width: 64px">
|
<ElSelect v-model="item.car_price_currency" style="width: 74px">
|
||||||
<ElOption
|
<ElOption
|
||||||
v-for="c in currencyOptions"
|
v-for="c in currencyOptions"
|
||||||
:key="c.currency_code"
|
:key="c.currency_code"
|
||||||
@@ -448,7 +492,7 @@
|
|||||||
</ElSelect>
|
</ElSelect>
|
||||||
</template>
|
</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
<ElInput v-model="item.unit_price_currency_snapshot" type="hidden" />
|
<ElInput v-model="item.car_price_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
<!-- <ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
<!-- <ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
||||||
@@ -477,13 +521,7 @@
|
|||||||
disabled
|
disabled
|
||||||
>
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<span style="font-size: 11px">
|
<span style="font-size: 11px">人民币</span>
|
||||||
{{
|
|
||||||
((currencyOptions || []).find((c: any) => c.currency_code === baseForm.settlement_currency)
|
|
||||||
?.currency_name) ||
|
|
||||||
baseForm.settlement_currency
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
</template>
|
</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
@@ -543,9 +581,9 @@
|
|||||||
<ElRow :gutter="12">
|
<ElRow :gutter="12">
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
||||||
<ElFormItem label="合计到岸价" label-width="105px">
|
<ElFormItem label="合计到岸价" label-width="105px">
|
||||||
<ElInput v-model.number="baseForm.total_cif" placeholder="请输入合计到岸价">
|
<ElInput v-model.number="baseForm.cif_total" placeholder="请输入合计到岸价">
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<ElSelect v-model="baseForm.total_cif_currency" style="width: 64px">
|
<ElSelect v-model="baseForm.cif_total_currency" style="width: 64px">
|
||||||
<ElOption
|
<ElOption
|
||||||
v-for="c in currencyOptions"
|
v-for="c in currencyOptions"
|
||||||
:key="c.currency_code"
|
:key="c.currency_code"
|
||||||
@@ -555,7 +593,7 @@
|
|||||||
</ElSelect>
|
</ElSelect>
|
||||||
</template>
|
</template>
|
||||||
</ElInput>
|
</ElInput>
|
||||||
<ElInput v-model="baseForm.total_cif_currency_snapshot" type="hidden" />
|
<ElInput v-model="baseForm.cif_total_currency_snapshot" type="hidden" />
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
<ElCol :sm="12" :md="12" :lg="6" :xl="6">
|
||||||
@@ -792,8 +830,9 @@
|
|||||||
</ElRow>
|
</ElRow>
|
||||||
<ElRow :gutter="12">
|
<ElRow :gutter="12">
|
||||||
<ElCol :span="24" style="text-align: right;">
|
<ElCol :span="24" style="text-align: right;">
|
||||||
|
<ElButton type="success" size="small" @click="copyPaymentItem(idx)">复制</ElButton>
|
||||||
|
<ElButton type="primary" size="small" @click="addPaymentItem" v-if="idx === paymentItems.length - 1">添加</ElButton>
|
||||||
<ElButton type="danger" size="small" @click="removePaymentItem(idx)" :disabled="paymentItems.length === 1">删除</ElButton>
|
<ElButton type="danger" size="small" @click="removePaymentItem(idx)" :disabled="paymentItems.length === 1">删除</ElButton>
|
||||||
<ElButton type="primary" size="small" @click="addPaymentItem" v-if="idx === paymentItems.length - 1">添加收款信息</ElButton>
|
|
||||||
</ElCol>
|
</ElCol>
|
||||||
</ElRow>
|
</ElRow>
|
||||||
</ElForm>
|
</ElForm>
|
||||||
@@ -807,30 +846,46 @@
|
|||||||
<span class="border"></span>
|
<span class="border"></span>
|
||||||
<span class="title">上传合同</span>
|
<span class="title">上传合同</span>
|
||||||
</div>
|
</div>
|
||||||
<el-upload
|
<MultiFileUpload
|
||||||
class="upload-box"
|
v-model="contractFiles"
|
||||||
:action="actionImageUplode"
|
upload-text="点击上传"
|
||||||
:headers="uploadHeaders"
|
hint-text="支持多文件上传"
|
||||||
:show-file-list="false"
|
:icon-src="contractIcon"
|
||||||
:on-success="handleContractUpload"
|
|
||||||
:before-upload="beforeContractUpload"
|
|
||||||
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
||||||
>
|
@change="(files) => (baseForm.contract = files.map((f) => f.file_name))"
|
||||||
<div class="qrcode-upload-box">
|
/>
|
||||||
<input type="hidden" v-model="baseForm.contract"/>
|
</div>
|
||||||
<img v-if="!contractFile" class="avatar" src="@/assets/img/crm/contract.png" />
|
|
||||||
<div v-else class="file-preview">
|
<!-- 上传PI -->
|
||||||
<img v-if="isImageFile(contractFile)" :src="contractFile.url" class="preview-image" />
|
<div class="boxshadow">
|
||||||
<div v-else class="file-icon">
|
<div class="form-title">
|
||||||
<i class="iconfont-sys"></i>
|
<span class="border"></span>
|
||||||
<span class="file-name">{{ contractFile.name }}</span>
|
<span class="title">上传PI</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="file-actions">
|
<MultiFileUpload
|
||||||
<el-button type="text" size="small" @click.stop="removeContractFile">删除</el-button>
|
v-model="piFiles"
|
||||||
</div>
|
upload-text="点击上传"
|
||||||
</div>
|
hint-text="支持多文件上传"
|
||||||
</div>
|
:icon-src="contractIcon"
|
||||||
</el-upload>
|
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
||||||
|
@change="(files) => (baseForm.pi_doc = files.map((f) => f.file_name))"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 上传水单 -->
|
||||||
|
<div class="boxshadow">
|
||||||
|
<div class="form-title">
|
||||||
|
<span class="border"></span>
|
||||||
|
<span class="title">上传水单</span>
|
||||||
|
</div>
|
||||||
|
<MultiFileUpload
|
||||||
|
v-model="waterBillFiles"
|
||||||
|
upload-text="点击上传"
|
||||||
|
hint-text="支持多文件上传"
|
||||||
|
:icon-src="contractIcon"
|
||||||
|
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
||||||
|
@change="(files) => (baseForm.transaction_slip = files.map((f) => f.file_name))"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-card">
|
<div class="form-card">
|
||||||
<!-- 底部信息 -->
|
<!-- 底部信息 -->
|
||||||
@@ -964,6 +1019,8 @@
|
|||||||
import { CrmService } from '@/api/crmApi'
|
import { CrmService } from '@/api/crmApi'
|
||||||
import { useUserStore } from '@/store/modules/user'
|
import { useUserStore } from '@/store/modules/user'
|
||||||
import { useStockingForm } from '@/composables/useStockingForm'
|
import { useStockingForm } from '@/composables/useStockingForm'
|
||||||
|
import MultiFileUpload from '@/components/core/forms/MultiFileUpload.vue'
|
||||||
|
import contractIcon from '@/assets/img/crm/contract.png'
|
||||||
import { onMounted, ref, computed } from 'vue'
|
import { onMounted, ref, computed } from 'vue'
|
||||||
defineOptions({ name: 'CrmStockingEdit' })
|
defineOptions({ name: 'CrmStockingEdit' })
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@@ -1004,7 +1061,7 @@
|
|||||||
{ required: true, message: '请输入二手挂牌价', trigger: 'blur' }
|
{ required: true, message: '请输入二手挂牌价', trigger: 'blur' }
|
||||||
]
|
]
|
||||||
rules[`items.${idx}.unit_price`] = [
|
rules[`items.${idx}.unit_price`] = [
|
||||||
{ required: true, message: '请输入成交价', trigger: 'blur' }
|
{ required: true, message: '请输入收款价', trigger: 'blur' }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
return rules
|
return rules
|
||||||
@@ -1049,7 +1106,9 @@
|
|||||||
baseForm,
|
baseForm,
|
||||||
items,
|
items,
|
||||||
paymentItems,
|
paymentItems,
|
||||||
contractFile,
|
contractFiles,
|
||||||
|
piFiles,
|
||||||
|
waterBillFiles,
|
||||||
customerDialog,
|
customerDialog,
|
||||||
vehicleDialog,
|
vehicleDialog,
|
||||||
// 选项数据
|
// 选项数据
|
||||||
@@ -1078,6 +1137,7 @@
|
|||||||
validateContractRate,
|
validateContractRate,
|
||||||
wrapMoney,
|
wrapMoney,
|
||||||
calcProfit,
|
calcProfit,
|
||||||
|
handleUserEdit,
|
||||||
|
|
||||||
// 合同文件方法
|
// 合同文件方法
|
||||||
isImageFile,
|
isImageFile,
|
||||||
@@ -1091,6 +1151,7 @@
|
|||||||
removeRow,
|
removeRow,
|
||||||
|
|
||||||
// 收款项方法
|
// 收款项方法
|
||||||
|
copyPaymentItem,
|
||||||
addPaymentItem,
|
addPaymentItem,
|
||||||
removePaymentItem,
|
removePaymentItem,
|
||||||
|
|
||||||
@@ -1211,6 +1272,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-image {
|
.preview-image {
|
||||||
|
|||||||
@@ -88,7 +88,7 @@
|
|||||||
type="success"
|
type="success"
|
||||||
underline="never"
|
underline="never"
|
||||||
@click="handleView(scope.row)"
|
@click="handleView(scope.row)"
|
||||||
style="margin-right: 8px"
|
style="margin-right: 8px;color: #333333;"
|
||||||
>
|
>
|
||||||
<i class="iconfont-sys"></i> 查看
|
<i class="iconfont-sys"></i> 查看
|
||||||
</el-link>
|
</el-link>
|
||||||
@@ -114,15 +114,15 @@
|
|||||||
<i class="iconfont-sys"></i> 查看终版
|
<i class="iconfont-sys"></i> 查看终版
|
||||||
</el-link>
|
</el-link>
|
||||||
<el-link
|
<el-link
|
||||||
type="warning"
|
type="danger"
|
||||||
underline="never"
|
underline="never"
|
||||||
@click="copys(scope.row)"
|
@click="copys(scope.row)"
|
||||||
style="margin-right: 8px"
|
style="margin-right: 8px;color: #F04800;"
|
||||||
>
|
>
|
||||||
<i class="iconfont-sys"></i> 复制
|
<i class="iconfont-sys"></i> 复制
|
||||||
</el-link>
|
</el-link>
|
||||||
<el-link
|
<el-link
|
||||||
type="warning"
|
type="success"
|
||||||
underline="never"
|
underline="never"
|
||||||
@click="showDialogtimeline(scope.row)"
|
@click="showDialogtimeline(scope.row)"
|
||||||
style="margin-right: 8px"
|
style="margin-right: 8px"
|
||||||
@@ -131,7 +131,7 @@
|
|||||||
</el-link>
|
</el-link>
|
||||||
<el-link
|
<el-link
|
||||||
v-if="scope.row.approval_status == 1"
|
v-if="scope.row.approval_status == 1"
|
||||||
type="primary"
|
type="danger"
|
||||||
underline="never"
|
underline="never"
|
||||||
@click="stockrecallfn(scope.row)"
|
@click="stockrecallfn(scope.row)"
|
||||||
style="margin-right: 8px"
|
style="margin-right: 8px"
|
||||||
@@ -173,7 +173,7 @@
|
|||||||
>
|
>
|
||||||
<div style="max-height: 70vh; display: flex; flex-direction: column; gap: 12px">
|
<div style="max-height: 70vh; display: flex; flex-direction: column; gap: 12px">
|
||||||
<div style="display: flex; justify-content: flex-end; gap: 8px">
|
<div style="display: flex; justify-content: flex-end; gap: 8px">
|
||||||
<el-button @click="download">下载</el-button>
|
<el-button @click="download" v-if="isFinites">下载</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="pdf.images.length"
|
v-if="pdf.images.length"
|
||||||
@@ -203,44 +203,19 @@
|
|||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
>
|
>
|
||||||
<OrderDetailContent :orderData="orderDialog.orderData" />
|
<OrderDetailContent :orderData="orderDialog.orderData" />
|
||||||
|
<!-- 合同文件 -->
|
||||||
<div class="boxshadow">
|
<div class="boxshadow">
|
||||||
<div class="form-title">
|
<FilePreview title="合同文件" :files="contractFiles" empty-text="暂无合同文件" />
|
||||||
<!-- <span class="border"></span> -->
|
</div>
|
||||||
<span class="title">合同</span>
|
|
||||||
</div>
|
<!-- PI文件 -->
|
||||||
<div class="file-preview">
|
<div class="boxshadow">
|
||||||
<div v-if="contractFile" class="contract-file">
|
<FilePreview title="PI文件" :files="piFiles" empty-text="暂无PI文件" />
|
||||||
<div v-if="isImageFile(contractFile)" class="image-preview">
|
</div>
|
||||||
<img
|
|
||||||
:src="contractFile.url"
|
<!-- 水单文件 -->
|
||||||
:alt="contractFile.name"
|
<div class="boxshadow">
|
||||||
class="preview-image"
|
<FilePreview title="水单文件" :files="waterBillFiles" empty-text="暂无水单文件" />
|
||||||
@click="previewImage(contractFile)"
|
|
||||||
/>
|
|
||||||
<div class="file-info">
|
|
||||||
<span class="file-name">{{ contractFile.name }}</span>
|
|
||||||
<el-button type="text" size="small" @click="previewImage(contractFile)">
|
|
||||||
预览
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="document-preview">
|
|
||||||
<div class="file-icon">
|
|
||||||
<i class="iconfont-sys"></i>
|
|
||||||
</div>
|
|
||||||
<div class="file-info">
|
|
||||||
<span class="file-name">{{ contractFile.name }}</span>
|
|
||||||
<el-button type="primary" size="small" @click="downloadFile(contractFile)">
|
|
||||||
下载
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="no-file">
|
|
||||||
<i class="iconfont-sys"></i>
|
|
||||||
<span>暂无合同文件</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div style="display: flex; justify-content: flex-end; gap: 8px">
|
<div style="display: flex; justify-content: flex-end; gap: 8px">
|
||||||
@@ -268,13 +243,16 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { router } from '@/router'
|
import { router } from '@/router'
|
||||||
import { CrmService } from '@/api/crmApi'
|
import { CrmService } from '@/api/crmApi'
|
||||||
import { usePdfPreview } from '@/composables/usePdfPreview'
|
import { ElMessage } from 'element-plus'
|
||||||
import OrderDetailContent from '@/components/custom/OrderDetailContent.vue'
|
import OrderDetailContent from '@/components/custom/OrderDetailContent.vue'
|
||||||
import type { OrderData } from '@/composables/useOrderDetailDialog'
|
import type { OrderData } from '@/composables/useOrderDetailDialog'
|
||||||
import ApprovalTimeline from '@/components/custom/ApprovalTimeline.vue'
|
import ApprovalTimeline from '@/components/custom/ApprovalTimeline.vue'
|
||||||
|
import FilePreview from '@/components/custom/FilePreview.vue'
|
||||||
|
import { usePdfPreview } from '@/composables/usePdfPreview'
|
||||||
import { manageService } from '@/api/adminApi'
|
import { manageService } from '@/api/adminApi'
|
||||||
const timelineDialogVisible = ref(false)
|
const timelineDialogVisible = ref(false)
|
||||||
const approvalRecords = ref<any[]>([])
|
const approvalRecords = ref<any[]>([])
|
||||||
|
const isFinites = ref(false)
|
||||||
// import { useAuth } from '@/composables/useAuth'
|
// import { useAuth } from '@/composables/useAuth'
|
||||||
// const { hasAuth } = useAuth()
|
// const { hasAuth } = useAuth()
|
||||||
|
|
||||||
@@ -286,10 +264,6 @@
|
|||||||
const tableData = ref<any[]>([])
|
const tableData = ref<any[]>([])
|
||||||
const pagination = reactive({ currentPage: 1, pageSize: 10, total: 0 })
|
const pagination = reactive({ currentPage: 1, pageSize: 10, total: 0 })
|
||||||
|
|
||||||
// PDF 预览/打印(公共)
|
|
||||||
const { pdf, frameRef, openWithResponse, download, preparePreview, prepareImages } =
|
|
||||||
usePdfPreview()
|
|
||||||
|
|
||||||
// 订单详情弹窗
|
// 订单详情弹窗
|
||||||
const orderDialog = reactive({
|
const orderDialog = reactive({
|
||||||
visible: false,
|
visible: false,
|
||||||
@@ -370,13 +344,29 @@
|
|||||||
try {
|
try {
|
||||||
// 获取订单详情数据
|
// 获取订单详情数据
|
||||||
const res = await CrmService.checkStock({ id: row.id })
|
const res = await CrmService.checkStock({ id: row.id })
|
||||||
if (res?.contract) {
|
|
||||||
contractFile.value = {
|
// 处理合同文件
|
||||||
name: '合同文件',
|
const file_list = res?.file_list
|
||||||
url: res.contract_url || res.contract,
|
if (file_list?.contract) {
|
||||||
file_name: res.contract
|
contractFiles.value = processFiles(file_list.contract, '合同')
|
||||||
}
|
} else {
|
||||||
|
contractFiles.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理PI文件
|
||||||
|
if (file_list?.pi_doc) {
|
||||||
|
piFiles.value = processFiles(file_list.pi_doc, 'PI')
|
||||||
|
} else {
|
||||||
|
piFiles.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理水单文件
|
||||||
|
if (file_list?.transaction_slip) {
|
||||||
|
waterBillFiles.value = processFiles(file_list.transaction_slip, '水单')
|
||||||
|
} else {
|
||||||
|
waterBillFiles.value = []
|
||||||
|
}
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
// 转换数据格式以适配 OrderDetailDialog
|
// 转换数据格式以适配 OrderDetailDialog
|
||||||
const orderData: OrderData = res
|
const orderData: OrderData = res
|
||||||
@@ -390,16 +380,39 @@
|
|||||||
ElMessage.error('获取订单详情失败')
|
ElMessage.error('获取订单详情失败')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const contractFile = ref<{ name: string; url: string; file_name: string } | null>(null)
|
// 文件数据
|
||||||
|
const contractFiles = ref<Array<{ name: string; url: string; file_name: string }>>([])
|
||||||
|
const piFiles = ref<Array<{ name: string; url: string; file_name: string }>>([])
|
||||||
|
const waterBillFiles = ref<Array<{ name: string; url: string; file_name: string }>>([])
|
||||||
|
|
||||||
|
// 处理文件数据
|
||||||
|
const processFiles = (files: any[], type: string) => {
|
||||||
|
if (!files || !Array.isArray(files)) return []
|
||||||
|
return files.map((file: any) => ({
|
||||||
|
name: `${type}文件`,
|
||||||
|
url: file.file_full_url || file.file_url,
|
||||||
|
file_name: file.file_url
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
const handleView1 = async (row: any) => {
|
const handleView1 = async (row: any) => {
|
||||||
const res = await CrmService.checkStock({ id: row.object_id })
|
const res = await CrmService.checkStock({ id: row.object_id })
|
||||||
|
|
||||||
|
// 处理合同文件
|
||||||
if (res?.contract) {
|
if (res?.contract) {
|
||||||
contractFile.value = {
|
contractFiles.value = processFiles(res.contract, '合同')
|
||||||
name: '合同文件',
|
|
||||||
url: res.contract_url || res.contract,
|
|
||||||
file_name: res.contract
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理PI文件
|
||||||
|
if (res?.pi_doc) {
|
||||||
|
piFiles.value = processFiles(res.pi_doc, 'PI')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理水单文件
|
||||||
|
if (res?.transaction_slip) {
|
||||||
|
waterBillFiles.value = processFiles(res.transaction_slip, '水单')
|
||||||
|
}
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
// 获取订单详情成功
|
// 获取订单详情成功
|
||||||
const orderData: OrderData = res
|
const orderData: OrderData = res
|
||||||
@@ -407,12 +420,6 @@
|
|||||||
orderDialog.title = '合塑实业-汽车事业部-备货单(客户下定)'
|
orderDialog.title = '合塑实业-汽车事业部-备货单(客户下定)'
|
||||||
orderDialog.visible = true
|
orderDialog.visible = true
|
||||||
}
|
}
|
||||||
// router.push({
|
|
||||||
// path: '/crmpc/stocking/final_show',
|
|
||||||
// query: { id: row.object_id } // 可带客户名等参数
|
|
||||||
// })
|
|
||||||
// router.push('/crmpc/stocking/final_show')
|
|
||||||
// TODO: 跳转或弹窗查看备货单
|
|
||||||
}
|
}
|
||||||
const handleCreateRepair = (row: any) => {
|
const handleCreateRepair = (row: any) => {
|
||||||
router.push({
|
router.push({
|
||||||
@@ -437,8 +444,16 @@
|
|||||||
console.log(err)
|
console.log(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// PDF 预览/打印(公共)
|
||||||
|
const { pdf, frameRef, openWithResponse, download, preparePreview, prepareImages } =
|
||||||
|
usePdfPreview()
|
||||||
//打印
|
//打印
|
||||||
const printfn = (row: any) => {
|
const printfn = (row: any) => {
|
||||||
|
if (row.approval_status == 2) {
|
||||||
|
isFinites.value = true
|
||||||
|
} else {
|
||||||
|
isFinites.value = false
|
||||||
|
}
|
||||||
CrmService.printStock({ id: row.id })
|
CrmService.printStock({ id: row.id })
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
openWithResponse(res)
|
openWithResponse(res)
|
||||||
@@ -450,116 +465,6 @@
|
|||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
})
|
})
|
||||||
}
|
|
||||||
// 判断是否为图片文件
|
|
||||||
const isImageFile = (file: { name: string; url: string; file_name: string }) => {
|
|
||||||
// 检查文件名
|
|
||||||
if (file.name && /\.(jpg|jpeg|png|gif|webp)$/i.test(file.name)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查file_name字段
|
|
||||||
if (file.file_name && file.file_name.startsWith('image/')) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查URL中的文件扩展名(去除查询参数)
|
|
||||||
if (file.url) {
|
|
||||||
const urlWithoutParams = file.url.split('?')[0] // 移除查询参数
|
|
||||||
if (/\.(jpg|jpeg|png|gif|webp)$/i.test(urlWithoutParams)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 预览图片
|
|
||||||
const previewImage = (file: { name: string; url: string; file_name: string }) => {
|
|
||||||
// 创建图片预览弹窗
|
|
||||||
const imagePreview = document.createElement('div')
|
|
||||||
imagePreview.style.cssText = `
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: rgba(0, 0, 0, 0.8);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 9999;
|
|
||||||
cursor: pointer;
|
|
||||||
`
|
|
||||||
|
|
||||||
const image = document.createElement('img')
|
|
||||||
image.src = file.url
|
|
||||||
image.alt = file.name
|
|
||||||
image.style.cssText = `
|
|
||||||
max-width: 90%;
|
|
||||||
max-height: 90%;
|
|
||||||
object-fit: contain;
|
|
||||||
border-radius: 4px;
|
|
||||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
|
||||||
`
|
|
||||||
|
|
||||||
const closeBtn = document.createElement('div')
|
|
||||||
closeBtn.innerHTML = '×'
|
|
||||||
closeBtn.style.cssText = `
|
|
||||||
position: absolute;
|
|
||||||
top: 20px;
|
|
||||||
right: 30px;
|
|
||||||
color: white;
|
|
||||||
font-size: 30px;
|
|
||||||
cursor: pointer;
|
|
||||||
z-index: 10000;
|
|
||||||
`
|
|
||||||
|
|
||||||
imagePreview.appendChild(image)
|
|
||||||
imagePreview.appendChild(closeBtn)
|
|
||||||
document.body.appendChild(imagePreview)
|
|
||||||
|
|
||||||
// 点击关闭
|
|
||||||
const closePreview = () => {
|
|
||||||
document.body.removeChild(imagePreview)
|
|
||||||
}
|
|
||||||
|
|
||||||
imagePreview.addEventListener('click', closePreview)
|
|
||||||
closeBtn.addEventListener('click', (e) => {
|
|
||||||
e.stopPropagation()
|
|
||||||
closePreview()
|
|
||||||
})
|
|
||||||
|
|
||||||
// ESC键关闭
|
|
||||||
const handleKeydown = (e: KeyboardEvent) => {
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
closePreview()
|
|
||||||
document.removeEventListener('keydown', handleKeydown)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
document.addEventListener('keydown', handleKeydown)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下载文件
|
|
||||||
const downloadFile = (file: { name: string; url: string; file_name: string }) => {
|
|
||||||
try {
|
|
||||||
const link = document.createElement('a')
|
|
||||||
link.href = file.url
|
|
||||||
link.download = file.name
|
|
||||||
link.target = '_blank'
|
|
||||||
document.body.appendChild(link)
|
|
||||||
link.click()
|
|
||||||
document.body.removeChild(link)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('下载失败:', error)
|
|
||||||
ElMessage.error('下载失败,请稍后重试')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 订单详情打印
|
|
||||||
const handleOrderPrint = (data: OrderData) => {
|
|
||||||
console.log('打印订单详情:', data)
|
|
||||||
// 可以在这里添加具体的打印逻辑
|
|
||||||
window.print()
|
|
||||||
}
|
}
|
||||||
//复制订单
|
//复制订单
|
||||||
const copys = (row: any) => {
|
const copys = (row: any) => {
|
||||||
@@ -684,17 +589,4 @@
|
|||||||
color: #ff0000;
|
color: #ff0000;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.no-file {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
color: #999;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-file i {
|
|
||||||
font-size: 48px;
|
|
||||||
color: #ddd;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user