Merge remote-tracking branch 'origin/dev' into dev

dev
wanghao 3 months ago
commit 2efbf747e2

@ -8,7 +8,7 @@
"type": "module",
"scripts": {
"dev": "set NODE_OPTIONS=--no-experimental-strip-types && vite serve --mode development",
"dev": "vite serve --mode development",
"build:prod": "vite build --mode production",
"build:dev": "vite build --mode development",
"preview": "vite preview",

@ -5,9 +5,9 @@ export interface ContractMaterialVO {
contractMaterialId: string | number;
/**
* 1 2
* 1 2
*/
planFlag: string;
materialFlag: string;
/**
* ID
@ -98,9 +98,9 @@ export interface ContractMaterialForm extends BaseEntity {
contractMaterialId?: string | number;
/**
* 1 2
* 1 2
*/
planFlag?: string;
materialFlag?: string;
/**
* ID
@ -187,9 +187,9 @@ export interface ContractMaterialForm extends BaseEntity {
export interface ContractMaterialQuery extends PageQuery {
/**
* 1 2
* 1 2
*/
planFlag?: string;
materialFlag?: string;
/**
* ID

@ -97,3 +97,14 @@ export const submitProjectChangeAndFlowStart = (data: ErpProjectChangeForm) => {
data: data
});
};
/**
*
* @param projectPlanId
*/
export const queryProjectChangeByProjectPlanId = (projectPlanId: string | number): AxiosPromise<ErpProjectChangeVO[]> => {
return request({
url: '/oa/erp/erpProjectChange/queryByProjectPlanId/' + projectPlanId,
method: 'get'
});
};

@ -254,6 +254,11 @@ export interface ErpProjectChangeVO {
*/
progressList?: ErpProjectChangeProgress[];
/**
*
*/
createName?: string;
}
export interface ErpProjectChangeForm extends BaseEntity {
@ -402,6 +407,11 @@ export interface ErpProjectChangeForm extends BaseEntity {
*/
bizExt?: any;
/**
*
*/
createName?: string;
}
export interface ErpProjectChangeQuery extends PageQuery {
@ -515,6 +525,13 @@ export interface ErpProjectChangeQuery extends PageQuery {
*
*/
params?: any;
/**
*
*/
createName?: string;
}

@ -86,15 +86,3 @@ export function getErpProjectInfoList(query) {
params: query
});
}
/**
* id
* @param query
* @returns {*}
*/
export const listProjectInfoByDept = (query?: ProjectInfoQuery): AxiosPromise<ProjectInfoVO[]> => {
return request({
url: '/oa/erp/projectInfo/listByDept',
method: 'get',
params: query
});
};

@ -104,6 +104,13 @@ export interface ProjectInfoVO {
*/
activeFlag: string;
deptName?: string;
managerName?: string;
chargeName?: string;
deputyName?: string;
}
export interface ProjectInfoForm extends BaseEntity {
@ -227,10 +234,16 @@ export interface ProjectInfoForm extends BaseEntity {
*/
bizExt?: any;
deptName?: string;
managerName?: string;
chargeName?: string;
deputyName?: string;
}
export interface ProjectInfoQuery extends PageQuery {
/**
* 1 2
*/
@ -330,7 +343,12 @@ export interface ProjectInfoQuery extends PageQuery {
*
*/
params?: any;
deptName?: string;
managerName?: string;
chargeName?: string;
deputyName?: string;
}

@ -0,0 +1,88 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { ProjectPurchaseVO, ProjectPurchaseForm, ProjectPurchaseQuery } from '@/api/oa/erp/projectPurchase/types';
/**
*
* @param query
* @returns {*}
*/
export const listProjectPurchase = (query?: ProjectPurchaseQuery): AxiosPromise<ProjectPurchaseVO[]> => {
return request({
url: '/oa/erp/projectPurchase/list',
method: 'get',
params: query
});
};
/**
*
* @param projectPurchaseId
*/
export const getProjectPurchase = (projectPurchaseId: string | number): AxiosPromise<ProjectPurchaseVO> => {
return request({
url: '/oa/erp/projectPurchase/' + projectPurchaseId,
method: 'get'
});
};
/**
*
* @param data
*/
export const addProjectPurchase = (data: ProjectPurchaseForm) => {
return request({
url: '/oa/erp/projectPurchase',
method: 'post',
data: data
});
};
/**
*
* @param data
*/
export const updateProjectPurchase = (data: ProjectPurchaseForm) => {
return request({
url: '/oa/erp/projectPurchase',
method: 'put',
data: data
});
};
/**
*
* @param data
*/
export const projectPurchaseSubmitAndFlowStart = (data: ProjectPurchaseForm) => {
return request({
url: '/oa/erp/projectPurchase/submitAndFlowStart',
method: 'post',
data: data
});
};
/**
*
* @param projectPurchaseId
*/
export const delProjectPurchase = (projectPurchaseId: string | number | Array<string | number>) => {
return request({
url: '/oa/erp/projectPurchase/' + projectPurchaseId,
method: 'delete'
});
};
/**
*
* @param query
* @returns {*}
*/
export function getErpProjectPurchaseList (query) {
return request({
url: '/oa/erp/projectPurchase/getErpProjectPurchaseList',
method: 'get',
params: query
});
};

@ -0,0 +1,291 @@
export interface ProjectPurchaseVO {
/**
* ID
*/
projectPurchaseId: string | number;
/**
* ID
*/
projectId: string | number;
/**
*
*/
projectCode: string;
/**
*
*/
projectName?: string;
/**
*
*/
managerId: string | number;
/**
*
*/
chargeId: string | number;
/**
*
*/
deputyId: string | number;
/**
*
*/
reporterId: string | number;
/**
*
*/
consigneeUser: string;
/**
*
*/
consigneeAddress: string;
/**
*
*/
consigneeContact: string;
/**
* (1 2 3 4 5 6 7)
*/
projectPurchaseStatus: string;
/**
*
*/
flowStatus: string;
/**
*
*/
sortOrder: number;
/**
* /ID
*/
relationId: string | number;
/**
*
*/
remark: string;
/**
* 1 0
*/
spareFlag: string;
/**
* 1 0
*/
activeFlag: string;
}
export interface ProjectPurchaseForm extends BaseEntity {
/**
* ID
*/
projectPurchaseId?: string | number;
/**
* ID
*/
projectId?: string | number;
/**
*
*/
projectCode?: string;
/**
*
*/
projectName?: string;
/**
*
*/
managerId?: string | number;
/**
*
*/
chargeId?: string | number;
/**
*
*/
deputyId?: string | number;
/**
*
*/
reporterId?: string | number;
/**
*
*/
consigneeUser?: string;
/**
*
*/
consigneeAddress?: string;
/**
*
*/
consigneeContact?: string;
/**
* (1 2 3 4 5 6 7)
*/
projectPurchaseStatus?: string;
/**
*
*/
flowStatus?: string;
/**
*
*/
sortOrder?: number;
/**
* /ID
*/
relationId?: string | number;
/**
*
*/
remark?: string;
/**
* 1 0
*/
spareFlag?: string;
/**
* 1 0
*/
activeFlag?: string;
/**
*
*/
flowCode?: any;
/**
*
*/
variables?: any;
/**
*
*/
bizExt?: any;
}
export interface ProjectPurchaseQuery extends PageQuery {
/**
* ID
*/
projectId?: string | number;
/**
*
*/
projectCode?: string;
/**
*
*/
projectName?: string;
/**
*
*/
managerId?: string | number;
/**
*
*/
chargeId?: string | number;
/**
*
*/
deputyId?: string | number;
/**
*
*/
reporterId?: string | number;
/**
*
*/
consigneeUser?: string;
/**
*
*/
consigneeAddress?: string;
/**
*
*/
consigneeContact?: string;
/**
* (1 2 3 4 5 6 7)
*/
projectPurchaseStatus?: string;
/**
*
*/
flowStatus?: string;
/**
*
*/
sortOrder?: number;
/**
* /ID
*/
relationId?: string | number;
/**
* 1 0
*/
spareFlag?: string;
/**
* 1 0
*/
activeFlag?: string;
/**
*
*/
params?: any;
}

@ -0,0 +1,76 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { ProjectPurchaseMaterialVO, ProjectPurchaseMaterialForm, ProjectPurchaseMaterialQuery } from '@/api/oa/erp/projectPurchaseMaterial/types';
/**
*
* @param query
* @returns {*}
*/
export const listProjectPurchaseMaterial = (query?: ProjectPurchaseMaterialQuery): AxiosPromise<ProjectPurchaseMaterialVO[]> => {
return request({
url: '/oa/erp/projectPurchaseMaterial/list',
method: 'get',
params: query
});
};
/**
*
* @param purchaseMaterialId
*/
export const getProjectPurchaseMaterial = (purchaseMaterialId: string | number): AxiosPromise<ProjectPurchaseMaterialVO> => {
return request({
url: '/oa/erp/projectPurchaseMaterial/' + purchaseMaterialId,
method: 'get'
});
};
/**
*
* @param data
*/
export const addProjectPurchaseMaterial = (data: ProjectPurchaseMaterialForm) => {
return request({
url: '/oa/erp/projectPurchaseMaterial',
method: 'post',
data: data
});
};
/**
*
* @param data
*/
export const updateProjectPurchaseMaterial = (data: ProjectPurchaseMaterialForm) => {
return request({
url: '/oa/erp/projectPurchaseMaterial',
method: 'put',
data: data
});
};
/**
*
* @param purchaseMaterialId
*/
export const delProjectPurchaseMaterial = (purchaseMaterialId: string | number | Array<string | number>) => {
return request({
url: '/oa/erp/projectPurchaseMaterial/' + purchaseMaterialId,
method: 'delete'
});
};
/**
*
* @param query
* @returns {*}
*/
export function getErpProjectPurchaseMaterialList (query) {
return request({
url: '/oa/erp/projectPurchaseMaterial/getErpProjectPurchaseMaterialList',
method: 'get',
params: query
});
};

@ -0,0 +1,276 @@
export interface ProjectPurchaseMaterialVO {
/**
* ID
*/
purchaseMaterialId: string | number;
/**
* ID
*/
projectPurchaseId: string | number;
/**
* ID
*/
relationDetailsId: string | number;
/**
* 1 0
*/
spareFlag: string;
/**
* 1 2
*/
purchasePlanFlag: string;
/**
* 1 2
*/
materialFlag: string;
/**
* ID
*/
materialId: string | number;
/**
* ID
*/
relationMaterialId: string | number;
/**
*
*/
materialCode: string;
/**
*
*/
materialName: string;
/**
*
*/
specificationDescription: string;
/**
* ID
*/
unitId: string | number;
/**
*
*/
needPurchaseAmount: number;
/**
*
*/
purchaseAmount: number;
/**
*
*/
arrivalTime: string;
/**
*
*/
serialNumber: number;
/**
*
*/
remark: string;
/**
* 1 0
*/
activeFlag: string;
}
export interface ProjectPurchaseMaterialForm extends BaseEntity {
/**
* ID
*/
purchaseMaterialId?: string | number;
/**
* ID
*/
projectPurchaseId?: string | number;
/**
* ID
*/
relationDetailsId?: string | number;
/**
* 1 0
*/
spareFlag?: string;
/**
* 1 2
*/
purchasePlanFlag?: string;
/**
* 1 2
*/
materialFlag?: string;
/**
* ID
*/
materialId?: string | number;
/**
* ID
*/
relationMaterialId?: string | number;
/**
*
*/
materialCode?: string;
/**
*
*/
materialName?: string;
/**
*
*/
specificationDescription?: string;
/**
* ID
*/
unitId?: string | number;
/**
*
*/
needPurchaseAmount?: number;
/**
*
*/
purchaseAmount?: number;
/**
*
*/
arrivalTime?: string;
/**
*
*/
serialNumber?: number;
/**
*
*/
remark?: string;
/**
* 1 0
*/
activeFlag?: string;
}
export interface ProjectPurchaseMaterialQuery extends PageQuery {
/**
* ID
*/
projectPurchaseId?: string | number;
/**
* ID
*/
relationDetailsId?: string | number;
/**
* 1 0
*/
spareFlag?: string;
/**
* 1 2
*/
purchasePlanFlag?: string;
/**
* 1 2
*/
materialFlag?: string;
/**
* ID
*/
materialId?: string | number;
/**
* ID
*/
relationMaterialId?: string | number;
/**
*
*/
materialCode?: string;
/**
*
*/
materialName?: string;
/**
*
*/
specificationDescription?: string;
/**
* ID
*/
unitId?: string | number;
/**
*
*/
needPurchaseAmount?: number;
/**
*
*/
purchaseAmount?: number;
/**
*
*/
arrivalTime?: string;
/**
*
*/
serialNumber?: number;
/**
* 1 0
*/
activeFlag?: string;
/**
*
*/
params?: any;
}

@ -15,6 +15,19 @@ export const listProjectReport = (query?: ProjectReportQuery): AxiosPromise<Proj
params: query
});
};
/**
* ID
* @param query
* @returns {*}
*/
export const listProjectReportByDept = (query?: ProjectReportQuery): AxiosPromise<ProjectReportVO[]> => {
return request({
url: '/oa/erp/projectReport/listByDept',
method: 'get',
params: query
});
};
/**
*

@ -1,4 +1,4 @@
export interface ProjectReportVO {
export interface ProjectReportVO extends extraInfo {
/**
* ID
*/
@ -67,10 +67,9 @@ export interface ProjectReportVO {
/**
*
*/
projectCode: string;
}
export interface ProjectReportForm extends BaseEntity {
export interface ProjectReportForm extends BaseEntity, extraInfo {
/**
* ID
*/
@ -142,7 +141,7 @@ export interface ProjectReportForm extends BaseEntity {
projectCode?: string;
}
export interface ProjectReportQuery extends PageQuery {
export interface ProjectReportQuery extends PageQuery, extraInfo {
/**
* ID
*/
@ -208,3 +207,13 @@ export interface ProjectReportQuery extends PageQuery {
*/
params?: any;
}
export interface extraInfo {
deptName?: string;
managerName?: string;
chargeName?: string;
deputyName?: string;
}

@ -24,21 +24,9 @@
</transition>
<el-card shadow="hover">
<template v-if="prop.multiple" #header>
<el-tag
v-for="material in selectMaterialList"
:key="material.materialId"
closable
style="margin: 2px"
@close="handleCloseTag(material)"
>
{{ material.saleMaterialName }}
</el-tag>
</template>
<vxe-table
ref="tableRef"
height="400px"
height="300px"
border
show-overflow
:data="projectInfoList"
@ -49,13 +37,13 @@
@checkbox-change="handleCheckboxChange"
>
<vxe-column type="checkbox" width="50" align="center" />
<!-- <vxe-column key="relationMaterialId" title="关联物料ID" align="center" field="relationMaterialId" />-->
<vxe-column key="projectCode" title="项目编码" align="center" field="projectCode" width="120" />
<vxe-column key="projectName" title="项目名称" align="center" field="projectName" width="120" />
<vxe-column key="managerId" title="项目经理" align="center" field="managerId" width="120" />
<vxe-column key="deptId" title="部门ID" align="center" field="deptId" width="120" />
<vxe-column key="chargeId" title="部门负责人" align="center" field="chargeId" width="120" />
<vxe-column key="business_direction" title="业务方向" align="center" field="business_direction" width="120" />
<vxe-column key="managerName" title="项目经理" align="center" field="managerName" width="120" />
<vxe-column key="deptName" title="部门ID" align="center" field="deptName" width="120" />
<vxe-column key="chargeName" title="部门负责人" align="center" field="chargeName" width="120" />
<vxe-column key="deputyName" title="分管副总" align="center" field="deputyName" width="120" />
<!-- <vxe-column key="business_direction" title="业务方向" align="center" field="business_direction" width="120" /> -->
<!-- <vxe-column key="customerName" title="客户名称" align="center" field="customerName" width="120" />
<vxe-column key="saleMaterialName" title="销售物料名称" align="center" field="saleMaterialName" width="120" /> -->
<!-- <vxe-column key="purchasePrice" title="采购单价(元)" align="center" field="purchasePrice" width="120" />-->
@ -91,7 +79,7 @@
import { VxeTableInstance } from 'vxe-table';
import useDialog from '@/hooks/useDialog';
import { ProjectInfoVO, ProjectInfoQuery, ProjectInfoForm } from '@/api/oa/erp/projectInfo/types';
import { listProjectInfoByDept, listProjectInfo, getProjectInfo, delProjectInfo, addProjectInfo, updateProjectInfo } from '@/api/oa/erp/projectInfo';
import { listProjectInfo } from '@/api/oa/erp/projectInfo';
interface PropType {
modelValue?: ProjectInfoVO[] | ProjectInfoVO | undefined;
@ -107,17 +95,17 @@ const prop = withDefaults(defineProps<PropType>(), {
const emit = defineEmits(['update:modelValue', 'confirmCallBack']);
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { active_flag } = toRefs<any>(proxy?.useDict('active_flag'));
const materialInfoList = ref<RelationMaterialVO[]>([]);
const projectInfoList = ref<ProjectInfoVO[]>([]);
const loading = ref(true);
const showSearch = ref(true);
const total = ref(0);
const selectMaterialList = ref<RelationMaterialVO[]>([]);
//
const projectInfoList = ref<ProjectInfoVO[]>([]);
//
const selectProjectList = ref<ProjectInfoVO[]>([]);
const queryFormRef = ref<ElFormInstance>();
const tableRef = ref<VxeTableInstance<RelationMaterialVO>>();
const tableRef = ref<VxeTableInstance<ProjectInfoVO>>();
const projectSelectDialog = useDialog({
title: '项目选择'
@ -172,50 +160,11 @@ const projectSelectData = reactive<PageData<ProjectInfoForm, ProjectInfoQuery>>(
activeFlag: undefined,
params: {}
},
rules: {
contractFlag: [{ required: true, message: '有无合同不能为空', trigger: 'change' }],
projectCode: [{ required: true, message: '项目编号不能为空', trigger: 'blur' }],
projectName: [{ required: true, message: '项目名称不能为空', trigger: 'blur' }],
businessDirection: [{ required: true, message: '业务方向不能为空', trigger: 'change' }],
projectCategory: [{ required: true, message: '项目类别不能为空', trigger: 'change' }]
}
rules: {}
});
const { queryParams, form, rules } = toRefs(projectSelectData);
const defaultSelectMaterialIds = computed(() => computedIds(prop.data));
const confirm = () => {
emit('update:modelValue', selectMaterialList.value);
emit('confirmCallBack', selectMaterialList.value);
projectSelectDialog.closeDialog();
};
const computedIds = (data) => {
if (data === '' || data === null || data === undefined) {
return [];
}
if (data instanceof Array) {
return data.map((item) => String(item));
} else if (typeof data === 'string') {
return data.split(',');
} else if (typeof data === 'number') {
return [String(data)];
} else {
console.warn('<MaterialSelect> The data type of data should be array or string or number, but I received other');
return [];
}
};
/** 根据部门id查询项目信息 */
const getList = async () => {
loading.value = true;
const res = await listProjectInfoByDept(queryParams.value);
projectInfoList.value = res.rows;
total.value = res.total;
loading.value = false;
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
@ -229,81 +178,78 @@ const resetQuery = (refresh = true) => {
refresh && handleQuery();
};
const pageList = async () => {
await getList();
const materials = materialInfoList.value.filter((item) => {
return selectMaterialList.value.some((material) => material.relationMaterialId === item.relationMaterialId);
});
await tableRef.value.setCheckboxRow(materials, true);
};
//
const handleCheckboxChange = (checked) => {
//
if (!prop.multiple && checked.checked) {
tableRef.value.setCheckboxRow(selectMaterialList.value, false);
selectMaterialList.value = [];
tableRef.value.setCheckboxRow(selectProjectList.value, false);
selectProjectList.value = [];
}
const row = checked.row;
if (checked.checked) {
selectMaterialList.value.push(row);
selectProjectList.value.push(row);
} else {
selectMaterialList.value = selectMaterialList.value.filter((item) => {
return item.relationMaterialId !== row.relationMaterialId;
selectProjectList.value = selectProjectList.value.filter((item) => {
return item.projectId !== row.projectId;
});
}
};
const handleCheckboxAll = (checked) => {
const rows = materialInfoList.value;
const rows = projectInfoList.value;
if (checked.checked) {
rows.forEach((row) => {
if (!selectMaterialList.value.some((item) => item.relationMaterialId === row.relationMaterialId)) {
selectMaterialList.value.push(row);
if (!selectProjectList.value.some((item) => item.projectId === row.projectId)) {
selectProjectList.value.push(row);
}
});
} else {
selectMaterialList.value = selectMaterialList.value.filter((item) => {
return !rows.some((row) => row.relationMaterialId === item.relationMaterialId);
selectProjectList.value = selectProjectList.value.filter((item) => {
return !rows.some((row) => row.projectId === item.projectId);
});
}
};
const handleCloseTag = (material: RelationMaterialVO) => {
const relationMaterialId = material.relationMaterialId;
// 使splice
const index = selectMaterialList.value.findIndex((item) => item.relationMaterialId === relationMaterialId);
const rows = selectMaterialList.value[index];
tableRef.value?.setCheckboxRow(rows, false);
selectMaterialList.value.splice(index, 1);
};
const initSelectMaterial = async () => {
if (defaultSelectMaterialIds.value.length > 0) {
//
const materials = materialInfoList.value.filter((item) => {
return defaultSelectMaterialIds.value.includes(String(item.relationMaterialId));
});
selectMaterialList.value = materials;
await nextTick(() => {
tableRef.value.setCheckboxRow(materials, true);
});
}
//
const pageList = async () => {
await getList();
const projectInfo = projectInfoList.value.filter((item) => {
return selectProjectList.value.some((projectInfo) => projectInfo.projectId === item.projectId);
});
await tableRef.value.setCheckboxRow(projectInfo, true);
};
const close = () => {
emit('confirmCallBack', []);
projectSelectDialog.closeDialog();
};
//
const confirm = () => {
emit('update:modelValue', selectProjectList.value);
emit('confirmCallBack', selectProjectList.value);
projectSelectDialog.closeDialog();
};
/** 查询项目信息 */
const getList = async () => {
loading.value = true;
const res = await listProjectInfo(queryParams.value);
projectInfoList.value = res.rows;
total.value = res.total;
loading.value = false;
};
watch(
() => projectSelectDialog.visible.value,
async (newValue: boolean) => {
if (newValue) {
await getList(); //
await initSelectMaterial();
} else {
tableRef.value.clearCheckboxReserve();
tableRef.value.clearCheckboxRow();
resetQuery(false);
selectMaterialList.value = [];
selectProjectList.value = [];
}
}
);

@ -54,6 +54,11 @@ export enum FlowCodeEnum {
*/
CONTRACT_CODE = 'OAC',
/**
* KEY
*/
PROJECT_PURCHASE_CODE = 'xmcg',
/**
* KEY
*/

@ -19,7 +19,7 @@
</template>
<el-empty v-else :description="'消息为空'"></el-empty>
</div>
<div v-if="newsList.length > 0" class="foot-box" @click="onGoToGiteeClick"></div>
<div class="foot-box" @click="onGoToGiteeClick"></div>
</div>
</template>
@ -56,7 +56,6 @@ const onNewsClick = (item: any) => {
//
const onGoToGiteeClick = () => {
// window.open('https://gitee.com/dromara/RuoYi-Vue-Plus/tree/5.X/');
proxy?.$tab.openPage('/task/taskWaiting');
};

@ -102,7 +102,7 @@ export const constantRoutes: RouteRecordRaw[] = [
{
path: 'contractInfo/edit',
component: () => import('@/views/oa/erp/contractInfo/edit.vue'),
name: 'ContractInfoEdit',
name: 'ContractInfoEdit'
},
{
path: 'erpProjectPlan/edit/:projectPlanId',
@ -123,18 +123,18 @@ export const constantRoutes: RouteRecordRaw[] = [
name: 'ErpProjectPlanGantt',
meta: { title: '项目计划甘特图', activeMenu: '/oa/erp/erpProjectPlan' }
},
{
path: 'erpProjectChange/edit',
component: () => import('@/views/oa/erp/erpProjectChange/edit.vue'),
name: 'ErpProjectChangeEdit',
meta: { title: '项目变更', activeMenu: '/oa/erp/erpProjectPlan' }
},
{
path: 'erpProjectChange/edit/:projectChangeId',
component: () => import('@/views/oa/erp/erpProjectChange/edit.vue'),
name: 'ErpProjectChangeEditById',
meta: { title: '项目变更编辑', activeMenu: '/oa/erp/erpProjectPlan' }
}
{
path: 'erpProjectChange/edit',
component: () => import('@/views/oa/erp/erpProjectChange/edit.vue'),
name: 'ErpProjectChangeEdit',
meta: { title: '项目变更', activeMenu: '/oa/erp/erpProjectPlan' }
},
{
path: 'erpProjectChange/edit/:projectChangeId',
component: () => import('@/views/oa/erp/erpProjectChange/edit.vue'),
name: 'ErpProjectChangeEditById',
meta: { title: '项目变更编辑', activeMenu: '/oa/erp/erpProjectPlan' }
}
]
},
{
@ -153,7 +153,7 @@ export const constantRoutes: RouteRecordRaw[] = [
component: () => import('@/views/oa/crm/crmQuoteInfo/edit.vue'),
name: 'crmQuoteInfoView',
meta: { title: '报价单查看', activeMenu: '/oa/crm/crmQuoteInfo' }
},
}
]
},
{
@ -168,14 +168,11 @@ export const constantRoutes: RouteRecordRaw[] = [
meta: { title: '项目预算申请', activeMenu: '/erp/budgetInfo' }
}
]
},
}
];
// 动态路由,基于用户权限动态去加载
export const dynamicRoutes: RouteRecordRaw[] = [
];
export const dynamicRoutes: RouteRecordRaw[] = [];
/**
*

@ -139,7 +139,7 @@
<!-- <el-input v-model="form.templateData" type="textarea" placeholder="请输入内容" />-->
<!-- </el-form-item>-->
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
<el-input type="textarea" v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
<!-- <el-form-item label="激活标识" prop="activeFlag">-->
<!-- <el-radio-group v-model="form.activeFlag">-->
@ -189,8 +189,8 @@ const columns = ref<FieldOption[]>([
{ key: 2, label: `模板名称`, visible: true },
{ key: 3, label: `版本号`, visible: true },
{ key: 4, label: `模板类型`, visible: true },
{ key: 5, label: `模板状态`, visible: true },
{ key: 6, label: `流程状态`, visible: true },
{ key: 5, label: `模板状态`, visible: false },
{ key: 6, label: `流程状态`, visible: false },
{ key: 7, label: `模板数据`, visible: false },
{ key: 8, label: `备注`, visible: true },
{ key: 9, label: `激活标识`, visible: false },

@ -82,7 +82,7 @@ const options = ref({
//
const renderTemplate = (str, data) => {
return str.replace(/#\{(.*?)\}/g, (_, path) => {
let arr = path.split('.');
const arr = path.split('.');
if (arr.length > 0) {
arr[0] = `#{${arr[0]}}`;
}
@ -96,7 +96,7 @@ const rowRenderTemplate = (str, index) => {
return templateData[`^{${path}}`][index] || ' ';
});
res = res.replace(/#\{(.*?)\}/g, (_, path) => {
let arr = path.split('.');
const arr = path.split('.');
if (arr.length > 0) {
arr[0] = `#{${arr[0]}}`;
}
@ -143,12 +143,12 @@ const fillRowData = (e, index) => {
//
const tableTemplate = (table) => {
let data = JSON.parse(JSON.stringify(table));
let arr = [];
const data = JSON.parse(JSON.stringify(table));
const arr = [];
data.forEach((item) => {
let [bol, length] = hasCaretPattern(JSON.parse(JSON.stringify(item.content)));
const [bol, length] = hasCaretPattern(JSON.parse(JSON.stringify(item.content)));
if (bol) {
let obj = JSON.parse(JSON.stringify(item));
const obj = JSON.parse(JSON.stringify(item));
Array(length)
.fill(0)
.forEach((_, index) => {
@ -212,8 +212,8 @@ onMounted(async () => {
getPrintTemplate(route.query.templateId).then((e) => {
template.value = e.data;
const editor = editorRef.value;
let docData = JSON.parse(e.data.templateData || '{}');
let data = fillData(docData);
const docData = JSON.parse(e.data.templateData || '{}');
const data = fillData(docData);
// console.log(data);
// console.log(JSON.parse(e.data.templateData || '{}'));
// editor.setContent(JSON.parse(e.data.templateData || '{}'));

@ -217,15 +217,15 @@
<el-form ref="materialFormRef" :model="materialForm" :rules="materialRules" label-width="120px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="计划标识" prop="planFlag">
<el-radio-group v-model="materialForm.planFlag">
<el-radio v-for="dict in plan_flag" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
<el-form-item label="标准物料标识" prop="materialFlag">
<el-radio-group v-model="materialForm.materialFlag">
<el-radio v-for="dict in material_flag" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物料名称" prop="materialName" v-if="materialForm.planFlag === '1'">
<el-input v-model="materialForm.materialName" placeholder="计划内请点击右侧图标检索物料">
<el-form-item label="物料名称" prop="materialName" v-if="materialForm.materialFlag === '1'">
<el-input v-model="materialForm.materialName" placeholder="请点击右侧图标检索物料">
<template #suffix>
<el-icon style="cursor: pointer" @click="openSaleMaterialSelect">
<Search />
@ -235,12 +235,12 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物料编号" prop="materialCode" v-if="materialForm.planFlag === '1'">
<el-form-item label="物料编号" prop="materialCode" v-if="materialForm.materialFlag === '1'">
<el-input v-model="materialForm.materialCode" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="客户名称" prop="customerName" v-if="materialForm.planFlag === '1'">
<el-form-item label="客户名称" prop="customerName" v-if="materialForm.materialFlag === '1'">
<el-input v-model="materialForm.customerName" disabled />
</el-form-item>
</el-col>
@ -388,8 +388,8 @@ const router = useRouter();
//
const routeParams = ref<Record<string, any>>({});
const { contract_category, business_direction, contract_flag, contract_type, contract_status, plan_flag } = toRefs<any>(
proxy?.useDict('contract_category', 'business_direction', 'contract_flag', 'contract_type', 'contract_status', 'plan_flag')
const { contract_category, business_direction, contract_flag, contract_type, contract_status, material_flag } = toRefs<any>(
proxy?.useDict('contract_category', 'business_direction', 'contract_flag', 'contract_type', 'contract_status', 'material_flag')
);
const buttonLoading = ref(false);
@ -469,7 +469,7 @@ const materialDialog = reactive({
//
const initMaterialFormData: ContractMaterialForm = {
contractMaterialId: undefined,
planFlag: '2',
materialFlag: '2',
contractId: undefined,
productName: undefined,
specificationDescription: undefined,

@ -4,9 +4,9 @@
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="80px">
<el-form-item label="计划标识" prop="planFlag">
<el-select v-model="queryParams.planFlag" placeholder="请选择计划标识" clearable>
<el-option v-for="dict in plan_flag" :key="dict.value" :label="dict.label" :value="dict.value" />
<el-form-item label="标准物料标识" prop="materialFlag">
<el-select v-model="queryParams.materialFlag" placeholder="请选择标准物料标识" clearable>
<el-option v-for="dict in material_flag" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<!-- <el-form-item label="合同ID" prop="contractId">-->
@ -64,9 +64,9 @@
<el-table v-loading="loading" border :data="contractMaterialList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="合同物料ID" align="center" prop="contractMaterialId" v-if="columns[0].visible" />
<el-table-column label="计划标识" align="center" prop="planFlag" v-if="columns[2].visible">
<el-table-column label="标准物料标识" align="center" prop="materialFlag" v-if="columns[2].visible">
<template #default="scope">
<dict-tag :options="plan_flag" :value="scope.row.planFlag" />
<dict-tag :options="material_flag" :value="scope.row.materialFlag" />
</template>
</el-table-column>
<el-table-column label="合同ID" align="center" prop="contractId" v-if="columns[3].visible" />
@ -116,9 +116,9 @@
<!-- 添加或修改合同物料信息对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="contractMaterialFormRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="计划标识" prop="planFlag">
<el-radio-group v-model="form.planFlag">
<el-radio v-for="dict in plan_flag" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
<el-form-item label="标准物料标识" prop="materialFlag">
<el-radio-group v-model="form.materialFlag">
<el-radio v-for="dict in material_flag" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="合同ID" prop="contractId">
@ -184,7 +184,7 @@ import {
import { ContractMaterialVO, ContractMaterialQuery, ContractMaterialForm } from '@/api/oa/erp/contractMaterial/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { active_flag, plan_flag } = toRefs<any>(proxy?.useDict('active_flag', 'plan_flag'));
const { active_flag, material_flag } = toRefs<any>(proxy?.useDict('active_flag', 'material_flag'));
const contractMaterialList = ref<ContractMaterialVO[]>([]);
const buttonLoading = ref(false);
@ -207,7 +207,7 @@ const dialog = reactive<DialogOption>({
const columns = ref<FieldOption[]>([
{ key: 0, label: `合同物料ID`, visible: false },
{ key: 1, label: `租户编号`, visible: false },
{ key: 2, label: `计划标识`, visible: true },
{ key: 2, label: `标准物料标识`, visible: true },
{ key: 3, label: `合同ID`, visible: true },
{ key: 4, label: `产品名称`, visible: true },
{ key: 5, label: `规格描述`, visible: true },
@ -231,7 +231,7 @@ const columns = ref<FieldOption[]>([
const initFormData: ContractMaterialForm = {
contractMaterialId: undefined,
planFlag: undefined,
materialFlag: undefined,
contractId: undefined,
productName: undefined,
specificationDescription: undefined,
@ -251,7 +251,7 @@ const data = reactive<PageData<ContractMaterialForm, ContractMaterialQuery>>({
queryParams: {
pageNum: 1,
pageSize: 10,
planFlag: undefined,
materialFlag: undefined,
contractId: undefined,
productName: undefined,
specificationDescription: undefined,

@ -2,6 +2,7 @@
<div class="p-2">
<el-card shadow="never">
<approvalButton
v-if="!isViewMode"
@submitForm="handleApprovalSubmit"
@approvalVerifyOpen="approvalVerifyOpen"
@handleApprovalRecord="handleApprovalRecord"
@ -11,6 +12,13 @@
:pageType="approvalPageType"
:mode="false"
/>
<!-- 查看模式下显示返回按钮和审批记录 -->
<el-row v-if="isViewMode" :gutter="10" class="mb-2">
<el-col :span="24">
<el-button @click="goBack"></el-button>
<el-button v-if="form.projectChangeStatus === '2' || form.projectChangeStatus === '3'" @click="handleApprovalRecord"></el-button>
</el-col>
</el-row>
<el-form ref="projectChangeFormRef" :model="form" :rules="rules" label-width="140px">
<!-- 基本信息 -->
@ -18,7 +26,21 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="项目名称" prop="projectId">
<el-input v-model="form.projectName" disabled placeholder="项目名称" />
<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-else v-model="form.projectName" disabled placeholder="项目名称" />
</el-form-item>
</el-col>
<el-col :span="12">
@ -204,15 +226,20 @@
<script setup lang="ts" name="ErpProjectChangeEdit">
import { ref, reactive, onMounted, getCurrentInstance, toRefs, watch, onActivated, nextTick, computed } from 'vue';
import type { ComponentInternalInstance } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { getErpProjectChange, addErpProjectChange, updateErpProjectChange, prepareProjectChangeWithInfo, submitProjectChangeAndFlowStart } from '@/api/oa/erp/erpProjectChange';
import { ErpProjectChangeForm, ErpProjectChangeBudget, ErpProjectChangeProgress } from '@/api/oa/erp/erpProjectChange/types';
import { ElMessage, ElMessageBox } from 'element-plus';
import { useUserStore } from '@/store/modules/user';
import type { FormInstance as ElFormInstance } from 'element-plus';
import type { ComponentInternalInstance } from 'vue';
import type { ErpProjectChangeForm, ErpProjectChangeBudget } from '@/api/oa/erp/erpProjectChange/types';
import { useDict } from '@/utils/dict';
// import approvalButton from '@/components/Workflow/approvalButton.vue';
// import SubmitVerify from '@/components/Workflow/SubmitVerify.vue';
// import ApprovalRecord from '@/components/Workflow/ApprovalRecord.vue';
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';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { project_category, change_type, project_phases } = toRefs<any>(proxy?.useDict('project_category', 'change_type', 'project_phases'));
@ -236,8 +263,14 @@ const taskVariables = ref<Record<string, any>>({});
const isViewMode = computed(() => routeParams.value.type === 'view');
//
const isApprovalMode = computed(() => routeParams.value.type === 'approval');
//
const isFormEditable = computed(() => !isViewMode.value && !isApprovalMode.value);
// 稿/
const isFormEditable = computed(() => {
if (isViewMode.value || isApprovalMode.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;
@ -296,6 +329,56 @@ const form = ref<ErpProjectChangeForm>({
...getDefaultForm()
});
// projectId
const projectInfoList = ref([]);
const showProjectSelect = computed(() => {
const projectId = route.query.projectId as string;
return (!routeParams.value.projectChangeId || routeParams.value.projectChangeId === '0') && !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 handleProjectChange = async (projectId: string | number) => {
if (!projectId) return;
try {
const res = await prepareProjectChangeWithInfo(projectId);
if (res.code === 200) {
//
const changeData = {
changeType: form.value.changeType,
currentStatus: form.value.currentStatus,
changeReason: form.value.changeReason,
followUpWork: form.value.followUpWork,
budgetList: form.value.budgetList,
progressList: form.value.progressList
};
Object.assign(form.value, res.data, changeData);
//
if (form.value.changeType) {
changeTypeList.value = form.value.changeType.split(',');
}
}
} catch (error) {
console.error('加载项目信息失败:', error);
ElMessage.error('加载项目信息失败');
}
};
const resetFormState = async () => {
form.value = { ...getDefaultForm() };
changeTypeList.value = [];
@ -436,18 +519,18 @@ const submitCallback = async () => {
const loadFormData = async () => {
await resetFormState();
//
routeParams.value = {
...route.params,
...route.query
};
// 使 query.id/使 params.projectChangeId
const id = routeParams.value.id as string | number;
const projectChangeId = route.params.projectChangeId as string;
const projectId = route.query.projectId as string;
// //
if (id && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) {
// // id
@ -491,7 +574,7 @@ const loadFormData = async () => {
} else if (projectId) {
// ID
await loadProjectDataByProjectId(projectId);
} else {
} else if (!showProjectSelect.value) {
proxy?.$modal.msgError('缺少必要的参数项目ID或变更申请ID');
}
};
@ -500,6 +583,7 @@ let skipNextActivated = false;
onMounted(async () => {
skipNextActivated = true;
await loadProjectList();
await loadFormData();
});

@ -4,9 +4,9 @@
<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="项目ID" prop="projectId">
<!-- <el-form-item label="项目ID" prop="projectId">
<el-input v-model="queryParams.projectId" placeholder="请输入项目ID" clearable @keyup.enter="handleQuery" />
</el-form-item>
</el-form-item>-->
<el-form-item label="项目编号" prop="projectCode">
<el-input v-model="queryParams.projectCode" placeholder="请输入项目编号" clearable @keyup.enter="handleQuery" />
</el-form-item>
@ -18,7 +18,7 @@
<el-option v-for="dict in project_category" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="变更次数" prop="changeNumber">
<!-- <el-form-item label="变更次数" prop="changeNumber">
<el-input v-model="queryParams.changeNumber" placeholder="请输入变更次数" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="项目经理ID" prop="projectManagerId">
@ -59,16 +59,16 @@
<el-form-item label="后续工作" prop="followUpWork">
<el-input v-model="queryParams.followUpWork" placeholder="请输入后续工作" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="项目变更状态(1暂存 2审批中 3可用)" prop="projectChangeStatus">
<el-select v-model="queryParams.projectChangeStatus" placeholder="请选择项目变更状态(1暂存 2审批中 3可用)" clearable >
<el-form-item label="项目变更状态" prop="projectChangeStatus">
<el-select v-model="queryParams.projectChangeStatus" placeholder="请选择项目变更状态" clearable >
<el-option v-for="dict in project_change_status" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="激活标识" prop="activeFlag">
</el-form-item>-->
<!-- <el-form-item label="激活标识" prop="activeFlag">
<el-select v-model="queryParams.activeFlag" placeholder="请选择激活标识" clearable >
<el-option v-for="dict in active_flag" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
</el-form-item>-->
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button>
@ -84,9 +84,9 @@
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['oa/erp:erpProjectChange:add']"></el-button>
</el-col>
<el-col :span="1.5">
<!-- <el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['oa/erp:erpProjectChange:edit']"></el-button>
</el-col>
</el-col> -->
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['oa/erp:erpProjectChange:remove']"></el-button>
</el-col>
@ -130,7 +130,7 @@
<el-table-column label="项目当前情况" align="center" prop="currentStatus" v-if="columns[17].visible"/>
<el-table-column label="变更原因" align="center" prop="changeReason" v-if="columns[18].visible"/>
<el-table-column label="后续工作" align="center" prop="followUpWork" v-if="columns[19].visible"/>
<el-table-column label="项目变更状态(1暂存 2审批中 3可用)" align="center" prop="projectChangeStatus" v-if="columns[20].visible">
<el-table-column label="项目变更状态" align="center" prop="projectChangeStatus" v-if="columns[20].visible">
<template #default="scope">
<dict-tag :options="project_change_status" :value="scope.row.projectChangeStatus"/>
</template>
@ -142,7 +142,7 @@
<dict-tag :options="active_flag" :value="scope.row.activeFlag"/>
</template>
</el-table-column>
<el-table-column label="创建人" align="center" prop="createBy" v-if="columns[26].visible"/>
<el-table-column label="创建人" align="center" prop="createName" v-if="columns[26].visible"/>
<el-table-column label="创建时间" align="center" prop="createTime" width="180" v-if="columns[27].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
@ -150,11 +150,25 @@
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<!-- 查看按钮非草稿状态显示 -->
<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-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/erp:erpProjectChange:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['oa/erp:erpProjectChange:remove']"></el-button>
<!-- 新增变更按钮完成状态显示 -->
<el-tooltip v-if="scope.row.projectChangeStatus === '3'" content="新增变更" placement="top">
<el-button link type="success" icon="Plus" @click="handleAddChange(scope.row)" v-hasPermi="['oa/erp:erpProjectChange:add']"></el-button>
</el-tooltip>
<!-- 审批记录按钮审批中或完成状态显示 -->
<!-- <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-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['oa/erp:erpProjectChange:remove']"></el-button>
</el-tooltip>
</template>
</el-table-column>
@ -162,120 +176,20 @@
<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-form ref="erpProjectChangeFormRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="项目ID" prop="projectId">
<el-input v-model="form.projectId" placeholder="请输入项目ID" />
</el-form-item>
<el-form-item label="项目编号" prop="projectCode">
<el-input v-model="form.projectCode" placeholder="请输入项目编号" />
</el-form-item>
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="form.projectName" placeholder="请输入项目名称" />
</el-form-item>
<el-form-item label="项目类别" prop="projectCategory">
<el-select v-model="form.projectCategory" placeholder="请选择项目类别">
<el-option
v-for="dict in project_category"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="变更类型" prop="changeType">
<el-checkbox-group v-model="form.changeType">
<el-checkbox
v-for="dict in change_type"
:key="dict.value"
:label="dict.value">
{{dict.label}}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="变更次数" prop="changeNumber">
<el-input v-model="form.changeNumber" placeholder="请输入变更次数" />
</el-form-item>
<el-form-item label="项目经理ID" prop="projectManagerId">
<el-input v-model="form.projectManagerId" placeholder="请输入项目经理ID" />
</el-form-item>
<el-form-item label="项目经理姓名" prop="projectManagerName">
<el-input v-model="form.projectManagerName" placeholder="请输入项目经理姓名" />
</el-form-item>
<el-form-item label="部门负责人ID" prop="deptHeadId">
<el-input v-model="form.deptHeadId" placeholder="请输入部门负责人ID" />
</el-form-item>
<el-form-item label="部门负责人姓名" prop="deptHeadName">
<el-input v-model="form.deptHeadName" placeholder="请输入部门负责人姓名" />
</el-form-item>
<el-form-item label="分管副总ID" prop="responsibleVpId">
<el-input v-model="form.responsibleVpId" placeholder="请输入分管副总ID" />
</el-form-item>
<el-form-item label="分管副总姓名" prop="responsibleVpName">
<el-input v-model="form.responsibleVpName" placeholder="请输入分管副总姓名" />
</el-form-item>
<el-form-item label="申请变更时间" prop="applyChangeDate">
<el-date-picker clearable
v-model="form.applyChangeDate"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择申请变更时间">
</el-date-picker>
</el-form-item>
<el-form-item label="项目合同额" prop="contractAmount">
<el-input v-model="form.contractAmount" placeholder="请输入项目合同额" />
</el-form-item>
<el-form-item label="项目合同净额" prop="contractNetAmount">
<el-input v-model="form.contractNetAmount" placeholder="请输入项目合同净额" />
</el-form-item>
<el-form-item label="变更原因" prop="changeReason">
<el-input v-model="form.changeReason" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="后续工作" prop="followUpWork">
<el-input v-model="form.followUpWork" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="项目变更状态(1暂存 2审批中 3可用)" prop="projectChangeStatus">
<el-radio-group v-model="form.projectChangeStatus">
<el-radio
v-for="dict in project_change_status"
:key="dict.value"
:value="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="激活标识" prop="activeFlag">
<el-radio-group v-model="form.activeFlag">
<el-radio
v-for="dict in active_flag"
:key="dict.value"
:value="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="ErpProjectChange" lang="ts">
import { listErpProjectChange, getErpProjectChange, delErpProjectChange, addErpProjectChange, updateErpProjectChange } from '@/api/oa/erp/erpProjectChange';
import { listErpProjectChange, delErpProjectChange } from '@/api/oa/erp/erpProjectChange';
import { ErpProjectChangeVO, ErpProjectChangeQuery, ErpProjectChangeForm } from '@/api/oa/erp/erpProjectChange/types';
import { useRouter } from 'vue-router';
const router = useRouter();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { active_flag, change_type, project_change_status, project_category } = toRefs<any>(proxy?.useDict('active_flag', 'change_type', 'project_change_status', 'project_category'));
const erpProjectChangeList = ref<ErpProjectChangeVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
@ -284,12 +198,6 @@
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const erpProjectChangeFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
//
const columns = ref<FieldOption[]>([
@ -313,7 +221,7 @@
{ key: 17, label: `项目当前情况`, visible: false },
{ key: 18, label: `变更原因`, visible: false },
{ key: 19, label: `后续工作`, visible: false },
{ key: 20, label: `项目变更状态`, visible: true },
{ key: 20, label: `项目变更状态`, visible: false },
{ key: 21, label: `流程状态`, visible: false },
{ key: 22, label: `备注`, visible: false },
{ key: 23, label: `激活标识`, visible: false },
@ -325,34 +233,7 @@
{ key: 29, label: `更新时间`, visible: false },
]);
const initFormData: ErpProjectChangeForm = {
projectChangeId: undefined,
projectId: undefined,
projectCode: undefined,
projectName: undefined,
projectCategory: undefined,
changeType: [],
changeNumber: undefined,
projectManagerId: undefined,
projectManagerName: undefined,
deptHeadId: undefined,
deptHeadName: undefined,
responsibleVpId: undefined,
responsibleVpName: undefined,
applyChangeDate: undefined,
contractAmount: undefined,
contractNetAmount: undefined,
currentStatus: undefined,
changeReason: undefined,
followUpWork: undefined,
projectChangeStatus: undefined,
flowStatus: undefined,
remark: undefined,
activeFlag: undefined,
}
const data = reactive<PageData<ErpProjectChangeForm, ErpProjectChangeQuery>>({
form: {...initFormData},
queryParams: {
const queryParams = reactive<ErpProjectChangeQuery>({
pageNum: 1,
pageSize: 10,
projectId: undefined,
@ -378,22 +259,8 @@
activeFlag: undefined,
params: {
}
},
rules: {
projectChangeId: [
{ required: true, message: "项目变更ID不能为空", trigger: "blur" }
],
projectId: [
{ required: true, message: "项目ID不能为空", trigger: "blur" }
],
applyChangeDate: [
{ required: true, message: "申请变更时间不能为空", trigger: "blur" }
],
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询项目变更申请列表 */
const getList = async () => {
loading.value = true;
@ -403,18 +270,6 @@
loading.value = false;
}
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
}
/** 表单重置 */
const reset = () => {
form.value = {...initFormData};
erpProjectChangeFormRef.value?.resetFields();
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
@ -436,38 +291,33 @@
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = "添加项目变更申请";
//
router.push('/oa/erp/erpProjectChange/edit/0');
}
/** 修改按钮操作 */
const handleUpdate = async (row?: ErpProjectChangeVO) => {
reset();
const _projectChangeId = row?.projectChangeId || ids.value[0]
const res = await getErpProjectChange(_projectChangeId);
Object.assign(form.value, res.data);
form.value.changeType = form.value.changeType.split(",");
dialog.visible = true;
dialog.title = "修改项目变更申请";
const handleUpdate = (row?: ErpProjectChangeVO) => {
const _projectChangeId = row?.projectChangeId || ids.value[0];
//
router.push(`/oa/erp/erpProjectChange/edit/${_projectChangeId}`);
}
/** 提交按钮 */
const submitForm = () => {
erpProjectChangeFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
form.value.changeType = form.value.changeType.join(",");
if (form.value.projectChangeId) {
await updateErpProjectChange(form.value).finally(() => buttonLoading.value = false);
} else {
await addErpProjectChange(form.value).finally(() => buttonLoading.value = false);
}
proxy?.$modal.msgSuccess("操作成功");
dialog.visible = false;
await getList();
}
});
/** 查看按钮操作 */
const handleView = (row: ErpProjectChangeVO) => {
//
router.push(`/oa/erp/erpProjectChange/edit/${row.projectChangeId}?type=view`);
}
/** 新增变更按钮操作 */
const handleAddChange = (row: ErpProjectChangeVO) => {
// projectId
router.push(`/oa/erp/erpProjectChange/edit/0?projectId=${row.projectId}`);
}
/** 审批记录按钮操作 */
const handleApprovalRecord = (row: ErpProjectChangeVO) => {
//
router.push(`/oa/erp/erpProjectChange/edit/${row.projectChangeId}?type=view`);
}
/** 删除按钮操作 */

@ -0,0 +1,629 @@
<template>
<div class="p-2" v-loading="pageLoading">
<approvalButton
class="mb-4"
@submitForm="submitForm"
@approvalVerifyOpen="approvalVerifyOpen"
@handleApprovalRecord="handleApprovalRecord"
:buttonLoading="buttonLoading"
:id="form.projectPurchaseId as any"
:status="form.flowStatus as any"
:pageType="pageType"
:mode="false"
/>
<el-card shadow="never" class="mb-4">
<el-form ref="projectPurchaseFormRef" :model="form" :rules="rules" label-width="120px" :disabled="isReadOnly">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="项目号" prop="projectCode">
<el-input v-model="form.projectCode" placeholder="请选择项目" readonly>
<template #append>
<el-button icon="Search" @click="openProjectSelect" :disabled="isReadOnly">选择</el-button>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="form.projectName" placeholder="请选择项目后自动填充" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目经理" prop="managerId">
<el-select v-model="form.managerId" placeholder="请选择项目后自动填充" disabled>
<el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="部门负责人" prop="chargeId">
<el-select v-model="form.chargeId" placeholder="请选择项目后自动填充" disabled>
<el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="分管副总" prop="deputyId">
<el-select v-model="form.deputyId" placeholder="请选择项目后自动填充" disabled>
<el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="提报人" prop="reporterId">
<el-input v-model="reporterName" placeholder="当前登录用户" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="收货人" prop="consigneeUser">
<el-select v-model="form.consigneeUser" placeholder="请选择收货人" clearable filterable :disabled="isReadOnly" >
<el-option v-for="user in userList" :key="user.nickName" :label="user.nickName" :value="user.nickName" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="收货地址" prop="consigneeAddress">
<el-input type="textarea" v-model="form.consigneeAddress" placeholder="请输入收货地址" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系方式" prop="consigneeContact">
<el-input v-model="form.consigneeContact" placeholder="请输入收货人联系方式" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否备件类" prop="spareFlag">
<el-radio-group v-model="form.spareFlag" disabled>
<el-radio v-for="dict in spare_flag" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="项目采购状态" prop="projectPurchaseStatus">
<el-radio-group v-model="form.projectPurchaseStatus" disabled>
<el-radio v-for="dict in project_purchase_status" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入备注" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<el-card shadow="never">
<template #header>
<div class="flex items-center justify-between">
<span>采购物料</span>
<div>
<el-button icon="Refresh" @click="loadMaterials" class="mr-2" :disabled="materialLoading">刷新</el-button>
<el-button
type="primary"
icon="Plus"
@click="handleAddMaterial"
:disabled="disableMaterialActions"
v-if="!isReadOnly"
>
新增物料
</el-button>
</div>
</div>
</template>
<el-table v-loading="materialLoading" :data="materialList" border>
<el-table-column label="物料名称" prop="materialName" min-width="160" show-overflow-tooltip />
<el-table-column label="物料编码" prop="materialCode" min-width="140" show-overflow-tooltip />
<el-table-column label="规格参数" prop="specificationDescription" min-width="160" show-overflow-tooltip />
<el-table-column label="计划标识" prop="purchasePlanFlag" width="100">
<template #default="scope">
<dict-tag :options="purchase_plan_flag" :value="scope.row.purchasePlanFlag" />
</template>
</el-table-column>
<el-table-column label="标准物料" prop="materialFlag" width="100">
<template #default="scope">
<dict-tag :options="material_flag" :value="scope.row.materialFlag" />
</template>
</el-table-column>
<el-table-column label="需采购数量" prop="needPurchaseAmount" width="120" />
<el-table-column label="本次采购数量" prop="purchaseAmount" width="140" />
<el-table-column label="需求到货时间" prop="arrivalTime" width="180">
<template #default="scope">
<span>{{ proxy?.parseTime?.(scope.row.arrivalTime, '{y}-{m}-{d} {h}:{i}') || scope.row.arrivalTime }}</span>
</template>
</el-table-column>
<el-table-column label="是否备件" prop="spareFlag" width="100">
<template #default="scope">
<dict-tag :options="spare_flag" :value="scope.row.spareFlag" />
</template>
</el-table-column>
<el-table-column label="激活标识" prop="activeFlag" width="100">
<template #default="scope">
<dict-tag :options="active_flag" :value="scope.row.activeFlag" />
</template>
</el-table-column>
<el-table-column label="备注" prop="remark" min-width="160" show-overflow-tooltip />
<el-table-column label="操作" fixed="right" width="160" align="center" v-if="!isReadOnly">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleEditMaterial(scope.row)"></el-button>
<el-button link type="danger" icon="Delete" @click="handleDeleteMaterial(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog :title="materialDialog.title" v-model="materialDialog.visible" width="600px" append-to-body>
<el-form ref="materialFormRef" :model="materialForm" :rules="materialRules" label-width="120px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="计划标识" prop="purchasePlanFlag">
<el-radio-group v-model="materialForm.purchasePlanFlag">
<el-radio v-for="dict in purchase_plan_flag" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="标准物料" prop="materialFlag">
<el-radio-group v-model="materialForm.materialFlag">
<el-radio v-for="dict in material_flag" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物料名称" prop="materialName">
<el-input v-model="materialForm.materialName" placeholder="请输入物料名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物料编码" prop="materialCode">
<el-input v-model="materialForm.materialCode" placeholder="请输入物料编码" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物料ID" prop="materialId">
<el-input v-model="materialForm.materialId" placeholder="请输入物料ID" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="销售物料ID" prop="relationMaterialId">
<el-input v-model="materialForm.relationMaterialId" placeholder="请输入销售物料ID" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="详细参数" prop="specificationDescription">
<el-input v-model="materialForm.specificationDescription" placeholder="请输入详细参数" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="单位ID" prop="unitId">
<el-input v-model="materialForm.unitId" placeholder="请输入单位ID" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否备件" prop="spareFlag">
<el-radio-group v-model="materialForm.spareFlag">
<el-radio v-for="dict in spare_flag" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="需采购数量" prop="needPurchaseAmount">
<el-input-number v-model="materialForm.needPurchaseAmount" :min="0" :controls="false" class="w-full" placeholder="请输入数量" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="本次采购数量" prop="purchaseAmount">
<el-input-number v-model="materialForm.purchaseAmount" :min="0" :controls="false" class="w-full" placeholder="请输入数量" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="需求到货时间" prop="arrivalTime">
<el-date-picker v-model="materialForm.arrivalTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择需求到货时间" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="序号" prop="serialNumber">
<el-input-number v-model="materialForm.serialNumber" :min="0" :controls="false" class="w-full" placeholder="请输入序号" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="materialForm.remark" type="textarea" :rows="3" placeholder="请输入备注" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="激活标识" prop="activeFlag">
<el-radio-group v-model="materialForm.activeFlag">
<el-radio v-for="dict in active_flag" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" :loading="materialLoading" @click="submitMaterialForm"> </el-button>
<el-button @click="materialDialog.visible = false"> </el-button>
</div>
</template>
</el-dialog>
<submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
<approvalRecord ref="approvalRecordRef" />
<ProjectSelect ref="projectSelectRef" :multiple="false" @confirm-call-back="projectInfoSelectCallBack" />
</div>
</template>
<script setup name="ProjectPurchaseEdit" lang="ts">
import { computed, reactive, ref, watch, getCurrentInstance, toRefs } from 'vue';
import type { ComponentInternalInstance } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import type { FormInstance } from 'element-plus';
import { addProjectPurchase, getProjectPurchase, updateProjectPurchase, projectPurchaseSubmitAndFlowStart } from '@/api/oa/erp/projectPurchase';
import type { ProjectPurchaseForm } from '@/api/oa/erp/projectPurchase/types';
import {
listProjectPurchaseMaterial,
addProjectPurchaseMaterial,
updateProjectPurchaseMaterial,
delProjectPurchaseMaterial
} from '@/api/oa/erp/projectPurchaseMaterial';
import type { ProjectPurchaseMaterialVO, ProjectPurchaseMaterialForm } from '@/api/oa/erp/projectPurchaseMaterial/types';
import SubmitVerify from '@/components/Process/submitVerify.vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import ApprovalButton from '@/components/Process/approvalButton.vue';
import ProjectSelect from '@/components/ProjectSelect/index.vue';
import { FlowCodeEnum } from '@/enums/OAEnum';
import type { ProjectInfoVO } from '@/api/oa/erp/projectInfo/types';
import { listUser } from '@/api/system/user';
import type { UserVO, UserQuery } from '@/api/system/user/types';
import { useUserStore } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const router = useRouter();
const route = useRoute();
const userStore = useUserStore();
const { active_flag, project_purchase_status, spare_flag, purchase_plan_flag, material_flag } = toRefs<any>(
proxy?.useDict('active_flag', 'project_purchase_status', 'spare_flag', 'purchase_plan_flag', 'material_flag')
);
const routeParams = reactive<Record<string, any>>({});
const pageType = ref<string>((route.query.type as string) || 'add');
const isReadOnly = computed(() => pageType.value === 'view' || pageType.value === 'approval');
const pageLoading = ref(false);
const buttonLoading = ref(false);
const projectPurchaseFormRef = ref<FormInstance>();
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
const projectSelectRef = ref<InstanceType<typeof ProjectSelect>>();
const taskVariables = ref<Record<string, any>>({});
const initFormData: ProjectPurchaseForm & { projectName?: string } = {
projectPurchaseId: undefined,
projectId: undefined,
projectCode: undefined,
projectName: undefined,
managerId: undefined,
chargeId: undefined,
deputyId: undefined,
reporterId: undefined,
consigneeUser: undefined,
consigneeAddress: undefined,
consigneeContact: undefined,
projectPurchaseStatus: undefined,
flowStatus: undefined,
sortOrder: undefined,
relationId: undefined,
remark: undefined,
spareFlag: undefined,
activeFlag: undefined
};
const form = ref<ProjectPurchaseForm & { projectName?: string }>({ ...initFormData });
const rules = {
projectCode: [{ required: true, message: '项目号不能为空', trigger: 'blur' }],
consigneeUser: [{ required: true, message: '收货人不能为空', trigger: 'blur' }],
consigneeAddress: [{ required: true, message: '收货地址不能为空', trigger: 'blur' }]
};
const materialList = ref<ProjectPurchaseMaterialVO[]>([]);
const materialLoading = ref(false);
const disableMaterialActions = computed(() => isReadOnly.value || !form.value.projectPurchaseId || materialLoading.value);
//
const userList = ref<UserVO[]>([]);
const getUserList = async () => {
const params: UserQuery = { pageNum: 1, pageSize: 9999 };
const res = await listUser(params);
userList.value = res.rows || [];
};
//
const reporterName = computed(() => {
return userStore.nickname || '';
});
const materialDialog = reactive({
visible: false,
title: ''
});
const materialFormRef = ref<FormInstance>();
const initMaterialFormData: ProjectPurchaseMaterialForm = {
purchaseMaterialId: undefined,
projectPurchaseId: undefined,
relationDetailsId: undefined,
spareFlag: undefined,
purchasePlanFlag: undefined,
materialFlag: undefined,
materialId: undefined,
relationMaterialId: undefined,
materialCode: undefined,
materialName: undefined,
specificationDescription: undefined,
unitId: undefined,
needPurchaseAmount: undefined,
purchaseAmount: undefined,
arrivalTime: undefined,
serialNumber: undefined,
remark: undefined,
activeFlag: undefined
};
const materialForm = ref<ProjectPurchaseMaterialForm>({ ...initMaterialFormData });
const materialRules = {
materialName: [{ required: true, message: '物料名称不能为空', trigger: 'blur' }],
purchaseAmount: [{ required: true, message: '采购数量不能为空', trigger: 'blur' }]
};
const resetForm = () => {
Object.assign(form.value, initFormData);
form.value.projectPurchaseStatus = '1';
form.value.flowStatus = 'draft';
//
if (userStore.userId) {
form.value.reporterId = userStore.userId;
}
if (!form.value.activeFlag && active_flag.value?.length) {
form.value.activeFlag = active_flag.value[0].value;
}
};
const resetMaterialForm = () => {
Object.assign(materialForm.value, initMaterialFormData);
};
const loadDetail = async (projectPurchaseId: string | number) => {
if (!projectPurchaseId) {
resetForm();
materialList.value = [];
return;
}
pageLoading.value = true;
try {
resetForm();
const res = await getProjectPurchase(projectPurchaseId);
Object.assign(form.value, res?.data || {});
if (!form.value.projectPurchaseStatus) {
form.value.projectPurchaseStatus = '1';
}
if (!form.value.flowStatus) {
form.value.flowStatus = 'draft';
}
// ID
if (userList.value.length === 0) {
await getUserList();
}
await loadMaterials();
} finally {
pageLoading.value = false;
}
};
//
getUserList();
const loadMaterials = async () => {
if (!form.value.projectPurchaseId) {
materialList.value = [];
return;
}
materialLoading.value = true;
try {
const res = await listProjectPurchaseMaterial({ projectPurchaseId: form.value.projectPurchaseId, pageNum: 1, pageSize: 999 });
materialList.value = res?.rows || [];
} finally {
materialLoading.value = false;
}
};
const submitForm = async (status: string, mode?: boolean) => {
if (!projectPurchaseFormRef.value) return;
try {
await projectPurchaseFormRef.value.validate();
} catch (error) {
return;
}
buttonLoading.value = true;
try {
const payload: ProjectPurchaseForm & { projectName?: string } = { ...form.value };
if (status !== 'draft') {
payload.flowCode = FlowCodeEnum.PROJECT_PURCHASE_CODE;
payload.variables = {
projectPurchaseId: payload.projectPurchaseId,
projectCode: payload.projectCode,
projectName: payload.projectName
};
payload.bizExt = {
businessTitle: '项目采购审批',
businessCode: payload.projectCode
};
payload.projectPurchaseStatus = '2';
payload.flowStatus = 'waiting';
const res: any = await projectPurchaseSubmitAndFlowStart(payload);
if (res?.data) {
Object.assign(form.value, res.data);
} else {
Object.assign(form.value, payload);
}
proxy?.$modal.msgSuccess('操作成功');
proxy?.$tab.closePage();
router.go(-1);
} else {
payload.projectPurchaseStatus = '1';
payload.flowStatus = 'draft';
if (payload.projectPurchaseId) {
await updateProjectPurchase(payload);
} else {
const res: any = await addProjectPurchase(payload);
const newId = res?.data?.projectPurchaseId ?? res?.data ?? res?.msg;
if (newId) {
payload.projectPurchaseId = newId;
form.value.projectPurchaseId = newId as any;
}
}
Object.assign(form.value, payload);
proxy?.$modal.msgSuccess('暂存成功');
proxy?.$tab.closePage();
router.go(-1);
}
} finally {
buttonLoading.value = false;
}
};
const handleAddMaterial = () => {
if (isReadOnly.value) {
return;
}
if (!form.value.projectPurchaseId) {
proxy?.$modal.msgWarning('请先保存项目采购信息');
return;
}
resetMaterialForm();
materialForm.value.projectPurchaseId = form.value.projectPurchaseId;
materialForm.value.purchasePlanFlag = materialForm.value.purchasePlanFlag || (purchase_plan_flag.value?.[0]?.value ?? undefined);
materialForm.value.materialFlag = materialForm.value.materialFlag || (material_flag.value?.[0]?.value ?? undefined);
materialForm.value.spareFlag = materialForm.value.spareFlag || (spare_flag.value?.[0]?.value ?? undefined);
materialForm.value.activeFlag = materialForm.value.activeFlag || (active_flag.value?.[0]?.value ?? undefined);
materialDialog.title = '新增物料';
materialDialog.visible = true;
};
const handleEditMaterial = (row: ProjectPurchaseMaterialVO) => {
if (isReadOnly.value) {
return;
}
resetMaterialForm();
Object.assign(materialForm.value, row);
materialDialog.title = '编辑物料';
materialDialog.visible = true;
};
const submitMaterialForm = () => {
if (isReadOnly.value) {
return;
}
materialFormRef.value?.validate(async (valid: boolean) => {
if (!valid) return;
materialLoading.value = true;
try {
materialForm.value.projectPurchaseId = form.value.projectPurchaseId;
if (materialForm.value.purchaseMaterialId) {
await updateProjectPurchaseMaterial(materialForm.value);
} else {
await addProjectPurchaseMaterial(materialForm.value);
}
proxy?.$modal.msgSuccess('操作成功');
materialDialog.visible = false;
await loadMaterials();
} finally {
materialLoading.value = false;
}
});
};
const handleDeleteMaterial = async (row: ProjectPurchaseMaterialVO) => {
if (isReadOnly.value) {
return;
}
await proxy?.$modal.confirm(`是否确认删除物料"${row.materialName}"`);
await delProjectPurchaseMaterial(row.purchaseMaterialId);
proxy?.$modal.msgSuccess('删除成功');
await loadMaterials();
};
const approvalVerifyOpen = async () => {
taskVariables.value = {
projectPurchaseId: form.value.projectPurchaseId,
projectCode: form.value.projectCode,
projectName: form.value.projectName
};
const taskId = (routeParams.taskId as string) || (route.query.taskId as string);
if (taskId) {
await submitVerifyRef.value?.openDialog(taskId);
}
};
const handleApprovalRecord = () => {
if (form.value.projectPurchaseId) {
approvalRecordRef.value?.init(form.value.projectPurchaseId);
}
};
const submitCallback = async () => {
await proxy?.$tab.closePage(route);
router.go(-1);
};
//
const openProjectSelect = () => {
if (isReadOnly.value) {
return;
}
projectSelectRef.value?.open();
};
//
const projectInfoSelectCallBack = (data: ProjectInfoVO[]) => {
if (data && data.length > 0) {
const project = data[0];
form.value.projectId = project.projectId;
form.value.projectCode = project.projectCode;
form.value.projectName = project.projectName;
form.value.managerId = project.managerId;
form.value.chargeId = project.chargeId;
form.value.deputyId = project.deputyId;
form.value.spareFlag = project.spareFlag;
}
};
watch(
() => ({
id: route.query.id,
type: route.query.type,
taskId: route.query.taskId
}),
async (val) => {
Object.assign(routeParams, val);
pageType.value = (val.type as string) || 'add';
const projectPurchaseId = val.id as string | number | undefined;
if (projectPurchaseId) {
await loadDetail(projectPurchaseId);
} else {
resetForm();
materialList.value = [];
}
},
{ immediate: true }
);
</script>

@ -0,0 +1,254 @@
<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="managerId">
<el-input v-model="queryParams.managerId" placeholder="请输入项目经理" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="项目采购状态" prop="projectPurchaseStatus">
<el-select v-model="queryParams.projectPurchaseStatus" placeholder="请选择项目采购状态" clearable>
<el-option v-for="dict in project_purchase_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</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:projectPurchase: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:projectPurchase: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:projectPurchase:remove']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['oa/erp:projectPurchase: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="projectPurchaseList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="项目采购ID" align="center" prop="projectPurchaseId" width="120" v-if="columns[0].visible" />
<el-table-column label="项目ID" align="center" prop="projectId" width="120" v-if="columns[2].visible" />
<el-table-column label="项目号" align="center" prop="projectCode" width="150" v-if="columns[3].visible" />
<el-table-column label="项目名称" align="center" prop="projectName" width="200" show-overflow-tooltip v-if="columns[4].visible" />
<el-table-column label="项目经理" align="center" prop="managerId" width="120" v-if="columns[5].visible" />
<el-table-column label="部门负责人" align="center" prop="chargeId" width="120" v-if="columns[6].visible" />
<el-table-column label="分管副总" align="center" prop="deputyId" width="120" v-if="columns[7].visible" />
<el-table-column label="提报人" align="center" prop="reporterId" width="120" v-if="columns[9].visible" />
<el-table-column label="收货人" align="center" prop="consigneeUser" width="120" v-if="columns[10].visible" />
<el-table-column label="收货地址" align="center" prop="consigneeAddress" width="200" show-overflow-tooltip v-if="columns[11].visible" />
<el-table-column label="收货人联系方式" align="center" prop="consigneeContact" width="150" v-if="columns[12].visible" />
<el-table-column label="项目采购状态" align="center" prop="projectPurchaseStatus" width="140" v-if="columns[13].visible">
<template #default="scope">
<dict-tag :options="project_purchase_status" :value="scope.row.projectPurchaseStatus" />
</template>
</el-table-column>
<el-table-column label="流程状态" align="center" prop="flowStatus" width="120" v-if="columns[14].visible" />
<el-table-column label="排序号" align="center" prop="sortOrder" width="100" v-if="columns[15].visible" />
<el-table-column label="合同/预算ID" align="center" prop="relationId" width="130" v-if="columns[16].visible" />
<el-table-column label="备注" align="center" prop="remark" width="180" show-overflow-tooltip v-if="columns[17].visible" />
<el-table-column label="是否备件类" align="center" prop="spareFlag" width="120" v-if="columns[18].visible">
<template #default="scope">
<dict-tag :options="spare_flag" :value="scope.row.spareFlag" />
</template>
</el-table-column>
<el-table-column label="激活标识" align="center" prop="activeFlag" width="120" v-if="columns[19].visible">
<template #default="scope">
<dict-tag :options="active_flag" :value="scope.row.activeFlag" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="160" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="查看" placement="top">
<el-button link type="info" icon="View" @click="handleView(scope.row)"></el-button>
</el-tooltip>
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/erp:projectPurchase:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['oa/erp:projectPurchase:remove']"></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>
</div>
</template>
<script setup name="ProjectPurchase" lang="ts">
import { reactive, ref, toRefs, getCurrentInstance, onMounted } from 'vue';
import type { ComponentInternalInstance } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import type { FormInstance } from 'element-plus';
import { listProjectPurchase, delProjectPurchase } from '@/api/oa/erp/projectPurchase';
import type { ProjectPurchaseVO, ProjectPurchaseQuery } from '@/api/oa/erp/projectPurchase/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const router = useRouter();
const route = useRoute();
const { active_flag, project_purchase_status, spare_flag } = toRefs<any>(proxy?.useDict('active_flag', 'project_purchase_status', 'spare_flag'));
const projectPurchaseList = ref<ProjectPurchaseVO[]>([]);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<FormInstance>();
const columns = ref<FieldOption[]>([
{ key: 0, label: `项目采购ID`, visible: true },
{ key: 1, label: `租户编号`, visible: true },
{ key: 2, label: `项目ID`, visible: true },
{ 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: true },
{ key: 12, label: `收货人联系方式`, visible: true },
{ key: 13, label: `项目采购状态`, visible: true },
{ key: 14, label: `流程状态`, visible: true },
{ key: 15, label: `排序号`, visible: true },
{ key: 16, label: `合同/预算ID`, visible: true },
{ key: 17, label: `备注`, visible: true },
{ key: 18, label: `是否备件类`, visible: true },
{ key: 19, label: `激活标识`, visible: true },
{ key: 20, label: `删除标志`, visible: true },
{ key: 21, label: `创建部门`, visible: true },
{ key: 22, label: `创建人`, visible: true },
{ key: 23, label: `创建时间`, visible: true },
{ key: 24, label: `更新人`, visible: true },
{ key: 25, label: `更新时间`, visible: true }
]);
const data = reactive<{ queryParams: ProjectPurchaseQuery }>({
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: undefined,
projectCode: undefined,
projectName: undefined,
managerId: undefined,
chargeId: undefined,
deputyId: undefined,
reporterId: undefined,
consigneeUser: undefined,
consigneeAddress: undefined,
consigneeContact: undefined,
projectPurchaseStatus: undefined,
flowStatus: undefined,
sortOrder: undefined,
relationId: undefined,
spareFlag: undefined,
activeFlag: undefined,
params: {}
}
});
const { queryParams } = toRefs(data);
const getList = async () => {
loading.value = true;
const res = await listProjectPurchase(queryParams.value);
projectPurchaseList.value = res.rows;
total.value = res.total;
loading.value = false;
};
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
};
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
const handleSelectionChange = (selection: ProjectPurchaseVO[]) => {
ids.value = selection.map((item) => item.projectPurchaseId);
single.value = selection.length !== 1;
multiple.value = selection.length === 0;
};
const handleAdd = () => {
proxy?.$tab.closePage(route);
router.push({
path: '/purchase/projectPurchase/edit',
query: { type: 'add' }
});
};
const handleUpdate = (row?: ProjectPurchaseVO) => {
const projectPurchaseId = row?.projectPurchaseId || ids.value[0];
if (!projectPurchaseId) {
return;
}
proxy?.$tab.closePage(route);
router.push({
path: '/oa/erp/projectPurchase/edit',
query: { id: projectPurchaseId, type: 'update' }
});
};
const handleView = (row: ProjectPurchaseVO) => {
proxy?.$tab.closePage(route);
router.push({
path: '/oa/erp/projectPurchase/edit',
query: { id: row.projectPurchaseId, type: 'view' }
});
};
const handleDelete = async (row?: ProjectPurchaseVO) => {
const projectPurchaseIds = row?.projectPurchaseId || ids.value;
await proxy?.$modal.confirm(`是否确认删除项目采购信息编号为"${projectPurchaseIds}"的数据项?`).finally(() => {
loading.value = false;
});
await delProjectPurchase(projectPurchaseIds);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
const handleExport = () => {
proxy?.download(
'oa/erp/projectPurchase/export',
{
...queryParams.value
},
`projectPurchase_${new Date().getTime()}.xlsx`
);
};
onMounted(() => {
getList();
});
</script>

@ -0,0 +1,446 @@
<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="项目采购ID" prop="projectPurchaseId">
<el-input v-model="queryParams.projectPurchaseId" placeholder="请输入项目采购ID" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="关联明细ID" prop="relationDetailsId">
<el-input v-model="queryParams.relationDetailsId" placeholder="请输入关联明细ID" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="是否备件类" prop="spareFlag">
<el-select v-model="queryParams.spareFlag" placeholder="请选择是否备件类" clearable >
<el-option v-for="dict in spare_flag" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="计划标识" prop="purchasePlanFlag">
<el-select v-model="queryParams.purchasePlanFlag" placeholder="请选择计划标识" clearable >
<el-option v-for="dict in purchase_plan_flag" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="标准物料标识" prop="materialFlag">
<el-select v-model="queryParams.materialFlag" placeholder="请选择标准物料标识" clearable >
<el-option v-for="dict in material_flag" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="物料ID" prop="materialId">
<el-input v-model="queryParams.materialId" placeholder="请输入物料ID" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="销售物料ID" prop="relationMaterialId">
<el-input v-model="queryParams.relationMaterialId" placeholder="请输入销售物料ID" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="采购物料编码" prop="materialCode">
<el-input v-model="queryParams.materialCode" placeholder="请输入采购物料编码" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="采购物料名称" prop="materialName">
<el-input v-model="queryParams.materialName" placeholder="请输入采购物料名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="详细参数" prop="specificationDescription">
<el-input v-model="queryParams.specificationDescription" placeholder="请输入详细参数" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="单位ID" prop="unitId">
<el-input v-model="queryParams.unitId" placeholder="请输入单位ID" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="需采购总数量" prop="needPurchaseAmount">
<el-input v-model="queryParams.needPurchaseAmount" placeholder="请输入需采购总数量" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="本次采购数量" prop="purchaseAmount">
<el-input v-model="queryParams.purchaseAmount" placeholder="请输入本次采购数量" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="需求到货时间" prop="arrivalTime">
<el-date-picker clearable
v-model="queryParams.arrivalTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择需求到货时间"
/>
</el-form-item>
<el-form-item label="序号" prop="serialNumber">
<el-input v-model="queryParams.serialNumber" placeholder="请输入序号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="激活标识" prop="activeFlag">
<el-select v-model="queryParams.activeFlag" placeholder="请选择激活标识" clearable >
<el-option v-for="dict in active_flag" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</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:projectPurchaseMaterial: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:projectPurchaseMaterial: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:projectPurchaseMaterial:remove']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['oa/erp:projectPurchaseMaterial: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="projectPurchaseMaterialList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="项目采购ID" align="center" prop="purchaseMaterialId" v-if="columns[0].visible"/>
<el-table-column label="项目采购ID" align="center" prop="projectPurchaseId" v-if="columns[2].visible"/>
<el-table-column label="关联明细ID" align="center" prop="relationDetailsId" v-if="columns[3].visible"/>
<el-table-column label="是否备件类" align="center" prop="spareFlag" v-if="columns[4].visible">
<template #default="scope">
<dict-tag :options="spare_flag" :value="scope.row.spareFlag"/>
</template>
</el-table-column>
<el-table-column label="计划标识" align="center" prop="purchasePlanFlag" v-if="columns[5].visible">
<template #default="scope">
<dict-tag :options="purchase_plan_flag" :value="scope.row.purchasePlanFlag"/>
</template>
</el-table-column>
<el-table-column label="标准物料标识" align="center" prop="materialFlag" v-if="columns[6].visible">
<template #default="scope">
<dict-tag :options="material_flag" :value="scope.row.materialFlag"/>
</template>
</el-table-column>
<el-table-column label="物料ID" align="center" prop="materialId" v-if="columns[7].visible"/>
<el-table-column label="销售物料ID" align="center" prop="relationMaterialId" v-if="columns[8].visible"/>
<el-table-column label="采购物料编码" align="center" prop="materialCode" v-if="columns[9].visible"/>
<el-table-column label="采购物料名称" align="center" prop="materialName" v-if="columns[10].visible"/>
<el-table-column label="详细参数" align="center" prop="specificationDescription" v-if="columns[11].visible"/>
<el-table-column label="单位ID" align="center" prop="unitId" v-if="columns[12].visible"/>
<el-table-column label="需采购总数量" align="center" prop="needPurchaseAmount" v-if="columns[13].visible"/>
<el-table-column label="本次采购数量" align="center" prop="purchaseAmount" v-if="columns[14].visible"/>
<el-table-column label="需求到货时间" align="center" prop="arrivalTime" width="180" v-if="columns[15].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.arrivalTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="序号" align="center" prop="serialNumber" v-if="columns[16].visible"/>
<el-table-column label="备注" align="center" prop="remark" v-if="columns[17].visible"/>
<el-table-column label="激活标识" align="center" prop="activeFlag" v-if="columns[18].visible">
<template #default="scope">
<dict-tag :options="active_flag" :value="scope.row.activeFlag"/>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/erp:projectPurchaseMaterial:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['oa/erp:projectPurchaseMaterial:remove']"></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-form ref="projectPurchaseMaterialFormRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="项目采购ID" prop="projectPurchaseId">
<el-input v-model="form.projectPurchaseId" placeholder="请输入项目采购ID" />
</el-form-item>
<el-form-item label="关联明细ID" prop="relationDetailsId">
<el-input v-model="form.relationDetailsId" placeholder="请输入关联明细ID" />
</el-form-item>
<el-form-item label="是否备件类" prop="spareFlag">
<el-radio-group v-model="form.spareFlag">
<el-radio
v-for="dict in spare_flag"
:key="dict.value"
:value="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="计划标识" prop="purchasePlanFlag">
<el-radio-group v-model="form.purchasePlanFlag">
<el-radio
v-for="dict in purchase_plan_flag"
:key="dict.value"
:value="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="标准物料标识" prop="materialFlag">
<el-radio-group v-model="form.materialFlag">
<el-radio
v-for="dict in material_flag"
:key="dict.value"
:value="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="物料ID" prop="materialId">
<el-input v-model="form.materialId" placeholder="请输入物料ID" />
</el-form-item>
<el-form-item label="销售物料ID" prop="relationMaterialId">
<el-input v-model="form.relationMaterialId" placeholder="请输入销售物料ID" />
</el-form-item>
<el-form-item label="采购物料编码" prop="materialCode">
<el-input v-model="form.materialCode" placeholder="请输入采购物料编码" />
</el-form-item>
<el-form-item label="采购物料名称" prop="materialName">
<el-input v-model="form.materialName" placeholder="请输入采购物料名称" />
</el-form-item>
<el-form-item label="详细参数" prop="specificationDescription">
<el-input v-model="form.specificationDescription" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="单位ID" prop="unitId">
<el-input v-model="form.unitId" placeholder="请输入单位ID" />
</el-form-item>
<el-form-item label="需采购总数量" prop="needPurchaseAmount">
<el-input v-model="form.needPurchaseAmount" placeholder="请输入需采购总数量" />
</el-form-item>
<el-form-item label="本次采购数量" prop="purchaseAmount">
<el-input v-model="form.purchaseAmount" placeholder="请输入本次采购数量" />
</el-form-item>
<el-form-item label="需求到货时间" prop="arrivalTime">
<el-date-picker clearable
v-model="form.arrivalTime"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择需求到货时间">
</el-date-picker>
</el-form-item>
<el-form-item label="序号" prop="serialNumber">
<el-input v-model="form.serialNumber" placeholder="请输入序号" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="激活标识" prop="activeFlag">
<el-radio-group v-model="form.activeFlag">
<el-radio
v-for="dict in active_flag"
:key="dict.value"
:value="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="ProjectPurchaseMaterial" lang="ts">
import { listProjectPurchaseMaterial, getProjectPurchaseMaterial, delProjectPurchaseMaterial, addProjectPurchaseMaterial, updateProjectPurchaseMaterial } from '@/api/oa/erp/projectPurchaseMaterial';
import { ProjectPurchaseMaterialVO, ProjectPurchaseMaterialQuery, ProjectPurchaseMaterialForm } from '@/api/oa/erp/projectPurchaseMaterial/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { active_flag, purchase_plan_flag, material_flag, spare_flag } = toRefs<any>(proxy?.useDict('active_flag', 'purchase_plan_flag', 'material_flag', 'spare_flag'));
const projectPurchaseMaterialList = ref<ProjectPurchaseMaterialVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const projectPurchaseMaterialFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
//
const columns = ref<FieldOption[]>([
{ key: 0, label: `项目采购ID`, visible: true },
{ key: 1, label: `租户编号`, visible: true },
{ key: 2, label: `项目采购ID`, visible: true },
{ key: 3, label: `关联明细ID`, visible: true },
{ key: 4, label: `是否备件类`, visible: true },
{ key: 5, label: `计划标识`, visible: true },
{ key: 6, label: `标准物料标识`, visible: true },
{ key: 7, label: `物料ID`, visible: true },
{ key: 8, label: `销售物料ID`, visible: true },
{ key: 9, label: `采购物料编码`, visible: true },
{ key: 10, label: `采购物料名称`, visible: true },
{ key: 11, label: `详细参数`, visible: true },
{ key: 12, label: `单位ID`, visible: true },
{ key: 13, label: `需采购总数量`, visible: true },
{ key: 14, label: `本次采购数量`, visible: true },
{ key: 15, label: `需求到货时间`, visible: true },
{ key: 16, label: `序号`, visible: true },
{ key: 17, label: `备注`, visible: true },
{ key: 18, label: `激活标识`, visible: true },
{ key: 19, label: `删除标志`, visible: true },
{ key: 20, label: `创建部门`, visible: true },
{ key: 21, label: `创建人`, visible: true },
{ key: 22, label: `创建时间`, visible: true },
{ key: 23, label: `更新人`, visible: true },
{ key: 24, label: `更新时间`, visible: true },
]);
const initFormData: ProjectPurchaseMaterialForm = {
purchaseMaterialId: undefined,
projectPurchaseId: undefined,
relationDetailsId: undefined,
spareFlag: undefined,
purchasePlanFlag: undefined,
materialFlag: undefined,
materialId: undefined,
relationMaterialId: undefined,
materialCode: undefined,
materialName: undefined,
specificationDescription: undefined,
unitId: undefined,
needPurchaseAmount: undefined,
purchaseAmount: undefined,
arrivalTime: undefined,
serialNumber: undefined,
remark: undefined,
activeFlag: undefined,
}
const data = reactive<PageData<ProjectPurchaseMaterialForm, ProjectPurchaseMaterialQuery>>({
form: {...initFormData},
queryParams: {
pageNum: 1,
pageSize: 10,
projectPurchaseId: undefined,
relationDetailsId: undefined,
spareFlag: undefined,
purchasePlanFlag: undefined,
materialFlag: undefined,
materialId: undefined,
relationMaterialId: undefined,
materialCode: undefined,
materialName: undefined,
specificationDescription: undefined,
unitId: undefined,
needPurchaseAmount: undefined,
purchaseAmount: undefined,
arrivalTime: undefined,
serialNumber: undefined,
activeFlag: undefined,
params: {
}
},
rules: {
materialFlag: [
{ required: true, message: "标准物料标识不能为空", trigger: "change" }
],
materialName: [
{ required: true, message: "采购物料名称不能为空", trigger: "blur" }
],
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询项目采购物料列表 */
const getList = async () => {
loading.value = true;
const res = await listProjectPurchaseMaterial(queryParams.value);
projectPurchaseMaterialList.value = res.rows;
total.value = res.total;
loading.value = false;
}
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
}
/** 表单重置 */
const reset = () => {
form.value = {...initFormData};
projectPurchaseMaterialFormRef.value?.resetFields();
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
}
/** 多选框选中数据 */
const handleSelectionChange = (selection: ProjectPurchaseMaterialVO[]) => {
ids.value = selection.map(item => item.purchaseMaterialId);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = "添加项目采购物料";
}
/** 修改按钮操作 */
const handleUpdate = async (row?: ProjectPurchaseMaterialVO) => {
reset();
const _purchaseMaterialId = row?.purchaseMaterialId || ids.value[0]
const res = await getProjectPurchaseMaterial(_purchaseMaterialId);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = "修改项目采购物料";
}
/** 提交按钮 */
const submitForm = () => {
projectPurchaseMaterialFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.purchaseMaterialId) {
await updateProjectPurchaseMaterial(form.value).finally(() => buttonLoading.value = false);
} else {
await addProjectPurchaseMaterial(form.value).finally(() => buttonLoading.value = false);
}
proxy?.$modal.msgSuccess("操作成功");
dialog.visible = false;
await getList();
}
});
}
/** 删除按钮操作 */
const handleDelete = async (row?: ProjectPurchaseMaterialVO) => {
const _purchaseMaterialIds = row?.purchaseMaterialId || ids.value;
await proxy?.$modal.confirm('是否确认删除项目采购物料编号为"' + _purchaseMaterialIds + '"的数据项?').finally(() => loading.value = false);
await delProjectPurchaseMaterial(_purchaseMaterialIds);
proxy?.$modal.msgSuccess("删除成功");
await getList();
}
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download('oa/erp/projectPurchaseMaterial/export', {
...queryParams.value
}, `projectPurchaseMaterial_${new Date().getTime()}.xlsx`)
}
onMounted(() => {
getList();
});
</script>

@ -0,0 +1,851 @@
<template>
<div class="p-2">
<el-card shadow="never">
<!-- 审批按钮组件 -->
<approvalButton
@submitForm="submitForm"
@approvalVerifyOpen="approvalVerifyOpen"
@handleApprovalRecord="handleApprovalRecord"
:buttonLoading="buttonLoading"
:id="form.projectId"
:status="form.flowStatus"
:pageType="routeParams.type"
:mode="false"
/>
<el-form
ref="contractInfoFormRef"
:model="form"
:loading="buttonLoading"
:disabled="routeParams.type === 'view' || routeParams.type === 'approval'"
:rules="rules"
label-width="120px"
>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="form.projectName" placeholder="请输入项目名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目编号" prop="projectCode">
<el-input v-model="form.projectCode" placeholder="请输入项目编号" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="里程碑计划" prop="milestonePlan">
<el-input v-model="form.milestonePlan" placeholder="请输入里程碑计划" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目经理" prop="managerName">
<el-input v-model="form.managerName" placeholder="请输入项目经理" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="部门" prop="deptName">
<el-input v-model="form.deptName" placeholder="请输入部门" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="部门负责人" prop="chargeName">
<el-input v-model="form.chargeName" placeholder="请输入部门负责人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="分管副总" prop="deputyName">
<el-input v-model="form.deputyName" placeholder="请输入分管副总" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="附件" prop="ossId">
<el-button type="primary" plain icon="Upload" @click="handleFile"></el-button>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="项目ID" prop="projectId">
<el-input v-model="form.projectId" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="项目经理ID" prop="managerId">
<el-input v-model="form.managerId" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="部门ID" prop="deptId">
<el-input v-model="form.deptId" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="部门负责人ID" prop="chargeId">
<el-input v-model="form.chargeId" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="分管副总ID" prop="deputyId">
<el-input v-model="form.deputyId" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="附件ID" prop="ossId">
<el-input v-model="form.ossId" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="排序号" prop="sortOrder">
<el-input v-model="form.sortOrder" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="激活标识" prop="activeFlag">
<el-input v-model="form.activeFlag" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="周报说明" prop="informationNote">
<el-input v-model="form.informationNote" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<!-- 合同物料管理区域 -->
<el-card shadow="never" style="margin-top: 20px">
<template #header>
<div style="text-align: left; font-weight: bold; font-size: 18px">合同物料管理</div>
</template>
<!-- 合同物料表格 -->
<div style="margin-bottom: 16px">
<el-button type="primary" icon="Plus" v-if="routeParams.type !== 'view' && routeParams.type != 'approval'" @click="handleAddMaterial"
>新增物料
</el-button>
</div>
<el-table :data="contractMaterialList" v-loading="buttonLoading" border>
<el-table-column label="产品名称" align="center" prop="productName" min-width="120" />
<el-table-column label="规格描述" align="center" prop="specificationDescription" min-width="120" />
<el-table-column label="物料编号" align="center" prop="materialCode" width="120" />
<el-table-column label="物料名称" align="center" prop="materialName" width="120" />
<el-table-column label="销售物料名称" align="center" prop="saleMaterialName" width="120" />
<el-table-column label="数量" align="center" prop="amount" width="80">
<template #default="scope">
{{ scope.row.amount ? Number(scope.row.amount).toFixed(2) : '0.00' }}
</template>
</el-table-column>
<el-table-column label="单位" align="center" prop="unitName" width="60" />
<el-table-column label="未税单价" align="center" prop="beforePrice" width="100">
<template #default="scope">
{{ scope.row.beforePrice ? Number(scope.row.beforePrice).toFixed(2) : '0.00' }}
</template>
</el-table-column>
<el-table-column label="税率(%)" align="center" prop="taxRate" width="80">
<template #default="scope">
{{ scope.row.taxRate ? Number(scope.row.taxRate).toFixed(2) : '0.00' }}
</template>
</el-table-column>
<el-table-column label="含税单价" align="center" prop="includingPrice" width="100">
<template #default="scope">
{{ scope.row.includingPrice ? Number(scope.row.includingPrice).toFixed(2) : '0.00' }}
</template>
</el-table-column>
<el-table-column label="小计" align="center" prop="subtotal" width="80">
<template #default="scope">
{{ scope.row.subtotal ? Number(scope.row.subtotal).toFixed(2) : '0.00' }}
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" min-width="100" />
<el-table-column label="操作" align="center" fixed="right" width="150" v-if="routeParams.type !== 'view' && routeParams.type != 'approval'">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleEditMaterial(scope.row)"></el-button>
<el-button link type="danger" icon="Delete" @click="handleDeleteMaterial(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 合同物料编辑对话框 -->
<el-dialog :title="materialDialog.title" v-model="materialDialog.visible" width="800px" append-to-body>
<el-form ref="materialFormRef" :model="materialForm" :rules="materialRules" label-width="120px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="计划标识" prop="planFlag">
<el-radio-group v-model="materialForm.planFlag">
<el-radio v-for="dict in plan_flag" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物料名称" prop="materialName" v-if="materialForm.planFlag === '1'">
<el-input v-model="materialForm.materialName" placeholder="计划内请点击右侧图标检索物料">
<template #suffix>
<el-icon style="cursor: pointer" @click="openSaleMaterialSelect">
<Search />
</el-icon>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物料编号" prop="materialCode" v-if="materialForm.planFlag === '1'">
<el-input v-model="materialForm.materialCode" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="客户名称" prop="customerName" v-if="materialForm.planFlag === '1'">
<el-input v-model="materialForm.customerName" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="产品名称" prop="productName">
<el-input v-model="materialForm.productName" placeholder="请输入产品名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="规格描述" prop="specificationDescription">
<el-input v-model="materialForm.specificationDescription" placeholder="请输入规格描述" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="数量" prop="amount">
<el-input-number
v-model="materialForm.amount"
placeholder="请输入数量"
style="width: 100%"
@change="calculateSubtotal"
:precision="2"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物料单位" prop="unitId">
<el-select v-model="materialForm.unitId" placeholder="请选择物料单位">
<el-option v-for="item in unitInfoList" :key="item.unitId" :label="item.unitName" :value="item.unitId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="税率(%)" prop="taxRate">
<el-select
v-model="materialForm.taxRate"
placeholder="请选择或输入税率"
style="width: 100%"
@change="calculateBeforePrice"
filterable
allow-create
default-first-option
>
<el-option label="6" :value="6"></el-option>
<el-option label="13" :value="13"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="未税单价" prop="beforePrice">
<el-input-number
v-model="materialForm.beforePrice"
placeholder="自动计算"
style="width: 100%"
:precision="2"
:controls="false"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="含税单价" prop="includingPrice">
<el-input-number
v-model="materialForm.includingPrice"
placeholder="请输入含税单价"
style="width: 100%"
:precision="2"
@change="calculateBeforePrice"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="小计" prop="subtotal">
<el-input-number
v-model="materialForm.subtotal"
placeholder="自动计算"
style="width: 100%"
readonly
:precision="2"
:controls="false"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="materialForm.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitMaterialForm"> </el-button>
<el-button @click="cancelMaterial"> </el-button>
</div>
</template>
</el-dialog>
<!-- 销售物料选择 -->
<SaleMaterialSelect ref="saleMaterialSelectRef" :multiple="false" @confirm-call-back="saleMaterialSelectCallBack"></SaleMaterialSelect>
<!-- 添加或修改OSS对象存储对话框 -->
<el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
<el-form ref="ossFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="文件名">
<fileUpload v-if="type === 0" v-model="ossFileModel" />
<imageUpload v-if="type === 1" v-model="ossFileModel" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitOss"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
<!-- 提交审批组件 -->
<submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
<!-- 审批记录 -->
<approvalRecord ref="approvalRecordRef" />
</div>
</template>
<script setup name="ContractInfoEdit" lang="ts">
import { addContractInfo, contractSubmitAndFlowStart, getContractInfo, updateContractInfo } from '@/api/oa/erp/contractInfo';
import { ContractInfoForm } from '@/api/oa/erp/contractInfo/types';
import { ContractMaterialVO, ContractMaterialForm } from '@/api/oa/erp/contractMaterial/types';
import { getBaseUnitInfoList } from '@/api/oa/base/unitInfo';
import { getRuleGenerateCode } from '@/api/system/codeRule';
import { startWorkFlow } from '@/api/workflow/task';
import { StartProcessBo } from '@/api/workflow/workflowCommon/types';
import SaleMaterialSelect from '@/components/SaleMaterialSelect/index.vue';
import SubmitVerify from '@/components/Process/submitVerify.vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import ApprovalButton from '@/components/Process/approvalButton.vue';
import { ref } from 'vue';
import { allListDept, listDept } from '@/api/system/dept';
import { getCrmCustomerInfoList } from '@/api/oa/crm/customerInfo';
import { getBasePrintTemplateList } from '@/api/oa/base/printTemplate';
import { CodeRuleEnum, FlowCodeEnum } from '@/enums/OAEnum';
import { getInfo } from '@/api/login';
import { ProjectReportVO, ProjectReportQuery, ProjectReportForm } from '@/api/oa/erp/projectReport/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const route = useRoute();
const router = useRouter();
//
const routeParams = ref<Record<string, any>>({});
const { contract_category, business_direction, contract_flag, contract_type, contract_status, plan_flag } = toRefs<any>(
proxy?.useDict('contract_category', 'business_direction', 'contract_flag', 'contract_type', 'contract_status', 'plan_flag')
);
const buttonLoading = ref(false);
const contractInfoFormRef = ref<ElFormInstance>();
//
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
//
const submitFormData = ref<StartProcessBo>({
businessId: '',
flowCode: 'OAC',
variables: {},
bizExt: {}
});
//
const taskVariables = ref<Record<string, any>>({});
const flowInstanceBizExtBo = ref<Record<string, any>>({});
const type = ref(0);
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
// OSS v-model form
const ossFileModel = ref<string | string[] | undefined>(undefined);
//
const isCodeGenerated = ref(false);
//
const materialFormRef = ref<ElFormInstance>();
//
const contractMaterialList = computed(() => {
return (form.value as any).contractMaterialList || [];
});
/** 查询打印模板下拉框结构 */
const printTemplateList = ref([]);
const getPrintTemplateListSelect = async () => {
const res = await getBasePrintTemplateList(null);
printTemplateList.value = res.data;
};
/** 查询单位信息下拉框结构 */
const unitInfoList = ref([]);
const getUnitInfoListSelect = async () => {
const res = await getBaseUnitInfoList(null);
unitInfoList.value = res.data;
};
/** 查询部门信息下拉框结构 */
const deptInfoList = ref([]);
const getDeptInfoListSelect = async () => {
const params = { deptCategory: '03' } as any;
const res = await allListDept(params);
deptInfoList.value = res.data;
};
/** 查询客户信息下拉框结构 */
const customerInfoList = ref([]);
const getCustomerInfoListSelect = async () => {
const res = await getCrmCustomerInfoList(null);
customerInfoList.value = res.data;
};
//
const materialDialog = reactive({
visible: false,
title: ''
});
//
const initMaterialFormData: ContractMaterialForm = {
contractMaterialId: undefined,
planFlag: '2',
contractId: undefined,
productName: undefined,
specificationDescription: undefined,
materialId: undefined,
relationMaterialId: undefined,
amount: undefined,
unitId: undefined,
beforePrice: undefined,
taxRate: undefined,
includingPrice: undefined,
subtotal: undefined,
remark: undefined,
activeFlag: '1'
};
const materialForm = ref<ContractMaterialForm>({ ...initMaterialFormData });
//
const materialRules = {
productName: [{ required: true, message: '产品名称不能为空', trigger: 'blur' }],
amount: [{ required: true, message: '数量不能为空', trigger: 'blur' }],
taxRate: [{ required: true, message: '税率不能为空', trigger: 'blur' }]
};
const initFormData: ProjectReportForm = {
reportId: undefined,
projectId: undefined,
projectName: undefined,
projectCode: undefined,
milestonePlan: undefined,
managerId: undefined,
deptId: undefined,
chargeId: undefined,
deputyId: undefined,
informationNote: undefined,
sortOrder: undefined,
ossId: undefined,
remark: undefined,
activeFlag: undefined,
deptName: undefined,
managerName: undefined,
chargeName: undefined,
deputyName: undefined
};
const data = reactive<{ form: ProjectReportForm; rules: any }>({
form: { ...initFormData },
rules: {
contractId: [{ required: true, message: '合同ID不能为空', trigger: 'blur' }]
}
});
const { form, rules } = toRefs(data);
// // contractFlag
// watch(
// () => form.value.contractFlag,
// (newVal) => {
// if (newVal === '2') {
// // ""
// form.value.contractCode = undefined;
// isCodeGenerated.value = false;
// }
// }
// );
const saleMaterialSelectRef = ref<InstanceType<typeof SaleMaterialSelect>>();
//
const openSaleMaterialSelect = () => {
saleMaterialSelectRef.value.open();
};
//
const saleMaterialSelectCallBack = (data: any) => {
const materialList = data;
if (materialList.length > 0) {
materialForm.value.materialId = materialList[0].materialId;
materialForm.value.materialCode = materialList[0].materialCode;
materialForm.value.materialName = materialList[0].materialName;
materialForm.value.productName = materialList[0].saleMaterialName;
materialForm.value.relationMaterialId = materialList[0].relationMaterialId;
materialForm.value.customerName = materialList[0].customerName;
}
};
/** 取消按钮 */
function cancel() {
dialog.visible = false;
}
/** 文件按钮操作 */
const handleFile = () => {
type.value = 0;
dialog.visible = true;
dialog.title = '上传合同附件';
//
ossFileModel.value = form.value.ossId as any;
};
/** 提交按钮 */
const submitForm = (status: string, mode: boolean) => {
try {
contractInfoFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
// 稿
if (status != 'draft') {
//
form.value.flowCode = FlowCodeEnum.CONTRACT_CODE;
//
form.value.variables = {
contractName: form.value.contractName,
totalPrice: form.value.totalPrice,
contractCode: form.value.contractCode
};
//
form.value.bizExt = {
businessTitle: '合同审批',
businessCode: form.value.contractCode
};
form.value.contractStatus = '2';
form.value.flowStatus = 'waiting';
const res = await contractSubmitAndFlowStart(form.value).finally(() => (buttonLoading.value = false));
form.value = res.data;
buttonLoading.value = false;
proxy?.$modal.msgSuccess('操作成功');
proxy?.$tab.closePage();
router.go(-1);
} else {
if (status === 'draft') {
form.value.contractStatus = '1';
form.value.flowStatus = 'draft';
}
if (form.value.contractId) {
await updateContractInfo(form.value).finally(() => (buttonLoading.value = false));
} else {
await addContractInfo(form.value).finally(() => (buttonLoading.value = false));
}
buttonLoading.value = false;
proxy?.$modal.msgSuccess('暂存成功');
proxy?.$tab.closePage();
router.go(-1);
}
}
});
} finally {
buttonLoading.value = false;
}
};
//
const handleStartWorkFlow = async (data: ContractInfoForm) => {
try {
submitFormData.value.flowCode = 'OAC';
submitFormData.value.businessId = data.contractId;
//
taskVariables.value = {
contractId: data.contractId,
contractName: data.contractName,
totalPrice: data.totalPrice,
contractCode: data.contractCode
};
//
flowInstanceBizExtBo.value = {
businessTitle: '合同审批',
businessCode: data.contractCode
};
submitFormData.value.variables = taskVariables.value;
submitFormData.value.bizExt = flowInstanceBizExtBo.value;
const resp = await startWorkFlow(submitFormData.value);
if (submitVerifyRef.value) {
buttonLoading.value = false;
await submitVerifyRef.value.openDialog(resp.data.taskId);
}
} finally {
buttonLoading.value = false;
router.go(-1);
}
};
// v-model ossId
const submitOss = () => {
// ossId
form.value.ossId = ossFileModel.value as any;
dialog.visible = false;
proxy?.$modal.msgSuccess('附件已更新');
};
// contractId
const handleAddMaterial = () => {
resetMaterialForm();
materialForm.value.contractId = form.value.contractId;
materialDialog.visible = true;
materialDialog.title = '新增合同物料';
};
//
const handleEditMaterial = (row: ContractMaterialVO) => {
resetMaterialForm();
materialForm.value = { ...row };
materialDialog.visible = true;
materialDialog.title = '编辑合同物料';
};
//
const handleDeleteMaterial = async (row: ContractMaterialVO) => {
await proxy?.$modal.confirm('是否确认删除该合同物料?');
try {
// contractMaterialList
if (!(form.value as any).contractMaterialList) {
(form.value as any).contractMaterialList = [];
}
//
const index = (form.value as any).contractMaterialList.findIndex((item: any) => item.contractMaterialId === row.contractMaterialId);
if (index !== -1) {
(form.value as any).contractMaterialList.splice(index, 1);
}
//
calculateTotalPrice();
proxy?.$modal.msgSuccess('删除成功');
} catch (error) {
console.error('删除合同物料失败:', error);
}
};
//
const resetMaterialForm = () => {
materialForm.value = { ...initMaterialFormData };
materialFormRef.value?.resetFields();
};
//
const cancelMaterial = () => {
resetMaterialForm();
materialDialog.visible = false;
};
//
const calculateBeforePrice = () => {
const tax = Number(materialForm.value.taxRate);
const including = Number(materialForm.value.includingPrice);
if (!isNaN(tax) && !isNaN(including)) {
const divisor = 1 + tax / 100;
if (divisor > 0) {
materialForm.value.beforePrice = Number((including / divisor).toFixed(2));
}
}
//
calculateSubtotal();
};
// ×
const calculateSubtotal = () => {
const amount = Number(materialForm.value.amount);
const including = Number(materialForm.value.includingPrice);
if (!isNaN(amount) && !isNaN(including)) {
materialForm.value.subtotal = Number((amount * including).toFixed(2));
}
//
calculateTotalPrice();
};
//
const calculateTotalPrice = () => {
const materialList = (form.value as any).contractMaterialList || [];
const total = materialList.reduce((sum: number, material: any) => {
const subtotal = Number(material.subtotal) || 0;
return sum + subtotal;
}, 0);
form.value.totalPrice = Number(total.toFixed(2));
};
// -
const submitMaterialForm = () => {
materialFormRef.value?.validate((valid: boolean) => {
if (valid) {
// contractMaterialList
if (!(form.value as any).contractMaterialList) {
(form.value as any).contractMaterialList = [];
}
if (materialForm.value.contractMaterialId) {
//
const index = (form.value as any).contractMaterialList.findIndex(
(item: any) => item.contractMaterialId === materialForm.value.contractMaterialId
);
if (index !== -1) {
(form.value as any).contractMaterialList[index] = { ...materialForm.value };
}
} else {
//
const newMaterial = {
...materialForm.value,
contractMaterialId: Date.now() // ID
};
(form.value as any).contractMaterialList.push(newMaterial);
}
//
calculateTotalPrice();
proxy?.$modal.msgSuccess('操作成功');
materialDialog.visible = false;
}
});
};
//
const loadSelectOptions = () => {
getUnitInfoListSelect();
getDeptInfoListSelect();
getCustomerInfoListSelect();
getPrintTemplateListSelect();
};
onMounted(async () => {
nextTick(async () => {
// //
// routeParams.value = route.query;
// loadSelectOptions();
// const id = routeParams.value.id as string | number;
// if (id && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) {
// proxy?.$modal.loading('...');
// const res = await getContractInfo(id);
// Object.assign(form.value, res.data);
// proxy?.$modal.closeLoading();
// //
// if (form.value.contractCode) {
// isCodeGenerated.value = true;
// } else if (form.value.contractFlag === '1') {
// //
// isCodeGenerated.value = false;
// }
// } else {
// // ID
// try {
// const userInfoRes = await getInfo();
// if (userInfoRes.data?.user?.deptId && !form.value.contractDeptId) {
// form.value.contractDeptId = userInfoRes.data.user.deptId;
// }
// } catch (error) {
// console.error(':', error);
// }
// //
// if (form.value.contractCode) {
// isCodeGenerated.value = true;
// } else if (form.value.contractFlag === '1') {
// //
// isCodeGenerated.value = false;
// }
// }
//
routeParams.value = route.query;
loadSelectOptions();
//
if (routeParams.value.type === 'add') {
//
if (routeParams.value.projectId) {
form.value.projectId = routeParams.value.projectId;
form.value.projectName = routeParams.value.projectName;
form.value.projectCode = routeParams.value.projectCode;
form.value.managerId = routeParams.value.managerId;
form.value.managerName = routeParams.value.managerName;
form.value.deptId = routeParams.value.deptId;
form.value.deptName = routeParams.value.deptName;
form.value.chargeId = routeParams.value.chargeId;
form.value.chargeName = routeParams.value.chargeName;
form.value.deputyId = routeParams.value.deputyId;
form.value.deputyName = routeParams.value.deputyName;
}
}
//
if (routeParams.value.type === 'update' || routeParams.value.type === 'approval') {
const id = routeParams.value.id;
if (id) {
proxy?.$modal.loading('正在加载数据,请稍后...');
const res = await getContractInfo(id);
Object.assign(form.value, res.data);
proxy?.$modal.closeLoading();
}
}
});
});
//
const handleApprovalRecord = () => {
approvalRecordRef.value.init(form.value.contractId);
};
//
const submitCallback = async () => {
await proxy.$tab.closePage(proxy.$route);
router.go(-1);
};
//
const approvalVerifyOpen = async () => {
await submitVerifyRef.value.openDialog(routeParams.value.taskId);
};
// ossId
//
watch(
() => form.value.ossId,
(val) => {
if (!dialog.visible) {
ossFileModel.value = val as any;
}
}
);
</script>

@ -18,31 +18,81 @@
</el-col>
<el-col :span="12">
<el-form-item label="项目编号" prop="projectCode">
<el-input v-model="queryParams.projectCode" placeholder="请输入项目编号" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.projectCode" placeholder="请输入项目编号" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10" class="form-row">
<el-col :span="12">
<el-form-item label="项目经理" prop="managerId">
<el-input v-model="queryParams.managerId" placeholder="请输入项目经理" clearable @keyup.enter="handleQuery" />
<el-form-item label="项目经理" prop="managerName">
<el-input v-model="queryParams.managerName" placeholder="请输入项目经理" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="当前里程碑" prop="milestonePlan">
<el-input v-model="queryParams.milestonePlan" placeholder="请输入当前里程碑" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.milestonePlan" placeholder="请输入当前里程碑" clearable />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="10" class="form-row">
<el-col :span="12">
<el-form-item label="部门ID" prop="deptId">
<el-input v-model="queryParams.deptId" placeholder="请输入部门ID" clearable @keyup.enter="handleQuery" />
<el-form-item label="部门名称" prop="deptName">
<el-input v-model="queryParams.deptName" placeholder="请输入部门名称" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="部门负责人" prop="chargeId">
<el-input v-model="queryParams.chargeId" placeholder="请输入部门负责人" clearable @keyup.enter="handleQuery" />
<el-form-item label="部门负责人" prop="chargeName">
<el-input v-model="queryParams.chargeName" placeholder="请输入部门负责人" clearable />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="项目ID" prop="projectId">
<el-input v-model="queryParams.projectId" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="项目经理ID" prop="managerId">
<el-input v-model="queryParams.managerId" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="部门ID" prop="deptId">
<el-input v-model="queryParams.deptId" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="部门负责人ID" prop="chargeId">
<el-input v-model="queryParams.chargeId" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="分管副总ID" prop="deputyId">
<el-input v-model="queryParams.deputyId" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="分管副总" prop="deputyName">
<el-input v-model="queryParams.deputyName" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="附件ID" prop="ossId">
<el-input v-model="queryParams.ossId" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="排序号" prop="sortOrder">
<el-input v-model="queryParams.sortOrder" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="激活标识" prop="activeFlag">
<el-input v-model="queryParams.activeFlag" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
<el-col :span="12" v-show="false">
<el-form-item label="周报说明" prop="informationNote">
<el-input v-model="queryParams.informationNote" placeholder="请点击右侧图标选择项目" />
</el-form-item>
</el-col>
</el-row>
@ -65,65 +115,49 @@
<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:projectReportDetail:add']"></el-button>
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['oa/erp:projectReport:add']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['oa:projectReportDetail:edit']"
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['oa/erp:projectReport:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['oa:projectReportDetail:remove']"
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['oa/erp:projectReport:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['oa:projectReportDetail:export']"></el-button>
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['oa/erp:projectReport: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="projectReportDetailList" @selection-change="handleSelectionChange">
<!-- 项目周报信息表格展示 -->
<el-table v-loading="loading" border :data="projectReportList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="项目周报明细ID" align="center" prop="reportDetailId" v-if="columns[0].visible" />
<el-table-column label="项目周报ID" align="center" prop="reportId" v-if="columns[1].visible" />
<el-table-column label="项目周报ID" align="center" prop="reportId" v-if="columns[0].visible" />
<el-table-column label="项目ID" align="center" prop="projectId" v-if="columns[2].visible" />
<el-table-column label="填写日期" align="center" prop="fillTime" width="180" v-if="columns[3].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.fillTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="所在的工作周" align="center" prop="currentWorkWeek" v-if="columns[4].visible" />
<el-table-column label="所属里程碑" align="center" prop="milestonePlan" v-if="columns[5].visible" />
<el-table-column label="二级进度阶段" align="center" prop="secondaryPhase" v-if="columns[6].visible" />
<el-table-column label="本周完成工作" align="center" prop="tasksCompleted" v-if="columns[7].visible" />
<el-table-column label="下周计划" align="center" prop="nextPlan" v-if="columns[8].visible" />
<el-table-column label="风险及解决措施" align="center" prop="riskResolution" v-if="columns[9].visible" />
<el-table-column label="计划完成率" align="center" prop="plannedCompletionRate" v-if="columns[10].visible" />
<el-table-column label="周报情况说明" align="center" prop="informationNote" v-if="columns[11].visible" />
<el-table-column label="项目状态" align="center" prop="scheduleStatus" v-if="columns[12].visible" />
<el-table-column label="周报状态(1暂存 2审批中 3可用)" align="center" prop="projectReportStatus" v-if="columns[13].visible" />
<el-table-column label="流程状态" align="center" prop="flowStatus" v-if="columns[14].visible" />
<el-table-column label="排序号" align="center" prop="sortOrder" v-if="columns[15].visible" />
<el-table-column label="项目阶段(预留)" align="center" prop="projectPhases" v-if="columns[16].visible" />
<el-table-column label="合同ID(预留)" align="center" prop="contractId" v-if="columns[17].visible" />
<el-table-column label="附件ID" align="center" prop="ossId" v-if="columns[18].visible" />
<el-table-column label="备注" align="center" prop="remark" v-if="columns[19].visible" />
<el-table-column label="激活标识" align="center" prop="activeFlag" v-if="columns[20].visible" />
<el-table-column label="项目名称" align="center" prop="projectName" v-if="columns[3].visible" />
<el-table-column label="项目编码" align="center" prop="projectCode" v-if="columns[20].visible" />
<el-table-column label="当前里程碑" align="center" prop="milestonePlan" v-if="columns[4].visible" />
<el-table-column label="项目经理" align="center" prop="managerName" v-if="columns[5].visible" />
<el-table-column label="部门ID" align="center" prop="deptName" v-if="columns[6].visible" />
<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="informationNote" v-if="columns[9].visible" />
<el-table-column label="排序号" align="center" prop="sortOrder" v-if="columns[10].visible" />
<el-table-column label="附件ID" align="center" prop="ossId" v-if="columns[11].visible" />
<el-table-column label="备注" align="center" prop="remark" v-if="columns[12].visible" />
<el-table-column label="激活标识" align="center" prop="activeFlag" v-if="columns[13].visible" />
<!-- <el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[20].visible" /> -->
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa:projectReportDetail:edit']"></el-button>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa:projectReport:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['oa:projectReportDetail:remove']"
></el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['oa:projectReport:remove']"></el-button>
</el-tooltip>
</template>
</el-table-column>
@ -131,61 +165,39 @@
<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-form ref="projectReportDetailFormRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="项目周报ID" prop="reportId">
<el-input v-model="form.reportId" placeholder="请输入项目周报ID" />
<el-form ref="projectReportFormRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="form.projectName" placeholder="请输入项目名称" />
</el-form-item>
<el-form-item label="项目ID" prop="projectId">
<el-input v-model="form.projectId" placeholder="请输入项目ID" />
<el-form-item label="项目编号" prop="projectCode">
<el-input v-model="form.projectCode" placeholder="请输入项目编号" />
</el-form-item>
<el-form-item label="填写日期" prop="fillTime">
<el-date-picker clearable v-model="form.fillTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择填写日期">
</el-date-picker>
<el-form-item label="当前里程碑" prop="milestonePlan">
<el-input v-model="form.milestonePlan" placeholder="请输入当前里程碑" />
</el-form-item>
<el-form-item label="所在的工作周" prop="currentWorkWeek">
<el-input v-model="form.currentWorkWeek" placeholder="请输入所在的工作周" />
<el-form-item label="项目经理" prop="managerId">
<el-input v-model="form.managerId" placeholder="请输入项目经理" />
</el-form-item>
<el-form-item label="所属里程碑" prop="milestonePlan">
<el-input v-model="form.milestonePlan" placeholder="请输入所属里程碑" />
<el-form-item label="部门ID" prop="deptId">
<el-input v-model="form.deptId" placeholder="请输入部门ID" />
</el-form-item>
<el-form-item label="二级进度阶段" prop="secondaryPhase">
<el-input v-model="form.secondaryPhase" placeholder="请输入二级进度阶段" />
<el-form-item label="部门负责人" prop="chargeId">
<el-input v-model="form.chargeId" placeholder="请输入部门负责人" />
</el-form-item>
<el-form-item label="本周完成工作" prop="tasksCompleted">
<el-input v-model="form.tasksCompleted" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="下周计划" prop="nextPlan">
<el-input v-model="form.nextPlan" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="风险及解决措施" prop="riskResolution">
<el-input v-model="form.riskResolution" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="计划完成率" prop="plannedCompletionRate">
<el-input v-model="form.plannedCompletionRate" placeholder="请输入计划完成率" />
<el-form-item label="分管副总" prop="deputyId">
<el-input v-model="form.deputyId" placeholder="请输入分管副总" />
</el-form-item>
<el-form-item label="周报情况说明" prop="informationNote">
<el-input v-model="form.informationNote" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="排序号" prop="sortOrder">
<el-input v-model="form.sortOrder" placeholder="请输入排序号" />
</el-form-item>
<el-form-item label="项目阶段(预留)" prop="projectPhases">
<el-input v-model="form.projectPhases" placeholder="请输入项目阶段(预留)" />
</el-form-item>
<el-form-item label="合同ID(预留)" prop="contractId">
<el-input v-model="form.contractId" placeholder="请输入合同ID(预留)" />
</el-form-item>
<el-form-item label="附件ID" prop="ossId">
<el-input v-model="form.ossId" placeholder="请输入附件ID" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="激活标识" prop="activeFlag">
<el-input v-model="form.activeFlag" placeholder="请输入激活标识" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
@ -198,76 +210,57 @@
</template>
<script setup name="ProjectReport" lang="ts">
import { listProjectReport, getProjectReport, delProjectReport, addProjectReport, updateProjectReport } from '@/api/oa/erp/projectReport';
import { ProjectReportVO, ProjectReportQuery, ProjectReportForm } from '@/api/oa/erp/projectReport/types';
import {
listProjectReportDetail,
getProjectReportDetail,
delProjectReportDetail,
addProjectReportDetail,
updateProjectReportDetail
} from '@/api/oa/erp/projectReportDetail/index';
import { ProjectReportDetailVO, ProjectReportDetailQuery, ProjectReportDetailForm } from '@/api/oa/erp/projectReportDetail/types';
import { listProjectReport, getProjectReport, delProjectReport, addProjectReport, updateProjectReport } from '@/api/oa/erp/projectReport';
import ProjectSelect from '@/components/ProjectSelect/index.vue';
//
const projectSelectRef = ref<InstanceType<typeof ProjectSelect>>();
//
const openProjectSelect = () => {
projectSelectRef.value.open();
};
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const projectReportList = ref<ProjectReportVO[]>([]);
const projectReportDetailList = ref<ProjectReportDetailVO[]>([]);
const route = useRoute();
const router = useRouter();
const buttonLoading = ref(false);
const loading = ref(true);
const loading = ref(false);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
//
const queryFormRef = ref<ElFormInstance>();
const projectReportDetailFormRef = ref<ElFormInstance>();
//
const projectReportFormRef = ref<ElFormInstance>();
//
const projectSelectRef = ref<InstanceType<typeof ProjectSelect>>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
//
const columns = ref<FieldOption[]>([
{ key: 0, label: `项目周报明细ID`, visible: true },
{ key: 1, label: `项目周报ID`, visible: true },
{ key: 2, label: `项目ID`, visible: true },
{ 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: true },
{ key: 12, label: `项目状态`, visible: true },
{ key: 13, label: `周报状态(1暂存 2审批中 3可用)`, visible: true },
{ key: 14, label: `流程状态`, visible: true },
{ key: 15, label: `排序号`, visible: true },
{ key: 16, label: `项目阶段(预留)`, visible: true },
{ key: 17, label: `合同ID(预留)`, visible: true },
{ key: 18, label: `附件ID`, visible: true },
{ key: 19, label: `备注`, visible: true },
{ key: 20, label: `激活标识`, visible: true },
{ key: 21, label: `删除标志`, visible: true },
{ key: 22, label: `创建部门`, visible: true },
{ key: 23, label: `创建时间`, visible: true },
{ key: 24, label: `创建人`, visible: true },
{ key: 25, label: `更新人`, visible: true },
{ key: 26, label: `更新时间`, visible: true }
{ key: 0, label: `项目周报ID`, visible: false },
{ key: 1, label: `租户编号`, visible: false },
{ key: 2, label: `项目ID`, visible: false },
{ key: 3, label: `项目名称`, visible: true },
{ key: 4, label: `当前里程碑`, visible: true },
{ key: 5, label: `项目经理`, visible: true },
{ key: 6, label: `部门ID`, 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: `附件ID`, visible: true },
{ key: 12, label: `备注`, visible: true },
{ key: 13, label: `激活标识`, visible: true },
{ key: 14, label: `删除标志`, visible: true },
{ key: 15, label: `创建部门`, visible: true },
{ key: 16, label: `创建人`, visible: true },
{ key: 17, label: `创建时间`, visible: true },
{ key: 18, label: `更新人`, visible: true },
{ key: 19, label: `更新时间`, visible: true },
{ key: 20, label: `项目编码`, visible: true }
]);
const initFormData: ProjectReportForm = {
reportId: undefined,
projectId: undefined,
@ -282,7 +275,11 @@ const initFormData: ProjectReportForm = {
sortOrder: undefined,
ossId: undefined,
remark: undefined,
activeFlag: undefined
activeFlag: undefined,
deptName: undefined,
managerName: undefined,
chargeName: undefined,
deputyName: undefined
};
const data = reactive<PageData<ProjectReportForm, ProjectReportQuery>>({
form: { ...initFormData },
@ -301,51 +298,23 @@ const data = reactive<PageData<ProjectReportForm, ProjectReportQuery>>({
sortOrder: undefined,
ossId: undefined,
activeFlag: undefined,
deptName: undefined,
managerName: undefined,
chargeName: undefined,
deputyName: undefined,
params: {}
},
rules: {
reportId: [{ required: true, message: '项目周报ID不能为空', trigger: 'blur' }]
projectName: [{ required: true, message: '项目名称不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询项目周报信息列表 */
const getList = async () => {
loading.value = true;
const res = await listProjectReport(queryParams.value);
projectReportList.value = res.rows;
total.value = res.total;
loading.value = false;
//
const openProjectSelect = () => {
projectSelectRef.value.open();
};
//
const projectInfoSelectCallBack = (data: any) => {
const projectInfoList = data;
console.log(projectInfoList);
if (projectInfoList.length > 0) {
queryParams.value.projectId = projectInfoList[0].projectId;
queryParams.value.projectName = projectInfoList[0].projectName;
queryParams.value.projectCode = projectInfoList[0].projectCode;
queryParams.value.managerId = projectInfoList[0].managerId;
queryParams.value.milestonePlan = projectInfoList[0].milestonePlan;
queryParams.value.deptId = projectInfoList[0].deptId;
queryParams.value.chargeId = projectInfoList[0].chargeId;
} else {
}
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
projectReportDetailFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
@ -357,6 +326,54 @@ const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
/** 根据部门查询项目周报信息列表 */
const getList = async () => {
loading.value = true;
const res = await listProjectReport(queryParams.value);
projectReportList.value = res.rows;
total.value = res.total;
loading.value = false;
};
//
const projectInfoSelectCallBack = (data: any) => {
if (data.length > 0) {
setFromProjectInfo(data);
getList();
} else {
queryFormRef.value?.resetFields();
proxy?.$modal.msgWarning('请选择项目信息');
getList();
}
};
//
const setFromProjectInfo = (data: any) => {
const projectInfoList = data;
queryParams.value.projectId = projectInfoList[0].projectId;
queryParams.value.projectName = projectInfoList[0].projectName;
queryParams.value.projectCode = projectInfoList[0].projectCode;
queryParams.value.managerId = projectInfoList[0].managerId;
queryParams.value.milestonePlan = projectInfoList[0].milestonePlan;
queryParams.value.deptId = projectInfoList[0].deptId;
queryParams.value.chargeId = projectInfoList[0].chargeId;
queryParams.value.deputyId = projectInfoList[0].deputyId;
queryParams.value.managerName = projectInfoList[0].managerName;
queryParams.value.deptName = projectInfoList[0].deptName;
queryParams.value.chargeName = projectInfoList[0].chargeName;
queryParams.value.deputyName = projectInfoList[0].deputyName;
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 所有表单重置 */
const reset = () => {
form.value = { ...initFormData };
projectReportFormRef.value?.resetFields();
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: ProjectReportVO[]) => {
@ -368,8 +385,26 @@ const handleSelectionChange = (selection: ProjectReportVO[]) => {
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加项目周报信息';
proxy.$tab.closePage(route);
//
const routeParams = {
type: 'add',
projectId: queryParams.value.projectId,
projectName: queryParams.value.projectName,
projectCode: queryParams.value.projectCode,
managerId: queryParams.value.managerId,
managerName: queryParams.value.managerName,
deptId: queryParams.value.deptId,
deptName: queryParams.value.deptName,
chargeId: queryParams.value.chargeId,
chargeName: queryParams.value.chargeName,
deputyId: queryParams.value.deputyId,
deputyName: queryParams.value.deputyName
};
router.push({
path: '/project/projectReport/edit',
query: routeParams
});
};
/** 修改按钮操作 */
@ -384,7 +419,7 @@ const handleUpdate = async (row?: ProjectReportVO) => {
/** 提交按钮 */
const submitForm = () => {
projectReportDetailFormRef.value?.validate(async (valid: boolean) => {
projectReportFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.reportId) {

Loading…
Cancel
Save