Commit e1b0bfb8 by zhangtw

入库结合物料组件

parent 203b5590
...@@ -33,8 +33,7 @@ ...@@ -33,8 +33,7 @@
:key="item.orderTypeId" :key="item.orderTypeId"
:label="item.orderTypeName" :label="item.orderTypeName"
:value="item.orderTypeId" :value="item.orderTypeId"
> />
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
...@@ -45,8 +44,7 @@ ...@@ -45,8 +44,7 @@
:key="item.orderStatus" :key="item.orderStatus"
:label="item.orderStatusName" :label="item.orderStatusName"
:value="item.orderStatus" :value="item.orderStatus"
> />
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="订单类型" prop="orderType"> <el-form-item label="订单类型" prop="orderType">
...@@ -56,8 +54,7 @@ ...@@ -56,8 +54,7 @@
:key="item.orderType" :key="item.orderType"
:label="item.orderTypeName" :label="item.orderTypeName"
:value="item.orderType" :value="item.orderType"
> />
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
...@@ -118,18 +115,36 @@ ...@@ -118,18 +115,36 @@
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column label="入库单号" align="center" prop="orderId" /> <el-table-column label="入库单号" align="center" prop="orderId" />
<el-table-column label="系统编号" align="center" prop="systemNo" /> <el-table-column label="系统编号" align="center" prop="systemNo" />
<el-table-column label="入库类型" align="center" prop="orderTypeId" /> <el-table-column label="入库类型" align="center" prop="orderTypeId">
<template slot-scope="scope">
<el-tag type="success" size="small">
{{ getInBoundTypeName(scope.row.orderTypeId) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="订单类型" align="center" prop="orderType">
<template slot-scope="scope">
<el-tag type="success" size="small">
{{ getOrderTypeName(scope.row.orderType) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="批次ID" align="center" prop="batchCode" /> <el-table-column label="批次ID" align="center" prop="batchCode" />
<el-table-column label="入库单状态" align="center" prop="orderStatus"/> <el-table-column label="入库单状态" align="center" prop="orderStatus">
<el-table-column label="排序" align="center" prop="sortNo" /> <!-- 状态显示 -->
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span> <el-tag
:type="getStatusType(scope.row.orderStatus)"
size="small"
>
{{ getStatusName(scope.row.orderStatus) }}
</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="更新时间" align="center" prop="updateTime" width="180"> <el-table-column label="创建时间" align="center" prop="createTime" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.updateTime, '{y}-{m}-{d}') }}</span> <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="300"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="300">
...@@ -175,8 +190,7 @@ ...@@ -175,8 +190,7 @@
/> />
<!-- 添加或修改入库对话框 --> <!-- 添加或修改入库对话框 -->
<el-dialog :title="title" :visible.sync="open" width="1200px" append-to-body class="scrollable-dialog">
<el-dialog :title="title" :visible.sync="open" width="1200px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px"> <el-form ref="form" :model="form" :rules="rules" label-width="80px">
<!-- 表单内容保持不变 --> <!-- 表单内容保持不变 -->
<el-divider content-position="center">入库单基础信息</el-divider> <el-divider content-position="center">入库单基础信息</el-divider>
...@@ -185,21 +199,20 @@ ...@@ -185,21 +199,20 @@
<el-form-item label="入库单号" prop="orderId"> <el-form-item label="入库单号" prop="orderId">
<el-input v-model="form.orderId" placeholder="请输入入库单号" /> <el-input v-model="form.orderId" placeholder="请输入入库单号" />
</el-form-item> </el-form-item>
<el-form-item label="入库类型" prop="orderTypeId">
<el-input v-model="form.orderTypeId" placeholder="请输入入库类型" />
</el-form-item>
<el-form-item label="货主ID" prop="ownerId">
<el-input v-model="form.ownerId" placeholder="请输入货主ID" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="系统编号" prop="systemNo">
<el-input v-model="form.systemNo" placeholder="请输入系统编号" />
</el-form-item>
<el-form-item label="批次ID" prop="batchCode"> <el-form-item label="批次ID" prop="batchCode">
<el-input v-model="form.batchCode" placeholder="请输入批次ID" /> <el-input v-model="form.batchCode" placeholder="请输入批次ID" />
</el-form-item> </el-form-item>
<el-form-item label="入库日期" prop="inboundDate" lebel-width="100"> <el-form-item label="入库类型" prop="orderTypeId">
<el-select v-model="form.orderTypeId" placeholder="请选择入库类型" clearable>
<el-option
v-for="item in inBoundTypeOptions"
:key="item.orderTypeId"
:label="item.orderTypeName"
:value="item.orderTypeId"
/>
</el-select>
</el-form-item>
<el-form-item label="入库日期" prop="inboundDate">
<el-date-picker clearable <el-date-picker clearable
v-model="form.inboundDate" v-model="form.inboundDate"
type="date" type="date"
...@@ -208,11 +221,30 @@ ...@@ -208,11 +221,30 @@
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12">
<el-form-item label="系统编号" prop="systemNo">
<el-input v-model="form.systemNo" placeholder="请输入系统编号" />
</el-form-item>
<el-form-item label="货主ID" prop="ownerId">
<el-input v-model="form.ownerId" placeholder="请输入货主ID" />
</el-form-item>
<el-form-item label="订单类型" prop="orderType">
<el-select v-model="form.orderType" placeholder="请选择订单类型" clearable>
<el-option
v-for="item in orderTypeOptions"
:key="item.orderType"
:label="item.orderTypeName"
:value="item.orderType"
/>
</el-select>
</el-form-item>
</el-col>
</el-row> </el-row>
<el-divider content-position="center">入库其他信息</el-divider> <el-divider content-position="center">入库其他信息</el-divider>
<el-row :gutter="24"> <el-row :gutter="24">
<el-col :span="12"> <el-col :span="12">
<div class="form-col">
<el-form-item label="计划量" prop="totalPlannedQuantity"> <el-form-item label="计划量" prop="totalPlannedQuantity">
<el-input v-model="form.totalPlannedQuantity" placeholder="请输入计划量" /> <el-input v-model="form.totalPlannedQuantity" placeholder="请输入计划量" />
</el-form-item> </el-form-item>
...@@ -222,7 +254,9 @@ ...@@ -222,7 +254,9 @@
<el-form-item label="仓库ID" prop="warehouseId"> <el-form-item label="仓库ID" prop="warehouseId">
<el-input v-model="form.warehouseId" placeholder="请输入仓库ID" /> <el-input v-model="form.warehouseId" placeholder="请输入仓库ID" />
</el-form-item> </el-form-item>
</div>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="实际量" prop="totalActualQuantity"> <el-form-item label="实际量" prop="totalActualQuantity">
<el-input v-model="form.totalActualQuantity" placeholder="请输入实际量" /> <el-input v-model="form.totalActualQuantity" placeholder="请输入实际量" />
...@@ -230,40 +264,22 @@ ...@@ -230,40 +264,22 @@
<el-form-item label="负责人" prop="opUserName"> <el-form-item label="负责人" prop="opUserName">
<el-input v-model="form.opUserName" placeholder="请输入负责人" /> <el-input v-model="form.opUserName" placeholder="请输入负责人" />
</el-form-item> </el-form-item>
<el-form-item label="排序" prop="sortNo"> <!-- <el-form-item label="排序" prop="sortNo">
<el-input v-model="form.sortNo" placeholder="请输入排序" /> <el-input v-model="form.sortNo" placeholder="请输入排序" />
</el-form-item> </el-form-item> -->
</el-col> </el-col>
</el-row>
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"/> <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"/>
</el-form-item> </el-form-item>
</el-row>
<el-divider content-position="center">入库单明细信息</el-divider>
<!-- <el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
icon="el-icon-plus"
size="mini"
@click="handleAddInboundItem"
>添加明细</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
icon="el-icon-delete"
size="mini"
@click="handleDeleteSelectedItems"
>删除选中</el-button>
</el-col>
</el-row> -->
<!-- 入库明细组件 --> <el-divider content-position="center">入库单明细信息</el-divider>
<InboundItems <InboundItems
ref="inboundItemsRef" ref="inboundItemsRef"
v-model="form.inboundOrderItemsList" v-model="form.inboundOrderItemsList"
:embedded="true" :embedded="true"
:order-id="form.orderId" :order-id="orderId"
:show-search-form="false" :show-search-form="false"
:show-pagination="false" :show-pagination="false"
:show-toolbar="true" :show-toolbar="true"
...@@ -280,6 +296,7 @@ ...@@ -280,6 +296,7 @@
@row-deleted="handleRowDeleted" @row-deleted="handleRowDeleted"
@batch-delete="handleBatchDelete" @batch-delete="handleBatchDelete"
@cell-change="handleCellChange" @cell-change="handleCellChange"
@show-materials="showMaterials"
/> />
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
...@@ -287,17 +304,94 @@ ...@@ -287,17 +304,94 @@
<el-button @click="cancel"> </el-button> <el-button @click="cancel"> </el-button>
</div> </div>
</el-dialog> </el-dialog>
<!-- 入库单详情弹窗 -->
<el-dialog
title="入库单详细信息"
:visible.sync="detailOpen"
width="1200px"
append-to-body
class="scrollable-dialog"
>
<div class="detail-container">
<!-- 基础信息展示 -->
<el-descriptions :column="2" border class="mb20">
<el-descriptions-item label="入库单号">{{ detailForm.orderId || '-' }}</el-descriptions-item>
<el-descriptions-item label="系统编号">{{ detailForm.systemNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="批次ID">{{ detailForm.batchCode || '-' }}</el-descriptions-item>
<el-descriptions-item label="货主ID">{{ detailForm.ownerId || '-' }}</el-descriptions-item>
<el-descriptions-item label="入库类型">
{{ getInBoundTypeName(detailForm.orderTypeId) }}
</el-descriptions-item>
<el-descriptions-item label="订单类型">
{{ getOrderTypeName(detailForm.orderType) }}
</el-descriptions-item>
<el-descriptions-item label="入库日期">{{ detailForm.inboundDate || '-' }}</el-descriptions-item>
<el-descriptions-item label="负责人">{{ detailForm.opUserName || '-' }}</el-descriptions-item>
<el-descriptions-item label="计划量">{{ detailForm.totalPlannedQuantity || '-' }}</el-descriptions-item>
<el-descriptions-item label="实际量">{{ detailForm.totalActualQuantity || '-' }}</el-descriptions-item>
<el-descriptions-item label="总件数">{{ detailForm.totalPackages || '-' }}</el-descriptions-item>
<el-descriptions-item label="仓库ID">{{ detailForm.warehouseId || '-' }}</el-descriptions-item>
<!-- <el-descriptions-item label="排序">{{ detailForm.sortNo || '-' }}</el-descriptions-item> -->
<el-descriptions-item label="备注" :span="2">
<div class="remark-text">{{ detailForm.remark || '-' }}</div>
</el-descriptions-item>
</el-descriptions>
<!-- 明细信息展示 -->
<el-divider content-position="center">入库单明细信息</el-divider>
<InboundItems
ref="detailItemsRef"
v-model="detailForm.inboundOrderItemsList"
:embedded="true"
:order-id="detailForm.orderId"
:show-search-form="false"
:show-pagination="false"
:show-toolbar="false"
:show-action-column="false"
:show-selection="false"
:show-add-button="false"
:show-edit-button="false"
:show-delete-button="false"
/>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="detailOpen = false">关闭</el-button>
</div>
</el-dialog>
<!-- 物料选择弹窗 -->
<el-dialog
title="选择物料"
:visible.sync="materialSelectOpen"
width="1200px"
append-to-body
>
<MaterialSelector
v-model="selectedMaterialIds"
:multiple="true"
@change="handleMaterialChange"
ref="materialSelector"
/>
<div slot="footer">
<el-button @click="materialSelectOpen = false">取消</el-button>
<el-button type="primary" @click="confirmMaterialSelect">确定</el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { listInbound, getInbound, delInbound, addInbound, updateInbound } from "@/api/inventory/inbound" import { listInbound, getInbound, delInbound, addInbound, updateInbound } from "@/api/inventory/inbound"
import InboundItems from "@/views/inventory/inbound_items/index.vue" import InboundItems from "@/views/inventory/inbound_items/index.vue"
import RightToolbar from "@/components/RightToolbar" // 确保导入这个组件
import MaterialSelector from "@/views/inventory/materials/materialsSeletor.vue";
export default { export default {
name: "Inbound", name: "Inbound",
components: { components: {
InboundItems InboundItems,
RightToolbar,
MaterialSelector
}, },
data() { data() {
return { return {
...@@ -306,14 +400,23 @@ export default { ...@@ -306,14 +400,23 @@ export default {
{ orderTypeId: '2', orderTypeName: '入库类型2' } { orderTypeId: '2', orderTypeName: '入库类型2' }
], ],
inBoundStatusOptions: [ inBoundStatusOptions: [
{ orderStatus: '1', orderStatusName: '草稿' }, { orderStatus: 1, orderStatusName: '草稿', type: 'info'},
{ orderStatus: '2', orderStatusName: '已完成' }, { orderStatus: 2, orderStatusName: '已完成', type: 'success'},
{ orderStatus: '3', orderStatusName: '已取消' } { orderStatus: 3, orderStatusName: '已取消', type: 'danger'}
], ],
orderTypeOptions:[ orderTypeOptions:[
{ orderType: '1', orderTypeName: '订单类型1' }, { orderType: '1', orderTypeName: '订单类型1' },
{ orderType: '2', orderTypeName: '订单类型2' } { orderType: '2', orderTypeName: '订单类型2' }
], ],
// 物料组件显示
materialSelectOpen: false,
selectedMaterialIds: [],
// 组件带来的选中的物料详情(code、name)
selectedMaterials: [],
detailOpen: false,
detailForm: {}, // 新增详情表单数据
// 组件监听修改时的orderId变化
orderId: null,
// 选中的明细项 // 选中的明细项
selectedItems: [], selectedItems: [],
// 遮罩层 // 遮罩层
...@@ -355,7 +458,7 @@ export default { ...@@ -355,7 +458,7 @@ export default {
batchCode: null, batchCode: null,
warehouseId: null, warehouseId: null,
ownerId: null, ownerId: null,
orderStatus: null, orderStatus: 1,
referenceNo: null, referenceNo: null,
plannedArrivalDate: undefined, plannedArrivalDate: undefined,
actualArrivalDate: undefined, actualArrivalDate: undefined,
...@@ -401,9 +504,30 @@ export default { ...@@ -401,9 +504,30 @@ export default {
this.inboundList = response.rows this.inboundList = response.rows
this.total = response.total this.total = response.total
this.loading = false this.loading = false
}).catch(() => {
this.loading = false
}) })
}, },
/** 获取状态样式类型 */
getStatusType(status) {
const item = this.inBoundStatusOptions.find(item => item.orderStatus === status)
return item ? item.type : 'info'
},
/** 获取状态类型名称 */
getStatusName(status) {
const item = this.inBoundStatusOptions.find(item => item.orderStatus === status)
return item ? item.orderStatusName : status
},
getInBoundTypeName(typeId) {
if (!typeId) return '未知类型'
const item = this.inBoundTypeOptions.find(item => item.orderTypeId === typeId)
return item ? item.orderTypeName : '未知类型'
},
getOrderTypeName(type) {
if (!type) return '未知类型'
const item = this.orderTypeOptions.find(item => item.orderType === type)
return item ? item.orderTypeName : '未知类型'
},
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.queryParams.pageNum = 1 this.queryParams.pageNum = 1
...@@ -412,14 +536,14 @@ export default { ...@@ -412,14 +536,14 @@ export default {
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
this.resetForm("queryForm") this.$refs.queryForm.resetFields()
this.handleQuery() this.handleQuery()
}, },
/** 多选框选中数据 */ /** 多选框选中数据 */
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.ids = selection.map(item => item.id) this.ids = selection.map(item => item.id)
this.single = selection.length!==1 this.single = selection.length !== 1
this.multiple = !selection.length this.multiple = !selection.length
}, },
...@@ -436,16 +560,54 @@ export default { ...@@ -436,16 +560,54 @@ export default {
const id = row.id || this.ids const id = row.id || this.ids
getInbound(id).then(response => { getInbound(id).then(response => {
this.form = response.data this.form = response.data
console.log(this.form) this.orderId = response.data.orderId
// 加载明细数据 // 加载明细数据
if (response.data.inboundOrderItemsList) { if (this.$refs.inboundItemsRef) {
this.form.inboundOrderItemsList = response.data.inboundOrderItemsList this.$refs.inboundItemsRef.loadRelatedData(this.orderId)
} }
this.open = true this.open = true
this.title = "修改入库" this.title = "修改入库"
}) })
}, },
// 打开物料选择弹窗
showMaterials(status) {
this.materialSelectOpen = status;
// 清空之前的选择
this.selectedMaterialIds = [];
this.selectedMaterials = [];
},
// 物料选择变化回调
handleMaterialChange(selectedRows) {
this.selectedMaterials = selectedRows;
},
// 确认选择物料并添加到明细
confirmMaterialSelect() {
if (this.selectedMaterials.length === 0) {
this.$message.warning("请选择物料");
return;
}
// 将选中的物料添加到入库明细
this.selectedMaterials.forEach(material => {
// 检查是否已存在该物料,避免重复添加
const exists = this.form.inboundOrderItemsList.some(
item => item.materialCode === material.materialCode
);
if (!exists) {
this.form.inboundOrderItemsList.push({
materialCode: material.materialCode, // 存储物料编码
materialName: material.materialName, // 仅用于展示
// 其他需要的字段...
});
}
});
this.materialSelectOpen = false;
this.$message.success(`成功添加 ${this.selectedMaterials.length} 个物料`);
},
/** 确认入库操作 */ /** 确认入库操作 */
handleConfirm(row) { handleConfirm(row) {
this.$confirm('确认要入库吗?', '提示', { this.$confirm('确认要入库吗?', '提示', {
...@@ -458,23 +620,34 @@ export default { ...@@ -458,23 +620,34 @@ export default {
// this.$modal.msgSuccess("确认成功") // this.$modal.msgSuccess("确认成功")
// this.getList() // this.getList()
// }) // })
this.$message.success('确认入库成功')
this.getList()
}) })
}, },
/** 查看详情 */ /** 查看详情 */
handleDetail(row) { handleDetail(row) {
// 可以打开一个新的详情页面或者弹窗 const id = row.id || this.ids
console.log('查看详情:', row) getInbound(id).then(response => {
this.detailForm = response.data
// 加载明细数据到详情
if (this.$refs.detailItemsRef) {
this.$refs.detailItemsRef.loadRelatedData(this.detailForm.orderId)
}
this.detailOpen = true
})
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const ids = row.id || this.ids const ids = row.id || this.ids
this.$modal.confirm('是否确认删除入库编号为"' + ids + '"的数据项?').then(function() { this.$confirm('是否确认删除入库编号为"' + ids + '"的数据项?', '提示', {
type: 'warning'
}).then(() => {
return delInbound(ids) return delInbound(ids)
}).then(() => { }).then(() => {
this.getList() this.getList()
this.$modal.msgSuccess("删除成功") this.$message.success("删除成功")
}).catch(() => {}) }).catch(() => {})
}, },
...@@ -510,13 +683,13 @@ export default { ...@@ -510,13 +683,13 @@ export default {
if (this.form.id != null) { if (this.form.id != null) {
updateInbound(submitData).then(response => { updateInbound(submitData).then(response => {
this.$modal.msgSuccess("修改成功") this.$message.success("修改成功")
this.open = false this.open = false
this.getList() this.getList()
}) })
} else { } else {
addInbound(submitData).then(response => { addInbound(submitData).then(response => {
this.$modal.msgSuccess("新增成功") this.$message.success("新增成功")
this.open = false this.open = false
this.getList() this.getList()
}) })
...@@ -539,7 +712,7 @@ export default { ...@@ -539,7 +712,7 @@ export default {
batchCode: null, batchCode: null,
warehouseId: null, warehouseId: null,
ownerId: null, ownerId: null,
orderStatus: null, orderStatus: 1,
referenceNo: null, referenceNo: null,
plannedArrivalDate: null, plannedArrivalDate: null,
actualArrivalDate: null, actualArrivalDate: null,
...@@ -559,7 +732,9 @@ export default { ...@@ -559,7 +732,9 @@ export default {
if (this.$refs.inboundItemsRef) { if (this.$refs.inboundItemsRef) {
this.$refs.inboundItemsRef.resetEmbeddedData() this.$refs.inboundItemsRef.resetEmbeddedData()
} }
this.resetForm("form") if (this.$refs.form) {
this.$refs.form.resetFields()
}
}, },
...@@ -634,8 +809,6 @@ export default { ...@@ -634,8 +809,6 @@ export default {
this.form.totalPackages = totals.packages this.form.totalPackages = totals.packages
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {
this.download('inventory/inbound/export', { this.download('inventory/inbound/export', {
...@@ -645,18 +818,28 @@ export default { ...@@ -645,18 +818,28 @@ export default {
} }
} }
</script> </script>
<style scoped> <style scoped>
/* 强制允许点击输入框 */ .scrollable-dialog .el-dialog__body {
.el-form-item .el-input__inner { max-height: 80vh; /* 最大高度80%视口高度 */
pointer-events: all !important; overflow-y: auto; /* 超出滚动 */
cursor: auto !important; padding: 20px;
}
.detail-container {
padding: 10px;
} }
/* 确保没有遮罩层 */
.el-dialog__wrapper { .remark-text {
overflow: visible !important; line-height: 1.5;
min-height: 40px;
white-space: pre-wrap;
}
.mb20 {
margin-bottom: 20px;
} }
.el-dialog__body { .mb8 {
overflow: visible !important; margin-bottom: 8px;
} }
</style> </style>
<template> <template>
<div class="inbound-items-container"> <div class="inbound-items-container">
<!-- 保留查询表单,但可以通过props控制显示 -->
<el-form
v-if="showSearchForm"
:model="queryParams"
ref="queryForm"
size="small"
:inline="true"
label-width="100px"
class="mb8"
>
<el-form-item label="货物ID" prop="materialId">
<el-input
v-model="queryParams.materialId"
placeholder="请输入货物ID"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="批次ID" prop="batchId">
<el-input
v-model="queryParams.batchId"
placeholder="请输入批次ID"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="仓库ID" prop="warehouseId">
<el-input
v-model="queryParams.warehouseId"
placeholder="请输入仓库ID"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="库位ID" prop="locationId">
<el-input
v-model="queryParams.locationId"
placeholder="请输入库位ID"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<!-- 添加关联查询按钮 -->
<el-button v-if="embedded" type="info" icon="el-icon-connection" size="mini" @click="handleLoadRelated">加载关联</el-button>
</el-form-item>
</el-form>
<!-- 操作按钮区域 --> <!-- 操作按钮区域 -->
<div v-if="showToolbar" class="toolbar-container mb8"> <div class="toolbar-container mb8">
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
v-if="showAddButton"
type="primary" type="primary"
plain plain
icon="el-icon-plus" icon="el-icon-plus"
size="mini" size="mini"
@click="handleAddItem" @click="handleAddItem"
>新增明细</el-button> >新增物料</el-button>
</el-col> </el-col>
<!-- <el-col :span="1.5">
<el-button
v-if="showEditButton"
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleEditItem"
>修改</el-button>
</el-col> -->
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
v-if="showDeleteButton"
type="danger" type="danger"
plain plain
icon="el-icon-delete" icon="el-icon-delete"
...@@ -85,7 +22,7 @@ ...@@ -85,7 +22,7 @@
@click="handleBatchDelete" @click="handleBatchDelete"
>删除</el-button> >删除</el-button>
</el-col> </el-col>
<el-col :span="1.5" v-if="showExportButton"> <el-col :span="1.5">
<el-button <el-button
type="warning" type="warning"
plain plain
...@@ -95,7 +32,7 @@ ...@@ -95,7 +32,7 @@
v-hasPermi="['inventory:inbound_items:import']" v-hasPermi="['inventory:inbound_items:import']"
>导入</el-button> >导入</el-button>
</el-col> </el-col>
<el-col :span="1.5" v-if="showExportButton"> <el-col :span="1.5">
<el-button <el-button
type="warning" type="warning"
plain plain
...@@ -111,7 +48,7 @@ ...@@ -111,7 +48,7 @@
<div class="table-container"> <div class="table-container">
<el-table <el-table
v-loading="loading" v-loading="loading"
:data="displayData" :data="pagedDisplayData"
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
:row-key="getRowKey" :row-key="getRowKey"
ref="dataTable" ref="dataTable"
...@@ -123,7 +60,6 @@ ...@@ -123,7 +60,6 @@
> >
<!-- 选择列 --> <!-- 选择列 -->
<el-table-column <el-table-column
v-if="showSelection"
type="selection" type="selection"
width="55" width="55"
align="center" align="center"
...@@ -131,7 +67,15 @@ ...@@ -131,7 +67,15 @@
/> />
<!-- 序号列 --> <!-- 序号列 -->
<el-table-column label="序号" align="center" width="60" type="index" /> <el-table-column
label="序号"
align="center"
width="60"
>
<template slot-scope="scope">
{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}
</template>
</el-table-column>
<!-- 数据列 --> <!-- 数据列 -->
<el-table-column <el-table-column
...@@ -166,7 +110,6 @@ ...@@ -166,7 +110,6 @@
<el-input-number <el-input-number
v-model="scope.row[column.prop]" v-model="scope.row[column.prop]"
:min="column.min || 0" :min="column.min || 0"
:max="column.max"
:step="column.step || 1" :step="column.step || 1"
size="small" size="small"
style="width: 100%" style="width: 100%"
...@@ -187,7 +130,6 @@ ...@@ -187,7 +130,6 @@
<!-- 只读模式 --> <!-- 只读模式 -->
<template v-else> <template v-else>
<!-- 状态显示 -->
<template v-if="column.prop === 'itemStatus'"> <template v-if="column.prop === 'itemStatus'">
<el-tag <el-tag
:type="getStatusType(scope.row[column.prop])" :type="getStatusType(scope.row[column.prop])"
...@@ -196,13 +138,9 @@ ...@@ -196,13 +138,9 @@
{{ getStatusText(scope.row[column.prop]) }} {{ getStatusText(scope.row[column.prop]) }}
</el-tag> </el-tag>
</template> </template>
<!-- 数字格式化 -->
<template v-else-if="column.type === 'number'"> <template v-else-if="column.type === 'number'">
{{ formatNumber(scope.row[column.prop]) }} {{ formatNumber(scope.row[column.prop]) }}
</template> </template>
<!-- 默认显示 -->
<template v-else> <template v-else>
{{ scope.row[column.prop] }} {{ scope.row[column.prop] }}
</template> </template>
...@@ -212,14 +150,12 @@ ...@@ -212,14 +150,12 @@
<!-- 操作列 --> <!-- 操作列 -->
<el-table-column <el-table-column
v-if="showActionColumn"
label="操作" label="操作"
align="center" align="center"
width="150" width="150"
fixed="right" fixed="right"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<template v-if="embedded">
<el-button <el-button
size="mini" size="mini"
type="text" type="text"
...@@ -241,32 +177,17 @@ ...@@ -241,32 +177,17 @@
@click="handleRowDelete(scope.row, scope.$index)" @click="handleRowDelete(scope.row, scope.$index)"
>删除</el-button> >删除</el-button>
</template> </template>
<template v-else>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="() => { this.$refs.dataTable.toggleRowSelection(scope.row); handleEditItem(); }"
>编辑</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleRowDelete(scope.row)"
>删除</el-button>
</template>
</template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 分页 --> <!-- 分页 -->
<pagination <pagination
v-if="showPagination && !embedded"
v-show="total>0" v-show="total>0"
:total="total" :total="total"
:page.sync="queryParams.pageNum" :page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize" :limit.sync="queryParams.pageSize"
@pagination="getList" @pagination="handlePagination"
@size-change="handleSizeChange"
/> />
<import-excel <import-excel
ref="import" ref="import"
...@@ -274,173 +195,38 @@ ...@@ -274,173 +195,38 @@
import-url="/inventory/inbound_items/import" import-url="/inventory/inbound_items/import"
template-url="/inventory/inbound_items/exportTemplate" template-url="/inventory/inbound_items/exportTemplate"
template-name="入库明细模板" template-name="入库明细模板"
@success="getList" @success="handleImportSuccess"
/>
</div>
<!-- 非嵌入式模式下的添加/编辑对话框 -->
<el-dialog
v-if="!embedded"
:title="dialogTitle"
:visible.sync="dialogVisible"
width="800px"
append-to-body
@closed="handleDialogClosed"
>
<el-form
ref="dialogForm"
:model="form"
:rules="rules"
label-width="120px"
size="small"
>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="货物ID" prop="materialId">
<el-input v-model="form.materialId" placeholder="请输入货物ID" />
</el-form-item>
<el-form-item label="批次ID" prop="batchId">
<el-input v-model="form.batchId" placeholder="请输入批次ID" />
</el-form-item>
<el-form-item label="仓库ID" prop="warehouseId">
<el-input v-model="form.warehouseId" placeholder="请输入仓库ID" />
</el-form-item>
<el-form-item label="库位ID" prop="locationId">
<el-input v-model="form.locationId" placeholder="请输入库位ID" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="计划数量" prop="plannedQuantity">
<el-input-number
v-model="form.plannedQuantity"
:min="0"
:step="1"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="实际数量" prop="actualQuantity">
<el-input-number
v-model="form.actualQuantity"
:min="0"
:step="1"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="单价" prop="unitPrice">
<el-input-number
v-model="form.unitPrice"
:min="0"
:precision="2"
style="width: 100%"
/> />
</el-form-item>
<el-form-item label="状态" prop="itemStatus">
<el-select v-model="form.itemStatus" placeholder="请选择状态" style="width: 100%">
<el-option label="待入库" value="1" />
<el-option label="已入库" value="2" />
<el-option label="已取消" value="3" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" :rows="2" placeholder="请输入备注" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="submitDialogForm">确 定</el-button>
</div> </div>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { listInbound_items, getInbound_items, delInbound_items, addInbound_items, updateInbound_items } from "@/api/inventory/inbound_items" import { listInbound_items, delInbound_items } from "@/api/inventory/inbound_items"
import ImportExcel from "@/components/ImportExcel/index" import ImportExcel from "@/components/ImportExcel/index"
export default { export default {
name: "InboundItems", name: "InboundItems",
inheritAttrs: false, inheritAttrs: false,
components: { components: { ImportExcel },
ImportExcel
},
props: { props: {
// 数据源(用于嵌入式模式) // 数据源
value: { value: {
type: Array, type: Array,
default: () => [] default: () => []
}, },
// 是否为嵌入式模式(在表单中) // 主表ID
embedded: {
type: Boolean,
default: false
},
// 主表ID(入库单号)
orderId: { orderId: {
type: [String, Number], type: [String, Number],
default: null default: null
}, },
// 是否显示查询表单
showSearchForm: {
type: Boolean,
default: true
},
// 是否显示工具栏
showToolbar: {
type: Boolean,
default: true
},
// 是否显示操作列
showActionColumn: {
type: Boolean,
default: true
},
// 是否显示选择框
showSelection: {
type: Boolean,
default: false
},
// 是否显示分页
showPagination: {
type: Boolean,
default: true
},
// 是否显示新增按钮
showAddButton: {
type: Boolean,
default: true
},
// 是否显示编辑按钮
showEditButton: {
type: Boolean,
default: true
},
// 是否显示删除按钮
showDeleteButton: {
type: Boolean,
default: true
},
// 是否显示导出按钮
showExportButton: {
type: Boolean,
default: true
},
// 权限控制
permissions: {
type: Array,
default: () => []
},
// 初始查询参数
initQuery: {
type: Object,
default: () => ({})
},
// 表格列配置 // 表格列配置
columns: { columns: {
type: Array, type: Array,
default: () => [ default: () => [
{ prop: 'materialId', label: '货物ID', width: '120', editable: true }, { prop: 'materialId', label: '货物ID', width: '120', editable: true },
{ prop: 'batchId', label: '批次ID', width: '120', editable: true }, { prop: 'materialsName', label: '货物名称', width: '120', editable: true},
// { prop: 'batchId', label: '批次ID', width: '120', editable: true },
{ prop: 'warehouseId', label: '仓库ID', width: '120', editable: true }, { prop: 'warehouseId', label: '仓库ID', width: '120', editable: true },
{ prop: 'locationId', label: '库位ID', width: '120', editable: true }, { prop: 'locationId', label: '库位ID', width: '120', editable: true },
{ prop: 'plannedQuantity', label: '计划数量', width: '100', type: 'number', editable: true }, { prop: 'plannedQuantity', label: '计划数量', width: '100', type: 'number', editable: true },
...@@ -448,68 +234,48 @@ export default { ...@@ -448,68 +234,48 @@ export default {
{ prop: 'plannedPackages', label: '计划件数', width: '100', type: 'number', editable: true }, { prop: 'plannedPackages', label: '计划件数', width: '100', type: 'number', editable: true },
{ prop: 'actualPackages', label: '实际件数', width: '100', type: 'number', editable: true }, { prop: 'actualPackages', label: '实际件数', width: '100', type: 'number', editable: true },
{ prop: 'unitPrice', label: '单价', width: '100', type: 'number', editable: true }, { prop: 'unitPrice', label: '单价', width: '100', type: 'number', editable: true },
{ prop: 'itemStatus', label: '状态', width: '100', editable: true, type: 'select' },
{ prop: 'remark', label: '备注', minWidth: '150', editable: true }, { prop: 'remark', label: '备注', minWidth: '150', editable: true },
] ]
},
// 每页条数
pageSize: {
type: Number,
default: 10
} }
}, },
data() { data() {
return { return {
// 遮罩层
loading: false, loading: false,
// 选中数组
selectedRows: [], selectedRows: [],
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 总条数
total: 0, total: 0,
// 显示数据
displayData: [], displayData: [],
// 对话框相关 pagedDisplayData: [],
dialogVisible: false,
dialogTitle: "",
dialogMode: 'add', // 'add' or 'edit'
// 查询参数
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: this.pageSize,
orderId: this.orderId, orderId: this.orderId
materialId: null,
batchId: null,
warehouseId: null,
locationId: null,
labelColor: null,
...this.initQuery
},
// 表单参数
form: this.getDefaultForm(),
// 表单校验
rules: {
materialId: [
{ required: true, message: "货物ID不能为空", trigger: "blur" }
],
plannedQuantity: [
{ required: true, message: "计划数量不能为空", trigger: "blur" },
{ type: 'number', min: 0, message: "计划数量不能小于0", trigger: "blur" }
],
actualQuantity: [
{ type: 'number', min: 0, message: "实际数量不能小于0", trigger: "blur" }
]
}, },
// 缓存原始数据(用于嵌入式模式)
cachedData: [] cachedData: []
} }
}, },
computed: {
multiple() {
return this.selectedRows.length === 0
},
// 计算总数
totals() {
return this.displayData.reduce((acc, item) => {
acc.plannedQuantity += parseFloat(item.plannedQuantity) || 0
acc.actualQuantity += parseFloat(item.actualQuantity) || 0
acc.totalAmount += (parseFloat(item.plannedQuantity) || 0) * (parseFloat(item.unitPrice) || 0)
return acc
}, { plannedQuantity: 0, actualQuantity: 0, totalAmount: 0 })
}
},
watch: { watch: {
// 监听value变化(嵌入式模式)
value: { value: {
immediate: true, immediate: true,
handler(newVal) { handler(newVal) {
if (this.embedded) {
// 只有当数据真正变化时才更新
const stringifiedNewVal = JSON.stringify(newVal || []) const stringifiedNewVal = JSON.stringify(newVal || [])
const stringifiedDisplayData = JSON.stringify(this.displayData.map(item => { const stringifiedDisplayData = JSON.stringify(this.displayData.map(item => {
const { editable, tempId, ...rest } = item const { editable, tempId, ...rest } = item
...@@ -523,204 +289,159 @@ export default { ...@@ -523,204 +289,159 @@ export default {
editable: false, editable: false,
tempId: item.id || Date.now() + Math.random() tempId: item.id || Date.now() + Math.random()
})) }))
this.total = this.displayData.length
this.handlePagination()
this.calculateTotals() this.calculateTotals()
} }
} }
}
}, },
// 监听嵌入式数据变化,通知父组件
displayData: { displayData: {
deep: true, deep: true,
handler(newVal) { handler() {
if (this.embedded) { this.total = this.displayData.length
const dataToEmit = newVal.map(item => { this.handlePagination()
const { editable, tempId, ...rest } = item
// 确保新添加的行有orderId
if (this.orderId && !rest.orderId) {
rest.orderId = this.orderId
}
return rest
})
// 避免不必要的更新循环
const shouldEmit = JSON.stringify(dataToEmit) !== JSON.stringify(this.value || [])
if (shouldEmit) {
this.$emit('input', dataToEmit)
this.$emit('data-change', dataToEmit)
}
this.calculateTotals() this.calculateTotals()
} this.syncDataToParent()
} }
}, },
// 监听orderId变化
orderId: { orderId: {
immediate: true, immediate: true,
handler(newVal) { handler(newVal) {
if (newVal) {
if (!this.embedded) {
this.queryParams.orderId = newVal this.queryParams.orderId = newVal
this.getList() this.loadRelatedData(newVal)
} else { this.displayData.forEach(item => {
// 在嵌入式模式下,更新所有没有orderId的项 if (!item.orderId) item.orderId = newVal
this.displayData = this.displayData.map(item => ({ })
...item,
orderId: item.orderId || newVal
}))
}
}
}
} }
}, },
computed: { pageSize: {
// 计算总数量和金额 handler(val) {
totals() { this.queryParams.pageSize = val
if (!this.displayData.length) return { plannedQuantity: 0, actualQuantity: 0, totalAmount: 0 } this.handlePagination()
}
return this.displayData.reduce((acc, item) => {
acc.plannedQuantity += parseFloat(item.plannedQuantity) || 0
acc.actualQuantity += parseFloat(item.actualQuantity) || 0
acc.totalAmount += (parseFloat(item.plannedQuantity) || 0) * (parseFloat(item.unitPrice) || 0)
return acc
}, { plannedQuantity: 0, actualQuantity: 0, totalAmount: 0 })
} }
}, },
created() { created() {
if (!this.embedded) { this.handlePagination()
this.getList()
}
}, },
methods: { methods: {
/** 获取默认表单数据 */ // 加载关联数据
getDefaultForm() { loadRelatedData(orderId) {
return { if (!orderId) return
id: null,
orderId: this.orderId,
materialId: null,
batchId: null,
warehouseId: null,
locationId: null,
plannedQuantity: 0,
actualQuantity: 0,
plannedPackages: 0,
actualPackages: 0,
unitPrice: 0,
itemStatus: '1',
remark: null
}
},
/** 查询数据列表 */
getList() {
this.loading = true this.loading = true
this.queryParams.orderId = orderId
listInbound_items(this.queryParams).then(response => { listInbound_items(this.queryParams).then(response => {
this.displayData = response.rows this.displayData = response.rows.map(item => ({
...item,
editable: false,
tempId: item.id || Date.now() + Math.random()
}))
this.total = response.total this.total = response.total
this.handlePagination()
this.loading = false this.loading = false
this.$emit('load-success', response)
}).catch(() => { }).catch(() => {
this.loading = false this.loading = false
}) })
}, },
// 分页处理
handlePagination() {
const totalItems = this.displayData.length
const totalPages = Math.ceil(totalItems / this.queryParams.pageSize)
/** 搜索按钮操作 */ // 页码越界处理
handleQuery() { if (this.queryParams.pageNum > totalPages && totalPages > 0) {
this.queryParams.pageNum = 1 this.queryParams.pageNum = totalPages
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm")
this.queryParams = {
pageNum: 1,
pageSize: 10,
orderId: this.orderId,
...this.initQuery
} }
this.handleQuery()
},
/** 加载关联数据 */ // 计算分页数据
handleLoadRelated() { const start = (this.queryParams.pageNum - 1) * this.queryParams.pageSize
if (!this.orderId) { const end = start + this.queryParams.pageSize
this.$message.warning('请先保存主表信息') this.pagedDisplayData = this.displayData.slice(start, end)
return
}
this.queryParams.orderId = this.orderId
this.getList()
}, },
// 切换每页条数
/** 处理选择变化 */ handleSizeChange(val) {
handleSelectionChange(selection) { this.queryParams.pageSize = val
this.selectedRows = selection this.queryParams.pageNum = 1
this.ids = selection.map(item => item.id) this.handlePagination()
this.single = selection.length !== 1
this.multiple = !selection.length
this.$emit('selection-change', selection)
}, },
// 同步数据到父组件
/** 获取行key */ syncDataToParent() {
const dataToEmit = this.displayData.map(item => {
const { editable, tempId, ...rest } = item
return rest
})
this.$emit('input', dataToEmit)
this.$emit('data-change', dataToEmit)
},
// 获取行key
getRowKey(row) { getRowKey(row) {
return row.id || row.tempId return row.id || row.tempId
}, },
// 新增物料
/** 新增明细项 */
handleAddItem() { handleAddItem() {
if (this.embedded) { this.$emit('show-materials',true)
// 嵌入式模式:直接添加行
const newItem = { const newItem = {
...this.getDefaultForm(), id: null,
orderId: this.orderId,
materialId: null,
batchId: null,
warehouseId: null,
locationId: null,
plannedQuantity: 0,
actualQuantity: 0,
plannedPackages: 0,
actualPackages: 0,
unitPrice: 0,
remark: null,
editable: true, editable: true,
tempId: Date.now() + Math.random() tempId: Date.now() + Math.random()
} }
this.displayData.push(newItem) this.displayData.push(newItem)
this.$emit('item-added', newItem)
} else {
// 独立模式:打开对话框
this.dialogMode = 'add'
this.dialogTitle = "添加入库明细"
this.form = this.getDefaultForm()
this.dialogVisible = true
}
},
/** 编辑明细项 */ // 自动跳转到最后一页
handleEditItem() { const totalPages = Math.ceil(this.displayData.length / this.queryParams.pageSize)
if (this.single) return if (totalPages > this.queryParams.pageNum) {
const row = this.selectedRows[0] this.queryParams.pageNum = totalPages
if (this.embedded) {
// 嵌入式模式:直接设置为可编辑
const index = this.displayData.findIndex(item => (item.id || item.tempId) === (row.id || row.tempId))
if (index > -1) {
this.$set(this.displayData[index], 'editable', true)
} }
} else {
// 独立模式:打开对话框
this.dialogMode = 'edit'
this.dialogTitle = "修改入库明细"
this.form = JSON.parse(JSON.stringify(row))
this.dialogVisible = true
}
},
/** 行编辑 */ this.$emit('item-added', newItem)
},
// 行编辑
handleRowEdit(row) { handleRowEdit(row) {
const index = this.displayData.findIndex(item => (item.id || item.tempId) === (row.id || row.tempId)) const index = this.displayData.findIndex(item => item.tempId === row.tempId)
if (index > -1) { if (index > -1) {
this.$set(this.displayData[index], 'editable', true) this.$set(this.displayData[index], 'editable', true)
} }
}, },
// 行保存
/** 行保存 */
handleRowSave(row) { handleRowSave(row) {
const index = this.displayData.findIndex(item => (item.id || item.tempId) === (row.id || row.tempId)) const index = this.displayData.findIndex(item => item.tempId === row.tempId)
if (index > -1) { if (index > -1) {
this.$set(this.displayData[index], 'editable', false) this.$set(this.displayData[index], 'editable', false)
this.$emit('row-saved', row) this.$emit('row-saved', row)
} }
}, },
// 行删除
handleRowDelete(row, index) {
this.$confirm('确定要删除该明细项吗?', '提示', {
type: 'warning'
}).then(() => {
this.displayData.splice(index, 1)
// 删除后页码处理
const currentPageDataCount = this.pagedDisplayData.length
if (currentPageDataCount === 0 && this.queryParams.pageNum > 1) {
this.queryParams.pageNum -= 1
}
/** 批量删除 */ this.$emit('row-deleted', row)
})
},
// 批量删除
handleBatchDelete() { handleBatchDelete() {
if (this.selectedRows.length === 0) { if (this.selectedRows.length === 0) {
this.$message.warning('请先选择要删除的项') this.$message.warning('请先选择要删除的项')
...@@ -728,131 +449,88 @@ export default { ...@@ -728,131 +449,88 @@ export default {
} }
this.$confirm('确定要删除选中的明细项吗?', '提示', { this.$confirm('确定要删除选中的明细项吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
if (this.embedded) {
// 嵌入式模式:从displayData中删除
const idsToDelete = this.selectedRows.map(row => row.id || row.tempId) const idsToDelete = this.selectedRows.map(row => row.id || row.tempId)
this.displayData = this.displayData.filter(item => this.displayData = this.displayData.filter(item =>
!idsToDelete.includes(item.id || item.tempId) !idsToDelete.includes(item.id || item.tempId)
) )
// 删除后页码处理
const totalPages = Math.ceil(this.displayData.length / this.queryParams.pageSize)
if (this.queryParams.pageNum > totalPages && totalPages > 0) {
this.queryParams.pageNum = totalPages
}
this.selectedRows = [] this.selectedRows = []
this.$emit('batch-delete', idsToDelete) this.$emit('batch-delete', idsToDelete)
} else {
// 独立模式:调用API删除
const ids = this.selectedRows.map(row => row.id).join(',')
delInbound_items(ids).then(() => {
this.$modal.msgSuccess("删除成功")
this.getList()
this.selectedRows = []
})
}
}) })
}, },
/** 导入按钮操作 */
/** 行删除 */ handleImport() {
handleRowDelete(row, index) { this.$refs.import.show()
this.$confirm('确定要删除该明细项吗?', '提示', { },
confirmButtonText: '确定', // 导入成功处理
cancelButtonText: '取消', handleImportSuccess() {
type: 'warning' this.$message.success('导入成功')
}).then(() => { this.loading = true
if (this.embedded) { listInbound_items(this.queryParams).then(response => {
this.displayData.splice(index, 1) this.displayData = response.rows.map(item => ({
this.$emit('row-deleted', row) ...item,
} else { editable: false,
delInbound_items(row.id).then(() => { tempId: item.id || Date.now() + Math.random()
this.$modal.msgSuccess("删除成功") }))
this.getList() this.loading = false
})
}
}) })
}, },
// 导出
/** 导出 */
handleExport() { handleExport() {
this.download('inventory/inbound_items/export', { this.download('inventory/inbound_items/export', {
...this.queryParams ...this.queryParams
}, `inbound_items_${new Date().getTime()}.xlsx`) }, `inbound_items_${new Date().getTime()}.xlsx`)
}, },
// 输入框变化
/** 处理输入框变化 */
handleInputChange(row, prop) { handleInputChange(row, prop) {
this.$emit('cell-change', { row, prop, value: row[prop] }) this.$emit('cell-change', { row, prop, value: row[prop] })
}, },
// 数字变化
/** 处理数字变化 */
handleNumberChange(row, prop) { handleNumberChange(row, prop) {
row[prop] = parseFloat(row[prop]) || 0 row[prop] = parseFloat(row[prop]) || 0
this.$emit('cell-change', { row, prop, value: row[prop] }) this.$emit('cell-change', { row, prop, value: row[prop] })
}, },
// 选择框变化
/** 处理列变化 */
handleColumnChange(row, prop) { handleColumnChange(row, prop) {
this.$emit('cell-change', { row, prop, value: row[prop] }) this.$emit('cell-change', { row, prop, value: row[prop] })
}, },
// 输入框失去焦点
/** 处理输入框失去焦点 */
handleInputBlur(row, prop) { handleInputBlur(row, prop) {
// 可以在这里添加验证逻辑
this.$emit('cell-blur', { row, prop, value: row[prop] }) this.$emit('cell-blur', { row, prop, value: row[prop] })
}, },
// 选择变化
/** 提交对话框表单 */ handleSelectionChange(selection) {
submitDialogForm() { this.selectedRows = selection
this.$refs["dialogForm"].validate(valid => { this.$emit('selection-change', selection)
if (valid) {
if (this.dialogMode === 'add') {
addInbound_items(this.form).then(response => {
this.$modal.msgSuccess("新增成功")
this.dialogVisible = false
this.getList()
})
} else {
updateInbound_items(this.form).then(response => {
this.$modal.msgSuccess("修改成功")
this.dialogVisible = false
this.getList()
})
}
}
})
},
/** 对话框关闭 */
handleDialogClosed() {
this.$refs["dialogForm"].resetFields()
}, },
// 获取状态类型
/** 获取状态类型 */
getStatusType(status) { getStatusType(status) {
const map = { '1': 'info', '2': 'success', '3': 'danger' } const map = { '1': 'info', '2': 'success', '3': 'danger' }
return map[status] || 'info' return map[status] || 'info'
}, },
// 获取状态文本
/** 获取状态文本 */
getStatusText(status) { getStatusText(status) {
const map = { '1': '待入库', '2': '已入库', '3': '已取消' } const map = { '1': '待入库', '2': '已入库', '3': '已取消' }
return map[status] || status return map[status] || status
}, },
// 格式化数字
/** 格式化数字 */
formatNumber(num) { formatNumber(num) {
if (num == null) return '' if (num == null) return ''
return parseFloat(num).toLocaleString() return parseFloat(num).toLocaleString()
}, },
// 计算总数并通知父组件
/** 计算总数并通知父组件 */
calculateTotals() { calculateTotals() {
if (this.embedded) { this.$emit('totals-change', this.totals)
const totals = this.totals
this.$emit('totals-change', totals)
}
}, },
// 验证数据
/** 验证数据 */
validate() { validate() {
const errors = [] const errors = []
this.displayData.forEach((item, index) => { this.displayData.forEach((item, index) => {
...@@ -865,57 +543,20 @@ export default { ...@@ -865,57 +543,20 @@ export default {
}) })
return errors return errors
}, },
// 获取所有数据
/** 获取所有数据 */
getItems() { getItems() {
return this.displayData.map(item => { return this.displayData.map(item => {
const { editable, tempId, ...rest } = item const { editable, tempId, ...rest } = item
return rest return rest
}) })
}, },
// 重置数据
/** 重置数据(嵌入式模式) */
resetEmbeddedData() { resetEmbeddedData() {
this.displayData = JSON.parse(JSON.stringify(this.cachedData)).map(item => ({ this.displayData = JSON.parse(JSON.stringify(this.cachedData)).map(item => ({
...item, ...item,
editable: false, editable: false,
tempId: item.id || Date.now() + Math.random() tempId: item.id || Date.now() + Math.random()
})) }))
},
/** 导入按钮操作 */
handleImport() {
this.$refs.import.show()
},
/** 新增明细项(供父组件调用) */
addItem(options = {}) {
const newItem = {
...this.getDefaultForm(),
...options,
orderId: this.orderId || options.orderId,
editable: true,
tempId: Date.now() + Math.random()
}
this.displayData.push(newItem)
return newItem
},
/** 新增空行(嵌入式模式) */
addEmptyRow() {
return this.addItem()
},
/** 删除选中项(供父组件调用) */
deleteSelected() {
if (this.selectedRows.length > 0) {
const idsToDelete = this.selectedRows.map(row => row.id || row.tempId)
this.displayData = this.displayData.filter(item =>
!idsToDelete.includes(item.id || item.tempId)
)
this.selectedRows = []
this.$emit('batch-delete', idsToDelete)
return true
}
return false
} }
} }
} }
......
...@@ -143,8 +143,8 @@ ...@@ -143,8 +143,8 @@
<!-- 表格列保持不变 --> <!-- 表格列保持不变 -->
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" label="序号" align="center"/> <el-table-column type="index" label="序号" align="center"/>
<el-table-column label="物料编码" align="center" prop="materialCode" /> <el-table-column label="物料编码" align="center" prop="materialCode" width="120"/>
<el-table-column label="物料名称" align="center" prop="materialName" /> <el-table-column label="物料名称" align="center" prop="materialName" width="150"/>
<el-table-column label="SAP物料号" align="center" prop="sapNo" /> <el-table-column label="SAP物料号" align="center" prop="sapNo" />
<el-table-column label="TS Code" align="center" prop="tsCode" /> <el-table-column label="TS Code" align="center" prop="tsCode" />
<el-table-column label="物料分类" align="center" prop="categoryCode" > <el-table-column label="物料分类" align="center" prop="categoryCode" >
......
<template>
<div class="material-selector-container" style="overflow: hidden;">
<splitpanes class="default-theme">
<!-- 左侧分类树 -->
<pane size="16" style="overflow: auto;">
<TreeComponent
ref="treeComponent"
:tree-data="categoryTreeData"
:tree-props="treeProps"
:node-key="nodeKey"
:show-search="true"
search-placeholder="请输入分类名称"
:default-expand-all="true"
:highlight-current="true"
:loading="loadingTree"
@node-click="handleTreeClick"
>
<template #node-content="{ node, data }">
<span class="custom-tree-node">{{ node.label }}</span>
</template>
</TreeComponent>
</pane>
<!-- 右侧物料列表(仅展示和查询) -->
<pane size="84" style="overflow: auto;">
<div style="padding: 10px; display: flex; flex-direction: column;">
<!-- 查询表单 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="88px">
<el-form-item label="物料编码" prop="materialCode">
<el-input
v-model="queryParams.materialCode"
placeholder="请输入物料编码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="物料名称" prop="materialName">
<el-input
v-model="queryParams.materialName"
placeholder="请输入物料名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="SAP物料号" prop="sapNo">
<el-input
v-model="queryParams.sapNo"
placeholder="请输入SAP物料号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="物料分类" prop="categoryNameInput">
<el-input
v-model="queryParams.categoryNameInput"
placeholder="请输入物料分类"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 物料表格(隐藏操作列,保留选择功能) -->
<el-table
v-loading="loading"
:data="materialsList"
@selection-change="handleSelectionChange"
:scroll-x="true"
:row-key="row => row.id"
@row-click="handleRowClick"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" label="序号" align="center"/>
<el-table-column label="物料编码" align="center" prop="materialCode" width="120"/>
<el-table-column label="物料名称" align="center" prop="materialName" width="150"/>
<el-table-column label="SAP物料号" align="center" prop="sapNo" />
<el-table-column label="TS Code" align="center" prop="tsCode" />
<el-table-column label="物料分类" align="center" prop="categoryCode" >
<template slot-scope="scope">
{{ scope.row.displayCategory || categoryMap[scope.row.categoryCode] || scope.row.categoryCode }}
</template>
</el-table-column>
<el-table-column label="规格型号" align="center" prop="specification" />
<el-table-column label="计量单位" align="center" prop="materialUnit" />
<el-table-column label="是否批次管理" align="center" prop="isBatchManaged">
<template slot-scope="scope">
<el-tag :type="scope.row.isBatchManaged === 1 ? 'success' : 'info'" size="mini">
{{ scope.row.isBatchManaged === 1 ? '是' : '否' }}
</el-tag>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
</pane>
</splitpanes>
</div>
</template>
<script>
import { listMaterials } from "@/api/inventory/materials"
import { listMaterials_category } from "@/api/inventory/materials_category"
import TreeComponent from '@/views/inventory/materials_category/treeComponent.vue'
import { Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'
export default {
name: "MaterialSelector",
components: { TreeComponent, Splitpanes, Pane },
props: {
// 支持传入默认选中的物料ID(可选)
value: {
type: [Array, Number, String],
default: () => []
},
// 是否允许多选
multiple: {
type: Boolean,
default: true
}
},
data() {
return {
categoryTreeData: [],
treeProps: { children: 'children', label: 'label', value: 'sid' },
nodeKey: 'sid',
loadingTree: false,
categoryMap: {},
categoryNameToCodeMap: {},
currentNodeId: null,
queryParams: {
pageNum: 1,
pageSize: 10,
materialCode: null,
materialName: null,
sapNo: null,
tsCode: null,
categoryCode: null,
categoryNameInput: null,
specification: null,
},
materialsList: [],
total: 0,
loading: true,
selectedRows: [] // 选中的物料数据
}
},
watch: {
value: {
immediate: true,
handler(val) {
// 初始化选中状态(如果需要)
if (val && val.length) {
this.$nextTick(() => {
if (this.$refs.table) {
this.materialsList.forEach(row => {
if (val.includes(row.id)) {
this.$refs.table.toggleRowSelection(row, true)
}
})
}
})
}
}
}
},
async created() {
await Promise.all([
this.getCategoryTreeData(),
this.getCategoryList()
]);
this.getList()
},
methods: {
async getCategoryList() {
try {
const response = await listMaterials_category({ pageNum: 1, pageSize: 1000 });
if (response.rows && response.rows.length > 0) {
this.categoryMap = {};
this.categoryNameToCodeMap = {};
response.rows.forEach(item => {
if (item.isUsed !== 0 && item.isUsed !== '0') {
this.categoryMap[item.categoryCode] = item.categoryName;
if (!this.categoryNameToCodeMap[item.categoryName]) {
this.categoryNameToCodeMap[item.categoryName] = item.categoryCode;
} else if (!Array.isArray(this.categoryNameToCodeMap[item.categoryName])) {
this.categoryNameToCodeMap[item.categoryName] = [this.categoryNameToCodeMap[item.categoryName], item.categoryCode];
} else {
this.categoryNameToCodeMap[item.categoryName].push(item.categoryCode);
}
}
});
}
} catch (error) {
console.error('获取分类列表失败:', error);
}
},
async getCategoryTreeData() {
this.loadingTree = true;
try {
const response = await listMaterials_category({ pageNum: 1, pageSize: 1000 });
if (response.rows && response.rows.length > 0) {
const activeCategories = response.rows.filter(item => item.isUsed !== 0 && item.isUsed !== '0');
this.categoryTreeData = this.buildTreeData(activeCategories);
}
} catch (error) {
console.error('获取分类树数据失败:', error);
} finally {
this.loadingTree = false;
}
},
buildTreeData(list, parentId = null) {
return list
.filter(item => parentId === null
? (!item.parentId || item.parentId === 0 || item.parentId === '0')
: item.parentId == parentId
)
.map(item => ({
...item,
sid: String(item.id),
label: item.categoryName,
children: this.buildTreeData(list, item.id).length
? this.buildTreeData(list, item.id)
: undefined
}));
},
handleTreeClick(data) {
this.currentNodeId = data.sid;
this.queryParams.categoryCode = data.categoryCode;
this.queryParams.categoryNameInput = null;
this.queryParams.pageNum = 1;
this.getList();
},
getList() {
this.loading = true;
listMaterials(this.queryParams).then(response => {
this.materialsList = response.rows
.filter(item => item.isUsed !== 0 && item.isUsed !== '0')
.map(item => ({
...item,
displayCategory: this.categoryMap[item.categoryCode] || `${item.categoryCode}(未匹配分类)`
}));
this.total = response.total;
}).finally(() => {
this.loading = false;
});
},
handleQuery() {
const inputName = this.queryParams.categoryNameInput;
if (inputName) {
const matchedCode = this.categoryNameToCodeMap[inputName];
if (matchedCode) {
this.queryParams.categoryCode = Array.isArray(matchedCode) ? matchedCode[0] : matchedCode;
} else {
const matchedCodes = Object.entries(this.categoryMap)
.filter(([code, name]) => name.includes(inputName))
.map(([code]) => code);
if (matchedCodes.length > 0) {
this.queryParams.categoryCode = matchedCodes[0];
}
}
}
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.queryParams = {
pageNum: 1,
pageSize: 10,
materialCode: null,
materialName: null,
sapNo: null,
tsCode: null,
categoryCode: null,
categoryNameInput: null,
specification: null,
};
this.currentNodeId = null;
if (this.$refs.treeComponent && this.$refs.treeComponent.$refs.tree) {
this.$refs.treeComponent.$refs.tree.setCurrentKey(null);
}
this.getList();
},
handleSelectionChange(selection) {
this.selectedRows = selection;
const selectedData = selection.map(item => ({
id: item.id,
materialCode: item.materialCode,
materialName: item.materialName,
// specification: item.specification, // 可选:规格型号
// materialUnit: item.materialUnit // 可选:计量单位
}));
this.$emit('change', selectedData); // 返回包含所需字段的对象
this.$emit('input', selection.map(item => item.id));
},
handleRowClick(row) {
if (!this.multiple) {
// 单选模式下点击行直接选中并触发事件
this.$refs.table.clearSelection();
this.$refs.table.toggleRowSelection(row, true);
this.$emit('input', row.id);
this.$emit('select', row);
}
},
// 提供外部调用的方法:获取选中的物料详情
getSelectedMaterials() {
return this.selectedRows;
}
}
}
</script>
<style scoped>
.material-selector-container {
height: 100%;
min-height: 500px;
}
.custom-tree-node {
font-size: 14px;
}
</style>
\ No newline at end of file
...@@ -83,10 +83,10 @@ public class InboundOrdersController extends BaseController ...@@ -83,10 +83,10 @@ public class InboundOrdersController extends BaseController
} }
/** /**
* 修改入库单 * 修改入库单
*/ */
@PreAuthorize("@ss.hasPermi('inventory:inbound:edit')") @PreAuthorize("@ss.hasPermi('inventory:inbound:edit')")
@Log(title = "入库单", businessType = BusinessType.UPDATE) @Log(title = "入库单", businessType = BusinessType.UPDATE)
@PutMapping @PutMapping
public AjaxResult edit(@RequestBody InboundOrders inboundOrders) public AjaxResult edit(@RequestBody InboundOrders inboundOrders)
{ {
...@@ -94,10 +94,10 @@ public class InboundOrdersController extends BaseController ...@@ -94,10 +94,10 @@ public class InboundOrdersController extends BaseController
} }
/** /**
* 删除入库单 * 删除入库单
*/ */
@PreAuthorize("@ss.hasPermi('inventory:inbound:remove')") @PreAuthorize("@ss.hasPermi('inventory:inbound:remove')")
@Log(title = "入库单", businessType = BusinessType.DELETE) @Log(title = "入库单", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}") @DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids) public AjaxResult remove(@PathVariable String[] ids)
{ {
......
...@@ -77,7 +77,7 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService ...@@ -77,7 +77,7 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
public int updateInboundOrders(InboundOrders inboundOrders) public int updateInboundOrders(InboundOrders inboundOrders)
{ {
inboundOrders.setUpdateTime(DateUtils.getNowDate()); inboundOrders.setUpdateTime(DateUtils.getNowDate());
inboundOrdersMapper.deleteInboundOrderItemsByOrderId(inboundOrders.getId()); inboundOrdersMapper.deleteInboundOrderItemsByOrderId(inboundOrders.getOrderId());
insertInboundOrderItems(inboundOrders); insertInboundOrderItems(inboundOrders);
return inboundOrdersMapper.updateInboundOrders(inboundOrders); return inboundOrdersMapper.updateInboundOrders(inboundOrders);
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论