mirror of
https://github.com/jekip/naive-ui-admin.git
synced 2026-02-12 09:12:28 +08:00
fix Bug or esLink formatting
This commit is contained in:
@@ -2,4 +2,3 @@ export { default as BasicTable } from './src/Table.vue';
|
||||
export { default as TableAction } from './src/components/TableAction.vue';
|
||||
export * from './src/types/table';
|
||||
export * from './src/types/tableAction';
|
||||
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
<template>
|
||||
<div class="table-toolbar">
|
||||
|
||||
<!--顶部左侧区域-->
|
||||
<div class="flex items-center table-toolbar-left ">
|
||||
<div class="flex items-center table-toolbar-left">
|
||||
<template v-if="title">
|
||||
<div class="table-toolbar-left-title">
|
||||
{{ title }}
|
||||
<n-tooltip trigger="hover" v-if="titleTooltip">
|
||||
<template #trigger>
|
||||
<n-icon size="18" class="ml-1 cursor-pointer text-gray-400">
|
||||
<QuestionCircleOutlined/>
|
||||
<QuestionCircleOutlined />
|
||||
</n-icon>
|
||||
</template>
|
||||
{{ titleTooltip }}
|
||||
@@ -20,7 +19,6 @@
|
||||
</div>
|
||||
|
||||
<div class="flex items-center table-toolbar-right">
|
||||
|
||||
<!--顶部右侧区域-->
|
||||
<slot name="toolbar"></slot>
|
||||
|
||||
@@ -29,7 +27,7 @@
|
||||
<template #trigger>
|
||||
<div class="table-toolbar-right-icon" @click="reload">
|
||||
<n-icon size="18">
|
||||
<ReloadOutlined/>
|
||||
<ReloadOutlined />
|
||||
</n-icon>
|
||||
</div>
|
||||
</template>
|
||||
@@ -40,9 +38,14 @@
|
||||
<n-tooltip trigger="hover">
|
||||
<template #trigger>
|
||||
<div class="table-toolbar-right-icon">
|
||||
<n-dropdown @select="densitySelect" trigger="click" :options="densityOptions" v-model:value="tableSize">
|
||||
<n-dropdown
|
||||
@select="densitySelect"
|
||||
trigger="click"
|
||||
:options="densityOptions"
|
||||
v-model:value="tableSize"
|
||||
>
|
||||
<n-icon size="18">
|
||||
<ColumnHeightOutlined/>
|
||||
<ColumnHeightOutlined />
|
||||
</n-icon>
|
||||
</n-dropdown>
|
||||
</div>
|
||||
@@ -51,17 +54,15 @@
|
||||
</n-tooltip>
|
||||
|
||||
<!--表格设置单独抽离成组件-->
|
||||
<ColumnSetting></ColumnSetting>
|
||||
|
||||
<ColumnSetting />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="s-table">
|
||||
<n-data-table
|
||||
v-bind="getBindValues"
|
||||
:pagination="pagination"
|
||||
@update:page="updatePage"
|
||||
@update:page-size="updatePageSize"
|
||||
v-bind="getBindValues"
|
||||
:pagination="pagination"
|
||||
@update:page="updatePage"
|
||||
@update:page-size="updatePageSize"
|
||||
>
|
||||
<template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
|
||||
<slot :name="item" v-bind="data"></slot>
|
||||
@@ -71,226 +72,212 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { NDataTable } from 'naive-ui'
|
||||
import { ref, defineComponent, reactive, unref, onMounted, toRaw, onBeforeMount, computed, toRefs, watch } from "vue"
|
||||
import { ReloadOutlined, ColumnHeightOutlined, SettingOutlined, DragOutlined, QuestionCircleOutlined } from '@vicons/antd'
|
||||
import { createTableContext } from './hooks/useTableContext';
|
||||
import { NDataTable } from 'naive-ui';
|
||||
import { ref, defineComponent, reactive, unref, toRaw, computed, toRefs } from 'vue';
|
||||
import { ReloadOutlined, ColumnHeightOutlined, QuestionCircleOutlined } from '@vicons/antd';
|
||||
import { createTableContext } from './hooks/useTableContext';
|
||||
|
||||
import ColumnSetting from './components/settings/ColumnSetting.vue'
|
||||
import ColumnSetting from './components/settings/ColumnSetting.vue';
|
||||
|
||||
import { useLoading } from './hooks/useLoading';
|
||||
import { useColumns } from './hooks/useColumns';
|
||||
import { useDataSource } from './hooks/useDataSource';
|
||||
import { usePagination } from './hooks/usePagination';
|
||||
import { useLoading } from './hooks/useLoading';
|
||||
import { useColumns } from './hooks/useColumns';
|
||||
import { useDataSource } from './hooks/useDataSource';
|
||||
import { usePagination } from './hooks/usePagination';
|
||||
|
||||
import { basicProps } from './props'
|
||||
import { basicProps } from './props';
|
||||
|
||||
import { BasicTableProps } from './types/table'
|
||||
import { BasicTableProps } from './types/table';
|
||||
|
||||
const densityOptions = [
|
||||
{
|
||||
type: 'menu',
|
||||
label: '紧凑',
|
||||
key: 'small',
|
||||
},
|
||||
{
|
||||
type: 'menu',
|
||||
label: '默认',
|
||||
key: 'medium',
|
||||
},
|
||||
{
|
||||
type: 'menu',
|
||||
label: '宽松',
|
||||
key: 'large',
|
||||
},
|
||||
];
|
||||
|
||||
const densityOptions = [
|
||||
{
|
||||
type: "menu",
|
||||
label: '紧凑',
|
||||
key: 'small',
|
||||
},
|
||||
{
|
||||
type: "menu",
|
||||
label: '默认',
|
||||
key: "medium"
|
||||
},
|
||||
{
|
||||
type: "menu",
|
||||
label: '宽松',
|
||||
key: 'large'
|
||||
}
|
||||
]
|
||||
export default defineComponent({
|
||||
components: {
|
||||
ReloadOutlined,
|
||||
ColumnHeightOutlined,
|
||||
ColumnSetting,
|
||||
QuestionCircleOutlined,
|
||||
},
|
||||
props: {
|
||||
...NDataTable.props, // 这里继承原 UI 组件的 props
|
||||
...basicProps,
|
||||
},
|
||||
emits: ['fetch-success', 'fetch-error', 'update:checked-row-keys'],
|
||||
setup(props, { emit }) {
|
||||
const wrapRef = ref<Nullable<HTMLDivElement>>(null);
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
ReloadOutlined, ColumnHeightOutlined, SettingOutlined, DragOutlined, ColumnSetting, QuestionCircleOutlined
|
||||
},
|
||||
props: {
|
||||
...NDataTable.props, // 这里继承原 UI 组件的 props
|
||||
...basicProps
|
||||
},
|
||||
emits: [
|
||||
'fetch-success',
|
||||
'fetch-error',
|
||||
'update:checked-row-keys'
|
||||
],
|
||||
setup(props, { emit }) {
|
||||
const tableData = ref<Recordable[]>([]);
|
||||
const innerPropsRef = ref<Partial<BasicTableProps>>();
|
||||
|
||||
const wrapRef = ref<Nullable<HTMLDivElement>>(null);
|
||||
const getProps = computed(() => {
|
||||
return { ...props, ...unref(innerPropsRef) } as BasicTableProps;
|
||||
});
|
||||
|
||||
const tableData = ref<Recordable[]>([]);
|
||||
const innerPropsRef = ref<Partial<BasicTableProps>>();
|
||||
const { getLoading, setLoading } = useLoading(getProps);
|
||||
|
||||
const getProps = computed(() => {
|
||||
return { ...props, ...unref(innerPropsRef) } as BasicTableProps;
|
||||
});
|
||||
const { getPaginationInfo, setPagination } = usePagination(getProps);
|
||||
|
||||
const { getLoading, setLoading } = useLoading(getProps);
|
||||
|
||||
const {
|
||||
getPaginationInfo,
|
||||
getPagination,
|
||||
setPagination,
|
||||
setShowPagination,
|
||||
getShowPagination,
|
||||
} = usePagination(getProps)
|
||||
|
||||
const { getDataSourceRef, getRowKey, getDataSource, setDataSource, reload } = useDataSource(
|
||||
getProps, {
|
||||
const { getDataSourceRef, getRowKey, reload } = useDataSource(
|
||||
getProps,
|
||||
{
|
||||
getPaginationInfo,
|
||||
setPagination,
|
||||
tableData,
|
||||
setLoading
|
||||
}, emit
|
||||
)
|
||||
setLoading,
|
||||
},
|
||||
emit
|
||||
);
|
||||
|
||||
const {
|
||||
getPageColumns,
|
||||
setColumns,
|
||||
getColumns,
|
||||
getCacheColumns,
|
||||
setCacheColumnsField,
|
||||
getColumnsRef
|
||||
} = useColumns(getProps)
|
||||
const { getPageColumns, setColumns, getColumns, getCacheColumns, setCacheColumnsField } =
|
||||
useColumns(getProps);
|
||||
|
||||
const state = reactive({
|
||||
tableSize: 'medium',
|
||||
isColumnSetting: false
|
||||
})
|
||||
const state = reactive({
|
||||
tableSize: 'medium',
|
||||
isColumnSetting: false,
|
||||
});
|
||||
|
||||
//页码切换
|
||||
function updatePage(page) {
|
||||
setPagination({ page: page, });
|
||||
reload()
|
||||
}
|
||||
|
||||
//分页数量切换
|
||||
function updatePageSize(size) {
|
||||
setPagination({ page: 1, pageSize: size, });
|
||||
reload()
|
||||
}
|
||||
|
||||
//密度切换
|
||||
function densitySelect(e) {
|
||||
state.tableSize = e
|
||||
}
|
||||
|
||||
//选中行
|
||||
function updateCheckedRowKeys(rowKeys) {
|
||||
emit('update:checked-row-keys', rowKeys)
|
||||
}
|
||||
|
||||
//重置 Columns
|
||||
const resetColumns = () => {
|
||||
columns.map(item => {
|
||||
item.isShow = true
|
||||
})
|
||||
}
|
||||
|
||||
//获取表格大小
|
||||
const getTableSize = computed(() => state.tableSize)
|
||||
|
||||
//组装表格信息
|
||||
const getBindValues = computed(() => {
|
||||
const tableData = unref(getDataSourceRef);
|
||||
let propsData = {
|
||||
...unref(getProps),
|
||||
loading: unref(getLoading),
|
||||
columns: toRaw(unref(getPageColumns)),
|
||||
rowKey: unref(getRowKey),
|
||||
data: tableData,
|
||||
size: unref(getTableSize),
|
||||
remote: true
|
||||
//页码切换
|
||||
function updatePage(page) {
|
||||
setPagination({ page: page });
|
||||
reload();
|
||||
}
|
||||
return propsData
|
||||
})
|
||||
|
||||
//获取分页信息
|
||||
const pagination = computed(() => toRaw(unref(getPaginationInfo)))
|
||||
//分页数量切换
|
||||
function updatePageSize(size) {
|
||||
setPagination({ page: 1, pageSize: size });
|
||||
reload();
|
||||
}
|
||||
|
||||
function setProps(props: Partial<BasicTableProps>) {
|
||||
innerPropsRef.value = { ...unref(innerPropsRef), ...props };
|
||||
}
|
||||
//密度切换
|
||||
function densitySelect(e) {
|
||||
state.tableSize = e;
|
||||
}
|
||||
|
||||
const tableAction: TableActionType = {
|
||||
reload,
|
||||
setColumns,
|
||||
setLoading,
|
||||
setProps,
|
||||
getColumns,
|
||||
getPageColumns,
|
||||
getCacheColumns,
|
||||
setCacheColumnsField,
|
||||
emit,
|
||||
getSize: () => {
|
||||
return unref(getBindValues).size as SizeType;
|
||||
},
|
||||
};
|
||||
//选中行
|
||||
function updateCheckedRowKeys(rowKeys) {
|
||||
emit('update:checked-row-keys', rowKeys);
|
||||
}
|
||||
|
||||
createTableContext({ ...tableAction, wrapRef, getBindValues });
|
||||
//重置 Columns
|
||||
const resetColumns = () => {
|
||||
columns.map((item) => {
|
||||
item.isShow = true;
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
getBindValues,
|
||||
densityOptions,
|
||||
reload,
|
||||
densitySelect,
|
||||
updatePage,
|
||||
updatePageSize,
|
||||
updateCheckedRowKeys,
|
||||
pagination,
|
||||
resetColumns,
|
||||
tableAction
|
||||
}
|
||||
}
|
||||
})
|
||||
//获取表格大小
|
||||
const getTableSize = computed(() => state.tableSize);
|
||||
|
||||
//组装表格信息
|
||||
const getBindValues = computed(() => {
|
||||
const tableData = unref(getDataSourceRef);
|
||||
let propsData = {
|
||||
...unref(getProps),
|
||||
loading: unref(getLoading),
|
||||
columns: toRaw(unref(getPageColumns)),
|
||||
rowKey: unref(getRowKey),
|
||||
data: tableData,
|
||||
size: unref(getTableSize),
|
||||
remote: true,
|
||||
};
|
||||
return propsData;
|
||||
});
|
||||
|
||||
//获取分页信息
|
||||
const pagination = computed(() => toRaw(unref(getPaginationInfo)));
|
||||
|
||||
function setProps(props: Partial<BasicTableProps>) {
|
||||
innerPropsRef.value = { ...unref(innerPropsRef), ...props };
|
||||
}
|
||||
|
||||
const tableAction: TableActionType = {
|
||||
reload,
|
||||
setColumns,
|
||||
setLoading,
|
||||
setProps,
|
||||
getColumns,
|
||||
getPageColumns,
|
||||
getCacheColumns,
|
||||
setCacheColumnsField,
|
||||
emit,
|
||||
getSize: () => {
|
||||
return unref(getBindValues).size as SizeType;
|
||||
},
|
||||
};
|
||||
|
||||
createTableContext({ ...tableAction, wrapRef, getBindValues });
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
getBindValues,
|
||||
densityOptions,
|
||||
reload,
|
||||
densitySelect,
|
||||
updatePage,
|
||||
updatePageSize,
|
||||
updateCheckedRowKeys,
|
||||
pagination,
|
||||
resetColumns,
|
||||
tableAction,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang='less' scoped>
|
||||
.table-toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0 0 16px 0;
|
||||
|
||||
&-left {
|
||||
<style lang="less" scoped>
|
||||
.table-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex: 1;
|
||||
justify-content: space-between;
|
||||
padding: 0 0 16px 0;
|
||||
|
||||
&-title {
|
||||
&-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
flex: 1;
|
||||
|
||||
&-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-right {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex: 1;
|
||||
&-right {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex: 1;
|
||||
|
||||
&-icon {
|
||||
margin-left: 12px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
color: var(--text-color);
|
||||
&-icon {
|
||||
margin-left: 12px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
color: var(--text-color);
|
||||
|
||||
:hover {
|
||||
color: #1890ff;
|
||||
:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-toolbar-inner-popover-title {
|
||||
padding: 2px 0;
|
||||
}
|
||||
.table-toolbar-inner-popover-title {
|
||||
padding: 2px 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -5,18 +5,17 @@
|
||||
<n-button v-bind="action" class="mx-2">{{ action.label }}</n-button>
|
||||
</template>
|
||||
<n-dropdown
|
||||
v-if="dropDownActions && getDropdownList.length"
|
||||
trigger="hover"
|
||||
:options="getDropdownList"
|
||||
@select="select"
|
||||
v-if="dropDownActions && getDropdownList.length"
|
||||
trigger="hover"
|
||||
:options="getDropdownList"
|
||||
@select="select"
|
||||
>
|
||||
<slot name="more"></slot>
|
||||
<n-button v-bind="getMoreProps" class="mx-2" v-if="!$slots.more" icon-placement="right">
|
||||
|
||||
<div class="flex items-center">
|
||||
<span>更多</span>
|
||||
<n-icon size="14" class="ml-1">
|
||||
<DownOutlined/>
|
||||
<DownOutlined />
|
||||
</n-icon>
|
||||
</div>
|
||||
<!-- <template #icon>-->
|
||||
@@ -29,64 +28,56 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, computed, toRaw } from 'vue';
|
||||
import { ActionItem } from '@/components/Table';
|
||||
import { usePermission } from '@/hooks/web/usePermission';
|
||||
import { isString, isBoolean, isFunction } from "@/utils/is";
|
||||
import { DownOutlined } from '@vicons/antd'
|
||||
import { defineComponent, PropType, computed, toRaw } from 'vue';
|
||||
import { ActionItem } from '@/components/Table';
|
||||
import { usePermission } from '@/hooks/web/usePermission';
|
||||
import { isBoolean, isFunction } from '@/utils/is';
|
||||
import { DownOutlined } from '@vicons/antd';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TableAction',
|
||||
components: { DownOutlined },
|
||||
props: {
|
||||
actions: {
|
||||
type: Array as PropType<ActionItem[]>,
|
||||
default: null,
|
||||
export default defineComponent({
|
||||
name: 'TableAction',
|
||||
components: { DownOutlined },
|
||||
props: {
|
||||
actions: {
|
||||
type: Array as PropType<ActionItem[]>,
|
||||
default: null,
|
||||
},
|
||||
dropDownActions: {
|
||||
type: Array as PropType<ActionItem[]>,
|
||||
default: null,
|
||||
},
|
||||
style: {
|
||||
type: String as PropType<String>,
|
||||
default: 'button',
|
||||
},
|
||||
select: {
|
||||
type: Function as PropType<Function>,
|
||||
default: () => {},
|
||||
},
|
||||
},
|
||||
dropDownActions: {
|
||||
type: Array as PropType<ActionItem[]>,
|
||||
default: null,
|
||||
},
|
||||
style: {
|
||||
type: String as PropType<String>,
|
||||
default: 'button'
|
||||
},
|
||||
select:{
|
||||
type: Function as PropType<Function>,
|
||||
default: () =>{ }
|
||||
}
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const { hasPermission } = usePermission();
|
||||
setup(props) {
|
||||
const { hasPermission } = usePermission();
|
||||
|
||||
const getTooltip = computed(() => {
|
||||
return (data: string | TooltipProps): TooltipProps => {
|
||||
if (isString(data)) {
|
||||
return { title: data, placement: 'bottom' };
|
||||
} else {
|
||||
return Object.assign({ placement: 'bottom' }, data);
|
||||
}
|
||||
};
|
||||
});
|
||||
const actionType =
|
||||
props.style === 'button' ? 'default' : props.style === 'text' ? 'primary' : 'default';
|
||||
const actionText =
|
||||
props.style === 'button' ? undefined : props.style === 'text' ? true : undefined;
|
||||
|
||||
const actionType = props.style === 'button' ? 'default' : props.style === 'text' ? 'primary' : 'default'
|
||||
const actionText = props.style === 'button' ? undefined : props.style === 'text' ? true : undefined
|
||||
|
||||
const getMoreProps = computed(() => {
|
||||
const getMoreProps = computed(() => {
|
||||
return {
|
||||
text: actionText,
|
||||
type: actionType,
|
||||
size: "small"
|
||||
}
|
||||
})
|
||||
size: 'small',
|
||||
};
|
||||
});
|
||||
|
||||
const getDropdownList = computed(() => {
|
||||
return (toRaw(props.dropDownActions) || [])
|
||||
const getDropdownList = computed(() => {
|
||||
return (toRaw(props.dropDownActions) || [])
|
||||
.filter((action) => {
|
||||
return hasPermission(action.auth) && isIfShow(action);
|
||||
})
|
||||
.map((action, index) => {
|
||||
const { label, popConfirm } = action;
|
||||
.map((action) => {
|
||||
const { popConfirm } = action;
|
||||
return {
|
||||
size: 'small',
|
||||
text: actionText,
|
||||
@@ -94,27 +85,27 @@ export default defineComponent({
|
||||
...action,
|
||||
...popConfirm,
|
||||
onConfirm: popConfirm?.confirm,
|
||||
onCancel: popConfirm?.cancel
|
||||
onCancel: popConfirm?.cancel,
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function isIfShow(action: ActionItem): boolean {
|
||||
const ifShow = action.ifShow;
|
||||
function isIfShow(action: ActionItem): boolean {
|
||||
const ifShow = action.ifShow;
|
||||
|
||||
let isIfShow = true;
|
||||
let isIfShow = true;
|
||||
|
||||
if (isBoolean(ifShow)) {
|
||||
isIfShow = ifShow;
|
||||
if (isBoolean(ifShow)) {
|
||||
isIfShow = ifShow;
|
||||
}
|
||||
if (isFunction(ifShow)) {
|
||||
isIfShow = ifShow(action);
|
||||
}
|
||||
return isIfShow;
|
||||
}
|
||||
if (isFunction(ifShow)) {
|
||||
isIfShow = ifShow(action);
|
||||
}
|
||||
return isIfShow;
|
||||
}
|
||||
|
||||
const getActions = computed(() => {
|
||||
return (toRaw(props.actions) || [])
|
||||
const getActions = computed(() => {
|
||||
return (toRaw(props.actions) || [])
|
||||
.filter((action) => {
|
||||
return hasPermission(action.auth) && isIfShow(action);
|
||||
})
|
||||
@@ -132,14 +123,13 @@ export default defineComponent({
|
||||
enable: !!popConfirm,
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
getActions,
|
||||
getDropdownList,
|
||||
getTooltip,
|
||||
getMoreProps
|
||||
}
|
||||
}
|
||||
})
|
||||
return {
|
||||
getActions,
|
||||
getDropdownList,
|
||||
getMoreProps,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -5,46 +5,62 @@
|
||||
<n-popover trigger="click" :width="230" class="toolbar-popover" placement="bottom-end">
|
||||
<template #trigger>
|
||||
<n-icon size="18">
|
||||
<SettingOutlined/>
|
||||
<SettingOutlined />
|
||||
</n-icon>
|
||||
</template>
|
||||
<template #header>
|
||||
<div class="table-toolbar-inner-popover-title">
|
||||
<n-space>
|
||||
<n-checkbox v-model:checked="checkAll" @update:checked="onCheckAll">列展示</n-checkbox>
|
||||
<n-checkbox v-model:checked="selection" @update:checked="onSelection">勾选列</n-checkbox>
|
||||
<n-button text type="info" size="small" class="mt-1" @click="resetColumns">重置</n-button>
|
||||
<n-checkbox v-model:checked="checkAll" @update:checked="onCheckAll"
|
||||
>列展示</n-checkbox
|
||||
>
|
||||
<n-checkbox v-model:checked="selection" @update:checked="onSelection"
|
||||
>勾选列</n-checkbox
|
||||
>
|
||||
<n-button text type="info" size="small" class="mt-1" @click="resetColumns"
|
||||
>重置</n-button
|
||||
>
|
||||
</n-space>
|
||||
</div>
|
||||
</template>
|
||||
<div class="table-toolbar-inner">
|
||||
<n-checkbox-group v-model:value="checkList" @update:value="onChange">
|
||||
<Draggable v-model="columnsList" animation="300" item-key="key" @end="draggableEnd">
|
||||
<template #item="{element, index}">
|
||||
<div class="table-toolbar-inner-checkbox"
|
||||
:class="{'table-toolbar-inner-checkbox-dark':getDarkTheme === true}">
|
||||
<template #item="{ element }">
|
||||
<div
|
||||
class="table-toolbar-inner-checkbox"
|
||||
:class="{ 'table-toolbar-inner-checkbox-dark': getDarkTheme === true }"
|
||||
>
|
||||
<span class="drag-icon">
|
||||
<n-icon size="18">
|
||||
<DragOutlined/>
|
||||
<DragOutlined />
|
||||
</n-icon>
|
||||
</span>
|
||||
<n-checkbox :value="element.key" :label="element.title"/>
|
||||
<n-checkbox :value="element.key" :label="element.title" />
|
||||
<div class="fixed-item">
|
||||
<n-tooltip trigger="hover" placement="bottom">
|
||||
<template #trigger>
|
||||
<n-icon size="18" :color="element.fixed === 'left' ? '#2080f0':undefined"
|
||||
class="cursor-pointer" @click="fixedColumn(element,'left')">
|
||||
<VerticalRightOutlined/>
|
||||
<n-icon
|
||||
size="18"
|
||||
:color="element.fixed === 'left' ? '#2080f0' : undefined"
|
||||
class="cursor-pointer"
|
||||
@click="fixedColumn(element, 'left')"
|
||||
>
|
||||
<VerticalRightOutlined />
|
||||
</n-icon>
|
||||
</template>
|
||||
<span>固定到左侧</span>
|
||||
</n-tooltip>
|
||||
<n-divider vertical/>
|
||||
<n-divider vertical />
|
||||
<n-tooltip trigger="hover" placement="bottom">
|
||||
<template #trigger>
|
||||
<n-icon size="18" :color="element.fixed === 'right' ? '#2080f0':undefined"
|
||||
class="cursor-pointer" @click="fixedColumn(element,'right')">
|
||||
<VerticalLeftOutlined/>
|
||||
<n-icon
|
||||
size="18"
|
||||
:color="element.fixed === 'right' ? '#2080f0' : undefined"
|
||||
class="cursor-pointer"
|
||||
@click="fixedColumn(element, 'right')"
|
||||
>
|
||||
<VerticalLeftOutlined />
|
||||
</n-icon>
|
||||
</template>
|
||||
<span>固定到右侧</span>
|
||||
@@ -63,221 +79,226 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ref, defineComponent, reactive, unref, toRaw, computed, toRefs, watchEffect } from "vue"
|
||||
import { useTableContext } from '../../hooks/useTableContext';
|
||||
import { ReloadOutlined, ColumnHeightOutlined, SettingOutlined, DragOutlined, VerticalRightOutlined, VerticalLeftOutlined } from '@vicons/antd'
|
||||
import Draggable from 'vuedraggable/src/vuedraggable'
|
||||
import { useDesignSetting } from "@/hooks/setting/useDesignSetting";
|
||||
import { ref, defineComponent, reactive, unref, toRaw, computed, toRefs, watchEffect } from 'vue';
|
||||
import { useTableContext } from '../../hooks/useTableContext';
|
||||
import {
|
||||
SettingOutlined,
|
||||
DragOutlined,
|
||||
VerticalRightOutlined,
|
||||
VerticalLeftOutlined,
|
||||
} from '@vicons/antd';
|
||||
import Draggable from 'vuedraggable/src/vuedraggable';
|
||||
import { useDesignSetting } from '@/hooks/setting/useDesignSetting';
|
||||
|
||||
interface Options {
|
||||
title: string;
|
||||
key: string;
|
||||
fixed?: boolean | 'left' | 'right';
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ColumnSetting',
|
||||
components: {
|
||||
ReloadOutlined, ColumnHeightOutlined, SettingOutlined, DragOutlined, Draggable,
|
||||
VerticalRightOutlined, VerticalLeftOutlined
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const { getDarkTheme } = useDesignSetting()
|
||||
const table = useTableContext();
|
||||
const columnsList = ref<Options[]>([]);
|
||||
const cacheColumnsList = ref<Options[]>([]);
|
||||
|
||||
const state = reactive({
|
||||
selection: false,
|
||||
checkAll: true,
|
||||
checkList: [],
|
||||
defaultCheckList: []
|
||||
})
|
||||
|
||||
const getSelection = computed(() => {
|
||||
return state.selection
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
const columns = table.getColumns();
|
||||
if (columns.length) {
|
||||
init();
|
||||
}
|
||||
});
|
||||
|
||||
//初始化
|
||||
function init() {
|
||||
const columns = getColumns();
|
||||
const checkList = columns.map(item => item.key)
|
||||
state.checkList = checkList
|
||||
state.defaultCheckList = checkList
|
||||
columnsList.value = columns
|
||||
cacheColumnsList.value = columns
|
||||
}
|
||||
|
||||
//切换
|
||||
function onChange(checkList) {
|
||||
if (state.selection) {
|
||||
checkList.unshift('selection')
|
||||
}
|
||||
setColumns(checkList)
|
||||
}
|
||||
|
||||
//设置
|
||||
function setColumns(columns) {
|
||||
table.setColumns(columns)
|
||||
}
|
||||
|
||||
//获取
|
||||
function getColumns() {
|
||||
let newRet = []
|
||||
table.getColumns().forEach(item => {
|
||||
newRet.push({ ...item })
|
||||
})
|
||||
return newRet
|
||||
}
|
||||
|
||||
//重置
|
||||
function resetColumns() {
|
||||
state.checkList = [...state.defaultCheckList]
|
||||
state.checkAll = true;
|
||||
let cacheColumnsKeys: any[] = table.getCacheColumns()
|
||||
let newColumns = cacheColumnsKeys.map(item => {
|
||||
return {
|
||||
...item,
|
||||
fixed: undefined
|
||||
}
|
||||
})
|
||||
setColumns(newColumns);
|
||||
columnsList.value = newColumns
|
||||
}
|
||||
|
||||
//全选
|
||||
function onCheckAll(e) {
|
||||
let checkList = table.getCacheColumns(true)
|
||||
if (e) {
|
||||
setColumns(checkList);
|
||||
state.checkList = checkList
|
||||
} else {
|
||||
setColumns([]);
|
||||
state.checkList = []
|
||||
}
|
||||
}
|
||||
|
||||
//拖拽排序
|
||||
function draggableEnd() {
|
||||
const newColumns = toRaw(unref(columnsList))
|
||||
columnsList.value = newColumns
|
||||
setColumns(newColumns);
|
||||
}
|
||||
|
||||
//勾选列
|
||||
function onSelection(e) {
|
||||
let checkList = table.getCacheColumns()
|
||||
if (e) {
|
||||
checkList.unshift({ type: 'selection', key: 'selection' })
|
||||
setColumns(checkList);
|
||||
} else {
|
||||
checkList.splice(0, 1)
|
||||
setColumns(checkList);
|
||||
}
|
||||
}
|
||||
|
||||
//固定
|
||||
function fixedColumn(item, fixed) {
|
||||
console.log('item:', item)
|
||||
if (!state.checkList.includes(item.key)) return;
|
||||
let columns = getColumns();
|
||||
const isFixed = item.fixed === fixed ? undefined : fixed
|
||||
let index = columns.findIndex(res => res.key === item.key)
|
||||
console.log('index:', index)
|
||||
if (index !== -1) {
|
||||
columns[index].fixed = isFixed;
|
||||
}
|
||||
table.setCacheColumnsField(item.key, { fixed: isFixed })
|
||||
columnsList.value[index].fixed = isFixed
|
||||
console.log('columnsList:', columnsList.value)
|
||||
setColumns(columns);
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
columnsList,
|
||||
getDarkTheme,
|
||||
onChange,
|
||||
onCheckAll,
|
||||
onSelection,
|
||||
resetColumns,
|
||||
fixedColumn,
|
||||
draggableEnd,
|
||||
getSelection
|
||||
}
|
||||
interface Options {
|
||||
title: string;
|
||||
key: string;
|
||||
fixed?: boolean | 'left' | 'right';
|
||||
}
|
||||
})
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ColumnSetting',
|
||||
components: {
|
||||
SettingOutlined,
|
||||
DragOutlined,
|
||||
Draggable,
|
||||
VerticalRightOutlined,
|
||||
VerticalLeftOutlined,
|
||||
},
|
||||
setup() {
|
||||
const { getDarkTheme } = useDesignSetting();
|
||||
const table = useTableContext();
|
||||
const columnsList = ref<Options[]>([]);
|
||||
const cacheColumnsList = ref<Options[]>([]);
|
||||
|
||||
const state = reactive({
|
||||
selection: false,
|
||||
checkAll: true,
|
||||
checkList: [],
|
||||
defaultCheckList: [],
|
||||
});
|
||||
|
||||
const getSelection = computed(() => {
|
||||
return state.selection;
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
const columns = table.getColumns();
|
||||
if (columns.length) {
|
||||
init();
|
||||
}
|
||||
});
|
||||
|
||||
//初始化
|
||||
function init() {
|
||||
const columns: any[] = getColumns();
|
||||
const checkList: any = columns.map((item) => item.key);
|
||||
state.checkList = checkList;
|
||||
state.defaultCheckList = checkList;
|
||||
columnsList.value = columns;
|
||||
cacheColumnsList.value = columns;
|
||||
}
|
||||
|
||||
//切换
|
||||
function onChange(checkList) {
|
||||
if (state.selection) {
|
||||
checkList.unshift('selection');
|
||||
}
|
||||
setColumns(checkList);
|
||||
}
|
||||
|
||||
//设置
|
||||
function setColumns(columns) {
|
||||
table.setColumns(columns);
|
||||
}
|
||||
|
||||
//获取
|
||||
function getColumns() {
|
||||
let newRet = [];
|
||||
table.getColumns().forEach((item) => {
|
||||
newRet.push({ ...item });
|
||||
});
|
||||
return newRet;
|
||||
}
|
||||
|
||||
//重置
|
||||
function resetColumns() {
|
||||
state.checkList = [...state.defaultCheckList];
|
||||
state.checkAll = true;
|
||||
let cacheColumnsKeys: any[] = table.getCacheColumns();
|
||||
let newColumns = cacheColumnsKeys.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
fixed: undefined,
|
||||
};
|
||||
});
|
||||
setColumns(newColumns);
|
||||
columnsList.value = newColumns;
|
||||
}
|
||||
|
||||
//全选
|
||||
function onCheckAll(e) {
|
||||
let checkList = table.getCacheColumns(true);
|
||||
if (e) {
|
||||
setColumns(checkList);
|
||||
state.checkList = checkList;
|
||||
} else {
|
||||
setColumns([]);
|
||||
state.checkList = [];
|
||||
}
|
||||
}
|
||||
|
||||
//拖拽排序
|
||||
function draggableEnd() {
|
||||
const newColumns = toRaw(unref(columnsList));
|
||||
columnsList.value = newColumns;
|
||||
setColumns(newColumns);
|
||||
}
|
||||
|
||||
//勾选列
|
||||
function onSelection(e) {
|
||||
let checkList = table.getCacheColumns();
|
||||
if (e) {
|
||||
checkList.unshift({ type: 'selection', key: 'selection' });
|
||||
setColumns(checkList);
|
||||
} else {
|
||||
checkList.splice(0, 1);
|
||||
setColumns(checkList);
|
||||
}
|
||||
}
|
||||
|
||||
//固定
|
||||
function fixedColumn(item, fixed) {
|
||||
if (!state.checkList.includes(item.key)) return;
|
||||
let columns = getColumns();
|
||||
const isFixed = item.fixed === fixed ? undefined : fixed;
|
||||
let index = columns.findIndex((res) => res.key === item.key);
|
||||
if (index !== -1) {
|
||||
columns[index].fixed = isFixed;
|
||||
}
|
||||
table.setCacheColumnsField(item.key, { fixed: isFixed });
|
||||
columnsList.value[index].fixed = isFixed;
|
||||
setColumns(columns);
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
columnsList,
|
||||
getDarkTheme,
|
||||
onChange,
|
||||
onCheckAll,
|
||||
onSelection,
|
||||
resetColumns,
|
||||
fixedColumn,
|
||||
draggableEnd,
|
||||
getSelection,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.table-toolbar {
|
||||
&-inner-popover-title {
|
||||
padding: 3px 0;
|
||||
}
|
||||
.table-toolbar {
|
||||
&-inner-popover-title {
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
&-right {
|
||||
&-icon {
|
||||
margin-left: 12px;
|
||||
font-size: 16px;
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
&-right {
|
||||
&-icon {
|
||||
margin-left: 12px;
|
||||
font-size: 16px;
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
|
||||
:hover {
|
||||
color: #1890ff;
|
||||
:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-toolbar-inner {
|
||||
&-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 14px;
|
||||
|
||||
&:hover {
|
||||
background: #e6f7ff;
|
||||
}
|
||||
|
||||
.drag-icon {
|
||||
display: inline-flex;
|
||||
margin-right: 8px;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.fixed-item {
|
||||
.table-toolbar-inner {
|
||||
&-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.ant-checkbox-wrapper {
|
||||
flex: 1;
|
||||
padding: 10px 14px;
|
||||
|
||||
&:hover {
|
||||
color: #1890ff !important;
|
||||
background: #e6f7ff;
|
||||
}
|
||||
|
||||
.drag-icon {
|
||||
display: inline-flex;
|
||||
margin-right: 8px;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.fixed-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.ant-checkbox-wrapper {
|
||||
flex: 1;
|
||||
|
||||
&:hover {
|
||||
color: #1890ff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-checkbox-dark {
|
||||
&:hover {
|
||||
background: hsla(0, 0%, 100%, 0.08);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-checkbox-dark {
|
||||
&:hover {
|
||||
background: hsla(0, 0%, 100%, .08);
|
||||
.toolbar-popover {
|
||||
.n-popover__content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar-popover {
|
||||
.n-popover__content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import componentSetting from '@/settings/componentSetting'
|
||||
import componentSetting from '@/settings/componentSetting';
|
||||
|
||||
const { table } = componentSetting
|
||||
const { table } = componentSetting;
|
||||
|
||||
const { apiSetting, defaultPageSize, pageSizes } = table;
|
||||
|
||||
@@ -9,7 +9,3 @@ export const DEFAULTPAGESIZE = defaultPageSize;
|
||||
export const APISETTING = apiSetting;
|
||||
|
||||
export const PAGESIZES = pageSizes;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,126 +1,125 @@
|
||||
import { ref, Ref, ComputedRef, unref, computed, watch, toRaw } from 'vue';
|
||||
import type { BasicColumn, BasicTableProps } from '../types/table';
|
||||
import { isEqual, cloneDeep } from 'lodash-es';
|
||||
import { isArray, isString } from '@/utils/is';
|
||||
import { isArray, isString, isBoolean, isFunction } from '@/utils/is';
|
||||
import { usePermission } from '@/hooks/web/usePermission';
|
||||
import { isString, isBoolean, isFunction } from "@/utils/is";
|
||||
import { ActionItem } from "@/components/Table";
|
||||
import { ActionItem } from '@/components/Table';
|
||||
|
||||
export function useColumns(propsRef: ComputedRef<BasicTableProps>) {
|
||||
const columnsRef = ref(unref(propsRef).columns) as unknown as Ref<BasicColumn[]>;
|
||||
let cacheColumns = unref(propsRef).columns;
|
||||
const columnsRef = ref(unref(propsRef).columns) as unknown as Ref<BasicColumn[]>;
|
||||
let cacheColumns = unref(propsRef).columns;
|
||||
|
||||
const getColumnsRef = computed(() => {
|
||||
const columns = cloneDeep(unref(columnsRef));
|
||||
const getColumnsRef = computed(() => {
|
||||
const columns = cloneDeep(unref(columnsRef));
|
||||
|
||||
handleActionColumn(propsRef, columns);
|
||||
if (!columns) return [];
|
||||
return columns;
|
||||
})
|
||||
handleActionColumn(propsRef, columns);
|
||||
if (!columns) return [];
|
||||
return columns;
|
||||
});
|
||||
|
||||
const { hasPermission } = usePermission();
|
||||
const { hasPermission } = usePermission();
|
||||
|
||||
function isIfShow(action: ActionItem): boolean {
|
||||
const ifShow = action.ifShow;
|
||||
function isIfShow(action: ActionItem): boolean {
|
||||
const ifShow = action.ifShow;
|
||||
|
||||
let isIfShow = true;
|
||||
let isIfShow = true;
|
||||
|
||||
if (isBoolean(ifShow)) {
|
||||
isIfShow = ifShow;
|
||||
}
|
||||
if (isFunction(ifShow)) {
|
||||
isIfShow = ifShow(action);
|
||||
}
|
||||
return isIfShow;
|
||||
if (isBoolean(ifShow)) {
|
||||
isIfShow = ifShow;
|
||||
}
|
||||
if (isFunction(ifShow)) {
|
||||
isIfShow = ifShow(action);
|
||||
}
|
||||
return isIfShow;
|
||||
}
|
||||
|
||||
const getPageColumns = computed(() => {
|
||||
const pageColumns = unref(getColumnsRef);
|
||||
const columns = cloneDeep(pageColumns);
|
||||
return columns.filter((column) => {
|
||||
return hasPermission(column.auth) && isIfShow(column);
|
||||
})
|
||||
})
|
||||
const getPageColumns = computed(() => {
|
||||
const pageColumns = unref(getColumnsRef);
|
||||
const columns = cloneDeep(pageColumns);
|
||||
return columns.filter((column) => {
|
||||
// @ts-ignore
|
||||
return hasPermission(column.auth) && isIfShow(column);
|
||||
});
|
||||
});
|
||||
|
||||
watch(
|
||||
() => unref(propsRef).columns,
|
||||
(columns) => {
|
||||
columnsRef.value = columns;
|
||||
cacheColumns = columns;
|
||||
watch(
|
||||
() => unref(propsRef).columns,
|
||||
(columns) => {
|
||||
columnsRef.value = columns;
|
||||
cacheColumns = columns;
|
||||
}
|
||||
);
|
||||
|
||||
function handleActionColumn(propsRef: ComputedRef<BasicTableProps>, columns: BasicColumn[]) {
|
||||
const { actionColumn } = unref(propsRef);
|
||||
if (!actionColumn) return;
|
||||
// @ts-ignore
|
||||
columns.push({
|
||||
...actionColumn,
|
||||
});
|
||||
}
|
||||
|
||||
//设置
|
||||
function setColumns(columnList: string[]) {
|
||||
const columns: any[] = cloneDeep(columnList);
|
||||
if (!isArray(columns)) return;
|
||||
|
||||
if (!columns.length) {
|
||||
columnsRef.value = [];
|
||||
return;
|
||||
}
|
||||
const cacheKeys = cacheColumns.map((item) => item.key);
|
||||
//针对拖拽排序
|
||||
if (!isString(columns[0])) {
|
||||
columnsRef.value = columns;
|
||||
} else {
|
||||
const newColumns: any[] = [];
|
||||
cacheColumns.forEach((item) => {
|
||||
if (columnList.includes(item.key)) {
|
||||
newColumns.push({ ...item });
|
||||
}
|
||||
);
|
||||
|
||||
function handleActionColumn(propsRef: ComputedRef<BasicTableProps>, columns: BasicColumn[]) {
|
||||
const { actionColumn } = unref(propsRef);
|
||||
if (!actionColumn) return;
|
||||
columns.push({
|
||||
...actionColumn
|
||||
});
|
||||
if (!isEqual(cacheKeys, columns)) {
|
||||
newColumns.sort((prev, next) => {
|
||||
return cacheKeys.indexOf(prev.key) - cacheKeys.indexOf(next.key);
|
||||
});
|
||||
}
|
||||
columnsRef.value = newColumns;
|
||||
}
|
||||
}
|
||||
|
||||
//设置
|
||||
function setColumns(columnList: string[]) {
|
||||
const columns: any[] = cloneDeep(columnList);
|
||||
if (!isArray(columns)) return;
|
||||
//获取
|
||||
function getColumns() {
|
||||
const columns = toRaw(unref(getColumnsRef));
|
||||
return columns.map((item) => {
|
||||
return { ...item, title: item.title, key: item.key, fixed: item.fixed || undefined };
|
||||
});
|
||||
}
|
||||
|
||||
if (!columns.length) {
|
||||
columnsRef.value = [];
|
||||
return;
|
||||
}
|
||||
const cacheKeys = cacheColumns.map((item) => item.key);
|
||||
//针对拖拽排序
|
||||
if (!isString(columns[0])) {
|
||||
columnsRef.value = columns;
|
||||
} else {
|
||||
const newColumns: any[] = []
|
||||
cacheColumns.forEach(item => {
|
||||
if (columnList.includes(item.key)) {
|
||||
newColumns.push({ ...item })
|
||||
}
|
||||
})
|
||||
if (!isEqual(cacheKeys, columns)) {
|
||||
newColumns.sort((prev, next) => {
|
||||
return (
|
||||
cacheKeys.indexOf(prev.key) - cacheKeys.indexOf(next.key)
|
||||
);
|
||||
});
|
||||
}
|
||||
columnsRef.value = newColumns
|
||||
}
|
||||
//获取原始
|
||||
function getCacheColumns(isKey?: boolean): any[] {
|
||||
return isKey ? cacheColumns.map((item) => item.key) : cacheColumns;
|
||||
}
|
||||
|
||||
//更新原始数据单个字段
|
||||
function setCacheColumnsField(dataIndex: string | undefined, value: Partial<BasicColumn>) {
|
||||
if (!dataIndex || !value) {
|
||||
return;
|
||||
}
|
||||
cacheColumns.forEach((item) => {
|
||||
if (item.key === dataIndex) {
|
||||
Object.assign(item, value);
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//获取
|
||||
function getColumns() {
|
||||
let columns = toRaw(unref(getColumnsRef));
|
||||
return columns.map(item => {
|
||||
return { ...item, title: item.title, key: item.key, fixed: item.fixed || undefined }
|
||||
})
|
||||
}
|
||||
|
||||
//获取原始
|
||||
function getCacheColumns(isKey?: boolean): any[] {
|
||||
return isKey ? cacheColumns.map(item => item.key) : cacheColumns;
|
||||
}
|
||||
|
||||
//更新原始数据单个字段
|
||||
function setCacheColumnsField(dataIndex: string | undefined, value: Partial<BasicColumn>) {
|
||||
if (!dataIndex || !value) {
|
||||
return;
|
||||
}
|
||||
cacheColumns.forEach((item) => {
|
||||
if (item.key === dataIndex) {
|
||||
Object.assign(item, value);
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
getColumnsRef,
|
||||
getCacheColumns,
|
||||
setCacheColumnsField,
|
||||
setColumns,
|
||||
getColumns,
|
||||
getPageColumns
|
||||
};
|
||||
return {
|
||||
getColumnsRef,
|
||||
getCacheColumns,
|
||||
setCacheColumnsField,
|
||||
setColumns,
|
||||
getColumns,
|
||||
getPageColumns,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,137 +5,134 @@ import { isBoolean } from '@/utils/is';
|
||||
import { APISETTING } from '../const';
|
||||
|
||||
export function useDataSource(
|
||||
propsRef: ComputedRef<BasicTableProps>,
|
||||
{
|
||||
getPaginationInfo,
|
||||
setPagination,
|
||||
setLoading,
|
||||
tableData
|
||||
},
|
||||
emit
|
||||
propsRef: ComputedRef<BasicTableProps>,
|
||||
{ getPaginationInfo, setPagination, setLoading, tableData },
|
||||
emit
|
||||
) {
|
||||
const dataSourceRef = ref([]);
|
||||
const dataSourceRef = ref([]);
|
||||
|
||||
watchEffect(() => {
|
||||
tableData.value = unref(dataSourceRef);
|
||||
});
|
||||
watchEffect(() => {
|
||||
tableData.value = unref(dataSourceRef);
|
||||
});
|
||||
|
||||
watch(
|
||||
() => unref(propsRef).dataSource,
|
||||
() => {
|
||||
const { dataSource }: any = unref(propsRef);
|
||||
dataSource && (dataSourceRef.value = dataSource);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
watch(
|
||||
() => unref(propsRef).dataSource,
|
||||
() => {
|
||||
const { dataSource }: any = unref(propsRef);
|
||||
dataSource && (dataSourceRef.value = dataSource);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
const getRowKey = computed(() => {
|
||||
const { rowKey }: any = unref(propsRef);
|
||||
return rowKey ? rowKey : () => {
|
||||
return 'key'
|
||||
const getRowKey = computed(() => {
|
||||
const { rowKey }: any = unref(propsRef);
|
||||
return rowKey
|
||||
? rowKey
|
||||
: () => {
|
||||
return 'key';
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const getDataSourceRef = computed(() => {
|
||||
const dataSource = unref(dataSourceRef);
|
||||
if (!dataSource || dataSource.length === 0) {
|
||||
return unref(dataSourceRef);
|
||||
}
|
||||
return unref(dataSourceRef);
|
||||
});
|
||||
|
||||
async function fetch(opt?) {
|
||||
try {
|
||||
setLoading(true);
|
||||
const { request, pagination }: any = unref(propsRef);
|
||||
|
||||
//组装分页信息
|
||||
const pageField = APISETTING.pageField
|
||||
const sizeField = APISETTING.sizeField
|
||||
const totalField = APISETTING.totalField
|
||||
const listField = APISETTING.listField
|
||||
|
||||
let pageParams = {};
|
||||
const { page = 1, pageSize = 10 } = unref(getPaginationInfo) as PaginationProps;
|
||||
|
||||
if ((isBoolean(pagination) && !pagination) || isBoolean(getPaginationInfo)) {
|
||||
pageParams = {};
|
||||
} else {
|
||||
pageParams[pageField] = (opt && opt[pageField]) || page;
|
||||
pageParams[sizeField] = pageSize;
|
||||
}
|
||||
|
||||
let params = {
|
||||
...pageParams,
|
||||
}
|
||||
const res = await request(params);
|
||||
|
||||
const resultTotal = res[totalField] || 0
|
||||
const currentPage = res[pageField]
|
||||
|
||||
// 如果数据异常,需获取正确的页码再次执行
|
||||
if (resultTotal) {
|
||||
const currentTotalPage = Math.ceil(resultTotal / pageSize);
|
||||
if (page > currentTotalPage) {
|
||||
setPagination({
|
||||
[pageField]: currentTotalPage,
|
||||
});
|
||||
fetch(opt);
|
||||
}
|
||||
}
|
||||
let resultInfo = res[listField] ? res[listField] : []
|
||||
dataSourceRef.value = resultInfo;
|
||||
setPagination({
|
||||
[pageField]: currentPage,
|
||||
[totalField]: resultTotal,
|
||||
});
|
||||
if (opt && opt[pageField]) {
|
||||
setPagination({
|
||||
[pageField]: opt[pageField] || 1,
|
||||
});
|
||||
}
|
||||
emit('fetch-success', {
|
||||
items: unref(resultInfo),
|
||||
resultTotal
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
emit('fetch-error', error);
|
||||
dataSourceRef.value = [];
|
||||
// setPagination({
|
||||
// pageCount: 0,
|
||||
// });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
const getDataSourceRef = computed(() => {
|
||||
const dataSource = unref(dataSourceRef);
|
||||
if (!dataSource || dataSource.length === 0) {
|
||||
return unref(dataSourceRef);
|
||||
}
|
||||
return unref(dataSourceRef);
|
||||
});
|
||||
|
||||
async function fetch(opt?) {
|
||||
try {
|
||||
setLoading(true);
|
||||
const { request, pagination }: any = unref(propsRef);
|
||||
|
||||
//组装分页信息
|
||||
const pageField = APISETTING.pageField;
|
||||
const sizeField = APISETTING.sizeField;
|
||||
const totalField = APISETTING.totalField;
|
||||
const listField = APISETTING.listField;
|
||||
|
||||
let pageParams = {};
|
||||
const { page = 1, pageSize = 10 } = unref(getPaginationInfo) as PaginationProps;
|
||||
|
||||
if ((isBoolean(pagination) && !pagination) || isBoolean(getPaginationInfo)) {
|
||||
pageParams = {};
|
||||
} else {
|
||||
pageParams[pageField] = (opt && opt[pageField]) || page;
|
||||
pageParams[sizeField] = pageSize;
|
||||
}
|
||||
|
||||
const params = {
|
||||
...pageParams,
|
||||
};
|
||||
const res = await request(params);
|
||||
|
||||
const resultTotal = res[totalField] || 0;
|
||||
const currentPage = res[pageField];
|
||||
|
||||
// 如果数据异常,需获取正确的页码再次执行
|
||||
if (resultTotal) {
|
||||
const currentTotalPage = Math.ceil(resultTotal / pageSize);
|
||||
if (page > currentTotalPage) {
|
||||
setPagination({
|
||||
[pageField]: currentTotalPage,
|
||||
});
|
||||
fetch(opt);
|
||||
}
|
||||
}
|
||||
const resultInfo = res[listField] ? res[listField] : [];
|
||||
dataSourceRef.value = resultInfo;
|
||||
setPagination({
|
||||
[pageField]: currentPage,
|
||||
[totalField]: resultTotal,
|
||||
});
|
||||
if (opt && opt[pageField]) {
|
||||
setPagination({
|
||||
[pageField]: opt[pageField] || 1,
|
||||
});
|
||||
}
|
||||
emit('fetch-success', {
|
||||
items: unref(resultInfo),
|
||||
resultTotal,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
emit('fetch-error', error);
|
||||
dataSourceRef.value = [];
|
||||
// setPagination({
|
||||
// pageCount: 0,
|
||||
// });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
fetch();
|
||||
}, 16)
|
||||
});
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
fetch();
|
||||
}, 16);
|
||||
});
|
||||
|
||||
function setTableData(values) {
|
||||
dataSourceRef.value = values;
|
||||
}
|
||||
function setTableData(values) {
|
||||
dataSourceRef.value = values;
|
||||
}
|
||||
|
||||
function getDataSource(): any[] {
|
||||
return getDataSourceRef.value;
|
||||
}
|
||||
function getDataSource(): any[] {
|
||||
return getDataSourceRef.value;
|
||||
}
|
||||
|
||||
async function reload(opt?) {
|
||||
await fetch(opt);
|
||||
}
|
||||
async function reload(opt?) {
|
||||
await fetch(opt);
|
||||
}
|
||||
|
||||
return {
|
||||
fetch,
|
||||
getRowKey,
|
||||
getDataSourceRef,
|
||||
getDataSource,
|
||||
setTableData,
|
||||
reload
|
||||
}
|
||||
return {
|
||||
fetch,
|
||||
getRowKey,
|
||||
getDataSourceRef,
|
||||
getDataSource,
|
||||
setTableData,
|
||||
reload,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,20 +2,20 @@ import { ref, ComputedRef, unref, computed, watch } from 'vue';
|
||||
import type { BasicTableProps } from '../types/table';
|
||||
|
||||
export function useLoading(props: ComputedRef<BasicTableProps>) {
|
||||
const loadingRef = ref(unref(props).loading);
|
||||
const loadingRef = ref(unref(props).loading);
|
||||
|
||||
watch(
|
||||
() => unref(props).loading,
|
||||
(loading) => {
|
||||
loadingRef.value = loading;
|
||||
}
|
||||
);
|
||||
|
||||
const getLoading = computed(() => unref(loadingRef));
|
||||
|
||||
function setLoading(loading: boolean) {
|
||||
loadingRef.value = loading;
|
||||
watch(
|
||||
() => unref(props).loading,
|
||||
(loading) => {
|
||||
loadingRef.value = loading;
|
||||
}
|
||||
);
|
||||
|
||||
return { getLoading, setLoading };
|
||||
const getLoading = computed(() => unref(loadingRef));
|
||||
|
||||
function setLoading(loading: boolean) {
|
||||
loadingRef.value = loading;
|
||||
}
|
||||
|
||||
return { getLoading, setLoading };
|
||||
}
|
||||
|
||||
@@ -6,43 +6,43 @@ import { isBoolean } from '@/utils/is';
|
||||
import { DEFAULTPAGESIZE, PAGESIZES } from '../const';
|
||||
|
||||
export function usePagination(refProps: ComputedRef<BasicTableProps>) {
|
||||
const configRef = ref<PaginationProps>({});
|
||||
const show = ref(true);
|
||||
const configRef = ref<PaginationProps>({});
|
||||
const show = ref(true);
|
||||
|
||||
const getPaginationInfo = computed((): PaginationProps | boolean => {
|
||||
const { pagination } = unref(refProps);
|
||||
if (!unref(show) || (isBoolean(pagination) && !pagination)) {
|
||||
return false;
|
||||
}
|
||||
return {
|
||||
pageSize: DEFAULTPAGESIZE,
|
||||
pageSizes: PAGESIZES,
|
||||
showSizePicker: true,
|
||||
showQuickJumper: true,
|
||||
...(isBoolean(pagination) ? {} : pagination),
|
||||
...unref(configRef),
|
||||
};
|
||||
});
|
||||
|
||||
function setPagination(info: Partial<PaginationProps>) {
|
||||
const paginationInfo = unref(getPaginationInfo);
|
||||
configRef.value = {
|
||||
...(!isBoolean(paginationInfo) ? paginationInfo : {}),
|
||||
...info,
|
||||
};
|
||||
const getPaginationInfo = computed((): PaginationProps | boolean => {
|
||||
const { pagination } = unref(refProps);
|
||||
if (!unref(show) || (isBoolean(pagination) && !pagination)) {
|
||||
return false;
|
||||
}
|
||||
return {
|
||||
pageSize: DEFAULTPAGESIZE,
|
||||
pageSizes: PAGESIZES,
|
||||
showSizePicker: true,
|
||||
showQuickJumper: true,
|
||||
...(isBoolean(pagination) ? {} : pagination),
|
||||
...unref(configRef),
|
||||
};
|
||||
});
|
||||
|
||||
function getPagination() {
|
||||
return unref(getPaginationInfo);
|
||||
}
|
||||
function setPagination(info: Partial<PaginationProps>) {
|
||||
const paginationInfo = unref(getPaginationInfo);
|
||||
configRef.value = {
|
||||
...(!isBoolean(paginationInfo) ? paginationInfo : {}),
|
||||
...info,
|
||||
};
|
||||
}
|
||||
|
||||
function getShowPagination() {
|
||||
return unref(show);
|
||||
}
|
||||
function getPagination() {
|
||||
return unref(getPaginationInfo);
|
||||
}
|
||||
|
||||
async function setShowPagination(flag: boolean) {
|
||||
show.value = flag;
|
||||
}
|
||||
function getShowPagination() {
|
||||
return unref(show);
|
||||
}
|
||||
|
||||
return { getPagination, getPaginationInfo, setShowPagination, getShowPagination, setPagination };
|
||||
async function setShowPagination(flag: boolean) {
|
||||
show.value = flag;
|
||||
}
|
||||
|
||||
return { getPagination, getPaginationInfo, setShowPagination, getShowPagination, setPagination };
|
||||
}
|
||||
|
||||
@@ -5,18 +5,18 @@ import { provide, inject, ComputedRef } from 'vue';
|
||||
const key = Symbol('s-table');
|
||||
|
||||
type Instance = TableActionType & {
|
||||
wrapRef: Ref<Nullable<HTMLElement>>;
|
||||
getBindValues: ComputedRef<Recordable>;
|
||||
wrapRef: Ref<Nullable<HTMLElement>>;
|
||||
getBindValues: ComputedRef<Recordable>;
|
||||
};
|
||||
|
||||
type RetInstance = Omit<Instance, 'getBindValues'> & {
|
||||
getBindValues: ComputedRef<BasicTableProps>;
|
||||
getBindValues: ComputedRef<BasicTableProps>;
|
||||
};
|
||||
|
||||
export function createTableContext(instance: Instance) {
|
||||
provide(key, instance);
|
||||
provide(key, instance);
|
||||
}
|
||||
|
||||
export function useTableContext(): RetInstance {
|
||||
return inject(key) as RetInstance;
|
||||
return inject(key) as RetInstance;
|
||||
}
|
||||
|
||||
@@ -1,49 +1,47 @@
|
||||
import type { PropType } from 'vue'
|
||||
import { BasicColumn } from './types/table'
|
||||
import type { PropType } from 'vue';
|
||||
import { BasicColumn } from './types/table';
|
||||
|
||||
export const basicProps = {
|
||||
title: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
titleTooltip: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'medium',
|
||||
},
|
||||
tableData: {
|
||||
type: [Object],
|
||||
default: () => {
|
||||
},
|
||||
},
|
||||
columns: {
|
||||
type: [Array] as PropType<BasicColumn[]>,
|
||||
default: () => [],
|
||||
required: true,
|
||||
},
|
||||
request: {
|
||||
type: Function as PropType<(...arg: any[]) => Promise<any>>,
|
||||
default: null,
|
||||
required: true
|
||||
},
|
||||
rowKey: {
|
||||
type: [String, Function] as PropType<string | ((record) => string)>,
|
||||
default: undefined,
|
||||
},
|
||||
pagination: {
|
||||
type: [Object, Boolean],
|
||||
default: () => {
|
||||
}
|
||||
},
|
||||
showPagination: {
|
||||
type: [String, Boolean],
|
||||
default: 'auto'
|
||||
},
|
||||
actionColumn: {
|
||||
type: Object as PropType<BasicColumn>,
|
||||
default: null,
|
||||
},
|
||||
}
|
||||
title: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
titleTooltip: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'medium',
|
||||
},
|
||||
tableData: {
|
||||
type: [Object],
|
||||
default: () => {},
|
||||
},
|
||||
columns: {
|
||||
type: [Array] as PropType<BasicColumn[]>,
|
||||
default: () => [],
|
||||
required: true,
|
||||
},
|
||||
request: {
|
||||
type: Function as PropType<(...arg: any[]) => Promise<any>>,
|
||||
default: null,
|
||||
required: true,
|
||||
},
|
||||
rowKey: {
|
||||
type: [String, Function] as PropType<string | ((record) => string)>,
|
||||
default: undefined,
|
||||
},
|
||||
pagination: {
|
||||
type: [Object, Boolean],
|
||||
default: () => {},
|
||||
},
|
||||
showPagination: {
|
||||
type: [String, Boolean],
|
||||
default: 'auto',
|
||||
},
|
||||
actionColumn: {
|
||||
type: Object as PropType<BasicColumn>,
|
||||
default: null,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import Pagination from 'naive-ui/lib/pagination';
|
||||
import { VNodeChild } from 'vue';
|
||||
|
||||
export interface PaginationProps {
|
||||
page?: number;
|
||||
pageCount?: number,
|
||||
pageSize?: number,
|
||||
pageSizes?: number[],
|
||||
showSizePicker?: boolean,
|
||||
showQuickJumper?: boolean,
|
||||
page?: number;
|
||||
pageCount?: number;
|
||||
pageSize?: number;
|
||||
pageSizes?: number[];
|
||||
showSizePicker?: boolean;
|
||||
showQuickJumper?: boolean;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
import type {
|
||||
TableBaseColumn,
|
||||
} from 'naive-ui/lib/data-table/src/interface';
|
||||
import type { TableBaseColumn } from 'naive-ui/lib/data-table/src/interface';
|
||||
|
||||
export interface BasicColumn extends TableBaseColumn {
|
||||
|
||||
}
|
||||
export type BasicColumn = TableBaseColumn;
|
||||
|
||||
export interface TableActionType {
|
||||
reload: (opt) => Promise<void>;
|
||||
emit?: any;
|
||||
getColumns: (opt) => BasicColumn[];
|
||||
setColumns: (columns: BasicColumn[] | string[]) => void;
|
||||
reload: (opt) => Promise<void>;
|
||||
emit?: any;
|
||||
getColumns: (opt?) => BasicColumn[];
|
||||
setColumns: (columns: BasicColumn[] | string[]) => void;
|
||||
}
|
||||
|
||||
export interface BasicTableProps<T = any> {
|
||||
title?: string,
|
||||
dataSource: Function,
|
||||
columns: any[],
|
||||
pagination: object,
|
||||
showPagination: boolean
|
||||
export interface BasicTableProps {
|
||||
title?: string;
|
||||
dataSource: Function;
|
||||
columns: any[];
|
||||
pagination: object;
|
||||
showPagination: boolean;
|
||||
actionColumn: any[];
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
import { NButton, NTooltip } from 'naive-ui';
|
||||
import { RoleEnum } from '/@/enums/roleEnum';
|
||||
|
||||
// @ts-ignore
|
||||
import { NButton } from 'naive-ui';
|
||||
import { RoleEnum } from '@/enums/roleEnum';
|
||||
// @ts-ignore
|
||||
export interface ActionItem extends NButton.props {
|
||||
onClick?: Fn;
|
||||
label?: string;
|
||||
color?: 'success' | 'error' | 'warning';
|
||||
icon?: string;
|
||||
popConfirm?: PopConfirm;
|
||||
disabled?: boolean;
|
||||
divider?: boolean;
|
||||
// 权限编码控制是否显示
|
||||
auth?: RoleEnum | RoleEnum[] | string | string[];
|
||||
// 业务控制是否显示
|
||||
ifShow?: boolean | ((action: ActionItem) => boolean);
|
||||
tooltip?: string | TooltipProps;
|
||||
onClick?: Fn;
|
||||
label?: string;
|
||||
color?: 'success' | 'error' | 'warning';
|
||||
icon?: string;
|
||||
popConfirm?: PopConfirm;
|
||||
disabled?: boolean;
|
||||
divider?: boolean;
|
||||
// 权限编码控制是否显示
|
||||
auth?: RoleEnum | RoleEnum[] | string | string[];
|
||||
// 业务控制是否显示
|
||||
ifShow?: boolean | ((action: ActionItem) => boolean);
|
||||
}
|
||||
|
||||
export interface PopConfirm {
|
||||
title: string;
|
||||
okText?: string;
|
||||
cancelText?: string;
|
||||
confirm: Fn;
|
||||
cancel?: Fn;
|
||||
icon?: string;
|
||||
title: string;
|
||||
okText?: string;
|
||||
cancelText?: string;
|
||||
confirm: Fn;
|
||||
cancel?: Fn;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user