| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- <script setup lang="ts">
- import { ref, defineProps, withDefaults, defineEmits, watch, onBeforeUnmount } from "vue"
- import type { Sort, Header } from "@/components/Table/table-partials/models"
- import TableHeadRow from "@/components/Table/table-partials/table-content/table-head/TableHeadRow.vue"
- import TableBodyRow from "@/components/Table/table-partials/table-content/table-body/TableBodyRow.vue"
- const props = withDefaults(
- defineProps<{
- table: any
- header: Array<Header>
- data: Array<any>
- selectedItems: Array<any>
- fixedNumber: number
- hasCheckbox?: boolean //是否有选择框
- checkboxField?: string //选择框字段
- checkMultiple?: boolean //是否多选
- multiplePageCheck?: boolean //跨页多选
- sortField?: string //排序字段
- sortOrder?: "asc" | "desc"
- tableBoxClass?: string
- tableClass?: string
- headerClass?: string
- bodyClass?: string
- thTrClass?: string
- tdTrClass?: string
- rowSpanSuffix?: string //rowsapn 的字段后缀 后台应该组成 `${字段}${后缀}`
- }>(),
- {
- hasCheckbox: true,
- checkMultiple: false,
- multiplePageCheck: false,
- checkboxField: "",
- sortOrder: "asc",
- tableBoxClass: "bg-white",
- rowSpanSuffix: "_rowSpan",
- }
- )
- const emits = defineEmits<{
- (e: "on-sort", v: Sort): void
- (e: "on-select-all", v: any): void
- (e: "update:selectedItems", v: Array<any>): void
- (e: "on-sort", v: Sort): void
- (e: "on-change", isChecked: boolean, v: any, row: any): void
- (e: "on-items-all-change", isChecked: boolean, rows: Array<any>): void
- }>()
- const fixedNum = ref(props.hasCheckbox ? props.fixedNumber + 1 : props.fixedNumber)
- const tableBox = ref()
- const selectedItems = ref(props.selectedItems)
- const allSelectedItems = ref<Array<unknown>>([])
- const check = ref<boolean>(false)
- const onSelectAll = (checked: any) => {
- check.value = checked
- if (checked) {
- selectedItems.value = [...new Set([...selectedItems.value, ...allSelectedItems.value])]
- } else {
- selectedItems.value = []
- }
- emits("on-select-all", check.value)
- }
- const onSelectItemsChange = (isChecked: boolean, v: any, row: any) => {
- emits("update:selectedItems", v)
- selectedItems.value = []
- v.forEach((item: any) => {
- if (!selectedItems.value.includes(item)) selectedItems.value.push(item)
- })
- check.value =
- Array.from(new Set([...selectedItems.value, ...allSelectedItems.value])).length ==
- Array.from(new Set([...selectedItems.value])).length
- emits("on-change", isChecked, v, row)
- }
- const onSort = (v: Sort) => {
- emits("on-sort", v)
- }
- function onScroll() {
- tableBox.value.className = tableBox.value.className.replace("no-shadow", "")
- if (props.table.parentElement) {
- const left = props.table.parentElement.scrollLeft
- if (left == 0) {
- tableBox.value.className += " no-shadow"
- }
- }
- }
- watch(
- () => props.data,
- () => {
- selectedItems.value = props.multiplePageCheck ? selectedItems.value : []
- allSelectedItems.value = []
- check.value = false
- props.data.forEach((item: any) => {
- if (item[props.checkboxField]) {
- allSelectedItems.value.push(item[props.checkboxField])
- }
- })
- //console.log("allSelectedItems:", allSelectedItems.value)
- }
- )
- watch(
- () => props.table,
- (val: HTMLElement) => {
- const tr = val.firstElementChild?.firstElementChild
- if (tr && tr.children) {
- let width = 0
- for (let i = 0; i < fixedNum.value; i++) {
- width += tr.children[i]?.clientWidth ?? 0
- }
- tableBox.value.style.width = width + "px"
- tableBox.value.firstElementChild.style.width = val.clientWidth + "px"
- }
- if (props.table.parentElement) {
- props.table.parentElement.addEventListener("scroll", onScroll, true)
- }
- }
- )
- onBeforeUnmount(() => {
- if (props.table?.parentElement) {
- props.table.parentElement.removeEventListener("scroll", onScroll, true)
- }
- })
- </script>
- <template>
- <div class="fixed-columns no-shadow" ref="tableBox">
- <table class="table align-middle fs-6 gy-5 no-footer" :class="tableClass">
- <TableHeadRow
- @on-sort="onSort"
- @on-select-all="onSelectAll"
- :checkbox-all-value="check"
- :has-checkbox="hasCheckbox"
- :check-multiple="checkMultiple"
- :sort-field="sortField"
- :sort-order="sortOrder"
- :header="header"
- :header-class="headerClass"
- :th-tr-class="thTrClass"
- >
- <template v-for="(_, name) in $slots" #[name]="{ row: item }">
- <slot v-if="name.toString().endsWith('_header')" :name="name" :row="item" />
- </template>
- </TableHeadRow>
- <TableBodyRow
- v-if="data.length !== 0"
- @on-change="onSelectItemsChange"
- v-model:currently-selected-items="selectedItems"
- :check-multiple="checkMultiple"
- :data="data"
- :header="header"
- :has-checkbox="hasCheckbox"
- :checkbox-field="checkboxField"
- :body-class="bodyClass"
- :td-tr-class="tdTrClass"
- :row-span-suffix="rowSpanSuffix"
- >
- <template v-for="(_, name) in $slots" v-slot:[name]="{ row: item }">
- <slot v-if="!name.toString().endsWith('_header')" :name="name" :row="item" />
- </template>
- </TableBodyRow>
- </table>
- </div>
- </template>
|