refactor(erp): 统一项目相关模块编辑页代码结构和交互优化

- 统一新增、编辑、查看模式的路由参数处理逻辑,使用ref对象存储routeParams
- 所有模块审批按钮组件绑定参数改为使用routeParams.type确保一致性
- 替换项目选择控件为统一的ProjectSelect弹窗组件,提升交互体验
- 在项目变更、项目计划、项目验收模块中新增打开项目选择弹窗及回调处理方法
- 项目名称字段统一改为只读输入框,附带打开项目弹窗图标,避免使用ElSelect
- 优化提交逻辑,增加项目经理权限校验及超级管理员绕过权限判断
- 合并暂存与提交审批逻辑,统一使用submitForm方法控制状态和流程启动
- 添加表单验证前置处理,防止无效提交
- 加入通知列表页刷新机制,确保操作后列表页数据更新
- 取消多余计算属性及loading状态,改用单一buttonLoading管理加载状态
- 代码中增加注释,提升可读性和维护性
- 移除部分重复代码,简化数据加载流程,统一loading提示逻辑
- 表单初始化和数据加载保持与项目信息模块一致的业务逻辑处理
- 审批记录和流程进度调用方式统一
- 修改样式调整卡片组件上边距,使页面布局更紧凑一致
dev
zangch@mesnac.com 2 months ago
parent 4b9c695a2a
commit 6b29c694f9

