heli-mes/mes-ui/mes-ui-admin-vue3/src/views/heli/purchaseorderno/partReceived.vue

568 lines
21 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>
<el-card class="hl-card">
<template #header>
<span>零件采购收货</span>
</template>
<ContentWrap class="borderxx">
<!-- 搜索工作栏 -->
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="120px">
<el-form-item label="采购订单号" prop="purchaseNo">
<el-input
v-model="queryParams.purchaseNo" placeholder="采购订单号" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="项目编码" prop="projectCode">
<el-input
v-model="queryParams.projectCode" placeholder="请输入项目编码" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="项目简称" prop="projectName">
<el-input
v-model="queryParams.projectName" placeholder="请输入项目简称" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="客户简称" prop="customerName">
<el-input
v-model="queryParams.customerName"
placeholder="请输入客户简称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="子项目简称" prop="projectSubName">
<el-input
v-model="queryParams.projectSubName" placeholder="子项目简称" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="零件" prop="boomName">
<el-input
v-model="queryParams.boomName" placeholder="请输入零件" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="图号" prop="blueprintNo">
<el-input
v-model="queryParams.blueprintNo" placeholder="请输入图号" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="工序" prop="procedureName">
<el-input
v-model="queryParams.procedureName" placeholder="请输入工序" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="供应商" prop="supplierName">
<el-input
v-model="queryParams.supplierName" placeholder="供应商" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="责任人" prop="username">
<el-input
v-model="queryParams.username" placeholder="责任人" clearable @keyup.enter="handleQuery" :readonly="isReadOnly"
class="!w-240px" />
</el-form-item>
<el-form-item label="收货状态" prop="receivingStatus">
<el-select v-model="queryParams.receivingStatus" placeholder="下拉选择" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.HELI_PURCHASE_RECEIVING_STATUS).filter(item=>item.value!=2)" :key="dict.value"
:label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item style="margin-left:50px">
<el-button @click="handleQuery" type="primary">
<Icon icon="ep:search" class="mr-5px" /> 搜索
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" /> 重置
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<el-card class="hl-card-info">
<template #header>
<div class="hl-card-info-icona"></div><span class="hl-card-info-text">订单明细</span>
<el-button style="margin-left: 20px" @click="receiveGoods" type="success" size="large">收货</el-button>
<el-button style="margin-left: 20px" @click="isPrint" type="primary" size="large">打印</el-button>
<el-button
style="margin-left: 20px"
type="success"
plain
@click="handleExportDetail"
:loading="exportLoading"
>
<Icon icon="ep:download" class="mr-5px" /> 导出EXCEL
</el-button>
</template>
<el-row>
<el-col>
<el-card class="hl-incard">
<el-form ref="subFormRef" :model="list" v-loading="formLoading" label-width="0" >
<el-table
v-loading="loading" :data="list" :show-overflow-tooltip="true" class="hl-table" ref="multipleTableRef" show-summary :summary-method="getSummaries" @selection-change="handleSelectionChange" :row-class-name="tableRowClassName">
<el-table-column type="selection" width="80" fixed="left" />
<!-- <el-table-column label="收货状态" align="center" prop="receivingStatus" min-width="120">-->
<!-- <template #default="scope">-->
<!-- <dict-tag :type="DICT_TYPE.HELI_PURCHASE_RECEIVING_STATUS" :value="scope.row.receivingStatus" />-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column prop="projectSubCode" min-width="240" label="子项目编码" align="center"/>
<el-table-column prop="blueprintNo" min-width="80" label="图号" align="center"/>
<el-table-column prop="boomName" min-width="180" label="零件名称" align="center"/>
<el-table-column prop="boomSpec" min-width="110" label="规格/型号" align="center"/>
<el-table-column prop="supplierName" min-width="100" label="供应商" align="center"/>
<el-table-column prop="procedureName" min-width="100" label="工序" align="center"/>
<el-table-column prop="compositionName" min-width="100" label="材质" align="center"/>
<el-table-column prop="purchaseAmount" min-width="100" label="采购数量" align="center" />
<!-- <el-table-column prop="purchaseRemAmount" min-width="100" label="剩余数量" align="center"/>-->
<el-table-column prop="purchaseRemAmounts" min-width="170" align="center" label="入库数量"/>
<el-table-column prop="estimatedPrice" min-width="170" label="单价" align="center">
<template #header>单价</template>
<template #default="scope">
<el-form-item :prop="`${scope.$index}.unitPrice`" class="mb-0px!">
<el-input-number
style="width: 100%"
v-model="scope.row.unitPrice"
placeholder="单价"
:min="0"
:precision="2"
@change="changeUnitPrice(scope.row)"
@input="(val)=>handleInput(val,scope.row)"
@keyup.enter="(e)=>handleEnterUnitPrice(e,scope.row)"
:id="'unitPrice'+scope.row.id"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="estimatedPrice" min-width="170" label="预估总价(元)" align="center">
<template #header><span class="hl-table_header">*</span>预估总价(元)</template>
<template #default="scope">
<el-form-item :prop="`${scope.$index}.estimatedPrice`" class="mb-0px!">
<el-input-number
style="width: 100%" v-model="scope.row.estimatedPrice" placeholder="预估总价" :min="0" :precision="2"
@input="(val)=>handleInput(val,scope.row)"
@keyup.enter="(e)=>handleEnter(e,scope.row)"
@change="changeEstimatedPrice(scope.row)"
:id="'estimatedPrice'+scope.row.id"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="createTime" min-width="150" label="订单生成日期" align="center" :formatter="dateFormatter1"/>
<!-- <el-table-column prop="requireTime" min-width="150" label="需要完成日期" align="center" :formatter="dateFormatter1"/>-->
<el-table-column prop="arriveTime" min-width="150" label="收货日期" align="center" :formatter="dateFormatter1" />
<el-table-column prop="description" min-width="150" label="技术要求" align="center"/>
<!-- <el-table-column prop="theWeight" min-width="100" label="理论重量" align="center"/>-->
<el-table-column label="操作" align="center" fixed="right" min-width="200">
<template #default="scope">
<el-button link type="danger" v-if="scope.row.receivingStatus!=3" @click="receiveGood(scope.row)">
未收货
</el-button>
<el-button link type="primary" @click="updateFrom(scope.row)" v-if="scope.row.receivingStatus==3">
总价修改
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="getList" />
</el-form>
</el-card>
</el-col>
</el-row>
</el-card>
</el-card>
<PrintRef ref="printRef"/>
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import * as PurchaseOrderApi from '@/api/heli/purchaseorder'
import * as UserApi from '@/api/system/user'
import {ElButton, ElTable} from 'element-plus'
import {useUserStore} from "@/store/modules/user";
import {dateFormatter1} from "@/utils/formatTime";
import * as PurchaseOrderNoDetailApi from "@/api/heli/purchaseordernodetail";
import download from "@/utils/download";
import {exportExcel} from "@/api/heli/purchaseordernodetail";
import axios from "axios";
import {getAccessToken, getTenantId} from "@/utils/auth";
import PrintRef from "./print.vue"
defineOptions({ name: 'PurchaseordernopartReceived' })
const userStore = useUserStore()
const username = userStore.getUser.nickname
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const router = useRouter()
const loading = ref(true) // 列表的加载中
const isReadOnly = ref(false) // 列表的加载中
const list = ref([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
id: undefined,
ids: undefined,
purchaseNo: undefined,
supplierId: undefined,
contractNo: undefined,
purchaseType: undefined,
projectMaterialPlanId: undefined,
goodsType: 2,
currencyType: undefined,
taxRatio: undefined,
estimatedPrice: undefined,
actualPrice: undefined,
status: undefined,
submitUserId: undefined,
submitTime: [],
auditor: undefined,
auditTime: [],
description: undefined,
creator: undefined,
createTime: undefined,
receivingStatus:1,
projectName:undefined,
projectSubName:undefined,
username:username,
supplierName:undefined,
boomName:undefined,
blueprintNo:undefined,
procedureName:undefined,
customerName:undefined,
projectCode:undefined
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
const changeUnitPrice =(row:any)=>{
row.estimatedPrice=parseFloat((row.unitPrice* row.purchaseAmount).toFixed(2))
}
const changeEstimatedPrice =(row:any)=>{
row.unitPrice=parseFloat((row.estimatedPrice/row.purchaseAmount).toFixed(2))
}
const handleInput = (val: number, row: PurchaseOrderNoDetailApi.PurchaseOrderNoDetailVO) => {
console.log(val, 'val');
//输入判断当前行是否选中如无将当前行选中
if (multipleSelection.value.indexOf(row) == -1) {
multipleSelection.value.push(row);
multipleTableRef.value.toggleRowSelection(row)
};
}
const handleEnter = (e: KeyboardEvent, row: PurchaseOrderNoDetailApi.PurchaseOrderNoDetailVO) => {
//敲下回车时切换到下一行的预估总价 如果为0.00将其=null
console.log(e, 'e');
if (list.value.indexOf(row) == list.value.length - 1) {
return
}
const index = list.value.findIndex((item) => item.id == row.id)
const input = document.getElementById("estimatedPrice" + list.value[index + 1].id);
if (input) {
input.focus();
if (list.value[index + 1].estimatedPrice == 0.00) {
list.value[index + 1].estimatedPrice = ''
}
}
console.log(input, 'input');
}
const handleEnterUnitPrice = (e: KeyboardEvent, row: PurchaseOrderNoDetailApi.PurchaseOrderNoDetailVO) => {
if (list.value.indexOf(row) == list.value.length - 1) {
return
}
const index = list.value.findIndex((item) => item.id == row.id)
const input = document.getElementById("unitPrice" + list.value[index + 1].id);
if (input) {
input.focus();
if (list.value[index + 1].unitPrice == 0.00) {
list.value[index + 1].unitPrice = ''
}
}
}
const getSummaries = (param: SummaryMethodProps) => {
const summaryField = ["purchaseRemAmounts"];
const { columns, data } = param;
const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = '合计';
return;
}
if (!summaryField.includes(column.property)) {
sums[index] = '';
return;
}
const values = data.map(item => Number(item[column.property]));
if (!values.every(value => isNaN(value))) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return floatAdd(prev, curr);
} else {
return prev;
}
}, 0);
const thousandsField = [];
if (thousandsField.includes(column.property)) {
sums[index] = thousandsFormat(sums[index]);
}
} else {
sums[index] = '';
}
});
// const sumValue = computed(() => {
// return list.value.reduce((sum, item) => sum + item.quantityLent, 0);
// });
// const sums = ['合计','','','','','','','',sumValue];
return sums;
}
const floatAdd = (a, b) => {
var c, d, e;
if (undefined === a || null === a || "" === a || isNaN(a)) { a = 0; }
if (undefined === b || null === b || "" === b || isNaN(b)) { b = 0; }
try {
c = a.toString().split(".")[1].length;
} catch (f) {
c = 0;
}
try {
d = b.toString().split(".")[1].length;
} catch (f) {
d = 0;
}
e = Math.pow(10, Math.max(c, d));
return (floatMul(a, e) + floatMul(b, e)) / e;
};
const floatMul = (a, b) => {
var c = 0,
d = a.toString(),
e = b.toString();
try {
c += d.split(".")[1].length;
} catch (f) {}
try {
c += e.split(".")[1].length;
} catch (f) {}
return Number(d.replace(".", "")) * Number(e.replace(".", "")) / Math.pow(10, c);
}
const tableRowClassName = ({ row }) => {
return row.isSelected ? 'selected-row' : '';
}
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
queryParams.ids = undefined
const data = await PurchaseOrderNoDetailApi.getReceiveGoodDetail(queryParams)
list.value = data.list
list.value.forEach(item=>{
item.isSelected=false
if (item.receivingStatus!=3){
item.arriveTime=null
}
})
total.value = data.total
} finally {
loading.value = false
}
}
const updateFrom = async (row) => {
await PurchaseOrderNoDetailApi.updateFrom(row)
loading.value = true;
message.success("修改成功");
getList(); // 确保刷新完成
emit('success');
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 导出按钮操作 */
const handleExportDetail = async () => {
try {
const list = multipleSelection.value|| []; // 安全获取数据
// 1. 检查空数据
if (!list || list.length==null||list.length==0) {
message.error("采购订单信息未选择,请确认");
return;
}
// 导出的二次确认
await message.exportConfirm()
const ids = list.map(item => item.id).join(',');
queryParams.ids=ids
loading.value = true;
// 收集选中的ID
const baseUrl = import.meta.env.VITE_BASE_URL;
// 使用axios直接请求文件流
const response = await axios({
url: baseUrl+'/admin-api/heli/purchase-order-no-detail/exportExcel',
method: 'get',
headers: { // 这里应该是headers而不是header
'tenant-id': getTenantId(),
'Authorization': getAccessToken()
},
params: {
ids: queryParams.ids ? queryParams.ids : undefined
},
responseType: 'blob' // 关键指定响应类型为blob
})
// 创建下载链接
const url = window.URL.createObjectURL(new Blob([response.data]))
const link = document.createElement('a')
link.href = url
link.setAttribute('download', '零件采购收货.xlsx') // 设置下载文件名
document.body.appendChild(link)
link.click()
// 清理
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
} catch {
} finally {
loading.value = false;
exportLoading.value = false
queryParams.ids=undefined
}
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
const multipleTableRef: any = ref<InstanceType<typeof ElTable>>()
const multipleSelection: any = ref([])
const handleSelectionChange = (val: PurchaseOrderApi.PurchaseOrderVO[]) => {
// 第一步:重置所有行的 isSelected 为 false
list.value.forEach(row => {
row.isSelected = false;
});
// 第二步:将当前选中行的 isSelected 设为 true
val.forEach(selectedRow => {
// 找到对应行并更新状态(通过唯一标识符匹配更准确)
const targetRow = list.value.find(row => row.id === selectedRow.id);
if (targetRow) {
targetRow.isSelected = true;
}
});
multipleSelection.value = val
}
const receiveGood = async (row) => {
multipleTableRef.value.clearSelection()
multipleTableRef.value.toggleRowSelection(row)
multipleSelection.value.indexOf(row) == -1 && multipleSelection.value.push(row) ;
receiveGoods();
}
const receiveGoods = async () => {
try {
const list = multipleSelection.value|| []; // 安全获取数据
// 1. 检查空数据
if (!list || list.length==null||list.length==0) {
message.error("采购单信息未选择,请确认");
return;
}
for (let i = 0; i < list.length; i++) {
if (list[i].purchaseRemAmounts==null||list[i].purchaseRemAmounts==0){
message.error("零件"+list[i].boomName+"入库数量为空或数量为0,请确认")
return
}
if (list[i].estimatedPrice==null||list[i].estimatedPrice==''){
message.error("零件"+list[i].boomName+"预估总价为空,请确认")
return
}
}
await PurchaseOrderNoDetailApi.verification(list)
const res = await Promise.race([
PurchaseOrderNoDetailApi.receiveGoods(list),
new Promise((_, reject) =>
setTimeout(() => reject(new Error("请求超时")), 30000)
)
]);
loading.value = true;
message.success("收货成功");
getList(); // 确保刷新完成
emit('success');
} catch (error) {
} finally {
loading.value = false;
}
}
const printRef = ref<InstanceType<typeof PrintRef>>()
const isPrint = async () => {
function formatDate(val) {
if (!val) return ''
const date = new Date(val)
return date.toLocaleDateString()
}
try {
const list = multipleSelection.value|| []; // 安全获取数据
if(list.length==0){
message.warning("请选择订单信息");
return;
}
//日期 客户名 模具名 件号 零件名称 材料 规格 数量 单价 总价格 要求日期
//createTime brief projectSubCode blueprintNo boomName compositionName matSpec purchaseAmount unitPrice estimatedPrice requireTime
const data = list?.map((item,idx) => ({
编号:idx + 1,
日期: formatDate(item.createTime),
客户名: item.brief,
模具名: item.projectSubCode,
件号: item.blueprintNo,
零件名称: item.boomName,
材料: item.compositionName,
规格: item.matSpec,
数量: item.purchaseAmount,
单价: item.unitPrice,
总价格: item.estimatedPrice,
要求日期: formatDate(item.requireTime),
})) || [];
console.log(data)
// openPrintDialog(newVar)
printRef.value?.open(data,"")
} finally {
}
}
/** 初始化 **/
const route = useRoute()
const routeValue = ref('')
onMounted(async () => {
const newVar = await UserApi.isAdministrator();
if (newVar==false){
isReadOnly.value=true
}
console.log(newVar)
getList()
})
</script>
<style>
.selected-row {
background-color: #ffe6cc !important;
}
</style>