|
|
|
|
@ -1,17 +1,19 @@
|
|
|
|
|
<template>
|
|
|
|
|
<div class="p-2">
|
|
|
|
|
<el-card shadow="never">
|
|
|
|
|
<div class="mb-3 flex items-center justify-between">
|
|
|
|
|
<div>
|
|
|
|
|
<el-button type="info" :loading="draftLoading" :disabled="submitLoading" @click="handleSave('draft')">暂存</el-button>
|
|
|
|
|
<el-button type="primary" :loading="submitLoading" :disabled="draftLoading" @click="handleSave('submit')">提交</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<el-button @click="goBack">返回</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<approvalButton
|
|
|
|
|
@submitForm="handleApprovalSubmit"
|
|
|
|
|
@approvalVerifyOpen="approvalVerifyOpen"
|
|
|
|
|
@handleApprovalRecord="handleApprovalRecord"
|
|
|
|
|
:buttonLoading="buttonLoading"
|
|
|
|
|
:id="form.projectChangeId ?? ''"
|
|
|
|
|
:status="form.flowStatus ?? 'draft'"
|
|
|
|
|
:pageType="approvalPageType"
|
|
|
|
|
:mode="false"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<el-form ref="projectChangeFormRef" :model="form" :rules="rules" label-width="140px">
|
|
|
|
|
<!-- 基本信息 -->
|
|
|
|
|
<el-divider content-position="left">基本信息</el-divider>
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
@ -53,12 +55,19 @@
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<el-form-item label="申请变更日期" prop="applyChangeDate">
|
|
|
|
|
<el-date-picker v-model="form.applyChangeDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择申请变更日期" style="width: 100%"/>
|
|
|
|
|
<el-date-picker
|
|
|
|
|
v-model="form.applyChangeDate"
|
|
|
|
|
type="date"
|
|
|
|
|
value-format="YYYY-MM-DD"
|
|
|
|
|
placeholder="请选择申请变更日期"
|
|
|
|
|
:disabled="!isFormEditable"
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
/>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="24">
|
|
|
|
|
<el-form-item label="变更类型" prop="changeType">
|
|
|
|
|
<el-checkbox-group v-model="changeTypeList">
|
|
|
|
|
<el-checkbox-group v-model="changeTypeList" :disabled="!isFormEditable">
|
|
|
|
|
<el-checkbox v-for="dict in change_type" :key="dict.value" :label="dict.value">{{ dict.label }}</el-checkbox>
|
|
|
|
|
</el-checkbox-group>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
@ -78,7 +87,7 @@
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
<el-row :gutter="10" class="mb8">
|
|
|
|
|
<el-row v-if="isFormEditable" :gutter="10" class="mb8">
|
|
|
|
|
<el-col :span="1.5">
|
|
|
|
|
<el-button type="primary" icon="Plus" @click="handleAddBudget">添加预算行</el-button>
|
|
|
|
|
</el-col>
|
|
|
|
|
@ -87,35 +96,35 @@
|
|
|
|
|
<el-table-column label="序号" type="index" width="60" align="center" />
|
|
|
|
|
<el-table-column label="科目名称" width="200" align="center">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<el-input v-model="scope.row.subjectName" placeholder="请输入科目名称" />
|
|
|
|
|
<el-input v-model="scope.row.subjectName" placeholder="请输入科目名称" :disabled="!isFormEditable" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="变更前预算" width="150" align="center">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<el-input-number v-model="scope.row.budgetBefore" :min="0" :precision="2" controls-position="right" style="width: 100%" />
|
|
|
|
|
<el-input-number v-model="scope.row.budgetBefore" :min="0" :precision="2" controls-position="right" :disabled="!isFormEditable" style="width: 100%" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="变更后预算" width="150" align="center">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<el-input-number v-model="scope.row.budgetAfter" :min="0" :precision="2" controls-position="right" style="width: 100%" />
|
|
|
|
|
<el-input-number v-model="scope.row.budgetAfter" :min="0" :precision="2" controls-position="right" :disabled="!isFormEditable" style="width: 100%" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="已使用金额" width="150" align="center">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<el-input-number v-model="scope.row.amountUsed" :min="0" :precision="2" controls-position="right" style="width: 100%" />
|
|
|
|
|
<el-input-number v-model="scope.row.amountUsed" :min="0" :precision="2" controls-position="right" :disabled="!isFormEditable" style="width: 100%" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="费用调整原因" min-width="200" align="center">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<el-input v-model="scope.row.adjustmentReason" placeholder="请输入费用调整原因" />
|
|
|
|
|
<el-input v-model="scope.row.adjustmentReason" placeholder="请输入费用调整原因" :disabled="!isFormEditable" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="备注" min-width="150" align="center">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<el-input v-model="scope.row.remark" placeholder="请输入备注" />
|
|
|
|
|
<el-input v-model="scope.row.remark" placeholder="请输入备注" :disabled="!isFormEditable" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="操作" width="80" align="center" fixed="right">
|
|
|
|
|
<el-table-column v-if="isFormEditable" label="操作" width="80" align="center" fixed="right">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<el-button type="danger" link icon="Delete" @click="handleDeleteBudget(scope.$index)">删除</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
@ -132,7 +141,7 @@
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="里程碑名称" width="150" align="center">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<el-input v-model="scope.row.milestoneName" placeholder="请输入里程碑名称" />
|
|
|
|
|
<el-input v-model="scope.row.milestoneName" placeholder="请输入里程碑名称" :disabled="!isFormEditable" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="原计划时间起" width="160" align="center">
|
|
|
|
|
@ -147,22 +156,22 @@
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="变更后时间起" width="160" align="center">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<el-date-picker v-model="scope.row.changedStart" type="date" value-format="YYYY-MM-DD" placeholder="选择日期" style="width: 100%" />
|
|
|
|
|
<el-date-picker v-model="scope.row.changedStart" type="date" value-format="YYYY-MM-DD" placeholder="选择日期" :disabled="!isFormEditable" style="width: 100%" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="变更后时间止" width="160" align="center">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<el-date-picker v-model="scope.row.changedEnd" type="date" value-format="YYYY-MM-DD" placeholder="选择日期" style="width: 100%" />
|
|
|
|
|
<el-date-picker v-model="scope.row.changedEnd" type="date" value-format="YYYY-MM-DD" placeholder="选择日期" :disabled="!isFormEditable" style="width: 100%" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="里程碑完成程度(%)" width="180" align="center">
|
|
|
|
|
<el-table-column label="完成程度" width="120" align="center">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<el-input-number v-model="scope.row.completionDegree" :min="0" :max="100" :precision="2" controls-position="right" style="width: 100%" />
|
|
|
|
|
<el-input-number v-model="scope.row.completionDegree" :min="0" :max="100" :precision="0" controls-position="right" :disabled="!isFormEditable" style="width: 100%" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
<el-table-column label="备注" min-width="200" align="center">
|
|
|
|
|
<template #default="scope">
|
|
|
|
|
<el-input v-model="scope.row.remark" placeholder="请输入备注" />
|
|
|
|
|
<el-input v-model="scope.row.remark" placeholder="请输入备注" :disabled="!isFormEditable" />
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
|
@ -170,34 +179,40 @@
|
|
|
|
|
<el-divider content-position="left">项目当前情况说明</el-divider>
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
<el-col :span="24">
|
|
|
|
|
<el-form-item label="当前情况说明" prop="currentStatus">
|
|
|
|
|
<el-input v-model="form.currentStatus" type="textarea" :rows="3" placeholder="请输入当前情况说明" />
|
|
|
|
|
<el-form-item label="当前情况" prop="currentStatus">
|
|
|
|
|
<el-input v-model="form.currentStatus" type="textarea" :rows="3" placeholder="请输入当前情况" :disabled="!isFormEditable" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="24">
|
|
|
|
|
<el-form-item label="变更原因" prop="changeReason">
|
|
|
|
|
<el-input v-model="form.changeReason" type="textarea" :rows="3" placeholder="请输入变更原因" />
|
|
|
|
|
<el-input v-model="form.changeReason" type="textarea" :rows="3" placeholder="请输入变更原因" :disabled="!isFormEditable" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="24">
|
|
|
|
|
<el-form-item label="后续工作" prop="followUpWork">
|
|
|
|
|
<el-input v-model="form.followUpWork" type="textarea" :rows="3" placeholder="请输入后续工作" />
|
|
|
|
|
<el-input v-model="form.followUpWork" type="textarea" :rows="3" placeholder="请输入后续工作" :disabled="!isFormEditable" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
</el-form>
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
<submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
|
|
|
|
|
<approvalRecord ref="approvalRecordRef" />
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts" name="ErpProjectChangeEdit">
|
|
|
|
|
import { ref, reactive, onMounted, getCurrentInstance, toRefs, watch, onActivated, nextTick } from 'vue';
|
|
|
|
|
import { ref, reactive, onMounted, getCurrentInstance, toRefs, watch, onActivated, nextTick, computed } from 'vue';
|
|
|
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
|
|
import { getErpProjectChange, addErpProjectChange, updateErpProjectChange, prepareProjectChangeWithInfo, submitProjectChangeAndFlowStart } from '@/api/oa/erp/erpProjectChange';
|
|
|
|
|
import { ErpProjectChangeForm, ErpProjectChangeBudget, ErpProjectChangeProgress } from '@/api/oa/erp/erpProjectChange/types';
|
|
|
|
|
import { useUserStore } from '@/store/modules/user';
|
|
|
|
|
import type { FormInstance as ElFormInstance } from 'element-plus';
|
|
|
|
|
import type { ComponentInternalInstance } from 'vue';
|
|
|
|
|
import SubmitVerify from '@/components/Process/submitVerify.vue';
|
|
|
|
|
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
|
|
|
|
|
import ApprovalButton from '@/components/Process/approvalButton.vue';
|
|
|
|
|
|
|
|
|
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
|
|
const { project_category, change_type, project_phases } = toRefs<any>(proxy?.useDict('project_category', 'change_type', 'project_phases'));
|
|
|
|
|
@ -209,6 +224,28 @@ const projectChangeFormRef = ref<ElFormInstance>();
|
|
|
|
|
const draftLoading = ref(false);
|
|
|
|
|
const submitLoading = ref(false);
|
|
|
|
|
const changeTypeList = ref<string[]>([]);
|
|
|
|
|
const routeParams = ref<any>({
|
|
|
|
|
...route.params,
|
|
|
|
|
...route.query
|
|
|
|
|
});
|
|
|
|
|
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
|
|
|
|
|
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
|
|
|
|
|
const taskVariables = ref<Record<string, any>>({});
|
|
|
|
|
|
|
|
|
|
// 计算属性:判断是否为查看模式
|
|
|
|
|
const isViewMode = computed(() => routeParams.value.type === 'view');
|
|
|
|
|
// 计算属性:判断是否为审批模式
|
|
|
|
|
const isApprovalMode = computed(() => routeParams.value.type === 'approval');
|
|
|
|
|
// 计算属性:判断表单是否可编辑
|
|
|
|
|
const isFormEditable = computed(() => !isViewMode.value && !isApprovalMode.value);
|
|
|
|
|
const buttonLoading = computed(() => draftLoading.value || submitLoading.value);
|
|
|
|
|
const approvalPageType = computed(() => {
|
|
|
|
|
const type = routeParams.value.type as string | undefined;
|
|
|
|
|
if (!type) {
|
|
|
|
|
return form.value.projectChangeId ? 'update' : 'add';
|
|
|
|
|
}
|
|
|
|
|
return type === 'edit' ? 'update' : type;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const formatToday = () => (proxy?.parseTime ? proxy.parseTime(new Date(), '{y}-{m}-{d}') : new Date().toISOString().slice(0, 10));
|
|
|
|
|
|
|
|
|
|
@ -241,6 +278,7 @@ const getDefaultForm = (): ErpProjectChangeForm => ({
|
|
|
|
|
changeReason: '',
|
|
|
|
|
followUpWork: '',
|
|
|
|
|
projectChangeStatus: '1',
|
|
|
|
|
flowStatus: 'draft',
|
|
|
|
|
activeFlag: '1',
|
|
|
|
|
budgetList: [],
|
|
|
|
|
progressList: []
|
|
|
|
|
@ -375,13 +413,65 @@ const goBack = () => {
|
|
|
|
|
router.back();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleApprovalSubmit = async (status: string, _mode: boolean) => {
|
|
|
|
|
if (status === 'draft' || status === 'submit') {
|
|
|
|
|
await handleSave(status as 'draft' | 'submit');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const approvalVerifyOpen = async () => {
|
|
|
|
|
const taskId = routeParams.value.taskId as string | undefined;
|
|
|
|
|
await submitVerifyRef.value?.openDialog(taskId);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleApprovalRecord = () => {
|
|
|
|
|
if (form.value.projectChangeId) {
|
|
|
|
|
approvalRecordRef.value?.init(form.value.projectChangeId);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const submitCallback = async () => {
|
|
|
|
|
await loadFormData();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const loadFormData = async () => {
|
|
|
|
|
await resetFormState();
|
|
|
|
|
|
|
|
|
|
// 获取路由参数
|
|
|
|
|
routeParams.value = {
|
|
|
|
|
...route.params,
|
|
|
|
|
...route.query
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 优先使用 query.id(审批/查看模式),其次使用 params.projectChangeId(列表编辑模式)
|
|
|
|
|
const id = routeParams.value.id as string | number;
|
|
|
|
|
const projectChangeId = route.params.projectChangeId as string;
|
|
|
|
|
const projectId = route.query.projectId as string;
|
|
|
|
|
|
|
|
|
|
if (projectChangeId && projectChangeId !== '0') {
|
|
|
|
|
// 编辑模式:加载已有的变更申请数据
|
|
|
|
|
// 判断是否为查看/审批/编辑模式
|
|
|
|
|
if (id && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) {
|
|
|
|
|
// 审批/查看/编辑模式:根据 id 加载数据
|
|
|
|
|
try {
|
|
|
|
|
proxy?.$modal.loading('正在加载数据,请稍后...');
|
|
|
|
|
const res = await getErpProjectChange(id);
|
|
|
|
|
if (res.data) {
|
|
|
|
|
Object.assign(form.value, res.data);
|
|
|
|
|
const dateOnly = toDateOnly(form.value.applyChangeDate);
|
|
|
|
|
form.value.applyChangeDate = dateOnly ?? formatToday();
|
|
|
|
|
form.value.budgetList = res.data.budgetList ?? [];
|
|
|
|
|
form.value.progressList = res.data.progressList ?? [];
|
|
|
|
|
if (res.data.changeType) {
|
|
|
|
|
changeTypeList.value = res.data.changeType.split(',');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
proxy?.$modal.closeLoading();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
proxy?.$modal.closeLoading();
|
|
|
|
|
proxy?.$modal.msgError('加载变更申请数据失败');
|
|
|
|
|
console.error(error);
|
|
|
|
|
}
|
|
|
|
|
} else if (projectChangeId && projectChangeId !== '0') {
|
|
|
|
|
// 列表编辑模式:加载已有的变更申请数据
|
|
|
|
|
try {
|
|
|
|
|
const res = await getErpProjectChange(projectChangeId);
|
|
|
|
|
if (res.data) {
|
|
|
|
|
@ -402,7 +492,7 @@ const loadFormData = async () => {
|
|
|
|
|
// 新增模式:根据项目ID加载项目计划信息
|
|
|
|
|
await loadProjectDataByProjectId(projectId);
|
|
|
|
|
} else {
|
|
|
|
|
proxy?.$modal.msgError('缺少必要的参数:项目ID');
|
|
|
|
|
proxy?.$modal.msgError('缺少必要的参数:项目ID或变更申请ID');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|