入库任务功能

This commit is contained in:
liuhanqing
2025-05-23 14:33:44 +08:00
parent d128105ea7
commit 7a0f4606dc
7 changed files with 650 additions and 102 deletions

View File

@@ -0,0 +1,442 @@
<template>
<div class="app-container">
<div>
<div class="page-header">
<span>{{ $t('receiveStockinAdd.title') }}</span>
</div>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-row>
<el-col :span="8">
<el-form-item :label="$t('receiveStockinAdd.warehouse')" prop="warehouseId">
<el-select v-model="form.warehouseId" :placeholder="$t('receiveStockinAdd.selectWarehouse')">
<el-option
v-for="item in warehouseOptions"
:key="item.warehouseId"
:label="item.warehouseName"
:value="item.warehouseId"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="$t('receiveStockinAdd.supplier')" prop="supplierId">
<el-select v-model="form.supplierId" :placeholder="$t('receiveStockinAdd.selectSupplier')">
<el-option
v-for="item in supplierOptions"
:key="item.supplierNo"
:label="item.simpleName"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<!-- <el-col :span="8">
<el-form-item label="批次号" prop="batchNo">
<el-input v-model="form.batchNo" placeholder="请输入批次号" />
</el-form-item>
</el-col>-->
<el-col :span="8">
<el-form-item :label="$t('receiveStockinAdd.remark')" prop="remark">
<el-input v-model="form.remark" :placeholder="$t('receiveStockinAdd.inputRemark')"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<div class="mt-3">
<div class="page-header">
<span>{{ $t('receiveStockinAdd.InboundMaterials') }}</span>
<el-row>
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleAddProduct" v-hasPermi="['bas:BasProduct:list']">
{{ $t('receiveStockinAdd.AddMaterials') }}</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="el-icon-download" size="mini" @click="handleImport" v-hasPermi="['receive:stockin:import']">
{{ $t('receiveStockinAdd.ImportMaterials') }}</el-button>
</el-col>
</el-row>
</div>
<el-table :data="productList" border>
<el-table-column type="index" :label="$t('receiveStockinAdd.serialNumber')" width="50" align="center"/>
<el-table-column :label="$t('receiveStockinAdd.guid')" align="center" prop="productGuid"/>
<el-table-column :label="$t('receiveStockinAdd.parentId')" align="center" prop="parentId"/>
<el-table-column :label="$t('receiveStockinAdd.productCode')" align="center" prop="productId"/>
<el-table-column :label="$t('receiveStockinAdd.productName')" align="center" prop="productName"/>
<el-table-column :label="$t('receiveStockinAdd.price')" align="center" prop="price"/>
<el-table-column :label="$t('receiveStockinAdd.brand')" align="center" prop="cargoNo"/>
<el-table-column :label="$t('receiveStockinAdd.unit')" align="center" prop="unit"/>
<el-table-column :label="$t('receiveStockinAdd.spec')" align="center" prop="spec"/>
<el-table-column :label="$t('receiveStockinAdd.description')" align="center" prop="remark"/>
<!-- <el-table-column label="备用字段1" align="center" prop="spare1" v-if="false"/> -->
<!-- <el-table-column label="备用字段2" align="center" prop="spare2" />-->
<!-- <el-table-column label="备用字段3" align="center" prop="spare3" />-->
<!-- <el-table-column label="备用字段4" align="center" prop="spare4" />-->
<!-- <el-table-column label="备用字段5" align="center" prop="spare5" />-->
<!-- <el-table-column label="备用字段6" align="center" prop="spare6" />-->
<el-table-column :label="$t('receiveStockinAdd.batchNumber')" width="120" align="center">
<template slot-scope="scope">
<el-input
v-model="scope.row.lotNo"
controls-position="right"
required="required"
/>
</template>
</el-table-column>
<el-table-column :label="$t('receiveStockinAdd.quantity')" width="120" align="center">
<template slot-scope="scope">
<el-input-number
v-model="scope.row.quantity"
:min="1"
controls-position="right"
required="required"
@change="calculateTotal"
/>
</template>
</el-table-column>
<el-table-column :label="$t('receiveStockinAdd.unitPrice')" width="120" align="center">
<template slot-scope="scope">
<el-input-number
v-model="scope.row.price"
:precision="2"
:min="0"
controls-position="right"
@change="calculateTotal"
/>
</template>
</el-table-column>
<el-table-column :label="$t('receiveStockinAdd.amount')" width="120" align="center">
<template slot-scope="scope">
<span>{{ (scope.row.quantity * scope.row.price).toFixed(2) }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('receiveStockinAdd.operation')" width="100" align="center">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDeleteProduct(scope.$index)"
>{{ $t('receiveStockinAdd.delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="total-info" style="margin-top: 15px; text-align: right">
<span>{{ $t('receiveStockinAdd.totalQuantity') }}:{{ totalQuantity }}</span>
<span style="margin-left: 20px">{{ $t('receiveStockinAdd.totalAmount') }}:{{ totalAmount }}</span>
</div>
</div>
<div class="submit-block" style="margin-top: 20px; text-align: right">
<el-button type="primary" @click="submitForm" v-hasPermi="['receive:stockin:add']">{{ $t('receiveStockinAdd.submit') }}</el-button>
<el-button @click="cancel">{{ $t('receiveStockinAdd.cancel') }}</el-button>
</div>
<!-- 选择物料对话框 -->
<el-dialog :title="$t('receiveStockinAdd.selectProduct')" :visible.sync="productSelectVisible" width="800px" append-to-body>
<el-table :data="productOptions" border @selection-change="handleProductSelectionChange">
<el-table-column type="selection" width="55"/>
<el-table-column :label="$t('receiveStockinAdd.guid')" align="center" prop="productGuid"/>
<el-table-column :label="$t('receiveStockinAdd.parentId')" align="center" prop="parentId"/>
<el-table-column :label="$t('receiveStockinAdd.productCode')" align="center" prop="productId"/>
<el-table-column :label="$t('receiveStockinAdd.productName')" align="center" prop="productName"/>
<el-table-column :label="$t('receiveStockinAdd.price')" align="center" prop="price"/>
<el-table-column :label="$t('receiveStockinAdd.brand')" align="center" prop="cargoNo"/>
<el-table-column :label="$t('receiveStockinAdd.unit')" align="center" prop="unit"/>
<el-table-column :label="$t('receiveStockinAdd.spec')" align="center" prop="spec"/>
<el-table-column :label="$t('receiveStockinAdd.description')" align="center" prop="remark"/>
<!-- <el-table-column label="备用字段1" align="center" prop="spare1" v-if="false"/> -->
<!-- <el-table-column label="备用字段2" align="center" prop="spare2" />-->
<!-- <el-table-column label="备用字段3" align="center" prop="spare3" />-->
<!-- <el-table-column label="备用字段4" align="center" prop="spare4" />-->
<!-- <el-table-column label="备用字段5" align="center" prop="spare5" />-->
<!-- <el-table-column label="备用字段6" align="center" prop="spare6" />-->
</el-table>
<pagination
v-show="productTotal>0"
:total="productTotal"
:page.sync="queryProductParams.pageNum"
:limit.sync="queryProductParams.pageSize"
@pagination="getProductList"
/>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="confirmSelectProduct">{{ $t('receiveStockinAdd.confirm') }}</el-button>
<el-button @click="productSelectVisible = false">{{ $t('receiveStockinAdd.cancel') }}</el-button>
</div>
</el-dialog>
<!-- 物料导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">{{ $t('receiveStockinAdd.dragText') }}<em>{{ $t('receiveStockinAdd.clickUpload') }}</em></div>
<div class="el-upload__tip text-center" slot="tip">
<span>{{ $t('receiveStockinAdd.uploadTip') }}</span>
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">{{ $t('receiveStockinAdd.downloadTemplate') }}</el-link>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm">{{ $t('receiveStockinAdd.confirm') }}</el-button>
<el-button @click="upload.open = false">{{ $t('receiveStockinAdd.cancel') }}</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {addStockin} from "@/api/receive/stockin";
import {listBasProduct} from "@/api/bas/BasProduct";
import {listBasSupplier} from "@/api/bas/BasSupplier";
import { getToken } from "@/utils/auth"
export default {
name: "InAdd",
dicts: ['sys_normal_disable', 'is_active', 'storage_cond'],
data() {
return {
// 表单参数
form: {
warehouseId: undefined,
supplierId: undefined,
remark: undefined,
totalQuantity: 0,
totalAmount: 0,
file: undefined,
},
// 表单校验
rules: {
warehouseId: [
{required: true, message: this.$t('receiveStockinAdd.warehouseRequired'), trigger: "change"}
],
supplierId: [
{required: true, message: this.$t('receiveStockinAdd.supplierRequired'), trigger: "change"}
],
},
// 仓库选项
warehouseOptions: [
{warehouseId: 1, warehouseName: "主仓库"},
{warehouseId: 2, warehouseName: "次仓库"}
],
// 供应商选项
supplierOptions: [],
// 物料列表
productList: [],
// 物料选择对话框
productSelectVisible: false,
// 物料选项,
productOptions: [],
// 已选物料
selectedProducts: [],
// 总数量
totalQuantity: 0,
// 总金额
totalAmount: 0,
//物料总数
productTotal: 0,
//物料查询参数
queryProductParams: {
pageNum: 1,
pageSize: 5
},
//物料遮盖
productLoading: true,
// 用户导入参数
upload: {
// 是否显示弹出层(用户导入)
open: false,
// 弹出层标题(用户导入)
title: "",
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的用户数据
updateSupport: 0,
// 设置上传的请求头部
headers: { Authorization: "Bearer " + getToken() },
// 上传的地址
url: process.env.VUE_APP_BASE_API + "/receive/stockin/analyseExportFile",
}
};
},
created() {
//this.getWarehouseList();
this.getSupplierList();
console.log(this.supplierOptions)
},
methods: {
/** 获取仓库列表 */
getWarehouseList() {
listWarehouse().then(response => {
this.warehouseOptions = response.rows;
});
},
/** 获取物料列表 */
getProductList() {
listBasProduct(this.queryProductParams).then(response => {
this.productOptions = response.rows;
this.productTotal = response.total;
this.productLoading = false;
});
},
/** 获取供应商列表 */
getSupplierList() {
listBasSupplier().then(response => {
this.supplierOptions = response.rows;
});
},
/** 添加物料按钮操作 */
handleAddProduct() {
this.getProductList();
this.productSelectVisible = true;
},
handleExportProduct() {
},
/** 物料选择变更 */
handleProductSelectionChange(selection) {
this.selectedProducts = selection;
},
/** 确认选择物料 */
confirmSelectProduct() {
const newProducts = this.selectedProducts.map(item => ({
productGuid: item.productGuid,
productId: item.productId,
parentId: item.parentId,
price: item.price,
cargoNo: item.cargoNo,
unit: item.unit,
spec: item.spec,
remark: item.remark,
productName: item.productName,
quantity: 1,
}));
this.productList.push(...newProducts);
this.productSelectVisible = false;
this.calculateTotal();
},
/** 删除物料 */
handleDeleteProduct(index) {
this.productList.splice(index, 1);
this.calculateTotal();
},
/** 计算总计 */
calculateTotal() {
this.totalQuantity = this.productList.reduce((sum, item) => sum + (item.quantity || 0), 0);
this.totalAmount = this.productList.reduce((sum, item) => sum + ((item.quantity || 0) * (item.price || 0)), 0);
this.form.totalQuantity = this.totalQuantity;
this.form.totalAmount = this.totalAmount;
},
/** 表单提交 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.productList.length === 0) {
this.$modal.msgError(this.$t('receiveStockinAdd.addMaterialsRequired'));
return;
}
//校验lotNo productGuid quantity 不能为空
if (this.productList.some(item => !item.lotNo || !item.productGuid || !item.quantity)) {
this.$modal.msgError(this.$t('receiveStockinAdd.materialInfoRequired'));
return;
}
// 构建请求数据
const data = {
warehouseId: this.form.warehouseId,
supplierId: this.form.supplierId,
//batchId: this.form.batchNo,
productVoList: this.productList.map(item => ({
productGuid: item.productGuid,
quantity: item.quantity,
lotNo: item.lotNo
}))
};
// 提交收货单
addStockin(data).then(() => {
this.$modal.msgSuccess(this.$t('receiveStockinAdd.addSuccess'));
// 重置表单数据
this.form = {
warehouseId: undefined,
supplierId: undefined,
remark: undefined,
totalQuantity: 0,
totalAmount: 0,
};
// 清空物料列表
this.productList = [];
// 重置计数器
this.totalQuantity = 0;
this.totalAmount = 0;
// 重置表单校验结果
this.$refs["form"].resetFields();
});
}
});
},
cancel() {
this.productSelectVisible = false;
},
/** 导入按钮操作 */
handleImport() {
this.upload.title = this.$t('receiveStockinAdd.uploadTitle')
this.upload.open = true
},
/** 下载模板操作 */
importTemplate() {
this.download('/receive/stockin/importTemplate', {
}, `product_template_${new Date().getTime()}.xlsx`)
},// 文件上传中处理
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true
},
// 文件上传成功处理
handleFileSuccess(response, file, fileList) {
this.upload.open = false
this.upload.isUploading = false
this.$refs.upload.clearFiles()
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", {dangerouslyUseHTMLString: true});
if (response.code === 200) {
this.$modal.msgSuccess("导入成功");
this.productList.push(...response.data)
this.upload.open = false;
} else {
this.$modal.msgError(response.msg);
}
},
// 提交上传文件
submitFileForm() {
this.$refs.upload.submit()
},
}
};
</script>
<style scoped>
.page-header {
padding-bottom: 15px;
border-bottom: 1px solid #dcdfe6;
margin-bottom: 15px;
display: flex;
justify-content: space-between;
align-items: center;
}
.mt-3 {
margin-top: 1rem;
}
.total-info span {
font-size: 16px;
font-weight: bold;
}
</style>