123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489 |
- import {computed, nextTick, reactive, Ref, ref, watch, onMounted} from 'vue'
- import type {VxePagerProps, VxeTableProps} from "vxe-table";
- import {VxePager, VxeTable, VxeColumn} from "vxe-table";
- import {TablePublicMethods, VxeTableEventProps} from "vxe-table/types/table";
- import XEUtils from "xe-utils";
- import {stringIsBlank, stringNotBlank} from "@/utils/blank-utils";
- import {TableExportMethods} from "vxe-table/types/export";
- import {BizException, ExceptionEnum} from "@/utils/BizException";
- import {eachAndReturnList} from "@/utils/cyRefList";
- import {ElButton, ElPopover} from "element-plus";
- import setDialogToJs from "@/components/js-dialog-comp/useDialogToJs";
- import CyDialog from "@/components/cy/dialog/src/CyDialog.vue";
- import {IsCyDialog} from "@/components/cy/dialog/src/useCyDialog";
- import CyFlex from "@/components/cy/flex/src/CyFlex.vue";
- declare type PageQuery = {
- currentPage?: number,
- pageSize?: number,
- }
- declare type SimplifiedConfiguration<D> = {
- rowHeight?: number,
- keyField?: string,
- currentKey?: string | number,
- remoteSearch?: (data?: PageQuery & any) => Promise<D[]>,
- tableProps?: VxeTableEventProps<D> & VxeTableProps<D>,
- showPage?: boolean,
- result?: string,
- total?: string,
- pagesProps?: VxePagerProps,
- showCheckbox?: boolean,
- mountedQuery?: boolean,
- dialogProps?: IsCyDialog,
- dialogHeader?: () => any
- }
- function tsxVModel(modelValue: object, name: string, modelName?: string) {
- const updateName = modelName || name
- return {
- // @ts-ignore
- [updateName]: modelValue[name],
- ['onUpdate:' + updateName]: (el: any) => {
- // @ts-ignore
- modelValue[name] = el
- }
- }
- }
- function useVxeTable<D = any>(simplifiedConfiguration: SimplifiedConfiguration<D>) {
- const tableRef: Ref<TablePublicMethods<D> & TableExportMethods<D> | undefined> = ref()
- const props: VxeTableProps<D> & VxeTableEventProps<D> & SimplifiedConfiguration<D> = reactive({
- height: '100%',
- rowConfig: {
- isHover: true,
- isCurrent: true,
- height: simplifiedConfiguration?.rowHeight || 48,
- useKey: true,
- keyField: simplifiedConfiguration?.keyField || '',
- },
- scrollY: {
- enabled: true,
- gt: 0
- },
- columnConfig: {
- resizable: true
- },
- scrollX: {
- enabled: false,
- },
- exportConfig: {},
- showOverflow: true,
- currentKey: '',
- menuConfig: {
- enabled: true
- },
- loading: false,
- loadingConfig: {
- text: '加载中...',
- icon: '',
- },
- checkboxConfig: {
- reserve: true,
- highlight: true,
- range: true,
- },
- data: [],
- })
- if (simplifiedConfiguration.showPage) {
- delete props.rowConfig?.height
- props.scrollY!.enabled = false
- props!.showOverflow = false
- props!.checkboxConfig!.reserve = true
- if (stringIsBlank(props.rowConfig?.keyField)) {
- BizException(ExceptionEnum.MESSAGE_ERROR, '请先设置行id')
- }
- }
- const pageVO = reactive({
- currentPage: 1,
- pageSize: 30,
- total: 0
- })
- const pagerProps: VxePagerProps = reactive({
- loading: false,
- })
- watch(() => props.currentKey, () => {
- if (stringNotBlank(defaultProps.value.rowConfig?.keyField)) {
- const findData = XEUtils.find(tableRef.value?.getData(), (item) => {
- // @ts-ignore
- return item[defaultProps.value.rowConfig?.keyField] === props.currentKey;
- })
- if (findData) {
- tableRef.value?.scrollToRow(findData)
- tableRef.value?.setCurrentRow(findData)
- }
- }
- }, {flush: 'post'})
- const defaultProps = computed(() => {
- return {
- ...simplifiedConfiguration?.tableProps,
- ...props
- } as VxeTableProps<D>
- })
- const CyVxeTable = (props: VxeTableProps<D>, {slots}: any) => {
- mutation.setTableDefaultSlots = () => {
- return slots.default ? slots.default() : null
- }
- const TempVxeTable = () => {
- return <VxeTable
- ref={tableRef}
- {...defaultProps.value}
- {...props}
- >
- {{
- default: () => {
- function renderIcon(checked: boolean, indeterminate: boolean) {
- if (indeterminate) {
- return <i class="vxe-icon-square-minus-fill"></i>
- } else if (checked) {
- return <i class="vxe-icon-square-checked-fill"></i>
- } else {
- return <i class="vxe-icon-checkbox-unchecked"></i>
- }
- }
- function checkboxHeader(checked: boolean, indeterminate: boolean) {
- return <ElPopover placement="right">
- {{
- default: () => {
- return [
- `当前选中${pageMemory.size}条`,
- <div style="text-align: right;margin-top: 5px;">
- <ElButton
- type="primary"
- onClick={(el) => {
- if (pageMemory.size > 0)
- handelLookCheckBox()
- }}
- >{{default: () => '详情'}}
- </ElButton>
- <ElButton
- type="danger"
- onClick={(el) => {
- mutation.clearCheckboxRow()
- }}
- >{{default: () => '清空'}}
- </ElButton>
- </div>
- ]
- },
- reference: () => {
- return <span
- style={"font-size: 1.1em;cursor: pointer;"}
- onClick={(el) => {
- el.preventDefault()
- el.stopPropagation()
- handelCheckboxAll()
- }}>{renderIcon(checked, indeterminate)}</span>
- }
- }}
- </ElPopover>
- }
- return [
- simplifiedConfiguration.showCheckbox ?
- <VxeColumn type="checkbox" width={"max-content"}>
- {{
- // @ts-ignore
- header({checked, indeterminate}) {
- return checkboxHeader(checked, indeterminate)
- },
- // @ts-ignore
- checkbox({row, checked, indeterminate}) {
- return <span style={"font-size: 1.1em;cursor: pointer;"}
- onClick={(el) => {
- el.preventDefault()
- el.stopPropagation()
- handelCheckboxChange({row, checked: !checked})
- }}>
- {renderIcon(checked, indeterminate)}
- </span>
- }
- }}
- </VxeColumn> : null,
- ...slots.default ? slots.default() : null,
- ];
- }
- }}
- </VxeTable>
- }
- if (simplifiedConfiguration.showPage) {
- return <div class="cy_display_flex_y">
- <div class="cy_flex_1-y">
- <TempVxeTable/>
- </div>
- <div style="height:max-content">
- <VxePager
- onPageChange={(data) => {
- pageChange()
- }}
- size={"small"}
- {...tsxVModel(pageVO, 'currentPage')}
- {...tsxVModel(pageVO, 'pageSize')}
- total={pageVO.total}
- {...simplifiedConfiguration.pagesProps}
- {...pagerProps}
- />
- </div>
- </div>
- } else {
- return <TempVxeTable/>
- }
- }
- function exportExcel(filename: string = '', sheetName: string = 'sheet1') {
- if (!XEUtils.isString(filename)) {
- filename = ''
- }
- tableRef.value?.openExport({
- filename,
- sheetName,
- types: ['xlsx', 'csv', 'html', 'xml', 'txt'],
- type: 'xlsx',
- useStyle: true,
- original: true,
- })
- }
- let queryParamsCache = {}
- function pageChange() {
- if (XEUtils.isEmpty(queryParamsCache)) {
- return
- }
- const data = {
- ...queryParamsCache,
- ...pageVO
- }
- props.loading = true
- pageQuery(data, false)
- }
- function pageQuery(data: any, clearCurrentPage: boolean = true) {
- pagerProps.loading = true
- // @ts-ignore
- simplifiedConfiguration.remoteSearch(data).then(res => {
- // @ts-ignore
- const data: D[] = XEUtils.get(res, simplifiedConfiguration!.result || 'result') as D[]
- // @ts-ignore
- const total: number = XEUtils.get(res, simplifiedConfiguration!.total || 'total') as number
- props.data = data
- pageVO.total = total
- }).catch((e) => {
- props.data = []
- pageVO.total = 0
- console.error(e)
- }).finally(() => {
- if (clearCurrentPage) {
- pageVO.currentPage = 1
- pageMemory.clear()
- }
- props.loading = false
- pagerProps.loading = false
- handelPageCheckBox()
- })
- }
- const pageMemory = reactive(new Map<any, D>());
- function getCheckboxRecords() {
- // @ts-ignore
- return eachAndReturnList(pageMemory, (item) => {
- return item
- })
- }
- function handelCheckbox() {
- const data = tableRef.value!.getCheckboxRecords()
- if (data.length > 0) {
- XEUtils.arrayEach(tableRef.value!.getCheckboxRecords(), (item) => {
- // @ts-ignore
- pageMemory.set(item[simplifiedConfiguration.keyField], item)
- })
- } else {
- XEUtils.arrayEach(tableRef.value!.getData(), (item) => {
- // @ts-ignore
- pageMemory.delete(item[simplifiedConfiguration.keyField])
- })
- }
- }
- function handelPageCheckBox() {
- nextTick().then(() => {
- // @ts-ignore
- XEUtils.arrayEach(pageMemory, (item) => {
- tableRef.value?.setCheckboxRow(item, true)
- })
- })
- }
- function handelCheckboxChange({row, checked}: { row: any, checked: boolean }) {
- mutation.setCheckboxRow(row, checked)
- }
- async function handelCheckboxAll() {
- await tableRef.value?.toggleAllCheckboxRow()
- nextTick().then(() => {
- handelCheckbox()
- })
- }
- function querySearch() {
- props.loading = true
- // @ts-ignore
- if (simplifiedConfiguration.showPage) {
- const pageData = {
- ...pageVO,
- total: 0,
- currentPage: 1
- }
- queryParamsCache = pageData
- pageQuery(pageData)
- } else {
- // @ts-ignore
- simplifiedConfiguration.remoteSearch({...pageVO}).then(res => {
- props.data = res
- }).catch(() => {
- props.data = []
- }).finally(() => {
- props.loading = false
- })
- }
- }
- function handelLookCheckBox() {
- const dialog = (
- <CyDialog title="选中详情"
- ignore-error
- body-width="70%"
- {...simplifiedConfiguration.dialogProps}>
- {{
- default: () => {
- const data = getCheckboxRecords()
- return <CyFlex>
- {{
- header: () => {
- try {
- if (simplifiedConfiguration.dialogHeader) {
- const Scc = simplifiedConfiguration?.dialogHeader();
- if (typeof Scc !== 'undefined') {
- return <Scc/>
- } else {
- console.error('dialogHeader需要返回一个组件')
- }
- }
- } catch (e) {
- console.error('dialogHeader需要返回一个组件', e)
- return null
- }
- },
- default: () => {
- return <VxeTable data={data}
- rowConfig={{
- keyField: simplifiedConfiguration.keyField,
- isCurrent: true,
- isHover: true,
- useKey: true,
- }}
- scrollY={{enabled: true, gt: 100}}
- showOverflow={data.length > 100}
- height={"100%"}>
- {{
- default: () => {
- return [
- <VxeColumn title={"删除"} width={80} fixed="left">
- {{
- default({row}: any) {
- return <ElButton
- type="danger"
- onClick={(el) => {
- handelCheckboxChange({row, checked: false})
- }}
- >{{default: () => '删除'}}
- </ElButton>
- }
- }}
- </VxeColumn>,
- mutation.setTableDefaultSlots()
- ]
- }
- }}
- </VxeTable>
- }
- }}
- </CyFlex>
- }
- }}
- </CyDialog>
- )
- setDialogToJs(dialog, null).then(() => {
- })
- }
- const mutation = {
- updateByIndex: function updateByIndex(data: D | any, index: number) {
- const tableData = tableRef.value?.getData()
- // @ts-ignore
- tableData[index] = data
- // @ts-ignore
- tableRef.value?.loadData(tableData)
- },
- setCheckboxRow: async function (row: D, checked: boolean) {
- await tableRef.value?.setCheckboxRow(row, checked)
- // @ts-ignore
- const key = XEUtils.get(row, simplifiedConfiguration!.keyField, null) as string | null
- if (key === null) return
- if (checked) {
- pageMemory.set(key, row)
- } else {
- pageMemory.delete(key)
- }
- },
- clearCheckboxRow() {
- tableRef.value?.clearCheckboxRow()
- pageMemory.clear()
- },
- setTableDefaultSlots(): any {
- }
- }
- onMounted(() => {
- if (simplifiedConfiguration.mountedQuery) {
- nextTick().then(() => {
- querySearch()
- })
- }
- })
- return {
- tableRef,
- CyVxeTable: CyVxeTable,
- tableProps: props,
- exportExcel,
- mutation,
- querySearch,
- getCheckboxRecords
- }
- }
- export default useVxeTable
|