|
|
|
@ -29,6 +29,7 @@ |
|
|
|
<el-button type="primary" style="margin-left: 2px" @click="toggleEditMode"> |
|
|
|
{{ editMode ? '确定' : '编辑' }} |
|
|
|
</el-button> |
|
|
|
<el-button type="primary" style="margin-left: 2px" @click="exportModal">导入</el-button> |
|
|
|
</el-form-item> |
|
|
|
</el-form> |
|
|
|
<el-table |
|
|
|
@ -52,72 +53,48 @@ |
|
|
|
:label="item.columnLabel"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<template v-if="editMode && item.editAble && item.columnProp==='supplierName'"> |
|
|
|
<el-select |
|
|
|
v-model="rowSupplierNo[scope.row.id]" |
|
|
|
<el-input |
|
|
|
v-model="scope.row.supplierName" |
|
|
|
size="mini" |
|
|
|
style="width: 100%" |
|
|
|
clearable |
|
|
|
filterable |
|
|
|
style="width: 100%; cursor: pointer" |
|
|
|
readonly |
|
|
|
placeholder="请选择供应商" |
|
|
|
@change="(val) => handleSupplierChange(scope.row, val)"> |
|
|
|
<el-option |
|
|
|
v-for="opt in supplierOptions" |
|
|
|
:key="String(opt.value)" |
|
|
|
:label="opt.label" |
|
|
|
:value="opt.value"> |
|
|
|
</el-option> |
|
|
|
</el-select> |
|
|
|
@click.native="openSupplierSelect(scope.row)"> |
|
|
|
<i slot="suffix" class="el-icon-search" style="cursor: pointer"></i> |
|
|
|
</el-input> |
|
|
|
</template> |
|
|
|
<template v-else-if="editMode && item.editAble && item.columnProp==='partNo'"> |
|
|
|
<el-select |
|
|
|
v-model="rowPartNo[scope.row.id]" |
|
|
|
<el-input |
|
|
|
v-model="scope.row.partNo" |
|
|
|
size="mini" |
|
|
|
style="width: 100%" |
|
|
|
clearable |
|
|
|
filterable |
|
|
|
style="width: 100%; cursor: pointer" |
|
|
|
readonly |
|
|
|
placeholder="请选择物料" |
|
|
|
@change="(val) => handlePartNoChange(scope.row, val)"> |
|
|
|
<el-option |
|
|
|
v-for="opt in poPartNoOptions" |
|
|
|
:key="String(opt.value)" |
|
|
|
:label="opt.label" |
|
|
|
:value="opt.value"> |
|
|
|
</el-option> |
|
|
|
</el-select> |
|
|
|
@click.native="openPartNoSelect(scope.row)"> |
|
|
|
<i slot="suffix" class="el-icon-search" style="cursor: pointer"></i> |
|
|
|
</el-input> |
|
|
|
</template> |
|
|
|
<template v-else-if="editMode && item.editAble && item.columnProp==='departure'"> |
|
|
|
<el-select |
|
|
|
v-model="rowDeparture[scope.row.id]" |
|
|
|
<el-input |
|
|
|
v-model="scope.row.departure" |
|
|
|
size="mini" |
|
|
|
style="width: 100%" |
|
|
|
clearable |
|
|
|
filterable |
|
|
|
style="width: 100%; cursor: pointer" |
|
|
|
readonly |
|
|
|
placeholder="请选择始发港" |
|
|
|
@change="(val) => handlePortChange(scope.row, val)"> |
|
|
|
<el-option |
|
|
|
v-for="opt in poDepartureOptions" |
|
|
|
:key="String(opt.value)" |
|
|
|
:label="opt.label" |
|
|
|
:value="opt.value"> |
|
|
|
</el-option> |
|
|
|
</el-select> |
|
|
|
@click.native="openDepartureSelect(scope.row)"> |
|
|
|
<i slot="suffix" class="el-icon-search" style="cursor: pointer"></i> |
|
|
|
</el-input> |
|
|
|
</template> |
|
|
|
<template v-else-if="editMode && item.editAble && item.columnProp==='destination'"> |
|
|
|
<el-select |
|
|
|
v-model="rowDestination[scope.row.id]" |
|
|
|
<el-input |
|
|
|
v-model="scope.row.destination" |
|
|
|
size="mini" |
|
|
|
style="width: 100%" |
|
|
|
clearable |
|
|
|
filterable |
|
|
|
style="width: 100%; cursor: pointer" |
|
|
|
readonly |
|
|
|
placeholder="请选择目的港" |
|
|
|
@change="(val) => handlePortChange(scope.row, val)"> |
|
|
|
<el-option |
|
|
|
v-for="opt in poDestinationOptions" |
|
|
|
:key="String(opt.value)" |
|
|
|
:label="opt.label" |
|
|
|
:value="opt.value"> |
|
|
|
</el-option> |
|
|
|
</el-select> |
|
|
|
@click.native="openDestinationSelect(scope.row)"> |
|
|
|
<i slot="suffix" class="el-icon-search" style="cursor: pointer"></i> |
|
|
|
</el-input> |
|
|
|
</template> |
|
|
|
<template v-else-if="editMode && item.editAble && item.columnProp==='shipVia'"> |
|
|
|
<el-select |
|
|
|
@ -204,6 +181,68 @@ |
|
|
|
:total="totalPage" |
|
|
|
layout="total, sizes, prev, pager, next, jumper"> |
|
|
|
</el-pagination> |
|
|
|
|
|
|
|
<!-- 导入弹窗 --> |
|
|
|
<el-dialog title="PO订单数据导入" :visible.sync="uploadDialogVisible" width="800px"> |
|
|
|
<!-- 选择文件 --> |
|
|
|
<div style="margin-bottom:15px;display:flex;align-items:center"> |
|
|
|
<span style="margin-right:10px">请选择文件</span> |
|
|
|
<el-input v-model="uploadFileName" style="width:400px;margin-right:10px" readonly></el-input> |
|
|
|
<el-upload ref="upload" action="/api/pODetail/upload" |
|
|
|
:show-file-list="false" :on-change="handleFileChange" |
|
|
|
:auto-upload="false"> |
|
|
|
<el-button type="primary">选择文件</el-button> |
|
|
|
</el-upload> |
|
|
|
<el-button type="success" style="margin-left:10px" @click="previewUpload">上传</el-button> |
|
|
|
<el-button type="primary" @click="downloadTemplate" style="margin-left:10px"> |
|
|
|
<i class="el-icon-download"></i> 下载模板 |
|
|
|
</el-button> |
|
|
|
</div> |
|
|
|
<!-- 预览表格 --> |
|
|
|
<el-table |
|
|
|
:data="uploadPreviewList" |
|
|
|
border |
|
|
|
height="250" |
|
|
|
style="width:100%;margin-top:10px" |
|
|
|
> |
|
|
|
<el-table-column prop="customer" label="客户名" align="center" width="120"></el-table-column> |
|
|
|
<el-table-column prop="buyer" label="买手名" align="center" width="100"></el-table-column> |
|
|
|
<el-table-column prop="supplierName" label="供应商名" align="center" width="150"></el-table-column> |
|
|
|
<el-table-column prop="poNo" label="订单号" align="center" width="140"></el-table-column> |
|
|
|
<el-table-column prop="item" label="款号" align="center" width="90"></el-table-column> |
|
|
|
<el-table-column prop="price" label="单价" align="center" width="80"></el-table-column> |
|
|
|
<el-table-column prop="qty" label="订单数量" align="center" width="90"></el-table-column> |
|
|
|
<el-table-column prop="shipQty" label="出运数量" align="center" width="90"></el-table-column> |
|
|
|
<el-table-column prop="departure" label="始发港" align="center" width="90"></el-table-column> |
|
|
|
<el-table-column prop="destination" label="目的港" align="center" width="90"></el-table-column> |
|
|
|
<el-table-column prop="shipVia" label="运输方式" align="center" width="100"></el-table-column> |
|
|
|
<el-table-column prop="orderDate" label="订单下单日期" align="center" width="120"></el-table-column> |
|
|
|
<el-table-column prop="enquiry" label="订单询单日期" align="center" width="120"></el-table-column> |
|
|
|
<el-table-column prop="confirmed" label="订单确认日期" align="center" width="120"></el-table-column> |
|
|
|
<el-table-column prop="wantReceiveDate" label="Original Arrival Date" align="center" width="150"></el-table-column> |
|
|
|
<el-table-column prop="crd" label="确认完货日期" align="center" width="120"></el-table-column> |
|
|
|
<el-table-column prop="advancePayment" label="是否需要预付款" align="center" width="130"></el-table-column> |
|
|
|
<el-table-column prop="planner" label="分管Planner" align="center" width="110"></el-table-column> |
|
|
|
<el-table-column prop="remark" label="备注" align="center" min-width="150"></el-table-column> |
|
|
|
</el-table> |
|
|
|
<!-- 按钮 --> |
|
|
|
<div style="margin-top:20px;text-align:center"> |
|
|
|
<el-button type="primary" @click="confirmUpload">保存</el-button> |
|
|
|
<el-button @click="uploadDialogVisible=false" style="margin-right:30px">关闭</el-button> |
|
|
|
</div> |
|
|
|
</el-dialog> |
|
|
|
|
|
|
|
<!-- 供应商选择弹窗 --> |
|
|
|
<Chooselist ref="baseList" @getBaseData="getSupplierData"></Chooselist> |
|
|
|
|
|
|
|
<!-- 物料选择弹窗 --> |
|
|
|
<Chooselist ref="partNoList" @getBaseData="getPartNoData"></Chooselist> |
|
|
|
|
|
|
|
<!-- 始发港选择弹窗 --> |
|
|
|
<Chooselist ref="departureList" @getBaseData="getDepartureData"></Chooselist> |
|
|
|
|
|
|
|
<!-- 目的港选择弹窗 --> |
|
|
|
<Chooselist ref="destinationList" @getBaseData="getDestinationData"></Chooselist> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
@ -212,9 +251,13 @@ import { searchPoDetailPage, batchUpdatePoDetail } from '@/api/order/poOrder.js' |
|
|
|
import { getPartList } from '@/api/part/partInfo.js' |
|
|
|
import { checkSrmSupplierList } from '@/api/srm/srmSupplier.js' |
|
|
|
import { searchTransportOptions } from '@/api/port/portTransit.js' |
|
|
|
import Chooselist from '@/views/modules/common/Chooselist.vue' |
|
|
|
|
|
|
|
export default { |
|
|
|
name: 'PoOrder', |
|
|
|
components: { |
|
|
|
Chooselist |
|
|
|
}, |
|
|
|
data () { |
|
|
|
return { |
|
|
|
loading: false, |
|
|
|
@ -228,6 +271,10 @@ export default { |
|
|
|
rowShipVia: {}, // 存储每行选中的运输方式 |
|
|
|
transportOptions: [], // 运输方式选项 |
|
|
|
rowPartNo: {}, //存储每行选中的物料编号 |
|
|
|
currentSelectRow: null, // 当前正在选择供应商的行 |
|
|
|
currentPartNoRow: null, // 当前正在选择物料的行 |
|
|
|
currentDepartureRow: null, // 当前正在选择始发港的行 |
|
|
|
currentDestinationRow: null, // 当前正在选择目的港的行 |
|
|
|
rowSupplierNo: {}, //存储每行选中的供应商编号 |
|
|
|
poPartNoOptions: [], |
|
|
|
supplierOptions: [], |
|
|
|
@ -235,6 +282,12 @@ export default { |
|
|
|
poDestinationOptions: [], |
|
|
|
customEditColumnProps: [], |
|
|
|
|
|
|
|
// 上传相关 |
|
|
|
uploadDialogVisible: false, |
|
|
|
uploadFileName: '', |
|
|
|
uploadFile: null, |
|
|
|
uploadPreviewList: [], |
|
|
|
|
|
|
|
currentRow: null, |
|
|
|
// 各列下拉:select 列通过 selectOptionsKey 指向此处;也可在列定义里写 selectOptions 数组 - rqrq |
|
|
|
columnSelectOptions: { |
|
|
|
@ -1456,6 +1509,219 @@ export default { |
|
|
|
.catch(error => { |
|
|
|
this.$message.error('操作失败: ' + error.message) |
|
|
|
}) |
|
|
|
}, |
|
|
|
|
|
|
|
// ========== 上传功能 ========== |
|
|
|
// 打开上传弹窗 |
|
|
|
exportModal() { |
|
|
|
this.uploadDialogVisible = true |
|
|
|
this.uploadFileName = '' |
|
|
|
this.uploadFile = null |
|
|
|
this.uploadPreviewList = [] |
|
|
|
}, |
|
|
|
// 文件选择变化 |
|
|
|
handleFileChange(file) { |
|
|
|
this.uploadFile = file.raw |
|
|
|
this.uploadFileName = file.name |
|
|
|
}, |
|
|
|
// 预览上传数据 |
|
|
|
previewUpload() { |
|
|
|
if (!this.uploadFile) { |
|
|
|
this.$message.warning('请先选择文件') |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
const formData = new FormData() |
|
|
|
formData.append('file', this.uploadFile) |
|
|
|
|
|
|
|
// 调用后端预览接口 |
|
|
|
this.$http({ |
|
|
|
url: this.$http.adornUrl('/pODetail/previewUpload'), |
|
|
|
method: 'post', |
|
|
|
data: formData |
|
|
|
// 注意:不要手动设置 Content-Type,让 axios 自动处理 boundary |
|
|
|
}).then(({ data }) => { |
|
|
|
if (data && data.code === 0) { |
|
|
|
this.uploadPreviewList = data.data || [] |
|
|
|
this.$message.success('文件解析成功,请确认数据后点击保存') |
|
|
|
} else { |
|
|
|
this.$message.error(data.msg || '文件解析失败') |
|
|
|
} |
|
|
|
}).catch((error) => { |
|
|
|
console.error('文件解析失败:', error) |
|
|
|
const errorMsg = (error.response && error.response.data && error.response.data.msg) || error.message || '未知错误' |
|
|
|
this.$message.error('文件解析失败: ' + errorMsg) |
|
|
|
}) |
|
|
|
}, |
|
|
|
// 确认上传 |
|
|
|
confirmUpload() { |
|
|
|
if (this.uploadPreviewList.length === 0) { |
|
|
|
this.$message.warning('没有可保存的数据') |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
this.$confirm(`确认保存 ${this.uploadPreviewList.length} 条数据吗?`, '提示', { |
|
|
|
confirmButtonText: '确定', |
|
|
|
cancelButtonText: '取消', |
|
|
|
type: 'warning' |
|
|
|
}).then(() => { |
|
|
|
const formData = new FormData() |
|
|
|
formData.append('file', this.uploadFile) |
|
|
|
|
|
|
|
// 调用后端保存接口 |
|
|
|
this.$http({ |
|
|
|
url: this.$http.adornUrl('/pODetail/batchSave'), |
|
|
|
method: 'post', |
|
|
|
data: formData |
|
|
|
// 注意:不要手动设置 Content-Type,让 axios 自动处理 boundary |
|
|
|
}).then(({ data }) => { |
|
|
|
if (data && data.code === 0) { |
|
|
|
this.$message.success('数据保存成功') |
|
|
|
this.uploadDialogVisible = false |
|
|
|
this.getDataList() |
|
|
|
} else { |
|
|
|
this.$message.error(data.msg || '数据保存失败') |
|
|
|
} |
|
|
|
}).catch((error) => { |
|
|
|
console.error('数据保存失败:', error) |
|
|
|
const errorMsg = (error.response && error.response.data && error.response.data.msg) || error.message || '未知错误' |
|
|
|
this.$message.error('数据保存失败: ' + errorMsg) |
|
|
|
}) |
|
|
|
}).catch(() => {}) |
|
|
|
}, |
|
|
|
// 下载模板 |
|
|
|
downloadTemplate() { |
|
|
|
const loading = this.$loading({ |
|
|
|
lock: true, |
|
|
|
text: '正在下载模板...', |
|
|
|
spinner: 'el-icon-loading', |
|
|
|
background: 'rgba(0, 0, 0, 0.7)' |
|
|
|
}) |
|
|
|
|
|
|
|
this.$http({ |
|
|
|
url: this.$http.adornUrl('/pODetail/downloadTemplate'), |
|
|
|
method: 'get', |
|
|
|
responseType: 'blob' |
|
|
|
}).then(response => { |
|
|
|
loading.close() |
|
|
|
|
|
|
|
// 创建下载文件 |
|
|
|
const blob = new Blob([response.data], { |
|
|
|
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' |
|
|
|
}) |
|
|
|
|
|
|
|
const url = window.URL.createObjectURL(blob) |
|
|
|
const link = document.createElement('a') |
|
|
|
link.href = url |
|
|
|
link.download = 'PO订单导入模板.xlsx' |
|
|
|
|
|
|
|
document.body.appendChild(link) |
|
|
|
link.click() |
|
|
|
document.body.removeChild(link) |
|
|
|
|
|
|
|
window.URL.revokeObjectURL(url) |
|
|
|
|
|
|
|
this.$message.success('模板下载成功') |
|
|
|
}).catch(error => { |
|
|
|
loading.close() |
|
|
|
console.error('模板下载失败:', error) |
|
|
|
this.$message.error('模板下载失败,请联系管理员') |
|
|
|
}) |
|
|
|
}, |
|
|
|
|
|
|
|
// 打开供应商选择弹窗 |
|
|
|
openSupplierSelect(row) { |
|
|
|
this.currentSelectRow = row |
|
|
|
this.$refs.baseList.init(1100, '', '') |
|
|
|
}, |
|
|
|
|
|
|
|
// 打开物料选择弹窗 |
|
|
|
openPartNoSelect(row) { |
|
|
|
this.currentPartNoRow = row |
|
|
|
this.$refs.partNoList.init(507, '', '') |
|
|
|
}, |
|
|
|
|
|
|
|
// 打开始发港选择弹窗 |
|
|
|
openDepartureSelect(row) { |
|
|
|
this.currentDepartureRow = row |
|
|
|
this.$refs.departureList.init(2018, '', '') |
|
|
|
}, |
|
|
|
|
|
|
|
// 打开目的港选择弹窗 |
|
|
|
openDestinationSelect(row) { |
|
|
|
this.currentDestinationRow = row |
|
|
|
this.$refs.destinationList.init(2018, '', '') |
|
|
|
}, |
|
|
|
|
|
|
|
// 接收供应商选择数据 |
|
|
|
getSupplierData(data) { |
|
|
|
console.log('选择的供应商数据:', data) |
|
|
|
if (data && this.currentSelectRow) { |
|
|
|
// 更新当前行的供应商信息 |
|
|
|
// Chooselist 返回的是下划线命名:supplier_name, supplier_no |
|
|
|
this.$set(this.currentSelectRow, 'supplierName', data.supplier_name || data.supplierName || '') |
|
|
|
this.$set(this.currentSelectRow, 'supplierNo', data.supplier_no || data.supplierNo || '') |
|
|
|
this.$set(this.currentSelectRow, 'shortOffice', data.cshortOffice || data.shortOffice || '') |
|
|
|
this.$set(this.currentSelectRow, 'shortNpc', data.cshortNpc || data.shortNpc || '') |
|
|
|
this.$set(this.currentSelectRow, 'changeFlag', 1) |
|
|
|
|
|
|
|
console.log('更新后的行数据:', this.currentSelectRow) |
|
|
|
|
|
|
|
// 清空当前选择行 |
|
|
|
this.currentSelectRow = null |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
// 接收物料选择数据 |
|
|
|
getPartNoData(data) { |
|
|
|
console.log('选择的物料数据:', data) |
|
|
|
if (data && this.currentPartNoRow) { |
|
|
|
// 更新当前行的物料信息 |
|
|
|
// Chooselist 返回的是下划线命名:part_no, part_desc |
|
|
|
this.$set(this.currentPartNoRow, 'partNo', data.part_no || data.partNo || '') |
|
|
|
this.$set(this.currentPartNoRow, 'category', data.category || '') |
|
|
|
this.$set(this.currentPartNoRow, 'sku', data.sku || '') |
|
|
|
this.$set(this.currentPartNoRow, 'changeFlag', 1) |
|
|
|
|
|
|
|
console.log('更新后的行数据:', this.currentPartNoRow) |
|
|
|
|
|
|
|
// 清空当前选择行 |
|
|
|
this.currentPartNoRow = null |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
// 接收始发港选择数据 |
|
|
|
getDepartureData(data) { |
|
|
|
console.log('选择的始发港数据:', data) |
|
|
|
if (data && this.currentDepartureRow) { |
|
|
|
// 更新当前行的始发港信息 |
|
|
|
// 根据实际返回的字段名进行映射 |
|
|
|
this.$set(this.currentDepartureRow, 'departure', data.port_code || data.portCode || data.departure || '') |
|
|
|
this.$set(this.currentDepartureRow, 'departureName', data.port_name || data.portName || '') |
|
|
|
this.$set(this.currentDepartureRow, 'changeFlag', 1) |
|
|
|
|
|
|
|
console.log('更新后的行数据:', this.currentDepartureRow) |
|
|
|
|
|
|
|
// 清空当前选择行 |
|
|
|
this.currentDepartureRow = null |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
// 接收目的港选择数据 |
|
|
|
getDestinationData(data) { |
|
|
|
console.log('选择的目的港数据:', data) |
|
|
|
if (data && this.currentDestinationRow) { |
|
|
|
// 更新当前行的目的港信息 |
|
|
|
// 根据实际返回的字段名进行映射 |
|
|
|
this.$set(this.currentDestinationRow, 'destination', data.port_code || data.portCode || data.destination || '') |
|
|
|
this.$set(this.currentDestinationRow, 'destinationName', data.port_name || data.portName || '') |
|
|
|
this.$set(this.currentDestinationRow, 'changeFlag', 1) |
|
|
|
|
|
|
|
console.log('更新后的行数据:', this.currentDestinationRow) |
|
|
|
|
|
|
|
// 清空当前选择行 |
|
|
|
this.currentDestinationRow = null |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|