@ethan1979/jf-lib 0.0.32
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/.vscode/extensions.json +3 -0
- package/README.md +3 -0
- package/babel.config.js +3 -0
- package/dist/App.vue.d.ts +2 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/v-table/components/content/components/operations.vue.d.ts +47 -0
- package/dist/components/v-table/components/content/index.vue.d.ts +13 -0
- package/dist/components/v-table/components/modal-form.vue.d.ts +30 -0
- package/dist/components/v-table/components/search.vue.d.ts +12 -0
- package/dist/components/v-table/components/toolbar.vue.d.ts +11 -0
- package/dist/components/v-table/get-render-function.d.ts +6 -0
- package/dist/components/v-table/hooks.d.ts +80 -0
- package/dist/components/v-table/index.vue.d.ts +17 -0
- package/dist/components/v-table/util.d.ts +2 -0
- package/dist/favicon.ico +0 -0
- package/dist/jf-lib.es.js +6553 -0
- package/dist/jf-lib.umd.js +27 -0
- package/dist/main.d.ts +1 -0
- package/dist/style.css +1 -0
- package/dist/types/global.d.ts +43 -0
- package/dist/utils/utils.d.ts +11 -0
- package/docs/superpowers/plans/2026-09-19-collapsible-table-search.md +194 -0
- package/docs/superpowers/specs/2026-09-19-collapsible-table-search-design.md +80 -0
- package/index.html +13 -0
- package/package.json +31 -0
- package/public/favicon.ico +0 -0
- package/scripts/check-collapsible-search.mjs +67 -0
- package/src/App.vue +98 -0
- package/src/assets/logo.png +0 -0
- package/src/components/index.ts +18 -0
- package/src/components/v-table/components/content/components/operations.vue +119 -0
- package/src/components/v-table/components/content/index.vue +295 -0
- package/src/components/v-table/components/modal-form.vue +111 -0
- package/src/components/v-table/components/search.vue +181 -0
- package/src/components/v-table/components/toolbar.vue +121 -0
- package/src/components/v-table/get-render-function.ts +15 -0
- package/src/components/v-table/hooks.ts +128 -0
- package/src/components/v-table/index.vue +338 -0
- package/src/components/v-table/typings.d.ts +164 -0
- package/src/components/v-table/util.ts +14 -0
- package/src/env.d.ts +12 -0
- package/src/main.ts +13 -0
- package/src/types/global.ts +48 -0
- package/src/utils/utils.ts +77 -0
- package/tsconfig.json +38 -0
- package/tsconfig.node.json +8 -0
- package/vite.config.ts +47 -0
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ethan1979/jf-lib",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "0.0.32",
|
|
5
|
+
"main": "./dist/jf-lib.es.js",
|
|
6
|
+
"typings": "./dist/components/index.d.ts",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"dev": "vite",
|
|
10
|
+
"build": "vite build && vue-tsc --emitDeclarationOnly",
|
|
11
|
+
"test:collapsible-search": "node scripts/check-collapsible-search.mjs",
|
|
12
|
+
"preview": "vite preview"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@arco-design/web-vue": "latest",
|
|
18
|
+
"@types/lodash": "^4.14.182",
|
|
19
|
+
"@types/node": "^17.0.26",
|
|
20
|
+
"@vitejs/plugin-vue": "^2.3.1",
|
|
21
|
+
"less": "^4.1.2",
|
|
22
|
+
"typescript": "^4.5.4",
|
|
23
|
+
"vite": "^2.9.5",
|
|
24
|
+
"vue-tsc": "^0.34.7",
|
|
25
|
+
"vite-plugin-dts": "^1.1.1",
|
|
26
|
+
"lodash": "^4.17.21",
|
|
27
|
+
"vue": "^3.2.25",
|
|
28
|
+
"@vitejs/plugin-vue-jsx": "^1.2.0",
|
|
29
|
+
"@vue/babel-plugin-jsx": "^1.1.1"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import assert from 'node:assert/strict'
|
|
2
|
+
import { readFile } from 'node:fs/promises'
|
|
3
|
+
|
|
4
|
+
const [packageSource, searchSource, typingsSource] = await Promise.all([
|
|
5
|
+
readFile(new URL('../package.json', import.meta.url), 'utf8'),
|
|
6
|
+
readFile(
|
|
7
|
+
new URL(
|
|
8
|
+
'../src/components/v-table/components/search.vue',
|
|
9
|
+
import.meta.url
|
|
10
|
+
),
|
|
11
|
+
'utf8'
|
|
12
|
+
),
|
|
13
|
+
readFile(
|
|
14
|
+
new URL('../src/components/v-table/typings.d.ts', import.meta.url),
|
|
15
|
+
'utf8'
|
|
16
|
+
),
|
|
17
|
+
])
|
|
18
|
+
|
|
19
|
+
const pkg = JSON.parse(packageSource)
|
|
20
|
+
const checks = [
|
|
21
|
+
[
|
|
22
|
+
'declares the collapsible option',
|
|
23
|
+
() => assert.match(typingsSource, /collapsible\?: boolean/),
|
|
24
|
+
],
|
|
25
|
+
[
|
|
26
|
+
'declares the default visible fields option',
|
|
27
|
+
() =>
|
|
28
|
+
assert.match(typingsSource, /defaultVisibleFields\?: string\[\]/),
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
'renders the derived visible field list',
|
|
32
|
+
() => assert.match(searchSource, /in visibleForm/),
|
|
33
|
+
],
|
|
34
|
+
[
|
|
35
|
+
'requires collapsible to be explicitly enabled',
|
|
36
|
+
() => assert.match(searchSource, /collapsible\s*===\s*true/),
|
|
37
|
+
],
|
|
38
|
+
[
|
|
39
|
+
'exposes the expansion state',
|
|
40
|
+
() => assert.match(searchSource, /:aria-expanded="expanded"/),
|
|
41
|
+
],
|
|
42
|
+
[
|
|
43
|
+
'renders both toggle labels',
|
|
44
|
+
() => assert.match(searchSource, /expanded \? '收起' : '展开'/),
|
|
45
|
+
],
|
|
46
|
+
[
|
|
47
|
+
'uses the release version',
|
|
48
|
+
() => assert.equal(pkg.version, '0.0.32'),
|
|
49
|
+
],
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
const failures = []
|
|
53
|
+
for (const [name, check] of checks) {
|
|
54
|
+
try {
|
|
55
|
+
check()
|
|
56
|
+
} catch {
|
|
57
|
+
failures.push(name)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (failures.length > 0) {
|
|
62
|
+
console.error('Collapsible search contract failed:')
|
|
63
|
+
failures.forEach((failure) => console.error('- ' + failure))
|
|
64
|
+
process.exitCode = 1
|
|
65
|
+
} else {
|
|
66
|
+
console.log('Collapsible search contract is valid.')
|
|
67
|
+
}
|
package/src/App.vue
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div style="height:100vh">
|
|
3
|
+
<v-table :config="config" />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
import { ref } from "vue";
|
|
9
|
+
import VTable from "./components/v-table/index.vue";
|
|
10
|
+
import { TableConfig } from "./components/v-table/typings";
|
|
11
|
+
// console.log('zzzz',VTable);
|
|
12
|
+
const createData = () => {
|
|
13
|
+
const data: TableConfig = {
|
|
14
|
+
title:'test',
|
|
15
|
+
card:false,
|
|
16
|
+
table: {
|
|
17
|
+
data: [],
|
|
18
|
+
summary:true
|
|
19
|
+
},
|
|
20
|
+
columns: [],
|
|
21
|
+
};
|
|
22
|
+
const keys:string[]=[]
|
|
23
|
+
new Array(5).fill(0).map((_, index) => {
|
|
24
|
+
keys.push(`test${index}-1`,`test${index}-2`)
|
|
25
|
+
data.columns.push( {
|
|
26
|
+
title: `test${index}`,
|
|
27
|
+
dataIndex: `test${index}`,
|
|
28
|
+
children: [
|
|
29
|
+
{
|
|
30
|
+
title: `test${index}-1`,
|
|
31
|
+
dataIndex: `test${index}-1`,
|
|
32
|
+
width:120,
|
|
33
|
+
form:true
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
title: `test${index}-2`,
|
|
37
|
+
dataIndex: `test${index}-2`,
|
|
38
|
+
width:120,
|
|
39
|
+
form:true
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
},)
|
|
43
|
+
// console.log("index", index);
|
|
44
|
+
// data.table.data
|
|
45
|
+
});
|
|
46
|
+
keys.forEach(()=>{
|
|
47
|
+
const obj:{[key:string]:number}={}
|
|
48
|
+
keys.forEach(key=>{
|
|
49
|
+
obj[key]=Math.floor(Math.random()*100)
|
|
50
|
+
})
|
|
51
|
+
data.table.data.push(obj)
|
|
52
|
+
})
|
|
53
|
+
return data
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const config = ref<TableConfig>(createData());
|
|
57
|
+
setTimeout(()=>{
|
|
58
|
+
// config.value.table.summary=true
|
|
59
|
+
config.value.columns.push({
|
|
60
|
+
dataIndex:'title',
|
|
61
|
+
title:'zzz',
|
|
62
|
+
form:{
|
|
63
|
+
hiddenSearch:true
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
},100)
|
|
67
|
+
// setTimeout(() => {
|
|
68
|
+
// config.value=createData()
|
|
69
|
+
// // config.value = {
|
|
70
|
+
// // table: {
|
|
71
|
+
// // data: [
|
|
72
|
+
// // {
|
|
73
|
+
// // test: 1,
|
|
74
|
+
// // test2: 2,
|
|
75
|
+
// // },
|
|
76
|
+
// // ],
|
|
77
|
+
// // },
|
|
78
|
+
// // columns: [
|
|
79
|
+
// // {
|
|
80
|
+
// // title: "test1",
|
|
81
|
+
// // dataIndex: "test1",
|
|
82
|
+
// // children: [
|
|
83
|
+
// // {
|
|
84
|
+
// // title: "test",
|
|
85
|
+
// // dataIndex: "test",
|
|
86
|
+
// // },
|
|
87
|
+
// // {
|
|
88
|
+
// // title: "test2",
|
|
89
|
+
// // dataIndex: "test2",
|
|
90
|
+
// // },
|
|
91
|
+
// // ],
|
|
92
|
+
// // },
|
|
93
|
+
// // ],
|
|
94
|
+
// // };
|
|
95
|
+
// }, 1000);
|
|
96
|
+
</script>
|
|
97
|
+
|
|
98
|
+
<style lang="scss" scoped></style>
|
|
Binary file
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// import VTable from './v-table/index.vue'
|
|
2
|
+
|
|
3
|
+
const NAV_HEIGHT = 60
|
|
4
|
+
|
|
5
|
+
const getContainerHeight = () => {
|
|
6
|
+
const { innerHeight } = window
|
|
7
|
+
const height = innerHeight - NAV_HEIGHT - 32
|
|
8
|
+
window.containerHeight = height
|
|
9
|
+
document.body.style.setProperty('--container-height', `${height}px`)
|
|
10
|
+
}
|
|
11
|
+
getContainerHeight()
|
|
12
|
+
window.addEventListener('resize', () => getContainerHeight())
|
|
13
|
+
|
|
14
|
+
// export default {
|
|
15
|
+
// VTable
|
|
16
|
+
// }
|
|
17
|
+
|
|
18
|
+
export {default as VTable} from './v-table/index.vue'
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span class="column-operations">
|
|
3
|
+
<template v-if="extendRender && props.extendPostion === 'left'">
|
|
4
|
+
<component :is="extendRender" />
|
|
5
|
+
</template>
|
|
6
|
+
<a-button
|
|
7
|
+
v-if="!updateButton?.hidden"
|
|
8
|
+
type="text"
|
|
9
|
+
:disabled="updateButton?.disabled"
|
|
10
|
+
@click="updateData"
|
|
11
|
+
>编辑</a-button
|
|
12
|
+
>
|
|
13
|
+
<template v-if="extendRender && props.extendPostion === 'center'">
|
|
14
|
+
<component :is="extendRender" />
|
|
15
|
+
</template>
|
|
16
|
+
<a-popconfirm content="确定要删除此项内容吗" @ok="deleteData">
|
|
17
|
+
<a-button
|
|
18
|
+
v-if="!deleteButton?.hidden"
|
|
19
|
+
type="text"
|
|
20
|
+
status="danger"
|
|
21
|
+
:disabled="deleteButton?.disabled"
|
|
22
|
+
>删除</a-button
|
|
23
|
+
>
|
|
24
|
+
</a-popconfirm>
|
|
25
|
+
<template v-if="extendRender && props.extendPostion === 'right'">
|
|
26
|
+
<component :is="extendRender" />
|
|
27
|
+
</template>
|
|
28
|
+
</span>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script setup lang="ts">
|
|
32
|
+
import { computed, h, onMounted, toRefs } from 'vue'
|
|
33
|
+
import {
|
|
34
|
+
CellRenderFN,
|
|
35
|
+
OperationsButtonConfig,
|
|
36
|
+
TableConfig,
|
|
37
|
+
} from '@/components/v-table/typings'
|
|
38
|
+
import { BaseObj } from '../../../../../types/global'
|
|
39
|
+
import { TableColumnData } from '@arco-design/web-vue';
|
|
40
|
+
|
|
41
|
+
export interface ColumnData {
|
|
42
|
+
record: BaseObj
|
|
43
|
+
column: TableColumnData
|
|
44
|
+
rowIndex: number
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const props = withDefaults(
|
|
48
|
+
defineProps<{
|
|
49
|
+
config: TableConfig
|
|
50
|
+
columnData: ColumnData
|
|
51
|
+
extend?: CellRenderFN
|
|
52
|
+
extendPostion?: 'center' | 'left' | 'right'
|
|
53
|
+
updateButton?: OperationsButtonConfig
|
|
54
|
+
deleteButton?: OperationsButtonConfig
|
|
55
|
+
}>(),
|
|
56
|
+
{
|
|
57
|
+
extendPostion: 'center',
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
const emit = defineEmits(['updateData', 'deleteData'])
|
|
62
|
+
|
|
63
|
+
const { config, columnData, extend } = toRefs(props)
|
|
64
|
+
|
|
65
|
+
const extendRender = computed(() => {
|
|
66
|
+
if (!columnData) return false
|
|
67
|
+
const { record, column, rowIndex } = columnData?.value as ColumnData
|
|
68
|
+
return () =>
|
|
69
|
+
extend?.value ? extend.value(record, column, rowIndex) : h('span')
|
|
70
|
+
// return false
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const updateData = async () => {
|
|
74
|
+
if (typeof props.updateButton?.onClick === 'function') {
|
|
75
|
+
const result = await props.updateButton?.onClick(columnData?.value?.record)
|
|
76
|
+
if (result === false) return
|
|
77
|
+
}
|
|
78
|
+
emit('updateData', columnData?.value?.record)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const deleteData = async () => {
|
|
82
|
+
if (typeof props.deleteButton?.onClick === 'function') {
|
|
83
|
+
const result = await props.deleteButton?.onClick(columnData?.value?.record)
|
|
84
|
+
if (result === false) return
|
|
85
|
+
}
|
|
86
|
+
emit('deleteData', columnData?.value?.record)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
onMounted(() => {
|
|
90
|
+
const columns = config?.value?.columns
|
|
91
|
+
if (!columns) return
|
|
92
|
+
const dataIndex = columnData?.value?.column.dataIndex
|
|
93
|
+
for (let i = 0; i < columns.length; i += 1) {
|
|
94
|
+
if (columns[i].dataIndex === dataIndex) {
|
|
95
|
+
const column = columns[i]
|
|
96
|
+
if (column.titleRender) return
|
|
97
|
+
const { title } = column
|
|
98
|
+
column.titleRender = () =>
|
|
99
|
+
h(
|
|
100
|
+
'span',
|
|
101
|
+
{
|
|
102
|
+
style: {
|
|
103
|
+
marginLeft: '6px',
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
title
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
<style lang="less">
|
|
114
|
+
.column-operations {
|
|
115
|
+
.arco-btn-size-medium {
|
|
116
|
+
padding: 0 6px;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
</style>
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
<script lang="tsx">
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
import {
|
|
4
|
+
computed,
|
|
5
|
+
defineComponent,
|
|
6
|
+
h,
|
|
7
|
+
inject,
|
|
8
|
+
nextTick,
|
|
9
|
+
onMounted,
|
|
10
|
+
onUnmounted,
|
|
11
|
+
PropType,
|
|
12
|
+
Ref,
|
|
13
|
+
ref,
|
|
14
|
+
toRefs,
|
|
15
|
+
VNode,
|
|
16
|
+
// watch,
|
|
17
|
+
} from 'vue'
|
|
18
|
+
import type _Table from '@arco-design/web-vue/es/table'
|
|
19
|
+
// import type _TableColumn from '@arco-design/web-vue/es/table/table-column'
|
|
20
|
+
import {
|
|
21
|
+
CellComponents,
|
|
22
|
+
CellRenderFN,
|
|
23
|
+
Columns,
|
|
24
|
+
OperationsProps,
|
|
25
|
+
TableConfig,
|
|
26
|
+
} from '../../typings'
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
28
|
+
import operations from './components/operations.vue'
|
|
29
|
+
import { BaseObj } from '../../../../types/global'
|
|
30
|
+
import { setSelectedRowKeys } from '../../util'
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
32
|
+
import ModalForm from '../modal-form.vue'
|
|
33
|
+
import { Table, TableColumn, TableColumnData } from '@arco-design/web-vue'
|
|
34
|
+
import { omit } from 'lodash'
|
|
35
|
+
|
|
36
|
+
export default defineComponent({
|
|
37
|
+
props: {
|
|
38
|
+
config: {
|
|
39
|
+
type: Object as PropType<TableConfig>,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
setup(props, { emit, expose }) {
|
|
43
|
+
const components = { operations }
|
|
44
|
+
|
|
45
|
+
// type Table = InstanceType<typeof _Table>;
|
|
46
|
+
|
|
47
|
+
// const props = defineProps({
|
|
48
|
+
// config: Object as PropType<TableConfig>,
|
|
49
|
+
// });
|
|
50
|
+
|
|
51
|
+
// const emit = defineEmits(["update", "deleteData", "get"]);
|
|
52
|
+
|
|
53
|
+
const tableRef = ref<InstanceType<typeof Table>>()
|
|
54
|
+
expose({tableRef})
|
|
55
|
+
const { config } = toRefs(props)
|
|
56
|
+
|
|
57
|
+
const TABLE_BASE_CONFIG: typeof Table['$props'] = {
|
|
58
|
+
pagination: {
|
|
59
|
+
current: 1,
|
|
60
|
+
showPageSize: true,
|
|
61
|
+
total: config?.value?.table?.data?.length || 0,
|
|
62
|
+
pageSize: 30,
|
|
63
|
+
showTotal: true,
|
|
64
|
+
showJumper: true,
|
|
65
|
+
},
|
|
66
|
+
rowSelection: {
|
|
67
|
+
type: 'checkbox',
|
|
68
|
+
showCheckedAll: true,
|
|
69
|
+
selectedRowKeys: [],
|
|
70
|
+
},
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const columns = computed(() => {
|
|
74
|
+
return config?.value?.columns
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const setPagination = (obj: BaseObj) => {
|
|
78
|
+
if (typeof config?.value?.table.pagination === 'object') {
|
|
79
|
+
config.value.table.pagination = {
|
|
80
|
+
...config.value.table.pagination,
|
|
81
|
+
...obj,
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const pageChange = (current: number) => {
|
|
86
|
+
setPagination({ current })
|
|
87
|
+
emit('get')
|
|
88
|
+
}
|
|
89
|
+
const pageSizeChange = (pageSize: number) => {
|
|
90
|
+
setPagination({ pageSize })
|
|
91
|
+
setPagination({ current: 1 })
|
|
92
|
+
emit('get')
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// const selectedRowKeys = inject<Ref<string[] | undefined>>('selectedRowKeys')
|
|
96
|
+
const selectionChange = (ids: string[] | undefined) => {
|
|
97
|
+
setSelectedRowKeys((config as Ref<TableConfig>).value, ids)
|
|
98
|
+
// if (selectedRowKeys) selectedRowKeys.value = ids
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const operationsRender = computed(() => {
|
|
102
|
+
let render = false
|
|
103
|
+
columns?.value?.forEach((column) => {
|
|
104
|
+
if (
|
|
105
|
+
typeof column.cellRender === 'object' &&
|
|
106
|
+
column.cellRender.type === 'operations'
|
|
107
|
+
) {
|
|
108
|
+
render = true
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
return render
|
|
112
|
+
})
|
|
113
|
+
const getProps = (
|
|
114
|
+
props:
|
|
115
|
+
| OperationsProps
|
|
116
|
+
| ((params: BaseObj) => OperationsProps)
|
|
117
|
+
| undefined,
|
|
118
|
+
params: any
|
|
119
|
+
) => {
|
|
120
|
+
if (typeof props === 'function') return props(params)
|
|
121
|
+
return {
|
|
122
|
+
...props,
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const visible = ref(false)
|
|
127
|
+
const renderParams = ref<BaseObj>({})
|
|
128
|
+
const modalForm = ref<{
|
|
129
|
+
formData: {
|
|
130
|
+
[x: string]: unknown
|
|
131
|
+
}
|
|
132
|
+
}>()
|
|
133
|
+
const updateData = (params: BaseObj) => {
|
|
134
|
+
renderParams.value = params
|
|
135
|
+
const formData = modalForm.value?.formData as {
|
|
136
|
+
[x: string]: unknown
|
|
137
|
+
}
|
|
138
|
+
Object.keys(formData).forEach((key) => {
|
|
139
|
+
// console.log(' params[key]', params[key], key, formData)
|
|
140
|
+
formData[key] = params[key]
|
|
141
|
+
})
|
|
142
|
+
// 主键,一般为id
|
|
143
|
+
const rowKey = config?.value?.table.rowKey
|
|
144
|
+
if (typeof rowKey === 'string') formData[rowKey] = params[rowKey]
|
|
145
|
+
visible.value = true
|
|
146
|
+
}
|
|
147
|
+
const deleteData = (params: BaseObj) => {
|
|
148
|
+
// console.log('????')
|
|
149
|
+
emit('deleteData', { ...params })
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const tableId = inject<string>('tableId')
|
|
153
|
+
|
|
154
|
+
const RenderColumns = (columns: Columns<BaseObj>[]) => {
|
|
155
|
+
return columns.map((column) => {
|
|
156
|
+
const slot: {
|
|
157
|
+
title?: () => VNode
|
|
158
|
+
cell?: any
|
|
159
|
+
} = {}
|
|
160
|
+
if (column.titleRender) slot.title = column.titleRender
|
|
161
|
+
if (!column.children && column.cellRender) {
|
|
162
|
+
if (typeof column.cellRender === 'function') {
|
|
163
|
+
slot.cell = column.cellRender
|
|
164
|
+
} else {
|
|
165
|
+
const component = column.cellRender as CellComponents<any>
|
|
166
|
+
slot.cell = (record: any) =>
|
|
167
|
+
h(components[component.type] as any, {
|
|
168
|
+
config: config?.value,
|
|
169
|
+
columnData: {
|
|
170
|
+
...record,
|
|
171
|
+
// column,
|
|
172
|
+
// rowIndex,
|
|
173
|
+
},
|
|
174
|
+
...getProps(component?.props, record),
|
|
175
|
+
onUpdateData: updateData,
|
|
176
|
+
onDeleteData: deleteData,
|
|
177
|
+
})
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return (
|
|
181
|
+
<TableColumn
|
|
182
|
+
v-slots={slot}
|
|
183
|
+
ellipsis={true}
|
|
184
|
+
{...(omit(column, [
|
|
185
|
+
'cellRender',
|
|
186
|
+
'form',
|
|
187
|
+
'hidden',
|
|
188
|
+
'children',
|
|
189
|
+
'titleRender',
|
|
190
|
+
]) as any)}
|
|
191
|
+
key={column.dataIndex ?? Date.now()}
|
|
192
|
+
>
|
|
193
|
+
{column.children && RenderColumns(column.children)}
|
|
194
|
+
</TableColumn>
|
|
195
|
+
)
|
|
196
|
+
})
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
onMounted(() => {
|
|
200
|
+
if (config?.value) {
|
|
201
|
+
if (!config.value.batchDelete)
|
|
202
|
+
delete (TABLE_BASE_CONFIG as any).rowSelection
|
|
203
|
+
config.value.table = {
|
|
204
|
+
...TABLE_BASE_CONFIG,
|
|
205
|
+
...config.value.table,
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// emit("get");
|
|
209
|
+
// setTimeout(() => resize());
|
|
210
|
+
// window.addEventListener("resize", resize);
|
|
211
|
+
})
|
|
212
|
+
// onUnmounted(() => {
|
|
213
|
+
// // window.removeEventListener("resize", resize);
|
|
214
|
+
// });
|
|
215
|
+
|
|
216
|
+
return () => {
|
|
217
|
+
// console.log("render");
|
|
218
|
+
return (
|
|
219
|
+
<div
|
|
220
|
+
style={{
|
|
221
|
+
flex: 1,
|
|
222
|
+
overflow: 'hidden',
|
|
223
|
+
}}
|
|
224
|
+
>
|
|
225
|
+
<Table
|
|
226
|
+
// 无实际意义,仅为激活表格的flex布局,请勿更改!!!
|
|
227
|
+
scroll={{
|
|
228
|
+
y: 100,
|
|
229
|
+
}}
|
|
230
|
+
{...omit(config.value?.table, 'v-slots')}
|
|
231
|
+
class='v-table-content'
|
|
232
|
+
onPageChange={pageChange}
|
|
233
|
+
onPageSizeChange={pageSizeChange}
|
|
234
|
+
//@ts-ignore
|
|
235
|
+
onSelectionChange={selectionChange}
|
|
236
|
+
ref={tableRef}
|
|
237
|
+
v-slots={{
|
|
238
|
+
...(config.value?.table?.['v-slots'] || {}),
|
|
239
|
+
columns: () =>
|
|
240
|
+
RenderColumns(
|
|
241
|
+
columns.value?.filter((item) => !item.hidden) || []
|
|
242
|
+
),
|
|
243
|
+
}}
|
|
244
|
+
></Table>
|
|
245
|
+
{operationsRender.value && (
|
|
246
|
+
<ModalForm
|
|
247
|
+
{...config.value?.table}
|
|
248
|
+
ref={modalForm}
|
|
249
|
+
title='编辑'
|
|
250
|
+
onUpdate:visible={(v:any) => (visible.value = v)}
|
|
251
|
+
visible={visible.value}
|
|
252
|
+
type='Update'
|
|
253
|
+
renderParams={renderParams.value}
|
|
254
|
+
onOkEvent={(data:any) => emit('update', data)}
|
|
255
|
+
/>
|
|
256
|
+
)}
|
|
257
|
+
</div>
|
|
258
|
+
)
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
})
|
|
262
|
+
</script>
|
|
263
|
+
|
|
264
|
+
<style lang="less">
|
|
265
|
+
.v-table-content {
|
|
266
|
+
height: 100%;
|
|
267
|
+
.arco-spin {
|
|
268
|
+
overflow: hidden;
|
|
269
|
+
.arco-table-container {
|
|
270
|
+
flex: 1;
|
|
271
|
+
min-height: 0;
|
|
272
|
+
.arco-table-content {
|
|
273
|
+
overflow: hidden;
|
|
274
|
+
.arco-table-body {
|
|
275
|
+
flex: 1;
|
|
276
|
+
min-height: 0;
|
|
277
|
+
max-height: 100% !important;
|
|
278
|
+
height: 0;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// .arco-table-body {
|
|
284
|
+
// // height: var(--v-table-height);
|
|
285
|
+
// }
|
|
286
|
+
}
|
|
287
|
+
</style>
|
|
288
|
+
|
|
289
|
+
<style lang="less" scoped>
|
|
290
|
+
.v-table-content {
|
|
291
|
+
:deep(.arco-table-pagination) {
|
|
292
|
+
margin-top: 16px;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
</style>
|