Commit d5f05998 by yubin

Merge remote-tracking branch 'origin/master'

parents e5c97a2f fde2e5ee
<template>
<div class="app-container">
<!-- 标题栏 + 操作按钮(对齐字典页面) -->
<!-- 标题栏 + 操作按钮 -->
<PageTitle>
<template #buttons>
<el-button
......@@ -14,7 +14,7 @@
</template>
</PageTitle>
<!-- 搜索区域(对齐字典页面的page-wrapper-search组件) -->
<!-- 搜索区域 -->
<div class="page-container">
<page-wrapper-search
:model="queryParams"
......@@ -103,7 +103,7 @@
</el-form-item>
</page-wrapper-search>
<!-- 表格区域(对齐字典页面的样式) -->
<!-- 表格区域 -->
<div class="table-container">
<el-table
v-loading="loading"
......@@ -138,27 +138,10 @@
<span>{{ parseTime(scope.row.inboundDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<!-- <el-table-column
label="操作"
align="center"
class-name="small-padding fixed-width"
fixed="right"
width="250"
>
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-more"
@click="handleDetail(scope.row)"
v-hasPermi="['inventory:inbound:view']"
>详情</el-button>
</template>
</el-table-column> -->
</el-table>
</div>
<!-- 分页组件(位置对齐) -->
<!-- 分页组件 -->
<pagination
v-show="total>0"
:total="total"
......@@ -166,11 +149,13 @@
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 仓库选择组件 -->
<WarehouseSelector
v-model="warehouseSelectorVisible"
@selected="handleWarehouseSelected"
/>
<!-- 库位选择组件 -->
<LocationSelector
v-model="locationSelectorVisible"
......@@ -178,85 +163,20 @@
@selected="handleLocationSelected"
/>
</div>
<!-- 入库单详情弹窗 -->
<!-- <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.batchId || '-' }}</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="备注" :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"
:inboundOrderId="detailForm.inboundOrderId"
:isEditable="isEditable"
: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> -->
</div>
</template>
<script>
import { inbound_details } from "@/api/inventory/inbound_items"
import { batchAddInventory } from "@/api/inventory/inventory"
import InboundItems from "@/views/inventory/inbound_items/index.vue"
import PageTitle from "@/components/PageTitle" // 引入字典页面的标题组件
import PageWrapperSearch from "@/components/Search/PageWrapperSearch" // 引入搜索包装组件
import { listWarehouses } from "@/api/inventory/warehouses"
import PageTitle from "@/components/PageTitle"
import PageWrapperSearch from "@/components/Search/PageWrapperSearch"
import WarehouseSelector from "@/views/compononents/WarehouseSelector.vue"
import LocationSelector from "@/views/compononents/LocationSelector.vue"
export default {
name: "InboundDetails",
dicts: ['label_color'],
filters: {
dictFilter(value, dictType) {
if (!value || !this.dict[dictType]) return '-';
return this.dict.type[dictType][value] || '-';
}
},
components: {
InboundItems,
PageTitle,
PageWrapperSearch,
WarehouseSelector,
......@@ -264,32 +184,12 @@ export default {
},
data() {
return {
labelColorOptions: [],
// 仓库列表
warehouseOptions: [],
// 库位列表
locationOptions: [],
loadingWarehouse: false,
// 仓库选择相关
warehouseSelectorVisible: false,
queryWarehouseName: null,
// 库位选择相关
locationSelectorVisible: false,
queryLocationName: null,
// 可编辑状态
isEditable: true,
// 物料组件显示
materialSelectOpen: false,
selectedMaterialIds: [],
inboundItemsUpdateStatus: false,
// 组件带来的选中的物料详情(code、name)
selectedMaterials: [],
detailOpen: false,
detailForm: {}, // 新增详情表单数据
// 组件监听修改时的orderId变化
inboundOrderId: null,
// 选中的明细项
selectedItems: [],
// 遮罩层
loading: true,
// 选中数组
......@@ -298,89 +198,44 @@ export default {
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 入库表格数据
inboundList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
materialId: null,
sapNo: null,
materialName: null,
orderId: null,
orderTypeId: null,
systemNo: null,
batchId: null,
warehouseId: null,
ownerId: null,
orderStatus: null,
orderType: null
},
// 表单参数
form: {
id: null,
orderId: null,
orderTypeId: null,
batchId: null,
warehouseId: null,
ownerId: null,
orderStatus: 1,
referenceNo: null,
plannedArrivalDate: undefined,
actualArrivalDate: undefined,
totalPlannedQuantity: null,
totalActualQuantity: null,
totalPackages: null,
remark: null,
opUserName: null,
isUsed: null,
sortNo: null,
createTime: null,
createUserCode: null,
updateTime: null,
updateUserCode: null,
// 明细列表
inboundOrderItemsList: []
locationId: null,
labelColor: null
}
}
},
mounted(){
// console.log("标签颜色字典数据:", this.dict.type.label_color);
},
created() {
this.getList()
// 初始化标签颜色下拉选项
},
methods: {
// 封装字典取值方法
getDictLabel(dictType, value) {
// 1. 空值/字典不存在时返回默认值
if (!value || !this.dict?.type?.[dictType]) return '-';
// 2. 从字典数组中匹配 value 对应的 label
const dictItem = this.dict.type[dictType].find(item => item.value === value);
return dictItem?.label || '-';
},
getDictListClass(dictType, value){
// 1. 空值/字典不存在时返回默认值
getDictListClass(dictType, value) {
if (!value || !this.dict?.type?.[dictType]) return '-';
// 2. 从字典数组中匹配 value 对应的 label
const dictItem = this.dict.type[dictType].find(item => item.value === value);
return dictItem?.raw?.listClass || '';
},
/** 查询入库列表 */
getList() {
this.loading = true
inbound_details(this.queryParams).then(response => {
console.log(this.queryParams)
console.log(response.rows)
this.inboundList = response.rows
this.total = response.total
this.loading = false
......@@ -388,6 +243,7 @@ export default {
this.loading = false
})
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
......@@ -396,20 +252,19 @@ export default {
/** 重置按钮操作 */
resetQuery() {
this.dateRange = []
this.queryParams = {
pageNum: 1,
pageSize: 10,
sapNo: null,
materialName: null,
orderId: null,
orderTypeId: null,
systemNo: null,
batchId: null,
warehouseId: null,
ownerId: null,
orderStatus: null,
orderType: null
locationId: null,
labelColor: null
}
// this.$refs.queryForm.resetFields()
this.queryWarehouseName = null
this.queryLocationName = null
this.handleQuery()
},
......@@ -420,43 +275,11 @@ export default {
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.open = true
this.title = "添加入库"
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const id = row.id
getInbound(id).then(response => {
this.form = response.data
// 加载明细数据
this.inboundOrderId = id
this.$nextTick(() => {
})
this.open = true
this.title = "修改入库单"
})
},
/** 查看详情 */
handleDetail(row) {
this.reset()
const id = row.id
this.isEditable = false
getInbound(id).then(response => {
// 加载明细数据到详情
this.detailForm = response.data
this.detailForm.inboundOrderId = id
this.detailOpen = true
})
},
/** 打开仓库选择器 */
openWarehouseSelector() {
this.warehouseSelectorVisible = true
},
/** 仓库选择回调 */
handleWarehouseSelected(warehouse) {
if (!warehouse) return
......@@ -467,16 +290,17 @@ export default {
this.queryParams.locationId = null
this.handleQuery()
},
/** 清空仓库选择 */
clearQueryWarehouse() {
this.queryWarehouseName = null
this.queryParams.warehouseId = null
this.queryParams.warehousesCode = null
// 清空仓库时,同时清空库位
this.queryLocationName = null
this.queryParams.locationId = null
this.handleQuery()
},
/** 打开库位选择器 */
openLocationSelector() {
if (!this.queryParams.warehouseId) {
......@@ -485,6 +309,7 @@ export default {
}
this.locationSelectorVisible = true
},
/** 库位选择回调 */
handleLocationSelected(location) {
if (!location) return
......@@ -492,270 +317,13 @@ export default {
this.queryLocationName = location.locationName || location.locationCode
this.handleQuery()
},
/** 清空库位选择 */
clearQueryLocation() {
this.queryLocationName = null
this.queryParams.locationId = null
this.handleQuery()
},
// 打开物料选择弹窗
showMaterials(status) {
this.materialSelectOpen = status;
if (status) { // 只有打开弹窗时才清空选择
this.selectedMaterialIds = []; // 先清空父组件数据
this.selectedMaterials = [];
this.$nextTick(() => {
// 确保弹窗渲染完成后再调用子组件方法
this.$refs.materialSelector?.clearSelection();
});
}
},
// 物料选择变化回调
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.sapNo === material.sapNo
);
if (!exists) {
this.form.inboundOrderItemsList.push({
materialId: material.sapNo, // 存储物料编码
materialName: material.materialName, // 仅用于展示
// 其他需要的字段...
});
}
});
this.materialSelectOpen = false;
this.$refs.inboundItemsRef.handleAddItem(this.selectedMaterials)
this.$message.success(`成功添加 ${this.selectedMaterials.length} 个物料`);
},
/** 确认入库操作 */
async handleConfirm(row) { // 标记为 async 函数
try {
// 第一步:确认弹窗
await this.$confirm('确认要入库吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
});
// 第二步:等待 listInbound_items 执行完成
const queryForm = {
pageNum: 1,
pageSize: 9999,
orderId: row.orderId
};
const response = await listInbound_items(queryForm);
row.inboundOrderItemsList = response.rows;
// 第三步:确保数据存在后调用入库接口
if (!row.inboundOrderItemsList || row.inboundOrderItemsList.length === 0) {
this.$message.warning('暂无入库明细数据,无法确认入库');
return;
}
await batchAddInventory(row.inboundOrderItemsList);
// 第四步:操作成功提示
this.$modal.msgSuccess("确认成功");
this.$message.success('确认入库成功');
row.orderStatus = 2
updateInbound(row).then(() => {
this.getList();
})
} catch (error) {
// 捕获取消确认/接口失败的异常
if (error !== 'cancel') {
this.$message.error('确认入库失败:' + (error.msg || '网络异常'));
}
}
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids.length
this.$confirm((row.orderId ? '是否确认删除入库单编号为"' + row.orderId + '"的数据项?' : '是否确认删除选中的' + ids + '条入库单'), '提示', {
type: 'warning'
}).then(() => {
return delInbound(ids)
}).then(() => {
this.getList()
this.$message.success("删除成功")
}).catch(() => {})
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (!valid) return
// 验证明细表
const errors = this.$refs.inboundItemsRef ? this.$refs.inboundItemsRef.validate() : []
if (errors.length > 0) {
this.$message.error(errors.join(';'))
return
}
// 确保明细项数量大于0
if (!this.form.inboundOrderItemsList || this.form.inboundOrderItemsList.length === 0) {
this.$message.warning('请至少添加一条入库明细')
return
}
// 自动计算总数
this.calculateTotals()
// 提交数据
const submitData = {
...this.form,
inboundOrderItemsList: this.form.inboundOrderItemsList.map(item => ({
...item,
orderId: this.form.orderId, // 确保明细项有主表ID
batchId: this.form.batchId
}))
}
if (this.form.id != null) {
updateInbound(submitData).then(response => {
this.$message.success("修改成功")
this.open = false
this.getList()
})
} else {
addInbound(submitData).then(response => {
this.$message.success("新增成功")
this.open = false
this.getList()
})
}
})
},
/** 取消按钮 */
cancel() {
this.open = false
this.reset()
},
/** 表单重置 */
reset() {
this.form = {
id: null,
orderId: null,
orderTypeId: null,
batchId: null,
warehouseId: null,
ownerId: null,
orderStatus: 1,
referenceNo: null,
plannedArrivalDate: null,
actualArrivalDate: null,
totalPlannedQuantity: 0,
totalActualQuantity: 0,
totalPackages: 0,
remark: null,
opUserName: null,
isUsed: null,
sortNo: null,
createTime: null,
createUserCode: null,
updateTime: null,
updateUserCode: null,
inboundOrderItemsList: []
}
if (this.$refs.inboundItemsRef) {
this.$refs.inboundItemsRef.resetEmbeddedData()
}
if (this.$refs.form) {
this.$refs.form.resetFields()
}
},
/** 导入按钮操作 */
handleImport() {
this.$refs.import.show()
},
/** 处理明细项选择变化 */
handleItemsSelectionChange(selection) {
this.selectedItems = selection
},
/** 处理明细数据变化 */
handleItemsDataChange(items) {
this.form.inboundOrderItemsList = items
this.calculateTotals()
},
/** 处理总数变化 */
handleTotalsChange(totals) {
this.form.totalPlannedQuantity = totals.plannedQuantity
this.form.totalActualQuantity = totals.actualQuantity
this.form.totalPackages = totals.packages
},
/** 添加明细项回调 */
handleItemAdded(item) {
// 为新项设置orderId
item.orderId = this.form.orderId
},
/** 行保存回调 */
handleRowSaved(row) {
// 可以在这里添加保存后的逻辑
},
/** 行删除回调 */
handleRowDeleted(row) {
this.$message.success('删除成功')
},
/** 批量删除回调 */
handleBatchDelete(ids) {
this.$message.success(`成功删除 ${ids.length} 项`)
},
/** 单元格变化回调 */
handleCellChange({ row, prop, value }) {
// 可以在这里处理特定字段的变化
if (prop === 'plannedQuantity' || prop === 'actualQuantity') {
this.calculateTotals()
}
},
/** 计算总数 */
calculateTotals() {
if (!this.form.inboundOrderItemsList || this.form.inboundOrderItemsList.length === 0) {
this.form.totalPlannedQuantity = 0
this.form.totalActualQuantity = 0
this.form.totalPackages = 0
return
}
const totals = this.form.inboundOrderItemsList.reduce(
(acc, item) => {
acc.plannedQuantity += parseFloat(item.plannedQuantity) || 0
acc.actualQuantity += parseFloat(item.actualQuantity) || 0
acc.packages += parseFloat(item.plannedPackages) || 0
return acc
},
{ plannedQuantity: 0, actualQuantity: 0, packages: 0 }
)
this.form.totalPlannedQuantity = totals.plannedQuantity
this.form.totalActualQuantity = totals.actualQuantity
this.form.totalPackages = totals.packages
},
/** 导出按钮操作 */
handleExport() {
......@@ -768,7 +336,7 @@ export default {
</script>
<style scoped>
/* 对齐字典页面的样式类名和布局 */
/* 核心样式保留,冗余样式删除 */
.page-container {
padding: 16px;
background: #fff;
......@@ -779,29 +347,4 @@ export default {
.table-container {
margin-top: 16px;
}
.scrollable-dialog .el-dialog__body {
max-height: 80vh; /* 最大高度80%视口高度 */
overflow-y: auto; /* 超出滚动 */
padding: 20px;
}
.detail-container {
padding: 10px;
}
.remark-text {
line-height: 1.5;
min-height: 40px;
white-space: pre-wrap;
}
.mb20 {
margin-bottom: 20px;
}
/* 统一对话框底部按钮样式 */
.dialog-footer {
text-align: center;
}
</style>
\ No newline at end of file
......@@ -607,7 +607,7 @@ export default {
}
},
mounted() {
console.log("dict:",this.dict)
},
created() {
this.getList()
......@@ -706,7 +706,7 @@ export default {
let id = row.id;
if(id === undefined){
id = this.ids
id = this.ids[0]
}
getInbound(id).then(response => {
if(response.data.orderStatus === 2){
......@@ -906,7 +906,6 @@ export default {
orderId: row.orderId
}
const response = await listInbound_itemsAndMname(queryForm)
console.log(response.rows)
row.inboundOrderItemsList = response.rows.map(item => {
return {
...item,
......@@ -915,10 +914,10 @@ export default {
inventoryStatus: 1,
ownerId: row.ownerId,
quantity: item.actualQuantity,
unitWeight: item.unitWeight
unitWeight: item.unitWeight,
isUsed: 1
};
})
console.log(row.inboundOrderItemsList)
// 第三步:确保数据存在后调用入库接口
if (!row.inboundOrderItemsList || row.inboundOrderItemsList.length === 0) {
this.$message.warning('暂无入库明细数据,无法确认入库')
......
......@@ -562,7 +562,6 @@ export default {
// 构建树形结构
this.categoryTreeData = this.buildTreeData(activeCategories)
console.log('分类树数据:', this.categoryTreeData)
}
} catch (error) {
console.error('获取分类树数据失败:', error)
......@@ -598,7 +597,7 @@ export default {
/** 处理树节点点击 */
handleTreeClick(data) {
console.log('点击树节点:', data)
this.currentNodeId = data.sid
// 更新查询参数,按选中的分类筛选物料
......
......@@ -276,7 +276,7 @@ export default {
dialogFormData: {
immediate: true,
handler(val) {
console.log(val)
this.form = { ...val }
}
},
......
......@@ -5,8 +5,9 @@ import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import com.ruoyi.inventory.domain.*;
import com.ruoyi.inventory.domain.vo.InboundMaterialTotalVO;
import com.ruoyi.inventory.mapper.MaterialsMapper;
import com.ruoyi.inventory.mapper.*;
import org.apache.commons.lang3.SystemUtils;
import org.springframework.util.CollectionUtils;
import com.ruoyi.common.exception.ServiceException;
......@@ -21,9 +22,6 @@ import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.inventory.domain.InboundOrderItems;
import com.ruoyi.inventory.mapper.InboundOrdersMapper;
import com.ruoyi.inventory.domain.InboundOrders;
import com.ruoyi.inventory.service.IInboundOrdersService;
/**
......@@ -39,6 +37,13 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
private InboundOrdersMapper inboundOrdersMapper;
@Autowired
private MaterialsMapper materialsMapper;
@Autowired
private OwnersMapper ownersMapper;
@Autowired
private WarehousesMapper warehousesMapper;
@Autowired
private StorageLocationsMapper storageLocationsMapper;
private static final Logger log = LoggerFactory.getLogger(InboundOrdersServiceImpl.class);
/**
......@@ -182,7 +187,9 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
Date now = DateUtils.getNowDate();
Long userId = SecurityUtils.getUserId();
String operId = userId.toString();
Warehouses warehouses = new Warehouses();
Owners owners = new Owners();
StorageLocations storageLocations = new StorageLocations();
// 3. 按入库单号分组(核心:同一入库单的多条明细归为一组)
Map<String, List<InboundTemplateVO>> orderGroupMap = inboundOrdersList.stream()
.filter(vo -> StringUtils.isNotBlank(vo.getOrderId())) // 过滤无入库单号的无效行
......@@ -234,10 +241,14 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
// mainDO.setUpdateBy(operId);
// mainDO.setUpdateTime(now);
// mainDO.setUpdateUserCode(operId);
owners.setOwnerName(mainDO.getOwnerName());
List<Owners> olist = ownersMapper.selectOwnersList(owners);
mainDO.setId(UUID.randomUUID().toString());
mainDO.setOrderId(orderId);
mainDO.setOrderTypeId(orderType+"");
mainDO.setOwnerId(olist.get(0).getId());
// 设置默认值
if (mainDO.getSortNo() == null) {
mainDO.setSortNo(0L);
......@@ -261,6 +272,8 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
itemDO.setCreateBy(operId);
itemDO.setCreateTime(now);
itemDO.setCreateUserCode(operId);
List<Warehouses> wlist = warehousesMapper.selectWarehousesList(warehouses);
List<StorageLocations> slist = storageLocationsMapper.selectStorageLocationsList(storageLocations);
itemDO.setId(UUID.randomUUID().toString());
Map<String,String> sapAndId = sapAndIdMap.get(vo.getSapNo());
......@@ -268,7 +281,8 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
itemDO.setOrderId(orderId); // 关联入库单号
itemDO.setBatchId(mainDO.getBatchId());
itemDO.setInboundOrderId(mainDO.getId()); // 关联主表ID(核心!)
itemDO.setWarehouseId(wlist.get(0).getId());
itemDO.setLocationId(slist.get(0).getId());
itemDO.setSortNo(0L);
// 校验物料字段(示例:必填sapNo)
if (StringUtils.isBlank(vo.getSapNo())) {
......@@ -315,6 +329,7 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
return finalSuccessMsg;
}
}
/**
* 统计本月入库数量
*
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论