Files
FT517-WMS/ruoyi-ui/src/views/in/receive/add/index.vue
2025-09-11 11:19:00 +08:00

652 lines
23 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="app-container">
<div>
<div class="page-header">
<span>收货入库</span>
</div>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-row>
<el-col :span="6">
<el-form-item label="仓库" prop="warehouseId">
<el-select v-model="form.warehouseId" placeholder="请选择仓库">
<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="6">
<el-form-item label="供应商" prop="supplierId">
<el-input
v-model="form.supplierName"
placeholder="请选择供应商"
@click.native="openSupplierSelector"
readonly
/>
</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="6">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<div class="mt-3">
<div class="page-header">
<span>入库物料</span>
<el-row>
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-download" size="mini" @click="handleAddProduct" v-hasPermi="['receive:stockin:add']">
添加物料</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']">
导入物料</el-button>
</el-col>
</el-row>
</div>
<el-table :data="productList" border style="width: 100%">
<el-table-column type="index" label="序号" width="50" align="center"/>
<!-- <el-table-column label="主键" align="center" prop="productGuid" />-->
<el-table-column fixed label="物料编码" align="left" prop="productId" /><!--物料编码-->
<el-table-column fixed label="物料名称" align="left" prop="productName" /><!--物料名称-->
<el-table-column fixed label="英文描述" align="left" prop="spare1"/><!--英文描述-->
<el-table-column label="单位" align="left" prop="unit" /><!--单位-->
<el-table-column label="单件净重KG" align="right" prop="spare2" width="120px"/><!--单件净重KG-->
<el-table-column label="总净重KG" width="120" align="right">
<template slot-scope="scope">
<span>{{ (scope.row.quantity * scope.row.spare2).toFixed(2) }}</span>
</template>
</el-table-column>
<el-table-column label="箱号" align="left" prop="spare3" /><!--箱号-->
<el-table-column label="包装方式" align="left" prop="spare4" /><!--包装方式-->
<el-table-column label="长MM" align="right" prop="spare5" /><!--长MM-->
<el-table-column label="宽MM" align="right" prop="spare6" /><!--宽MM-->
<el-table-column label="高MM" align="right" prop="spare7" /><!--高MM-->
<el-table-column label="体积m³" align="right" prop="spare8" /><!--体积m³-->
<!-- <el-table-column label="净重KG" align="center" prop="netWeight" />净重KG -->
<el-table-column label="净重KG" width="120" align="right">
<template slot-scope="scope">
<span>{{ (scope.row.quantity * scope.row.spare2).toFixed(2) }}</span>
</template>
</el-table-column>
<!-- <el-table-column label="毛重KG" align="center" prop="grossWeight" />毛重KG -->
<el-table-column label="毛重KG" width="120" align="right">
<template slot-scope="scope">
<span>{{ (scope.row.quantity * scope.row.spare2).toFixed(2) }}</span>
</template>
</el-table-column>
<el-table-column label="价格" align="right" prop="price" /><!--价格-->
<el-table-column label="描述" align="center" prop="remark" /><!--描述-->
<!-- <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="数量" width="120" align="right">
<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="单价" width="120" align="left">
<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="金额" width="120" align="right">
<template slot-scope="scope">
<span>{{ (scope.row.quantity * scope.row.price).toFixed(2) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="100" align="center">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDeleteProduct(scope.$index)"
>删除</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">总金额:{{ 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']">提交</el-button>
<el-button @click="cancelPri">取消</el-button>
</div>
<!-- 选择物料对话框 -->
<el-dialog title="选择物料" :visible.sync="productSelectVisible" width="1300px" append-to-body>
<el-table :data="productOptions" border @selection-change="handleProductSelectionChange">
<el-table-column type="selection" width="55"/>
<!-- <el-table-column label="主键" align="center" prop="productGuid" />-->
<el-table-column label="物料编码" align="left" width="120px" prop="productId" /><!--物料编码-->
<el-table-column label="物料名称" align="left" prop="productName" /><!--物料名称-->
<el-table-column label="英文描述" align="left" prop="spare1"/><!--英文描述-->
<el-table-column label="单位" align="left" prop="unit" /><!--单位-->
<el-table-column label="单件净重KG" align="right" prop="spare2" /><!--单件净重KG-->
<!-- <el-table-column :label="$t('receiveStockinAdd.spare3')" align="center" prop="spare3" />&lt;!&ndash;箱号&ndash;&gt;-->
<!-- <el-table-column :label="$t('receiveStockinAdd.spare4')" align="center" prop="spare4" />&lt;!&ndash;包装方式&ndash;&gt;-->
<el-table-column label="长MM" align="right" prop="spare5" /><!--长MM-->
<el-table-column label="宽MM" align="right" prop="spare6" /><!--宽MM-->
<el-table-column label="高MM" align="right" prop="spare7" /><!--高MM-->
<el-table-column label="体积m³" align="right" prop="spare8" /><!--体积m³-->
<!-- <el-table-column label="净重KG" align="center" prop="spare8" />
<el-table-column label="毛重KG" align="center" prop="spare9" />-->
<el-table-column label="价格" align="right" prop="price" /><!--价格-->
<el-table-column label="描述" align="left" prop="remark" /><!--描述-->
</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">确定</el-button>
<el-button @click="productSelectVisible = false">取消</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">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<span>仅允许导入xls、xlsx格式文件。</span>
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm">确定</el-button>
<el-button @click="upload.open = false">取消</el-button>
</div>
</el-dialog>
<!-- 供应商选择对话框 -->
<el-dialog title="选择供应商" :visible.sync="supplierDialog" width="800px" append-to-body>
<el-form :model="supplierQueryParams" ref="supplierQueryForm" :inline="true">
<el-form-item label="供应商编号" prop="supplierNo">
<el-input
v-model="supplierQueryParams.supplierNo"
placeholder="请输入供应商编号"
clearable
size="small"
@keyup.enter.native="handleSupplierQuery"
/>
</el-form-item>
<el-form-item label="供应商名称" prop="supplierName">
<el-input
v-model="supplierQueryParams.supplierName"
placeholder="请输入供应商名称"
clearable
size="small"
@keyup.enter.native="handleSupplierQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleSupplierQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetSupplierQuery">重置</el-button>
</el-form-item>
</el-form>
<el-table
ref="supplierTable"
v-loading="supplierLoading"
:data="supplierList"
border
@row-click="handleSupplierRowClick"
highlight-current-row
style="width: 100%"
>
<el-table-column type="index" label="序号" width="50" align="center" />
<el-table-column label="供应商编号" align="center" prop="supplierNo" />
<el-table-column label="供应商名称" align="center" prop="supplierName" />
<el-table-column label="简称" align="center" prop="simpleName" />
<el-table-column label="是否可用" align="center" prop="useable">
<template slot-scope="scope">
<dict-tag :options="dict.type.is_available" :value="scope.row.useable"/>
</template>
</el-table-column>
</el-table>
<pagination
v-show="supplierTotal > 0"
:total="supplierTotal"
:page.sync="supplierQueryParams.pageNum"
:limit.sync="supplierQueryParams.pageSize"
@pagination="getSupplierList"
/>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="confirmSelectSupplier">确定</el-button>
<el-button @click="cancelSelectSupplier">取消</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"
import {listWarehouse} from "@/api/bas/warehouse"
export default {
name: "InAdd",
dicts: ['sys_normal_disable', 'is_active', 'storage_cond', 'is_available'],
data() {
return {
// 表单参数
form: {
warehouseId: undefined,
supplierId: undefined,
supplierName: undefined,
remark: undefined,
totalQuantity: 0,
totalAmount: 0,
totalNetWeight:0,
netWeight:0,
grossWeight:0,
file: undefined,
},
// 表单校验
rules: {
warehouseId: [
{required: true, message: "请选择仓库", trigger: "change"}
],
supplierId: [
{required: true, message: "请选择供应商", trigger: "change"}
],
},
// 仓库选项
warehouseOptions: [],
// 供应商选项
supplierOptions: [],
// 供应商选择对话框
supplierDialog: false,
// 供应商列表
supplierList: [],
// 选中的供应商
selectedSupplier: null,
// 供应商总数
supplierTotal: 0,
// 供应商加载状态
supplierLoading: false,
// 供应商查询参数
supplierQueryParams: {
pageNum: 1,
pageSize: 10,
supplierNo: null,
supplierName: null
},
// 物料列表
productList: [],
// 物料选择对话框
productSelectVisible: false,
// 物料选项,
productOptions: [],
// 已选物料
selectedProducts: [],
// 总数量
totalQuantity: 0,
// 总金额
totalAmount: 0,
totalNetWeight:0,
netWeight:0,
grossWeight:0,
//物料总数
productTotal: 0,
//物料查询参数
queryProductParams: {
pageNum: 1,
pageSize: 10
},
//仓库查询参数
queryWarehouseParams: {
pageNum: 1,
pageSize: 99
},
//物料遮盖
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(this.queryWarehouseParams).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;
});
},
/** 打开供应商选择对话框 */
openSupplierSelector() {
this.getSupplierListForDialog();
this.supplierDialog = true;
},
/** 获取供应商列表(对话框数据) */
getSupplierListForDialog() {
this.supplierLoading = true;
listBasSupplier(this.supplierQueryParams).then(response => {
this.supplierList = response.rows;
this.supplierTotal = response.total;
this.supplierLoading = false;
});
},
/** 供应商查询 */
handleSupplierQuery() {
this.supplierQueryParams.pageNum = 1;
this.getSupplierListForDialog();
},
/** 重置供应商查询 */
resetSupplierQuery() {
this.resetForm("supplierQueryForm");
// this.supplierQueryParams.useable = "0";
this.handleSupplierQuery();
},
/** 供应商行点击事件 */
handleSupplierRowClick(row) {
this.selectedSupplier = row;
this.$refs.supplierTable.setCurrentRow(row);
},
/** 确认选择供应商 */
confirmSelectSupplier() {
if (!this.selectedSupplier) {
this.$modal.msgError("请选择一个供应商");
return;
}
this.form.supplierId = this.selectedSupplier.supplierNo;
this.form.supplierName = this.selectedSupplier.supplierName;
this.supplierDialog = false;
},
/** 取消选择供应商 */
cancelSelectSupplier() {
this.selectedSupplier = null;
this.supplierDialog = false;
},
/** 添加物料按钮操作 */
handleAddProduct() {
this.getProductList();
this.productSelectVisible = true;
},
handleExportProduct() {
},
/** 物料选择变更 */
handleProductSelectionChange(selection) {
this.selectedProducts = selection;
},
/** 确认选择物料 */
confirmSelectProduct() {
// 检查选中的物料是否已存在于表单中
const duplicateProducts = this.selectedProducts.filter(selected =>
this.productList.some(existing => existing.productId === selected.productId)
);
if (duplicateProducts.length > 0) {
this.$modal.msgError('选择的物料已存在');
return;
}
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,
spare1: item.spare1,
spare2: item.spare2,
spare3: item.spare3,
spare4: item.spare4,
spare5: item.spare5,
spare6: item.spare6,
spare7: item.spare7,
spare8: item.spare8,
totalNetWeight: 0,
netWeight: 0,
grossWeight: 0
}));
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.totalNetWeight = this.productList.reduce((sum, item) => sum + ((item.quantity || 0) * (item.spare2 || 0)), 0);
this.netWeight = this.totalNetWeight;
this.grossWeight = this.totalNetWeight;
this.form.totalQuantity = this.totalQuantity;
this.form.totalAmount = this.totalAmount;
this.form.totalNetWeight = this.totalNetWeight;
this.form.netWeight = this.netWeight;
this.form.grossWeight = this.grossWeight;
},
cancelPri(){
// 重置表单数据
this.form = {
warehouseId: undefined,
supplierId: undefined,
supplierName: undefined,
remark: undefined,
totalQuantity: 0,
totalAmount: 0,
};
// 清空物料列表
this.productList = [];
// 重置计数器
this.totalQuantity = 0;
this.totalAmount = 0;
// 清空选中的供应商
this.selectedSupplier = null;
// 重置表单校验结果
this.$refs["form"].resetFields();
},
/** 表单提交 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.productList.length === 0) {
this.$modal.msgError('请添加物料');
return;
}
//校验lotNo productGuid quantity 不能为空
if (this.productList.some(item => !item.productGuid || !item.quantity)) {
this.$modal.msgError('物料信息不完整');
return;
}
// 构建请求数据
const data = {
warehouseId: this.form.warehouseId,
supplierId: this.form.supplierId,
//batchId: this.form.batchNo,
productVoList: this.productList.map(item => ({
productId: item.productId,
quantity: item.quantity,
lotNo: item.lotNo,
productGuid: item.productGuid,
englishDesc: item.spare1,
cartonNo: item.spare3,
packingMethod: item.spare4,
length: item.spare5,
width: item.spare6,
height: item.spare7,
volume: item.spare8,
totalNetWeight: item.totalNetWeight,
netWeight: item.netWeight,
grossWeight: item.grossWeight,
materialDesc: item.productName,
unit: item.unit,
unitNetWeight:item.spare2
}))
};
// 提交收货单
addStockin(data).then(() => {
this.$modal.msgSuccess('添加成功');
// 重置表单数据
this.cancelPri();
});
}
});
},
cancel() {
this.productSelectVisible = false;
},
/** 导入按钮操作 */
handleImport() {
this.upload.title = '导入物料'
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>