index.jsx 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
  2. import moment from "moment";
  3. import {ProCard} from '@ant-design/pro-components';
  4. import {Button, Checkbox, Descriptions, Divider, message, Tag} from 'antd'
  5. import {styled} from 'styled-components'
  6. import {CheckCardList} from '../../components/CheckCardList.jsx';
  7. import {TreeMenu} from '../../components/TreeMenu';
  8. import {MoreOutlined} from '@ant-design/icons'
  9. import {DomainForm} from "../ModalManage/components/DomainForm";
  10. import {ActionIcon} from "../../components/ActionIcon";
  11. import {IndexCreator} from "./components/IndexCreator";
  12. import {IndexDetail} from "./components/IndexDetail";
  13. import {DEFINE_TYPE, FORM_TYPE, SEN_COLOR_LEVEL, SENSITIVE, STATUS_COLOR_LEVEL} from "./constants";
  14. import {IndexFilterForm} from "./components/IndexFilterForm";
  15. import {AUTH_TYPE, PUBLISH_TYPE, STATUS_TYPE, TYPE_ENUM} from "../../constants";
  16. import {ACTION_TYPES} from "../../components/WorkFlow/constants";
  17. import {AuthorizationPanel} from "./components/AuthorizationPanel";
  18. import {VolumeAuthPanel} from "./components/VolumeAuthPanel";
  19. import {useAppDispatch, useAppSelector} from "../../../redux/configureStore";
  20. import {selectDomains, selectIndexLibs} from "../MainPage/slice/selectors";
  21. import {bizConditionToSQL} from "../../../utils/listTools";
  22. import {
  23. batchPublish,
  24. batchRoleAuth,
  25. batchUnPublish,
  26. createDomain,
  27. createMetric,
  28. deleteMetric,
  29. getAuthList,
  30. getDomains,
  31. getIndexByConditions,
  32. getIndexDetail, getPersistenceConfig,
  33. getRoles,
  34. persistenceConfig,
  35. queryDimensions,
  36. roleAuthDelete,
  37. roleAuthGrant,
  38. updateMetric
  39. } from "../MainPage/slice/thunks";
  40. import useI18NPrefix from "../../hooks/useI18NPrefix";
  41. // TODO
  42. // 1.指标SQL创建AS中文,
  43. // 2.创建指标退出时SQL字段配置重置,
  44. // 5.批量设置、指标应用权限
  45. // 8.派生指标自动带入来自指标的维度
  46. export const IndexDefine = () => {
  47. const t = useI18NPrefix('global');
  48. const dispatch = useAppDispatch();
  49. /** 打开主题域表单 */
  50. const [domainModalOpen, setDomainModalOpen] = useState(false);
  51. /** 指标创建表单对话框打开状态 */
  52. const [openCreator, setOpenCreator] = useState(false);
  53. /** 指标卡片详情 */
  54. const [openDetail,setOpenDetail] = useState(false);
  55. /** 授权面板 */
  56. const [openAuth,setOpenAuth] = useState(false);
  57. /** 指标批量授权 */
  58. const [openIndexAuth,setOpenIndexAuth] = useState(false);
  59. /** 当前主题名称 */
  60. const [subTile,setSubTitle] = useState(t("title.baseInfo"));
  61. /** 筛选的Ref */
  62. const filterRef = useRef(null);
  63. /** 卡片列表的Ref,用于全选*/
  64. const cardListRef = useRef(null);
  65. /** 数据缓存*/
  66. const commonRef = useRef({
  67. treeSelect: {
  68. id:0,
  69. name:t("title.models")
  70. },
  71. indexCreator:{},
  72. indexDetail:{},
  73. datatype:'',
  74. metricSelect:{}
  75. });
  76. /** 主题域 */
  77. const domains = useAppSelector(selectDomains);
  78. /** 指标列表 */
  79. const indexLib = useAppSelector(selectIndexLibs);
  80. useEffect(()=>{
  81. /** 获取主题域 */
  82. dispatch(getDomains());
  83. dispatch(getRoles({}));
  84. },[]);
  85. /** 右键打开情景框 */
  86. const onRightClick=useCallback(({event})=>{
  87. event.preventDefault();
  88. },[]);
  89. /** 右键情景框选择后回调 */
  90. const onRightSelect = (event)=>{
  91. if (event.key==='update'){
  92. setDomainModalOpen(true)
  93. }
  94. if (event.key==='auth'){
  95. commonRef.current.datatype = TYPE_ENUM.DOMAIN
  96. setOpenAuth(true)
  97. }
  98. };
  99. /** 主题域表单提交-取消 */
  100. const handelDomainFormCancel=useCallback(()=>{
  101. setDomainModalOpen(false)
  102. },[]);
  103. /** 主题域表单-打开 */
  104. // const handelDomainFormOpen=useCallback(()=>{
  105. // setDomainModalOpen(true)
  106. // },[]);
  107. /** 主题域表单--提交 */
  108. const domainFormSubmit = useCallback((values) => {
  109. const {parentId} = values;
  110. const params = {
  111. ...values,
  112. parentId: parentId ? parentId : 0
  113. }
  114. dispatch(
  115. createDomain({
  116. params,
  117. resolve(){
  118. message.success(t("validation.success"));
  119. dispatch(getDomains());
  120. setDomainModalOpen(false);
  121. }
  122. })
  123. );
  124. },[]);
  125. /** 左侧主题树目录 */
  126. const buildTree = useMemo(()=>{
  127. const items = [
  128. {
  129. key: 'update',
  130. label: t("operation.update")
  131. },
  132. {
  133. key: 'auth',
  134. label: t("operation.auth")
  135. },
  136. {
  137. key: 'remove',
  138. label: t("operation.remove")
  139. }
  140. ];
  141. function insertKey(arr) {
  142. let temp = [];
  143. for (const i in arr) {
  144. const record = arr[i];
  145. const {children} = record;
  146. let item = {
  147. key: record.id,
  148. title:<ActionIcon trigger="contextMenu" items={items} children={record.title} onSelect={onRightSelect} tooltip="右键编辑"/>,
  149. data: record,
  150. isLeaf: children?.length===0,
  151. }
  152. if (children?.length>0) {
  153. item.children = insertKey(children)
  154. }
  155. temp.push(item)
  156. }
  157. return temp
  158. }
  159. return insertKey(domains)
  160. },[domains]);
  161. /** 侧边栏主题域钩子 */
  162. const onSelect = useCallback((keys, info) => {
  163. const {node} = info;
  164. if (commonRef.current.treeSelect?.id!==node?.data?.id){
  165. dispatch(getIndexByConditions({
  166. params:{
  167. domainIds: keys,
  168. current:1,
  169. pageSize:999
  170. },
  171. }))
  172. commonRef.current.treeSelect=node.data;
  173. }
  174. },[]);
  175. /** 侧边栏主题域搜索钩子 */
  176. const onSearch = useCallback(() => {},[]);
  177. /** 筛选表单提交 */
  178. const onFilterFormFinish = useCallback((filter)=>{
  179. dispatch(getIndexByConditions({
  180. params:{
  181. domainIds: [commonRef.current.treeSelect.id],
  182. ...filter,
  183. current:1,
  184. pageSize:999
  185. },
  186. }))
  187. },[]);
  188. /** 选择创建模式-回调 */
  189. const onModelSelect = useCallback((info) => {
  190. //setOpenCreator(true)
  191. if (commonRef.current.treeSelect.id){
  192. commonRef.current.indexCreator.type=info.value
  193. commonRef.current.indexCreator.sensitiveLevel="0"
  194. commonRef.current.indexCreator.invokeMethod='AUTO'
  195. commonRef.current.indexCreator.decimalPlaces = 2
  196. commonRef.current.indexCreator.domainId = commonRef.current.treeSelect.id
  197. commonRef.current.indexCreator.dataFormatType = 'DECIMAL'
  198. setOpenCreator(true)
  199. }else{
  200. message.error(t("validation.domain"))
  201. }
  202. }, []);
  203. /** 指标创建表单-提交 */
  204. const onCreatorFinish = useCallback((values)=>{
  205. try {
  206. const {
  207. id,domainId,type,decimalPlaces,relateDimension,dateDimId,
  208. measure,operations,sensitiveLevel,filters,formIndex,incrementPeriod,
  209. invokeMethod, periodId,runCycleCode,measureExpr, way, startTime,syncToBI
  210. } = values;
  211. let drillDownDimensions = [];
  212. if (relateDimension){
  213. dateDimId && drillDownDimensions.push({
  214. dimensionId:dateDimId,
  215. necessary:false,
  216. inheritedFromModel:false
  217. })
  218. relateDimension.forEach(v=>
  219. drillDownDimensions.push({
  220. dimensionId:v,
  221. necessary:false,
  222. inheritedFromModel:false
  223. }))
  224. }
  225. const bizCondition = bizConditionToSQL(filters);
  226. // 部分字段需再次处理
  227. let params = {
  228. ...values,
  229. alias:values?.name,
  230. sensitiveLevel:parseInt(sensitiveLevel),
  231. typeEnum:TYPE_ENUM.METRIC,
  232. dataFormat:{
  233. needMultiply100:false,
  234. decimalPlaces:decimalPlaces?decimalPlaces:2,
  235. },
  236. relateDimension:{
  237. drillDownDimensions
  238. },
  239. metricDefineType:DEFINE_TYPE[type],
  240. statisticsPeriod:periodId
  241. }
  242. // 派生指标
  243. if (type===FORM_TYPE.DERIVED.value){
  244. const formIndexObj=JSON.parse(formIndex);
  245. params.operations=formIndexObj?.operations
  246. params.ext = {filters}
  247. params.metricDefineByMeasureParams={
  248. measures:[
  249. {
  250. agg:formIndexObj?.operations,
  251. bizName:formIndexObj.bizName,
  252. constraint:measureExpr.expr||bizCondition,
  253. }
  254. ],
  255. expr:formIndexObj.expr,
  256. filterSql:""
  257. }
  258. }
  259. // 派生指标
  260. if (type!==FORM_TYPE.COMPOSITE.value) {
  261. params.metricDefineByMetricParams = {}
  262. }
  263. // 原子指标
  264. if (type===FORM_TYPE.ATOMIC.value) {
  265. if (measureExpr.expr){
  266. params.metricDefineType='CUSTOM'
  267. params.metricDefineByMeasureParams = {}
  268. params.metricDefineByFieldParams = {
  269. fields:measureExpr.metrics.map(item=>({fieldName:item.bizName,agg:'SUM'})),
  270. expr:measureExpr.expr,
  271. filterSql:""
  272. }
  273. }else {
  274. params.metricDefineByMeasureParams={
  275. measures:[
  276. {
  277. agg:operations,
  278. bizName:measure,
  279. constraint:"",
  280. }
  281. ],
  282. expr:measure,
  283. filterSql:""
  284. }
  285. }
  286. }
  287. // 更新、创建指标
  288. if (id){
  289. dispatch(updateMetric({
  290. params,
  291. resolve({id}){
  292. if (id){
  293. message.success(t("validation.success"));
  294. dispatch(getIndexByConditions({
  295. params:{
  296. domainIds: [domainId],
  297. current:1,
  298. pageSize:999
  299. },
  300. }))
  301. dispatch(persistenceConfig({
  302. params:{
  303. metricId:id,
  304. runCycleCode,
  305. tableName:'index_metric_'+id,
  306. defaultConfig:JSON.stringify({
  307. unit:1,
  308. period:incrementPeriod,
  309. type:invokeMethod,
  310. startTime,
  311. way,
  312. syncToBI
  313. }),
  314. }
  315. }))
  316. setOpenCreator(false)
  317. }
  318. }
  319. }))
  320. }else {
  321. dispatch(createMetric({
  322. params,
  323. resolve({id}){
  324. if (id){
  325. message.success(t("validation.success"));
  326. dispatch(getIndexByConditions({
  327. params:{
  328. domainIds: [commonRef.current.treeSelect.id],
  329. current:1,
  330. pageSize:999
  331. },
  332. }))
  333. dispatch(persistenceConfig({
  334. params:{
  335. metricId:id,
  336. runCycleCode,
  337. tableName:'index_metric_'+id,
  338. defaultConfig:JSON.stringify({
  339. metricTypeDefaultConfig:{
  340. timeDefaultConfig:{
  341. timeMode:"RECENT",
  342. unit:1,
  343. period:incrementPeriod,
  344. type:invokeMethod,
  345. startTime,
  346. way
  347. }
  348. },
  349. }),
  350. }
  351. }))
  352. setOpenCreator(false)
  353. }
  354. }
  355. }))
  356. }
  357. }catch (error) {
  358. throw error;
  359. }
  360. },[]);
  361. /** 双击打开详情 */
  362. const onCardDoubleClick = useCallback((event)=>{
  363. const {value,title,tag} = event;
  364. dispatch(getIndexDetail({
  365. id:value,
  366. resolve(detail){
  367. dispatch(queryDimensions({
  368. params:{
  369. ids:detail.drillDownDimensions.map(v=>v.dimensionId),
  370. },
  371. resolve(data){
  372. commonRef.current.indexDetail= {
  373. ...detail,
  374. title,
  375. tag,
  376. dimensions:data.list
  377. }
  378. setOpenDetail(true)
  379. }
  380. }))
  381. dispatch(getPersistenceConfig({
  382. id:value,
  383. resolve(data){
  384. commonRef.current.persistenceConfig = data
  385. }
  386. }))
  387. }
  388. }))
  389. },[]);
  390. /** 关闭详情 */
  391. const onDetailClose = useCallback(()=>{
  392. setOpenDetail(false)
  393. },[]);
  394. /** 查询指标 */
  395. const getMetrics = (domainIds)=>{
  396. dispatch(getIndexByConditions({
  397. params:{
  398. domainIds:[domainIds],
  399. current:1,
  400. pageSize:999
  401. },
  402. }))
  403. }
  404. /** 卡片Extra选项回调 */
  405. const onExtraSelect =(event,item)=>{
  406. const {
  407. id,
  408. domainId,
  409. title,
  410. tag,
  411. type,
  412. relateDimension,
  413. sensitiveLevel,
  414. metricDefineByMeasureParams,
  415. metricDefineByMetricParams,
  416. metricDefineType,
  417. dateDimId
  418. } = item;
  419. // 编辑指标
  420. if (event.key==="update"){
  421. let bizName
  422. if (type===FORM_TYPE.ATOMIC.value){
  423. // 原子指标回显维度
  424. if (metricDefineType==='MEASURE'){
  425. const measureParams = metricDefineByMeasureParams.measures[0]
  426. bizName = measureParams.bizName
  427. }
  428. }else if (type===FORM_TYPE.COMPOSITE.value){
  429. // 其他指标回显维度
  430. const measureParams = metricDefineByMetricParams.metrics[0]
  431. bizName = measureParams.bizName
  432. }
  433. commonRef.current.indexCreator = {
  434. ...item,
  435. sensitiveLevel:`${sensitiveLevel}`,
  436. measure:bizName,
  437. relateDimension:relateDimension.drillDownDimensions.filter((item)=>item.dimensionId!==dateDimId).map(item=>item.dimensionId)
  438. }
  439. setOpenCreator(true)
  440. }
  441. // 指标授权
  442. if (event.key==="auth"){
  443. commonRef.current.datatype=TYPE_ENUM.METRIC;
  444. commonRef.current.metricSelect=item;
  445. setOpenAuth(true)
  446. }
  447. // 删除指标
  448. if (event.key==="remove"){
  449. dispatch(deleteMetric({
  450. id,
  451. resolve(){
  452. if (domainId){
  453. dispatch(getIndexByConditions({
  454. params:{
  455. domainIds: [domainId],
  456. current:1,
  457. pageSize:999
  458. },
  459. }))
  460. }
  461. }
  462. }))
  463. }
  464. // 指标详情
  465. if (event.key==="detail"){
  466. dispatch(getIndexDetail({
  467. id,
  468. resolve(data){
  469. commonRef.current.indexDetail= {...data,title,tag}
  470. setOpenDetail(true)
  471. }
  472. }))
  473. }
  474. // 取消发布
  475. if (event.key==="disPublish"){
  476. dispatch(batchUnPublish({
  477. params:{
  478. ids:[id],
  479. type:"DELETE",
  480. },
  481. resolve(){
  482. getMetrics(domainId)
  483. message.success(t("validation.success"));
  484. }
  485. }))
  486. }
  487. // 发布指标
  488. if (event.key==="publish"){
  489. dispatch(batchPublish({
  490. params:{
  491. ids:[id],
  492. status:1,
  493. type:"ADD",
  494. },
  495. resolve(data){
  496. if (data){
  497. getMetrics(domainId)
  498. message.success(t("validation.success"));
  499. }else {
  500. message.error(t("validation.failed"));
  501. }
  502. }
  503. }))
  504. }
  505. }
  506. /** 指标列表 */
  507. const cardOption = useMemo(()=> (indexLib||[]).map((item)=>({
  508. title: item.name,
  509. tag:FORM_TYPE[item.type],
  510. value:item.id,
  511. description:item.description,
  512. extra:[
  513. <ActionIcon
  514. key={2}
  515. items={ACTION_TYPES.CHECK.filter(opt=>item.isPublish?opt.key!=="publish":opt.key!=="disPublish")}
  516. onSelect={(event)=>onExtraSelect(event,item)}
  517. >
  518. <Button type="link" ><MoreOutlined rotate={90} style={{fontSize:25}}/></Button>
  519. </ActionIcon>
  520. ],
  521. content:(
  522. <CustomDescriptions column={5}>
  523. <Descriptions.Item label={t("formItem.domain")}>{item.domainName}</Descriptions.Item>
  524. <Descriptions.Item label={t("formItem.metricCode")}>{item.bizName}</Descriptions.Item>
  525. <Descriptions.Item label={t("formItem.sensitiveLevel")} contentStyle={{color:SEN_COLOR_LEVEL[item.sensitiveLevel]}} children={SENSITIVE[item.sensitiveLevel]}/>
  526. <Descriptions.Item label={t("formItem.lastVersionNo")}>无</Descriptions.Item>
  527. <Descriptions.Item label={t("formItem.status")} contentStyle={{color:STATUS_COLOR_LEVEL[item.status]}} children={STATUS_TYPE[item.status]}/>
  528. <Descriptions.Item label={t("formItem.caliber")}>{item.alias}</Descriptions.Item>
  529. <Descriptions.Item label={t("formItem.director")}>{item.createdBy}</Descriptions.Item>
  530. <Descriptions.Item label={t("formItem.creator")}>{item.createdBy}</Descriptions.Item>
  531. <Descriptions.Item label={t("formItem.createDate")}>{moment(item.createdAt).format('YYYY-MM-DD hh:mm:ss')}</Descriptions.Item>
  532. <Descriptions.Item label={t("formItem.isPublish")} contentStyle={{color:STATUS_COLOR_LEVEL[item.isPublish]}} children={PUBLISH_TYPE[item.isPublish]}/>
  533. </CustomDescriptions>
  534. )
  535. })),[indexLib])
  536. /** 指标列表 */
  537. const onCardSelect = useCallback((e)=>setSubTitle(e),[])
  538. /** 创建指标面板-关闭 */
  539. const handelCreatorClose = useCallback(() => {
  540. commonRef.current.indexCreator = {}
  541. setOpenCreator(false)
  542. }, []);
  543. /** 卡片选中 */
  544. const onCardChecked = useCallback((list)=>{
  545. commonRef.current.indexChosen = list.map(item=>({id:item.value,value:item.value,label:item.title}))
  546. },[]);
  547. /** 关闭授权面板 */
  548. const onAuthPanelClose = useCallback(()=>setOpenAuth(false),[])
  549. /** 关闭授权面板 */
  550. const onIndexAuthPanelClose = useCallback(()=>setOpenIndexAuth(false),[])
  551. /** 关闭授权面板 */
  552. const onIndexAuthPanelOpen = useCallback(()=>setOpenIndexAuth(true),[])
  553. /** 批量授权回调*/
  554. const onAuthConfigChange=useCallback(()=>{},[])
  555. /** 批量发布按钮回调*/
  556. const onVolumePublish = useCallback(()=>{
  557. const {indexChosen,treeSelect} = commonRef.current
  558. const params = {
  559. ids:indexChosen.map(item=>item.id),
  560. status:1,
  561. type:"ADD"
  562. }
  563. dispatch(batchPublish({
  564. params,
  565. resolve(data){
  566. if (data){
  567. getMetrics(treeSelect.id)
  568. message.success(t("validation.success"));
  569. }else {
  570. message.error(t("validation.failed"));
  571. }
  572. }
  573. }))
  574. },[])
  575. /** 获取主题域 */
  576. const onGetAuthList = ()=>{
  577. dispatch(getAuthList({
  578. params:{
  579. dataType:commonRef.current.datatype
  580. }
  581. }))
  582. }
  583. /** 主题域授权 */
  584. const onDomainAuthFinish=useCallback((value)=>{
  585. dispatch(roleAuthGrant({
  586. params:value,
  587. resolve(){
  588. onGetAuthList()
  589. }
  590. }))
  591. },[])
  592. /** 删除授权 */
  593. const onAuthDelete = useCallback((row)=>{
  594. dispatch(roleAuthDelete({
  595. id:row.roleId,
  596. resolve(){
  597. onGetAuthList()
  598. }
  599. }))
  600. },[])
  601. /** 指标批量授权 */
  602. const onVolumeAuth=useCallback((value)=>{
  603. let authType = [];
  604. if (value.version){
  605. authType = authType.concat(AUTH_TYPE.ADMIN)
  606. }
  607. if (value.detail){
  608. authType = authType.concat(AUTH_TYPE.VISIBLE)
  609. }
  610. if (value.publish){
  611. authType = authType.concat(AUTH_TYPE.PUBLISH)
  612. }
  613. const params = {
  614. dataType: TYPE_ENUM.METRIC,
  615. dataIds: (value?.tags||[]).map(item=>item.value),
  616. roleIds: (value?.roles||[]).map(item=>item.value),
  617. authType,
  618. }
  619. dispatch(batchRoleAuth({params}))
  620. },[])
  621. return (
  622. <ProCard gutter={8} ghost>
  623. {/** 主题域编辑面板 */}
  624. <DomainForm
  625. open={domainModalOpen}
  626. onCancel={handelDomainFormCancel}
  627. onFinish={domainFormSubmit}
  628. values={commonRef.current.treeSelect}
  629. />
  630. {/** 创建指标面板 */}
  631. <IndexCreator
  632. handleCancel={handelCreatorClose}
  633. initialValues={commonRef.current.indexCreator}
  634. onFinish={onCreatorFinish}
  635. open={openCreator}
  636. />
  637. {/** 指标明细面板 */}
  638. <IndexDetail
  639. admin={true}
  640. title={t("title.metricDetail")}
  641. open={openDetail}
  642. onClose={onDetailClose}
  643. values={commonRef.current.indexDetail}
  644. persistence={commonRef.current.persistenceConfig}
  645. onCopy={onExtraSelect}
  646. />
  647. {/** 主题授权管理面板 */}
  648. <AuthorizationPanel
  649. type={commonRef.current.datatype}
  650. open={openAuth}
  651. onCancel={onAuthPanelClose}
  652. onDelete={onAuthDelete}
  653. onFinish={onDomainAuthFinish}
  654. values={
  655. commonRef.current.datatype===TYPE_ENUM.DOMAIN
  656. ? commonRef.current.treeSelect
  657. : commonRef.current.metricSelect
  658. }
  659. />
  660. {/** 指标批量授权面板 */}
  661. <VolumeAuthPanel
  662. open={openIndexAuth}
  663. onCancel={onIndexAuthPanelClose}
  664. onChange={onAuthConfigChange}
  665. onSubmit={onVolumeAuth}
  666. values={commonRef.current.indexChosen}
  667. />
  668. {/** 左侧的主题与目录 */}
  669. <ProCard
  670. bordered
  671. headerBordered
  672. colSpan="20%"
  673. title={t("title.domain")}
  674. style={{height:'85vh'}}
  675. // extra={<ExtraLink onClick={handelDomainFormOpen}>+{t("button.domainCreate")}</ExtraLink>}
  676. >
  677. <TreeMenu
  678. onRightClick={onRightClick}
  679. onSelect={onSelect}
  680. treeData={buildTree}
  681. onSearch={onSearch}
  682. />
  683. </ProCard>
  684. {/** 主面板 */}
  685. <ProCard bordered headerBordered title={subTile} bodyStyle={{height:'80vh',display:"flex",flexDirection:'column'}} style={{height:'85vh'}}>
  686. {/** 筛选栏 */}
  687. <div>
  688. <IndexFilterForm onModelSelect={onModelSelect} onFinish={onFilterFormFinish} ref={filterRef}/>
  689. <Span>
  690. <CustomCheckbox onChange={(e)=>cardListRef?.current?.onAllCheck(e.target.checked)}>全选</CustomCheckbox>
  691. <CustomButton onClick={onIndexAuthPanelOpen}>{t("button.batchAuth")}</CustomButton>
  692. <CustomButton onClick={onVolumePublish}>{t("button.batchPublish")}</CustomButton>
  693. </Span>
  694. <Divider style={{margin:'6px 0'}}/>
  695. </div>
  696. {/** 指标列表 */}
  697. <div style={{flexShrink: 1,overflow:"hidden"}}>
  698. <CheckCardList
  699. ref={cardListRef}
  700. type="checkBox"
  701. tooltip={t("placeholder.doubleClick")}
  702. options={cardOption}
  703. onSelect={onCardSelect}
  704. onDoubleClick={onCardDoubleClick}
  705. onChecked={onCardChecked}
  706. onCreate={()=>{filterRef.current.onModelSelectOpen()}}
  707. />
  708. </div>
  709. </ProCard>
  710. </ProCard>
  711. )
  712. }
  713. const Span = styled.span``;
  714. const CustomButton = styled(Button)`
  715. margin-left: 25px;
  716. `;
  717. const CustomCheckbox = styled(Checkbox)`
  718. margin-left: 25px;
  719. `;
  720. // const ExtraLink = styled.a`
  721. // font-size: ${p=>p.theme.fontSizeLG}px;
  722. // `
  723. const CustomDescriptions = styled(Descriptions)`
  724. .ant-descriptions-item-content {
  725. white-space: nowrap;
  726. text-overflow: ellipsis;
  727. overflow: hidden;
  728. }
  729. `;