Commit 6eab010a by zhaochengxiang

移植迈瑞资产多模版

parent 2cd87653
......@@ -12,10 +12,14 @@ module.exports = {
'@ant-prefix': 'yy',
// '@border-color-split': 'hsv(0, 0, 85%)',
'@border-radius-base': '4px',
'@primary-color': '#196AD2',
'@primary-color': '#ffbc00',
'@success-color': '#8FC31F',
'@warning-color': '#F7AB00',
'@error-color': '#E94848',
'@error-color': '#db0007',
'@menu-dark-bg': '#00477F',
'@menu-dark-submenu-bg': '#013D6C',
'@menu-dark-inline-submenu-bg': '#013D6C',
'@layout-header-background': '#00477F',
},
javascriptEnabled: true,
},
......
......@@ -75,6 +75,6 @@
"last 1 safari version"
]
},
"proxy": "http://139.198.127.28:17277",
"proxy": "http://139.198.126.96:8089",
"homepage": "http://myhost/data-govern"
}
......@@ -4,7 +4,7 @@ import {
Route, Switch
} from 'react-router-dom';
import { $hostParams, ContextPath } from './util';
import { $hostParams, ContextPath, generateUUID } from './util';
import Signin from './view/Signin';
import Home from './view/Home';
import Manage from './view/Manage';
......@@ -32,6 +32,8 @@ import { AssetMountReference } from './util/constant';
export const AppContext = React.createContext();
export const appId = generateUUID();
export class App extends React.Component {
constructor() {
super();
......
import * as service from '../service/dataassetmanager';
import * as metadataService from '../service/metadata';
import { call } from 'redux-saga/effects';
export function* importElement(payload) {
......@@ -13,8 +15,12 @@ export function* listElements() {
return yield call(service.listElements);
}
export function* listElementsByDirId(payload) {
return yield call(service.listElementsByDirId, payload);
export function* listElementsAndFillValue(payload) {
return yield call(service.listElementsAndFillValue, payload)
}
export function* listSupportSourceModels() {
return yield call(service.listSupportSourceModels)
}
export function* listUserElements() {
......@@ -25,20 +31,16 @@ export function* listCustomElements() {
return yield call(service.listCustomElements);
}
export function* listFilterElementIds() {
return yield call(service.listFilterElementIds);
export function* listFilterElementIds(payload) {
return yield call(service.listFilterElementIds, payload);
}
export function* listFilterElements() {
return yield call(service.listFilterElements);
}
export function* listFilterElementsGroupByType() {
return yield call(service.listFilterElementsGroupByType);
}
export function* listFilterElementsGroupByTypeWithDirId(payload) {
return yield call(service.listFilterElementsGroupByTypeWithDirId, payload);
export function* listFilterElementsGroupByType(payload) {
return yield call(service.listFilterElementsGroupByType, payload);
}
export function* setupFilterElementIds(payload) {
......@@ -53,16 +55,16 @@ export function* setupFilterElementIdsConfig(payload) {
return yield call(service.setupFilterElementIdsConfig, payload);
}
export function* listComputableElements() {
return yield call(service.listComputableElements);
export function* addOrUpdateDataAsset(payload) {
return yield call(service.addOrUpdateDataAsset, payload);
}
export function* computeBySelectElements(payload) {
return yield call(service.computeBySelectElements, payload);
export function* checkCodeIsExist(payload) {
return yield call(service.checkCodeIsExist, payload);
}
export function* addOrUpdateDataAsset(payload) {
return yield call(service.addOrUpdateDataAsset, payload);
export function* checkDataAssetEditable(payload) {
return yield call(service.checkDataAssetEditable, payload);
}
export function* addDataAssetByDirIds(payload) {
......@@ -80,21 +82,37 @@ export function* getDataAssetDetail(payload) {
export function* listDataAssetsByPage(payload) {
return yield call(service.listDataAssetsByPage, payload);
}
export function* listDataAssetsByPersonalCustomType(payload) {
return yield call(service.listDataAssetsByPersonalCustomType, payload);
}
export function* listRecycleBinDataAssetsByPage(payload) {
return yield call(service.listRecycleBinDataAssetsByPage, payload);
}
export function* addOrUpdateDirectory(payload) {
return yield call(service.addOrUpdateDirectory, payload);
}
export function* checkDirectoryDeleteAble(payload) {
return yield call(service.checkDirectoryDeleteAble, payload)
}
export function* deleteDirectory(payload) {
return yield call(service.deleteDirectory, payload);
}
export function* deletePersonalCustomDirectory(payload) {
return yield call(service.deletePersonalCustomDirectory, payload);
}
export function* existDataAsset(payload) {
return yield call(service.existDataAsset, payload);
}
export function* queryAllDirectoryAsTree() {
return yield call(service.queryAllDirectoryAsTree);
}
export function* queryDirectoryTreeByMetadataId(payload) {
return yield call(service.queryDirectoryTreeByMetadataId, payload);
}
export function* queryResourceDirectoryAsTree() {
return yield call(service.queryResourceDirectoryAsTree);
}
......@@ -113,10 +131,18 @@ export function* previewTreeByCustomElements(payload) {
return yield call(service.previewTreeByCustomElements, payload);
}
export function* previewTreeByCustomElementsAndResourceType(payload) {
return yield call(service.previewTreeByCustomElementsAndResourceType, payload);
}
export function* saveTreeByCustomElements(payload) {
return yield call(service.saveTreeByCustomElements, payload);
}
export function* saveTreeByCustomElementsAndResourceType(payload) {
return yield call(service.saveTreeByCustomElementsAndResourceType, payload);
}
export function* assetImport(payload) {
return yield call(service.assetImport, payload);
}
......@@ -125,14 +151,30 @@ export function* getDirectoryById(payload) {
return yield call(service.getDirectoryById, payload);
}
export function* getPersonalCustomDirectoryById(payload) {
return yield call(service.getPersonalCustomDirectoryById, payload);
}
export function* upDownDirectory(payload) {
return yield call(service.upDownDirectory, payload);
}
export function* upDownPersonalCustomDirectory(payload) {
return yield call(service.upDownPersonalCustomDirectory, payload);
}
export function* listDirectoryByName(payload) {
return yield call(service.listDirectoryByName, payload);
}
export function* getDirectoryChild(payload) {
return yield call(service.getDirectoryChild, payload);
}
export function* getPersonalCustomDirecotryChild(payload) {
return yield call(service.getPersonalCustomDirecotryChild, payload);
}
export function* loadDataAssets(payload) {
return yield call(service.loadDataAssets, payload);
}
......@@ -141,6 +183,10 @@ export function* unloadDataAssets(payload) {
return yield call(service.unloadDataAssets, payload);
}
export function* unloadDataAssetsFromAllDirs(payload) {
return yield call(service.unloadDataAssetsFromAllDirs, payload);
}
export function* getDataAssetLocation(payload) {
return yield call(service.getDataAssetLocation, payload);
}
......@@ -153,6 +199,10 @@ export function* importLogs(payload) {
return yield call(service.importLogs, payload);
}
export function* recoveryFromRecycleBin(payload) {
return yield call(service.recoveryFromRecycleBin, payload);
}
export function* getMetadataModelTree() {
return yield call(service.getMetadataModelTree);
}
......@@ -193,14 +243,14 @@ export function* fillElementValueBeforeCreate(payload) {
return yield call(service.fillElementValueBeforeCreate, payload);
}
export function* listSupportSourceModels() {
return yield call(service.listSupportSourceModels)
}
export function* countResourceState(payload) {
return yield call(service.countResourceState, payload);
}
export function* getAssetPaths(payload) {
return yield call(service.getAssetPaths, payload);
}
export function* getResourceRelations(payload) {
return yield call(service.getResourceRelations, payload);
}
......@@ -209,70 +259,74 @@ export function* updateResourceState(payload) {
return yield call(service.updateResourceState, payload);
}
export function* saveWorkbook(payload) {
return yield call(service.saveWorkbook, payload);
export function* subs(payload) {
return yield call(service.subs, payload);
}
export function* startFlow(payload) {
return yield call(service.startFlow, payload);
}
export function* getWorkbookUrl(payload) {
return yield call(service.getWorkbookUrl, payload);
export function* getSystems(payload) {
return yield call(service.getSystems, payload);
}
export function* listWorkbooks(payload) {
return yield call(service.listWorkbooks, payload);
export function* getMetadataAttributes(payload) {
return yield call(metadataService.getAttributes, payload);
}
export function* deleteWorkbooks(payload) {
return yield call(service.deleteWorkbooks, payload);
export function* exportMetadataAttributes(payload) {
return yield call(metadataService.exportAttributes, payload);
}
export function* saveSmartBIWorkbook(payload) {
return yield call(service.saveSmartBIWorkbook, payload);
export function* importMetadataAttributes(payload) {
return yield call(metadataService.importAttributes, payload);
}
export function* getSmartBIWorkbookUrl(payload) {
return yield call(service.getSmartBIWorkbookUrl, payload);
export function* getMetadataImportAssetLog(payload) {
return yield call(metadataService.listImportAssetLog, payload);
}
export function* listSmartBIWorkbooks(payload) {
return yield call(service.listSmartBIWorkbooks, payload);
export function* getMetadataImportAssetLogDetail(payload) {
return yield call(metadataService.getImportAssetLogDetail, payload);
}
export function* deleteSmartBIWorkbooks(payload) {
return yield call(service.deleteSmartBIWorkbooks, payload);
export function* getStandardTree(payload) {
return yield call(service.getStandardTree, payload);
}
export function* listTasks(payload) {
return yield call(service.listTasks, payload);
export function* getStandardList(payload) {
return yield call(service.getStandardList, payload);
}
export function* saveTask(payload) {
return yield call(service.saveTask, payload);
export function* standardBatchMetadata(payload) {
return yield call(service.standardBatchMetadata, payload);
}
export function* auditTask(payload) {
return yield call(service.auditTask, payload);
export function* getMetadataStandardList(payload) {
return yield call(service.getMetadataStandardList, payload);
}
export function* uploadDataAssetExcel(payload) {
return yield call(service.uploadDataAssetExcel, payload);
export function* deleteStandardBatchMetadata(payload) {
return yield call(service.deleteStandardBatchMetadata, payload);
}
export function* subs(payload) {
return yield call(service.subs, payload);
export function* exportIndicator(payload) {
return yield call(service.exportIndicator, payload);
}
export function* getScore(payload) {
return yield call(service.getScore, payload);
export function* importIndicator(payload) {
return yield call(service.importIndicator, payload);
}
export function* getResourceTypes(payload) {
return yield call(service.getResourceTypes, payload);
export function* importIndicatorLog(payload) {
return yield call(service.importIndicatorLog, payload);
}
export function* getDirectoryChild(payload) {
return yield call(service.getDirectoryChild, payload);
export function* getPermission(payload) {
return yield call(service.getPermission, payload);
}
export function* queryCustomTypeRootDirectory() {
return yield call(service.queryCustomTypeRootDirectory);
export function* getTemplates() {
return yield call(service.getTemplates)
}
\ No newline at end of file
import { PostJSON, GetJSON, PostFile, Post, Get } from "../util/axios"
import { PostJSON, GetJSON, PostFile, Post, Get, callFetchRaw } from "../util/axios"
export function importElement(payload) {
return PostFile("/dataassetmanager/elementApi/import", payload);
......@@ -12,8 +12,8 @@ export function listElements() {
return PostJSON("/dataassetmanager/elementApi/listElements");
}
export function listElementsByDirId(payload) {
return GetJSON("/dataassetmanager/elementApi/listElementsByDirId", payload);
export function listElementsAndFillValue(payload) {
return PostJSON("/dataassetmanager/elementApi/listElementAndFillValueByDirId", payload)
}
export function listUserElements() {
......@@ -24,34 +24,22 @@ export function listCustomElements() {
return GetJSON("/dataassetmanager/elementApi/listCustomElements");
}
export function listFilterElementIds() {
return GetJSON("/dataassetmanager/elementApi/listFilterElementIds");
export function listFilterElementIds(payload) {
return GetJSON("/dataassetmanager/elementApi/listFilterElementIds", payload);
}
export function listFilterElements() {
return GetJSON("/dataassetmanager/elementApi/listFilterElements");
}
export function listFilterElementsGroupByType() {
return GetJSON("/dataassetmanager/elementApi/listFilterElementsGroupByType");
}
export function listFilterElementsGroupByTypeWithDirId(payload) {
return GetJSON("/dataassetmanager/elementApi/listFilterElementsGroupByTypeWithDirId", payload);
export function listFilterElementsGroupByType(payload) {
return GetJSON("/dataassetmanager/elementApi/listFilterElementsGroupByType", payload);
}
export function setupFilterElementIds(payload) {
return PostJSON("/dataassetmanager/elementApi/setupFilterElementIds", payload);
}
export function listComputableElements() {
return GetJSON("/dataassetmanager/elementApi/listComputableElements");
}
export function computeBySelectElements(payload) {
return PostJSON("/dataassetmanager/elementApi/computeBySelectElements", payload);
}
export function listFilterElementIdsConfig() {
return PostJSON("/dataassetmanager/configApi/listFilterElementIds");
}
......@@ -64,6 +52,14 @@ export function addOrUpdateDataAsset(payload) {
return PostJSON("/dataassetmanager/dataAssetApi/addOrUpdateDataAsset", payload);
}
export function checkCodeIsExist(payload) {
return Post("/dataassetmanager/dataAssetApi/checkDataAssetCodeIsExist", payload);
}
export function checkDataAssetEditable(payload) {
return Post("/dataassetmanager/dataAssetApi/checkDataAssetEditable", payload);
}
export function addDataAssetByDirIds(payload) {
return PostJSON("/dataassetmanager/dataAssetApi/addDataAssetByDirIds", payload);
}
......@@ -80,6 +76,10 @@ export function listDataAssetsByPage(payload) {
return GetJSON("/dataassetmanager/dataAssetApi/listDataAssetsByPage", payload);
}
export function listDataAssetsByPersonalCustomType(payload) {
return GetJSON("/dataassetmanager/dataAssetApi/listDataAssetsByPersonalCustomType", payload);
}
export function listRecycleBinDataAssetsByPage(payload) {
return GetJSON("/dataassetmanager/dataAssetApi/listRecycleBinDataAssetsByPage", payload);
}
......@@ -92,6 +92,10 @@ export function unloadDataAssets(payload) {
return PostJSON("/dataassetmanager/dataAssetApi/unloadDataAssetsByDataAssetIdAndDirId", payload);
}
export function unloadDataAssetsFromAllDirs(payload) {
return PostJSON("/dataassetmanager/dataAssetApi/unloadDataAssetsFromAllDirs", payload);
}
export function getDataAssetLocation(payload) {
return GetJSON("/dataassetmanager/dataAssetApi/locateDataAssetById", payload);
}
......@@ -104,14 +108,30 @@ export function importLogs(payload) {
return GetJSON("/dataassetmanager/dataAssetApi/listDataAssetImportLogsByPage", payload);
}
export function recoveryFromRecycleBin(payload) {
return PostJSON("/dataassetmanager/dataAssetApi/recoveryFromRecycleBin", payload);
}
export function getAssetPaths(payload) {
return GetJSON("/dataassetmanager/dataAssetApi/getMultiPath", payload);
}
export function addOrUpdateDirectory(payload) {
return PostJSON("/dataassetmanager/directoryApi/addOrUpdateDirectory", payload);
}
export function checkDirectoryDeleteAble(payload) {
return Post("/dataassetmanager/directoryApi/checkDirDeleteAble", payload);
}
export function deleteDirectory(payload) {
return PostJSON("/dataassetmanager/directoryApi/deleteDirectory", payload);
}
export function deletePersonalCustomDirectory(payload) {
return PostJSON("/dataassetmanager/directoryApi/deletePersonalCustomDirectory", payload);
}
export function existDataAsset(payload) {
return GetJSON("/dataassetmanager/directoryApi/existDataAsset", payload);
}
......@@ -120,6 +140,10 @@ export function queryAllDirectoryAsTree() {
return GetJSON("/dataassetmanager/directoryApi/queryAllDirectoryAsTree");
}
export function queryDirectoryTreeByMetadataId(payload) {
return GetJSON("/dataassetmanager/directoryApi/queryDirectoryTreeByMetadataIdPath", payload)
}
export function queryResourceDirectoryAsTree() {
return PostJSON("/dataassetmanager/directoryApi/querySourceTypeAsTree");
}
......@@ -140,10 +164,18 @@ export function previewTreeByCustomElements(payload) {
return PostJSON("/dataassetmanager/directoryApi/previewAsTreeByCustomElements", payload);
}
export function previewTreeByCustomElementsAndResourceType(payload) {
return PostJSON("/dataassetmanager/directoryApi/previewAsTreeByCustomElementsAndResourceType", payload);
}
export function saveTreeByCustomElements(payload) {
return PostJSON("/dataassetmanager/directoryApi/saveCustomElementTree", payload);
}
export function saveTreeByCustomElementsAndResourceType(payload) {
return PostJSON("/dataassetmanager/directoryApi/savePersonalCustomElementTreeByResourceType", payload);
}
export function assetImport(payload) {
return PostFile("/dataassetmanager/dataAssetApi/import", payload);
}
......@@ -152,14 +184,30 @@ export function getDirectoryById(payload) {
return GetJSON("/dataassetmanager/directoryApi/getDirectoryById", payload);
}
export function getPersonalCustomDirectoryById(payload) {
return GetJSON("/dataassetmanager/directoryApi/getPersonalCustomDirectoryById", payload);
}
export function upDownDirectory(payload) {
return PostJSON("/dataassetmanager/directoryApi/upDownDirectory", payload);
}
export function upDownPersonalCustomDirectory(payload) {
return PostJSON("/dataassetmanager/directoryApi/upDownPersonalCustomDirectory", payload);
}
export function listDirectoryByName(payload) {
return GetJSON("/dataassetmanager/directoryApi/listDirectoryByName", payload);
}
export function getDirectoryChild(payload) {
return GetJSON("/dataassetmanager/directoryApi/getChildByParentId", payload);
}
export function getPersonalCustomDirecotryChild(payload) {
return GetJSON("/dataassetmanager/directoryApi/getPersonalCustomChildByParentId", payload);
}
export function getMetadataModelTree() {
return GetJSON("/metadatarepo/rest/model/tree");
}
......@@ -216,70 +264,54 @@ export function updateResourceState(payload) {
return PostJSON("/dataassetmanager/resourceApi/updateResourceState", payload);
}
export function saveWorkbook(payload) {
return Post("/dataassetmanager/tableauApi/saveWorkbook", payload);
}
export function getWorkbookUrl(payload) {
return Get("/dataassetmanager/tableauApi/getWorkbookUrl", payload);
}
export function listWorkbooks(payload) {
return GetJSON("/dataassetmanager/tableauApi/listWorkbooks", payload);
}
export function deleteWorkbooks(payload) {
return Post("/dataassetmanager/tableauApi/deleteWorkbooks", payload);
}
export function saveSmartBIWorkbook(payload) {
return Post("/dataassetmanager/smartBIApi/saveWorkbook", payload);
export function subs(payload) {
return Get("/dataassetmanager/subApi/subs", payload);
}
export function getSmartBIWorkbookUrl(payload) {
return Get("/dataassetmanager/smartBIApi/getWorkbookUrl", payload);
export function startFlow(payload) {
return Post("/dataassetmanager/flowApi/startDataAssetFlow", payload);
}
export function listSmartBIWorkbooks(payload) {
return GetJSON("/dataassetmanager/smartBIApi/listWorkbooks", payload);
export function getSystems(payload) {
return GetJSON(`/authservice/domains/${payload.env}/systems`);
}
export function deleteSmartBIWorkbooks(payload) {
return Post("/dataassetmanager/smartBIApi/deleteWorkbooks", payload);
export function getStandardTree(payload) {
return GetJSON('/standard/rest/standard/maintain/tree/list', payload);
}
export function listTasks(payload) {
return PostJSON("/dataassetmanager/dataAssetCheckApi/listTasks", payload);
export function getStandardList(payload) {
return PostJSON('/standard/rest/standard/maintain/standard/list', payload);
}
export function saveTask(payload) {
return PostJSON("/dataassetmanager/dataAssetCheckApi/saveTask", payload);
export function standardBatchMetadata(payload) {
return PostJSON('/standard/indicator/save/batch', payload);
}
export function auditTask(payload) {
return PostJSON("/dataassetmanager/dataAssetCheckApi/audit", payload);
export function getMetadataStandardList(payload) {
return PostJSON('/standard/indicator/find', payload);
}
export function uploadDataAssetExcel(payload) {
return PostFile("/dataassetmanager/dataAssetCheckApi/uploadDataAssetExcel", payload, 'reportFile');
export function deleteStandardBatchMetadata(payload) {
return PostJSON('/standard/indicator/delete', payload);
}
export function subs(payload) {
return Get("/dataassetmanager/subApi/subs", payload);
export function exportIndicator(payload) {
return callFetchRaw('post', '/standard/indicator/exportData', payload)
}
export function getScore(payload) {
return Get("/dataassetmanager/dataAssetApi/getScoreByDirectoryId", payload);
export function importIndicator(payload) {
return PostFile('/standard/indicator/import', payload);
}
export function getResourceTypes(payload) {
return GetJSON("/dataassetmanager/dataAssetApi/listSupportResourceTypes", payload);
export function importIndicatorLog(payload) {
return GetJSON('/standard/indicator/importLog', payload);
}
export function getDirectoryChild(payload) {
return GetJSON("/dataassetmanager/directoryApi/getChildByParentId", payload);
export function getPermission(payload) {
return GetJSON("/dataassetmanager/permissionApi/getPermissionDetail", payload);
}
export function queryCustomTypeRootDirectory() {
return GetJSON("/dataassetmanager/directoryApi/queryCustomTypeRootDirectory");
export function getTemplates() {
return GetJSON("/dataassetmanager/elementTemplateApi/listSupportTemplates")
}
\ No newline at end of file
import { GetJSON } from "../util/axios"
import { GetJSON, PostJSON, callFetchRaw, PostFile } from "../util/axios"
export function queryDatabase(payload) {
return GetJSON("/metadatarepo/rest/tag/getDatabaseBySystemCode", payload);
......@@ -15,3 +15,27 @@ export function queryAllDataTable(payload) {
export function queryAllFields(payload) {
return GetJSON("/metadatarepo/rest/metadata/getChild", payload);
}
export function getSystemAllGraph(payload) {
return GetJSON("/metadatarelation/getSystemAllGraph", payload);
}
export function getAttributes(payload) {
return PostJSON("/metadatarepo/rest/metadata/getByIdList", payload);
}
export function exportAttributes(payload) {
return callFetchRaw('post', '/metadatarepo/rest/download/exportAssetInfo', payload)
}
export function importAttributes(payload) {
return PostFile("/metadatarepo/rest/import/importAssetInf", payload);
}
export function listImportAssetLog(payload) {
return GetJSON('/metadatarepo/rest/import/listImportAssertLog', payload);
}
export function getImportAssetLogDetail(payload) {
return GetJSON('/metadatarepo/rest/import/getImportAssertLog', payload);
}
\ No newline at end of file
import axios from 'axios';
import LocalStorage from 'local-storage';
import { appId } from '../App';
import { IsArr, showMessage, isSzseEnv } from './index';
......@@ -101,12 +102,16 @@ const callback = resp => {
return resp.data || resp;
}
export function getTemplateType() {
return LocalStorage.get(`templateType-${appId}`)
}
export function Get(url, params) {
const cancelToken = __source ? __source.token : null;
const env = LocalStorage.get('assetsEnv')??debugEnv;
return textplain.get(url, {
params: {...params, env}, cancelToken
params: {...params, env, templateType: getTemplateType()}, cancelToken
}).then(
callback
)
......@@ -117,7 +122,7 @@ export function GetJSON(url, params) {
const env = LocalStorage.get('assetsEnv')??debugEnv;
return instance.get(url, {
params: {...params, env}, cancelToken,
params: {...params, env, templateType: getTemplateType()}, cancelToken,
validateStatus: false
}).then(
callback
......@@ -129,7 +134,7 @@ export function Delete(url, params) {
const env = LocalStorage.get('assetsEnv')??debugEnv;
return instance.delete(url, {
params: {...params, env}, cancelToken,
params: {...params, env, templateType: getTemplateType()}, cancelToken,
}).then(
callback
)
......@@ -141,11 +146,11 @@ export function PostJSON(url, payload) {
const env = LocalStorage.get('assetsEnv')??debugEnv;
return IsArr(data) ? instance.post(url, data, {
params: {...params, env}, cancelToken
params: {...params, env, templateType: getTemplateType()}, cancelToken
}).then(
callback
) : instance.post(url, null, {
params: {...params, env}, data, cancelToken
params: {...params, env, templateType: getTemplateType()}, data, cancelToken
}).then(
callback
)
......@@ -157,7 +162,7 @@ export function Post(url, payload) {
const env = LocalStorage.get('assetsEnv')??debugEnv;
return textplain.post(url, null, {
params: {...params, env}, data, cancelToken
params: {...params, env, templateType: getTemplateType()}, data, cancelToken
}).then(
callback
)
......@@ -172,7 +177,7 @@ export function PostFile(url, payload, fileName='file') {
formData.append(fileName, file);
});
return fileplain.post(url, formData, { params: {...params, env} } ).then(
return fileplain.post(url, formData, { params: {...params, env, templateType: getTemplateType()} } ).then(
callback
)
}
......@@ -191,6 +196,7 @@ export const callFetchRaw = (method, url, options) => {
Object.keys(params||[]).forEach(key => {
bodyFormData.append(key, params[key]);
});
bodyFormData.append('templateType', getTemplateType());
return axios.request({
method,
......
import { AxiosResponse } from "axios"
export default function (res: AxiosResponse<any>) {
const blob = res.data
const headers = res.headers
let tempName = headers["content-disposition"]
?.split(";")?.[1]
?.split("filename=")?.[1];
tempName = decodeURI(tempName);
// const blob = new Blob([content], { type: 'application/octet-stream' })
var url = (window.URL && window.URL.createObjectURL) ? window.URL.createObjectURL(blob) : window.webkitURL.createObjectURL(blob);
const link = document.createElement('a');
link.style.display = 'none';
link.href = url;
link.setAttribute('download', tempName); //or any other extension
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href) // 释放URL 对象
document.body.removeChild(link)
}
\ No newline at end of file
import { useEffect, useState, useContext } from 'react';
import { useEffect, useState } from 'react';
import { Radio } from 'antd';
import { dispatch } from '../../../../model';
import Relation from './Relation';
import Thermodynamic from './Thermodynamic';
import { AssetBrowseReference, ResourceBrowseReference } from '../../../../util/constant';
import { AppContext } from '../../../../App';
const relationTypes = [
{
......@@ -15,6 +14,10 @@ const relationTypes = [
{
title: '热力图',
key: 'thermodynamic'
},
{
title: '数据地图',
key: 'map',
}
]
......@@ -22,8 +25,6 @@ const RelationContainer = (props) => {
const { nodeParams, onChange, reference, resize } = props;
const { env } = useContext(AppContext);
const [ type, setType ] = useState('relation');
const [ dirs, setDirs ] = useState([]);
const [ nodes, setNodes ] = useState([]);
......@@ -33,7 +34,7 @@ const RelationContainer = (props) => {
useEffect(() => {
getDirectoryData();
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ env ])
}, [])
useEffect(() => {
if (type === 'relation') {
......@@ -45,7 +46,7 @@ const RelationContainer = (props) => {
setRelationData(null);
}
} else {
if ((nodeParams?.centerId||'')!== '' && (dirs||[]).length>0) {
if ((nodeParams?.centerId||'')!=='' && (dirs||[]).length>0) {
generateThermodynamicData();
} else {
setThermodynamicData(null);
......@@ -184,8 +185,10 @@ const RelationContainer = (props) => {
let nodeLevelId = `${node.levelId}-`;
let currentLevelId = `${currentNode.levelId}-`;
if (currentNode.levelId.split('-').length > 1) {
if ((node.levelId.split('-').length===currentNode.levelId.split('-').length+1) && node.levelId.slice(0, currentLevelId.length)===currentLevelId) {
node.show = true;
node.show = !node.show;
}
}
if (node.levelId.split('-').length >2) {
......@@ -201,6 +204,7 @@ const RelationContainer = (props) => {
}
})
console.log('data', data)
setNodes(data);
generateCenterNodeRelationData(data);
......@@ -261,8 +265,12 @@ const RelationContainer = (props) => {
}
const onTypeChange = (e) => {
if (e.target.value === 'map') {
window?.open('/center-home/menu/asset-map');
} else {
setType(e.target.value);
}
}
return (
<div style={{ width: '100%', height: '100%', position: 'relative' }}>
......
import React from 'react';
import * as echarts from 'echarts';
import { dispatch } from '../../../../model'
//https://echarts.apache.org/examples/zh/editor.html?c=treemap-show-parent&lang=js
class Thermodynamic extends React.Component {
componentDidMount() {
const { data, onClick } = this.props;
if (data) {
if (data && data.length>0 && (data[0].children||[]).length>0) {
this.graph = init(this)(this.elem, data, onClick);
this.getScore();
}
}
......@@ -17,37 +16,20 @@ class Thermodynamic extends React.Component {
const { data, onClick, resize } = this.props;
if (data !== prevProps.data) {
this.graph?.dispose();
this.graph = init(this)(this.elem, data, onClick);
this.getScore();
} else if (resize !== prevProps.resize) {
this.graph?.resize();
}
}
getScore() {
const { data } = this.props;
dispatch({
type: 'assetmanage.getScore',
payload: {
dirId: (data?.length>0) ? data[0]?.nodeId: ''
},
callback: newScore => {
this.graph?.setOption({
title: {
subtext: `价值评分 ${newScore}`,
itemGap: 2,
}
})
}
})
}
elem = undefined;
graph = undefined;
render() {
return (
<div ref={ref => this.elem = ref} style={{ position: 'relative', width: '100%', height: '100%' }}></div>
<div ref={ref => this.elem = ref} style={{ position: 'relative', width: '100%', height: '100%' }}>
</div>
);
}
}
......@@ -61,7 +43,7 @@ const init = (ctx) => function (container, data, onClick) {
return [
{
itemStyle: {
borderColor: '#777',
borderColor: ((data||[]).length>0)&&(data[0].dataAssetAndSubDirCount===0||(data[0].children||[]).reduce((preVal, item) => item?.dataAssetAndSubDirCount + preVal, 0)===0) ? '#97aeed' : '#777',
borderWidth: 0,
gapWidth: 1
},
......@@ -96,9 +78,9 @@ const init = (ctx) => function (container, data, onClick) {
title: {
text: ((data||[]).length>0) ? `${data[0]?.text||''} (${data[0]?.dataAssetAndSubDirCount})` : '',
left: 'center',
bottom: 0,
bottom: 10,
textStyle: {
fontSize: 14
fontSize: 16
}
},
tooltip: {
......@@ -117,20 +99,22 @@ const init = (ctx) => function (container, data, onClick) {
},
series: [
{
name: ((data||[]).length>0) ? `${data[0]?.text||''} (${data[0]?.dataAssetAndSubDirCount})` : '',
type: 'treemap',
height: '85%',
visibleMin: 0,
childrenVisibleMin: 0,
visibleMin: 1,
childrenVisibleMin: 1,
label: {
show: true,
formatter: '{b}'
},
upperLabel: {
show: true,
height: 30
height: 30,
color: '#fff',
},
itemStyle: {
borderColor: '#fff'
borderColor: '#555'
},
breadcrumb: {
show: false,
......@@ -144,7 +128,6 @@ const init = (ctx) => function (container, data, onClick) {
myChart.setOption(option);
myChart.on('click', function (params) {
console.log(params);
const { data } = params;
if (onClick && data && data.nodeId) {
......
import React, { useState } from 'react';
import classNames from 'classnames';
import { CaretLeftOutlined, CaretRightOutlined } from '@ant-design/icons';
import { ResizableBox } from 'react-resizable';
import AssetTree from '../AssetManage/Component/AssetTree';
import AssetDirectory from '../AssetManage/Component/AssetDirectory';
......@@ -16,16 +17,17 @@ const AssetBrowse = (props) => {
const { reference = AssetBrowseReference } = props;
const [ nodeParams, setNodeParams ] = useState({ centerId: '', expandId: '' });
const [ nodeParams, setNodeParams ] = useState({ centerId: null, expandId: '', nodeType: '' });
const [ expandTree, setExpandTree ] = useState(true);
const [ expandRelation, setExpandRelation ] = useState(true);
const [ assetCount, setAssetCount ] = useState(0);
const [ resizeRelation, setResizeRelation ] = useState(false);
const [ assetFullScreen, setAssetFullScreen ] = useState(false);
const { centerId, expandId } = nodeParams;
const onTreeSelect = (value, type) => {
setNodeParams({ centerId: value||'', expandId: '' });
setNodeParams({ centerId: value, expandId: '', nodeType: type });
}
const treeToggleClick = () => {
......@@ -46,11 +48,8 @@ const AssetBrowse = (props) => {
setAssetCount(count);
}
let nodeId = '';
if ((expandId||'') !== '') {
nodeId = expandId;
} else {
nodeId = centerId;
const onFullScreenChange = (value) => {
setAssetFullScreen(value);
}
const classes = classNames('asset-browse', {
......@@ -58,36 +57,46 @@ const AssetBrowse = (props) => {
'asset-browse-relation-collapse': !expandRelation,
});
const rightClasses = classNames('right', {
'right-fullscreen': assetFullScreen
});
return (
<div className={classes}>
<div className='left'>
<ResizableBox
className='left'
width={230}
height={Infinity}
axis='x'
minConstraints={[230, Infinity]} maxConstraints={[Infinity, Infinity]}
>
<AssetTree centerId={centerId} onSelect={onTreeSelect} reference={reference} {...props} />
</div>
</ResizableBox>
{
expandTree && <Separate width={15} />
}
<div className='right'>
<AssetDirectory id={nodeId} assetCount={assetCount} reference={reference} />
<Separate height={15} />
<div className={rightClasses}>
{/* <AssetDirectory id={centerId} assetCount={assetCount} reference={reference} nodeType={nodeParams.nodeType} />
<Separate height={15} /> */}
<div className='flex' style={{ flex: 1, height: '100%', overflow: 'hidden' }}>
{
expandRelation && <React.Fragment>
<div style={{ flex: 1, height: '100%', overflow: 'hidden' }}>
<RelationContainer reference={reference} nodeParams={nodeParams} onChange={onRelationChange} resize={resizeRelation} />
</div>
<Separate width={15} />
</React.Fragment>
// expandRelation && <React.Fragment>
// <div style={{ flex: 1, height: '100%', overflow: 'hidden' }}>
// <RelationContainer reference={reference} nodeParams={nodeParams} onChange={onRelationChange} resize={resizeRelation} />
// </div>
// <Separate width={15} />
// </React.Fragment>
}
<div style={{ flex: 1, overflow: 'hidden' }}>
<AssetTable nodeId={nodeId} reference={reference} onCountChange={onAssetCountChange} {...props} />
</div>
<AssetTable nodeId={centerId} nodeType={nodeParams.nodeType} reference={reference} onCountChange={onAssetCountChange} onFullScreenChange={onFullScreenChange} {...props} />
</div>
</div>
<div className='tree-toggle' onClick={treeToggleClick}>
{ expandTree ? <CaretLeftOutlined /> : <CaretRightOutlined /> }
</div>
<div className='relation-toggle' onClick={relationToggleClick}>
{/* <div className='relation-toggle' onClick={relationToggleClick}>
{ expandRelation ? <CaretLeftOutlined /> : <CaretRightOutlined /> }
</div> */}
</div>
</div>
)
......
......@@ -5,7 +5,7 @@
height: 100%;
.left {
width: 230px;
flex: 0 0 auto;
border-right: 1px solid #EFEFEF;
overflow: hidden;
}
......@@ -18,7 +18,7 @@
right: 0;
background: #f2f5fc;
position: absolute;
left: 245px;
left: 0px;
top: calc(50% - 40px);
width: 12px;
height: 80px;
......@@ -29,18 +29,24 @@
}
.right {
position: relative;
display: flex;
width: calc(100% - 245px);
flex: 1;
overflow: hidden;
flex-direction: column;
}
.right-fullscreen {
position: static;
}
.relation-toggle {
display: flex;
justify-content: center;
align-items: center;
background: #f2f5fc;
position: absolute;
left: calc(50% + 130px);
left: calc(50% + 7.5px);
top: calc(50% - 40px);
width: 12px;
height: 80px;
......@@ -52,24 +58,20 @@
&.asset-browse-relation-collapse {
.relation-toggle {
left: 245px;
left: 0px;
}
}
}
.asset-browse-tree-collapse {
.left {
width: 0;
width: 0 !important;
}
.tree-toggle {
left: 0;
}
.right {
width: 100%;
}
.relation-toggle {
left: calc(50% + 7.5px);
}
......
......@@ -45,6 +45,16 @@ const AddAssetModel = (props) => {
setConfirmLoading(true);
dispatch({
type: 'assetmanage.checkCodeIsExist',
payload: {
data: { elements: newElements }
},
callback: isExist => {
if (isExist === 'true') {
setConfirmLoading(false);
showMessage('warn', '已存在相同的资产目录编号,请重新输入');
} else {
dispatch({
type: 'assetmanage.addOrUpdateDataAsset',
payload: {
params,
......@@ -59,6 +69,12 @@ const AddAssetModel = (props) => {
setConfirmLoading(false);
}
})
}
},
error: () => {
setConfirmLoading(false);
}
})
} catch (errInfo) {
console.log('Validate Failed:', errInfo);
......@@ -70,7 +86,7 @@ const AddAssetModel = (props) => {
<Modal
forceRender
className='asset-add'
title='新增资产信息'
title='新增资产目录信息'
visible={ visible }
width={ 600 }
onCancel={() => { onCancel && onCancel(); } }
......
import React, { useEffect, useState } from 'react';
import { Form, Spin, Input, Descriptions, Space, Button, Tooltip } from 'antd';
import { DownOutlined, UpOutlined } from '@ant-design/icons';
import React, { useEffect, useState, useContext, useMemo, useRef } from 'react';
import { Form, Spin, Input, Descriptions, Space, Button, Tooltip, Select, Cascader, Radio, Divider, Typography, Modal, Row, Col, Pagination } from 'antd';
import { DownOutlined, UpOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import LocalStorage from 'local-storage';
import { Subject } from 'rxjs';
import MetadataInfo from './MetadataInfo';
import { dispatch } from '../../../../model';
import { highlightSearchContentByTerms, showMessage } from '../../../../util';
import { AppContext } from '../../../../App';
import { highlightSearchContentByTerms, showMessage, paginate } from '../../../../util';
import { AppContext, appId } from '../../../../App';
import Tag from '../../Tag';
import Separate from './Separate';
import AssetTagModal from './AssetTagModal';
import StandardName from './StandardName';
import { AnchorId, AnchorDirId, AssetManageReference } from '../../../../util/constant';
import IndexCode from './IndexCode';
// import Upload from './Upload';
import Table from '../../ResizeableTable';
import { CancelSvg, EditSvg, SaveSvg, FullScreenSvg, CancelFullScreenSvg } from './AssetSvg';
// import SelectUser from '../../Model/Component/SelectUsers';
// import SelectFilter from '../../Model/Component/SelectFilter';
import { checkDataAssetEditable } from '../../../../service/dataassetmanager';
// import download from '../../../../util/download';
import SelectStandard from './SelectStandard';
import AttributeMaintain from './AttributeMaintain';
export const AssetActionSubject = new Subject()
import './AssetAction.less';
const AssetAction = (props) => {
const { id, dirId, action, terms, onChange, readOnly = false, form, onMetadataChange, onElementsChange } = props;
const { id, dirId, action, terms, onChange, reference, form, onMetadataChange, onElementsChange, readonly = false, permissionId } = props;
const [ currentAction, setCurrentAction ] = useState(action);
const [ assetParams, setAssetParams ] = useState({ assets: {}, attributes: [], attributesFoldMap: {} });
const [ elements, setElements ] = useState([]);
const [ wholeElements, setWholeElements ] = useState([]);
const [ metadataId, setMetadataId ] = useState('');
const [ loading, setLoading ] = useState(false);
const [ confirmLoading, setConfirmLoading ] = useState(false);
const [ fullScreen, setFullScreen ] = useState(false);
const [ assetPaths, setAssetPaths ] = useState([]);
const [ resourceRelations, setResourceRelations ] = useState([]);
const { assets, attributes, attributesFoldMap } = assetParams;
const [ assetTagModalVisible, setAssetTagModalVisible ] = useState(false);
const [ keyword, setKeyword ] = useState('');
const [ selectTag, setSelectTag ] = useState({});
const [ systems, setSystems] = useState([]);
const [ loadingSystems, setLoadingSystems ] = useState(false);
const [ users, setUsers ] = useState([]);
const [ loadingUsers, setLoadingUsers ] = useState(false);
const [ departments, setDepartments ] = useState([]);
const [ loadingDepartments, setLoadingDepartments ] = useState(false);
const [ treeData, setTreeData ] = useState([]);
const [ treeDataMap, setTreeDataMap ] = useState(undefined);
const [currentDomainGroup, setCurrentDomainGroup] = useState(undefined);
const [currentBussinessDomain, setCurrentBussinessDomain] = useState(undefined);
const [canEdit, setEdit] = useState(false);
const [metadata, setMetadata] = useState(undefined);
const [loadingMetadataColumnList, setLoadingMetadataColumnList] = useState(false);
const [metadataColumnList, setMetadataColumnList] = useState(undefined);
const [selectStandardParam, setSelectStandardParam] = useState({ visible: false, id: undefined });
const [standardList, setStandardList] = useState(undefined);
const [attributeMaintainParam, setAttributeMaintainParam] = useState({
visible: false,
metadataId: undefined
});
const [ pagination, setPagination ] = useState({ pageNum: 1, pageSize: 20 });
const { pageNum, pageSize } = pagination;
const [modal, contextHolder] = Modal.useModal();
const [permissions, setPermissions] = useState(undefined);
const [keyword, setKeyword] = useState('');
useEffect(() => {
const $$assetAction = AssetActionSubject.subscribe((act) => {
if (act?.type === 'update') {
if (id) {
getAsset();
const app = useContext(AppContext);
const uploadRef = useRef(undefined);
const columns = [
{
title: '技术ID(英文名称)',
dataIndex: 'name',
width: 160,
ellipsis: true,
render: (text, record, _) => {
return (
<Tooltip title={text||''}>
<a onClick={() => {
window.open(`/center-home/metadetail?mid=${record._id}&action=metadetail&type=detail&manager=false&activekey=1`);
}}>
{highlightSearchContentByTerms(text||'', terms)}
</a>
</Tooltip>
);
}
},
{
title: '名称',
dataIndex: 'cnName',
// width: 200,
ellipsis: true,
render: (text, _) => highlightSearchContentByTerms(text||'', terms)
},
{
title: '是否有权限',
dataIndex: 'permission',
width: 100,
ellipsis: true,
render: (_, record) => {
const index = (permissions||[]).findIndex(item => item.columnMetadataId===record._id);
if (index!==-1) {
return permissions[index].visible === 'Y' ? '是':'否';
}
return '否';
}
},
{
title: '业务规则',
dataIndex: 'businessRules',
width: 240,
ellipsis: true,
render: (text, _) => highlightSearchContentByTerms(text||'', terms)
},
{
title: '计量单位',
dataIndex: 'unitOfMeasurement',
ellipsis: true,
render: (text, _) => highlightSearchContentByTerms(text||'', terms)
},
{
title: '备注信息',
dataIndex: 'remarks',
ellipsis: true,
render: (text, _) => highlightSearchContentByTerms(text||'', terms)
},
{
title: '类型',
dataIndex: 'typeName',
width: 100,
ellipsis: true,
render: (text, _) => highlightSearchContentByTerms(text||'', terms)
},
{
title: '长度',
dataIndex: 'size',
width: 60,
ellipsis: true,
},
{
title: '引用标准',
dataIndex: 'standard',
ellipsis: true,
render: (_, record) => {
return <AppContext.Consumer>
{
appValue => <a onClick={() => {
appValue?.setGlobalState && appValue?.setGlobalState({
message: 'data-govern-show-index-detail-message',
data: { id: record.standard?.standardId }
})
}}>
<span>{record.standard?.standardName}</span>
</a>
}
</AppContext.Consumer>
}
},
{
title: '操作',
dataIndex: 'action',
width: 170,
fixed: 'right',
render: (_, record) => {
return (reference===AssetManageReference||canEdit) ? <Space>
<Button
size='small'
onClick={() => {
setSelectStandardParam({ visible: true, id: record._id });
}}
>
关联标准
</Button>
{
record.standard?.standardId && <Button
size='small'
onClick={() => {
modal.confirm({
title: '您确定要取消关联标准吗?',
onOk: () => {
dispatch({
type: 'assetmanage.deleteStandardBatchMetadata',
payload: {
params: {
ids: record.standard?.id
}
},
callback: () => {
showMessage("success","取消成功");
getMetadataStandardList();
}
})
return () => {
$$assetAction.unsubscribe()
}
}, [id])
})
}}
>
取消关联
</Button>
}
</Space>: null;
}
}
];
useEffect(() => {
getSystems();
getUsers();
getTreeData();
getDepartments();
if (action === 'add') {
getElements();
// getElements();
} else {
setCurrentAction('detail');
if ((id||'')!=='') {
setPagination({...pagination, pageNum: 1});
getElements();
getAssetPaths();
getResourceRelations();
checkDataAssetEditable();
getAsset();
} else {
setMetadataId('');
setAssetParams({...assetParams, ...{assets: {}, attributes: []}});
......@@ -60,52 +230,180 @@ const AssetAction = (props) => {
}
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [id])
}, [id, dirId])
const getResourceRelations = () => {
useEffect(() => {
if (permissionId) {
getPermission();
}
}, [permissionId, app?.env])
const domains = useMemo(() => {
if (currentDomainGroup && treeDataMap) {
return treeDataMap[currentDomainGroup];
}
return [];
}, [currentDomainGroup, treeDataMap])
const businessData = useMemo(() => {
if (currentDomainGroup && currentBussinessDomain && treeDataMap) {
const currentLevel2Data = treeDataMap[currentDomainGroup];
const index = (currentLevel2Data||[]).findIndex(item => item.text === currentBussinessDomain);
if (index !== -1) {
return currentLevel2Data[index].children;
}
}
return [];
}, [currentDomainGroup, currentBussinessDomain, treeDataMap])
const tableData = useMemo(() => {
if (metadataColumnList && standardList) {
const newMetadataColumnList = [];
metadataColumnList.filter(item => {
return (
!keyword
|| (item.name??'').indexOf(keyword)!==-1
|| (item.cnName??'').indexOf(keyword)!==-1
|| (item.businessRules??'').indexOf(keyword)!==-1
)
}).forEach(item => {
const index = standardList?.findIndex(_item => _item.metadataId === item._id);
let newItem = {...item};
if (index !== -1) {
newItem.standard = standardList[index];
}
newMetadataColumnList.push(newItem);
});
return paginate(newMetadataColumnList, pageNum, pageSize);
}
return [];
}, [metadataColumnList, standardList, pagination, keyword])
const getPermission = () => {
dispatch({
type: 'assetmanage.getResourceRelations',
type: 'assetmanage.getPermission',
payload: {
dataAssetId: id,
permissionId,
env: app?.env?.domainId||LocalStorage.get('assetsEnv')
},
callback: data => {
setResourceRelations(data);
setPermissions(data.columnPermissions);
}
});
}
const getElements = ( cb = null ) => {
if (!dirId) return;
const getAssetPaths = () => {
dispatch({
type: 'assetmanage.getAssetPaths',
payload: {
dataAssetId: id,
},
callback: data => {
setAssetPaths(data||[]);
}
});
}
setLoading(true);
const getSystems = () => {
setLoadingSystems(true);
dispatch({
type: 'assetmanage.listElementsByDirId',
type: 'assetmanage.getSystems',
payload: {
dirId
env: app?.env?.domainId||LocalStorage.get('assetsEnv'),
},
callback: data => {
setLoading(false);
setElements(data||[]);
onElementsChange && onElementsChange(data||[]);
setLoadingSystems(false);
setSystems(data||[])
},
error: () => {
setLoadingSystems(false);
}
});
}
const _attributes = [];
(data||[]).forEach(element => {
if (_attributes.indexOf(element.type) === -1) {
_attributes.push(element.type);
const getUsers = () => {
setLoadingUsers(true);
dispatch({
type: 'pds.getOwners',
callback: (data) => {
setLoadingUsers(false);
setUsers(data);
},
error: () => {
setLoadingUsers(false);
}
})
}
let newAttributesFoldMap = {...attributesFoldMap};
(_attributes||[]).forEach(attribute => {
if (newAttributesFoldMap[attribute]===undefined || newAttributesFoldMap[attribute]===null) {
newAttributesFoldMap[attribute] = true;
const getTreeData = () => {
dispatch({
type: 'assetmanage.queryAllDirectoryAsTree',
callback: (data) => {
setTreeData(data);
const newTreeDataMap = {};
data?.forEach(item => {
newTreeDataMap[item.text] = item.children;
})
setTreeDataMap(newTreeDataMap);
}
})
}
setAssetParams({ assets: {}, attributes: _attributes, attributesFoldMap: newAttributesFoldMap });
form?.resetFields();
const getDepartments = () => {
setLoadingDepartments(true);
dispatch({
type: 'pds.getDepartments',
callback: (data) => {
setLoadingDepartments(false);
setDepartments(data);
},
error: () => {
setLoadingDepartments(false);
}
})
}
cb && cb();
const getResourceRelations = () => {
dispatch({
type: 'assetmanage.getResourceRelations',
payload: {
dataAssetId: id,
},
callback: data => {
setResourceRelations(data||[]);
}
});
}
const getElements = ( cb = null ) => {
dispatch({
type: (currentAction==='add')?'assetmanage.listElementsAndFillValue':'assetmanage.listElements',
payload: (currentAction==='add')?{
params: {
dirId
}
}:undefined,
callback: data => {
setWholeElements(data||[]);
}
})
}
const getUserElements = () => {
setLoading(true);
dispatch({
type: 'assetmanage.listUserElements',
callback: data => {
setLoading(false);
getAsset(data||[]);
},
error: () => {
setLoading(false);
......@@ -113,21 +411,61 @@ const AssetAction = (props) => {
})
}
const getAsset = () => {
const checkDataAssetEditable = () => {
dispatch({
type: 'assetmanage.checkDataAssetEditable',
payload: {
params: {
dataAssetId: id,
}
},
callback: value => {
setEdit(value==='true'?true:false);
}
})
}
const getAsset = (userElements=null) => {
setLoading(true);
dispatch({
type: 'assetmanage.getDataAssetDetail',
payload: {
dataAssetId: id,
dirId: dirId,
checkPermission: reference!==AssetManageReference
},
callback: data => {
setLoading(false);
const metadataIndex = data?.elements?.findIndex(item => item.name === '资产项');
if (metadataIndex !== -1) {
let metadataValue = data?.elements[metadataIndex].value;
try {
setMetadata(JSON.parse(metadataValue));
getMetadataAttributes();
getMetadataStandardList();
} catch(error) {
}
}
if (userElements) {
const userElementIds = [];
(userElements||[]).forEach(element => {
userElementIds.push(element?.id);
});
const filterElements = (data?.elements||[]).filter(element => userElementIds.indexOf(element?.id) !== -1);
data = { ...data, elements: filterElements };
}
setElements(data?.elements||[]);
onElementsChange && onElementsChange(data?.elements||[]);
setMetadataId(data?.mid||'');
onMetadataChange && onMetadataChange(data?.mid||'');
setMetadataId(data?.metadataId||'');
onMetadataChange && onMetadataChange(data?.metadataId||'');
const _attributes = [];
(data?.elements||[]).forEach(element => {
......@@ -148,6 +486,11 @@ const AssetAction = (props) => {
let _fieldsValue = {};
(data.elements||[]).forEach(element => {
_fieldsValue[element.name] = element.value||'';
if (element.name === '主题域分组') {
setCurrentDomainGroup(element.value);
} else if (element.name === '主题域') {
setCurrentBussinessDomain(element.value);
}
})
form?.setFieldsValue(_fieldsValue);
......@@ -158,6 +501,67 @@ const AssetAction = (props) => {
})
}
const getMetadataAttributes = () => {
setMetadata(prevMetadata => {
const ids = prevMetadata?.columnItems.map(item => item.metadataColumnId);
if ((ids||[]).length > 0) {
setLoadingMetadataColumnList(true);
dispatch({
type: 'assetmanage.getMetadataAttributes',
payload: {
data: ids,
params: {
catalog: app?.env?.domainId||LocalStorage.get('assetsEnv'),
}
},
callback: data => {
setLoadingMetadataColumnList(false);
const newData = [...data||[]];
if (prevMetadata?.metadataTableId?.toLowerCase().indexOf('query') !== -1) {
newData.forEach(item => {
item.typeName = item.datatype;
item.size = item.length;
});
}
setMetadataColumnList(newData);
},
error: () => {
setLoadingMetadataColumnList(false);
}
});
}
return prevMetadata
})
}
const getMetadataStandardList = () => {
setMetadata(prevMetadata => {
if (prevMetadata.metadataTableId) {
dispatch({
type: 'assetmanage.getMetadataStandardList',
payload: {
data: {
parentMetadataId: prevMetadata.metadataTableId
},
params: {
page: 1,
size: 999999
}
},
callback: data => {
setStandardList(data?.content);
},
});
}
return prevMetadata;
})
}
const onCancelButtonClick = () => {
setCurrentAction('detail');
getAsset();
......@@ -171,14 +575,40 @@ const AssetAction = (props) => {
}
}
const jumpToPath = () => {
setFullScreen(false);
const onAuthorizationButtonClick = () => {
if (assets?.metadataId) {
app?.setGlobalState && app?.setGlobalState({
message: 'data-govern-assets-admit',
data: assets
})
} else {
showMessage("warn","该资产目录没有关联元数据信息");
}
}
const jumpToPath = (item) => {
const timestamp = new Date().getTime();
LocalStorage.set('assetDirChange', !(LocalStorage.get('assetDirChange')||false));
let event = new Event('storage');
event.key = 'assetDirChange';
event.dirId = dirId||'';
window?.dispatchEvent(event);
if (item.resourceType==='innerSource'||item.resourceType==='outerSource') {
window.open(`/center-home/menu/asset-resource-browse?${AnchorId}=${item?.dataAssetId}&${AnchorDirId}=${item?.dirId}&timestamp=${timestamp}`);
} else if (item.resourceType==='dataAsset') {
window.open(`/center-home/menu/asset-browse?${AnchorId}=${item?.dataAssetId}&${AnchorDirId}=${item?.dirId}&templateType=${LocalStorage.get(`templateType-${appId}`)}&timestamp=${timestamp}`);
} else {
showMessage('warn', '资产目录类型不是资源也不是资产!');
}
}
const jumpToRelation = (relation) => {
const timestamp = new Date().getTime();
if (relation.resourceType==='innerSource'||relation.resourceType==='outerSource') {
window.open(`/center-home/menu/asset-resource-browse?${AnchorId}=${relation?.dataAssetId}&${AnchorDirId}=${relation?.dirId}&timestamp=${timestamp}`);
} else if (relation.resourceType==='dataAsset') {
window.open(`/center-home/menu/asset-browse?${AnchorId}=${relation?.dataAssetId}&${AnchorDirId}=${relation?.dirId}&timestamp=${timestamp}`);
} else {
showMessage('warn', '资产目录类型不是资源也不是资产!');
}
}
const onOk = async() => {
......@@ -203,6 +633,16 @@ const AssetAction = (props) => {
setConfirmLoading(true);
dispatch({
type: 'assetmanage.checkCodeIsExist',
payload: {
data: action==='add' ? { elements: newElements } : { ...assets, elements: newElements }
},
callback: isExist => {
if (isExist === 'true') {
setConfirmLoading(false);
showMessage('warn', '已存在相同的资产目录编号,请重新输入');
} else {
dispatch({
type: 'assetmanage.addOrUpdateDataAsset',
payload: {
params,
......@@ -219,6 +659,12 @@ const AssetAction = (props) => {
setConfirmLoading(false);
}
})
}
},
error: () => {
setConfirmLoading(false);
}
})
} catch (errInfo) {
console.log('Validate Failed:', errInfo);
......@@ -257,8 +703,8 @@ const AssetAction = (props) => {
})
}
const onAssetTag = (keyword) => {
setKeyword(keyword);
const onAssetTag = (value) => {
setSelectTag(value);
setAssetTagModalVisible(true);
}
......@@ -274,72 +720,224 @@ const AssetAction = (props) => {
}
}
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 17 },
},
};
// const formItemLayout = {
// labelCol: {
// xs: { span: 24 },
// sm: { span: 5 },
// },
// wrapperCol: {
// xs: { span: 24 },
// sm: { span: 17 },
// },
// };
const elementEditComponent = (element) => {
if (element.name==='资产项') return <MetadataInfo />;
if (element.name === '数据源系统') {
return (
<Select
allowClear
loading={loadingSystems}
disabled={element.manualMaintain==='否'}
>
{
systems?.map((system, index) => {
return <Select.Option key={index} value={system.scopeName}>
{system.scopeName}
</Select.Option>
})
}
</Select>
)
}
// if (element.name==='数据关键用户' || element.name?.toLowerCase()==='业务数据owner' || element.name?.toLowerCase()==='it责任人') {
// return <SelectUser
// type='edit'
// loading={loadingUsers}
// users={users}
// disabled={element.manualMaintain==='否'}
// />
// }
// if (element.name==='业务责任部门' || element.name?.toLowerCase()==='it责任部门') {
// return <SelectFilter
// loading={loadingDepartments}
// data={departments}
// disabled={element.manualMaintain==='否'}
// />
// }
if (element.name === '主题域分组') {
return (
<Select
allowClear
disabled={element.manualMaintain==='否'}
>
{
treeData?.map((item, index) => {
return <Select.Option key={index} value={item.text}>
{item.text}
</Select.Option>
})
}
</Select>
)
}
if (element.name === '主题域') {
return (
<Select
allowClear
disabled={element.manualMaintain==='否'}
>
{
domains?.map((item, index) => {
return <Select.Option key={index} value={item.text}>
{item.text}
</Select.Option>
})
}
</Select>
)
}
if (element.name === '业务对象') {
return (
<Select
allowClear
disabled={element.manualMaintain==='否'}
>
{
businessData?.map((item, index) => {
return <Select.Option key={index} value={item.text}>
{item.text}
</Select.Option>
})
}
</Select>
)
}
if (element.selectMode==='单选') {
return (
<Select
allowClear
disabled={element.manualMaintain==='否'}
>
{
element.optional?.split(',').map((value, index) => {
return <Select.Option key={index} value={value}>
{value}
</Select.Option>
})
}
</Select>
)
}
if (element.selectMode==='多选') return <MultipleSelect element={element}/>;
return <Input disabled={element.manualMaintain==='否'} />;
}
const elementDetailComponent = (item) => {
if (item.name === '资产项') {
return <MetadataInfo config={false} value={item.value||''} terms={terms} />;
}
if (item.name === '指标标准编码') {
return <IndexCode value={item.value||''} terms={terms} />;
}
// if (item.name==='数据关键用户' || item.name?.toLowerCase()==='业务数据owner' || item.name?.toLowerCase()==='it责任人' || item.name==='创建人' || item.name==='更新人') {
// return <SelectUser
// type='detail'
// users={users}
// terms={terms}
// value={item.value||''}
// />
// }
return <span className='text-color'>{highlightSearchContentByTerms(item.value||'', terms)}</span>;
}
// const onExportClick = () => {
// dispatch({
// type: 'assetmanage.exportMetadataAttributes',
// payload: {
// responseType: 'blob',
// params: {
// tableId: metadata?.metadataTableId
// }
// },
// callback: (res) => {
// download(res);
// }
// })
// }
const onSelectStandardCancel = (refresh = false) => {
setSelectStandardParam({ visible: false, id: undefined });
refresh && getMetadataStandardList();
}
const onAttributeMaintainCancel = () => {
setAttributeMaintainParam({visible: false, metadataId: undefined});
}
const onAttributeMaintainChange = (catalogId) => {
if (catalogId === '1') {
setPagination({...pagination, pageNum: 1});
getMetadataAttributes();
} else {
getMetadataStandardList();
}
}
const onValuesChange = (changedValues, allValues) => {
if (changedValues.hasOwnProperty('主题域分组')) {
setCurrentDomainGroup(changedValues['主题域分组']);
form.setFieldsValue({'主题域': '', '业务对象': ''});
} else if (changedValues.hasOwnProperty('主题域')) {
setCurrentBussinessDomain(changedValues['主题域']);
form.setFieldsValue({'业务对象': ''});
} else if (changedValues.hasOwnProperty('业务数据Owner')) {
if (changedValues['业务数据Owner']) {
const index = (users||[]).findIndex(item => item.pernr === changedValues['业务数据Owner']);
if (index !== -1) {
form.setFieldsValue({'业务责任部门': users[index].orgtx});
}
}
} else if (changedValues.hasOwnProperty('IT责任人')) {
if (changedValues['IT责任人']) {
const index = (users||[]).findIndex(item => item.pernr === changedValues['IT责任人']);
if (index !== -1) {
form.setFieldsValue({'IT责任部门': users[index].orgtx});
}
}
}
}
return (
<div
className='flex'
className='flex asset-action'
style={{
height: '100%',
flexDirection: 'column',
position: fullScreen?'absolute':'relative',
left: 0,
right: 0,
top: 0,
bottom: 0,
backgroundColor: '#fff',
zIndex: fullScreen?100:0,
}}
>
{
(!readOnly&&action!=='add') && <div
className='flex px-common primary-bg-container'
style={{
height: 46,
alignItems: 'center',
justifyContent: 'space-between',
color: '#fff',
}}
>
<div>资产详情</div>
(!readonly && (reference===AssetManageReference||canEdit)) && <div className='flex' style={{ justifyContent: 'right' }}>
<Space>
{
((id||'')!=='') && <React.Fragment>
{
(currentAction!=='detail') && <Tooltip title='取消编辑'>
<Button
onClick={onCancelButtonClick}
icon={<CancelSvg className='greyIcon' style={{ width: 20, height: 20 }} />}
type='text'
/>
</Tooltip>
}
<Tooltip title={(currentAction==='detail')?'编辑':'保存'}>
<Button
loading={confirmLoading}
onClick={onActionButtonClick}
icon={(currentAction==='detail')?<EditSvg className='greyIcon' style={{ width: 20, height: 20 }} />: <SaveSvg className='greyIcon' style={{ width: 20, height: 20 }} />}
type='text'
/>
</Tooltip>
currentAction==='detail' ? <Button type='primary' onClick={onActionButtonClick}>编辑</Button> : <React.Fragment>
<Button type='primary' onClick={onCancelButtonClick}>取消</Button>
<Button type='primary' onClick={onActionButtonClick}>保存</Button>
</React.Fragment>
}
<Tooltip title={fullScreen?'取消全屏':'全屏'}>
<Button
onClick={onFullScreenClick}
icon={fullScreen?<CancelFullScreenSvg className='greyIcon' style={{ width: 20, height: 20 }} />: <FullScreenSvg className='greyIcon' style={{ width: 20, height: 20 }} />}
type='text'
/>
</Tooltip>
<Button type='primary' onClick={onAuthorizationButtonClick}>授权</Button>
</Space>
</div>
}
......@@ -348,17 +946,22 @@ const AssetAction = (props) => {
<div className='pl-common py-compact-common'>
<Descriptions column={1}>
<Descriptions.Item
label={<div className='title-text' style={{ textAlign: 'right', width: 60 }}>资产路径</div>}
style={{ paddingBottom: 15 }}
label={<div className='title-text' style={{ textAlign: 'right', width: 90 }}>资产目录路径</div>}
style={{ paddingBottom: 0 }}
>
<a onClick={()=>{jumpToPath();}}>
{assets.currentPath||''}
<div className='flex' style={{ flexDirection: 'column' }}>
{
(assetPaths||[]).map((item, key) => {
return (
<a key={key} onClick={() => { jumpToPath(item); }}>
<span>{item?.dataAssetName||''}</span>
</a>
);
})
}
</div>
</Descriptions.Item>
<Descriptions.Item label={<div className='title-text' style={{ textAlign: 'right', width: 60 }}>价值评分</div>} style={{ paddingBottom: 15 }}>
<div>{assets.score}</div>
</Descriptions.Item>
<Descriptions.Item label={<div className='title-text' style={{ textAlign: 'right', width: 60 }}>资产标签</div>} style={{ paddingBottom: 15 }}>
{/* <Descriptions.Item label={<div className='title-text' style={{ textAlign: 'right', width: 90 }}>资产目录标签</div>} style={{ paddingBottom: 15 }}>
<AppContext.Consumer>
{
value => {
......@@ -366,151 +969,231 @@ const AssetAction = (props) => {
}
}
</AppContext.Consumer>
</Descriptions.Item>
<Descriptions.Item
label={<div className='title-text' style={{ textAlign: 'right', width: 60 }}>关联关系</div>}
</Descriptions.Item> */}
{/* <Descriptions.Item
label={<div className='title-text' style={{ textAlign: 'right', width: 80 }}>关联关系</div>}
style={{ paddingBottom: 0 }}
>
<div className='flex' style={{ flexDirection: 'column' }}>
{
(resourceRelations||[]).map((item, key) => {
return (
<span key={key}>{item}</span>
<a key={key} onClick={() => { jumpToRelation(item); }}>{item?.dataAssetName||''}</a>
);
})
}
</div>
</Descriptions.Item>
</Descriptions.Item> */}
</Descriptions>
</div>
{
!readOnly && <Separate height={8} />
}
</div>
}
<div
{/* <div
style={{
flex: 1,
overflow: 'auto',
}}
>
> */}
<Spin
spinning={loading}
style={{ marginTop: 30 }}
>
<Form form={form} onValuesChange={onValuesChange}>
{
attributes?.map((attribute, index) => {
return <div key={index}>
<Divider orientation='left'>{attribute}</Divider>
<Descriptions column={1} bordered>
{
(attributes||[]).map((attribute, index) => {
let sameAttributeElements = (elements||[]).filter(element => element.type===attribute);
wholeElements?.length>0 && elements?.map((element, index) => {
if (element.type!==attribute || element.name === '资产项') return null;
if (currentAction!=='add' && !fullScreen && attributesFoldMap[attribute]) {
sameAttributeElements = (sameAttributeElements||[]).filter(element => element.foldAble==='否');
let interpretation = null;
const filterElements = wholeElements?.filter(_element => _element.id === element.id);
if (filterElements.length>0) {
interpretation = filterElements[0].interpretation;
}
return (
<div key={index}>
<div
className='flex pl-common'
style={{
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: '#fff',
height: 46,
borderBottom: '1px solid #f0f0f0',
}}
>
<div
className='flex'
style={{
alignItems: 'center'
}}
>
<div className='primary-bg-color' style={{ width: 3, height: 14, marginRight: 5 }} />
<div className='title-text' style={{ fontWeight: 'bold' }}>{attribute||''}</div>
</div>
<Descriptions.Item
key={index}
label={
<span>
{element.name}
{
currentAction!=='add'&&!fullScreen && (
attributesFoldMap[attribute] ? <Button
type='text'
style={{ padding: 0 }}
onClick={() => { onFoldButtonClick(attribute, false) }}
icon={<DownOutlined className='default' />}
/> : <Button
type='text'
style={{ padding: 0 }}
onClick={() => { onFoldButtonClick(attribute, true) }}
icon={<UpOutlined className='default' />}
/>
)
}
</div>
<div className='px-common py-compact-common'>
{
(currentAction==='add'||currentAction==='edit') ? <Form {...formItemLayout} form={form}>
<AppContext.Consumer>
{
value => {
value?.onGlobalStateChange&&value?.onGlobalStateChange((state, prev) => {
if (state.message === 'data-govern-show-metadata-list-callback-message') {
setMetadataId(state.data?.metadataId||'');
onMetadataChange && onMetadataChange(state.data?.metadataId||'');
form?.setFieldsValue({ '资产项': state.data?.metadataInfoJson||'' });
if ((state.data?.metadataId||'') !== '') {
fillElementValueBeforeCreate(state.data?.metadataId||'');
(currentAction==='add'||currentAction==='edit') && element.required && <span style={{ color: 'red' }}>*</span>
}
</span>
}
});
return (
(sameAttributeElements||[]).map((element, _index) => {
return (
labelStyle={{ width: 180 }}
>
{
(currentAction==='add'||currentAction==='edit') ?
<Row gutter={8} align='middle'>
<Col span={22}>
<Form.Item
label={<div className='title-color'>{element.name||''}</div>}
label=''
name={element.name}
key={_index}
style={{ marginBottom: (_index===sameAttributeElements.length-1)? 0 : 15 }}
rules={[{ required: element.required }]}
style={{ marginBottom: 0 }}
>
{ (element.name==='资产项') ? <MetadataInfo /> : <Input disabled={element.manualMaintain==='否'} /> }
{elementEditComponent(element)}
</Form.Item>
);
})
);
}}
</AppContext.Consumer>
</Form> : <Descriptions column={1}>
</Col>
{
(sameAttributeElements||[]).map((item, index) => {
return (
<Descriptions.Item label={<div className='title-common' style={{ textAlign: 'right', width: 60 }}>{item.name||''}</div>} key={index} style={{ paddingBottom: (index===sameAttributeElements.length-1)? 0 : 10 }}>
{
item.name==='资产项' && <MetadataInfo config={false} value={item.value||''} terms={terms} />
interpretation && <Col span={2}>
<Tooltip placement="left" title={interpretation}>
<QuestionCircleOutlined style={{ fontSize: 16 }} />
</Tooltip>
</Col>
}
</Row>
: <React.Fragment>
<Row gutter={8} align='middle'>
<Col span={22}>
{ elementDetailComponent(element) }
</Col>
{
item.name==='关联标准' && <StandardName value={item.value||''} terms={terms} />
interpretation && <Col span={2}>
<Tooltip placement="left" title={interpretation}>
<QuestionCircleOutlined style={{ fontSize: 16 }} />
</Tooltip>
</Col>
}
{
item.name!=='资产项' && item.name!=='关联标准' && <span className='text-color'>{highlightSearchContentByTerms(item.value||'', terms)}</span>
</Row>
</React.Fragment>
}
</Descriptions.Item>
);
)
})
}
</Descriptions>
</div>
})
}
</Form>
</Spin>
{/* </div> */}
<div>
<Divider orientation='left'>字段级资产目录信息</Divider>
</div>
<Space style={{ marginLeft: 'auto' }}>
{
currentAction!=='add' && (index < (attributes.length-1)) && !readOnly && <Separate height={8} />
(reference===AssetManageReference||canEdit) && <Button
type='primary'
onClick={() => {
if (metadata?.metadataTableId) {
setAttributeMaintainParam({
visible: true,
metadataId: metadata?.metadataTableId
});
} else {
showMessage("warn","该资产目录没有关联元数据信息");
}
</div>
);
}}
>
字段级维护
</Button>
}
<Button type='primary' onClick={() => {
if (metadata?.metadataTableId) {
app?.setGlobalState?.({
message: 'data-govern-show-metadata-relation',
data: { id: metadata?.metadataTableId, type: 'lineage' }
})
} else {
showMessage("warn","该资产目录没有关联元数据信息");
}
</Spin>
</div>
}}>
血缘关系
</Button>
<Button type='primary' onClick={() => {
if (metadata?.metadataTableId) {
app?.setGlobalState?.({
message: 'data-govern-show-metadata-relation',
data: { id: metadata?.metadataTableId, type: 'impact' }
})
} else {
showMessage("warn","该资产目录没有关联元数据信息");
}
}}>
影响关系
</Button>
<Input size="middle"
placeholder="搜索中英文名称/业务规则"
value={keyword}
bordered={true} allowClear
onChange={(e) => {
setPagination({...paginate, pageNum: 1})
setKeyword(e.target.value)
}} />
{/* {
(reference===AssetManageReference||canEdit) && <Button type='primary' onClick={() => {
uploadRef.current?.chooseFile()
}}>导入</Button>
} */}
{/* <Button type='primary' onClick={() => {
uploadRef.current?.chooseFile()
}}>导入</Button>
<Button type='primary' onClick={onExportClick}>导出</Button> */}
</Space>
<Table
className='mt-2'
loading={loadingMetadataColumnList}
columns={permissionId?columns:columns.filter(item => item.dataIndex !== 'permission')}
rowKey='_id'
dataSource={tableData||[]}
pagination={{
position: ['bottomLeft'],
size: 'small',
total: (tableData||[]).length,
showTotal: (total) => `${total}`,
showSizeChanger: true,
current: pageNum,
pageSize,
onChange: (_pageNum, _pageSize) => {
setPagination({ pageNum: _pageNum||1, pageSize: _pageSize || 20 });
},
onShowSizeChange: (_pageNum, _pageSize) => {
setPagination({ pageNum: _pageNum||1, pageSize: _pageSize || 20 });
},
}}
/>
{/* <Upload ref={uploadRef} accept={'.xls,.xlsx'} upload={(files) => {
dispatch({
type: 'assetmanage.importMetadataAttributes',
payload: {
fileList: [files[0]],
params: {
catalog: app?.env?.domainId||LocalStorage.get('assetsEnv'),
}
},
callback: (data) => {
getMetadataAttributes();
},
error: () => {
}
})
}} /> */}
<SelectStandard
visible={selectStandardParam.visible}
id={selectStandardParam.id}
onCancel={onSelectStandardCancel}
/>
<AttributeMaintain
visible={attributeMaintainParam.visible}
metadataId={attributeMaintainParam.metadataId}
onCancel={onAttributeMaintainCancel}
onChange={onAttributeMaintainChange}
/>
<AppContext.Consumer>
{
value => {
......@@ -518,7 +1201,7 @@ const AssetAction = (props) => {
<AssetTagModal
visible={assetTagModalVisible}
id={id}
keyword={keyword}
tag={selectTag}
creator={value?.user?.userName||''}
onCancel={onAssetTagModalCancel}
/>
......@@ -526,8 +1209,52 @@ const AssetAction = (props) => {
}
}
</AppContext.Consumer>
{contextHolder}
</div>
)
}
export default AssetAction;
const MultipleSelect = ({ value = null, element, onChange }) => {
const handleChange = (values) => {
onChange?.(values?.join(','))
}
return (
<Select
allowClear
value={value?value?.split(','):[]}
mode='multiple'
disabled={element.manualMaintain==='否'}
onChange={handleChange}
>
{
element.optional?.split(',').map((value, index) => {
return <Select.Option key={index} value={value}>
{value}
</Select.Option>
})
}
</Select>
)
}
const CascaderItem = ({ value = null, data, onChange, ...restProps }) => {
const handleChange = (values) => {
onChange?.((!values||values.length===0)?'':values[values.length-1]);
}
return (
<Cascader
allowClear
options={data}
value={value?value.split('/'):undefined}
onChange={handleChange}
{...restProps}
/>
)
}
\ No newline at end of file
.asset-action {
.yy-table-tbody > tr > td {
padding: 8px 8px !important;
}
}
\ No newline at end of file
import { useState } from "react";
import { Modal, Radio, Popover } from "antd";
import { QuestionCircleOutlined } from '@ant-design/icons';
const AssetDeleteModal = (props) => {
const { visible, onCancel, onDelete, onDeleteAll } = props;
const [ value, setValue ] = useState(1);
const onChange = (e) => {
setValue(e.target.value);
};
return (
<Modal
title="删除资产目录"
visible={visible}
width={530}
onCancel={
() => {
onCancel && onCancel();
}
}
onOk={
() => {
if (value === 1) {
onDelete && onDelete();
} else {
onDeleteAll && onDeleteAll();
}
}
}
>
<Radio.Group onChange={onChange} value={value}>
<Radio value={1}>
<span>删除本目录下的资产目录</span>
&nbsp;
<Popover content={
<span>
当要删除的资产目录,只存在一个目录时,删除该资产目录并且设置为未分类资产目录;<br/>
存在多个目录时,只删除该目录下的这项资产目录,不会设置为未分类资产目录
</span>
}
>
<QuestionCircleOutlined className='pointer' />
</Popover>
</Radio>
<Radio value={2}>
<span>删除该资产目录(所有目录下的资产目录均删除)</span>
&nbsp;
<Popover content='该资产目录所在的目录内,均删除该项资产目录,并设置为未分类资产目录' >
<QuestionCircleOutlined className='pointer' />
</Popover>
</Radio>
</Radio.Group>
</Modal>
);
}
export default AssetDeleteModal;
\ No newline at end of file
......@@ -4,33 +4,70 @@ import { Spin, Descriptions, Divider } from "antd";
import MetadataInfo from './MetadataInfo';
import { highlightSearchContentByTerms } from '../../../../util';
import { dispatch } from '../../../../model';
import StandardName from './StandardName';
import IndexCode from './IndexCode';
// import SelectUser from '../../Model/Component/SelectUsers';
const AssetDetail = (props)=>{
const { id, dirId, terms } = props;
const { id, dirId, terms, reference = '' } = props;
const [ asset, setAsset ] = useState('');
const [ types, setTypes ] = useState([]);
const [ loading, setLoading ] = useState(false);
const [ users, setUsers ] = useState([]);
useEffect(() => {
if ((id||'') !== '') {
getAssetThenGetAssetName();
// getUserElements();
getUsers();
getAsset([]);
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ id ])
const getAssetThenGetAssetName = () => {
const getUserElements = () => {
setLoading(true);
dispatch({
type: 'assetmanage.listUserElements',
callback: data => {
getAsset(data||[]);
},
error: () => {
setLoading(false);
}
})
}
const getUsers = () => {
dispatch({
type: 'pds.getOwners',
callback: (data) => {
setUsers(data);
}
})
}
const getAsset = (userElements) => {
setLoading(true);
dispatch({
type: 'assetmanage.getDataAssetDetail',
payload: {
dataAssetId: id,
dirId: dirId||''
dirId: dirId||'',
checkPermission: true
},
callback: data => {
setLoading(false);
// const userElementIds = [];
// (userElements||[]).forEach(element => {
// userElementIds.push(element?.id);
// })
// const filterElements = (data?.elements||[]).filter(element => userElementIds.indexOf(element?.id) !== -1);
// data = { ...data, elements: filterElements }
setAsset(data);
const _types = [];
......@@ -48,6 +85,26 @@ const AssetDetail = (props)=>{
})
}
const elementItemComponent = (item) => {
if (item.name === '资产项') {
return <MetadataInfo config={false} value={item.value||''} terms={terms} />;
}
if (item.name === '指标标准编码') {
return <IndexCode value={item.value||''} terms={terms} />;
}
// if (item.name==='数据关键用户' || item.name==='业务部门负责人' || item.name?.toLowerCase()==='it责任人' || item.name==='创建人' || item.name==='更新人') {
// return <SelectUser
// type='detail'
// users={users}
// value={item.value||''}
// />
// }
return <span className='text-color'>{highlightSearchContentByTerms(item.value||'', terms)}</span>;
}
return(
<Spin spinning={loading}>
{
......@@ -67,7 +124,7 @@ const AssetDetail = (props)=>{
return (
<div key={index}>
<div className='flex' style={{ alignItems: 'center', padding: '15px 0' }}>
<div className='flex' style={{ alignItems: 'center', padding: (reference==='full-search'&&index===0)?'0 0 15px':'15px 0' }}>
<div style={{ width: 3, height: 14, backgroundColor: '#0069AC', marginRight: 5 }} />
<span style={{ fontWeight: 'bold', color: '#464646' }}>{type||''}</span>
</div>
......@@ -77,15 +134,7 @@ const AssetDetail = (props)=>{
(_currentValues||[]).map((item, index) => {
return (
<Descriptions.Item label={item.name||''} key={index}>
{
item.name==='资产项' && <MetadataInfo config={false} value={item.value||''} terms={terms} />
}
{
item.name==='关联标准' && <StandardName value={item.value||''} terms={terms} />
}
{
item.name!=='资产项' && item.name!=='关联标准' && <span className='text-color'>{highlightSearchContentByTerms(item.value||'', terms)}</span>
}
{ elementItemComponent(item) }
</Descriptions.Item>
);
})
......
......@@ -4,24 +4,26 @@ import { Drawer, Form } from 'antd';
import AssetAction from './AssetAction';
const AssetDetailDrawer = (props) => {
const { onCancel, visible, id, dirId } = props;
const { onCancel, visible, id, dirId, reference } = props;
const [ form ] = Form.useForm();
return (
<Drawer
forceRender
visible={ visible }
title='资产详情'
width={600}
title='资产目录详情'
width='80%'
placement="right"
closable={ true }
destroyOnClose
onClose={() => {
onCancel && onCancel();
}}
>
{
visible && <AssetAction form={form} id={id} dirId={dirId} action='detail' readOnly />
visible && <AssetAction reference={reference} form={form} id={id} dirId={dirId} action='detail' onChange={() => {
onCancel?.(true);
}} />
}
</Drawer>
)
......
import React, { useEffect, useState } from "react";
import LocalStorage from 'local-storage';
import { Spin } from "antd";
import AssetDetail from './AssetDetail';
import AssetAction from "./AssetAction";
import { getQueryParam } from '../../../../util';
import { dispatch } from '../../../../model';
import './AssetDetailPage.less';
import { getDataAssetDetail } from "../../../../service/dataassetmanager";
import { appId } from "../../../../App";
const AssetDetailPage = (props)=>{
const [ data, setData ] = useState({ id: '', dirId: '' });
const [loading, setLoading] = useState(false)
const [templateType, setTemplateType] = useState()
const { id, dirId } = data;
useEffect(() => {
......@@ -16,20 +22,48 @@ const AssetDetailPage = (props)=>{
const _id = getQueryParam('id', props.location.search);
const _dirId = getQueryParam('dirId', props.location.search);
setData({ id: _id, dirId: _dirId });
getDataAssetDetail()
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
const getDataAssetDetail = () => {
const _id = getQueryParam('id', props.location.search);
const _dirId = getQueryParam('dirId', props.location.search);
dispatch({
type: 'assetmanage.getDataAssetDetail',
payload: {
dataAssetId: _id,
dirId: _dirId||'',
checkPermission: true
},
callback: data => {
setLoading(false);
LocalStorage.set(`templateType-${appId}`, data?.templateType)
setTemplateType(data?.templateType)
},
error: () => {
setLoading(false);
}
})
}
return(
<div className='asset-detail position-relative'>
<div className='detail-header'>
<span style={{ fontSize: 16, fontWeight: 'bold', color: '#fff' }}>资产详情</span>
<span style={{ fontSize: 16, fontWeight: 'bold', color: '#000' }}>资产目录详情</span>
</div>
<Spin spinning={loading}>
<div className='detail-container'>
<div className='detail-container-card'>
<AssetDetail id={id} dirId={dirId} />
{
templateType && <AssetAction id={id} dirId={dirId} action='detail' />
}
</div>
</div>
</Spin>
</div>
)
}
......
......@@ -4,7 +4,7 @@
width: 100%;
height: 44px;
padding: 0 15px;
background-color: #464d6e;
background-color: white;
align-items: center;
position: fixed;
justify-content: space-between;
......
import React, { useEffect, useState } from 'react';
import { Spin, Tooltip, Typography, Dropdown, Menu } from 'antd';
import LocalStorage from 'local-storage';
import { dispatch } from '../../../../model';
import { AssetManageReference, ResourceBrowseReference } from '../../../../util/constant';
import { AssetBrowseReference, AssetManageReference, ResourceBrowseReference } from '../../../../util/constant';
import ImportElement from './ImportElement';
import ExportElement from './ExportElement';
import AttributeRelationModal from "./AttributeRelationModal";
import FilterElementModal from './FilterElementModal';
import { showNotifaction } from '../../../../util';
......@@ -14,15 +12,15 @@ import Separate from './Separate';
import record from '../Assets/record.png';
import './AssetDirectory.less';
import { getTemplateType } from '../../../../util/axios';
const { Paragraph, Text } = Typography;
const AssetDirectory = (props) => {
const { id, directoryChanged, assetCount, reference = AssetManageReference, onElementsChange } = props;
const { id, directoryChanged, assetCount, reference = AssetManageReference, onElementsChange, nodeType } = props;
const [ dir, setDir ] = useState(null);
const [ loading, setLoading ] = useState(false);
const [ importElementVisible, setImportElementVisible ] = useState(false);
const [ exportElementVisible, setExportElementVisible ] = useState(false);
const [ attributeRelationModalVisible, setAttributeRelationModalVisible ] = useState(false);
const [ filterElementVisible, setFilterElementVisible ] = useState(false);
const [ resourceState, setResourceState ] = useState(null);
......@@ -47,14 +45,21 @@ const AssetDirectory = (props) => {
useEffect(() => {
if ((id||'')!=='') {
getDirectory();
} else {
setDir()
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ id, directoryChanged ])
const getDirectory = () => {
let url = 'assetmanage.getDirectoryById';
if ((reference===AssetBrowseReference|| reference===ResourceBrowseReference) && nodeType==='custom') {
url = 'assetmanage.getPersonalCustomDirectoryById';
}
setLoading(true);
dispatch({
type: 'assetmanage.getDirectoryById',
type: url,
payload: {
dirId: id
},
......@@ -93,7 +98,7 @@ const AssetDirectory = (props) => {
}
const onExportElementBtnClick = () => {
setExportElementVisible(true);
window.open(`/api/dataassetmanager/elementApi/export?templateType=${getTemplateType()}`);
}
const onFilterElementClick = () => {
......@@ -116,10 +121,6 @@ const AssetDirectory = (props) => {
}
}
const onExportElementCancel = () => {
setExportElementVisible(false);
}
const onFilterElementModalCancel = () => {
setFilterElementVisible(false);
}
......@@ -132,22 +133,22 @@ const AssetDirectory = (props) => {
<Menu>
<Menu.Item>
<div className='text-center' onClick={onImportElementBtnClick}>
导入资产属性
导入资产目录属性
</div>
</Menu.Item>
<Menu.Item>
<div className='text-center' onClick={onExportElementBtnClick}>
导出资产属性
导出资产目录属性
</div>
</Menu.Item>
<Menu.Item>
<div className='text-center' onClick={onFilterElementClick}>
资产属性管理
资产目录浏览管理
</div>
</Menu.Item>
<Menu.Item>
<div className='text-center' onClick={onAttributeRelationBtnClick}>
资产属性关联
资产目录属性关联
</div>
</Menu.Item>
</Menu>
......@@ -185,7 +186,7 @@ const AssetDirectory = (props) => {
</Tooltip>
</Paragraph>
</div>
<div className={(reference===AssetManageReference || reference===ResourceBrowseReference)?'mb-common':''}>
<div className={(reference===AssetManageReference)?'mb-common':''}>
<Paragraph>
<Tooltip title={dir?.desc||''}>
<Text className='title-color' ellipsis={true}>
......@@ -196,9 +197,7 @@ const AssetDirectory = (props) => {
</Paragraph>
</div>
{
(reference===AssetManageReference || reference===ResourceBrowseReference) && <div className='flex'>
{
(reference === AssetManageReference) && <React.Fragment>
(reference===AssetManageReference) && <div className='flex'>
<Paragraph style={{ flex: 1, overflow: 'hidden' }}>
<Tooltip title={dir?.remarks||''}>
<Text className='title-color' ellipsis={true}>
......@@ -208,10 +207,8 @@ const AssetDirectory = (props) => {
</Tooltip>
</Paragraph>
<Separate width={10} background='#fff' />
</React.Fragment>
}
{
(reference===ResourceBrowseReference || resourceState) && <React.Fragment>
{/* {
resourceState && <React.Fragment>
<Paragraph style={{ flex: 1, overflow: 'hidden' }}>
<Tooltip title={resourceState?.relatedAsset}>
<Text className='title-color' ellipsis={true}>
......@@ -239,7 +236,7 @@ const AssetDirectory = (props) => {
</Tooltip>
</Paragraph>
</React.Fragment>
}
} */}
</div>
}
</div>
......@@ -266,7 +263,7 @@ const AssetDirectory = (props) => {
</div>
</div>
{
{/* {
(reference===AssetManageReference) && <Dropdown overlay={elementManageMenu} placement="bottomCenter">
<div
className='flex more-container'
......@@ -281,7 +278,7 @@ const AssetDirectory = (props) => {
<span style={{ fontSize: 10 }}>更多</span>
</div>
</Dropdown>
}
} */}
</div>
......@@ -290,11 +287,6 @@ const AssetDirectory = (props) => {
onCancel={onImportElementCancel}
/>
<ExportElement
visible={exportElementVisible}
onCancel={onExportElementCancel}
/>
<FilterElementModal
visible={ filterElementVisible }
onCancel={ onFilterElementModalCancel}
......
......@@ -2,20 +2,20 @@
.asset-directory {
// .more-container {
// cursor: pointer;
// color: @icon-normal-color;
.more-container {
cursor: pointer;
color: @icon-normal-color;
// .icon {
// fill: @icon-normal-color !important;
// }
.icon {
fill: @icon-normal-color !important;
}
// &:hover {
// color: @icon-hover-color;
&:hover {
color: @icon-hover-color;
// .icon {
// fill: @icon-hover-color !important;
// }
// }
// }
.icon {
fill: @icon-hover-color !important;
}
}
}
}
\ No newline at end of file
import React, { useEffect, useState, useRef } from 'react';
import {Card, Spin, Tooltip, Tree, Dropdown, Menu, Modal, AutoComplete, Select} from 'antd';
import { PlusOutlined, ImportOutlined,ExportOutlined,ReloadOutlined, SettingOutlined } from '@ant-design/icons';
import classNames from 'classnames';
import { useContextMenu, Menu as RcMenu, Item as RcItem } from "react-contexify";
import LocalStorage from 'local-storage';
import { dispatch } from '../../../../model';
import ImportDirectory from './ImportDirectory';
import UpdateDirectoryModal from './UpdateDirectoryModal';
import CustomDirectoryModal from './CustomDirectoryModal';
import { showMessage, getQueryParam } from '../../../../util';
import { AnchorTimestamp, AnchorId, AssetManageReference, AssetBrowseReference, ResourceBrowseReference, AssetMountReference, AnchorDirId } from '../../../../util/constant';
import { highlightSearchContentByTerms } from '../../../../util';
import './AssetManageTree.less';
import 'react-contexify/dist/ReactContexify.css';
import { appId } from '../../../../App';
import { getTemplateType } from '../../../../util/axios';
const { Option } = AutoComplete;
function updateTreeData(list, key, children) {
return list.map((node) => {
if (node.nodeId === key) {
return { ...node, children };
}
if (node.children) {
return {
...node,
children: updateTreeData(node.children, key, children),
};
}
return node;
});
}
const AssetManageTree = (props) => {
const MENU_ID = 'asset-manage-tree';
const { show } = useContextMenu({
id: MENU_ID,
});
const { checkable = false, onSelect, className, onCheck, tableId, reference=AssetManageReference, onDirectoryChange, centerId, metadataIds } = props;
const [ keyword, setKeyword ] = useState('');
const [ loading, setLoading ] = useState(false);
const [ treeData, setTreeData ] = useState([]);
const [ dataList, setDataList ] = useState([]);
const [ groupIds, setGroupIds ] = useState([]);
const [ expandedKeys, setExpandedKeys ] = useState([]);
const [ checkedKeys, setCheckedKeys ] = useState([]);
const [ autoExpandParent, setAutoExpandParent ] = useState(false);
const [ currentDirId, setCurrentDirId ] = useState('');
const [ currentDirType, setCurrentDirType ] = useState('');
const [ currentDir, setCurrentDir ] = useState({});
const [ currentRightClickDir, setCurrentRightClickDir ] = useState({});
const [ importDirectoryVisible, setImportDirectoryVisible ] = useState(false);
const [ updateDirectoryModalVisible, setUpdateDirectoryModalVisible ] = useState(false);
const [ updateDirectoryAction, setUpdateDirectoryAction ] = useState('');
const [ customDirectoryModalVisible, setCustomDirectoryModalVisible ] = useState(false);
const [ customDirectoryAction, setCustomDirectoryAction ] = useState('');
const [options, setOptions] = useState([]);
const [ loadedKeys, setLoadedKeys ] = useState([]);
const [loadingTemplates, setLoadingTemplates] = useState(false)
const [templates, setTemplates] = useState()
const [currentTemplateType, setTemplateType] = useState()
const [modal, contextHolder] = Modal.useModal();
const timestamp = getQueryParam(AnchorTimestamp, props?.location?.search);
const id = getQueryParam(AnchorId, props?.location?.search);
const did = getQueryParam(AnchorDirId, props?.location?.search);
const treeDataRef = useRef([]);
const dataListRef = useRef([]);
useEffect(() => {
if (reference === AssetManageReference) {
getTemplates()
} else {
getAllDirectoryAsTree(false)
}
window?.addEventListener("storage", storageChange);
return () => {
window?.removeEventListener("storage", storageChange);
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [metadataIds])
// useEffect(() => {
// if ((did||'') !== '') {
// getAllDirectoryAsTree(true, did);
// } else if ((id||'') !== '') {
// getDataAssetLocationThenGetTreeData();
// } else {
// getAllDirectoryAsTree(true);
// }
// //eslint-disable-next-line react-hooks/exhaustive-deps
// }, [timestamp])
useEffect(() => {
if ((tableId||'') !== '') {
getTableDirIds();
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [tableId])
useEffect(() => {
if ((centerId||'')!=='' && centerId!==currentDirId) {
treeDirectoryChanged(centerId);
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [centerId])
const storageChange = (e) => {
if (e.key === 'assetDirChangeEvent' || e.key === 'assetPathOnClickEvent') {
if ((e.dirId||'') !== '') {
treeDirectoryChanged(e.dirId);
}
} else if (e.key === 'assetRelationOnClickEvent') {
treeDirectoryChanged(e.relation?.dirId);
}
}
const getTemplates = () => {
setLoadingTemplates(true)
dispatch({
type: 'assetmanage.getTemplates',
callback: data => {
setLoadingTemplates(false)
setTemplates(data)
if ((data??[]).length > 0) {
setTemplateType(data[0].type)
LocalStorage.set(`templateType-${appId}`, data[0].type)
onSelect?.('', '')
getAllDirectoryAsTree(false)
}
},
error: () => {
setLoadingTemplates(false)
}
})
}
const getDataAssetLocationThenGetTreeData = () => {
setLoading(true);
dispatch({
type: 'assetmanage.getDataAssetLocation',
payload: {
dataAssetId: id
},
callback: data => {
getAllDirectoryAsTree(true, data.dirId||'');
},
error: () => {
setLoading(false);
getAllDirectoryAsTree(true);
}
});
}
const getTableDirIds = () => {
dispatch({
type: 'assetmanage.getDataAssetDetail',
payload: {
dataAssetId: tableId
},
callback: data => {
setCheckedKeys(data.dirIds||[]);
setExpandedKeys(data.dirIds||[]);
setAutoExpandParent(true);
onCheck && onCheck(data.dirIds||[]);
},
})
}
const getAllDirectoryAsTree = (resetCurrentDirId=true, defaultSelectedId='', refresh = false) => {
setLoading(true);
// if (resetCurrentDirId) {
// onSelect && onSelect('', '');
// }
function disposeData(data) {
setLoading(false);
refresh && showMessage('success', '操作成功');
let newData = [...data];
if (reference === AssetMountReference) {
newData = newData.filter(item => item.resourceType!=='custom');
}
setLoadedKeys([]);
setTreeData(newData);
const _dataList = [], _groupIds = [];
generateList(newData, _dataList);
generateGroupIds(newData, _groupIds);
setDataList(_dataList);
setGroupIds(_groupIds);
treeDataRef.current = newData;
dataListRef.current = _dataList;
let defaultItem = null;
if ((defaultSelectedId||'') === '') {
_dataList.forEach(item => {
if ((defaultSelectedId||'')==='') {
defaultSelectedId = item.key;
}
})
}
function recursion(subCatalogs) {
if ((subCatalogs||[]).length===0) return;
(subCatalogs||[]).forEach(catalog=> {
if (catalog.nodeId === defaultSelectedId) {
defaultItem = catalog;
}
recursion(catalog.children);
})
}
if ((defaultSelectedId||'') !== '') {
recursion(newData);
}
if (resetCurrentDirId) {
if (defaultItem) {
const expandedKeys = _dataList
.map(item => {
if (item.key.indexOf(defaultSelectedId) > -1) {
return getParentKey(item.key, newData);
}
return null;
})
.filter((item, i, self) => item && self.indexOf(item) === i);
setExpandedKeys([...expandedKeys, defaultSelectedId]);
setAutoExpandParent(true);
setCurrentDirId(defaultItem.nodeId);
setCurrentDirType(defaultItem.type||'');
setCurrentDir(defaultItem);
onSelect && onSelect(defaultItem.nodeId, defaultItem.type||'', defaultItem.level);
}
}
}
if ((metadataIds??[]).length > 0) {
dispatch({
type: 'assetmanage.queryDirectoryTreeByMetadataId',
payload: {
metadataIdPath: metadataIds[0]
},
callback: data => {
disposeData(data)
},
error: () => {
setLoading(false);
}
});
} else {
let url = '';
if (reference === AssetManageReference || reference === AssetMountReference) {
url = 'assetmanage.queryAllDirectoryAsTree';
}
dispatch({
type: url,
callback: data => {
disposeData(data)
},
error: () => {
setLoading(false);
}
});
}
}
const treeDirectoryChanged = (did) => {
let defaultItem = null;
function recursion(subCatalogs) {
if ((subCatalogs||[]).length===0) return;
(subCatalogs||[]).forEach(catalog=> {
if (catalog.nodeId === did) {
defaultItem = catalog;
}
recursion(catalog.children);
})
}
if ((did||'') !== '') {
recursion(treeDataRef.current);
}
if (defaultItem) {
const expandedKeys = (dataListRef.current||[])
.map(item => {
if (item.key.indexOf(did) > -1) {
return getParentKey(item.key, treeDataRef.current);
}
return null;
})
.filter((item, i, self) => item && self.indexOf(item) === i);
setExpandedKeys([...expandedKeys, did]);
setAutoExpandParent(true);
setCurrentDirId(defaultItem.nodeId);
setCurrentDirType(defaultItem.type||'');
setCurrentDir(defaultItem)
onSelect && onSelect(defaultItem.nodeId, defaultItem.type||'', defaultItem.level);
}
}
const generateList = (treeData, list, path = null) => {
for (let i = 0; i < treeData.length; i++) {
if (treeData[i].resourceType !== 'custom') {
const node = treeData[i];
const { nodeId, text } = node;
const currentPath = path ? `${path}/${text}` : text;
list.push({ key: nodeId , title: text, value: currentPath, level: node.level });
if (node.children) {
generateList(node.children, list, currentPath);
}
}
}
};
const generateGroupIds = (treeData, list) => {
function generateGroupItem(data, list) {
for (let i = 0; i < data.length; i++) {
const node = data[i];
list.push(node.nodeId);
if (node.children) {
generateGroupItem(node.children, list);
}
}
}
for (let i = 0; i < treeData.length; i++) {
const channelTreeData = treeData[i];
if (channelTreeData.children) {
for (let j =0; j < channelTreeData.children.length; j++) {
const node = channelTreeData.children[j];
const { nodeId } = node;
const groupItem = [nodeId];
if (node.children) {
generateGroupItem(node.children, groupItem);
}
list.push(groupItem);
}
}
}
};
const getParentKey = (key, tree) => {
let parentKey;
for (let i = 0; i < tree.length; i++) {
const node = tree[i];
if (node.children) {
if (node.children.some(item => item.nodeId === key)) {
parentKey = node.nodeId;
} else if (getParentKey(key, node.children)) {
parentKey = getParentKey(key, node.children);
}
}
}
return parentKey;
};
const getCurrentType = (key, tree) => {
let type = '';
(tree||[]).forEach(node => {
if (node.nodeId === key) {
type = node.type||'';
} else if (node.children) {
if (getCurrentType(key, node.children)) {
type = getCurrentType(key, node.children);
}
}
})
return type;
}
const getCurrentDir = (key, tree) => {
let dir = undefined;
(tree||[]).forEach(node => {
if (node.nodeId === key) {
dir = node
} else if (node.children) {
if (getCurrentDir(key, node.children)) {
dir = getCurrentDir(key, node.children);
}
}
})
return dir;
}
const addDir = () => {
if (currentDir?.resourceType==='custom') return;
setUpdateDirectoryAction('add');
setUpdateDirectoryModalVisible(true);
}
const editDir = () => {
if ((currentDirType||'') === '') {
setUpdateDirectoryAction('edit');
setUpdateDirectoryModalVisible(true);
} else if (currentDirType === 'custom') {
setCustomDirectoryAction('edit');
setCustomDirectoryModalVisible(true);
}
}
const refreshTree = () => {
getAllDirectoryAsTree(false, '', true);
}
const importDir = () => {
if (currentDirType==='custom') return;
setImportDirectoryVisible(true);
}
const exportAllDir = () => {
window.open(`/api/dataassetmanager/directoryApi/export?templateType=${getTemplateType()}`);
}
const exportCurrentDir = () => {
if(currentDirId){
dispatch({
type: 'assetmanage.getDirectoryById',
payload: {
dirId: currentDirId
},
callback: data => {
window.open(`/api/dataassetmanager/directoryApi/export?parentPath=${data.path}&templateType=${getTemplateType()}`);
}
})
} else {
showMessage("warn","请选择目录")
}
}
const deleteDir = () => {
if (currentRightClickDir.nodeId) {
modal.confirm({
title: '您确定要删除该目录吗?',
onOk: () => {
dispatch({
type: 'assetmanage.checkDirectoryDeleteAble',
payload: {
params: {
dirId: currentRightClickDir.nodeId
}
},
callback: able => {
if (able === 'true') {
dispatch({
type: 'assetmanage.deleteDirectory',
payload: {data: [ currentRightClickDir.nodeId ]},
callback: () => {
showMessage("success","删除成功");
getAllDirectoryAsTree(true, (currentRightClickDir.nodeId===currentDirId)?'':currentDirId);
}
})
} else {
showMessage("warn","目录下有资产目录信息,不允许删除!");
}
}
})
}
})
} else {
showMessage('info', '请先选择目录');
}
}
const moveNode = (steps) => {
if ((currentRightClickDir.nodeId||'') === '') {
showMessage('info', '请先选择目录');
return;
}
setLoading(true);
dispatch({
type: 'assetmanage.upDownDirectory',
payload: {
params: {
dirId: currentRightClickDir.nodeId,
steps
}
},
callback: () => {
showMessage('success', (steps===1)?'上移目录成功':'下移目录成功');
getAllDirectoryAsTree(false);
},
error: () => {
setLoading(false);
}
});
}
const customDir = () => {
setCustomDirectoryAction('add');
setCustomDirectoryModalVisible(true);
}
// const onChange = (e) => {
// const { value } = e.target;
// if (value === '') {
// setExpandedKeys([]);
// setAutoExpandParent(false);
// setKeyword(value);
// return;
// }
// const expandedKeys = dataList
// .map(item => {
// if (item.title.indexOf(value) > -1) {
// return getParentKey(item.key, treeData);
// }
// return null;
// })
// .filter((item, i, self) => item && self.indexOf(item) === i);
// setExpandedKeys(expandedKeys);
// setAutoExpandParent(true);
// setKeyword(value);
// }
const onTreeSelect = (keys, { node }) => {
if ((keys||[]).length === 0) {
setCurrentDirId();
onSelect?.('', '');
return;
}
setCurrentDirId(keys[0]);
const _currentDirType = getCurrentType(keys[0], treeData);
const _currentDir = getCurrentDir(keys[0], treeData);
setCurrentDirType(_currentDirType);
setCurrentDir(_currentDir);
onSelect && onSelect(keys[0], _currentDirType, node.level);
}
const onTreeCheck = (values, e) => {
//同一主题下只能挂载一个目录
if (e.node?.level === 1) {
showMessage('warn', '栏目不允许勾选');
return;
}
// const _checkedKeysValue = [...(values.checked||[])];
if (e.checked) {
// const _currentNodeId = e.node?.key;
// let _groupItem = [];
// groupIds.forEach(groupItem => {
// groupItem.forEach(id => {
// if (id === _currentNodeId) {
// _groupItem = groupItem;
// }
// })
// })
// const _filterKeys = (_checkedKeysValue.filter(item => item===_currentNodeId || !(_groupItem.includes(item))));
setCheckedKeys([e.node?.key]);
onCheck && onCheck([e.node?.key]);
} else {
setCheckedKeys([]);
onCheck && onCheck([]);
}
}
const onExpand = (expandedKeys) => {
setExpandedKeys(expandedKeys);
setAutoExpandParent(false);
};
const onUpdateDirectoryCancel = (refresh=false, id) => {
setUpdateDirectoryModalVisible(false);
if (refresh) {
if (updateDirectoryAction === 'add') {
getAllDirectoryAsTree(true, id);
} else {
getAllDirectoryAsTree();
onDirectoryChange && onDirectoryChange();
}
}
}
const onImportDirectoryCancel = (refresh=false, resetCurrentDirId=false) => {
setImportDirectoryVisible(false);
refresh && getAllDirectoryAsTree(resetCurrentDirId);
}
const onCustomDirectoryCancel = (refresh=false, id='') => {
setCustomDirectoryModalVisible(false);
if (refresh) {
if (customDirectoryAction === 'add') {
getAllDirectoryAsTree(true, id);
} else {
getAllDirectoryAsTree(false);
}
}
}
const displayMenu = (e) => {
show({
event: e,
position: {
x: e.clientX + 30,
y: e.clientY - 10
}
});
}
const onAutoCompleteSearch = (searchText) => {
setKeyword(searchText);
setOptions(
!searchText ? [] : (dataList||[]).filter(item => item.value.indexOf(searchText)!==-1),
);
};
const onAutoCompleteSelect = (value, option) => {
const paths = value.split('/');
setKeyword(paths[paths.length-1]);
treeDirectoryChanged(option.key);
};
const onLoadData = ({ key, children }) =>
new Promise((resolve) => {
if (children) {
resolve();
return;
}
setLoadedKeys([...loadedKeys, key]);
dispatch({
type: 'assetmanage.getDirectoryChild',
payload: {
parentId: key,
},
callback: (data) => {
if (data && data.length>0) {
let newTreeData = updateTreeData(treeData, key, data);
setTreeData(newTreeData);
treeDataRef.current = newTreeData;
}
resolve();
},
error: () => {
resolve();
}
});
});
const exportMenu = (
<Menu>
<Menu.Item>
<div style={{ textAlign: 'center' }} onClick={() => exportAllDir()}>
导出所有
</div>
</Menu.Item>
<Menu.Item>
<div style={{ textAlign: 'center' }} onClick={() => exportCurrentDir()}>
导出选中目录
</div>
</Menu.Item>
</Menu>
);
const loop = (data, rootResourceType = null) =>
data.map(item => {
if (item.level === 1) {
rootResourceType = item.resourceType;
}
const title = (
<span
className={(item.level===1)?'title-color': 'text-color'}
>
{item.text}
{
//自定义类型栏目不统计资产数
(item.level!==1||(item.level===1&&item.resourceType!=='custom')) && <span>{` (${item.dataAssetAndSubDirCount})`}</span>
}
</span>
);
if (item.children && item.children.length>0) {
return { ...item, ...{title, key: item.nodeId, disableCheckbox: (item.level!==3), children: loop(item.children, rootResourceType), className: (item.level===1)?'root':''} };
}
if (rootResourceType !== 'custom') {
return { ...item, ...{ title, key: item.nodeId, disableCheckbox: (item.level!==3), isLeaf: true, className: (item.level===1)?'root':'' }};
}
return { ...item, ...{ title, key: item.nodeId, disableCheckbox: (item.level!==3), children: null, className: (item.level===1)?'root':''}};
});
const classes = classNames('asset-manage-tree', className, {
'asset-manage-tree-read-only': (reference===AssetBrowseReference||reference===ResourceBrowseReference),
'asset-manage-tree-asset-mount-reference': reference===AssetMountReference,
});
return (
<Card
className={classes}
title={ (reference===AssetBrowseReference||reference===ResourceBrowseReference || reference===AssetMountReference) ? null : (
<div
className='flex'
style={{
height: 57,
alignItems: 'center',
justifyContent: 'space-between',
padding: '0 15px'
}}
>
<Select
loading={loadingTemplates}
size='small'
value={currentTemplateType}
onChange={(val) => {
setTemplateType(val)
LocalStorage.set(`templateType-${appId}`, val);
setCurrentDirId();
onSelect?.(null, null);
setTimeout(() => {
onSelect?.('', '');
getAllDirectoryAsTree(false)
}, 100)
}}
style={{ width: 65 }}
>
{
(templates??[]).map((item, index) => <Select.Option key={index} value={item.type}>{item.name}</Select.Option>)
}
</Select>
<Tooltip title="新增目录">
<PlusOutlined className={(currentDir?.resourceType==='custom')?'disable': 'default'} onClick={addDir} style={{ fontSize:16,cursor: (currentDirType==='custom')?'not-allowed':'pointer' }}/>
</Tooltip>
<Tooltip title="刷新目录">
<ReloadOutlined className='default' onClick={refreshTree} style={{ fontSize:16,cursor:'pointer' }} />
</Tooltip>
<Tooltip title="导入目录">
<ImportOutlined className={(currentDirType==='custom')?'disable': 'default'} onClick={importDir} style={{ fontSize:16,cursor:(currentDirType==='custom')?'not-allowed':'pointer' }} />
</Tooltip>
<Dropdown overlay={exportMenu} placement="bottomCenter" >
<Tooltip title="导出目录">
<ExportOutlined className='default' style={{ fontSize:16,cursor:'pointer' }} />
</Tooltip>
</Dropdown>
{/* <Tooltip title="自定义目录">
<SettingOutlined className='default' onClick={customDir} style={{ fontSize:16,cursor:'pointer' }} />
</Tooltip> */}
</div>
)}
bordered={false}
bodyStyle={{ padding: '10px 15px' }}
headStyle={{ padding: 0 }}
style={{ width: '100%' }}
>
<Spin spinning={loading}>
<AutoComplete
allowClear
value={keyword}
style={{ marginBottom: 10, width: '100%' }}
placeholder='搜索目录'
onSelect={onAutoCompleteSelect}
onSearch={onAutoCompleteSearch}
onClear={() => { setKeyword(''); }}
notFoundContent={keyword?<span>暂无数据</span>:null}
>
{
(options||[]).map((item, index) => {
return (
<Option key={item.key} value={item.value}>
<div style={{ whiteSpace: 'normal' }}>
{highlightSearchContentByTerms(item.value, [keyword])}
</div>
</Option>
);
})
}
</AutoComplete>
<Tree
className='tree-contextmenu'
checkable={checkable}
showLine={true}
showIcon={false}
onExpand={onExpand}
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
treeData={loop(treeData)}
loadData={onLoadData}
loadedKeys={loadedKeys}
selectedKeys={[currentDirId||'']}
onSelect={onTreeSelect}
onCheck={onTreeCheck}
checkedKeys={checkedKeys}
checkStrictly
onRightClick={({event, node}) => {
if (reference === AssetManageReference) {
setCurrentRightClickDir(node);
setCurrentDirType(node.type||'');
displayMenu(event);
}
}}
/>
</Spin>
<UpdateDirectoryModal
visible={ updateDirectoryModalVisible }
onCancel={ onUpdateDirectoryCancel }
action={ updateDirectoryAction }
dirId={ (updateDirectoryAction==='add')?currentDirId:currentRightClickDir.nodeId }
/>
<ImportDirectory
visible={ importDirectoryVisible }
onCancel={ onImportDirectoryCancel }
dirId={ currentDirId }
/>
<CustomDirectoryModal
visible={ customDirectoryModalVisible }
onCancel={ onCustomDirectoryCancel }
action={ customDirectoryAction }
dirId= { currentDirId }
/>
{
(reference!==AssetMountReference) && <RcMenu id={MENU_ID}>
{
currentRightClickDir && (currentRightClickDir.type!=='custom') && <RcItem id="edit" onClick={editDir}>
{ (currentRightClickDir.level===1)?'修改栏目':'修改目录' }
</RcItem>
}
<RcItem id="up" onClick={() => { moveNode(1); }}>
{ (currentRightClickDir.level===1)?'上移栏目':'上移目录' }
</RcItem>
<RcItem id="down" onClick={() => { moveNode(-1); }}>
{ (currentRightClickDir.level===1)?'下移栏目':'下移目录' }
</RcItem>
{
currentRightClickDir && (currentRightClickDir.type!=='custom'||(currentRightClickDir.type==='custom'&&currentRightClickDir.level===2)) && <RcItem id="delete" onClick={deleteDir}>
{ (currentRightClickDir.level===1)?'删除栏目':'删除目录' }
</RcItem>
}
</RcMenu>
}
{contextHolder}
</Card>
)
}
export default AssetManageTree;
\ No newline at end of file
@import '../../../../variables.less';
.asset-manage-tree {
.yy-card-head-title {
padding: 0;
}
.yy-tree{
height: calc(100vh - @header-height - @breadcrumb-height - 25px - 57px - 62px) !important;
overflow: auto !important;
}
// .root {
// display: flex;
// position: relative;
// width: 100%;
// background-color: #e7f2ff;
// margin-bottom: 3px;
// padding: 5px;
// align-items: center;
// .yy-tree-switcher {
// display: block;
// position: absolute;
// opacity: 0 !important;
// left: 0;
// top: 0;
// width: 100%;
// height: 100%;
// }
// .yy-tree-node-content-wrapper {
// margin-left: 20px;
// }
// }
// .yy-tree-indent .yy-tree-indent-unit:first-child {
// opacity: 0 !important;
// }
.site-tree-search-value {
color: #f50;
}
}
.asset-manage-tree-read-only {
.yy-tree {
height: calc(100vh - @header-height - @breadcrumb-height - 25px - 62px) !important;;
overflow: auto !important;
}
}
.asset-manage-tree-asset-mount-reference {
.yy-tree {
height: 400px !important;
overflow: auto !important;
}
}
\ No newline at end of file
import React,{ useState, useEffect, useRef, useContext } from "react";
import { Button, Pagination, Space, Modal, Input, Table, Tooltip, Checkbox, Typography, Dropdown, Menu } from "antd";
import React,{ useState, useEffect, useRef, useContext, useMemo } from "react";
import { Button, Pagination, Space, Modal, Input, Table, Tooltip, Checkbox, Typography, Dropdown, Menu, Divider, Select } from "antd";
import classNames from 'classnames';
import SmoothScroll from 'smooth-scroll';
import { Resizable } from 'react-resizable';
import ResizeObserver from 'rc-resize-observer';
import { useContextMenu, Menu as RcMenu, Item as RcItem } from "react-contexify";
......@@ -13,22 +12,24 @@ import ImportAssetDrawer from './ImportAssetDrawer';
import AssetEdit from './AddAssetModel';
import AssetDetailDrawer from "./AssetDetailDrawer";
import { dispatch, dispatchLatestHomepage } from '../../../../model';
import { showMessage, showNotifaction, getQueryParam, inputWidth, isSzseEnv, highlightSearchContentByTerms } from '../../../../util';
import { AnchorId, AnchorTimestamp, AssetBrowseReference, AssetManageReference, AssetRecycleReference, ResourceBrowseReference } from '../../../../util/constant';
import { showMessage, showNotifaction, getQueryParam, inputWidth, isSzseEnv } from '../../../../util';
import { AnchorId, AnchorDirId, AnchorTimestamp, AssetBrowseReference, AssetManageReference, AssetRecycleReference, ResourceBrowseReference } from '../../../../util/constant';
import { FullScreenSvg, CancelFullScreenSvg } from './AssetSvg';
import { AppContext } from "../../../../App";
import WorksheetModal from "./WorksheetModal";
import WorkbookDrawer from "./WorkbookDrawer";
import AssetDeleteModal from './AssetDeleteModal';
import { AppContext, appId } from "../../../../App";
import StartFlowModal from "./StartFlow";
import "./AssetTable.less";
import 'react-contexify/dist/ReactContexify.css';
import { getTemplateType } from "../../../../util/axios";
const { Text } = Typography;
const { Search } = Input;
const { Column } = Table;
//资产项
const AssetItem = (props) => {
const { metadata, terms } = props;
const { metadata } = props;
let content = '';
if (typeof metadata==='string') {
......@@ -50,14 +51,14 @@ const AssetItem = (props) => {
ellipsis: true,
},
{
title: '字段中文名称',
title: '名称',
width: 160,
dataIndex: 'metadataColumnCnName',
editable: true,
ellipsis: true,
},
{
title: '字段英文名称',
title: '技术ID(英文名称)',
width: 160,
dataIndex: 'metadataColumnName',
editable: true,
......@@ -79,7 +80,7 @@ const AssetItem = (props) => {
</div>}
>
<Text ellipsis={true}>
{highlightSearchContentByTerms(content||'', terms)}
{content||''}
</Text>
</Tooltip>
);
......@@ -117,7 +118,7 @@ const ResizeableHeaderCell = props => {
const AssetTable = (props) => {
const { className, nodeId, nodeType, elementsChanged, assetActionChanged, onSelect, onCountChange, reference = AssetManageReference } = props;
const { className, nodeId, nodeType, nodeLevel, elementsChanged, assetActionChanged, onSelect, onCountChange, reference = AssetManageReference, onFullScreenChange } = props;
const MENU_ID = 'asset-table';
......@@ -127,54 +128,127 @@ const AssetTable = (props) => {
const [ loading, setLoading ] = useState(false);
const [ columns, setColumns ] = useState([]);
const [ realColumns, setRealColumns ] = useState([]);
const [ assets, setAssets ] = useState([]);
const [ total, setTotal ] = useState(0);
const [ selectItem, setSelectItem ] = useState({});
const [ contextMenuItem, setContextMenuItem ] = useState({});
const [ checkedKeys, setCheckedKeys ] = useState([]);
const [ checkedItems, setCheckedItems ] = useState([]);
const [ importAssetVisible, setImportAssetVisible ] = useState(false);
const [ filterElementVisible, setFilterElementVisible ] = useState(false);
const [ assetEditVisible, setAssetEditVisible ] = useState(false);
const [ assetMountVisible, setAssetMountVisible ] = useState(false);
const [ assetDetailDrawerVisible, setAssetDetailDrawerVisible ] = useState(false);
// const [ currentAssetId, setCurrentAssetId ] = useState('');
const [ pagination, setPagination ] = useState( { pageNum: 1, pageSize: 20 } );
const { pageNum, pageSize } = pagination;
const [ keyword, setKeyword ] = useState('');
const [ batchCatalogChange, setBatchCatalogChange ] = useState(false);
const [ fullScreen, setFullScreen ] = useState(false);
const [ recursive, setRecursive ] = useState(true);
const [ fullSearch, setFullSearch ] = useState(false);
const [ TableWidth, setTableWidth ] = useState(0);
const [ compact, setCompact ] = useState(false);
const [ worksheetModalVisible, setWorksheetModalVisible ] = useState(false);
const [ workbookDrawerVisible, setWorkbookDrawerVisible ] = useState(false);
const [ biType, setBiType ] = useState('');
const [ assetDeleteModalVisible, setAssetDeleteModalVisible ] = useState(false);
const [ startFlowModalVisible, setStartFlowModalVisible ] = useState(false);
const [ users, setUsers ] = useState([]);
const [ assetMountParam, setAssetMountParam ] = useState({
visible: false,
ids: undefined
})
const [loadingTemplates, setLoadingTemplates] = useState(false)
const [templates, setTemplates] = useState()
const [currentTemplateType, setTemplateType] = useState()
const [ modal, contextHolder ] = Modal.useModal();
const anchorId = getQueryParam(AnchorId, props.location.search);
const timestamp = getQueryParam(AnchorTimestamp, props.location.search);
const anchorId = getQueryParam(AnchorId, props?.location?.search);
const timestamp = getQueryParam(AnchorTimestamp, props?.location?.search);
const anchorDid = getQueryParam(AnchorDirId, props?.location?.search);
const app = useContext(AppContext);
const { env } = app;
const shouldScrollRef = useRef(false);
const metadataIndexRef = useRef('');
const remoteRelationRef = useRef(null);
const mountRef = useRef(true)
const app = useContext(AppContext)
const actionCol = {
title: '操作',
dataIndex: 'action',
width: 120,
fixed: 'right',
filter: false,
render: (_, record) => {
return (
<Space size={5} split={<Divider type='vertical' style={{margin:0}} />}>
{
(reference===AssetManageReference||(reference===AssetBrowseReference&&record.hasPermission)) && <a onClick={(e) => {
e.stopPropagation();
handleItemClick('authorization', record);
}}>授权</a>
}
{
(reference===AssetManageReference||(reference===AssetBrowseReference&&record.hasPermission)) && <a onClick={(e) => {
e.stopPropagation();
setAssetMountParam({
visible: true,
ids: [record.id]
});
}}>变更目录</a>
}
</Space>
)
}
}
useEffect(() => {
if (TableWidth>0 && columns.length>0) {
const newColumns = [...columns, actionCol];
const currentWidth = (newColumns.reduce((preVal, col) => (col.width?col.width:0) + preVal, 0)) + 32.0;
if (currentWidth < TableWidth) {
newColumns.forEach(column => {
column.width = (TableWidth - 32.0)/newColumns.length;
})
}
setRealColumns([...newColumns, <Column key='auto' />]);
} else {
setRealColumns([]);
}
}, [columns, TableWidth])
useEffect(() => {
getUsers();
if (reference === AssetRecycleReference) {
getTemplates()
}
window?.addEventListener("storage", storageChange);
return () => {
window?.removeEventListener("storage", storageChange);
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
useEffect(() => {
if ((nodeId||'') !== '' ) {
if (nodeId !== null && nodeId !== undefined) {
setSelectItem({});
setCheckedKeys([]);
if (shouldScrollRef.current === true) {
shouldScrollRef.current = false;
if (remoteRelationRef.current) {
getDataAssetLocationByRelation();
} else {
getDataAssetLocation();
}
} else {
setPagination({ ...pagination, pageNum: 1 });
}
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ nodeId ])
......@@ -189,42 +263,98 @@ const AssetTable = (props) => {
}, [timestamp])
useEffect(() => {
if (nodeId) {
getFilterElementsGroupByDirIdThenGetDataAssets();
} else if (reference===AssetRecycleReference) {
if (reference !== AssetRecycleReference && nodeId !== null) {
getFilterElementsGroupThenGetDataAssets();
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ keyword, pagination, elementsChanged, assetActionChanged, recursive, fullSearch ])
useEffect(() => {
if (reference===AssetRecycleReference) {
getFilterElementsGroupThenGetDataAssets();
if (reference === AssetRecycleReference) {
if (!mountRef.current) {
getFilterElementsGroupThenGetDataAssets()
}
if (mountRef.current) {
mountRef.current = false
}
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ env ])
}, [ keyword, pagination, elementsChanged ])
useEffect(() => {
if (shouldScrollRef.current) {
SmoothScroll('a[href*="#"]');
const realAssets = useMemo(() => {
const newAssets = [...assets];
if (users?.length > 0 && assets?.length > 0 && columns?.length > 0) {
const specialCol = ['数据关键用户', '业务数据owner', 'it责任人', '创建人', '更新人'];
var scroll = new SmoothScroll();
var anchor = document.querySelector(`#data-asset-${anchorId}`);
const indexArray = [];
columns.forEach((item, index) => {
if (specialCol.indexOf(item.title?.toLowerCase()) !== -1) {
indexArray.push(index);
}
});
if (anchor) {
scroll.animateScroll(anchor);
shouldScrollRef.current = false;
newAssets?.forEach((item) => {
indexArray?.forEach(index => {
const user = users?.filter((user)=>(user.pernr===item[`element${index+1}`]));
if (user && user.length > 0) {
item[`element${index+1}`] = user[0].nachn?`${user[0].nachn}(${user[0].pernr})`:user[0].pernr;
}
})
})
}
return newAssets;
}, [users, assets, columns])
const storageChange = (e) => {
if (e.key === 'assetRelationOnClickEvent') {
remoteRelationRef.current = e.relation;
shouldScrollRef.current = true;
} else if (e.key === 'assetPathOnClickEvent') {
remoteRelationRef.current = {
dataAssetId: e.id,
dirId: e.dirId
};
shouldScrollRef.current = true;
}
}
const getTemplates = () => {
setLoadingTemplates(true)
dispatch({
type: 'assetmanage.getTemplates',
callback: data => {
setLoadingTemplates(false)
setTemplates(data)
if ((data??[]).length > 0) {
setTemplateType(data[0].type)
LocalStorage.set(`templateType-${appId}`, data[0].type)
getFilterElementsGroupThenGetDataAssets();
}
},
error: () => {
setLoadingTemplates(false)
}
})
}
const getDataAssetLocation = () => {
const getUsers = () => {
dispatch({
type: 'pds.getOwners',
callback: (data) => {
setUsers(data);
}
})
}
const getDataAssetLocationByRelation = () => {
setLoading(true);
dispatch({
type: 'assetmanage.getDataAssetLocation',
payload: {
dataAssetId: anchorId
dataAssetId: remoteRelationRef.current?.dataAssetId,
dirId: remoteRelationRef.current?.dirId,
},
callback: data => {
const anchorLocation = data.offset;
......@@ -233,115 +363,45 @@ const AssetTable = (props) => {
},
error: () => {
setLoading(false);
remoteRelationRef.current = null;
setPagination({ ...pagination, pageNum: 1 });
}
});
}
const changeCurrent = (page,size) => {
setCheckedKeys([]);
setPagination({ pageNum: page, pageSize: size });
}
const getFilterElementsGroupByDirIdThenGetDataAssets = () => {
const getDataAssetLocation = () => {
setLoading(true);
dispatch({
type: 'assetmanage.listFilterElementsGroupByTypeWithDirId',
type: 'assetmanage.getDataAssetLocation',
payload: {
dirId: nodeId
dataAssetId: anchorId||'',
dirId: anchorDid||'',
},
callback: data => {
let _columns = [];
let index = 0, _metadataIndex = '';
(data||[]).forEach(group => {
(group.names||[]).forEach((name, i) => {
index++;
const params = {
title: name,
dataIndex: `element${index}`,
ellipsis: true,
width: 120,
render: (text, record) => {
return (
<Tooltip title={text||''}>
<Text ellipsis={true}>
{highlightSearchContentByTerms(text||'', keyword?[keyword]:[])}
</Text>
</Tooltip>
);
}
};
if (name === '编号') {
params.width = 60;
// params.fixed = 'left';
} else if (name === '中文名称') {
// params.fixed = 'left';
} else if (name === '英文名称') {
params.width = isSzseEnv?250:120;
// params.fixed = 'left';
// params.render = (text, record) => {
// return (
// <Tooltip title={text||''}>
// <a onClick={()=>{detailAsset(record);}}>
// {text||''}
// </a>
// </Tooltip>
// );
// }
} else if (name === '资产项') {
params.width = isSzseEnv?250:120;
params.render = (metadata, _) => {
return (
<AssetItem metadata={metadata} terms={keyword?[keyword]:[]} />
);
}
_metadataIndex = `element${index}`;
} else if (name === '资产路径') {
params.render = (text, record) => {
return (
<Tooltip title={text||''}>
<Text ellipsis={true}>
<a onClick={()=>{
LocalStorage.set('assetDirChange', !(LocalStorage.get('assetDirChange')||false));
let event = new Event('storage');
event.key = 'assetDirChange';
event.dirId = record.dirId||'';
window?.dispatchEvent(event);
}}>
{highlightSearchContentByTerms(text||'', keyword?[keyword]:[])}
</a>
</Text>
</Tooltip>
);
}
}
_columns.push(params);
})
})
setAssets([]);
setColumns(_columns);
metadataIndexRef.current = _metadataIndex;
getDataAssets(_metadataIndex);
const anchorLocation = data.offset;
const _pageNum = parseInt(anchorLocation/pageSize + ((anchorLocation%pageSize===0)?0:1));
setPagination({ ...pagination, pageNum: _pageNum });
},
error: () => {
setLoading(false)
setLoading(false);
setPagination({ ...pagination, pageNum: 1 });
}
})
});
}
const changeCurrent = (page,size) => {
setCheckedKeys([]);
setPagination({ pageNum: page, pageSize: size });
}
const getFilterElementsGroupThenGetDataAssets = () => {
setLoading(true);
dispatch({
type: 'assetmanage.listFilterElementsGroupByType',
payload: {
isAdmin: (reference===AssetManageReference)
},
callback: data => {
let _columns = [];
......@@ -359,7 +419,7 @@ const AssetTable = (props) => {
return (
<Tooltip title={text||''}>
<Text ellipsis={true}>
{highlightSearchContentByTerms(text||'', keyword?[keyword]:[])}
{text||''}
</Text>
</Tooltip>
);
......@@ -370,9 +430,10 @@ const AssetTable = (props) => {
params.width = 60;
// params.fixed = 'left';
} else if (name === '中文名称') {
params.width = isSzseEnv?230:160;
// params.fixed = 'left';
} else if (name === '英文名称') {
params.width = isSzseEnv?250:120;
params.width = isSzseEnv?224:160;
// params.fixed = 'left';
// params.render = (text, record) => {
// return (
......@@ -388,24 +449,23 @@ const AssetTable = (props) => {
params.render = (metadata, _) => {
return (
<AssetItem metadata={metadata} terms={keyword?[keyword]:[]} />
<AssetItem metadata={metadata} />
);
}
_metadataIndex = `element${index}`;
} else if (name === '资产路径') {
} else if (name === '资产目录路径') {
params.render = (text, record) => {
return (
<Tooltip title={text||''}>
<Text ellipsis={true}>
<a onClick={()=>{
LocalStorage.set('assetDirChange', !(LocalStorage.get('assetDirChange')||false));
let event = new Event('storage');
event.key = 'assetDirChange';
event.key = 'assetDirChangeEvent';
event.dirId = record.dirId||'';
window?.dispatchEvent(event);
}}>
{highlightSearchContentByTerms(text||'', keyword?[keyword]:[])}
{text||''}
</a>
</Text>
</Tooltip>
......@@ -418,6 +478,7 @@ const AssetTable = (props) => {
})
setAssets([]);
setColumns(_columns);
metadataIndexRef.current = _metadataIndex;
......@@ -437,7 +498,7 @@ const AssetTable = (props) => {
dirId: nodeId,
pageNum,
pageSize,
keyword: keyword
keyword: encodeURIComponent(keyword)
};
if (reference !== AssetRecycleReference) {
......@@ -449,8 +510,24 @@ const AssetTable = (props) => {
}
}
let url = 'assetmanage.listDataAssetsByPage';
if (reference===AssetRecycleReference) {
url = 'assetmanage.listRecycleBinDataAssetsByPage';
} else if ((reference===AssetBrowseReference|| reference===ResourceBrowseReference)) {
params.checkPermission = true;
if (nodeType === 'custom') {
url = 'assetmanage.listDataAssetsByPersonalCustomType';
if (reference === AssetBrowseReference) {
params.resourceType = 'dataAsset';
} else if (reference === ResourceBrowseReference) {
params.resourceType = 'innerSource,outerSource';
}
}
}
dispatchLatestHomepage({
type: (reference===AssetRecycleReference)?'assetmanage.listRecycleBinDataAssetsByPage':'assetmanage.listDataAssetsByPage',
type: url,
payload: params,
callback: data => {
const _assets = [];
......@@ -487,20 +564,48 @@ const AssetTable = (props) => {
setAssets(_assets);
if (reference === AssetManageReference) {
if ((selectItem?.id||'') !=='') {
const index = _assets.findIndex((asset) => asset.id === selectItem?.id);
if (index === -1) {
setSelectItem(_assets.length>0?_assets[0]:{});
onSelect && onSelect(_assets.length>0?_assets[0].id:'', _assets.length>0?_assets[0].dirId:'');
}
if (shouldScrollRef.current) {
let scrollId = null;
if (remoteRelationRef.current) {
scrollId = remoteRelationRef.current.dataAssetId;
} else {
setSelectItem(_assets.length>0?_assets[0]:{});
onSelect && onSelect(_assets.length>0?_assets[0].id:'', _assets.length>0?_assets[0].dirId:'');
scrollId = anchorId;
}
shouldScrollRef.current = false;
setTimeout(() => {
var anchor = document.querySelector(`#data-asset-${scrollId}`);
anchor?.scrollIntoView();
}, 500)
}
// if (reference === AssetManageReference) {
// if (remoteRelationRef.current) {
// const index = _assets.findIndex((asset) => asset.id === remoteRelationRef.current.dataAssetId);
// remoteRelationRef.current = null;
// if (index === -1) {
// setSelectItem(_assets.length>0?_assets[0]:{});
// onSelect && onSelect(_assets.length>0?_assets[0].id:'', _assets.length>0?_assets[0].dirId:'');
// } else {
// setSelectItem(_assets[index]);
// onSelect && onSelect(_assets[index].id, _assets[index].dirId);
// }
// } else if ((selectItem?.id||'') !=='') {
// const index = _assets.findIndex((asset) => asset.id === selectItem?.id);
// if (index === -1) {
// setSelectItem(_assets.length>0?_assets[0]:{});
// onSelect && onSelect(_assets.length>0?_assets[0].id:'', _assets.length>0?_assets[0].dirId:'');
// }
// } else {
// setSelectItem(_assets.length>0?_assets[0]:{});
// onSelect && onSelect(_assets.length>0?_assets[0].id:'', _assets.length>0?_assets[0].dirId:'');
// }
// }
setTotal(data.total||0);
onCountChange && onCountChange(data.total||0);
setLoading(false);
......@@ -526,8 +631,17 @@ const AssetTable = (props) => {
}
const onAssetMountCancel = (refresh = false) => {
setAssetMountVisible(false);
refresh && getDataAssets();
setAssetMountParam({
visible: false,
ids: undefined
});
if (refresh) {
setCheckedKeys([]);
getDataAssets();
showMessage('success', (reference === AssetRecycleReference)?'挂载成功':'变更目录成功');
}
}
const importAsset = () => {
......@@ -538,62 +652,52 @@ const AssetTable = (props) => {
setFilterElementVisible(true);
}
const onTableauAnalyseClick = () => {
if ((checkedKeys||[]).length === 0) {
showMessage('warn', '请先选择一个资产');
} else if ((checkedKeys||[]).length > 1) {
showMessage('warn', '只能选择一个资产');
} else {
setBiType('tableau');
setWorksheetModalVisible(true);
}
const onRecursiveChange = (e) => {
setRecursive(!e.target.checked);
}
const onTableauWorkbookClick = () => {
setBiType('tableau');
setWorkbookDrawerVisible(true);
const onFullSearchChange = (e) => {
setFullSearch(e.target.checked);
}
const onSmartBIAnalyseClick = () => {
const exportAsset = () => {
if ((checkedKeys||[]).length === 0) {
showMessage('warn', '请先选择一个资产');
} else if ((checkedKeys||[]).length > 1) {
showMessage('warn', '只能选择一个资产');
} else {
setBiType('smartBI');
setWorksheetModalVisible(true);
}
modal.confirm({
title: '提示',
content: '是否导出所有资产目录?',
onOk: () => {
window.open(`/api/dataassetmanager/dataAssetApi/exportByDataAssetIds?exportAll=true&templateType=${getTemplateType()}`);
}
const onSmartBIWorkbookClick = () => {
setBiType('smartBI');
setWorkbookDrawerVisible(true);
})
} else {
window.open(`/api/dataassetmanager/dataAssetApi/exportByDataAssetIds?dataAssetIds=${checkedKeys.join(',')}&templateType=${getTemplateType()}`);
}
const onWorksheetModalCancel = () => {
setWorksheetModalVisible(false);
}
const onWorkbookDrawerCancel = () => {
setWorkbookDrawerVisible(false);
}
const subscriptAsset = () => {
if ((checkedKeys||[]).length === 0) return;
const onRecursiveChange = (e) => {
setRecursive(!e.target.checked);
modal.confirm({
title: '提示',
content: '是否确认订阅选中资产目录?',
onOk: () => {
let payload = {
dataAssetIds: (checkedKeys||[]).join(','),
env: app?.env?.domainId
}
const onFullSearchChange = (e) => {
setFullSearch(e.target.checked);
dispatch({
type: 'assetmanage.subs',
payload,
callback: () => {
showMessage("success","订阅成功");
setCheckedKeys([]);
},
error: () => {
}
const exportAsset = () => {
if ((checkedKeys||[]).length === 0) {
showMessage('warn', '请先选择资产');
} else {
const env = LocalStorage.get('assetsEnv');
window.open(`/api/dataassetmanager/dataAssetApi/exportByDataAssetIds?dataAssetIds=${checkedKeys.join(',')}&env=${env}`);
})
}
})
}
// const detailAsset = (item)=>{
......@@ -602,32 +706,18 @@ const AssetTable = (props) => {
// }
const deleteAssets = () => {
if ((checkedKeys||[]).length > 0) {
if ((checkedKeys||[]).length === 0) return;
modal.confirm({
title: '提示',
content: (reference!==AssetRecycleReference)?'这些资产在所有目录上唯一存在,移除后,你可以前往“未挂载资产”重新挂载。': '您确定要永久删除这些资产吗?',
content: '您确定要删除这些资产目录吗?',
onOk: () => {
let payload = {
data: checkedKeys
}
if (reference !== AssetRecycleReference) {
const asssetIdsAndDirIds = [];
(assets||[]).forEach(asset => {
if (checkedKeys.indexOf(asset.id) !== -1) {
asssetIdsAndDirIds.push({ dataAssetId: asset.id||'', dirId: asset.dirId||'' });
}
})
payload = {
data: asssetIdsAndDirIds
}
}
dispatch({
type: (reference!==AssetRecycleReference)?'assetmanage.unloadDataAssets':'assetmanage.deleteDataAssets',
type: (reference===AssetManageReference)?'assetmanage.unloadDataAssetsFromAllDirs':'assetmanage.deleteDataAssets',
payload,
callback: () => {
showMessage("success","删除成功");
......@@ -639,9 +729,6 @@ const AssetTable = (props) => {
})
}
})
}else{
showMessage("warn","请选择删除项")
}
}
const onImportAssetCancel = () => {
......@@ -651,9 +738,9 @@ const AssetTable = (props) => {
const onImportAssetSuccess = (tip = '') => {
getDataAssets();
if ((tip||'') !== '') {
showNotifaction('导入提示', tip, 5);
}
// if ((tip||'') !== '') {
// showNotifaction('导入提示', tip, 5);
// }
}
const onFilterElementModalCancel = (refresh = false) => {
......@@ -661,77 +748,141 @@ const AssetTable = (props) => {
refresh && getFilterElementsGroupThenGetDataAssets();
}
const onAssetDetailDrawerCancel = () => {
const onAssetDetailDrawerCancel = (refresh = false) => {
setAssetDetailDrawerVisible(false);
refresh && getDataAssets();
}
const onBatchCatalogChangeBtnClick = () => {
setBatchCatalogChange(true);
setAssetMountVisible(true);
if ((checkedKeys||[]).length===0) return;
setAssetMountParam({
visible: true,
ids: checkedKeys
});
}
const subscriptAsset = () => {
if ((checkedKeys||[]).length === 0) return;
const onAssetDeleteModalCancel = () => {
setAssetDeleteModalVisible(false);
}
const onAssetDeleteModalDelete = () => {
setAssetDeleteModalVisible(false);
const asssetIdsAndDirIds = [];
(assets||[]).forEach(asset => {
if (checkedKeys.indexOf(asset.id) !== -1) {
asssetIdsAndDirIds.push({ dataAssetId: asset.id||'', dirId: asset.dirId||'' });
}
})
let payload = {
data: asssetIdsAndDirIds
};
dispatch({
type: 'assetmanage.unloadDataAssets',
payload,
callback: () => {
showMessage("success","删除成功");
getDataAssets();
setCheckedKeys([]);
}
})
}
const onAssetDeleteModalDeleteAll = () => {
setAssetDeleteModalVisible(false);
let payload = {
data: checkedKeys
};
dispatch({
type: 'assetmanage.unloadDataAssetsFromAllDirs',
payload,
callback: () => {
showMessage("success","删除成功");
getDataAssets();
setCheckedKeys([]);
}
})
}
const recoveryAssets = () => {
if ((checkedKeys||[]).length > 0) {
modal.confirm({
title: '提示',
content: '您确定要订阅这些资产吗?',
content: '您确定要恢复这些资产目录吗?',
onOk: () => {
let payload = {
dataAssetIds: (checkedKeys||[]).join(','),
data: checkedKeys
}
dispatch({
type: 'assetmanage.subs',
type: 'assetmanage.recoveryFromRecycleBin',
payload,
callback: () => {
showMessage("success","订阅成功");
showMessage("success","恢复成功");
getDataAssets();
setCheckedKeys([]);
},
error: () => {
}
})
}
})
}else{
showMessage("warn","请选择资产目录");
}
}
const onSelectChange = keys => {
setCheckedKeys(keys);
const newCheckedItems = assets?.filter(item => keys.indexOf(item.id)!==-1);
setCheckedItems(newCheckedItems);
};
const onFullScreenClick = () => {
setFullScreen(!fullScreen);
onFullScreenChange && onFullScreenChange(!fullScreen);
}
const onStartFlowClick = () => {
setStartFlowModalVisible(true);
}
const onStartFlowModalCancel = (refresh = false) => {
setStartFlowModalVisible(false);
if (refresh) {
setCheckedKeys([]);
}
}
const handleResize = index => (e, { size }) => {
const nextColumns = [...columns];
const nextColumns = [...realColumns];
nextColumns[index] = {
...nextColumns[index],
width: size.width,
};
setColumns(nextColumns);
setRealColumns(nextColumns);
};
const displayMenu = (e) => {
show(e);
show({
event: e
})
}
const handleItemClick = ({ event, props, data, triggerEvent }) => {
const key = event.currentTarget.id;
if (key === 'uncombed') {
const handleItemClick = (id, record) => {
if (id === 'uncombed') {
modal.confirm({
title: '提示',
content: '是否将该条非资产的资源转为未梳理状态?',
content: '是否将该条非资产目录的资源转为未梳理状态?',
onOk: () => {
dispatch({
type: 'assetmanage.updateResourceState',
payload: {
params: {
dataAssetId: contextMenuItem.id,
dataAssetId: record.id,
resourceState: 'uncombed'
}
},
......@@ -746,16 +897,16 @@ const AssetTable = (props) => {
});
}
});
} else if (key === 'notRelatedAsset') {
} else if (id === 'notRelatedAsset') {
modal.confirm({
title: '提示',
content: '是否将该条未梳理的资源转为非资产?',
content: '是否将该条未梳理的资源转为非资产目录?',
onOk: () => {
dispatch({
type: 'assetmanage.updateResourceState',
payload: {
params: {
dataAssetId: contextMenuItem.id,
dataAssetId: record.id,
resourceState: 'notRelatedAsset'
}
},
......@@ -770,15 +921,14 @@ const AssetTable = (props) => {
});
}
});
} else if (key === 'authorization') {
if (contextMenuItem?.metadata?.metadataTableId) {
console.log('metadataTableId', contextMenuItem?.metadata?.metadataTableId);
} else if (id === 'authorization') {
if (record.metadata?.metadataTableId) {
app?.setGlobalState && app?.setGlobalState({
message: 'data-govern-assets-admit',
data: contextMenuItem
data: record
})
} else {
showMessage("warn","该资产没有关联元数据信息");
showMessage("warn","该资产目录没有关联元数据信息");
}
}
}
......@@ -786,9 +936,18 @@ const AssetTable = (props) => {
const moreMenu = (
<Menu>
{
(reference===AssetManageReference && nodeType!=='custom') && <Menu.Item>
<div className='text-center' onClick={importAsset}>
导入
// (reference===AssetManageReference) &&
// <Menu.Item disabled={(checkedKeys||[]).length===0}>
// <div className='text-center' onClick={onStartFlowClick}>
// 申请
// </div>
// </Menu.Item>
}
{
(reference!==AssetRecycleReference) &&
<Menu.Item disabled={(checkedKeys||[]).length===0}>
<div className='text-center' onClick={subscriptAsset}>
订阅
</div>
</Menu.Item>
}
......@@ -796,20 +955,10 @@ const AssetTable = (props) => {
{
(reference===AssetManageReference || reference===AssetRecycleReference) && <React.Fragment>
<Menu.Item disabled={(checkedKeys||[]).length===0}>
<div className='text-center' onClick={exportAsset}>
导出
</div>
</Menu.Item>
<Menu.Item disabled={(checkedKeys||[]).length===0}>
<div className='text-center' onClick={onBatchCatalogChangeBtnClick}>
{(reference===AssetRecycleReference)?'挂载':'变更目录'}
</div>
</Menu.Item>
<Menu.Item disabled={(checkedKeys||[]).length===0}>
<div className='text-center' onClick={subscriptAsset}>
订阅
</div>
</Menu.Item>
{
//自定义目录下的资产不允许新增 删除
(nodeType!=='custom') && <Menu.Item disabled={(checkedKeys||[]).length===0}>
......@@ -826,75 +975,6 @@ const AssetTable = (props) => {
可见列设置
</div>
</Menu.Item>
{
(reference===AssetManageReference) && <Menu.Item disabled={(checkedKeys||[]).length===0}>
<div className='text-center' onClick={onTableauAnalyseClick}>
tableau自助分析
</div>
</Menu.Item>
}
{
(reference===AssetManageReference) && <Menu.Item>
<div className='text-center' onClick={onTableauWorkbookClick}>
tableau工作簿
</div>
</Menu.Item>
}
{
(reference===AssetManageReference) && <Menu.Item disabled={(checkedKeys||[]).length===0}>
<div className='text-center' onClick={onSmartBIAnalyseClick}>
smartBI自助分析
</div>
</Menu.Item>
}
{
(reference===AssetManageReference) && <Menu.Item>
<div className='text-center' onClick={onSmartBIWorkbookClick}>
smartBI工作簿
</div>
</Menu.Item>
}
</Menu>
);
const browseMoreMenu = (
<Menu>
{
(reference!==AssetRecycleReference) && <Menu.Item disabled={(checkedKeys||[]).length===0}>
<div className='text-center' onClick={subscriptAsset}>
订阅
</div>
</Menu.Item>
}
<Menu.Item>
<div className='text-center' onClick={onFilterElementClick}>
可见列设置
</div>
</Menu.Item>
<Menu.Item disabled={(checkedKeys||[]).length===0}>
<div className='text-center' onClick={onTableauAnalyseClick}>
tableau自助分析
</div>
</Menu.Item>
<Menu.Item>
<div className='text-center' onClick={onTableauWorkbookClick}>
tableau工作簿
</div>
</Menu.Item>
<Menu.Item disabled={(checkedKeys||[]).length===0}>
<div className='text-center' onClick={onSmartBIAnalyseClick}>
smartBI自助分析
</div>
</Menu.Item>
<Menu.Item>
<div className='text-center' onClick={onSmartBIWorkbookClick}>
smartBI工作簿
</div>
</Menu.Item>
</Menu>
);
......@@ -911,10 +991,10 @@ const AssetTable = (props) => {
if ((assets||[]).length>0) {
if (fullScreen) {
scrollY = 'calc(100vh - 209px - 72px)';
} else if (reference===AssetManageReference||reference===ResourceBrowseReference) {
scrollY = 'calc(100vh - 209px - 123px - 15px - 72px)';
} else if (reference===AssetBrowseReference) {
scrollY = 'calc(100vh - 209px - 94px - 15px - 72px)';
} else if (reference===AssetManageReference) {
scrollY = 'calc(100vh - 209px - 72px)';
} else if (reference===AssetBrowseReference ||reference===ResourceBrowseReference) {
scrollY = 'calc(100vh - 209px - 72px)';
} else if (reference===AssetRecycleReference) {
scrollY = 'calc(100vh - 209px - 72px)';
}
......@@ -923,51 +1003,102 @@ const AssetTable = (props) => {
return(
<div className={classes}>
<div
className='flex p-common'
className='flex p-3'
style={{
alignItems: 'center',
justifyContent: 'space-between',
borderBottom: '1px solid rgb(239, 239, 239)',
}}
>
<Space size={15}>
{
(reference===AssetManageReference && nodeType!=='custom') && <Button onClick={addAsset}>新增</Button>
//栏目和自定义目录 不允许新增资产
// (reference===AssetManageReference && nodeLevel!==1 && nodeType!=='custom') && <Button onClick={addAsset}>新增</Button>
}
{
reference === AssetRecycleReference && <Select
loading={loadingTemplates}
value={currentTemplateType}
onChange={(val) => {
setTemplateType(val)
LocalStorage.set(`templateType-${appId}`, val);
setPagination({ ...pagination, pageNum: 1 });
}}
style={{ width: 80 }}
>
{
(templates??[]).map((item, index) => <Select.Option key={index} value={item.type}>{item.name}</Select.Option>)
}
</Select>
}
{
(reference===AssetManageReference && nodeType!=='custom') && <Button onClick={importAsset}>导入</Button>
}
{
(reference===AssetManageReference || reference===AssetRecycleReference) &&
<Tooltip>
<Button onClick={exportAsset} >导出</Button>
</Tooltip>
}
{
// (reference===AssetBrowseReference||reference===ResourceBrowseReference) &&
// <Tooltip title={(checkedKeys||[]).length===0?'请先选择资产目录':''}>
// <Button onClick={onStartFlowClick} disabled={(checkedKeys||[]).length===0} >申请</Button>
// </Tooltip>
}
{
(reference===AssetManageReference) ? <Dropdown overlay={moreMenu} placement="bottomCenter">
(compact && reference!==AssetRecycleReference) ? <Dropdown overlay={moreMenu} placement="bottomCenter">
<Button>其他操作</Button>
</Dropdown> : <React.Fragment>
{
(reference===AssetRecycleReference) && <React.Fragment>
<Tooltip title={(checkedKeys||[]).length===0?'请先选择资产':''}>
<Button onClick={exportAsset} disabled={(checkedKeys||[]).length===0} >导出</Button>
// (reference===AssetManageReference) &&
// <Tooltip title={(checkedKeys||[]).length===0?'请先选择资产目录':''}>
// <Button onClick={onStartFlowClick} disabled={(checkedKeys||[]).length===0} >申请</Button>
// </Tooltip>
}
{
(reference!==AssetRecycleReference) &&
<Tooltip title={(checkedKeys||[]).length===0?'请先选择资产目录':''}>
<Button onClick={subscriptAsset} disabled={(checkedKeys||[]).length===0} >订阅</Button>
</Tooltip>
<Tooltip title={(checkedKeys||[]).length===0?'请先选择资产':''}>
}
{
(reference===AssetManageReference || reference===AssetRecycleReference) && <React.Fragment>
<Tooltip title={(checkedKeys||[]).length===0?'请先选择资产目录':''}>
<Button onClick={onBatchCatalogChangeBtnClick} disabled={(checkedKeys||[]).length===0} >{(reference===AssetRecycleReference)?'挂载':'变更目录'}</Button>
</Tooltip>
{
(reference===AssetRecycleReference) && <Tooltip title={(checkedKeys||[]).length===0?'请先选择资产目录':''}>
<Button onClick={recoveryAssets} disabled={(checkedKeys||[]).length===0} >恢复</Button>
</Tooltip>
}
{
//自定义目录下的资产不允许删除
(nodeType!=='custom') && <Tooltip title={(checkedKeys||[]).length===0?'请先选择资产':''}>
(nodeType!=='custom') && <Tooltip title={(checkedKeys||[]).length===0?'请先选择资产目录':''}>
<Button onClick={deleteAssets} disabled={(checkedKeys||[]).length===0} >删除</Button>
</Tooltip>
}
</React.Fragment>
}
<Dropdown overlay={browseMoreMenu} placement="bottomCenter">
<Button>其他操作</Button>
</Dropdown>
<Button onClick={onFilterElementClick}>可见列设置</Button>
</React.Fragment>
}
{
{/* {
(reference!==AssetRecycleReference && isSzseEnv) && <Checkbox onChange={onRecursiveChange} checked={!recursive}>仅显示当前目录</Checkbox>
}
} */}
</Space>
<Space>
{
{/* {
(reference!==AssetRecycleReference) && <Checkbox onChange={onFullSearchChange} checked={fullSearch}>全部数据</Checkbox>
}
} */}
<Search
placeholder="请输入资产要素值"
placeholder="请输入资产目录要素值"
allowClear
onSearch={onSearchInputChange}
enterButton
......@@ -981,10 +1112,12 @@ const AssetTable = (props) => {
</Space>
</div>
<div
className='px-common'
className='p-3'
>
<ResizeObserver
onResize={({ width }) => {
setTableWidth(width);
if (width < 1030 && !compact) {
setCompact(true);
} else if (width >= 1030 && compact) {
......@@ -1006,28 +1139,31 @@ const AssetTable = (props) => {
setSelectItem(record);
onSelect && onSelect(record?.id, record?.dirId);
if (reference !== AssetManageReference) {
setAssetDetailDrawerVisible(true);
}
},
onContextMenu: event => {
if (reference===AssetManageReference && (record.resourceState==='uncombed'||record.resourceState==='notRelatedAsset')) {
setContextMenuItem(record);
displayMenu(event);
}
// if ((reference===AssetManageReference||(reference===AssetBrowseReference&&record.hasPermission)) && (record.resourceState==='uncombed'||record.resourceState==='notRelatedAsset')) {
// setContextMenuItem(record);
// displayMenu(event);
// }
},
}
}}
rowClassName={(record, index) => {
let classNames = [];
// if (reference===AssetManageReference && (record.resourceState==='uncombed'||record.resourceState==='notRelatedAsset')) {
// classNames.push('cursor-contextmenu');
// }
if (record?.id===anchorId || record?.id===selectItem?.id) {
return 'yy-table-select-row';
classNames.push('yy-table-select-row');
}
return '';
return classNames.join(' ');
}}
loading={loading}
columns={
columns.map((column, index) => {
(realColumns||[]).map((column, index) => {
return {
...column,
onHeaderCell: column => ({
......@@ -1038,18 +1174,16 @@ const AssetTable = (props) => {
})
}
rowKey='id'
dataSource={assets}
dataSource={realAssets}
pagination={false}
size='default'
scroll={{ x: 1000, y: scrollY }}
scroll={{ y: scrollY }}
/>
</ResizeObserver>
</div>
<Pagination
size="small"
className="text-center m-3"
className="text-center mt-3"
showSizeChanger
showQuickJumper
onChange={changeCurrent}
onShowSizeChange={changeCurrent}
current={pageNum}
......@@ -1058,6 +1192,7 @@ const AssetTable = (props) => {
total={total}
showTotal={total => `共 ${total} 条`}
/>
</div>
<AssetEdit
visible={assetEditVisible}
......@@ -1071,14 +1206,15 @@ const AssetTable = (props) => {
onSuccess={onImportAssetSuccess}
/>
<AssetMount
visible={ assetMountVisible }
visible={ assetMountParam.visible }
reference={reference}
ids={ batchCatalogChange?checkedKeys:[] }
ids={ assetMountParam.ids }
onCancel={ onAssetMountCancel }
{...props}
/>
<FilterElementModal
type={(reference===AssetManageReference)?'admin': 'user'}
reference={reference}
visible={ filterElementVisible }
onCancel={ onFilterElementModalCancel}
/>
......@@ -1086,24 +1222,22 @@ const AssetTable = (props) => {
id={selectItem?.id}
dirId={selectItem?.dirId}
visible={assetDetailDrawerVisible}
reference={reference}
onCancel={onAssetDetailDrawerCancel}
/>
<WorksheetModal
type={biType}
visible={ worksheetModalVisible }
id={ (checkedKeys||[]).length>0?checkedKeys[0]:'' }
metadata={ (checkedItems||[]).length>0?checkedItems[0].metadata:{} }
onCancel={onWorksheetModalCancel}
<AssetDeleteModal
visible={assetDeleteModalVisible}
onCancel={onAssetDeleteModalCancel}
onDelete={onAssetDeleteModalDelete}
onDeleteAll={onAssetDeleteModalDeleteAll}
/>
<WorkbookDrawer
type={biType}
visible={workbookDrawerVisible}
onCancel={onWorkbookDrawerCancel}
<StartFlowModal
visible={startFlowModalVisible}
ids={checkedKeys||[]}
onCancel={onStartFlowModalCancel}
/>
<RcMenu id={MENU_ID}>
{
{/* {
(contextMenuItem.resourceState==='notRelatedAsset') && <RcItem id="uncombed" onClick={handleItemClick}>
转为未梳理
</RcItem>
......@@ -1112,10 +1246,10 @@ const AssetTable = (props) => {
(contextMenuItem.resourceState==='uncombed') && <RcItem id="notRelatedAsset" onClick={handleItemClick}>
转为非资产
</RcItem>
}
{/* <RcItem id="authorization" onClick={handleItemClick}>
} */}
<RcItem id="authorization" onClick={handleItemClick}>
授权
</RcItem> */}
</RcItem>
</RcMenu>
{contextHolder}
......
......@@ -3,6 +3,7 @@ import { Modal, Form, Input, Space, Button, Select } from 'antd';
import { dispatch } from '../../../../model';
import { AppContext } from '../../../../App';
import MetadataInfo from './MetadataInfo';
import { showMessage } from '../../../../util';
const { Option } = Select;
......@@ -48,7 +49,7 @@ const DirsSelect = ({ value = [], data = [], onChange, ...restProps }) => {
const AssetTagModal = (props) => {
const { onCancel, visible, id, keyword, creator } = props;
const { onCancel, visible, id, tag, creator } = props;
const [ form ] = Form.useForm();
const [ confirmLoading, setConfirmLoading ] = useState(false);
const [ elements, setElements ] = useState([]);
......@@ -69,12 +70,12 @@ const AssetTagModal = (props) => {
useEffect(() => {
if (visible && (keyword||'')!=='') {
getDirectoryByName(keyword);
if (visible && (tag?.name||'')!=='') {
getDirectoryByName(tag?.name);
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ visible, keyword ])
}, [ visible ])
const getAsset = () => {
dispatch({
......@@ -140,7 +141,7 @@ const AssetTagModal = (props) => {
});
const params = {
dirId: row.tags.join(','),
dirId: (row.dirs||[]).join(','),
}
if ((metadataId||'')!=='') {
......@@ -150,38 +151,38 @@ const AssetTagModal = (props) => {
setConfirmLoading(true);
dispatch({
type: 'assetmanage.addOrUpdateDataAsset',
type: 'assetmanage.checkCodeIsExist',
payload: {
params,
data: { ...asset, elements: newElements }
},
callback: () => {
const nameList = [];
(dirs||[]).forEach(dir=>{
if (row.tags.indexOf(dir.id) !== -1) {
nameList.push(dir.path);
}
})
callback: isExist => {
if (isExist === 'true') {
setConfirmLoading(false);
showMessage('warn', '已存在相同的资产目录编号,请重新输入');
} else {
dispatch({
type: 'tag.getTagIdListByNameList',
type: 'assetmanage.addOrUpdateDataAsset',
payload: {
params: {
nameList: nameList.join(',')
}
params,
data: { ...asset, elements: newElements }
},
callback: data => {
const ids = [id];
if (data && ((data?.id||'')!=='') && (data?.id!==id)) {
ids.push(data?.id);
}
dispatch({
type: 'tag.batchAddTagResourceByTagList',
payload: {
params: {
tagIds: (data||[]).join(','),
resourceIds: id,
tagIds: tag?.tagId,
resourceIds: ids.join(','),
type: 'dataAsset',
creator
}
},
callback: () => {
setConfirmLoading(false);
reset();
onCancel && onCancel(true);
},
......@@ -194,6 +195,7 @@ const AssetTagModal = (props) => {
setConfirmLoading(false);
}
})
}
},
error: () => {
setConfirmLoading(false);
......@@ -226,7 +228,7 @@ const AssetTagModal = (props) => {
<Modal
forceRender
className='asset-add'
title='资产打标签'
title='资产目录打标签'
visible={ visible }
width={ 600 }
onCancel={() => {
......@@ -259,8 +261,14 @@ const AssetTagModal = (props) => {
return (
<>
<Form.Item
label='资产标签'
name='tags'
label='资产目录标签'
name='tag'
>
<span>{tag?.name||''}</span>
</Form.Item>
<Form.Item
label='挂载目录'
name='dirs'
required={true}
>
<DirsSelect data={dirs||[]} />
......
import React, { useEffect, useState, useRef, useContext } from 'react';
import { useMount, useUnmount } from 'ahooks';
import {Card, Spin, Tooltip, Tree, Dropdown, Menu, Modal, AutoComplete} from 'antd';
import { PlusOutlined, ImportOutlined,ExportOutlined,ReloadOutlined, SettingOutlined, CalculatorOutlined, UnorderedListOutlined } from '@ant-design/icons';
import classNames from 'classnames';
import React, { useEffect, useState, useRef } from 'react';
import {Card, Spin, Tooltip, Tree, Modal, AutoComplete, Select} from 'antd';
import { ReloadOutlined, SettingOutlined } from '@ant-design/icons';
import { useContextMenu, Menu as RcMenu, Item as RcItem } from "react-contexify";
import LocalStorage from 'local-storage';
import { dispatch } from '../../../../model';
import ImportDirectory from './ImportDirectory';
import UpdateDirectoryModal from './UpdateDirectoryModal';
import CustomDirectoryModal from './CustomDirectoryModal';
import { showMessage, getQueryParam } from '../../../../util';
import { AnchorTimestamp, AnchorId, AssetManageReference, AssetBrowseReference, ResourceBrowseReference, AssetMountReference, AnchorDirId, Asset1104ManageReference } from '../../../../util/constant';
import { AnchorTimestamp, AnchorId, AssetBrowseReference, ResourceBrowseReference, AnchorDirId } from '../../../../util/constant';
import { highlightSearchContentByTerms } from '../../../../util';
import { AppContext } from '../../../../App';
import ComputeScore from './ComputeScore';
import './AssetTree.less';
import 'react-contexify/dist/ReactContexify.css';
import { appId } from '../../../../App';
const { Option } = AutoComplete;
const viewModes = [
{
key: 'dir',
name: '目录视角'
},
{
key: 'custom',
name: '自定义目录视角'
}
];
function updateTreeData(list, key, children) {
return list.map((node) => {
if (node.nodeId === key) {
......@@ -57,29 +41,22 @@ const AssetTree = (props) => {
id: MENU_ID,
});
const { env } = useContext(AppContext);
const { checkable = false, onSelect, className, onCheck, tableId, reference=AssetManageReference, onDirectoryChange, centerId } = props;
const { onSelect, onCheck, tableId, reference=AssetBrowseReference, centerId } = props;
const [ keyword, setKeyword ] = useState('');
const [ loading, setLoading ] = useState(false);
const [ treeData, setTreeData ] = useState([]);
const [ dataList, setDataList ] = useState([]);
const [ groupIds, setGroupIds ] = useState([]);
const [ expandedKeys, setExpandedKeys ] = useState([]);
const [ checkedKeys, setCheckedKeys ] = useState([]);
const [ autoExpandParent, setAutoExpandParent ] = useState(false);
const [ currentDirId, setCurrentDirId ] = useState('');
const [ currentDirType, setCurrentDirType ] = useState('');
const [ currentRightClickDir, setCurrentRightClickDir ] = useState({});
const [ importDirectoryVisible, setImportDirectoryVisible ] = useState(false);
const [ updateDirectoryModalVisible, setUpdateDirectoryModalVisible ] = useState(false);
const [ updateDirectoryAction, setUpdateDirectoryAction ] = useState('');
const [ customDirectoryModalVisible, setCustomDirectoryModalVisible ] = useState(false);
const [ customDirectoryAction, setCustomDirectoryAction ] = useState('');
const [options, setOptions] = useState([]);
const [ computeScoreVisible, setComputeScoreVisible ] = useState(false);
const [ loadedKeys, setLoadedKeys ] = useState([]);
const [ viewSelectedKey, setViewSelectedKey ] = useState(viewModes[0].key);
const [loadingTemplates, setLoadingTemplates] = useState(false)
const [templates, setTemplates] = useState()
const [currentTemplateType, setTemplateType] = useState()
const [modal, contextHolder] = Modal.useModal();
......@@ -89,30 +66,28 @@ const AssetTree = (props) => {
const treeDataRef = useRef([]);
const dataListRef = useRef([]);
const viewSelectedKeyRef = useRef(viewModes[0].key)
useMount(() => {
useEffect(() => {
getTemplates()
window?.addEventListener("storage", storageChange);
})
useUnmount(() => {
return () => {
window?.removeEventListener("storage", storageChange);
})
useEffect(() => {
if ((id||'') !== '') {
setViewSelectedKey(viewModes[0].key);
viewSelectedKeyRef.current = viewModes[0].key;
getDataAssetLocationThenGetTreeData();
} else if ((did||'') !== '') {
setViewSelectedKey(viewModes[0].key);
viewSelectedKeyRef.current = viewModes[0].key;
getAllDirectoryAsTree(true, did);
} else {
getAllDirectoryAsTree(true);
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [env, timestamp])
}, [])
// useEffect(() => {
// if ((did||'') !== '') {
// getAllDirectoryAsTree(true, did);
// } else if ((id||'') !== '') {
// getDataAssetLocationThenGetTreeData();
// } else {
// getAllDirectoryAsTree(true);
// }
// //eslint-disable-next-line react-hooks/exhaustive-deps
// }, [timestamp])
useEffect(() => {
if ((tableId||'') !== '') {
......@@ -122,20 +97,54 @@ const AssetTree = (props) => {
}, [tableId])
useEffect(() => {
if ((centerId||'') !== '') {
if ((centerId||'')!=='' && centerId!==currentDirId) {
treeDirectoryChanged(centerId);
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [centerId])
const storageChange = (e) => {
if (e.key === 'assetDirChange') {
if (e.key === 'assetDirChangeEvent') {
if ((e.dirId||'') !== '') {
treeDirectoryChanged(e.dirId);
}
} else if (e.key === 'assetRelationOnClickEvent') {
treeDirectoryChanged(e.relation?.dirId);
}
}
const getTemplates = () => {
setLoadingTemplates(true)
dispatch({
type: 'assetmanage.getTemplates',
callback: data => {
setLoadingTemplates(false)
setTemplates(data)
if ((data??[]).length > 0) {
setTemplateType(data[0].type)
const _templateType = getQueryParam('templateType', props?.location?.search)
const _dirId = getQueryParam(AnchorDirId, props?.location?.search)
if (_templateType) {
LocalStorage.set(`templateType-${appId}`, _templateType)
} else {
LocalStorage.set(`templateType-${appId}`, data[0].type)
}
if (_dirId) {
getAllDirectoryAsTree(true, _dirId)
} else {
onSelect?.('', '')
getAllDirectoryAsTree(false)
}
}
},
error: () => {
setLoadingTemplates(false)
}
})
}
const getDataAssetLocationThenGetTreeData = () => {
setLoading(true);
dispatch({
......@@ -160,7 +169,6 @@ const AssetTree = (props) => {
dataAssetId: tableId
},
callback: data => {
setCheckedKeys(data.dirIds||[]);
setExpandedKeys(data.dirIds||[]);
setAutoExpandParent(true);
onCheck && onCheck(data.dirIds||[]);
......@@ -168,62 +176,27 @@ const AssetTree = (props) => {
})
}
const getAllDirectoryAsTree = (resetCurrentDirId=true, defaultSelectedId='') => {
const getAllDirectoryAsTree = (resetCurrentDirId=true, defaultSelectedId='', refresh = false) => {
setLoading(true);
if (resetCurrentDirId) {
onSelect && onSelect('', '');
}
// if (resetCurrentDirId) {
// onSelect && onSelect('', '');
// }
let url = '';
if (reference === AssetManageReference || reference === AssetMountReference || reference === Asset1104ManageReference) {
url = 'assetmanage.queryAllDirectoryAsTree';
} else if (reference === AssetBrowseReference) {
if (reference === AssetBrowseReference) {
url = 'assetmanage.queryAssetDirectoryAsTree';
} else if (reference === ResourceBrowseReference) {
url = 'assetmanage.queryResourceDirectoryAsTree';
}
if (viewSelectedKeyRef.current === 'custom') {
url = 'assetmanage.queryCustomTypeRootDirectory';
}
dispatch({
type: url,
callback: data => {
setLoading(false);
refresh && showMessage('success', '操作成功');
let newData = [];
if (viewSelectedKeyRef.current==='dir') {
newData = [...data];
} else {
newData = (data||[]).map((item) => {
console.log(item);
return {...item, text: item.name, nodeId: item.id, type: item.resourceType}
});
}
if (reference === Asset1104ManageReference) {
function recursion1104(subCatalogs) {
if ((subCatalogs||[]).length===0) return;
(subCatalogs||[]).forEach(catalog=> {
if (catalog.text === '合规数据') {
newData = [catalog];
return;
}
recursion1104(catalog.children);
})
}
recursion1104(data);
}
if (reference === AssetMountReference) {
newData = newData.filter(item => item.type!=='custom');
}
let newData = [...data];
setLoadedKeys([]);
setTreeData(newData);
......@@ -233,13 +206,19 @@ const AssetTree = (props) => {
generateGroupIds(newData, _groupIds);
setDataList(_dataList);
setGroupIds(_groupIds);
treeDataRef.current = newData;
dataListRef.current = _dataList;
let defaultItem = null;
if ((defaultSelectedId||'') === '') {
_dataList.forEach(item => {
if ((defaultSelectedId||'')==='') {
defaultSelectedId = item.key;
}
})
}
function recursion(subCatalogs) {
if ((subCatalogs||[]).length===0) return;
......@@ -259,7 +238,6 @@ const AssetTree = (props) => {
}
if (resetCurrentDirId) {
if (viewSelectedKeyRef.current==='custom') { defaultItem = newData[0]; }
if (defaultItem) {
const expandedKeys = _dataList
......@@ -271,22 +249,12 @@ const AssetTree = (props) => {
})
.filter((item, i, self) => item && self.indexOf(item) === i);
setExpandedKeys(expandedKeys);
setExpandedKeys([...expandedKeys, defaultSelectedId]);
setAutoExpandParent(true);
setCurrentDirId(defaultItem.nodeId);
setCurrentDirType(defaultItem.type||'');
onSelect && onSelect(defaultItem.nodeId, defaultItem.type||'');
} else {
const _currentDirId = (newData&&newData[0]?(newData[0].nodeId||''):'');
const _type = (newData&&newData[0]?(newData[0].type||''):'');
setCurrentDirId(_currentDirId);
setCurrentDirType(_type);
onSelect && onSelect(_currentDirId, _type);
}
}
......@@ -329,11 +297,10 @@ const AssetTree = (props) => {
})
.filter((item, i, self) => item && self.indexOf(item) === i);
setExpandedKeys(expandedKeys);
setExpandedKeys([...expandedKeys,did]);
setAutoExpandParent(true);
setCurrentDirId(defaultItem.nodeId);
setCurrentDirType(defaultItem.type||'');
onSelect && onSelect(defaultItem.nodeId, defaultItem.type||'');
}
}
......@@ -341,6 +308,9 @@ const AssetTree = (props) => {
const generateList = (treeData, list, path = null) => {
for (let i = 0; i < treeData.length; i++) {
const node = treeData[i];
if (node.resourceType !== 'custom') {
const { nodeId, text } = node;
const currentPath = path ? `${path}/${text}` : text;
......@@ -349,6 +319,7 @@ const AssetTree = (props) => {
generateList(node.children, list, currentPath);
}
}
}
};
const generateGroupIds = (treeData, list) => {
......@@ -408,76 +379,37 @@ const AssetTree = (props) => {
return type;
}
const addDir = () => {
if (currentDirType==='custom') return;
setUpdateDirectoryAction('add');
setUpdateDirectoryModalVisible(true);
}
const editDir = () => {
if ((currentDirType||'') === '') {
setUpdateDirectoryAction('edit');
setUpdateDirectoryModalVisible(true);
} else if (currentDirType === 'custom') {
setCustomDirectoryAction('edit');
setCustomDirectoryModalVisible(true);
}
}
const refreshTree = () => {
getAllDirectoryAsTree(false);
}
const importDir = () => {
if (currentDirType==='custom') return;
setImportDirectoryVisible(true);
}
const exportAllDir = () => {
const env = LocalStorage.get('assetsEnv');
window.open(`/api/dataassetmanager/directoryApi/export?env=${env}`);
}
const exportCurrentDir = () => {
if(currentDirId){
dispatch({
type: 'assetmanage.getDirectoryById',
payload: {
dirId: currentDirId
},
callback: data => {
const env = LocalStorage.get('assetsEnv');
window.open(`/api/dataassetmanager/directoryApi/export?parentPath=${data.path}&env=${env}`);
}
})
} else {
showMessage("warn","请选择目录")
}
getAllDirectoryAsTree(false, '', true);
}
const deleteDir = () => {
if (currentRightClickDir.nodeId) {
modal.confirm({
title: '提示',
content: '节点下可能包含资产信息,删除后将把资产从该目录上移除,确定继续吗?',
title: '您确定要删除该目录吗?',
onOk: () => {
dispatch({
type: 'assetmanage.deleteDirectory',
type: 'assetmanage.checkDirectoryDeleteAble',
payload: {
params: {
dirId: currentRightClickDir.nodeId
}
},
callback: able => {
if (able === 'true') {
dispatch({
type: 'assetmanage.deletePersonalCustomDirectory',
payload: {data: [ currentRightClickDir.nodeId ]},
callback: () => {
showMessage("success","删除成功");
getAllDirectoryAsTree(true, currentDirId);
}
})
} else {
showMessage("warn","目录下有资产目录信息,不允许删除!");
}
}
})
}
})
......@@ -494,7 +426,7 @@ const AssetTree = (props) => {
setLoading(true);
dispatch({
type: 'assetmanage.upDownDirectory',
type: 'assetmanage.upDownPersonalCustomDirectory',
payload: {
params: {
dirId: currentRightClickDir.nodeId,
......@@ -516,90 +448,11 @@ const AssetTree = (props) => {
setCustomDirectoryModalVisible(true);
}
const onViewClick = ({ key }) => {
if (viewSelectedKey && viewSelectedKey===key ) return;
viewSelectedKeyRef.current = key;
setViewSelectedKey(key);
setExpandedKeys([]);
getAllDirectoryAsTree();
}
const viewMenus = (
<Menu selectedKeys={[viewSelectedKey]} onClick={onViewClick}>
{
viewModes && viewModes.map(item => {
return (
<Menu.Item key={item.key} value={item.key} >
<div style={{ textAlign: 'center' }}>
{item.name}
</div>
</Menu.Item>
)
})
}
</Menu>
);
const onLoadData = ({ key, children }) =>
new Promise((resolve) => {
if (children) {
resolve();
return;
}
setLoadedKeys([...loadedKeys, key]);
dispatch({
type: 'assetmanage.getDirectoryChild',
payload: {
parentId: key,
},
callback: (data) => {
if (data && data.length>0) {
let newTreeData = updateTreeData(treeData, key, data);
setTreeData(newTreeData);
treeDataRef.current = newTreeData;
}
resolve();
},
error: () => {
resolve();
}
});
});
// const onChange = (e) => {
// const { value } = e.target;
// if (value === '') {
// setExpandedKeys([]);
// setAutoExpandParent(false);
// setKeyword(value);
// return;
// }
// const expandedKeys = dataList
// .map(item => {
// if (item.title.indexOf(value) > -1) {
// return getParentKey(item.key, treeData);
// }
// return null;
// })
// .filter((item, i, self) => item && self.indexOf(item) === i);
// setExpandedKeys(expandedKeys);
// setAutoExpandParent(true);
// setKeyword(value);
// }
const onTreeSelect = (keys, _) => {
if ((keys||[]).length === 0) {
setCurrentDirId();
onSelect?.('', '');
return;
}
......@@ -607,59 +460,14 @@ const AssetTree = (props) => {
const _currentDirType = getCurrentType(keys[0], treeData);
setCurrentDirType(_currentDirType);
onSelect && onSelect(keys[0], _currentDirType);
}
const onTreeCheck = (values, e) => {
//同一主题下只能挂载一个目录
const _checkedKeysValue = [...(values.checked||[])];
if (e.checked) {
const _currentNodeId = e.node?.key;
let _groupItem = [];
groupIds.forEach(groupItem => {
groupItem.forEach(id => {
if (id === _currentNodeId) {
_groupItem = groupItem;
}
})
})
const _filterKeys = (_checkedKeysValue.filter(item => item===_currentNodeId || !(_groupItem.includes(item))));
setCheckedKeys(_filterKeys);
onCheck && onCheck(_filterKeys);
} else {
setCheckedKeys(_checkedKeysValue);
onCheck && onCheck(_checkedKeysValue);
}
}
const onExpand = (expandedKeys) => {
setExpandedKeys(expandedKeys);
setAutoExpandParent(false);
};
const onUpdateDirectoryCancel = (refresh=false, id) => {
setUpdateDirectoryModalVisible(false);
if (refresh) {
if (updateDirectoryAction === 'add') {
getAllDirectoryAsTree(true, id);
} else {
getAllDirectoryAsTree();
onDirectoryChange && onDirectoryChange();
}
}
}
const onImportDirectoryCancel = (refresh=false, resetCurrentDirId=false) => {
setImportDirectoryVisible(false);
refresh && getAllDirectoryAsTree(resetCurrentDirId);
}
const onCustomDirectoryCancel = (refresh=false, id='') => {
setCustomDirectoryModalVisible(false);
if (refresh) {
......@@ -671,10 +479,6 @@ const AssetTree = (props) => {
}
}
const onComputeScoreCancel = () => {
setComputeScoreVisible(false);
}
const displayMenu = (e) => {
show(e, {
position: {
......@@ -697,25 +501,41 @@ const AssetTree = (props) => {
treeDirectoryChanged(option.key);
};
const exportMenu = (
<Menu>
<Menu.Item>
<div style={{ textAlign: 'center' }} onClick={() => exportAllDir()}>
导出所有
</div>
</Menu.Item>
<Menu.Item>
<div style={{ textAlign: 'center' }} onClick={() => exportCurrentDir()}>
导出选中目录
</div>
</Menu.Item>
</Menu>
);
const onLoadData = ({ key, children }) =>
new Promise((resolve) => {
if (children) {
resolve();
return;
}
setLoadedKeys([...loadedKeys, key]);
dispatch({
type: 'assetmanage.getPersonalCustomDirecotryChild',
payload: {
parentId: key,
},
callback: (data) => {
if (data && data.length>0) {
let newTreeData = updateTreeData(treeData, key, data);
setTreeData(newTreeData);
treeDataRef.current = newTreeData;
}
resolve();
},
error: () => {
resolve();
}
});
});
const loop = (data, rootResourceType = null) =>
data.map(item => {
if (item.level === 1) {
rootResourceType = item.resourceType;
rootResourceType = item.type;
}
const title = (
......@@ -724,90 +544,79 @@ const AssetTree = (props) => {
>
{item.text}
{
(item.resourceType!=='custom') && <span>{` (${item.dataAssetAndSubDirCount})`}</span>
(item.level!==1||(item.level===1&&item.resourceType!=='custom')) && <span>{` (${item.dataAssetAndSubDirCount})`}</span>
}
</span>
);
if (item.children && item.children.length>0) {
return { ...item, ...{title, key: item.nodeId, children: loop(item.children, rootResourceType), className: (item.level===1)?'root':''} };
return { ...item, ...{ title, key: item.nodeId, children: loop(item.children, rootResourceType) }};
}
if (rootResourceType !== 'custom') {
return { ...item, ...{ title, key: item.nodeId, isLeaf: true, className: (item.level===1)?'root':'' }};
return { ...item, ...{ title, key: item.nodeId, isLeaf: true }};
}
return { ...item, ...{ title, key: item.nodeId, children: null, className: (item.level===1)?'root':''}};
});
const classes = classNames('asset-tree', className, {
'asset-tree-read-only': (reference===AssetBrowseReference||reference===ResourceBrowseReference),
'asset-tree-asset-mount-reference': reference===AssetMountReference,
return { ...item, ...{ title, key: item.nodeId, children: null }};
});
return (
<Card
className={classes}
title={ (reference===AssetBrowseReference||reference===ResourceBrowseReference || reference===AssetMountReference) ? null : (
className='asset-tree'
title={
<div
className='flex px-2'
className='flex'
style={{
height: 40,
height: 57,
alignItems: 'center',
justifyContent: 'space-around',
justifyContent: 'space-between',
padding: '0 15px'
}}
>
<Dropdown overlay={viewMenus} placement="bottomLeft">
<Tooltip title="视角">
<UnorderedListOutlined className='default' style={{ fontSize:16,cursor:'pointer' }} />
</Tooltip>
</Dropdown>
<Select
size='small'
loading={loadingTemplates}
value={currentTemplateType}
onChange={(val) => {
setTemplateType(val)
LocalStorage.set(`templateType-${appId}`, val);
setCurrentDirId();
onSelect?.(null, null);
setTimeout(() => {
onSelect?.('', '');
getAllDirectoryAsTree(false)
}, 100)
}}
style={{ width: 65 }}
>
{
(viewSelectedKeyRef.current==='dir') ? <React.Fragment>
<Tooltip title="新增目录">
<PlusOutlined className={(currentDirType==='custom')?'disable': 'default'} onClick={addDir} style={{ fontSize:16,cursor: (currentDirType==='custom')?'not-allowed':'pointer' }}/>
</Tooltip>
<Tooltip title="刷新目录">
<ReloadOutlined className='default' onClick={refreshTree} style={{ fontSize:16,cursor:'pointer' }} />
</Tooltip>
<Tooltip title="导入目录">
<ImportOutlined className={(currentDirType==='custom')?'disable': 'default'} onClick={importDir} style={{ fontSize:16,cursor:(currentDirType==='custom')?'not-allowed':'pointer' }} />
</Tooltip>
<Dropdown overlay={exportMenu} placement="bottomCenter" >
<Tooltip title="导出目录">
<ExportOutlined className='default' style={{ fontSize:16,cursor:'pointer' }} />
</Tooltip>
</Dropdown>
<Tooltip title="资产价值评分">
<CalculatorOutlined className='default' onClick={() => {setComputeScoreVisible(true)}} style={{ fontSize:16,cursor:'pointer' }} />
</Tooltip>
</React.Fragment> : <React.Fragment>
(templates??[]).map((item, index) => <Select.Option key={index} value={item.type}>{item.name}</Select.Option>)
}
</Select>
<Tooltip title="刷新目录">
<ReloadOutlined className='default' onClick={refreshTree} style={{ fontSize:16,cursor:'pointer' }} />
</Tooltip>
<Tooltip title="自定义目录">
<SettingOutlined className='default' onClick={customDir} style={{ fontSize:16,cursor:'pointer' }} />
<ReloadOutlined className='default' onClick={refreshTree} style={{ fontSize:16,cursor:'pointer',flex:1}} />
</Tooltip>
<div />
<div />
<div />
</React.Fragment>
}
{/* <Tooltip title="自定义目录">
<SettingOutlined className='default' onClick={customDir} style={{ fontSize:16,cursor:'pointer',flex:1}} />
</Tooltip> */}
<div style={{ flex: 3 }}></div>
</div>
)}
}
bordered={false}
bodyStyle={{ padding: '10px 15px' }}
headStyle={{ padding: 0 }}
style={{ width: '100%' }}
>
<Spin spinning={loading}>
{viewSelectedKeyRef.current==='dir' && <AutoComplete
<AutoComplete
allowClear
value={keyword}
style={{ marginBottom: 10, width: '100%' }}
placeholder='搜索目录'
onSelect={onAutoCompleteSelect}
onSearch={onAutoCompleteSearch}
onClear={() => { setKeyword(''); }}
notFoundContent={keyword?<span>暂无数据</span>:null}
>
{
(options||[]).map((item, index) => {
......@@ -821,9 +630,7 @@ const AssetTree = (props) => {
})
}
</AutoComplete>
}
<Tree
checkable={checkable}
showLine={true}
showIcon={false}
onExpand={onExpand}
......@@ -834,11 +641,9 @@ const AssetTree = (props) => {
loadedKeys={loadedKeys}
selectedKeys={[currentDirId||'']}
onSelect={onTreeSelect}
onCheck={onTreeCheck}
checkedKeys={checkedKeys}
checkStrictly
onRightClick={({event, node}) => {
if (reference === AssetManageReference) {
if (node.level>1 && node.type==='custom') {
setCurrentRightClickDir(node);
displayMenu(event);
}
......@@ -846,46 +651,30 @@ const AssetTree = (props) => {
/>
</Spin>
<UpdateDirectoryModal
visible={ updateDirectoryModalVisible }
onCancel={ onUpdateDirectoryCancel }
action={ updateDirectoryAction }
dirId={ (updateDirectoryAction==='add')?currentDirId:currentRightClickDir.nodeId }
/>
<ImportDirectory
visible={ importDirectoryVisible }
onCancel={ onImportDirectoryCancel }
dirId={ currentDirId }
/>
<CustomDirectoryModal
visible={ customDirectoryModalVisible }
onCancel={ onCustomDirectoryCancel }
action={ customDirectoryAction }
reference={ reference }
dirId= { currentDirId }
/>
<ComputeScore
visible={computeScoreVisible}
onCancel={ onComputeScoreCancel }
/>
{
(reference!==AssetMountReference) && <RcMenu id={MENU_ID}>
<RcMenu id={MENU_ID}>
{
viewSelectedKeyRef.current==='dir' && <React.Fragment>
<RcItem id="edit" onClick={editDir}>
修改目录
</RcItem>
<RcItem id="up" onClick={() => { moveNode(1); }}>
currentRightClickDir && currentRightClickDir.level>1 && currentRightClickDir.type==='custom' && <RcItem id="up" onClick={() => { moveNode(1); }}>
上移目录
</RcItem>
<RcItem id="down" onClick={() => { moveNode(-1); }}>
}
{
currentRightClickDir && currentRightClickDir.level>1 && currentRightClickDir.type==='custom' && <RcItem id="up" onClick={() => { moveNode(-1); }}>
下移目录
</RcItem>
</React.Fragment>
}
<RcItem id="delete" onClick={deleteDir}>
{
currentRightClickDir && currentRightClickDir.level===2 && currentRightClickDir.type==='custom' && !currentRightClickDir.adminCreate && <RcItem id="up" onClick={deleteDir}>
删除目录
</RcItem>
}
</RcMenu>
}
{contextHolder}
......
......@@ -7,7 +7,7 @@
}
.yy-tree{
height: calc(100vh - @header-height - @breadcrumb-height - 25px - 40px - 62px) !important;
height: calc(100vh - @header-height - @breadcrumb-height - 25px - 57px - 62px) !important;
overflow: auto !important;
}
......@@ -15,17 +15,3 @@
color: #f50;
}
}
\ No newline at end of file
.asset-tree-read-only {
.yy-tree {
height: calc(100vh - @header-height - @breadcrumb-height - 25px - 62px) !important;;
overflow: auto !important;
}
}
.asset-tree-asset-mount-reference {
.yy-tree {
height: 400px !important;
overflow: auto !important;
}
}
\ No newline at end of file
import React, { useState, useEffect, useContext } from 'react';
import { Button, Upload, Drawer, Table, Pagination, Divider, Form, Typography, Select, Space, Radio, Modal, Spin } from 'antd';
import { UploadOutlined, DownloadOutlined } from '@ant-design/icons';
import { dispatch } from '../../../../model';
import { showMessage, formatDate } from '../../../../util';
import { AppContext } from '../../../../App';
import download from '../../../../util/download';
const catalogs = [
{ title: '字段级资产目录', key: '1' },
{ title: '映射关系', key: '2' },
]
const FC = (props) => {
const { onCancel, onSuccess, visible, metadataId, onChange } = props;
const [loading, setLoading] = useState(false);
const [catalogId, setCatalogId] = useState('1');
const [logs, setLogs] = useState([]);
const [pagination, setPagination] = useState({ pageNum: 1, pageSize: 20 });
const { pageNum, pageSize } = pagination;
const [total, setTotal] = useState(0);
const [step, setStep] = useState(1);
const [fileList, setFileList] = useState([]);
const [detailParam, setDetailParam] = useState({visible: false, type: undefined, id: undefined, message: undefined});
const app = useContext(AppContext);
const columns = [
{
title: '序号',
dataIndex: 'key',
render: (text, record, index) => {
return (index+1).toString();
},
width: 60,
},
{
title: '开始时间',
dataIndex: 'startTime',
ellipsis: true,
render: (_, record, __) => {
return formatDate(record.startTime);
}
},
{
title: '结束时间',
dataIndex: 'endTime',
ellipsis: true,
render: (_, record, __) => {
return formatDate(record.endTime);
}
},
{
title: '耗时',
dataIndex: 'costTime',
ellipsis: true,
render: (_, record, __) => {
return record.costTime?`${Number(record.costTime/1000)}秒`:'';
}
},
// {
// title: '导入人',
// dataIndex: 'operator',
// width: 100,
// ellipsis: true,
// },
{
title: '导入状态',
dataIndex: 'state',
ellipsis: true,
},
{
title: '操作',
dataIndex: 'action',
width: 80,
render: (_, record) => {
return <a onClick={() => {
if (catalogId === '1') {
setDetailParam({...detailParam, visible: true, type: catalogId, id: record.id});
} else {
setDetailParam({...detailParam, visible: true, type: catalogId, message: record.message});
}
}}>详情</a>
}
}
]
useEffect(() => {
if (visible) {
getLogs();
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [visible, pagination, catalogId])
const getLogs = () => {
setLoading(true);
if (catalogId === '1') {
dispatch({
type: 'assetmanage.getMetadataImportAssetLog',
payload: {
catalog: app?.env?.domainId,
page: pageNum,
size: pageSize,
},
callback: data => {
setLoading(false);
setTotal(data.totalElements);
setLogs(data.content||[]);
},
error: () => {
setLoading(false);
}
});
} else {
dispatch({
type: 'assetmanage.importIndicatorLog',
payload: {
page: pageNum,
size: pageSize,
updater: app?.user?.userName,
},
callback: data => {
setLoading(false);
setTotal(data.totalElements);
data.content?.forEach((item, index) => {
item.id = index;
item.startTime = item.updateTime;
item.costTime = item.cost;
});
setLogs(data.content||[]);
},
error: () => {
setLoading(false);
}
});
}
}
const reset = () => {
setFileList([]);
setStep(1);
setCatalogId('1');
}
const downloadTemplate = () => {
if (catalogId === '2') {
window.open("/api/standard/indicator/exportModel");
}
}
const onImportClick = () => {
if (fileList.length === 0) {
showMessage('warn', '请先上传文件');
return;
}
if (catalogId === '1') {
dispatch({
type: 'assetmanage.importMetadataAttributes',
payload: {
fileList: [fileList[0]],
params: {
catalog: app?.env?.domainId,
}
},
callback: (data) => {
onChange?.(catalogId);
showMessage('success', '导入动作完成,详情查看日志');
}
})
} else {
dispatch({
type: 'assetmanage.importIndicator',
payload: {
fileList: [fileList[0]],
params: {
updater: app?.user?.userName
}
},
callback: (data) => {
onChange?.(catalogId);
showMessage('success', '导入动作完成,详情查看日志');
}
})
}
}
const onExportClick = () => {
if (catalogId === '1') {
dispatch({
type: 'assetmanage.exportMetadataAttributes',
payload: {
responseType: 'blob',
params: {
tableId: metadataId
}
},
callback: (res) => {
download(res);
}
})
} else {
dispatch({
type: 'assetmanage.getMetadataStandardList',
payload: {
data: {
parentMetadataId: metadataId
},
params: {
page: 1,
size: 999999
}
},
callback: data => {
dispatch({
type: 'assetmanage.exportIndicator',
payload: {
responseType: 'blob',
params: {
tableId: metadataId,
ids: data.content?.map(item => item.id)
}
},
callback: (res) => {
download(res);
}
})
},
});
}
}
const onDetailCancel = () => {
setDetailParam({...detailParam, visible: false});
}
const uploadProps = {
onRemove: file => {
const index = fileList.indexOf(file);
const newFileList = fileList.slice();
newFileList.splice(index, 1);
setFileList(newFileList);
},
beforeUpload: file => {
const isLt2OM = file.size / 1024 / 1024 < 20;
if (!isLt2OM) {
showMessage('error', '上传文件必须小于20M');
setFileList([]);
return false;
}
setFileList([file]);
return false;
},
fileList: fileList || [],
accept:".xlsx",
};
return (
<Drawer
visible={visible}
title='字段级资产目录维护'
width={900}
placement="right"
closable={ true }
onClose={() => {
reset();
onCancel?.();
}}
>
{
step === 1 && <React.Fragment>
<div className='flex' style={{ justifyContent: 'space-between' }}>
<Button type='primary' onClick={() => {setStep(2);}}>上传文件</Button>
<Space>
<Select
value={catalogId}
onChange={(value) => {
setCatalogId(value);
}}
style={{ width: 150 }}
>
{
catalogs?.map((catalog, index) => {
return <Select.Option key={index} value={catalog.key}>
{catalog.title}
</Select.Option>
})
}
</Select>
<Button onClick={() => getLogs()}>刷新</Button>
</Space>
</div>
<Table
className='mt-3'
columns={columns||[]}
rowKey='id'
dataSource={logs||[]}
pagination={false}
loading={loading}
sticky
/>
<Pagination
className="text-center mt-3"
showSizeChanger
showQuickJumper
onChange={(_pageNum, _pageSize) => {
setPagination({ pageNum: _pageNum||1, pageSize: _pageSize || 20 });
}}
onShowSizeChange={(_pageNum, _pageSize) => {
setPagination({ pageNum: _pageNum || 1, pageSize: _pageSize || 20 });
}}
current={pageNum}
pageSize={pageSize}
defaultCurrent={1}
total={total}
pageSizeOptions={[10,20]}
showTotal={total => `共 ${total} 条`}
/>
</React.Fragment>
}
{
step === 2 && <React.Fragment>
<div className='flex' style={{ justifyContent: 'space-between', alignItems: 'center' }}>
<Radio.Group
onChange={(e) => {
setCatalogId(e.target.value);
}}
value={catalogId}
>
{
catalogs.map((catalog, index) => <Radio key={index} value={catalog.key}>{catalog.title}</Radio>)
}
</Radio.Group>
<Button onClick={() => {
setStep(1);
getLogs();
}}>查看日志</Button>
</div>
<div className='flex mt-3' style={{ justifyContent: 'space-between' }}>
<Upload style={{ display: 'inline' }} {...uploadProps }>
<Button icon={
<UploadOutlined />}>
选择文件上传
</Button>
</Upload>
{/* {
catalogId === '2' && <Button icon={<DownloadOutlined />} onClick={ downloadTemplate }>
模板下载
</Button>
} */}
</div>
<div className='mt-3'>
<Space>
<Button type='primary' onClick={onImportClick}>导入</Button>
<Button type='primary' onClick={onExportClick}>导出</Button>
</Space>
</div>
</React.Fragment>
}
<Detail
visible={detailParam.visible}
type={detailParam.type}
id={detailParam.id}
message={detailParam.message}
onCancel={onDetailCancel}
/>
</Drawer>
)
}
export default FC;
const Detail = ({ visible, message, id, type, onCancel }) => {
const [currentMessage, setCurrentMessage] = useState(undefined);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (visible) {
if (type === '1') {
getMetadataImportAssetLogDetail();
} else {
setCurrentMessage(message);
}
}
}, [visible, type, message, id])
const getMetadataImportAssetLogDetail = () => {
setLoading(true);
dispatch({
type: 'assetmanage.getMetadataImportAssetLogDetail',
payload: {
logId: id
},
callback: data => {
setLoading(false);
setCurrentMessage(data?.message);
},
error: () => {
setLoading(false);
}
});
}
return (
<Modal
title='导入详情'
width={600}
visible={visible}
footer={null}
onCancel={() => {
setLoading(false);
onCancel?.();
}}
bodyStyle={{
height: 400,
overflow: 'auto'
}}
>
<Spin spinning={loading}>
{
(type === '1') ? currentMessage?.split('<br />').map((info, index) => {
return <Typography.Paragraph key={index}>{info}</Typography.Paragraph>
}) : currentMessage?.split('\n').map((info, index) => {
return <Typography.Paragraph key={index}>{info}</Typography.Paragraph>
})
}
</Spin>
</Modal>
)
}
\ No newline at end of file
......@@ -389,7 +389,7 @@ const AttributeRelationModal = (props) => {
return (
<Modal
forceRender
title={'资产属性关联'}
title={'资产目录属性关联'}
visible={visible}
width={1000}
onCancel={() => {
......
import React, { useEffect, useState, useMemo } from 'react';
import { Modal, Checkbox, Row, Input, Col, Space, Button } from 'antd';
import { dispatch } from '../../../../model';
import { showMessage } from '../../../../util';
import { AssetActionSubject } from './AssetAction';
const FC = (props) => {
const { visible, onCancel } = props;
const [keyword, setKeyword] = useState('');
const [elements, setElements] = useState([]);
const [checkedValues, setCheckedValues] = useState([]);
const [confirmLoading, setConfirmLoading] = useState(false);
useEffect(() => {
if (visible) {
getComputableElements();
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [visible])
const filterElements = useMemo(() => {
return elements?.filter(item => (item.name||'').indexOf(keyword)!==-1);
}, [keyword, elements])
const getComputableElements = () => {
dispatch({
type: 'assetmanage.listComputableElements',
callback: data => {
setElements(data);
}
})
}
const onSearchChange = (e) => {
setKeyword(e.target.value);
}
const onCheckboxChange = (newValues) => {
setCheckedValues(newValues);
}
const reset = () => {
setConfirmLoading(false);
setKeyword('');
setCheckedValues([]);
setElements([]);
}
const onOk = () => {
if ((checkedValues||[]).length === 0) {
showMessage('info', '请先选择要素');
return;
}
setConfirmLoading(true);
dispatch({
type: 'assetmanage.computeBySelectElements',
payload: {
data: checkedValues
},
callback: data => {
setConfirmLoading(false);
reset();
AssetActionSubject.next({type: 'update'})
onCancel?.();
},
error: () => {
setConfirmLoading(false);
}
})
}
return (
<Modal
forceRender
title='资产价值评分'
visible={visible}
width={800}
confirmLoading={confirmLoading}
onCancel={() => {
reset();
onCancel?.();
}}
footer={
<Space>
<Button onClick={() => onCancel?.() }>取消</Button>
<Button type="primary" onClick={ onOk } loading={ confirmLoading }>计算</Button>
</Space>
}
>
<div>
<div className='mb-3'>资产要素</div>
<Input
value={keyword}
allowClear
placeholder='请输入资产要素'
style={{ marginBottom:10 }}
onChange={(e) => { onSearchChange(e) }}
/>
<div style={{ maxHeight: 500, overflow: 'auto' }}>
<Checkbox.Group value={checkedValues} onChange={onCheckboxChange} style={{ width: '100%' }}>
<Row>
{
elements?.map((item, index) => {
const exsit = filterElements?.some(filterItem => filterItem.id === item.id);
return (
<Col key={index} span={6} style={{ display: exsit?'':'none' }}>
<Checkbox value={item.id||''}>{item.name||''}</Checkbox>
</Col>
);
})
}
</Row>
</Checkbox.Group>
</div>
</div>
</Modal>
);
}
export default FC;
\ No newline at end of file
import React, { useEffect, useState, useCallback } from 'react';
import { Modal, Checkbox, Row, Col, Form, Input, Empty } from 'antd';
import { Modal, Checkbox, Row, Col, Form, Input, Empty, Select } from 'antd';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import update from 'immutability-helper';
......@@ -7,11 +7,18 @@ import update from 'immutability-helper';
import DragTag from './DragTag';
import PreviewTree from './PreviewTree';
import { dispatch, dispatchLatest } from '../../../../model';
import { AssetManageReference, AssetBrowseReference, ResourceBrowseReference } from '../../../../util/constant';
import { showMessage } from '../../../../util';
const resourceTypes = [
{ key: 'innerSource', name: '内部资源' },
{ key: 'outerSource', name: '外部资源' },
{ key: 'dataAsset', name: '资产' },
]
const CustomDirectoryModal = (props) => {
const { visible, onCancel, action, dirId } = props;
const { visible, onCancel, action, dirId, reference = AssetManageReference } = props;
const [ keyword, setKeyword ] = useState('');
const [ data, setData ] = useState([]);
......@@ -67,11 +74,33 @@ const CustomDirectoryModal = (props) => {
}
const getPreviewTreeData = () => {
dispatchLatest({
type: 'assetmanage.previewTreeByCustomElements',
payload: {
if ((checkedValues||[]).length === 0) {
return;
}
let url = 'assetmanage.previewTreeByCustomElements';
let payload = {
data: checkedValues
},
}
if (reference===AssetManageReference) {
payload.params = {
resourceTypes: (form.getFieldValue('resourceTypes')||[]).join(',')
};
}
if (reference===AssetBrowseReference || reference===ResourceBrowseReference) {
url = 'assetmanage.previewTreeByCustomElementsAndResourceType';
payload.params = {
resourceType: (reference===ResourceBrowseReference)?'resource':'dataAsset',
}
}
dispatchLatest({
type: url,
payload,
callback: data => {
setPreviewTreeData((data||[]).length>0?data[0]:{});
}
......@@ -98,6 +127,12 @@ const CustomDirectoryModal = (props) => {
setCheckedData(_checkedData);
}
const onValuesChange = (changedValues, allValues) => {
if (changedValues.hasOwnProperty('resourceTypes')) {
getPreviewTreeData();
}
}
const reset = () => {
setConfirmLoading(false);
setKeyword('');
......@@ -127,8 +162,23 @@ const CustomDirectoryModal = (props) => {
payload.params = {...payload.params, dirId};
}
let url = 'assetmanage.saveTreeByCustomElements';
if (reference===AssetManageReference) {
payload.params = {
...payload.params,
resourceTypes: (row.resourceTypes||[]).join(',')
}
}
if (reference===AssetBrowseReference || reference===ResourceBrowseReference) {
url = 'assetmanage.saveTreeByCustomElementsAndResourceType';
payload.params = { ...payload.params, resourceType: (reference===ResourceBrowseReference)?'resource':'dataAsset' };
}
dispatch({
type: 'assetmanage.saveTreeByCustomElements',
type: url,
payload,
callback: data => {
setConfirmLoading(false);
......@@ -194,6 +244,7 @@ const CustomDirectoryModal = (props) => {
title={action==='add'?'新增自定义':'修改自定义'}
visible={visible}
width={800}
centered
confirmLoading={confirmLoading}
onCancel={() => {
reset();
......@@ -203,10 +254,10 @@ const CustomDirectoryModal = (props) => {
>
<Row gutter={30}>
<Col span={8} style={{ borderRight: '1px solid #EFEFEF' }}>
<div className='mb-3'>资产要素</div>
<div className='mb-3'>资产目录要素</div>
<Input
value={keyword}
placeholder='请输入资产要素'
placeholder='请输入资产目录要素'
style={{ marginBottom:10 }}
onChange={(e) => { onSearchChange(e) }}
/>
......@@ -244,7 +295,7 @@ const CustomDirectoryModal = (props) => {
</div>
</>
}
<Form className='mt-5' {...formItemLayout} form={form}>
<Form className='mt-5' {...formItemLayout} form={form} onValuesChange={onValuesChange}>
<Form.Item
label='命名'
name='name'
......@@ -252,6 +303,20 @@ const CustomDirectoryModal = (props) => {
>
<Input />
</Form.Item>
{
reference===AssetManageReference && <Form.Item
label='数据范围'
name='resourceTypes'
>
<Select mode="multiple" allowClear>
{
resourceTypes.map((item,index) => {
return <Select.Option key={item.key}>{item.name}</Select.Option>
})
}
</Select>
</Form.Item>
}
<Form.Item
label='描述或原因'
name='desc'
......
import React, { useEffect, useState } from 'react';
import { Button, Upload, Modal, Select, Space, Spin } from 'antd';
import { DownloadOutlined, UploadOutlined } from '@ant-design/icons';
import LocalStorage from 'local-storage';
import { dispatchLatest, dispatch } from '../../../../model';
import { showMessage } from '../../../../util';
const FC = (props) => {
const { onCancel, visible } = props;
const [ resourceTypes, setResourceTypes ] = useState(undefined);
const [ currentResourceType, setCurrentResourceType ] = useState(undefined);
const [ loading, setLoading ] = useState(false);
useEffect(() => {
if (visible) {
getResourceTypes();
}
}, [visible])
const getResourceTypes = () => {
setLoading(true);
dispatch({
type: 'assetmanage.getResourceTypes',
callback: data => {
setLoading(false);
setResourceTypes(data);
if ((data||[]).length > 0) {
setCurrentResourceType(data[0].code);
}
},
error: () => {
setLoading(false);
}
})
}
const handleOk = () => {
if (!currentResourceType) {
showMessage('info', '请先选择资产类型');
return;
}
const env = LocalStorage.get('assetsEnv');
window.open(`/api/dataassetmanager/elementApi/export?env=${env}&resourceType=${currentResourceType}`);
reset();
onCancel();
}
const reset = () => {
setLoading(false);
}
return (
<Modal
forceRender
visible={visible}
title='资产属性导出'
width={520}
onCancel={() => {
reset();
onCancel && onCancel();
}}
onOk={handleOk}
>
<Spin spinning={loading} >
<div className='mb-3 flex'>
<Select
value={currentResourceType}
placeholder='请选择资产类型'
onChange={(val) => {
setCurrentResourceType(val);
}}
style={{ width: 200 }}
>
{
resourceTypes?.map((item,index) => {
return <Select.Option key={item.code}>{item.name}</Select.Option>
})
}
</Select>
</div>
</Spin>
</Modal>
)
}
export default FC;
\ No newline at end of file
......@@ -3,6 +3,7 @@ import { Row, Col, Checkbox, Typography, Button, Switch, Modal } from 'antd';
import { dispatch } from '../../../../model';
import './FilterElementModal.less';
import { AssetManageReference } from '../../../../util/constant';
//type
//global 全局设置
......@@ -11,7 +12,7 @@ import './FilterElementModal.less';
const FilterElementModal = (props) => {
const { visible, onCancel, type = 'global' } = props;
const { visible, onCancel, type = 'global', reference = AssetManageReference } = props;
const [ elements, setElements ] = useState([]);
const [ typesOfElements, setTypesOfElements ] = useState([]);
const [ selectedKeys, setSelectedKeys ] = useState([]);
......@@ -28,14 +29,19 @@ const FilterElementModal = (props) => {
const getAllFilterElementIdsThenGetAllElements = () => {
let url = '';
let payload = null;
if (type === 'global') {
url = 'assetmanage.listFilterElementIdsConfig';
} else {
url = 'assetmanage.listFilterElementIds';
payload = {
isAdmin: (reference===AssetManageReference)
}
}
dispatch({
type: url,
payload,
callback: data => {
setSelectedKeys(data||[]);
getAllElements();
......@@ -123,7 +129,10 @@ const FilterElementModal = (props) => {
dispatch({
type: url,
payload: {
data: selectedKeys
data: selectedKeys,
params: {
isAdmin: (reference===AssetManageReference)
}
},
callback: () => {
reset();
......@@ -148,7 +157,7 @@ const FilterElementModal = (props) => {
<Modal
forceRender
visible={visible}
title={type==='global'?'资产属性管理':'可见列设置'}
title={type==='global'?'资产目录浏览管理':'可见列设置'}
width={520}
onCancel={cancel}
footer={[
......
import React, { useState, useEffect } from 'react';
import { Button, Upload, Drawer, Table, Pagination, Divider, Form, Select } from 'antd';
import React, { useState, useEffect, useContext } from 'react';
import { Button, Upload, Drawer, Table, Pagination, Divider, Form, Typography } from 'antd';
import { UploadOutlined, DownloadOutlined } from '@ant-design/icons';
import LocalStorage from 'local-storage';
import { dispatch } from '../../../../model';
import { showMessage, formatDate } from '../../../../util';
import { AppContext } from '../../../../App';
import { getTemplateType } from '../../../../util/axios';
const ImportAssetDrawer = (props) => {
const { onCancel, onSuccess, visible, nodeId } = props;
......@@ -16,8 +17,9 @@ const ImportAssetDrawer = (props) => {
const [ pagination, setPagination ] = useState( { pageNum: 1, pageSize: 20 } );
const { pageNum, pageSize } = pagination;
const [ total, setTotal ] = useState(0);
const [ resourceTypes, setResourceTypes ] = useState(undefined);
const [ currentResourceType, setCurrentResourceType ] = useState(undefined);
const [ users, setUsers ] = useState([]);
const app = useContext(AppContext);
const columns = [
{
......@@ -60,6 +62,14 @@ const ImportAssetDrawer = (props) => {
dataIndex: 'operator',
width: 100,
ellipsis: true,
render: (text, record) => {
const user = users?.filter((user)=>user.pernr===text);
if (user && user.length > 0) {
return user[0].nachn?`${user[0].nachn}(${user[0].pernr})`:user[0].pernr;
}
return text;
}
},
{
title: '导入状态',
......@@ -72,41 +82,15 @@ const ImportAssetDrawer = (props) => {
if (visible) {
setPagination({ pageNum: 1, pageSize: 20 });
getUsers();
getLogs();
getResourceTypes();
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [visible])
const getResourceTypes = () => {
dispatch({
type: 'assetmanage.getResourceTypes',
callback: data => {
setResourceTypes(data);
if ((data||[]).length > 0) {
setCurrentResourceType(data[0].code);
}
}
})
}
const downloadTemplate = () => {
if (!currentResourceType) {
showMessage('warn', '请先选择资产类型');
return;
}
const env = LocalStorage.get('assetsEnv');
dispatch({
type: 'assetmanage.getDirectoryById',
payload: {
dirId: nodeId
},
callback: data => {
window.open(`/api/dataassetmanager/dataAssetApi/getImportTemplate?env=${env}&resourceType=${currentResourceType}`);
}
})
window.open(`/api/dataassetmanager/dataAssetApi/getImportTemplate?templateType=${getTemplateType()}`);
}
const getLogs = (p = 1, s = 20) => {
......@@ -128,6 +112,15 @@ const ImportAssetDrawer = (props) => {
})
}
const getUsers = () => {
dispatch({
type: 'pds.getOwners',
callback: (data) => {
setUsers(data);
}
})
}
const uploadProps = {
onRemove: file => {
......@@ -154,24 +147,21 @@ const ImportAssetDrawer = (props) => {
};
const handleOk = () => {
if (!currentResourceType) {
showMessage('warn', '请先选择资产类型');
return;
}
if ((fileList||[]).length === 0) {
showMessage('info', '请先选择模上传');
showMessage('info', '请先选择模上传');
return;
}
setConfirmLoading(true);
dispatch({
type: 'assetmanage.assetImport',
payload: { fileList: fileList, params: { dirId: nodeId, resourceType: currentResourceType } },
payload: { fileList: fileList, params: { env: `${app?.env?.domainId}` } },
callback: data => {
setConfirmLoading(false);
setFileList([]);
getLogs(pageNum, pageSize);
showMessage('success', '导入动作完成,详情查看日志');
onSuccess && onSuccess(data||'');
},
error: () => {
......@@ -189,7 +179,7 @@ const ImportAssetDrawer = (props) => {
<Drawer
forceRender
visible={ visible }
title='资产导入'
title='资产目录导入'
width={900}
placement="right"
closable={ true }
......@@ -198,11 +188,11 @@ const ImportAssetDrawer = (props) => {
onCancel && onCancel();
}}
>
<div className='mt-3 flex' style={{ justifyContent: 'space-between' }}>
<div className='mt-3'>
<Form layout='inline'>
<Form.Item label='Word上传:'>
<Form.Item label='Excel导入:'>
<Button className='mr-2' icon={<DownloadOutlined />} onClick={ downloadTemplate }>
下载
下载
</Button>
<Upload style={{ display: 'inline' }} {...uploadProps }>
<Button icon={
......@@ -214,21 +204,8 @@ const ImportAssetDrawer = (props) => {
<Form.Item>
<Button type='primary' onClick={handleOk} loading={confirmLoading}>确定导入</Button>
</Form.Item>
<Button onClick={() => getLogs()} style={{ marginLeft: 'auto' }}>刷新日志</Button>
</Form>
<Select
value={currentResourceType}
placeholder='请选择资产类型'
onChange={(val) => {
setCurrentResourceType(val);
}}
style={{ width: 200 }}
>
{
resourceTypes?.map((item,index) => {
return <Select.Option key={item.code}>{item.name}</Select.Option>
})
}
</Select>
</div>
<Divider orientation="left">导入日志</Divider>
<Table
......@@ -239,7 +216,11 @@ const ImportAssetDrawer = (props) => {
pagination={false}
loading={loading}
expandable={{
expandedRowRender: record => <p style={{ margin: 0 }}>{record.message||''}</p>
expandedRowRender: record => <React.Fragment>
{record.message?.split('<br/>').map((info, index) => {
return <Typography.Paragraph key={index}>{info}</Typography.Paragraph>
})}
</React.Fragment>
}}
sticky
/>
......
......@@ -4,6 +4,7 @@ import { UploadOutlined } from '@ant-design/icons';
import { dispatch } from '../../../../model';
import { showNotifaction } from '../../../../util';
import { getTemplateType } from '../../../../util/axios';
const ImportDirectory = (props) => {
const { visible, onCancel, dirId } = props;
......@@ -41,7 +42,7 @@ const ImportDirectory = (props) => {
}
const download = () => {
window.open("/data-govern/docs/AssetThemeModel.xlsx");
window.open(`/api/dataassetmanager/directoryApi/getImportTemplate?templateType=${getTemplateType()}`);
}
const upload = async (ignoreRepeatPath = false) => {
......@@ -51,23 +52,12 @@ const ImportDirectory = (props) => {
setUploading(true);
let payload;
if (row.type === 'root') {
payload = {
const payload = {
params: {
ignoreRepeatPath
},
fileList: fileList,
};
} else {
payload = {
params: {
ignoreRepeatPath,
parentPath: dir.path
},
fileList: fileList
};
}
dispatch({
type: 'assetmanage.directoryImport',
......@@ -143,7 +133,7 @@ const ImportDirectory = (props) => {
onCancel={() => { onCancel && onCancel() }}
footer={
<Space>
<Button type="primary" onClick={ download } >下载</Button>
<Button type="primary" onClick={ download } >下载</Button>
<Button type="primary" onClick={() => { upload(false); } } loading={uploading}>上传</Button>
<Button onClick={() => { onCancel && onCancel() }}>返回</Button>
</Space>
......@@ -152,13 +142,10 @@ const ImportDirectory = (props) => {
<Form {...formItemLayout} form={form}>
<Form.Item
label="挂载位置"
name="type"
// name="type"
rules={[{ required: true, message: '必填项'}]}
>
<Radio.Group >
<Radio value='root' >根节点导入</Radio>
<Radio value='self' disabled={ dirId===null }>选中节点导入</Radio>
</Radio.Group>
<span>根节点导入</span>
</Form.Item>
<Form.Item
label="文件"
......
import React, { useEffect, useState } from 'react';
import { Button, Upload, Modal, Select, Space, Spin } from 'antd';
import React, { useState } from 'react';
import { Button, Upload, Modal } from 'antd';
import { DownloadOutlined, UploadOutlined } from '@ant-design/icons';
import { dispatchLatest, dispatch } from '../../../../model';
import { dispatchLatest } from '../../../../model';
import { showMessage } from '../../../../util';
import { getTemplateType } from '../../../../util/axios';
const ImportElement = (props) => {
const { onCancel, visible } = props;
const [ fileList, setFileList ] = useState([]);
const [ confirmLoading, setConfirmLoading ] = useState(false);
const [ resourceTypes, setResourceTypes ] = useState(undefined);
const [ currentResourceType, setCurrentResourceType ] = useState(undefined);
const [ loading, setLoading ] = useState(false);
useEffect(() => {
if (visible) {
getResourceTypes();
}
}, [visible])
const getResourceTypes = () => {
setLoading(true);
dispatch({
type: 'assetmanage.getResourceTypes',
callback: data => {
setLoading(false);
setResourceTypes(data);
if ((data||[]).length > 0) {
setCurrentResourceType(data[0].code);
}
},
error: () => {
setLoading(false);
}
})
}
const downloadTemplate = () => {
window.open("/data-govern/docs/ElementModel.xlsx");
window.open(`/api/dataassetmanager/elementApi/getImportTemplate?templateType=${getTemplateType()}`);
}
const uploadProps = {
......@@ -61,19 +36,14 @@ const ImportElement = (props) => {
const handleOk = () => {
if ((fileList||[]).length === 0) {
showMessage('info', '请先选择模上传');
showMessage('info', '请先选择模上传');
return;
}
setConfirmLoading(true);
dispatchLatest({
type: 'assetmanage.importElement',
payload: {
params: {
resourceType: currentResourceType
},
fileList
},
payload: { fileList },
callback: data => {
setConfirmLoading(false);
reset();
......@@ -87,15 +57,13 @@ const ImportElement = (props) => {
const reset = () => {
setFileList([]);
setLoading(false);
setConfirmLoading(false);
}
return (
<Modal
forceRender
visible={visible}
title='资产属性导入'
title='资产目录属性导入'
width={520}
confirmLoading={confirmLoading}
onCancel={() => {
......@@ -104,34 +72,18 @@ const ImportElement = (props) => {
}}
onOk={handleOk}
>
<Spin spinning={loading} >
<div className='mb-3 flex'>
<Select
value={currentResourceType}
placeholder='请选择资产类型'
onChange={(val) => {
setCurrentResourceType(val);
}}
style={{ width: 200 }}
>
{
resourceTypes?.map((item,index) => {
return <Select.Option key={item.code}>{item.name}</Select.Option>
})
}
</Select>
<div>
<Button icon={<DownloadOutlined />} onClick={ downloadTemplate }>
模板下载
</Button>
</div>
<Space>
<div className='mt-3'>
<Upload {...uploadProps}>
<Button icon={<UploadOutlined />}>
选择文件上传
</Button>
</Upload>
<Button icon={<DownloadOutlined />} onClick={ downloadTemplate }>
模版下载
</Button>
</Space>
</Spin>
</div>
</Modal>
)
}
......
......@@ -9,7 +9,7 @@ const FC = ({ value = '', terms = [] }) => {
{
appValue => <a onClick={() => {
appValue?.setGlobalState && appValue?.setGlobalState({
message: 'data-govern-show-standard-detail-message',
message: 'data-govern-show-index-detail-message',
data: { name: value }
})
}}>
......
......@@ -2,9 +2,10 @@ import React from 'react';
import { Button } from 'antd';
import { SettingFilled } from '@ant-design/icons';
import { highlightSearchContentByTerms } from '../../../../util';
import { AppContext } from '../../../../App';
const MetadataInfo = ({ value = '', config = true }) => {
const MetadataInfo = ({ value = '', config = true, terms = [] }) => {
let metadata = {};
try {
......@@ -18,13 +19,13 @@ const MetadataInfo = ({ value = '', config = true }) => {
{
value => <div className='flex'>
{
(typeof metadata==='string') ? <span style={{ marginRight: 5 }}>{metadata||''}</span> : <div className='flex' style={{ flexDirection: 'column' }}>
(typeof metadata==='string') ? <span style={{ marginRight: 5 }}>{highlightSearchContentByTerms(metadata||'', terms)}</span> : <div className='flex' style={{ flexDirection: 'column' }}>
<a onClick={() => {
value?.setGlobalState && value?.setGlobalState({
message: 'data-govern-show-metadata-message',
data: metadata
})
}} style={{ marginRight: 5, marginTop: config?5:0 }}>{metadata?.tableName||''}
}} style={{ marginRight: 5, marginTop: config?5:0 }}>{highlightSearchContentByTerms(metadata?.tableName||'',terms)}
</a>
{
(metadata?.columnItems||[]).map((item, index) => {
......@@ -36,7 +37,7 @@ const MetadataInfo = ({ value = '', config = true }) => {
_content += item.metadataColumnName||'';
return <span key={index}>{_content}</span>
return <span key={index}>{highlightSearchContentByTerms(_content,terms)}</span>
})
}
</div>
......
import React, { useEffect, useState } from "react";
import { Modal, Button, Space, Tree, Row, Col, Table, Pagination, Select, Input, Divider, Spin } from "antd";
import { getAttributesByMetadataModel } from "../../../../service/dataassetmanager";
import { dispatch } from '../../../../model';
import { showMessage } from "../../../../util";
import useDebounce from "../../../../layout/useDebounce";
const options = [
{ name: '基础数据名称', key: 'name' },
{ name: '基础数据编码', key: 'code' },
]
const FC = (props) => {
const { visible, onCancel, id } = props;
const [treeData, setTreeData] = useState(undefined);
const [tableData, setTableData] = useState(undefined);
const [total, setTotal] = useState(0);
const [ pagination, setPagination ] = useState( { pageNum: 1, pageSize: 20 } );
const [loadingTree, setLoadingTree] = useState(false);
const [loadingTable,setLoadingTable] = useState(false);
const [currentTreeParams, setCurrentTreeParams] = useState({
treeId: undefined,
dataType: undefined,
});
const [queryProperty, setQueryProperty] = useState(options[0].key);
const [keyword, setKeyword] = useState(undefined);
const debouncedKeyword = useDebounce(keyword, 300);
const { pageNum, pageSize } = pagination;
const columns = [
{
title: '序号',
dataIndex: 'key',
render: (text, record, index) => {
return (index+1).toString();
},
width: 60,
ellipsis: true,
},
{
title: '基础数据编码',
dataIndex: 'code',
ellipsis: true,
render: (text, record) => {
return <a onClick={() => {
onOk(record._id);
}}>
{text}
</a>
}
},
{
title: '基础数据名称',
dataIndex: 'name',
ellipsis: true,
render: (text, record) => {
return <a onClick={() => {
onOk(record._id);
}}>
{text}
</a>
}
},
];
useEffect(() => {
if (visible) {
getTreeData();
}
}, [visible])
useEffect(() => {
if (visible && currentTreeParams.treeId) {
getTableData();
}
}, [visible, pagination, currentTreeParams, queryProperty, debouncedKeyword])
const getTreeData = () => {
setLoadingTree(true);
dispatch({
type: 'assetmanage.getStandardTree',
payload: {
namePath: 0,
needOrg: true,
parentClass: 'Catalog'
},
callback: data => {
setLoadingTree(false);
const filterData = data?.filter(item => item.name !== '草稿');
if (filterData && filterData.length > 0) {
if (filterData[0].cnName === '指标标准') {
setCurrentTreeParams({ treeId: filterData[0]._id, dataType: 'IndicatorStandard' });
} else if (filterData[0].cnName === '维度标准') {
setCurrentTreeParams({ treeId: filterData[0]._id, dataType: 'DimensionStandard' });
} else {
setCurrentTreeParams({ treeId: filterData[0]._id, dataType: filterData[0].type });
}
}
setTreeData(filterData);
},
error: () => {
setLoadingTree(false);
}
});
}
const getTableData = () => {
setLoadingTable(true);
dispatch({
type: 'assetmanage.getStandardList',
payload: {
params: {
page: pageNum,
size: pageSize,
parentId: currentTreeParams.treeId,
keyword: debouncedKeyword,
queryProperty: queryProperty,
},
data: [`Catalog,StandardCatalog,${currentTreeParams.dataType}`]
},
callback: data => {
setLoadingTable(false);
data.content?.forEach(item => {
item.children = null;
});
setTableData(data.content);
setTotal(data.totalElements);
},
error: () => {
setLoadingTable(false);
}
});
}
const onOk = (standardId) => {
dispatch({
type: 'assetmanage.getMetadataStandardList',
payload: {
data: {
metadataId: id
},
params: {
page: 1,
size: 999999
}
},
callback: data => {
if ((data.content||[]).length === 0) {
dispatch({
type: 'assetmanage.standardBatchMetadata',
payload: {
params: {
metadataIds: id,
standardId
},
},
callback: () => {
showMessage('success', '关联成功');
onCancel?.(true);
}
});
} else {
dispatch({
type: 'assetmanage.deleteStandardBatchMetadata',
payload: {
params: {
ids: data.content?.map(item => item.id).toString()
}
},
callback: () => {
dispatch({
type: 'assetmanage.standardBatchMetadata',
payload: {
params: {
metadataIds: id,
standardId
},
},
callback: () => {
showMessage('success', '关联成功');
onCancel?.(true);
}
});
}
});
}
},
});
}
const onTreeSelect = (keys, {node}) => {
if (keys.length > 0) {
let paths = node.namePath.split(',');
if(paths[1]==='指标标准'){
setCurrentTreeParams({ treeId: keys[0], dataType: 'IndicatorStandard' });
}else if(paths[1]==='维度标准'){
setCurrentTreeParams({ treeId: keys[0], dataType: 'DimensionStandard' });
}else{
setCurrentTreeParams({ treeId: keys[0], dataType: node.type });
}
}
}
const onSelectChange = (value) => {
setQueryProperty(value);
}
const onSearchChange = (e) => {
setKeyword(e.target.value);
}
const changeCurrent = (page,size) => {
setPagination({ pageNum: page, pageSize: size });
}
const reset = () => {
setLoadingTree(false);
setLoadingTable(false);
setCurrentTreeParams({
treeId: undefined,
dataType: undefined,
});
setQueryProperty(options[0].key);
setKeyword(undefined);
setPagination({ pageNum: 1, pageSize: 20 });
}
const loop = (data) =>
data?.map(item => {
if (item.children && item.children.length>0) {
return {...item, title: item.name, key: item._id, children: loop(item.children)};
}
return {...item, title: item.name, key: item._id, children: null};
});
return (
<Modal
title='选择标准'
visible={ visible }
centered
width='90%'
onCancel={() => {
reset();
onCancel?.();
}}
footer={
<Space>
<Button onClick={() => {
reset();
onCancel?.();
}}>取消</Button>
</Space>
}
bodyStyle={{ padding: '24px', height: '70vh', overflow: 'auto' }}
>
<Row>
<Col span={5}>
<Spin spinning={loadingTree}>
<Tree
showLine={true}
showIcon={false}
treeData={loop(treeData)}
onSelect={onTreeSelect}
selectedKeys={currentTreeParams.treeId ? [currentTreeParams.treeId]: undefined}
/>
</Spin>
</Col>
<Col span={1}>
<div style={{ width: 1, height: 'calc(70vh - 48px)', backgroundColor: '#f0f0f0' }} ></div>
</Col>
<Col span={18}>
<div>
<Space>
<Select
value={queryProperty}
onChange={onSelectChange}
style={{ width: 160 }}
>
{
options.map((option, index) => {
return (
<Select.Option key={index} value={option.key} >{option.name}</Select.Option>
)
})
}
</Select>
<Input value={keyword} onChange={onSearchChange} placeholder='请输入关键字' />
</Space>
</div>
<Divider style={{ margin: '10px 0' }} />
<Table
loading={loadingTable}
columns={columns}
dataSource={tableData||[]}
rowKey='_id'
pagination={false}
/>
<Pagination
className="m-3"
size='small'
position={['bottomLeft']}
onChange={changeCurrent}
onShowSizeChange={changeCurrent}
current={pageNum}
pageSize={pageSize}
defaultCurrent={1}
total={total}
showTotal={total => `共 ${total} 条`}
/>
</Col>
</Row>
</Modal>
)
}
export default FC;
\ No newline at end of file
import React, { useState, useContext } from 'react';
import { Modal, Form, Input } from 'antd';
import { dispatchLatest } from '../../../../model';
import { showNotifaction } from '../../../../util';
import { AppContext } from '../../../../App';
const StartFlowModal = (props) => {
const { visible, onCancel, ids } = props;
const [ form ] = Form.useForm();
const [ confirmLoading, setConfirmLoading ] = useState(false);
const app = useContext(AppContext);
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 20 },
},
};
const handleOk = async () => {
try {
const values = await form.validateFields();
setConfirmLoading(true);
dispatchLatest({
type: 'assetmanage.startFlow',
payload: {
params: {
env: app?.env?.domainId,
dataAssetIds: ids.join(','),
applyReason: values?.desc
}
},
callback: data => {
reset();
if (data) {
showNotifaction('申请提示', (data === 'ok')?'资产目录申请成功,请在我的流程》我的申请中查看详情':data, 5);
}
onCancel && onCancel(true);
},
error: () => {
setConfirmLoading(false);
}
})
} catch (errInfo) {
}
}
const reset = () => {
setConfirmLoading(false);
form.resetFields();
}
return (
<Modal
forceRender
visible={visible}
title='资产目录申请'
width={520}
confirmLoading={confirmLoading}
onCancel={() => {
reset();
onCancel && onCancel();
}}
onOk={handleOk}
>
<Form
{...formItemLayout}
form={form}
>
<Form.Item
label="申请原因"
name="desc"
rules={[{ required: true, message: '请在申请原因栏中描述用途说明以及必要性(资产目录和服务权限申请需要说明请求字段)' }]}
>
<Input.TextArea rows={6} />
</Form.Item>
</Form>
</Modal>
);
}
export default StartFlowModal;
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useMemo } from 'react';
import { Modal, Form, Input, Space, Button, Radio, Select } from 'antd';
import { dispatch } from '../../../../model';
import { showMessage } from '../../../../util';
// const resourceTypes = [
// { key: 'innerSource', name: '内部资源' },
// { key: 'outerSource', name: '外部资源' },
// // { key: 'innerSource', name: '内部资源' },
// // { key: 'outerSource', name: '外部资源' },
// { key: 'dataAsset', name: '资产' },
// { key: 'custom', name: '自定义' },
// ]
const CodeInput = ({ value = '', onChange, restrict = false, action }) => {
const onCodeChange = (e) => {
if (!restrict || (
restrict&&(e.target.value===''||/^[A-Z]+$/.test(e.target.value))
)) {
onChange?.(e.target.value);
}
}
return <Input
placeholder="请输入编号(只允许输入大写英文字母,并且最多3个)"
disabled={action!=='add'}
maxLength={restrict?3:null}
value={value}
onChange={onCodeChange}
/>
}
const UpdateDirectoryModal = (props) => {
const { visible, onCancel, dirId, action } = props;
......@@ -18,7 +38,6 @@ const UpdateDirectoryModal = (props) => {
const [ dir, setDir ] = useState(null);
const [ confirmLoading, setConfirmLoading ] = useState(false);
const [ isThemeAdd, setIsThemeAdd ] = useState(false);
const [ resourceTypes, setResourceTypes ] = useState(undefined);
useEffect(() => {
......@@ -26,7 +45,10 @@ const UpdateDirectoryModal = (props) => {
setDir(null);
form.resetFields();
getResourceTypes();
if (action === 'add') {
form.setFieldsValue({ resourceType: 'dataAsset' });
}
if ((dirId||'')!=='') {
getDirectory();
}
......@@ -35,15 +57,18 @@ const UpdateDirectoryModal = (props) => {
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [ visible ])
const getResourceTypes = () => {
dispatch({
type: 'assetmanage.getResourceTypes',
callback: data => {
setResourceTypes(data);
}
})
const codeRestrict = useMemo(() => {
if (action === 'add') {
if (isThemeAdd) return true;
return (dir && dir.level === 1) ? true : false;
} else {
return (dir && dir.level <= 2) ? true : false;
}
return false;
}, [action, dir, isThemeAdd])
const getDirectory = () => {
setDir(null);
dispatch({
......@@ -55,7 +80,7 @@ const UpdateDirectoryModal = (props) => {
setDir(data);
if (action !== 'add') {
form.setFieldsValue({ code: data?.code, name: data?.name||'', desc: data?.desc||'', remarks: data?.remarks||'', resourceType: data?.resourceType });
form.setFieldsValue({ code: data?.code, name: data?.name||'', desc: data?.desc||'', remarks: data?.remarks||'' });
}
}
})
......@@ -73,7 +98,7 @@ const UpdateDirectoryModal = (props) => {
name: row.name,
desc: row.desc,
remarks: row.remarks,
resourceType: row.resourceType
resourceType: 'dataAsset',
}
};
......@@ -81,7 +106,7 @@ const UpdateDirectoryModal = (props) => {
if (row.type === 'directory') {
if (dir === null) {
showMessage('warn', '资产目录节点信息正在加载中...');
showMessage('warn', '资产目录的目录节点信息正在加载中...');
return;
}
......@@ -89,16 +114,19 @@ const UpdateDirectoryModal = (props) => {
parentPath: dir.path||''
}};
} else {
payload.data.resourceType = row.resourceType;
payload.data.resourceType = 'dataAsset';
}
} else {
if (dir === null) {
showMessage('warn', '资产目录节点信息正在加载中...');
showMessage('warn', '资产目录的目录节点信息正在加载中...');
return;
}
payload.data = { ...payload.data, ...{ order: dir.order, id: dirId } };
if (dir.level === 3) {
payload.data = { ...payload.data, code: dir.code };
}
const parentPath = dir.path.substring(0, dir.path.lastIndexOf("/"));;
payload = { ...payload, params: {
......@@ -111,6 +139,7 @@ const UpdateDirectoryModal = (props) => {
payload: payload,
callback: data => {
setConfirmLoading(false);
reset();
onCancel && onCancel(true, data?.id||'');
},
error: () => {
......@@ -123,16 +152,23 @@ const UpdateDirectoryModal = (props) => {
}
}
const reset = () => {
setIsThemeAdd(false);
setDir(undefined);
form.resetFields();
}
const onReset = () => {
if(action === 'add') {
setIsThemeAdd(false);
form.resetFields();
} else {
if (dir === null) {
showMessage('warn', '资产目录节点信息正在加载中...');
showMessage('warn', '资产目录的目录节点信息正在加载中...');
return;
}
form.resetFields();
form.setFieldsValue({ code: dir?.code, name: dir?.name||'', desc: dir?.desc||'', remarks: dir?.remarks||'' });
}
}
......@@ -140,6 +176,9 @@ const UpdateDirectoryModal = (props) => {
if (action==='add') {
if (changedValues.type === 'theme') {
setIsThemeAdd(true);
// if (allValues.code?.length > 3 || !(/^[A-Z]+$/.test(allValues.code))) {
// form.setFieldsValue({ code: '' });
// }
} else if (changedValues.type === 'directory') {
setIsThemeAdd(false);
}
......@@ -160,15 +199,21 @@ const UpdateDirectoryModal = (props) => {
return (
<Modal
forceRender
title={'资产目录信息'}
title={'资产目录的目录信息'}
visible={visible}
width={600}
onCancel={() => { onCancel && onCancel() }}
onCancel={() => {
reset();
onCancel && onCancel();
}}
footer={
<Space>
<Button type="primary" onClick={onOk} loading={confirmLoading}>提交</Button>
<Button onClick={onReset} >重置</Button>
<Button onClick={() => onCancel && onCancel() }>返回</Button>
<Button onClick={() => {
reset();
onCancel && onCancel();
}}>返回</Button>
</Space>
}
>
......@@ -180,34 +225,20 @@ const UpdateDirectoryModal = (props) => {
rules={[{ required: true, message: '必填项' }]}
>
<Radio.Group>
<Radio value='theme'>主题</Radio>
<Radio value='directory' disabled={ dirId===null }>目录</Radio>
<Radio value='theme'>栏目</Radio>
<Radio value='directory' disabled={ !dirId }>目录</Radio>
</Radio.Group>
</Form.Item>
}
{
((action==='add'&&isThemeAdd) || action!=='add') && <Form.Item
label="资产类型"
name="resourceType"
placeholder='请选择资产类型'
rules={[{ required: true, message: '必填项' }]}
>
<Select>
{
resourceTypes?.map((item,index) => {
return <Select.Option key={item.code}>{item.name}</Select.Option>
})
}
</Select>
</Form.Item>
}
<Form.Item
codeRestrict && <Form.Item
label="编号"
name="code"
rules={[{ required: true, message: '必填项' }]}
>
<Input placeholder="请输入编号" />
<CodeInput restrict={codeRestrict} action={action} />
</Form.Item>
}
<Form.Item
label="名称"
name="name"
......
import React, { useState, useEffect } from 'react';
import { Drawer, Pagination, List } from 'antd';
import { dispatch } from '../../../../model';
const WorkbookDrawer = (props) => {
const { onCancel, visible, type = 'tableau' } = props;
const [ loading, setLoading ] = useState(false);
const [ workbooks, setWorkbooks ] = useState([]);
const [ pagination, setPagination ] = useState( { pageNum: 1, pageSize: 20 } );
const { pageNum, pageSize } = pagination;
const [ total, setTotal ] = useState(0);
useEffect(() => {
if (visible) {
setPagination({ pageNum: 1, pageSize: 20 });
getWorkbooks();
}
//eslint-disable-next-line react-hooks/exhaustive-deps
}, [visible])
const getWorkbooks = (p = 1, s = 20) => {
setLoading(true);
const url = (type==='tableau') ? 'assetmanage.listWorkbooks' : 'assetmanage.listSmartBIWorkbooks';
dispatch({
type: url,
payload: {
pageNum: p,
pageSize: s
},
callback: data => {
setLoading(false);
setTotal(data.total);
setWorkbooks(data.data||[]);
},
error: () => {
setLoading(false);
}
})
}
// const onDeleteClick = (id) => {
// dispatch({
// type: 'assetmanage.deleteWorkbooks',
// payload: {
// data: [id]
// },
// callback: () => {
// getWorkbooks();
// }
// })
// }
const onDevelopClick = (id) => {
const url = (type==='tableau') ? 'assetmanage.getWorkbookUrl' : 'assetmanage.getSmartBIWorkbookUrl';
dispatch({
type: url,
payload: {
workbookId: id,
},
callback: data => {
window.open(data||'');
}
})
}
return (
<Drawer
forceRender
visible={ visible }
title={`${type}工作簿`}
width={900}
placement="right"
closable={ true }
onClose={() => {
onCancel && onCancel();
}}
>
<List
itemLayout="horizontal"
size="small"
loading={loading}
dataSource={workbooks}
renderItem={item => (
<List.Item
key={item.id}
actions={[<a key="develop" onClick={() => { onDevelopClick(item.id); }}>报表开发</a>]}
>
<List.Item.Meta
title={item.name}
/>
</List.Item>
)}
/>
<Pagination
className="text-center mt-3"
showSizeChanger
showQuickJumper
onChange={(_pageNum, _pageSize) => {
setPagination({ pageNum: _pageNum||1, pageSize: _pageSize || 20 });
getWorkbooks(_pageNum||1, _pageSize||20);
}}
onShowSizeChange={(_pageNum, _pageSize) => {
setPagination({ pageNum: _pageNum || 1, pageSize: _pageSize || 20 });
getWorkbooks(_pageNum||1, _pageSize||20);
}}
current={pageNum}
pageSize={pageSize}
defaultCurrent={1}
total={total}
pageSizeOptions={[10,20]}
showTotal={total => `共 ${total} 条`}
/>
</Drawer>
)
}
export default WorkbookDrawer;
\ No newline at end of file
import React, { useEffect, useState } from 'react';
import { Modal, Form, Button, Space, Input, Checkbox, Row, Col, Typography } from 'antd';
import { dispatch } from '../../../../model';
import { showMessage } from '../../../../util';
const WorksheetModal = (props) => {
const { onCancel, visible, id, type = 'tableau', metadata = {} } = props;
const [ confirmLoading, setConfirmLoading ] = useState(false);
const [ form ] = Form.useForm();
useEffect(() => {
if (visible) {
form?.setFieldsValue({ tableName: metadata?.tableName, columnNames: metadata?.columnItems?.map(item => item.metadataColumnName) });
}
}, [visible, type])
const onOk = async() => {
try {
const row = await form?.validateFields();
setConfirmLoading(true);
const url = (type === 'tableau') ? 'assetmanage.saveWorkbook': 'assetmanage.saveSmartBIWorkbook';
let metadataTableId = '';
metadata?.columnItems?.forEach(item => {
if (!metadataTableId) {
metadataTableId = item.metadataTableId;
}
})
dispatch({
type: url,
payload: {
data: {
dataAssetId:id,
metadataTableId,
...row,
}
},
callback: data => {
window.open(data);
reset();
setConfirmLoading(false);
showMessage("success","新增成功");
onCancel && onCancel(true);
},
error: () => {
setConfirmLoading(false);
}
})
} catch (errInfo) {
console.log('Validate Failed:', errInfo);
setConfirmLoading(false);
}
}
const reset = () => {
setConfirmLoading(false);
form?.resetFields();
}
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 3 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 21 },
},
};
return (
<Modal
forceRender
title='工作簿信息'
visible={ visible }
width={ 600 }
onCancel={() => {
reset();
onCancel && onCancel();
}}
footer={
<Space>
<Button onClick={() => {
reset();
onCancel && onCancel();
}}>取消</Button>
<Button type="primary" onClick={ onOk } loading={ confirmLoading }>确定</Button>
</Space>
}
>
<Form form={form} style={{ maxHeight: 600, overflow: 'auto' }} {...formItemLayout}>
<Form.Item
label="名称"
name="name"
rules={[{ required: true, message: '请填写工作簿名称!' }]}
>
<Input />
</Form.Item>
<Form.Item
label="字段"
name="columnNames"
>
<Checkbox.Group>
<Row>
{
metadata?.columnItems?.map((item, index) => <Col key={index} span={8}>
<Checkbox
value={item.metadataColumnName}
style={{
lineHeight: '32px',
}}
>
<Typography.Text style={{ width: 120 }} ellipsis>{item.metadataColumnName}</Typography.Text>
</Checkbox>
</Col>)
}
</Row>
</Checkbox.Group>
</Form.Item>
<Form.Item
label="元数据"
name="tableName"
hidden={true}
>
<Input />
</Form.Item>
</Form>
</Modal>
);
}
export default WorksheetModal;
\ No newline at end of file
......@@ -2,8 +2,9 @@ import React, { useState } from 'react';
import classNames from 'classnames';
import { Form } from 'antd';
import { CaretLeftOutlined, CaretRightOutlined } from '@ant-design/icons';
import { ResizableBox } from 'react-resizable';
import AssetTree from './Component/AssetTree';
import AssetTree from './Component/AssetManageTree';
import AssetDirectory from './Component/AssetDirectory';
import AssetTable from './Component/AssetTable';
import AssetAction from './Component/AssetAction';
......@@ -15,10 +16,12 @@ import './index.less';
const AssetManage = (props) => {
const [ nodeId, setNodeId ] = useState('');
const [ nodeId, setNodeId ] = useState(null);
const [ nodeType, setNodeType ] = useState('');
const [ nodeLevel, setNodeLevel ] = useState(null);
const [ assetParams, setAssetParams ] = useState({ assetId: '', assetDirId: '' })
const [ expandTree, setExpandTree ] = useState(true);
const [ assetFullScreen, setAssetFullScreen ] = useState(false);
const [ assetCount, setAssetCount ] = useState(0);
const [ directoryChanged, setDirectoryChanged ] = useState(false);
......@@ -28,9 +31,11 @@ const AssetManage = (props) => {
const { assetId, assetDirId } = assetParams;
const onTreeSelect = (value, type) => {
setNodeId(value||'');
const onTreeSelect = (value, type, level) => {
setNodeId(value);
setNodeType(type);
setNodeLevel(level);
}
const onTableSelect = (id, did) => {
......@@ -57,31 +62,45 @@ const AssetManage = (props) => {
setAssetCount(count);
}
const onFullScreenChange = (value) => {
setAssetFullScreen(value);
}
const classes = classNames('asset-manage', {
'asset-manage-collapse': !expandTree
});
const middleClasses = classNames('middle', {
'middle-fullscreen': assetFullScreen
});
return (
<div className={classes}>
<div className='left'>
<ResizableBox
className='left'
width={230}
height={Infinity}
axis='x'
minConstraints={[230, Infinity]} maxConstraints={[Infinity, Infinity]}
>
<AssetTree onSelect={onTreeSelect} onDirectoryChange={onDirectoryChange} {...props} />
</div>
</ResizableBox>
{
expandTree && <Separate width={15} />
}
<div className='middle'>
<AssetDirectory id={nodeId} assetCount={assetCount} directoryChanged={directoryChanged} onElementsChange={onElementsChange} />
<Separate height={15} />
<AssetTable nodeId={nodeId} nodeType={nodeType} reference={AssetManageReference} elementsChanged={elementsChanged} assetActionChanged={assetActionChanged} onSelect={onTableSelect} onCountChange={onAssetCountChange} {...props} />
</div>
<Separate width='15px' />
<div className='right'>
<AssetAction form={form} id={assetId} dirId={assetDirId} action='detail' onChange={onAssetActionChange} />
</div>
<div className={middleClasses}>
{/* <AssetDirectory id={nodeId} assetCount={assetCount} directoryChanged={directoryChanged} onElementsChange={onElementsChange} />
<Separate height={15} /> */}
<AssetTable nodeId={nodeId} nodeType={nodeType} nodeLevel={nodeLevel} reference={AssetManageReference} elementsChanged={elementsChanged} assetActionChanged={assetActionChanged} onSelect={onTableSelect} onCountChange={onAssetCountChange} onFullScreenChange={onFullScreenChange} {...props} />
<div className='tree-toggle' onClick={treeToggleClick}>
{ expandTree ? <CaretLeftOutlined /> : <CaretRightOutlined /> }
</div>
</div>
{/* <Separate width='15px' />
<div className='right'>
<AssetAction form={form} id={assetId} dirId={assetDirId} action='detail' onChange={onAssetActionChange} />
</div> */}
</div>
)
}
......
......@@ -5,7 +5,7 @@
height: 100%;
.left {
width: 230px;
flex: 0 0 auto;
border-right: 1px solid #EFEFEF;
overflow: hidden;
}
......@@ -14,7 +14,7 @@
display: flex;
justify-content: center;
align-items: center;
left: 245px;
left: 0px;
right: 0;
background: #f2f5fc;
position: absolute;
......@@ -28,7 +28,13 @@
}
.middle {
width: calc(100% - 230px - 400px - 30px);
position: relative;
flex: 1;
overflow: hidden;
}
.middle-fullscreen {
position: static;
}
.right {
......@@ -39,14 +45,10 @@
.asset-manage-collapse {
.left {
width: 0;
width: 0 !important;
}
.tree-toggle {
left: 0;
}
.middle {
width: calc(100% - 400px - 30px);
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@ import React, { useState } from "react";
import { Modal } from "antd";
import { dispatch } from '../../../../model';
import AssetTree from '../../AssetManage/Component/AssetTree';
import AssetTree from '../../AssetManage/Component/AssetManageTree';
import { showMessage } from '../../../../util';
import { AssetManageReference, AssetRecycleReference, AssetMountReference } from "../../../../util/constant";
......@@ -19,7 +19,7 @@ const AssetMount = (props) => {
const onOk = () => {
if ((dirIds||[]).length === 0) {
showMessage('warn', '请先选择资产目录');
showMessage('warn', '请先选择资产目录的目录');
return;
}
......@@ -50,6 +50,7 @@ const AssetMount = (props) => {
return(
<Modal
forceRender
title={(reference===AssetRecycleReference)?'挂载目录详情':'变更目录详情'}
visible={ visible }
width={ 400 }
......@@ -60,12 +61,14 @@ const AssetMount = (props) => {
}}
onOk={ onOk }
>
<AssetTree
{
visible && <AssetTree
checkable={true}
onCheck={onCheck}
tableId={(reference===AssetManageReference&&(ids||[].length>0))?ids[0]:''}
reference={AssetMountReference}
/>
}
</Modal>
)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment