Browse Source
feat(npcIqc): 新增物流管理模块和附件功能
feat(npcIqc): 新增物流管理模块和附件功能
- 创建物流管理页面,包含进仓编号、供应商信息查询功能 - 实现主表数据展示和分页功能 - 添加PO清单页签显示订单明细信息 - 开发附件上传、下载、删除功能组件 - 集成附件管理到物流管理页面页签中 - 添加物流相关API接口定义 - 调整首页样式以适配技术框架布局master
4 changed files with 624 additions and 0 deletions
-
6src/api/npcIqc/npcIqc.js
-
29src/views/common/home.vue
-
266src/views/modules/npcIqc/com_logisticsAttachmentTab.vue
-
323src/views/modules/npcIqc/logisticsManagement.vue
@ -0,0 +1,266 @@ |
|||||
|
<template> |
||||
|
<div class="customer-css"> |
||||
|
<!-- 操作按钮 --> |
||||
|
<el-form :inline="true" style="margin-bottom: 2px;"> |
||||
|
<el-button type="primary" icon="el-icon-upload" @click="handleUpload" :disabled="!searchData.flexId">上传附件</el-button> |
||||
|
</el-form> |
||||
|
|
||||
|
<!-- 附件文件列表表格 --> |
||||
|
<el-table |
||||
|
:data="fileList" |
||||
|
:height="tableHeight" |
||||
|
border |
||||
|
v-loading="loading" |
||||
|
style="width: 100%;"> |
||||
|
<el-table-column |
||||
|
type="index" |
||||
|
label="序号" |
||||
|
width="80" |
||||
|
align="center" /> |
||||
|
<el-table-column |
||||
|
prop="fileName" |
||||
|
label="附件名称" |
||||
|
min-width="250" |
||||
|
show-overflow-tooltip /> |
||||
|
<el-table-column |
||||
|
prop="createdBy" |
||||
|
label="创建人" |
||||
|
width="120" |
||||
|
align="center" /> |
||||
|
<el-table-column |
||||
|
prop="createDate" |
||||
|
label="创建时间" |
||||
|
width="160" |
||||
|
align="center" /> |
||||
|
<el-table-column |
||||
|
label="操作" |
||||
|
width="150" |
||||
|
align="center" |
||||
|
fixed="right"> |
||||
|
<template slot-scope="scope"> |
||||
|
<el-link type="primary" @click="handleDownload(scope.row)">查看 |</el-link> |
||||
|
<el-link type="danger" @click="handleRemove(scope.row)">删除</el-link> |
||||
|
</template> |
||||
|
</el-table-column> |
||||
|
</el-table> |
||||
|
|
||||
|
<!-- 上传附件弹窗 --> |
||||
|
<el-dialog title="上传附件" :visible.sync="ossVisible" width="450px" append-to-body :close-on-click-modal="false"> |
||||
|
<el-form ref="form" :model="ossForm" label-width="80px" label-position="top"> |
||||
|
<el-form-item label=" " class="auto"> |
||||
|
<el-upload |
||||
|
drag |
||||
|
:file-list="uploadFileList" |
||||
|
action="#" |
||||
|
ref="upload" |
||||
|
:on-remove="onRemoveFile" |
||||
|
:on-change="onChangeFile" |
||||
|
multiple |
||||
|
:auto-upload="false"> |
||||
|
<i class="el-icon-upload"></i> |
||||
|
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div> |
||||
|
</el-upload> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
<span slot="footer" class="dialog-footer"> |
||||
|
<el-button type="primary" :loading="uploadLoading" @click="submitData">确定</el-button> |
||||
|
<el-button @click="ossVisible = false">取消</el-button> |
||||
|
</span> |
||||
|
</el-dialog> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { queryOssFilePlus, removeOss, previewOssFileById } from '@/api/oss/oss' |
||||
|
import { ossUploadNoSaveOSSForYJY } from '@/api/oss/oss' |
||||
|
|
||||
|
export default { |
||||
|
name: 'LogisticsAttachmentTab', |
||||
|
|
||||
|
props: { |
||||
|
detailData: { |
||||
|
type: Object, |
||||
|
default: () => ({}) |
||||
|
}, |
||||
|
tableHeight: { |
||||
|
type: Number, |
||||
|
default: 400 |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
data() { |
||||
|
return { |
||||
|
fileList: [], |
||||
|
loading: false, |
||||
|
searchData: { |
||||
|
flexId: '', |
||||
|
site: '' |
||||
|
}, |
||||
|
ossVisible: false, |
||||
|
uploadLoading: false, |
||||
|
uploadFileList: [], |
||||
|
ossForm: { |
||||
|
remark: '' |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
watch: { |
||||
|
// 监听 detailData 变化,触发查询 |
||||
|
detailData: { |
||||
|
handler(newVal) { |
||||
|
if (newVal && newVal.flexId) { |
||||
|
this.searchData.flexId = newVal.flexId |
||||
|
this.searchData.site = newVal.site || '' |
||||
|
this.searchTable() |
||||
|
} else { |
||||
|
this.fileList = [] |
||||
|
} |
||||
|
}, |
||||
|
deep: true, |
||||
|
immediate: true |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
methods: { |
||||
|
// 查询附件列表 |
||||
|
searchTable() { |
||||
|
if (!this.searchData.flexId) { |
||||
|
this.fileList = [] |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
console.log('当前 searchData:', this.searchData) |
||||
|
this.loading = true |
||||
|
let params = { |
||||
|
orderRef1: this.searchData.site, |
||||
|
orderRef2: this.searchData.flexId, |
||||
|
orderRef3: '', |
||||
|
orderReftype: 'LogisticsAttachment' |
||||
|
} |
||||
|
console.log('查询附件参数:', params) |
||||
|
|
||||
|
queryOssFilePlus(params).then(({ data }) => { |
||||
|
console.log('查询附件返回:', data) |
||||
|
if (data && data.code === 0) { |
||||
|
this.fileList = data.rows || [] |
||||
|
console.log('附件列表:', this.fileList) |
||||
|
} else { |
||||
|
this.fileList = [] |
||||
|
} |
||||
|
this.loading = false |
||||
|
}).catch((error) => { |
||||
|
console.error('查询附件失败:', error) |
||||
|
this.loading = false |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 打开上传弹窗 |
||||
|
handleUpload() { |
||||
|
this.$nextTick(() => { |
||||
|
if (this.$refs.upload) { |
||||
|
this.$refs.upload.clearFiles() |
||||
|
} |
||||
|
}) |
||||
|
this.uploadFileList = [] |
||||
|
this.ossForm.remark = '' |
||||
|
this.ossVisible = true |
||||
|
}, |
||||
|
|
||||
|
// 移除文件 |
||||
|
onRemoveFile(file, fileList) { |
||||
|
this.uploadFileList = fileList |
||||
|
}, |
||||
|
|
||||
|
// 文件选择变化 |
||||
|
onChangeFile(file, fileList) { |
||||
|
this.uploadFileList = fileList |
||||
|
}, |
||||
|
|
||||
|
// 提交上传 |
||||
|
submitData() { |
||||
|
if (this.uploadFileList.length === 0) { |
||||
|
this.$message.error('请选择文件') |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
this.uploadLoading = true |
||||
|
|
||||
|
let formData = new FormData() |
||||
|
for (let i = 0; i < this.uploadFileList.length; i++) { |
||||
|
formData.append('file', this.uploadFileList[i].raw) |
||||
|
} |
||||
|
formData.append('orderRef1', this.searchData.site) |
||||
|
formData.append('orderRef2', this.searchData.flexId) |
||||
|
formData.append('orderRef3', '') |
||||
|
formData.append('createdBy', this.$store.state.user.name) |
||||
|
formData.append('fileRemark', this.ossForm.remark || '') |
||||
|
formData.append('orderReftype', 'LogisticsAttachment') |
||||
|
|
||||
|
ossUploadNoSaveOSSForYJY(formData).then(({ data }) => { |
||||
|
if (data && data.code === 0) { |
||||
|
this.$message.success('上传成功') |
||||
|
this.searchTable() |
||||
|
this.ossVisible = false |
||||
|
} else { |
||||
|
this.$message.warning(data.msg || '上传失败') |
||||
|
} |
||||
|
this.uploadLoading = false |
||||
|
}).catch((error) => { |
||||
|
this.$message.error('上传失败') |
||||
|
this.uploadLoading = false |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 下载文件 |
||||
|
handleDownload(row) { |
||||
|
let params = { |
||||
|
id: row.id |
||||
|
} |
||||
|
previewOssFileById(params).then((response) => { |
||||
|
const blob = new Blob([response.data], { type: response.headers['content-type'] }) |
||||
|
const link = document.createElement('a') |
||||
|
link.href = URL.createObjectURL(blob) |
||||
|
link.setAttribute('download', row.fileName) |
||||
|
link.target = '_blank' |
||||
|
link.click() |
||||
|
URL.revokeObjectURL(link.href) |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 删除文件 |
||||
|
handleRemove(row) { |
||||
|
this.$confirm('确定要删除该附件吗?', '提示', { |
||||
|
confirmButtonText: '确定', |
||||
|
cancelButtonText: '取消', |
||||
|
type: 'warning' |
||||
|
}).then(() => { |
||||
|
let ids = [row.id] |
||||
|
removeOss(ids).then(({ data }) => { |
||||
|
if (data && data.code === 0) { |
||||
|
this.$message.success('删除成功') |
||||
|
this.searchTable() |
||||
|
} else { |
||||
|
this.$message.warning(data.msg || '删除失败') |
||||
|
} |
||||
|
}).catch((error) => { |
||||
|
this.$message.error('删除失败') |
||||
|
}) |
||||
|
}).catch(() => {}) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped lang="scss"> |
||||
|
.customer-css { |
||||
|
padding: 0; |
||||
|
margin: 0; |
||||
|
background: #fff; |
||||
|
} |
||||
|
|
||||
|
.auto /deep/ .el-form-item__content { |
||||
|
height: auto; |
||||
|
line-height: 1.5; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,323 @@ |
|||||
|
<template> |
||||
|
<div class="customer-css"> |
||||
|
<!-- 查询条件 --> |
||||
|
<el-form :inline="true" label-position="top" class="search-form-inline"> |
||||
|
<div class="search-row"> |
||||
|
<el-form-item label="进仓编号" class="search-item"> |
||||
|
<el-input v-model="searchData.flexId" style="width: 150px" @keyup.enter.native="getMainData"/> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="供应商编码" class="search-item"> |
||||
|
<el-input v-model="searchData.supplierNo" style="width: 120px" @keyup.enter.native="getMainData"/> |
||||
|
</el-form-item> |
||||
|
<el-form-item label="供应商名称" class="search-item"> |
||||
|
<el-input v-model="searchData.supplierName" style="width: 200px" @keyup.enter.native="getMainData"/> |
||||
|
</el-form-item> |
||||
|
<el-form-item label=" " class="search-item search-btn-item"> |
||||
|
<el-button type="primary" @click="getMainData">查询</el-button> |
||||
|
</el-form-item> |
||||
|
</div> |
||||
|
</el-form> |
||||
|
|
||||
|
<el-table |
||||
|
:height="height" |
||||
|
:data="mainDataList" |
||||
|
border |
||||
|
ref="mainTable" |
||||
|
highlight-current-row |
||||
|
@row-click="changeData" |
||||
|
v-loading="dataListLoading" |
||||
|
style="margin-top: 0px; width: 100%;"> |
||||
|
<el-table-column |
||||
|
type="index" |
||||
|
label="序号" |
||||
|
width="80" |
||||
|
align="center" /> |
||||
|
<el-table-column |
||||
|
prop="flexId" |
||||
|
label="进仓编号" |
||||
|
min-width="150" |
||||
|
show-overflow-tooltip /> |
||||
|
<el-table-column |
||||
|
prop="supplierNo" |
||||
|
label="供应商编码" |
||||
|
width="120" |
||||
|
align="center" /> |
||||
|
<el-table-column |
||||
|
prop="supplierName" |
||||
|
label="供应商名称" |
||||
|
min-width="200" |
||||
|
show-overflow-tooltip /> |
||||
|
<el-table-column |
||||
|
prop="poCount" |
||||
|
label="PO数量" |
||||
|
width="100" |
||||
|
align="center" /> |
||||
|
<el-table-column |
||||
|
prop="shippedQty" |
||||
|
label="已出货数量" |
||||
|
width="120" |
||||
|
align="center" /> |
||||
|
<el-table-column |
||||
|
label="操作" |
||||
|
width="150" |
||||
|
align="center" |
||||
|
fixed="right"> |
||||
|
<template slot-scope="scope"> |
||||
|
<el-link type="danger" @click="handleDeleteAttachment(scope.row)">删除附件</el-link> |
||||
|
</template> |
||||
|
</el-table-column> |
||||
|
</el-table> |
||||
|
|
||||
|
<!-- 分页插件 --> |
||||
|
<el-pagination style="margin-top: 0px" |
||||
|
@size-change="sizeChangeHandle" |
||||
|
@current-change="currentChangeHandle" |
||||
|
:current-page="pageIndex" |
||||
|
:page-sizes="[20, 50, 100, 200, 500]" |
||||
|
:page-size="pageSize" |
||||
|
:total="totalPage" |
||||
|
layout="total, sizes, prev, pager, next, jumper"> |
||||
|
</el-pagination> |
||||
|
|
||||
|
<!-- 详情页签 --> |
||||
|
<el-tabs v-model="activeTab" style="margin-top: 0px; width: 99%;" @tab-click="handleTabClick" class="customer-tab" type="border-card"> |
||||
|
<!-- PO清单 --> |
||||
|
<el-tab-pane label="PO清单" name="poList"> |
||||
|
<el-table |
||||
|
:data="poListData" |
||||
|
border |
||||
|
:height="detailHeight" |
||||
|
v-loading="poListLoading" |
||||
|
style="width: 100%;"> |
||||
|
<el-table-column |
||||
|
type="index" |
||||
|
label="序号" |
||||
|
width="80" |
||||
|
align="center" /> |
||||
|
<el-table-column |
||||
|
prop="orderNo" |
||||
|
label="PO" |
||||
|
min-width="150" |
||||
|
show-overflow-tooltip /> |
||||
|
<el-table-column |
||||
|
prop="orderDate" |
||||
|
label="PO Date" |
||||
|
width="120" |
||||
|
align="center" /> |
||||
|
<el-table-column |
||||
|
prop="partNo" |
||||
|
label="SKU" |
||||
|
min-width="150" |
||||
|
show-overflow-tooltip /> |
||||
|
<el-table-column |
||||
|
prop="qty" |
||||
|
label="Qty" |
||||
|
width="100" |
||||
|
align="center" /> |
||||
|
<el-table-column |
||||
|
prop="shippedQty" |
||||
|
label="Qty Shipped" |
||||
|
width="120" |
||||
|
align="center" /> |
||||
|
</el-table> |
||||
|
</el-tab-pane> |
||||
|
<!-- 附件 --> |
||||
|
<el-tab-pane label="附件" name="attachment"> |
||||
|
<logistics-attachment-tab ref="attachmentTab" :detail-data="currentRow" :table-height="detailHeight" /> |
||||
|
</el-tab-pane> |
||||
|
</el-tabs> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import LogisticsAttachmentTab from './com_logisticsAttachmentTab.vue' |
||||
|
import { searchLogistics, getPoList } from '@/api/npcIqc/npcIqc.js' |
||||
|
|
||||
|
export default { |
||||
|
components: { |
||||
|
LogisticsAttachmentTab |
||||
|
}, |
||||
|
data () { |
||||
|
return { |
||||
|
height: 400, |
||||
|
detailHeight: 400, |
||||
|
currentRow: {}, |
||||
|
activeTab: 'poList', |
||||
|
searchData: { |
||||
|
flexId: '', |
||||
|
supplierNo: '', |
||||
|
supplierName: '', |
||||
|
site: this.$store.state.user.site, |
||||
|
page: 1, |
||||
|
limit: 50 |
||||
|
}, |
||||
|
pageIndex: 1, |
||||
|
pageSize: 50, |
||||
|
totalPage: 0, |
||||
|
mainDataList: [], |
||||
|
poListData: [], |
||||
|
dataListLoading: false, |
||||
|
poListLoading: false |
||||
|
} |
||||
|
}, |
||||
|
mounted () { |
||||
|
this.$nextTick(() => { |
||||
|
this.height = (window.innerHeight - 220) / 2 |
||||
|
this.detailHeight = (window.innerHeight - 220) / 2 |
||||
|
this.getMainData() |
||||
|
}) |
||||
|
}, |
||||
|
methods: { |
||||
|
// 查询数据 |
||||
|
getMainData () { |
||||
|
this.searchData.limit = this.pageSize |
||||
|
this.searchData.page = this.pageIndex |
||||
|
this.dataListLoading = true |
||||
|
|
||||
|
searchLogistics(this.searchData).then(({ data }) => { |
||||
|
if (data.code === 0) { |
||||
|
this.mainDataList = data.page.list |
||||
|
this.pageIndex = data.page.currPage |
||||
|
this.pageSize = data.page.pageSize |
||||
|
this.totalPage = data.page.totalCount |
||||
|
|
||||
|
this.$nextTick(() => { |
||||
|
if (this.$refs.mainTable) { |
||||
|
this.$refs.mainTable.clearSelection() |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
// 判断是否有数据 |
||||
|
if (this.mainDataList.length > 0) { |
||||
|
this.$refs.mainTable.setCurrentRow(this.mainDataList[0]) |
||||
|
this.changeData(this.mainDataList[0]) |
||||
|
} else { |
||||
|
this.changeData(null) |
||||
|
} |
||||
|
} |
||||
|
this.dataListLoading = false |
||||
|
}).catch(() => { |
||||
|
this.dataListLoading = false |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 每页数 |
||||
|
sizeChangeHandle (val) { |
||||
|
this.pageSize = val |
||||
|
this.pageIndex = 1 |
||||
|
this.getMainData() |
||||
|
}, |
||||
|
|
||||
|
// 当前页 |
||||
|
currentChangeHandle (val) { |
||||
|
this.pageIndex = val |
||||
|
this.getMainData() |
||||
|
}, |
||||
|
|
||||
|
// 页签点击事件 |
||||
|
handleTabClick (tab) { |
||||
|
if (tab.name === 'poList') { |
||||
|
this.loadPoList() |
||||
|
} else if (tab.name === 'attachment') { |
||||
|
this.$nextTick(() => { |
||||
|
if (this.$refs.attachmentTab) { |
||||
|
this.$refs.attachmentTab.searchTable() |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// 行点击事件 |
||||
|
changeData (row) { |
||||
|
this.currentRow = row ? JSON.parse(JSON.stringify(row)) : {} |
||||
|
this.loadPoList() |
||||
|
}, |
||||
|
|
||||
|
// 加载PO清单 |
||||
|
loadPoList () { |
||||
|
if (!this.currentRow.flexId) { |
||||
|
this.poListData = [] |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
this.poListLoading = true |
||||
|
const params = { |
||||
|
flexId: this.currentRow.flexId, |
||||
|
supplierNo: this.currentRow.supplierNo || '', |
||||
|
site: this.$store.state.user.site, |
||||
|
page: 1, |
||||
|
limit: 1000 |
||||
|
} |
||||
|
|
||||
|
getPoList(params).then(({ data }) => { |
||||
|
if (data.code === 0 && data.page) { |
||||
|
this.poListData = data.page.list || [] |
||||
|
} else { |
||||
|
this.poListData = [] |
||||
|
} |
||||
|
this.poListLoading = false |
||||
|
}).catch(() => { |
||||
|
this.poListData = [] |
||||
|
this.poListLoading = false |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 删除附件 |
||||
|
handleDeleteAttachment (row) { |
||||
|
this.$message.info('删除附件功能待开发') |
||||
|
} |
||||
|
}, |
||||
|
created () { |
||||
|
this.getMainData() |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped lang="scss"> |
||||
|
.customer-css { |
||||
|
padding: 0; |
||||
|
margin: 0; |
||||
|
background: #fff; |
||||
|
} |
||||
|
|
||||
|
.search-form-inline { |
||||
|
background: #fff; |
||||
|
} |
||||
|
|
||||
|
.search-row { |
||||
|
display: flex; |
||||
|
align-items: flex-end; |
||||
|
flex-wrap: nowrap; |
||||
|
gap: 15px; |
||||
|
} |
||||
|
|
||||
|
.search-item { |
||||
|
flex: none; |
||||
|
margin-bottom: 10px; |
||||
|
} |
||||
|
|
||||
|
.search-btn-item { |
||||
|
flex: none; |
||||
|
margin-bottom: 10px; |
||||
|
} |
||||
|
|
||||
|
.search-btn-item /deep/ .el-form-item__content { |
||||
|
line-height: normal; |
||||
|
} |
||||
|
|
||||
|
.search-item /deep/ .el-form-item__label { |
||||
|
font-size: 13px; |
||||
|
color: #606266; |
||||
|
padding-bottom: 5px; |
||||
|
line-height: 1; |
||||
|
height: auto; |
||||
|
} |
||||
|
|
||||
|
.search-item /deep/ .el-form-item__content { |
||||
|
line-height: normal; |
||||
|
} |
||||
|
|
||||
|
/deep/ .customer-tab .el-tabs__content { |
||||
|
padding: 5px !important; |
||||
|
} |
||||
|
</style> |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue