@antsoo-lib/core 3.0.0 → 3.0.1
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/CHANGELOG.md +6 -0
- package/dist/core.css +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +6 -5
- package/dist/types/BaseSearch/index.d.ts +1 -1
- package/dist/types/BaseTable/index.d.ts +5 -475
- package/dist/types/Form/CoreForm.d.ts +82 -0
- package/dist/types/SSelectPage/index.d.ts +102 -0
- package/package.json +3 -3
- package/src/BaseSearch/index.vue +371 -371
- package/src/BaseTable/index.vue +910 -910
- package/src/Form/CoreForm.vue +782 -782
- package/src/Form/types.ts +86 -86
- package/src/SSelectPage/index.vue +607 -607
- package/src/index.ts +17 -17
- package/src/render/AreaCascader.tsx +64 -64
- package/src/render/AutoComplete.tsx +101 -101
- package/src/render/Button.tsx +62 -62
- package/src/render/Cascader.tsx +45 -45
- package/src/render/Checkbox.tsx +65 -65
- package/src/render/CheckboxGroup.tsx +57 -57
- package/src/render/Custom.tsx +19 -19
- package/src/render/DatePicker.tsx +83 -83
- package/src/render/Input.tsx +140 -140
- package/src/render/InputGroup.tsx +115 -115
- package/src/render/InputNumber.tsx +205 -205
- package/src/render/InputPassword.tsx +81 -81
- package/src/render/InputRange.tsx +154 -154
- package/src/render/RadioGroup.tsx +63 -63
- package/src/render/Select.tsx +96 -96
- package/src/render/SselectPage.tsx +107 -107
- package/src/render/Switch.tsx +60 -60
- package/src/render/Tree.tsx +136 -136
- package/src/render/TreeSelect.tsx +81 -81
- package/src/render/Upload.tsx +91 -91
- package/src/render/helper.tsx +221 -221
- package/src/render/index.ts +108 -108
- package/src/render/registry.ts +20 -20
- package/src/render/state.ts +37 -37
- package/src/render/types.ts +567 -567
- package/src/utils/attrMapping.ts +106 -106
- package/vite.config.ts +61 -61
- package/.turbo/turbo-build.log +0 -40
|
@@ -1,107 +1,107 @@
|
|
|
1
|
-
import type { VoidFunction } from '@antsoo-lib/shared'
|
|
2
|
-
import { isFunction } from '@antsoo-lib/utils'
|
|
3
|
-
|
|
4
|
-
import { computed, markRaw, nextTick } from 'vue'
|
|
5
|
-
import type { ComponentPublicInstance, VNode } from 'vue'
|
|
6
|
-
|
|
7
|
-
import { getRegisteredComponent } from './registry'
|
|
8
|
-
import type { ToolbarState } from './state'
|
|
9
|
-
import type { SselectPageProps, SselectPageToolbarItem, ToolbarItem } from './types'
|
|
10
|
-
|
|
11
|
-
export function renderSselectPage(item: ToolbarItem, toolbarState: ToolbarState): VNode {
|
|
12
|
-
const sselectPageItem = item as SselectPageToolbarItem
|
|
13
|
-
const { key, events = {} } = sselectPageItem
|
|
14
|
-
const { props = {} as SselectPageProps, disabled = false } = sselectPageItem
|
|
15
|
-
|
|
16
|
-
// 处理动态禁用逻辑
|
|
17
|
-
const isDisabled = isFunction(disabled)
|
|
18
|
-
? disabled(toolbarState.getAllValues(), toolbarState)
|
|
19
|
-
: disabled
|
|
20
|
-
|
|
21
|
-
// 处理事件,注入工具栏状态
|
|
22
|
-
const processedEvents: Record<string, VoidFunction> = {}
|
|
23
|
-
Object.keys(events).forEach((eventName) => {
|
|
24
|
-
processedEvents[eventName] = (...args: any[]) => {
|
|
25
|
-
// 对于 SselectPage,先更新状态,再调用外部事件处理函数
|
|
26
|
-
if (eventName === 'onUpdate:value' || eventName === 'onChange') {
|
|
27
|
-
const value = args[0] // SselectPage 的第一个参数是选中的值
|
|
28
|
-
// 立即更新工具栏状态,确保外部事件处理函数能获取到最新值
|
|
29
|
-
toolbarState.setValue(key, value)
|
|
30
|
-
|
|
31
|
-
// 对于 onChange 事件,使用 nextTick 确保在下一个 tick 中执行外部处理函数
|
|
32
|
-
if (eventName === 'onChange') {
|
|
33
|
-
nextTick(() => {
|
|
34
|
-
;(events[eventName] as VoidFunction)?.(
|
|
35
|
-
...args,
|
|
36
|
-
toolbarState.getAllValues(),
|
|
37
|
-
toolbarState,
|
|
38
|
-
)
|
|
39
|
-
})
|
|
40
|
-
return // 提前返回,避免重复执行
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// 调用原始事件处理函数,传入完整的上下文
|
|
45
|
-
events[eventName]?.(...args, toolbarState.getAllValues(), toolbarState)
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
// 如果没有设置 onChange 事件,添加默认的状态更新
|
|
50
|
-
if (!processedEvents['onUpdate:value'] && !processedEvents.onChange) {
|
|
51
|
-
processedEvents['onUpdate:value'] = (value: any) => {
|
|
52
|
-
toolbarState.setValue(key, value)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 处理 extraParams 的响应式更新
|
|
57
|
-
// 如果 props.extraParams 是函数,则动态计算
|
|
58
|
-
const computedProps = computed(() => {
|
|
59
|
-
const allValues = toolbarState.getAllValues()
|
|
60
|
-
const dynamicProps: any = { ...props, disabled: isDisabled }
|
|
61
|
-
|
|
62
|
-
// 动态计算 extraParams
|
|
63
|
-
if (isFunction(props.extraParams)) {
|
|
64
|
-
dynamicProps.extraParams = props.extraParams(allValues, toolbarState)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return dynamicProps
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
// 如果需要自动聚焦,添加 ref 处理
|
|
71
|
-
if (props.autoFocus) {
|
|
72
|
-
processedEvents.ref = (el: ComponentPublicInstance | null) => {
|
|
73
|
-
const component = el
|
|
74
|
-
if (component) {
|
|
75
|
-
// 使用 nextTick 确保 DOM 已经渲染完成
|
|
76
|
-
nextTick(() => {
|
|
77
|
-
try {
|
|
78
|
-
;(component as any)?.$refs?.selectRef?.focus?.()
|
|
79
|
-
} catch {
|
|
80
|
-
// 忽略焦点设置失败的错误
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// 计算安全的默认值
|
|
88
|
-
const rawVal = toolbarState.getValue(key)
|
|
89
|
-
const propVal = props.value
|
|
90
|
-
const safeValue =
|
|
91
|
-
rawVal !== undefined && rawVal !== null
|
|
92
|
-
? rawVal
|
|
93
|
-
: propVal !== undefined && propVal !== null
|
|
94
|
-
? propVal
|
|
95
|
-
: undefined
|
|
96
|
-
|
|
97
|
-
const SselectPageComponent = getRegisteredComponent('SselectPage')
|
|
98
|
-
if (!SselectPageComponent) {
|
|
99
|
-
console.warn('BaseTable: SselectPage component is not registered.')
|
|
100
|
-
return <span style={{ color: 'red' }}>SselectPage component missing</span>
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const Comp = markRaw(SselectPageComponent) as any
|
|
104
|
-
return (
|
|
105
|
-
<Comp key={key} value={safeValue} allowClear {...computedProps.value} {...processedEvents} />
|
|
106
|
-
)
|
|
107
|
-
}
|
|
1
|
+
import type { VoidFunction } from '@antsoo-lib/shared'
|
|
2
|
+
import { isFunction } from '@antsoo-lib/utils'
|
|
3
|
+
|
|
4
|
+
import { computed, markRaw, nextTick } from 'vue'
|
|
5
|
+
import type { ComponentPublicInstance, VNode } from 'vue'
|
|
6
|
+
|
|
7
|
+
import { getRegisteredComponent } from './registry'
|
|
8
|
+
import type { ToolbarState } from './state'
|
|
9
|
+
import type { SselectPageProps, SselectPageToolbarItem, ToolbarItem } from './types'
|
|
10
|
+
|
|
11
|
+
export function renderSselectPage(item: ToolbarItem, toolbarState: ToolbarState): VNode {
|
|
12
|
+
const sselectPageItem = item as SselectPageToolbarItem
|
|
13
|
+
const { key, events = {} } = sselectPageItem
|
|
14
|
+
const { props = {} as SselectPageProps, disabled = false } = sselectPageItem
|
|
15
|
+
|
|
16
|
+
// 处理动态禁用逻辑
|
|
17
|
+
const isDisabled = isFunction(disabled)
|
|
18
|
+
? disabled(toolbarState.getAllValues(), toolbarState)
|
|
19
|
+
: disabled
|
|
20
|
+
|
|
21
|
+
// 处理事件,注入工具栏状态
|
|
22
|
+
const processedEvents: Record<string, VoidFunction> = {}
|
|
23
|
+
Object.keys(events).forEach((eventName) => {
|
|
24
|
+
processedEvents[eventName] = (...args: any[]) => {
|
|
25
|
+
// 对于 SselectPage,先更新状态,再调用外部事件处理函数
|
|
26
|
+
if (eventName === 'onUpdate:value' || eventName === 'onChange') {
|
|
27
|
+
const value = args[0] // SselectPage 的第一个参数是选中的值
|
|
28
|
+
// 立即更新工具栏状态,确保外部事件处理函数能获取到最新值
|
|
29
|
+
toolbarState.setValue(key, value)
|
|
30
|
+
|
|
31
|
+
// 对于 onChange 事件,使用 nextTick 确保在下一个 tick 中执行外部处理函数
|
|
32
|
+
if (eventName === 'onChange') {
|
|
33
|
+
nextTick(() => {
|
|
34
|
+
;(events[eventName] as VoidFunction)?.(
|
|
35
|
+
...args,
|
|
36
|
+
toolbarState.getAllValues(),
|
|
37
|
+
toolbarState,
|
|
38
|
+
)
|
|
39
|
+
})
|
|
40
|
+
return // 提前返回,避免重复执行
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 调用原始事件处理函数,传入完整的上下文
|
|
45
|
+
events[eventName]?.(...args, toolbarState.getAllValues(), toolbarState)
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
// 如果没有设置 onChange 事件,添加默认的状态更新
|
|
50
|
+
if (!processedEvents['onUpdate:value'] && !processedEvents.onChange) {
|
|
51
|
+
processedEvents['onUpdate:value'] = (value: any) => {
|
|
52
|
+
toolbarState.setValue(key, value)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 处理 extraParams 的响应式更新
|
|
57
|
+
// 如果 props.extraParams 是函数,则动态计算
|
|
58
|
+
const computedProps = computed(() => {
|
|
59
|
+
const allValues = toolbarState.getAllValues()
|
|
60
|
+
const dynamicProps: any = { ...props, disabled: isDisabled }
|
|
61
|
+
|
|
62
|
+
// 动态计算 extraParams
|
|
63
|
+
if (isFunction(props.extraParams)) {
|
|
64
|
+
dynamicProps.extraParams = props.extraParams(allValues, toolbarState)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return dynamicProps
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
// 如果需要自动聚焦,添加 ref 处理
|
|
71
|
+
if (props.autoFocus) {
|
|
72
|
+
processedEvents.ref = (el: ComponentPublicInstance | null) => {
|
|
73
|
+
const component = el
|
|
74
|
+
if (component) {
|
|
75
|
+
// 使用 nextTick 确保 DOM 已经渲染完成
|
|
76
|
+
nextTick(() => {
|
|
77
|
+
try {
|
|
78
|
+
;(component as any)?.$refs?.selectRef?.focus?.()
|
|
79
|
+
} catch {
|
|
80
|
+
// 忽略焦点设置失败的错误
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 计算安全的默认值
|
|
88
|
+
const rawVal = toolbarState.getValue(key)
|
|
89
|
+
const propVal = props.value
|
|
90
|
+
const safeValue =
|
|
91
|
+
rawVal !== undefined && rawVal !== null
|
|
92
|
+
? rawVal
|
|
93
|
+
: propVal !== undefined && propVal !== null
|
|
94
|
+
? propVal
|
|
95
|
+
: undefined
|
|
96
|
+
|
|
97
|
+
const SselectPageComponent = getRegisteredComponent('SselectPage')
|
|
98
|
+
if (!SselectPageComponent) {
|
|
99
|
+
console.warn('BaseTable: SselectPage component is not registered.')
|
|
100
|
+
return <span style={{ color: 'red' }}>SselectPage component missing</span>
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const Comp = markRaw(SselectPageComponent) as any
|
|
104
|
+
return (
|
|
105
|
+
<Comp key={key} value={safeValue} allowClear {...computedProps.value} {...processedEvents} />
|
|
106
|
+
)
|
|
107
|
+
}
|
package/src/render/Switch.tsx
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
import { Switch } from '@antsoo-lib/components'
|
|
2
|
-
import type { SwitchProps } from '@antsoo-lib/components'
|
|
3
|
-
import type { VoidFunction } from '@antsoo-lib/shared'
|
|
4
|
-
import { isFunction } from '@antsoo-lib/utils'
|
|
5
|
-
|
|
6
|
-
import { markRaw } from 'vue'
|
|
7
|
-
import type { VNode } from 'vue'
|
|
8
|
-
|
|
9
|
-
import type { ToolbarState } from './state'
|
|
10
|
-
import type { SwitchToolbarItem, ToolbarItem } from './types'
|
|
11
|
-
|
|
12
|
-
// 开关渲染函数
|
|
13
|
-
export function renderSwitch(item: ToolbarItem, toolbarState: ToolbarState): VNode {
|
|
14
|
-
const { key, events = {} } = item
|
|
15
|
-
const switchItem = item as SwitchToolbarItem
|
|
16
|
-
const { props = {}, disabled = false } = switchItem
|
|
17
|
-
// SwitchProps doesn't have 'value', it uses 'checked'.
|
|
18
|
-
// Remove 'value' to avoid warning if passed by mistake
|
|
19
|
-
const { value: _ignored, ...otherProps } = props as any
|
|
20
|
-
|
|
21
|
-
const isDisabled = isFunction(disabled)
|
|
22
|
-
? disabled(toolbarState.getAllValues(), toolbarState)
|
|
23
|
-
: disabled
|
|
24
|
-
const finalProps: Partial<SwitchProps> & { disabled?: boolean; checked?: boolean } = {
|
|
25
|
-
...otherProps,
|
|
26
|
-
disabled: isDisabled,
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// 处理事件,注入工具栏状态
|
|
30
|
-
const processedEvents: Record<string, VoidFunction> = {}
|
|
31
|
-
Object.keys(events).forEach((eventName) => {
|
|
32
|
-
processedEvents[eventName] = (...args: any[]) => {
|
|
33
|
-
// 对于开关,自动更新状态
|
|
34
|
-
if (eventName === 'onUpdate:checked' || eventName === 'onChange') {
|
|
35
|
-
const checked = args[0]?.target?.checked ?? args[0]
|
|
36
|
-
toolbarState.setValue(key, checked)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// 调用原始事件处理函数
|
|
40
|
-
events[eventName]?.(...args, toolbarState.getAllValues(), toolbarState)
|
|
41
|
-
}
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
// 如果没有设置onChange事件,添加默认的状态更新
|
|
45
|
-
if (!processedEvents['onUpdate:checked'] && !processedEvents.onChange) {
|
|
46
|
-
processedEvents['onUpdate:checked'] = (checked: boolean) => {
|
|
47
|
-
toolbarState.setValue(key, checked)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const Comp = markRaw(Switch)
|
|
52
|
-
return (
|
|
53
|
-
<Comp
|
|
54
|
-
key={key}
|
|
55
|
-
checked={toolbarState.getValue(key) ?? finalProps.checked ?? false}
|
|
56
|
-
{...finalProps}
|
|
57
|
-
{...processedEvents}
|
|
58
|
-
/>
|
|
59
|
-
)
|
|
60
|
-
}
|
|
1
|
+
import { Switch } from '@antsoo-lib/components'
|
|
2
|
+
import type { SwitchProps } from '@antsoo-lib/components'
|
|
3
|
+
import type { VoidFunction } from '@antsoo-lib/shared'
|
|
4
|
+
import { isFunction } from '@antsoo-lib/utils'
|
|
5
|
+
|
|
6
|
+
import { markRaw } from 'vue'
|
|
7
|
+
import type { VNode } from 'vue'
|
|
8
|
+
|
|
9
|
+
import type { ToolbarState } from './state'
|
|
10
|
+
import type { SwitchToolbarItem, ToolbarItem } from './types'
|
|
11
|
+
|
|
12
|
+
// 开关渲染函数
|
|
13
|
+
export function renderSwitch(item: ToolbarItem, toolbarState: ToolbarState): VNode {
|
|
14
|
+
const { key, events = {} } = item
|
|
15
|
+
const switchItem = item as SwitchToolbarItem
|
|
16
|
+
const { props = {}, disabled = false } = switchItem
|
|
17
|
+
// SwitchProps doesn't have 'value', it uses 'checked'.
|
|
18
|
+
// Remove 'value' to avoid warning if passed by mistake
|
|
19
|
+
const { value: _ignored, ...otherProps } = props as any
|
|
20
|
+
|
|
21
|
+
const isDisabled = isFunction(disabled)
|
|
22
|
+
? disabled(toolbarState.getAllValues(), toolbarState)
|
|
23
|
+
: disabled
|
|
24
|
+
const finalProps: Partial<SwitchProps> & { disabled?: boolean; checked?: boolean } = {
|
|
25
|
+
...otherProps,
|
|
26
|
+
disabled: isDisabled,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 处理事件,注入工具栏状态
|
|
30
|
+
const processedEvents: Record<string, VoidFunction> = {}
|
|
31
|
+
Object.keys(events).forEach((eventName) => {
|
|
32
|
+
processedEvents[eventName] = (...args: any[]) => {
|
|
33
|
+
// 对于开关,自动更新状态
|
|
34
|
+
if (eventName === 'onUpdate:checked' || eventName === 'onChange') {
|
|
35
|
+
const checked = args[0]?.target?.checked ?? args[0]
|
|
36
|
+
toolbarState.setValue(key, checked)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 调用原始事件处理函数
|
|
40
|
+
events[eventName]?.(...args, toolbarState.getAllValues(), toolbarState)
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// 如果没有设置onChange事件,添加默认的状态更新
|
|
45
|
+
if (!processedEvents['onUpdate:checked'] && !processedEvents.onChange) {
|
|
46
|
+
processedEvents['onUpdate:checked'] = (checked: boolean) => {
|
|
47
|
+
toolbarState.setValue(key, checked)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const Comp = markRaw(Switch)
|
|
52
|
+
return (
|
|
53
|
+
<Comp
|
|
54
|
+
key={key}
|
|
55
|
+
checked={toolbarState.getValue(key) ?? finalProps.checked ?? false}
|
|
56
|
+
{...finalProps}
|
|
57
|
+
{...processedEvents}
|
|
58
|
+
/>
|
|
59
|
+
)
|
|
60
|
+
}
|
package/src/render/Tree.tsx
CHANGED
|
@@ -1,136 +1,136 @@
|
|
|
1
|
-
import { Tree } from '@antsoo-lib/components'
|
|
2
|
-
import type { AnyObject } from '@antsoo-lib/shared'
|
|
3
|
-
import { isFunction } from '@antsoo-lib/utils'
|
|
4
|
-
|
|
5
|
-
import { markRaw } from 'vue'
|
|
6
|
-
import type { VNode } from 'vue'
|
|
7
|
-
|
|
8
|
-
import type { ToolbarState } from './state'
|
|
9
|
-
import type { ToolbarItem, TreeToolbarItem } from './types'
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* 按工具栏项缓存树展开状态,避免表单重渲染后丢失展开态
|
|
13
|
-
*/
|
|
14
|
-
const treeExpandedKeysCache = new WeakMap<object, any[]>()
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* 解析树组件选中值
|
|
18
|
-
* @description 优先级:formValues -> toolbarState -> props.checkedKeys
|
|
19
|
-
*/
|
|
20
|
-
function resolveTreeCheckedKeys(
|
|
21
|
-
key: string | undefined,
|
|
22
|
-
props: AnyObject,
|
|
23
|
-
toolbarState: ToolbarState,
|
|
24
|
-
formValues?: AnyObject,
|
|
25
|
-
): any[] {
|
|
26
|
-
if (key && formValues && formValues[key] !== undefined) {
|
|
27
|
-
return formValues[key] ?? []
|
|
28
|
-
}
|
|
29
|
-
if (key) {
|
|
30
|
-
const stateValue = toolbarState.getValue(key)
|
|
31
|
-
if (stateValue !== undefined) {
|
|
32
|
-
return stateValue ?? []
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
const propValue = props?.checkedKeys
|
|
36
|
-
if (isFunction(propValue)) {
|
|
37
|
-
return propValue(toolbarState.getAllValues(), toolbarState) ?? []
|
|
38
|
-
}
|
|
39
|
-
return propValue ?? []
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* 标准化树勾选值
|
|
44
|
-
* @description 兼容 strict 模式下 { checked, halfChecked } 结构
|
|
45
|
-
*/
|
|
46
|
-
function normalizeCheckedKeys(value: any): any {
|
|
47
|
-
if (Array.isArray(value)) return value
|
|
48
|
-
if (value && typeof value === 'object' && Array.isArray(value.checked)) return value.checked
|
|
49
|
-
return value
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* 渲染树控件
|
|
54
|
-
* @description 提供 checkedKeys 与 expandedKeys 的同步能力,并桥接到 CoreForm 事件系统
|
|
55
|
-
*/
|
|
56
|
-
export function renderTree(
|
|
57
|
-
item: ToolbarItem,
|
|
58
|
-
toolbarState: ToolbarState,
|
|
59
|
-
formValues?: AnyObject,
|
|
60
|
-
): VNode {
|
|
61
|
-
const treeItem = item as TreeToolbarItem
|
|
62
|
-
const { key, events = {} } = treeItem
|
|
63
|
-
const { props = {}, disabled } = treeItem
|
|
64
|
-
const finalDisabled = isFunction(disabled)
|
|
65
|
-
? disabled(toolbarState.getAllValues(), toolbarState)
|
|
66
|
-
: disabled
|
|
67
|
-
|
|
68
|
-
const { treeData: originalTreeData, ...otherProps } = props as AnyObject
|
|
69
|
-
const treeData = (() => {
|
|
70
|
-
if (isFunction(originalTreeData)) {
|
|
71
|
-
return originalTreeData(toolbarState.getAllValues())
|
|
72
|
-
}
|
|
73
|
-
if (originalTreeData && typeof originalTreeData === 'object' && 'value' in originalTreeData) {
|
|
74
|
-
return (originalTreeData as AnyObject).value || []
|
|
75
|
-
}
|
|
76
|
-
return originalTreeData || []
|
|
77
|
-
})()
|
|
78
|
-
|
|
79
|
-
const allValues = () => toolbarState.getAllValues()
|
|
80
|
-
const cachedExpanded = treeExpandedKeysCache.get(treeItem as object)
|
|
81
|
-
const expandedKeys = (props as AnyObject).expandedKeys ?? cachedExpanded
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* 同步勾选键值
|
|
85
|
-
*/
|
|
86
|
-
const syncCheckedKeys = (value: any) => {
|
|
87
|
-
const normalized = normalizeCheckedKeys(value)
|
|
88
|
-
if (key) {
|
|
89
|
-
toolbarState.setValue(key, normalized)
|
|
90
|
-
}
|
|
91
|
-
const values = allValues()
|
|
92
|
-
events['onUpdate:checkedKeys']?.(normalized, values, toolbarState)
|
|
93
|
-
;(events as AnyObject)['onUpdate:value']?.(normalized, values, toolbarState)
|
|
94
|
-
events.onChange?.(normalized, values, toolbarState)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* 同步展开键值
|
|
99
|
-
*/
|
|
100
|
-
const syncExpandedKeys = (value: any) => {
|
|
101
|
-
treeExpandedKeysCache.set(treeItem as object, value)
|
|
102
|
-
const values = allValues()
|
|
103
|
-
;(events as AnyObject)['onUpdate:expandedKeys']?.(value, values, toolbarState)
|
|
104
|
-
;(events as AnyObject).onExpand?.(value, values, toolbarState)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const Comp = markRaw(Tree)
|
|
108
|
-
return (
|
|
109
|
-
<div
|
|
110
|
-
style={{
|
|
111
|
-
border: '1px solid rgba(228, 229, 235, 1)',
|
|
112
|
-
borderRadius: '6px',
|
|
113
|
-
padding: '8px 0 8px 8px',
|
|
114
|
-
}}
|
|
115
|
-
>
|
|
116
|
-
<Comp
|
|
117
|
-
key={key}
|
|
118
|
-
checkedKeys={resolveTreeCheckedKeys(key, props as AnyObject, toolbarState, formValues)}
|
|
119
|
-
treeData={treeData}
|
|
120
|
-
disabled={finalDisabled}
|
|
121
|
-
{...(expandedKeys !== undefined ? { expandedKeys } : {})}
|
|
122
|
-
{...otherProps}
|
|
123
|
-
onUpdate:checkedKeys={syncCheckedKeys}
|
|
124
|
-
onCheck={(checked: any, info: any) => {
|
|
125
|
-
syncCheckedKeys(checked)
|
|
126
|
-
;(events as AnyObject).onCheck?.(checked, info, allValues(), toolbarState)
|
|
127
|
-
}}
|
|
128
|
-
onUpdate:expandedKeys={syncExpandedKeys}
|
|
129
|
-
onExpand={(keys: any, info: any) => {
|
|
130
|
-
syncExpandedKeys(keys)
|
|
131
|
-
;(events as AnyObject).onExpand?.(keys, info, allValues(), toolbarState)
|
|
132
|
-
}}
|
|
133
|
-
/>
|
|
134
|
-
</div>
|
|
135
|
-
)
|
|
136
|
-
}
|
|
1
|
+
import { Tree } from '@antsoo-lib/components'
|
|
2
|
+
import type { AnyObject } from '@antsoo-lib/shared'
|
|
3
|
+
import { isFunction } from '@antsoo-lib/utils'
|
|
4
|
+
|
|
5
|
+
import { markRaw } from 'vue'
|
|
6
|
+
import type { VNode } from 'vue'
|
|
7
|
+
|
|
8
|
+
import type { ToolbarState } from './state'
|
|
9
|
+
import type { ToolbarItem, TreeToolbarItem } from './types'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 按工具栏项缓存树展开状态,避免表单重渲染后丢失展开态
|
|
13
|
+
*/
|
|
14
|
+
const treeExpandedKeysCache = new WeakMap<object, any[]>()
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 解析树组件选中值
|
|
18
|
+
* @description 优先级:formValues -> toolbarState -> props.checkedKeys
|
|
19
|
+
*/
|
|
20
|
+
function resolveTreeCheckedKeys(
|
|
21
|
+
key: string | undefined,
|
|
22
|
+
props: AnyObject,
|
|
23
|
+
toolbarState: ToolbarState,
|
|
24
|
+
formValues?: AnyObject,
|
|
25
|
+
): any[] {
|
|
26
|
+
if (key && formValues && formValues[key] !== undefined) {
|
|
27
|
+
return formValues[key] ?? []
|
|
28
|
+
}
|
|
29
|
+
if (key) {
|
|
30
|
+
const stateValue = toolbarState.getValue(key)
|
|
31
|
+
if (stateValue !== undefined) {
|
|
32
|
+
return stateValue ?? []
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const propValue = props?.checkedKeys
|
|
36
|
+
if (isFunction(propValue)) {
|
|
37
|
+
return propValue(toolbarState.getAllValues(), toolbarState) ?? []
|
|
38
|
+
}
|
|
39
|
+
return propValue ?? []
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 标准化树勾选值
|
|
44
|
+
* @description 兼容 strict 模式下 { checked, halfChecked } 结构
|
|
45
|
+
*/
|
|
46
|
+
function normalizeCheckedKeys(value: any): any {
|
|
47
|
+
if (Array.isArray(value)) return value
|
|
48
|
+
if (value && typeof value === 'object' && Array.isArray(value.checked)) return value.checked
|
|
49
|
+
return value
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 渲染树控件
|
|
54
|
+
* @description 提供 checkedKeys 与 expandedKeys 的同步能力,并桥接到 CoreForm 事件系统
|
|
55
|
+
*/
|
|
56
|
+
export function renderTree(
|
|
57
|
+
item: ToolbarItem,
|
|
58
|
+
toolbarState: ToolbarState,
|
|
59
|
+
formValues?: AnyObject,
|
|
60
|
+
): VNode {
|
|
61
|
+
const treeItem = item as TreeToolbarItem
|
|
62
|
+
const { key, events = {} } = treeItem
|
|
63
|
+
const { props = {}, disabled } = treeItem
|
|
64
|
+
const finalDisabled = isFunction(disabled)
|
|
65
|
+
? disabled(toolbarState.getAllValues(), toolbarState)
|
|
66
|
+
: disabled
|
|
67
|
+
|
|
68
|
+
const { treeData: originalTreeData, ...otherProps } = props as AnyObject
|
|
69
|
+
const treeData = (() => {
|
|
70
|
+
if (isFunction(originalTreeData)) {
|
|
71
|
+
return originalTreeData(toolbarState.getAllValues())
|
|
72
|
+
}
|
|
73
|
+
if (originalTreeData && typeof originalTreeData === 'object' && 'value' in originalTreeData) {
|
|
74
|
+
return (originalTreeData as AnyObject).value || []
|
|
75
|
+
}
|
|
76
|
+
return originalTreeData || []
|
|
77
|
+
})()
|
|
78
|
+
|
|
79
|
+
const allValues = () => toolbarState.getAllValues()
|
|
80
|
+
const cachedExpanded = treeExpandedKeysCache.get(treeItem as object)
|
|
81
|
+
const expandedKeys = (props as AnyObject).expandedKeys ?? cachedExpanded
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 同步勾选键值
|
|
85
|
+
*/
|
|
86
|
+
const syncCheckedKeys = (value: any) => {
|
|
87
|
+
const normalized = normalizeCheckedKeys(value)
|
|
88
|
+
if (key) {
|
|
89
|
+
toolbarState.setValue(key, normalized)
|
|
90
|
+
}
|
|
91
|
+
const values = allValues()
|
|
92
|
+
events['onUpdate:checkedKeys']?.(normalized, values, toolbarState)
|
|
93
|
+
;(events as AnyObject)['onUpdate:value']?.(normalized, values, toolbarState)
|
|
94
|
+
events.onChange?.(normalized, values, toolbarState)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 同步展开键值
|
|
99
|
+
*/
|
|
100
|
+
const syncExpandedKeys = (value: any) => {
|
|
101
|
+
treeExpandedKeysCache.set(treeItem as object, value)
|
|
102
|
+
const values = allValues()
|
|
103
|
+
;(events as AnyObject)['onUpdate:expandedKeys']?.(value, values, toolbarState)
|
|
104
|
+
;(events as AnyObject).onExpand?.(value, values, toolbarState)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const Comp = markRaw(Tree)
|
|
108
|
+
return (
|
|
109
|
+
<div
|
|
110
|
+
style={{
|
|
111
|
+
border: '1px solid rgba(228, 229, 235, 1)',
|
|
112
|
+
borderRadius: '6px',
|
|
113
|
+
padding: '8px 0 8px 8px',
|
|
114
|
+
}}
|
|
115
|
+
>
|
|
116
|
+
<Comp
|
|
117
|
+
key={key}
|
|
118
|
+
checkedKeys={resolveTreeCheckedKeys(key, props as AnyObject, toolbarState, formValues)}
|
|
119
|
+
treeData={treeData}
|
|
120
|
+
disabled={finalDisabled}
|
|
121
|
+
{...(expandedKeys !== undefined ? { expandedKeys } : {})}
|
|
122
|
+
{...otherProps}
|
|
123
|
+
onUpdate:checkedKeys={syncCheckedKeys}
|
|
124
|
+
onCheck={(checked: any, info: any) => {
|
|
125
|
+
syncCheckedKeys(checked)
|
|
126
|
+
;(events as AnyObject).onCheck?.(checked, info, allValues(), toolbarState)
|
|
127
|
+
}}
|
|
128
|
+
onUpdate:expandedKeys={syncExpandedKeys}
|
|
129
|
+
onExpand={(keys: any, info: any) => {
|
|
130
|
+
syncExpandedKeys(keys)
|
|
131
|
+
;(events as AnyObject).onExpand?.(keys, info, allValues(), toolbarState)
|
|
132
|
+
}}
|
|
133
|
+
/>
|
|
134
|
+
</div>
|
|
135
|
+
)
|
|
136
|
+
}
|