@cfmm/umi-plugins-ui-v2 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
import { CloudDownloadOutlined, DownloadOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons';
|
|
2
|
-
import { ActionType, ColumnsState, ProColumns, ProTable } from '@ant-design/pro-components';
|
|
2
|
+
import { ActionType, ColumnsState, ProColumns, ProFormInstance, ProTable } from '@ant-design/pro-components';
|
|
3
3
|
import { cfmmUtils, ImportExecl, useFormatLocale, useIntl, useModel } from '@umijs/max';
|
|
4
|
-
import { Button, Dropdown, MenuProps, message, Modal, Progress } from 'antd';
|
|
4
|
+
import { Button, Drawer, Dropdown, MenuProps, message, Modal, Progress } from 'antd';
|
|
5
5
|
import React, { ForwardedRef, forwardRef, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
6
6
|
import useAction from '../hooks/useAction';
|
|
7
7
|
import useAuthority from '../hooks/useAuthority';
|
|
8
8
|
import useMemoizedFn from '../hooks/useMemoizedFn';
|
|
9
9
|
import useQueryTableList from '../hooks/useQueryTableList';
|
|
10
|
-
import {
|
|
10
|
+
import { importMultiLangList, queryLangInfoExportList } from '../services';
|
|
11
|
+
import {
|
|
12
|
+
API,
|
|
13
|
+
CrudTableConfig,
|
|
14
|
+
CrudTableRefType,
|
|
15
|
+
ExportMultiLangListItem,
|
|
16
|
+
LangInfoItem,
|
|
17
|
+
RefDrawerFormRefType,
|
|
18
|
+
} from '../types';
|
|
19
|
+
import { genExcel, genExcelAdvanced, getExportColumns, getExportValueForColumns } from '../utils/excelHelper';
|
|
20
|
+
import { handleImportList, showCheckErrorTips } from '../utils/importHelper';
|
|
11
21
|
import ActionLogDrawer from './ActionLogDrawer';
|
|
12
22
|
import CreateForm from './AddDrawerForm';
|
|
13
23
|
import DropdownButton from './DropdownButton';
|
|
14
24
|
import EditMultiLangForm from './EditMultiLangForm';
|
|
15
25
|
import MyFooterToolbar from './MyFooterToolbar';
|
|
16
26
|
import ViewTableItemDrawer from './ViewTableItemDrawer';
|
|
17
|
-
import { genExcel, genExcelAdvanced, getExportColumns, getExportValueForColumns } from '../utils/excelHelper';
|
|
18
|
-
import { importMultiLangList, queryLangInfoExportList } from '../services';
|
|
19
|
-
import { handleImportList, showCheckErrorTips } from '../utils/importHelper';
|
|
20
27
|
|
|
21
28
|
const { confirm } = Modal;
|
|
22
29
|
export const TABLE_SCROLL = { x: 'max-content' };
|
|
@@ -87,6 +94,7 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
87
94
|
const actionRef = useRef<ActionType>();
|
|
88
95
|
const updateDrawerRef = useRef<RefDrawerFormRefType>();
|
|
89
96
|
const timer = useRef<NodeJS.Timeout>();
|
|
97
|
+
const updateFormRef = useRef<ProFormInstance>();
|
|
90
98
|
|
|
91
99
|
// 状态管理
|
|
92
100
|
const [tableList, setTableList] = useState<T[]>([]);
|
|
@@ -96,6 +104,7 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
96
104
|
const [selectedRows, setSelectedRows] = useState<T[]>([]);
|
|
97
105
|
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
|
98
106
|
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
|
|
107
|
+
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
|
|
99
108
|
|
|
100
109
|
// 多语言编辑状态
|
|
101
110
|
const [editLangModalOpen, setEditLangModalOpen] = useState<boolean>(false);
|
|
@@ -133,27 +142,35 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
133
142
|
setEditLangModalOpen(true);
|
|
134
143
|
});
|
|
135
144
|
|
|
136
|
-
|
|
137
|
-
|
|
145
|
+
// 查询多语言数据
|
|
146
|
+
const queryMultiLangData = useMemoizedFn(
|
|
147
|
+
async (tableName: string, columnName: string): Promise<ExportMultiLangListItem[]> => {
|
|
148
|
+
if (!multiLang) return [];
|
|
138
149
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
150
|
+
if (multiLang.multiLangList) {
|
|
151
|
+
return multiLang.multiLangList;
|
|
152
|
+
}
|
|
142
153
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
154
|
+
if (multiLang.queryExportMultiLangData) {
|
|
155
|
+
return await multiLang.queryExportMultiLangData(tableName, columnName);
|
|
156
|
+
}
|
|
146
157
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
158
|
+
const result = await doAction(
|
|
159
|
+
'GET',
|
|
160
|
+
{ tableName, columnName },
|
|
161
|
+
{
|
|
162
|
+
actionFn: queryLangInfoExportList,
|
|
163
|
+
},
|
|
164
|
+
);
|
|
150
165
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
166
|
+
if (result.success && result.data) {
|
|
167
|
+
return result.data;
|
|
168
|
+
}
|
|
169
|
+
return [];
|
|
170
|
+
},
|
|
171
|
+
);
|
|
156
172
|
|
|
173
|
+
// 导出多语言数据
|
|
157
174
|
const handleExportMultiLang = useMemoizedFn(async () => {
|
|
158
175
|
if (multiLang?.exportMultiLangData) {
|
|
159
176
|
return await multiLang.exportMultiLangData();
|
|
@@ -173,7 +190,14 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
173
190
|
|
|
174
191
|
if (!data.length) return;
|
|
175
192
|
|
|
176
|
-
const handleData = data.map(item => [
|
|
193
|
+
const handleData = data.map((item) => [
|
|
194
|
+
item.dataId,
|
|
195
|
+
item.columnValue,
|
|
196
|
+
item.zh_CN,
|
|
197
|
+
item.zh_TW,
|
|
198
|
+
item.en_US,
|
|
199
|
+
item.th_TH,
|
|
200
|
+
]);
|
|
177
201
|
|
|
178
202
|
genExcelAdvanced(
|
|
179
203
|
`${title}.xlsx`,
|
|
@@ -184,10 +208,12 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
184
208
|
codeColumns: codeList,
|
|
185
209
|
title: title,
|
|
186
210
|
titleStyle: { fontSize: 18, bold: true },
|
|
187
|
-
notice: [
|
|
211
|
+
notice: [
|
|
212
|
+
formatMessage({ id: 'cfmmUI.common.button.exportMultiLang.notice', defaultMessage: '请勿修改表格结构' }),
|
|
213
|
+
],
|
|
188
214
|
worksheetColumns: new Array(codeList.length).fill('').map((item, index) => ({ hidden: index == 0, width: 25 })),
|
|
189
215
|
lockedColumns: [0], // 第一列不允许修改
|
|
190
|
-
}
|
|
216
|
+
},
|
|
191
217
|
);
|
|
192
218
|
return false;
|
|
193
219
|
});
|
|
@@ -212,14 +238,18 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
212
238
|
// return Promise.resolve({ success: false });
|
|
213
239
|
// }
|
|
214
240
|
|
|
215
|
-
const result = await doAction(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
241
|
+
const result = await doAction(
|
|
242
|
+
'IMPORT',
|
|
243
|
+
{
|
|
244
|
+
tableName: tableName,
|
|
245
|
+
columnName: columnName,
|
|
246
|
+
i18nDataList: newList.filter((item) => item.en_US || item.zh_CN || item.zh_TW || item.th_TH),
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
actionFn: importMultiLangList,
|
|
250
|
+
showMsg: false,
|
|
251
|
+
},
|
|
252
|
+
);
|
|
223
253
|
|
|
224
254
|
if (result.success) {
|
|
225
255
|
actionRef.current?.reload();
|
|
@@ -359,6 +389,10 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
359
389
|
editData = processedData;
|
|
360
390
|
}
|
|
361
391
|
|
|
392
|
+
setUpdateModalOpen(true);
|
|
393
|
+
|
|
394
|
+
updateFormRef.current?.setFieldsValue(editData);
|
|
395
|
+
|
|
362
396
|
updateDrawerRef.current?.show();
|
|
363
397
|
setEditRow(editData);
|
|
364
398
|
});
|
|
@@ -402,9 +436,9 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
402
436
|
});
|
|
403
437
|
};
|
|
404
438
|
|
|
405
|
-
//
|
|
439
|
+
// 导入列表数据
|
|
406
440
|
const importListData = useMemoizedFn(async (list: T[]) => {
|
|
407
|
-
if(!apis.importData && !interceptors.importData?.submitImportListData) return;
|
|
441
|
+
if (!apis.importData && !interceptors.importData?.submitImportListData) return;
|
|
408
442
|
|
|
409
443
|
// 处理导入数据,正确赋值字段以及转格式
|
|
410
444
|
const newList = interceptors.importData?.request?.(list) ?? handleImportList<T>(list);
|
|
@@ -417,7 +451,7 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
417
451
|
return Promise.resolve({ success: false });
|
|
418
452
|
}
|
|
419
453
|
|
|
420
|
-
const resutl = await interceptors.importData?.submitImportListData?.(newList) || await submitListData(newList);
|
|
454
|
+
const resutl = (await interceptors.importData?.submitImportListData?.(newList)) || (await submitListData(newList));
|
|
421
455
|
|
|
422
456
|
onAfterImport?.(resutl);
|
|
423
457
|
|
|
@@ -427,13 +461,14 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
427
461
|
return resutl;
|
|
428
462
|
});
|
|
429
463
|
|
|
464
|
+
// 处理进度条变化
|
|
430
465
|
const handlePercentChange = (value: number) => {
|
|
431
466
|
setPercent(value);
|
|
432
467
|
};
|
|
433
468
|
|
|
434
469
|
/**
|
|
435
|
-
|
|
436
|
-
|
|
470
|
+
* 下载数据为Excel
|
|
471
|
+
*/
|
|
437
472
|
const handleDownloadExcel = async () => {
|
|
438
473
|
const result = await handleSearchAll();
|
|
439
474
|
if (!result.success || result.error || !result.data) {
|
|
@@ -569,7 +604,7 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
569
604
|
...(actionColumnConfig?.columnConfig ?? {}),
|
|
570
605
|
},
|
|
571
606
|
];
|
|
572
|
-
}, [rowKey, columns, multiLang, defaultAuthCodes, actionColumnConfig]);
|
|
607
|
+
}, [rowKey, columns, multiLang, defaultAuthCodes, actionColumnConfig, updateFormRef]);
|
|
573
608
|
|
|
574
609
|
useImperativeHandle(
|
|
575
610
|
ref,
|
|
@@ -630,7 +665,7 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
630
665
|
|
|
631
666
|
// 处理表格额外操作按钮列表
|
|
632
667
|
const handleTableButtonList = (allButtons: MenuProps['items']) => {
|
|
633
|
-
if(!allButtons?.length) return allButtons;
|
|
668
|
+
if (!allButtons?.length) return allButtons;
|
|
634
669
|
|
|
635
670
|
let renderList: MenuProps['items'] | any[] = [...(allButtons ?? [])];
|
|
636
671
|
|
|
@@ -704,7 +739,8 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
704
739
|
),
|
|
705
740
|
},
|
|
706
741
|
{
|
|
707
|
-
auth:
|
|
742
|
+
auth:
|
|
743
|
+
getAuthorityFn(defaultAuthCodes.import) && (apis.importData || interceptors.importData?.submitImportListData),
|
|
708
744
|
key: 'import',
|
|
709
745
|
label: (
|
|
710
746
|
<ImportExecl key="importMaterial" rangeStart={{ c: 0, r: 2 }} onChange={importListData}>
|
|
@@ -719,19 +755,19 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
719
755
|
auth: getAuthorityFn(defaultAuthCodes.export),
|
|
720
756
|
key: 'export',
|
|
721
757
|
disabled: !tableList.length || loading,
|
|
722
|
-
label:
|
|
723
|
-
<
|
|
724
|
-
|
|
725
|
-
|
|
758
|
+
label: (
|
|
759
|
+
<a onClick={handleDownloadExcel} key="export">
|
|
760
|
+
<CloudDownloadOutlined style={{ marginRight: 6 }} />
|
|
761
|
+
{formatMessage({ id: 'cfmmUI.common.button.exportData', defaultMessage: '导出数据' })}
|
|
762
|
+
</a>
|
|
763
|
+
),
|
|
726
764
|
},
|
|
727
765
|
];
|
|
728
766
|
|
|
729
767
|
allButtons = handleTableButtonList(allButtons);
|
|
730
768
|
|
|
731
769
|
// 过滤有权限的按钮,并移除 auth 属性避免传递到 DOM
|
|
732
|
-
return allButtons
|
|
733
|
-
.filter((button) => button.auth)
|
|
734
|
-
.map(({ auth, ...rest }) => rest);
|
|
770
|
+
return allButtons!.filter((button) => button.auth).map(({ auth, ...rest }) => rest);
|
|
735
771
|
}, [tableList, loading, columnsStateMap]);
|
|
736
772
|
|
|
737
773
|
return (
|
|
@@ -750,10 +786,14 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
750
786
|
toolBarRender={useMemoizedFn(() => {
|
|
751
787
|
if (!getBarButtons?.length) return [];
|
|
752
788
|
return [
|
|
753
|
-
<Dropdown.Button
|
|
789
|
+
<Dropdown.Button
|
|
790
|
+
type="primary"
|
|
791
|
+
loading={actionLoading || downloadButtonLoading}
|
|
792
|
+
menu={{ items: getBarButtons.slice(1) }}
|
|
793
|
+
>
|
|
754
794
|
{getBarButtons[0].icon}
|
|
755
795
|
{getBarButtons[0].label}
|
|
756
|
-
</Dropdown.Button
|
|
796
|
+
</Dropdown.Button>,
|
|
757
797
|
];
|
|
758
798
|
})}
|
|
759
799
|
request={useMemoizedFn(async (params, sorter) => {
|
|
@@ -844,7 +884,7 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
844
884
|
)}
|
|
845
885
|
|
|
846
886
|
{/* 编辑表单 */}
|
|
847
|
-
{updateConfig.Component
|
|
887
|
+
{updateConfig.Component ? (
|
|
848
888
|
<updateConfig.Component
|
|
849
889
|
updateDrawerRef={updateDrawerRef}
|
|
850
890
|
values={editRow}
|
|
@@ -864,6 +904,64 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
864
904
|
}}
|
|
865
905
|
{...(updateConfig.props as U)}
|
|
866
906
|
/>
|
|
907
|
+
) : (
|
|
908
|
+
<Drawer
|
|
909
|
+
width={500}
|
|
910
|
+
title={formatMessage({
|
|
911
|
+
id: `${baseLocalCode}.update.title`,
|
|
912
|
+
defaultMessage: '修改',
|
|
913
|
+
})}
|
|
914
|
+
forceRender // 勿删,否则formRef无法被绑定到ProTable上,因为ProTable是异步渲染的
|
|
915
|
+
maskClosable={false}
|
|
916
|
+
open={updateModalOpen}
|
|
917
|
+
onClose={() => {
|
|
918
|
+
setEditRow(null);
|
|
919
|
+
setUpdateModalOpen(false);
|
|
920
|
+
}}
|
|
921
|
+
// footer={<Button onClick={() => props.form?.resetFields()}>清空</Button>}
|
|
922
|
+
>
|
|
923
|
+
<ProTable<T, T>
|
|
924
|
+
loading={actionLoading}
|
|
925
|
+
onSubmit={useMemoizedFn(async (value) => {
|
|
926
|
+
|
|
927
|
+
const success = await handleAction('PUT', {
|
|
928
|
+
...value,
|
|
929
|
+
[rowKey]: editRow?.[rowKey],
|
|
930
|
+
});
|
|
931
|
+
if (success) {
|
|
932
|
+
actionRef.current?.reload();
|
|
933
|
+
setEditRow(null);
|
|
934
|
+
setUpdateModalOpen(false);
|
|
935
|
+
}
|
|
936
|
+
return success;
|
|
937
|
+
})}
|
|
938
|
+
rowKey={rowKey as string}
|
|
939
|
+
type="form"
|
|
940
|
+
columns={columns}
|
|
941
|
+
{...(updateConfig.props as U)}
|
|
942
|
+
formRef={updateFormRef}
|
|
943
|
+
onReset={() => {
|
|
944
|
+
updateFormRef.current?.setFieldsValue({ ...(editRow || {}) });
|
|
945
|
+
}}
|
|
946
|
+
// 自定义按钮
|
|
947
|
+
// form={{
|
|
948
|
+
// submitter: {
|
|
949
|
+
// searchConfig: {
|
|
950
|
+
// submitText: '保存',
|
|
951
|
+
// resetText: '还原',
|
|
952
|
+
// },
|
|
953
|
+
// submitButtonProps: { type: 'primary' },
|
|
954
|
+
// resetButtonProps: { type: 'default' },
|
|
955
|
+
// render: (props, dom) => (
|
|
956
|
+
// <Space>
|
|
957
|
+
// <Button onClick={() => props.form?.resetFields()}>清空</Button>
|
|
958
|
+
// {dom[1]} {/* 默认提交按钮 */}
|
|
959
|
+
// </Space>
|
|
960
|
+
// ),
|
|
961
|
+
// },
|
|
962
|
+
// }}
|
|
963
|
+
/>
|
|
964
|
+
</Drawer>
|
|
867
965
|
)}
|
|
868
966
|
|
|
869
967
|
{/* 多语言编辑 */}
|
|
@@ -886,8 +984,4 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
886
984
|
);
|
|
887
985
|
}
|
|
888
986
|
|
|
889
|
-
export default React.memo(forwardRef(CrudTable)) as
|
|
890
|
-
props: CrudTableConfig<T, U, C> & {
|
|
891
|
-
ref?: ForwardedRef<CrudTableRefType<T>>;
|
|
892
|
-
},
|
|
893
|
-
) => JSX.Element;
|
|
987
|
+
export default React.memo(forwardRef(CrudTable)) as typeof CrudTable;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
// This file is generated by Umi automatically
|
|
3
|
+
// DO NOT CHANGE IT MANUALLY!
|
|
1
4
|
import { Empty, Select, Spin } from 'antd';
|
|
2
5
|
import React, {
|
|
3
6
|
ForwardedRef,
|
|
@@ -16,24 +19,6 @@ import { MySelectProps } from '../types';
|
|
|
16
19
|
|
|
17
20
|
const { Option } = Select;
|
|
18
21
|
|
|
19
|
-
/**
|
|
20
|
-
* @param autoSelect 列表只有一项时,直接选中,不需要再次点击
|
|
21
|
-
* @param showAllList 获取所有数据,不分页
|
|
22
|
-
* @param localListData 传递给组件的下拉数据
|
|
23
|
-
* @param backShowList 回显列表
|
|
24
|
-
* @param request 请求列表数据
|
|
25
|
-
* @param keyNames Option组件的参数
|
|
26
|
-
* @param searchKey 搜索传给后端的key
|
|
27
|
-
* @param otherSearchValue 根据其他条件查询下拉列表数据
|
|
28
|
-
* @param selectKey 下拉框选择的值
|
|
29
|
-
* @param onlyShowName 只显示名称
|
|
30
|
-
* @param itemRender 自定义渲染
|
|
31
|
-
* @param valueType 内容类型
|
|
32
|
-
* @param showDropdown 判断下拉框的显示
|
|
33
|
-
* @param getSelectList 获取当前选中的原始数据数组
|
|
34
|
-
* @param dropDownListChange 数据下拉列表变化回调
|
|
35
|
-
* @param 组件Select的参数
|
|
36
|
-
*/
|
|
37
22
|
const MySelect = <T,>(props: MySelectProps<T>, ref: ForwardedRef<any>) => {
|
|
38
23
|
const {
|
|
39
24
|
readonly,
|
|
@@ -262,6 +247,23 @@ const MySelect = <T,>(props: MySelectProps<T>, ref: ForwardedRef<any>) => {
|
|
|
262
247
|
);
|
|
263
248
|
};
|
|
264
249
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
250
|
+
/**
|
|
251
|
+
* 写在这里使用时才有提示
|
|
252
|
+
* @param autoSelect 列表只有一项时,直接选中,不需要再次点击
|
|
253
|
+
* @param showAllList 获取所有数据,不分页
|
|
254
|
+
* @param localListData 传递给组件的下拉数据
|
|
255
|
+
* @param backShowList 回显列表
|
|
256
|
+
* @param request 请求列表数据
|
|
257
|
+
* @param keyNames Option组件的参数
|
|
258
|
+
* @param searchKey 搜索传给后端的key
|
|
259
|
+
* @param otherSearchValue 根据其他条件查询下拉列表数据
|
|
260
|
+
* @param selectKey 下拉框选择的值
|
|
261
|
+
* @param onlyShowName 只显示名称
|
|
262
|
+
* @param itemRender 自定义渲染
|
|
263
|
+
* @param valueType 内容类型
|
|
264
|
+
* @param showDropdown 判断下拉框的显示
|
|
265
|
+
* @param getSelectList 获取当前选中的原始数据数组
|
|
266
|
+
* @param dropDownListChange 数据下拉列表变化回调
|
|
267
|
+
* @param 组件Select的参数
|
|
268
|
+
*/
|
|
269
|
+
export default React.memo(forwardRef(MySelect)) as typeof MySelect;
|
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
import { CloudDownloadOutlined, DownloadOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons';
|
|
2
|
-
import { ActionType, ColumnsState, ProColumns, ProTable } from '@ant-design/pro-components';
|
|
2
|
+
import { ActionType, ColumnsState, ProColumns, ProFormInstance, ProTable } from '@ant-design/pro-components';
|
|
3
3
|
import { cfmmUtils, ImportExecl, useFormatLocale, useIntl, useModel } from '@umijs/max';
|
|
4
|
-
import { Button, Dropdown, MenuProps, message, Modal, Progress } from 'antd';
|
|
4
|
+
import { Button, Drawer, Dropdown, MenuProps, message, Modal, Progress } from 'antd';
|
|
5
5
|
import React, { ForwardedRef, forwardRef, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
6
6
|
import useAction from '../hooks/useAction';
|
|
7
7
|
import useAuthority from '../hooks/useAuthority';
|
|
8
8
|
import useMemoizedFn from '../hooks/useMemoizedFn';
|
|
9
9
|
import useQueryTableList from '../hooks/useQueryTableList';
|
|
10
|
-
import {
|
|
10
|
+
import { importMultiLangList, queryLangInfoExportList } from '../services';
|
|
11
|
+
import {
|
|
12
|
+
API,
|
|
13
|
+
CrudTableConfig,
|
|
14
|
+
CrudTableRefType,
|
|
15
|
+
ExportMultiLangListItem,
|
|
16
|
+
LangInfoItem,
|
|
17
|
+
RefDrawerFormRefType,
|
|
18
|
+
} from '../types';
|
|
19
|
+
import { genExcel, genExcelAdvanced, getExportColumns, getExportValueForColumns } from '../utils/excelHelper';
|
|
20
|
+
import { handleImportList, showCheckErrorTips } from '../utils/importHelper';
|
|
11
21
|
import ActionLogDrawer from './ActionLogDrawer';
|
|
12
22
|
import CreateForm from './AddDrawerForm';
|
|
13
23
|
import DropdownButton from './DropdownButton';
|
|
14
24
|
import EditMultiLangForm from './EditMultiLangForm';
|
|
15
25
|
import MyFooterToolbar from './MyFooterToolbar';
|
|
16
26
|
import ViewTableItemDrawer from './ViewTableItemDrawer';
|
|
17
|
-
import { genExcel, genExcelAdvanced, getExportColumns, getExportValueForColumns } from '../utils/excelHelper';
|
|
18
|
-
import { importMultiLangList, queryLangInfoExportList } from '../services';
|
|
19
|
-
import { handleImportList, showCheckErrorTips } from '../utils/importHelper';
|
|
20
27
|
|
|
21
28
|
const { confirm } = Modal;
|
|
22
29
|
export const TABLE_SCROLL = { x: 'max-content' };
|
|
@@ -87,6 +94,7 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
87
94
|
const actionRef = useRef<ActionType>();
|
|
88
95
|
const updateDrawerRef = useRef<RefDrawerFormRefType>();
|
|
89
96
|
const timer = useRef<NodeJS.Timeout>();
|
|
97
|
+
const updateFormRef = useRef<ProFormInstance>();
|
|
90
98
|
|
|
91
99
|
// 状态管理
|
|
92
100
|
const [tableList, setTableList] = useState<T[]>([]);
|
|
@@ -96,6 +104,7 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
96
104
|
const [selectedRows, setSelectedRows] = useState<T[]>([]);
|
|
97
105
|
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
|
98
106
|
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
|
|
107
|
+
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
|
|
99
108
|
|
|
100
109
|
// 多语言编辑状态
|
|
101
110
|
const [editLangModalOpen, setEditLangModalOpen] = useState<boolean>(false);
|
|
@@ -133,27 +142,35 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
133
142
|
setEditLangModalOpen(true);
|
|
134
143
|
});
|
|
135
144
|
|
|
136
|
-
|
|
137
|
-
|
|
145
|
+
// 查询多语言数据
|
|
146
|
+
const queryMultiLangData = useMemoizedFn(
|
|
147
|
+
async (tableName: string, columnName: string): Promise<ExportMultiLangListItem[]> => {
|
|
148
|
+
if (!multiLang) return [];
|
|
138
149
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
150
|
+
if (multiLang.multiLangList) {
|
|
151
|
+
return multiLang.multiLangList;
|
|
152
|
+
}
|
|
142
153
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
154
|
+
if (multiLang.queryExportMultiLangData) {
|
|
155
|
+
return await multiLang.queryExportMultiLangData(tableName, columnName);
|
|
156
|
+
}
|
|
146
157
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
158
|
+
const result = await doAction(
|
|
159
|
+
'GET',
|
|
160
|
+
{ tableName, columnName },
|
|
161
|
+
{
|
|
162
|
+
actionFn: queryLangInfoExportList,
|
|
163
|
+
},
|
|
164
|
+
);
|
|
150
165
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
166
|
+
if (result.success && result.data) {
|
|
167
|
+
return result.data;
|
|
168
|
+
}
|
|
169
|
+
return [];
|
|
170
|
+
},
|
|
171
|
+
);
|
|
156
172
|
|
|
173
|
+
// 导出多语言数据
|
|
157
174
|
const handleExportMultiLang = useMemoizedFn(async () => {
|
|
158
175
|
if (multiLang?.exportMultiLangData) {
|
|
159
176
|
return await multiLang.exportMultiLangData();
|
|
@@ -173,7 +190,14 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
173
190
|
|
|
174
191
|
if (!data.length) return;
|
|
175
192
|
|
|
176
|
-
const handleData = data.map(item => [
|
|
193
|
+
const handleData = data.map((item) => [
|
|
194
|
+
item.dataId,
|
|
195
|
+
item.columnValue,
|
|
196
|
+
item.zh_CN,
|
|
197
|
+
item.zh_TW,
|
|
198
|
+
item.en_US,
|
|
199
|
+
item.th_TH,
|
|
200
|
+
]);
|
|
177
201
|
|
|
178
202
|
genExcelAdvanced(
|
|
179
203
|
`${title}.xlsx`,
|
|
@@ -184,10 +208,12 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
184
208
|
codeColumns: codeList,
|
|
185
209
|
title: title,
|
|
186
210
|
titleStyle: { fontSize: 18, bold: true },
|
|
187
|
-
notice: [
|
|
211
|
+
notice: [
|
|
212
|
+
formatMessage({ id: 'cfmmUI.common.button.exportMultiLang.notice', defaultMessage: '请勿修改表格结构' }),
|
|
213
|
+
],
|
|
188
214
|
worksheetColumns: new Array(codeList.length).fill('').map((item, index) => ({ hidden: index == 0, width: 25 })),
|
|
189
215
|
lockedColumns: [0], // 第一列不允许修改
|
|
190
|
-
}
|
|
216
|
+
},
|
|
191
217
|
);
|
|
192
218
|
return false;
|
|
193
219
|
});
|
|
@@ -212,14 +238,18 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
212
238
|
// return Promise.resolve({ success: false });
|
|
213
239
|
// }
|
|
214
240
|
|
|
215
|
-
const result = await doAction(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
241
|
+
const result = await doAction(
|
|
242
|
+
'IMPORT',
|
|
243
|
+
{
|
|
244
|
+
tableName: tableName,
|
|
245
|
+
columnName: columnName,
|
|
246
|
+
i18nDataList: newList.filter((item) => item.en_US || item.zh_CN || item.zh_TW || item.th_TH),
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
actionFn: importMultiLangList,
|
|
250
|
+
showMsg: false,
|
|
251
|
+
},
|
|
252
|
+
);
|
|
223
253
|
|
|
224
254
|
if (result.success) {
|
|
225
255
|
actionRef.current?.reload();
|
|
@@ -359,6 +389,10 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
359
389
|
editData = processedData;
|
|
360
390
|
}
|
|
361
391
|
|
|
392
|
+
setUpdateModalOpen(true);
|
|
393
|
+
|
|
394
|
+
updateFormRef.current?.setFieldsValue(editData);
|
|
395
|
+
|
|
362
396
|
updateDrawerRef.current?.show();
|
|
363
397
|
setEditRow(editData);
|
|
364
398
|
});
|
|
@@ -402,9 +436,9 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
402
436
|
});
|
|
403
437
|
};
|
|
404
438
|
|
|
405
|
-
//
|
|
439
|
+
// 导入列表数据
|
|
406
440
|
const importListData = useMemoizedFn(async (list: T[]) => {
|
|
407
|
-
if(!apis.importData && !interceptors.importData?.submitImportListData) return;
|
|
441
|
+
if (!apis.importData && !interceptors.importData?.submitImportListData) return;
|
|
408
442
|
|
|
409
443
|
// 处理导入数据,正确赋值字段以及转格式
|
|
410
444
|
const newList = interceptors.importData?.request?.(list) ?? handleImportList<T>(list);
|
|
@@ -417,7 +451,7 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
417
451
|
return Promise.resolve({ success: false });
|
|
418
452
|
}
|
|
419
453
|
|
|
420
|
-
const resutl = await interceptors.importData?.submitImportListData?.(newList) || await submitListData(newList);
|
|
454
|
+
const resutl = (await interceptors.importData?.submitImportListData?.(newList)) || (await submitListData(newList));
|
|
421
455
|
|
|
422
456
|
onAfterImport?.(resutl);
|
|
423
457
|
|
|
@@ -427,13 +461,14 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
427
461
|
return resutl;
|
|
428
462
|
});
|
|
429
463
|
|
|
464
|
+
// 处理进度条变化
|
|
430
465
|
const handlePercentChange = (value: number) => {
|
|
431
466
|
setPercent(value);
|
|
432
467
|
};
|
|
433
468
|
|
|
434
469
|
/**
|
|
435
|
-
|
|
436
|
-
|
|
470
|
+
* 下载数据为Excel
|
|
471
|
+
*/
|
|
437
472
|
const handleDownloadExcel = async () => {
|
|
438
473
|
const result = await handleSearchAll();
|
|
439
474
|
if (!result.success || result.error || !result.data) {
|
|
@@ -569,7 +604,7 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
569
604
|
...(actionColumnConfig?.columnConfig ?? {}),
|
|
570
605
|
},
|
|
571
606
|
];
|
|
572
|
-
}, [rowKey, columns, multiLang, defaultAuthCodes, actionColumnConfig]);
|
|
607
|
+
}, [rowKey, columns, multiLang, defaultAuthCodes, actionColumnConfig, updateFormRef]);
|
|
573
608
|
|
|
574
609
|
useImperativeHandle(
|
|
575
610
|
ref,
|
|
@@ -630,7 +665,7 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
630
665
|
|
|
631
666
|
// 处理表格额外操作按钮列表
|
|
632
667
|
const handleTableButtonList = (allButtons: MenuProps['items']) => {
|
|
633
|
-
if(!allButtons?.length) return allButtons;
|
|
668
|
+
if (!allButtons?.length) return allButtons;
|
|
634
669
|
|
|
635
670
|
let renderList: MenuProps['items'] | any[] = [...(allButtons ?? [])];
|
|
636
671
|
|
|
@@ -704,7 +739,8 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
704
739
|
),
|
|
705
740
|
},
|
|
706
741
|
{
|
|
707
|
-
auth:
|
|
742
|
+
auth:
|
|
743
|
+
getAuthorityFn(defaultAuthCodes.import) && (apis.importData || interceptors.importData?.submitImportListData),
|
|
708
744
|
key: 'import',
|
|
709
745
|
label: (
|
|
710
746
|
<ImportExecl key="importMaterial" rangeStart={{ c: 0, r: 2 }} onChange={importListData}>
|
|
@@ -719,19 +755,19 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
719
755
|
auth: getAuthorityFn(defaultAuthCodes.export),
|
|
720
756
|
key: 'export',
|
|
721
757
|
disabled: !tableList.length || loading,
|
|
722
|
-
label:
|
|
723
|
-
<
|
|
724
|
-
|
|
725
|
-
|
|
758
|
+
label: (
|
|
759
|
+
<a onClick={handleDownloadExcel} key="export">
|
|
760
|
+
<CloudDownloadOutlined style={{ marginRight: 6 }} />
|
|
761
|
+
{formatMessage({ id: 'cfmmUI.common.button.exportData', defaultMessage: '导出数据' })}
|
|
762
|
+
</a>
|
|
763
|
+
),
|
|
726
764
|
},
|
|
727
765
|
];
|
|
728
766
|
|
|
729
767
|
allButtons = handleTableButtonList(allButtons);
|
|
730
768
|
|
|
731
769
|
// 过滤有权限的按钮,并移除 auth 属性避免传递到 DOM
|
|
732
|
-
return allButtons
|
|
733
|
-
.filter((button) => button.auth)
|
|
734
|
-
.map(({ auth, ...rest }) => rest);
|
|
770
|
+
return allButtons!.filter((button) => button.auth).map(({ auth, ...rest }) => rest);
|
|
735
771
|
}, [tableList, loading, columnsStateMap]);
|
|
736
772
|
|
|
737
773
|
return (
|
|
@@ -750,10 +786,14 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
750
786
|
toolBarRender={useMemoizedFn(() => {
|
|
751
787
|
if (!getBarButtons?.length) return [];
|
|
752
788
|
return [
|
|
753
|
-
<Dropdown.Button
|
|
789
|
+
<Dropdown.Button
|
|
790
|
+
type="primary"
|
|
791
|
+
loading={actionLoading || downloadButtonLoading}
|
|
792
|
+
menu={{ items: getBarButtons.slice(1) }}
|
|
793
|
+
>
|
|
754
794
|
{getBarButtons[0].icon}
|
|
755
795
|
{getBarButtons[0].label}
|
|
756
|
-
</Dropdown.Button
|
|
796
|
+
</Dropdown.Button>,
|
|
757
797
|
];
|
|
758
798
|
})}
|
|
759
799
|
request={useMemoizedFn(async (params, sorter) => {
|
|
@@ -844,7 +884,7 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
844
884
|
)}
|
|
845
885
|
|
|
846
886
|
{/* 编辑表单 */}
|
|
847
|
-
{updateConfig.Component
|
|
887
|
+
{updateConfig.Component ? (
|
|
848
888
|
<updateConfig.Component
|
|
849
889
|
updateDrawerRef={updateDrawerRef}
|
|
850
890
|
values={editRow}
|
|
@@ -864,6 +904,64 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
864
904
|
}}
|
|
865
905
|
{...(updateConfig.props as U)}
|
|
866
906
|
/>
|
|
907
|
+
) : (
|
|
908
|
+
<Drawer
|
|
909
|
+
width={500}
|
|
910
|
+
title={formatMessage({
|
|
911
|
+
id: `${baseLocalCode}.update.title`,
|
|
912
|
+
defaultMessage: '修改',
|
|
913
|
+
})}
|
|
914
|
+
forceRender // 勿删,否则formRef无法被绑定到ProTable上,因为ProTable是异步渲染的
|
|
915
|
+
maskClosable={false}
|
|
916
|
+
open={updateModalOpen}
|
|
917
|
+
onClose={() => {
|
|
918
|
+
setEditRow(null);
|
|
919
|
+
setUpdateModalOpen(false);
|
|
920
|
+
}}
|
|
921
|
+
// footer={<Button onClick={() => props.form?.resetFields()}>清空</Button>}
|
|
922
|
+
>
|
|
923
|
+
<ProTable<T, T>
|
|
924
|
+
loading={actionLoading}
|
|
925
|
+
onSubmit={useMemoizedFn(async (value) => {
|
|
926
|
+
|
|
927
|
+
const success = await handleAction('PUT', {
|
|
928
|
+
...value,
|
|
929
|
+
[rowKey]: editRow?.[rowKey],
|
|
930
|
+
});
|
|
931
|
+
if (success) {
|
|
932
|
+
actionRef.current?.reload();
|
|
933
|
+
setEditRow(null);
|
|
934
|
+
setUpdateModalOpen(false);
|
|
935
|
+
}
|
|
936
|
+
return success;
|
|
937
|
+
})}
|
|
938
|
+
rowKey={rowKey as string}
|
|
939
|
+
type="form"
|
|
940
|
+
columns={columns}
|
|
941
|
+
{...(updateConfig.props as U)}
|
|
942
|
+
formRef={updateFormRef}
|
|
943
|
+
onReset={() => {
|
|
944
|
+
updateFormRef.current?.setFieldsValue({ ...(editRow || {}) });
|
|
945
|
+
}}
|
|
946
|
+
// 自定义按钮
|
|
947
|
+
// form={{
|
|
948
|
+
// submitter: {
|
|
949
|
+
// searchConfig: {
|
|
950
|
+
// submitText: '保存',
|
|
951
|
+
// resetText: '还原',
|
|
952
|
+
// },
|
|
953
|
+
// submitButtonProps: { type: 'primary' },
|
|
954
|
+
// resetButtonProps: { type: 'default' },
|
|
955
|
+
// render: (props, dom) => (
|
|
956
|
+
// <Space>
|
|
957
|
+
// <Button onClick={() => props.form?.resetFields()}>清空</Button>
|
|
958
|
+
// {dom[1]} {/* 默认提交按钮 */}
|
|
959
|
+
// </Space>
|
|
960
|
+
// ),
|
|
961
|
+
// },
|
|
962
|
+
// }}
|
|
963
|
+
/>
|
|
964
|
+
</Drawer>
|
|
867
965
|
)}
|
|
868
966
|
|
|
869
967
|
{/* 多语言编辑 */}
|
|
@@ -886,8 +984,4 @@ function CrudTable<T extends Record<string, any>, U = {}, C = {}>(
|
|
|
886
984
|
);
|
|
887
985
|
}
|
|
888
986
|
|
|
889
|
-
export default React.memo(forwardRef(CrudTable)) as
|
|
890
|
-
props: CrudTableConfig<T, U, C> & {
|
|
891
|
-
ref?: ForwardedRef<CrudTableRefType<T>>;
|
|
892
|
-
},
|
|
893
|
-
) => JSX.Element;
|
|
987
|
+
export default React.memo(forwardRef(CrudTable)) as typeof CrudTable;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
// This file is generated by Umi automatically
|
|
3
|
+
// DO NOT CHANGE IT MANUALLY!
|
|
1
4
|
import { Empty, Select, Spin } from 'antd';
|
|
2
5
|
import React, {
|
|
3
6
|
ForwardedRef,
|
|
@@ -16,24 +19,6 @@ import { MySelectProps } from '../types';
|
|
|
16
19
|
|
|
17
20
|
const { Option } = Select;
|
|
18
21
|
|
|
19
|
-
/**
|
|
20
|
-
* @param autoSelect 列表只有一项时,直接选中,不需要再次点击
|
|
21
|
-
* @param showAllList 获取所有数据,不分页
|
|
22
|
-
* @param localListData 传递给组件的下拉数据
|
|
23
|
-
* @param backShowList 回显列表
|
|
24
|
-
* @param request 请求列表数据
|
|
25
|
-
* @param keyNames Option组件的参数
|
|
26
|
-
* @param searchKey 搜索传给后端的key
|
|
27
|
-
* @param otherSearchValue 根据其他条件查询下拉列表数据
|
|
28
|
-
* @param selectKey 下拉框选择的值
|
|
29
|
-
* @param onlyShowName 只显示名称
|
|
30
|
-
* @param itemRender 自定义渲染
|
|
31
|
-
* @param valueType 内容类型
|
|
32
|
-
* @param showDropdown 判断下拉框的显示
|
|
33
|
-
* @param getSelectList 获取当前选中的原始数据数组
|
|
34
|
-
* @param dropDownListChange 数据下拉列表变化回调
|
|
35
|
-
* @param 组件Select的参数
|
|
36
|
-
*/
|
|
37
22
|
const MySelect = <T,>(props: MySelectProps<T>, ref: ForwardedRef<any>) => {
|
|
38
23
|
const {
|
|
39
24
|
readonly,
|
|
@@ -262,6 +247,23 @@ const MySelect = <T,>(props: MySelectProps<T>, ref: ForwardedRef<any>) => {
|
|
|
262
247
|
);
|
|
263
248
|
};
|
|
264
249
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
250
|
+
/**
|
|
251
|
+
* 写在这里使用时才有提示
|
|
252
|
+
* @param autoSelect 列表只有一项时,直接选中,不需要再次点击
|
|
253
|
+
* @param showAllList 获取所有数据,不分页
|
|
254
|
+
* @param localListData 传递给组件的下拉数据
|
|
255
|
+
* @param backShowList 回显列表
|
|
256
|
+
* @param request 请求列表数据
|
|
257
|
+
* @param keyNames Option组件的参数
|
|
258
|
+
* @param searchKey 搜索传给后端的key
|
|
259
|
+
* @param otherSearchValue 根据其他条件查询下拉列表数据
|
|
260
|
+
* @param selectKey 下拉框选择的值
|
|
261
|
+
* @param onlyShowName 只显示名称
|
|
262
|
+
* @param itemRender 自定义渲染
|
|
263
|
+
* @param valueType 内容类型
|
|
264
|
+
* @param showDropdown 判断下拉框的显示
|
|
265
|
+
* @param getSelectList 获取当前选中的原始数据数组
|
|
266
|
+
* @param dropDownListChange 数据下拉列表变化回调
|
|
267
|
+
* @param 组件Select的参数
|
|
268
|
+
*/
|
|
269
|
+
export default React.memo(forwardRef(MySelect)) as typeof MySelect;
|