出库部分

This commit is contained in:
张怡蓉
2025-05-23 13:58:55 +08:00
parent 1f61c0c84a
commit d128105ea7
38 changed files with 5033 additions and 22 deletions

View File

@@ -0,0 +1,66 @@
import request from '@/utils/request'
// 查询出库主单列表
export function listOutStockout(query) {
return request({
url: '/out/outStockout/list',
method: 'get',
params: query
})
}
// 查询出库子单详细
export function getOutStockoutDetail(query) {
return request({
url: '/out/outStockoutDetail/getDetailByGuid',
method: 'get',
params: query
})
}
// 获取仓库列表
export function getWarehouseList() {
return request({
url: '/bas/warehouse/list',
method: 'get'
})
}
// 查询可出库的库存物资信息列表
export function listProductAndStock(query) {
return request({
url: '/out/productAndStock/list',
method: 'get',
params: query
})
}
//单据保存
export function saveOutStock(data)
{
return request({
url: '/out/outStockout/saveBill',
method: 'post',
data: data
})
}
//修改单据状态
export function updateOutStockStatus(params)
{
const searchParams = new URLSearchParams();
if (Array.isArray(params.stockoutIds)) {
params.stockoutIds.forEach(id => searchParams.append('stockoutIds', id));
}
if (params.status) {
searchParams.append('status', params.status);
}
if (params.newStatus) {
searchParams.append('newStatus', params.newStatus);
}
return request({
url: '/out/outStockout/changeStatus?' + searchParams.toString(),
method: 'get'
})
}

View File

