@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,170 @@
|
|
|
1
|
+
import { defineComponent, h, PropType, VNode } from "vue"
|
|
2
|
+
import { DefaultInfo, SearchData } from "@complex-suite/data"
|
|
3
|
+
import type { DictionaryEditMod } from "@complex-suite/data"
|
|
4
|
+
import EditView from "./EditView"
|
|
5
|
+
import type { EditViewDefaultProps } from "./EditView"
|
|
6
|
+
import type { AutoItemPayloadType } from "./dictionary/AutoItem"
|
|
7
|
+
import antdConfig from "../antdConfig"
|
|
8
|
+
|
|
9
|
+
export interface SearchAreaProps extends EditViewDefaultProps {
|
|
10
|
+
search: SearchData
|
|
11
|
+
searchMenu?: (string | DictionaryEditMod)[]
|
|
12
|
+
inline?: boolean
|
|
13
|
+
collapseMenuRender?: (collapse: boolean) => null | VNode | VNode[]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface SearchAreaOption extends SearchAreaProps {
|
|
17
|
+
ref?: string
|
|
18
|
+
onMenu?: (prop: string, payload: AutoItemPayloadType<'edit'>) => unknown
|
|
19
|
+
onEnter?: (prop: string, payload: AutoItemPayloadType<'edit'>) => unknown
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default defineComponent({
|
|
23
|
+
name: 'SearchArea',
|
|
24
|
+
emits: {
|
|
25
|
+
menu: (prop: string, _payload: AutoItemPayloadType<'edit'>) => {
|
|
26
|
+
return !!prop
|
|
27
|
+
},
|
|
28
|
+
enter: (prop: string, _payload: AutoItemPayloadType<'edit'>) => {
|
|
29
|
+
return !!prop
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
props: {
|
|
33
|
+
search: {
|
|
34
|
+
type: Object as PropType<SearchAreaProps['search']>,
|
|
35
|
+
required: true
|
|
36
|
+
},
|
|
37
|
+
searchMenu: {
|
|
38
|
+
type: Object as PropType<SearchAreaProps['searchMenu']>,
|
|
39
|
+
required: false
|
|
40
|
+
},
|
|
41
|
+
inline: {
|
|
42
|
+
type: Boolean,
|
|
43
|
+
required: false,
|
|
44
|
+
default: () => {
|
|
45
|
+
return antdConfig.search.inline
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
formProps: { // form-model-view设置项
|
|
49
|
+
type: Object as PropType<SearchAreaProps['formProps']>,
|
|
50
|
+
required: false
|
|
51
|
+
},
|
|
52
|
+
choice: {
|
|
53
|
+
type: Number,
|
|
54
|
+
required: false
|
|
55
|
+
},
|
|
56
|
+
menu: {
|
|
57
|
+
type: Object as PropType<SearchAreaProps['menu']>,
|
|
58
|
+
required: false
|
|
59
|
+
},
|
|
60
|
+
labelAlign: { // label 标签的文本对齐方式
|
|
61
|
+
type: String as PropType<SearchAreaProps['labelAlign']>,
|
|
62
|
+
required: false
|
|
63
|
+
},
|
|
64
|
+
gridParse: {
|
|
65
|
+
type: Object as PropType<SearchAreaProps['gridParse']>,
|
|
66
|
+
required: false
|
|
67
|
+
},
|
|
68
|
+
gridRowProps: { // form-model-view设置项
|
|
69
|
+
type: Object as PropType<SearchAreaProps['gridRowProps']>,
|
|
70
|
+
required: false
|
|
71
|
+
},
|
|
72
|
+
enter: {
|
|
73
|
+
type: Boolean,
|
|
74
|
+
required: false,
|
|
75
|
+
default: true
|
|
76
|
+
},
|
|
77
|
+
collapseMenuRender: {
|
|
78
|
+
type: Object as PropType<SearchAreaProps['collapseMenuRender']>,
|
|
79
|
+
required: false
|
|
80
|
+
},
|
|
81
|
+
collapse: {
|
|
82
|
+
type: Boolean,
|
|
83
|
+
required: false,
|
|
84
|
+
default: () => {
|
|
85
|
+
return antdConfig.search.collapse
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
disabled: {
|
|
89
|
+
type: Boolean,
|
|
90
|
+
required: false
|
|
91
|
+
},
|
|
92
|
+
loading: {
|
|
93
|
+
type: Boolean,
|
|
94
|
+
required: false
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
computed: {
|
|
98
|
+
currentSearchMenu() {
|
|
99
|
+
const currentSearchMenu = this.searchMenu ? this.search.$menu.list.concat(this.searchMenu) : this.search.$menu.list
|
|
100
|
+
return currentSearchMenu.map(menuOption => {
|
|
101
|
+
if (typeof menuOption === 'string') {
|
|
102
|
+
menuOption = SearchData.$getMenu(menuOption)!
|
|
103
|
+
}
|
|
104
|
+
return menuOption
|
|
105
|
+
}) as DefaultInfo[]
|
|
106
|
+
},
|
|
107
|
+
currentMenu() {
|
|
108
|
+
if (this.menu) {
|
|
109
|
+
return this.currentSearchMenu!.concat(this.menu)
|
|
110
|
+
} else {
|
|
111
|
+
return this.currentSearchMenu
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
methods: {
|
|
116
|
+
renderEdit(runtime: NonNullable<SearchData['$runtime']>) {
|
|
117
|
+
return h(EditView, {
|
|
118
|
+
form: runtime.form,
|
|
119
|
+
list: runtime.list,
|
|
120
|
+
type: this.search.$prop,
|
|
121
|
+
menu: this.currentMenu,
|
|
122
|
+
labelAlign: this.labelAlign,
|
|
123
|
+
gridParse: this.inline ? undefined : (this.gridParse || this.search.$layout.grid.getValue(this.search.$prop)),
|
|
124
|
+
gridRowProps: this.gridRowProps!,
|
|
125
|
+
formProps: this.formProps,
|
|
126
|
+
choice: this.choice,
|
|
127
|
+
enter: this.enter,
|
|
128
|
+
collapse: this.search.$collapse,
|
|
129
|
+
disabled: this.disabled,
|
|
130
|
+
loading: this.loading,
|
|
131
|
+
onMenu: (prop: string, payload: AutoItemPayloadType<'edit'>) => {
|
|
132
|
+
this.$emit('menu', prop, payload)
|
|
133
|
+
},
|
|
134
|
+
onEnter: (prop: string, payload: AutoItemPayloadType<'edit'>) => {
|
|
135
|
+
this.$emit('enter', prop, payload)
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
},
|
|
139
|
+
renderCollapseMenu() {
|
|
140
|
+
if (this.collapse && this.search.$collapse !== undefined) {
|
|
141
|
+
// 存在值时则进行展示
|
|
142
|
+
return h('div',
|
|
143
|
+
{
|
|
144
|
+
class: 'complex-search-area-collapse-menu'
|
|
145
|
+
},
|
|
146
|
+
[
|
|
147
|
+
!this.collapseMenuRender ? antdConfig.collapseMenuRender(this.search.$collapse, this.search) : this.collapseMenuRender(this.search.$collapse)
|
|
148
|
+
]
|
|
149
|
+
)
|
|
150
|
+
} else {
|
|
151
|
+
return null
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
render() {
|
|
156
|
+
if (this.search.$runtime) {
|
|
157
|
+
return h('div',
|
|
158
|
+
{
|
|
159
|
+
class: 'complex-search-area'
|
|
160
|
+
},
|
|
161
|
+
[
|
|
162
|
+
this.renderEdit(this.search.$runtime),
|
|
163
|
+
this.renderCollapseMenu()
|
|
164
|
+
]
|
|
165
|
+
)
|
|
166
|
+
} else {
|
|
167
|
+
return null
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
})
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span class="complex-select-text" :style="style" >{{ !format ? value ? value.label : missValue : format(value) }}</span>
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import { PropType, defineComponent } from "vue"
|
|
7
|
+
import { dataConfig } from "@complex-suite/data"
|
|
8
|
+
import type { SelectValueType } from "@complex-suite/data"
|
|
9
|
+
|
|
10
|
+
export default defineComponent({
|
|
11
|
+
name: 'SelectText',
|
|
12
|
+
props: {
|
|
13
|
+
value: {
|
|
14
|
+
type: Object as PropType<SelectValueType>,
|
|
15
|
+
required: false
|
|
16
|
+
},
|
|
17
|
+
color: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
required: false,
|
|
20
|
+
default: true
|
|
21
|
+
},
|
|
22
|
+
disabled: {
|
|
23
|
+
type: Boolean,
|
|
24
|
+
required: false,
|
|
25
|
+
default: false
|
|
26
|
+
},
|
|
27
|
+
format: {
|
|
28
|
+
type: Function as PropType<(value?: SelectValueType) => string>,
|
|
29
|
+
required: false
|
|
30
|
+
},
|
|
31
|
+
missValue: {
|
|
32
|
+
type: String,
|
|
33
|
+
required: false,
|
|
34
|
+
default: ''
|
|
35
|
+
},
|
|
36
|
+
emptyValue: {
|
|
37
|
+
type: String,
|
|
38
|
+
required: false,
|
|
39
|
+
default: ''
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
computed: {
|
|
43
|
+
style() {
|
|
44
|
+
if (this.value && this.color) {
|
|
45
|
+
return {
|
|
46
|
+
color: this.disabled ? dataConfig.style.color.disabled : this.value.$color ? dataConfig.style.color[this.value.$color] : this.value.color ? this.value.color : this.value.disabled ? dataConfig.style.color.disabled : undefined
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
methods: {
|
|
52
|
+
currentText() {
|
|
53
|
+
const value = this.value
|
|
54
|
+
const format = this.format
|
|
55
|
+
return !format ? value ? value.label : this.missValue : format(value) ?? this.emptyValue
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
</script>
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { defineComponent, h, PropType, VNode } from "vue"
|
|
2
|
+
import { Empty } from "ant-design-vue"
|
|
3
|
+
import { deepCloneData, updateData } from "@complex-suite/utils"
|
|
4
|
+
import { DefaultInfo, dataConfig, DefaultList } from "@complex-suite/data"
|
|
5
|
+
import PaginationView from "./components/PaginationView"
|
|
6
|
+
import TableMenu from "./components/TableMenu"
|
|
7
|
+
import type { tablePayload, TableViewDefaultProps } from "./TableView"
|
|
8
|
+
import antdConfig from "../antdConfig"
|
|
9
|
+
|
|
10
|
+
export interface SimpleTableProps extends TableViewDefaultProps {
|
|
11
|
+
lineHeight?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default defineComponent({
|
|
15
|
+
name: 'SimpleTable',
|
|
16
|
+
emits: {
|
|
17
|
+
menu: (prop: string, _payload: tablePayload) => {
|
|
18
|
+
return typeof prop === 'string'
|
|
19
|
+
},
|
|
20
|
+
pagination: (prop: 'page' | 'size', _page: number, _size: number) => {
|
|
21
|
+
return prop === 'page' || prop === 'size'
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
props: {
|
|
25
|
+
listData: {
|
|
26
|
+
type: Object as PropType<SimpleTableProps['listData']>,
|
|
27
|
+
required: false
|
|
28
|
+
},
|
|
29
|
+
columnList: { // 定制列配置
|
|
30
|
+
type: Object as PropType<SimpleTableProps['columnList']>,
|
|
31
|
+
required: false
|
|
32
|
+
},
|
|
33
|
+
data: { // 单独指定列表数据,不从listData.$list中取值
|
|
34
|
+
type: Array as PropType<SimpleTableProps['data']>,
|
|
35
|
+
required: false
|
|
36
|
+
},
|
|
37
|
+
paginationData: { // 单独制定分页器数据,不从listData中取值
|
|
38
|
+
type: Object as PropType<SimpleTableProps['paginationData']>,
|
|
39
|
+
required: false,
|
|
40
|
+
default: null
|
|
41
|
+
},
|
|
42
|
+
menu: {
|
|
43
|
+
type: Object as PropType<SimpleTableProps['menu']>,
|
|
44
|
+
required: false
|
|
45
|
+
},
|
|
46
|
+
listProp: {
|
|
47
|
+
type: String,
|
|
48
|
+
required: false,
|
|
49
|
+
default: 'list'
|
|
50
|
+
},
|
|
51
|
+
auto: {
|
|
52
|
+
type: Object as PropType<SimpleTableProps['auto']>,
|
|
53
|
+
required: false
|
|
54
|
+
},
|
|
55
|
+
lineHeight: {
|
|
56
|
+
type: Number as PropType<SimpleTableProps['lineHeight']>,
|
|
57
|
+
required: false
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
computed: {
|
|
61
|
+
currentData () {
|
|
62
|
+
if (this.data) {
|
|
63
|
+
return this.data
|
|
64
|
+
} else {
|
|
65
|
+
return this.listData?.$list!
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
currentIdList() {
|
|
69
|
+
return this.currentData.map(item => {
|
|
70
|
+
return item[this.listData!.getDictionaryProp('id')!]
|
|
71
|
+
})
|
|
72
|
+
},
|
|
73
|
+
currentAuto() {
|
|
74
|
+
return updateData(deepCloneData(antdConfig.table.auto), this.auto)
|
|
75
|
+
},
|
|
76
|
+
currentPaginationData() {
|
|
77
|
+
if (this.paginationData) {
|
|
78
|
+
return this.paginationData
|
|
79
|
+
} else {
|
|
80
|
+
return this.listData?.$module.pagination
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
currentColumnList() {
|
|
84
|
+
return this.columnList || this.listData!.getDictionaryPageList(this.listProp, this.listData!.getDictionaryList(this.listProp)!) as DefaultList[]
|
|
85
|
+
},
|
|
86
|
+
isEmpty() {
|
|
87
|
+
return !this.currentData || this.currentData.length === 0
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
methods: {
|
|
91
|
+
rowWidth(column: DefaultList | DefaultInfo) {
|
|
92
|
+
if (column.$width) {
|
|
93
|
+
return {
|
|
94
|
+
width: typeof column.$width === 'number' ? dataConfig.formatPixel(column.$width) : column.$width
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
return undefined
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
renderTable() {
|
|
101
|
+
return h('div', { class: 'complex-table-content complex-simple-table-content' }, {
|
|
102
|
+
default: () => [
|
|
103
|
+
this.currentColumnList.map(column => this.renderColumn(column))
|
|
104
|
+
]
|
|
105
|
+
})
|
|
106
|
+
},
|
|
107
|
+
renderColumn(column: DefaultList | DefaultInfo) {
|
|
108
|
+
return h('div', {
|
|
109
|
+
class: 'complex-simple-table-content-column complex-simple-table-content-column-' + ((column as DefaultList).align || 'left'),
|
|
110
|
+
style: this.rowWidth(column)
|
|
111
|
+
}, [
|
|
112
|
+
h('div', {
|
|
113
|
+
class: 'complex-simple-table-content-header'
|
|
114
|
+
}, column.$name),
|
|
115
|
+
!this.isEmpty ? this.currentData.map((val, index) => {
|
|
116
|
+
return h('div', {
|
|
117
|
+
class: 'complex-simple-table-content-row'
|
|
118
|
+
}, [
|
|
119
|
+
this.renderContent(column, val, index)
|
|
120
|
+
])
|
|
121
|
+
}) : null
|
|
122
|
+
])
|
|
123
|
+
},
|
|
124
|
+
renderEmpty() {
|
|
125
|
+
return !this.isEmpty ? null : h('div', {
|
|
126
|
+
class: 'complex-simple-table-content-empty'
|
|
127
|
+
}, [
|
|
128
|
+
h(Empty, {
|
|
129
|
+
"image": Empty.PRESENTED_IMAGE_SIMPLE
|
|
130
|
+
})
|
|
131
|
+
])
|
|
132
|
+
},
|
|
133
|
+
renderContent(column: DefaultList | DefaultInfo, record: Record<PropertyKey, unknown>, index: number) {
|
|
134
|
+
const content = this.$renderContent(column, record, index)
|
|
135
|
+
if (!this.lineHeight) {
|
|
136
|
+
return content
|
|
137
|
+
} else {
|
|
138
|
+
return h('div', {
|
|
139
|
+
style: {
|
|
140
|
+
height: dataConfig.formatPixel(this.lineHeight)
|
|
141
|
+
}
|
|
142
|
+
}, content)
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
$renderContent(column: DefaultList | DefaultInfo, record: Record<PropertyKey, unknown>, index: number) {
|
|
146
|
+
const payload: tablePayload = {
|
|
147
|
+
targetData: record,
|
|
148
|
+
type: this.listProp,
|
|
149
|
+
index: index,
|
|
150
|
+
payload: { column: column }
|
|
151
|
+
}
|
|
152
|
+
const text = antdConfig.table.renderTableValue(record[column.$prop], payload)
|
|
153
|
+
const targetRender = antdConfig.componentConfig.parseData(column.$renders, 'target')
|
|
154
|
+
const pureRender = antdConfig.componentConfig.parseData(column.$renders, 'pure')
|
|
155
|
+
const menuOption = antdConfig.componentConfig.parseData(this.menu, column.$prop)
|
|
156
|
+
if (pureRender) {
|
|
157
|
+
return pureRender({
|
|
158
|
+
text: text,
|
|
159
|
+
payload
|
|
160
|
+
}) as VNode | VNode[]
|
|
161
|
+
} else if (targetRender) {
|
|
162
|
+
return targetRender({
|
|
163
|
+
text: text,
|
|
164
|
+
payload
|
|
165
|
+
}) as VNode | VNode[]
|
|
166
|
+
} else if (menuOption) {
|
|
167
|
+
return h(TableMenu, {
|
|
168
|
+
list: menuOption,
|
|
169
|
+
payload: payload,
|
|
170
|
+
onMenu: (prop: string, payload: tablePayload) => {
|
|
171
|
+
this.$emit('menu', prop, payload)
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
} else if (column.$prop === this.currentAuto.index.prop) {
|
|
175
|
+
return antdConfig.table.renderIndex(record, index, this.currentAuto.index.pagination ? this.currentPaginationData : undefined)
|
|
176
|
+
} else if ((column as DefaultList).ellipsis) {
|
|
177
|
+
// 自动省略切自动换行
|
|
178
|
+
return antdConfig.table.renderAutoText(text as string, column, payload, antdConfig.componentConfig.parseData(column.$local, 'autoText'))
|
|
179
|
+
} else {
|
|
180
|
+
return h('p', antdConfig.componentConfig.parseAttrs(antdConfig.componentConfig.parseData(column.$local, 'target')), {
|
|
181
|
+
default: () => text
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
renderFooter() {
|
|
186
|
+
const render = h('div', { class: 'complex-table-footer complex-simple-table-footer' }, {
|
|
187
|
+
default: () => [this.renderFooterLeft(), this.renderFooterRight()]
|
|
188
|
+
})
|
|
189
|
+
return render
|
|
190
|
+
},
|
|
191
|
+
renderFooterLeft() {
|
|
192
|
+
const render = h('div', { class: 'complex-table-footer-left complex-simple-table-footer-left' }, {
|
|
193
|
+
default: () => null
|
|
194
|
+
})
|
|
195
|
+
return render
|
|
196
|
+
},
|
|
197
|
+
renderFooterRight() {
|
|
198
|
+
const render = h('div', { class: 'complex-table-footer-right complex-simple-table-footer-right' }, {
|
|
199
|
+
default: () => [this.renderPagination()]
|
|
200
|
+
})
|
|
201
|
+
return render
|
|
202
|
+
},
|
|
203
|
+
renderPagination() {
|
|
204
|
+
if (this.currentPaginationData) {
|
|
205
|
+
const data = h(PaginationView, {
|
|
206
|
+
pagination: this.currentPaginationData,
|
|
207
|
+
style: {
|
|
208
|
+
padding: '10px 0'
|
|
209
|
+
},
|
|
210
|
+
onCurrent: (page: number, size: number) => {
|
|
211
|
+
if (this.currentAuto.pagination.auto) {
|
|
212
|
+
this.listData?.reloadData({
|
|
213
|
+
data: true,
|
|
214
|
+
ing: true,
|
|
215
|
+
sync: true,
|
|
216
|
+
trigger: {
|
|
217
|
+
from: 'pagination',
|
|
218
|
+
action: 'page'
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
this.$emit('pagination', 'page', page, size)
|
|
223
|
+
},
|
|
224
|
+
onSize: (page: number, size: number) => {
|
|
225
|
+
if (this.currentAuto.pagination.auto) {
|
|
226
|
+
this.listData?.reloadData({
|
|
227
|
+
data: true,
|
|
228
|
+
ing: true,
|
|
229
|
+
sync: true,
|
|
230
|
+
trigger: {
|
|
231
|
+
from: 'pagination',
|
|
232
|
+
action: 'size'
|
|
233
|
+
}
|
|
234
|
+
})
|
|
235
|
+
}
|
|
236
|
+
this.$emit('pagination', 'size', page, size)
|
|
237
|
+
}
|
|
238
|
+
})
|
|
239
|
+
return data
|
|
240
|
+
} else {
|
|
241
|
+
return null
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
/**
|
|
246
|
+
* 主要模板
|
|
247
|
+
|
|
248
|
+
* @returns {VNode}
|
|
249
|
+
*/
|
|
250
|
+
render() {
|
|
251
|
+
const render = h('div', { class: 'complex-table complex-simple-table' }, {
|
|
252
|
+
default: () => [this.renderTable(), this.renderEmpty(), this.renderFooter()]
|
|
253
|
+
})
|
|
254
|
+
return render
|
|
255
|
+
}
|
|
256
|
+
})
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { defineComponent, h, PropType, ref, watch, VNode } from "vue"
|
|
2
|
+
import { useInjectFormItemContext } from "ant-design-vue/es/form"
|
|
3
|
+
import type { defaultFileOption, fileDataType } from "@complex-suite/data"
|
|
4
|
+
import type { FileEditOption } from "@complex-suite/data"
|
|
5
|
+
import { FileValue } from "@complex-suite/data"
|
|
6
|
+
import type { fileValueType } from "@complex-suite/data"
|
|
7
|
+
import { FileView } from "@complex-suite/component"
|
|
8
|
+
import type { FileProps } from "@complex-suite/component"
|
|
9
|
+
import antdConfig from "../antdConfig"
|
|
10
|
+
|
|
11
|
+
export interface DefaultImportProps {
|
|
12
|
+
button?: defaultFileOption['button']
|
|
13
|
+
complex?: defaultFileOption['complex']
|
|
14
|
+
isUrl?: defaultFileOption['isUrl']
|
|
15
|
+
image?: defaultFileOption['image']
|
|
16
|
+
loading?: boolean
|
|
17
|
+
render?: {
|
|
18
|
+
menu?: () => (VNode | VNode[])
|
|
19
|
+
content?: () => (VNode | VNode[])
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface SingleImportProps extends FileProps, DefaultImportProps {
|
|
24
|
+
value?: fileValueType
|
|
25
|
+
upload?: FileEditOption<false>['upload']
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const defaultUpload = function(file: File) {
|
|
29
|
+
return Promise.resolve({ file: { value: file, name: file.name } })
|
|
30
|
+
} as NonNullable<SingleImportProps['upload']>
|
|
31
|
+
|
|
32
|
+
export default defineComponent({
|
|
33
|
+
name: 'SingleImport',
|
|
34
|
+
props: {
|
|
35
|
+
value: {
|
|
36
|
+
type: [String, Object] as PropType<SingleImportProps['value']>
|
|
37
|
+
},
|
|
38
|
+
button: {
|
|
39
|
+
type: Object as PropType<SingleImportProps['button']>,
|
|
40
|
+
required: false
|
|
41
|
+
},
|
|
42
|
+
complex: {
|
|
43
|
+
type: Boolean as PropType<SingleImportProps['complex']>,
|
|
44
|
+
required: false
|
|
45
|
+
},
|
|
46
|
+
isUrl: {
|
|
47
|
+
type: Boolean as PropType<SingleImportProps['isUrl']>,
|
|
48
|
+
required: false
|
|
49
|
+
},
|
|
50
|
+
image: {
|
|
51
|
+
type: Object as PropType<SingleImportProps['image']>,
|
|
52
|
+
required: false
|
|
53
|
+
},
|
|
54
|
+
upload: {
|
|
55
|
+
type: Function as PropType<SingleImportProps['upload']>,
|
|
56
|
+
required: false
|
|
57
|
+
},
|
|
58
|
+
render: {
|
|
59
|
+
type: Object as PropType<SingleImportProps['render']>,
|
|
60
|
+
required: false
|
|
61
|
+
},
|
|
62
|
+
loading: {
|
|
63
|
+
type: Boolean,
|
|
64
|
+
required: false
|
|
65
|
+
},
|
|
66
|
+
accept: {
|
|
67
|
+
type: String,
|
|
68
|
+
required: false
|
|
69
|
+
},
|
|
70
|
+
size: { // MB
|
|
71
|
+
type: Number,
|
|
72
|
+
required: false
|
|
73
|
+
},
|
|
74
|
+
disabled: {
|
|
75
|
+
type: Boolean,
|
|
76
|
+
required: false
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
setup(props, { emit }) {
|
|
80
|
+
const formItemContext = useInjectFormItemContext()
|
|
81
|
+
const parseValue = function (value?: fileValueType) {
|
|
82
|
+
return value ? new FileValue(value, props.isUrl) : undefined
|
|
83
|
+
}
|
|
84
|
+
const operate = ref(false)
|
|
85
|
+
const currentValue = ref(props.value)
|
|
86
|
+
const data = ref(parseValue(props.value))
|
|
87
|
+
|
|
88
|
+
const syncValue = () => {
|
|
89
|
+
if (props.value !== currentValue.value) {
|
|
90
|
+
currentValue.value = props.value
|
|
91
|
+
}
|
|
92
|
+
data.value = parseValue(props.value)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
watch(() => props.value, () => {
|
|
96
|
+
syncValue()
|
|
97
|
+
formItemContext.onFieldChange()
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
const onSelect = (file: File) => {
|
|
101
|
+
operate.value = true;
|
|
102
|
+
(props.upload || defaultUpload)(file).then(res => {
|
|
103
|
+
onUpload(res.file, true)
|
|
104
|
+
}).catch((err: unknown) => {
|
|
105
|
+
console.error(err)
|
|
106
|
+
}).finally(() => {
|
|
107
|
+
operate.value = false
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const onUpload = (file: fileDataType, emit?: boolean) => {
|
|
112
|
+
if (!data.value || data.value.value !== file.value) {
|
|
113
|
+
currentValue.value = !props.complex ? file.value : file
|
|
114
|
+
data.value = new FileValue(file, props.isUrl)
|
|
115
|
+
if (emit) {
|
|
116
|
+
emitData()
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const emitData = () => {
|
|
122
|
+
emit('change', currentValue.value)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const renderFile = () => {
|
|
126
|
+
return h(FileView, {
|
|
127
|
+
class: 'complex-import-file',
|
|
128
|
+
ref: 'file',
|
|
129
|
+
accept: props.accept,
|
|
130
|
+
disabled: props.disabled,
|
|
131
|
+
size: props.size,
|
|
132
|
+
onSelect: onSelect,
|
|
133
|
+
onChange(e: Event) {
|
|
134
|
+
e.stopPropagation() // 阻止事件冒泡
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const deleteData = () => {
|
|
140
|
+
if (props.disabled || props.loading) {
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
currentValue.value = undefined
|
|
144
|
+
data.value = undefined
|
|
145
|
+
emitData()
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const renderContent = (file?: FileValue) => {
|
|
149
|
+
return (file && file.value) ? antdConfig.import.renderContent(file, props.disabled, props.image, () => {
|
|
150
|
+
deleteData()
|
|
151
|
+
}) : null
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
operate,
|
|
156
|
+
currentValue,
|
|
157
|
+
data,
|
|
158
|
+
onSelect,
|
|
159
|
+
onUpload,
|
|
160
|
+
emitData,
|
|
161
|
+
renderFile,
|
|
162
|
+
deleteData,
|
|
163
|
+
renderContent
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
render() {
|
|
167
|
+
let content: null | VNode | VNode[]
|
|
168
|
+
if (this.$slots.content || (this.render && this.render.content)) {
|
|
169
|
+
content = (this.$slots.content || this.render!.content)!({
|
|
170
|
+
props: {
|
|
171
|
+
upload: this.upload,
|
|
172
|
+
value: this.currentValue,
|
|
173
|
+
data: this.data,
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
} else {
|
|
177
|
+
content = this.renderContent(this.data)
|
|
178
|
+
}
|
|
179
|
+
return h('div', {
|
|
180
|
+
class: 'complex-import',
|
|
181
|
+
}, {
|
|
182
|
+
default: () => [
|
|
183
|
+
this.renderFile(),
|
|
184
|
+
antdConfig.import.renderMenu(this as any),
|
|
185
|
+
content,
|
|
186
|
+
]
|
|
187
|
+
})
|
|
188
|
+
}
|
|
189
|
+
})
|