diff --git a/src/api/oa/erp/projectContracts/types.ts b/src/api/oa/erp/projectContracts/types.ts index 97b9668..b7951f6 100644 --- a/src/api/oa/erp/projectContracts/types.ts +++ b/src/api/oa/erp/projectContracts/types.ts @@ -44,6 +44,36 @@ export interface ProjectContractsVO { */ projectName?: string; + /** + * 项目类型ID + */ + projectTypeId?: string | number; + + /** + * 部门ID + */ + deptId?: string | number; + + /** + * 项目经理 + */ + managerId?: string | number; + + /** + * 部门负责人 + */ + chargeId?: string | number; + + /** + * 分管副总 + */ + deputyId?: string | number; + + /** + * 抄送人员 + */ + peopleId?: string; + /** * 合同编号 */ diff --git a/src/api/oa/erp/projectInfo/types.ts b/src/api/oa/erp/projectInfo/types.ts index 0e79ac0..9f3b80a 100644 --- a/src/api/oa/erp/projectInfo/types.ts +++ b/src/api/oa/erp/projectInfo/types.ts @@ -54,6 +54,11 @@ export interface ProjectInfoVO { */ projectTypeId: string | number; + /** + * 订单类型(字典 erp_order_type) + */ + orderType?: string; + /** * 付款方式 */ @@ -264,6 +269,11 @@ export interface ProjectInfoForm extends BaseEntity { */ projectTypeId?: string | number; + /** + * 订单类型(字典 erp_order_type) + */ + orderType?: string; + /** * 付款方式 */ @@ -479,6 +489,11 @@ export interface ProjectInfoQuery extends PageQuery { */ projectTypeId?: string | number; + /** + * 订单类型(字典 erp_order_type) + */ + orderType?: string; + /** * 付款方式 */ diff --git a/src/enums/OAEnum.ts b/src/enums/OAEnum.ts index abca634..6d7ad2a 100644 --- a/src/enums/OAEnum.ts +++ b/src/enums/OAEnum.ts @@ -59,10 +59,16 @@ export enum CodeRuleEnum { * 项目类别枚举 */ export enum ProjectCategoryEnum { + /** - * 销售项目(实施、物流) + * 销售项目(实施) */ - SALE_IMPLEMENT = '1', + SALE_IMPLEMENT = '0', + + /** + * 销售项目(物流) + */ + SALE_LOGISTICS = '1', /** * 销售项目(备件) diff --git a/src/views/oa/erp/contractInfo/contractOrderIndex.vue b/src/views/oa/erp/contractInfo/contractOrderIndex.vue index 0a2a999..0bbc9c0 100644 --- a/src/views/oa/erp/contractInfo/contractOrderIndex.vue +++ b/src/views/oa/erp/contractInfo/contractOrderIndex.vue @@ -121,7 +121,11 @@ - + + + @@ -205,8 +209,20 @@ import ApprovalRecord from '@/components/Process/approvalRecord.vue'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; const route = useRoute(); const router = useRouter(); -const { business_direction, project_status, active_flag, contract_flag, project_category, spare_flag, wf_business_status, order_purchase_status, order_delivery_status, order_invoice_status } = toRefs( - proxy?.useDict('business_direction', 'project_status', 'active_flag', 'contract_flag', 'project_category', 'spare_flag', 'wf_business_status', 'order_purchase_status', 'order_delivery_status', 'order_invoice_status') +const { business_direction, project_status, active_flag, contract_flag, project_category, spare_flag, wf_business_status, order_purchase_status, order_delivery_status, order_invoice_status, erp_order_type } = toRefs( + proxy?.useDict( + 'business_direction', + 'project_status', + 'active_flag', + 'contract_flag', + 'project_category', + 'spare_flag', + 'wf_business_status', + 'order_purchase_status', + 'order_delivery_status', + 'order_invoice_status', + 'erp_order_type' + ) ); const approvalRecordRef = ref>(); @@ -269,6 +285,7 @@ const data = reactive<{ queryParams: ProjectInfoQuery }>({ projectCategory: undefined, spareFlag: undefined, projectTypeId: undefined, + orderType: undefined, paymentMethod: undefined, deptId: undefined, managerId: undefined, diff --git a/src/views/oa/erp/contractInfo/index.vue b/src/views/oa/erp/contractInfo/index.vue index 0dd8ffe..d9af35f 100644 --- a/src/views/oa/erp/contractInfo/index.vue +++ b/src/views/oa/erp/contractInfo/index.vue @@ -260,11 +260,11 @@ - + @@ -394,7 +394,7 @@ const columns = ref([ { key: 5, label: `合同大类`, visible: true }, { key: 6, label: `合同类型`, visible: false }, { key: 7, label: `业务方向`, visible: true }, - { key: 8, label: `部门`, visible: true }, + { key: 8, label: `部门`, visible: false }, { key: 9, label: `合同签订日期`, visible: true }, { key: 10, label: `合同总价`, visible: true }, { key: 11, label: `甲方公司`, visible: true }, diff --git a/src/views/oa/erp/contractInfo/orderActivate.vue b/src/views/oa/erp/contractInfo/orderActivate.vue index 2cf98cd..f9ff722 100644 --- a/src/views/oa/erp/contractInfo/orderActivate.vue +++ b/src/views/oa/erp/contractInfo/orderActivate.vue @@ -110,15 +110,10 @@ - - + + + + @@ -126,13 +121,6 @@ - - - - - - - + + + + @@ -482,9 +481,20 @@ const router = useRouter(); // 页面状态:路由、字典、加载状态 // --------------------------------------------------------------------------- const routeParams = ref>({}); -const { business_direction, project_status, contract_flag, project_category, spare_flag, contract_status, project_phases, project_source } = toRefs( - proxy?.useDict('business_direction', 'project_status', 'contract_flag', 'project_category', 'spare_flag', 'contract_status', 'project_phases', 'project_source') +const { business_direction, project_status, contract_flag, project_category, spare_flag, contract_status, project_phases, project_source, erp_order_type } = toRefs( + proxy?.useDict( + 'business_direction', + 'project_status', + 'contract_flag', + 'project_category', + 'spare_flag', + 'contract_status', + 'project_phases', + 'project_source', + 'erp_order_type' + ) ); +const addProjectCategoryOptions = computed(() => (project_category.value || []).filter((item: any) => Number(item.value) >= 0 && Number(item.value) <= 2)); const buttonLoading = ref(false); const projectInfoFormRef = ref(); @@ -499,7 +509,10 @@ const isCodeGenerated = ref(false); // 关联项目(erp_project_contracts):列表、新增弹窗、选择已有项目弹窗 // --------------------------------------------------------------------------- /** 关联项目行类型:projectSource 区分新增/已有;_projectForm 仅新增项目暂存时的表单快照 */ -type ProjectRow = ProjectContractsVO & { _projectForm?: any }; +type ProjectRow = ProjectContractsVO & { + projectTypeId?: string | number; + _projectForm?: any; +}; const projectList = ref([]); const projectListLoading = ref(false); @@ -523,6 +536,7 @@ const addProjectForm = reactive>({ projectCode: undefined, projectName: undefined, projectCategory: undefined, + projectTypeId: undefined, deptId: undefined, managerId: undefined, chargeId: undefined, @@ -534,7 +548,7 @@ const addProjectForm = reactive>({ const addProjectRules = { projectCode: [{ required: true, message: '项目编号不能为空', trigger: 'blur' }], projectName: [{ required: true, message: '项目名称不能为空', trigger: 'blur' }], - projectCategory: [{ required: true, message: '项目类别不能为空', trigger: 'change' }], + projectTypeId: [{ required: true, message: '项目类型不能为空', trigger: 'change' }], deptId: [{ required: true, message: '部门不能为空', trigger: 'change' }], managerId: [{ required: true, message: '项目经理不能为空', trigger: 'change' }], deputyId: [{ required: true, message: '分管副总不能为空', trigger: 'change' }], @@ -559,6 +573,7 @@ const resetAddProjectForm = () => { addProjectForm.projectCode = undefined; addProjectForm.projectName = undefined; addProjectForm.projectCategory = undefined; + addProjectForm.projectTypeId = undefined; addProjectForm.deptId = undefined; addProjectForm.managerId = undefined; addProjectForm.chargeId = undefined; @@ -586,6 +601,7 @@ const submitAddProject = () => { row.managerName = manager ? manager.nickName : undefined; row.amount = addProjectForm.amount as any; row.projectCategory = addProjectForm.projectCategory; + row.projectTypeId = addProjectForm.projectTypeId; proxy?.$modal.msgSuccess('项目修改成功'); } else { // 新增项目行 @@ -602,6 +618,7 @@ const submitAddProject = () => { managerName: manager ? manager.nickName : undefined, amount: addProjectForm.amount as any, projectCategory: addProjectForm.projectCategory, + projectTypeId: addProjectForm.projectTypeId, projectSource: PROJECT_SOURCE_NEW, _projectForm: { ...addProjectForm } }; @@ -632,14 +649,16 @@ const handleEditProject = (row: ProjectRow) => { addProjectForm.projectCode = pf.projectCode ?? row.projectCode; addProjectForm.projectName = pf.projectName ?? row.projectName; addProjectForm.projectCategory = pf.projectCategory ?? row.projectCategory; - addProjectForm.deptId = pf.deptId ?? undefined; - addProjectForm.managerId = pf.managerId ?? undefined; - addProjectForm.chargeId = pf.chargeId ?? undefined; - addProjectForm.deputyId = pf.deputyId ?? undefined; - if (pf.peopleId) { + addProjectForm.projectTypeId = pf.projectTypeId ?? row.projectTypeId; + addProjectForm.deptId = pf.deptId ?? (row as any).deptId ?? undefined; + addProjectForm.managerId = pf.managerId ?? (row as any).managerId ?? undefined; + addProjectForm.chargeId = pf.chargeId ?? (row as any).chargeId ?? undefined; + addProjectForm.deputyId = pf.deputyId ?? (row as any).deputyId ?? undefined; + const peopleIdVal = pf.peopleId ?? (row as any).peopleId; + if (peopleIdVal) { addProjectForm.peopleId = Array.isArray(pf.peopleId) ? pf.peopleId - : String(pf.peopleId) + : String(peopleIdVal) .split(',') .map((id: string) => id.trim()) .filter((id: string) => id) as any; @@ -675,7 +694,31 @@ const loadProjectContractsList = async () => { projectListLoading.value = true; try { const res = await getErpProjectContractsList({ contractId } as any); - projectList.value = (res.data || []).map((item: ProjectContractsVO) => ({ ...(item as any) })); + projectList.value = (res.data || []).map((item: ProjectContractsVO) => { + const row = { ...(item as any) } as ProjectRow; + if (row.projectSource === PROJECT_SOURCE_NEW) { + const peopleIdVal = (row as any).peopleId; + row._projectForm = { + projectCode: row.projectCode, + projectName: row.projectName, + projectCategory: row.projectCategory, + projectTypeId: row.projectTypeId, + deptId: (row as any).deptId, + managerId: (row as any).managerId, + chargeId: (row as any).chargeId, + deputyId: (row as any).deputyId, + peopleId: Array.isArray(peopleIdVal) + ? peopleIdVal + : String(peopleIdVal || '') + .split(',') + .map((id: string) => id.trim()) + .filter((id: string) => id), + amount: row.amount, + remark: row.remark + }; + } + return row; + }); } catch (e) { console.error(e); projectList.value = []; @@ -731,7 +774,7 @@ const projectSelectCallback = (selectedProjects: ProjectInfoVO[]) => { }; // --------------------------------------------------------------------------- -// 下拉与字典:部门、用户、回款阶段、项目类型 +// 下拉与字典:部门、用户、回款阶段 // --------------------------------------------------------------------------- const deptInfoList = ref([]); const getDeptInfoListSelect = async () => { @@ -787,9 +830,38 @@ const projectTypeList = ref([]); const getProjectTypeList = async () => { const res = await listProjectType({} as any); projectTypeList.value = res.data || []; - projectTypeOptions.value = proxy?.handleTree(res.data, 'projectTypeId', 'parentId') || []; + projectTypeOptions.value = proxy?.handleTree(res.data || [], 'projectTypeId', 'parentId') || []; }; +/** 项目类型父级ID -> 项目类别 映射 */ +function mapProjectCategoryByParentId(parentId: string | number | undefined): string | undefined { + const parentIdStr = parentId === undefined || parentId === null ? '' : String(parentId); + const categoryMap: Record = { + '1': ProjectCategoryEnum.SALE_IMPLEMENT, + '8': ProjectCategoryEnum.SALE_LOGISTICS, + '11': ProjectCategoryEnum.SALE_SPARE + }; + return categoryMap[parentIdStr]; +} + +/** 根据项目类型自动回填项目类别(parentId: 1->实施, 8->物流, 11->备件) */ +function syncProjectCategoryByProjectType(projectTypeId: string | number | undefined): void { + if (projectTypeId === undefined || projectTypeId === null || projectTypeId === '') return; + const type = projectTypeList.value.find((item) => String(item.projectTypeId) === String(projectTypeId)); + if (!type) return; + const mappedCategory = mapProjectCategoryByParentId(type.parentId); + if (mappedCategory !== undefined) { + addProjectForm.projectCategory = mappedCategory; + } +} + +watch( + () => addProjectForm.projectTypeId, + (newProjectTypeId) => { + syncProjectCategoryByProjectType(newProjectTypeId); + } +); + // --------------------------------------------------------------------------- // 主表单:合同订单(项目)信息、校验规则、计算属性 // --------------------------------------------------------------------------- @@ -814,6 +886,7 @@ const initFormData: ProjectInfoFormEx = { projectCategory: '9', spareFlag: '1', projectTypeId: undefined, + orderType: undefined, paymentMethod: undefined, deptId: undefined, managerId: undefined, @@ -844,9 +917,8 @@ const data = reactive<{ form: ProjectInfoFormEx; rules: any }>({ projectName: [{ required: true, message: '订单名称不能为空', trigger: 'blur' }], businessDirection: [{ required: true, message: '业务方向不能为空', trigger: 'change' }], projectCategory: [{ required: true, message: '订单类别不能为空', trigger: 'change' }], - projectTypeId: [{ required: true, message: '订单类型不能为空', trigger: 'change' }], + orderType: [{ required: true, message: '订单类型不能为空', trigger: 'change' }], customerContractCode: [{ required: true, message: '客户合同编号不能为空', trigger: 'blur' }], - deptId: [{ required: true, message: '部门不能为空', trigger: 'change' }], peopleId: [{ required: true, message: '抄送人员不能为空', trigger: 'change' }], ossId: [{ required: true, message: '请上传终版合同', trigger: 'change' }] } @@ -895,6 +967,7 @@ function buildProjectContractsPayload(row: ProjectRow, index: number): Record { // 数据加载:合同信息、关联项目、项目阶段计划 // --------------------------------------------------------------------------- const loadSelectOptions = async () => { - await Promise.all([getUserList(), getDeptInfoListSelect(), getPaymentStageList(), getCustomerInfoListSelect()]); + await Promise.all([getUserList(), getDeptInfoListSelect(), getPaymentStageList(), getCustomerInfoListSelect(), getProjectTypeList()]); }; /** 日期格式化为 YYYY-MM-DD */ @@ -1127,7 +1200,6 @@ onMounted(async () => { console.error('获取合同信息失败:', error); } } - await getProjectTypeList(); proxy?.$modal.closeLoading(); }); }); diff --git a/src/views/oa/erp/projectInfo/edit.vue b/src/views/oa/erp/projectInfo/edit.vue index 27838e0..abe8eb5 100644 --- a/src/views/oa/erp/projectInfo/edit.vue +++ b/src/views/oa/erp/projectInfo/edit.vue @@ -21,7 +21,7 @@ 项目关联合同 - + @@ -70,7 +70,7 @@ - + {{ dict.label }} @@ -344,13 +344,36 @@ const projectTypeOptions = ref([]); const projectTypeList = ref([]); /** 查询项目类型列表 */ const getProjectTypeList = async () => { - const params = { spareFlag: form.value.spareFlag } as any; + const params = { } as any; const res = await listProjectType(params); // 保存原始数据用于查找 projectTypeList.value = res.data || []; projectTypeOptions.value = proxy?.handleTree(res.data, 'projectTypeId', 'parentId') || []; }; +/** 项目类型父级ID -> 项目类别 映射 */ +function mapProjectCategoryByParentId(parentId: string | number | undefined): string | undefined { + const parentIdStr = parentId === undefined || parentId === null ? '' : String(parentId); + const categoryMap: Record = { + '1': ProjectCategoryEnum.SALE_IMPLEMENT, + '8': ProjectCategoryEnum.SALE_LOGISTICS, + '11': ProjectCategoryEnum.SALE_SPARE + }; + return categoryMap[parentIdStr]; +} + +/** 根据项目类型自动回填项目类别(仅新增模式) */ +function syncProjectCategoryByProjectType(projectTypeId: string | number | undefined): void { + const mappedCategory = projectTypeId + ? mapProjectCategoryByParentId( + projectTypeList.value.find((item) => String(item.projectTypeId) === String(projectTypeId))?.parentId + ) + : undefined; + if (!mappedCategory) return; + form.value.projectCategory = mappedCategory; + form.value.spareFlag = mappedCategory === ProjectCategoryEnum.SALE_SPARE ? '1' : '0'; +} + type ProjectInfoFormEx = ProjectInfoForm & { flowCode?: string; variables?: any; @@ -406,6 +429,15 @@ const data = reactive<{ form: ProjectInfoFormEx; rules: any }>({ const { form, rules } = toRefs(data); +watch( + () => form.value.projectTypeId, + (newProjectTypeId) => { + const editingMode = !!form.value.projectId; + if (editingMode) return; + syncProjectCategoryByProjectType(newProjectTypeId as any); + } +); + // 生成项目编号 const generateProjectCode = async () => { if (isCodeGenerated.value) return; @@ -554,10 +586,6 @@ onMounted(async () => { if (form.value.projectCode) { isCodeGenerated.value = true; } - // 新增模式:设置项目类别 - if (routeParams.value.projectCategory) { - form.value.projectCategory = routeParams.value.projectCategory as string; - } } form.value.spareFlag = form.value.projectCategory === ProjectCategoryEnum.SALE_SPARE ? '1' : '0'; await getProjectTypeList(); diff --git a/src/views/oa/erp/projectInfo/index.vue b/src/views/oa/erp/projectInfo/index.vue index ad90736..54310c4 100644 --- a/src/views/oa/erp/projectInfo/index.vue +++ b/src/views/oa/erp/projectInfo/index.vue @@ -67,8 +67,7 @@ - 销售项目(实施、物流) - 销售项目(备件) + 销售项目 研发项目 预投项目 @@ -139,7 +138,7 @@ - + @@ -281,7 +280,7 @@ const columns = ref([ { key: 5, label: `业务方向`, visible: true }, { key: 6, label: `项目类别`, visible: true }, { key: 7, label: `备件标识`, visible: true }, - { key: 8, label: `项目类型`, visible: true }, + { key: 8, label: `销售项目类型`, visible: true }, { key: 9, label: `付款方式`, visible: false }, { key: 10, label: `部门`, visible: true }, { key: 11, label: `项目经理`, visible: true },