diff --git a/src/api/system/systemLog.ts b/src/api/system/systemLog.ts
index 4d0f7a1d..b3a5ca32 100644
--- a/src/api/system/systemLog.ts
+++ b/src/api/system/systemLog.ts
@@ -16,3 +16,8 @@ export const getHourlyOnlineStatisticsApi = (params: any) => {
export const getUserLoginStatisticsApi = (params: any) => {
return post(`${PREFIX}systemLog/getUserLoginStatistics`, params);
};
+
+// 统计某时间段(天)的文件下载数
+export const getDailyOperateStatisticsApi = (params: any) => {
+ return post(`${PREFIX}systemLog/getDailyOperateStatistics`, params);
+};
diff --git a/src/components/common/treeCaseTable/nodeDetailDialog.vue b/src/components/common/treeCaseTable/nodeDetailDialog.vue
index 9ae38cf0..a7b69259 100644
--- a/src/components/common/treeCaseTable/nodeDetailDialog.vue
+++ b/src/components/common/treeCaseTable/nodeDetailDialog.vue
@@ -26,17 +26,20 @@
@change="onFormChangeFun"
>
-
-
+
+
+
+
-
+
@@ -58,15 +61,18 @@ import { getTagKeyMap, NODE_TYPE } from '@/utils/enum/node';
import { disposeTaskMembers } from '@/utils/task';
import { disposeTagKey } from '@/views/task/projectDetail/components/project';
import { isCategoryType, isCategoryNodeType, validateCategoryLevel } from '@/utils/node';
-import flowTemplateSelect from './flowTemplateSelect.vue';
-import knowledgeSelect from './knowledgeSelect.vue';
-import nodeNameMixed from './nodeNameMixed.vue';
+import FlowTemplateSelect from './flowTemplateSelect.vue';
+import ReportTemplateSelect from './reportTemplateSelect.vue';
+import KnowledgeSelect from './knowledgeSelect.vue';
+import NodeNameMixed from './nodeNameMixed.vue';
import { TABLE_NAME } from '@/utils/enum/tableName';
import { useDict } from '@/utils/useDict';
import { useI18n } from 'vue-i18n';
import { useTaskStore } from '@/stores/taskPool';
+import { useReportStore } from '@/stores/reportTemplate';
const taskStore = useTaskStore();
+const reportStore = useReportStore();
enum OPERATION_TYPE {
ADD = 'add',
EDIT = 'edit',
@@ -138,6 +144,7 @@ watch(
}
});
taskStore.fetchTemplates(true);
+ reportStore.fetchTemplates(true);
}
}
);
diff --git a/src/components/common/treeCaseTable/reportTemplateSelect.vue b/src/components/common/treeCaseTable/reportTemplateSelect.vue
new file mode 100644
index 00000000..1a258cba
--- /dev/null
+++ b/src/components/common/treeCaseTable/reportTemplateSelect.vue
@@ -0,0 +1,210 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('工况库.关联N个报告模版', { count: selectedTemplates.length }) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/common/treeCaseTable/treeTable.vue b/src/components/common/treeCaseTable/treeTable.vue
index d434e7ac..11f20e01 100644
--- a/src/components/common/treeCaseTable/treeTable.vue
+++ b/src/components/common/treeCaseTable/treeTable.vue
@@ -322,6 +322,21 @@
+
+
+
+
+
+
+
+
+
([]);
const taskStore = useTaskStore();
+const reportStore = useReportStore();
const treeDataFormatFun = (data: any, build: any, pId: any) => {
data.forEach((item: any) => {
@@ -721,6 +739,7 @@ const seeApproveDetailFun = async (row: any) => {
onMounted(() => {
initProjectDicts();
taskStore.fetchTemplates();
+ reportStore.fetchTemplates();
});
defineExpose({
diff --git a/src/components/common/userSelect/index.vue b/src/components/common/userSelect/index.vue
index dd078cb2..4fd07f88 100644
--- a/src/components/common/userSelect/index.vue
+++ b/src/components/common/userSelect/index.vue
@@ -9,6 +9,7 @@
:remote="remote"
:remote-method="getUserDataByKeyFun"
clearable
+ :collapse-tags="multiple"
:disabled="disabled"
:multiple="multiple"
:fit-input-width="fitInputWidth"
diff --git a/src/components/taskDetail/taskInfo.vue b/src/components/taskDetail/taskInfo.vue
index 03db009d..e047f959 100644
--- a/src/components/taskDetail/taskInfo.vue
+++ b/src/components/taskDetail/taskInfo.vue
@@ -15,13 +15,14 @@
-
+
@@ -68,6 +69,9 @@ const formAttrs = ref({
step: 0.01,
},
});
+const searchParams = ref({
+ businessId: props.taskInfo.uuid,
+});
const localDetail = ref({});
@@ -186,7 +190,8 @@ onMounted(() => {});
}
}
.oprate-log {
- flex: 1;
+ // flex: 1;
+ height: calc(100% - 210px);
}
}
diff --git a/src/stores/reportTemplate.ts b/src/stores/reportTemplate.ts
new file mode 100644
index 00000000..3bfeeec2
--- /dev/null
+++ b/src/stores/reportTemplate.ts
@@ -0,0 +1,57 @@
+import { defineStore } from 'pinia';
+import { ref, computed } from 'vue';
+import { queryReportTemplateApi } from '@/api/capability/report';
+import { REPORT_TEMPLATE_PUBLIC_STATUS, FLOW_USE_STATUS } from '@/utils/enum/report';
+
+interface ReportTemplate {
+ templateName?: string;
+ templateCode?: string;
+ [k: string]: any;
+}
+
+export const useReportStore = defineStore('reportTemplate', () => {
+ const templates = ref([]);
+ const loaded = ref(false);
+ let pendingPromise: Promise | null = null;
+
+ const options = computed(() =>
+ templates.value.map((item) => ({
+ label: item.templateName || '',
+ value: item.templateCode || '',
+ }))
+ );
+
+ const fetchTemplates = async (force = false) => {
+ if (!force && loaded.value && templates.value.length) return templates.value;
+ if (pendingPromise) return pendingPromise;
+
+ pendingPromise = (async () => {
+ try {
+ const req = {
+ current: 1,
+ size: 99999,
+ type: REPORT_TEMPLATE_PUBLIC_STATUS.PUBLIC,
+ templateStatus: FLOW_USE_STATUS.USED,
+ };
+ const res: any = await queryReportTemplateApi(req);
+ if (res && res.code === 200) {
+ const list = res.data?.data || res.data || [];
+ templates.value = Array.isArray(list) ? list : [];
+ } else {
+ templates.value = [];
+ }
+ loaded.value = true;
+ } catch {
+ templates.value = [];
+ loaded.value = true;
+ } finally {
+ pendingPromise = null;
+ }
+ return templates.value;
+ })();
+
+ return pendingPromise;
+ };
+
+ return { templates, options, fetchTemplates, loaded };
+});
diff --git a/src/utils/enum/node.ts b/src/utils/enum/node.ts
index 9ae06daa..627564ad 100644
--- a/src/utils/enum/node.ts
+++ b/src/utils/enum/node.ts
@@ -108,6 +108,7 @@ export const poolNodePropPickMap = {
'days',
'flowTemplate',
'standard',
+ 'reportTemplate',
'analyseTarget',
'confidence',
'analyseSoftware',
diff --git a/src/utils/i18n/en.ts b/src/utils/i18n/en.ts
index f608387d..fb2dc654 100644
--- a/src/utils/i18n/en.ts
+++ b/src/utils/i18n/en.ts
@@ -87,6 +87,9 @@ const lang = {
项目详情: 'Project Detail',
任务创建: 'Task Creation',
仿真执行: 'Task Execution',
+ 报工列表: 'Work Report List',
+ 我确认的: 'I Confirmed',
+ 我负责的: 'I Responsible',
应用中心: 'Application Center',
数据管理: 'Data Management',
数据总览: 'Data Overview',
@@ -201,6 +204,7 @@ const lang = {
没有修改的数据需要提交审批: 'No modified data to submit for approval',
指标库列表: 'Performance Pool List',
关联N个流程模版: 'Associated {count} Flow Templates',
+ 关联N个报告模版: 'Associated {count} Report Templates',
关联N个执行规范: 'Associated {count} Standards',
关联N个工况: 'Associated {count} Tasks',
请选择工况库: 'Please select task pool',
@@ -329,6 +333,7 @@ const lang = {
'指标完成统计(学科)': 'Performance Completion Statistics (Discipline)',
工位评审通过统计: 'Workspace Review Statistics',
项目任务完成情况统计: 'Project Task Completion Statistics',
+ 文件操作统计: 'File Operate Statistics',
},
工位时间维护: {
阶段: 'Phase',
diff --git a/src/utils/i18n/zh.ts b/src/utils/i18n/zh.ts
index f60b4902..b8fd02f2 100644
--- a/src/utils/i18n/zh.ts
+++ b/src/utils/i18n/zh.ts
@@ -86,6 +86,9 @@ const lang = {
项目详情: '项目详情',
任务创建: '任务创建',
仿真执行: '仿真执行',
+ 报工列表: '报工列表',
+ 我确认的: '我确认的',
+ 我负责的: '我负责的',
应用中心: '应用中心',
数据管理: '数据管理',
数据总览: '数据总览',
@@ -197,6 +200,7 @@ const lang = {
没有修改的数据需要提交审批: '没有修改的数据需要提交审批',
指标库列表: '指标库列表',
关联N个流程模版: '关联{count}个流程模版',
+ 关联N个报告模版: '关联{count}个报告模版',
关联N个执行规范: '关联{count}个执行规范',
关联N个工况: '关联{count}个工况',
请选择工况库: '请选择工况库',
@@ -324,6 +328,7 @@ const lang = {
'指标完成统计(学科)': '指标完成统计(学科)',
工位评审通过统计: '工位评审通过统计',
项目任务完成情况统计: '项目任务完成情况统计',
+ 文件操作统计: '文件操作统计',
},
工位时间维护: {
阶段: '阶段',
diff --git a/src/views/simulation/parameter/components/addParamObject.vue b/src/views/simulation/parameter/components/addParamObject.vue
index c894ee49..f1d30cfe 100644
--- a/src/views/simulation/parameter/components/addParamObject.vue
+++ b/src/views/simulation/parameter/components/addParamObject.vue
@@ -7,13 +7,16 @@
v-model:data="formData"
showDisabled
:itemNum="6"
+ :hideKeys="hideKeys"
@change="changeFun"
+ @remove="removeFun"
:formAttrs="{
templateId: {
moduleCode: 'PARAM_APPROVAL',
},
files: {
accept: '.json',
+ multiple: false,
},
}"
/>
@@ -55,22 +58,37 @@ const closeFun = () => {
};
const onConfirmFun = async () => {
+ if (!formData.value.files.length) {
+ formData.value.templateId = '';
+ formData.value.templateName = '';
+ }
const valid = await tableFormRef.value?.validateFun();
if (valid) {
emits('createFun', formData.value);
}
};
+const hideKeys = ref(['templateId']);
+
const changeFun = (data: any) => {
const { key, val } = data;
if (key === 'files') {
formData.value.file = val.raw;
formData.value.fileName = val.name;
+ hideKeys.value = [];
}
if (key === 'templateId') {
formData.value.templateName = val.label;
}
};
+const removeFun = (data: any) => {
+ const { key } = data;
+ if (key === 'files') {
+ formData.value.file = '';
+ formData.value.fileName = '';
+ hideKeys.value = ['templateId'];
+ }
+};
onMounted(() => {
if (props.libTypeInfo) {
diff --git a/src/views/simulation/parameter/index.vue b/src/views/simulation/parameter/index.vue
index 24068ccc..64e9fbda 100644
--- a/src/views/simulation/parameter/index.vue
+++ b/src/views/simulation/parameter/index.vue
@@ -421,10 +421,12 @@ const creatLibParamObjFun = async (data: any) => {
parameterLibraryId: data.parameterLibraryId,
parameterLibraryCategoryId: data.parameterLibraryCategoryId,
parameterLibraryCategoryObjectName: data.parameterLibraryCategoryObjectName,
- fileName: data.fileName,
- file: data.file,
- templateId: data.templateId,
- templateName: data.templateName,
+ ...(data.file && {
+ fileName: data.fileName,
+ file: data.file,
+ templateId: data.templateId,
+ templateName: data.templateName,
+ }),
});
if (res && res.code === 200) {
@@ -434,6 +436,8 @@ const creatLibParamObjFun = async (data: any) => {
return item.name === data.parameterLibraryCategoryObjectName;
});
libTreeRef.value.append(node, currentNode.value.nodeKey);
+ } else {
+ ElMessage.warning(res.message);
}
showParamObjVisible.value = false;
};
@@ -454,15 +458,25 @@ const deleteConfirmFun = () => {
const deleteParamFun = async (flag: any, row?: any) => {
currentNode.value = { ...row };
- // 如果删除的是参数,要走审批流程
+ // 如果删除的是参数对象,
if (flag === 'param') {
- delParams.value = {
- // type: currentNode.value.type,
- // id: currentNode.value.id,
- type: row.type,
- id: row.id,
- };
- approveDelShow.value = true;
+ // 有参数 要走审批流程,没参数可以直接删
+ const res: any = await getSimulationParameterLibraryCategoryObjectApi({
+ ObjectId: row.id,
+ });
+ if (res && res.code === 200) {
+ if (res.data && res.data.parameterJsonValue && res.data.parameterJsonValue.length) {
+ delParams.value = {
+ type: row.type,
+ id: row.id,
+ };
+ approveDelShow.value = true;
+ } else {
+ // 直接删除
+ deleteAction(flag, row);
+ }
+ }
+
return;
} else {
// 0228需求 参数库、分类删除逻辑修改:下级有参数data=true,走审核流程;下级没有参数,直接删除
@@ -478,32 +492,36 @@ const deleteParamFun = async (flag: any, row?: any) => {
};
approveDelShow.value = true;
} else {
- // 走删除流程
- ElMessageBox.confirm(
- `确认要删除这个${flag === 'lib' ? '参数库' : flag === 'type' ? '参数库分类' : '参数对象'}吗?`,
- '警告',
- {
- confirmButtonText: '确认',
- cancelButtonText: '取消',
- type: 'warning',
- }
- ).then(async () => {
- const res: any = await deleteSimulationParameterApi({
- type: row.type,
- id: row.id,
- isApprove: false,
- });
- if (res && res.code === 200) {
- ElMessage.success('删除成功!');
- libTreeRef.value.remove(currentNode.value.nodeKey);
- currentNode.value = {};
- paramObjInfo.value = '';
- }
- });
+ deleteAction(flag, row);
}
}
};
+const deleteAction = (flag: any, row: any) => {
+ // 走删除流程
+ ElMessageBox.confirm(
+ `确认要删除这个${flag === 'lib' ? '参数库' : flag === 'type' ? '参数库分类' : '参数对象'}吗?`,
+ '警告',
+ {
+ confirmButtonText: '确认',
+ cancelButtonText: '取消',
+ type: 'warning',
+ }
+ ).then(async () => {
+ const res: any = await deleteSimulationParameterApi({
+ type: row.type,
+ id: row.id,
+ isApprove: false,
+ });
+ if (res && res.code === 200) {
+ ElMessage.success('删除成功!');
+ libTreeRef.value.remove(currentNode.value.nodeKey);
+ currentNode.value = {};
+ paramObjInfo.value = '';
+ }
+ });
+};
+
const updateParams = ref({});
const approveUpdateShow = ref(false);
const updateParamFun = () => {
diff --git a/src/views/simulation/reportLib/components/addDialog.vue b/src/views/simulation/reportLib/components/addDialog.vue
index 96e127c6..a9a8124c 100644
--- a/src/views/simulation/reportLib/components/addDialog.vue
+++ b/src/views/simulation/reportLib/components/addDialog.vue
@@ -45,7 +45,7 @@
取消
确定 {
if (await tableFormRef.value.validateFun()) {
loadingInterface.value = true;
const flowForm = tableFormRef.value.getFormDataFun();
+ flowForm.simulationPoolInfoList = simulationPoolInfoList.value;
if (
props.dialogType === REPORT_OPERATION_TYPE.CREATE ||
props.dialogType === REPORT_OPERATION_TYPE.COPY
) {
const formData = new FormData();
formData.append('templateVersion', 'V1.0');
+ formData.append('simulationPoolInfoListStr', JSON.stringify(simulationPoolInfoList.value));
for (const key in flowForm) {
if (key === 'file') {
// 就算复制模板,如果上传了新的文件就不复制文件了
@@ -122,7 +124,8 @@ const confirmFun = async (type: string) => {
key !== 'templateStatus' &&
key !== 'creatorName' &&
key !== 'createTime' &&
- key !== 'approveType'
+ key !== 'approveType' &&
+ key !== 'simulationPoolInfoList'
) {
formData.append(key, flowForm[key] ? flowForm[key] : '');
}
@@ -130,17 +133,27 @@ const confirmFun = async (type: string) => {
}
const flowUuid = await createFlow(formData);
emits('confirm', { type, uuid: flowUuid });
- } else if (props.dialogType === REPORT_OPERATION_TYPE.UPGRADE) {
- emits('confirm', {
- type,
- uuid: flowForm.uuid,
- comment: flowForm.comment,
- file: flowForm.file,
- fileId: flowForm.file[0].id,
- });
} else {
- await editReport(flowForm);
- emits('confirm', { type, uuid: flowForm.uuid });
+ if (type === 'ok') {
+ await editReport(flowForm);
+ emits('confirm', { type, uuid: flowForm.uuid, tVersion: props.templateVersion });
+ }
+ if (type === 'next') {
+ if (oldComment.value !== flowForm.comment) {
+ // 升版时只更新描述,不更新工况,工况在提交审批时传递给接口
+ await editReport({ ...flowForm, simulationPoolInfoList: oldSimulationPoolInfoList.value });
+ }
+ emits('confirm', {
+ type,
+ uuid: flowForm.uuid,
+ comment: flowForm.comment,
+ file: flowForm.file,
+ fileId: flowForm.file[0].id,
+ tVersion: props.templateVersion,
+ // 不更新工况,工况在提交审批时传递给升版接口
+ simulationPoolInfoList: hasChangeLoadcase.value ? simulationPoolInfoList.value : null,
+ });
+ }
}
loadingInterface.value = false;
}
@@ -188,6 +201,7 @@ const editReport = async (params: any) => {
formData.append('extras', params.extras);
formData.append('fileId', oldFormData.value.fileId);
formData.append('templateContent', oldFormData.value.templateContent);
+ formData.append('simulationPoolInfoListStr', JSON.stringify(params.simulationPoolInfoList));
if (params.file && params.file.length > 0) {
if (params.file[0].raw) {
formData.append('file', params.file[0].raw);
@@ -217,12 +231,17 @@ const closeFun = () => {
const oldFormData = ref({});
-const editRowInfo = ref({});
+const editRowInfo = ref({});
+
+const oldSimulationPoolInfoList = ref([]);
+const oldComment = ref('');
const setEditForm = (val: any) => {
oldFormData.value = val;
// nextTick(() => {
simulationPoolInfoList.value = val.simulationPoolInfoList || [];
+ oldSimulationPoolInfoList.value = val.simulationPoolInfoList || [];
+ oldComment.value = val.comment;
// tableFormRef.value.setFormDataFun({ ...val });
editRowInfo.value = { ...val };
// });
@@ -245,6 +264,29 @@ const setOptionsFun = (key: string, options: any[]) => {
tableFormRef.value.setOptionsFun(key, options);
};
+const hasChangeLoadcase = ref(false);
+
+watch(
+ () => simulationPoolInfoList.value,
+ () => {
+ const oldIds: any[] = [];
+ oldSimulationPoolInfoList.value.forEach((item) => {
+ oldIds.push(...item.simulationPoolTaskIds);
+ });
+ const newIds: any[] = [];
+ simulationPoolInfoList.value.forEach((item) => {
+ newIds.push(...item.simulationPoolTaskIds);
+ });
+ oldIds.sort();
+ newIds.sort();
+ if (JSON.stringify(oldIds) !== JSON.stringify(newIds)) {
+ hasChangeLoadcase.value = true;
+ } else {
+ hasChangeLoadcase.value = false;
+ }
+ }
+);
+
watch(
() => props.showDialog,
async () => {
diff --git a/src/views/task/dashboard/components/dataStatistics.vue b/src/views/task/dashboard/components/dataStatistics.vue
index b0eb5e6d..e79a1d37 100644
--- a/src/views/task/dashboard/components/dataStatistics.vue
+++ b/src/views/task/dashboard/components/dataStatistics.vue
@@ -28,6 +28,7 @@
import { onMounted, ref, provide } from 'vue';
import { getThemeColor } from '@/utils/theme';
// 引入子组件
+import fileOperateChart from './dataStatistics/fileOperateChart.vue';
import userGroupProjectChart from './dataStatistics/userGroupProjectChart.vue';
import userTaskCompleteChart from './dataStatistics/userTaskCompleteChart.vue';
import userDifficultyCoefficientChart from './dataStatistics/userDifficultyCoefficientChart.vue';
@@ -145,6 +146,11 @@ const baseList = ref([
processNodeColorList,
},
},
+ {
+ id: 'fileOperate',
+ component: fileOperateChart,
+ props: {},
+ },
]);
// 当前展示的图表
const currentList = ref();
diff --git a/src/views/task/dashboard/components/dataStatistics/fileOperateChart.vue b/src/views/task/dashboard/components/dataStatistics/fileOperateChart.vue
new file mode 100644
index 00000000..3acd97d0
--- /dev/null
+++ b/src/views/task/dashboard/components/dataStatistics/fileOperateChart.vue
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/task/dashboard/components/dataStatistics/settingDia.vue b/src/views/task/dashboard/components/dataStatistics/settingDia.vue
index 067a1e07..ae6e2213 100644
--- a/src/views/task/dashboard/components/dataStatistics/settingDia.vue
+++ b/src/views/task/dashboard/components/dataStatistics/settingDia.vue
@@ -86,6 +86,7 @@ const baseTable = [
{ key: 'performanceCompletionMechine', title: '指标完成统计(机台)', inBoard: true },
{ key: 'performanceCompletionDiscipline', title: '指标完成统计(学科)', inBoard: true },
{ key: 'reviewPassed', title: '工位评审通过统计', inBoard: true },
+ { key: 'fileOperate', title: '文件下载统计', inBoard: true },
];
const vxeTableRef = ref();
diff --git a/src/views/task/projectDetail/components/taskDetail.vue b/src/views/task/projectDetail/components/taskDetail.vue
index 890e2aae..dd3c34bb 100644
--- a/src/views/task/projectDetail/components/taskDetail.vue
+++ b/src/views/task/projectDetail/components/taskDetail.vue
@@ -9,7 +9,7 @@
show-footer
>
-
+
-
+
@@ -350,7 +350,7 @@ const reportInpDiaShow = ref(false);
const dialogVisible = ref(true);
// const activeTab = ref(props.showTaskInfo ? 'info' : 'model-3d');
const activeTab = ref('info');
-const activeRadio = ref('report');
+const activeRadio = ref('detail');
const keyResultType = ref('performance');
const taskPerformanceRef = ref();
const taskInfoRef = ref();