diff --git a/src/api/crmApi.ts b/src/api/crmApi.ts index 66775bf..3843245 100644 --- a/src/api/crmApi.ts +++ b/src/api/crmApi.ts @@ -278,5 +278,11 @@ export class CrmService { params }) } - + //终极备货单 提交 + static stockultimateapproval(params: any) { + return request.post({ + url: '/crm/stock/order/ultimate/approval', + params + }) + } } diff --git a/src/composables/useStockingForm.ts b/src/composables/useStockingForm.ts index a75bdc0..5851e7d 100644 --- a/src/composables/useStockingForm.ts +++ b/src/composables/useStockingForm.ts @@ -45,6 +45,7 @@ export interface BaseForm { export interface ItemRow { sku_id: string vin?: string + _echo_vin?: boolean mileage?: number listing_price?: number | undefined listing_price_currency: string @@ -161,10 +162,10 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { clearance_port_snapshot: '', latest_arrival_date: '', contract_exchange_rate: '', - settlement_currency: 'USD', + settlement_currency: 'CNY', remark: '', total_cif: undefined, - total_cif_currency: 'USD', + total_cif_currency: 'CNY', total_cif_currency_snapshot: '', is_final: isFinal ? '1' : '0', object_id: stockingId || '0', @@ -178,12 +179,13 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { const newItem = (): ItemRow => ({ sku_id: '', model_snapshot: '', + _echo_vin: false, mileage: 0, listing_price: undefined, - listing_price_currency: 'USD', + listing_price_currency: 'CNY', listing_price_currency_snapshot: '', reduction_price: undefined, - reduction_price_currency: 'USD', + reduction_price_currency: 'CNY', reduction_price_currency_snapshot: '', color_interior_code: '', color_interior_snapshot: '', @@ -194,38 +196,38 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { fob_transport_fee: undefined, port_misc_fee: '', ocean_freight: '', - ocean_freight_currency: 'USD', + ocean_freight_currency: 'CNY', ocean_freight_currency_snapshot: '', retrofit_fee: '', total_price: undefined, official_price: undefined, discount_price: undefined, fob_fee: undefined, - fob_fee_currency: 'USD', + fob_fee_currency: 'CNY', fob_fee_currency_snapshot: '', helper_fee: undefined, - helper_fee_currency: 'USD', + helper_fee_currency: 'CNY', helper_fee_currency_snapshot: '', domestic_freight: undefined, - domestic_freight_currency: 'USD', + domestic_freight_currency: 'CNY', domestic_freight_currency_snapshot: '', port_fee: undefined, - port_fee_currency: 'USD', + port_fee_currency: 'CNY', port_fee_currency_snapshot: '', - unit_price_currency: 'USD', + unit_price_currency: 'CNY', unit_price_currency_snapshot: '', - total_price_currency: 'USD', + total_price_currency: 'CNY', total_price_currency_snapshot: '', - guide_price_currency: 'USD', + guide_price_currency: 'CNY', guide_price_currency_snapshot: '', discount: undefined, - discount_currency: 'USD', + discount_currency: 'CNY', discount_currency_snapshot: '', contract_rate: 7.16, profit: undefined, modify_ids: [], modify_list: [], - modify_fee_currency: 'USD', + modify_fee_currency: 'CNY', modify_fee_currency_snapshot: '' }) @@ -234,7 +236,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { remit_country_id: '', remit_country_name_snapshot: '', remit_date: '', - currency_code: 'USD', + currency_code: 'CNY', currency_name_snapshot: '', account_id: '', account_name_snapshot: '', @@ -280,7 +282,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { res.forEach((item: any) => { item.cn_addrs = item.cn_addr + '(' + item.en_addr + ')' }) - console.log(res) + // console.log(res) countryOptions.value = res || [] } @@ -390,34 +392,69 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { return Number.isNaN(r) ? 0 : r } - const toUSD = (amount: any, code?: string): number => { + const convertCurrency = (amount: any, fromCode?: string, toCode?: 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 from = fromCode || 'USD' + const to = toCode || 'USD' + if (from === to) return val + const rateFrom = getRateNumber(from) + const rateTo = getRateNumber(to) || 1 + if (!rateFrom) return 0 + return (val * rateFrom) / rateTo } 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 ocean =toUSD(it.ocean_freight ?? (it as any).ocean_freight, (it as any).ocean_freight_currency) + const targetCurrency = baseForm.settlement_currency || 'USD' + const unit = convertCurrency(it.unit_price, it.unit_price_currency, targetCurrency) + const retrofit = convertCurrency(it.retrofit_fee, (it as any).modify_fee_currency, targetCurrency) + const fob = convertCurrency( + it.fob_transport_fee ?? (it as any).fob_fee, + (it as any).fob_fee_currency, + targetCurrency + ) + const handling = convertCurrency( + it.handling_fee ?? (it as any).helper_fee, + (it as any).helper_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 + ) 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) + const listing = convertCurrency( + it.listing_price ?? (it as any).listing_price, + (it as any).listing_price_currency, + targetCurrency + ) + const reduction = convertCurrency( + it.reduction_price ?? (it as any).reduction_price, + (it as any).reduction_price_currency, + targetCurrency + ) return unit - (retrofit + fob + listing + reduction + handling + port + ocean) } // 新车/里程<=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) + const guide = convertCurrency( + it.official_price ?? (it as any).guide_price, + (it as any).guide_price_currency, + targetCurrency + ) + const discount = convertCurrency( + it.discount_price ?? (it as any).discount, + (it as any).discount_currency, + targetCurrency + ) return unit - (retrofit + fob + guide + discount + handling + port + ocean) } @@ -597,7 +634,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { 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_id = res.shipping_method_id ? String(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 || '' @@ -607,24 +644,25 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { baseForm.clearance_port_snapshot = res.clearance_port_snapshot || '' baseForm.latest_arrival_date = res.latest_arrival_date || '' baseForm.remark = res.remark || '' - + baseForm.settlement_currency = res.settlement_currency || 'CNY' // 合计与汇率 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) - + 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 || '', + _echo_vin: Boolean(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: it.listing_price?.currency || 'CNY', 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: it.reduction_price?.currency || 'CNY', reduction_price_currency_snapshot: '', color_interior_code: it.color_interior_code || '', color_interior_snapshot: it.color_interior_snapshot || '', @@ -635,32 +673,32 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { fob_transport_fee: it.fob_transport_fee?.amount ? Number(it.fob_transport_fee.amount) : undefined, port_misc_fee: it.port_misc_fee?.amount ?? '', ocean_freight: it.ocean_freight?.amount ?? '', - ocean_freight_currency: it.ocean_freight?.currency || 'USD', + ocean_freight_currency: it.ocean_freight?.currency || 'CNY', ocean_freight_currency_snapshot: '', 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: it.fob_transport_fee?.currency || 'CNY', fob_fee_currency_snapshot: '', helper_fee: undefined, - helper_fee_currency: it.handling_fee?.currency || 'USD', + helper_fee_currency: it.handling_fee?.currency || 'CNY', helper_fee_currency_snapshot: '', domestic_freight: undefined, - domestic_freight_currency: it.domestic_freight?.currency || 'USD', + domestic_freight_currency: it.domestic_freight?.currency || 'CNY', domestic_freight_currency_snapshot: '', port_fee: undefined, - port_fee_currency: it.port_misc_fee?.currency || 'USD', + port_fee_currency: it.port_misc_fee?.currency || 'CNY', port_fee_currency_snapshot: '', - unit_price_currency: it.unit_price?.currency || 'USD', + unit_price_currency: it.unit_price?.currency || 'CNY', unit_price_currency_snapshot: '', - total_price_currency: it.total_price?.currency || 'USD', + total_price_currency: it.total_price?.currency || 'CNY', total_price_currency_snapshot: '', - guide_price_currency: it.official_price?.currency || 'USD', + guide_price_currency: it.official_price?.currency || 'CNY', guide_price_currency_snapshot: '', discount: undefined, - discount_currency: it.discount_price?.currency || 'USD', + discount_currency: it.discount_price?.currency || 'CNY', discount_currency_snapshot: '', contract_rate: baseForm.contract_exchange_rate ? Number(baseForm.contract_exchange_rate) : undefined, profit: undefined, @@ -669,7 +707,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { 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: it.retrofit_fee?.currency || 'CNY', modify_fee_currency_snapshot: '' })) // 计划收款 @@ -680,7 +718,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { 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_id: p.account_id ? p.account_id : '', account_name_snapshot: p.account_name_snapshot || '', remitter_name: p.remitter_name || '', amount: p.amount ? Number(p.amount) : undefined @@ -696,7 +734,16 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { } // 提交方法 - const handleSubmit = async (type: number, edit?: string) => { + const handleSubmit = async (type: number, edit?: string, isfinal?: string) => { + // 提交校验:最终提交且为提交动作时(type=1),必须填写 VIN + const isFinalFlag = isfinal === '1' || (isfinal as any) === true + if (isFinalFlag && type === 1) { + const hasEmptyVin = (items.value || []).some((it) => !it.vin || String(it.vin).trim() === '') + if (hasEmptyVin) { + ElMessage.error('存在未填写车架号(VIN)的明细,请补全后再提交') + return + } + } const mappedItems = items.value.map((it) => ({ sku_id: it.sku_id, vin: it.vin || '', @@ -721,7 +768,8 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { ocean_freight: wrapMoney(it.ocean_freight, (it as any).ocean_freight_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, '总价'), + // total_price: wrapMoney(it.total_price, (it as any).total_price_currency, '总价'), + total_price: wrapMoney(it.unit_price, (it as any).unit_price_currency, '总价'), official_price: wrapMoney( (it as any).official_price ?? (it as any).guide_price, (it as any).guide_price_currency, @@ -761,7 +809,11 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { ElMessage.success(message || '保存成功') } setTimeout(() => { - window.location.href = '/crmpc/stocking/stocking_list' + if (isfinal == '1') { + window.location.href = '/crmpc/stocking/final_list' + } else { + window.location.href = '/crmpc/stocking/stocking_list' + } }, 1000) } catch (e) { ElMessage.error('保存失败') @@ -774,7 +826,14 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { (newCurrency) => { if (newCurrency) { baseForm.contract_exchange_rate = getCurrencyRate(newCurrency) - validateContractRate() + if (typeof validateContractRate === 'function') { + validateContractRate() + } + // 结算币种变化时,按新币种重算所有行利润 + (items.value || []).forEach((it: any, index: number) => { + const profit = calcProfit(it) + if (items.value[index]) items.value[index].profit = isNaN(profit) ? 0 : Number(profit.toFixed(2)) + }) } } ) @@ -783,7 +842,9 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { () => baseForm.contract_exchange_rate, (newCurrency) => { if (newCurrency) { - validateContractRate() + if (typeof validateContractRate === 'function') { + validateContractRate() + } } } ) @@ -827,7 +888,7 @@ export function useStockingForm(isFinal = false, stockingId?: string | number) { ]) // 设置默认汇率 - baseForm.contract_exchange_rate = getCurrencyRate('USD') + baseForm.contract_exchange_rate = getCurrencyRate('CNY') // 设置预计发送日默认为当天 const today = new Date() diff --git a/src/views/admin/approval/approval_add.vue b/src/views/admin/approval/approval_add.vue index f8bb745..9c7fb32 100644 --- a/src/views/admin/approval/approval_add.vue +++ b/src/views/admin/approval/approval_add.vue @@ -319,6 +319,7 @@ import { commonService } from '@/api/commonApi' import { manageService } from '@/api/adminApi' import { router } from '@/router' + defineOptions({ name: 'AdminApprovalFlow' }) //审批类型 AWF_STEP_TYPE const approvalType = ref([]) diff --git a/src/views/admin/approval/approval_edit.vue b/src/views/admin/approval/approval_edit.vue index d898f3d..57537e7 100644 --- a/src/views/admin/approval/approval_edit.vue +++ b/src/views/admin/approval/approval_edit.vue @@ -319,7 +319,7 @@ import { ElMessage } from 'element-plus' import { commonService } from '@/api/commonApi' import { manageService } from '@/api/adminApi' - + defineOptions({ name: 'AdminApprovalEdit' }) //审批类型 AWF_STEP_TYPE const approvalType = ref([]) //角色类型 diff --git a/src/views/admin/approval/approval_list.vue b/src/views/admin/approval/approval_list.vue index 97ac8cf..1764301 100644 --- a/src/views/admin/approval/approval_list.vue +++ b/src/views/admin/approval/approval_list.vue @@ -106,7 +106,7 @@ import { useAuth } from '@/composables/useAuth' import { router } from '@/router' const { hasAuth } = useAuth() - defineOptions({ name: 'VehicleColor' }) + defineOptions({ name: 'AdminApprovalList' }) // 响应式数据 const loading = ref(false) diff --git a/src/views/admin/approval/stocking_auth.vue b/src/views/admin/approval/stocking_auth.vue index 6ca5e9f..6fc7c83 100644 --- a/src/views/admin/approval/stocking_auth.vue +++ b/src/views/admin/approval/stocking_auth.vue @@ -116,6 +116,7 @@ import { commonService } from '@/api/commonApi' import OrderDetailContent from '@/components/custom/OrderDetailContent.vue' import type { OrderData } from '@/composables/useOrderDetailDialog' + defineOptions({ name: 'AdminStockingPage' }) const orderDialog = reactive({ orderData: {} as OrderData }) diff --git a/src/views/admin/approval/stocking_auth_detil.vue b/src/views/admin/approval/stocking_auth_detil.vue index d96c4da..65dab8b 100644 --- a/src/views/admin/approval/stocking_auth_detil.vue +++ b/src/views/admin/approval/stocking_auth_detil.vue @@ -135,6 +135,7 @@ import OrderDetailContent from '@/components/custom/OrderDetailContent.vue' import type { OrderData } from '@/composables/useOrderDetailDialog' import { router } from '@/router' + defineOptions({ name: 'AdminStockingAuthDetil' }) const { pdf, frameRef, download } = usePdfPreview() const route = useRoute() // const approval_id = route.query.id diff --git a/src/views/admin/customer/customeraudit.vue b/src/views/admin/customer/customeraudit.vue index 03390d4..deb92de 100644 --- a/src/views/admin/customer/customeraudit.vue +++ b/src/views/admin/customer/customeraudit.vue @@ -167,6 +167,7 @@ import { ref, reactive, onMounted, watch } from 'vue' import { useAuth } from '@/composables/useAuth' import { manageService } from '@/api/adminApi' + defineOptions({ name: 'AdminCustomerAudit' }) const { hasAuth } = useAuth() const keyword = ref('') const loading = ref(false) diff --git a/src/views/admin/customer/highseas.vue b/src/views/admin/customer/highseas.vue index 503411e..f302631 100644 --- a/src/views/admin/customer/highseas.vue +++ b/src/views/admin/customer/highseas.vue @@ -257,6 +257,7 @@ import { manageService } from '@/api/adminApi' import { useAuth } from '@/composables/useAuth' import emptyimg from '@/assets/img/crm/empty.png' + defineOptions({ name: 'AdminHighseas' }) const TIMELINE_PLACEMENT = 'top' const activecolor = '#3471ff' const { hasAuth } = useAuth() diff --git a/src/views/admin/customer/index.vue b/src/views/admin/customer/index.vue index 921eee4..74d3226 100644 --- a/src/views/admin/customer/index.vue +++ b/src/views/admin/customer/index.vue @@ -341,6 +341,7 @@ import { manageService } from '@/api/adminApi' import { useAuth } from '@/composables/useAuth' import emptyimg from '@/assets/img/crm/empty.png' + defineOptions({ name: 'AdminCustomer' }) const TIMELINE_PLACEMENT = 'top' const activecolor = '#3471ff' const { hasAuth } = useAuth() diff --git a/src/views/admin/customer/recycle.vue b/src/views/admin/customer/recycle.vue index db34887..c5f4332 100644 --- a/src/views/admin/customer/recycle.vue +++ b/src/views/admin/customer/recycle.vue @@ -154,6 +154,7 @@ import { ref, reactive, onMounted, watch } from 'vue' import { manageService } from '@/api/adminApi' import { useAuth } from '@/composables/useAuth' + defineOptions({ name: 'AdminRecycle' }) const { hasAuth } = useAuth() const selectValue = ref([]) const loading = ref(false) diff --git a/src/views/admin/finance/currency.vue b/src/views/admin/finance/currency.vue index a4bb94e..7596e42 100644 --- a/src/views/admin/finance/currency.vue +++ b/src/views/admin/finance/currency.vue @@ -182,7 +182,7 @@ import { financeService } from '@/api/financeApi' import { useAuth } from '@/composables/useAuth' const { hasAuth } = useAuth() - defineOptions({ name: 'Type ' }) + defineOptions({ name: 'TypeCurrency' }) const loading = ref(false) const dialogVisible = ref(false) const formRef = ref() diff --git a/src/views/admin/inquiry_system/index.vue b/src/views/admin/inquiry_system/index.vue index 3804990..996b433 100644 --- a/src/views/admin/inquiry_system/index.vue +++ b/src/views/admin/inquiry_system/index.vue @@ -349,6 +349,7 @@ import { CrmService } from '@/api/crmApi' import { manageService } from '@/api/adminApi' import { useAuth } from '@/composables/useAuth' + defineOptions({ name: 'InquirySystem' }) const { hasAuth } = useAuth() const loading = ref(false) const dialogType = ref('add') diff --git a/src/views/admin/stock/final_list_admin.vue b/src/views/admin/stock/final_list_admin.vue index b7ffe83..a833ef8 100644 --- a/src/views/admin/stock/final_list_admin.vue +++ b/src/views/admin/stock/final_list_admin.vue @@ -54,7 +54,18 @@ @@ -114,6 +125,37 @@ + + +
+
+ 下载 +
+
+ +
+