@ -1,26 +1,33 @@
<template>
<div class="p-2">
<el-card shadow="never">
<el-card shadow="never" style="margin-top: 0">
<!-- 审批按钮组件 -->
<approvalButton
@submitForm="handleApprovalSubmit"
@submitForm="submitForm"
@approvalVerifyOpen="approvalVerifyOpen"
@handleApprovalRecord="handleApprovalRecord"
:buttonLoading="buttonLoading"
:id="form.projectChangeId ?? ''"
:status="form.flowStatus ?? 'draft'"
:pageType="approvalPageType"
:id="form.projectChangeId"
:status="form.flowStatus"
:pageType="routeParams.type"
:mode="false"
/>
</el-card>
<el-card shadow="never" style="margin-top: 0">
<el-form ref="projectChangeFormRef" :model="form" :disabled="!isFormEditable" :rules="rules" label-width="140px">
<!-- 基本信息 -->
<el-divider content-position="left">基本信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="项目名称" prop="projectId">
<el-select v-if="showProjectSelect" v-model="form.projectId" placeholder="请选择项目" @change="handleProjectChange" style="width: 100%">
<el-option v-for="project in projectInfoList" :key="project.projectId" :label="project.projectName" :value="project.projectId" />
</el-select>
<el-input v-if="showProjectSelect" v-model="form.projectName" placeholder="请选择项目" readonly>
<template #suffix>
<el-icon style="cursor: pointer" @click="openProjectSelect">
<Search />
</el-icon>
</template>
</el-input>
<el-input v-else v-model="form.projectName" disabled placeholder="项目名称" />
</el-form-item>
</el-col>
@ -74,8 +81,8 @@
</el-col>
<el-col :span="24">
<el-form-item label="变更类型" prop="changeType">
<el-checkbox-group v-model="changeTypeList">
<el-checkbox v-for="dict in change_type" :key="dict.value" :label="dict.value">{{ dict.label }}</el-checkbox>
<el-checkbox-group v-model="changeTypeList" :validate-event="false">
<el-checkbox v-for="dict in change_type" :key="dict.value" :value="dict.value">{{ dict.label }}</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-col>
@ -215,12 +222,12 @@
<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 lang="ts" name="ErpProjectChangeEdit">
import type { ComponentInternalInstance } from 'vue';
import { computed, getCurrentInstance, nextTick, onActivated, onMounted, reactive, ref, toRefs, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import {
addErpProjectChange,
@ -238,7 +245,8 @@ import type { ErpProjectChangeBudget, ErpProjectChangeForm } from '@/api/oa/erp/
import SubmitVerify from '@/components/Process/submitVerify.vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import ApprovalButton from '@/components/Process/approvalButton.vue';
import { getErpProjectInfoList } from '@/api/oa/erp/projectInfo';
import ProjectSelect from '@/components/ProjectSelect/index.vue';
import type { ProjectInfoVO } from '@/api/oa/erp/projectInfo/types';
import { FlowCodeEnum } from '@/enums/OAEnum';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -246,15 +254,18 @@ const { project_category, change_type, project_phases } = toRefs<any>(proxy?.use
const route = useRoute();
const router = useRouter();
const userStore = useUserStore();
const refreshFlagKey = 'erpProjectChangeListShouldRefresh';
/** 通知列表页刷新 */
const notifyListRefresh = () => {
sessionStorage.setItem(refreshFlagKey, Date.now().toString());
};
const projectChangeFormRef = ref<ElFormInstance>();
const draftLoading = ref(false);
const submitLoading = ref(false);
const buttonLoading = ref(false);
const changeTypeList = ref<string[]>([]);
const routeParams = ref<any>({
...route.params,
...route.query
});
//
const routeParams = ref<Record<string, any>>({});
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
const taskVariables = ref<Record<string, any>>({});
@ -266,26 +277,16 @@ const taskVariables = ref<Record<string, any>>({});
// 3.
const isCodeGenerated = ref(false);
//
const isViewMode = computed(() => routeParams.value.type === 'view');
//
const isApprovalMode = computed(() => routeParams.value.type === 'approval');
//
const isViewMode = computed(() => routeParams.value.type === 'view' || routeParams.value.type === 'approval');
// 稿/
const isFormEditable = computed(() => {
if (isViewMode.value || isApprovalMode.value) {
if (isViewMode.value) {
return false;
}
// 稿
return form.value.projectChangeStatus === '1';
});
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));
@ -338,22 +339,25 @@ const form = ref<ErpProjectChangeForm>({
});
// projectId
const projectInfoList = ref([]);
const projectSelectRef = ref<InstanceType<typeof ProjectSelect>>();
const showProjectSelect = computed(() => {
const projectId = route.query.projectId as string;
return (!routeParams.value.projectChangeId || routeParams.value.projectChangeId === '0') && !projectId;
return routeParams.value.type === 'add' && !routeParams.value.projectId;
});
const loadProjectList = async () => {
if (showProjectSelect.value) {
try {
const res = await getErpProjectInfoList({});
if (res.code === 200) {
projectInfoList.value = res.data;
}
} catch (error) {
console.error('加载项目列表失败:', error);
}
/** 打开项目选择弹窗 */
const openProjectSelect = () => {
projectSelectRef.value?.open();
};
/** 项目选择回调,自动填充项目相关信息 */
const projectInfoSelectCallBack = async (data: ProjectInfoVO[]) => {
if (data && data.length > 0) {
const project = data[0];
form.value.projectId = project.projectId;
form.value.projectName = project.projectName || '';
form.value.projectCode = project.projectCode || '';
// handleProjectChange
await handleProjectChange(project.projectId as string | number);
}
};
@ -442,82 +446,69 @@ const handleDeleteBudget = (index: number) => {
form.value.budgetList.splice(index, 1);
};
const handleSave = async (action: 'draft' | 'submit') => {
await projectChangeFormRef.value?.validate();
/** 提交按钮(与项目信息保持一致的处理方式) */
const submitForm = (status: string, mode: boolean) => {
projectChangeFormRef.value?.validate(async (valid: boolean) => {
if (!valid) return;
buttonLoading.value = true;
if (!form.value.projectManagerId) {
proxy?.$modal.msgError('请先选择项目');
return;
}
if (action === 'submit' && userStore.userId !== form.value.projectManagerId) {
proxy?.$modal.msgError('只有项目经理才能提交项目变更申请');
return;
}
form.value.changeType = changeTypeList.value.join(',');
if (action === 'draft') {
// 稿
form.value.projectChangeStatus = '1';
form.value.flowStatus = 'draft';
draftLoading.value = true;
try {
if (form.value.projectChangeId) {
await updateErpProjectChange(form.value);
} else {
await addErpProjectChange(form.value);
//
if (!form.value.projectManagerId) {
proxy?.$modal.msgError('请先选择项目');
buttonLoading.value = false;
return;
}
const isSuperAdmin = userStore.roles.includes('admin') || userStore.roles.includes('superadmin');
if (!isSuperAdmin && status === 'submit' && userStore.userId !== form.value.projectManagerId) {
proxy?.$modal.msgError('只有项目经理才能提交项目变更申请');
buttonLoading.value = false;
return;
}
proxy?.$modal.msgSuccess('暂存成功');
goBack();
} catch (error) {
proxy?.$modal.msgError('暂存失败');
} finally {
draftLoading.value = false;
}
} else {
//
form.value.projectChangeStatus = '2';
form.value.flowStatus = 'waiting';
submitLoading.value = true;
try {
//
form.value.flowCode = FlowCodeEnum.PROJECT_PLAN_CHANGE_CODE; //OAEP
//
form.value.variables = {
projectId: form.value.projectId,
projectName: form.value.projectName,
projectCode: form.value.projectCode,
projectManagerId: form.value.projectManagerId,
deptHeadId: form.value.deptHeadId,
changeType: form.value.changeType
};
// 使使
form.value.bizExt = {
businessTitle: form.value.projectName,
businessCode: form.value.projectChangeCode
};
await submitProjectChangeAndFlowStart(form.value);
proxy?.$modal.msgSuccess('提交成功');
goBack();
} catch (error) {
proxy?.$modal.msgError('提交失败');
} finally {
submitLoading.value = false;
}
}
};
const goBack = () => {
// tab
proxy?.$tab.closePage(route as any);
router.go(-1);
};
form.value.changeType = changeTypeList.value.join(',');
const handleApprovalSubmit = async (status: string, _mode: boolean) => {
if (status === 'draft' || status === 'submit') {
await handleSave(status as 'draft' | 'submit');
}
//
if (status !== 'draft') {
form.value.flowCode = FlowCodeEnum.PROJECT_PLAN_CHANGE_CODE; //OAEP
form.value.variables = {
projectId: form.value.projectId,
projectName: form.value.projectName,
projectCode: form.value.projectCode,
projectManagerId: form.value.projectManagerId,
deptHeadId: form.value.deptHeadId,
changeType: form.value.changeType
};
//
form.value.bizExt = {
businessTitle: form.value.projectName,
businessCode: form.value.projectChangeCode
};
form.value.projectChangeStatus = '2';
form.value.flowStatus = 'waiting';
await submitProjectChangeAndFlowStart(form.value);
proxy?.$modal.msgSuccess('操作成功');
notifyListRefresh();
proxy?.$tab.closePage();
router.go(-1);
} else {
//
form.value.projectChangeStatus = '1';
form.value.flowStatus = 'draft';
if (form.value.projectChangeId) {
await updateErpProjectChange(form.value);
} else {
await addErpProjectChange(form.value);
}
proxy?.$modal.msgSuccess('暂存成功');
notifyListRefresh();
proxy?.$tab.closePage();
router.go(-1);
}
} finally {
buttonLoading.value = false;
}
});
};
const approvalVerifyOpen = async () => {
@ -533,26 +524,21 @@ const handleApprovalRecord = () => {
const submitCallback = async () => {
// /退
goBack();
proxy?.$tab.closePage();
router.go(-1);
};
const loadFormData = async () => {
await resetFormState();
//
routeParams.value = route.query;
buttonLoading.value = false;
//
routeParams.value = {
...route.params,
...route.query
};
const id = routeParams.value.id as string;
const projectId = routeParams.value.projectId as string;
// 使 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 (id && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) {
// // id
// //
if (id && id !== '0' && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) {
try {
proxy?.$modal.loading('正在加载数据,请稍后...');
const res = await getErpProjectChange(id);
@ -562,8 +548,6 @@ const loadFormData = async () => {
form.value.applyChangeDate = dateOnly ?? formatToday();
form.value.budgetList = res.data.budgetList ?? [];
form.value.progressList = res.data.progressList ?? [];
//
//
isCodeGenerated.value = !!form.value.projectChangeCode;
if (res.data.changeType) {
changeTypeList.value = res.data.changeType.split(',');
@ -575,27 +559,6 @@ const loadFormData = async () => {
proxy?.$modal.msgError('加载变更申请数据失败');
console.error(error);
}
} else if (projectChangeId && projectChangeId !== '0') {
//
try {
const res = await getErpProjectChange(projectChangeId);
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 ?? [];
//
// true projectChangeCode
isCodeGenerated.value = !!form.value.projectChangeCode;
if (res.data.changeType) {
changeTypeList.value = res.data.changeType.split(',');
}
}
} catch (error) {
proxy?.$modal.msgError('加载变更申请数据失败');
console.error(error);
}
} else if (projectId) {
// ID
await loadProjectDataByProjectId(projectId);
@ -604,19 +567,26 @@ const loadFormData = async () => {
}
};
let skipNextActivated = false;
watch(
() => route.fullPath,
() => {
//
if (route.path.includes('erpProjectChange/edit')) {
loadFormData();
}
}
);
onMounted(async () => {
skipNextActivated = true;
await loadProjectList();
await loadFormData();
});
onActivated(async () => {
if (skipNextActivated) {
skipNextActivated = false;
return;
}
await loadFormData();
// loadFormDataloading
});
</script>
<style scoped lang="scss">
.card-title {
font-weight: bold;
font-size: 16px;
color: #303133;
}
</style>

@ -149,8 +149,8 @@
<dict-tag :options="active_flag" :value="scope.row.activeFlag" />
</template>
</el-table-column>
<el-table-column label="创建人" align="center" prop="createName" width="140" v-if="columns[26].visible" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180" v-if="columns[27].visible">
<el-table-column label="创建人" align="center" prop="createName" width="140" v-if="columns[24].visible" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180" v-if="columns[25].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
@ -161,8 +161,12 @@
<el-tooltip v-if="scope.row.projectChangeStatus !== '1'" content="查看" placement="top">
<el-button link type="primary" icon="View" @click="handleView(scope.row)"></el-button>
</el-tooltip>
<!-- 修改按钮仅草稿状态显示 -->
<el-tooltip v-if="scope.row.projectChangeStatus === '1'" content="修改" placement="top">
<!-- 修改按钮草稿驳回或撤回状态显示 -->
<el-tooltip
v-if="scope.row.projectChangeStatus === '1' || scope.row.flowStatus === 'back' || scope.row.flowStatus === 'cancel'"
content="修改"
placement="top"
>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/erp:erpProjectChange:edit']"></el-button>
</el-tooltip>
<!-- 新增变更按钮仅在该项目最新且已完成的变更记录上显示 -->
@ -173,8 +177,12 @@
<el-tooltip v-if="scope.row.projectChangeStatus === '2' || scope.row.projectChangeStatus === '3'" content="审批记录" placement="top">
<el-button link type="info" icon="DocumentCopy" @click="handleApprovalRecord(scope.row)"></el-button>
</el-tooltip>
<!-- 删除按钮仅草稿状态显示 -->
<el-tooltip v-if="scope.row.projectChangeStatus === '1'" content="删除" placement="top">
<!-- 删除按钮草稿驳回或撤回状态显示 -->
<el-tooltip
v-if="scope.row.projectChangeStatus === '1' || scope.row.flowStatus === 'back' || scope.row.flowStatus === 'cancel'"
content="删除"
placement="top"
>
<el-button
link
type="danger"
@ -189,17 +197,24 @@
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 审批记录 -->
<ApprovalRecord ref="approvalRecordRef" />
</div>
</template>
<script setup name="ErpProjectChange" lang="ts">
import { delErpProjectChange, listErpProjectChange } from '@/api/oa/erp/erpProjectChange';
import { ErpProjectChangeQuery, ErpProjectChangeVO } from '@/api/oa/erp/erpProjectChange/types';
import { useRouter } from 'vue-router';
import { useRoute, useRouter } from 'vue-router';
import { onActivated } from 'vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
const route = useRoute();
const router = useRouter();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
const refreshFlagKey = 'erpProjectChangeListShouldRefresh';
const { active_flag, change_type, project_change_status, project_category, wf_business_status } = toRefs<any>(
proxy?.useDict('active_flag', 'change_type', 'project_change_status', 'project_category', 'wf_business_status')
);
@ -243,12 +258,8 @@ const columns = ref<FieldOption[]>([
{ key: 21, label: `流程状态`, visible: false },
{ key: 22, label: `备注`, visible: false },
{ key: 23, label: `激活标识`, visible: false },
{ key: 24, label: `删除标志`, visible: false },
{ key: 25, label: `创建部门`, visible: false },
{ key: 26, label: `创建人`, visible: true },
{ key: 27, label: `创建时间`, visible: true },
{ key: 28, label: `更新人`, visible: false },
{ key: 29, label: `更新时间`, visible: false }
{ key: 24, label: `创建人`, visible: true },
{ key: 25, label: `创建时间`, visible: true }
]);
// +
@ -332,23 +343,32 @@ const handleSelectionChange = (selection: ErpProjectChangeVO[]) => {
multiple.value = !selection.length;
};
/** 新增按钮操作 */
/** 新增按钮操作(与项目信息保持一致) */
const handleAdd = () => {
//
router.push('/oa/erp/erpProjectChange/edit/0');
proxy?.$tab.closePage(route);
router.push({
path: '/project/erpProjectChange/edit',
query: { type: 'add' }
});
};
/** 修改按钮操作 */
/** 修改按钮操作(与项目信息保持一致) */
const handleUpdate = (row?: ErpProjectChangeVO) => {
const _projectChangeId = row?.projectChangeId || ids.value[0];
//
router.push(`/oa/erp/erpProjectChange/edit/${_projectChangeId}`);
proxy?.$tab.closePage(route);
router.push({
path: '/project/erpProjectChange/edit',
query: { id: _projectChangeId, type: 'update' }
});
};
/** 查看按钮操作 */
/** 查看按钮操作(与项目信息保持一致) */
const handleView = (row: ErpProjectChangeVO) => {
//
router.push(`/oa/erp/erpProjectChange/edit/${row.projectChangeId}?type=view`);
proxy?.$tab.closePage(route);
router.push({
path: '/project/erpProjectChange/edit',
query: { id: row.projectChangeId, type: 'view' }
});
};
//
@ -361,16 +381,18 @@ const isLatestCompletedChange = (row: ErpProjectChangeVO) => {
return latestCompletedChangeMap.value[pid] === row.changeNumber;
};
/** 新增变更按钮操作 */
/** 新增变更按钮操作(与项目信息保持一致) */
const handleAddChange = (row: ErpProjectChangeVO) => {
// projectId
router.push(`/oa/erp/erpProjectChange/edit/0?projectId=${row.projectId}`);
proxy?.$tab.closePage(route);
router.push({
path: '/project/erpProjectChange/edit',
query: { type: 'add', projectId: row.projectId }
});
};
/** 审批记录按钮操作 */
const handleApprovalRecord = (row: ErpProjectChangeVO) => {
//
router.push(`/oa/erp/erpProjectChange/edit/${row.projectChangeId}?type=view`);
approvalRecordRef.value?.init(row.projectChangeId);
};
/** 删除按钮操作 */
@ -393,7 +415,21 @@ const handleExport = () => {
);
};
/** 检查是否需要刷新列表 */
const checkShouldRefresh = () => {
const flag = sessionStorage.getItem(refreshFlagKey);
if (flag) {
sessionStorage.removeItem(refreshFlagKey);
handleQuery();
}
};
onMounted(() => {
getList();
checkShouldRefresh();
});
onActivated(() => {
checkShouldRefresh();
});
</script>

@ -1,35 +1,43 @@
<template>
<div class="p-2">
<el-card shadow="never">
<div v-if="showApprovalButton" class="mb-3 flex items-center justify-between">
<el-card shadow="never" style="margin-top: 0">
<!-- 审批按钮组件标准流程场景 -->
<approvalButton
v-if="!isLimitedMode"
@submitForm="submitForm"
@approvalVerifyOpen="approvalVerifyOpen"
@handleApprovalRecord="handleApprovalRecord"
:buttonLoading="buttonLoading"
:id="form.projectPlanId"
:status="form.flowStatus"
:pageType="routeParams.type"
:mode="false"
/>
<!-- 审批完成后维护模式仅可编辑延期天数进度备注等 -->
<div v-else class="mb-3 flex items-center justify-between">
<div>
<el-button v-if="showSubmitButtons" type="info" :loading="draftLoading" :disabled="submitLoading" @click="handleSubmitAction('draft')"
>暂存</el-button
>
<el-button v-if="showSubmitButtons" type="primary" :loading="submitLoading" :disabled="draftLoading" @click="handleSubmitAction('submit')"
>提交</el-button
>
<el-button v-if="showApprovalAction" type="primary" :disabled="draftLoading || submitLoading" @click="approvalVerifyOpen"></el-button>
<el-button v-if="showProgressButton" type="primary" :disabled="draftLoading || submitLoading" @click="handleApprovalRecord"
>流程进度</el-button
>
<el-button type="primary" :loading="buttonLoading" @click="saveLimited"></el-button>
<el-button type="primary" @click="handleApprovalRecord"></el-button>
</div>
<div>
<el-button @click="goBack"></el-button>
</div>
</div>
<div v-else-if="showLimitedActions" class="mb-3 text-right">
<el-button type="primary" :loading="buttonLoading" @click="handleSave"></el-button>
<el-button @click="goBack"></el-button>
</div>
</el-card>
<el-card shadow="never" style="margin-top: 0">
<el-form ref="projectPlanFormRef" :model="form" :rules="rules" :disabled="isViewMode" label-width="120px">
<el-divider content-position="left">基本信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="项目名称" prop="projectId">
<el-select v-model="form.projectId" placeholder="请选择项目" filterable :disabled="!isBasicEditable" @change="handleProjectChange">
<el-option v-for="item in projectInfoList" :key="item.projectId" :label="item.projectName" :value="item.projectId" />
</el-select>
<el-input v-model="selectedProjectName" placeholder="请选择项目" readonly :disabled="!isBasicEditable">
<template #suffix>
<el-icon style="cursor: pointer" @click="openProjectSelect" :disabled="!isBasicEditable">
<Search />
</el-icon>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
@ -270,6 +278,8 @@
<submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
<!-- 审批记录 -->
<approvalRecord ref="approvalRecordRef" />
<!-- 项目选择弹窗 -->
<ProjectSelect ref="projectSelectRef" :multiple="false" @confirm-call-back="projectInfoSelectCallBack" />
<!-- 附件上传/预览对话框 -->
<el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
@ -290,7 +300,6 @@
</template>
<script setup lang="ts" name="ErpProjectPlanEdit">
import { computed, getCurrentInstance, onActivated, onMounted, reactive, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { addErpProjectPlan, getErpProjectPlan, projectPlanSubmitAndFlowStart, updateErpProjectPlan } from '@/api/oa/erp/erpProjectPlan';
import { ErpProjectPlanForm } from '@/api/oa/erp/erpProjectPlan/types';
@ -299,6 +308,8 @@ import { getErpProjectInfoList } from '@/api/oa/erp/projectInfo';
import type { ProjectInfoVO } from '@/api/oa/erp/projectInfo/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 { useUserStore } from '@/store/modules/user';
import { FlowCodeEnum } from '@/enums/OAEnum';
@ -315,31 +326,11 @@ const refreshFlagKey = 'erpProjectPlanListShouldRefresh';
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
//
const routeParams = ref<any>({});
const syncRouteParams = () => {
const projectPlanId = (route.params.projectPlanId as string) || (route.query.id as string);
const type = (route.query.type as string) || (route.params.type as string) || 'edit';
const taskId = (route.query.taskId as string) || (route.params.taskId as string);
routeParams.value = {
projectPlanId,
type,
taskId
};
};
//
const routeParams = ref<Record<string, any>>({});
syncRouteParams();
// approvalButtonpageType'edit''update'
const approvalPageType = computed(() => {
if (routeParams.value.type === 'edit') {
return 'update';
}
return routeParams.value.type;
});
//
const isViewMode = computed(() => ['view', 'approval'].includes(routeParams.value.type));
//
const isViewMode = computed(() => routeParams.value.type === 'view' || routeParams.value.type === 'approval');
//
const taskVariables = ref<any>({});
@ -365,45 +356,16 @@ const canEditLimited = computed(() => {
return form.value.projectPlanStatus === '3' || form.value.flowStatus === 'finish';
});
//
//
const isLimitedMode = computed(() => !isBasicEditable.value && canEditLimited.value);
//
const showApprovalButton = computed(() => {
if (isLimitedMode.value) {
return false;
}
if (routeParams.value.type === 'approval') {
return true;
}
return !isViewMode.value;
});
const showLimitedActions = computed(() => !isViewMode.value && isLimitedMode.value);
const showSubmitButtons = computed(() => {
if (approvalPageType.value === 'add') return true;
if (approvalPageType.value === 'update' && form.value.flowStatus && ['draft', 'cancel', 'back'].includes(form.value.flowStatus as string)) {
return true;
}
return false;
});
const showApprovalAction = computed(() => {
return approvalPageType.value === 'approval' && form.value.flowStatus === 'waiting';
});
const showProgressButton = computed(() => {
return !!form.value.projectPlanId && form.value.flowStatus !== 'draft';
});
const projectPlanFormRef = ref<ElFormInstance>();
const buttonLoading = ref(false);
const draftLoading = ref(false);
const submitLoading = ref(false);
const currentAction = ref<'draft' | 'submit' | null>(null);
const projectInfoList = ref<Partial<ProjectInfoVO>[]>([]);
const selectedProjectCode = ref<string>(''); //
const selectedProjectName = ref<string>(''); //
const baseDataLoaded = ref(false);
const projectSelectRef = ref<InstanceType<typeof ProjectSelect>>();
//
const projectChangeList = ref<any[]>([]); //
@ -432,6 +394,7 @@ const createEmptyForm = (): ErpProjectPlanForm => ({
contractId: undefined,
ossId: undefined,
remark: undefined,
activeFlag: '1',
planStageList: []
});
@ -465,6 +428,26 @@ const initBaseData = async () => {
baseDataLoaded.value = true;
};
/** 打开项目选择弹窗 */
const openProjectSelect = () => {
if (!isBasicEditable.value) {
return;
}
projectSelectRef.value?.open();
};
/** 项目选择回调,自动填充项目相关信息 */
const projectInfoSelectCallBack = (data: ProjectInfoVO[]) => {
if (data && data.length > 0) {
const project = data[0];
form.value.projectId = project.projectId;
selectedProjectCode.value = project.projectCode || '';
selectedProjectName.value = project.projectName || '';
// handleProjectChange
handleProjectChange(project.projectId, { syncManagerAndCharge: true, syncPaymentMethod: true });
}
};
/** 添加阶段 */
const handleAddStage = () => {
const newStage = {
@ -593,33 +576,25 @@ const cancel = () => {
dialog.visible = false;
};
/** 提交表单 */
const submitForm = async (status = 'draft') => {
currentAction.value = status as 'draft' | 'submit';
if (currentAction.value === 'draft') {
draftLoading.value = true;
} else if (currentAction.value === 'submit') {
submitLoading.value = true;
}
//
if (!form.value.managerId) {
proxy?.$modal.msgError('请先选择项目');
resetActionLoading();
return;
}
//
const isSuperAdmin = userStore.roles.includes('admin') || userStore.roles.includes('superadmin');
if (!isSuperAdmin && userStore.userId !== form.value.managerId) {
proxy?.$modal.msgError('只有项目经理才能提交项目计划');
resetActionLoading();
return;
}
/** 提交按钮(与项目信息保持一致的处理方式) */
const submitForm = (status: string, mode: boolean) => {
projectPlanFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
try {
//
if (!form.value.managerId) {
proxy?.$modal.msgError('请先选择项目');
buttonLoading.value = false;
return;
}
const isSuperAdmin = userStore.roles.includes('admin') || userStore.roles.includes('superadmin');
if (!isSuperAdmin && userStore.userId !== form.value.managerId) {
proxy?.$modal.msgError('只有项目经理才能提交项目计划');
buttonLoading.value = false;
return;
}
// projectId
if (form.value.planStageList) {
form.value.planStageList.forEach((stage) => {
@ -627,8 +602,8 @@ const submitForm = async (status = 'draft') => {
});
}
//
if (status === 'submit') {
//
if (status !== 'draft') {
const project = projectInfoList.value.find((p) => p.projectId === form.value.projectId);
form.value.flowCode = FlowCodeEnum.PROJECT_PLAN_CODE; //OAPS
form.value.variables = {
@ -636,32 +611,28 @@ const submitForm = async (status = 'draft') => {
projectName: project?.projectName,
managerId: form.value.managerId
};
// 使使
//
form.value.bizExt = {
businessTitle: project?.projectName,
businessCode: form.value.projectPlanCode
};
form.value.projectPlanStatus = '2';
form.value.flowStatus = 'waiting';
const res = await projectPlanSubmitAndFlowStart(form.value).finally(() => (buttonLoading.value = false));
const res = await projectPlanSubmitAndFlowStart(form.value);
form.value = res.data;
buttonLoading.value = false;
proxy?.$modal.msgSuccess('操作成功');
notifyListRefresh();
proxy?.$tab.closePage();
router.go(-1);
} else {
//
if (status === 'draft') {
form.value.projectPlanStatus = '1';
form.value.flowStatus = 'draft';
}
form.value.projectPlanStatus = '1';
form.value.flowStatus = 'draft';
if (form.value.projectPlanId) {
await updateErpProjectPlan(form.value).finally(() => (buttonLoading.value = false));
await updateErpProjectPlan(form.value);
} else {
await addErpProjectPlan(form.value).finally(() => (buttonLoading.value = false));
await addErpProjectPlan(form.value);
}
buttonLoading.value = false;
proxy?.$modal.msgSuccess('暂存成功');
notifyListRefresh();
proxy?.$tab.closePage();
@ -669,39 +640,11 @@ const submitForm = async (status = 'draft') => {
}
} finally {
buttonLoading.value = false;
resetActionLoading();
}
} else {
resetActionLoading();
buttonLoading.value = false;
}
});
};
const handleSubmitAction = (type: 'draft' | 'submit') => {
if (draftLoading.value || submitLoading.value) return;
submitForm(type);
};
const resetActionLoading = () => {
if (currentAction.value === 'draft') {
draftLoading.value = false;
}
if (currentAction.value === 'submit') {
submitLoading.value = false;
}
currentAction.value = null;
};
/** 保存按钮 - 保存为草稿 */
const handleSave = () => {
if (isLimitedMode.value) {
saveLimited();
} else {
submitForm('draft');
}
};
/** 审批完成后的保存逻辑 */
const saveLimited = () => {
projectPlanFormRef.value?.validate(async (valid: boolean) => {
@ -729,6 +672,11 @@ const approvalVerifyOpen = async () => {
await submitVerifyRef.value?.openDialog(routeParams.value.taskId);
};
/** 审批记录 */
const handleApprovalRecord = () => {
approvalRecordRef.value?.init(form.value.projectPlanId);
};
/**
* 获取指定阶段在某个变更中的进度信息
* @param change 变更记录
@ -786,16 +734,15 @@ const loadProjectChangeList = async () => {
const loadFormData = async () => {
await initBaseData();
syncRouteParams();
const projectPlanId = routeParams.value.projectPlanId;
draftLoading.value = false;
submitLoading.value = false;
//
routeParams.value = route.query;
buttonLoading.value = false;
if (projectPlanId && projectPlanId !== '0') {
const res = await getErpProjectPlan(projectPlanId as string);
form.value = res.data;
const id = routeParams.value.id as string;
if (id && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) {
proxy?.$modal.loading('正在加载数据,请稍后...');
const res = await getErpProjectPlan(id);
Object.assign(form.value, res.data);
if (!form.value.flowStatus) {
form.value.flowStatus = 'draft';
}
@ -803,6 +750,12 @@ const loadFormData = async () => {
form.value.planStageList = [];
}
if (form.value.projectId) {
//
const project = projectInfoList.value.find((item) => String(item.projectId) === String(form.value.projectId));
if (project) {
selectedProjectName.value = (project.projectName as string) || '';
selectedProjectCode.value = (project.projectCode as string) || '';
}
handleProjectChange(form.value.projectId, {
syncManagerAndCharge: false,
syncPaymentMethod: false
@ -812,6 +765,7 @@ const loadFormData = async () => {
if (isViewMode.value || form.value.projectPlanStatus === '3') {
await loadProjectChangeList();
}
proxy?.$modal.closeLoading();
} else {
resetForm();
form.value.flowStatus = 'draft';
@ -824,11 +778,6 @@ const goBack = () => {
router.back();
};
/** 审批记录 */
const handleApprovalRecord = () => {
approvalRecordRef.value?.init(form.value.projectPlanId);
};
//
const submitCallback = async () => {
notifyListRefresh();
@ -843,12 +792,8 @@ watch(
}
);
onMounted(() => {
loadFormData();
});
onActivated(() => {
loadFormData();
onMounted(async () => {
await loadFormData();
});
</script>

@ -97,7 +97,11 @@
v-hasPermi="['oa/erp:erpProjectPlan:query']"
></el-button>
</el-tooltip>
<el-tooltip content="修改" placement="top" v-if="scope.row.projectPlanStatus === '1'">
<el-tooltip
content="修改"
placement="top"
v-if="scope.row.projectPlanStatus === '1' || scope.row.flowStatus === 'back' || scope.row.flowStatus === 'cancel'"
>
<el-button link type="success" icon="Edit" @click="handleEdit(scope.row)" v-hasPermi="['oa/erp:erpProjectPlan:edit']"></el-button>
</el-tooltip>
<el-tooltip content="维护进度" placement="top" v-if="scope.row.projectPlanStatus === '3' || scope.row.flowStatus === 'finish'">
@ -212,10 +216,11 @@ import { listUser } from '@/api/system/user';
import { getErpProjectInfoList } from '@/api/oa/erp/projectInfo';
import { getErpContractInfoList } from '@/api/oa/erp/contractInfo';
import { onActivated } from 'vue';
import { useRouter } from 'vue-router';
import { useRoute, useRouter } from 'vue-router';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const route = useRoute();
const router = useRouter();
const { active_flag, project_plan_status, project_phases, collection_stage, wf_business_status } = toRefs<any>(
proxy?.useDict('active_flag', 'project_plan_status', 'project_phases', 'collection_stage', 'wf_business_status')
@ -246,7 +251,7 @@ const dialog = reactive<DialogOption>({
//
const columns = ref<FieldOption[]>([
{ key: 0, label: `序号`, visible: false },
{ key: 0, label: `序号`, visible: true },
{ key: 1, label: `项目计划编号`, visible: true },
{ key: 2, label: `项目编号`, visible: true },
{ key: 3, label: `项目名称`, visible: true },
@ -383,24 +388,40 @@ const handleProjectChangeInDialog = (projectId: number) => {
}
};
/** 新增按钮操作 */
/** 新增按钮操作(与项目信息保持一致) */
const handleAdd = () => {
router.push('/oa/erp/erpProjectPlan/edit/0');
proxy.$tab.closePage(route);
router.push({
path: '/project/erpProjectPlanStage/edit',
query: { type: 'add' }
});
};
/** 查看按钮操作 */
/** 查看按钮操作(与项目信息保持一致) */
const handleView = (row: ErpProjectPlanVO) => {
router.push(`/oa/erp/erpProjectPlan/view/${row.projectPlanId}?type=view`);
proxy.$tab.closePage(route);
router.push({
path: '/project/erpProjectPlanStage/edit',
query: { id: row.projectPlanId, type: 'view' }
});
};
/** 编辑按钮操作 */
/** 编辑按钮操作(与项目信息保持一致) */
const handleEdit = (row: ErpProjectPlanVO) => {
router.push(`/oa/erp/erpProjectPlan/edit/${row.projectPlanId}?type=edit`);
proxy.$tab.closePage(route);
router.push({
path: '/project/erpProjectPlanStage/edit',
query: { id: row.projectPlanId, type: 'update' }
});
};
/** 审批完成后维护延期与进度 */
const handleProgress = (row: ErpProjectPlanVO) => {
router.push(`/oa/erp/erpProjectPlan/edit/${row.projectPlanId}?type=edit`);
proxy.$tab.closePage(route);
router.push({
path: '/project/erpProjectPlanStage/edit',
query: { id: row.projectPlanId, type: 'update' }
});
};
//
@ -408,10 +429,13 @@ const handleApprovalRecord = (row: ErpProjectPlanVO) => {
approvalRecordRef.value?.init(row.projectPlanId);
};
/** 项目计划变更按钮操作 */
/** 项目计划变更按钮操作(与项目信息保持一致) */
const handlePlanChange = (row: ErpProjectPlanVO) => {
// ID
router.push(`/oa/erp/erpProjectChange/edit/0?projectId=${row.projectId}`);
proxy.$tab.closePage(route);
router.push({
path: '/project/erpProjectChange/edit',
query: { type: 'add', projectId: row.projectId }
});
};
/** 甘特图按钮 */

@ -7,8 +7,8 @@
@handleApprovalRecord="handleApprovalRecord"
:buttonLoading="buttonLoading"
:id="form.acceptanceId"
:status="approvalStatus"
:pageType="pageTypeForButton"
:status="form.flowStatus"
:pageType="routeParams.type"
:mode="false"
/>
</el-card>
@ -23,22 +23,13 @@
</el-col>
<el-col :span="12">
<el-form-item label="项目名称" prop="projectName">
<el-select
v-model="selectedProjectId"
filterable
clearable
placeholder="请选择项目"
:disabled="routeParams.type !== 'add'"
:remote-method="remoteSearchProject"
@change="onProjectChange"
>
<el-option
v-for="item in projectOptions"
:key="item.projectId"
:label="item.projectName + ' / ' + item.projectCode"
:value="item.projectId"
/>
</el-select>
<el-input v-model="form.projectName" placeholder="请选择项目" readonly :disabled="routeParams.type !== 'add'">
<template #suffix>
<el-icon v-if="routeParams.type === 'add'" style="cursor: pointer" @click="openProjectSelect">
<Search />
</el-icon>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
@ -89,16 +80,19 @@
<ApprovalRecord ref="approvalRecordRef" />
<SubmitVerify ref="submitVerifyRef" @submit-callback="submitCallback" />
<!-- 项目选择弹窗 -->
<ProjectSelect ref="projectSelectRef" :multiple="false" @confirm-call-back="projectInfoSelectCallBack" />
</div>
</template>
<script setup lang="ts">
<script setup lang="ts" name="ProjectAcceptanceEdit">
import ApprovalButton from '@/components/Process/approvalButton.vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import FileUpload from '@/components/FileUpload/index.vue';
import { useRoute } from 'vue-router';
import ProjectSelect from '@/components/ProjectSelect/index.vue';
import { useRoute, useRouter } from 'vue-router';
import { useUserStore } from '@/store/modules/user';
import { getErpProjectInfoList } from '@/api/oa/erp/projectInfo';
import type { ProjectInfoVO } from '@/api/oa/erp/projectInfo/types';
import {
addProjectAcceptance,
getProjectAcceptance,
@ -110,17 +104,20 @@ import type { ProjectAcceptanceForm } from '@/api/oa/erp/projectAcceptance/types
import { FlowCodeEnum } from '@/enums/OAEnum';
import SubmitVerify from '@/components/Process/submitVerify.vue';
const { proxy } = getCurrentInstance() as any;
const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const route = useRoute();
// path :acceptanceId query id
const routeParams = reactive<{ id?: string | number; type?: string; taskId?: string | number }>({
id: (route.params.acceptanceId || route.query.id) as any,
type: (route.query.type as any) || 'add',
taskId: route.query.taskId as any
});
const router = useRouter();
//
const routeParams = ref<Record<string, any>>({});
const userStore = useUserStore();
const refreshFlagKey = 'projectAcceptanceListShouldRefresh';
/** 通知列表页刷新 */
const notifyListRefresh = () => {
sessionStorage.setItem(refreshFlagKey, Date.now().toString());
};
const isSuperAdmin = computed(() => {
const roles = userStore.roles || [];
return roles.includes('admin') || roles.includes('superadmin');
@ -131,8 +128,7 @@ const formRef = ref<ElFormInstance>();
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
const projectOptions = ref<any[]>([]);
const selectedProjectId = ref<any>();
const projectSelectRef = ref<InstanceType<typeof ProjectSelect>>();
const initFormData: ProjectAcceptanceForm = {
acceptanceId: undefined,
@ -148,6 +144,8 @@ const initFormData: ProjectAcceptanceForm = {
deputyId: undefined,
deputyName: undefined as any,
remark: undefined,
acceptanceStatus: '1',
flowStatus: 'draft' as any,
flowCode: FlowCodeEnum.PROJECT_ACCEPTANCE_CODE,
variables: {},
bizExt: {}
@ -155,23 +153,6 @@ const initFormData: ProjectAcceptanceForm = {
const form = ref<ProjectAcceptanceForm>({ ...initFormData });
const normalizeFlowStatus = (status?: string) => {
if (!status) return 'draft';
const dictList = wf_business_status.value || [];
const match = dictList.find((item: any) => item?.value === status || item?.label === status);
return match?.value || status;
};
//
const approvalStatus = computed(() => normalizeFlowStatus(form.value.flowStatus as any));
const pageTypeForButton = computed(() => {
if (routeParams.taskId) {
return 'approval';
}
return routeParams.type;
});
const rules = {
projectName: [{ required: true, message: '项目名称不能为空', trigger: 'blur' }],
projectCode: [{ required: true, message: '项目号不能为空', trigger: 'blur' }],
@ -188,14 +169,22 @@ const ossIdString = computed({
}
});
const preloadProjectList = async () => {
const res = await getErpProjectInfoList({});
projectOptions.value = res.data || [];
/** 打开项目选择弹窗 */
const openProjectSelect = () => {
if (routeParams.value.type !== 'add') return;
projectSelectRef.value?.open();
};
const remoteSearchProject = async (query: string) => {
const res = await getErpProjectInfoList({ projectName: query });
projectOptions.value = res.data || [];
/** 项目选择回调,自动填充项目相关信息 */
const projectInfoSelectCallBack = async (data: ProjectInfoVO[]) => {
if (data && data.length > 0) {
const project = data[0];
form.value.projectId = project.projectId;
form.value.projectName = project.projectName || '';
form.value.projectCode = project.projectCode || '';
// onProjectChange
await onProjectChange(project.projectId);
}
};
const onProjectChange = async (val: any) => {
@ -209,10 +198,9 @@ const onProjectChange = async (val: any) => {
const applyLeaderFromManager = () => {};
const loadDetail = async () => {
if (!routeParams.id || Number(routeParams.id) === 0) return;
const res = await getProjectAcceptance(routeParams.id as any);
if (!routeParams.value.id) return;
const res = await getProjectAcceptance(routeParams.value.id);
Object.assign(form.value, res.data);
selectedProjectId.value = form.value.projectId;
};
const submitForm = (status: string, mode: boolean) => {
@ -221,16 +209,42 @@ const submitForm = (status: string, mode: boolean) => {
//
if (!form.value.managerId) {
proxy?.$modal.msgError('请先选择项目');
buttonLoading.value = false;
return;
}
if (!isSuperAdmin.value && userStore.userId !== form.value.managerId) {
proxy?.$modal.msgError('只有项目经理才能提交或暂存项目验收确认');
buttonLoading.value = false;
return;
}
buttonLoading.value = true;
try {
if (status === 'draft') {
// draft
//
if (status !== 'draft') {
// waiting
form.value.acceptanceStatus = '2';
form.value.flowStatus = 'waiting' as any;
form.value.flowCode = FlowCodeEnum.PROJECT_ACCEPTANCE_CODE; //OAPA
form.value.variables = {
projectId: form.value.projectId,
projectCode: form.value.projectCode,
projectName: form.value.projectName,
managerId: form.value.managerId,
managerName: form.value.projectManagerName,
chargeId: form.value.chargeId,
deputyId: form.value.deputyId
};
form.value.bizExt = {
businessCode: form.value.acceptanceCode,
businessTitle: form.value.projectName
};
await submitProjectAcceptanceAndFlowStart(form.value);
proxy?.$modal.msgSuccess('操作成功');
notifyListRefresh();
proxy?.$tab.closePage();
router.go(-1);
} else {
// draft
form.value.flowStatus = 'draft' as any;
form.value.acceptanceStatus = '1'; //
@ -240,20 +254,9 @@ const submitForm = (status: string, mode: boolean) => {
await addProjectAcceptance(form.value);
}
proxy?.$modal.msgSuccess('暂存成功');
proxy?.$tab.closePage(proxy.$route);
proxy?.$router.go(-1);
} else {
const variables: any = { managerId: form.value.managerId, managerName: form.value.projectManagerName };
const payload: ProjectAcceptanceForm = {
...form.value,
flowCode: FlowCodeEnum.PROJECT_ACCEPTANCE_CODE, //OAPA
variables,
bizExt: { businessCode: form.value.acceptanceCode, businessTitle: form.value.projectName }
} as any;
await submitProjectAcceptanceAndFlowStart(payload);
proxy?.$modal.msgSuccess('已提交并发起流程');
proxy?.$tab.closePage(proxy.$route);
proxy?.$router.go(-1);
notifyListRefresh();
proxy?.$tab.closePage();
router.go(-1);
}
} finally {
buttonLoading.value = false;
@ -262,31 +265,12 @@ const submitForm = (status: string, mode: boolean) => {
};
const submitCallback = async () => {
await proxy?.$tab.closePage(proxy.$route);
proxy?.$router.go(-1);
await proxy?.$tab.closePage(route);
router.go(-1);
};
const approvalVerifyOpen = async () => {
await submitVerifyRef.value?.openDialog(routeParams.taskId as any);
};
const submitAndStartFlow = async () => {
formRef.value?.validate(async (valid: boolean) => {
if (!valid) return;
buttonLoading.value = true;
try {
const payload: ProjectAcceptanceForm = {
...form.value,
flowCode: FlowCodeEnum.PROJECT_ACCEPTANCE_CODE, //OAPA
variables: {},
bizExt: { businessCode: form.value.acceptanceCode, businessTitle: form.value.projectName }
} as any;
await submitProjectAcceptanceAndFlowStart(payload);
proxy?.$modal.msgSuccess('已提交并发起流程');
} finally {
buttonLoading.value = false;
}
});
await submitVerifyRef.value?.openDialog(routeParams.value.taskId);
};
const handleApprovalRecord = () => {
@ -295,29 +279,63 @@ const handleApprovalRecord = () => {
}
};
// 稿
const formDisabled = computed(() => {
const status = normalizeFlowStatus(form.value.flowStatus as any);
const byStatus = !!status && status !== 'draft' && status !== 'back';
return pageTypeForButton.value === 'view' || pageTypeForButton.value === 'approval' || byStatus;
if (routeParams.value.type === 'view' || routeParams.value.type === 'approval') {
return true;
}
// 稿acceptanceStatus === '1'
if (!form.value.acceptanceStatus) {
return false;
}
return form.value.acceptanceStatus !== '1';
});
onMounted(async () => {
// ID使 path :acceptanceId使 query.id
routeParams.id = (route.params.acceptanceId || route.query.id) as any;
routeParams.type = (route.query.type as any) || (routeParams.id && Number(routeParams.id) !== 0 ? 'update' : 'add');
routeParams.taskId = route.query.taskId as any;
const setNowIfAdd = () => {
const d = new Date();
const s = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
form.value.acceptanceDate = s as any;
};
//
await preloadProjectList();
const loadFormData = async () => {
//
routeParams.value = route.query;
//
form.value = { ...initFormData };
//
await loadDetail();
//
if (routeParams.type === 'add') {
const d = new Date();
const s = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}`;
form.value.acceptanceDate = s as any;
if (routeParams.value.type === 'add') {
setNowIfAdd();
// projectId
const projectId = routeParams.value.projectId;
if (projectId) {
await onProjectChange(projectId);
}
}
};
watch(
() => route.fullPath,
() => {
loadFormData();
}
);
onMounted(async () => {
proxy?.$modal.loading('正在加载数据,请稍后...');
try {
await loadFormData();
} finally {
proxy?.$modal.closeLoading();
}
});
</script>
<style scoped lang="scss">
.card-title {
font-weight: bold;
font-size: 16px;
color: #303133;
}
</style>

@ -1,333 +1,353 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width='100px'>
<el-form-item label="项目号" prop="projectCode">
<el-input v-model="queryParams.projectCode" placeholder="请输入项目号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="验收日期" prop="acceptanceDate">
<el-date-picker
v-model="acceptanceDateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
clearable
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['oa/erp:projectAcceptance:add']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['oa/erp:projectAcceptance:edit']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['oa/erp:projectAcceptance:remove']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['oa/erp:projectAcceptance:export']"></el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" :columns="columns" :search="true" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="projectAcceptanceList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="50" align="center" v-if="columns[0].visible"/>
<el-table-column label="验收确认编号" align="center" prop="acceptanceCode" v-if="columns[1].visible"/>
<el-table-column label="项目号" align="center" prop="projectCode" v-if="columns[2].visible"/>
<el-table-column label="项目名称" align="center" prop="projectName" v-if="columns[3].visible"/>
<el-table-column label="项目经理" align="center" prop="projectManagerName" v-if="columns[4].visible">
<template #default="scope">
<span>{{ scope.row.projectManagerName }}</span>
</template>
</el-table-column>
<el-table-column label="验收日期" align="center" prop="acceptanceDate" width="180" v-if="columns[5].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.acceptanceDate, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="验收单附件" align="center" v-if="columns[6].visible">
<template #default="scope">
<el-button v-if="scope.row.ossId" link type="primary" icon="Download" @click="downloadOss(scope.row.ossId)"></el-button>
<span v-else style="color:#999">暂无附件</span>
</template>
</el-table-column>
<el-table-column label="部门负责人" align="center" prop="chargeName" v-if="columns[7].visible"/>
<el-table-column label="分管副总" align="center" prop="deputyName" v-if="columns[8].visible"/>
<el-table-column label="备注" align="center" prop="remark" v-if="columns[9].visible"/>
<el-table-column label="业务状态" align="center" prop="acceptanceStatus" v-if="columns[10].visible">
<template #default="scope">
<dict-tag :options="acceptance_status" :value="scope.row.acceptanceStatus" />
</template>
</el-table-column>
<el-table-column label="流程状态" align="center" v-if="columns[11].visible">
<template #default="scope">
<dict-tag :options="wf_business_status" :value="scope.row.flowStatus || 'draft'" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="120" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top" v-if="!scope.row.flowStatus || scope.row.flowStatus === 'draft' || scope.row.flowStatus === '草稿' || scope.row.flowStatus === 'back' || scope.row.flowStatus === '驳回'">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/erp:projectAcceptance:edit']"></el-button>
</el-tooltip>
<el-tooltip content="查看" placement="top" v-if="scope.row.flowStatus && scope.row.flowStatus !== 'draft' && scope.row.flowStatus !== '草稿' && scope.row.flowStatus !== 'back' && scope.row.flowStatus !== '驳回'">
<el-button link type="info" icon="DocumentChecked" @click="handleView(scope.row)"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['oa/erp:projectAcceptance:remove']"></el-button>
</el-tooltip>
<el-tooltip content="审批记录" placement="top" v-if="scope.row.acceptanceId">
<el-button link type="warning" icon="Histogram" @click="handleApprovalRecord(scope.row)"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px">
<el-form-item label="项目号" prop="projectCode">
<el-input v-model="queryParams.projectCode" placeholder="请输入项目号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="验收日期" prop="acceptanceDate">
<el-date-picker
v-model="acceptanceDateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
clearable
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
</el-card>
<!-- 对话框逻辑已切换为编辑页流程
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['oa/erp:projectAcceptance:add']"></el-button>
</el-col>
<!-- 顶部修改按钮已停用改由操作列提供入口 -->
<!-- <el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['oa/erp:projectAcceptance:edit']"></el-button>
</el-col> -->
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['oa/erp:projectAcceptance:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['oa/erp:projectAcceptance:export']"></el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" :columns="columns" :search="true" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="projectAcceptanceList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="50" align="center" v-if="columns[0].visible" />
<el-table-column label="验收确认编号" align="center" prop="acceptanceCode" v-if="columns[1].visible" />
<el-table-column label="项目号" align="center" prop="projectCode" v-if="columns[2].visible" />
<el-table-column label="项目名称" align="center" prop="projectName" v-if="columns[3].visible" />
<el-table-column label="项目经理" align="center" prop="projectManagerName" v-if="columns[4].visible">
<template #default="scope">
<span>{{ scope.row.projectManagerName }}</span>
</template>
</el-table-column>
<el-table-column label="验收日期" align="center" prop="acceptanceDate" width="180" v-if="columns[5].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.acceptanceDate, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="验收单附件" align="center" v-if="columns[6].visible">
<template #default="scope">
<el-button v-if="scope.row.ossId" link type="primary" icon="Download" @click="downloadOss(scope.row.ossId)"></el-button>
<span v-else style="color: #999">暂无附件</span>
</template>
</el-table-column>
<el-table-column label="部门负责人" align="center" prop="chargeName" v-if="columns[7].visible" />
<el-table-column label="分管副总" align="center" prop="deputyName" v-if="columns[8].visible" />
<el-table-column label="备注" align="center" prop="remark" v-if="columns[9].visible" />
<el-table-column label="业务状态" align="center" prop="acceptanceStatus" v-if="columns[10].visible">
<template #default="scope">
<dict-tag :options="acceptance_status" :value="scope.row.acceptanceStatus || ''" />
</template>
</el-table-column>
<el-table-column label="流程状态" align="center" v-if="columns[11].visible">
<template #default="scope">
<dict-tag :options="wf_business_status" :value="scope.row.flowStatus || 'draft'" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="120" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip
content="修改"
placement="top"
v-if="!scope.row.flowStatus || scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'back' || scope.row.flowStatus === 'cancel'"
>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/erp:projectAcceptance:edit']"></el-button>
</el-tooltip>
<el-tooltip
content="查看"
placement="top"
v-if="scope.row.flowStatus && scope.row.flowStatus !== 'draft' && scope.row.flowStatus !== 'back'"
>
<el-button link type="info" icon="DocumentChecked" @click="handleView(scope.row)"></el-button>
</el-tooltip>
<el-tooltip
content="删除"
placement="top"
v-if="!scope.row.flowStatus || scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'back' || scope.row.flowStatus === 'cancel'"
>
<el-button
link
type="danger"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['oa/erp:projectAcceptance:remove']"
></el-button>
</el-tooltip>
<el-tooltip content="审批记录" placement="top" v-if="scope.row.flowStatus && scope.row.flowStatus !== 'draft'">
<el-button link type="warning" icon="Histogram" @click="handleApprovalRecord(scope.row)"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 对话框逻辑已切换为编辑页流程
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>...</el-dialog>
-->
<ApprovalRecord ref="approvalRecordRef" />
</div>
<ApprovalRecord ref="approvalRecordRef" />
</div>
</template>
<script setup name="ProjectAcceptance" lang="ts">
import { listProjectAcceptance, getProjectAcceptance, delProjectAcceptance, addProjectAcceptance, updateProjectAcceptance, submitProjectAcceptanceAndFlowStart, prepareProjectAcceptanceByProjectId } from '@/api/oa/erp/projectAcceptance';
import { ProjectAcceptanceVO, ProjectAcceptanceQuery, ProjectAcceptanceForm } from '@/api/oa/erp/projectAcceptance/types';
import { delProjectAcceptance, listProjectAcceptance } from '@/api/oa/erp/projectAcceptance';
import { ProjectAcceptanceForm, ProjectAcceptanceQuery, ProjectAcceptanceVO } from '@/api/oa/erp/projectAcceptance/types';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import { useRoute, useRouter } from 'vue-router';
import { onActivated } from 'vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import { useRouter, useRoute } from 'vue-router';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const router = useRouter();
const route = useRoute();
const { wf_business_status, acceptance_status } = toRefs<any>(proxy?.useDict('wf_business_status', 'acceptance_status'));
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const router = useRouter();
const route = useRoute();
const { wf_business_status, acceptance_status } = toRefs<any>(
proxy?.useDict('wf_business_status', 'acceptance_status')
);
const projectAcceptanceList = ref<ProjectAcceptanceVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const selectedRow = ref<ProjectAcceptanceVO | null>(null);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const projectAcceptanceList = ref<ProjectAcceptanceVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const selectedRow = ref<ProjectAcceptanceVO | null>(null);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const projectAcceptanceFormRef = ref<ElFormInstance>();
const queryFormRef = ref<ElFormInstance>();
const projectAcceptanceFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
//
const columns = ref<FieldOption[]>([
{ key: 0, label: `序号`, visible: true },
{ key: 1, label: `验收确认编号`, visible: true },
{ key: 2, label: `项目号`, visible: false },
{ key: 3, label: `项目名称`, visible: true },
{ key: 4, label: `项目经理`, visible: true },
{ key: 5, label: `验收日期`, visible: true },
{ key: 6, label: `验收单附件`, visible: true },
{ key: 7, label: `部门负责人`, visible: true },
{ key: 8, label: `分管副总`, visible: true },
{ key: 9, label: `备注`, visible: true },
{ key: 10, label: `业务状态`, visible: true },
{ key: 11, label: `流程状态`, visible: false }
]);
//
const columns = ref<FieldOption[]>([
{ key: 0, label: `序号`, visible: true },
{ key: 1, label: `验收确认编号`, visible: true },
{ key: 2, label: `项目号`, visible: false },
{ key: 3, label: `项目名称`, visible: true },
{ key: 4, label: `项目经理`, visible: true },
{ key: 5, label: `验收日期`, visible: true },
{ key: 6, label: `验收单附件`, visible: true },
{ key: 7, label: `部门负责人`, visible: true },
{ key: 8, label: `分管副总`, visible: true },
{ key: 9, label: `备注`, visible: true },
{ key: 10, label: `业务状态`, visible: true },
{ key: 11, label: `流程状态`, visible: false },
]);
const initFormData: ProjectAcceptanceForm = {
acceptanceId: undefined,
projectId: undefined,
projectCode: undefined,
projectName: undefined,
managerId: undefined,
acceptanceDate: undefined,
ossId: undefined,
chargeId: undefined,
deputyId: undefined,
remark: undefined
};
const data = reactive<PageData<ProjectAcceptanceForm, ProjectAcceptanceQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: undefined,
projectCode: undefined,
projectName: undefined,
managerId: undefined,
acceptanceDate: undefined,
ossId: undefined,
chargeId: undefined,
deputyId: undefined,
params: {}
},
rules: {
projectCode: [{ required: true, message: '项目号不能为空', trigger: 'blur' }],
projectName: [{ required: true, message: '项目名称不能为空', trigger: 'blur' }],
acceptanceDate: [{ required: true, message: '验收日期不能为空', trigger: 'change' }]
}
});
const initFormData: ProjectAcceptanceForm = {
acceptanceId: undefined,
projectId: undefined,
projectCode: undefined,
projectName: undefined,
managerId: undefined,
acceptanceDate: undefined,
ossId: undefined,
chargeId: undefined,
deputyId: undefined,
remark: undefined,
const { queryParams, form, rules } = toRefs(data);
const acceptanceDateRange = ref<string[]>();
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
const refreshFlagKey = 'projectAcceptanceListShouldRefresh';
/** 查询项目验收确认列表 */
const getList = async () => {
loading.value = true;
const res = await listProjectAcceptance(queryParams.value);
projectAcceptanceList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
// reset();
// dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
// form.value = {...initFormData};
// projectAcceptanceFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
if (acceptanceDateRange.value && acceptanceDateRange.value.length === 2) {
queryParams.value.params.beginTime = acceptanceDateRange.value[0];
queryParams.value.params.endTime = acceptanceDateRange.value[1];
} else {
if (queryParams.value.params) {
queryParams.value.params.beginTime = undefined as any;
queryParams.value.params.endTime = undefined as any;
}
const data = reactive<PageData<ProjectAcceptanceForm, ProjectAcceptanceQuery>>({
form: {...initFormData},
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: undefined,
projectCode: undefined,
projectName: undefined,
managerId: undefined,
acceptanceDate: undefined,
ossId: undefined,
chargeId: undefined,
deputyId: undefined,
params: {
}
},
rules: {
projectCode: [{ required: true, message: '项目号不能为空', trigger: 'blur' }],
projectName: [{ required: true, message: '项目名称不能为空', trigger: 'blur' }],
acceptanceDate: [{ required: true, message: '验收日期不能为空', trigger: 'change' }]
}
});
}
getList();
};
const { queryParams, form, rules } = toRefs(data);
const acceptanceDateRange = ref<string[]>();
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
acceptanceDateRange.value = undefined; //
handleQuery();
};
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
/** 多选框选中数据 */
const handleSelectionChange = (selection: ProjectAcceptanceVO[]) => {
ids.value = selection.map((item) => item.acceptanceId);
single.value = selection.length != 1;
multiple.value = !selection.length;
selectedRow.value = selection.length === 1 ? selection[0] : null;
};
/** 查询项目验收确认列表 */
const getList = async () => {
loading.value = true;
const res = await listProjectAcceptance(queryParams.value);
projectAcceptanceList.value = res.rows;
total.value = res.total;
loading.value = false;
}
/** 新增按钮操作(与项目信息保持一致) */
const handleAdd = () => {
proxy?.$tab.closePage(route);
router.push({
path: '/project/projectAcceptance/edit',
query: { type: 'add' }
});
};
/** 取消按钮 */
const cancel = () => {
// reset();
// dialog.visible = false;
}
/** 修改按钮操作(与项目信息保持一致) */
const handleUpdate = async (row?: ProjectAcceptanceVO) => {
const target = row || (selectedRow.value as any);
if (!target) return;
proxy?.$tab.closePage(route);
router.push({
path: '/project/projectAcceptance/edit',
query: { id: target.acceptanceId, type: 'update' }
});
};
/** 表单重置 */
const reset = () => {
// form.value = {...initFormData};
// projectAcceptanceFormRef.value?.resetFields();
}
/** 查看按钮操作(与项目信息保持一致) */
const handleView = (row: ProjectAcceptanceVO) => {
proxy?.$tab.closePage(route);
router.push({
path: '/project/projectAcceptance/edit',
query: { id: row.acceptanceId, type: 'view' }
});
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
if (acceptanceDateRange.value && acceptanceDateRange.value.length === 2) {
queryParams.value.params.beginTime = acceptanceDateRange.value[0];
queryParams.value.params.endTime = acceptanceDateRange.value[1];
} else {
if (queryParams.value.params) {
queryParams.value.params.beginTime = undefined as any;
queryParams.value.params.endTime = undefined as any;
}
}
getList();
}
/** 提交按钮 */
// const submitForm = () => { /* */ }
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
}
// const submitAndStartFlow = async () => { /* */ }
/** 多选框选中数据 */
const handleSelectionChange = (selection: ProjectAcceptanceVO[]) => {
ids.value = selection.map(item => item.acceptanceId);
single.value = selection.length != 1;
multiple.value = !selection.length;
selectedRow.value = selection.length === 1 ? selection[0] : null;
}
/** 删除按钮操作 */
const handleDelete = async (row?: ProjectAcceptanceVO) => {
const _acceptanceIds = row?.acceptanceId || ids.value;
await proxy?.$modal.confirm('是否确认删除项目验收确认编号为"' + _acceptanceIds + '"的数据项?').finally(() => (loading.value = false));
await delProjectAcceptance(_acceptanceIds);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 新增按钮操作 */
const handleAdd = () => {
//
proxy?.$tab.closePage(route as any);
router.push({
path: '/project/projectAcceptance/edit',
query: {
type: 'add'
}
});
}
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'oa/erp/projectAcceptance/export',
{
...queryParams.value
},
`projectAcceptance_${new Date().getTime()}.xlsx`
);
};
/** 修改按钮操作 */
const handleUpdate = async (row?: ProjectAcceptanceVO) => {
const target = row || (selectedRow.value as any);
if (!target) return;
// null'draft''稿''back'''
const canEdit = !target.flowStatus || target.flowStatus === 'draft' || target.flowStatus === '草稿' || target.flowStatus === 'back' || target.flowStatus === '驳回';
if (!canEdit) {
proxy?.$modal.msgWarning('当前记录已进入审批或已完成,禁止修改');
return;
}
const pid = target.projectId ?? '';
proxy?.$tab.closePage(route as any);
router.push({
path: '/project/projectAcceptance/edit',
query: {
id: target.acceptanceId,
type: 'update',
projectId: pid
}
});
}
/** 检查是否需要刷新列表 */
const checkShouldRefresh = () => {
const flag = sessionStorage.getItem(refreshFlagKey);
if (flag) {
sessionStorage.removeItem(refreshFlagKey);
handleQuery();
}
};
const handleView = (row: ProjectAcceptanceVO) => {
proxy?.$tab.closePage(route as any);
router.push({
path: '/project/projectAcceptance/edit',
query: {
id: row.acceptanceId,
type: 'view'
}
});
}
onMounted(() => {
getList();
checkShouldRefresh();
});
/** 提交按钮 */
// const submitForm = () => { /* */ }
onActivated(() => {
checkShouldRefresh();
});
// const submitAndStartFlow = async () => { /* */ }
const downloadOss = (ossId: string | number) => {
proxy?.$download.oss(ossId as any);
};
/** 删除按钮操作 */
const handleDelete = async (row?: ProjectAcceptanceVO) => {
const _acceptanceIds = row?.acceptanceId || ids.value;
await proxy?.$modal.confirm('是否确认删除项目验收确认编号为"' + _acceptanceIds + '"的数据项?').finally(() => loading.value = false);
await delProjectAcceptance(_acceptanceIds);
proxy?.$modal.msgSuccess("删除成功");
await getList();
}
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download('oa/erp/projectAcceptance/export', {
...queryParams.value
}, `projectAcceptance_${new Date().getTime()}.xlsx`)
}
onMounted(() => {
getList();
});
const downloadOss = (ossId: string | number) => {
proxy?.$download.oss(ossId as any);
};
const handleApprovalRecord = (row: ProjectAcceptanceVO) => {
approvalRecordRef.value?.init(row.acceptanceId as any);
};
const handleApprovalRecord = (row: ProjectAcceptanceVO) => {
approvalRecordRef.value?.init(row.acceptanceId as any);
};
</script>

@ -7,8 +7,8 @@
@handleApprovalRecord="handleApprovalRecord"
:buttonLoading="buttonLoading"
:id="form.receivingId"
:status="approvalStatus"
:pageType="pageTypeForButton"
:status="form.flowStatus"
:pageType="routeParams.type"
:mode="false"
/>
</el-card>
@ -23,22 +23,13 @@
</el-col>
<el-col :span="12">
<el-form-item label="项目名称" prop="projectName">
<el-select
v-model="selectedProjectId"
filterable
clearable
placeholder="请选择项目"
:disabled="routeParams.type !== 'add'"
:remote-method="remoteSearchProject"
@change="onProjectChange"
>
<el-option
v-for="item in projectOptions"
:key="item.projectId"
:label="item.projectName + ' / ' + item.projectCode"
:value="item.projectId"
/>
</el-select>
<el-input v-model="form.projectName" placeholder="请选择项目" readonly :disabled="routeParams.type !== 'add'">
<template #suffix>
<el-icon v-if="routeParams.type === 'add'" style="cursor: pointer" @click="openProjectSelect">
<Search />
</el-icon>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
@ -83,16 +74,19 @@
<ApprovalRecord ref="approvalRecordRef" />
<SubmitVerify ref="submitVerifyRef" @submit-callback="submitCallback" />
<!-- 项目选择弹窗 -->
<ProjectSelect ref="projectSelectRef" :multiple="false" @confirm-call-back="projectInfoSelectCallBack" />
</div>
</template>
<script setup lang="ts">
<script setup lang="ts" name="ProjectReceivingEdit">
import ApprovalButton from '@/components/Process/approvalButton.vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import FileUpload from '@/components/FileUpload/index.vue';
import { useRoute } from 'vue-router';
import ProjectSelect from '@/components/ProjectSelect/index.vue';
import { useRoute, useRouter } from 'vue-router';
import { useUserStore } from '@/store/modules/user';
import { getErpProjectInfoList } from '@/api/oa/erp/projectInfo';
import type { ProjectInfoVO } from '@/api/oa/erp/projectInfo/types';
import {
addProjectReceiving,
getProjectReceiving,
@ -104,17 +98,20 @@ import type { ProjectReceivingForm } from '@/api/oa/erp/projectReceiving/types';
import { FlowCodeEnum } from '@/enums/OAEnum';
import SubmitVerify from '@/components/Process/submitVerify.vue';
const { proxy } = getCurrentInstance() as any;
const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const route = useRoute();
// path :receivingId query id
const routeParams = reactive<{ id?: string | number; type?: string; taskId?: string | number }>({
id: (route.params.receivingId || route.query.id) as any,
type: (route.query.type as any) || 'add',
taskId: route.query.taskId as any
});
const router = useRouter();
//
const routeParams = ref<Record<string, any>>({});
const userStore = useUserStore();
const refreshFlagKey = 'projectReceivingListShouldRefresh';
/** 通知列表页刷新 */
const notifyListRefresh = () => {
sessionStorage.setItem(refreshFlagKey, Date.now().toString());
};
const isSuperAdmin = computed(() => {
const roles = userStore.roles || [];
return roles.includes('admin') || roles.includes('superadmin');
@ -125,8 +122,7 @@ const formRef = ref<ElFormInstance>();
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
const projectOptions = ref<any[]>([]);
const selectedProjectId = ref<any>();
const projectSelectRef = ref<InstanceType<typeof ProjectSelect>>();
const initFormData: ProjectReceivingForm = {
receivingId: undefined,
@ -135,7 +131,6 @@ const initFormData: ProjectReceivingForm = {
projectName: undefined,
managerId: undefined,
projectManagerName: undefined,
arrivalDate: undefined,
ossId: undefined,
chargeId: undefined,
@ -143,6 +138,8 @@ const initFormData: ProjectReceivingForm = {
deputyId: undefined,
deputyName: undefined as any,
remark: undefined,
receivingStatus: '1',
flowStatus: 'draft' as any,
flowCode: FlowCodeEnum.PROJECT_RECEIVING_CODE,
variables: {},
bizExt: {}
@ -150,23 +147,6 @@ const initFormData: ProjectReceivingForm = {
const form = ref<ProjectReceivingForm>({ ...initFormData });
const normalizeFlowStatus = (status?: string) => {
if (!status) return 'draft';
const dictList = wf_business_status.value || [];
const match = dictList.find((item: any) => item?.value === status || item?.label === status);
return match?.value || status;
};
//
const approvalStatus = computed(() => normalizeFlowStatus(form.value.flowStatus as any));
const pageTypeForButton = computed(() => {
if (routeParams.taskId) {
return 'approval';
}
return routeParams.type;
});
const rules = {
projectName: [{ required: true, message: '项目名称不能为空', trigger: 'blur' }],
projectCode: [{ required: true, message: '项目号不能为空', trigger: 'blur' }],
@ -183,14 +163,22 @@ const ossIdString = computed({
}
});
const remoteSearchProject = async (query: string) => {
const res = await getErpProjectInfoList({ projectName: query });
projectOptions.value = res.data || [];
/** 打开项目选择弹窗 */
const openProjectSelect = () => {
if (routeParams.value.type !== 'add') return;
projectSelectRef.value?.open();
};
const preloadProjectList = async () => {
const res = await getErpProjectInfoList({});
projectOptions.value = res.data || [];
/** 项目选择回调,自动填充项目相关信息 */
const projectInfoSelectCallBack = async (data: ProjectInfoVO[]) => {
if (data && data.length > 0) {
const project = data[0];
form.value.projectId = project.projectId;
form.value.projectName = project.projectName || '';
form.value.projectCode = project.projectCode || '';
// onProjectChange
await onProjectChange(project.projectId);
}
};
const setNowIfAdd = () => {
@ -210,10 +198,9 @@ const onProjectChange = async (val: any) => {
const applyLeaderFromManager = () => {};
const loadDetail = async () => {
if (!routeParams.id || Number(routeParams.id) === 0) return;
const res = await getProjectReceiving(routeParams.id as any);
if (!routeParams.value.id) return;
const res = await getProjectReceiving(routeParams.value.id);
Object.assign(form.value, res.data);
selectedProjectId.value = form.value.projectId;
};
const submitForm = (status: string, mode: boolean) => {
@ -222,16 +209,42 @@ const submitForm = (status: string, mode: boolean) => {
//
if (!form.value.managerId) {
proxy?.$modal.msgError('请先选择项目');
buttonLoading.value = false;
return;
}
if (!isSuperAdmin.value && userStore.userId !== form.value.managerId) {
proxy?.$modal.msgError('只有项目经理才能提交或暂存项目收货确认');
buttonLoading.value = false;
return;
}
buttonLoading.value = true;
try {
if (status === 'draft') {
// draft
//
if (status !== 'draft') {
// waiting
form.value.receivingStatus = '2';
form.value.flowStatus = 'waiting' as any;
form.value.flowCode = FlowCodeEnum.PROJECT_RECEIVING_CODE; //OAPR
form.value.variables = {
projectId: form.value.projectId,
projectCode: form.value.projectCode,
projectName: form.value.projectName,
managerId: form.value.managerId,
managerName: form.value.projectManagerName,
chargeId: form.value.chargeId,
deputyId: form.value.deputyId
};
form.value.bizExt = {
businessCode: form.value.receivingCode,
businessTitle: form.value.projectName
};
await submitProjectReceivingAndFlowStart(form.value);
proxy?.$modal.msgSuccess('操作成功');
notifyListRefresh();
proxy?.$tab.closePage();
router.go(-1);
} else {
// draft
form.value.flowStatus = 'draft' as any;
form.value.receivingStatus = '1'; //
@ -241,20 +254,9 @@ const submitForm = (status: string, mode: boolean) => {
await addProjectReceiving(form.value);
}
proxy?.$modal.msgSuccess('暂存成功');
proxy?.$tab.closePage(proxy.$route);
proxy?.$router.go(-1);
} else {
const variables: any = { managerId: form.value.managerId, managerName: form.value.projectManagerName };
const payload: ProjectReceivingForm = {
...form.value,
flowCode: FlowCodeEnum.PROJECT_RECEIVING_CODE, //OAPR
variables,
bizExt: { businessCode: form.value.receivingCode, businessTitle: form.value.projectName }
} as any;
await submitProjectReceivingAndFlowStart(payload);
proxy?.$modal.msgSuccess('已提交并发起流程');
proxy?.$tab.closePage(proxy.$route);
proxy?.$router.go(-1);
notifyListRefresh();
proxy?.$tab.closePage();
router.go(-1);
}
} finally {
buttonLoading.value = false;
@ -263,31 +265,12 @@ const submitForm = (status: string, mode: boolean) => {
};
const submitCallback = async () => {
await proxy?.$tab.closePage(proxy.$route);
proxy?.$router.go(-1);
await proxy?.$tab.closePage(route);
router.go(-1);
};
const approvalVerifyOpen = async () => {
await submitVerifyRef.value?.openDialog(routeParams.taskId as any);
};
const submitAndStartFlow = async () => {
formRef.value?.validate(async (valid: boolean) => {
if (!valid) return;
buttonLoading.value = true;
try {
const payload: ProjectReceivingForm = {
...form.value,
flowCode: FlowCodeEnum.PROJECT_RECEIVING_CODE, //OAPR
variables: {},
bizExt: { businessCode: form.value.receivingCode, businessTitle: form.value.projectName }
} as any;
await submitProjectReceivingAndFlowStart(payload);
proxy?.$modal.msgSuccess('已提交并发起流程');
} finally {
buttonLoading.value = false;
}
});
await submitVerifyRef.value?.openDialog(routeParams.value.taskId);
};
const handleApprovalRecord = () => {
@ -296,23 +279,57 @@ const handleApprovalRecord = () => {
}
};
// 稿
const formDisabled = computed(() => {
const status = normalizeFlowStatus(form.value.flowStatus as any);
const byStatus = !!status && status !== 'draft' && status !== 'back';
return pageTypeForButton.value === 'view' || pageTypeForButton.value === 'approval' || byStatus;
if (routeParams.value.type === 'view' || routeParams.value.type === 'approval') {
return true;
}
// 稿receivingStatus === '1'
if (!form.value.receivingStatus) {
return false;
}
return form.value.receivingStatus !== '1';
});
onMounted(async () => {
// ID使 path :receivingId使 query.id
routeParams.id = (route.params.receivingId || route.query.id) as any;
routeParams.type = (route.query.type as any) || (routeParams.id && Number(routeParams.id) !== 0 ? 'update' : 'add');
routeParams.taskId = route.query.taskId as any;
const loadFormData = async () => {
//
routeParams.value = route.query;
//
form.value = { ...initFormData };
await preloadProjectList();
await loadDetail();
if (routeParams.type === 'add') {
if (routeParams.value.type === 'add') {
setNowIfAdd();
// projectId
const projectId = routeParams.value.projectId;
if (projectId) {
await onProjectChange(projectId);
}
}
};
watch(
() => route.fullPath,
() => {
loadFormData();
}
);
onMounted(async () => {
proxy?.$modal.loading('正在加载数据,请稍后...');
try {
await loadFormData();
} finally {
proxy?.$modal.closeLoading();
}
});
</script>
<style scoped lang="scss">
.card-title {
font-weight: bold;
font-size: 16px;
color: #303133;
}
</style>

@ -1,327 +1,347 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width='100px'>
<el-form-item label="项目号" prop="projectCode">
<el-input v-model="queryParams.projectCode" placeholder="请输入项目号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="到货日期" prop="arrivalDate">
<el-date-picker
v-model="arrivalDateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
clearable
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['oa/erp:projectReceiving:add']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['oa/erp:projectReceiving:edit']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['oa/erp:projectReceiving:remove']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['oa/erp:projectReceiving:export']"></el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" :columns="columns" :search="true" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="projectReceivingList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="50" align="center" v-if="columns[0].visible"/>
<el-table-column label="收货确认编号" align="center" prop="receivingCode" v-if="columns[1].visible"/>
<el-table-column label="项目号" align="center" prop="projectCode" v-if="columns[2].visible"/>
<el-table-column label="项目名称" align="center" prop="projectName" v-if="columns[3].visible"/>
<el-table-column label="项目经理" align="center" prop="projectManagerName" v-if="columns[4].visible">
<template #default="scope">
<span>{{ scope.row.projectManagerName }}</span>
</template>
</el-table-column>
<el-table-column label="到货日期" align="center" prop="arrivalDate" width="180" v-if="columns[5].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.arrivalDate, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="收货单附件" align="center" v-if="columns[6].visible">
<template #default="scope">
<el-button v-if="scope.row.ossId" link type="primary" icon="Download" @click="downloadOss(scope.row.ossId)"></el-button>
<span v-else style="color:#999">暂无附件</span>
</template>
</el-table-column>
<el-table-column label="部门负责人" align="center" prop="chargeName" v-if="columns[7].visible"/>
<el-table-column label="分管副总" align="center" prop="deputyName" v-if="columns[8].visible"/>
<el-table-column label="备注" align="center" prop="remark" v-if="columns[9].visible"/>
<el-table-column label="业务状态" align="center" prop="receivingStatus" v-if="columns[10].visible">
<template #default="scope">
<dict-tag :options="receiving_status" :value="scope.row.receivingStatus" />
</template>
</el-table-column>
<el-table-column label="流程状态" align="center" v-if="columns[11].visible">
<template #default="scope">
<dict-tag :options="wf_business_status" :value="scope.row.flowStatus || 'draft'" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="120" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top" v-if="!scope.row.flowStatus || scope.row.flowStatus === 'draft' || scope.row.flowStatus === '草稿' || scope.row.flowStatus === 'back' || scope.row.flowStatus === '驳回'">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/erp:projectReceiving:edit']"></el-button>
</el-tooltip>
<el-tooltip content="查看" placement="top" v-if="scope.row.flowStatus && scope.row.flowStatus !== 'draft' && scope.row.flowStatus !== '草稿' && scope.row.flowStatus !== 'back' && scope.row.flowStatus !== '驳回'">
<el-button link type="info" icon="DocumentChecked" @click="handleView(scope.row)"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['oa/erp:projectReceiving:remove']"></el-button>
</el-tooltip>
<el-tooltip content="审批记录" placement="top" v-if="scope.row.receivingId">
<el-button link type="warning" icon="Histogram" @click="handleApprovalRecord(scope.row)"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px">
<el-form-item label="项目号" prop="projectCode">
<el-input v-model="queryParams.projectCode" placeholder="请输入项目号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="到货日期" prop="arrivalDate">
<el-date-picker
v-model="arrivalDateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
clearable
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
</el-card>
<ApprovalRecord ref="approvalRecordRef" />
</div>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['oa/erp:projectReceiving:add']"></el-button>
</el-col>
<!-- 顶部修改按钮已停用改由操作列提供入口 -->
<!-- <el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['oa/erp:projectReceiving:edit']"></el-button>
</el-col> -->
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['oa/erp:projectReceiving:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['oa/erp:projectReceiving:export']"></el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" :columns="columns" :search="true" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="projectReceivingList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="50" align="center" v-if="columns[0].visible" />
<el-table-column label="收货确认编号" align="center" prop="receivingCode" v-if="columns[1].visible" />
<el-table-column label="项目号" align="center" prop="projectCode" v-if="columns[2].visible" />
<el-table-column label="项目名称" align="center" prop="projectName" v-if="columns[3].visible" />
<el-table-column label="项目经理" align="center" prop="projectManagerName" v-if="columns[4].visible">
<template #default="scope">
<span>{{ scope.row.projectManagerName }}</span>
</template>
</el-table-column>
<el-table-column label="到货日期" align="center" prop="arrivalDate" width="180" v-if="columns[5].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.arrivalDate, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="收货单附件" align="center" v-if="columns[6].visible">
<template #default="scope">
<el-button v-if="scope.row.ossId" link type="primary" icon="Download" @click="downloadOss(scope.row.ossId)"></el-button>
<span v-else style="color: #999">暂无附件</span>
</template>
</el-table-column>
<el-table-column label="部门负责人" align="center" prop="chargeName" v-if="columns[7].visible" />
<el-table-column label="分管副总" align="center" prop="deputyName" v-if="columns[8].visible" />
<el-table-column label="备注" align="center" prop="remark" v-if="columns[9].visible" />
<el-table-column label="业务状态" align="center" prop="receivingStatus" v-if="columns[10].visible">
<template #default="scope">
<dict-tag :options="receiving_status" :value="scope.row.receivingStatus || ''" />
</template>
</el-table-column>
<el-table-column label="流程状态" align="center" v-if="columns[11].visible">
<template #default="scope">
<dict-tag :options="wf_business_status" :value="scope.row.flowStatus || 'draft'" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="120" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip
content="修改"
placement="top"
v-if="!scope.row.flowStatus || scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'back' || scope.row.flowStatus === 'cancel'"
>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/erp:projectReceiving:edit']"></el-button>
</el-tooltip>
<el-tooltip
content="查看"
placement="top"
v-if="scope.row.flowStatus && scope.row.flowStatus !== 'draft' && scope.row.flowStatus !== 'back'"
>
<el-button link type="info" icon="DocumentChecked" @click="handleView(scope.row)"></el-button>
</el-tooltip>
<el-tooltip
content="删除"
placement="top"
v-if="!scope.row.flowStatus || scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'back' || scope.row.flowStatus === 'cancel'"
>
<el-button
link
type="danger"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['oa/erp:projectReceiving:remove']"
></el-button>
</el-tooltip>
<el-tooltip content="审批记录" placement="top" v-if="scope.row.flowStatus && scope.row.flowStatus !== 'draft'">
<el-button link type="warning" icon="Histogram" @click="handleApprovalRecord(scope.row)"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<ApprovalRecord ref="approvalRecordRef" />
</div>
</template>
<script setup name="ProjectReceiving" lang="ts">
import { listProjectReceiving, getProjectReceiving, delProjectReceiving, addProjectReceiving, updateProjectReceiving, submitProjectReceivingAndFlowStart, prepareProjectReceivingByProjectId } from '@/api/oa/erp/projectReceiving';
import { ProjectReceivingVO, ProjectReceivingQuery, ProjectReceivingForm } from '@/api/oa/erp/projectReceiving/types';
import { delProjectReceiving, listProjectReceiving } from '@/api/oa/erp/projectReceiving';
import { ProjectReceivingForm, ProjectReceivingQuery, ProjectReceivingVO } from '@/api/oa/erp/projectReceiving/types';
import { useRouter, useRoute } from 'vue-router';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import { useRoute, useRouter } from 'vue-router';
import { onActivated } from 'vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const router = useRouter();
const route = useRoute();
const { wf_business_status, receiving_status } = toRefs<any>(
proxy?.useDict('wf_business_status', 'receiving_status')
);
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const router = useRouter();
const route = useRoute();
const { wf_business_status, receiving_status } = toRefs<any>(proxy?.useDict('wf_business_status', 'receiving_status'));
const projectReceivingList = ref<ProjectReceivingVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const selectedRow = ref<ProjectReceivingVO | null>(null);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const projectReceivingList = ref<ProjectReceivingVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const selectedRow = ref<ProjectReceivingVO | null>(null);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const projectReceivingFormRef = ref<ElFormInstance>();
const queryFormRef = ref<ElFormInstance>();
const projectReceivingFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
//
const columns = ref<FieldOption[]>([
{ key: 0, label: `序号`, visible: true },
{ key: 1, label: `收货确认编号`, visible: true },
{ key: 2, label: `项目号`, visible: false },
{ key: 3, label: `项目名称`, visible: true },
{ key: 4, label: `项目经理`, visible: true },
{ key: 5, label: `到货日期`, visible: true },
{ key: 6, label: `收货单附件`, visible: true },
{ key: 7, label: `部门负责人`, visible: true },
{ key: 8, label: `分管副总`, visible: true },
{ key: 9, label: `备注`, visible: true },
{ key: 10, label: `业务状态`, visible: true },
{ key: 11, label: `流程状态`, visible: false },
]);
//
const columns = ref<FieldOption[]>([
{ key: 0, label: `序号`, visible: true },
{ key: 1, label: `收货确认编号`, visible: true },
{ key: 2, label: `项目号`, visible: false },
{ key: 3, label: `项目名称`, visible: true },
{ key: 4, label: `项目经理`, visible: true },
{ key: 5, label: `到货日期`, visible: true },
{ key: 6, label: `收货单附件`, visible: true },
{ key: 7, label: `部门负责人`, visible: true },
{ key: 8, label: `分管副总`, visible: true },
{ key: 9, label: `备注`, visible: true },
{ key: 10, label: `业务状态`, visible: true },
{ key: 11, label: `流程状态`, visible: false }
]);
const initFormData: ProjectReceivingForm = {
receivingId: undefined,
projectCode: undefined,
projectName: undefined,
managerId: undefined,
arrivalDate: undefined,
ossId: undefined,
chargeId: undefined,
deputyId: undefined,
remark: undefined,
const initFormData: ProjectReceivingForm = {
receivingId: undefined,
projectCode: undefined,
projectName: undefined,
managerId: undefined,
arrivalDate: undefined,
ossId: undefined,
chargeId: undefined,
deputyId: undefined,
remark: undefined
};
const data = reactive<PageData<ProjectReceivingForm, ProjectReceivingQuery>>({
form: { ...initFormData },
queryParams: {
pageNum: 1,
pageSize: 10,
projectCode: undefined,
projectName: undefined,
managerId: undefined,
arrivalDate: undefined,
ossId: undefined,
chargeId: undefined,
deputyId: undefined,
params: {}
},
rules: {
projectCode: [{ required: true, message: '项目号不能为空', trigger: 'blur' }],
projectName: [{ required: true, message: '项目名称不能为空', trigger: 'blur' }],
arrivalDate: [{ required: true, message: '到货日期不能为空', trigger: 'change' }]
}
});
const { queryParams, form, rules } = toRefs(data);
const arrivalDateRange = ref<string[]>();
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
const refreshFlagKey = 'projectReceivingListShouldRefresh';
/** 查询项目收货确认列表 */
const getList = async () => {
loading.value = true;
const res = await listProjectReceiving(queryParams.value);
projectReceivingList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 取消按钮 */
const cancel = () => {
// reset();
// dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
// form.value = {...initFormData};
// projectReceivingFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
if (arrivalDateRange.value && arrivalDateRange.value.length === 2) {
queryParams.value.params.beginTime = arrivalDateRange.value[0];
queryParams.value.params.endTime = arrivalDateRange.value[1];
} else {
if (queryParams.value.params) {
queryParams.value.params.beginTime = undefined as any;
queryParams.value.params.endTime = undefined as any;
}
const data = reactive<PageData<ProjectReceivingForm, ProjectReceivingQuery>>({
form: {...initFormData},
queryParams: {
pageNum: 1,
pageSize: 10,
projectCode: undefined,
projectName: undefined,
managerId: undefined,
arrivalDate: undefined,
ossId: undefined,
chargeId: undefined,
deputyId: undefined,
params: {
}
},
rules: {
projectCode: [{ required: true, message: '项目号不能为空', trigger: 'blur' }],
projectName: [{ required: true, message: '项目名称不能为空', trigger: 'blur' }],
arrivalDate: [{ required: true, message: '到货日期不能为空', trigger: 'change' }]
}
});
}
getList();
};
const { queryParams, form, rules } = toRefs(data);
const arrivalDateRange = ref<string[]>();
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
arrivalDateRange.value = undefined; //
handleQuery();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ProjectReceivingVO[]) => {
ids.value = selection.map((item) => item.receivingId);
single.value = selection.length != 1;
multiple.value = !selection.length;
selectedRow.value = selection.length === 1 ? selection[0] : null;
};
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
/** 新增按钮操作(与项目信息保持一致) */
const handleAdd = () => {
proxy?.$tab.closePage(route);
router.push({
path: '/project/projectReceiving/edit',
query: { type: 'add' }
});
};
/** 查询项目收货确认列表 */
const getList = async () => {
loading.value = true;
const res = await listProjectReceiving(queryParams.value);
projectReceivingList.value = res.rows;
total.value = res.total;
loading.value = false;
}
/** 修改按钮操作(与项目信息保持一致) */
const handleUpdate = async (row?: ProjectReceivingVO) => {
const target = row || (selectedRow.value as any);
if (!target) return;
proxy?.$tab.closePage(route);
router.push({
path: '/project/projectReceiving/edit',
query: { id: target.receivingId, type: 'update' }
});
};
/** 取消按钮 */
const cancel = () => {
// reset();
// dialog.visible = false;
}
/** 查看按钮操作(与项目信息保持一致) */
const handleView = (row: ProjectReceivingVO) => {
proxy?.$tab.closePage(route);
router.push({
path: '/project/projectReceiving/edit',
query: { id: row.receivingId, type: 'view' }
});
};
/** 表单重置 */
const reset = () => {
// form.value = {...initFormData};
// projectReceivingFormRef.value?.resetFields();
}
/** 提交按钮 */
// const submitForm = () => { /* */ }
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
if (arrivalDateRange.value && arrivalDateRange.value.length === 2) {
queryParams.value.params.beginTime = arrivalDateRange.value[0];
queryParams.value.params.endTime = arrivalDateRange.value[1];
} else {
if (queryParams.value.params) {
queryParams.value.params.beginTime = undefined as any;
queryParams.value.params.endTime = undefined as any;
}
}
getList();
}
// const submitAndStartFlow = async () => { /* */ }
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
}
/** 删除按钮操作 */
const handleDelete = async (row?: ProjectReceivingVO) => {
const _receivingIds = row?.receivingId || ids.value;
await proxy?.$modal.confirm('是否确认删除项目收货确认编号为"' + _receivingIds + '"的数据项?').finally(() => (loading.value = false));
await delProjectReceiving(_receivingIds);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ProjectReceivingVO[]) => {
ids.value = selection.map(item => item.receivingId);
single.value = selection.length != 1;
multiple.value = !selection.length;
selectedRow.value = selection.length === 1 ? selection[0] : null;
}
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'oa/erp/projectReceiving/export',
{
...queryParams.value
},
`projectReceiving_${new Date().getTime()}.xlsx`
);
};
/** 新增按钮操作 */
const handleAdd = () => {
//
proxy?.$tab.closePage(route as any);
router.push({
path: '/project/projectReceiving/edit',
query: {
type: 'add'
}
});
}
/** 检查是否需要刷新列表 */
const checkShouldRefresh = () => {
const flag = sessionStorage.getItem(refreshFlagKey);
if (flag) {
sessionStorage.removeItem(refreshFlagKey);
handleQuery();
}
};
/** 修改按钮操作 */
const handleUpdate = async (row?: ProjectReceivingVO) => {
const target = row || (selectedRow.value as any);
if (!target) return;
// null'draft''稿''back'''
const canEdit = !target.flowStatus || target.flowStatus === 'draft' || target.flowStatus === '草稿' || target.flowStatus === 'back' || target.flowStatus === '驳回';
if (!canEdit) {
proxy?.$modal.msgWarning('当前记录已进入审批或已完成,禁止修改');
return;
}
const pid = target.projectId ?? '';
proxy?.$tab.closePage(route as any);
router.push({
path: '/project/projectReceiving/edit',
query: {
id: target.receivingId,
type: 'update',
projectId: pid
}
});
}
onMounted(() => {
getList();
checkShouldRefresh();
});
const handleView = (row: ProjectReceivingVO) => {
proxy?.$tab.closePage(route as any);
router.push({
path: '/project/projectReceiving/edit',
query: {
id: row.receivingId,
type: 'view'
}
});
}
onActivated(() => {
checkShouldRefresh();
});
/** 提交按钮 */
// const submitForm = () => { /* */ }
const downloadOss = (ossId: string | number) => {
proxy?.$download.oss(ossId as any);
};
// const submitAndStartFlow = async () => { /* */ }
/** 删除按钮操作 */
const handleDelete = async (row?: ProjectReceivingVO) => {
const _receivingIds = row?.receivingId || ids.value;
await proxy?.$modal.confirm('是否确认删除项目收货确认编号为"' + _receivingIds + '"的数据项?').finally(() => loading.value = false);
await delProjectReceiving(_receivingIds);
proxy?.$modal.msgSuccess("删除成功");
await getList();
}
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download('oa/erp/projectReceiving/export', {
...queryParams.value
}, `projectReceiving_${new Date().getTime()}.xlsx`)
}
onMounted(() => {
getList();
});
const downloadOss = (ossId: string | number) => {
proxy?.$download.oss(ossId as any);
};
const handleApprovalRecord = (row: ProjectReceivingVO) => {
approvalRecordRef.value?.init(row.receivingId as any);
};
const handleApprovalRecord = (row: ProjectReceivingVO) => {
approvalRecordRef.value?.init(row.receivingId as any);
};
</script>

Loading…
Cancel
Save