|
|
|
|
|
<template>
|
|
|
|
|
|
<div class="p-2" v-loading="pageLoading">
|
|
|
|
|
|
<approvalButton
|
|
|
|
|
|
class="mb-4"
|
|
|
|
|
|
@submitForm="submitForm"
|
|
|
|
|
|
@approvalVerifyOpen="approvalVerifyOpen"
|
|
|
|
|
|
@handleApprovalRecord="handleApprovalRecord"
|
|
|
|
|
|
:buttonLoading="buttonLoading"
|
|
|
|
|
|
:id="form.projectPurchaseId as any"
|
|
|
|
|
|
:status="form.flowStatus as any"
|
|
|
|
|
|
:pageType="pageType"
|
|
|
|
|
|
:mode="false"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<el-card shadow="never" class="mb-4">
|
|
|
|
|
|
<el-form ref="projectPurchaseFormRef" :model="form" :rules="rules" label-width="120px" :disabled="isReadOnly">
|
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="项目号" prop="projectCode">
|
|
|
|
|
|
<el-input v-model="form.projectCode" placeholder="请选择项目" readonly>
|
|
|
|
|
|
<template #append>
|
|
|
|
|
|
<el-button icon="Search" @click="openProjectSelect" :disabled="isReadOnly">选择</el-button>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-input>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="采购编号" prop="purchaseCode">
|
|
|
|
|
|
<el-input v-model="form.purchaseCode" placeholder="自动生成" disabled />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="项目名称" prop="projectName">
|
|
|
|
|
|
<el-input v-model="form.projectName" placeholder="请选择项目后自动填充" disabled />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="项目经理" prop="managerId">
|
|
|
|
|
|
<el-select v-model="form.managerId" placeholder="请选择项目后自动填充" disabled>
|
|
|
|
|
|
<el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="部门负责人" prop="chargeId">
|
|
|
|
|
|
<el-select v-model="form.chargeId" placeholder="请选择项目后自动填充" disabled>
|
|
|
|
|
|
<el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="分管副总" prop="deputyId">
|
|
|
|
|
|
<el-select v-model="form.deputyId" placeholder="请选择项目后自动填充" disabled>
|
|
|
|
|
|
<el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="提报人" prop="reporterId">
|
|
|
|
|
|
<el-input v-model="reporterName" placeholder="当前登录用户" disabled />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="收货人" prop="consigneeUser">
|
|
|
|
|
|
<el-select v-model="form.consigneeUser" placeholder="请选择收货人" clearable filterable :disabled="isReadOnly">
|
|
|
|
|
|
<el-option v-for="user in userList" :key="user.nickName" :label="user.nickName" :value="user.nickName" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="收货地址" prop="consigneeAddress">
|
|
|
|
|
|
<el-input type="textarea" v-model="form.consigneeAddress" placeholder="请输入收货地址" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="联系方式" prop="consigneeContact">
|
|
|
|
|
|
<el-input v-model="form.consigneeContact" placeholder="请输入收货人联系方式" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="是否备件类" prop="spareFlag">
|
|
|
|
|
|
<el-radio-group v-model="form.spareFlag" disabled>
|
|
|
|
|
|
<el-radio v-for="dict in spare_flag" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
|
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="24">
|
|
|
|
|
|
<el-form-item label="项目采购状态" prop="projectPurchaseStatus">
|
|
|
|
|
|
<el-radio-group v-model="form.projectPurchaseStatus" disabled>
|
|
|
|
|
|
<el-radio v-for="dict in project_purchase_status" :key="dict.value" :label="dict.value">{{ dict.label }} </el-radio>
|
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="24">
|
|
|
|
|
|
<el-form-item label="备注" prop="remark">
|
|
|
|
|
|
<el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入备注" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
|
|
<el-card shadow="never" class="mb-4">
|
|
|
|
|
|
<template #header>
|
|
|
|
|
|
<div class="flex items-center">
|
|
|
|
|
|
<el-button type="primary" icon="Plus" @click="handleAddMaterial(true)" :disabled="disableMaterialActions" v-if="!isReadOnly" class="mr-2">
|
|
|
|
|
|
添加标准物料
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<el-table v-loading="materialLoading" :data="standardMaterialList" border :row-class-name="getRowClassName">
|
|
|
|
|
|
<el-table-column label="采购物料名称" prop="materialName" min-width="160" show-overflow-tooltip />
|
|
|
|
|
|
<el-table-column label="采购物料编码" prop="materialCode" min-width="140" show-overflow-tooltip />
|
|
|
|
|
|
<el-table-column label="规格参数" prop="specificationDescription" min-width="160" show-overflow-tooltip />
|
|
|
|
|
|
<el-table-column label="计划标识" prop="purchasePlanFlag" width="100">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<dict-tag :options="purchase_plan_flag" :value="scope.row.purchasePlanFlag" />
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column label="需采购数量" prop="needPurchaseAmount" width="120" />
|
|
|
|
|
|
<el-table-column label="本次采购数量" prop="purchaseAmount" width="140" />
|
|
|
|
|
|
<el-table-column label="需求到货时间" prop="arrivalTime" width="180">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<span>{{ proxy?.parseTime?.(scope.row.arrivalTime, '{y}-{m}-{d} {h}:{i}') || scope.row.arrivalTime }}</span>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column label="备注" prop="remark" min-width="160" show-overflow-tooltip />
|
|
|
|
|
|
<el-table-column label="操作" fixed="right" width="160" align="center" v-if="!isReadOnly">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<el-button link type="primary" icon="Edit" @click="handleEditMaterial(scope.row)">编辑</el-button>
|
|
|
|
|
|
<el-button link type="danger" icon="Delete" @click="handleDeleteMaterial(scope.row)">删除</el-button>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
|
|
<el-card shadow="never">
|
|
|
|
|
|
<template #header>
|
|
|
|
|
|
<div class="flex items-center">
|
|
|
|
|
|
<el-button type="primary" icon="Plus" @click="handleAddMaterial(false)" :disabled="disableMaterialActions" v-if="!isReadOnly" class="mr-2">
|
|
|
|
|
|
添加非标准物料
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<el-table v-loading="materialLoading" :data="nonStandardMaterialList" border :row-class-name="getRowClassName">
|
|
|
|
|
|
<el-table-column label="采购物料名称" prop="materialName" min-width="160" show-overflow-tooltip />
|
|
|
|
|
|
<el-table-column label="采购物料编码" prop="materialCode" min-width="140" show-overflow-tooltip />
|
|
|
|
|
|
<el-table-column label="规格参数" prop="specificationDescription" min-width="160" show-overflow-tooltip />
|
|
|
|
|
|
<el-table-column label="计划标识" prop="purchasePlanFlag" width="100">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<dict-tag :options="purchase_plan_flag" :value="scope.row.purchasePlanFlag" />
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column label="需采购数量" prop="needPurchaseAmount" width="120" />
|
|
|
|
|
|
<el-table-column label="本次采购数量" prop="purchaseAmount" width="140" />
|
|
|
|
|
|
<el-table-column label="需求到货时间" prop="arrivalTime" width="180">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<span>{{ proxy?.parseTime?.(scope.row.arrivalTime, '{y}-{m}-{d} {h}:{i}') || scope.row.arrivalTime }}</span>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column label="备注" prop="remark" min-width="160" show-overflow-tooltip />
|
|
|
|
|
|
<el-table-column label="操作" fixed="right" width="160" align="center" v-if="!isReadOnly">
|
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
|
<el-button link type="primary" icon="Edit" @click="handleEditMaterial(scope.row)">编辑</el-button>
|
|
|
|
|
|
<el-button link type="danger" icon="Delete" @click="handleDeleteMaterial(scope.row)">删除</el-button>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
|
|
<el-dialog :title="materialDialog.title" v-model="materialDialog.visible" width="800px" append-to-body>
|
|
|
|
|
|
<el-form ref="materialFormRef" :model="materialForm" :rules="materialRules" label-width="120px">
|
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="计划标识" prop="purchasePlanFlag">
|
|
|
|
|
|
<el-radio-group v-model="materialForm.purchasePlanFlag">
|
|
|
|
|
|
<el-radio v-for="dict in purchase_plan_flag" :key="dict.value" :label="dict.value">{{ dict.label }} </el-radio>
|
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<!-- <el-col :span="12">-->
|
|
|
|
|
|
<!-- <el-form-item label="标准物料" prop="materialFlag">-->
|
|
|
|
|
|
<!-- <el-radio-group v-model="materialForm.materialFlag">-->
|
|
|
|
|
|
<!-- <el-radio v-for="dict in material_flag" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>-->
|
|
|
|
|
|
<!-- </el-radio-group>-->
|
|
|
|
|
|
<!-- </el-form-item>-->
|
|
|
|
|
|
<!-- </el-col>-->
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="采购物料名称" prop="materialName">
|
|
|
|
|
|
<el-input v-model="materialForm.materialName" placeholder="请输入采购物料名称" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="采购物料编码" prop="materialCode">
|
|
|
|
|
|
<el-input v-model="materialForm.materialCode" placeholder="请输入采购物料编码" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<!-- <el-col :span="12">-->
|
|
|
|
|
|
<!-- <el-form-item label="物料ID" prop="materialId">-->
|
|
|
|
|
|
<!-- <el-input v-model="materialForm.materialId" placeholder="请输入物料ID" />-->
|
|
|
|
|
|
<!-- </el-form-item>-->
|
|
|
|
|
|
<!-- </el-col>-->
|
|
|
|
|
|
<!-- <el-col :span="12">-->
|
|
|
|
|
|
<!-- <el-form-item label="销售物料ID" prop="relationMaterialId">-->
|
|
|
|
|
|
<!-- <el-input v-model="materialForm.relationMaterialId" placeholder="请输入销售物料ID" />-->
|
|
|
|
|
|
<!-- </el-form-item>-->
|
|
|
|
|
|
<!-- </el-col>-->
|
|
|
|
|
|
<el-col :span="24">
|
|
|
|
|
|
<el-form-item label="详细参数" prop="specificationDescription">
|
|
|
|
|
|
<el-input v-model="materialForm.specificationDescription" placeholder="请输入详细参数" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="单位" prop="unitId">
|
|
|
|
|
|
<el-select v-model="materialForm.unitId" placeholder="请选择单位" clearable filterable>
|
|
|
|
|
|
<el-option v-for="item in unitInfoList" :key="item.unitId" :label="item.unitName" :value="item.unitId" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="需采购数量" prop="needPurchaseAmount">
|
|
|
|
|
|
<el-input-number v-model="materialForm.needPurchaseAmount" :min="0" :controls="false" class="w-full" placeholder="请输入数量" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="本次采购数量" prop="purchaseAmount">
|
|
|
|
|
|
<el-input-number v-model="materialForm.purchaseAmount" :min="0" :controls="false" class="w-full" placeholder="请输入数量" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="需求到货时间" prop="arrivalTime">
|
|
|
|
|
|
<el-date-picker
|
|
|
|
|
|
v-model="materialForm.arrivalTime"
|
|
|
|
|
|
type="datetime"
|
|
|
|
|
|
value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
|
|
|
placeholder="请选择需求到货时间"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="24">
|
|
|
|
|
|
<el-form-item label="备注" prop="remark">
|
|
|
|
|
|
<el-input v-model="materialForm.remark" type="textarea" :rows="3" placeholder="请输入备注" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
<template #footer>
|
|
|
|
|
|
<div class="dialog-footer">
|
|
|
|
|
|
<el-button type="primary" :loading="materialLoading" @click="submitMaterialForm">确 定</el-button>
|
|
|
|
|
|
<el-button @click="materialDialog.visible = false">取 消</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
|
|
|
|
<submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
|
|
|
|
|
|
<approvalRecord ref="approvalRecordRef" />
|
|
|
|
|
|
<ProjectSelect ref="projectSelectRef" :multiple="false" @confirm-call-back="projectInfoSelectCallBack" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup name="ProjectPurchaseEdit" lang="ts">
|
|
|
|
|
|
import { computed, reactive, ref, watch, getCurrentInstance, toRefs, onMounted, nextTick } from 'vue';
|
|
|
|
|
|
import type { ComponentInternalInstance } from 'vue';
|
|
|
|
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
|
|
|
import type { FormInstance } from 'element-plus';
|
|
|
|
|
|
import { addProjectPurchase, getProjectPurchase, updateProjectPurchase, projectPurchaseSubmitAndFlowStart } from '@/api/oa/erp/projectPurchase';
|
|
|
|
|
|
import type { ProjectPurchaseForm } from '@/api/oa/erp/projectPurchase/types';
|
|
|
|
|
|
import { getErpProjectPurchaseMaterialList } from '@/api/oa/erp/projectPurchaseMaterial';
|
|
|
|
|
|
import type { ProjectPurchaseMaterialVO, ProjectPurchaseMaterialForm } from '@/api/oa/erp/projectPurchaseMaterial/types';
|
|
|
|
|
|
import SubmitVerify from '@/components/Process/submitVerify.vue';
|
|
|
|
|
|
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
|
|
|
|
|
|
import ApprovalButton from '@/components/Process/approvalButton.vue';
|
|
|
|
|
|
import ProjectSelect from '@/components/ProjectSelect/index.vue';
|
|
|
|
|
|
import { FlowCodeEnum } from '@/enums/OAEnum';
|
|
|
|
|
|
import type { ProjectInfoVO } from '@/api/oa/erp/projectInfo/types';
|
|
|
|
|
|
import { listUser } from '@/api/system/user';
|
|
|
|
|
|
import type { UserVO, UserQuery } from '@/api/system/user/types';
|
|
|
|
|
|
import { useUserStore } from '@/store/modules/user';
|
|
|
|
|
|
import { getBaseUnitInfoList } from '@/api/oa/base/unitInfo';
|
|
|
|
|
|
|
|
|
|
|
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
const route = useRoute();
|
|
|
|
|
|
const userStore = useUserStore();
|
|
|
|
|
|
|
|
|
|
|
|
const { active_flag, project_purchase_status, spare_flag, purchase_plan_flag, material_flag } = toRefs<any>(
|
|
|
|
|
|
proxy?.useDict('active_flag', 'project_purchase_status', 'spare_flag', 'purchase_plan_flag', 'material_flag')
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const routeParams = reactive<Record<string, any>>({});
|
|
|
|
|
|
const pageType = ref<string>((route.query.type as string) || 'add');
|
|
|
|
|
|
const isReadOnly = computed(() => pageType.value === 'view' || pageType.value === 'approval');
|
|
|
|
|
|
|
|
|
|
|
|
const pageLoading = ref(false);
|
|
|
|
|
|
const buttonLoading = ref(false);
|
|
|
|
|
|
const projectPurchaseFormRef = ref<FormInstance>();
|
|
|
|
|
|
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
|
|
|
|
|
|
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
|
|
|
|
|
|
const projectSelectRef = ref<InstanceType<typeof ProjectSelect>>();
|
|
|
|
|
|
const taskVariables = ref<Record<string, any>>({});
|
|
|
|
|
|
|
|
|
|
|
|
const initFormData: ProjectPurchaseForm & { projectName?: string } = {
|
|
|
|
|
|
projectPurchaseId: undefined,
|
|
|
|
|
|
projectId: undefined,
|
|
|
|
|
|
projectCode: undefined,
|
|
|
|
|
|
purchaseCode: undefined,
|
|
|
|
|
|
projectName: undefined,
|
|
|
|
|
|
managerId: undefined,
|
|
|
|
|
|
chargeId: undefined,
|
|
|
|
|
|
deputyId: undefined,
|
|
|
|
|
|
reporterId: undefined,
|
|
|
|
|
|
consigneeUser: undefined,
|
|
|
|
|
|
consigneeAddress: undefined,
|
|
|
|
|
|
consigneeContact: undefined,
|
|
|
|
|
|
projectPurchaseStatus: undefined,
|
|
|
|
|
|
flowStatus: undefined,
|
|
|
|
|
|
sortOrder: undefined,
|
|
|
|
|
|
relationId: undefined,
|
|
|
|
|
|
remark: undefined,
|
|
|
|
|
|
spareFlag: undefined,
|
|
|
|
|
|
activeFlag: undefined
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const form = ref<ProjectPurchaseForm & { projectName?: string }>({ ...initFormData });
|
|
|
|
|
|
|
|
|
|
|
|
const rules = {
|
|
|
|
|
|
projectCode: [{ required: true, message: '项目号不能为空', trigger: 'blur' }],
|
|
|
|
|
|
consigneeUser: [{ required: true, message: '收货人不能为空', trigger: 'blur' }],
|
|
|
|
|
|
consigneeAddress: [{ required: true, message: '收货地址不能为空', trigger: 'blur' }]
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const materialList = ref<ProjectPurchaseMaterialVO[]>([]);
|
|
|
|
|
|
const materialLoading = ref(false);
|
|
|
|
|
|
const disableMaterialActions = computed(() => isReadOnly.value || materialLoading.value);
|
|
|
|
|
|
|
|
|
|
|
|
// 标准物料列表(materialFlag 为 '1')
|
|
|
|
|
|
// 标准物料(materialFlag = 1)
|
|
|
|
|
|
const standardMaterialList = computed(() => {
|
|
|
|
|
|
return materialList.value.filter((item) => item.materialFlag === '1');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 非标准物料列表(materialFlag 为 '2')
|
|
|
|
|
|
const nonStandardMaterialList = computed(() => {
|
|
|
|
|
|
return materialList.value.filter((item) => item.materialFlag === '2');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 获取行类名,计划外的行显示黄色背景
|
|
|
|
|
|
const getRowClassName = ({ row }: { row: ProjectPurchaseMaterialVO }) => {
|
|
|
|
|
|
// 计划外通常是 '2' 或 '否',根据实际字典值调整
|
|
|
|
|
|
if (row.purchasePlanFlag === '2' || row.purchasePlanFlag === '否' || row.purchasePlanFlag === '计划外') {
|
|
|
|
|
|
return 'plan-out-row';
|
|
|
|
|
|
}
|
|
|
|
|
|
return '';
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 用户列表
|
|
|
|
|
|
const userList = ref<UserVO[]>([]);
|
|
|
|
|
|
const getUserList = async () => {
|
|
|
|
|
|
const params: UserQuery = { pageNum: 1, pageSize: 9999 };
|
|
|
|
|
|
const res = await listUser(params);
|
|
|
|
|
|
userList.value = res.rows || [];
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 单位列表
|
|
|
|
|
|
const unitInfoList = ref<any[]>([]);
|
|
|
|
|
|
const getUnitInfoListSelect = async () => {
|
|
|
|
|
|
const res = await getBaseUnitInfoList(null);
|
|
|
|
|
|
unitInfoList.value = res.data || [];
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 提报人名称(当前登录用户)
|
|
|
|
|
|
const reporterName = computed(() => {
|
|
|
|
|
|
return userStore.nickname || '';
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const materialDialog = reactive({
|
|
|
|
|
|
visible: false,
|
|
|
|
|
|
title: ''
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const materialFormRef = ref<FormInstance>();
|
|
|
|
|
|
const initMaterialFormData: ProjectPurchaseMaterialForm = {
|
|
|
|
|
|
purchaseMaterialId: undefined,
|
|
|
|
|
|
projectPurchaseId: undefined,
|
|
|
|
|
|
relationDetailsId: undefined,
|
|
|
|
|
|
spareFlag: undefined,
|
|
|
|
|
|
purchasePlanFlag: undefined,
|
|
|
|
|
|
materialFlag: undefined,
|
|
|
|
|
|
materialId: undefined,
|
|
|
|
|
|
relationMaterialId: undefined,
|
|
|
|
|
|
materialCode: undefined,
|
|
|
|
|
|
materialName: undefined,
|
|
|
|
|
|
specificationDescription: undefined,
|
|
|
|
|
|
unitId: undefined,
|
|
|
|
|
|
needPurchaseAmount: undefined,
|
|
|
|
|
|
purchaseAmount: undefined,
|
|
|
|
|
|
arrivalTime: undefined,
|
|
|
|
|
|
serialNumber: undefined,
|
|
|
|
|
|
remark: undefined,
|
|
|
|
|
|
activeFlag: undefined
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const materialForm = ref<ProjectPurchaseMaterialForm>({ ...initMaterialFormData });
|
|
|
|
|
|
|
|
|
|
|
|
const materialRules = {
|
|
|
|
|
|
materialName: [{ required: true, message: '采购物料名称不能为空', trigger: 'blur' }],
|
|
|
|
|
|
purchaseAmount: [{ required: true, message: '采购数量不能为空', trigger: 'blur' }]
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 重置主表表单
|
|
|
|
|
|
*/
|
|
|
|
|
|
const resetForm = () => {
|
|
|
|
|
|
Object.assign(form.value, initFormData);
|
|
|
|
|
|
form.value.projectPurchaseStatus = '1';
|
|
|
|
|
|
form.value.flowStatus = 'draft';
|
|
|
|
|
|
// 自动填充当前登录用户为提报人
|
|
|
|
|
|
if (userStore.userId) {
|
|
|
|
|
|
form.value.reporterId = userStore.userId;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!form.value.activeFlag && active_flag.value?.length) {
|
|
|
|
|
|
form.value.activeFlag = active_flag.value[0].value;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 重置物料表单
|
|
|
|
|
|
*/
|
|
|
|
|
|
const resetMaterialForm = () => {
|
|
|
|
|
|
Object.assign(materialForm.value, initMaterialFormData);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 根据项目采购ID加载详情
|
|
|
|
|
|
*/
|
|
|
|
|
|
const loadDetail = async (projectPurchaseId: string | number) => {
|
|
|
|
|
|
if (!projectPurchaseId) {
|
|
|
|
|
|
resetForm();
|
|
|
|
|
|
materialList.value = [];
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
pageLoading.value = true;
|
|
|
|
|
|
try {
|
|
|
|
|
|
resetForm();
|
|
|
|
|
|
const res = await getProjectPurchase(projectPurchaseId);
|
|
|
|
|
|
Object.assign(form.value, res?.data || {});
|
|
|
|
|
|
if (!form.value.projectPurchaseStatus) {
|
|
|
|
|
|
form.value.projectPurchaseStatus = '1';
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!form.value.flowStatus) {
|
|
|
|
|
|
form.value.flowStatus = 'draft';
|
|
|
|
|
|
}
|
|
|
|
|
|
// 确保用户列表已加载,然后根据收货人名称查找对应的用户ID
|
|
|
|
|
|
if (userList.value.length === 0) {
|
|
|
|
|
|
await getUserList();
|
|
|
|
|
|
}
|
|
|
|
|
|
await loadMaterials();
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
pageLoading.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 加载物料列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
const loadMaterials = async () => {
|
|
|
|
|
|
if (!form.value.projectPurchaseId) {
|
|
|
|
|
|
materialList.value = [];
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
materialLoading.value = true;
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await getErpProjectPurchaseMaterialList({ projectPurchaseId: form.value.projectPurchaseId });
|
|
|
|
|
|
materialList.value = res?.data || [];
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
materialLoading.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 提交主表单
|
|
|
|
|
|
* @param status 提交状态(draft or submit)
|
|
|
|
|
|
*/
|
|
|
|
|
|
const submitForm = async (status: string, mode?: boolean) => {
|
|
|
|
|
|
if (!projectPurchaseFormRef.value) return;
|
|
|
|
|
|
try {
|
|
|
|
|
|
await projectPurchaseFormRef.value.validate();
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
buttonLoading.value = true;
|
|
|
|
|
|
try {
|
|
|
|
|
|
const payload: ProjectPurchaseForm & {
|
|
|
|
|
|
projectName?: string;
|
|
|
|
|
|
purchaseMaterialList?: ProjectPurchaseMaterialForm[];
|
|
|
|
|
|
} = {
|
|
|
|
|
|
...form.value,
|
|
|
|
|
|
purchaseMaterialList: materialList.value.map((item) => ({
|
|
|
|
|
|
...item,
|
|
|
|
|
|
projectPurchaseId: form.value.projectPurchaseId
|
|
|
|
|
|
}))
|
|
|
|
|
|
};
|
|
|
|
|
|
if (status !== 'draft') {
|
|
|
|
|
|
payload.flowCode = FlowCodeEnum.PROJECT_PURCHASE_CODE;
|
|
|
|
|
|
payload.variables = {
|
|
|
|
|
|
projectPurchaseId: payload.projectPurchaseId,
|
|
|
|
|
|
projectCode: payload.projectCode,
|
|
|
|
|
|
projectName: payload.projectName
|
|
|
|
|
|
};
|
|
|
|
|
|
payload.bizExt = {
|
|
|
|
|
|
businessTitle: '项目采购审批',
|
|
|
|
|
|
businessCode: payload.projectCode
|
|
|
|
|
|
};
|
|
|
|
|
|
payload.projectPurchaseStatus = '2';
|
|
|
|
|
|
payload.flowStatus = 'waiting';
|
|
|
|
|
|
const res: any = await projectPurchaseSubmitAndFlowStart(payload);
|
|
|
|
|
|
if (res?.data) {
|
|
|
|
|
|
Object.assign(form.value, res.data);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Object.assign(form.value, payload);
|
|
|
|
|
|
}
|
|
|
|
|
|
proxy?.$modal.msgSuccess('操作成功');
|
|
|
|
|
|
proxy?.$tab.closePage();
|
|
|
|
|
|
router.go(-1);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
payload.projectPurchaseStatus = '1';
|
|
|
|
|
|
payload.flowStatus = 'draft';
|
|
|
|
|
|
if (payload.projectPurchaseId) {
|
|
|
|
|
|
await updateProjectPurchase(payload);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
const res: any = await addProjectPurchase(payload);
|
|
|
|
|
|
const newId = res?.data?.projectPurchaseId ?? res?.data ?? res?.msg;
|
|
|
|
|
|
if (newId) {
|
|
|
|
|
|
payload.projectPurchaseId = newId;
|
|
|
|
|
|
form.value.projectPurchaseId = newId as any;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Object.assign(form.value, payload);
|
|
|
|
|
|
proxy?.$modal.msgSuccess('暂存成功');
|
|
|
|
|
|
proxy?.$tab.closePage();
|
|
|
|
|
|
router.go(-1);
|
|
|
|
|
|
}
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
buttonLoading.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 打开新增物料弹窗
|
|
|
|
|
|
* @param isStandard 是否标准物料
|
|
|
|
|
|
*/
|
|
|
|
|
|
const handleAddMaterial = (isStandard: boolean) => {
|
|
|
|
|
|
if (isReadOnly.value) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
resetMaterialForm();
|
|
|
|
|
|
materialForm.value.purchasePlanFlag = materialForm.value.purchasePlanFlag || (purchase_plan_flag.value?.[0]?.value ?? undefined);
|
|
|
|
|
|
// 根据 isStandard 设置 materialFlag
|
|
|
|
|
|
if (isStandard) {
|
|
|
|
|
|
materialForm.value.materialFlag = '1'; // 标准物料
|
|
|
|
|
|
materialDialog.title = '添加标准物料';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
materialForm.value.materialFlag = '2'; // 非标准物料
|
|
|
|
|
|
materialDialog.title = '添加非标准物料';
|
|
|
|
|
|
}
|
|
|
|
|
|
materialForm.value.spareFlag = materialForm.value.spareFlag || (spare_flag.value?.[0]?.value ?? undefined);
|
|
|
|
|
|
materialForm.value.activeFlag = materialForm.value.activeFlag || (active_flag.value?.[0]?.value ?? undefined);
|
|
|
|
|
|
materialDialog.visible = true;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 编辑物料
|
|
|
|
|
|
*/
|
|
|
|
|
|
const handleEditMaterial = (row: ProjectPurchaseMaterialVO) => {
|
|
|
|
|
|
if (isReadOnly.value) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
resetMaterialForm();
|
|
|
|
|
|
Object.assign(materialForm.value, row);
|
|
|
|
|
|
materialDialog.title = '编辑物料';
|
|
|
|
|
|
materialDialog.visible = true;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 提交物料表单(仅操作本地列表)
|
|
|
|
|
|
*/
|
|
|
|
|
|
const submitMaterialForm = () => {
|
|
|
|
|
|
if (isReadOnly.value) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
materialFormRef.value?.validate((valid: boolean) => {
|
|
|
|
|
|
if (!valid) return;
|
|
|
|
|
|
if (materialForm.value.purchaseMaterialId) {
|
|
|
|
|
|
// 编辑:更新列表中的物料
|
|
|
|
|
|
const index = materialList.value.findIndex((item) => item.purchaseMaterialId === materialForm.value.purchaseMaterialId);
|
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
|
Object.assign(materialList.value[index], materialForm.value);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 新增:添加到列表
|
|
|
|
|
|
materialList.value.push({ ...materialForm.value } as ProjectPurchaseMaterialVO);
|
|
|
|
|
|
}
|
|
|
|
|
|
proxy?.$modal.msgSuccess('操作成功');
|
|
|
|
|
|
materialDialog.visible = false;
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 删除物料(仅操作本地列表)
|
|
|
|
|
|
*/
|
|
|
|
|
|
const handleDeleteMaterial = async (row: ProjectPurchaseMaterialVO) => {
|
|
|
|
|
|
if (isReadOnly.value) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
await proxy?.$modal.confirm(`是否确认删除物料"${row.materialName}"?`);
|
|
|
|
|
|
const index = materialList.value.findIndex(
|
|
|
|
|
|
(item) => (row.purchaseMaterialId && item.purchaseMaterialId === row.purchaseMaterialId) || (!row.purchaseMaterialId && item === row)
|
|
|
|
|
|
);
|
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
|
materialList.value.splice(index, 1);
|
|
|
|
|
|
proxy?.$modal.msgSuccess('删除成功');
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 打开审批弹窗
|
|
|
|
|
|
*/
|
|
|
|
|
|
const approvalVerifyOpen = async () => {
|
|
|
|
|
|
taskVariables.value = {
|
|
|
|
|
|
projectPurchaseId: form.value.projectPurchaseId,
|
|
|
|
|
|
projectCode: form.value.projectCode,
|
|
|
|
|
|
projectName: form.value.projectName
|
|
|
|
|
|
};
|
|
|
|
|
|
const taskId = (routeParams.taskId as string) || (route.query.taskId as string);
|
|
|
|
|
|
if (taskId) {
|
|
|
|
|
|
await submitVerifyRef.value?.openDialog(taskId);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 查看审批记录
|
|
|
|
|
|
*/
|
|
|
|
|
|
const handleApprovalRecord = () => {
|
|
|
|
|
|
if (form.value.projectPurchaseId) {
|
|
|
|
|
|
approvalRecordRef.value?.init(form.value.projectPurchaseId);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 提交审批后的回调
|
|
|
|
|
|
*/
|
|
|
|
|
|
const submitCallback = async () => {
|
|
|
|
|
|
await proxy?.$tab.closePage(route);
|
|
|
|
|
|
router.go(-1);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 打开项目选择框
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 打开项目选择弹窗
|
|
|
|
|
|
*/
|
|
|
|
|
|
const openProjectSelect = () => {
|
|
|
|
|
|
if (isReadOnly.value) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
projectSelectRef.value?.open();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 项目选择回调,自动填充项目相关信息
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 项目选择回调
|
|
|
|
|
|
*/
|
|
|
|
|
|
const projectInfoSelectCallBack = (data: ProjectInfoVO[]) => {
|
|
|
|
|
|
if (data && data.length > 0) {
|
|
|
|
|
|
const project = data[0];
|
|
|
|
|
|
form.value.projectId = project.projectId;
|
|
|
|
|
|
form.value.projectCode = project.projectCode;
|
|
|
|
|
|
form.value.projectName = project.projectName;
|
|
|
|
|
|
form.value.managerId = project.managerId;
|
|
|
|
|
|
form.value.chargeId = project.chargeId;
|
|
|
|
|
|
form.value.deputyId = project.deputyId;
|
|
|
|
|
|
form.value.spareFlag = project.spareFlag;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化调用
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 初始化下拉数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
const loadSelectOptions = () => {
|
|
|
|
|
|
getUserList();
|
|
|
|
|
|
getUnitInfoListSelect();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
nextTick(async () => {
|
|
|
|
|
|
// 获取路由参数
|
|
|
|
|
|
Object.assign(routeParams, route.query);
|
|
|
|
|
|
loadSelectOptions();
|
|
|
|
|
|
const id = routeParams.id as string | number;
|
|
|
|
|
|
const type = routeParams.type as string;
|
|
|
|
|
|
pageType.value = type || 'add';
|
|
|
|
|
|
|
|
|
|
|
|
if (id && (type === 'update' || type === 'view' || type === 'approval')) {
|
|
|
|
|
|
pageLoading.value = true;
|
|
|
|
|
|
try {
|
|
|
|
|
|
await loadDetail(id);
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
pageLoading.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
resetForm();
|
|
|
|
|
|
materialList.value = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
:deep(.plan-out-row) {
|
|
|
|
|
|
background-color: #fffbe6 !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.plan-out-row:hover) {
|
|
|
|
|
|
background-color: #fff8d1 !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|