@@ -0,0 +1,306 @@
<template>
<div class="app-container">
<!-- 主表信息录入 -->
<el-form :model="formData" ref="formRef" size="small" :inline="true" label-width="68px" :rules="rules">
<el-form-item label="仓库" prop="warehouseId" required>
<el-select v-model="formData.warehouseId" placeholder="请选择仓库" clearable>
<el-option
v-for="dict in warehouseOptions"
:key="dict.warehouseId"
:label="dict.warehouseName"
:value="dict.warehouseId"
/>
</el-select>
</el-form-item>
<el-form-item label="客户" prop="customerNo" required>
<el-input
v-model="formData.customerNo"
placeholder="请输入客户编号"
clearable
/>
</el-form-item>
<el-form-item label="单据类型" prop="outType" required>
<el-select v-model="formData.outType" placeholder="请选择单据类型" clearable>
<el-option
v-for="dict in dict.type.out_bill_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="warning" icon="el-icon-refresh" size="mini" @click="reset">重置</el-button>
<el-button type="success" icon="el-icon-check" size="mini" @click="handleSave">保存单据</el-button>
</el-form-item>
</el-form>
<div class="mb8">
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleSelectMaterials">选择物资</el-button>
<el-button type="info" icon="el-icon-refresh-right" size="mini" @click="handleReload">重新建单</el-button>
</div>
<!-- 物资明细表格 -->
<el-table v-loading="loading" :data="materialList">
<el-table-column label="物资编号" align="center" prop="productId" />
<el-table-column label="物资名称" align="center" prop="productName" />
<el-table-column label="批号" align="center" prop="lotNo" />
<el-table-column label="数量" align="center" prop="quantity">
<template slot-scope="scope">
<el-input-number v-model="scope.row.quantity" :min="1" size="mini" @change="handleQuantityChange(scope.row)" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 选择物资弹窗 -->
<el-dialog title="选择物资" :visible.sync="materialDialog" width="800px" append-to-body>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="68px">
<el-form-item label="物资编码" prop="productId">
<el-input
v-model="queryParams.productId"
placeholder="请输入物资编码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="物资名称" prop="productName">
<el-input
v-model="queryParams.productName"
placeholder="请输入物资名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="批号" prop="lotNo">
<el-input
v-model="queryParams.lotNo"
placeholder="请输入批号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-input
v-model="queryParams.warehouseId"
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="materialLoading" :data="materialOptions" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column label="物资编码" align="center" prop="productId" />
<el-table-column label="物资名称" align="center" prop="productName" />
<el-table-column label="批号" align="center" prop="lotNo" />
<el-table-column label="数量" align="center" prop="quantity" />
<el-table-column label="仓库" align="center" prop="warehouseId" />
</el-table>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="confirmSelectMaterials">确 定</el-button>
<el-button @click="cancelSelectMaterials">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { getWarehouseList,listProductAndStock,saveOutStock } from "@/api/out/outStockout";
export default {
name: "AddOutStock",
dicts: ['out_bill_type', 'bill_status'],
data() {
return {
// 遮罩层
loading: false,
materialLoading: false,
// 表单验证规则
rules: {
warehouseId: [
{ required: true, message: "请选择仓库", trigger: "change" }
],
customerNo: [
{ required: true, message: "请输入客户编号", trigger: "blur" }
],
billType: [
{ required: true, message: "请选择单据类型", trigger: "change" }
]
},
// 主表数据
formData: {
warehouseId: null,
customerNo: null,
outType: null
},
// 仓库选项
warehouseOptions: [],
// 物资明细列表
materialList: [],
// 选择物资弹窗
materialDialog: false,
// 物资选项数据
materialOptions: [],
// 已选择的物资
selectedMaterials: [],
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
onlyIdentity: null,
productId: null,
lotNo: null,
productName: null,
quantity: null,
warehouseId: null
}
};
},
created() {
this.getWarehouseOptions();
},
methods: {
/** 获取仓库选项 */
getWarehouseOptions() {
this.warehouseOptions = [
{
warehouseName: "仓库1",
warehouseId: "1"
},
{
warehouseName: "仓库2",
warehouseId: "2"
}
];
// getWarehouseList().then(response => {
// this.warehouseOptions = response.data;
// });
},
/** 打开选择物资弹窗 */
handleSelectMaterials() {
this.materialDialog = true;
this.getMaterialList();
},
/** 获取物资列表 */
getMaterialList() {
this.materialLoading = true;
listProductAndStock(this.queryParams).then(response => {
this.materialOptions = response.rows;
this.materialLoading = false;
});
},
/** 物资选择变更 */
handleSelectionChange(selection) {
this.selectedMaterials = selection;
},
/** 确认选择物资 */
confirmSelectMaterials() {
if (this.selectedMaterials.length === 0) {
this.$modal.msgError("请选择物资");
return;
}
// 过滤掉已经存在的物资
const newMaterials = this.selectedMaterials.filter(item => {
return !this.materialList.some(existing => existing.onlyIdentity === item.onlyIdentity);
});
if (newMaterials.length === 0) {
this.$modal.msgWarning("所选物资已存在,请重新选择");
return;
}
this.materialList = this.materialList.concat(
newMaterials.map(item => ({
productId: item.productId,
productName: item.productName,
quantity: item.quantity,
quantityOrignal: item.quantity,
lotNo: item.lotNo,
onlyIdentity: item.onlyIdentity
}))
);
this.materialDialog = false;
this.selectedMaterials = [];
},
/** 取消选择物资 */
cancelSelectMaterials() {
this.selectedMaterials = [];
this.materialDialog = false;
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getMaterialList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
/** 删除物资 */
handleDelete(index) {
this.materialList.splice(index, 1);
},
/** 数量变更 */
handleQuantityChange(row) {
// 如果没有初始数量,则设置初始数量
// 如果修改后的数量大于初始数量,给出提示并重置为当前值
if (row.quantity > row.quantityOrignal) {
this.$modal.msgError("数量不能大于库存数量");
row.quantity = row.quantityOrignal;
}
},
/** 保存单据 */
handleSave() {
this.$refs.formRef.validate(valid => {
if (valid) {
if (this.materialList.length === 0) {
this.$modal.msgError("请选择物资");
return;
}
const data = {
outStockout: this.formData,
detailList: this.materialList
};
// 这里需要调用保存接口
saveOutStock(data).then(response => {
console.log(response)
this.$modal.msgSuccess("单据"+response.msg+"保存成功");
this.$tab.refreshPage(this.$route);
// this.reset();
});
}
});
},
/** 重置数据 */
reset() {
this.formData = {
warehouseId: null,
customerNo: null,
outType: null
};
this.materialList = [];
},
/** 重新建单 */
handleReload() {
this.$tab.refreshPage(this.$route);
}
}
};
</script>

