687 lines
22 KiB
Vue
687 lines
22 KiB
Vue
<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"> </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> |