@yorha2b-lab/autodev 3.3.0 → 3.4.0

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": "3.3.0",
3
+ "version": "3.4.0",
4
4
  "description": "基于视觉大模型的前端(react+Antd)全自动 CRUD 代码生成器",
5
5
  "bin": {
6
6
  "autodev": "bin/autodev.js"
@@ -40,8 +40,9 @@ module.exports = `
40
40
  - 命名规范:
41
41
  - daterange: name 必须设为 '字段英文名start,字段英文名end'。
42
42
  - 增强属性:
43
- - 必填校验: 若图片中 label 前有红色星号,必须加入 rules:[{required:true,message:'xxx不能为空'}]。
44
43
  - 文字单位: 若项末尾有单位(如 元/kg),必须存入 unit 属性。
44
+ - 尾操作: 若项末尾有操作按钮(如 选择、编辑 等操作),必须存入 {renderAction:true,addonAfter:'尾操作名'} 属性。
45
+ - 必填校验: 若图片中 label 前有红色星号,必须加入 rules:[{required:true,message:'xxx不能为空'}]。
45
46
 
46
47
  ## 3. 下拉选项字典 (OptionDict)
47
48
  - 结构: optionDict: { 字段英文名Options: [] }
@@ -45,17 +45,17 @@ export const EditableRow = ({ index, record, ...props }) => {
45
45
  * 支持多种装配模式(text/number/select/checkbox),并具备“自动对焦”与“失焦自愈(自动保存)”功能。
46
46
  *
47
47
  * @param {Object} props - 构筑参数
48
- * @param {string} props.title - 零部件视觉标题,兼作占位符使用
48
+ * @param {Array} [props.rules=[]] - 逻辑校验准则
49
49
  * @param {Object} props.record - 当前行原始物资数据
50
- * @param {boolean} props.editable - 权限协议:是否允许开启编辑模式
51
50
  * @param {boolean} props.disabled - 物理锁定:是否禁止修改
51
+ * @param {string} props.title - 零部件视觉标题,兼作占位符使用
52
+ * @param {React.ReactNode} props.children - 默认展示的视觉节点
53
+ * @param {boolean} props.editable - 权限协议:是否允许开启编辑模式
52
54
  * @param {string} props.dataIndex - 逻辑寻址地址:对应后端数据的字段名
55
+ * @param {Array} [props.options=[]] - 数据字典(仅用于 select/checkbox)
53
56
  * @param {Function} props.handleSave - 物理封存协议:数据校验通过后的保存回调
54
57
  * @param {boolean} [props.defaultEdit] - 持久化模式:是否默认始终开启编辑状态
55
- * @param {Array} [props.rules=[]] - 逻辑校验准则
56
- * @param {Array} [props.options=[]] - 数据字典(仅用于 select/checkbox)
57
58
  * @param {string} [props.editType='text'] - 零部件型号(text/number/select/checkbox)
58
- * @param {React.ReactNode} props.children - 默认展示的视觉节点
59
59
  */
60
60
  export const EditableCell = ({ title, record, editable, disabled, children, dataIndex, placeholder, handleSave, defaultEdit, rules = [], options = [], editType = 'text', ...restProps }) => {
61
61
 
@@ -63,9 +63,9 @@ const renderFormContent = ({ item, prefixName = [] }) => {
63
63
  *
64
64
  * @param {Object} props - 组件属性
65
65
  * @param {Object} props.item - 构筑协议对象
66
+ * @param {Object} props.form - Antd Form 实例,用于实现复杂的跨组件联动
66
67
  * @param {boolean} [props.item.isList] - 模式切换:是否开启动态增减列表模式
67
68
  * @param {Function} [props.item.render] - 逻辑劫持:支持自定义渲染函数,可完全改写渲染行为
68
- * @param {Object} props.form - Antd Form 实例,用于实现复杂的跨组件联动
69
69
  *
70
70
  * @example
71
71
  * // 模式 A:标准表单项
@@ -99,7 +99,7 @@ export const MyBaseForm = ({ item, form }) => {
99
99
  tooltip={item.tooltip}
100
100
  labelCol={item.labelCol}
101
101
  wrapperCol={item.wrapperCol}
102
- required={item.required ?? !!item.rules}
102
+ required={item.required ?? item.rules?.some(v => v.required)}
103
103
  style={{ marginBottom: !item.name ? 0 : undefined, ...item.style }}
104
104
  >
105
105
  {/*
@@ -1,7 +1,99 @@
1
1
  import dayjs from 'dayjs'
2
2
  import { MyBaseForm } from './MyBaseForm'
3
- import { useState, useEffect } from 'react'
4
- import { Row, Col, Form, Modal, } from 'antd'
3
+ import { MyModalTable } from './MyModalTable'
4
+ import { useMemo, useState, useEffect } from 'react'
5
+ import { Row, Col, Form, Modal, Button, Collapse } from 'antd'
6
+
7
+ const LAYOUT_PROCESSORS = {
8
+ // 分节布局
9
+ section: ({ item, children }) => (
10
+ <Col span={item.span ?? 24}>
11
+ <div className={item.className}>{item.title}</div>
12
+ <Row gutter={[24, 0]}>{children}</Row>
13
+ </Col>
14
+ ),
15
+ // 手风琴布局
16
+ collapse: ({ item, renderCore }) => (
17
+ <Col span={item.span ?? 24}>
18
+ <Collapse ghost accordion defaultActiveKey={[0]}>
19
+ {item.childItems?.map((child, ind) => (
20
+ <Collapse.Panel key={child.name || ind} header={<span style={{ fontWeight: 'bold' }}>{child.title}</span>}>
21
+ <Row gutter={[24, 0]}>
22
+ {renderCore(child.childItems || [child])}
23
+ </Row>
24
+ </Collapse.Panel>
25
+ ))}
26
+ </Collapse>
27
+ </Col>
28
+ ),
29
+ default: ({ children }) => <>{children}</>
30
+ }
31
+
32
+ // 定义“零部件增强协议”处理器,以后加任何新功能,只需要在这个对象里加一个 Key,不需要动主逻辑!
33
+ const ACTION_PROCESSORS = {
34
+ // 处理尾操作按钮
35
+ addonAfter: (item, { tableConfig, setModalTable, setSelectedTableRows }) => ({
36
+ props: {
37
+ addonAfter: (
38
+ <Button onClick={() => {
39
+ setSelectedTableRows([])
40
+ setModalTable({ visible: true, title: `选择${item.label}`, ...tableConfig[item.name] })
41
+ }}>
42
+ {item.addonAfter}
43
+ </Button>
44
+ )
45
+ }
46
+ }),
47
+ // 以后想加个“前缀图标”?直接加在这里:
48
+ // prefix: (item) => ({ props: { prefix: <Icon type={item.prefix} /> } }),
49
+ }
50
+
51
+ const FormRenderer = ({ form, formItems, tableConfig, setModalTable, setSelectedTableRows }) => {
52
+
53
+ // 定义核心渲染逻辑,供递归使用
54
+ const renderCore = items => (
55
+ <FormRenderer
56
+ form={form}
57
+ formItems={items}
58
+ tableConfig={tableConfig}
59
+ setModalTable={setModalTable}
60
+ setSelectedTableRows={setSelectedTableRows}
61
+ />
62
+ )
63
+
64
+ // 定义单项动作注入逻辑
65
+ const getRenderItemProps = item => {
66
+ if (!item.renderAction) return {}
67
+ const props = {}
68
+ Object.keys(ACTION_PROCESSORS).forEach(key => {
69
+ if (item[key]) {
70
+ Object.assign(props, ACTION_PROCESSORS[key](item, { tableConfig, setModalTable, setSelectedTableRows }))
71
+ }
72
+ })
73
+ return props
74
+ }
75
+
76
+ return formItems.map((item, index) => {
77
+ // 情况 A:发现容器型零件 (含有 layoutType)
78
+ if (item.layoutType && LAYOUT_PROCESSORS[item.layoutType]) {
79
+ const Layout = LAYOUT_PROCESSORS[item.layoutType] ?? LAYOUT_PROCESSORS.default
80
+ return (
81
+ <Layout
82
+ item={item}
83
+ key={item.name || index}
84
+ renderCore={renderCore} // 注入渲染能力,让 Layout 自己去 Map
85
+ />
86
+ )
87
+ }
88
+
89
+ // 情况 B:标准作战零件
90
+ return (
91
+ <Col span={item.span ?? 24} key={item.name || index}>
92
+ <MyBaseForm item={{ ...item, ...getRenderItemProps(item) }} form={form} />
93
+ </Col>
94
+ )
95
+ })
96
+ }
5
97
 
6
98
  /**
7
99
  * @component MyModalForm
@@ -9,29 +101,42 @@ import { Row, Col, Form, Modal, } from 'antd'
9
101
  * 集成了“语义回显自愈”、“自动时间戳转换”及“原子级提交锁定”三大核心协议。
10
102
  *
11
103
  * @param {Object} props - 构筑参数
12
- * @param {string|number} [props.width] - 舱体物理宽度
13
104
  * @param {string} [props.title] - 舱体视觉标题
14
- * @param {Function} props.submit - 数据发射协议:提交表单后的核心回调函数
15
- * @param {Object} [props.record] - 初始物资包:用于编辑模式的数据回显
16
- * @param {boolean} props.visible - 激活信号:控制弹窗的物理显示状态
17
- * @param {Function} props.setModal - 指令中心:用于更新弹窗状态(开启/关闭)
18
- * @param {Array} props.formItems - 零部件清单:定义表单内部的输入单元
19
105
  * @param {Object} [props.labelCol] - 标签布局校准
20
106
  * @param {Object} [props.wrapperCol] - 控件布局校准
107
+ * @param {string|number} [props.width] - 舱体物理宽度
108
+ * @param {boolean} props.visible - 激活信号:控制弹窗的物理显示状态
109
+ * @param {Array} props.formItems - 零部件清单:定义表单内部的输入单元
110
+ * @param {Object} [props.record] - 初始物资包:用于编辑模式的数据回显
111
+ * @param {Function} props.submit - 数据发射协议:提交表单后的核心回调函数
112
+ * @param {Function} props.setModal - 指令中心:用于更新弹窗状态(开启/关闭)
21
113
  * @param {Function} [props.onValuesChange] - 联动传感:捕获表单内部的信号波动
22
114
  *
23
115
  * @example
24
116
  * <MyModalForm
25
117
  * title="构筑新模块"
26
118
  * visible={visible}
27
- * formItems={[{ label: '截止日期', name: 'deadline', type: 'date' }]}
28
119
  * submit={async (vals) => await save(vals)}
120
+ * formItems={[{ label: '截止日期', name: 'deadline', type: 'date' }]}
29
121
  * />
30
122
  */
31
- export const MyModalForm = ({ width, title, submit, record, visible, setModal, labelCol, formItems, wrapperCol, onValuesChange }) => {
123
+ export const MyModalForm = ({ width, title, submit, record, visible, setModal, labelCol, formItems, wrapperCol, tableConfig, onValuesChange, handleModalTableOk }) => {
124
+
125
+ const rowKey = tableConfig?.rowKey || 'id'
32
126
 
33
127
  const [form] = Form.useForm()
34
128
  const [pending, setPending] = useState(false)
129
+ const [modalTable, setModalTable] = useState({})
130
+ const [selectedTableRows, setSelectedTableRows] = useState([])
131
+
132
+ const flattenFormItems = items => {
133
+ return items.flatMap(item => {
134
+ if (item.layoutType && item.childItems) {
135
+ return flattenFormItems(item.childItems)
136
+ }
137
+ return item
138
+ })
139
+ }
35
140
 
36
141
  /**
37
142
  * @description [数据回显协议] 当构筑舱开启时,自动对初始物资进行“语义格式化”。
@@ -41,11 +146,11 @@ export const MyModalForm = ({ width, title, submit, record, visible, setModal, l
41
146
  if (visible) {
42
147
  form.resetFields()
43
148
  if (record && Object.keys(record).length > 0) {
44
- const itemMap = new Map(formItems.map(i => [i.name, i]))
149
+ const itemMap = new Map(flattenFormItems(formItems).map(i => [i.name, i]))
45
150
  const initialData = {}
46
151
  Object.entries(record).forEach(([key, value]) => {
47
152
  const config = itemMap.get(key)
48
- // 💡 语义识别:若零部件类型为日期且数值存在,执行物理转化
153
+ // 语义识别:若零部件类型为日期且数值存在,执行物理转化
49
154
  if (config?.type?.includes('date') && value) {
50
155
  if (Array.isArray(value)) {
51
156
  // 处理范围日期
@@ -91,13 +196,16 @@ export const MyModalForm = ({ width, title, submit, record, visible, setModal, l
91
196
  if (submit) {
92
197
  setPending(true)
93
198
  await submit({ ...record, ...formattedValues })
94
- setPending(false)
95
199
  }
96
200
  } catch (error) {
97
201
  console.log('表单校验失败:', error)
202
+ } finally {
203
+ setPending(false)
98
204
  }
99
205
  }
100
206
 
207
+ const modalTableOk = () => handleModalTableOk({ form, selectedTableRows, setModalTable })
208
+
101
209
  /**
102
210
  * @function handleCancel
103
211
  * @description 执行“撤退协议”:关闭构筑舱并清除当前逻辑残留。
@@ -107,15 +215,17 @@ export const MyModalForm = ({ width, title, submit, record, visible, setModal, l
107
215
  form.resetFields()
108
216
  }
109
217
 
218
+ const tableRowSelection = useMemo(() => ({
219
+ selectedRowKeys: selectedTableRows.map(row => row[rowKey]),
220
+ onChange: (selectedRowKeys, selectedRows) => setSelectedTableRows(selectedRows),
221
+ }), [rowKey, modalTable, selectedTableRows])
222
+
110
223
  return (
111
224
  <Modal centered title={title} width={width} open={visible} onOk={handleOk} destroyOnClose onCancel={handleCancel} confirmLoading={pending}>
225
+ {modalTable.visible && <MyModalTable rowKey={rowKey} {...modalTable} rowSelection={tableRowSelection} onOk={modalTableOk} setModal={setModalTable} />}
112
226
  <Form form={form} preserve={false} labelCol={labelCol} wrapperCol={wrapperCol} onValuesChange={(changed, all) => onValuesChange?.({ changed, all, form, record })}>
113
227
  <Row gutter={[24, 0]}>
114
- {formItems.map((item, index) =>
115
- <Col span={item.span ?? 24} key={item.name || index}>
116
- <MyBaseForm item={item} form={form} />
117
- </Col>
118
- )}
228
+ <FormRenderer form={form} formItems={formItems} tableConfig={tableConfig} setModalTable={setModalTable} setSelectedTableRows={setSelectedTableRows} />
119
229
  </Row>
120
230
  </Form>
121
231
  </Modal>
@@ -11,22 +11,22 @@ import { useTableQuery } from '../hooks/useTableQuery'
11
11
  * 具备独立的数据获取链路、可选的搜索过滤系统以及与主构筑舱(setModalForm)的跨维协同能力。
12
12
  *
13
13
  * @param {Object} props - 支援参数
14
- * @param {Function} props.api - 弹窗内独立的数据源指令
15
- * @param {Function} [props.onOk] - 战果物理确认:按下确认按钮后的异步回调协议
16
14
  * @param {string} [props.title] - 舱体视觉标题
15
+ * @param {Function} props.api - 弹窗内独立的数据源指令
17
16
  * @param {string|number} [props.width] - 舱体物理宽度
18
- * @param {React.ReactNode} [props.footer] - 底座指令区:支持完全自定义操作按钮
17
+ * @param {Object} [props.rowSelection] - 战术勾选:用于多选物资
19
18
  * @param {boolean} props.visible - 激活信号:控制支援单元的显示状态
20
- * @param {Function} props.operate - 动态火力配置:生成操作列的函数,接收 { refresh, setModalForm } 句柄
21
19
  * @param {Function} props.setModal - 单元注销中心:用于关闭当前弹窗
22
- * @param {Array} [props.formItems] - 局部搜索零部件:用于在弹窗内执行精准情报过滤
23
- * @param {Function} [props.setModalForm] - [重要] 跨维调用:由主页面注入的表单控制句柄,实现“弹窗开弹窗”的非耦合交互
24
- * @param {Object} [props.rowSelection] - 战术勾选:用于多选物资
25
- * @param {Function} props.formatResponse - 数据清洗协议:对 API 吐出的原始物资进行格式化
26
- * @param {Array} [props.functionButtons] - 功能挂件组:位于表格上方的操作按钮,可直接操控表格状态
27
20
  * @param {Array} props.columns - 零部件初始清单 (别名: modalColumns)
21
+ * @param {Function} [props.onOk] - 战果物理确认:按下确认按钮后的异步回调协议
28
22
  * @param {Object} [props.initialParams={}] - 初始战备物资:定义的初始搜索参数
23
+ * @param {React.ReactNode} [props.footer] - 底座指令区:支持完全自定义操作按钮
24
+ * @param {Array} [props.formItems] - 局部搜索零部件:用于在弹窗内执行精准情报过滤
25
+ * @param {Function} props.formatResponse - 数据清洗协议:对 API 吐出的原始物资进行格式化
29
26
  * @param {boolean|Object} [props.modalPagination=true] - 局部后勤协议:弹窗内是否开启分页
27
+ * @param {Array} [props.functionButtons] - 功能挂件组:位于表格上方的操作按钮,可直接操控表格状态
28
+ * @param {Function} props.operate - 动态火力配置:生成操作列的函数,接收 { refresh, setModalForm } 句柄
29
+ * @param {Function} [props.setModalForm] - [重要] 跨维调用:由主页面注入的表单控制句柄,实现“弹窗开弹窗”的非耦合交互
30
30
  *
31
31
  * @example
32
32
  * <MyModalTable
@@ -36,7 +36,7 @@ import { useTableQuery } from '../hooks/useTableQuery'
36
36
  * operate={({ refresh, setModalForm }) => ({ label: '详情', onClick: (rec) => setModalForm(...) })}
37
37
  * />
38
38
  */
39
- export const MyModalTable = ({ api, onOk, title, width, footer, visible, operate, setModal, formItems, setModalForm, rowSelection, formatResponse, functionButtons, columns: modalColumns, initialParams = {}, modalPagination = true }) => {
39
+ export const MyModalTable = ({ api, onOk, title, width, footer, visible, operate, setModal, formItems, setModalForm, rowSelection, formatResponse, functionButtons, columns: modalColumns, rowKey = 'id', initialParams = {}, modalPagination = true }) => {
40
40
 
41
41
  const [pending, setPending] = useState(false)
42
42
 
@@ -90,6 +90,7 @@ export const MyModalTable = ({ api, onOk, title, width, footer, visible, operate
90
90
  {functionButtons?.length > 0 && <Space>{functionButtons.map(item => <Button key={item.name} type={item.type} onClick={() => item.onClick({ refresh, setLoading, setSearch, setDataSource })}>{item.name}</Button>)}</Space>}
91
91
  <MyTable
92
92
  total={total}
93
+ rowKey={rowKey}
93
94
  search={search}
94
95
  loading={loading}
95
96
  scroll={{ y: 400 }}
@@ -10,25 +10,25 @@ import { Row, Col, Form, Button, Space } from 'antd'
10
10
  *
11
11
  * @param {Object} props - 指挥官指令包
12
12
  * @param {Object} props.form - Antd Form 实例,表单的主控舵盘
13
- * @param {Object} props.search - 当前的全局搜索状态(包含 pageNo, pageSize 及各过滤项)
14
- * @param {boolean} props.loading - 战场负载状态:请求中时锁定按钮,防止由于重复指令导致的逻辑冲突
15
- * @param {Function} props.setSearch - 状态分发器:用于更新全局搜索参数并触发重新构筑
13
+ * @param {Function} [props.customReset] - 逻辑劫持:自定义重置协议
14
+ * @param {Function} [props.customFinish] - 逻辑劫持:自定义提交协议
16
15
  * @param {Array} props.formItems - 零部件清单:定义所有的搜索输入单元
17
16
  * @param {number} [props.showLimit=7] - 初始可见能级:默认展示的零部件数量
17
+ * @param {number} [props.defaultPageSize=10] - 默认吞吐量:重置时的初始每页条数
18
+ * @param {Function} [props.onValuesChange] - 联动传感:当表单值变动时的即时反馈
18
19
  * @param {Object} props.initialValues - 初始信号:从 URL 或缓存中解析出的初始参数
19
- * @param {Function} [props.customReset] - 逻辑劫持:自定义重置协议
20
- * @param {Function} [props.customFinish] - 逻辑劫持:自定义提交协议
20
+ * @param {Function} props.setSearch - 状态分发器:用于更新全局搜索参数并触发重新构筑
21
+ * @param {Object} props.search - 当前的全局搜索状态(包含 pageNo, pageSize 及各过滤项)
21
22
  * @param {React.ReactNode} [props.extraOperate] - 额外挂件:在按钮区域注入自定义战术单元
22
- * @param {Function} [props.onValuesChange] - 联动传感:当表单值变动时的即时反馈
23
+ * @param {boolean} props.loading - 战场负载状态:请求中时锁定按钮,防止由于重复指令导致的逻辑冲突
23
24
  * @param {boolean} [props.syncUrlParams=true] - 物理同步开关:是否将搜索状态实时镜像至 URL 链接中
24
- * @param {number} [props.defaultPageSize=10] - 默认吞吐量:重置时的初始每页条数
25
25
  *
26
26
  * @example
27
27
  * <MySearchForm
28
28
  * form={form}
29
29
  * search={search}
30
- * formItems={[{ label: '状态', name: 'status', type: 'select', options: [...] }]}
31
30
  * setSearch={setSearch}
31
+ * formItems={[{ label: '状态', name: 'status', type: 'select', options: [...] }]}
32
32
  * />
33
33
  */
34
34
  export const MySearchForm = ({ form, search, loading, labelCol, setSearch, formItems, showLimit = 7, initialValues, customReset, extraOperate, customFinish, onValuesChange, syncUrlParams = true, defaultPageSize = 10 }) => {
@@ -102,7 +102,7 @@ export const MySearchForm = ({ form, search, loading, labelCol, setSearch, formI
102
102
  newValues[item.name] = item.type?.includes('date') ? dayjs(Number(value)) : value
103
103
  }
104
104
  // 处理双字段(日期范围)回显:执行物理重组
105
- if (item.name.includes(',') && item.type?.includes('date')) {
105
+ if (item.name?.includes(',') && item.type?.includes('date')) {
106
106
  const [startKey, endKey] = item.name.split(',')
107
107
  if (initialValues[startKey] && initialValues[endKey]) {
108
108
  newValues[item.name] = [dayjs(Number(initialValues[startKey])), dayjs(Number(initialValues[endKey]))]
@@ -8,31 +8,50 @@ import { useRef, useMemo, useEffect, useCallback } from 'react'
8
8
  * 它是地堡系统的“火力中心”,集成了行内编辑、自动滚动定位、动态分页协议及 Optimistic UI (乐观更新) 等工业级特性。
9
9
  *
10
10
  * @param {Object} props - 平台配置参数
11
- * @param {string} [props.size='middle'] - 视觉能级:表格的物理尺寸 (small/middle/large)
12
- * @param {Object} [props.query] - 侦察参数:包含 rowIndex 用于执行物理追踪定位
13
11
  * @param {number} props.total - 物资总量:用于构筑分页器的刻度
12
+ * @param {Object} [props.rowSelection] - 战术勾选:配置行选择逻辑
13
+ * @param {string} [props.rowKey='id'] - 唯一标识:每一行物资的数字指纹
14
+ * @param {boolean} [props.loading=false] - 战场负载状态:显示加载动画
15
+ * @param {Array} [props.dataSource=[]] - 物理物资包:表格展示的原始数据
14
16
  * @param {Object} props.search - 当前物流状态:包含 pageNo 和 pageSize
17
+ * @param {Object} [props.query] - 侦察参数:包含 rowIndex 用于执行物理追踪定位
15
18
  * @param {boolean} [props.autoScroll] - 视觉引导开关:是否开启自动滚动至目标行逻辑
19
+ * @param {Function} [props.lineFormChange] - 行级信号监听:捕获行内表单的实时变动
16
20
  * @param {Function} props.onChange - 战位协同回调:分页、排序、筛选变动时的通信协议
17
21
  * @param {boolean|Object} [props.pagination] - 分页配置:支持布尔开关或物理对象覆盖
18
- * @param {string|Function} [props.rowClassName] - 行视觉涂装:支持静态字符串或基于逻辑的动态类名
19
22
  * @param {Function} [props.customSave] - 物理封存协议:行内编辑保存后的外部持久化回调
20
- * @param {Function} props.setDataSource - 状态设置器:直接操作地堡的原始数据流(支持函数式更新)
21
- * @param {Function} [props.lineFormChange] - 行级信号监听:捕获行内表单的实时变动
22
23
  * @param {Array} props.columns - 零部件清单:定义列的构筑协议,支持 editType 等扩展属性
23
- * @param {Object} [props.rowSelection] - 战术勾选:配置行选择逻辑
24
- * @param {string} [props.rowKey='id'] - 唯一标识:每一行物资的数字指纹
25
- * @param {boolean} [props.loading=false] - 战场负载状态:显示加载动画
26
- * @param {Array} [props.dataSource=[]] - 物理物资包:表格展示的原始数据
27
24
  * @param {Object} [props.scroll={x:'max-content'}] - 滚动配置:默认开启横向物理溢出防护
25
+ * @param {string} [props.size='middle'] - 视觉能级:表格的物理尺寸 (small/middle/large)
26
+ * @param {Function} props.setDataSource - 状态设置器:直接操作地堡的原始数据流(支持函数式更新)
27
+ * @param {string|Function} [props.rowClassName] - 行视觉涂装:支持静态字符串或基于逻辑的动态类名
28
+ *
29
+ * @param {Object} [props.renderAction] - [后期物理绑定协议] 运行时逻辑注入仓库。
30
+ * @description
31
+ * 这是地堡系统的“黑客骇入”接口。
32
+ * 由于 resource.js 必须保持纯净的静态 JSON 格式以确保主权安全性,
33
+ * 凡是涉及“查看图片”、“跳转链接”等需要运行时函数支持的列,
34
+ * 统一通过该协议在渲染阶段执行“逻辑对冲”。
35
+ *
36
+ * @logic
37
+ * 1. 物理寻址:通过 col.dataIndex 锁定目标零部件位点。
38
+ * 2. 逻辑脱壳:删除临时标记字段 [renderAction: true]。
39
+ * 3. 语义注入:将 index.js 中定义的真实 Action 物理焊接到 columns.render 属性上。
28
40
  *
29
41
  * @example
42
+ * // 1. 在 resource.js 中标记:
43
+ * { title: '图片', dataIndex: 'imgUrl', renderAction: true }
44
+ *
45
+ * // 2. 在 index.js 中提供弹药:
30
46
  * <MyTable
47
+ * total={100}
31
48
  * columns={columns}
32
49
  * dataSource={data}
33
- * total={100}
34
50
  * setDataSource={setData}
35
51
  * customSave={(row) => saveApi(row)}
52
+ * renderAction={{
53
+ * imgUrl: (text, record) => <a onClick={() => showImg(record)}>查看物资</a>
54
+ * }}
36
55
  * />
37
56
  */
38
57
  export const MyTable = ({ size, query, total, search, autoScroll, onChange, pagination, renderAction, rowClassName, customSave, setDataSource, lineFormChange, columns = [], rowSelection, rowKey = 'id', loading = false, dataSource = [], scroll = { x: 'max-content' }, ...restProps }) => {
@@ -82,7 +101,7 @@ export const MyTable = ({ size, query, total, search, autoScroll, onChange, pagi
82
101
  const mergedColumns = useMemo(() => {
83
102
  return columns.map(col => {
84
103
  if (!col.editType) {
85
- if (col.renderAction && renderAction[col.dataIndex]) {
104
+ if (col.renderAction && renderAction?.[col.dataIndex]) {
86
105
  return { ...col, render: renderAction[col.dataIndex] }
87
106
  }
88
107
  return col
@@ -9,11 +9,11 @@ import { Button, Tree, Radio, Input, Upload, Select, Cascader, Checkbox, DatePic
9
9
  * 集成了“物理路径自动重组”、“STS 令牌自动续期”以及“ Antd 属性无损透传”三大核心协议。
10
10
  *
11
11
  * @param {Object} props - 构筑参数
12
+ * @param {string} [props.path] - 默认存储扇区:定义文件在云端的物理根路径
13
+ * @param {string} [props.url] - 司令部通信地址:用于申请最新的物理传输令牌 (STS)
12
14
  * @param {Array} props.value - 传感器当前封存的文件列表 (符合 Antd fileList 规范)
13
15
  * @param {Function} props.onChange - 状态反馈协议:当物理文件状态变更时同步至地堡中枢
14
16
  * @param {Object} [props.oss] - 外部空投的初始凭证包。若缺失,组件将启动自主初始化流程。
15
- * @param {string} [props.url] - 司令部通信地址:用于申请最新的物理传输令牌 (STS)
16
- * @param {string} [props.path] - 默认存储扇区:定义文件在云端的物理根路径
17
17
  * @param {Object} [props.options] - 通信加密/配置参数:在申请令牌时透传给 request 的额外负载
18
18
  * @param {Object} [props.originUploadProps] - [重要] 无损透传:支持 Antd Upload 的所有原生属性(如 multiple, accept 等)
19
19
  *
@@ -81,7 +81,7 @@ const AliyunOSSUpload = ({ value, onChange, ...restProps }) => {
81
81
  */
82
82
  const beforeUpload = async file => {
83
83
  let currentOSS = OSSData
84
- const expire = Number(OSSData.expire) * 1000
84
+ const expire = Number(OSSData?.expire ?? 0) * 1000
85
85
  if (expire < Date.now()) {
86
86
  currentOSS = await init()
87
87
  }
@@ -119,12 +119,12 @@ const AliyunOSSUpload = ({ value, onChange, ...restProps }) => {
119
119
  *
120
120
  * @param {Object} params - 装配参数
121
121
  * @param {Object} params.item - 零部件配置对象
122
- * @param {string} params.item.type - 构筑类型(date/number/ossUpload/select/daterange 等)
123
- * @param {boolean} [params.item.readOnly] - 物理锁定开关
124
122
  * @param {string|number} [params.item.width] - 宽度校准
123
+ * @param {boolean} [params.item.readOnly] - 物理锁定开关
125
124
  * @param {string} [params.item.placeholder] - 视觉占位提示
126
- * @param {Array} [params.item.options] - 数据字典(用于 select/radio/tree 等)
127
125
  * @param {Object} [params.item.props] - 透传给底层组件的原始控制参数
126
+ * @param {Array} [params.item.options] - 数据字典(用于 select/radio/tree 等)
127
+ * @param {string} params.item.type - 构筑类型(date/number/ossUpload/select/daterange 等)
128
128
  *
129
129
  * @returns {React.ReactNode} 物理装配完成的 UI 单元
130
130
  */
@@ -6,21 +6,21 @@ import { useRef, useState, useEffect, useCallback } from 'react'
6
6
  * 负责全自动管理表格的生命周期,包括数据抓取、状态同步、动态列指纹识别及“竞态病毒”物理免疫。
7
7
  *
8
8
  * @param {Object} params - 引擎配置包
9
- * @param {Function} params.api - 任务指令:必须返回 Promise 的数据抓取函数
10
9
  * @param {Array} [params.cols] - 初始战备物资:前端预设的静态列配置
10
+ * @param {Function} params.api - 任务指令:必须返回 Promise 的数据抓取函数
11
11
  * @param {Object} [params.initialParams={}] - 初始导航坐标:包含 pageNo, pageSize 及默认过滤参数
12
12
  * @param {Function} params.formatResponse - 数据解码协议:将 API 原始信号转化为 { data, total, columns } 结构
13
13
  *
14
14
  * @returns {Object} 物理操作句柄包
15
15
  * @returns {number} .total - 仓库物资总量
16
- * @returns {Array} .columns - 当前生效的动态列配置(已通过指纹协议校验)
17
16
  * @returns {boolean} .loading - 引擎负载状态
18
- * @returns {Array} .dataSource - 已解压的物理物资列表
19
- * @returns {Object} .search - 当前导航参数(pageNo, pageSize 等)
20
17
  * @returns {Function} .setSearch - 坐标修改器
18
+ * @returns {Array} .dataSource - 已解压的物理物资列表
21
19
  * @returns {Function} .setLoading - 负载状态手动干预句柄
22
- * @returns {Function} .setDataSource - 物资流手动修改句柄(用于行内编辑等乐观更新)
20
+ * @returns {Object} .search - 当前导航参数(pageNo, pageSize 等)
23
21
  * @returns {Function} .refresh - 强制重启协议:立即执行一次数据抓取
22
+ * @returns {Array} .columns - 当前生效的动态列配置(已通过指纹协议校验)
23
+ * @returns {Function} .setDataSource - 物资流手动修改句柄(用于行内编辑等乐观更新)
24
24
  *
25
25
  * @example
26
26
  * const { dataSource, loading, refresh } = useTableQuery({
@@ -51,8 +51,8 @@ export const initOSS = async (url, options) => {
51
51
  /**
52
52
  * @function formatQuery
53
53
  * @description [数据脱水] 搜索参数校准协议:根据零部件类型(如日期)自动执行类型转换(String -> Number)。
54
- * @param {Object} params - 原始表单/URL 传感器数据
55
54
  * @param {Array} formItems - 对应的零部件配置清单
55
+ * @param {Object} params - 原始表单/URL 传感器数据
56
56
  * @returns {Object} 经过物理清洗、可直接用于 API 请求的参数包
57
57
  */
58
58
  export const formatQuery = (params, formItems) => {
@@ -96,9 +96,9 @@ export const timeRender = ({ time, date, minute }) => {
96
96
  * @description [物资外运] 数据表格导出协议:支持复杂的渲染逻辑回溯,将页面数据封存为 .xlsx 格式。
97
97
  * @param {string} url - 数据源地址
98
98
  * @param {Object} options - 请求参数
99
- * @param {Array} columns - 表格列配置,支持 exportRender 优先级
100
99
  * @param {string} fileName - 导出的文件名
101
100
  * @param {Function} [formatter] - 数据预处理回调
101
+ * @param {Array} columns - 表格列配置,支持 exportRender 优先级
102
102
  */
103
103
  export const exportDataToExcel = async (url, options, columns, fileName, formatter) => {
104
104
  /* const response = await request(url, options)
@@ -216,8 +216,8 @@ export const moneyRender = (value, { decimals = 2, currency = 'CNY', language =
216
216
  * @description [视觉渲染] 单位自动进阶协议:实现 B/KB/MB... 等数据的物理量级自动折算。
217
217
  * @param {number} value - 原始字节数值
218
218
  * @param {Object} [options] - 配置参数
219
- * @param {number} [options.k=1024] - 进位系数
220
219
  * @param {Array} [options.units] - 单位阶梯
220
+ * @param {number} [options.k=1024] - 进位系数
221
221
  * @param {number} [options.decimals=2] - 保留小数位
222
222
  * @returns {string} 带单位的物理量级文本
223
223
  */