View File

@@ -0,0 +1,293 @@
<template>
<div class="app-container">
<!-- 查询表单 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="出库单编号" prop="stockoutId">
<el-input
v-model="queryParams.stockoutId"
placeholder="请输入出库单编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="出库类型" prop="outType">
<el-select v-model="queryParams.outType" placeholder="请选择出库类型" clearable>
<el-option
v-for="dict in dict.type.out_bill_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="单据状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择单据状态" clearable>
<el-option
v-for="dict in dict.type.out_bill_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="客户编码" prop="customerNo">
<el-input
v-model="queryParams.customerNo"
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-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-check"
size="mini"
@click="handleAudit(2)"
>单据审核</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-circle-check"
size="mini"
@click="handleAudit(4)"
>单据确认</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
@click="handleAudit(5)"
>单据作废</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-s-promotion"
size="mini"
@click="handleAutoAllot"
>自动分配</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="el-icon-s-tools"
size="mini"
@click="handleManualAllot"
>手动分配</el-button>
</el-col>
</el-row>
<!-- 主表数据 -->
<el-table v-loading="loading" :data="outStockoutList" @selection-change="handleSelectionChange" @row-click="handleRowClick">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="出库单编号" align="center" prop="stockoutId" />
<el-table-column label="出库类型" align="center" prop="outType">
<template slot-scope="scope">
<dict-tag :options="dict.type.out_bill_type" :value="scope.row.outType"/>
</template>
</el-table-column>
<el-table-column label="单据状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.out_bill_status" :value="scope.row.status"/>
</template>
</el-table-column>
<el-table-column label="客户编码" align="center" prop="customerNo" />
<el-table-column label="建单人" align="center" prop="createManId" />
<el-table-column label="创建时间" align="center" prop="createDate" />
<el-table-column label="开始时间" align="center" prop="startDate" />
<el-table-column label="确认时间" align="center" prop="finishDate" />
<el-table-column label="仓库编号" align="center" prop="warehouseId" />
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 子表数据 -->
<el-table v-loading="detailLoading" :data="outStockDetailList.slice((detailQueryParams.pageNum-1)*detailQueryParams.pageSize, detailQueryParams.pageNum*detailQueryParams.pageSize)" style="margin-top: 20px;">
<el-table-column label="出库子单编号" align="center" prop="stockoutDetailId" />
<el-table-column label="物资编码" align="center" prop="productId" />
<el-table-column label="批次" align="center" prop="lotNo" />
<el-table-column label="计划数量" align="center" prop="quantity" />
<el-table-column label="实际数量" align="center" prop="assignNum" />
<el-table-column label="分配数量" align="center" prop="allotQuantity" />
<el-table-column label="单位" align="center" prop="unit" />
<el-table-column label="规格" align="center" prop="spec" />
<el-table-column label="价格" align="center" prop="price" />
<el-table-column label="备注" align="center" prop="remark" />
</el-table>
<pagination
v-show="detailTotal>0"
:total="detailTotal"
:page.sync="detailQueryParams.pageNum"
:limit.sync="detailQueryParams.pageSize"
@pagination="getDetailList"
/>
</div>
</template>
<script>
import { listOutStockout } from "@/api/out/outStockout"
import { getOutStockoutDetail,updateOutStockStatus } from "@/api/out/outStockout"
export default {
name: "OutStockWithDetail",
dicts: ['out_bill_type', 'out_bill_status'],
data() {
return {
// 遮罩层
loading: true,
detailLoading: false,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 主表数据
outStockoutList: [],
// 子表数据
outStockDetailList: [],
// 选中数据
selectedRows: [],
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
stockoutId: null,
outType: null,
customerNo: null,
status: '1'
},
// 子表分页参数
detailQueryParams: {
pageNum: 1,
pageSize: 10,
status:null,
stockoutGuid:null
},
// 子表总条数
detailTotal: 0
}
},
created() {
this.getList()
},
methods: {
/** 查询主表数据 */
getList() {
this.loading = true
listOutStockout(this.queryParams).then(response => {
this.outStockoutList = response.rows
this.total = response.total
this.loading = false
})
},
/** 查询子表数据 */
getDetailList(stockoutGuid,status) {
this.detailLoading = true
this.detailQueryParams.stockoutGuid = stockoutGuid
this.detailQueryParams.status = status
getOutStockoutDetail(this.detailQueryParams).then(response => {
this.outStockDetailList = response.rows
this.detailTotal = response.total
this.detailLoading = false
})
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm")
this.handleQuery()
},
/** 点击行加载明细数据 */
handleRowClick(row) {
this.getDetailList(row.stockoutGuid,row.status)
},
/** 多选框选中数据 */
handleSelectionChange(selection) {
this.selectedRows = selection
},
/** 单据状态修改按钮操作 */
handleAudit(status) {
if (this.selectedRows.length === 0) {
this.$modal.msgError("请选择至少一条数据")
return
}
for(var i=0;i<this.selectedRows.length;i++){
if (this.selectedRows[i].status != "1" && status == "2") {
this.$modal.msgError(this.selectedRows[i].stockoutId+"单据已审核,请勿重复审核")
return
}
if (this.selectedRows[i].status < 3 && status == "4") {
this.$modal.msgError(this.selectedRows[i].stockoutId+"单据未开始,无法确认")
return
}
if (this.selectedRows[i].status != "1" && status == "5"){
this.$modal.msgError(this.selectedRows[i].stockoutId+"单据已审核,无法作废")
return;
}
}
const params = {
stockoutIds: this.selectedRows.map(row => row.stockoutId),
status: this.selectedRows[0].status,
newStatus: status
}
console.log("单据状态修改:", params)
//调用单据状态改变接口
updateOutStockStatus(params).then(response => {
this.$modal.msgSuccess(response)
this.getList()
})
},
/** 自动分配按钮操作 */
handleAutoAllot() {
if (this.selectedRows.length === 0) {
this.$modal.msgError("请选择至少一条数据")
return
}
const stockoutIds = this.selectedRows.map(row => row.stockoutId)
// TODO: 调用自动分配接口
console.log("自动分配:", stockoutIds)
},
/** 手动分配按钮操作 */
handleManualAllot() {
if (this.selectedRows.length === 0) {
this.$modal.msgError("请选择至少一条数据")
return
}
const stockoutIds = this.selectedRows.map(row => row.stockoutId)
// TODO: 调用手动分配接口
console.log("手动分配:", stockoutIds)
}
}
}
</script>

