feat: table组件支持排序

This commit is contained in:
xuqingkai 2023-10-28 18:15:14 +08:00
parent 68affd2f59
commit 9898b01c06
7 changed files with 220 additions and 1520 deletions

File diff suppressed because it is too large Load Diff

View File

@ -796,3 +796,6 @@ $-navbar-capsule-border-color: var(--wot-navbar-capsule-border-color, #e7e7e7);
$-navbar-capsule-border-radius: var(--wot-navbar-capsule-border-radius, 16px);
$-navbar-capsule-width: var(--wot-navbar-capsule-width, 88px);
$-navbar-capsule-height: var(--wot-navbar-capsule-height, 32px);
// table
$-table-color: var(--wot-table-color, $-font-gray-1);

View File

@ -24,7 +24,7 @@ export default {
}
</script>
<script lang="ts" setup>
import { type CSSProperties, computed, inject, onMounted, ref, watch, getCurrentInstance, reactive } from 'vue'
import { type CSSProperties, computed, inject, onMounted, ref, watch, getCurrentInstance } from 'vue'
import { isDef, objToStyle } from '../common/util'
interface Props {

View File

@ -1,6 +1,6 @@
type AlignType = 'left' | 'center' | 'right' // 列的对齐方式
type SortDirection = 'asc' | 'desc' // 列的排序方向
export type SortDirection = 0 | 1 | -1 // 列的排序方向
export interface TableColumn {
// 列对应字段
@ -16,5 +16,5 @@ export interface TableColumn {
// 列的对齐方式可选值left,center,right
align?: AlignType
// 列的排序方向
sortDirection?: SortDirection | ''
sortDirection: SortDirection
}

View File

@ -8,7 +8,7 @@
@click="handleRowClick(index)"
>
<slot v-if="$slots.default" :row="scope(index)"></slot>
<view class="cell" v-else>{{ row }}</view>
<text :class="`wd-table__value ${ellipsis ? 'is-ellipsis' : ''}`" v-else>{{ row }}</text>
</view>
</view>
</template>
@ -24,7 +24,7 @@ export default {
}
</script>
<script lang="ts" setup>
import { Ref, computed, inject, onMounted, ref } from 'vue'
import { type CSSProperties, computed, inject, onMounted } from 'vue'
import { addUnit, isDef, objToStyle, isOdd } from '../common/util'
type AlignType = 'left' | 'center' | 'right'
@ -51,29 +51,29 @@ const props = withDefaults(defineProps<Props>(), {
align: 'left'
})
// eslint-disable-next-line @typescript-eslint/ban-types
const setColumns: Function = inject('setColumns') as Function // .
// eslint-disable-next-line @typescript-eslint/ban-types
const setRowClick: Function = inject('setRowClick') as Function
const $props = inject<Ref>('$props') || ref({}) // table
const parent = inject<any>('wdTable', { data: [] }) // table
//
const stripe = computed(() => {
return $props.value.stripe || false
return parent.stripe || false
})
/**
* 是否有边框
*/
const border = computed(() => {
return $props.value.border || false
return parent.border || false
})
const ellipsis = computed(() => {
return parent.ellipsis || false
})
/**
* 根节点样式
*/
const rootStyle = computed(() => {
const style: Record<string, string | number> = {}
const style: CSSProperties = {}
if (isDef(props.width)) {
// widthpxpx
style['width'] = addUnit(props.width)
@ -83,8 +83,8 @@ const rootStyle = computed(() => {
})
const rowStyle = computed(() => {
const rowHeight: string | number = $props.value.rowHeight || '80rpx' //
const style: Record<string, string | number> = {}
const rowHeight: string | number = parent.rowHeight || '80rpx' //
const style: CSSProperties = {}
if (isDef(props.width)) {
// widthpxpx
style['width'] = addUnit(props.width)
@ -93,37 +93,40 @@ const rowStyle = computed(() => {
// widthpxpx
style['height'] = addUnit(rowHeight)
}
return objToStyle(style)
})
//
const scope = computed(() => {
return (index: number) => {
return $props.value.data[index] || {}
return parent.data[index] || {}
}
})
//
const column = computed(() => {
let column: any[] = $props.value.data.map((item) => {
let column: any[] = parent.data.map((item) => {
return item[props.prop]
})
return column
})
onMounted(() => {
setColumns({
parent.setColumns &&
parent.setColumns({
prop: props.prop,
label: props.label,
width: props.width,
sortable: props.sortable,
lightHigh: props.lightHigh,
sortDirection: 0,
align: props.align
})
})
function handleRowClick(index: number) {
setRowClick(index)
parent.setRowClick && parent.setRowClick(index)
}
</script>

View File

@ -55,7 +55,6 @@
width: 100%;
height: 48px;
display: flex;
pointer-events: none;
overflow-x: auto;
white-space: nowrap;
}
@ -66,13 +65,15 @@
}
@include e(cell) {
flex: 0 0 auto;
width: 220rpx;
display: flex;
align-items: center;
box-sizing: border-box;
padding: 10px;
flex: 0 0 auto;
width: 220rpx;
min-height: 50px;
padding: 8px 10px;
font-size: 13px;
color: $-table-color;
@include when(border) {
border-right: 1px solid #ececec;
@ -82,6 +83,24 @@
@include when(stripe) {
background: #f3f3f3;
}
@include when(left) {
justify-content: flex-start;
}
@include when(center) {
justify-content: center;
}
@include when(right) {
justify-content: flex-end;
}
}
@include e(value) {
@include when(ellipsis) {
@include multiEllipsis(2);
}
}
}

View File

@ -1,32 +1,48 @@
<template>
<view :class="`wd-table-content ${border ? 'is-border' : ''}`">
<view :class="`wd-table--fixed ${isShadow ? 'is-shadow' : ''}`" :style="fixedStyle">
<view :class="`wd-table--fixed ${isShadow ? 'is-shadow' : ''}`" :style="fixedStyle" v-if="$slots.fixed">
<view class="wd-table__header" v-if="showHeader">
<view
:class="`wd-table__cell ${border ? 'is-border' : ''} ${stripe ? 'is-stripe' : ''}`"
:class="`wd-table__cell ${border ? 'is-border' : ''} ${stripe ? 'is-stripe' : ''} is-${column.align}`"
:style="headerCellStyle(column.width)"
v-for="(column, index) in columns"
:key="index"
>
<text>{{ column.label }}</text>
<wd-sort-button
v-model="column.sortDirection"
allow-reset
:line="false"
:title="column.label"
@change="({ value }) => handleSortChange(value, index)"
v-if="column.sortable"
/>
<text v-else :class="`wd-table__value ${ellipsis ? 'is-ellipsis' : ''}`">{{ column.label }}</text>
</view>
</view>
<scroll-view class="wd-table__body" :style="fixedBodyStyle" :enable-flex="true" :scroll-y="true" :scroll-top="scrollTop">
<scroll-view class="wd-table__body" :style="fixedBodyStyle" :enable-flex="true" :throttle="false" :scroll-y="true" :scroll-top="scrollTop">
<view style="display: inline-flex" id="fixed-body">
<slot name="fixed"></slot>
</view>
</scroll-view>
</view>
<scroll-view :class="`wd-table is-border`" :style="wraperStyle" :scroll-x="true" :throttle="false" @scroll="handleWraperScroll">
<scroll-view class="wd-table" :style="wraperStyle" :scroll-x="true" :throttle="false" @scroll="handleWraperScroll">
<view class="wd-table__header" id="table-header" :style="rowStyle" v-if="showHeader">
<view
:class="`wd-table__cell ${border ? 'is-border' : ''} ${stripe ? 'is-stripe' : ''}`"
:class="`wd-table__cell ${border ? 'is-border' : ''} ${stripe ? 'is-stripe' : ''} is-${column.align}`"
:style="headerCellStyle(column.width)"
v-for="(column, index) in columns"
:key="index"
>
<text>{{ column.label }}</text>
<wd-sort-button
v-model="column.sortDirection"
allow-reset
:line="false"
:title="column.label"
@change="({ value }) => handleSortChange(value, index)"
v-if="column.sortable"
/>
<text v-else :class="`wd-table__value ${ellipsis ? 'is-ellipsis' : ''}`">{{ column.label }}</text>
</view>
</view>
<scroll-view class="wd-table__body" :style="bodyStyle" :enable-flex="true" :throttle="false" :scroll-y="true" @scroll="handleBodyScroll">
@ -51,9 +67,11 @@ export default {
</script>
<script lang="ts" setup>
import { type CSSProperties, computed, getCurrentInstance, nextTick, onMounted, provide, ref, watch } from 'vue'
import { type CSSProperties, computed, getCurrentInstance, nextTick, onMounted, provide, ref, watch, reactive } from 'vue'
import { addUnit, deepClone, getRect, isDef, objToStyle } from '../common/util'
import type { TableColumn } from '../wd-table-col/types'
import type { SortDirection, TableColumn } from '../wd-table-col/types'
const a = ref(0)
interface Props {
//
@ -68,6 +86,8 @@ interface Props {
rowHeight?: number | string
//
showHeader?: boolean
// 2
ellipsis?: boolean
}
const props = withDefaults(defineProps<Props>(), {
@ -79,16 +99,18 @@ const props = withDefaults(defineProps<Props>(), {
// table
height: '80vh',
//
rowHeight: '48px',
rowHeight: 50,
//
showHeader: true
showHeader: true,
// 2
ellipsis: true
})
// privide$dataSource
watch(
props,
() => {
$props.value = props
() => props.data,
(newValue) => {
parentData.data = newValue
},
{ deep: true }
)
@ -96,23 +118,25 @@ watch(
const scrollTop = ref<number>(0) // scroll-view
const scrollWidth = ref<number | string>('auto') // scroll-viewsticky
const columns = ref<TableColumn[]>([]) //
const $props = ref<Props>(props)
const fixedWidth = ref<number | string>(0) //
const isShadow = ref<boolean>(false) // shadow
const emit = defineEmits(['click', 'sort-method', 'row-click'])
/**
* 根节点样式
*/
const rootStyle = computed(() => {
const style: CSSProperties = {}
if (isDef(props.height)) {
style['height'] = addUnit(props.height)
}
return objToStyle(style)
const parentData = reactive({
data: props.data,
stripe: props.stripe,
border: props.border,
height: props.height,
rowHeight: props.rowHeight,
showHeader: props.showHeader,
ellipsis: props.ellipsis,
setRowClick,
setColumns
})
provide('wdTable', parentData)
const emit = defineEmits(['click', 'sort-method', 'row-click'])
/**
* 容器样式
*/
@ -145,7 +169,7 @@ const rowStyle = computed(() => {
return objToStyle(style)
})
const headerHeight = ref<string | number>(48) // header
const headerHeight = ref<string | number>(50) // header
const fixedBodyStyle = computed(() => {
const style: CSSProperties = {}
@ -193,31 +217,23 @@ function setColumns(column: TableColumn) {
* 表头单元格样式
*/
function headerCellStyle(width?: string | number) {
const style: Record<string, string | number> = {}
const style: CSSProperties = {}
if (isDef(width)) {
style['width'] = addUnit(width)
}
return objToStyle(style)
}
/**
* 排序事件
*/
function doSort(column, index) {
if (column.sortDirection === 'asc') {
columns.value[index].sortDirection = 'desc'
} else if (columns.value[index].sortDirection === 'desc') {
columns.value[index].sortDirection = ''
} else {
columns.value[index].sortDirection = 'asc'
}
function handleSortChange(value: SortDirection, index: number) {
columns.value[index].sortDirection = value
columns.value.forEach((col, i) => {
if (index != i) {
col.sortDirection = ''
col.sortDirection = 0
}
})
emit('sort-method', columns.value[index])
}
/**
* 滚动事件
*/
@ -245,11 +261,30 @@ function handleWraperScroll(event) {
function setRowClick(index: number) {
emit('row-click', { rowIndex: index })
}
provide('$props', $props) // provide
provide('setRowClick', setRowClick)
provide('setColumns', setColumns)
</script>
<!-- <script module="touch" lang="wxs">
function touchstart(event, ins) {
console.log(event);
console.log(ins);
}
function touchend(event, ins) {
console.log(event);
console.log(ins);
}
function transitionend(event, ins) {
console.log(event);
console.log(ins);
}
module.exports= {
touchstart,
touchend,
transitionend
}
</script> -->
<style lang="scss" scoped>
@import './index.scss';