update:预览

This commit is contained in:
2025-12-03 14:42:59 +08:00
parent 70e5841ba0
commit 4905044629
8 changed files with 257 additions and 92 deletions

View File

@@ -1,9 +1,9 @@
<!DOCTYPE html>
<!doctype html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SPDM</title>
</head>
<body>

View File

@@ -131,7 +131,10 @@ export const addLibraryCategoryApi = (params: any) => {
* @returns
*/
export const getSimulationParameterLibraryCategoryObjectApi = (params: any) => {
return get(`${PREFIX}simulationParameterLibrary/getSimulationParameterLibraryCategoryObject`, params);
return get(
`${PREFIX}simulationParameterLibrary/getSimulationParameterLibraryCategoryObject`,
params
);
};
/**
@@ -238,3 +241,8 @@ export const callBackknowledgeFileApi = (params: any) => {
export const chunkUploadCallbackApi = (params: any) => {
return post(`${PREFIX}data/chunkUploadCallback`, params);
};
// onlyOffice获取文件信息
export const downloadFileForEditApi = (params: any) => {
return get(`${PREFIX}data/downloadFileForEdit`, params);
};

View File

@@ -1,14 +1,14 @@
<template>
<div>
<Dialog
diaTitle="预览文件"
v-model="diaVisible"
fullscreen
@close="closeFun"
>
<div v-if="url" class="content">
<iframe class="iframe" :src="url" />
</div>
<Dialog v-model="diaVisible" diaTitle="预览文件" top="5vh" width="70%" @close="closeFun">
<template v-if="diaVisible">
<div v-if="url && type === 'default'" class="content">
<iframe class="iframe" :src="url" />
</div>
<div v-if="fileId && type === 'edit'" class="content">
<OnlyOffiece :fileId="fileId" />
</div>
</template>
</Dialog>
</div>
</template>
@@ -17,15 +17,18 @@
import { ref, watch } from 'vue';
import { getKKFileViewURLFromMinioApi } from '@/api/data/data';
import Dialog from '@/components/common/dialog/index.vue';
import OnlyOffiece from '@/components/common/onlyOffice/index.vue';
interface Props {
modelValue: boolean;
fileId: number;
type?: string;
}
const props = withDefaults(defineProps<Props>(), {
modelValue: false,
fileId: 0,
type: 'default', // default默认 edit启动onlyOffice
});
const env = import.meta.env;
@@ -34,12 +37,15 @@ const url = ref('');
const emit = defineEmits(['update:modelValue']);
watch(() => props.modelValue, (val: boolean) => {
diaVisible.value = val;
if (val) {
getPreviewUrlFun();
watch(
() => props.modelValue,
(val: boolean) => {
diaVisible.value = val;
if (val) {
getPreviewUrlFun();
}
}
});
);
const getPreviewUrlFun = () => {
const params = {
@@ -60,9 +66,10 @@ const closeFun = () => {
<style lang="scss" scoped>
.content {
width: 100%;
height: calc(90vh - 85px);
.iframe {
width: 100%;
height: calc(100vh - 74px);
height: 100%;
}
}
</style>

View File

@@ -0,0 +1,84 @@
<template>
<div class="comp-only-office">
<div id="fileEdit"></div>
</div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue';
import { downloadFileForEditApi } from '@/api/data/data';
import { getUserId } from '@/utils/user';
// 支持DOCX XLSX PPTX PDF
interface Props {
fileId: any;
}
const props = withDefaults(defineProps<Props>(), {
fileId: '',
});
const win: any = window;
let fileData: any = {};
onMounted(() => {
initFun();
});
const initFun = () => {
const params = {
fileId: props.fileId,
};
downloadFileForEditApi(params).then((res: any) => {
if (res.code === 200) {
fileData = res.data;
editFun();
}
});
};
const editFun = () => {
const { url, fileType, fileName } = fileData;
new win.DocsAPI.DocEditor('fileEdit', {
type: 'desktop', // 桌面模式
width: '100%',
height: '100%',
document: {
title: fileName,
url: url, // 文件地址
fileType: fileType,
key: `${props.fileId}_${getUserId()}`,
permissions: {
// 操作权限
download: true,
edit: true,
fillForms: true,
print: true,
},
},
editorConfig: {
lang: 'zh-CN', // 语言
callbackUrl: 'http://192.168.65.199:7104/data/onlyOfficeCallback', // 保持回调地址
customization: {
anonymous: {
request: false, // 不允许匿名编辑
},
autosave: false, // 自动保存
forcesave: true, // 强制保存
},
},
});
};
</script>
<style lang="scss" scoped>
.comp-only-office {
width: 100%;
height: 100%;
#fileEdit {
width: 100%;
height: 100%;
background-color: #aaa;
}
}
</style>

View File

@@ -15,8 +15,8 @@
</div>
<div v-else>
<div class="icon-btns">
<el-icon :size="18" class="cover-icon add" @click="previewFun"><View /></el-icon>
<el-icon v-if="!disabled" class="cover-icon del" :size="18" @click="delFun">
<el-icon :size="14" class="cover-icon add" @click="previewFun"><View /></el-icon>
<el-icon v-if="!disabled" :size="14" class="cover-icon del" @click="delFun">
<Delete />
</el-icon>
</div>
@@ -133,6 +133,8 @@ const updateFun = (data: any) => {
width: auto !important;
height: 22px !important;
.content {
display: flex;
align-items: center;
border: none;
.upload {
.add-text {

View File

@@ -22,7 +22,6 @@
import { ref, watch } from 'vue';
import TableForm from '@/components/common/table/tableForm.vue';
import { dataOverViewSearchSimulationNodeFilesApi } from '@/api/data/dataOverView';
import { ElMessage } from 'element-plus';
const emit = defineEmits(['update:modelValue', 'search']);
const tableFormRef = ref();
@@ -38,11 +37,14 @@ const props = withDefaults(defineProps<Props>(), {
dirId: 0,
});
watch(() => props.modelValue, (val: boolean) => {
visible.value = val;
});
watch(
() => props.modelValue,
(val: boolean) => {
visible.value = val;
}
);
const searchFun = async() => {
const searchFun = async () => {
const valid = await tableFormRef.value.validateFun();
if (valid) {
const fromData = tableFormRef.value.getFormDataFun();
@@ -54,7 +56,6 @@ const searchFun = async() => {
};
dataOverViewSearchSimulationNodeFilesApi(params).then((res: any) => {
if (res.code === 200) {
ElMessage.success('操作成功');
emit('search', res.data);
closeFun();
}

View File

@@ -6,7 +6,7 @@
:api="getSimulationNodeTreeApi"
:templateId="currentDimension"
:params="{
dimensionTemplateId: currentDimension
dimensionTemplateId: currentDimension,
}"
@choseNode="choseNodeFun"
@search="searchShow = true"
@@ -51,10 +51,18 @@
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="addDiaFun(NODE_TYPE.PROJECT)">新增项目</el-dropdown-item>
<el-dropdown-item @click="addDiaFun(NODE_TYPE.PHASE)">新增阶段</el-dropdown-item>
<el-dropdown-item @click="addDiaFun(NODE_TYPE.CATEGORY)">新增分类</el-dropdown-item>
<el-dropdown-item @click="addDiaFun(NODE_TYPE.TASK)">新增任务</el-dropdown-item>
<el-dropdown-item @click="addDiaFun(NODE_TYPE.PROJECT)">
新增项目
</el-dropdown-item>
<el-dropdown-item @click="addDiaFun(NODE_TYPE.PHASE)">
新增阶段
</el-dropdown-item>
<el-dropdown-item @click="addDiaFun(NODE_TYPE.CATEGORY)">
新增分类
</el-dropdown-item>
<el-dropdown-item @click="addDiaFun(NODE_TYPE.TASK)">
新增任务
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
@@ -74,7 +82,14 @@
</template>
</el-dropdown>
<el-button :icon="Edit" type="primary" @click="editFun">编辑</el-button>
<el-button :icon="Delete" type="danger" :disabled="chosenData.length === 0" @click="delFun">删除</el-button>
<el-button
:icon="Delete"
type="danger"
:disabled="chosenData.length === 0"
@click="delFun"
>
删除
</el-button>
<el-button :icon="Refresh" @click="reloadFun">刷新</el-button>
<span class="info-switch">
<el-switch
@@ -92,10 +107,12 @@
<el-icon :size="16">
<MessageBox v-if="row.relatedResourceUuidOwnType === NODE_TYPE.PROJECT" />
<Share v-else-if="row.relatedResourceUuidOwnType === NODE_TYPE.PHASE" />
<Document v-else-if="row.relatedResourceUuidOwnType === NODE_TYPE.TASK"/>
<Document v-else-if="row.relatedResourceUuidOwnType === NODE_TYPE.TASK" />
<Folder v-else />
</el-icon>
<el-link type="primary" class="name" @dblclick="goDetailFun(row)">{{ row.originalName }}</el-link>
<el-link type="primary" class="name" @dblclick="goDetailFun(row)">
{{ row.originalName }}
</el-link>
</template>
<template v-else>
<el-icon :size="16">
@@ -117,9 +134,7 @@
</BaseTable>
</div>
<div v-if="infoShow" class="info">
<FileInfo
:data="fileData"
/>
<FileInfo :data="fileData" />
</div>
</div>
</template>
@@ -130,16 +145,8 @@
:dimensionId="currentDimension"
@confirm="reloadNodeFun"
/>
<FileSearch
v-model="searchShow"
:dirId="currentData.id"
@search="searchFileFun"
/>
<AddDir
v-model="addDirShow"
:data="currentData"
@submit="reloadNodeFun"
/>
<FileSearch v-model="searchShow" :dirId="currentData.id" @search="searchFileFun" />
<AddDir v-model="addDirShow" :data="currentData" @submit="reloadNodeFun" />
<PhaseInfoDia
v-if="showNodeInfoDialog"
v-model:showNodeInfoDialog="showNodeInfoDialog"
@@ -155,11 +162,12 @@
/>
<NodeDetailDialog
v-model="modalVisible"
:operationType="editId ? 'edit': 'add'"
:operationType="editId ? 'edit' : 'add'"
:nodeType="nodeType"
:detail="editId ? editData: null"
:detail="editId ? editData : null"
@confirm="editNodeFun"
/>
<FilePreview v-model="previewVisible" :fileId="previewFileId" />
</div>
</template>
@@ -167,9 +175,19 @@
import { ref, onMounted, watch } from 'vue';
import FileTree from '@/components/common/dataFileTree/index.vue';
import { getSimulationNodeTreeApi, getAllTemplateApi } from '@/api/data/dimensionTemplate';
import { addNodeForDataApi, addTaskForDataApi, editTaskForDataApi, editNodeForDataApi, getNodeDetailForDataApi } from '@/api/project/node';
import {
addNodeForDataApi,
addTaskForDataApi,
editTaskForDataApi,
editNodeForDataApi,
getNodeDetailForDataApi,
} from '@/api/project/node';
import { getTaskDetailApi } from '@/api/project/task';
import { dataOverViewListSimulationNodeFilesApi, dataOverViewDeleteSimulationNodeFilesApi, dataOverViewUploadSimulationNodeFilesApi } from '@/api/data/dataOverView';
import {
dataOverViewListSimulationNodeFilesApi,
dataOverViewDeleteSimulationNodeFilesApi,
dataOverViewUploadSimulationNodeFilesApi,
} from '@/api/data/dataOverView';
import BaseTable from '@/components/common/table/baseTable.vue';
import Configuration from './components/configuration.vue';
import FileSearch from './components/search.vue';
@@ -179,12 +197,23 @@ import PhaseInfoDia from '@/components/project/phaseInfoDialog.vue';
import NodeDetailDialog from '@/components/common/treeCaseTable/nodeDetailDialog.vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import ProjectInfoDialog from '@/components/project/projectInfoDialog.vue';
import { CirclePlus, Upload, Edit, Refresh, Delete, Folder, Document, Share, MessageBox } from '@element-plus/icons-vue';
import {
CirclePlus,
Upload,
Edit,
Refresh,
Delete,
Folder,
Document,
Share,
MessageBox,
} from '@element-plus/icons-vue';
import { getTagMapList } from '@/utils/task';
import { NODE_TYPE } from '@/utils/enum/node';
import { useDict } from '@/utils/useDict';
import { formatFileSize } from '@/utils/file';
import { isCategoryNodeType } from '@/utils/node';
import FilePreview from '@/components/common/filePreview/index.vue';
const env = import.meta.env;
const { DATA_TYPE, DATA_SEARCH_FILE_TYPE } = useDict('DATA_TYPE', 'DATA_SEARCH_FILE_TYPE');
@@ -205,16 +234,32 @@ const chosenData = ref<any>([]);
const BaseTableRef = ref();
const fileData = ref<any>({});
const nodeType = ref<any>('');
const previewVisible = ref(false);
const previewFileId = ref<any>('');
const tableParams = ref<any>({
dimensionTemplateId: currentDimension.value,
fileId: '',
});
watch(() => currentDimension.value, (val: any) => {
tableParams.value.dimensionTemplateId = val;
});
watch(
() => currentDimension.value,
(val: any) => {
tableParams.value.dimensionTemplateId = val;
}
);
const actionList = ref([
{
title: '预览',
type: 'primary',
click: (row: any) => {
previewFileId.value = row.id;
previewVisible.value = true;
},
hide: (row: any) => {
return row.dataType === 1;
},
},
{
title: '下载',
type: 'primary',
@@ -256,7 +301,13 @@ const addDiaFun = (type: string) => {
showNodeInfoDialog.value = true;
}
if (type === NODE_TYPE.CATEGORY) {
if (!currentData.value || !(isCategoryNodeType(currentData.value.relatedResourceUuidOwnType) || NODE_TYPE.PHASE === currentData.value.relatedResourceUuidOwnType)) {
if (
!currentData.value ||
!(
isCategoryNodeType(currentData.value.relatedResourceUuidOwnType) ||
NODE_TYPE.PHASE === currentData.value.relatedResourceUuidOwnType
)
) {
ElMessage.warning('请在节点或分类下创建分类');
return;
}
@@ -308,23 +359,24 @@ const editFun = () => {
};
const delFun = () => {
ElMessageBox.confirm('删除后不可恢复,确认删除吗?', '提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
const proList: any[] = [];
chosenData.value.forEach((item: any) => {
proList.push(dataOverViewDeleteSimulationNodeFilesApi({ deleteId: item.id, dataType: item.dataType }));
});
Promise.all(proList).then(() => {
ElMessage.success('操作成功');
reloadNodeFun();
BaseTableRef.value?.resetFun();
});
}).catch(() => {});
ElMessageBox.confirm('删除后不可恢复,确认删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
const proList: any[] = [];
chosenData.value.forEach((item: any) => {
proList.push(
dataOverViewDeleteSimulationNodeFilesApi({ deleteId: item.id, dataType: item.dataType })
);
});
Promise.all(proList).then(() => {
ElMessage.success('操作成功');
reloadNodeFun();
});
})
.catch(() => {});
};
const cellClickFun = (data: any) => {
@@ -377,10 +429,12 @@ const editClassFun = (data: any) => {
} else {
api = addNodeForDataApi;
params = {
addNodeList: [{
...data,
pid: currentData.value.relatedResourceUuid,
}],
addNodeList: [
{
...data,
pid: currentData.value.relatedResourceUuid,
},
],
tagMap: getTagMapList(),
};
}
@@ -405,10 +459,12 @@ const editTaskFun = (data: any) => {
} else {
api = addTaskForDataApi;
params = {
addTaskList: [{
...data,
pid: currentData.value.relatedResourceUuid,
}],
addTaskList: [
{
...data,
pid: currentData.value.relatedResourceUuid,
},
],
tagMap: getTagMapList(),
};
}
@@ -447,11 +503,16 @@ const checkboxChangeFun = (data: any) => {
const reloadFun = () => {
chosenData.value = [];
currentData.value = '';
tableParams.value = {
dimensionTemplateId: currentDimension.value,
fileId: '',
};
FileTreeRef.value?.reloadFun();
};
const reloadNodeFun = () => {
FileTreeRef.value?.reloadNodeFun(currentData.value.id);
BaseTableRef.value?.resetFun();
};
</script>

View File

@@ -9,10 +9,7 @@ export default defineConfig(({ mode }) => {
return {
base: '/spdm/',
plugins: [
vue(),
vueJsx(),
],
plugins: [vue(), vueJsx()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
@@ -45,7 +42,8 @@ export default defineConfig(({ mode }) => {
changeOrigin: true,
rewrite: (path) => path.replace(/^\/local7101/, ''),
},
'/local7102': { // taskPool工况库模块
'/local7102': {
// taskPool工况库模块
// target: 'http://192.168.65.199:7102', // 李东洋
target: 'http://192.168.65.161:80/api/simulation/task', // 开发环境
// target: 'http://192.168.65.75:7100/simulation/task', // 朱欣茹
@@ -56,7 +54,8 @@ export default defineConfig(({ mode }) => {
changeOrigin: true,
rewrite: (path) => path.replace(/^\/local7102/, ''),
},
'/local7103': { // system系统模块
'/local7103': {
// system系统模块
// target: 'http://192.168.65.199:7103', // 李东洋
target: 'http://192.168.65.161:80/api/simulation/system', // 开发环境
// target: 'http://192.168.65.75:7100/simulation/system', // 朱欣茹
@@ -66,19 +65,22 @@ export default defineConfig(({ mode }) => {
return path.replace(/^\/local7103/, '');
},
},
'/local7104': { // data文件模块
'/local7104': {
// data文件模块
// target: 'http://192.168.65.199:7104', // 李东洋
target: 'http://192.168.65.161:80/api/simulation/data', // 开发环境
// target: 'http://192.168.65.161', // 开发环境
changeOrigin: true,
rewrite: (path) => path.replace(/^\/local7104/, ''),
},
'/local7105': { // pds模块
'/local7105': {
// pds模块
target: 'http://192.168.65.161:80/api/simulation/pbs', // 开发环境
changeOrigin: true,
rewrite: (path) => path.replace(/^\/local7105/, ''),
},
'/local7107': { // data文件模块
'/local7107': {
// capability模块
// target: 'http://192.168.65.199:7104', // 李东洋
target: 'http://192.168.65.161:80/api/simulation/capability', // 开发环境
// target: 'http://192.168.65.219:7107', // 戴琼瑶本地