新增耗材入库-ai批量入库
This commit is contained in:
@@ -149,6 +149,38 @@ const AuthAPI = {
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
// 入库单识别
|
||||
stockOcr(data: any) {
|
||||
return request<any, Responseres>({
|
||||
url: `${baseURL}/stock/ocr`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
},
|
||||
// ocr识别结果
|
||||
ocrResult(params: any) {
|
||||
return request<any, Responseres>({
|
||||
url: `${baseURL}/stock/ocrResult`,
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
},
|
||||
// 耗材入库
|
||||
stockIn(data: any) {
|
||||
return request<any, Responseres>({
|
||||
url: `${baseURL}/stock/in`,
|
||||
method: "POST",
|
||||
data,
|
||||
});
|
||||
},
|
||||
// 供应商-列表
|
||||
vendorList(params: any) {
|
||||
return request<any, Responseres>({
|
||||
url: `${baseURL}/vendor/list`,
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
<!-- 单图上传组件 -->
|
||||
<template>
|
||||
<el-upload
|
||||
v-model="modelValue"
|
||||
class="single-upload"
|
||||
list-type="picture-card"
|
||||
:show-file-list="false"
|
||||
:accept="props.accept"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:http-request="handleUpload"
|
||||
:on-success="onSuccess"
|
||||
:on-error="onError"
|
||||
multiple
|
||||
>
|
||||
<el-upload v-model="modelValue" class="single-upload" list-type="picture-card" :show-file-list="false"
|
||||
:accept="props.accept" :before-upload="handleBeforeUpload" :http-request="handleUpload" :on-success="onSuccess"
|
||||
:on-error="onError" multiple :before-remove="emits('clear')">
|
||||
<template #default>
|
||||
<el-image v-if="modelValue" :src="modelValue" />
|
||||
<el-icon v-if="modelValue" class="single-upload__delete-btn" @click.stop="handleDelete">
|
||||
@@ -120,6 +111,7 @@ function handleBeforeUpload(file: UploadRawFile) {
|
||||
*/
|
||||
function handleUpload(options: UploadRequestOptions) {
|
||||
return new Promise((resolve, reject) => {
|
||||
emits("upload", options);
|
||||
const file = options.file;
|
||||
|
||||
const formData = new FormData();
|
||||
@@ -147,7 +139,7 @@ function handleDelete() {
|
||||
modelValue.value = "";
|
||||
}
|
||||
|
||||
const emits = defineEmits(["onSuccess"]);
|
||||
const emits = defineEmits(["onSuccess", 'upload', 'clear']);
|
||||
/**
|
||||
* 上传成功回调
|
||||
*
|
||||
|
||||
@@ -681,13 +681,15 @@ export default {
|
||||
shopId: this.shopInfo.id
|
||||
});
|
||||
this.trade = res;
|
||||
this.tradeLoading = false;
|
||||
this.tradeSale = res.sale;
|
||||
this.tradeVip = res.vip;
|
||||
this.tradeCount = res.count;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.tradeLoading = false;
|
||||
}, 500);
|
||||
},
|
||||
lineChartTypeChange(i) {
|
||||
this.lineChartType = i;
|
||||
|
||||
@@ -8,9 +8,8 @@
|
||||
<el-form :model="query" inline label-position="left">
|
||||
<template v-if="orderType == 2">
|
||||
<el-form-item>
|
||||
<el-input placeholder="商品名称" v-model="query.productName" />
|
||||
<el-input placeholder="商品名称" v-model="query.productName" clearable />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item v-if="isHeadShop == 1 && loginType == 0">
|
||||
<el-select v-model="shopId" placeholder="选择分店" style="width: 200px; margin-right: 10px"
|
||||
@change="getCategory">
|
||||
@@ -35,12 +34,12 @@
|
||||
<el-radio-button value="custom">自定义</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-date-picker class="u-m-l-10" v-model="query.createdAt" type="daterange" range-separator="至"
|
||||
start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD HH:mm:ss"
|
||||
start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD" :disabled-date="disabledDate"
|
||||
v-if="timeValue == 'custom'"></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="getTableData">查询</el-button>
|
||||
<el-button @click="resetHandle">重置</el-button>
|
||||
<el-button type="primary" icon="Search" :loading="tableData.loading" @click="getTableData">查询</el-button>
|
||||
<el-button icon="Refresh" :loading="tableData.loading" @click="resetHandle">重置</el-button>
|
||||
<el-button icon="download" v-loading="downloadLoading" @click="downloadHandle">
|
||||
<span v-if="!downloadLoading">导出Excel</span>
|
||||
<span v-else>下载中...</span>
|
||||
@@ -205,7 +204,7 @@ export default {
|
||||
orderType: "2",
|
||||
categorys: [],
|
||||
query: {
|
||||
createdAt: [],
|
||||
createdAt: [dayjs().format("YYYY-MM-DD"), dayjs().format("YYYY-MM-DD")],
|
||||
productName: "",
|
||||
prodCategoryId: "",
|
||||
},
|
||||
@@ -225,6 +224,12 @@ export default {
|
||||
isHeadShop: JSON.parse(localStorage.getItem("userInfo")).isHeadShop,
|
||||
loginType: localStorage.getItem("loginType"),
|
||||
shopInfo: JSON.parse(localStorage.getItem("userInfo")),
|
||||
disabledDate: (time) => {
|
||||
// dayjs().startOf('day'):获取今天的 00:00:00
|
||||
// dayjs(time):将原生 Date 转为 dayjs 对象
|
||||
// isAfter:判断目标日期是否在今天之后
|
||||
return dayjs(time).isAfter(dayjs().startOf('day'));
|
||||
}
|
||||
};
|
||||
},
|
||||
filters: {
|
||||
@@ -268,9 +273,9 @@ export default {
|
||||
// 获取订单汇总
|
||||
async daycount() {
|
||||
try {
|
||||
if (this.query.createdAt[1]) {
|
||||
this.query.createdAt.splice(1, 1, this.query.createdAt[1].replace("00:00:00", "23:59:59"))
|
||||
}
|
||||
// if (this.query.createdAt[1]) {
|
||||
// this.query.createdAt.splice(1, 1, this.query.createdAt[1].replace("00:00:00", "23:59:59"))
|
||||
// }
|
||||
const res = await saleSummaryApi.count({
|
||||
beginDate: this.query.createdAt[0],
|
||||
endDate: this.query.createdAt[1],
|
||||
@@ -289,9 +294,9 @@ export default {
|
||||
async downloadHandle() {
|
||||
try {
|
||||
this.downloadLoading = true;
|
||||
if (this.query.createdAt[1]) {
|
||||
this.query.createdAt.splice(1, 1, this.query.createdAt[1].replace("00:00:00", "23:59:59"))
|
||||
}
|
||||
// if (this.query.createdAt[1]) {
|
||||
// this.query.createdAt.splice(1, 1, this.query.createdAt[1].replace("00:00:00", "23:59:59"))
|
||||
// }
|
||||
const file = await saleSummaryApi.export({
|
||||
beginDate: this.query.createdAt[0],
|
||||
endDate: this.query.createdAt[1],
|
||||
@@ -307,7 +312,7 @@ export default {
|
||||
},
|
||||
// 重置查询
|
||||
resetHandle() {
|
||||
this.timeValue = "";
|
||||
this.timeValue = 'today';
|
||||
this.query = { ...this.resetQuery };
|
||||
this.page = 1;
|
||||
this.getTableData();
|
||||
@@ -327,9 +332,9 @@ export default {
|
||||
this.tableData.loading = true;
|
||||
try {
|
||||
this.daycount();
|
||||
if (this.query.createdAt[1]) {
|
||||
this.query.createdAt.splice(1, 1, this.query.createdAt[1].replace("00:00:00", "23:59:59"))
|
||||
}
|
||||
// if (this.query.createdAt[1]) {
|
||||
// this.query.createdAt.splice(1, 1, this.query.createdAt[1].replace("00:00:00", "23:59:59"))
|
||||
// }
|
||||
const res = await saleSummaryApi.page({
|
||||
page: this.tableData.page,
|
||||
size: this.tableData.size,
|
||||
@@ -347,11 +352,17 @@ export default {
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
this.tableData.loading = false;
|
||||
setTimeout(() => {
|
||||
this.tableData.loading = false;
|
||||
}, 500);
|
||||
},
|
||||
// 切换时间
|
||||
timeChange(e) {
|
||||
this.query.createdAt = formatDateRange(e)
|
||||
if (e !== 'custom') {
|
||||
this.query.createdAt = formatDateRange(e)
|
||||
} else {
|
||||
this.query.createdAt = []
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -7,12 +7,8 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="耗材分类" prop="consGroupId">
|
||||
<el-select v-model="form.consGroupId" placeholder="请选择耗材分类" style="width: 200px">
|
||||
<el-option
|
||||
v-for="option in consGroups"
|
||||
:key="option.conTypeId"
|
||||
:label="option.label"
|
||||
:value="option.id"
|
||||
></el-option>
|
||||
<el-option v-for="option in consGroups" :key="option.conTypeId" :label="option.label"
|
||||
:value="option.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="耗材价格" prop="price">
|
||||
@@ -24,18 +20,11 @@
|
||||
<el-form-item label="状态">
|
||||
<el-switch v-model="form.status" :active-value="1" :inactive-value="0"></el-switch>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="单位" prop="conUnit">
|
||||
<el-input v-model="form.conUnit" placeholder="请输入单位"></el-input>
|
||||
</el-form-item>
|
||||
<el-alert
|
||||
class="u-m-t-10 u-m-b-10"
|
||||
title="提示"
|
||||
description="换算值为第二单位*第二单位转换数量=第一单位"
|
||||
type="warning"
|
||||
show-icon
|
||||
:closable="false"
|
||||
></el-alert>
|
||||
<el-alert class="u-m-t-10 u-m-b-10" title="提示" description="换算值为第二单位*第二单位转换数量=第一单位" type="warning" show-icon
|
||||
:closable="false"></el-alert>
|
||||
<el-form-item label="预警值">
|
||||
<el-input-number v-model="form.conWarning" placeholder="请输入耗材预警值"></el-input-number>
|
||||
</el-form-item>
|
||||
@@ -46,10 +35,7 @@
|
||||
<el-input v-model="form.conUnitTwo" placeholder="请输入第二单位"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="第二单位转换数量" prop="conUnitTwoConvert">
|
||||
<el-input-number
|
||||
v-model="form.conUnitTwoConvert"
|
||||
placeholder="第二单位转换数量"
|
||||
></el-input-number>
|
||||
<el-input-number v-model="form.conUnitTwoConvert" placeholder="第二单位转换数量"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="默认入库单位" prop="defaultUnit">
|
||||
<el-input v-model="form.defaultUnit" placeholder="请输入默认入库单位"></el-input>
|
||||
|
||||
393
src/views/inventory/consumables/components/aiEntryDialog.vue
Normal file
393
src/views/inventory/consumables/components/aiEntryDialog.vue
Normal file
@@ -0,0 +1,393 @@
|
||||
<!-- AI入库 -->
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog title="批量入库" width="1000px" v-model="visible" @close="dialogCloseHandle">
|
||||
<div class="content">
|
||||
<div class="title_wrap">
|
||||
<span class="t">第一步:上传图片</span>
|
||||
</div>
|
||||
<div class="upload_wrap" v-loading="uploadLoading">
|
||||
<div class="upload_btn">
|
||||
<SingleImageUpload v-model="imgUrl" @upload="uploadLoading = true" @on-success="uploadSuccess"
|
||||
@clear="resId = null" />
|
||||
</div>
|
||||
<div class="btn">
|
||||
<el-button type="primary" :disabled="resId === null" @click="startCheckOcrRes">开始解析</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title_wrap">
|
||||
<span class="t">第二步:编辑信息</span>
|
||||
</div>
|
||||
<div class="table" v-if="form.bodyList">
|
||||
<el-form :model="form" label-width="120px" label-position="top">
|
||||
<el-form-item label="供应商信息">
|
||||
<el-select v-model="form.vendorId" style="width: 200px;" :disabled="stockInStatus">
|
||||
<el-option v-for="item in vendorList" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="耗材信息">
|
||||
<div class="header_wrap">
|
||||
<div class="item">
|
||||
<span class="tb">共{{ form.bodyList.length }}种耗材,</span>
|
||||
<span class="tb">金额合计:¥{{multiplyAndFormat(form.bodyList.reduce((sum, item) => sum +
|
||||
(item.purchasePrice || 0) *
|
||||
(item.inOutNumber || 0), 0), 1)}}</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<el-button type="primary" @click="consumableListRef.show(form.bodyList)"
|
||||
v-if="!stockInStatus">选择耗材</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="form.bodyList" border stripe width="100%" v-loading="confirmLoading">
|
||||
<el-table-column prop="conName" label="耗材名称">
|
||||
<template v-slot="scope">
|
||||
<el-input v-model="scope.row.conName" :maxlength="8" :disabled="stockInStatus"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="purchasePrice" label="单价">
|
||||
<template v-slot="scope">
|
||||
<el-input v-model="scope.row.purchasePrice" :maxlength="8"
|
||||
@input="e => scope.row.purchasePrice = filterNumberInput(e)" :disabled="stockInStatus"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="unitName" label="单位">
|
||||
<template v-slot="scope">
|
||||
<el-input v-model="scope.row.unitName" :maxlength="8" :disabled="stockInStatus"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="inOutNumber" label="数量">
|
||||
<template v-slot="scope">
|
||||
<el-input v-model="scope.row.inOutNumber" @input="e => scope.row.inOutNumber = filterNumberInput(e)"
|
||||
:disabled="stockInStatus"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="subTotal" label="小计">
|
||||
<template v-slot="scope">
|
||||
{{ multiplyAndFormat(scope.row.purchasePrice || 0, scope.row.inOutNumber || 0) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="120">
|
||||
<template v-slot="scope">
|
||||
<div v-if="stockInStatus">
|
||||
<el-text type="success" v-if="scope.row.conId">入库成功</el-text>
|
||||
<div class="column" v-else>
|
||||
<div>
|
||||
<el-text type="danger">入库失败</el-text>
|
||||
</div>
|
||||
<div>
|
||||
<el-text type="info" size="small">失败原因:{{ scope.row.failReason }}</el-text>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
<template v-slot="scope">
|
||||
<el-button type="danger" link @click="form.bodyList.splice(scope.$index, 1)"
|
||||
v-if="!stockInStatus">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="result_wrap" v-if="stockInStatus">
|
||||
上传完成 共{{ form.bodyList.length }}条数据,其中成功
|
||||
<el-text type="success">{{form.bodyList.filter(item => item.conId).length}} </el-text> 条,失败 <el-text
|
||||
type="danger">{{form.bodyList.filter(item => !item.conId).length}} </el-text>条
|
||||
</div>
|
||||
</div>
|
||||
<div class="tips" v-else>
|
||||
<el-text type="danger">请解析后使用</el-text>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer" v-if="form.bodyList && !stockInStatus">
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="confirmLoading" @click="submitHandle">提交</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog title="扫描结果查询中..." width="500px" v-model="checkLoading" :show-close="false"
|
||||
:close-on-click-modal="false">
|
||||
<div class="loading_wrap" ref="loadingWrap" v-loading="checkLoading" :element-loading-text="loadingText"></div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="danger" @click="closeCheckOcrHandle">取消查询</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<consumableList ref="consumableListRef" @success="consumableListRes" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch, nextTick } from "vue";
|
||||
import SingleImageUpload from "@/components/Upload/SingleImageUpload.vue"
|
||||
import productApi from "@/api/product/index";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { filterNumberInput, multiplyAndFormat } from '@/utils'
|
||||
import consumableList from "../../operation_in/components/consumableList.vue";
|
||||
|
||||
const consumableListRef = ref(null);
|
||||
|
||||
function consumableListRes(e) {
|
||||
console.log(e);
|
||||
if (e.length) {
|
||||
let arr = e.map(item => ({
|
||||
id: item.id,
|
||||
conId: item.id,
|
||||
conName: item.conName,
|
||||
purchasePrice: item.price,
|
||||
unitName: item.conUnit,
|
||||
inOutNumber: 1,
|
||||
}));
|
||||
form.value.bodyList.push(...arr);
|
||||
}
|
||||
}
|
||||
|
||||
const emits = defineEmits(['update']);
|
||||
|
||||
const visible = ref(false);
|
||||
|
||||
const show = () => {
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
const dialogCloseHandle = () => {
|
||||
emits('update');
|
||||
resId.value = null;
|
||||
form.value = {};
|
||||
stockInStatus.value = false;
|
||||
imgUrl.value = "";
|
||||
};
|
||||
|
||||
// 上传图片
|
||||
let resId = ref(null);
|
||||
const uploadLoading = ref(false);
|
||||
const imgUrl = ref("");
|
||||
async function uploadSuccess(url) {
|
||||
try {
|
||||
imgUrl.value = url;
|
||||
uploadLoading.value = true;
|
||||
resId.value = await productApi.stockOcr({ url: imgUrl.value });
|
||||
} catch (error) {
|
||||
console.error('上传图片失败', error);
|
||||
}
|
||||
setTimeout(() => {
|
||||
uploadLoading.value = false;
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// 查询OCR结果
|
||||
const form = ref({})
|
||||
function startCheckOcrRes() {
|
||||
stockInStatus.value = false;
|
||||
startQueryInterval()
|
||||
.then((res) => {
|
||||
console.log('查询成功', JSON.stringify(res));
|
||||
form.value = res;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('查询失败', error);
|
||||
});
|
||||
}
|
||||
|
||||
// 启动查询方法,每5秒查询一次,五分钟后超时停止查询
|
||||
const checkLoading = ref(false);
|
||||
const speed = 10000; // 查询间隔时间,单位毫秒
|
||||
const timeout = 300000; // 超时时间,单位毫秒
|
||||
// const timeout = 15000; // 超时时间,单位毫秒
|
||||
const interval = ref(null);
|
||||
const checkNumber = ref(0);
|
||||
const loadingText = computed(() => `每${speed / 1000}秒查询1次,已查询:${checkNumber.value}次`);
|
||||
const loadingWrap = ref(null);
|
||||
|
||||
function updateOverlayText() {
|
||||
nextTick(() => {
|
||||
try {
|
||||
const el = loadingWrap.value && loadingWrap.value.querySelector && loadingWrap.value.querySelector('.el-loading-text');
|
||||
if (el) el.textContent = loadingText.value;
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
watch(loadingText, () => {
|
||||
if (checkLoading.value) updateOverlayText();
|
||||
});
|
||||
|
||||
watch(checkLoading, (val) => {
|
||||
if (val) updateOverlayText();
|
||||
});
|
||||
function startQueryInterval() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!resId.value) {
|
||||
reject(new Error('无效的 resId,无法查询'));
|
||||
return;
|
||||
}
|
||||
|
||||
// 重置计数并显示 loading
|
||||
checkNumber.value = 0;
|
||||
checkLoading.value = true;
|
||||
updateOverlayText();
|
||||
|
||||
const startTime = Date.now();
|
||||
interval.value = null;
|
||||
|
||||
async function checkOnce() {
|
||||
try {
|
||||
checkNumber.value++;
|
||||
console.log('ocr checkNumber:', checkNumber.value);
|
||||
checkLoading.value = true;
|
||||
const res = await productApi.ocrResult({ id: resId.value });
|
||||
if (res && res.batchNo) {
|
||||
ElMessage.success('查询成功');
|
||||
checkLoading.value = false;
|
||||
clearInterval(interval.value);
|
||||
resolve(res);
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果还未超时,则继续等待下一轮查询
|
||||
if (Date.now() - startTime >= timeout) {
|
||||
checkLoading.value = false;
|
||||
ElMessage.error('查询超时');
|
||||
clearInterval(interval.value);
|
||||
reject(new Error('查询超时'));
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('查询失败');
|
||||
checkLoading.value = false;
|
||||
clearInterval(interval.value);
|
||||
reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
// 立即执行一次查询,然后按间隔继续查询
|
||||
checkOnce();
|
||||
interval.value = setInterval(checkOnce, speed);
|
||||
});
|
||||
}
|
||||
|
||||
// 取消查询
|
||||
function closeCheckOcrHandle() {
|
||||
checkLoading.value = false;
|
||||
clearInterval(interval.value);
|
||||
// 清空 overlay 文本(如果存在)以避免残留描述
|
||||
nextTick(() => {
|
||||
try {
|
||||
const el = loadingWrap.value && loadingWrap.value.querySelector && loadingWrap.value.querySelector('.el-loading-text');
|
||||
if (el) el.textContent = '';
|
||||
} catch (e) { }
|
||||
});
|
||||
}
|
||||
|
||||
// 供应商列表
|
||||
const vendorList = ref([]);
|
||||
async function vendorListAjax() {
|
||||
try {
|
||||
vendorList.value = await productApi.vendorList();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
// 最终提交
|
||||
const confirmLoading = ref(false);
|
||||
const stockInStatus = ref(false);
|
||||
async function submitHandle() {
|
||||
try {
|
||||
confirmLoading.value = true;
|
||||
const res = await productApi.stockIn(form.value)
|
||||
form.value = res;
|
||||
stockInStatus.value = true;
|
||||
ElMessage.success('提交成功');
|
||||
} catch (error) {
|
||||
console.error('提交失败', error);
|
||||
}
|
||||
setTimeout(() => {
|
||||
confirmLoading.value = false;
|
||||
// visible.value = false;
|
||||
}, 500);
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
vendorListAjax();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
.title_wrap {
|
||||
background-color: #F8F8F8;
|
||||
height: 54px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 42px;
|
||||
|
||||
.t {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.upload_wrap {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 14px 0;
|
||||
|
||||
.upload_btn {
|
||||
width: 152px;
|
||||
height: 152px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading_wrap {
|
||||
height: 200px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.table {
|
||||
width: 100%;
|
||||
padding-top: 14px;
|
||||
}
|
||||
|
||||
.result_wrap {
|
||||
padding: 14px 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.tips {
|
||||
padding: 14px 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.header_wrap {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 14px;
|
||||
|
||||
.tb {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -82,6 +82,11 @@ const contentConfig: IContentConfig = {
|
||||
name: "reportinglosses",
|
||||
auth: "",
|
||||
},
|
||||
{
|
||||
text: "批量入库",
|
||||
name: "batchWarehousing",
|
||||
auth: "",
|
||||
},
|
||||
],
|
||||
defaultToolbar: ["refresh", "filter", "search"],
|
||||
cols: [
|
||||
|
||||
@@ -83,10 +83,14 @@
|
||||
<add-haocai ref="refAddHaocai" @refresh="refresh" />
|
||||
<!-- 耗材盘点 -->
|
||||
<addConsTakin ref="refAddHaocaiTakin" @success="refresh" />
|
||||
<!-- AI入库 -->
|
||||
<ai-entry-dialog ref="aiEntryDialogRef" @update="
|
||||
contentRef?.fetchPageData()" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import aiEntryDialog from "./components/aiEntryDialog.vue";
|
||||
import addHaocai from "./components/add-haocai.vue";
|
||||
import dataTongji from "./components/DataStatistics.vue";
|
||||
import addConsTakin from "./components/addConsTakin.vue";
|
||||
@@ -101,6 +105,12 @@ import searchConfig from "./config/search";
|
||||
import { returnOptionsLabel } from "./config/config";
|
||||
import { isSyncStatus } from "@/utils/index";
|
||||
|
||||
const aiEntryDialogRef = ref<any>(null);
|
||||
|
||||
function showAiEntryDialog() {
|
||||
aiEntryDialogRef.value?.show?.();
|
||||
}
|
||||
|
||||
const router = useRouter();
|
||||
const {
|
||||
searchRef,
|
||||
@@ -164,7 +174,7 @@ watch(
|
||||
);
|
||||
|
||||
//耗材盘点
|
||||
const refAddHaocaiTakin = ref();
|
||||
const refAddHaocaiTakin = ref<any>(null);
|
||||
function refAddHaocaiTakinShow(item: any, type: string) {
|
||||
console.log(item);
|
||||
if (type === "manual-in") {
|
||||
@@ -172,14 +182,14 @@ function refAddHaocaiTakinShow(item: any, type: string) {
|
||||
return;
|
||||
}
|
||||
if (type === "delete") {
|
||||
refAddHaocaiTakin.value.show(item, type);
|
||||
refAddHaocaiTakin.value?.show?.(item, type);
|
||||
return;
|
||||
}
|
||||
if (type === "consumables") {
|
||||
refAddHaocaiTakin.value.show(item, type);
|
||||
refAddHaocaiTakin.value?.show?.(item, type);
|
||||
return;
|
||||
}
|
||||
refAddHaocaiTakin.value.show(item);
|
||||
refAddHaocaiTakin.value?.show?.(item);
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
@@ -187,9 +197,9 @@ function refresh() {
|
||||
contentRef.value?.fetchPageData();
|
||||
getTongji(undefined);
|
||||
}
|
||||
const refAddHaocai = ref();
|
||||
const refAddHaocai = ref<any>(null);
|
||||
function refAddHaocaiOpen(item: any) {
|
||||
refAddHaocai.value.open(item);
|
||||
refAddHaocai.value?.open?.(item);
|
||||
}
|
||||
// 新增
|
||||
async function handleAddClick() {
|
||||
@@ -234,6 +244,10 @@ async function handleToolbarClick(name: string) {
|
||||
router.push({ path: "/inventory/libraryrecords", query: { inOutItem: name } });
|
||||
return;
|
||||
}
|
||||
if (name === "batchWarehousing") {
|
||||
showAiEntryDialog();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 其他操作列
|
||||
async function handleOperatClick(data: IOperatData) {
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import _ from "lodash";
|
||||
import CouponLists from "./coup-lists.vue";
|
||||
|
||||
import { ref, toRaw } from "vue";
|
||||
@@ -132,7 +133,7 @@ function open(data, index) {
|
||||
console.log("data", data);
|
||||
console.log("index", index);
|
||||
if (data && data.name) {
|
||||
form.value = { ...data };
|
||||
form.value = _.cloneDeep(toRaw(data));
|
||||
isedit.value = true;
|
||||
dataIndex = index;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user