|
|
|
@ -1,6 +1,13 @@
|
|
|
|
<script lang="tsx">
|
|
|
|
<script lang="tsx">
|
|
|
|
import { ElTable, ElTableColumn, ElPagination, ComponentSize, ElTooltipProps } from 'element-plus'
|
|
|
|
import {
|
|
|
|
import { defineComponent, PropType, ref, computed, unref, watch, onMounted } from 'vue'
|
|
|
|
ElTable,
|
|
|
|
|
|
|
|
ElTableColumn,
|
|
|
|
|
|
|
|
ElPagination,
|
|
|
|
|
|
|
|
ComponentSize,
|
|
|
|
|
|
|
|
ElTooltipProps,
|
|
|
|
|
|
|
|
ElImage
|
|
|
|
|
|
|
|
} from 'element-plus'
|
|
|
|
|
|
|
|
import { defineComponent, PropType, ref, computed, unref, watch, onMounted, nextTick } from 'vue'
|
|
|
|
import { propTypes } from '@/utils/propTypes'
|
|
|
|
import { propTypes } from '@/utils/propTypes'
|
|
|
|
import { setIndex } from './helper'
|
|
|
|
import { setIndex } from './helper'
|
|
|
|
import type { TableProps, TableColumn, Pagination, TableSetProps } from './types'
|
|
|
|
import type { TableProps, TableColumn, Pagination, TableSetProps } from './types'
|
|
|
|
@ -8,6 +15,8 @@ import { set } from 'lodash-es'
|
|
|
|
import { CSSProperties } from 'vue'
|
|
|
|
import { CSSProperties } from 'vue'
|
|
|
|
import { getSlot } from '@/utils/tsxHelper'
|
|
|
|
import { getSlot } from '@/utils/tsxHelper'
|
|
|
|
import TableActions from './components/TableActions.vue'
|
|
|
|
import TableActions from './components/TableActions.vue'
|
|
|
|
|
|
|
|
import Sortable from 'sortablejs'
|
|
|
|
|
|
|
|
import { Icon } from '@/components/Icon'
|
|
|
|
|
|
|
|
|
|
|
|
export default defineComponent({
|
|
|
|
export default defineComponent({
|
|
|
|
name: 'Table',
|
|
|
|
name: 'Table',
|
|
|
|
@ -48,6 +57,12 @@ export default defineComponent({
|
|
|
|
type: Array as PropType<Recordable[]>,
|
|
|
|
type: Array as PropType<Recordable[]>,
|
|
|
|
default: () => []
|
|
|
|
default: () => []
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
// 是否自动预览
|
|
|
|
|
|
|
|
preview: {
|
|
|
|
|
|
|
|
type: Array as PropType<string[]>,
|
|
|
|
|
|
|
|
default: () => []
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
sortable: propTypes.bool.def(false),
|
|
|
|
height: propTypes.oneOfType([Number, String]),
|
|
|
|
height: propTypes.oneOfType([Number, String]),
|
|
|
|
maxHeight: propTypes.oneOfType([Number, String]),
|
|
|
|
maxHeight: propTypes.oneOfType([Number, String]),
|
|
|
|
stripe: propTypes.bool.def(false),
|
|
|
|
stripe: propTypes.bool.def(false),
|
|
|
|
@ -173,7 +188,7 @@ export default defineComponent({
|
|
|
|
scrollbarAlwaysOn: propTypes.bool.def(false),
|
|
|
|
scrollbarAlwaysOn: propTypes.bool.def(false),
|
|
|
|
flexible: propTypes.bool.def(false)
|
|
|
|
flexible: propTypes.bool.def(false)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
emits: ['update:pageSize', 'update:currentPage', 'register', 'refresh'],
|
|
|
|
emits: ['update:pageSize', 'update:currentPage', 'register', 'refresh', 'sortable-change'],
|
|
|
|
setup(props, { attrs, emit, slots, expose }) {
|
|
|
|
setup(props, { attrs, emit, slots, expose }) {
|
|
|
|
const elTableRef = ref<ComponentRef<typeof ElTable>>()
|
|
|
|
const elTableRef = ref<ComponentRef<typeof ElTable>>()
|
|
|
|
|
|
|
|
|
|
|
|
@ -198,6 +213,33 @@ export default defineComponent({
|
|
|
|
return propsObj
|
|
|
|
return propsObj
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const sortableEl = ref()
|
|
|
|
|
|
|
|
// 初始化拖拽
|
|
|
|
|
|
|
|
const initDropTable = () => {
|
|
|
|
|
|
|
|
const el = unref(elTableRef)?.$el.querySelector('.el-table__body tbody')
|
|
|
|
|
|
|
|
if (!el) return
|
|
|
|
|
|
|
|
if (unref(sortableEl)) unref(sortableEl).destroy()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sortableEl.value = Sortable.create(el, {
|
|
|
|
|
|
|
|
handle: '.table-move',
|
|
|
|
|
|
|
|
animation: 180,
|
|
|
|
|
|
|
|
onEnd(e: any) {
|
|
|
|
|
|
|
|
emit('sortable-change', e)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
|
|
|
() => getProps.value.sortable,
|
|
|
|
|
|
|
|
async (v) => {
|
|
|
|
|
|
|
|
await nextTick()
|
|
|
|
|
|
|
|
v && initDropTable()
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
immediate: true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
const setProps = (props: TableProps = {}) => {
|
|
|
|
const setProps = (props: TableProps = {}) => {
|
|
|
|
mergeProps.value = Object.assign(unref(mergeProps), props)
|
|
|
|
mergeProps.value = Object.assign(unref(mergeProps), props)
|
|
|
|
outsideProps.value = { ...props } as any
|
|
|
|
outsideProps.value = { ...props } as any
|
|
|
|
@ -301,7 +343,7 @@ export default defineComponent({
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const renderTreeTableColumn = (columnsChildren: TableColumn[]) => {
|
|
|
|
const renderTreeTableColumn = (columnsChildren: TableColumn[]) => {
|
|
|
|
const { align, headerAlign, showOverflowTooltip } = unref(getProps)
|
|
|
|
const { align, headerAlign, showOverflowTooltip, preview } = unref(getProps)
|
|
|
|
return columnsChildren.map((v) => {
|
|
|
|
return columnsChildren.map((v) => {
|
|
|
|
if (v.hidden) return null
|
|
|
|
if (v.hidden) return null
|
|
|
|
const props = { ...v } as any
|
|
|
|
const props = { ...v } as any
|
|
|
|
@ -312,12 +354,20 @@ export default defineComponent({
|
|
|
|
const slots = {
|
|
|
|
const slots = {
|
|
|
|
default: (...args: any[]) => {
|
|
|
|
default: (...args: any[]) => {
|
|
|
|
const data = args[0]
|
|
|
|
const data = args[0]
|
|
|
|
|
|
|
|
let isImageUrl = false
|
|
|
|
|
|
|
|
if (preview.length) {
|
|
|
|
|
|
|
|
isImageUrl = preview.some((item) => (item as string) === v.field)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return children && children.length
|
|
|
|
return children && children.length
|
|
|
|
? renderTreeTableColumn(children)
|
|
|
|
? renderTreeTableColumn(children)
|
|
|
|
: props?.slots?.default
|
|
|
|
: props?.slots?.default
|
|
|
|
? props.slots.default(args)
|
|
|
|
? props.slots.default(args)
|
|
|
|
: v?.formatter?.(data.row, data.column, data.row[v.field], data.$index) ||
|
|
|
|
: v?.formatter
|
|
|
|
data.row[v.field]
|
|
|
|
? v?.formatter?.(data.row, data.column, data.row[v.field], data.$index)
|
|
|
|
|
|
|
|
: isImageUrl
|
|
|
|
|
|
|
|
? renderPreview(data.row[v.field])
|
|
|
|
|
|
|
|
: data.row[v.field]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (props?.slots?.header) {
|
|
|
|
if (props?.slots?.header) {
|
|
|
|
@ -338,6 +388,21 @@ export default defineComponent({
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const renderPreview = (url: string) => {
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
|
|
<div class="flex items-center">
|
|
|
|
|
|
|
|
<ElImage
|
|
|
|
|
|
|
|
src={url}
|
|
|
|
|
|
|
|
fit="cover"
|
|
|
|
|
|
|
|
class="w-[100%] h-100px"
|
|
|
|
|
|
|
|
lazy
|
|
|
|
|
|
|
|
preview-src-list={[url]}
|
|
|
|
|
|
|
|
preview-teleported
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const renderTableColumn = (columnsChildren?: TableColumn[]) => {
|
|
|
|
const renderTableColumn = (columnsChildren?: TableColumn[]) => {
|
|
|
|
const {
|
|
|
|
const {
|
|
|
|
columns,
|
|
|
|
columns,
|
|
|
|
@ -347,7 +412,8 @@ export default defineComponent({
|
|
|
|
align,
|
|
|
|
align,
|
|
|
|
headerAlign,
|
|
|
|
headerAlign,
|
|
|
|
showOverflowTooltip,
|
|
|
|
showOverflowTooltip,
|
|
|
|
reserveSelection
|
|
|
|
reserveSelection,
|
|
|
|
|
|
|
|
preview
|
|
|
|
} = unref(getProps)
|
|
|
|
} = unref(getProps)
|
|
|
|
|
|
|
|
|
|
|
|
return (columnsChildren || columns).map((v) => {
|
|
|
|
return (columnsChildren || columns).map((v) => {
|
|
|
|
@ -384,12 +450,21 @@ export default defineComponent({
|
|
|
|
const slots = {
|
|
|
|
const slots = {
|
|
|
|
default: (...args: any[]) => {
|
|
|
|
default: (...args: any[]) => {
|
|
|
|
const data = args[0]
|
|
|
|
const data = args[0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let isImageUrl = false
|
|
|
|
|
|
|
|
if (preview.length) {
|
|
|
|
|
|
|
|
isImageUrl = preview.some((item) => (item as string) === v.field)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return children && children.length
|
|
|
|
return children && children.length
|
|
|
|
? renderTreeTableColumn(children)
|
|
|
|
? renderTreeTableColumn(children)
|
|
|
|
: props?.slots?.default
|
|
|
|
: props?.slots?.default
|
|
|
|
? props.slots.default(args)
|
|
|
|
? props.slots.default(args)
|
|
|
|
: v?.formatter?.(data.row, data.column, data.row[v.field], data.$index) ||
|
|
|
|
: v?.formatter
|
|
|
|
data.row[v.field]
|
|
|
|
? v?.formatter?.(data.row, data.column, data.row[v.field], data.$index)
|
|
|
|
|
|
|
|
: isImageUrl
|
|
|
|
|
|
|
|
? renderPreview(data.row[v.field])
|
|
|
|
|
|
|
|
: data.row[v.field]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (props?.slots?.header) {
|
|
|
|
if (props?.slots?.header) {
|
|
|
|
@ -419,6 +494,21 @@ export default defineComponent({
|
|
|
|
if (getSlot(slots, 'append')) {
|
|
|
|
if (getSlot(slots, 'append')) {
|
|
|
|
tableSlots['append'] = (...args: any[]) => getSlot(slots, 'append', args)
|
|
|
|
tableSlots['append'] = (...args: any[]) => getSlot(slots, 'append', args)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { sortable } = unref(getProps)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const sortableEl = sortable ? (
|
|
|
|
|
|
|
|
<ElTableColumn
|
|
|
|
|
|
|
|
className="table-move cursor-move"
|
|
|
|
|
|
|
|
type="sortable"
|
|
|
|
|
|
|
|
prop="sortable"
|
|
|
|
|
|
|
|
width="60px"
|
|
|
|
|
|
|
|
align="center"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<Icon icon="ant-design:drag-outlined" />
|
|
|
|
|
|
|
|
</ElTableColumn>
|
|
|
|
|
|
|
|
) : null
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<div v-loading={unref(getProps).loading}>
|
|
|
|
<div v-loading={unref(getProps).loading}>
|
|
|
|
{unref(getProps).showAction ? (
|
|
|
|
{unref(getProps).showAction ? (
|
|
|
|
@ -426,7 +516,7 @@ export default defineComponent({
|
|
|
|
) : null}
|
|
|
|
) : null}
|
|
|
|
<ElTable ref={elTableRef} data={unref(getProps).data} {...unref(getBindValue)}>
|
|
|
|
<ElTable ref={elTableRef} data={unref(getProps).data} {...unref(getBindValue)}>
|
|
|
|
{{
|
|
|
|
{{
|
|
|
|
default: () => renderTableColumn(),
|
|
|
|
default: () => [sortableEl, ...renderTableColumn()],
|
|
|
|
...tableSlots
|
|
|
|
...tableSlots
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
</ElTable>
|
|
|
|
</ElTable>
|
|
|
|
|