@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yorha2b-lab/autodev",
3
- "version": "2.1.17",
3
+ "version": "2.1.19",
4
4
  "description": "基于视觉大模型的前端(react+Antd)全自动 CRUD 代码生成器",
5
5
  "bin": {
6
6
  "autodev": "bin/autodev.js"
@@ -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
- toggleEdit()
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} onBlur={save} placeholder={placeholder ?? title} />
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
- <Checkbox.Group ref={inputRef} options={options} />
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} onBlur={save} placeholder={placeholder ?? title} />
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 rules={rules} name={dataIndex} style={{ margin: 0 }}>
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 components = {
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
- const newData = [...dataSource]
21
- const index = newData.findIndex(item => row[rowKey] === item[rowKey])
22
- const item = newData[index]
23
- newData.splice(index, 1, { ...item, ...row })
24
- setDataSource(newData)
25
- customSave?.({ ...item, ...row })
26
- }
27
-
28
- const paginationConfig = useMemo(() => {
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
- return {
33
- total,
34
- showSizeChanger: true,
35
- current: search?.pageNo,
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
- }, [total, search, pagination])
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', 'daterange'].includes(item.type) ? '选择' : '输入'}`,
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.id),
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
- async params => await request('/api/{{fileName}}', { method: 'POST', body: params }),
7
- response => ({ data: response?.data ?? [], total: response?.total ?? 0 }),
8
- {...initParams, ...query},
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,3 +1,5 @@
1
+
2
+ const rowKey = 'id'
1
3
  const [form] = Form.useForm()
2
4
  const [modal, setModal] = useState({ visible:false, title:'', formItems:[] })
3
5
  {{#if hasRowSelection}}
@@ -1,11 +1,12 @@
1
1
  import { useRef, useState, useEffect, useCallback } from 'react'
2
2
 
3
- export const useTableQuery = (api, formatResponse, initialParams = {}) => {
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({ pageNo: 1, pageSize: 10, ...initialParams })
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
  }