Files
cashier-web/src/views/inventory/operation_in/index.vue
2025-12-26 16:55:36 +08:00

473 lines
16 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 bg-fff u-m-20">
<div class="head-container">
<el-form ref="queryForm" :model="queryForm" :rules="queryRules" label-position="left" label-width="100px">
<el-row>
<el-form-item label="类型">
<el-radio-group :model-value="type" @change="tabChange">
<el-radio v-if="type == 'reportinglosses'" value="reportinglosses">报损</el-radio>
<div v-else>
<el-radio value="in">入库</el-radio>
<el-radio value="out">出库</el-radio>
</div>
</el-radio-group>
</el-form-item>
</el-row>
<div v-if="type != 'reportinglosses'">
<el-row>
<el-col v-if="type == 'in'" :span="8">
<el-form-item label="供应商">
<el-select v-model="queryForm.vendorId" placeholder="请选择供应商" clearable style="width: 220px"
@change="changeTypeEnum">
<el-option v-for="item in purveyorList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
{{ queryForm.waitAmount }}
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="出入库时间" prop="inOutDate">
<el-date-picker v-model="queryForm.inOutDate" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
placeholder="选择日期" style="width: 220px" disabled="false" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<el-form-item label="应付金额">
<el-input v-model="queryForm.amountPayable" placeholder="请输入应收金额" style="width: 220px" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="实付金额">
<el-input v-model="queryForm.actualPaymentAmount" placeholder="请输入实收金额" style="width: 220px" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<el-form-item label="付款时间">
<el-date-picker v-model="queryForm.paymentDate" type="date" format="YYYY-MM-DD"
value-format="YYYY-MM-DD" placeholder="选择日期" style="width: 220px" />
</el-form-item>
</el-col>
<!-- <el-col :span="8">
<el-form-item label="批号">
<el-input v-model="queryForm.batchNo" placeholder="请输入批号" style="width: 220px" />
</el-form-item>
</el-col> -->
</el-row>
<!-- <el-row>
<el-col :span="8">
<el-form-item label="备注">
<el-input v-model="queryForm.remark" placeholder="请输入备注" style="width: 220px" />
</el-form-item>
</el-col>
</el-row> -->
</div>
<el-form-item label="选择耗材">
<div />
<el-button type="primary" @click="showHaocai">选择耗材</el-button>
<el-autocomplete v-model="autocompletename" :fetch-suggestions="querySearchAsync" value-key="conName"
placeholder="耗材搜索" style="width: 200px; margin-left: 20px" @select="handleSelect" />
</el-form-item>
</el-form>
</div>
<div style="font-weight: bold; font-size: 16px; color: #666">
{{ tableData.list.length }}种耗材金额合计
<span style="color: red">{{ amountPayable }}</span>
</div>
<div class="head-container">
<el-table :data="tableData.list">
<el-table-column label="耗材名称" prop="conName">
<template v-slot="scope">
{{ scope.row.conName }}
</template>
</el-table-column>
<el-table-column label="所属分类">
<template v-slot="scope">
{{ scope.row.consGroupName }}
</template>
</el-table-column>
<el-table-column>
<template v-slot="scope">
<el-input-number v-model="scope.row.price" :min="0" controls-position="right" />
<div class="tips" style="font-size: 16px">
原价
{{ returnPrice(scope.row, scope.row.originPrice) }}
/
{{ scope.row.unit }}
</div>
</template>
</el-table-column>
<el-table-column label="单位">
<template v-slot="scope">
<el-select v-model="scope.row.unit" :placeholder="scope.row.unit" @change="changeUnit(scope.row)">
<el-option :label="scope.row.conUnit" :value="scope.row.conUnit" />
<el-option v-if="scope.row.conUnitTwo" :label="scope.row.conUnitTwo" :value="scope.row.conUnitTwo" />
</el-select>
<div class="tips">&nbsp;</div>
</template>
</el-table-column>
<el-table-column label="数量">
<template v-slot="scope">
<el-input-number v-model="scope.row.stockNumber" :min="0" :step="1" step-strictly
controls-position="right" />
<div class="tips" style="font-size: 16px">
{{ type == "in" ? "入库" : "出库" }}
{{ returnStockNumber(scope.row, scope.row.number) }}
{{ scope.row.unit }}
</div>
</template>
</el-table-column>
<!-- <el-table-column v-if="type == 'reportinglosses'" label="报损数量">
<template v-slot="scope">
{{ scope.row.number }}
<div class="tips" style="font-size: 16px">
入库前
{{ returnStockNumber(scope.row, scope.row.number) }}
{{ scope.row.unit }}
</div>
</template>
</el-table-column> -->
<el-table-column v-if="type == 'reportinglosses'" label="上传图片">
<template v-slot="scope">
<MultiImageUpload v-model="scope.row.imgUrls" />
</template>
</el-table-column>
<!-- <el-table-column label="备注">
<template v-slot="scope">
<el-input v-model="textarea" stype="textarea" placeholder="" />
</template>
</el-table-column> -->
<el-table-column label="操作" width="80">
<template v-slot="scope">
<el-button link @click="tableData.list.splice(scope.$index, 1)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div>
<el-button type="primary" :loading="queryFormLoading" @click="submitHandle">
保存并返回
</el-button>
</div>
<!-- 选择耗材 -->
<ConsumableList ref="ConsumableList" @success="selectConsumable" />
<el-dialog v-model="showResult" :show-close="false" :close-on-press-escape="false" :close-on-click-modal="false">
<el-result icon="success" title="入库提交成功" :subTitle="`共操作${tableData.list.length}件商品`">
<template #extra>
<template>
<el-button type="primary" size="medium" @click="resetHandle">创建新的入库单</el-button>
<router-link to="/invoicing/operating_record">
<el-button size="medium">历史提交</el-button>
</router-link>
</template>
</template>
</el-result>
</el-dialog>
</div>
</template>
<script>
import { ElMessage, ElMessageBox } from "element-plus";
import consApi from "@/api/product/cons";
import Decimal from "decimal.js";
import vendorApi from "@/api/product/vendor";
import stockApi from "@/api/product/stock";
import dayjs from "dayjs";
import goodsList from "./components/goods-list.vue";
import MultiImageUpload from "@/components/Upload/MultiImageUpload.vue";
import ConsumableList from "./components/consumableList.vue";
import { formatDecimal } from "@/utils/tools.js";
export default {
name: "operation_in",
components: {
goodsList,
ConsumableList,
},
data() {
return {
type: "in", //in 入库 out出库
formatDecimal,
inTabValue: "consumable",
inTabs: [
{
label: "商品入库",
value: "goods",
type: "out",
},
{
label: "耗材入库",
value: "consumable",
type: "in",
},
],
shopTypesActive: 0,
resetForm: "",
queryFormLoading: false,
queryForm: {
batchNo: "",
bodyList: [],
actualPaymentAmount: 0,
paymentDate: "",
vendorId: "",
purveyorName: "",
remark: "",
inOutDate: dayjs().format("YYYY-MM-DD"),
amountPayable: 0,
type: "in",
shopId: localStorage.getItem("shopId"),
},
queryRules: {
vendorId: [
{
required: true,
message: "请选择供应商",
trigger: "change",
},
],
inOutDate: [
{
required: true,
message: " ",
trigger: "change",
},
],
},
purveyorList: [],
tableData: {
list: [],
},
showResult: false,
autocompletename: "",
restaurants: [],
timeout: null,
};
},
computed: {
amountPayable() {
if (!this.tableData.list.length) return 0;
const zong = this.tableData.list.reduce((prve, ele) => {
return (prve += ele.price * ele.stockNumber);
}, 0);
return zong.toFixed(2);
},
},
watch: {
amountPayable(newval) {
this.queryForm.amountPayable = newval;
},
},
mounted() {
this.type = this.$route.query.type || "in";
this.resetForm = { ...this.queryForm };
this.tbShopPurveyorGet();
},
methods: {
changeUnit(row) {
row.price = this.returnPrice(row, row.originPrice);
},
returnPrice(row, price = 0) {
if (!row.unit) {
return price;
}
if (row.unit == row.conUnit) {
return price;
}
if (row.conUnitTwo && row.unit == row.conUnitTwo) {
// console.log(price / row.conUnitTwoConvert);
// console.log(new Decimal(price).div(new Decimal(row.conUnitTwoConvert)));
return new Decimal(price).mul(new Decimal(row.conUnitTwoConvert));
}
return price;
},
returnStockNumber(row, number = 0) {
if (!row.unit) {
return number;
}
if (row.unit == row.conUnit) {
return number;
}
if (row.conUnitTwo && row.unit == row.conUnitTwo) {
return number / row.conUnitTwoConvert;
}
return number;
},
showHaocai() {
this.$refs.ConsumableList.show(this.tableData.list);
},
async querySearchAsync(queryString, cb) {
//快捷搜索
let res = null;
res = await consApi.getList({
page: 0,
size: 20,
conName: queryString ? queryString : "",
});
this.restaurants = res.records;
if (res.records.length == 0) {
//给个提示没有搜到
ElMessage("无此耗材");
return false;
}
var uniqueArray = this.restaurants.filter(
(item1) => !this.tableData.list.some((item2) => item2.productId == item1.id)
);
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
cb(uniqueArray);
}, 1000 * Math.random());
},
xiaoji(row) {
const price = row.price * row.stockNumber;
return price;
},
handleSelect(item) {
//选定后清空
this.autocompletename = "";
this.selectConsumable([item]);
},
// 切换入库内容
tabChange(value) {
this.shopTypesActive = value == "in" ? 0 : 1;
this.inTabValue = value;
this.type = value;
this.resetHandle();
// this.$refs.shopList.reset(); //清除选项
// this.$refs.ConsumableList.reset(); //清除选项
},
// 切换类型
changeTypeEnum(index) {
let filterd = this.purveyorList.filter((ele) => ele.id == index);
this.queryForm.waitAmount = filterd[0].waitAmount;
this.inTabs.forEach((i) => {
if (i.value == this.inTabValue) {
this.queryForm.type = i.type;
}
});
if (this.inTabValue == "consumable") {
return false;
}
//商品入库是否显示应付实付
if (this.queryForm.vendorId) {
this.shopTypesActive = 0;
} else {
this.shopTypesActive = 1;
}
},
// 提交
submitHandle() {
if (this.tableData.list.length == 0) {
ElMessage("请先选择耗材!");
return;
}
this.$refs.queryForm.validate(async (valid) => {
if (valid) {
try {
this.queryFormLoading = true;
const bodyList = this.tableData.list.map((v) => {
let inOutNumber = v.stockNumber;
if (v.unit == v.conUnit) {
inOutNumber = v.stockNumber;
}
if (v.conUnitTwo && v.unit == v.conUnitTwo) {
inOutNumber = v.stockNumber * v.conUnitTwoConvert;
}
return {
conId: v.id,
conName: v.conName,
purchasePrice: v.price,
unitName: v.conUnit,
inOutNumber: inOutNumber,
subTotal: this.xiaoji(v),
imgUrls: v.imgUrls,
number: inOutNumber,
};
});
if (this.type == "in") {
await stockApi.in({ ...this.queryForm, bodyList });
} else if (this.type == "out") {
await stockApi.out({ ...this.queryForm, bodyList });
} else if (this.type == "reportinglosses") {
await stockApi.reportDamage(bodyList);
}
this.queryFormLoading = false;
// const title = this.type == "in" ? "入库" : "出库";
ElMessage({
// message: title + "提交成功",
message: "提交成功",
type: "success",
});
this.$router.push("/inventory/consumables");
this.showResult = true;
// this.$refs.shopList.reset()//清除选项
// this.$refs.ConsumableList.reset()//清除选项
} catch (error) {
console.log(error);
this.queryFormLoading = false;
}
}
});
},
// 选择耗材
selectConsumable(res) {
console.log(res);
let arr = res.map((item) => {
item.number = item.stockNumber;
item.stockNumber = 0;
item.costPrice = item.price;
item.conInfoId = item.id;
item.unit = item.defaultUnit || item.conUnit;
item.originPrice = item.price;
item.price = this.returnPrice(item, item.price);
item.imgUrls = item.imgUrls ? item.imgUrls : [];
return item;
});
this.tableData.list = [...this.tableData.list, ...arr];
},
// 初始化
resetHandle() {
this.showResult = false;
this.queryForm = { ...this.resetForm };
console.log(this.inTabs, this.inTabValue);
this.queryForm.type = this.inTabs.find((item) => item.type == this.inTabValue).type;
this.tableData.list = [];
this.$refs.queryForm.resetFields();
},
// 获取供应商列表
async tbShopPurveyorGet() {
try {
const res = await vendorApi.getList({});
this.purveyorList = res.records;
} catch (error) {
console.log(error);
}
},
},
};
</script>
<style scoped lang="scss">
.name_wrap {
display: flex;
align-items: center;
.name {
margin-right: 10px;
}
}
.app-container {}
</style>