fix: 重写耗材模块

This commit is contained in:
2025-03-07 18:53:31 +08:00
parent 73057865da
commit 739f4a1062
67 changed files with 3610 additions and 1563 deletions

View File

@@ -0,0 +1,687 @@
<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="80px"
>
<el-row>
<el-col :span="8">
<el-form-item label="供应商">
<el-select
v-model="queryForm.purveyorId"
placeholder="请选择供应商"
clearable
style="width: 220px"
@change="changeTypeEnum"
>
<el-option
:label="item.name"
:value="item.id"
v-for="item in purveyorList"
:key="item.id"
></el-option>
</el-select>
{{ queryForm.waitAmount }}
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="入库时间" prop="time">
<el-date-picker
v-model="queryForm.time"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
placeholder="选择日期"
style="width: 220px"
></el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="shopTypes[shopTypesActive].value == 'purveyor'">
<el-col :span="8">
<el-form-item label="应付金额">
<el-input
v-model="queryForm.totalAmount"
placeholder="请输入应收金额"
style="width: 220px"
></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="实付金额">
<el-input
v-model="queryForm.paidAmount"
placeholder="请输入实收金额"
style="width: 220px"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="shopTypes[shopTypesActive].value == 'purveyor'">
<el-col :span="8">
<el-form-item label="付款时间">
<el-date-picker
v-model="queryForm.paidAt"
type="date"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
placeholder="选择日期"
style="width: 220px"
></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="批号">
<el-input
v-model="queryForm.batchNumber"
placeholder="请输入批号"
style="width: 220px"
></el-input>
</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-input>
</el-form-item>
</el-col>
</el-row>
<el-form-item>
<el-button type="primary" @click="showHaocai" v-if="inTabValue == 'consumable'">
选择耗材
</el-button>
<el-button type="primary" @click="$refs.shopList.show(tableData.list)" v-else>
选择商品
</el-button>
</el-form-item>
<el-autocomplete
v-model="autocompletename"
:fetch-suggestions="querySearchAsync"
:value-key="inTabValue == 'goods' ? 'name' : 'conName'"
:placeholder="inTabValue == 'goods' ? '商品搜索' : '耗材搜索'"
@select="handleSelect"
style="width: 500px"
></el-autocomplete>
</el-form>
</div>
<div class="head-container">
<el-button type="primary" plain v-if="inTabValue == 'consumable'">
{{ tableData.list.length }}种耗材金额合计
<span style="color: red">{{ queryForm.totalAmount }}</span>
</el-button>
<el-button type="primary" plain v-else>
{{ tableData.list.length }}种商品金额合计
<span style="color: red">{{ queryForm.totalAmount }}</span>
</el-button>
</div>
<div class="head-container">
<el-table :data="tableData.list" v-if="inTabValue == 'consumable'">
<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">
<el-input-number
v-model="scope.row.price"
:min="0"
controls-position="right"
@change="consCountTotal($event, scope.row, 'price')"
></el-input-number>
<div class="tips" style="font-size: 16px">
原价
<!-- {{ scope.row.costPrice }}/{{ scope.row.conUnit }} -->
{{
!scope.row.unit
? scope.row.defaultUnit
? scope.row.defaultUnit == scope.row.conUnitTwo
? (scope.row.costPrice * scope.row.conUnitTwoConvert).toFixed(2)
: scope.row.costPrice
: scope.row.costPrice
: scope.row.unit == scope.row.conUnitTwo
? (scope.row.costPrice * scope.row.conUnitTwoConvert).toFixed(2)
: scope.row.costPrice
}}
/
{{
!scope.row.unit
? scope.row.defaultUnit
? scope.row.defaultUnit
: scope.row.conUnit
: scope.row.unit
}}
</div>
</template>
</el-table-column>
<el-table-column label="单位">
<template v-slot="scope">
<el-select
@change="consCountTotal($event, scope.row, 'unit')"
v-model="scope.row.unit"
:placeholder="scope.row.defaultUnit ? scope.row.defaultUnit : scope.row.conUnit"
>
<el-option :label="scope.row.conUnit" :value="scope.row.conUnit"></el-option>
<el-option
:label="scope.row.conUnitTwo"
:value="scope.row.conUnitTwo"
v-if="scope.row.conUnitTwo"
></el-option>
</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"
@change="consCountTotal($event, scope.row, 'stockNumber')"
></el-input-number>
<div class="tips" style="font-size: 16px">入库前</div>
</template>
</el-table-column>
<el-table-column label="小计">
<template v-slot="scope">
<!-- <el-input-number v-model="scope.row.totalAmount" :min="0" scope.row.price , scope.row.stockNumber
controls-position="right"></el-input-number> -->
<el-input :value="formatDecimal(testform(scope.row))" readonly style="width: 100px" />
</template>
</el-table-column>
<!-- <el-table-column label="变动后剩余库存">
<template v-slot="scope">
{{ scope.row.stockNumber + scope.row.number }}{{ scope.row.conUnit }}
</template>
</el-table-column> -->
<el-table-column label="操作" width="80">
<template v-slot="scope">
<el-button link @click="tableData.list.splice(scope.$index, 1), spliceclick()">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<el-table :data="tableData.list" v-else>
<el-table-column type="index" width="50"></el-table-column>
<el-table-column label="商品名称" prop="name">
<template v-slot="scope">
<div class="name_wrap">
<span class="name">{{ scope.row.name }}</span>
<span v-if="scope.row.specSnap">({{ scope.row.specSnap }})</span>
<!-- <el-tag type="info" v-if="scope.row.specSnap" size="mini">{{ scope.row.specSnap }}</el-tag> -->
</div>
</template>
</el-table-column>
<el-table-column label="进价">
<template v-slot="scope">
<el-input-number
v-model="scope.row.costPrice"
:min="0"
controls-position="right"
@change="modifyPrice($event, scope.row, 'costPrice')"
></el-input-number>
<div class="tips">成本价{{ scope.row.costPrice }}/{{ scope.row.unitName }}</div>
</template>
</el-table-column>
<el-table-column label="数量">
<template v-slot="scope">
<el-input-number
v-model="scope.row.number"
:min="0"
:step="1"
step-strictly
controls-position="right"
@change="modifyPrice($event, scope.row, 'number', 'totalAmount')"
></el-input-number>
<div class="tips" style="font-size: 16px">
入库前
{{
!scope.row.unit
? scope.row.defaultUnit
? scope.row.defaultUnit == scope.row.conUnitTwo
? scope.row.number / scope.row.conUnitTwoConvert
: scope.row.number
: scope.row.number
: scope.row.unit == scope.row.conUnitTwo
? scope.row.number / scope.row.conUnitTwoConvert
: scope.row.number
}}
{{
!scope.row.unit
? scope.row.defaultUnit
? scope.row.defaultUnit
: scope.row.conUnit
: scope.row.unit
}}
</div>
</template>
</el-table-column>
<el-table-column label="小计">
<template v-slot="scope">
<!-- <el-input-number v-model="scope.row.totalAmount" :min="0"
controls-position="right"></el-input-number> -->
<el-input
:value="scope.row.costPrice * scope.row.number"
readonly
style="width: 100px"
/>
</template>
</el-table-column>
<el-table-column label="变动后剩余库存">
<template v-slot="scope">
{{ scope.row.stockNumber + scope.row.number }}{{ scope.row.unitName }}
</template>
</el-table-column>
<el-table-column label="操作" width="80">
<template v-slot="scope">
<el-button type="text" @click="tableData.list.splice(scope.$index, 1), spliceclick()">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div>
<el-button type="primary" @click="submitHandle" :loading="queryFormLoading">确定</el-button>
</div>
<!-- 选择商品 -->
<shopList ref="shopList" @success="selectShop" />
<!-- 选择耗材 -->
<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 vendorApi from "@/api/product/vendor";
import stockApi from "@/api/product/stock";
import dayjs from "dayjs";
import shopList from "./components/shopList.vue";
import ConsumableList from "./components/consumableList.vue";
import { formatDecimal } from "@/utils/tools.js";
export default {
name: "operation_in",
components: {
shopList,
ConsumableList,
},
data() {
return {
formatDecimal,
inTabValue: "consumable",
inTabs: [
{
label: "商品入库",
value: "goods",
type: "purveyor",
},
{
label: "耗材入库",
value: "consumable",
type: "in",
},
],
shopTypesActive: 0,
shopTypes: [
{
label: "供应商入库",
value: "purveyor",
},
{
label: "其他入库",
value: "purchase",
},
],
shopTypes2: [
{
label: "供应商入库",
value: "purveyor",
},
],
resetForm: "",
queryFormLoading: false,
queryForm: {
batchNumber: "",
list: [],
paidAmount: 0,
paidAt: "",
purveyorId: "",
purveyorName: "",
remark: "",
time: dayjs().format("YYYY-MM-DD"),
totalAmount: 0,
type: "in",
shopId: localStorage.getItem("shopId"),
},
queryRules: {
purveyorId: [
{
required: true,
message: "请选择供应商",
trigger: "change",
},
],
time: [
{
required: true,
message: " ",
trigger: "change",
},
],
},
purveyorList: [],
tableData: {
list: [],
},
showResult: false,
autocompletename: "",
restaurants: [],
timeout: null,
};
},
mounted() {
this.resetForm = { ...this.queryForm };
this.tbShopPurveyorGet();
},
methods: {
showHaocai() {
this.$refs.ConsumableList.show(this.tableData.list);
},
async querySearchAsync(queryString, cb) {
//快捷搜索
let res = null;
if (this.inTabValue == "goods") {
res = await tbProductlist({
page: 0,
size: 20,
name: queryString ? queryString : "",
shopId: localStorage.getItem("shopId"),
sort: "id",
});
} else {
res = await tbConsInfoGet({
page: 0,
size: 20,
shopId: localStorage.getItem("shopId"),
conName: queryString ? queryString : "",
});
}
this.restaurants = res.content;
if (res.content.length == 0) {
//给个提示没有搜到
this.$message("无此商品");
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());
},
testform(d) {
let p = 1;
if (d.unit && d.unit == d.conUnitTwo) {
p = d.conUnitTwoConvert;
}
return d.price * d.stockNumber * p;
},
handleSelect(item) {
//选定后清空
this.autocompletename = "";
if (this.inTabValue == "goods") {
this.selectShop([item]);
} else {
this.selectConsumable([item]);
}
},
//删除计算
spliceclick() {
var zong = 0;
if (this.inTabValue == "goods") {
this.tableData.list.forEach((ele) => {
zong += ele.costPrice * ele.number;
});
} else {
this.tableData.list.forEach((ele) => {
let p = 1;
if (ele.unit && ele.conUnitTwo == ele.unit) {
p = ele.conUnitTwoConvert;
}
zong += ele.price * ele.stockNumber * p;
});
}
this.queryForm.totalAmount = formatDecimal(zong);
},
// 选择商品
selectShop(res) {
let arr = [];
res.forEach((item) => {
item.skuList.forEach((i) => {
arr.push({
name: item.name,
unitName: item.unitName,
productId: item.id,
number: 0,
totalAmount: "",
...i,
});
});
});
this.tableData.list = [...this.tableData.list, ...arr];
},
// 切换入库内容
tabChange(value, type) {
this.shopTypesActive = type == "in" ? 0 : 1;
this.inTabValue = 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.purveyorId) {
this.shopTypesActive = 0;
} else {
this.shopTypesActive = 1;
}
},
// 计算耗材总价
consCountTotal(cvalue, row, key1, key2 = undefined) {
if (cvalue == undefined) {
setTimeout(() => {
row[key1] = 0;
let zong = 0;
this.tableData.list.forEach((ele) => {
zong += ele.price * ele.stockNumber;
});
this.queryForm.totalAmount = formatDecimal(zong);
}, 10);
} else {
row[key1] = cvalue;
let zong = 0;
this.tableData.list.forEach((ele) => {
let p = 1;
if (ele.unit && ele.conUnitTwo == ele.unit) {
p = ele.conUnitTwoConvert;
}
zong += ele.price * ele.stockNumber * p;
});
this.queryForm.totalAmount = formatDecimal(zong);
}
},
// 计算商品总价
modifyPrice(cvalue, row, key1, key2 = undefined) {
if (cvalue == undefined) {
setTimeout(() => {
row[key1] = 0;
row[key2] = 0;
let zong = 0;
this.tableData.list.forEach((ele) => {
zong += ele.costPrice * ele.number;
});
this.queryForm.totalAmount = formatDecimal(zong);
}, 10);
} else {
row[key1] = cvalue;
row[key2] = cvalue;
let zong = 0;
this.tableData.list.forEach((ele) => {
zong += ele.costPrice * ele.number;
});
this.queryForm.totalAmount = formatDecimal(zong);
}
},
// 提交
submitHandle() {
if (this.tableData.list.length == 0) {
switch (this.inTabValue) {
case "goods":
this.$message("请先选择商品!");
break;
case "consumable":
this.$message("请先选择耗材!");
break;
default:
break;
}
return false;
}
this.$refs.queryForm.validate(async (valid) => {
if (valid) {
try {
this.queryFormLoading = true;
switch (this.inTabValue) {
case "goods":
this.queryForm.list = this.tableData.list;
await tbProductStockOperateOutAndOn(this.queryForm);
break;
case "consumable":
this.queryForm.accountsPayable = this.queryForm.totalAmount;
this.queryForm.actualPayment = this.queryForm.paidAmount;
this.queryForm.paymentTime = this.queryForm.paidAt;
this.queryForm.supplierId = this.queryForm.purveyorId;
this.queryForm.list = this.tableData.list;
await stockApi.in(this.queryForm);
break;
default:
break;
}
this.queryFormLoading = false;
this.$message({
message: "入库提交成功",
type: "success",
});
this.resetHandle(); //初始化
// 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 = formatDecimal(item.stockNumber - item.stockConsume, 2, true);
item.stockNumber = 0;
item.costPrice = item.price;
item.conInfoId = item.id;
return item;
});
this.tableData.list = [...this.tableData.list, ...arr];
},
// 初始化
resetHandle() {
this.showResult = false;
this.queryForm = { ...this.resetForm };
if (this.inTabValue == "goods") {
this.queryForm.type = "purveyor";
} else {
this.queryForm.type = this.inTabs.find((item) => item.value == this.inTabValue).type;
}
this.tableData.list = [];
this.$refs.queryForm.resetFields();
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>