备货单 加 审批流程
This commit is contained in:
@@ -0,0 +1,862 @@
|
||||
import { ref, reactive, watch, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { CrmService } from '@/api/crmApi'
|
||||
import { commonService } from '@/api/commonApi'
|
||||
import { vehicleService } from '@/api/vehicleApi'
|
||||
import { useUploadHeaders } from '@/composables/useUploadHeaders'
|
||||
|
||||
// 类型定义
|
||||
export interface BaseForm {
|
||||
pi_no: string
|
||||
biz_date: string
|
||||
clearance_country_id: string
|
||||
clearance_country_snapshot: string
|
||||
customer_source_id: string
|
||||
customer_source_snapshot: string
|
||||
customer_id: string
|
||||
customer_snapshot: string
|
||||
customer_country_id: string
|
||||
customer_country_snapshot: string
|
||||
declarant_name: string
|
||||
eta_ship_date: string
|
||||
shipping_method_id: string
|
||||
shipping_method_snapshot: string
|
||||
domestic_port_id: string
|
||||
domestic_port_snapshot: string
|
||||
trade_term_id: string
|
||||
trade_term_snapshot: string
|
||||
clearance_port_id: string
|
||||
clearance_port_snapshot: string
|
||||
latest_arrival_date: string
|
||||
contract_exchange_rate: string
|
||||
contract_exchange_rate_currency: string
|
||||
remark: string
|
||||
total_cif: number | undefined
|
||||
total_cif_currency: string
|
||||
total_cif_currency_snapshot: string
|
||||
is_final: string
|
||||
object_id: string | number
|
||||
contract: string
|
||||
contract_url?: string
|
||||
}
|
||||
|
||||
export interface ItemRow {
|
||||
sku_id: string
|
||||
vin?: string
|
||||
mileage?: number
|
||||
listing_price?: number | undefined
|
||||
listing_price_currency: string
|
||||
listing_price_currency_snapshot: string
|
||||
reduction_price?: number | undefined
|
||||
reduction_price_currency: string
|
||||
reduction_price_currency_snapshot: string
|
||||
model_snapshot: string
|
||||
color_interior_code: string
|
||||
color_interior_snapshot: string
|
||||
color_exterior_code: string
|
||||
color_exterior_snapshot: string
|
||||
unit_price: number | undefined
|
||||
handling_fee: string
|
||||
fob_transport_fee: number | undefined
|
||||
port_misc_fee: string
|
||||
retrofit_fee: string
|
||||
total_price: number | undefined
|
||||
official_price: number | undefined
|
||||
discount_price: number | undefined
|
||||
fob_fee?: number | undefined
|
||||
fob_fee_currency: string
|
||||
fob_fee_currency_snapshot: string
|
||||
helper_fee?: number | undefined
|
||||
helper_fee_currency: string
|
||||
helper_fee_currency_snapshot: string
|
||||
domestic_freight?: number | undefined
|
||||
domestic_freight_currency: string
|
||||
domestic_freight_currency_snapshot: string
|
||||
port_fee?: number | undefined
|
||||
port_fee_currency: string
|
||||
port_fee_currency_snapshot: string
|
||||
unit_price_currency: string
|
||||
unit_price_currency_snapshot: string
|
||||
total_price_currency: string
|
||||
total_price_currency_snapshot: string
|
||||
guide_price_currency: string
|
||||
guide_price_currency_snapshot: string
|
||||
discount?: number | undefined
|
||||
discount_currency: string
|
||||
discount_currency_snapshot: string
|
||||
contract_rate?: number | undefined
|
||||
profit: number | undefined
|
||||
profit_type_snapshot?: string
|
||||
modify_ids: string[]
|
||||
modify_list: Array<{ option_id: string; option_name_snapshot: string }>
|
||||
modify_fee_currency: string
|
||||
modify_fee_currency_snapshot: string
|
||||
}
|
||||
|
||||
export interface PaymentItem {
|
||||
remit_country_id: string
|
||||
remit_country_name_snapshot: string
|
||||
remit_date: string
|
||||
currency_code: string
|
||||
currency_name_snapshot: string
|
||||
account_id: string
|
||||
account_name_snapshot: string
|
||||
remitter_name: string
|
||||
amount: number | undefined
|
||||
}
|
||||
|
||||
export interface DialogState {
|
||||
visible: boolean
|
||||
search: { keyword: string }
|
||||
loading: boolean
|
||||
tableData: any[]
|
||||
pagination: { currentPage: number; pageSize: number; total: number }
|
||||
targetIndex?: number
|
||||
}
|
||||
|
||||
export function useStockingForm(isFinal = false, stockingId?: string | number) {
|
||||
const { uploadHeaders } = useUploadHeaders()
|
||||
const actionImageUplode = `${import.meta.env.VITE_API_URL}/ticket/upload?scene=stock_orders`
|
||||
|
||||
// 选项数据
|
||||
const channelOptions = ref<any>()
|
||||
const countryOptions = ref<any>()
|
||||
const modificationOptions = ref<any>()
|
||||
const currencyOptions = ref<any>()
|
||||
const accountOptions = ref<any>()
|
||||
const customerOptions = ref<any>()
|
||||
const portOptions = ref<any>()
|
||||
const portOptionsall = ref<any>()
|
||||
const wcolorOptions = ref<Array<any>>([])
|
||||
const ncolorOptions = ref<Array<any>>([])
|
||||
const transportOptions = ref<Array<any>>([])
|
||||
const trade_termsOptions = ref<Array<any>>([])
|
||||
|
||||
// 表单数据
|
||||
const baseForm = reactive<BaseForm>({
|
||||
pi_no: '',
|
||||
biz_date: '',
|
||||
clearance_country_id: '',
|
||||
clearance_country_snapshot: '',
|
||||
customer_source_id: '',
|
||||
customer_source_snapshot: '',
|
||||
customer_id: '',
|
||||
customer_snapshot: '',
|
||||
customer_country_id: '',
|
||||
customer_country_snapshot: '',
|
||||
declarant_name: '',
|
||||
eta_ship_date: '',
|
||||
shipping_method_id: '',
|
||||
shipping_method_snapshot: '',
|
||||
domestic_port_id: '',
|
||||
domestic_port_snapshot: '',
|
||||
trade_term_id: '',
|
||||
trade_term_snapshot: '',
|
||||
clearance_port_id: '',
|
||||
clearance_port_snapshot: '',
|
||||
latest_arrival_date: '',
|
||||
contract_exchange_rate: '',
|
||||
contract_exchange_rate_currency: 'USD',
|
||||
remark: '',
|
||||
total_cif: undefined,
|
||||
total_cif_currency: 'USD',
|
||||
total_cif_currency_snapshot: '',
|
||||
is_final: isFinal ? '1' : '0',
|
||||
object_id: stockingId || '0',
|
||||
contract: '',
|
||||
contract_url: ''
|
||||
})
|
||||
|
||||
// 创建新的订单项
|
||||
const newItem = (): ItemRow => ({
|
||||
sku_id: '',
|
||||
model_snapshot: '',
|
||||
mileage: 0,
|
||||
listing_price: undefined,
|
||||
listing_price_currency: 'USD',
|
||||
listing_price_currency_snapshot: '',
|
||||
reduction_price: undefined,
|
||||
reduction_price_currency: 'USD',
|
||||
reduction_price_currency_snapshot: '',
|
||||
color_interior_code: '',
|
||||
color_interior_snapshot: '',
|
||||
color_exterior_code: '',
|
||||
color_exterior_snapshot: '',
|
||||
unit_price: undefined,
|
||||
handling_fee: '',
|
||||
fob_transport_fee: undefined,
|
||||
port_misc_fee: '',
|
||||
retrofit_fee: '',
|
||||
total_price: undefined,
|
||||
official_price: undefined,
|
||||
discount_price: undefined,
|
||||
fob_fee: undefined,
|
||||
fob_fee_currency: 'USD',
|
||||
fob_fee_currency_snapshot: '',
|
||||
helper_fee: undefined,
|
||||
helper_fee_currency: 'USD',
|
||||
helper_fee_currency_snapshot: '',
|
||||
domestic_freight: undefined,
|
||||
domestic_freight_currency: 'USD',
|
||||
domestic_freight_currency_snapshot: '',
|
||||
port_fee: undefined,
|
||||
port_fee_currency: 'USD',
|
||||
port_fee_currency_snapshot: '',
|
||||
unit_price_currency: 'USD',
|
||||
unit_price_currency_snapshot: '',
|
||||
total_price_currency: 'USD',
|
||||
total_price_currency_snapshot: '',
|
||||
guide_price_currency: 'USD',
|
||||
guide_price_currency_snapshot: '',
|
||||
discount: undefined,
|
||||
discount_currency: 'USD',
|
||||
discount_currency_snapshot: '',
|
||||
contract_rate: 7.16,
|
||||
profit: undefined,
|
||||
modify_ids: [],
|
||||
modify_list: [],
|
||||
modify_fee_currency: 'USD',
|
||||
modify_fee_currency_snapshot: ''
|
||||
})
|
||||
|
||||
// 创建新的收款项
|
||||
const newPaymentItem = (): PaymentItem => ({
|
||||
remit_country_id: '',
|
||||
remit_country_name_snapshot: '',
|
||||
remit_date: '',
|
||||
currency_code: '',
|
||||
currency_name_snapshot: '',
|
||||
account_id: '',
|
||||
account_name_snapshot: '',
|
||||
remitter_name: '',
|
||||
amount: undefined
|
||||
})
|
||||
|
||||
const items = ref<ItemRow[]>([newItem()])
|
||||
const paymentItems = ref<PaymentItem[]>([newPaymentItem()])
|
||||
const contractFile = ref<{ name: string; url: string; file_name: string } | null>(null)
|
||||
|
||||
// 弹框状态
|
||||
const customerDialog = reactive<DialogState>({
|
||||
visible: false,
|
||||
search: { keyword: '' },
|
||||
loading: false,
|
||||
tableData: [],
|
||||
pagination: { currentPage: 1, pageSize: 10, total: 0 }
|
||||
})
|
||||
|
||||
const vehicleDialog = reactive<DialogState>({
|
||||
visible: false,
|
||||
search: { keyword: '' },
|
||||
loading: false,
|
||||
tableData: [],
|
||||
pagination: { currentPage: 1, pageSize: 10, total: 0 },
|
||||
targetIndex: -1
|
||||
})
|
||||
|
||||
// 数据加载方法
|
||||
const getgetChannel = async () => {
|
||||
const res = await CrmService.getChannel()
|
||||
channelOptions.value = res || []
|
||||
}
|
||||
|
||||
const getcustomer = async () => {
|
||||
const res = await commonService.getCustomerSelect()
|
||||
customerOptions.value = res || []
|
||||
}
|
||||
|
||||
const getarea = async () => {
|
||||
const res = await CrmService.getCountry()
|
||||
countryOptions.value = res || []
|
||||
}
|
||||
|
||||
const getmodification = async () => {
|
||||
const res = await commonService.getModificationSelect()
|
||||
modificationOptions.value = res || []
|
||||
}
|
||||
|
||||
const loadColorOptions = async () => {
|
||||
try {
|
||||
const res = await commonService.getColorSelect({ type: 1 })
|
||||
wcolorOptions.value = res
|
||||
const response = await commonService.getColorSelect({ type: 2 })
|
||||
ncolorOptions.value = response
|
||||
} catch (error) {
|
||||
console.error('获取颜色列表失败:', error)
|
||||
ElMessage.error('获取颜色列表失败')
|
||||
}
|
||||
}
|
||||
|
||||
const loadAccountOptions = async () => {
|
||||
try {
|
||||
const res = await commonService.getAccountSelect()
|
||||
accountOptions.value = res
|
||||
} catch (error) {
|
||||
console.error('获取账户列表失败:', error)
|
||||
ElMessage.error('获取账户列表失败')
|
||||
}
|
||||
}
|
||||
|
||||
const loadCurrencyOptions = async () => {
|
||||
try {
|
||||
const res = await commonService.getCurrencySelect()
|
||||
currencyOptions.value = res
|
||||
} catch (error) {
|
||||
console.error('获取币种列表失败:', error)
|
||||
ElMessage.error('获取币种列表失败')
|
||||
}
|
||||
}
|
||||
|
||||
const loadPortOptions = async () => {
|
||||
try {
|
||||
const res = await commonService.getPortSelect({ scene: 'domestic' })
|
||||
const resall = await commonService.getPortSelect({})
|
||||
portOptions.value = res
|
||||
portOptionsall.value = resall
|
||||
} catch (error) {
|
||||
console.error('获取港口列表失败:', error)
|
||||
ElMessage.error('获取港口列表失败')
|
||||
}
|
||||
}
|
||||
|
||||
const loadDictOptions = async () => {
|
||||
const response = await commonService.getDictSelect({ scope: '2,15' })
|
||||
transportOptions.value = response.transport
|
||||
trade_termsOptions.value = response.trade_terms
|
||||
}
|
||||
|
||||
// 币种相关方法
|
||||
const getCurrencyRate = (code: string): string => {
|
||||
try {
|
||||
const found = (currencyOptions?.value || []).find((c: any) => c.currency_code === code)
|
||||
return found?.rate || found?.exchange_rate || ''
|
||||
} catch (e) {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
const getCurrencyBounds = (code: string): { min: number; max: number; base: number } => {
|
||||
const found: any = (currencyOptions?.value || []).find((c: any) => c.currency_code === code) || {}
|
||||
const base = Number(found?.rate || found?.exchange_rate || 0) || 0
|
||||
const up = Number(found?.float_percent_up)
|
||||
const down = Number(found?.float_percent_down)
|
||||
if (!Number.isNaN(up) || !Number.isNaN(down)) {
|
||||
const upPct = (Number.isNaN(up) ? 0 : up) / 100
|
||||
const downPct = (Number.isNaN(down) ? 0 : down) / 100
|
||||
return { min: base * (1 - downPct), max: base * (1 + upPct), base }
|
||||
}
|
||||
return { min: base * 0.9, max: base * 1.1, base }
|
||||
}
|
||||
|
||||
const validateContractRate = () => {
|
||||
const code = baseForm.contract_exchange_rate_currency || items.value[0]?.unit_price_currency || 'USD'
|
||||
const { min, max } = getCurrencyBounds(code)
|
||||
const val = Number(baseForm.contract_exchange_rate)
|
||||
if (Number.isNaN(val)) return
|
||||
if (val < min) {
|
||||
baseForm.contract_exchange_rate = String(Number(min.toFixed(6)))
|
||||
ElMessage?.warning?.('合同汇率已按币种浮动下限自动纠正')
|
||||
} else if (val > max) {
|
||||
baseForm.contract_exchange_rate = String(Number(max.toFixed(6)))
|
||||
ElMessage?.warning?.('合同汇率已按币种浮动上限自动纠正')
|
||||
}
|
||||
}
|
||||
|
||||
// 金额包装方法
|
||||
const wrapMoney = (amount: any, currency: string, remark: string) => ({
|
||||
currency: currency || '',
|
||||
amount: amount === undefined || amount === null ? '' : String(amount),
|
||||
rate: getCurrencyRate(currency),
|
||||
remark
|
||||
})
|
||||
|
||||
// 利润计算方法
|
||||
const getRateNumber = (code: string): number => {
|
||||
const r = Number(getCurrencyRate(code))
|
||||
return Number.isNaN(r) ? 0 : r
|
||||
}
|
||||
|
||||
const toUSD = (amount: any, code?: string): number => {
|
||||
const val = amount === undefined || amount === null || amount === '' ? 0 : Number(amount)
|
||||
if (Number.isNaN(val)) return 0
|
||||
const cur = code || 'USD'
|
||||
const rateCur = getRateNumber(cur)
|
||||
const rateUSD = getRateNumber('USD') || 1
|
||||
if (!rateCur) return 0
|
||||
return (val * rateCur) / rateUSD
|
||||
}
|
||||
|
||||
const calcProfit = (it: any): number => {
|
||||
const unit = toUSD(it.unit_price, it.unit_price_currency)
|
||||
const retrofit = toUSD(it.retrofit_fee, (it as any).modify_fee_currency)
|
||||
const fob = toUSD(it.fob_transport_fee ?? (it as any).fob_fee, (it as any).fob_fee_currency)
|
||||
const handling = toUSD(it.handling_fee ?? (it as any).helper_fee, (it as any).helper_fee_currency)
|
||||
const port = toUSD(it.port_misc_fee ?? (it as any).port_fee, (it as any).port_fee_currency)
|
||||
|
||||
const mileageVal = Number(it.mileage ?? 0)
|
||||
if (mileageVal > 0) {
|
||||
// 二手车:用挂牌价与二手减价替代官方指导价与优惠
|
||||
const listing = toUSD(it.listing_price ?? (it as any).listing_price, (it as any).listing_price_currency)
|
||||
const reduction = toUSD(it.reduction_price ?? (it as any).reduction_price, (it as any).reduction_price_currency)
|
||||
return unit - (retrofit + fob + listing + reduction + handling + port)
|
||||
}
|
||||
|
||||
// 新车/里程<=0:保持原有计算(官方指导价与优惠)
|
||||
const guide = toUSD(it.official_price ?? (it as any).guide_price, (it as any).guide_price_currency)
|
||||
const discount = toUSD(it.discount_price ?? (it as any).discount, (it as any).discount_currency)
|
||||
return unit - (retrofit + fob + guide + discount + handling + port)
|
||||
}
|
||||
|
||||
// 合同文件相关方法
|
||||
const isImageFile = (file: { name: string; url: string; file_name: string }) => {
|
||||
return /\.(jpg|jpeg|png|gif)$/i.test(file.name) || file.file_name.startsWith('image/')
|
||||
}
|
||||
|
||||
const beforeContractUpload = (file: File) => {
|
||||
const isValidType = /\.(jpg|jpeg|png|gif|pdf|doc|docx|xls|xlsx|txt)$/i.test(file.name)
|
||||
if (!isValidType) {
|
||||
ElMessage.error('只能上传图片或文档文件!')
|
||||
return false
|
||||
}
|
||||
const isLt10M = file.size / 1024 / 1024 < 10
|
||||
if (!isLt10M) {
|
||||
ElMessage.error('文件大小不能超过 10MB!')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const handleContractUpload = (response: any) => {
|
||||
if (response.code === 200) {
|
||||
const fileInfo = {
|
||||
name: response.data.original_name || '合同文件',
|
||||
url: response.data.file_url,
|
||||
file_name: response.data.file_name
|
||||
}
|
||||
contractFile.value = fileInfo
|
||||
baseForm.contract = response.data.file_name
|
||||
ElMessage.success('合同上传成功!')
|
||||
} else {
|
||||
ElMessage.error(response.message || '合同上传失败!')
|
||||
}
|
||||
}
|
||||
|
||||
const removeContractFile = () => {
|
||||
contractFile.value = null
|
||||
baseForm.contract = ''
|
||||
ElMessage.success('合同文件已删除')
|
||||
}
|
||||
|
||||
// 订单项操作方法
|
||||
const copyRow = (idx: number) => {
|
||||
const copied = JSON.parse(JSON.stringify(items.value[idx])) as ItemRow
|
||||
items.value.splice(idx + 1, 0, copied)
|
||||
}
|
||||
|
||||
const addRowAfter = (idx: number) => {
|
||||
items.value.splice(idx + 1, 0, newItem())
|
||||
}
|
||||
|
||||
const removeRow = (idx: number) => {
|
||||
items.value.splice(idx, 1)
|
||||
}
|
||||
|
||||
// 收款项操作方法
|
||||
const addPaymentItem = () => {
|
||||
paymentItems.value.push(newPaymentItem())
|
||||
}
|
||||
|
||||
const removePaymentItem = (idx: number) => {
|
||||
if (paymentItems.value.length > 1) {
|
||||
paymentItems.value.splice(idx, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// 客户选择相关方法
|
||||
const openCustomerDialog = () => {
|
||||
customerDialog.visible = true
|
||||
customerDialog.pagination.currentPage = 1
|
||||
getCustomerList()
|
||||
}
|
||||
|
||||
const getCustomerList = async () => {
|
||||
customerDialog.loading = true
|
||||
try {
|
||||
const { currentPage, pageSize } = customerDialog.pagination
|
||||
const params = { current: currentPage, size: pageSize, keyword: customerDialog.search.keyword }
|
||||
const { data, current, size, total } = await CrmService.getcustomerList(params as any)
|
||||
customerDialog.tableData = data || []
|
||||
Object.assign(customerDialog.pagination, { currentPage: current, pageSize: size, total })
|
||||
} catch (e) {
|
||||
} finally {
|
||||
customerDialog.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleCustomerSizeChange = (size: number) => {
|
||||
customerDialog.pagination.pageSize = size
|
||||
getCustomerList()
|
||||
}
|
||||
|
||||
const handleCustomerCurrentChange = (page: number) => {
|
||||
customerDialog.pagination.currentPage = page
|
||||
getCustomerList()
|
||||
}
|
||||
|
||||
const chooseCustomer = (row: any) => {
|
||||
baseForm.customer_id = row.id || ''
|
||||
baseForm.customer_snapshot = row.contacts || row.name || ''
|
||||
customerDialog.visible = false
|
||||
}
|
||||
|
||||
// 车辆选择相关方法
|
||||
const openVehicleDialog = (index: number) => {
|
||||
vehicleDialog.targetIndex = index
|
||||
vehicleDialog.visible = true
|
||||
vehicleDialog.pagination.currentPage = 1
|
||||
getVehicleList()
|
||||
}
|
||||
|
||||
const getVehicleList = async () => {
|
||||
vehicleDialog.loading = true
|
||||
try {
|
||||
const { currentPage, pageSize } = vehicleDialog.pagination
|
||||
const params = { current: currentPage, size: pageSize, keyword: vehicleDialog.search.keyword }
|
||||
const { records, current, size, total } = await vehicleService.getVehicleList(params)
|
||||
vehicleDialog.tableData = records || []
|
||||
Object.assign(vehicleDialog.pagination, { currentPage: current, pageSize: size, total })
|
||||
} catch {
|
||||
ElMessage.error('获取车辆列表失败')
|
||||
} finally {
|
||||
vehicleDialog.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleVehicleSizeChange = (size: number) => {
|
||||
vehicleDialog.pagination.pageSize = size
|
||||
getVehicleList()
|
||||
}
|
||||
|
||||
const handleVehicleCurrentChange = (page: number) => {
|
||||
vehicleDialog.pagination.currentPage = page
|
||||
getVehicleList()
|
||||
}
|
||||
|
||||
const chooseVehicle = (row: any) => {
|
||||
const idx = vehicleDialog.targetIndex
|
||||
if (idx !== undefined && idx >= 0 && idx < items.value.length) {
|
||||
const target = items.value[idx]
|
||||
target.sku_id = row.id || ''
|
||||
target.model_snapshot = row.model_name || row.name || ''
|
||||
target.color_exterior_code = row.color_exterior_code || ''
|
||||
target.color_exterior_snapshot = row.color_exterior_text || ''
|
||||
target.color_interior_code = row.color_interior_code || ''
|
||||
target.color_interior_snapshot = row.color_interior_text || ''
|
||||
target.official_price = row.msrp ?? target.official_price
|
||||
if (row.currency) {
|
||||
target.guide_price_currency = row.currency
|
||||
}
|
||||
}
|
||||
vehicleDialog.visible = false
|
||||
}
|
||||
|
||||
// 数据回显方法
|
||||
const populateFromDetail = (res: any) => {
|
||||
if (!res) return
|
||||
|
||||
// 基础信息
|
||||
baseForm.pi_no = res.pi_no || ''
|
||||
baseForm.contract = res.contract || ''
|
||||
baseForm.biz_date = res.biz_date || ''
|
||||
baseForm.clearance_country_id = res.clearance_country_id || ''
|
||||
baseForm.clearance_country_snapshot = res.clearance_country_snapshot || ''
|
||||
baseForm.customer_source_id = res.customer_source_id || ''
|
||||
baseForm.customer_source_snapshot = res.customer_source_snapshot || ''
|
||||
baseForm.customer_id = res.customer_id || ''
|
||||
baseForm.customer_snapshot = res.customer_snapshot || ''
|
||||
baseForm.customer_country_id = res.customer_country_id || ''
|
||||
baseForm.customer_country_snapshot = res.customer_country_snapshot || ''
|
||||
baseForm.declarant_name = res.declarant_name || ''
|
||||
baseForm.eta_ship_date = res.eta_ship_date || ''
|
||||
baseForm.shipping_method_id = res.shipping_method_id || ''
|
||||
baseForm.shipping_method_snapshot = res.shipping_method_snapshot || ''
|
||||
baseForm.domestic_port_id = res.domestic_port_id || ''
|
||||
baseForm.domestic_port_snapshot = res.domestic_port_snapshot || ''
|
||||
baseForm.trade_term_id = res.trade_term_id || ''
|
||||
baseForm.trade_term_snapshot = res.trade_term_snapshot || ''
|
||||
baseForm.clearance_port_id = res.clearance_port_id || ''
|
||||
baseForm.clearance_port_snapshot = res.clearance_port_snapshot || ''
|
||||
baseForm.latest_arrival_date = res.latest_arrival_date || ''
|
||||
baseForm.remark = res.remark || ''
|
||||
|
||||
// 合计与汇率
|
||||
baseForm.total_cif = res.cif_total_amount ? Number(res.cif_total_amount) : undefined
|
||||
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 : []
|
||||
items.value = list.map((it: any) => ({
|
||||
sku_id: it.sku_id ? String(it.sku_id) : '',
|
||||
vin: it.vin || '',
|
||||
mileage: it.mileage ?? 0,
|
||||
model_snapshot: it.model_snapshot || '',
|
||||
listing_price: it.listing_price?.amount ? Number(it.listing_price.amount) : undefined,
|
||||
listing_price_currency: it.listing_price?.currency || 'USD',
|
||||
listing_price_currency_snapshot: '',
|
||||
reduction_price: it.reduction_price?.amount ? Number(it.reduction_price.amount) : undefined,
|
||||
reduction_price_currency: it.reduction_price?.currency || 'USD',
|
||||
reduction_price_currency_snapshot: '',
|
||||
color_interior_code: it.color_interior_code || '',
|
||||
color_interior_snapshot: it.color_interior_snapshot || '',
|
||||
color_exterior_code: it.color_exterior_code || '',
|
||||
color_exterior_snapshot: it.color_exterior_snapshot || '',
|
||||
unit_price: it.unit_price?.amount ? Number(it.unit_price.amount) : undefined,
|
||||
handling_fee: it.handling_fee?.amount ?? '',
|
||||
fob_transport_fee: it.fob_transport_fee?.amount ? Number(it.fob_transport_fee.amount) : undefined,
|
||||
port_misc_fee: it.port_misc_fee?.amount ?? '',
|
||||
retrofit_fee: it.retrofit_fee?.amount ?? '',
|
||||
total_price: it.total_price?.amount ? Number(it.total_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,
|
||||
fob_fee: undefined,
|
||||
fob_fee_currency: it.fob_transport_fee?.currency || 'USD',
|
||||
fob_fee_currency_snapshot: '',
|
||||
helper_fee: undefined,
|
||||
helper_fee_currency: it.handling_fee?.currency || 'USD',
|
||||
helper_fee_currency_snapshot: '',
|
||||
domestic_freight: undefined,
|
||||
domestic_freight_currency: it.domestic_freight?.currency || 'USD',
|
||||
domestic_freight_currency_snapshot: '',
|
||||
port_fee: undefined,
|
||||
port_fee_currency: it.port_misc_fee?.currency || 'USD',
|
||||
port_fee_currency_snapshot: '',
|
||||
unit_price_currency: it.unit_price?.currency || 'USD',
|
||||
unit_price_currency_snapshot: '',
|
||||
total_price_currency: it.total_price?.currency || 'USD',
|
||||
total_price_currency_snapshot: '',
|
||||
guide_price_currency: it.official_price?.currency || 'USD',
|
||||
guide_price_currency_snapshot: '',
|
||||
discount: undefined,
|
||||
discount_currency: it.discount_price?.currency || 'USD',
|
||||
discount_currency_snapshot: '',
|
||||
contract_rate: baseForm.contract_exchange_rate ? Number(baseForm.contract_exchange_rate) : undefined,
|
||||
profit: undefined,
|
||||
profit_type_snapshot: '',
|
||||
modify_ids: Array.isArray(it.modify_list) ? it.modify_list.map((m: any) => Number(m.option_id)) : [],
|
||||
modify_list: Array.isArray(it.modify_list)
|
||||
? it.modify_list.map((m: any) => ({ option_id: String(m.option_id), option_name_snapshot: m.option_name_snapshot }))
|
||||
: [],
|
||||
modify_fee_currency: it.retrofit_fee?.currency || 'USD',
|
||||
modify_fee_currency_snapshot: ''
|
||||
}))
|
||||
// 计划收款
|
||||
const pays = Array.isArray(res.account_list) ? res.account_list : []
|
||||
paymentItems.value = pays.map((p: any) => ({
|
||||
remit_country_id: p.remit_country_id ? Number(p.remit_country_id) : '',
|
||||
remit_country_name_snapshot: p.remit_country_name_snapshot || '',
|
||||
remit_date: p.remit_date || '',
|
||||
currency_code: p.currency_code || '',
|
||||
currency_name_snapshot: p.currency_name_snapshot || '',
|
||||
account_id: p.account_id ? String(p.account_id) : '',
|
||||
account_name_snapshot: p.account_name_snapshot || '',
|
||||
remitter_name: p.remitter_name || '',
|
||||
amount: p.amount ? Number(p.amount) : undefined
|
||||
}))
|
||||
// 合同文件回显
|
||||
if (res.contract) {
|
||||
contractFile.value = {
|
||||
name: '合同文件',
|
||||
url: res.contract_url || res.contract,
|
||||
file_name: res.contract
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 提交方法
|
||||
const handleSubmit = async () => {
|
||||
const mappedItems = items.value.map((it) => ({
|
||||
sku_id: it.sku_id,
|
||||
vin: it.vin || '',
|
||||
mileage: it.mileage,
|
||||
model_snapshot: it.model_snapshot,
|
||||
color_interior_code: it.color_interior_code,
|
||||
color_interior_snapshot: it.color_interior_snapshot,
|
||||
color_exterior_code: it.color_exterior_code,
|
||||
color_exterior_snapshot: it.color_exterior_snapshot,
|
||||
unit_price: wrapMoney(it.unit_price, (it as any).unit_price_currency, '单价'),
|
||||
handling_fee: wrapMoney(it.handling_fee, (it as any).helper_fee_currency, '手续费'),
|
||||
fob_transport_fee: wrapMoney(
|
||||
it.fob_transport_fee ?? (it as any).fob_fee,
|
||||
(it as any).fob_fee_currency,
|
||||
'FOB运输费'
|
||||
),
|
||||
port_misc_fee: wrapMoney(
|
||||
it.port_misc_fee ?? (it as any).port_fee,
|
||||
(it as any).port_fee_currency,
|
||||
'港杂费'
|
||||
),
|
||||
retrofit_fee: wrapMoney((it as any).retrofit_fee, (it as any).modify_fee_currency, '改装费'),
|
||||
modify_list: it.modify_list,
|
||||
total_price: wrapMoney(it.total_price, (it as any).total_price_currency, '总价'),
|
||||
official_price: wrapMoney(
|
||||
(it as any).official_price ?? (it as any).guide_price,
|
||||
(it as any).guide_price_currency,
|
||||
'官方指导价'
|
||||
),
|
||||
discount_price: wrapMoney(
|
||||
(it as any).discount_price ?? (it as any).discount,
|
||||
(it as any).discount_currency,
|
||||
'优惠额'
|
||||
),
|
||||
listing_price: wrapMoney(it.listing_price, (it as any).listing_price_currency, '挂牌价'),
|
||||
reduction_price: wrapMoney(it.reduction_price, (it as any).reduction_price_currency, '二手减价')
|
||||
}))
|
||||
|
||||
const payload = {
|
||||
...baseForm,
|
||||
veh_list: mappedItems,
|
||||
account_list: paymentItems.value
|
||||
}
|
||||
|
||||
try {
|
||||
const { message } = await CrmService.addStock(payload as any)
|
||||
ElMessage.success(message || '保存成功')
|
||||
setTimeout(() => {
|
||||
window.location.href = '/crmpc/stocking/stocking_list'
|
||||
}, 1000)
|
||||
} catch (e) {
|
||||
ElMessage.error('保存失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 监听器
|
||||
watch(
|
||||
() => baseForm.contract_exchange_rate_currency,
|
||||
(newCurrency) => {
|
||||
if (newCurrency) {
|
||||
baseForm.contract_exchange_rate = getCurrencyRate(newCurrency)
|
||||
validateContractRate()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => baseForm.contract_exchange_rate,
|
||||
(newCurrency) => {
|
||||
if (newCurrency) {
|
||||
validateContractRate()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
items,
|
||||
(val) => {
|
||||
val.forEach((it: any, index: number) => {
|
||||
const profit = calcProfit(it)
|
||||
if (items.value[index]) items.value[index].profit = isNaN(profit) ? 0 : Number(profit.toFixed(2))
|
||||
})
|
||||
|
||||
// 合计到岸价 = 所有单价相加
|
||||
const sum = (val || []).reduce((acc: number, cur: any) => {
|
||||
const n = cur?.unit_price === undefined || cur?.unit_price === null || cur?.unit_price === '' ? 0 : Number(cur.unit_price)
|
||||
return acc + (isNaN(n) ? 0 : n)
|
||||
}, 0)
|
||||
baseForm.total_cif = Number(sum.toFixed(2))
|
||||
|
||||
// 同步合计币种为第一行单价币种(若有)
|
||||
if (items.value.length > 0) {
|
||||
const c = items.value[0]?.unit_price_currency
|
||||
if (c) baseForm.total_cif_currency = c
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
// 初始化方法
|
||||
const initializeForm = async () => {
|
||||
await Promise.all([
|
||||
getcustomer(),
|
||||
loadCurrencyOptions(),
|
||||
getgetChannel(),
|
||||
getarea(),
|
||||
getmodification(),
|
||||
loadColorOptions(),
|
||||
loadAccountOptions(),
|
||||
loadPortOptions(),
|
||||
loadDictOptions()
|
||||
])
|
||||
|
||||
// 设置默认汇率
|
||||
baseForm.contract_exchange_rate = getCurrencyRate('USD')
|
||||
}
|
||||
|
||||
return {
|
||||
// 数据
|
||||
baseForm,
|
||||
items,
|
||||
paymentItems,
|
||||
contractFile,
|
||||
customerDialog,
|
||||
vehicleDialog,
|
||||
|
||||
// 选项数据
|
||||
channelOptions,
|
||||
countryOptions,
|
||||
modificationOptions,
|
||||
currencyOptions,
|
||||
accountOptions,
|
||||
customerOptions,
|
||||
portOptions,
|
||||
portOptionsall,
|
||||
wcolorOptions,
|
||||
ncolorOptions,
|
||||
transportOptions,
|
||||
trade_termsOptions,
|
||||
|
||||
// 上传相关
|
||||
actionImageUplode,
|
||||
uploadHeaders,
|
||||
|
||||
// 方法
|
||||
initializeForm,
|
||||
populateFromDetail,
|
||||
handleSubmit,
|
||||
getCurrencyRate,
|
||||
validateContractRate,
|
||||
wrapMoney,
|
||||
calcProfit,
|
||||
|
||||
// 合同文件方法
|
||||
isImageFile,
|
||||
beforeContractUpload,
|
||||
handleContractUpload,
|
||||
removeContractFile,
|
||||
|
||||
// 订单项方法
|
||||
copyRow,
|
||||
addRowAfter,
|
||||
removeRow,
|
||||
newItem,
|
||||
|
||||
// 收款项方法
|
||||
addPaymentItem,
|
||||
removePaymentItem,
|
||||
newPaymentItem,
|
||||
|
||||
// 客户选择方法
|
||||
openCustomerDialog,
|
||||
getCustomerList,
|
||||
handleCustomerSizeChange,
|
||||
handleCustomerCurrentChange,
|
||||
chooseCustomer,
|
||||
|
||||
// 车辆选择方法
|
||||
openVehicleDialog,
|
||||
getVehicleList,
|
||||
handleVehicleSizeChange,
|
||||
handleVehicleCurrentChange,
|
||||
chooseVehicle
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user