@yorha2b-lab/autodev 2.1.17 → 2.1.19
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.
- package/package.json +1 -1
- package/templates/react/components/EditableCell.js +36 -12
- package/templates/react/components/MyModalTable.js +4 -3
- package/templates/react/components/MyTable.js +37 -32
- package/templates/react/components/index.js +3 -3
- package/templates/react/handlebars/MyTable.hbs +2 -2
- package/templates/react/handlebars/hookBlock.hbs +12 -5
- package/templates/react/handlebars/stateBlock.hbs +2 -0
- package/templates/react/hooks/useTableQuery.js +10 -4
package/package.json
CHANGED
|
@@ -3,10 +3,18 @@ import React, { useRef, useState, useEffect, useContext } from 'react'
|
|
|
3
3
|
|
|
4
4
|
const EditableContext = React.createContext(null)
|
|
5
5
|
|
|
6
|
-
export const EditableRow = ({ index, ...props }) => {
|
|
6
|
+
export const EditableRow = ({ index, record, ...props }) => {
|
|
7
|
+
|
|
7
8
|
const [form] = Form.useForm()
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
if (record) {
|
|
12
|
+
form.setFieldsValue(record)
|
|
13
|
+
}
|
|
14
|
+
}, [record])
|
|
15
|
+
|
|
8
16
|
return (
|
|
9
|
-
<Form form={form} component={false}>
|
|
17
|
+
<Form form={form} component={false} onValuesChange={(changedValue, allValue) => props?.onValuesChange?.({ changedValue, allValue, form })}>
|
|
10
18
|
<EditableContext.Provider value={form}>
|
|
11
19
|
<tr {...props} />
|
|
12
20
|
</EditableContext.Provider>
|
|
@@ -14,7 +22,7 @@ export const EditableRow = ({ index, ...props }) => {
|
|
|
14
22
|
)
|
|
15
23
|
}
|
|
16
24
|
|
|
17
|
-
export const EditableCell = ({ title, record, editable, children, dataIndex, placeholder, handleSave, rules = [], options = [], editType = 'text', ...restProps }) => {
|
|
25
|
+
export const EditableCell = ({ title, record, editable, disabled, children, dataIndex, placeholder, handleSave, defaultEdit, rules = [], options = [], editType = 'text', ...restProps }) => {
|
|
18
26
|
|
|
19
27
|
const inputRef = useRef(null)
|
|
20
28
|
const form = useContext(EditableContext)
|
|
@@ -37,7 +45,9 @@ export const EditableCell = ({ title, record, editable, children, dataIndex, pla
|
|
|
37
45
|
const save = async () => {
|
|
38
46
|
try {
|
|
39
47
|
const values = await form.validateFields()
|
|
40
|
-
|
|
48
|
+
if (!defaultEdit) {
|
|
49
|
+
toggleEdit()
|
|
50
|
+
}
|
|
41
51
|
handleSave({ ...record, ...values })
|
|
42
52
|
} catch (errInfo) {
|
|
43
53
|
console.log('保存失败:', errInfo)
|
|
@@ -46,13 +56,25 @@ export const EditableCell = ({ title, record, editable, children, dataIndex, pla
|
|
|
46
56
|
|
|
47
57
|
let inputNode
|
|
48
58
|
|
|
59
|
+
const formProps = {
|
|
60
|
+
rules,
|
|
61
|
+
name: dataIndex,
|
|
62
|
+
style: { margin: 0 },
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const commonProps = {
|
|
66
|
+
onBlur: save,
|
|
67
|
+
disabled: disabled,
|
|
68
|
+
placeholder: placeholder ?? title,
|
|
69
|
+
}
|
|
70
|
+
|
|
49
71
|
switch (editType) {
|
|
50
|
-
case 'number':
|
|
51
|
-
inputNode = <InputNumber ref={inputRef} onPressEnter={save} onBlur={save} placeholder={placeholder ?? title} />
|
|
52
|
-
break
|
|
53
72
|
case 'select':
|
|
54
|
-
inputNode = <Select ref={inputRef} options={options}
|
|
73
|
+
inputNode = <Select ref={inputRef} options={options} {...commonProps} />
|
|
55
74
|
break;
|
|
75
|
+
case 'number':
|
|
76
|
+
inputNode = <InputNumber ref={inputRef} onPressEnter={save} {...commonProps} />
|
|
77
|
+
break
|
|
56
78
|
case 'checkbox':
|
|
57
79
|
inputNode = (
|
|
58
80
|
<div tabIndex={-1} onBlur={e => {
|
|
@@ -61,19 +83,21 @@ export const EditableCell = ({ title, record, editable, children, dataIndex, pla
|
|
|
61
83
|
save()
|
|
62
84
|
}
|
|
63
85
|
}}>
|
|
64
|
-
<
|
|
86
|
+
<Form.Item {...formProps}>
|
|
87
|
+
<Checkbox.Group ref={inputRef} options={options} disabled={disabled} {...(options.length === 1 ? { onChange: save } : {})} />
|
|
88
|
+
</Form.Item>
|
|
65
89
|
</div>
|
|
66
90
|
)
|
|
67
91
|
break;
|
|
68
92
|
default:
|
|
69
|
-
inputNode = <Input ref={inputRef} onPressEnter={save}
|
|
93
|
+
inputNode = <Input ref={inputRef} onPressEnter={save} {...commonProps} />
|
|
70
94
|
}
|
|
71
95
|
|
|
72
96
|
return (
|
|
73
97
|
<td {...restProps}>
|
|
74
98
|
{editable ? (
|
|
75
|
-
editing ? (
|
|
76
|
-
<Form.Item
|
|
99
|
+
editing || defaultEdit ? (
|
|
100
|
+
<Form.Item {...(['checkbox'].includes(editType) ? { style: formProps.style } : formProps)}>
|
|
77
101
|
{inputNode}
|
|
78
102
|
</Form.Item>
|
|
79
103
|
) : (
|
|
@@ -15,17 +15,18 @@ export const MyModalTable = ({ api, onOk, title, width, footer, visible, columns
|
|
|
15
15
|
|
|
16
16
|
const handleTableChange = (pagination, filters, sorter) => setSearch({ ...search, pageNo: pagination.current, pageSize: pagination.pageSize, orderBy: sorter.column ? sorter.field : undefined })
|
|
17
17
|
|
|
18
|
-
const handleOk = () => {
|
|
18
|
+
const handleOk = async () => {
|
|
19
19
|
if (onOk) {
|
|
20
20
|
try {
|
|
21
21
|
setPending(true)
|
|
22
|
-
onOk()
|
|
22
|
+
await onOk()
|
|
23
23
|
setPending(false)
|
|
24
24
|
} catch (error) {
|
|
25
25
|
console.log('操作失败:', error)
|
|
26
|
+
} finally {
|
|
27
|
+
setPending(false)
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
|
-
setModal({ visible: false })
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
return (
|
|
@@ -1,43 +1,31 @@
|
|
|
1
1
|
import { Table } from 'antd'
|
|
2
|
-
import { useRef, useMemo, useEffect } from 'react'
|
|
3
2
|
import { EditableRow, EditableCell } from './EditableCell'
|
|
3
|
+
import { useRef, useMemo, useEffect, useCallback } from 'react'
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
body: {
|
|
7
|
-
row: EditableRow,
|
|
8
|
-
cell: EditableCell,
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export const MyTable = ({ size, query, total, search, autoScroll, onChange, pagination, rowClassName, customSave, setDataSource, columns = [], rowSelection, rowKey = 'id', loading = false, dataSource = [], scroll = { x: 'max-content' }, ...restProps }) => {
|
|
5
|
+
export const MyTable = ({ size, query, total, search, autoScroll, onChange, pagination, rowClassName, customSave, setDataSource, lineFormChange, columns = [], rowSelection, rowKey = 'id', loading = false, dataSource = [], scroll = { x: 'max-content' }, ...restProps }) => {
|
|
13
6
|
|
|
14
7
|
const tableRef = useRef(null)
|
|
15
8
|
const hasScrolledRef = useRef(false)
|
|
16
9
|
|
|
17
10
|
const isEditable = useMemo(() => columns.some(col => col.editType), [columns])
|
|
18
11
|
|
|
19
|
-
const handleSave = row => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (!pagination) return false
|
|
12
|
+
const handleSave = useCallback((row) => {
|
|
13
|
+
setDataSource(prev => {
|
|
14
|
+
const newData = [...prev]
|
|
15
|
+
const index = newData.findIndex(item => row[rowKey] === item[rowKey])
|
|
16
|
+
const item = newData[index]
|
|
17
|
+
newData.splice(index, 1, { ...item, ...row })
|
|
18
|
+
customSave?.({ ...item, ...row }, newData)
|
|
19
|
+
return newData
|
|
20
|
+
})
|
|
21
|
+
}, [rowKey, customSave, setDataSource])
|
|
31
22
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
pageSize: search?.pageSize,
|
|
37
|
-
showTotal: (total) => `共 ${total} 条`,
|
|
38
|
-
...(typeof pagination === 'object' ? pagination : {})
|
|
23
|
+
const components = useMemo(() => ({
|
|
24
|
+
body: {
|
|
25
|
+
row: EditableRow,
|
|
26
|
+
cell: EditableCell,
|
|
39
27
|
}
|
|
40
|
-
}, [
|
|
28
|
+
}), [])
|
|
41
29
|
|
|
42
30
|
const mergedColumns = useMemo(() => {
|
|
43
31
|
return columns.map(col => {
|
|
@@ -53,13 +41,29 @@ export const MyTable = ({ size, query, total, search, autoScroll, onChange, pagi
|
|
|
53
41
|
rules: col.rules,
|
|
54
42
|
options: col.options,
|
|
55
43
|
editType: col.editType,
|
|
56
|
-
editable: !!col.editType,
|
|
57
44
|
dataIndex: col.dataIndex,
|
|
58
|
-
placeholder: col.placeholder
|
|
45
|
+
placeholder: col.placeholder,
|
|
46
|
+
defaultEdit: col.defaultEdit,
|
|
47
|
+
disabled: col.specialDisabled ? record.disabled : col.disabled,
|
|
48
|
+
editable: col.specialEditType ? record.needEdit && !!col.editType : !!col.editType,
|
|
59
49
|
}),
|
|
60
50
|
}
|
|
61
51
|
})
|
|
62
|
-
}, [columns])
|
|
52
|
+
}, [columns, handleSave])
|
|
53
|
+
|
|
54
|
+
const paginationConfig = useMemo(() => {
|
|
55
|
+
|
|
56
|
+
if (!pagination) return false
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
total,
|
|
60
|
+
showSizeChanger: true,
|
|
61
|
+
current: search?.pageNo,
|
|
62
|
+
pageSize: search?.pageSize,
|
|
63
|
+
showTotal: (total) => `共 ${total} 条`,
|
|
64
|
+
...(typeof pagination === 'object' ? pagination : {})
|
|
65
|
+
}
|
|
66
|
+
}, [total, search, pagination])
|
|
63
67
|
|
|
64
68
|
useEffect(() => {
|
|
65
69
|
if (!autoScroll || !dataSource?.length || query?.rowIndex === undefined) return
|
|
@@ -92,6 +96,7 @@ export const MyTable = ({ size, query, total, search, autoScroll, onChange, pagi
|
|
|
92
96
|
rowSelection={rowSelection}
|
|
93
97
|
pagination={paginationConfig}
|
|
94
98
|
components={isEditable ? components : undefined}
|
|
99
|
+
onRow={(record, index) => ({ record, index, onValuesChange: lineFormChange })}
|
|
95
100
|
rowClassName={(record, index) => {
|
|
96
101
|
const externalClass = typeof rowClassName === 'function' ? rowClassName(record, index) : rowClassName
|
|
97
102
|
const classes = [externalClass]
|
|
@@ -71,7 +71,7 @@ export const formNode = ({ item }) => {
|
|
|
71
71
|
const commonProps = {
|
|
72
72
|
disabled: item.readOnly,
|
|
73
73
|
style: { width: item.width ?? '100%' },
|
|
74
|
-
placeholder: item.placeholder ?? `请${['select', 'cascader', 'date'
|
|
74
|
+
placeholder: item.placeholder ?? `请${['select', 'cascader', 'date'].includes(item.type) ? '选择' : '输入'}`,
|
|
75
75
|
...item.props
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -82,8 +82,6 @@ export const formNode = ({ item }) => {
|
|
|
82
82
|
return <InputNumber {...commonProps} />
|
|
83
83
|
case 'ossUpload':
|
|
84
84
|
return <AliyunOSSUpload {...commonProps} />
|
|
85
|
-
case 'daterange':
|
|
86
|
-
return <DatePicker.RangePicker {...commonProps} />
|
|
87
85
|
case 'radio':
|
|
88
86
|
return <Radio.Group options={item.options} {...commonProps} />
|
|
89
87
|
case 'treeSelect':
|
|
@@ -96,6 +94,8 @@ export const formNode = ({ item }) => {
|
|
|
96
94
|
return <Tree checkable treeData={item.options} {...commonProps} />
|
|
97
95
|
case 'textarea':
|
|
98
96
|
return <Input.TextArea autoSize={{ minRows: 4 }} {...commonProps} />
|
|
97
|
+
case 'daterange':
|
|
98
|
+
return <DatePicker.RangePicker {...commonProps} placeholder={undefined} />
|
|
99
99
|
case 'cascader':
|
|
100
100
|
return <Cascader showSearch allowClear options={item.options} {...commonProps} />
|
|
101
101
|
case 'upload':
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<MyTable
|
|
2
|
-
rowKey='id'
|
|
3
2
|
query={query}
|
|
4
3
|
total={total}
|
|
4
|
+
rowKey={rowKey}
|
|
5
5
|
search={search}
|
|
6
6
|
loading={loading}
|
|
7
7
|
dataSource={dataSource}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
{{#if hasRowSelection}}
|
|
21
21
|
{{{{raw}}}}
|
|
22
22
|
rowSelection={{
|
|
23
|
-
selectedRowKeys: selectedRows.map(item => item
|
|
23
|
+
selectedRowKeys: selectedRows.map(item => item[rowKey]),
|
|
24
24
|
onChange: (keys, rows) => setSelectedRows(rows)
|
|
25
25
|
}}
|
|
26
26
|
{{{{/raw}}}}
|
|
@@ -2,8 +2,15 @@ const initParams = {{#if hasTabs}}{ type: tabs[0].key }{{else}}{}{{/if}}
|
|
|
2
2
|
|
|
3
3
|
const query = formatQuery(Object.fromEntries(new URLSearchParams(location.search).entries()), {{formItems}})
|
|
4
4
|
|
|
5
|
-
const { total, loading, dataSource, search, setSearch, setDataSource, refresh } = useTableQuery(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
const { total, columns, loading, dataSource, search, setSearch, setDataSource, refresh } = useTableQuery({
|
|
6
|
+
api: async params => await request('/api/{{fileName}}', { method: 'POST', body: params }),
|
|
7
|
+
initialParams: { pageNo: 1, pageSize: 10, ...query },
|
|
8
|
+
cols:[],//前端指定列数组
|
|
9
|
+
formatResponse: response => {
|
|
10
|
+
return {
|
|
11
|
+
data: response?.data ?? [],
|
|
12
|
+
total: response?.data?.total ?? 0,
|
|
13
|
+
columns: [],//可选,解析接口动态列;优先级高于cols
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
})
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { useRef, useState, useEffect, useCallback } from 'react'
|
|
2
2
|
|
|
3
|
-
export const useTableQuery = (api,
|
|
3
|
+
export const useTableQuery = ({ api, cols = [], initialParams = {}, formatResponse }) => {
|
|
4
4
|
|
|
5
5
|
const [total, setTotal] = useState(0)
|
|
6
|
+
const [columns, setColumns] = useState(cols)
|
|
6
7
|
const [loading, setLoading] = useState(false)
|
|
7
8
|
const [dataSource, setDataSource] = useState([])
|
|
8
|
-
const [search, setSearch] = useState(
|
|
9
|
+
const [search, setSearch] = useState(initialParams)
|
|
9
10
|
|
|
10
11
|
const apiRef = useRef(api)
|
|
11
12
|
const fetchIdRef = useRef(0)
|
|
@@ -14,6 +15,8 @@ export const useTableQuery = (api, formatResponse, initialParams = {}) => {
|
|
|
14
15
|
apiRef.current = api
|
|
15
16
|
}, [api])
|
|
16
17
|
|
|
18
|
+
const getColumnSchema = cols => cols.map(col => ({ title: col.title, dataIndex: col.dataIndex })).join('|')
|
|
19
|
+
|
|
17
20
|
const fetchData = useCallback(async () => {
|
|
18
21
|
if (!apiRef.current) return
|
|
19
22
|
setLoading(true)
|
|
@@ -21,7 +24,10 @@ export const useTableQuery = (api, formatResponse, initialParams = {}) => {
|
|
|
21
24
|
try {
|
|
22
25
|
const response = await apiRef.current(search)
|
|
23
26
|
if (currentFetchId !== fetchIdRef.current) return
|
|
24
|
-
const { data, total } = formatResponse(response ?? {})
|
|
27
|
+
const { data, total, columns: newCols } = formatResponse(response ?? {})
|
|
28
|
+
if (newCols && getColumnSchema(newCols) !== getColumnSchema(columns)) {
|
|
29
|
+
setColumns(newCols)
|
|
30
|
+
}
|
|
25
31
|
setDataSource(data)
|
|
26
32
|
setTotal(total ?? 0)
|
|
27
33
|
} catch (error) {
|
|
@@ -37,5 +43,5 @@ export const useTableQuery = (api, formatResponse, initialParams = {}) => {
|
|
|
37
43
|
fetchData()
|
|
38
44
|
}, [fetchData])
|
|
39
45
|
|
|
40
|
-
return { total, loading, dataSource, search, setSearch, setDataSource, refresh: fetchData }
|
|
46
|
+
return { total, columns, loading, dataSource, search, setSearch, setDataSource, refresh: fetchData }
|
|
41
47
|
}
|