Showing
1 changed file
with
315 additions
and
104 deletions
| ... | ... | @@ -6,7 +6,7 @@ import React, { |
| 6 | 6 | useState, |
| 7 | 7 | } from 'react'; |
| 8 | 8 | import { history, useLocation, useParams } from 'umi'; |
| 9 | -import { useModel } from '@@/plugin-model/useModel'; | |
| 9 | +import { useModel } from 'umi'; | |
| 10 | 10 | import { EyeInvisibleOutlined, RedoOutlined } from '@ant-design/icons'; |
| 11 | 11 | import { Alert, Button, Empty, message, Modal, Result, Spin, Tabs } from 'antd'; |
| 12 | 12 | import _, { isFunction } from 'lodash'; |
| ... | ... | @@ -124,29 +124,39 @@ type ListViewCoreProps = { |
| 124 | 124 | relQuery?: any; |
| 125 | 125 | selectKeys?: string[]; |
| 126 | 126 | onSelect?: (record: any, selected: boolean, _selectedRows?: any[]) => void; |
| 127 | - onSelectAll?: (selected: boolean, selectedRows: any[], changeRows: any[]) => void; | |
| 127 | + onSelectAll?: ( | |
| 128 | + selected: boolean, | |
| 129 | + selectedRows: any[], | |
| 130 | + changeRows: any[], | |
| 131 | + ) => void; | |
| 128 | 132 | initSelectedIds?: string[]; |
| 129 | 133 | }; |
| 130 | 134 | |
| 131 | 135 | const getRows = (columns: any[]) => { |
| 132 | 136 | let rows = 1; |
| 133 | - const _columns = columns.filter(item => (item.key || item.dataIndex).indexOf('_merge_field') === 0); | |
| 134 | - _columns.forEach(item => { | |
| 137 | + const _columns = columns.filter( | |
| 138 | + (item) => (item.key || item.dataIndex).indexOf('_merge_field') === 0, | |
| 139 | + ); | |
| 140 | + _columns.forEach((item) => { | |
| 135 | 141 | if (item.children?.length) { |
| 136 | 142 | if (rows === 1) rows = 2; |
| 137 | 143 | item.children.forEach((it: any) => { |
| 138 | - if ((it.key || it.dataIndex).indexOf('_merge_field') === 0 && it.children?.length) { | |
| 144 | + if ( | |
| 145 | + (it.key || it.dataIndex).indexOf('_merge_field') === 0 && | |
| 146 | + it.children?.length | |
| 147 | + ) { | |
| 139 | 148 | rows = 3; |
| 140 | 149 | } |
| 141 | - }) | |
| 150 | + }); | |
| 142 | 151 | } |
| 143 | - }) | |
| 144 | - return rows | |
| 145 | -} | |
| 152 | + }); | |
| 153 | + return rows; | |
| 154 | +}; | |
| 146 | 155 | |
| 147 | 156 | const useTableScrollY = (deps: any[]) => { |
| 148 | 157 | const size = deps?.[0]?.size; |
| 149 | - const itemHeaderHeight = size === 'middle' ? 48 : size === 'default' ? 56 : 40; | |
| 158 | + const itemHeaderHeight = | |
| 159 | + size === 'middle' ? 48 : size === 'default' ? 56 : 40; | |
| 150 | 160 | const headerRows = getRows(deps?.[0]?.columns || []); |
| 151 | 161 | const TABLE_VIEW_LIST = 'qx-view-list'; |
| 152 | 162 | const PAGINATION_HEIGHT_CLASS_NAME = 'ant-pagination'; |
| ... | ... | @@ -157,9 +167,13 @@ const useTableScrollY = (deps: any[]) => { |
| 157 | 167 | const tableViewListDefaultHeight = 400; |
| 158 | 168 | const defaultPagePadding = 10; |
| 159 | 169 | |
| 160 | - const $ = (selectors: string) => document.querySelector<HTMLElement>(selectors); | |
| 170 | + const $ = (selectors: string) => | |
| 171 | + document.querySelector<HTMLElement>(selectors); | |
| 161 | 172 | |
| 162 | - const defaultScrollY = useMemo(() => document.body.clientHeight, [tableHeader]); | |
| 173 | + const defaultScrollY = useMemo( | |
| 174 | + () => document.body.clientHeight, | |
| 175 | + [tableHeader], | |
| 176 | + ); | |
| 163 | 177 | |
| 164 | 178 | const [scrollY, setScrollY] = useState<number>(defaultScrollY ?? 200); |
| 165 | 179 | |
| ... | ... | @@ -172,13 +186,16 @@ const useTableScrollY = (deps: any[]) => { |
| 172 | 186 | |
| 173 | 187 | const toolbar = $(`.${TOOLBAR_NAME}`); |
| 174 | 188 | |
| 175 | - const tableViewListClientHeight = tableViewList?.clientHeight || tableViewListDefaultHeight; | |
| 189 | + const tableViewListClientHeight = | |
| 190 | + tableViewList?.clientHeight || tableViewListDefaultHeight; | |
| 176 | 191 | |
| 177 | 192 | const toolBarHeight = (toolbar?.clientHeight ?? 0) + 20; |
| 178 | 193 | |
| 179 | 194 | const antPaginationHeight = |
| 180 | 195 | (antPagination?.clientHeight ?? paginationDefaultHeight) + |
| 181 | - (antPagination ? parseInt(getComputedStyle(antPagination).margin) : paginationDefaultMargin); | |
| 196 | + (antPagination | |
| 197 | + ? parseInt(getComputedStyle(antPagination).margin) | |
| 198 | + : paginationDefaultMargin); | |
| 182 | 199 | |
| 183 | 200 | const result = |
| 184 | 201 | tableViewListClientHeight - |
| ... | ... | @@ -207,7 +224,9 @@ const useTableScrollY = (deps: any[]) => { |
| 207 | 224 | const header = $('.ant-pro-top-nav-header'); |
| 208 | 225 | const appViewCont = $('.app-view-cont'); |
| 209 | 226 | if (appViewCont) { |
| 210 | - const headerHeight = header ? window.getComputedStyle(header).height : '0'; | |
| 227 | + const headerHeight = header | |
| 228 | + ? window.getComputedStyle(header).height | |
| 229 | + : '0'; | |
| 211 | 230 | const appViewContOffsetTop = appViewCont?.offsetTop ?? 0; |
| 212 | 231 | const height = `calc(100vh - ${ |
| 213 | 232 | parseInt(headerHeight) + appViewContOffsetTop + defaultPagePadding |
| ... | ... | @@ -340,7 +359,12 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 340 | 359 | const [filterTreeData, setFilterTreeData] = useState<any>(); |
| 341 | 360 | const [charts, setCharts] = useState<any[]>([]); |
| 342 | 361 | const [sorter, setSorter] = useState<any>([]); |
| 343 | - const [scrollY] = useTableScrollY([listProps, charts, isFullscreen, searchFoldState]) as any[]; | |
| 362 | + const [scrollY] = useTableScrollY([ | |
| 363 | + listProps, | |
| 364 | + charts, | |
| 365 | + isFullscreen, | |
| 366 | + searchFoldState, | |
| 367 | + ]) as any[]; | |
| 344 | 368 | const [modelId, setModelId] = useState<string>(''); |
| 345 | 369 | const [dataset, setDataset] = useState<boolean>(false); |
| 346 | 370 | const [relationTag, setRelationTag] = useState<any>(); |
| ... | ... | @@ -392,11 +416,13 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 392 | 416 | setSearchSchema(null); |
| 393 | 417 | } |
| 394 | 418 | setOptBar(el.bar); |
| 395 | - (el.funList?.columns || []).forEach((item: { type: string; className?: string }) => { | |
| 396 | - if (item.type === 'FILE') { | |
| 397 | - item.className = 'qx-custom-file'; | |
| 398 | - } | |
| 399 | - }); | |
| 419 | + (el.funList?.columns || []).forEach( | |
| 420 | + (item: { type: string; className?: string }) => { | |
| 421 | + if (item.type === 'FILE') { | |
| 422 | + item.className = 'qx-custom-file'; | |
| 423 | + } | |
| 424 | + }, | |
| 425 | + ); | |
| 400 | 426 | setListProps(el.funList); |
| 401 | 427 | setSelectMode(el.searchMode || ''); |
| 402 | 428 | } |
| ... | ... | @@ -416,7 +442,14 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 416 | 442 | qsIndex?: number; |
| 417 | 443 | }) { |
| 418 | 444 | //重置后需要保留的字段 |
| 419 | - const FIXED_FIELDS = ['_code', 'appId', 'pageSize', 'viewCode', 'viewType', '_filter']; | |
| 445 | + const FIXED_FIELDS = [ | |
| 446 | + '_code', | |
| 447 | + 'appId', | |
| 448 | + 'pageSize', | |
| 449 | + 'viewCode', | |
| 450 | + 'viewType', | |
| 451 | + '_filter', | |
| 452 | + ]; | |
| 420 | 453 | if (!query) { |
| 421 | 454 | return; |
| 422 | 455 | } |
| ... | ... | @@ -453,7 +486,9 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 453 | 486 | }; |
| 454 | 487 | } |
| 455 | 488 | oldStyle.enableTitle = false; |
| 456 | - oldStyle.dataLabelWeight = !!item?.factor ? parseInt(item?.factor) : 0; | |
| 489 | + oldStyle.dataLabelWeight = !!item?.factor | |
| 490 | + ? parseInt(item?.factor) | |
| 491 | + : 0; | |
| 457 | 492 | if (!!item?.unit) { |
| 458 | 493 | oldStyle.dataLabelSuffix = { |
| 459 | 494 | unit: item?.unit, |
| ... | ... | @@ -480,20 +515,27 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 480 | 515 | Object.values(res?.[index]?.result?.[1] || {})?.[0] === 0 |
| 481 | 516 | ? Object.values(res?.[index]?.result?.[1] || {})?.[0] |
| 482 | 517 | : ''; |
| 483 | - if (_.isEmpty(res[index]?.result) || (!item.metricsData && item.metricsData !== 0)) { | |
| 518 | + if ( | |
| 519 | + _.isEmpty(res[index]?.result) || | |
| 520 | + (!item.metricsData && item.metricsData !== 0) | |
| 521 | + ) { | |
| 484 | 522 | item.noneData = true; |
| 485 | 523 | } else { |
| 486 | 524 | item.noneData = false; |
| 487 | 525 | } |
| 488 | 526 | } else if (_widget === 'PIE') { |
| 489 | 527 | _options = transferSpecialEchartsJson( |
| 490 | - res[index]?.result && Array.isArray(res[index]?.result) ? res[index]?.result : [], | |
| 528 | + res[index]?.result && Array.isArray(res[index]?.result) | |
| 529 | + ? res[index]?.result | |
| 530 | + : [], | |
| 491 | 531 | { card: item.cardConfig }, |
| 492 | 532 | [], |
| 493 | 533 | 'totals', |
| 494 | 534 | ); |
| 495 | 535 | _fullOptions = transferSpecialEchartsJson( |
| 496 | - res[index]?.result && Array.isArray(res[index]?.result) ? res[index]?.result : [], | |
| 536 | + res[index]?.result && Array.isArray(res[index]?.result) | |
| 537 | + ? res[index]?.result | |
| 538 | + : [], | |
| 497 | 539 | { card: item.cardConfig }, |
| 498 | 540 | [], |
| 499 | 541 | ); |
| ... | ... | @@ -509,13 +551,17 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 509 | 551 | } |
| 510 | 552 | } else { |
| 511 | 553 | _options = transferEchartsJson( |
| 512 | - res[index]?.result && Array.isArray(res[index]?.result) ? res[index]?.result : [], | |
| 554 | + res[index]?.result && Array.isArray(res[index]?.result) | |
| 555 | + ? res[index]?.result | |
| 556 | + : [], | |
| 513 | 557 | { card: item.cardConfig }, |
| 514 | 558 | res[index]?.groups || [], |
| 515 | 559 | 'totals', |
| 516 | 560 | ); |
| 517 | 561 | _fullOptions = transferEchartsJson( |
| 518 | - res[index]?.result && Array.isArray(res[index]?.result) ? res[index]?.result : [], | |
| 562 | + res[index]?.result && Array.isArray(res[index]?.result) | |
| 563 | + ? res[index]?.result | |
| 564 | + : [], | |
| 519 | 565 | { card: item.cardConfig }, |
| 520 | 566 | res[index]?.groups || [], |
| 521 | 567 | ); |
| ... | ... | @@ -531,7 +577,9 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 531 | 577 | } |
| 532 | 578 | } |
| 533 | 579 | item.chartResult = |
| 534 | - res[index]?.result && Array.isArray(res[index]?.result) ? res[index]?.result : []; | |
| 580 | + res[index]?.result && Array.isArray(res[index]?.result) | |
| 581 | + ? res[index]?.result | |
| 582 | + : []; | |
| 535 | 583 | item.options = _.cloneDeep(_options); |
| 536 | 584 | item.fullOptions = _.cloneDeep(_fullOptions); |
| 537 | 585 | }); |
| ... | ... | @@ -617,7 +665,11 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 617 | 665 | }); |
| 618 | 666 | } |
| 619 | 667 | // 聚合表本身特性导致具有重复ID 前端特殊处理 |
| 620 | - if (location.href.indexOf('/dataset?') > -1 && result?.list && !props.relQuery) { | |
| 668 | + if ( | |
| 669 | + location.href.indexOf('/dataset?') > -1 && | |
| 670 | + result?.list && | |
| 671 | + !props.relQuery | |
| 672 | + ) { | |
| 621 | 673 | for (let i = 0; i < result.list.length; i++) { |
| 622 | 674 | const item = result.list[i]; |
| 623 | 675 | item.id = `${result.pageNum}-${i}-${item.id}`; |
| ... | ... | @@ -687,11 +739,14 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 687 | 739 | setProgressData(res || null); |
| 688 | 740 | }); |
| 689 | 741 | } else { |
| 690 | - exportProgress(appCode, funCode, viewCode || (query && query.viewCode), taskType).then( | |
| 691 | - (res) => { | |
| 692 | - setProgressData(res || null); | |
| 693 | - }, | |
| 694 | - ); | |
| 742 | + exportProgress( | |
| 743 | + appCode, | |
| 744 | + funCode, | |
| 745 | + viewCode || (query && query.viewCode), | |
| 746 | + taskType, | |
| 747 | + ).then((res) => { | |
| 748 | + setProgressData(res || null); | |
| 749 | + }); | |
| 695 | 750 | } |
| 696 | 751 | }; |
| 697 | 752 | const exportData4Word = (taskType: string) => { |
| ... | ... | @@ -707,11 +762,14 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 707 | 762 | setProgressData4Word(res || null); |
| 708 | 763 | }); |
| 709 | 764 | } else { |
| 710 | - exportProgress(appCode, funCode, viewCode || (query && query.viewCode), taskType).then( | |
| 711 | - (res) => { | |
| 712 | - setProgressData4Word(res || null); | |
| 713 | - }, | |
| 714 | - ); | |
| 765 | + exportProgress( | |
| 766 | + appCode, | |
| 767 | + funCode, | |
| 768 | + viewCode || (query && query.viewCode), | |
| 769 | + taskType, | |
| 770 | + ).then((res) => { | |
| 771 | + setProgressData4Word(res || null); | |
| 772 | + }); | |
| 715 | 773 | } |
| 716 | 774 | }; |
| 717 | 775 | const exportData4Dataset = (taskType: string) => { |
| ... | ... | @@ -720,7 +778,12 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 720 | 778 | setProgressData(res || null); |
| 721 | 779 | }); |
| 722 | 780 | }; |
| 723 | - const handle4Tree = async (data: any, _appCode: string, _funCode: string, _viewCode: string) => { | |
| 781 | + const handle4Tree = async ( | |
| 782 | + data: any, | |
| 783 | + _appCode: string, | |
| 784 | + _funCode: string, | |
| 785 | + _viewCode: string, | |
| 786 | + ) => { | |
| 724 | 787 | const params = { |
| 725 | 788 | viewCode: _viewCode || (query && query.viewCode), |
| 726 | 789 | viewType: 'tree', |
| ... | ... | @@ -754,7 +817,9 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 754 | 817 | }); |
| 755 | 818 | } |
| 756 | 819 | } |
| 757 | - const listButtons = data.list.columns.filter((el: any) => el.dataIndex === 'ACTION'); | |
| 820 | + const listButtons = data.list.columns.filter( | |
| 821 | + (el: any) => el.dataIndex === 'ACTION', | |
| 822 | + ); | |
| 758 | 823 | setRelationAside({ |
| 759 | 824 | listButtons: listButtons[0]?.renderData.buttons || [], |
| 760 | 825 | barButtons: data.bar?.buttons || [], |
| ... | ... | @@ -889,14 +954,20 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 889 | 954 | |
| 890 | 955 | if (!props.mode) { |
| 891 | 956 | //获取是否有导出任务并返回导出进度 |
| 892 | - if (location.href.indexOf('/dataset?') > -1 || query.viewType !== 'list') { | |
| 957 | + if ( | |
| 958 | + location.href.indexOf('/dataset?') > -1 || | |
| 959 | + query.viewType !== 'list' | |
| 960 | + ) { | |
| 893 | 961 | exportData('EXPORT'); |
| 894 | 962 | } |
| 895 | 963 | exportData4Word('WORD_EXPORT'); |
| 896 | 964 | } |
| 897 | 965 | remoteApi(appCode, funCode, viewCode || (query && query.viewCode)) |
| 898 | 966 | .then(async (data: any) => { |
| 899 | - if (!data || (!data.hasOwnProperty('list') && !data.hasOwnProperty('tree'))) { | |
| 967 | + if ( | |
| 968 | + !data || | |
| 969 | + (!data.hasOwnProperty('list') && !data.hasOwnProperty('tree')) | |
| 970 | + ) { | |
| 900 | 971 | setHasJurisdiction(false); |
| 901 | 972 | setLoading(false); |
| 902 | 973 | return; |
| ... | ... | @@ -906,11 +977,21 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 906 | 977 | if (data.hasOwnProperty('tree')) { |
| 907 | 978 | setTreeSchema(data); |
| 908 | 979 | setViewType('tree'); |
| 909 | - await handle4Tree(data, appCode, funCode, viewCode || (query && query.viewCode)); | |
| 980 | + await handle4Tree( | |
| 981 | + data, | |
| 982 | + appCode, | |
| 983 | + funCode, | |
| 984 | + viewCode || (query && query.viewCode), | |
| 985 | + ); | |
| 910 | 986 | return; |
| 911 | 987 | } else if (data.hasOwnProperty('relation')) { |
| 912 | 988 | setViewType('RELATION'); |
| 913 | - await relationSetting(data, appCode, funCode, viewCode || (query && query.viewCode)); | |
| 989 | + await relationSetting( | |
| 990 | + data, | |
| 991 | + appCode, | |
| 992 | + funCode, | |
| 993 | + viewCode || (query && query.viewCode), | |
| 994 | + ); | |
| 914 | 995 | return; |
| 915 | 996 | } |
| 916 | 997 | setViewType('list'); |
| ... | ... | @@ -942,7 +1023,9 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 942 | 1023 | data?.quickSearch?.quickSearchJsons && |
| 943 | 1024 | !!data?.quickSearch?.quickSearchJsons.length |
| 944 | 1025 | ) { |
| 945 | - setQuickSearchSchema(_.cloneDeep(data?.quickSearch?.quickSearchJsons)); | |
| 1026 | + setQuickSearchSchema( | |
| 1027 | + _.cloneDeep(data?.quickSearch?.quickSearchJsons), | |
| 1028 | + ); | |
| 946 | 1029 | activeCode = data?.quickSearch?.quickSearchJsons[0]?.code; |
| 947 | 1030 | setTabActiveCode(data?.quickSearch?.quickSearchJsons[0]?.code); |
| 948 | 1031 | params.qsIndex = 0; |
| ... | ... | @@ -982,11 +1065,13 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 982 | 1065 | ) { |
| 983 | 1066 | data.list.columns[0].fixed = true; |
| 984 | 1067 | } |
| 985 | - (data.list?.columns || []).forEach((item: { type: string; className?: string }) => { | |
| 986 | - if (item.type === 'FILE') { | |
| 987 | - item.className = 'qx-custom-file'; | |
| 988 | - } | |
| 989 | - }); | |
| 1068 | + (data.list?.columns || []).forEach( | |
| 1069 | + (item: { type: string; className?: string }) => { | |
| 1070 | + if (item.type === 'FILE') { | |
| 1071 | + item.className = 'qx-custom-file'; | |
| 1072 | + } | |
| 1073 | + }, | |
| 1074 | + ); | |
| 990 | 1075 | setListProps({ |
| 991 | 1076 | ...data.list, |
| 992 | 1077 | pageSize: data.list.pageSize || 10, |
| ... | ... | @@ -1056,7 +1141,12 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1056 | 1141 | queryParams._sort = ''; |
| 1057 | 1142 | } |
| 1058 | 1143 | queryParams.dataIds = dataIds || []; |
| 1059 | - const result = await exportPage4Word(appCode, funCode, viewCode, JSON.stringify(queryParams)); | |
| 1144 | + const result = await exportPage4Word( | |
| 1145 | + appCode, | |
| 1146 | + funCode, | |
| 1147 | + viewCode, | |
| 1148 | + JSON.stringify(queryParams), | |
| 1149 | + ); | |
| 1060 | 1150 | if (result.downloadUrl) { |
| 1061 | 1151 | setTimeout(() => { |
| 1062 | 1152 | exportData4Word('WORD_EXPORT'); |
| ... | ... | @@ -1088,7 +1178,10 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1088 | 1178 | } |
| 1089 | 1179 | |
| 1090 | 1180 | if (dataset) { |
| 1091 | - const result = await exportDatasetPage(funCode, JSON.stringify(queryParams)); | |
| 1181 | + const result = await exportDatasetPage( | |
| 1182 | + funCode, | |
| 1183 | + JSON.stringify(queryParams), | |
| 1184 | + ); | |
| 1092 | 1185 | setProgressData({ |
| 1093 | 1186 | percent: 0, |
| 1094 | 1187 | status: 'PROCESSING', |
| ... | ... | @@ -1111,7 +1204,12 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1111 | 1204 | JSON.stringify(queryParams), |
| 1112 | 1205 | ); |
| 1113 | 1206 | } else { |
| 1114 | - result = await exportPage(appCode, funCode, viewCode, JSON.stringify(queryParams)); | |
| 1207 | + result = await exportPage( | |
| 1208 | + appCode, | |
| 1209 | + funCode, | |
| 1210 | + viewCode, | |
| 1211 | + JSON.stringify(queryParams), | |
| 1212 | + ); | |
| 1115 | 1213 | } |
| 1116 | 1214 | setProgressData({ |
| 1117 | 1215 | percent: 0, |
| ... | ... | @@ -1159,7 +1257,9 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1159 | 1257 | useEffect(() => { |
| 1160 | 1258 | if (exportProgressData4Word) { |
| 1161 | 1259 | if (exportProgressData4Word.status === 'PROCESSING' && !intervalName) { |
| 1162 | - setIntervalName(setInterval(() => exportData4Word('WORD_EXPORT'), 1000 * 10)); | |
| 1260 | + setIntervalName( | |
| 1261 | + setInterval(() => exportData4Word('WORD_EXPORT'), 1000 * 10), | |
| 1262 | + ); | |
| 1163 | 1263 | return; |
| 1164 | 1264 | } |
| 1165 | 1265 | |
| ... | ... | @@ -1268,7 +1368,12 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1268 | 1368 | |
| 1269 | 1369 | //操作按钮需要调用的方法 |
| 1270 | 1370 | const handleOpt = _.debounce( |
| 1271 | - (btn: QxActionButton, record?: any, from?: string, isChildFun?: boolean) => { | |
| 1371 | + ( | |
| 1372 | + btn: QxActionButton, | |
| 1373 | + record?: any, | |
| 1374 | + from?: string, | |
| 1375 | + isChildFun?: boolean, | |
| 1376 | + ) => { | |
| 1272 | 1377 | if (isChildFun) { |
| 1273 | 1378 | setChildFun(true); |
| 1274 | 1379 | } else { |
| ... | ... | @@ -1282,7 +1387,13 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1282 | 1387 | switch (code) { |
| 1283 | 1388 | case 'ADD': |
| 1284 | 1389 | if (viewType === 'tree') { |
| 1285 | - viewDataCtrl('add', '', viewType || '', record?.id || record?.code, btn); | |
| 1390 | + viewDataCtrl( | |
| 1391 | + 'add', | |
| 1392 | + '', | |
| 1393 | + viewType || '', | |
| 1394 | + record?.id || record?.code, | |
| 1395 | + btn, | |
| 1396 | + ); | |
| 1286 | 1397 | } else { |
| 1287 | 1398 | if (isChildFun) { |
| 1288 | 1399 | if (!query._filter) { |
| ... | ... | @@ -1313,21 +1424,30 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1313 | 1424 | if ((record && record.id) || record?.code) { |
| 1314 | 1425 | Modal.confirm({ |
| 1315 | 1426 | title: '删除确认', |
| 1316 | - content: btn.needConfirm ? btn.confirmContent : `确定要删除当前记录吗?`, | |
| 1427 | + content: btn.needConfirm | |
| 1428 | + ? btn.confirmContent | |
| 1429 | + : `确定要删除当前记录吗?`, | |
| 1317 | 1430 | cancelText: '取消', |
| 1318 | 1431 | okText: '确定', |
| 1319 | 1432 | okType: 'danger', |
| 1320 | 1433 | onOk: () => { |
| 1321 | 1434 | if (isChildFun) { |
| 1322 | - removeRel(appCode, funCode, radioValue, record.id).then(() => { | |
| 1323 | - refresh(); | |
| 1324 | - if (from && from === 'view') { | |
| 1325 | - drawerRef.current.close(); | |
| 1326 | - } | |
| 1327 | - message.success('删除成功'); | |
| 1328 | - }); | |
| 1435 | + removeRel(appCode, funCode, radioValue, record.id).then( | |
| 1436 | + () => { | |
| 1437 | + refresh(); | |
| 1438 | + if (from && from === 'view') { | |
| 1439 | + drawerRef.current.close(); | |
| 1440 | + } | |
| 1441 | + message.success('删除成功'); | |
| 1442 | + }, | |
| 1443 | + ); | |
| 1329 | 1444 | } else { |
| 1330 | - remove(appCode, funCode, viewCode, record?.id || record?.code).then(() => { | |
| 1445 | + remove( | |
| 1446 | + appCode, | |
| 1447 | + funCode, | |
| 1448 | + viewCode, | |
| 1449 | + record?.id || record?.code, | |
| 1450 | + ).then(() => { | |
| 1331 | 1451 | refresh(); |
| 1332 | 1452 | if (from && from === 'view') { |
| 1333 | 1453 | drawerRef.current.close(); |
| ... | ... | @@ -1342,12 +1462,16 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1342 | 1462 | if (relationkeys && relationkeys.length > 0) { |
| 1343 | 1463 | Modal.confirm({ |
| 1344 | 1464 | title: '批量删除确认', |
| 1345 | - content: btn.needConfirm ? btn.confirmContent : `确定要删除所选记录吗?`, | |
| 1465 | + content: btn.needConfirm | |
| 1466 | + ? btn.confirmContent | |
| 1467 | + : `确定要删除所选记录吗?`, | |
| 1346 | 1468 | cancelText: '取消', |
| 1347 | 1469 | okText: '确定', |
| 1348 | 1470 | okType: 'danger', |
| 1349 | 1471 | onOk: () => { |
| 1350 | - batchDelete(appCode, funCode, viewCode, { ids: relationkeys }).then(() => { | |
| 1472 | + batchDelete(appCode, funCode, viewCode, { | |
| 1473 | + ids: relationkeys, | |
| 1474 | + }).then(() => { | |
| 1351 | 1475 | refresh(); |
| 1352 | 1476 | message.success('删除成功'); |
| 1353 | 1477 | }); |
| ... | ... | @@ -1360,18 +1484,24 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1360 | 1484 | if (keys && keys.length > 0) { |
| 1361 | 1485 | Modal.confirm({ |
| 1362 | 1486 | title: '批量删除确认', |
| 1363 | - content: btn.needConfirm ? btn.confirmContent : `确定要删除所选记录吗?`, | |
| 1487 | + content: btn.needConfirm | |
| 1488 | + ? btn.confirmContent | |
| 1489 | + : `确定要删除所选记录吗?`, | |
| 1364 | 1490 | cancelText: '取消', |
| 1365 | 1491 | okText: '确定', |
| 1366 | 1492 | okType: 'danger', |
| 1367 | 1493 | onOk: () => { |
| 1368 | 1494 | if (isChildFun) { |
| 1369 | - removeRelMul(appCode, funCode, radioValue, keys).then(() => { | |
| 1370 | - refresh(); | |
| 1371 | - message.success('删除成功'); | |
| 1372 | - }); | |
| 1495 | + removeRelMul(appCode, funCode, radioValue, keys).then( | |
| 1496 | + () => { | |
| 1497 | + refresh(); | |
| 1498 | + message.success('删除成功'); | |
| 1499 | + }, | |
| 1500 | + ); | |
| 1373 | 1501 | } else { |
| 1374 | - batchDelete(appCode, funCode, viewCode, { ids: keys }).then(() => { | |
| 1502 | + batchDelete(appCode, funCode, viewCode, { | |
| 1503 | + ids: keys, | |
| 1504 | + }).then(() => { | |
| 1375 | 1505 | refresh(); |
| 1376 | 1506 | message.success('删除成功'); |
| 1377 | 1507 | }); |
| ... | ... | @@ -1428,7 +1558,9 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1428 | 1558 | if (record && record.id) { |
| 1429 | 1559 | Modal.confirm({ |
| 1430 | 1560 | title: '移除确认', |
| 1431 | - content: btn.needConfirm ? btn.confirmContent : `您确认要移除吗?`, | |
| 1561 | + content: btn.needConfirm | |
| 1562 | + ? btn.confirmContent | |
| 1563 | + : `您确认要移除吗?`, | |
| 1432 | 1564 | cancelText: '取消', |
| 1433 | 1565 | okText: '确定', |
| 1434 | 1566 | okType: 'danger', |
| ... | ... | @@ -1482,7 +1614,13 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1482 | 1614 | if (!isChildFun && viewType === 'RELATION') { |
| 1483 | 1615 | ids = record ? [record.id] : relationkeys; |
| 1484 | 1616 | } else { |
| 1485 | - ids = record ? (record.id ? [record.id] : record.code ? [record.code] : keys) : keys; | |
| 1617 | + ids = record | |
| 1618 | + ? record.id | |
| 1619 | + ? [record.id] | |
| 1620 | + : record.code | |
| 1621 | + ? [record.code] | |
| 1622 | + : keys | |
| 1623 | + : keys; | |
| 1486 | 1624 | } |
| 1487 | 1625 | //const btnSchemas = ; |
| 1488 | 1626 | setBtnData(_.cloneDeep(btn)); |
| ... | ... | @@ -1619,9 +1757,15 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1619 | 1757 | <Button |
| 1620 | 1758 | onClick={() => { |
| 1621 | 1759 | if (exportProgressData4Word.finalMsg > 1) { |
| 1622 | - handleDownload(exportProgressData4Word.downloadUrl, '导出文件.zip'); | |
| 1760 | + handleDownload( | |
| 1761 | + exportProgressData4Word.downloadUrl, | |
| 1762 | + '导出文件.zip', | |
| 1763 | + ); | |
| 1623 | 1764 | } else { |
| 1624 | - handleDownload(exportProgressData4Word.downloadUrl, '导出文件.docx'); | |
| 1765 | + handleDownload( | |
| 1766 | + exportProgressData4Word.downloadUrl, | |
| 1767 | + '导出文件.docx', | |
| 1768 | + ); | |
| 1625 | 1769 | } |
| 1626 | 1770 | }} |
| 1627 | 1771 | type={'link'} |
| ... | ... | @@ -1630,7 +1774,9 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1630 | 1774 | </Button> |
| 1631 | 1775 | <Button |
| 1632 | 1776 | style={{ float: 'right' }} |
| 1633 | - onClick={() => handleCloseExport4Word(exportProgressData4Word.taskId)} | |
| 1777 | + onClick={() => | |
| 1778 | + handleCloseExport4Word(exportProgressData4Word.taskId) | |
| 1779 | + } | |
| 1634 | 1780 | type={'link'} |
| 1635 | 1781 | > |
| 1636 | 1782 | 【关闭提醒】 |
| ... | ... | @@ -1666,9 +1812,15 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1666 | 1812 | //存在排序时 |
| 1667 | 1813 | sortParam = { |
| 1668 | 1814 | _field_key: _sorter?.order ? _sorter?.field : '', |
| 1669 | - _sort: _sorter?.order ? (_sorter?.order === 'ascend' ? 'asc' : 'desc') : '', | |
| 1815 | + _sort: _sorter?.order | |
| 1816 | + ? _sorter?.order === 'ascend' | |
| 1817 | + ? 'asc' | |
| 1818 | + : 'desc' | |
| 1819 | + : '', | |
| 1670 | 1820 | }; |
| 1671 | - setSorter([{ dataIndex: _sorter?.field || '', order: _sorter?.order || '' }]); | |
| 1821 | + setSorter([ | |
| 1822 | + { dataIndex: _sorter?.field || '', order: _sorter?.order || '' }, | |
| 1823 | + ]); | |
| 1672 | 1824 | // 若列表字段没有值时,点击排序,顺序不要改变 |
| 1673 | 1825 | // 暂时注释掉 此处的判断逻辑不完善 |
| 1674 | 1826 | // const emptyArr = []; |
| ... | ... | @@ -1682,7 +1834,11 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1682 | 1834 | // sortParam._sort = ''; |
| 1683 | 1835 | // } |
| 1684 | 1836 | } |
| 1685 | - searchApi({ pageNum: pagination.current, pageSize: pagination.pageSize, ...sortParam }); | |
| 1837 | + searchApi({ | |
| 1838 | + pageNum: pagination.current, | |
| 1839 | + pageSize: pagination.pageSize, | |
| 1840 | + ...sortParam, | |
| 1841 | + }); | |
| 1686 | 1842 | }; |
| 1687 | 1843 | |
| 1688 | 1844 | const onActiveValue = (value: any) => { |
| ... | ... | @@ -1749,14 +1905,22 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1749 | 1905 | height: 200, |
| 1750 | 1906 | marginBottom: 0, |
| 1751 | 1907 | }} |
| 1752 | - description={<span style={{ fontSize: '16px', color: '#999' }}>暂无权限</span>} | |
| 1908 | + description={ | |
| 1909 | + <span style={{ fontSize: '16px', color: '#999' }}>暂无权限</span> | |
| 1910 | + } | |
| 1753 | 1911 | /> |
| 1754 | 1912 | </> |
| 1755 | 1913 | ) : ( |
| 1756 | 1914 | <> |
| 1757 | 1915 | {_.size(schemaAll) > 0 && !loading ? ( |
| 1758 | - <section className="qx-view" key={`${appCode}-${funCode}-${viewCode}`}> | |
| 1759 | - {filterAside && filterAside.type && viewType !== 'tree' && viewType !== 'RELATION' ? ( | |
| 1916 | + <section | |
| 1917 | + className="qx-view" | |
| 1918 | + key={`${appCode}-${funCode}-${viewCode}`} | |
| 1919 | + > | |
| 1920 | + {filterAside && | |
| 1921 | + filterAside.type && | |
| 1922 | + viewType !== 'tree' && | |
| 1923 | + viewType !== 'RELATION' ? ( | |
| 1760 | 1924 | <QxFilterSide |
| 1761 | 1925 | {...filterAside} |
| 1762 | 1926 | data={filterTreeData} |
| ... | ... | @@ -1771,9 +1935,11 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1771 | 1935 | <RelationSide |
| 1772 | 1936 | {...relationAside} |
| 1773 | 1937 | data={relationAsideData} |
| 1774 | - onClickBtn={(btn: QxActionButton, record?: any, from?: string) => | |
| 1775 | - handleOpt(btn, record, from, false) | |
| 1776 | - } | |
| 1938 | + onClickBtn={( | |
| 1939 | + btn: QxActionButton, | |
| 1940 | + record?: any, | |
| 1941 | + from?: string, | |
| 1942 | + ) => handleOpt(btn, record, from, false)} | |
| 1777 | 1943 | selectedKeys={query._filter ? [query._filter] : ['']} |
| 1778 | 1944 | onSelect={handleSideSelect} |
| 1779 | 1945 | checkData={checkData} |
| ... | ... | @@ -1782,7 +1948,10 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1782 | 1948 | /> |
| 1783 | 1949 | )} |
| 1784 | 1950 | |
| 1785 | - <section className="qx-view_content" style={{ marginRight: 0, paddingRight: 0 }}> | |
| 1951 | + <section | |
| 1952 | + className="qx-view_content" | |
| 1953 | + style={{ marginRight: 0, paddingRight: 0 }} | |
| 1954 | + > | |
| 1786 | 1955 | {viewType === 'RELATION' && relationTag?.length && ( |
| 1787 | 1956 | <RelationList |
| 1788 | 1957 | value={radioValue} |
| ... | ... | @@ -1797,10 +1966,16 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1797 | 1966 | roleId={query._filter || ''} |
| 1798 | 1967 | /> |
| 1799 | 1968 | )} |
| 1800 | - {searchSchema?.properties && viewType !== 'tree' && radioValue !== 'sys_role' ? ( | |
| 1969 | + {searchSchema?.properties && | |
| 1970 | + viewType !== 'tree' && | |
| 1971 | + radioValue !== 'sys_role' ? ( | |
| 1801 | 1972 | <> |
| 1802 | 1973 | <QxSearchForm |
| 1803 | - key={viewType === 'RELATION' ? radioValue + query._filter : ''} | |
| 1974 | + key={ | |
| 1975 | + viewType === 'RELATION' | |
| 1976 | + ? radioValue + query._filter | |
| 1977 | + : '' | |
| 1978 | + } | |
| 1804 | 1979 | onSearch={searchApi} |
| 1805 | 1980 | query={query} |
| 1806 | 1981 | onFoldChange={(foldState: boolean) => { |
| ... | ... | @@ -1813,7 +1988,11 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1813 | 1988 | {charts.length && viewType !== 'RELATION' ? ( |
| 1814 | 1989 | <Chart totals={charts} isRequest={false} requestIndex={-1} /> |
| 1815 | 1990 | ) : null} |
| 1816 | - <div className={`qx-view-list ${isFullscreen ? 'qx-view-list_full' : ''}`}> | |
| 1991 | + <div | |
| 1992 | + className={`qx-view-list ${ | |
| 1993 | + isFullscreen ? 'qx-view-list_full' : '' | |
| 1994 | + }`} | |
| 1995 | + > | |
| 1817 | 1996 | {viewType !== 'tree' && ( |
| 1818 | 1997 | <div className="qx-view-container__toolbar"> |
| 1819 | 1998 | {quickSearchSchema && !!quickSearchSchema.length ? ( |
| ... | ... | @@ -1850,7 +2029,11 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1850 | 2029 | {...optBar} |
| 1851 | 2030 | changeFullscreen={changeFullscreen} |
| 1852 | 2031 | isFullscreen={isFullscreen} |
| 1853 | - onClickBtn={(btn: QxActionButton, record?: any, from?: string) => { | |
| 2032 | + onClickBtn={( | |
| 2033 | + btn: QxActionButton, | |
| 2034 | + record?: any, | |
| 2035 | + from?: string, | |
| 2036 | + ) => { | |
| 1854 | 2037 | if (viewType === 'RELATION') { |
| 1855 | 2038 | handleOpt(btn, record, from, true); |
| 1856 | 2039 | } else { |
| ... | ... | @@ -1883,10 +2066,15 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1883 | 2066 | <Alert |
| 1884 | 2067 | style={{ marginBottom: '12px' }} |
| 1885 | 2068 | message={getExportMessage4Word()} |
| 1886 | - type={EXPORT_STATUS[exportProgressData4Word.status] || 'info'} | |
| 2069 | + type={ | |
| 2070 | + EXPORT_STATUS[exportProgressData4Word.status] || | |
| 2071 | + 'info' | |
| 2072 | + } | |
| 1887 | 2073 | showIcon |
| 1888 | 2074 | onClose={() => { |
| 1889 | - handleCloseExport4Word(exportProgressData4Word.taskId); | |
| 2075 | + handleCloseExport4Word( | |
| 2076 | + exportProgressData4Word.taskId, | |
| 2077 | + ); | |
| 1890 | 2078 | }} |
| 1891 | 2079 | /> |
| 1892 | 2080 | ) : null} |
| ... | ... | @@ -1923,7 +2111,11 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 1923 | 2111 | loading={tableLoading} |
| 1924 | 2112 | dataSource={dataSource} |
| 1925 | 2113 | sort={sorter} |
| 1926 | - onClickBtn={(btn: QxActionButton, record?: any, from?: string) => { | |
| 2114 | + onClickBtn={( | |
| 2115 | + btn: QxActionButton, | |
| 2116 | + record?: any, | |
| 2117 | + from?: string, | |
| 2118 | + ) => { | |
| 1927 | 2119 | if (viewType === 'RELATION') { |
| 1928 | 2120 | handleOpt(btn, record, from, true); |
| 1929 | 2121 | } else { |
| ... | ... | @@ -2075,7 +2267,10 @@ export const ListViewCore: React.FC<ListViewCoreProps> = ({ |
| 2075 | 2267 | }} |
| 2076 | 2268 | /> |
| 2077 | 2269 | } |
| 2078 | - <SubformEdit batchEditParam={batchEditParam} saveCallBack={saveCallBack} /> | |
| 2270 | + <SubformEdit | |
| 2271 | + batchEditParam={batchEditParam} | |
| 2272 | + saveCallBack={saveCallBack} | |
| 2273 | + /> | |
| 2079 | 2274 | <Modal |
| 2080 | 2275 | title={'更新历史'} |
| 2081 | 2276 | width={'800px'} |
| ... | ... | @@ -2154,7 +2349,10 @@ export const ListViewDialog: React.FC<ListViewDialogProps> = ({ |
| 2154 | 2349 | const PageList: React.FC = () => { |
| 2155 | 2350 | const [loading, setLoading] = useState<boolean>(true); |
| 2156 | 2351 | // @ts-ignore |
| 2157 | - const { appCode, funCode, viewCode } = useParams<{ appCode: string; funCode: string }>(); | |
| 2352 | + const { appCode, funCode, viewCode } = useParams<{ | |
| 2353 | + appCode: string; | |
| 2354 | + funCode: string; | |
| 2355 | + }>(); | |
| 2158 | 2356 | |
| 2159 | 2357 | // @ts-ignore |
| 2160 | 2358 | const { query, pathname } = useLocation(); |
| ... | ... | @@ -2165,7 +2363,9 @@ const PageList: React.FC = () => { |
| 2165 | 2363 | const [views, setViews] = useState<any[]>([]); |
| 2166 | 2364 | const [processing, setProcessing] = useState<boolean>(false); |
| 2167 | 2365 | const [processMessage, setProcessMessage] = useState<string>(''); |
| 2168 | - const [currentViewCode, setCurrentViewCode] = useState<string>(query.viewCode || ''); | |
| 2366 | + const [currentViewCode, setCurrentViewCode] = useState<string>( | |
| 2367 | + query.viewCode || '', | |
| 2368 | + ); | |
| 2169 | 2369 | const [isSysPage, setIsSysPage] = useState(false); |
| 2170 | 2370 | |
| 2171 | 2371 | const [dataset, setDataset] = useState(false); |
| ... | ... | @@ -2293,7 +2493,9 @@ const PageList: React.FC = () => { |
| 2293 | 2493 | onTabChange(viewArr[0]?.code || ''); |
| 2294 | 2494 | } else { |
| 2295 | 2495 | const _viewCode = query.viewCode || viewCode; |
| 2296 | - if (viewArr?.findIndex((item: any) => item.code === _viewCode) > -1) { | |
| 2496 | + if ( | |
| 2497 | + viewArr?.findIndex((item: any) => item.code === _viewCode) > -1 | |
| 2498 | + ) { | |
| 2297 | 2499 | onTabChange(_viewCode); |
| 2298 | 2500 | } else { |
| 2299 | 2501 | onTabChange(viewArr[0]?.code || ''); |
| ... | ... | @@ -2305,7 +2507,10 @@ const PageList: React.FC = () => { |
| 2305 | 2507 | .catch((e) => { |
| 2306 | 2508 | setLoading(false); |
| 2307 | 2509 | setViews([]); |
| 2308 | - if (e.errCode === 'FUN_ERROR_FUN_PROCESSING' || e.errCode === 'APP_UPGRADE_PROCESSING') { | |
| 2510 | + if ( | |
| 2511 | + e.errCode === 'FUN_ERROR_FUN_PROCESSING' || | |
| 2512 | + e.errCode === 'APP_UPGRADE_PROCESSING' | |
| 2513 | + ) { | |
| 2309 | 2514 | if (e.errCode === 'APP_UPGRADE_PROCESSING') { |
| 2310 | 2515 | e.msg = 'UPGRADE' + e.msg; |
| 2311 | 2516 | } |
| ... | ... | @@ -2330,7 +2535,9 @@ const PageList: React.FC = () => { |
| 2330 | 2535 | </Button>, |
| 2331 | 2536 | ] |
| 2332 | 2537 | : []; |
| 2333 | - return loading ? null : <Exception404 showGoBackLink={false} buttons={buttons} />; | |
| 2538 | + return loading ? null : ( | |
| 2539 | + <Exception404 showGoBackLink={false} buttons={buttons} /> | |
| 2540 | + ); | |
| 2334 | 2541 | }; |
| 2335 | 2542 | |
| 2336 | 2543 | const getErrMsg = (msg: string) => { |
| ... | ... | @@ -2364,7 +2571,11 @@ const PageList: React.FC = () => { |
| 2364 | 2571 | {pane.name} |
| 2365 | 2572 | {pane?.hidden && ( |
| 2366 | 2573 | <EyeInvisibleOutlined |
| 2367 | - style={{ fontSize: '12px', marginLeft: '5px', color: '#b6b6b6' }} | |
| 2574 | + style={{ | |
| 2575 | + fontSize: '12px', | |
| 2576 | + marginLeft: '5px', | |
| 2577 | + color: '#b6b6b6', | |
| 2578 | + }} | |
| 2368 | 2579 | /> |
| 2369 | 2580 | )} |
| 2370 | 2581 | </span> | ... | ... |