1568 lines
56 KiB
Vue
1568 lines
56 KiB
Vue
<template>
|
||
<div class="stocking-add-page">
|
||
<div class="header boxshadow">
|
||
<div class="title">合塑实业·汽车事业部-备货单(客户下定)</div>
|
||
<div class="subtitle">业务员:{{ getUserInfo.user.name }}</div>
|
||
</div>
|
||
<div class="boxshadow">
|
||
<div class="form-title">
|
||
<span class="border"></span>
|
||
<span class="title">基础信息</span>
|
||
</div>
|
||
<ElForm :model="baseForm" class="base-form">
|
||
<ElRow :gutter="12">
|
||
<ElCol :span="4">
|
||
<ElFormItem label="阿里订单号/PN号">
|
||
<ElInput v-model="baseForm.pi_no" placeholder="请输入阿里订单号/PN号" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="日期">
|
||
<ElDatePicker
|
||
v-model="baseForm.biz_date"
|
||
type="date"
|
||
value-format="YYYY-MM-DD"
|
||
format="YYYY-MM-DD"
|
||
placeholder="请选择日期"
|
||
style="width: 100%"
|
||
/>
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="清关目的国">
|
||
<el-select
|
||
v-model="baseForm.clearance_country_id"
|
||
filterable
|
||
placeholder="请选择国家"
|
||
@change="
|
||
(val) =>
|
||
(baseForm.clearance_country_snapshot =
|
||
(countryOptions || []).find((x: any) => x.id === val)?.cn_addr || '')
|
||
"
|
||
>
|
||
<el-option
|
||
v-for="item in countryOptions"
|
||
:key="item.id"
|
||
:label="item.cn_addr"
|
||
:value="item.id"
|
||
/>
|
||
</el-select>
|
||
<ElInput v-model="baseForm.clearance_country_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="客户来源">
|
||
<el-select
|
||
v-model="baseForm.customer_source_id"
|
||
filterable
|
||
placeholder="请选择客户渠道"
|
||
@change="
|
||
(val) =>
|
||
(baseForm.customer_source_snapshot =
|
||
(channelOptions || []).find((x: any) => x.id === val)?.name || '')
|
||
"
|
||
>
|
||
<el-option
|
||
v-for="item in channelOptions"
|
||
:key="item.id"
|
||
:label="item.name"
|
||
:value="item.id"
|
||
/>
|
||
</el-select>
|
||
<ElInput v-model="baseForm.customer_source_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="客户名称">
|
||
<ElInput
|
||
v-model="baseForm.customer_snapshot"
|
||
placeholder="请选择客户"
|
||
readonly
|
||
@click="openCustomerDialog"
|
||
>
|
||
<template #append>
|
||
<ElButton type="primary" text @click.stop="openCustomerDialog">选择</ElButton>
|
||
</template>
|
||
</ElInput>
|
||
<ElInput v-model="baseForm.customer_id" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="客户所在国">
|
||
<el-select
|
||
v-model="baseForm.customer_country_id"
|
||
filterable
|
||
placeholder="请选择国家"
|
||
@change="
|
||
(val) =>
|
||
(baseForm.customer_country_snapshot =
|
||
(countryOptions || []).find((x: any) => x.id === val)?.cn_addr || '')
|
||
"
|
||
>
|
||
<el-option
|
||
v-for="item in countryOptions"
|
||
:key="item.id"
|
||
:label="item.cn_addr"
|
||
:value="item.id"
|
||
/>
|
||
</el-select>
|
||
<ElInput v-model="baseForm.customer_country_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
</ElRow>
|
||
</ElForm>
|
||
</div>
|
||
<!-- 明细行 -->
|
||
<div class="boxshadow">
|
||
<div class="form-title">
|
||
<span class="border"></span>
|
||
<span class="title">订单详情</span>
|
||
</div>
|
||
<div class="items-wrap">
|
||
<div class="item-row" v-for="(item, idx) in items" :key="idx">
|
||
<ElRow :gutter="12">
|
||
<ElCol :span="8">
|
||
<ElFormItem label="车型" label-width="64px">
|
||
<ElInput
|
||
v-model="item.model_snapshot"
|
||
placeholder="请选择车型"
|
||
readonly
|
||
disabled
|
||
@click="openVehicleDialog(idx)"
|
||
>
|
||
<!-- <template #append>
|
||
<ElButton type="primary" text @click.stop="openVehicleDialog(idx)"
|
||
>选择</ElButton
|
||
>
|
||
</template> -->
|
||
</ElInput>
|
||
<ElInput v-model="item.sku_id" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="颜色/外饰" label-width="72px">
|
||
<el-select
|
||
v-model="item.color_exterior_snapshot"
|
||
filterable
|
||
placeholder="请选择内容"
|
||
@change="
|
||
(val) =>
|
||
(item.color_exterior_code =
|
||
(wcolorOptions || []).find((x: any) => x.color_text === val)?.color_code ||
|
||
'')
|
||
"
|
||
>
|
||
<ElOption
|
||
v-for="item in wcolorOptions"
|
||
:key="item.color_code"
|
||
:label="item.color_text"
|
||
:value="item.color_text"
|
||
/>
|
||
</el-select>
|
||
<ElInput v-model="item.color_exterior_code" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="颜色/内饰" label-width="72px">
|
||
<el-select
|
||
v-model="item.color_interior_snapshot"
|
||
filterable
|
||
placeholder="请选择内容"
|
||
@change="
|
||
(val) =>
|
||
(item.color_interior_code =
|
||
(ncolorOptions || []).find((x: any) => x.color_text === val)?.color_code ||
|
||
'')
|
||
"
|
||
>
|
||
<ElOption
|
||
v-for="item in ncolorOptions"
|
||
:key="item.color_code"
|
||
:label="item.color_text"
|
||
:value="item.color_text"
|
||
/>
|
||
</el-select>
|
||
<ElInput v-model="item.color_interior_code" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="8">
|
||
<ElFormItem label="改装" label-width="52px">
|
||
<el-select
|
||
v-model="item.modify_ids"
|
||
filterable
|
||
multiple
|
||
placeholder="请选择内容"
|
||
@change="
|
||
(vals) =>
|
||
(item.modify_list = (modificationOptions || [])
|
||
.filter((x: any) => (vals || []).includes(x.id))
|
||
.map((x: any) => ({ option_id: x.id, option_name_snapshot: x.name })))
|
||
"
|
||
>
|
||
<el-option
|
||
v-for="item in modificationOptions"
|
||
:key="item.id"
|
||
:label="item.name"
|
||
:value="item.id"
|
||
/>
|
||
</el-select>
|
||
</ElFormItem>
|
||
</ElCol>
|
||
</ElRow>
|
||
<ElRow :gutter="12">
|
||
<ElCol :span="4">
|
||
<ElFormItem label="改装费" label-width="60px">
|
||
<ElInput v-model.number="item.retrofit_fee" placeholder="请输入改装费">
|
||
<template #append>
|
||
<ElSelect v-model="item.modify_fee_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.modify_fee_currency_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="FOB段运费" label-width="84px">
|
||
<ElInput v-model.number="item.fob_transport_fee" placeholder="请输入FOB段运费">
|
||
<template #append>
|
||
<ElSelect v-model="item.fob_fee_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.fob_fee_currency_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="单价" label-width="52px">
|
||
<ElInput v-model.number="item.unit_price" placeholder="请输入单价">
|
||
<template #append>
|
||
<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>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="总价" label-width="52px">
|
||
<ElInput v-model.number="item.total_price" placeholder="请输入总价">
|
||
<template #append>
|
||
<ElSelect v-model="item.total_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.total_price_currency_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="官方指导价" label-width="85px">
|
||
<ElInput v-model.number="item.official_price" placeholder="请输入官方指导价">
|
||
<template #append>
|
||
<ElSelect v-model="item.guide_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.guide_price_currency_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="优惠" label-width="52px">
|
||
<ElInput v-model.number="item.discount_price" placeholder="请输入优惠额">
|
||
<template #append>
|
||
<ElSelect v-model="item.discount_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.discount_currency_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
</ElRow>
|
||
<ElRow :gutter="12">
|
||
<ElCol :span="4">
|
||
<ElFormItem label="手续费" label-width="60px">
|
||
<ElInput v-model.number="item.handling_fee" placeholder="请输入手续费">
|
||
<template #append>
|
||
<ElSelect v-model="item.helper_fee_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.helper_fee_currency_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<!-- <ElCol :span="4">
|
||
<ElFormItem label="国内运费" label-width="72px">
|
||
<ElInput v-model.number="item.domestic_freight" placeholder="请输入国内运费">
|
||
<template #append>
|
||
<ElSelect v-model="item.domestic_freight_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.domestic_freight_currency_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol> -->
|
||
<ElCol :span="4">
|
||
<ElFormItem label="港杂费" label-width="60px">
|
||
<ElInput v-model.number="item.port_misc_fee" placeholder="请输入港杂费">
|
||
<template #append>
|
||
<ElSelect v-model="item.port_fee_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.port_fee_currency_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="利润" label-width="52px">
|
||
<ElInput v-model="item.profit" placeholder="正在计算利润" disabled></ElInput>
|
||
<ElInput v-model="item.profit_type_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="8">
|
||
<ElFormItem label="车架号" label-width="70px">
|
||
<ElInput v-model.number="item.vin" placeholder="请输入" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
</ElRow>
|
||
</div>
|
||
<ElRow :gutter="12">
|
||
<ElCol :span="4">
|
||
<ElFormItem label="合计到岸价" label-width="85px">
|
||
<ElInput v-model.number="baseForm.total_cif" placeholder="请输入合计到岸价">
|
||
<template #append>
|
||
<ElSelect v-model="baseForm.total_cif_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="baseForm.total_cif_currency_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="合同汇率" label-width="70px">
|
||
<ElInput v-model="baseForm.contract_exchange_rate" placeholder="请输入" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
</ElRow>
|
||
</div>
|
||
</div>
|
||
<div class="boxshadow">
|
||
<div class="form-title">
|
||
<span class="border"></span>
|
||
<span class="title">运输详情</span>
|
||
</div>
|
||
<ElForm :model="baseForm" class="foot-form">
|
||
<ElRow :gutter="12">
|
||
<ElCol :span="4">
|
||
<ElFormItem label="清关人">
|
||
<ElInput v-model="baseForm.declarant_name" placeholder="请输入清关人" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="预计发送日">
|
||
<ElDatePicker
|
||
v-model="baseForm.eta_ship_date"
|
||
value-format="YYYY-MM-DD"
|
||
format="YYYY-MM-DD"
|
||
type="date"
|
||
placeholder="请选择日期"
|
||
style="width: 100%"
|
||
/>
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="运输方式">
|
||
<ElSelect
|
||
v-model="baseForm.shipping_method_id"
|
||
placeholder="请选择运输方式"
|
||
@change="
|
||
(val) =>
|
||
(baseForm.shipping_method_snapshot =
|
||
(transportOptions || []).find((x: any) => x.id === val)?.item_label || '')
|
||
"
|
||
>
|
||
<ElOption
|
||
v-for="t in transportOptions"
|
||
:key="t.id"
|
||
:label="t.item_label"
|
||
:value="t.id"
|
||
/>
|
||
</ElSelect>
|
||
<ElInput v-model="baseForm.shipping_method_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="国内收货港">
|
||
<ElSelect
|
||
v-model="baseForm.domestic_port_id"
|
||
placeholder="请选择国内收货商"
|
||
@change="
|
||
(val) =>
|
||
(baseForm.domestic_port_snapshot =
|
||
(portOptions || []).find((x: any) => x.id === val)?.port_name || '')
|
||
"
|
||
>
|
||
<ElOption v-for="p in portOptions" :key="p.id" :label="p.port_name" :value="p.id" />
|
||
</ElSelect>
|
||
<ElInput v-model="baseForm.domestic_port_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="贸易条款">
|
||
<ElSelect
|
||
v-model="baseForm.trade_term_id"
|
||
placeholder="请选择"
|
||
@change="
|
||
(val) =>
|
||
(baseForm.trade_term_snapshot =
|
||
(trade_termsOptions || []).find((x: any) => x.id === val)?.item_label || '')
|
||
"
|
||
>
|
||
<ElOption
|
||
v-for="t in trade_termsOptions"
|
||
:key="t.id"
|
||
:label="t.item_label"
|
||
:value="t.id"
|
||
/>
|
||
</ElSelect>
|
||
<ElInput v-model="baseForm.trade_term_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="清关目的港">
|
||
<ElSelect
|
||
v-model="baseForm.clearance_port_id"
|
||
placeholder="请选择"
|
||
@change="
|
||
(val) =>
|
||
(baseForm.clearance_port_snapshot =
|
||
(portOptionsall || []).find((x: any) => x.id === val)?.port_name || '')
|
||
"
|
||
>
|
||
<ElOption
|
||
v-for="p in portOptionsall"
|
||
:key="p.id"
|
||
:label="p.port_name"
|
||
:value="p.id"
|
||
/>
|
||
</ElSelect>
|
||
<ElInput v-model="baseForm.clearance_port_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
</ElRow>
|
||
<ElRow :gutter="12">
|
||
<ElCol :span="6">
|
||
<ElFormItem label="最迟到港时间">
|
||
<ElDatePicker
|
||
v-model="baseForm.latest_arrival_date"
|
||
type="date"
|
||
value-format="YYYY-MM-DD"
|
||
format="YYYY-MM-DD"
|
||
placeholder="请选择日期"
|
||
style="width: 100%"
|
||
/>
|
||
</ElFormItem>
|
||
</ElCol>
|
||
</ElRow>
|
||
</ElForm>
|
||
</div>
|
||
<div class="boxshadow">
|
||
<div class="form-title">
|
||
<span class="border"></span>
|
||
<span class="title">计划收款信息</span>
|
||
</div>
|
||
<div class="payment-section">
|
||
<div class="payment-items">
|
||
<div v-for="(payment, idx) in paymentItems" :key="idx" class="payment-item">
|
||
<ElForm :model="payment" label-width="55px" class="payment-form">
|
||
<ElRow :gutter="12">
|
||
<ElCol :span="4">
|
||
<ElFormItem label="汇款国">
|
||
<el-select v-model="payment.remit_country_id" filterable placeholder="请选择汇款国" @change="
|
||
(val) =>
|
||
(payment.remit_country_name_snapshot =
|
||
(countryOptions || []).find((x: any) => x.id === val)?.cn_addr || '')
|
||
">
|
||
<el-option
|
||
v-for="item in countryOptions"
|
||
:key="item.id"
|
||
:label="item.cn_addr"
|
||
:value="item.id"
|
||
/>
|
||
</el-select>
|
||
<ElInput v-model="payment.remit_country_name_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="日期">
|
||
<ElDatePicker
|
||
v-model="payment.remit_date"
|
||
type="date"
|
||
format="YYYY-MM-DD"
|
||
value-format="YYYY-MM-DD"
|
||
placeholder="请选择日期"
|
||
style="width: 100%"
|
||
/>
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="币种">
|
||
<ElSelect v-model="payment.currency_code" placeholder="请选择币种" @change="
|
||
(val) => {
|
||
const found = (currencyOptions || []).find((x: any) => x.currency_code === val)
|
||
payment.currency_name_snapshot = found?.currency_name || ''
|
||
}
|
||
">
|
||
<ElOption
|
||
v-for="c in currencyOptions"
|
||
:key="c.currency_code"
|
||
:label="c.currency_name"
|
||
:value="c.currency_code"
|
||
/>
|
||
</ElSelect>
|
||
<ElInput v-model="payment.currency_name_snapshot" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="账户">
|
||
<ElSelect v-model="payment.account_name_snapshot" placeholder="请选择账户" @change="
|
||
(val) =>
|
||
(payment.account_id =
|
||
(accountOptions || []).find((x: any) => x.account_number === val)?.id || '')
|
||
">
|
||
<ElOption
|
||
v-for="item in accountOptions"
|
||
:key="item.id"
|
||
:label="item.account_number"
|
||
:value="item.account_number"
|
||
/>
|
||
</ElSelect>
|
||
<ElInput v-model="payment.account_id" type="hidden" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="汇款人">
|
||
<ElInput v-model="payment.remitter_name" placeholder="请选择汇款人" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
<ElCol :span="4">
|
||
<ElFormItem label="金额">
|
||
<ElInput v-model.number="payment.amount" placeholder="请输入金额" />
|
||
</ElFormItem>
|
||
</ElCol>
|
||
</ElRow>
|
||
<ElRow :gutter="12">
|
||
<ElCol :span="24" style="text-align: right;">
|
||
<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>
|
||
</ElRow>
|
||
</ElForm>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- 上传合同 -->
|
||
<div class="boxshadow">
|
||
<div class="form-title">
|
||
<span class="border"></span>
|
||
<span class="title">上传合同</span>
|
||
</div>
|
||
<el-upload
|
||
class="upload-box"
|
||
:action="actionImageUplode"
|
||
:headers="uploadHeaders"
|
||
:show-file-list="false"
|
||
:on-success="handleContractUpload"
|
||
:before-upload="beforeContractUpload"
|
||
accept=".jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.txt"
|
||
>
|
||
<div class="qrcode-upload-box">
|
||
<input type="hidden" v-model="baseForm.contract"/>
|
||
<img v-if="!contractFile" class="avatar" src="@/assets/img/crm/contract.png" />
|
||
<div v-else class="file-preview">
|
||
<img v-if="isImageFile(contractFile)" :src="contractFile.url" class="preview-image" />
|
||
<div v-else class="file-icon">
|
||
<i class="iconfont-sys"></i>
|
||
<span class="file-name">{{ contractFile.name }}</span>
|
||
</div>
|
||
<div class="file-actions">
|
||
<el-button type="text" size="small" @click.stop="removeContractFile">删除</el-button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-upload>
|
||
</div>
|
||
<div class="form-card">
|
||
<!-- 底部信息 -->
|
||
<div class="submit-wrap">
|
||
<ElButton type="primary" size="large" class="submit-btn" @click="handleSubmit"
|
||
>提交</ElButton
|
||
>
|
||
</div>
|
||
</div>
|
||
<!-- 选择车型 弹框 -->
|
||
<ElDialog
|
||
v-model="vehicleDialog.visible"
|
||
title="选择车辆"
|
||
width="900px"
|
||
:close-on-click-modal="false"
|
||
top="40px"
|
||
>
|
||
<div
|
||
class="search-toolbar"
|
||
style="margin-bottom: 12px; display: flex; justify-content: flex-end; gap: 8px"
|
||
>
|
||
<el-input
|
||
v-model="vehicleDialog.search.keyword"
|
||
placeholder="请输入关键字"
|
||
clearable
|
||
style="width: 300px"
|
||
@keyup.enter="getVehicleList"
|
||
>
|
||
<template #suffix>
|
||
<el-icon class="clickable" @click="getVehicleList"><Search /></el-icon>
|
||
</template>
|
||
</el-input>
|
||
</div>
|
||
<ArtTable
|
||
:loading="vehicleDialog.loading"
|
||
:data="vehicleDialog.tableData"
|
||
:currentPage="vehicleDialog.pagination.currentPage"
|
||
:pageSize="vehicleDialog.pagination.pageSize"
|
||
:total="vehicleDialog.pagination.total"
|
||
@size-change="handleVehicleSizeChange"
|
||
@current-change="handleVehicleCurrentChange"
|
||
>
|
||
<template #default>
|
||
<ElTableColumn label="品牌" prop="brand_name" align="center" />
|
||
<ElTableColumn label="车系" prop="series_name" align="center" />
|
||
<ElTableColumn label="车型/配置" prop="model_name" min-width="160">
|
||
<template #default="scope">
|
||
<span class="primary">{{ scope.row.model_name }}</span>
|
||
</template>
|
||
</ElTableColumn>
|
||
<ElTableColumn label="年款" prop="model_year" width="80" align="center" />
|
||
<ElTableColumn label="指导价" prop="msrp" width="100" align="center" />
|
||
<ElTableColumn label="操作" width="100" align="center" fixed="right">
|
||
<template #default="scope">
|
||
<ElButton link type="primary" @click="chooseVehicle(scope.row)">选择</ElButton>
|
||
</template>
|
||
</ElTableColumn>
|
||
</template>
|
||
</ArtTable>
|
||
</ElDialog>
|
||
<!-- 选择客户 弹框 -->
|
||
<ElDialog
|
||
v-model="customerDialog.visible"
|
||
title="选择客户"
|
||
width="900px"
|
||
:close-on-click-modal="false"
|
||
top="40px"
|
||
>
|
||
<div
|
||
class="search-toolbar"
|
||
style="margin-bottom: 12px; display: flex; justify-content: flex-end; gap: 8px"
|
||
>
|
||
<el-input
|
||
v-model="customerDialog.search.keyword"
|
||
placeholder="请输入客户名称/电话"
|
||
clearable
|
||
style="width: 300px"
|
||
@keyup.enter="getCustomerList"
|
||
>
|
||
<template #suffix>
|
||
<el-icon class="clickable" @click="getCustomerList"><Search /></el-icon>
|
||
</template>
|
||
</el-input>
|
||
</div>
|
||
<ArtTable
|
||
:loading="customerDialog.loading"
|
||
:data="customerDialog.tableData"
|
||
:currentPage="customerDialog.pagination.currentPage"
|
||
:pageSize="customerDialog.pagination.pageSize"
|
||
:total="customerDialog.pagination.total"
|
||
@size-change="handleCustomerSizeChange"
|
||
@current-change="handleCustomerCurrentChange"
|
||
>
|
||
<template #default>
|
||
<ElTableColumn label="客户名称" prop="contacts" />
|
||
<ElTableColumn label="客户编码" prop="code" />
|
||
<ElTableColumn label="电话" prop="phone" />
|
||
<ElTableColumn label="公司" prop="company" />
|
||
<ElTableColumn label="操作" width="80" align="center" fixed="right">
|
||
<template #default="scope">
|
||
<ElButton link type="primary" @click="chooseCustomer(scope.row)">选择</ElButton>
|
||
</template>
|
||
</ElTableColumn>
|
||
</template>
|
||
</ArtTable>
|
||
</ElDialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ElMessage } from 'element-plus'
|
||
import { Search } from '@element-plus/icons-vue'
|
||
import { CrmService } from '@/api/crmApi'
|
||
import { commonService } from '@/api/commonApi'
|
||
import { vehicleService } from '@/api/vehicleApi'
|
||
import { useUserStore } from '@/store/modules/user'
|
||
import { watch } from 'vue'
|
||
import { useUploadHeaders } from '@/composables/useUploadHeaders'
|
||
const { uploadHeaders } = useUploadHeaders()
|
||
let actionImageUplode = `${import.meta.env.VITE_API_URL}/ticket/upload?scene=stock_orders`
|
||
const route = useRoute()
|
||
const stocking_id = route.query.id
|
||
const { getUserInfo } = useUserStore()
|
||
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 contractFile = ref<any>(null)
|
||
//渠道
|
||
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 transportOptions = ref<Array<any>>([])
|
||
const trade_termsOptions = ref<Array<any>>([])
|
||
const loadDictOptions = async () => {
|
||
const response = await commonService.getDictSelect({ scope: '2,15' })
|
||
transportOptions.value = response.transport
|
||
trade_termsOptions.value = response.trade_terms
|
||
}
|
||
// 合同文件相关方法
|
||
const isImageFile = (file: any) => {
|
||
if (!file) return false
|
||
const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp']
|
||
// 检查文件名
|
||
const fileName = file.name || file.file_name || ''
|
||
if (fileName && imageExtensions.some(ext => fileName.toLowerCase().endsWith(ext))) {
|
||
return true
|
||
}
|
||
// 检查URL中的文件扩展名(去除查询参数)
|
||
if (file.url) {
|
||
const urlWithoutParams = file.url.split('?')[0] // 移除查询参数
|
||
if (imageExtensions.some(ext => urlWithoutParams.toLowerCase().endsWith(ext))) {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
const beforeContractUpload = (file: any) => {
|
||
const isValidType = [
|
||
'image/jpeg',
|
||
'image/jpg',
|
||
'image/png',
|
||
'image/gif',
|
||
'image/webp',
|
||
'application/pdf',
|
||
'application/msword',
|
||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||
'application/vnd.ms-excel',
|
||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||
'text/plain'
|
||
].includes(file.type)
|
||
if (!isValidType) {
|
||
ElMessage.error('只能上传图片、PDF、Word、Excel或文本文件!')
|
||
return false
|
||
}
|
||
const isLt10M = file.size / 1024 / 1024 < 10
|
||
if (!isLt10M) {
|
||
ElMessage.error('文件大小不能超过 10MB!')
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
const handleContractUpload = (response: any) => {
|
||
if (response && response.code === 200) {
|
||
contractFile.value = {
|
||
name: response.data.original_name || '合同文件',
|
||
url: response.data.file_url,
|
||
file_name: response.data.file_name
|
||
}
|
||
baseForm.contract = response.data.file_name || ''
|
||
ElMessage.success('合同文件上传成功')
|
||
} else {
|
||
ElMessage.error('合同文件上传失败')
|
||
}
|
||
}
|
||
const removeContractFile = () => {
|
||
contractFile.value = null
|
||
ElMessage.success('合同文件已删除')
|
||
}
|
||
const stockingInfo = ref<any>()
|
||
const detailId = ref<string | number>('')
|
||
const populateFromDetail = (res: any) => {
|
||
if (!res) return
|
||
detailId.value = res.id || ''
|
||
// 基础信息
|
||
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 || '',
|
||
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: 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 getdetilfn = async () => {
|
||
const res = await CrmService.getStockDetail({ id: stocking_id })
|
||
stockingInfo.value = res
|
||
populateFromDetail(res)
|
||
}
|
||
onMounted(async () => {
|
||
getcustomer()
|
||
await loadCurrencyOptions()
|
||
getgetChannel()
|
||
getarea()
|
||
getmodification()
|
||
loadColorOptions()
|
||
loadAccountOptions()
|
||
loadPortOptions()
|
||
loadDictOptions()
|
||
// 设置默认汇率
|
||
baseForm.contract_exchange_rate = getCurrencyRate('USD')
|
||
// 如果有ID,加载详情数据
|
||
if (stocking_id) {
|
||
await getdetilfn()
|
||
}
|
||
})
|
||
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 baseForm = reactive({
|
||
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: '',
|
||
remark: '',
|
||
total_cif: undefined as number | undefined,
|
||
total_cif_currency: 'USD',
|
||
total_cif_currency_snapshot: '',
|
||
is_final: '1',
|
||
object_id: stocking_id,
|
||
contract: '',
|
||
contract_url: ''
|
||
})
|
||
type ItemRow = {
|
||
sku_id: string
|
||
vin: 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
|
||
}
|
||
|
||
const newItem = (): ItemRow => ({
|
||
sku_id: '',
|
||
vin: '',
|
||
model_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,
|
||
profit_type_snapshot: '',
|
||
modify_ids: [],
|
||
modify_list: [],
|
||
modify_fee_currency: 'USD',
|
||
modify_fee_currency_snapshot: ''
|
||
})
|
||
|
||
const items = ref<ItemRow[]>([newItem()])
|
||
// 监听币种变化,自动更新汇率
|
||
watch(
|
||
() => items.value[0].unit_price_currency,
|
||
(newCurrency) => {
|
||
if (newCurrency) {
|
||
baseForm.contract_exchange_rate = getCurrencyRate(newCurrency)
|
||
}
|
||
}
|
||
)
|
||
// 同时监听合计到岸价币种变化,联动更新合同汇率
|
||
watch(
|
||
() => baseForm.total_cif_currency,
|
||
(newCurrency) => {
|
||
if (newCurrency) {
|
||
baseForm.contract_exchange_rate = getCurrencyRate(newCurrency)
|
||
}
|
||
}
|
||
)
|
||
type 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
|
||
}
|
||
|
||
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 paymentItems = ref<PaymentItem[]>([newPaymentItem()])
|
||
|
||
const addPaymentItem = () => {
|
||
paymentItems.value.push(newPaymentItem())
|
||
}
|
||
|
||
const removePaymentItem = (idx: number) => {
|
||
if (paymentItems.value.length > 1) {
|
||
paymentItems.value.splice(idx, 1)
|
||
}
|
||
}
|
||
|
||
const wrapMoney = (amount: any, currency: string, remark: string) => ({
|
||
currency: currency || '',
|
||
amount: amount === undefined || amount === null ? '' : String(amount),
|
||
rate: getCurrencyRate(currency),
|
||
remark
|
||
})
|
||
// 计算单行利润 = 单价 - (改装费+FOB段运费+官方指导价+优惠+手续费+港杂费)
|
||
const calcProfit = (it: any): number => {
|
||
const toNum = (v: any) => (v === undefined || v === null || v === '' ? 0 : Number(v))
|
||
const unit = toNum(it.unit_price)
|
||
const retrofit = toNum(it.retrofit_fee)
|
||
const fob = toNum(it.fob_transport_fee ?? (it as any).fob_fee)
|
||
const guide = toNum(it.official_price ?? (it as any).guide_price)
|
||
const discount = toNum(it.discount_price ?? (it as any).discount)
|
||
const handling = toNum(it.handling_fee ?? (it as any).helper_fee)
|
||
const port = toNum(it.port_misc_fee ?? (it as any).port_fee)
|
||
return unit - (retrofit + fob + guide + discount + handling + port)
|
||
}
|
||
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 handleSubmit = async () => {
|
||
const mappedItems = items.value.map((it) => ({
|
||
sku_id: it.sku_id,
|
||
vin: it.vin,
|
||
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,
|
||
'优惠额'
|
||
)
|
||
}))
|
||
|
||
const payload = {
|
||
...baseForm,
|
||
veh_list: mappedItems,
|
||
account_list: paymentItems.value
|
||
}
|
||
try {
|
||
const { message } = await CrmService.addStock(payload as any)
|
||
ElMessage.success(message || '保存成功')
|
||
// 使用window.location进行强制跳转
|
||
setTimeout(() => {
|
||
window.location.href = '/crmpc/stocking/stocking_list'
|
||
}, 1000)
|
||
} catch (e) {
|
||
ElMessage.error('保存失败')
|
||
}
|
||
}
|
||
// 选择客户弹框逻辑
|
||
const customerDialog = reactive({
|
||
visible: false,
|
||
search: { keyword: '' },
|
||
loading: false,
|
||
tableData: [] as any[],
|
||
pagination: { currentPage: 1, pageSize: 10, total: 0 }
|
||
})
|
||
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 vehicleDialog = reactive({
|
||
visible: false,
|
||
targetIndex: -1,
|
||
search: { keyword: '' },
|
||
loading: false,
|
||
tableData: [] as any[],
|
||
pagination: { currentPage: 1, pageSize: 10, total: 0 }
|
||
})
|
||
|
||
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 >= 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
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
:deep(.el-input-group--append .el-input-group__append .el-select .el-select__wrapper) {
|
||
padding: 4px;
|
||
}
|
||
:deep(.el-select__selected-item span) {
|
||
font-size: 12px;
|
||
}
|
||
.form-title {
|
||
font-weight: bold;
|
||
color: #222;
|
||
margin-bottom: 15px;
|
||
}
|
||
.form-title .title {
|
||
margin-left: 6px;
|
||
}
|
||
.stocking-add-page {
|
||
// background: var(--art-main-bg-color);
|
||
min-height: 100vh;
|
||
}
|
||
|
||
.header {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 16px 20px;
|
||
margin-bottom: 12px;
|
||
|
||
.title {
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.subtitle {
|
||
color: var(--el-text-color-secondary);
|
||
}
|
||
}
|
||
|
||
.items-wrap {
|
||
margin-top: 6px;
|
||
}
|
||
|
||
.item-row {
|
||
padding: 8px 0;
|
||
}
|
||
|
||
.row-actions {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
justify-content: flex-end;
|
||
}
|
||
.row-actions span {
|
||
font-size: 12px;
|
||
cursor: pointer;
|
||
}
|
||
.row-actions .primary {
|
||
color: var(--el-color-primary);
|
||
cursor: pointer;
|
||
}
|
||
.row-actions .danger {
|
||
color: var(--el-color-danger);
|
||
cursor: pointer;
|
||
}
|
||
|
||
.submit-wrap {
|
||
display: flex;
|
||
justify-content: center;
|
||
padding: 24px 0 8px;
|
||
}
|
||
|
||
.submit-btn {
|
||
width: 220px;
|
||
height: 44px;
|
||
font-size: 16px;
|
||
}
|
||
.payment-item {
|
||
margin-bottom: 12px;
|
||
}
|
||
.upload-box { width: 200px; }
|
||
.file-preview {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.preview-image {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.file-icon {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: #f5f7fa;
|
||
border-radius: 4px;
|
||
border: 1px dashed #d9d9d9;
|
||
}
|
||
|
||
.file-icon i {
|
||
font-size: 32px;
|
||
color: #409eff;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.file-name {
|
||
font-size: 12px;
|
||
color: #606266;
|
||
text-align: center;
|
||
word-break: break-all;
|
||
padding: 0 8px;
|
||
}
|
||
|
||
.file-actions {
|
||
position: absolute;
|
||
top: 4px;
|
||
right: 4px;
|
||
opacity: 0;
|
||
transition: opacity 0.3s;
|
||
}
|
||
|
||
.file-preview:hover .file-actions {
|
||
opacity: 1;
|
||
}
|
||
|
||
.file-preview {
|
||
position: relative;
|
||
}
|
||
</style>
|