Browse Source

feat(order): 新增PO订单管理页面

- 实现PO订单列表展示功能,支持客户、买手、订单号、SKU等搜索条件
- 添加表格编辑模式,支持供应商、物料、始发港、目的港等字段的选择和修改
- 集成供应商选择、物料选择、港口选择等弹窗组件
- 实现订单数据导入功能,支持Excel文件上传和模板下载
- 添加分页功能和表格列配置管理
- 支持多种数据类型编辑,包括数字、日期、下拉选择等
- 实现批量更新订单详情的功能接口调用
master
qiankanghui 4 weeks ago
parent
commit
8bdb4bb689
  1. 370
      src/views/modules/order/poOrder.vue

370
src/views/modules/order/poOrder.vue

@ -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
}
}
}

Loading…
Cancel
Save