@complex-suite/component-antd 4.10.12
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/LayoutResizeObserver.ts +104 -0
- package/LocalResizeObserver.ts +46 -0
- package/README.md +67 -0
- package/antdConfig.ts +361 -0
- package/format.ts +458 -0
- package/history.md +325 -0
- package/icon.ts +65 -0
- package/index.test.ts +5 -0
- package/index.ts +55 -0
- package/package.json +39 -0
- package/plugin.ts +95 -0
- package/quick/QuickCascade.tsx +107 -0
- package/quick/QuickEdit.tsx +117 -0
- package/quick/QuickFloat.tsx +32 -0
- package/quick/QuickFloatModal.tsx +95 -0
- package/quick/QuickFloatValue.tsx +103 -0
- package/quick/QuickList.tsx +433 -0
- package/quick/data/FloatData.ts +77 -0
- package/src/AutoSpin.vue +39 -0
- package/src/AutoText.vue +101 -0
- package/src/ButtonView.tsx +62 -0
- package/src/CollapseArea.tsx +88 -0
- package/src/EditArea.tsx +205 -0
- package/src/EditView.tsx +179 -0
- package/src/FlexBox.tsx +74 -0
- package/src/FormList.tsx +226 -0
- package/src/ImageViewer.tsx +122 -0
- package/src/InfoArea.tsx +182 -0
- package/src/InfoView.tsx +150 -0
- package/src/MenuView.tsx +91 -0
- package/src/ModalView.tsx +274 -0
- package/src/MultipleImport.tsx +231 -0
- package/src/SearchArea.tsx +170 -0
- package/src/SelectText.vue +59 -0
- package/src/SimpleTable.tsx +256 -0
- package/src/SingleImport.tsx +189 -0
- package/src/TableView.tsx +415 -0
- package/src/components/AutoRender.tsx +19 -0
- package/src/components/ChoiceInfo.vue +73 -0
- package/src/components/PaginationView.tsx +103 -0
- package/src/components/TableMenu.tsx +93 -0
- package/src/dictionary/AutoEditItem.tsx +164 -0
- package/src/dictionary/AutoInfoItem.tsx +126 -0
- package/src/dictionary/AutoItem.tsx +219 -0
- package/src/icons/EmptyImage.vue +30 -0
- package/src/icons/ErrorImage.vue +30 -0
- package/src/style/index.css +304 -0
- package/tsconfig.json +8 -0
- package/type.ts +4 -0
- package/vitest.config.ts +11 -0
- package/widthCalculator.ts +20 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Life } from "@complex-suite/utils"
|
|
2
|
+
import { PluginLayout } from "@complex-suite/plugin"
|
|
3
|
+
|
|
4
|
+
export type LayoutResizeObserverType = (entries: ResizeObserverEntry[], observer: LayoutResizeObserver) => void
|
|
5
|
+
|
|
6
|
+
export interface LayoutResizeObserverSupplement {
|
|
7
|
+
unCount?: boolean // 不计算entry
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// ResizeObserver 在开始观察一个元素时,确实会立即触发回调一次,即使在观察开始时元素的尺寸没有发生变化。这个立即触发的回调提供了元素的初始尺寸信息。
|
|
11
|
+
class LayoutResizeObserver {
|
|
12
|
+
static life = new Life()
|
|
13
|
+
static init(layout: PluginLayout) {
|
|
14
|
+
layout.onLife('main', {
|
|
15
|
+
handler: () => {
|
|
16
|
+
LayoutResizeObserver.life.trigger('mainChange', 'main')
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
static createResizeObserverEntry(target: Element, rect?: DOMRect): ResizeObserverEntry {
|
|
21
|
+
if (!rect) {
|
|
22
|
+
rect = target.getBoundingClientRect()
|
|
23
|
+
}
|
|
24
|
+
const computedStyle = getComputedStyle(target)
|
|
25
|
+
const paddingWidth = parseFloat(computedStyle.paddingLeft || '0') + parseFloat(computedStyle.paddingRight || '0')
|
|
26
|
+
const paddingHeight = parseFloat(computedStyle.paddingTop || '0') + parseFloat(computedStyle.paddingBottom || '0')
|
|
27
|
+
const borderWidth = parseFloat(computedStyle.borderLeftWidth || '0') + parseFloat(computedStyle.borderRightWidth || '0')
|
|
28
|
+
const borderHeight = parseFloat(computedStyle.borderTopWidth || '0') + parseFloat(computedStyle.borderBottomWidth || '0')
|
|
29
|
+
const contentBoxSize = {
|
|
30
|
+
inlineSize: rect.width - paddingWidth - borderWidth,
|
|
31
|
+
blockSize: rect.height - paddingHeight - borderHeight
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const borderBoxSize = {
|
|
35
|
+
inlineSize: rect.width,
|
|
36
|
+
blockSize: rect.height
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
target: target,
|
|
40
|
+
contentRect: rect,
|
|
41
|
+
borderBoxSize: [borderBoxSize],
|
|
42
|
+
contentBoxSize: [contentBoxSize],
|
|
43
|
+
devicePixelContentBoxSize: [contentBoxSize]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
private observer: LayoutResizeObserverType
|
|
47
|
+
private supplement: LayoutResizeObserverSupplement
|
|
48
|
+
private targetElements: Map<Element, DOMRect>
|
|
49
|
+
private lifeId: string
|
|
50
|
+
constructor(observer: LayoutResizeObserverType, supplement?: LayoutResizeObserverSupplement) {
|
|
51
|
+
this.observer = observer
|
|
52
|
+
this.supplement = supplement || {}
|
|
53
|
+
this.targetElements = new Map()
|
|
54
|
+
this.lifeId = LayoutResizeObserver.life.on('mainChange', {
|
|
55
|
+
handler: () => {
|
|
56
|
+
this.check()
|
|
57
|
+
}
|
|
58
|
+
})!
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
observe(target: Element) {
|
|
62
|
+
// 初始化目标元素的尺寸缓存
|
|
63
|
+
this.targetElements.set(target, target.getBoundingClientRect())
|
|
64
|
+
this.check()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
unobserve(target: Element) {
|
|
68
|
+
this.targetElements.delete(target)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
disconnect() {
|
|
72
|
+
this.targetElements.clear()
|
|
73
|
+
LayoutResizeObserver.life.off('mainChange', this.lifeId)
|
|
74
|
+
this.lifeId = ''
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private check() {
|
|
78
|
+
const entries: ResizeObserverEntry[] = []
|
|
79
|
+
this.targetElements.forEach((lastRect, target) => {
|
|
80
|
+
const rect = target.getBoundingClientRect()
|
|
81
|
+
if (rect.width !== lastRect.width || rect.height !== lastRect.height) {
|
|
82
|
+
// 尺寸变化,更新缓存并收集变更条目
|
|
83
|
+
if (!this.supplement.unCount) {
|
|
84
|
+
this.targetElements.set(target, rect)
|
|
85
|
+
entries.push(LayoutResizeObserver.createResizeObserverEntry(target, rect))
|
|
86
|
+
} else {
|
|
87
|
+
entries.push({
|
|
88
|
+
target: target,
|
|
89
|
+
contentRect: rect,
|
|
90
|
+
borderBoxSize: [],
|
|
91
|
+
contentBoxSize: [],
|
|
92
|
+
devicePixelContentBoxSize: []
|
|
93
|
+
} as ResizeObserverEntry)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
if (entries.length > 0) {
|
|
99
|
+
this.observer(entries, this)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export default LayoutResizeObserver
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import LayoutResizeObserver from "./LayoutResizeObserver"
|
|
2
|
+
import type { LayoutResizeObserverSupplement } from "./LayoutResizeObserver"
|
|
3
|
+
|
|
4
|
+
export type LocalResizeObserverType = (entry: ResizeObserverEntry) => void
|
|
5
|
+
|
|
6
|
+
class LocalResizeObserver {
|
|
7
|
+
observer: ResizeObserver | LayoutResizeObserver
|
|
8
|
+
$observer: LocalResizeObserverType
|
|
9
|
+
targetElements: Element[]
|
|
10
|
+
constructor(observer: LocalResizeObserverType, supplement?: LayoutResizeObserverSupplement) {
|
|
11
|
+
this.$observer = observer
|
|
12
|
+
const observers = (entries: ResizeObserverEntry[]) => {
|
|
13
|
+
entries.forEach(entry => {
|
|
14
|
+
this.trigger(entry)
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
if (window.ResizeObserver) {
|
|
18
|
+
this.observer = new ResizeObserver(observers)
|
|
19
|
+
} else {
|
|
20
|
+
this.observer = new LayoutResizeObserver(observers, supplement)
|
|
21
|
+
}
|
|
22
|
+
this.targetElements = []
|
|
23
|
+
}
|
|
24
|
+
trigger(entry: ResizeObserverEntry) {
|
|
25
|
+
if (this.targetElements.indexOf(entry.target) > -1) {
|
|
26
|
+
this.$observer(entry)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
observe(target: Element) {
|
|
30
|
+
this.observer.observe(target)
|
|
31
|
+
this.targetElements.push(target)
|
|
32
|
+
}
|
|
33
|
+
unobserve(target: Element) {
|
|
34
|
+
this.observer.unobserve(target)
|
|
35
|
+
const index = this.targetElements.indexOf(target)
|
|
36
|
+
if (index > -1) {
|
|
37
|
+
this.targetElements.splice(index, 1)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
disconnect() {
|
|
41
|
+
this.observer.disconnect()
|
|
42
|
+
this.targetElements = []
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default LocalResizeObserver
|
package/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Complex Component Antd
|
|
2
|
+
|
|
3
|
+
一套基于 Ant Design Vue v4 封装的复杂组件库,旨在与 `complex-data` 深度集成,帮助您快速构建功能强大的数据驱动型用户界面。
|
|
4
|
+
|
|
5
|
+
## ✨ 功能特性
|
|
6
|
+
|
|
7
|
+
- **数据驱动**: 组件设计紧密围绕 `complex-data` 的数据结构,通过数据字典即可驱动大部分 UI 的生成。
|
|
8
|
+
- **功能丰富的表格**: 提供强大的 `TableView` 组件,内置分页、排序、行选择、操作菜单等常用功能。
|
|
9
|
+
- **灵活的表单**: 包含 `SearchArea`、`EditArea`、`InfoArea` 等组件,轻松应对搜索、编辑、详情展示等多种场景。
|
|
10
|
+
- **高级封装**: `quick` 系列组件(如 `QuickTable`, `QuickModal`)提供了更高层次的抽象,进一步简化开发流程,提升开发效率。
|
|
11
|
+
- **实用工具组件**: 包含 `ModalView`、`ImageViewer`、`SingleImport`、`MultipleImport` 等一系列开箱即用的通用组件。
|
|
12
|
+
- **高度可定制**: 提供丰富的属性和插槽,允许开发者对组件的外观和行为进行深度定制。
|
|
13
|
+
|
|
14
|
+
## 核心组件
|
|
15
|
+
|
|
16
|
+
- **`TableView`**: 核心表格组件,用于展示列表数据。支持复杂的列配置、排序、筛选、行选择和操作列。
|
|
17
|
+
- **`SearchArea`**: 搜索区域组件,用于构建数据筛选表单。
|
|
18
|
+
- **`EditArea` / `InfoArea`**: 编辑和详情展示组件,用于创建数据编辑表单和只读信息展示。
|
|
19
|
+
- **`ModalView`**: 模态框组件,封装了 Ant Design Vue 的 `Modal`,并集成了更便捷的菜单和布局管理。
|
|
20
|
+
- **`quick` 系列**: `QuickTable`, `QuickSearch`, `QuickModal` 等,这些组件将 `complex-data` 的数据管理能力与 UI 组件相结合,实现了更高程度的自动化。
|
|
21
|
+
|
|
22
|
+
## 📦 安装
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install complex-component-antd
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 🚀 快速上手
|
|
29
|
+
|
|
30
|
+
以下是一个使用 `TableView` 的基本示例:
|
|
31
|
+
|
|
32
|
+
```vue
|
|
33
|
+
<template>
|
|
34
|
+
<TableView :list-data="userList" />
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script lang="ts">
|
|
38
|
+
import { defineComponent } from 'vue';
|
|
39
|
+
import { TableView } from 'complex-component-antd';
|
|
40
|
+
import { ComplexList } from 'complex-data';
|
|
41
|
+
import userDictionary from './dictionary/user'; // 假设这是您的用户数据字典
|
|
42
|
+
|
|
43
|
+
export default defineComponent({
|
|
44
|
+
name: 'UserList',
|
|
45
|
+
components: {
|
|
46
|
+
TableView
|
|
47
|
+
},
|
|
48
|
+
setup() {
|
|
49
|
+
// 使用 complex-data 创建一个列表数据实例
|
|
50
|
+
const userList = new ComplexList(userDictionary);
|
|
51
|
+
|
|
52
|
+
// 加载数据
|
|
53
|
+
userList.loadData();
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
userList
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
</script>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 依赖
|
|
64
|
+
|
|
65
|
+
- `ant-design-vue`: ^4.2.6
|
|
66
|
+
- `complex-data`: 4.10.1 - 4.10.99
|
|
67
|
+
- `complex-component`: 4.10.1 - 4.10.99
|
package/antdConfig.ts
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { h, reactive } from "vue"
|
|
2
|
+
import { Button } from "ant-design-vue"
|
|
3
|
+
import type { ButtonType } from "ant-design-vue/es/button"
|
|
4
|
+
import { getType, camelToLine, downloadFile, parseColor } from "@complex-suite/utils"
|
|
5
|
+
import { notice, PluginLayout } from "@complex-suite/plugin"
|
|
6
|
+
import { ChoiceData, PaginationData, AttrsValue, DictionaryData, DictionaryValue, DefaultInfo, dataConfig, DefaultList, DefaultEdit, FileValue } from "@complex-suite/data"
|
|
7
|
+
import type { GridValue } from "@complex-suite/data"
|
|
8
|
+
import type { collapseType } from "@complex-suite/data"
|
|
9
|
+
import type { defaultFileOption, MenuValue } from "@complex-suite/data"
|
|
10
|
+
import { AutoIndex, FileView, componentConfig } from "@complex-suite/component"
|
|
11
|
+
import AutoText from "./src/AutoText.vue"
|
|
12
|
+
import type { modalLayoutOption } from "./src/ModalView"
|
|
13
|
+
import type { tablePayload } from "./src/TableView"
|
|
14
|
+
import MultipleImport from "./src/MultipleImport"
|
|
15
|
+
import SingleImport from "./src/SingleImport"
|
|
16
|
+
import MenuView from "./src/MenuView"
|
|
17
|
+
import ImageViewer from "./src/ImageViewer"
|
|
18
|
+
import type { QuickListProps } from "./quick/QuickList"
|
|
19
|
+
import $icon from "./icon"
|
|
20
|
+
|
|
21
|
+
export class LayoutLifeData {
|
|
22
|
+
life: string
|
|
23
|
+
data: number
|
|
24
|
+
constructor() {
|
|
25
|
+
this.life = ''
|
|
26
|
+
this.data = 0
|
|
27
|
+
}
|
|
28
|
+
bind(layout: PluginLayout) {
|
|
29
|
+
this.life = layout.onLife('resize', {
|
|
30
|
+
handler: () => {
|
|
31
|
+
this.data++
|
|
32
|
+
}
|
|
33
|
+
})!
|
|
34
|
+
}
|
|
35
|
+
unbind(layout: PluginLayout) {
|
|
36
|
+
layout.offLife('resize', this.life)
|
|
37
|
+
this.data = 0
|
|
38
|
+
this.life = ''
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const antdConfig = reactive({
|
|
43
|
+
componentConfig: componentConfig,
|
|
44
|
+
dataConfig: dataConfig,
|
|
45
|
+
pluginLayout: null as null | PluginLayout,
|
|
46
|
+
isEdit(target: DefaultInfo) {
|
|
47
|
+
return target instanceof DefaultEdit && target.$editable === true
|
|
48
|
+
},
|
|
49
|
+
parseMenuConfirm(confirm: MenuValue['confirm'], next: () => void) {
|
|
50
|
+
if (!confirm) {
|
|
51
|
+
next()
|
|
52
|
+
} else {
|
|
53
|
+
const confirmOption = typeof confirm === 'string' ? { content: confirm } : confirm
|
|
54
|
+
notice.confirm(confirmOption.content, confirmOption.title, (act => {
|
|
55
|
+
if (act === 'ok') {
|
|
56
|
+
next()
|
|
57
|
+
}
|
|
58
|
+
}), confirmOption.okText, confirmOption.cancelText)
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
parseCollapse(collapse: boolean, dictionaryCollapse?: collapseType) {
|
|
62
|
+
if (collapse) {
|
|
63
|
+
return !!dictionaryCollapse
|
|
64
|
+
} else {
|
|
65
|
+
return true
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
collapseMenuRender(collapse: boolean, dictionary: DictionaryData) {
|
|
69
|
+
if (collapse) {
|
|
70
|
+
return h(MenuView, {
|
|
71
|
+
data: {
|
|
72
|
+
icon: 'down',
|
|
73
|
+
type: 'primary',
|
|
74
|
+
name: '展开'
|
|
75
|
+
},
|
|
76
|
+
onClick() {
|
|
77
|
+
dictionary.$collapse = false
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
} else {
|
|
81
|
+
return h(MenuView, {
|
|
82
|
+
data: {
|
|
83
|
+
icon: 'up',
|
|
84
|
+
type: 'primary',
|
|
85
|
+
name: '折叠'
|
|
86
|
+
},
|
|
87
|
+
onClick() {
|
|
88
|
+
dictionary.$collapse = true
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
style: {
|
|
94
|
+
element: undefined as undefined | HTMLStyleElement
|
|
95
|
+
},
|
|
96
|
+
initStyle() {
|
|
97
|
+
let rootInnerHTML = ":root{"
|
|
98
|
+
let styleInnerHTML = ""
|
|
99
|
+
for (const name in dataConfig.style.color) {
|
|
100
|
+
const styleName = camelToLine(name, '-')
|
|
101
|
+
const styleProp = 'complex-color-' + styleName
|
|
102
|
+
const styleVarProp = '--' + styleProp
|
|
103
|
+
const styleValue = dataConfig.style.color[name]
|
|
104
|
+
const rgba = parseColor(styleValue)
|
|
105
|
+
const rgbStr = `${rgba?.r},${rgba?.g},${rgba?.b}`
|
|
106
|
+
rootInnerHTML += `\n${styleVarProp}-rgb:${rgbStr};`
|
|
107
|
+
rootInnerHTML += `\n${styleVarProp}-rgba:${rgbStr},${rgba?.a};`
|
|
108
|
+
rootInnerHTML += `\n${styleVarProp}:${styleValue};`
|
|
109
|
+
styleInnerHTML += `\n.${styleProp}{color:var(${styleVarProp});}`
|
|
110
|
+
styleInnerHTML += `\n.complex-bg-color-${styleName}{background-color:var(${styleVarProp});}`
|
|
111
|
+
}
|
|
112
|
+
dataConfig.style.data.animateTime = componentConfig.animateTime
|
|
113
|
+
for (const name in dataConfig.style.data) {
|
|
114
|
+
const styleVarProp = '--complex-style-' + camelToLine(name, '-')
|
|
115
|
+
const styleValue = dataConfig.style.data[name]
|
|
116
|
+
rootInnerHTML += `\n${styleVarProp}:${styleValue};`
|
|
117
|
+
}
|
|
118
|
+
rootInnerHTML += "\n}"
|
|
119
|
+
// 设置样式规则
|
|
120
|
+
if (!antdConfig.style.element) {
|
|
121
|
+
antdConfig.style.element = document.createElement('style')
|
|
122
|
+
antdConfig.style.element.innerHTML =rootInnerHTML + styleInnerHTML
|
|
123
|
+
// 将样式元素节点添加到页面头部
|
|
124
|
+
document.head.appendChild(antdConfig.style.element)
|
|
125
|
+
} else {
|
|
126
|
+
antdConfig.style.element.innerHTML =rootInnerHTML + styleInnerHTML
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
parseGrid(gridValue: GridValue) {
|
|
130
|
+
return gridValue
|
|
131
|
+
},
|
|
132
|
+
showValue(value: unknown): string | number | undefined {
|
|
133
|
+
if (!['object', 'array'].includes(getType(value))) {
|
|
134
|
+
return value as string | number | undefined
|
|
135
|
+
} else {
|
|
136
|
+
return (value as Record<PropertyKey, any> | any[]).toString()
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
search: {
|
|
140
|
+
inline: false,
|
|
141
|
+
collapse: true, // 是否展示折叠
|
|
142
|
+
lineHeight: 81
|
|
143
|
+
},
|
|
144
|
+
edit: {
|
|
145
|
+
inline: false,
|
|
146
|
+
observe: false
|
|
147
|
+
},
|
|
148
|
+
info: {
|
|
149
|
+
inline: false,
|
|
150
|
+
observe: false
|
|
151
|
+
},
|
|
152
|
+
table: {
|
|
153
|
+
size: 'default',
|
|
154
|
+
bordered: true,
|
|
155
|
+
auto: {
|
|
156
|
+
expandWidth: 50,
|
|
157
|
+
choiceWidth: 60,
|
|
158
|
+
index: {
|
|
159
|
+
prop: '$index',
|
|
160
|
+
pagination: true
|
|
161
|
+
},
|
|
162
|
+
pagination: {
|
|
163
|
+
auto: true,
|
|
164
|
+
default: 'choice',
|
|
165
|
+
front: 'total',
|
|
166
|
+
end: false
|
|
167
|
+
},
|
|
168
|
+
sort: {
|
|
169
|
+
auto: true
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
renderTableValue(text: unknown, payload: tablePayload) {
|
|
173
|
+
const column = payload.payload.column
|
|
174
|
+
if (column.parse) {
|
|
175
|
+
text = column.parse(text, payload)
|
|
176
|
+
}
|
|
177
|
+
const parent = column.$getParent() as DictionaryValue
|
|
178
|
+
if (parent && parent.parse) {
|
|
179
|
+
text = parent.parse(text, payload)
|
|
180
|
+
}
|
|
181
|
+
return antdConfig.showValue(text)
|
|
182
|
+
},
|
|
183
|
+
renderAutoText(text: string, column: DefaultList | DefaultInfo, payload: tablePayload, attrs?: AttrsValue) {
|
|
184
|
+
return h(AutoText, {
|
|
185
|
+
text: text,
|
|
186
|
+
auto: true,
|
|
187
|
+
tip: column.$tip,
|
|
188
|
+
...componentConfig.parseAttrs(attrs, payload)
|
|
189
|
+
})
|
|
190
|
+
},
|
|
191
|
+
renderIndex(record: Record<PropertyKey, unknown>, index: number, pagination?: PaginationData) {
|
|
192
|
+
let buildPagination = !!pagination
|
|
193
|
+
if (pagination) {
|
|
194
|
+
const depth = record[DictionaryData.$depth]
|
|
195
|
+
if (depth != undefined && depth !== 0) {
|
|
196
|
+
buildPagination = false
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return h(AutoIndex, {
|
|
200
|
+
index: index,
|
|
201
|
+
pagination: buildPagination ? pagination : undefined
|
|
202
|
+
})
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
choice: {
|
|
206
|
+
show: true,
|
|
207
|
+
menu: true,
|
|
208
|
+
emptyContent: '未选择',
|
|
209
|
+
formatInfo(payload: { choice: ChoiceData, size: number, menu: boolean }) {
|
|
210
|
+
return `已选择 ${payload.size}条数据`
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
pagination: {
|
|
214
|
+
formatInfo(payload: { pagination: PaginationData }) {
|
|
215
|
+
return `共${payload.pagination.page.total}页/${payload.pagination.count}条`
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
form: {
|
|
219
|
+
checkOnRuleChange: true,
|
|
220
|
+
checkOnInit: false,
|
|
221
|
+
clearCheckOnInit: true
|
|
222
|
+
},
|
|
223
|
+
modal: {
|
|
224
|
+
width: 520,
|
|
225
|
+
destroyOnClose: true,
|
|
226
|
+
layout: {
|
|
227
|
+
type: 'auto',
|
|
228
|
+
top: 100,
|
|
229
|
+
bottom: 100,
|
|
230
|
+
header: 24 + 8,
|
|
231
|
+
menu: 32 + 12,
|
|
232
|
+
padding: [24, 24, 24, 24],
|
|
233
|
+
mainPadding: [20, 24, 20, 24]
|
|
234
|
+
} as modalLayoutOption,
|
|
235
|
+
menu: {
|
|
236
|
+
close: {
|
|
237
|
+
type: 'default',
|
|
238
|
+
name: '关闭',
|
|
239
|
+
prop: 'close',
|
|
240
|
+
debounce: 200
|
|
241
|
+
},
|
|
242
|
+
cancel: {
|
|
243
|
+
type: 'default',
|
|
244
|
+
name: '取消',
|
|
245
|
+
prop: 'close',
|
|
246
|
+
debounce: 200
|
|
247
|
+
},
|
|
248
|
+
submit: {
|
|
249
|
+
type: 'primary',
|
|
250
|
+
name: '确认',
|
|
251
|
+
prop: 'submit',
|
|
252
|
+
debounce: 200
|
|
253
|
+
}
|
|
254
|
+
} as Record<string, MenuValue>,
|
|
255
|
+
getMenu(prop: string, targetOption?: Partial<MenuValue>): MenuValue {
|
|
256
|
+
const data = this.menu[prop as keyof typeof antdConfig.modal.menu]
|
|
257
|
+
if (data) {
|
|
258
|
+
return {
|
|
259
|
+
...data,
|
|
260
|
+
...targetOption
|
|
261
|
+
}
|
|
262
|
+
} else {
|
|
263
|
+
console.error(`${prop}未获取到menu初始化参数,请检查代码!`)
|
|
264
|
+
return {
|
|
265
|
+
type: 'default',
|
|
266
|
+
name: prop,
|
|
267
|
+
prop: prop,
|
|
268
|
+
...targetOption
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
list: {
|
|
274
|
+
components: ['spin', 'search', 'table', 'edit'] as ('spin' | 'search' | 'table' | 'info' | 'edit' | 'child')[],
|
|
275
|
+
editDebounce: {
|
|
276
|
+
value: 200,
|
|
277
|
+
start: true
|
|
278
|
+
} as QuickListProps['editDebounce']
|
|
279
|
+
},
|
|
280
|
+
import: {
|
|
281
|
+
renderMenu(target: (InstanceType<typeof MultipleImport> | InstanceType<typeof SingleImport>)) {
|
|
282
|
+
const { icon = 'import', type = 'default', name = '上传' } = target.button || {}
|
|
283
|
+
const props = {
|
|
284
|
+
class: 'complex-import-menu',
|
|
285
|
+
loading: target.loading || target.operate,
|
|
286
|
+
type: type === 'danger' ? 'primary' : type as ButtonType,
|
|
287
|
+
danger: type === 'danger',
|
|
288
|
+
icon: $icon.parse(icon),
|
|
289
|
+
disabled: target.disabled,
|
|
290
|
+
onClick: () => {
|
|
291
|
+
(target.$refs.file as InstanceType<typeof FileView>).$el.click()
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const menuRender = target.$slots.menu || (target.render && target.render.menu)
|
|
295
|
+
if (menuRender) {
|
|
296
|
+
return menuRender({
|
|
297
|
+
props,
|
|
298
|
+
name: name,
|
|
299
|
+
payload: {
|
|
300
|
+
value: target.currentValue
|
|
301
|
+
}
|
|
302
|
+
})
|
|
303
|
+
}
|
|
304
|
+
return h(Button, props, {
|
|
305
|
+
default: () => name
|
|
306
|
+
})
|
|
307
|
+
},
|
|
308
|
+
renderContent(file: FileValue, disabled: boolean, image: defaultFileOption['image'], onDelete: (file: FileValue) => void) {
|
|
309
|
+
if (!image) {
|
|
310
|
+
return h('div', {
|
|
311
|
+
class: 'complex-import-content'
|
|
312
|
+
}, {
|
|
313
|
+
default: () => [
|
|
314
|
+
h('span', {
|
|
315
|
+
class: file.url ? 'complex-import-content-name complex-color-link' : 'complex-import-content-name',
|
|
316
|
+
onClick: () => {
|
|
317
|
+
if (file.url) {
|
|
318
|
+
// 文件对象类型以及存在下载链接时,点击下载
|
|
319
|
+
downloadFile(file.url, file.name)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}, {
|
|
323
|
+
default: () => file.name
|
|
324
|
+
}),
|
|
325
|
+
h('span', {
|
|
326
|
+
class: 'complex-import-content-delete complex-color-danger',
|
|
327
|
+
onClick () {
|
|
328
|
+
onDelete(file)
|
|
329
|
+
}
|
|
330
|
+
}, disabled ? [] : [$icon.parse('close')]),
|
|
331
|
+
]
|
|
332
|
+
})
|
|
333
|
+
} else {
|
|
334
|
+
const width = antdConfig.componentConfig.dataConfig.formatPixel(image.width)
|
|
335
|
+
return h('div', {
|
|
336
|
+
class: 'complex-import-image',
|
|
337
|
+
style: {
|
|
338
|
+
width
|
|
339
|
+
}
|
|
340
|
+
}, {
|
|
341
|
+
default: () => [
|
|
342
|
+
h(ImageViewer, {
|
|
343
|
+
class: 'complex-import-image-viewer',
|
|
344
|
+
src: file.url,
|
|
345
|
+
...image
|
|
346
|
+
}),
|
|
347
|
+
h('span', {
|
|
348
|
+
class: 'complex-import-content-delete complex-color-danger',
|
|
349
|
+
onClick () {
|
|
350
|
+
onDelete(file)
|
|
351
|
+
}
|
|
352
|
+
}, disabled ? [] : [$icon.parse('close')]),
|
|
353
|
+
]
|
|
354
|
+
})
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
export default antdConfig
|