da2ff56e by lihua

支持dicom文件

1 parent 4aed1325
......@@ -351,3 +351,25 @@ export const htmlToWord = (params) => request({
data: params,
responseType: 'blob'
})
export const scanFolder = (dirPath = '') => request({
url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/directory/scan?dirPath=${dirPath}`,
method: 'get'
})
/** 获取扫描文件结果 */
export const getDicomMeta = (taskGuid) => request({
url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/get-dicom-meta?taskGuid=${taskGuid}`,
method: 'get'
})
/** 获取扫描文件统计结果 */
export const getDicomStatistics = (taskGuid) => request({
url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/get-dicom-statistics?taskGuid=${taskGuid}`,
method: 'get'
})
export const retryDicom = (taskGuid) => request({
url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/dicom/retry?taskGuid=${taskGuid}`,
method: 'get'
})
\ No newline at end of file
......
......@@ -273,7 +273,7 @@ defineExpose({
<template v-else-if="prefixInfo">
<span class="prefix-icon" style="margin-right: 4px">
<template v-if="data.type < 2">
<template v-if="data.type < 2 || data.type == 'DIRECTORY'">
<el-icon v-if="node.expanded">
<svg-icon name="file-open" />
</el-icon>
......
......@@ -862,8 +862,10 @@ export const tagMethod = (row, type) => {
tag = '未执行';
} else if (row[type] == 'E') { //部分通过
tag = '失败';
}else if (row[type] == 'R') { //部分通过
} else if (row[type] == 'R') { //部分通过
tag = '执行中';
} else {
tag = '--'
}
} else if (type == 'sensitiveIdentifyConfirmStatus') {
if (row[type] == 'Y') {
......
......@@ -4,7 +4,6 @@
<script lang="ts" setup name="anonResultReportView">
import {
exportAnonReport,
getAnonAnalyzePageData,
getAnonAnalyzeResult,
getAnonTaskDetail,
......@@ -253,15 +252,16 @@ onBeforeMount(() => {
<template>
<div class="table_tool_wrap" v-loading="resultDataLoading" ref="containerRef" :element-loading-text="loadingText">
<el-button v-show="!isWordStyle" style="margin-bottom: 8px;" type="primary" @click="transfer"
<!-- 连接器不需要显示下载报告按钮 -->
<!-- <el-button v-show="!isWordStyle" style="margin-bottom: 8px;" type="primary" @click="transfer"
v-preReClick>生成Word评估报告</el-button>
<div v-show="isWordStyle" style="margin-bottom: 8px;">
<el-button @click="isWordStyle = false">返回</el-button>
<el-button type="primary" @click="downloadWord">下载评估报告</el-button>
</div>
</div> -->
<anonResultAnalysis ref="resultReportRef" :show-title="true" :analysis-result-info="analysisResultInfo"
:isWordStyle="isWordStyle" :style="isWordStyle ? {
height: 'calc(100% - 36px)',
height: '100%',
'overflow-y': 'auto',
'margin-right': '-16px',
'padding-right': '16px',
......
......@@ -51,47 +51,87 @@
<ContentWrap v-show="formRef?.formInline?.dataSource == 3" id="id-folder" title="提取文件" description=""
style="margin-top: 16px;">
<div class="folder-main">
<el-upload ref="uploadRef" class="upload-file" action="#" :file-list="folderList" :limit="1" directory
:http-request="(file) => hanlderUploadFolder(file)">
<template #trigger>
<el-button :icon="Upload" class="mr8">上传文件</el-button>
<el-button v-show="!clickSelectNode.path && !Object.keys(dicomStatisticsData)?.length" :icon="Upload"
class="mr8" @click=uploadFolder>上传文件</el-button>
<Dialog ref="dialogRef" :dialog-info="uploadFileDialogInfo" @btnClick="dialogBtnClick">
<template #extra-content>
<div class="folder-main-content" v-loading="uploadFileDialogInfo.contentLoading">
<Tree ref="treeInfoRef" :treeInfo="folderTreeInfo" @nodeClick="nodeClick" key="path"
@loadNode="loadFolderTreeNode" />
</div>
<div class="folder-foot">{{ '当前选中文件夹路径:' + (clickSelectNode.path || '--') }}</div>
</template>
</el-upload>
</Dialog>
<div v-show="clickSelectNode.path && dicomStatisticsData.state" class="folder-foot">{{ '当前提取文件夹路径:' +
(clickSelectNode.path || '--') }}
</div>
<!-- 正在扫描的状态 -->
<div class="folder-progress"
v-show="clickSelectNode.path && (dicomStatisticsData.state == 'S' || !Object.keys(dicomStatisticsData)?.length)">
<div class="folder-title">正在扫描</div>
<el-progress :percentage="dicomStatisticsData.progress || 0" :stroke-width="12" striped striped-flow
:show-text="false" :duration="8" />
<div v-show="Object.keys(dicomStatisticsData)?.length" style="display: flex;justify-content: space-between;"><span class="cnt">{{ '共扫描' +
changeNum(dicomStatisticsData.total, 0) + '个文件' }}</span><span v-show="dicomStatisticsData.remainingTime" class="desc">{{ '剩' +
transferTime(dicomStatisticsData.remainingTime)
}}</span></div>
</div>
<!-- 正在解析的状态 -->
<div class="folder-progress">
<div class="folder-progress"
v-show="clickSelectNode.path && (dicomStatisticsData.state == 'R')">
<div class="folder-title">正在解析</div>
<el-progress :percentage="30" :stroke-width="12" striped striped-flow :show-text="false" :duration="8" />
<div style="display: flex;"><span class="cnt">{{ '共' + changeNum(100, 0) + '个文件, 已解析30%' }}</span></div>
<el-progress :percentage="dicomStatisticsData.progress || 0" :stroke-width="12" striped striped-flow
:show-text="false" :duration="8" />
<div style="display: flex;justify-content: space-between;"><span class="cnt">{{ '共' +
changeNum(dicomStatisticsData.total, 0) +
'个文件, 已解析'
+ (dicomStatisticsData.progress || 0) + '%' }}</span><span v-show="dicomStatisticsData.remainingTime" class="desc">{{ '剩' +
transferTime(dicomStatisticsData.remainingTime)
}}</span></div>
</div>
<!-- 解析失败的状态 -->
<div class="folder-progress">
<div class="folder-progress" v-show="clickSelectNode.path && dicomStatisticsData.state == 'E'">
<div class="folder-title">
<el-icon class="title-icon fail">
<CircleCloseFilled />
</el-icon><span>解析失败</span>
</div>
<el-progress :percentage="30" :stroke-width="12" color="#F30000" :show-text="false" />
<div style="display: flex;"><span class="cnt">{{ '已成功解析' + changeNum(100, 0) + '个文件, 失败' + changeNum(30,
0) +
'个文件' }}</span></div>
<el-progress :percentage="dicomStatisticsData.progress || 0" :stroke-width="12" color="#F30000"
:show-text="false" />
<div style="display: flex;justify-content: space-between;"><span class="cnt">{{ '已成功解析' +
changeNum(dicomStatisticsData.successCount, 0) + '个文件, 失败' + changeNum(dicomStatisticsData.errorCount,
0) + '个文件' }}</span><span class="desc">{{ '共耗时'
+ calculateElapsedTime(dicomStatisticsData.parsingTime, dicomStatisticsData.parsingCompletedTime)
}}</span></div>
<div style="text-align: center;">
<el-button @click="reAnalyzing">重试</el-button>
<el-button @click=deleteFolder>删除文件,重新上传解析</el-button>
</div>
</div>
<!-- 解析成功状态 -->
<div class="folder-progress">
<div class="folder-progress"
v-show="clickSelectNode.path && dicomStatisticsData.state == 'Y' && dicomStatisticsData.errorCount === 0">
<div class="folder-title">
<el-icon class="title-icon success">
<svg-icon name="icon-success" />
</el-icon><span>解析成功</span>
</div>
<el-progress :percentage="30" :stroke-width="12" color="#F30000" :show-text="false" />
<div style="display: flex;"><span class="cnt">{{ '已成功解析' + changeNum(100, 0) + '个文件, 失败' + changeNum(30,
0) +
'个文件' }}</span></div>
<el-progress :percentage="dicomStatisticsData.progress || 100" :stroke-width="12" color="#4FA55D"
:show-text="false" />
<div style="display: flex;justify-content: space-between;"><span class="cnt">{{ '已成功解析' +
changeNum(dicomStatisticsData.successCount, 0)
+ '个文件,失败' + changeNum(dicomStatisticsData.errorCount, 0) + '个文件' }}</span><span class="desc">{{ '共耗时'
+ calculateElapsedTime(dicomStatisticsData.parsingTime, dicomStatisticsData.parsingCompletedTime)
}}</span>
</div>
</div>
</div>
<div v-show="clickSelectNode.path && folderFileTableInfo.data?.length" class="preview-title">预览文件仅展示5条数据
</div>
<Table v-show="clickSelectNode.path && folderFileTableInfo.data?.length" :tableInfo="folderFileTableInfo">
</Table>
<div v-show="clickSelectNode.path && dicomStatisticsData.state == 'Y'" class="folder-bottom"><el-button
@click=deleteFolder>删除文件,重新上传解析</el-button></div>
</ContentWrap>
</div>
<!-- 第二步 配置匿名化方案,单独抽取vue组件页面 -->
......@@ -116,20 +156,22 @@
<div v-show="analysisResultInfo.errorMsg" class="error-desc">{{ '【' + analysisResultInfo.errorMsg + '】' }}
</div>
</div>
<anonResultAnalysis v-show="isExecEnd && analysisResultInfo.status == 'Y'" ref="resultReportRef" v-loading="downloadLoading"
:analysis-result-info="analysisResultInfo" :is-word-style="isWordStyle" :element-loading-text="loadingText"
:analysis-result-loading="analysisResultLoading" :analysis-result-table-fields="analysisResultTableFields"
:old-anon-task-value-info="oldAnonTaskValueInfo" :container-width="containerWidth"
:origin-result-table-field-column="originResultTableFieldColumn" :page-info="pageInfo"
:result-data="resultData" :fullResultData="fullResultData" @page-change="pageChange"></anonResultAnalysis>
<template #header>
<anonResultAnalysis v-show="isExecEnd && analysisResultInfo.status == 'Y'" ref="resultReportRef"
v-loading="downloadLoading" :analysis-result-info="analysisResultInfo" :is-word-style="isWordStyle"
:element-loading-text="loadingText" :analysis-result-loading="analysisResultLoading"
:analysis-result-table-fields="analysisResultTableFields" :old-anon-task-value-info="oldAnonTaskValueInfo"
:container-width="containerWidth" :origin-result-table-field-column="originResultTableFieldColumn"
:page-info="pageInfo" :result-data="resultData" :fullResultData="fullResultData" @page-change="pageChange">
</anonResultAnalysis>
<!-- 连接器只能查看报告 -->
<!-- <template #header>
<el-button v-show="isExecEnd && analysisResultInfo.status == 'Y' && !isWordStyle" type="primary"
v-loading="!!downPromise" @click="transfer">生成Word评估报告</el-button>
<div v-show="isWordStyle">
<el-button @click="isWordStyle = false">返回</el-button>
<el-button type="primary" @click="downloadWord">下载评估报告</el-button>
</div>
</template>
</template> -->
</ContentWrap>
</div>
<!-- 匿名化结果展示 -->
......@@ -146,7 +188,9 @@
<div class="bottom_tool_wrap">
<template v-if="step == 0">
<el-button @click="cancelTask">取消</el-button>
<el-button type="primary" @click="changeStep(formRef?.formInline?.handleType == '02' ? 3 : 2)">下一步</el-button>
<el-button type="primary"
:disabled="formRef?.formInline?.handleType == '02' && formRef?.formInline?.dataSource == 3 && dicomStatisticsData?.progress != 100"
@click="changeStep(formRef?.formInline?.handleType == '02' ? 3 : 2)">下一步</el-button>
</template>
<template v-else-if="step == 1">
<el-button @click="changeStep(1)">上一步</el-button>
......@@ -184,8 +228,11 @@ import {
saveAnonTask,
updateAnonTask,
exportAnonExecData,
exportAnonReport,
htmlToWord,
scanFolder,
getDicomMeta,
getDicomStatistics,
retryDicom
} from '@/api/modules/dataAnonymization';
import {
parseAndDecodeUrl,
......@@ -228,6 +275,38 @@ const { required } = useValidator();
const fullscreenLoading = ref(false);
const containerRef = ref();
const qualifiedIdentifierFloderList = ref([{
enName: 'patient_birth_date',
chName: '患者出生日期',
}, {
enName: 'patient_birth_time',
chName: '患者出生时间'
}, {
enName: 'patient_sex',
chName: '患者性别'
}, {
enName: 'patient_age',
chName: '患者年龄'
}, {
enName: 'patient_weight',
chName: '患者体重'
}, {
enName: 'pregnancy_status',
chName: '怀孕状态'
}, {
enName: 'military_rank',
chName: '军衔'
}, {
enName: 'branch_of_service',
chName: '服役分支'
}, {
enName: 'ethnic_group',
chName: '种族'
}, {
enName: 'occupation',
chName: '职业'
}]);
const containerWidth = ref(containerRef.value?.offsetWidth || 0)
const step = ref(0);
......@@ -607,6 +686,9 @@ const setDataSelectFormItems = (info, isDetail = false) => {
}
} else if (item.field == 'qualifiedIdentifier') {
item.visible = info['handleType'] == '02';
if (info['dataSource'] == 3) {
item.options = qualifiedIdentifierFloderList.value;
}
}
});
stepsInfo.value = info.handleType == '02' ? reportStepsInfo.value : originStepsInfo.value;
......@@ -734,9 +816,12 @@ watch(
);
watch(() => sampleTableFields.value, (val) => {
let formInfo = formRef.value.formInline;
if (formInfo.dataSource == 3) {
return;
}
let item = dataSelectInfoItems.value.find(selectItem => selectItem.field == 'qualifiedIdentifier');
item && (item.options = val);
let formInfo = formRef.value.formInline;
if (formInfo.handleType == '02' && !(taskGuid.value && (formInfo.file?.[0] && formInfo.file?.[0]?.url == detailInfo.value.filePath?.url || (formInfo.tableName && formInfo.tableName == detailInfo.value.tableName)))) {//需要同步清除准标识符的字段选择
setDataSelectFormItems(Object.assign({}, formInfo, { file: !formInfo['file'] ? [] : formInfo['file'], qualifiedIdentifier: [] }))
}
......@@ -902,16 +987,343 @@ const uploadFileChange = (file) => {
}
/*** ----------------------- 解析扫描文件 ------------------------------ */
const folderList: any = ref([]);
const hanlderUploadFolder = (file) => {
debugger
return Promise.resolve();
/** 上传选择文件夹对话框 */
const uploadFileDialogInfo = ref({
visible: false,
size: 700,
direction: "column",
header: {
title: "选择文件夹",
},
type: '',
contents: [],
footer: {
btns: [
{ type: "default", label: "取消", value: "cancel" },
{ type: "primary", label: "确定", value: "submit", loading: false },
],
},
contentLoading: false,
});
const folderRefreshTimer = ref();
const processFolderRefresh = async () => {
await getDicomStatisticsData(taskGuid.value);
if (!dicomStatisticsData.value.state || dicomStatisticsData.value.state == 'S' || dicomStatisticsData.value.state == 'R') {
if (folderRefreshTimer.value) {
return;
}
folderRefreshTimer.value = setInterval(async () => {
processFolderRefresh();
}, 10000);
} else if (dicomStatisticsData.value.state == 'Y') {
getDicomMetaData(taskGuid.value);
analysisResultInfo.value = {};
if (folderRefreshTimer.value) {
clearInterval(folderRefreshTimer.value);
folderRefreshTimer.value = null;
}
// processStepThreeResultView();
} else if (dicomStatisticsData.value.state == 'E') {
if (folderRefreshTimer.value) {
clearInterval(folderRefreshTimer.value);
folderRefreshTimer.value = null;
}
}
}
// TODO,需要将selectNode与oldSelectNode即对话框展开的做区分处理。
const dialogBtnClick = (btn) => {
if (btn.value == 'submit') {
clickSelectNode.value = dialogOpenSelectNode.value;
if (!clickSelectNode.value.path) {
proxy.$ElMessage.error('请先选择文件夹');
return;
}
let saveParams = { ...formRef.value.formInline };
if (saveParams.coverageArea?.length) {
saveParams.coverageArea = [saveParams.coverageArea];
} else {
saveParams.coverageArea = [];
}
saveParams.filePath = {
url: clickSelectNode.value.path
};
saveParams.samplingRate = null;
if (taskGuid.value) {
saveParams.guid = taskGuid.value;
}
dicomStatisticsData.value = {};
folderFileTableInfo.value.data = [];
if (!taskGuid.value) { //保存
uploadFileDialogInfo.value.footer.btns[1].loading = true;
saveAnonTask(saveParams).then(async (res: any) => {
uploadFileDialogInfo.value.footer.btns[1].loading = false;
if (res.code == proxy.$passCode) {
taskGuid.value = res.data?.taskGuid;
taskExecGuid.value = res.data?.lastExecGuid;
uploadFileDialogInfo.value.visible = false;
anonymizationStore.setIsAnonPageRefresh(true);
isExecEnd.value = false;
oldAnonTaskValueInfo.value = saveParams;
oldAnonTaskValueInfo.value.guid = taskGuid.value;
if (folderRefreshTimer.value) {
clearInterval(folderRefreshTimer.value);
folderRefreshTimer.value = null;
}
await 100;
processFolderRefresh();
} else {
ElMessage.error(res.msg);
}
});
} else { //更新
uploadFileDialogInfo.value.footer.btns[1].loading = true;
updateAnonTask(saveParams).then(async (res: any) => {
uploadFileDialogInfo.value.footer.btns[1].loading = false;
if (res.code == proxy.$passCode) {
taskExecGuid.value = res.data;
uploadFileDialogInfo.value.visible = false;
anonymizationStore.setIsAnonPageRefresh(true);
isExecEnd.value = false;
oldAnonTaskValueInfo.value = saveParams;
if (folderRefreshTimer.value) {
clearInterval(folderRefreshTimer.value);
folderRefreshTimer.value = null;
}
await 100;
processFolderRefresh();
} else {
ElMessage.error(res.msg);
}
})
}
} else if (btn.value == 'cancel') {
// clickSelectNode.value = {};
dialogOpenSelectNode.value = {};
uploadFileDialogInfo.value.visible = false;
}
};
const folderTreeInfo = ref({
id: "data-pickup-tree",
filter: true,
queryValue: "",
queryPlaceholder: "输入关键字搜索",
props: {
label: "name",
value: "path",
isLeaf: "isLeaf",
},
prefix: {
type: 'prefixIcon'
},
nodeKey: 'path',
lazy: true,
expandedKey: [],
currentNodeKey: '',
expandOnNodeClick: true,
data: <any>[],
//customFilter: true,
loading: false
});
const clickSelectNode: any = ref({});
const nodeClick = (data, node) => {
dialogOpenSelectNode.value = data;
}
const loadFolderTreeNode = (node, resolve) => {
if (node.level === 0 || node.isLeaf) {
return resolve([]);
}
scanFolder(node.data.path).then((res: any) => {
if (res?.code == proxy.$passCode) {
resolve(res.data || []);
} else {
ElMessage.error(res.msg);
}
})
}
const dialogOpenSelectNode: any = ref({})
const uploadFolder = () => {
// 先检查信息是否填写完整。
formRef.value?.ruleFormRef?.validate((valid) => {
if (valid) {
let formInline = formRef.value?.formInline;
if (formInline.handleType == '01' && formInline.dataSource == 3) {
proxy.$ElMessage.warning('暂不支持处理类型为数据匿名化处理的文件夹数据,请修改');
return;
}
clickSelectNode.value = {};
dialogOpenSelectNode.value = {};
uploadFileDialogInfo.value.visible = true;
folderTreeInfo.value.loading = true;
scanFolder().then((res: any) => {
folderTreeInfo.value.loading = false;
if (res?.code == proxy.$passCode) {
folderTreeInfo.value.data = res.data || [];
} else {
ElMessage.error(res.msg);
}
})
} else {
proxy.$ElMessage.warning('请先填写完整数据选择基本信息');
}
})
}
const deleteFolder = () => {
proxy.$openMessageBox("确定要删除该文件夹扫描解析结果,重新上传吗?", () => {
clickSelectNode.value = {};
folderFileTableInfo.value.data = [];
dicomStatisticsData.value = {};
}, () => {
proxy.$ElMessage.info("已取消删除");
})
}
/** 重试 */
const reAnalyzing = () => {
fullscreenLoading.value = true;
retryDicom(taskGuid.value).then((res: any) => {
fullscreenLoading.value = false;
if (res?.code == proxy.$passCode) {
if (folderRefreshTimer.value) {
clearInterval(folderRefreshTimer.value);
folderRefreshTimer.value = null;
}
processFolderRefresh();
} else {
res?.msg && ElMessage.error(res.msg);
}
})
}
/** 上传成功之后的文件信息 */
const folderFileTableInfo = ref({
id: "exec-contract-table",
height: '212px',
fields: <any>[],
data: [],
showPage: false,
actionInfo: {
show: false
},
loading: false
});
const dicomMetaData: any = ref({});
const metaDataWidthsJson = ref({
'患者姓名': 140,
'患者ID': 140,
'患者出生日期': 120,
'患者出生时间': 130,
'患者性别': 100,
"怀孕状态": 110,
"种族": 100,
"患者体重": 90,
'患者年龄': 110,
});
/** 获取预览的5条数据 */
const getDicomMetaData = (taskGuid) => {
folderFileTableInfo.value.loading = true;
getDicomMeta(taskGuid).then((res: any) => {
folderFileTableInfo.value.loading = false;
if (res?.code == proxy.$passCode) {
dicomMetaData.value = res.data || {};
folderFileTableInfo.value.fields = [{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" }].concat(dicomMetaData.value?.column?.map(f => {
return {
label: f, field: f, width: metaDataWidthsJson.value[f] || 120
}
}));
let column = dicomMetaData.value?.column || [];
folderFileTableInfo.value.data = dicomMetaData.value.datas?.map(d => {
let json = {};
column.forEach((c, index) => {
json[c] = d[index];
})
return json;
})
} else {
res?.msg && proxy.$ElMessage.error(res.msg);
}
})
}
const dicomStatisticsData: any = ref({});
/** 获取解析文件结果数据 */
const getDicomStatisticsData = (taskGuid) => {
return getDicomStatistics(taskGuid).then((res: any) => {
if (res?.code == proxy.$passCode) {
dicomStatisticsData.value = res.data || {};
} else {
res?.msg && proxy.$ElMessage.error(res.msg);
}
})
}
/** 将时间转换为时分秒 */
const transferTime = (time) => {
if (time == null) {
return '--';
}
// 4. 将毫秒转换为小时、分钟和秒
const totalSeconds = Math.floor(time / 1000);
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
// 5. 格式化输出
const parts: any[] = [];
if (hours > 0) {
parts.push(`${hours}小时`);
}
if (minutes > 0 || hours > 0) { // 如果有小时,即使分钟为0也显示0分钟
parts.push(`${minutes}分钟`);
}
parts.push(`${seconds}秒`);
return parts.join('');
}
/**
* 计算两个时间之间的耗时
* @param {string} parsingTime - 开始时间(ISO 8601格式)
* @param {string} parsingCompletedTime - 结束时间(ISO 8601格式)
* @returns {string} - 格式化的耗时字符串,如 "2小时30分钟"
*/
const calculateElapsedTime = (parsingTime, parsingCompletedTime) => {
// 1. 将时间字符串转换为Date对象
const startTime = new Date(parsingTime);
const endTime = new Date(parsingCompletedTime);
// 2. 计算时间差(毫秒)
const timeDiff = endTime - startTime;
// 3. 检查时间是否有效
if (isNaN(timeDiff)) {
// return "时间格式错误";
return '--';
}
if (timeDiff < 0) {
//return "结束时间早于开始时间";
return '--';
}
return transferTime(timeDiff);
}
/** 第二步的配置组件引用。 */
......@@ -954,8 +1366,14 @@ const changeStep = async (val) => {
saveParams.dataSourceGuid = null;
saveParams.tableName = null;
} else {
if (saveParams.dataSource == 3 && clickSelectNode.value.path) {
saveParams.filePath = {
url: clickSelectNode.value.path
};
} else {
saveParams.filePath = null;
}
}
let simpleFormInline = dataSimpleFormRef.value.formInline;
if (simpleFormInline.enableSamplingRate == 'Y') {
saveParams.samplingRate = simpleFormInline.samplingRate && parseInt(simpleFormInline.samplingRate);
......@@ -984,6 +1402,8 @@ const changeStep = async (val) => {
taskGuid.value = res.data?.taskGuid;
isExecEnd.value = false;
taskExecGuid.value = res.data?.lastExecGuid;
oldAnonTaskValueInfo.value = saveParams;
oldAnonTaskValueInfo.value.guid = taskGuid.value;
step.value = val - 1;
stepsInfo.value.step = val - 1;
analysisResultInfo.value = {};
......@@ -992,7 +1412,6 @@ const changeStep = async (val) => {
refreshTimer.value = null;
}
processStepThreeResultView();
oldAnonTaskValueInfo.value = saveParams;
anonymizationStore.setIsAnonPageRefresh(true);
} else {
ElMessage.error(res.msg);
......@@ -1045,17 +1464,26 @@ const changeStep = async (val) => {
} else {
formRef.value?.ruleFormRef?.validate((valid, errorItem) => {
if (valid) {
if (formRef.value?.formInline?.dataSource == 2 && !sampleTableFields.value?.length) {
let dataSource = formRef.value?.formInline?.dataSource;
if (dataSource == 2 && !sampleTableFields.value?.length) {
proxy.$ElMessage.error('上传文件的字段不能为空');
return;
}
if (dataSource != 3) {
dataSimpleFormRef.value?.ruleFormRef?.validate((valid) => {
if (valid) {
Object.assign(saveParams, { riskThreshold: '0.05' });
// Object.assign(saveParams, { riskThreshold: '0.05' });
exec(saveParams);
}
});
} else {
if (!clickSelectNode.value.path) {
proxy.$ElMessage.error('请先上传文件');
return;
}
exec(saveParams);
}
} else {
var obj = Object.keys(errorItem);
formRef.value.ruleFormRef?.scrollToField(obj[0])
}
......@@ -1101,15 +1529,15 @@ onBeforeMount(() => {
if (res?.code == proxy.$passCode) {
detailInfo.value = res.data || {};
taskExecGuid.value = detailInfo.value.lastExecGuid;
if (detailInfo.value.handleType == '01') {
oldAnonTaskValueInfo.value = {
guid: detailInfo.value.guid,
taskName: detailInfo.value.taskName,
dataSource: detailInfo.value.dataSource,
filePath: detailInfo.value.filePath && cloneDeep(detailInfo.value.filePath),
dataSourceGuid: detailInfo.value.dataSourceGuid,
tableName: detailInfo.value.tableName,
handleType: detailInfo.value.handleType,
coverageArea: detailInfo.value.coverageArea || [],
qualifiedIdentifier: detailInfo.value.qualifiedIdentifier,
samplingRate: detailInfo.value.samplingRate,
// patientPopulationRate: detailInfo.value.patientPopulationRate && typeof detailInfo.value.patientPopulationRate == 'number' ? detailInfo.value.patientPopulationRate?.toFixed(9) : detailInfo.value.patientPopulationRate,
dataSharingTypeCode: detailInfo.value.dataSharingTypeCode,
anonTaskRules: cloneDeep(detailInfo.value.anonTaskRules),
anonPrivacyMode: {
......@@ -1121,6 +1549,25 @@ onBeforeMount(() => {
tcThreshold: detailInfo.value.anonPrivacyMode?.tcThreshold,
}
}
} else {
oldAnonTaskValueInfo.value = {
guid: detailInfo.value.guid,
taskName: detailInfo.value.taskName,
dataSource: detailInfo.value.dataSource,
handleType: detailInfo.value.handleType,
coverageArea: detailInfo.value.coverageArea || [],
qualifiedIdentifier: detailInfo.value.qualifiedIdentifier,
samplingRate: detailInfo.value.samplingRate,
dataSharingTypeCode: detailInfo.value.dataSharingTypeCode,
}
}
if (detailInfo.value.dataSource == 1) {
oldAnonTaskValueInfo.value.dataSourceGuid = detailInfo.value.dataSourceGuid;
oldAnonTaskValueInfo.value.tableName = detailInfo.value.tableName;
} else {
oldAnonTaskValueInfo.value.filePath = detailInfo.value.filePath && cloneDeep(detailInfo.value.filePath);
}
detailInfo.value.dataSource == 3 && (clickSelectNode.value.path = oldAnonTaskValueInfo.value.filePath?.url);
setDataSelectFormItems(Object.assign(detailInfo.value, { file: detailInfo.value.filePath ? [detailInfo.value.filePath] : [] }), true);
if (detailInfo.value.samplingRate != null) {
dataSimpleFormItems.value[0].default = 'Y';
......@@ -1135,7 +1582,7 @@ onBeforeMount(() => {
dataSelectInfoItems.value[6].visible = dataSource == 1;
dataSelectInfoItems.value[8].visible = dataSource == 2;
try {
//文件解析
// 文件解析
if (dataSource == 2) {
let url = detailInfo.value.filePath?.url;
sampleTableDataLoading.value = true;
......@@ -1161,7 +1608,7 @@ onBeforeMount(() => {
} else {
proxy.$ElMessage.error(res.msg);
}
} else {
} else if (dataSource == 1) {
const res: any = await getDatabase({ connectStatus: 1 });
if (res?.code == proxy.$passCode) {
dataSourceList.value = res.data || [];
......@@ -1208,6 +1655,9 @@ onBeforeMount(() => {
ElMessage.error(res.msg);
}
});
} else if (dataSource == 3) {
getDicomMetaData(taskGuid.value);
await getDicomStatisticsData(taskGuid.value);
}
fullscreenLoading.value = false;
} catch (error) {
......@@ -1882,7 +2332,7 @@ onUnmounted(() => {
}
.folder-progress {
width: 360px;
width: 420px;
.cnt {
font-size: 14px;
......@@ -1891,9 +2341,50 @@ onUnmounted(() => {
margin-top: 8px;
}
.desc {
font-size: 14px;
color: #999999;
line-height: 21px;
margin-top: 8px;
}
.el-button {
margin-top: 12px;
}
}
}
.folder-main-content {
height: 450px;
padding: 8px 16px;
:deep(.tree_panel) {
height: 100%;
.el-tree {
overflow-y: auto;
}
}
}
.folder-foot {
padding: 0px 16px 8px;
line-height: 21px;
}
.preview-title {
margin-bottom: 8px;
font-size: 14px;
color: #212121;
line-height: 21px;
font-weight: 600;
}
.folder-bottom {
width: 100%;
padding: 8px 0px 0px;
display: flex;
justify-content: center;
align-items: center;
}
</style>
\ No newline at end of file
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!