1.0.36 采购审批流程

dev
yinq 1 month ago
parent 2482fbb29f
commit 231bfead58

@ -157,6 +157,11 @@ export interface ProjectPurchaseForm extends BaseEntity {
*/ */
deputyId?: string | number; deputyId?: string | number;
/**
* ID
*/
deptId?: string | number;
/** /**
* *
*/ */

@ -148,6 +148,21 @@ export interface ProjectPurchaseMaterialForm extends BaseEntity {
*/ */
relationMaterialId?: string | number; relationMaterialId?: string | number;
/**
*
*/
relationMaterialCode?: string;
/**
*
*/
relationMaterialName?: string;
/**
*
*/
purchaseMaterialName?: string;
/** /**
* *
*/ */

@ -18,8 +18,10 @@
<el-col :span="12"> <el-col :span="12">
<el-form-item label="项目号" prop="projectCode"> <el-form-item label="项目号" prop="projectCode">
<el-input v-model="form.projectCode" placeholder="请选择项目" readonly> <el-input v-model="form.projectCode" placeholder="请选择项目" readonly>
<template #append> <template #suffix>
<el-button icon="Search" @click="openProjectSelect" :disabled="isReadOnly">选择</el-button> <el-icon style="cursor: pointer" @click="openProjectSelect" :disabled="isReadOnly">
<Search />
</el-icon>
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
@ -130,7 +132,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="备注" prop="remark" min-width="160" show-overflow-tooltip align="center" /> <el-table-column label="备注" prop="remark" min-width="160" show-overflow-tooltip align="center" />
<el-table-column label="操作" fixed="right" width="150" align="center" v-if="!isReadOnly"> <el-table-column label="操作" fixed="right" width="150" align="center" v-if="canEditMaterial">
<template #default="scope"> <template #default="scope">
<el-button link type="warning" @click="splitMaterial(scope.row)"></el-button> <el-button link type="warning" @click="splitMaterial(scope.row)"></el-button>
<el-button link type="primary" @click="handleEditMaterial(scope.row)"></el-button> <el-button link type="primary" @click="handleEditMaterial(scope.row)"></el-button>
@ -173,7 +175,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="备注" prop="remark" min-width="160" show-overflow-tooltip align="center" /> <el-table-column label="备注" prop="remark" min-width="160" show-overflow-tooltip align="center" />
<el-table-column label="操作" fixed="right" width="150" align="center" v-if="!isReadOnly"> <el-table-column label="操作" fixed="right" width="150" align="center" v-if="canEditMaterial">
<template #default="scope"> <template #default="scope">
<el-button link type="warning" @click="splitMaterial(scope.row)"></el-button> <el-button link type="warning" @click="splitMaterial(scope.row)"></el-button>
<el-button link type="primary" @click="handleEditMaterial(scope.row)"></el-button> <el-button link type="primary" @click="handleEditMaterial(scope.row)"></el-button>
@ -249,23 +251,12 @@
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="本次采购数量" prop="purchaseAmount"> <el-form-item label="本次采购数量" prop="purchaseAmount">
<el-input-number <el-input-number v-model="materialForm.purchaseAmount" :min="0" class="w-full" placeholder="请输入数量" :precision="2" />
v-model="materialForm.purchaseAmount"
:min="0"
class="w-full"
placeholder="请输入数量"
:precision="2"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="需求到货时间" prop="arrivalTime"> <el-form-item label="需求到货时间" prop="arrivalTime">
<el-date-picker <el-date-picker v-model="materialForm.arrivalTime" type="date" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择需求到货时间" />
v-model="materialForm.arrivalTime"
type="date"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择需求到货时间"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24"> <el-col :span="24">
@ -299,7 +290,13 @@ import { computed, reactive, ref, watch, getCurrentInstance, toRefs, onMounted,
import type { ComponentInternalInstance } from 'vue'; import type { ComponentInternalInstance } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import type { FormInstance } from 'element-plus'; import type { FormInstance } from 'element-plus';
import { addProjectPurchase, getProjectPurchase, updateProjectPurchase, projectPurchaseSubmitAndFlowStart, getProjectMaterialsByProjectId } from '@/api/oa/erp/projectPurchase'; import {
addProjectPurchase,
getProjectPurchase,
updateProjectPurchase,
projectPurchaseSubmitAndFlowStart,
getProjectMaterialsByProjectId
} from '@/api/oa/erp/projectPurchase';
import type { ProjectPurchaseForm } from '@/api/oa/erp/projectPurchase/types'; import type { ProjectPurchaseForm } from '@/api/oa/erp/projectPurchase/types';
import { getErpProjectPurchaseMaterialList } from '@/api/oa/erp/projectPurchaseMaterial'; import { getErpProjectPurchaseMaterialList } from '@/api/oa/erp/projectPurchaseMaterial';
import type { ProjectPurchaseMaterialVO, ProjectPurchaseMaterialForm } from '@/api/oa/erp/projectPurchaseMaterial/types'; import type { ProjectPurchaseMaterialVO, ProjectPurchaseMaterialForm } from '@/api/oa/erp/projectPurchaseMaterial/types';
@ -313,6 +310,7 @@ import { listUser } from '@/api/system/user';
import type { UserVO, UserQuery } from '@/api/system/user/types'; import type { UserVO, UserQuery } from '@/api/system/user/types';
import { useUserStore } from '@/store/modules/user'; import { useUserStore } from '@/store/modules/user';
import { getBaseUnitInfoList } from '@/api/oa/base/unitInfo'; import { getBaseUnitInfoList } from '@/api/oa/base/unitInfo';
import { getInfo } from '@/api/login';
const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const router = useRouter(); const router = useRouter();
@ -327,6 +325,10 @@ const routeParams = reactive<Record<string, any>>({});
const pageType = ref<string>((route.query.type as string) || 'add'); const pageType = ref<string>((route.query.type as string) || 'add');
const isReadOnly = computed(() => pageType.value === 'view' || pageType.value === 'approval'); const isReadOnly = computed(() => pageType.value === 'view' || pageType.value === 'approval');
const userRoles = ref<string[]>([]);
const hasCgRole = computed(() => userRoles.value?.some((role) => role === 'CGJL'));
const canEditMaterial = computed(() => !isReadOnly.value || hasCgRole.value);
const pageLoading = ref(false); const pageLoading = ref(false);
const buttonLoading = ref(false); const buttonLoading = ref(false);
const projectPurchaseFormRef = ref<FormInstance>(); const projectPurchaseFormRef = ref<FormInstance>();
@ -344,6 +346,7 @@ const initFormData: ProjectPurchaseForm & { projectName?: string } = {
managerId: undefined, managerId: undefined,
chargeId: undefined, chargeId: undefined,
deputyId: undefined, deputyId: undefined,
deptId: undefined,
reporterId: undefined, reporterId: undefined,
consigneeUser: undefined, consigneeUser: undefined,
consigneeAddress: undefined, consigneeAddress: undefined,
@ -367,10 +370,8 @@ const rules = {
const materialList = ref<ProjectPurchaseMaterialVO[]>([]); const materialList = ref<ProjectPurchaseMaterialVO[]>([]);
const materialLoading = ref(false); const materialLoading = ref(false);
const disableMaterialActions = computed(() => isReadOnly.value || materialLoading.value);
// materialFlag '1' // materialFlag '1'
// materialFlag = 1
const standardMaterialList = computed(() => { const standardMaterialList = computed(() => {
return materialList.value.filter((item) => item.materialFlag === '1'); return materialList.value.filter((item) => item.materialFlag === '1');
}); });
@ -380,7 +381,6 @@ const nonStandardMaterialList = computed(() => {
return materialList.value.filter((item) => item.materialFlag === '2'); return materialList.value.filter((item) => item.materialFlag === '2');
}); });
const loadProjectMaterialsFromSource = async (projectId?: string | number, spareFlag?: string) => { const loadProjectMaterialsFromSource = async (projectId?: string | number, spareFlag?: string) => {
if (!projectId || !spareFlag) { if (!projectId || !spareFlag) {
return; return;
@ -435,6 +435,7 @@ const materialDialog = reactive({
}); });
const materialFormRef = ref<FormInstance>(); const materialFormRef = ref<FormInstance>();
const editingMaterialIndex = ref<number>(-1);
const initMaterialFormData: ProjectPurchaseMaterialForm = { const initMaterialFormData: ProjectPurchaseMaterialForm = {
purchaseMaterialId: undefined, purchaseMaterialId: undefined,
projectPurchaseId: undefined, projectPurchaseId: undefined,
@ -484,12 +485,13 @@ const resetForm = () => {
*/ */
const resetMaterialForm = () => { const resetMaterialForm = () => {
Object.assign(materialForm.value, initMaterialFormData); Object.assign(materialForm.value, initMaterialFormData);
editingMaterialIndex.value = -1;
}; };
/** /**
* 根据项目采购ID加载详情 * 根据项目采购ID加载详情
*/ */
const loadDetail = async (projectPurchaseId: string | number) => { const loadDetail = async (projectPurchaseId?: string | number) => {
if (!projectPurchaseId) { if (!projectPurchaseId) {
resetForm(); resetForm();
materialList.value = []; materialList.value = [];
@ -535,41 +537,38 @@ const loadMaterials = async () => {
/** /**
* 提交主表单 * 提交主表单
* @param status 提交状态draft or submit
*/ */
const submitForm = async (status: string, mode?: boolean) => { const buildProjectPurchasePayload = () => {
if (!projectPurchaseFormRef.value) return; if (!projectPurchaseFormRef.value) return;
try {
await projectPurchaseFormRef.value.validate();
} catch (error) {
return;
}
buttonLoading.value = true;
try {
const normalizedMaterials: ProjectPurchaseMaterialForm[] = materialList.value.map((item) => { const normalizedMaterials: ProjectPurchaseMaterialForm[] = materialList.value.map((item) => {
const payloadItem: ProjectPurchaseMaterialForm = { const payloadItem: ProjectPurchaseMaterialForm = {
...item, ...item,
projectPurchaseId: form.value.projectPurchaseId projectPurchaseId: form.value.projectPurchaseId
}; };
if (typeof payloadItem.purchaseMaterialId === 'string') {
payloadItem.purchaseMaterialId = undefined; payloadItem.purchaseMaterialId = undefined;
}
return payloadItem; return payloadItem;
}); });
const payload: ProjectPurchaseForm & { return {
projectName?: string;
purchaseMaterialList?: ProjectPurchaseMaterialForm[];
} = {
...form.value, ...form.value,
purchaseMaterialList: normalizedMaterials purchaseMaterialList: normalizedMaterials
} as ProjectPurchaseForm & {
projectName?: string;
purchaseMaterialList?: ProjectPurchaseMaterialForm[];
}; };
};
const submitForm = async (status: string, mode?: boolean) => {
await projectPurchaseFormRef.value.validate();
buttonLoading.value = true;
try {
const payload = buildProjectPurchasePayload();
if (status !== 'draft') { if (status !== 'draft') {
payload.flowCode = FlowCodeEnum.PROJECT_PURCHASE_CODE; payload.flowCode = FlowCodeEnum.PROJECT_PURCHASE_CODE;
payload.variables = { payload.variables = {
projectPurchaseId: payload.projectPurchaseId, projectPurchaseId: payload.projectPurchaseId,
projectCode: payload.projectCode, projectCode: payload.projectCode,
projectName: payload.projectName projectName: payload.projectName,
deptId: form.value.deptId
}; };
payload.bizExt = { payload.bizExt = {
businessTitle: '项目采购审批', businessTitle: '项目采购审批',
@ -613,11 +612,14 @@ const submitForm = async (status: string, mode?: boolean) => {
* 编辑物料 * 编辑物料
*/ */
const handleEditMaterial = (row: ProjectPurchaseMaterialVO) => { const handleEditMaterial = (row: ProjectPurchaseMaterialVO) => {
if (isReadOnly.value) { if (!canEditMaterial.value) {
return; return;
} }
resetMaterialForm(); resetMaterialForm();
Object.assign(materialForm.value, row); Object.assign(materialForm.value, row);
editingMaterialIndex.value = materialList.value.findIndex(
(item) => item === row || (!!row.purchaseMaterialId && item.purchaseMaterialId === row.purchaseMaterialId)
);
materialDialog.title = '编辑物料'; materialDialog.title = '编辑物料';
materialDialog.visible = true; materialDialog.visible = true;
}; };
@ -626,7 +628,7 @@ const handleEditMaterial = (row: ProjectPurchaseMaterialVO) => {
* 提交物料表单仅操作本地列表 * 提交物料表单仅操作本地列表
*/ */
const submitMaterialForm = () => { const submitMaterialForm = () => {
if (isReadOnly.value) { if (!canEditMaterial.value) {
return; return;
} }
materialFormRef.value?.validate((valid: boolean) => { materialFormRef.value?.validate((valid: boolean) => {
@ -637,12 +639,15 @@ const submitMaterialForm = () => {
if (index !== -1) { if (index !== -1) {
Object.assign(materialList.value[index], materialForm.value); Object.assign(materialList.value[index], materialForm.value);
} }
} else if (editingMaterialIndex.value !== -1) {
Object.assign(materialList.value[editingMaterialIndex.value], materialForm.value);
} else { } else {
// //
materialList.value.push({ ...materialForm.value } as ProjectPurchaseMaterialVO); materialList.value.push({ ...materialForm.value } as ProjectPurchaseMaterialVO);
} }
proxy?.$modal.msgSuccess('操作成功'); proxy?.$modal.msgSuccess('操作成功');
materialDialog.visible = false; materialDialog.visible = false;
editingMaterialIndex.value = -1;
}); });
}; };
@ -650,7 +655,7 @@ const submitMaterialForm = () => {
* 删除物料仅操作本地列表 * 删除物料仅操作本地列表
*/ */
const handleDeleteMaterial = async (row: ProjectPurchaseMaterialVO) => { const handleDeleteMaterial = async (row: ProjectPurchaseMaterialVO) => {
if (isReadOnly.value) { if (!canEditMaterial.value) {
return; return;
} }
await proxy?.$modal.confirm(`是否确认删除物料"${row.materialName}"`); await proxy?.$modal.confirm(`是否确认删除物料"${row.materialName}"`);
@ -667,7 +672,7 @@ const handleDeleteMaterial = async (row: ProjectPurchaseMaterialVO) => {
* 拆分物料为计划外 * 拆分物料为计划外
*/ */
const splitMaterial = (row: ProjectPurchaseMaterialVO) => { const splitMaterial = (row: ProjectPurchaseMaterialVO) => {
if (isReadOnly.value) { if (!canEditMaterial.value) {
return; return;
} }
const newItem: ProjectPurchaseMaterialVO = { const newItem: ProjectPurchaseMaterialVO = {
@ -716,6 +721,14 @@ const handleApprovalRecord = () => {
* 提交审批后的回调 * 提交审批后的回调
*/ */
const submitCallback = async () => { const submitCallback = async () => {
if (hasCgRole.value) {
await projectPurchaseFormRef.value?.validate();
const payload = buildProjectPurchasePayload();
if (payload?.projectPurchaseId) {
await updateProjectPurchase(payload);
Object.assign(form.value, payload);
}
}
await proxy?.$tab.closePage(route); await proxy?.$tab.closePage(route);
router.go(-1); router.go(-1);
}; };
@ -739,6 +752,7 @@ const projectInfoSelectCallBack = (data: ProjectInfoVO[]) => {
form.value.chargeId = project.chargeId; form.value.chargeId = project.chargeId;
form.value.deputyId = project.deputyId; form.value.deputyId = project.deputyId;
form.value.spareFlag = project.spareFlag; form.value.spareFlag = project.spareFlag;
form.value.deptId = project.deptId;
loadProjectMaterialsFromSource(project.projectId as string | number, project.spareFlag); loadProjectMaterialsFromSource(project.projectId as string | number, project.spareFlag);
} }
}; };
@ -758,17 +772,14 @@ onMounted(async () => {
const type = routeParams.type as string; const type = routeParams.type as string;
pageType.value = type || 'add'; pageType.value = type || 'add';
if (id && (type === 'update' || type === 'view' || type === 'approval')) {
pageLoading.value = true;
try { try {
await loadDetail(id); const userInfoRes = await getInfo();
} finally { userRoles.value = userInfoRes?.data?.roles || [];
pageLoading.value = false; } catch (error) {
} userRoles.value = [];
} else {
resetForm();
materialList.value = [];
} }
const shouldLoadDetail = !!id && (type === 'update' || type === 'view' || type === 'approval');
await loadDetail(shouldLoadDetail ? (id as string | number) : undefined);
}); });
}); });
</script> </script>

@ -84,10 +84,10 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="160" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" fixed="right" width="160" class-name="small-padding fixed-width">
<template #default="scope"> <template #default="scope">
<el-tooltip content="查看" placement="top"> <el-tooltip v-if="!canEdit(scope.row)" content="查看" placement="top">
<el-button link type="info" icon="View" @click="handleView(scope.row)"></el-button> <el-button link type="info" icon="View" @click="handleView(scope.row)"></el-button>
</el-tooltip> </el-tooltip>
<el-tooltip content="修改" placement="top"> <el-tooltip v-if="canEdit(scope.row)" content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/erp:projectPurchase:edit']"></el-button> <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/erp:projectPurchase:edit']"></el-button>
</el-tooltip> </el-tooltip>
<el-tooltip content="删除" placement="top"> <el-tooltip content="删除" placement="top">
@ -214,6 +214,10 @@ const handleAdd = () => {
}); });
}; };
const canEdit = (row?: ProjectPurchaseVO) => {
return row.projectPurchaseStatus === '1';
};
const handleUpdate = (row?: ProjectPurchaseVO) => { const handleUpdate = (row?: ProjectPurchaseVO) => {
const projectPurchaseId = row?.projectPurchaseId || ids.value[0]; const projectPurchaseId = row?.projectPurchaseId || ids.value[0];
if (!projectPurchaseId) { if (!projectPurchaseId) {
@ -229,7 +233,7 @@ const handleUpdate = (row?: ProjectPurchaseVO) => {
const handleView = (row: ProjectPurchaseVO) => { const handleView = (row: ProjectPurchaseVO) => {
proxy?.$tab.closePage(route); proxy?.$tab.closePage(route);
router.push({ router.push({
path: '/oa/erp/projectPurchase/edit', path: '/purchase/projectPurchase/edit',
query: { id: row.projectPurchaseId, type: 'view' } query: { id: row.projectPurchaseId, type: 'view' }
}); });
}; };

Loading…
Cancel
Save