View File

@@ -0,0 +1,142 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="序号" prop="onlyIdentity">
<el-input
v-model="queryParams.onlyIdentity"
placeholder="请输入序号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="物资编码" prop="productId">
<el-input
v-model="queryParams.productId"
placeholder="请输入物资编码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="批号" prop="lotNo">
<el-input
v-model="queryParams.lotNo"
placeholder="请输入批号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="物资名称" prop="productName">
<el-input
v-model="queryParams.productName"
placeholder="请输入物资名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-input
v-model="queryParams.warehouseId"
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-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['out:productAndStock:export']"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="productAndStockList">
<el-table-column label="序号" align="center" prop="onlyIdentity" />
<el-table-column label="物资编码" align="center" prop="productId" />
<el-table-column label="批号" align="center" prop="lotNo" />
<el-table-column label="物资名称" align="center" prop="productName" />
<el-table-column label="数量" align="center" prop="quantity" />
<el-table-column label="仓库" align="center" prop="warehouseId" />
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
</template>
<script>
import { listProductAndStock } from "@/api/out/outStockout"
export default {
name: "ProductAndStock",
data() {
return {
// 遮罩层
loading: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 可出库的库存物资信息表格数据
productAndStockList: [],
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
onlyIdentity: null,
productId: null,
lotNo: null,
productName: null,
quantity: null,
warehouseId: null
}
}
},
created() {
this.getList()
},
methods: {
/** 查询可出库的库存物资信息列表 */
getList() {
this.loading = true
listProductAndStock(this.queryParams).then(response => {
this.productAndStockList = response.rows
this.total = response.total
this.loading = false
})
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm")
this.handleQuery()
},
/** 导出按钮操作 */
handleExport() {
this.download('out/productAndStock/export', {
...this.queryParams
}, `productAndStock_${new Date().getTime()}.xlsx`)
}
}
}
</script>