Files
art-design/src/composables/useStockingForm.ts
T

908 lines
30 KiB
TypeScript
Raw Normal View History

2025-09-08 19:09:55 +08:00
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
2025-09-10 18:11:39 +08:00
pick_up_date: string
collect_all_date: string
2025-09-08 19:09:55 +08:00
contract_exchange_rate: string
2025-09-11 17:44:37 +08:00
settlement_currency: string
2025-09-08 19:09:55 +08:00
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
2025-09-10 18:11:39 +08:00
ocean_freight: string
ocean_freight_currency: string
ocean_freight_currency_snapshot: string
2025-09-08 19:09:55 +08:00
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: '',
2025-09-11 17:44:37 +08:00
settlement_currency: 'USD',
2025-09-08 19:09:55 +08:00
remark: '',
total_cif: undefined,
total_cif_currency: 'USD',
total_cif_currency_snapshot: '',
is_final: isFinal ? '1' : '0',
object_id: stockingId || '0',
contract: '',
2025-09-10 18:11:39 +08:00
contract_url: '',
pick_up_date:'',
collect_all_date: ''
2025-09-08 19:09:55 +08:00
})
// 创建新的订单项
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: '',
2025-09-10 18:11:39 +08:00
ocean_freight: '',
ocean_freight_currency: 'USD',
ocean_freight_currency_snapshot: '',
2025-09-08 19:09:55 +08:00
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: '',
2025-09-12 17:49:07 +08:00
currency_code: 'USD',
2025-09-08 19:09:55 +08:00
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()
2025-09-12 17:49:07 +08:00
res.forEach((item: any) => {
item.cn_addrs = item.cn_addr + '(' + item.en_addr + ')'
})
console.log(res)
2025-09-08 19:09:55 +08:00
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 = () => {
2025-09-11 17:44:37 +08:00
const code = baseForm.settlement_currency || items.value[0]?.unit_price_currency || 'USD'
2025-09-08 19:09:55 +08:00
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)
2025-09-10 18:11:39 +08:00
const ocean =toUSD(it.ocean_freight ?? (it as any).ocean_freight, (it as any).ocean_freight_currency)
2025-09-08 19:09:55 +08:00
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)
2025-09-10 18:11:39 +08:00
return unit - (retrofit + fob + listing + reduction + handling + port + ocean)
2025-09-08 19:09:55 +08:00
}
// 新车/里程<=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)
2025-09-10 18:11:39 +08:00
return unit - (retrofit + fob + guide + discount + handling + port + ocean)
2025-09-08 19:09:55 +08:00
}
// 合同文件相关方法
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 || ''
2025-09-10 18:11:39 +08:00
baseForm.customer_country_id = row.country_id || ''
baseForm.customer_country_snapshot = row.country_name || ''
2025-09-12 17:49:07 +08:00
baseForm.customer_source_id = row.channel_id || ''
baseForm.customer_source_snapshot = row.channel_name || ''
2025-09-08 19:09:55 +08:00
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
// 基础信息
2025-09-10 18:11:39 +08:00
baseForm.pick_up_date = res.pick_up_date || ''
baseForm.collect_all_date = res.collect_all_date || ''
2025-09-08 19:09:55 +08:00
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 ?? '',
2025-09-10 18:11:39 +08:00
ocean_freight: it.ocean_freight?.amount ?? '',
ocean_freight_currency: it.ocean_freight?.currency || 'USD',
ocean_freight_currency_snapshot: '',
2025-09-08 19:09:55 +08:00
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
}
}
}
// 提交方法
2025-09-10 18:11:39 +08:00
const handleSubmit = async (type: number, edit?: string) => {
2025-09-08 19:09:55 +08:00
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,
'港杂费'
),
2025-09-10 18:11:39 +08:00
ocean_freight: wrapMoney(it.ocean_freight, (it as any).ocean_freight_currency, '海运费'),
2025-09-08 19:09:55 +08:00
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, '二手减价')
}))
2025-09-11 17:44:37 +08:00
// 从提交参数中移除 settlement_currency
2025-09-10 18:11:39 +08:00
const baseFormWithoutCur = { ...(baseForm as any) }
delete (baseFormWithoutCur as any).total_cif
delete (baseFormWithoutCur as any).total_cif_currency
delete (baseFormWithoutCur as any).total_cif_currency_snapshot
delete (baseFormWithoutCur as any).contract_url
2025-09-08 19:09:55 +08:00
const payload = {
2025-09-10 18:11:39 +08:00
...baseFormWithoutCur,
2025-09-08 19:09:55 +08:00
veh_list: mappedItems,
2025-09-10 18:11:39 +08:00
account_list: paymentItems.value,
approval_status: type
2025-09-08 19:09:55 +08:00
}
try {
2025-09-10 18:11:39 +08:00
if (edit) {
const { message } = await CrmService.editStock({
...payload,
id: edit
} as any)
ElMessage.success(message || '保存成功')
} else {
const { message } = await CrmService.addStock(payload as any)
ElMessage.success(message || '保存成功')
}
2025-09-08 19:09:55 +08:00
setTimeout(() => {
window.location.href = '/crmpc/stocking/stocking_list'
}, 1000)
} catch (e) {
ElMessage.error('保存失败')
}
}
// 监听器
watch(
2025-09-11 17:44:37 +08:00
() => baseForm.settlement_currency,
2025-09-08 19:09:55 +08:00
(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')
2025-09-12 17:49:07 +08:00
// 设置预计发送日默认为当天
const today = new Date()
const year = today.getFullYear()
const month = String(today.getMonth() + 1).padStart(2, '0')
const day = String(today.getDate()).padStart(2, '0')
baseForm.biz_date = `${year}-${month}-${day}`
2025-09-08 19:09:55 +08:00
}
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
}
}