Commit e1b0bfb8 by zhangtw

入库结合物料组件

parent 203b5590
...@@ -28,36 +28,33 @@ ...@@ -28,36 +28,33 @@
</el-form-item> </el-form-item>
<el-form-item label="入库类型" prop="orderTypeId"> <el-form-item label="入库类型" prop="orderTypeId">
<el-select v-model="queryParams.orderTypeId" placeholder="请选择入库类型" clearable> <el-select v-model="queryParams.orderTypeId" placeholder="请选择入库类型" clearable>
<el-option <el-option
v-for="item in inBoundTypeOptions" v-for="item in inBoundTypeOptions"
: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>
<el-form-item label="入库单状态" prop="orderStatus"> <el-form-item label="入库单状态" prop="orderStatus">
<el-select v-model="queryParams.orderStatus" placeholder="请选择入库单状态" clearable> <el-select v-model="queryParams.orderStatus" placeholder="请选择入库单状态" clearable>
<el-option <el-option
v-for="item in inBoundStatusOptions" v-for="item in inBoundStatusOptions"
: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">
<el-select v-model="queryParams.orderType" placeholder="请选择订单类型" clearable> <el-select v-model="queryParams.orderType" placeholder="请选择订单类型" clearable>
<el-option <el-option
v-for="item in orderTypeOptions" v-for="item in orderTypeOptions"
: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">
...@@ -165,7 +180,7 @@ ...@@ -165,7 +180,7 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination <pagination
v-show="total>0" v-show="total>0"
:total="total" :total="total"
...@@ -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,21 +221,42 @@ ...@@ -208,21 +221,42 @@
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row>
<el-divider content-position="center">入库其他信息</el-divider>
<el-row :gutter="24">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="计划量" prop="totalPlannedQuantity"> <el-form-item label="系统编号" prop="systemNo">
<el-input v-model="form.totalPlannedQuantity" placeholder="请输入计划量" /> <el-input v-model="form.systemNo" placeholder="请输入系统编号" />
</el-form-item> </el-form-item>
<el-form-item label="总件数" prop="totalPackages"> <el-form-item label="货主ID" prop="ownerId">
<el-input v-model="form.totalPackages" placeholder="请输入总件数" /> <el-input v-model="form.ownerId" placeholder="请输入货主ID" />
</el-form-item> </el-form-item>
<el-form-item label="仓库ID" prop="warehouseId"> <el-form-item label="订单类型" prop="orderType">
<el-input v-model="form.warehouseId" placeholder="请输入仓库ID" /> <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-form-item>
</el-col> </el-col>
</el-row>
<el-divider content-position="center">入库其他信息</el-divider>
<el-row :gutter="24">
<el-col :span="12">
<div class="form-col">
<el-form-item label="计划量" prop="totalPlannedQuantity">
<el-input v-model="form.totalPlannedQuantity" placeholder="请输入计划量" />
</el-form-item>
<el-form-item label="总件数" prop="totalPackages">
<el-input v-model="form.totalPackages" placeholder="请输入总件数" />
</el-form-item>
<el-form-item label="仓库ID" prop="warehouseId">
<el-input v-model="form.warehouseId" placeholder="请输入仓库ID" />
</el-form-item>
</div>
</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-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"/>
</el-form-item>
</el-row> </el-row>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"/>
</el-form-item>
<el-divider content-position="center">入库单明细信息</el-divider> <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> -->
<!-- 入库明细组件 -->
<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,17 +400,26 @@ export default { ...@@ -306,17 +400,26 @@ 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: [],
// 遮罩层 // 遮罩层
loading: true, loading: true,
// 选中数组 // 选中数组
ids: [], ids: [],
...@@ -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,51 +504,110 @@ export default { ...@@ -401,51 +504,110 @@ 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
this.getList() this.getList()
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
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
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset() this.reset()
this.open = true this.open = true
this.title = "添加入库" this.title = "添加入库"
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset() this.reset()
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,47 +620,58 @@ export default { ...@@ -458,47 +620,58 @@ 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(() => {})
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (!valid) return if (!valid) return
// 验证明细表 // 验证明细表
const errors = this.$refs.inboundItemsRef ? this.$refs.inboundItemsRef.validate() : [] const errors = this.$refs.inboundItemsRef ? this.$refs.inboundItemsRef.validate() : []
if (errors.length > 0) { if (errors.length > 0) {
this.$message.error(errors.join(';')) this.$message.error(errors.join(';'))
return return
} }
// 确保明细项数量大于0 // 确保明细项数量大于0
if (!this.form.inboundOrderItemsList || this.form.inboundOrderItemsList.length === 0) { if (!this.form.inboundOrderItemsList || this.form.inboundOrderItemsList.length === 0) {
this.$message.warning('请至少添加一条入库明细') this.$message.warning('请至少添加一条入库明细')
return return
} }
// 自动计算总数 // 自动计算总数
this.calculateTotals() this.calculateTotals()
// 提交数据 // 提交数据
const submitData = { const submitData = {
...this.form, ...this.form,
...@@ -507,29 +680,29 @@ export default { ...@@ -507,29 +680,29 @@ export default {
orderId: this.form.orderId // 确保明细项有主表ID orderId: this.form.orderId // 确保明细项有主表ID
})) }))
} }
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()
}) })
} }
}) })
}, },
/** 取消按钮 */ /** 取消按钮 */
cancel() { cancel() {
this.open = false this.open = false
this.reset() this.reset()
}, },
/** 表单重置 */ /** 表单重置 */
reset() { reset() {
this.form = { this.form = {
...@@ -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,49 +732,51 @@ export default { ...@@ -559,49 +732,51 @@ 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()
}
}, },
/** 处理明细项选择变化 */ /** 处理明细项选择变化 */
handleItemsSelectionChange(selection) { handleItemsSelectionChange(selection) {
this.selectedItems = selection this.selectedItems = selection
}, },
/** 处理明细数据变化 */ /** 处理明细数据变化 */
handleItemsDataChange(items) { handleItemsDataChange(items) {
this.form.inboundOrderItemsList = items this.form.inboundOrderItemsList = items
this.calculateTotals() this.calculateTotals()
}, },
/** 处理总数变化 */ /** 处理总数变化 */
handleTotalsChange(totals) { handleTotalsChange(totals) {
this.form.totalPlannedQuantity = totals.plannedQuantity this.form.totalPlannedQuantity = totals.plannedQuantity
this.form.totalActualQuantity = totals.actualQuantity this.form.totalActualQuantity = totals.actualQuantity
this.form.totalPackages = totals.packages this.form.totalPackages = totals.packages
}, },
/** 添加明细项回调 */ /** 添加明细项回调 */
handleItemAdded(item) { handleItemAdded(item) {
// 为新项设置orderId // 为新项设置orderId
item.orderId = this.form.orderId item.orderId = this.form.orderId
}, },
/** 行保存回调 */ /** 行保存回调 */
handleRowSaved(row) { handleRowSaved(row) {
// 可以在这里添加保存后的逻辑 // 可以在这里添加保存后的逻辑
}, },
/** 行删除回调 */ /** 行删除回调 */
handleRowDeleted(row) { handleRowDeleted(row) {
this.$message.success('删除成功') this.$message.success('删除成功')
}, },
/** 批量删除回调 */ /** 批量删除回调 */
handleBatchDelete(ids) { handleBatchDelete(ids) {
this.$message.success(`成功删除 ${ids.length} 项`) this.$message.success(`成功删除 ${ids.length} 项`)
}, },
/** 单元格变化回调 */ /** 单元格变化回调 */
handleCellChange({ row, prop, value }) { handleCellChange({ row, prop, value }) {
// 可以在这里处理特定字段的变化 // 可以在这里处理特定字段的变化
...@@ -609,7 +784,7 @@ export default { ...@@ -609,7 +784,7 @@ export default {
this.calculateTotals() this.calculateTotals()
} }
}, },
/** 计算总数 */ /** 计算总数 */
calculateTotals() { calculateTotals() {
if (!this.form.inboundOrderItemsList || this.form.inboundOrderItemsList.length === 0) { if (!this.form.inboundOrderItemsList || this.form.inboundOrderItemsList.length === 0) {
...@@ -618,7 +793,7 @@ export default { ...@@ -618,7 +793,7 @@ export default {
this.form.totalPackages = 0 this.form.totalPackages = 0
return return
} }
const totals = this.form.inboundOrderItemsList.reduce( const totals = this.form.inboundOrderItemsList.reduce(
(acc, item) => { (acc, item) => {
acc.plannedQuantity += parseFloat(item.plannedQuantity) || 0 acc.plannedQuantity += parseFloat(item.plannedQuantity) || 0
...@@ -628,14 +803,12 @@ export default { ...@@ -628,14 +803,12 @@ export default {
}, },
{ plannedQuantity: 0, actualQuantity: 0, packages: 0 } { plannedQuantity: 0, actualQuantity: 0, packages: 0 }
) )
this.form.totalPlannedQuantity = totals.plannedQuantity this.form.totalPlannedQuantity = totals.plannedQuantity
this.form.totalActualQuantity = totals.actualQuantity this.form.totalActualQuantity = totals.actualQuantity
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>
\ No newline at end of file
<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
...@@ -109,9 +46,9 @@ ...@@ -109,9 +46,9 @@
<!-- 表格区域 --> <!-- 表格区域 -->
<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"
...@@ -122,23 +59,30 @@ ...@@ -122,23 +59,30 @@
v-on="$listeners" v-on="$listeners"
> >
<!-- 选择列 --> <!-- 选择列 -->
<el-table-column <el-table-column
v-if="showSelection" type="selection"
type="selection" width="55"
width="55"
align="center" align="center"
:reserve-selection="true" :reserve-selection="true"
/> />
<!-- 序号列 --> <!-- 序号列 -->
<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
v-for="column in columns" v-for="column in columns"
:key="column.prop" :key="column.prop"
:label="column.label" :label="column.label"
:prop="column.prop" :prop="column.prop"
:align="column.align || 'center'" :align="column.align || 'center'"
:width="column.width" :width="column.width"
:min-width="column.minWidth" :min-width="column.minWidth"
...@@ -148,9 +92,9 @@ ...@@ -148,9 +92,9 @@
<!-- 可编辑模式 --> <!-- 可编辑模式 -->
<template v-if="scope.row.editable && column.editable !== false"> <template v-if="scope.row.editable && column.editable !== false">
<template v-if="column.type === 'select'"> <template v-if="column.type === 'select'">
<el-select <el-select
v-model="scope.row[column.prop]" v-model="scope.row[column.prop]"
size="small" size="small"
style="width: 100%" style="width: 100%"
@change="handleColumnChange(scope.row, column.prop)" @change="handleColumnChange(scope.row, column.prop)"
> >
...@@ -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%"
...@@ -184,89 +127,67 @@ ...@@ -184,89 +127,67 @@
/> />
</template> </template>
</template> </template>
<!-- 只读模式 --> <!-- 只读模式 -->
<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])"
size="small" size="small"
> >
{{ 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>
</template> </template>
</template> </template>
</el-table-column> </el-table-column>
<!-- 操作列 --> <!-- 操作列 -->
<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" icon="el-icon-edit"
icon="el-icon-edit" @click="handleRowEdit(scope.row)"
@click="handleRowEdit(scope.row)" v-if="!scope.row.editable"
v-if="!scope.row.editable" >编辑</el-button>
>编辑</el-button> <el-button
<el-button size="mini"
size="mini" type="text"
type="text" icon="el-icon-check"
icon="el-icon-check" @click="handleRowSave(scope.row)"
@click="handleRowSave(scope.row)" v-else
v-else >保存</el-button>
>保存</el-button> <el-button
<el-button size="mini"
size="mini" type="text"
type="text" icon="el-icon-delete"
icon="el-icon-delete" @click="handleRowDelete(scope.row, scope.$index)"
@click="handleRowDelete(scope.row, scope.$index)" >删除</el-button>
>删除</el-button>
</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> </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> </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>
</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,411 +234,303 @@ export default { ...@@ -448,411 +234,303 @@ 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 stringifiedDisplayData = JSON.stringify(this.displayData.map(item => {
const stringifiedNewVal = JSON.stringify(newVal || []) const { editable, tempId, ...rest } = item
const stringifiedDisplayData = JSON.stringify(this.displayData.map(item => { return rest
const { editable, tempId, ...rest } = item }))
return rest
if (stringifiedNewVal !== stringifiedDisplayData) {
this.cachedData = JSON.parse(JSON.stringify(newVal || []))
this.displayData = (newVal || []).map(item => ({
...item,
editable: false,
tempId: item.id || Date.now() + Math.random()
})) }))
this.total = this.displayData.length
if (stringifiedNewVal !== stringifiedDisplayData) { this.handlePagination()
this.cachedData = JSON.parse(JSON.stringify(newVal || [])) this.calculateTotals()
this.displayData = (newVal || []).map(item => ({
...item,
editable: false,
tempId: item.id || Date.now() + Math.random()
}))
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 this.calculateTotals()
// 确保新添加的行有orderId this.syncDataToParent()
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()
}
} }
}, },
// 监听orderId变化
orderId: { orderId: {
immediate: true, immediate: true,
handler(newVal) { handler(newVal) {
if (newVal) { this.queryParams.orderId = newVal
if (!this.embedded) { this.loadRelatedData(newVal)
this.queryParams.orderId = newVal this.displayData.forEach(item => {
this.getList() if (!item.orderId) item.orderId = newVal
} else { })
// 在嵌入式模式下,更新所有没有orderId的项 }
this.displayData = this.displayData.map(item => ({ },
...item, pageSize: {
orderId: item.orderId || newVal handler(val) {
})) this.queryParams.pageSize = val
} this.handlePagination()
}
} }
}
},
computed: {
// 计算总数量和金额
totals() {
if (!this.displayData.length) return { plannedQuantity: 0, actualQuantity: 0, totalAmount: 0 }
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() {
handleQuery() { const totalItems = this.displayData.length
this.queryParams.pageNum = 1 const totalPages = Math.ceil(totalItems / this.queryParams.pageSize)
this.getList()
}, // 页码越界处理
if (this.queryParams.pageNum > totalPages && totalPages > 0) {
/** 重置按钮操作 */ this.queryParams.pageNum = totalPages
resetQuery() {
this.resetForm("queryForm")
this.queryParams = {
pageNum: 1,
pageSize: 10,
orderId: this.orderId,
...this.initQuery
}
this.handleQuery()
},
/** 加载关联数据 */
handleLoadRelated() {
if (!this.orderId) {
this.$message.warning('请先保存主表信息')
return
} }
this.queryParams.orderId = this.orderId
this.getList() // 计算分页数据
const start = (this.queryParams.pageNum - 1) * this.queryParams.pageSize
const end = start + this.queryParams.pageSize
this.pagedDisplayData = this.displayData.slice(start, end)
},
// 切换每页条数
handleSizeChange(val) {
this.queryParams.pageSize = val
this.queryParams.pageNum = 1
this.handlePagination()
}, },
// 同步数据到父组件
/** 处理选择变化 */ syncDataToParent() {
handleSelectionChange(selection) { const dataToEmit = this.displayData.map(item => {
this.selectedRows = selection const { editable, tempId, ...rest } = item
this.ids = selection.map(item => item.id) return rest
this.single = selection.length !== 1 })
this.multiple = !selection.length this.$emit('input', dataToEmit)
this.$emit('selection-change', selection) this.$emit('data-change', dataToEmit)
}, },
// 获取行key
/** 获取行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,
editable: true, orderId: this.orderId,
tempId: Date.now() + Math.random() materialId: null,
} batchId: null,
this.displayData.push(newItem) warehouseId: null,
this.$emit('item-added', newItem) locationId: null,
} else { plannedQuantity: 0,
// 独立模式:打开对话框 actualQuantity: 0,
this.dialogMode = 'add' plannedPackages: 0,
this.dialogTitle = "添加入库明细" actualPackages: 0,
this.form = this.getDefaultForm() unitPrice: 0,
this.dialogVisible = true remark: null,
editable: true,
tempId: Date.now() + Math.random()
} }
},
this.displayData.push(newItem)
/** 编辑明细项 */
handleEditItem() { // 自动跳转到最后一页
if (this.single) return const totalPages = Math.ceil(this.displayData.length / this.queryParams.pageSize)
const row = this.selectedRows[0] if (totalPages > this.queryParams.pageNum) {
if (this.embedded) { this.queryParams.pageNum = totalPages
// 嵌入式模式:直接设置为可编辑
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('请先选择要删除的项')
return return
} }
this.$confirm('确定要删除选中的明细项吗?', '提示', { this.$confirm('确定要删除选中的明细项吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
if (this.embedded) { const idsToDelete = this.selectedRows.map(row => row.id || row.tempId)
// 嵌入式模式:从displayData中删除 this.displayData = this.displayData.filter(item =>
const idsToDelete = this.selectedRows.map(row => row.id || row.tempId) !idsToDelete.includes(item.id || item.tempId)
this.displayData = this.displayData.filter(item => )
!idsToDelete.includes(item.id || item.tempId)
) // 删除后页码处理
this.selectedRows = [] const totalPages = Math.ceil(this.displayData.length / this.queryParams.pageSize)
this.$emit('batch-delete', idsToDelete) if (this.queryParams.pageNum > totalPages && totalPages > 0) {
} else { this.queryParams.pageNum = totalPages
// 独立模式:调用API删除
const ids = this.selectedRows.map(row => row.id).join(',')
delInbound_items(ids).then(() => {
this.$modal.msgSuccess("删除成功")
this.getList()
this.selectedRows = []
})
} }
this.selectedRows = []
this.$emit('batch-delete', idsToDelete)
}) })
}, },
/** 导入按钮操作 */
/** 行删除 */ 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
} }
} }
} }
...@@ -952,4 +593,4 @@ export default { ...@@ -952,4 +593,4 @@ export default {
.el-table--medium td { .el-table--medium td {
padding: 6px 0; padding: 6px 0;
} }
</style> </style>
\ No newline at end of file
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
</template> </template>
</TreeComponent> </TreeComponent>
</pane> </pane>
<!-- 物料管理:右侧面板 --> <!-- 物料管理:右侧面板 -->
<pane size="84" style="overflow: auto;"> <pane size="84" style="overflow: auto;">
<!-- 右侧内容保持不变 --> <!-- 右侧内容保持不变 -->
...@@ -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" >
...@@ -164,19 +164,19 @@ ...@@ -164,19 +164,19 @@
<el-table-column label="特殊存储要求" align="center" prop="specialRequirements" /> <el-table-column label="特殊存储要求" align="center" prop="specialRequirements" />
<el-table-column label="是否批次管理" align="center" prop="isBatchManaged"> <el-table-column label="是否批次管理" align="center" prop="isBatchManaged">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.isBatchManaged === 1 ? 'success' : 'info'" size="mini">{{ scope.row.isBatchManaged === 1 ? '是' : '否' }}</el-tag> <el-tag :type="scope.row.isBatchManaged === 1 ? 'success' : 'info'" size="mini">{{ scope.row.isBatchManaged === 1 ? '是' : '否' }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="是否序列号管理" align="center" prop="isSerialManaged"> <el-table-column label="是否序列号管理" align="center" prop="isSerialManaged">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.isSerialManaged === 1 ? 'success' : 'info'" size="mini">{{ scope.row.isSerialManaged === 1 ? '是' : '否' }}</el-tag> <el-tag :type="scope.row.isSerialManaged === 1 ? 'success' : 'info'" size="mini">{{ scope.row.isSerialManaged === 1 ? '是' : '否' }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="最低库存" align="center" prop="minStockLevel" /> <el-table-column label="最低库存" align="center" prop="minStockLevel" />
<el-table-column label="最高库存" align="center" prop="maxStockLevel" /> <el-table-column label="最高库存" align="center" prop="maxStockLevel" />
<el-table-column label="是否激活" align="center" prop="isActive"> <el-table-column label="是否激活" align="center" prop="isActive">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.isActive === 1 ? 'success' : 'info'" size="mini">{{ scope.row.isActive === 1 ? '是' : '否' }}</el-tag> <el-tag :type="scope.row.isActive === 1 ? 'success' : 'info'" size="mini">{{ scope.row.isActive === 1 ? '是' : '否' }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="风险等级" align="center" prop="riskLevel" /> <el-table-column label="风险等级" align="center" prop="riskLevel" />
...@@ -210,7 +210,7 @@ ...@@ -210,7 +210,7 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination <pagination
v-show="total>0" v-show="total>0"
:total="total" :total="total"
...@@ -235,10 +235,10 @@ ...@@ -235,10 +235,10 @@
</el-form-item> </el-form-item>
<el-form-item label="物料分类" prop="categoryCode"> <el-form-item label="物料分类" prop="categoryCode">
<el-select v-model="form.categoryCode" placeholder="请选择物料分类" clearable> <el-select v-model="form.categoryCode" placeholder="请选择物料分类" clearable>
<el-option <el-option
v-for="item in categoryTreeOptions" v-for="item in categoryTreeOptions"
:key="item.categoryCode" :key="item.categoryCode"
:label="item.categoryName" :label="item.categoryName"
:value="item.categoryCode" :value="item.categoryCode"
> >
</el-option> </el-option>
...@@ -345,9 +345,9 @@ import request from '@/utils/request' ...@@ -345,9 +345,9 @@ import request from '@/utils/request'
export default { export default {
name: "Materials", name: "Materials",
components: { components: {
TreeComponent, TreeComponent,
Splitpanes, Splitpanes,
Pane, Pane,
Treeselect, Treeselect,
ImportExcel ImportExcel
...@@ -363,7 +363,7 @@ export default { ...@@ -363,7 +363,7 @@ export default {
}, },
nodeKey: 'sid', nodeKey: 'sid',
loadingTree: false, loadingTree: false,
// 分类映射和选项 // 分类映射和选项
categoryMap: {}, categoryMap: {},
categoryNameToCodeMap: {}, categoryNameToCodeMap: {},
...@@ -372,25 +372,25 @@ export default { ...@@ -372,25 +372,25 @@ export default {
ids: [], ids: [],
single: true, single: true,
multiple: true, multiple: true,
// 显示搜索条件 // 显示搜索条件
showSearch: true, showSearch: true,
// 总条数 // 总条数
total: 0, total: 0,
// 物料表格数据 // 物料表格数据
materialsList: [], materialsList: [],
// 弹出层标题 // 弹出层标题
title: "", title: "",
// 是否显示弹出层 // 是否显示弹出层
open: false, open: false,
// 当前选中的分类列表 // 当前选中的分类列表
selectedCategories: [], selectedCategories: [],
// 查询参数 // 查询参数
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
...@@ -404,7 +404,7 @@ export default { ...@@ -404,7 +404,7 @@ export default {
specification: null, specification: null,
categoryCodes: [] categoryCodes: []
}, },
// 表单参数 // 表单参数
form: { form: {
id: null, id: null,
...@@ -434,7 +434,7 @@ export default { ...@@ -434,7 +434,7 @@ export default {
createUserCode: null, createUserCode: null,
updateUserCode: null updateUserCode: null
}, },
// 表单校验 // 表单校验
rules: { rules: {
materialCode: [{ required: true, message: '请输入物料编码', trigger: 'blur' }], materialCode: [{ required: true, message: '请输入物料编码', trigger: 'blur' }],
...@@ -442,7 +442,7 @@ export default { ...@@ -442,7 +442,7 @@ export default {
sapNo: [{ required: true, message: '请输入SAP物料号', trigger: 'blur' }], sapNo: [{ required: true, message: '请输入SAP物料号', trigger: 'blur' }],
tsCode: [{ required: true, message: '请输入TS Code', trigger: 'blur' }] tsCode: [{ required: true, message: '请输入TS Code', trigger: 'blur' }]
}, },
loading: true loading: true
} }
}, },
...@@ -460,13 +460,13 @@ export default { ...@@ -460,13 +460,13 @@ export default {
pageNum: 1, pageNum: 1,
pageSize: 1000 pageSize: 1000
}); });
if (response.rows && response.rows.length > 0) { if (response.rows && response.rows.length > 0) {
// 正向映射:code → name // 正向映射:code → name
this.categoryMap = {}; this.categoryMap = {};
// 反向映射:name → code(支持模糊匹配时用数组存储) // 反向映射:name → code(支持模糊匹配时用数组存储)
this.categoryNameToCodeMap = {}; this.categoryNameToCodeMap = {};
response.rows.forEach(item => { response.rows.forEach(item => {
if (item.isUsed !== 0 && item.isUsed !== '0') { if (item.isUsed !== 0 && item.isUsed !== '0') {
this.categoryMap[item.categoryCode] = item.categoryName; this.categoryMap[item.categoryCode] = item.categoryName;
...@@ -483,7 +483,7 @@ export default { ...@@ -483,7 +483,7 @@ export default {
} }
} }
}); });
this.categoryTreeOptions = response.rows this.categoryTreeOptions = response.rows
.filter(item => item.isUsed !== 0 && item.isUsed !== '0') .filter(item => item.isUsed !== 0 && item.isUsed !== '0')
.map(item => ({ .map(item => ({
...@@ -504,13 +504,13 @@ export default { ...@@ -504,13 +504,13 @@ export default {
pageNum: 1, pageNum: 1,
pageSize: 1000 // 获取足够多的数据 pageSize: 1000 // 获取足够多的数据
}) })
if (response.rows && response.rows.length > 0) { if (response.rows && response.rows.length > 0) {
// 过滤掉已禁用的分类 // 过滤掉已禁用的分类
const activeCategories = response.rows.filter(item => const activeCategories = response.rows.filter(item =>
item.isUsed !== 0 && item.isUsed !== '0' item.isUsed !== 0 && item.isUsed !== '0'
) )
// 构建树形结构 // 构建树形结构
this.categoryTreeData = this.buildTreeData(activeCategories) this.categoryTreeData = this.buildTreeData(activeCategories)
console.log('分类树数据:', this.categoryTreeData) console.log('分类树数据:', this.categoryTreeData)
...@@ -521,7 +521,7 @@ export default { ...@@ -521,7 +521,7 @@ export default {
this.loadingTree = false this.loadingTree = false
} }
}, },
/** 构建树形结构 */ /** 构建树形结构 */
buildTreeData(list, parentId = null) { buildTreeData(list, parentId = null) {
const result = list const result = list
...@@ -543,15 +543,15 @@ export default { ...@@ -543,15 +543,15 @@ export default {
children: children.length > 0 ? children : undefined children: children.length > 0 ? children : undefined
} }
}) })
return result return result
}, },
/** 处理分类选择变化 */ /** 处理分类选择变化 */
handleCategoryChange(selectedData) { handleCategoryChange(selectedData) {
console.log('选择分类变化:', selectedData) console.log('选择分类变化:', selectedData)
this.selectedCategories = selectedData; this.selectedCategories = selectedData;
// 更新查询参数,按选中的分类筛选物料 // 更新查询参数,按选中的分类筛选物料
if (selectedData.length > 0) { if (selectedData.length > 0) {
// 获取所有选中分类的编码 // 获取所有选中分类的编码
...@@ -564,30 +564,30 @@ export default { ...@@ -564,30 +564,30 @@ export default {
this.queryParams.categoryCodes = []; this.queryParams.categoryCodes = [];
this.queryParams.categoryCode = null; this.queryParams.categoryCode = null;
} }
this.queryParams.pageNum = 1; this.queryParams.pageNum = 1;
this.getList(); this.getList();
}, },
/** 查询物料列表 */ /** 查询物料列表 */
async getList() { async getList() {
this.loading = true this.loading = true
try { try {
let materialsList = []; let materialsList = [];
let total = 0; let total = 0;
// 检查是否有多个分类编码 // 检查是否有多个分类编码
if (this.queryParams.categoryCodes && this.queryParams.categoryCodes.length > 0) { if (this.queryParams.categoryCodes && this.queryParams.categoryCodes.length > 0) {
// 使用getMaterial接口并行获取每个分类的物料 // 使用getMaterial接口并行获取每个分类的物料
const promises = this.queryParams.categoryCodes.map(categoryCode => const promises = this.queryParams.categoryCodes.map(categoryCode =>
request({ request({
url: `/inventory/materials/getMaterial/${categoryCode}`, url: `/inventory/materials/getMaterial/${categoryCode}`,
method: 'get' method: 'get'
}) })
); );
const results = await Promise.all(promises); const results = await Promise.all(promises);
// 合并所有物料并去重 // 合并所有物料并去重
const materialMap = new Map(); const materialMap = new Map();
results.forEach(result => { results.forEach(result => {
...@@ -601,7 +601,7 @@ export default { ...@@ -601,7 +601,7 @@ export default {
}); });
} }
}); });
total = materialsList.length; total = materialsList.length;
} else { } else {
// 单分类或无分类查询,使用原接口 // 单分类或无分类查询,使用原接口
...@@ -609,7 +609,7 @@ export default { ...@@ -609,7 +609,7 @@ export default {
materialsList = response.rows; materialsList = response.rows;
total = response.total; total = response.total;
} }
// 对物料列表中的分类字段做映射处理 // 对物料列表中的分类字段做映射处理
this.materialsList = materialsList this.materialsList = materialsList
.filter(item => item.isUsed !== 0 && item.isUsed !== '0') .filter(item => item.isUsed !== 0 && item.isUsed !== '0')
...@@ -627,13 +627,13 @@ export default { ...@@ -627,13 +627,13 @@ export default {
this.loading = false; this.loading = false;
} }
}, },
// 取消按钮 // 取消按钮
cancel() { cancel() {
this.open = false this.open = false
this.reset() this.reset()
}, },
// 表单重置 // 表单重置
reset() { reset() {
this.form = { this.form = {
...@@ -666,12 +666,12 @@ export default { ...@@ -666,12 +666,12 @@ export default {
} }
this.$refs.form && this.$refs.form.resetFields() this.$refs.form && this.$refs.form.resetFields()
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
// 清空原有分类编码 // 清空原有分类编码
this.queryParams.categoryCode = null; this.queryParams.categoryCode = null;
// 获取用户输入的分类名称 // 获取用户输入的分类名称
const inputName = this.queryParams.categoryNameInput; const inputName = this.queryParams.categoryNameInput;
if (inputName) { if (inputName) {
...@@ -690,11 +690,11 @@ export default { ...@@ -690,11 +690,11 @@ export default {
} }
} }
} }
this.queryParams.pageNum = 1; this.queryParams.pageNum = 1;
this.getList(); this.getList();
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
this.resetForm("queryForm"); this.resetForm("queryForm");
...@@ -711,7 +711,7 @@ export default { ...@@ -711,7 +711,7 @@ export default {
categoryCodes: [] categoryCodes: []
}; };
this.selectedCategories = []; this.selectedCategories = [];
// 修复树形高亮重置:直接操作 TreeComponent 内部的 el-tree // 修复树形高亮重置:直接操作 TreeComponent 内部的 el-tree
if (this.$refs.treeComponent && this.$refs.treeComponent.$refs.tree) { if (this.$refs.treeComponent && this.$refs.treeComponent.$refs.tree) {
this.$refs.treeComponent.$refs.tree.setCurrentKey(null); // 清空选中 this.$refs.treeComponent.$refs.tree.setCurrentKey(null); // 清空选中
...@@ -720,24 +720,24 @@ export default { ...@@ -720,24 +720,24 @@ export default {
// 如果 TreeComponent 有自定义重置方法 // 如果 TreeComponent 有自定义重置方法
this.$refs.treeComponent.resetTree(); this.$refs.treeComponent.resetTree();
} }
this.getList(); this.getList();
}, },
// 多选框选中数据 // 多选框选中数据
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
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset() this.reset()
this.open = true this.open = true
this.title = "添加物料" this.title = "添加物料"
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset() this.reset()
...@@ -748,15 +748,15 @@ export default { ...@@ -748,15 +748,15 @@ export default {
this.title = "修改物料" this.title = "修改物料"
}) })
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
this.$refs.form.validate(valid => { this.$refs.form.validate(valid => {
if (valid) { if (valid) {
const promise = this.form.id const promise = this.form.id
? updateMaterials(this.form) ? updateMaterials(this.form)
: addMaterials(this.form) : addMaterials(this.form)
promise.then(response => { promise.then(response => {
this.$modal.msgSuccess(this.form.id ? "修改成功" : "新增成功") this.$modal.msgSuccess(this.form.id ? "修改成功" : "新增成功")
this.open = false this.open = false
...@@ -767,7 +767,7 @@ export default { ...@@ -767,7 +767,7 @@ export default {
} }
}) })
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const ids = row.id || this.ids const ids = row.id || this.ids
...@@ -778,19 +778,19 @@ export default { ...@@ -778,19 +778,19 @@ export default {
this.$modal.msgSuccess("删除成功") this.$modal.msgSuccess("删除成功")
}).catch(() => {}) }).catch(() => {})
}, },
/** 导入按钮操作 */ /** 导入按钮操作 */
handleImport() { handleImport() {
this.$refs.import.show() this.$refs.import.show()
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {
this.download('inventory/materials/export', { this.download('inventory/materials/export', {
...this.queryParams ...this.queryParams
}, `materials_${new Date().getTime()}.xlsx`) }, `materials_${new Date().getTime()}.xlsx`)
}, },
/** 表单重置方法 */ /** 表单重置方法 */
resetForm(formName) { resetForm(formName) {
if (this.$refs[formName]) { if (this.$refs[formName]) {
...@@ -813,4 +813,4 @@ export default { ...@@ -813,4 +813,4 @@ export default {
.mb8 { .mb8 {
margin-bottom: 8px; margin-bottom: 8px;
} }
</style> </style>
\ No newline at end of file
<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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论