feat(table): add table component
This commit is contained in:
parent
5b0a21ecb0
commit
faf3f4602e
|
|
@ -30,5 +30,5 @@ categories:
|
||||||
- 'workflow'
|
- 'workflow'
|
||||||
change-template: '- $TITLE (#$NUMBER) @$AUTHOR'
|
change-template: '- $TITLE (#$NUMBER) @$AUTHOR'
|
||||||
template: |
|
template: |
|
||||||
# Changes
|
# What's Changed
|
||||||
$CHANGES
|
$CHANGES
|
||||||
|
|
|
||||||
20
README.md
20
README.md
|
|
@ -15,12 +15,10 @@
|
||||||
|
|
||||||
项目基于`ant-design-vue`,`typescript`,`vue3.0`,`vite`,`tailwindcss`,`tsx`实现的 vue3 风格的后台管理系统,
|
项目基于`ant-design-vue`,`typescript`,`vue3.0`,`vite`,`tailwindcss`,`tsx`实现的 vue3 风格的后台管理系统,
|
||||||
|
|
||||||
|
|
||||||
### gitHub 地址
|
### gitHub 地址
|
||||||
|
|
||||||
[vue-vben-admin2.0](https://github.com/anncwb/vue-vben-admin)
|
[vue-vben-admin2.0](https://github.com/anncwb/vue-vben-admin)
|
||||||
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img alt="VbenAdmin Logo" width="100%" src="./build/docs/imgs/preview1.png">
|
<img alt="VbenAdmin Logo" width="100%" src="./build/docs/imgs/preview1.png">
|
||||||
<img alt="VbenAdmin Logo" width="100%" src="./build/docs/imgs/preview2.png">
|
<img alt="VbenAdmin Logo" width="100%" src="./build/docs/imgs/preview2.png">
|
||||||
|
|
@ -31,10 +29,6 @@
|
||||||
|
|
||||||
2.0 文档还没开始写。后续补上。。
|
2.0 文档还没开始写。后续补上。。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 使用到的技术
|
## 使用到的技术
|
||||||
|
|
||||||
- vue3
|
- vue3
|
||||||
|
|
@ -84,7 +78,6 @@ VSCode 插件
|
||||||
- `stylelint`: 样式代码检查
|
- `stylelint`: 样式代码检查
|
||||||
- `Prettier - Code formatter`:代码格式化
|
- `Prettier - Code formatter`:代码格式化
|
||||||
|
|
||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
|
@ -122,7 +115,6 @@ yarn build:no-cache # 打包 不会使用hardSource进行打包
|
||||||
yarn report # 生成构建包表表预览
|
yarn report # 生成构建包表表预览
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### 格式化
|
### 格式化
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -159,7 +151,6 @@ yarn log # 生成CHANGELOG
|
||||||
- `mod` 不确定分类的修改
|
- `mod` 不确定分类的修改
|
||||||
- `wip` 删除文件
|
- `wip` 删除文件
|
||||||
|
|
||||||
|
|
||||||
## 代码贡献
|
## 代码贡献
|
||||||
|
|
||||||
1. Fork 代码!
|
1. Fork 代码!
|
||||||
|
|
@ -205,20 +196,19 @@ yarn log # 生成CHANGELOG
|
||||||
- [x] 树组件
|
- [x] 树组件
|
||||||
- [x] 系统性能优化
|
- [x] 系统性能优化
|
||||||
- [x] 兼容最新`vuex`,`vue-router`
|
- [x] 兼容最新`vuex`,`vue-router`
|
||||||
- [] 图片预览组件
|
- [x] 图片预览组件
|
||||||
|
- [ ] 表格组件
|
||||||
|
- [ ] 可编辑表格
|
||||||
- [ ] 图表库
|
- [ ] 图表库
|
||||||
- [ ] 数字动画
|
- [ ] 数字动画
|
||||||
- [ ] 主题配置
|
- [ ] 主题配置
|
||||||
- [ ] 表格组件
|
|
||||||
- [ ] 富文本组件
|
- [ ] 富文本组件
|
||||||
- [ ] 首屏加载等待动画
|
- [ ] 首屏加载等待动画
|
||||||
- [ ] 上传组件
|
- [ ] 上传组件
|
||||||
- [ ] 可编辑表格
|
|
||||||
- [ ] 数据导入导出
|
- [ ] 数据导入导出
|
||||||
- [ ] 搭建`vite`版本
|
|
||||||
- [ ] 懒加载组件
|
|
||||||
- [ ] 黑暗主题
|
- [ ] 黑暗主题
|
||||||
- [ ] 更多组件/功能/建议/bug/欢迎提交 pr 或者 issue
|
|
||||||
|
更多组件/功能/建议/bug/欢迎提交 pr 或者 issue
|
||||||
|
|
||||||
## 加入我们
|
## 加入我们
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer';
|
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer';
|
||||||
import userMock from './sys/user';
|
import userMock from './sys/user';
|
||||||
import menuMock from './sys/menu';
|
import menuMock from './sys/menu';
|
||||||
|
import tableDemoMock from './demo/table-demo';
|
||||||
|
|
||||||
export function setupProdMockServer() {
|
export function setupProdMockServer() {
|
||||||
createProdMockServer([...userMock, ...menuMock]);
|
createProdMockServer([...userMock, ...menuMock, ...tableDemoMock]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,19 @@ export function resultSuccess<T = any>(result: T, { message = 'ok' } = {}) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resultPageSuccess<T = any>(items: T[], total: number, { message = 'ok' } = {}) {
|
export function resultPageSuccess<T = any>(
|
||||||
|
page: number,
|
||||||
|
pageSize: number,
|
||||||
|
list: T[],
|
||||||
|
{ message = 'ok' } = {}
|
||||||
|
) {
|
||||||
|
const pageData = pagination(page, pageSize, list);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code: 0,
|
code: 0,
|
||||||
result: {
|
result: {
|
||||||
items,
|
items: pageData,
|
||||||
total,
|
total: list.length,
|
||||||
},
|
},
|
||||||
message,
|
message,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { MockMethod } from 'vite-plugin-mock';
|
||||||
|
import { resultPageSuccess } from '../_util';
|
||||||
|
|
||||||
|
const demoList = (() => {
|
||||||
|
const result: any[] = [];
|
||||||
|
for (let index = 0; index < 60; index++) {
|
||||||
|
result.push({
|
||||||
|
id: `${index}`,
|
||||||
|
beginTime: '@datetime',
|
||||||
|
endTime: '@datetime',
|
||||||
|
address: '@city()',
|
||||||
|
name: '@cname()',
|
||||||
|
'no|100000-10000000': 100000,
|
||||||
|
'status|1': ['正常', '启用', '停用'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
})();
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
url: '/api/table/getDemoList',
|
||||||
|
timeout: 1000,
|
||||||
|
method: 'get',
|
||||||
|
response: ({ query }) => {
|
||||||
|
const { page = 1, pageSize = 20 } = query;
|
||||||
|
return resultPageSuccess(page, pageSize, demoList);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] as MockMethod[];
|
||||||
10
src/App.vue
10
src/App.vue
|
|
@ -1,10 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<ConfigProvider
|
<ConfigProvider :locale="zhCN" :transformCellText="transformCellText" v-bind="lockOn">
|
||||||
:locale="zhCN"
|
|
||||||
:renderEmpty="renderEmpty"
|
|
||||||
:transformCellText="transformCellText"
|
|
||||||
v-bind="lockOn"
|
|
||||||
>
|
|
||||||
<router-view />
|
<router-view />
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -28,10 +23,9 @@
|
||||||
useInitAppConfigStore();
|
useInitAppConfigStore();
|
||||||
useListenerNetWork();
|
useListenerNetWork();
|
||||||
createBreakpointListen();
|
createBreakpointListen();
|
||||||
const { renderEmpty, transformCellText } = useConfigProvider();
|
const { transformCellText } = useConfigProvider();
|
||||||
const { on: lockOn } = useLockPage();
|
const { on: lockOn } = useLockPage();
|
||||||
return {
|
return {
|
||||||
renderEmpty,
|
|
||||||
transformCellText,
|
transformCellText,
|
||||||
zhCN,
|
zhCN,
|
||||||
lockOn,
|
lockOn,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel';
|
||||||
|
/**
|
||||||
|
* @description: 请求列表接口参数
|
||||||
|
*/
|
||||||
|
export type DemoParams = BasicPageParams;
|
||||||
|
|
||||||
|
export interface DemoListItem {
|
||||||
|
id: string;
|
||||||
|
beginTime: string;
|
||||||
|
endTime: string;
|
||||||
|
address: string;
|
||||||
|
name: string;
|
||||||
|
no: number;
|
||||||
|
status: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 请求列表返回值
|
||||||
|
*/
|
||||||
|
export type DemoListGetResultModel = BasicFetchResult<DemoListItem>;
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { defHttp } from '/@/utils/http/axios';
|
||||||
|
import { DemoParams, DemoListGetResultModel } from './model/tableModel';
|
||||||
|
|
||||||
|
enum Api {
|
||||||
|
DEMO_LIST = '/table/getDemoList',
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 获取示例列表值
|
||||||
|
*/
|
||||||
|
export function demoListApi(params: DemoParams) {
|
||||||
|
return defHttp.request<DemoListGetResultModel>({
|
||||||
|
url: Api.DEMO_LIST,
|
||||||
|
method: 'GET',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
export interface BasicPageParams {
|
||||||
|
page: number;
|
||||||
|
pageSize: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BasicFetchResult<T extends any> {
|
||||||
|
items: T;
|
||||||
|
total: number;
|
||||||
|
}
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 372 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.9 KiB |
|
|
@ -1,4 +1,3 @@
|
||||||
export { default as BasicArrow } from './src/BasicArrow.vue';
|
export { default as BasicArrow } from './src/BasicArrow.vue';
|
||||||
export { default as BasicHelp } from './src/BasicHelp';
|
export { default as BasicHelp } from './src/BasicHelp';
|
||||||
export { default as BasicTitle } from './src/BasicTitle.vue';
|
export { default as BasicTitle } from './src/BasicTitle.vue';
|
||||||
export { default as BasicEmpty } from './src/BasicEmpty.vue';
|
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,16 @@
|
||||||
|
|
||||||
&.right {
|
&.right {
|
||||||
transform: rotate(0deg);
|
transform: rotate(0deg);
|
||||||
}
|
|
||||||
|
|
||||||
&__active {
|
> span {
|
||||||
transform: rotate(90deg) !important;
|
|
||||||
transition: all 0.3s ease 0.1s !important;
|
transition: all 0.3s ease 0.1s !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__active {
|
||||||
|
> span {
|
||||||
|
transform: rotate(90deg) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
<template>
|
|
||||||
<Empty :image="image" :description="description" />
|
|
||||||
</template>
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import { Empty } from 'ant-design-vue';
|
|
||||||
|
|
||||||
import emptySrc from '/@/assets/images/page_null.png';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
extends: Empty as any,
|
|
||||||
components: { Empty },
|
|
||||||
props: {
|
|
||||||
description: {
|
|
||||||
type: String,
|
|
||||||
default: '暂无内容',
|
|
||||||
},
|
|
||||||
image: {
|
|
||||||
type: String,
|
|
||||||
default: emptySrc,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<Button v-bind="getBindValue" :class="[getColor, $attrs.class]">
|
<Button v-bind="getBindValue" :class="[getColor, $attrs.class]">
|
||||||
<template v-slot:[item] v-for="item in Object.keys($slots)">
|
<template #[item]="data" v-for="item in Object.keys($slots)">
|
||||||
<slot :name="item" />
|
<slot :name="item" v-bind="data" />
|
||||||
</template>
|
</template>
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="collapse-container__body" v-else v-show="show">
|
<div class="collapse-container__body" v-else v-show="show">
|
||||||
<LazyContainer :timeout="lazyTime" v-if="lazy">
|
<LazyContainer :timeout="lazyTime" v-if="lazy">
|
||||||
<slot />
|
<slot />
|
||||||
<template v-slot:skeleton>
|
<template #skeleton>
|
||||||
<slot name="lazySkeleton" />
|
<slot name="lazySkeleton" />
|
||||||
</template>
|
</template>
|
||||||
</LazyContainer>
|
</LazyContainer>
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
:allDefaultValues="getAllDefaultValues"
|
:allDefaultValues="getAllDefaultValues"
|
||||||
:formModel="formModel"
|
:formModel="formModel"
|
||||||
>
|
>
|
||||||
<template v-slot:[item] v-for="item in Object.keys($slots)">
|
<template #[item]="data" v-for="item in Object.keys($slots)">
|
||||||
<slot :name="item" />
|
<slot :name="item" v-bind="data" />
|
||||||
</template>
|
</template>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
export { default as BasicTable } from './src/BasicTable.vue';
|
||||||
|
export { default as TableAction } from './src/components/TableAction';
|
||||||
|
export { default as TableImg } from './src/components/TableImg.vue';
|
||||||
|
export { renderEditableCell } from './src/components/renderEditableCell';
|
||||||
|
export { default as EditTableHeaderIcon } from './src/components/EditTableHeaderIcon.vue';
|
||||||
|
|
||||||
|
export * from './src/types/table';
|
||||||
|
export * from './src/types/pagination';
|
||||||
|
export * from './src/types/tableAction';
|
||||||
|
|
||||||
|
export { useTable } from './src/hooks/useTable';
|
||||||
|
|
||||||
|
export type { FormSchema, FormProps } from '/@/components/Form/src/types/form';
|
||||||
|
|
@ -0,0 +1,285 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="basic-table"
|
||||||
|
:class="{
|
||||||
|
'table-form-container': getBindValues.useSearchForm,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<BasicForm
|
||||||
|
v-bind="getFormProps"
|
||||||
|
v-if="getBindValues.useSearchForm"
|
||||||
|
:submitButtonOptions="{ loading }"
|
||||||
|
@register="registerForm"
|
||||||
|
@submit="handleSearchInfoChange"
|
||||||
|
@advanced-change="redoHeight"
|
||||||
|
>
|
||||||
|
<template #[item]="data" v-for="item in Object.keys($slots)">
|
||||||
|
<slot :name="`form-${item}`" v-bind="data" />
|
||||||
|
</template>
|
||||||
|
</BasicForm>
|
||||||
|
<Table
|
||||||
|
ref="tableElRef"
|
||||||
|
v-bind="getBindValues"
|
||||||
|
:rowClassName="getRowClassName"
|
||||||
|
:class="{
|
||||||
|
hidden: !getEmptyDataIsShowTable,
|
||||||
|
}"
|
||||||
|
@change="handleTableChange"
|
||||||
|
>
|
||||||
|
<template #[item]="data" v-for="item in Object.keys($slots)">
|
||||||
|
<slot :name="item" v-bind="data" />
|
||||||
|
</template>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref, computed, unref, watch, nextTick } from 'vue';
|
||||||
|
import { Table } from 'ant-design-vue';
|
||||||
|
import { basicProps } from './props';
|
||||||
|
import type {
|
||||||
|
BasicTableProps,
|
||||||
|
FetchParams,
|
||||||
|
GetColumnsParams,
|
||||||
|
TableActionType,
|
||||||
|
} from './types/table';
|
||||||
|
import { isFunction, isString } from '/@/utils/is';
|
||||||
|
|
||||||
|
import renderTitle from './components/renderTitle';
|
||||||
|
import renderFooter from './components/renderFooter';
|
||||||
|
import renderExpandIcon from './components/renderExpandIcon';
|
||||||
|
|
||||||
|
import { usePagination } from './hooks/usePagination';
|
||||||
|
import { useColumns } from './hooks/useColumns';
|
||||||
|
import { useDataSource } from './hooks/useDataSource';
|
||||||
|
import { useLoading } from './hooks/useLoading';
|
||||||
|
import { useRowSelection } from './hooks/useRowSelection';
|
||||||
|
import { useTableScroll } from './hooks/useTableScroll';
|
||||||
|
import { provideTable } from './hooks/useProvinceTable';
|
||||||
|
import { BasicForm, FormProps, useForm } from '/@/components/Form/index';
|
||||||
|
import { omit } from 'lodash-es';
|
||||||
|
import './style/index.less';
|
||||||
|
import { ROW_KEY } from './const';
|
||||||
|
import { PaginationProps } from './types/pagination';
|
||||||
|
import { deepMerge } from '/@/utils';
|
||||||
|
import { TableCustomRecord } from 'ant-design-vue/types/table/table';
|
||||||
|
import { useEvent } from '/@/hooks/event/useEvent';
|
||||||
|
export default defineComponent({
|
||||||
|
props: basicProps,
|
||||||
|
components: { Table, BasicForm },
|
||||||
|
emits: ['fetch-success', 'fetch-error', 'selection-change', 'register'],
|
||||||
|
setup(props, { attrs, emit, slots }) {
|
||||||
|
const tableElRef = ref<any>(null);
|
||||||
|
const innerPropsRef = ref<Partial<BasicTableProps>>();
|
||||||
|
const [registerForm, { getFieldsValue }] = useForm();
|
||||||
|
|
||||||
|
const getMergeProps = computed(
|
||||||
|
(): BasicTableProps => {
|
||||||
|
return {
|
||||||
|
...props,
|
||||||
|
...unref(innerPropsRef),
|
||||||
|
} as BasicTableProps;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const { loadingRef } = useLoading(getMergeProps);
|
||||||
|
const { getPaginationRef, setPagination } = usePagination(getMergeProps);
|
||||||
|
const { getColumnsRef, setColumns } = useColumns(getMergeProps, getPaginationRef);
|
||||||
|
const { getDataSourceRef, setTableData, fetch, getAutoCreateKey } = useDataSource(
|
||||||
|
getMergeProps,
|
||||||
|
{
|
||||||
|
getPaginationRef,
|
||||||
|
loadingRef,
|
||||||
|
setPagination,
|
||||||
|
getFieldsValue,
|
||||||
|
},
|
||||||
|
emit
|
||||||
|
);
|
||||||
|
const { getScrollRef, redoHeight } = useTableScroll(getMergeProps, tableElRef);
|
||||||
|
const {
|
||||||
|
getRowSelectionRef,
|
||||||
|
getSelectRows,
|
||||||
|
clearSelectedRowKeys,
|
||||||
|
getSelectRowKeys,
|
||||||
|
deleteSelectRowByKey,
|
||||||
|
setSelectedRowKeys,
|
||||||
|
} = useRowSelection(getMergeProps, emit);
|
||||||
|
|
||||||
|
const getRowKey = computed(() => {
|
||||||
|
const { rowKey } = unref(getMergeProps);
|
||||||
|
|
||||||
|
return unref(getAutoCreateKey) ? ROW_KEY : rowKey;
|
||||||
|
});
|
||||||
|
const getBindValues = computed(() => {
|
||||||
|
const { title, titleHelpMessage, showSummary } = unref(getMergeProps);
|
||||||
|
const titleData: any =
|
||||||
|
!slots.tableTitle && !isString(title) && !title && !slots.toolbar
|
||||||
|
? {}
|
||||||
|
: {
|
||||||
|
title:
|
||||||
|
!slots.tableTitle && !title && !slots.toolbar
|
||||||
|
? null
|
||||||
|
: renderTitle.bind(null, title, titleHelpMessage, slots),
|
||||||
|
};
|
||||||
|
const pagination = unref(getPaginationRef);
|
||||||
|
const rowSelection = unref(getRowSelectionRef);
|
||||||
|
const scroll = unref(getScrollRef);
|
||||||
|
const loading = unref(loadingRef);
|
||||||
|
const rowKey = unref(getRowKey);
|
||||||
|
const columns = unref(getColumnsRef);
|
||||||
|
const dataSource = unref(getDataSourceRef);
|
||||||
|
let propsData = {
|
||||||
|
size: 'middle',
|
||||||
|
...(slots.expandedRowRender ? { expandIcon: renderExpandIcon() } : {}),
|
||||||
|
...attrs,
|
||||||
|
...unref(getMergeProps),
|
||||||
|
...titleData,
|
||||||
|
scroll,
|
||||||
|
loading,
|
||||||
|
tableLayout: 'fixed',
|
||||||
|
rowSelection,
|
||||||
|
rowKey,
|
||||||
|
columns,
|
||||||
|
pagination,
|
||||||
|
dataSource,
|
||||||
|
};
|
||||||
|
if (slots.expandedRowRender) {
|
||||||
|
propsData = omit(propsData, 'scroll');
|
||||||
|
}
|
||||||
|
if (showSummary) {
|
||||||
|
propsData.footer = renderFooter.bind(null, {
|
||||||
|
scroll,
|
||||||
|
columnsRef: getColumnsRef,
|
||||||
|
summaryFunc: unref(getMergeProps).summaryFunc,
|
||||||
|
dataSourceRef: getDataSourceRef,
|
||||||
|
rowSelectionRef: getRowSelectionRef,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return propsData;
|
||||||
|
});
|
||||||
|
const getFormProps = computed(() => {
|
||||||
|
const { formConfig } = unref(getBindValues);
|
||||||
|
const formProps: FormProps = {
|
||||||
|
showAdvancedButton: true,
|
||||||
|
...(formConfig as FormProps),
|
||||||
|
compact: true,
|
||||||
|
};
|
||||||
|
return formProps;
|
||||||
|
});
|
||||||
|
|
||||||
|
const getEmptyDataIsShowTable = computed(() => {
|
||||||
|
const { emptyDataIsShowTable, useSearchForm } = unref(getMergeProps);
|
||||||
|
if (emptyDataIsShowTable || !useSearchForm) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return !!unref(getDataSourceRef).length;
|
||||||
|
});
|
||||||
|
|
||||||
|
function getRowClassName(record: TableCustomRecord<any>, index: number) {
|
||||||
|
const { striped, rowClassName } = unref(getMergeProps);
|
||||||
|
if (!striped) return;
|
||||||
|
if (rowClassName && isFunction(rowClassName)) {
|
||||||
|
return rowClassName(record);
|
||||||
|
}
|
||||||
|
return (index || 0) % 2 === 1 ? 'basic-table-row__striped' : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSearchInfoChange(info: any) {
|
||||||
|
const { handleSearchInfoFn } = unref(getMergeProps);
|
||||||
|
if (handleSearchInfoFn && isFunction(handleSearchInfoFn)) {
|
||||||
|
info = handleSearchInfoFn(info) || info;
|
||||||
|
}
|
||||||
|
fetch({ searchInfo: info, page: 1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTableChange(pagination: PaginationProps) {
|
||||||
|
const { clearSelectOnPageChange } = unref(getMergeProps);
|
||||||
|
if (clearSelectOnPageChange) {
|
||||||
|
clearSelectedRowKeys();
|
||||||
|
}
|
||||||
|
setPagination(pagination);
|
||||||
|
fetch();
|
||||||
|
}
|
||||||
|
watch(
|
||||||
|
() => unref(getDataSourceRef),
|
||||||
|
() => {
|
||||||
|
if (unref(getMergeProps).showSummary) {
|
||||||
|
nextTick(() => {
|
||||||
|
const tableEl = unref(tableElRef);
|
||||||
|
if (!tableEl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const bodyDomList = tableEl.$el.querySelectorAll(
|
||||||
|
'.ant-table-body'
|
||||||
|
) as HTMLDivElement[];
|
||||||
|
const bodyDom = bodyDomList[0];
|
||||||
|
useEvent({
|
||||||
|
el: bodyDom,
|
||||||
|
name: 'scroll',
|
||||||
|
listener: () => {
|
||||||
|
const footerBodyDom = tableEl.$el.querySelector(
|
||||||
|
'.ant-table-footer .ant-table-body'
|
||||||
|
) as HTMLDivElement;
|
||||||
|
if (!footerBodyDom || !bodyDom) return;
|
||||||
|
footerBodyDom.scrollLeft = bodyDom.scrollLeft;
|
||||||
|
},
|
||||||
|
wait: 0,
|
||||||
|
options: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const tableAction: TableActionType = {
|
||||||
|
reload: async (opt?: FetchParams) => {
|
||||||
|
await fetch(opt);
|
||||||
|
},
|
||||||
|
getSelectRows,
|
||||||
|
clearSelectedRowKeys,
|
||||||
|
getSelectRowKeys,
|
||||||
|
deleteSelectRowByKey,
|
||||||
|
setPagination,
|
||||||
|
setTableData,
|
||||||
|
redoHeight,
|
||||||
|
setSelectedRowKeys,
|
||||||
|
setColumns,
|
||||||
|
getPaginationRef: () => {
|
||||||
|
return unref(getPaginationRef);
|
||||||
|
},
|
||||||
|
getColumns: (opt?: GetColumnsParams) => {
|
||||||
|
const { ignoreIndex } = opt || {};
|
||||||
|
let columns = unref(getColumnsRef);
|
||||||
|
if (ignoreIndex) {
|
||||||
|
columns = columns.filter((item) => item.flag !== 'INDEX');
|
||||||
|
}
|
||||||
|
return columns;
|
||||||
|
},
|
||||||
|
getDataSource: () => {
|
||||||
|
return unref(getDataSourceRef);
|
||||||
|
},
|
||||||
|
setLoading: (loading: boolean) => {
|
||||||
|
loadingRef.value = loading;
|
||||||
|
},
|
||||||
|
setProps: (props: Partial<BasicTableProps>) => {
|
||||||
|
innerPropsRef.value = deepMerge(unref(innerPropsRef) || {}, props);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
provideTable(tableAction);
|
||||||
|
|
||||||
|
emit('register', tableAction);
|
||||||
|
return {
|
||||||
|
tableElRef,
|
||||||
|
getBindValues,
|
||||||
|
loading: loadingRef,
|
||||||
|
registerForm,
|
||||||
|
handleSearchInfoChange,
|
||||||
|
getFormProps,
|
||||||
|
getEmptyDataIsShowTable,
|
||||||
|
handleTableChange,
|
||||||
|
getRowClassName,
|
||||||
|
...tableAction,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { Component } from 'vue';
|
||||||
|
|
||||||
|
import { Input, Select, Checkbox, InputNumber, Switch } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { ComponentType } from './types/componentType';
|
||||||
|
|
||||||
|
const componentMap = new Map<ComponentType, Component>();
|
||||||
|
|
||||||
|
componentMap.set('Input', Input);
|
||||||
|
componentMap.set('InputPassword', Input.Password);
|
||||||
|
componentMap.set('InputNumber', InputNumber);
|
||||||
|
|
||||||
|
componentMap.set('Select', Select);
|
||||||
|
componentMap.set('Switch', Switch);
|
||||||
|
componentMap.set('Checkbox', Checkbox);
|
||||||
|
componentMap.set('CheckboxGroup', Checkbox.Group);
|
||||||
|
|
||||||
|
export function add(compName: ComponentType, component: Component) {
|
||||||
|
componentMap.set(compName, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function del(compName: ComponentType) {
|
||||||
|
componentMap.delete(compName);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { componentMap };
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { defineComponent, ref, computed, unref } from 'vue';
|
||||||
|
import { injectTable } from '../hooks/useProvinceTable';
|
||||||
|
import { getSlot } from '/@/utils/helper/tsxHelper';
|
||||||
|
|
||||||
|
import VueDraggableResizable from 'vue-draggable-resizable';
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'DragResize',
|
||||||
|
setup(props, { slots, attrs }) {
|
||||||
|
const elRef = ref<HTMLTableRowElement | null>(null);
|
||||||
|
const draggingMapRef = ref<{ [key in string]: number | string }>({});
|
||||||
|
|
||||||
|
const tableInstance = injectTable();
|
||||||
|
|
||||||
|
const getColumnsRef = computed(() => {
|
||||||
|
const columns = tableInstance.getColumns();
|
||||||
|
columns.forEach((col) => {
|
||||||
|
const { key } = col;
|
||||||
|
if (key) {
|
||||||
|
draggingMapRef.value[key] = col.width as number;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return columns;
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
const { key = '', ...restProps } = { ...attrs };
|
||||||
|
const col = unref(getColumnsRef).find((col) => {
|
||||||
|
const k = col.dataIndex || col.key;
|
||||||
|
return k === key;
|
||||||
|
});
|
||||||
|
if (!col || !col.width) {
|
||||||
|
return <th {...restProps}>{getSlot(slots, 'default')}</th>;
|
||||||
|
}
|
||||||
|
const onDrag = (x: number) => {
|
||||||
|
draggingMapRef.value[key] = 0;
|
||||||
|
col.width = Math.max(x, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDragstop = () => {
|
||||||
|
const el = unref(elRef);
|
||||||
|
if (!el) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
draggingMapRef.value[key] = el.getBoundingClientRect().width;
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<th
|
||||||
|
{...restProps}
|
||||||
|
class="resize-table-th"
|
||||||
|
ref={elRef}
|
||||||
|
style={{
|
||||||
|
width: `${col.width}px`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{getSlot(slots, 'default')}
|
||||||
|
<VueDraggableResizable
|
||||||
|
key={col.key}
|
||||||
|
class="table-draggable-handle"
|
||||||
|
w={10}
|
||||||
|
x={draggingMapRef.value[key] || col.width}
|
||||||
|
z={1}
|
||||||
|
axis="x"
|
||||||
|
draggable={true}
|
||||||
|
resizable={false}
|
||||||
|
onDragging={onDrag}
|
||||||
|
onDragstop={onDragstop}
|
||||||
|
/>
|
||||||
|
</th>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<template>
|
||||||
|
<span>
|
||||||
|
{{ title }}
|
||||||
|
<FormOutlined class="ml-2" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, PropType } from 'vue';
|
||||||
|
import { FormOutlined } from '@ant-design/icons-vue';
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'EditTableHeaderIcon',
|
||||||
|
components: { FormOutlined },
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String as PropType<string>,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup() {},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
import { defineComponent, PropType } from 'vue';
|
||||||
|
import { Dropdown, Menu, Popconfirm } from 'ant-design-vue';
|
||||||
|
import Icon from '/@/components/Icon/index';
|
||||||
|
import { DownOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { ActionItem } from '../types/tableAction';
|
||||||
|
import Button from '/@/components/Button/index.vue';
|
||||||
|
const prefixCls = 'basic-table-action';
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'TableAction',
|
||||||
|
props: {
|
||||||
|
actions: {
|
||||||
|
type: Array as PropType<ActionItem[]>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
dropDownActions: {
|
||||||
|
type: Array as PropType<ActionItem[]>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
// 增加按钮的TYPE和COLOR
|
||||||
|
return () => {
|
||||||
|
const { dropDownActions = [], actions } = props;
|
||||||
|
return (
|
||||||
|
<div class={prefixCls}>
|
||||||
|
{actions &&
|
||||||
|
actions.length &&
|
||||||
|
actions.map((action, index) => {
|
||||||
|
const {
|
||||||
|
disabled = false,
|
||||||
|
label,
|
||||||
|
props,
|
||||||
|
icon,
|
||||||
|
color = '',
|
||||||
|
type = 'link',
|
||||||
|
popConfirm = null,
|
||||||
|
} = action;
|
||||||
|
const button = (
|
||||||
|
<Button
|
||||||
|
type={type}
|
||||||
|
size="small"
|
||||||
|
disabled={disabled}
|
||||||
|
color={color}
|
||||||
|
{...props}
|
||||||
|
key={index}
|
||||||
|
>
|
||||||
|
{() => (
|
||||||
|
<>
|
||||||
|
{label}
|
||||||
|
{icon && <Icon icon={icon} />}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
if (popConfirm !== null) {
|
||||||
|
const {
|
||||||
|
title,
|
||||||
|
okText = '确定',
|
||||||
|
cancelText = '取消',
|
||||||
|
confirm = () => {},
|
||||||
|
cancel = () => {},
|
||||||
|
icon = '',
|
||||||
|
} = popConfirm;
|
||||||
|
return (
|
||||||
|
<Popconfirm
|
||||||
|
key={`P-${index}`}
|
||||||
|
title={title}
|
||||||
|
onConfirm={confirm}
|
||||||
|
onCancel={cancel}
|
||||||
|
okText={okText}
|
||||||
|
cancelText={cancelText}
|
||||||
|
icon={icon}
|
||||||
|
>
|
||||||
|
{() => button}
|
||||||
|
</Popconfirm>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return button;
|
||||||
|
})}
|
||||||
|
{dropDownActions && dropDownActions.length && (
|
||||||
|
<Dropdown>
|
||||||
|
{{
|
||||||
|
default: () => (
|
||||||
|
<Button type="link" size="small">
|
||||||
|
{{
|
||||||
|
default: () => (
|
||||||
|
<>
|
||||||
|
更多
|
||||||
|
<DownOutlined />
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
overlay: () => {
|
||||||
|
return (
|
||||||
|
<Menu>
|
||||||
|
{{
|
||||||
|
default: () => {
|
||||||
|
return dropDownActions.map((action, index) => {
|
||||||
|
const {
|
||||||
|
disabled = false,
|
||||||
|
label,
|
||||||
|
props,
|
||||||
|
icon,
|
||||||
|
color = '',
|
||||||
|
type = 'link',
|
||||||
|
} = action;
|
||||||
|
return (
|
||||||
|
<Menu.Item key={`${index}`} disabled={disabled}>
|
||||||
|
{() => (
|
||||||
|
<Button
|
||||||
|
type={type}
|
||||||
|
size="small"
|
||||||
|
{...props}
|
||||||
|
disabled={disabled}
|
||||||
|
color={color}
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
default: () => (
|
||||||
|
<>
|
||||||
|
{label}
|
||||||
|
{icon && <Icon icon={icon} />}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Menu.Item>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
</Dropdown>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<template>
|
||||||
|
<div class="basic-table-img__preview" v-if="imgList && imgList.length">
|
||||||
|
<template v-for="(img, index) in imgList" :key="img">
|
||||||
|
<img :width="size" @click="handlePreview(index)" :src="img" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, PropType } from 'vue';
|
||||||
|
import { createImgPreview } from '/@/components/Preview/index';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'TableAction',
|
||||||
|
props: {
|
||||||
|
imgList: {
|
||||||
|
type: Array as PropType<string[]>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: Number as PropType<number>,
|
||||||
|
default: 40,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
function handlePreview(index: number) {
|
||||||
|
const { imgList } = props;
|
||||||
|
|
||||||
|
createImgPreview({
|
||||||
|
imageList: imgList as string[],
|
||||||
|
index: index,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return { handlePreview };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
<template>
|
||||||
|
<BasicTitle class="basic-table-title" v-if="tableTitle" :helpMessage="helpMessage">
|
||||||
|
{{ tableTitle }}
|
||||||
|
</BasicTitle>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { computed, defineComponent, PropType } from 'vue';
|
||||||
|
|
||||||
|
import { BasicTitle } from '/@/components/Basic/index';
|
||||||
|
import { isFunction } from '/@/utils/is';
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'TableTitle',
|
||||||
|
components: { BasicTitle },
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: [Function, String] as PropType<string | ((data: any) => string)>,
|
||||||
|
},
|
||||||
|
getSelectRows: {
|
||||||
|
type: Function as PropType<() => any[]>,
|
||||||
|
},
|
||||||
|
helpMessage: {
|
||||||
|
type: [String, Array] as PropType<string | string[]>,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
const tableTitle = computed(() => {
|
||||||
|
const { title, getSelectRows = () => {} } = props;
|
||||||
|
let tit = title;
|
||||||
|
|
||||||
|
if (isFunction(title)) {
|
||||||
|
tit = title({
|
||||||
|
selectRows: getSelectRows(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return tit;
|
||||||
|
});
|
||||||
|
|
||||||
|
return { tableTitle };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
import { defineComponent, PropType, ref, unref, nextTick } from 'vue';
|
||||||
|
import { injectTable } from '../hooks/useProvinceTable';
|
||||||
|
import ClickOutSide from '/@/components/ClickOutSide/index.vue';
|
||||||
|
|
||||||
|
import { RenderEditableCellParams } from '../types/table';
|
||||||
|
import { ComponentType } from '../types/componentType';
|
||||||
|
|
||||||
|
import { componentMap } from '../componentMap';
|
||||||
|
import '../style/editable-cell.less';
|
||||||
|
import { isString, isBoolean } from '/@/utils/is';
|
||||||
|
import { FormOutlined, CloseOutlined, CheckOutlined } from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
const prefixCls = 'editable-cell';
|
||||||
|
const EditableCell = defineComponent({
|
||||||
|
name: 'EditableCell',
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: String as PropType<string>,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
type: Object as PropType<any>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
|
||||||
|
dataKey: {
|
||||||
|
type: String as PropType<string>,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
|
||||||
|
dataIndex: {
|
||||||
|
type: String as PropType<string>,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
|
||||||
|
component: {
|
||||||
|
type: String as PropType<ComponentType>,
|
||||||
|
default: 'Input',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props, { attrs }) {
|
||||||
|
const table = injectTable();
|
||||||
|
const elRef = ref<any>(null);
|
||||||
|
|
||||||
|
const isEditRef = ref(false);
|
||||||
|
const currentValueRef = ref<string | boolean>('');
|
||||||
|
|
||||||
|
function handleChange(e: ChangeEvent | string | boolean) {
|
||||||
|
if ((e as ChangeEvent).target && Reflect.has((e as ChangeEvent).target, 'value')) {
|
||||||
|
currentValueRef.value = (e as ChangeEvent).target.value;
|
||||||
|
}
|
||||||
|
if (isString(e) || isBoolean(e)) {
|
||||||
|
currentValueRef.value = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleEdit() {
|
||||||
|
isEditRef.value = true;
|
||||||
|
nextTick(() => {
|
||||||
|
const el = unref(elRef);
|
||||||
|
el && el.focus && el.focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCancel() {
|
||||||
|
isEditRef.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSubmit() {
|
||||||
|
const { dataKey, dataIndex } = props;
|
||||||
|
if (!dataKey || !dataIndex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isEditRef.value = false;
|
||||||
|
|
||||||
|
const { getDataSource } = table;
|
||||||
|
const dataSource = getDataSource();
|
||||||
|
const target = dataSource.find((item) => item.key === dataKey);
|
||||||
|
if (target) {
|
||||||
|
target[dataIndex] = unref(currentValueRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClickOutside() {
|
||||||
|
const { component } = props;
|
||||||
|
|
||||||
|
if (component?.includes('Input')) {
|
||||||
|
handleCancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
const { value, component, componentProps = {} } = props;
|
||||||
|
|
||||||
|
const Comp = componentMap.get(component!) as any;
|
||||||
|
// const propsData: any = {};
|
||||||
|
return (
|
||||||
|
<div class={prefixCls}>
|
||||||
|
{unref(isEditRef) && (
|
||||||
|
<ClickOutSide onClickOutside={onClickOutside}>
|
||||||
|
{() => (
|
||||||
|
<div class={`${prefixCls}__wrapper`}>
|
||||||
|
<Comp
|
||||||
|
{...{
|
||||||
|
...attrs,
|
||||||
|
...componentProps,
|
||||||
|
}}
|
||||||
|
style={{ width: 'calc(100% - 48px)' }}
|
||||||
|
ref={elRef}
|
||||||
|
value={value}
|
||||||
|
size="small"
|
||||||
|
onChange={handleChange}
|
||||||
|
onPressEnter={handleSubmit}
|
||||||
|
/>
|
||||||
|
<div class={`${prefixCls}__action`}>
|
||||||
|
<CheckOutlined class={[`${prefixCls}__icon`, 'mx-2']} onClick={handleSubmit} />
|
||||||
|
<CloseOutlined class={[`${prefixCls}__icon `]} onClick={handleCancel} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</ClickOutSide>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!unref(isEditRef) && (
|
||||||
|
<div class={`${prefixCls}__normal`} onClick={handleEdit}>
|
||||||
|
{value}
|
||||||
|
<FormOutlined class={`${prefixCls}__normal-icon`} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export function renderEditableCell({
|
||||||
|
dataIndex,
|
||||||
|
component,
|
||||||
|
componentOn = {},
|
||||||
|
componentProps = {},
|
||||||
|
}: RenderEditableCellParams) {
|
||||||
|
return ({ text, record }: { text: string; record: any }) => {
|
||||||
|
return (
|
||||||
|
<EditableCell
|
||||||
|
value={text}
|
||||||
|
dataKey={record.key}
|
||||||
|
dataIndex={dataIndex}
|
||||||
|
component={component}
|
||||||
|
on={componentOn}
|
||||||
|
componentProps={componentProps}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { BasicArrow } from '/@/components/Basic';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
return (props: any) => {
|
||||||
|
return (
|
||||||
|
<BasicArrow
|
||||||
|
onClick={(e: Event) => {
|
||||||
|
props.onExpand(props.record, e);
|
||||||
|
}}
|
||||||
|
expand={props.expanded}
|
||||||
|
class="right"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
import { Table } from 'ant-design-vue';
|
||||||
|
import { TableRowSelection } from 'ant-design-vue/types/table/table';
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
import { unref, ComputedRef } from 'vue';
|
||||||
|
import { BasicColumn } from '../types/table';
|
||||||
|
import { isFunction } from '/@/utils/is';
|
||||||
|
export default ({
|
||||||
|
scroll = {},
|
||||||
|
columnsRef,
|
||||||
|
summaryFunc,
|
||||||
|
rowKey = 'key',
|
||||||
|
dataSourceRef,
|
||||||
|
rowSelectionRef,
|
||||||
|
}: {
|
||||||
|
scroll: { x?: number | true; y?: number };
|
||||||
|
columnsRef: ComputedRef<BasicColumn[]>;
|
||||||
|
summaryFunc: any;
|
||||||
|
rowKey?: string;
|
||||||
|
dataSourceRef: ComputedRef<any[]>;
|
||||||
|
rowSelectionRef: ComputedRef<TableRowSelection<any> | null>;
|
||||||
|
}) => {
|
||||||
|
if (!summaryFunc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dataSource: any[] = isFunction(summaryFunc) ? summaryFunc(unref(dataSourceRef)) : [];
|
||||||
|
const columns: BasicColumn[] = cloneDeep(unref(columnsRef));
|
||||||
|
const index = columns.findIndex((item) => item.flag === 'INDEX');
|
||||||
|
const hasRowSummary = dataSource.some((item) => Reflect.has(item, '_row'));
|
||||||
|
const hasIndexSummary = dataSource.some((item) => Reflect.has(item, '_index'));
|
||||||
|
|
||||||
|
if (index !== -1) {
|
||||||
|
if (hasIndexSummary) {
|
||||||
|
columns[index].customRender = ({ record }) => record._index;
|
||||||
|
columns[index].ellipsis = false;
|
||||||
|
} else {
|
||||||
|
Reflect.deleteProperty(columns[index], 'customRender');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (unref(rowSelectionRef) && hasRowSummary) {
|
||||||
|
columns.unshift({
|
||||||
|
width: 60,
|
||||||
|
title: 'selection',
|
||||||
|
key: 'selectionKey',
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ record }) => record._row,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dataSource.forEach((item, i) => {
|
||||||
|
item[rowKey] = i;
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<Table
|
||||||
|
showHeader={false}
|
||||||
|
bordered={false}
|
||||||
|
pagination={false}
|
||||||
|
dataSource={dataSource}
|
||||||
|
rowKey={rowKey}
|
||||||
|
columns={columns}
|
||||||
|
tableLayout="fixed"
|
||||||
|
scroll={scroll as any}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { Slots } from 'vue';
|
||||||
|
import TableTitle from './TableTitle.vue';
|
||||||
|
import { getSlot } from '/@/utils/helper/tsxHelper';
|
||||||
|
export default (title: any, titleHelpMessage: string | string[], slots: Slots) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{getSlot(slots, 'tableTitle') ||
|
||||||
|
(title && <TableTitle helpMessage={titleHelpMessage} title={title} />) || (
|
||||||
|
<span> </span>
|
||||||
|
)}
|
||||||
|
{slots.toolbar && <div class="basic-table-toolbar">{getSlot(slots, 'toolbar')}</div>}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
export const ROW_KEY = 'key';
|
||||||
|
|
||||||
|
export const PAGE_SIZE_OPTIONS = ['10', '50', '80', '100'];
|
||||||
|
|
||||||
|
export const PAGE_SIZE = ~~PAGE_SIZE_OPTIONS[0];
|
||||||
|
|
||||||
|
export const FETCH_SETTING = {
|
||||||
|
pageField: 'page',
|
||||||
|
sizeField: 'pageSize',
|
||||||
|
listField: 'items',
|
||||||
|
totalField: 'total',
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
import { BasicColumn, BasicTableProps } from '../types/table';
|
||||||
|
import { PaginationProps } from '../types/pagination';
|
||||||
|
import { unref, ComputedRef, Ref, computed, watch, ref } from 'vue';
|
||||||
|
import { isBoolean, isArray, isObject } from '/@/utils/is';
|
||||||
|
import { PAGE_SIZE } from '../const';
|
||||||
|
import { useProps } from './useProps';
|
||||||
|
|
||||||
|
export function useColumns(
|
||||||
|
refProps: ComputedRef<BasicTableProps>,
|
||||||
|
getPaginationRef: ComputedRef<false | PaginationProps>
|
||||||
|
) {
|
||||||
|
const { propsRef } = useProps(refProps);
|
||||||
|
|
||||||
|
const columnsRef = (ref(unref(propsRef).columns) as unknown) as Ref<BasicColumn[]>;
|
||||||
|
const cacheColumnsRef = (ref(unref(propsRef).columns) as unknown) as Ref<BasicColumn[]>;
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => unref(propsRef).columns,
|
||||||
|
(columns) => {
|
||||||
|
columnsRef.value = columns;
|
||||||
|
cacheColumnsRef.value = columns;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const getColumnsRef = computed(() => {
|
||||||
|
const props = unref(propsRef);
|
||||||
|
const { showIndexColumn, indexColumnProps, ellipsis, actionColumn, isTreeTable } = props;
|
||||||
|
|
||||||
|
const columns = unref(columnsRef);
|
||||||
|
if (!columns) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
let pushIndexColumns = false;
|
||||||
|
columns.forEach((item) => {
|
||||||
|
const { key, dataIndex } = item;
|
||||||
|
item.align = item.align || 'center';
|
||||||
|
if (ellipsis) {
|
||||||
|
if (!key) {
|
||||||
|
item.key = dataIndex;
|
||||||
|
}
|
||||||
|
if (!isBoolean(item.ellipsis)) {
|
||||||
|
Object.assign(item, {
|
||||||
|
ellipsis,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const indIndex = columns.findIndex((column) => column.flag === 'INDEX');
|
||||||
|
if (showIndexColumn && !isTreeTable) {
|
||||||
|
pushIndexColumns = indIndex === -1;
|
||||||
|
} else if (!showIndexColumn && !isTreeTable && indIndex !== -1) {
|
||||||
|
columns.splice(indIndex, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (pushIndexColumns) {
|
||||||
|
const isFixedLeft = columns.some((item) => item.fixed === 'left');
|
||||||
|
|
||||||
|
columns.unshift({
|
||||||
|
flag: 'INDEX',
|
||||||
|
width: 50,
|
||||||
|
title: '序号',
|
||||||
|
align: 'center',
|
||||||
|
customRender: ({ index }) => {
|
||||||
|
const getPagination = unref(getPaginationRef);
|
||||||
|
if (isBoolean(getPagination)) {
|
||||||
|
return `${index + 1}`;
|
||||||
|
}
|
||||||
|
const { current = 1, pageSize = PAGE_SIZE } = getPagination;
|
||||||
|
const currentIndex = (current - 1) * pageSize + index + 1;
|
||||||
|
return currentIndex;
|
||||||
|
},
|
||||||
|
...(isFixedLeft
|
||||||
|
? {
|
||||||
|
fixed: 'left',
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
...indexColumnProps,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (actionColumn) {
|
||||||
|
const hasIndex = columns.findIndex((column) => column.flag === 'ACTION');
|
||||||
|
if (hasIndex === -1) {
|
||||||
|
columns.push({
|
||||||
|
fixed: 'right',
|
||||||
|
...actionColumn,
|
||||||
|
flag: 'ACTION',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
columns[hasIndex] = {
|
||||||
|
...columns[hasIndex],
|
||||||
|
fixed: 'right',
|
||||||
|
...actionColumn,
|
||||||
|
flag: 'ACTION',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return columns;
|
||||||
|
});
|
||||||
|
|
||||||
|
function setColumns(columns: BasicColumn[] | string[]) {
|
||||||
|
if (!isArray(columns)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (columns.length <= 0) {
|
||||||
|
columnsRef.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstColumn = columns[0];
|
||||||
|
if (isObject(firstColumn)) {
|
||||||
|
columnsRef.value = columns as any;
|
||||||
|
} else {
|
||||||
|
const newColumns = unref(cacheColumnsRef).filter((item) =>
|
||||||
|
(columns as string[]).includes(item.key! || item.dataIndex!)
|
||||||
|
);
|
||||||
|
columnsRef.value = newColumns;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { getColumnsRef, setColumns };
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
import { useTimeout } from '/@/hooks/core/useTimeout';
|
||||||
|
import { BasicTableProps, FetchParams } from '../types/table';
|
||||||
|
import { PaginationProps } from '../types/pagination';
|
||||||
|
import { watch, ref, unref, ComputedRef, computed, onMounted, Ref } from 'vue';
|
||||||
|
import { buildUUID } from '/@/utils/uuid';
|
||||||
|
import { isFunction, isBoolean } from '/@/utils/is';
|
||||||
|
import { FETCH_SETTING, ROW_KEY } from '../const';
|
||||||
|
import { get } from 'lodash-es';
|
||||||
|
import { useProps } from './useProps';
|
||||||
|
|
||||||
|
interface ActionType {
|
||||||
|
getPaginationRef: ComputedRef<false | PaginationProps>;
|
||||||
|
setPagination: (info: Partial<PaginationProps>) => void;
|
||||||
|
loadingRef: Ref<boolean | undefined>;
|
||||||
|
getFieldsValue: () => {
|
||||||
|
[field: string]: any;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export function useDataSource(
|
||||||
|
refProps: ComputedRef<BasicTableProps>,
|
||||||
|
{ getPaginationRef, setPagination, loadingRef, getFieldsValue }: ActionType,
|
||||||
|
emit: EmitType
|
||||||
|
) {
|
||||||
|
const { propsRef } = useProps(refProps);
|
||||||
|
|
||||||
|
const dataSourceRef = ref<any[]>([]);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => unref(propsRef).dataSource,
|
||||||
|
(data: any[]) => {
|
||||||
|
const { api } = unref(propsRef);
|
||||||
|
!api && (dataSourceRef.value = data);
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
function setTableKey(items: any[]) {
|
||||||
|
if (!items || !Array.isArray(items)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
items.forEach((item) => {
|
||||||
|
if (!item[ROW_KEY]) {
|
||||||
|
item[ROW_KEY] = buildUUID();
|
||||||
|
}
|
||||||
|
if (item.children && item.children.length) {
|
||||||
|
setTableKey(item.children);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const getAutoCreateKey = computed(() => {
|
||||||
|
return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey;
|
||||||
|
});
|
||||||
|
|
||||||
|
const getDataSourceRef = computed(() => {
|
||||||
|
const dataSource = unref(dataSourceRef);
|
||||||
|
if (!dataSource || dataSource.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (unref(getAutoCreateKey)) {
|
||||||
|
const firstItem = dataSource[0];
|
||||||
|
const lastItem = dataSource[dataSource.length - 1];
|
||||||
|
|
||||||
|
if (firstItem && lastItem) {
|
||||||
|
if (!firstItem[ROW_KEY] || !lastItem[ROW_KEY]) {
|
||||||
|
unref(dataSourceRef).forEach((item) => {
|
||||||
|
if (!item[ROW_KEY]) {
|
||||||
|
item[ROW_KEY] = buildUUID();
|
||||||
|
}
|
||||||
|
if (item.children && item.children.length) {
|
||||||
|
setTableKey(item.children);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return unref(dataSourceRef);
|
||||||
|
});
|
||||||
|
|
||||||
|
async function fetch(opt?: FetchParams) {
|
||||||
|
const { api, searchInfo, fetchSetting, beforeFetch, afterFetch, useSearchForm } = unref(
|
||||||
|
propsRef
|
||||||
|
);
|
||||||
|
if (!api && !isFunction(api)) return;
|
||||||
|
try {
|
||||||
|
loadingRef.value = true;
|
||||||
|
const { pageField, sizeField, listField, totalField } = fetchSetting || FETCH_SETTING;
|
||||||
|
let pageParams: any = {};
|
||||||
|
if (isBoolean(getPaginationRef)) {
|
||||||
|
pageParams = {};
|
||||||
|
} else {
|
||||||
|
const { current, pageSize } = unref(getPaginationRef) as PaginationProps;
|
||||||
|
pageParams[pageField] = opt?.page || current;
|
||||||
|
pageParams[sizeField] = pageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
let params: any = {
|
||||||
|
...pageParams,
|
||||||
|
...(useSearchForm ? getFieldsValue() : {}),
|
||||||
|
...searchInfo,
|
||||||
|
...(opt ? opt.searchInfo : {}),
|
||||||
|
};
|
||||||
|
if (beforeFetch && isFunction(beforeFetch)) {
|
||||||
|
params = beforeFetch(params) || params;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await api(params);
|
||||||
|
let resultItems: any[] = get(res, listField);
|
||||||
|
const resultTotal: number = get(res, totalField);
|
||||||
|
if (afterFetch && isFunction(afterFetch)) {
|
||||||
|
resultItems = afterFetch(resultItems) || resultItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataSourceRef.value = resultItems;
|
||||||
|
setPagination({
|
||||||
|
total: resultTotal || 0,
|
||||||
|
});
|
||||||
|
if (opt && opt.page) {
|
||||||
|
setPagination({
|
||||||
|
current: opt.page || 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
emit('fetch-success', {
|
||||||
|
items: unref(resultItems),
|
||||||
|
total: resultTotal,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
emit('fetch-error', error);
|
||||||
|
dataSourceRef.value = [];
|
||||||
|
setPagination({
|
||||||
|
total: 0,
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
loadingRef.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTableData(values: any[]) {
|
||||||
|
dataSourceRef.value = values;
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
// 转异步任务
|
||||||
|
useTimeout(() => {
|
||||||
|
unref(propsRef).immediate && fetch();
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
return { getDataSourceRef, setTableData, getAutoCreateKey, fetch: fetch };
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { watch, ref, ComputedRef, unref } from 'vue';
|
||||||
|
import { BasicTableProps } from '../types/table';
|
||||||
|
import { useProps } from './useProps';
|
||||||
|
export function useLoading(refProps: ComputedRef<BasicTableProps>) {
|
||||||
|
const { propsRef } = useProps(refProps);
|
||||||
|
|
||||||
|
const loadingRef = ref(unref(propsRef).loading);
|
||||||
|
watch(
|
||||||
|
() => unref(propsRef).loading,
|
||||||
|
(v: boolean) => {
|
||||||
|
loadingRef.value = v;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return { loadingRef };
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
import { computed, unref, ref, ComputedRef } from 'vue';
|
||||||
|
import { PaginationProps } from '../types/pagination';
|
||||||
|
import { isBoolean } from '/@/utils/is';
|
||||||
|
import { LeftOutlined, RightOutlined } from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '../const';
|
||||||
|
import { useProps } from './useProps';
|
||||||
|
import { BasicTableProps } from '../..';
|
||||||
|
export function usePagination(refProps: ComputedRef<BasicTableProps>) {
|
||||||
|
const configRef = ref<PaginationProps>({});
|
||||||
|
const { propsRef } = useProps(refProps);
|
||||||
|
|
||||||
|
const getPaginationRef = computed((): PaginationProps | false => {
|
||||||
|
const { pagination } = unref(propsRef);
|
||||||
|
if (isBoolean(pagination) && !pagination) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
current: 1,
|
||||||
|
pageSize: PAGE_SIZE,
|
||||||
|
size: 'small',
|
||||||
|
defaultPageSize: PAGE_SIZE,
|
||||||
|
showTotal: (total) => `共 ${total} 条数据`,
|
||||||
|
showSizeChanger: true,
|
||||||
|
pageSizeOptions: PAGE_SIZE_OPTIONS,
|
||||||
|
itemRender: ({ page, type, originalElement }) => {
|
||||||
|
if (type === 'prev') {
|
||||||
|
if (page === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return <LeftOutlined />;
|
||||||
|
} else if (type === 'next') {
|
||||||
|
if (page === 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return <RightOutlined />;
|
||||||
|
}
|
||||||
|
return originalElement;
|
||||||
|
},
|
||||||
|
showQuickJumper: true,
|
||||||
|
...(isBoolean(pagination) ? {} : pagination),
|
||||||
|
...unref(configRef),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
function setPagination(info: Partial<PaginationProps>) {
|
||||||
|
configRef.value = {
|
||||||
|
...unref(getPaginationRef),
|
||||||
|
...info,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return { getPaginationRef, setPagination };
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* @description:
|
||||||
|
* @author: wenbin.chen
|
||||||
|
* @Date: 2020-05-12 13:20:26
|
||||||
|
* @LastEditors: vben
|
||||||
|
* @LastEditTime: 2020-10-07 14:52:34
|
||||||
|
* @email: 190848757@qq.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Ref, ref, watch, unref } from 'vue';
|
||||||
|
import { BasicTableProps } from '../types/table';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @Date: 2020-05-12 13:20:37
|
||||||
|
*/
|
||||||
|
export function useProps(props: Readonly<Ref<BasicTableProps>>) {
|
||||||
|
const propsRef = (ref<BasicTableProps>(unref(props)) as unknown) as Ref<BasicTableProps>;
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(v) => {
|
||||||
|
propsRef.value = unref(v);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return { propsRef };
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { provide, inject } from 'vue';
|
||||||
|
import { TableActionType } from '../types/table';
|
||||||
|
|
||||||
|
const key = Symbol('table');
|
||||||
|
|
||||||
|
export function provideTable(instance: TableActionType) {
|
||||||
|
provide(key, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function injectTable(): TableActionType {
|
||||||
|
return inject(key) as TableActionType;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
import { computed, ref, unref, ComputedRef } from 'vue';
|
||||||
|
import { BasicTableProps } from '../types/table';
|
||||||
|
import { TableRowSelection } from 'ant-design-vue/types/table/table';
|
||||||
|
import { useProps } from './useProps';
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
export function useRowSelection(refProps: ComputedRef<BasicTableProps>, emit: EmitType) {
|
||||||
|
const { propsRef } = useProps(refProps);
|
||||||
|
|
||||||
|
const selectedRowKeysRef = ref<string[]>([]);
|
||||||
|
const selectedRowRef = ref<any[]>([]);
|
||||||
|
|
||||||
|
const getRowSelectionRef = computed((): TableRowSelection<any> | null => {
|
||||||
|
const rowSelection = unref(propsRef).rowSelection;
|
||||||
|
if (!rowSelection) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
selectedRowKeys: unref(selectedRowKeysRef),
|
||||||
|
hideDefaultSelections: false,
|
||||||
|
onChange: (selectedRowKeys: string[], selectedRows: any[]) => {
|
||||||
|
selectedRowKeysRef.value = selectedRowKeys;
|
||||||
|
selectedRowRef.value = selectedRows;
|
||||||
|
emit('selection-change', {
|
||||||
|
keys: selectedRowKeys,
|
||||||
|
rows: selectedRows,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
...rowSelection,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
function setSelectedRowKeys(rowKeys: string[]) {
|
||||||
|
selectedRowKeysRef.value = rowKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearSelectedRowKeys() {
|
||||||
|
selectedRowRef.value = [];
|
||||||
|
selectedRowKeysRef.value = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteSelectRowByKey(key: string) {
|
||||||
|
const selectedRowKeys = unref(selectedRowKeysRef);
|
||||||
|
const index = selectedRowKeys.findIndex((item) => item === key);
|
||||||
|
if (index !== -1) {
|
||||||
|
unref(selectedRowKeysRef).splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getSelectRowKeys() {
|
||||||
|
return unref(selectedRowKeysRef);
|
||||||
|
}
|
||||||
|
function getSelectRows() {
|
||||||
|
return unref(selectedRowRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
getRowSelectionRef,
|
||||||
|
getSelectRows,
|
||||||
|
getSelectRowKeys,
|
||||||
|
setSelectedRowKeys,
|
||||||
|
clearSelectedRowKeys,
|
||||||
|
deleteSelectRowByKey,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
import type { BasicTableProps, TableActionType, FetchParams, BasicColumn } from '../types/table';
|
||||||
|
import type { PaginationProps } from '../types/pagination';
|
||||||
|
import { ref, getCurrentInstance, onUnmounted, unref } from 'vue';
|
||||||
|
import { isProdMode } from '/@/utils/env';
|
||||||
|
|
||||||
|
export function useTable(
|
||||||
|
tableProps?: Partial<BasicTableProps>
|
||||||
|
): [(instance: TableActionType) => void, TableActionType] {
|
||||||
|
if (!getCurrentInstance()) {
|
||||||
|
throw new Error('Please put useTable function in the setup function!');
|
||||||
|
}
|
||||||
|
|
||||||
|
const tableRef = ref<TableActionType | null>(null);
|
||||||
|
const loadedRef = ref<boolean | null>(false);
|
||||||
|
|
||||||
|
function register(instance: TableActionType) {
|
||||||
|
onUnmounted(() => {
|
||||||
|
tableRef.value = null;
|
||||||
|
loadedRef.value = null;
|
||||||
|
});
|
||||||
|
if (unref(loadedRef) && isProdMode() && instance === unref(tableRef)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tableRef.value = instance;
|
||||||
|
tableProps && instance.setProps(tableProps);
|
||||||
|
loadedRef.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTableInstance(): TableActionType {
|
||||||
|
const table = unref(tableRef);
|
||||||
|
if (!table) {
|
||||||
|
throw new Error('table is undefined!');
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
const methods: TableActionType = {
|
||||||
|
reload: (opt?: FetchParams) => {
|
||||||
|
getTableInstance().reload(opt);
|
||||||
|
},
|
||||||
|
setProps: (props: Partial<BasicTableProps>) => {
|
||||||
|
getTableInstance().setProps(props);
|
||||||
|
},
|
||||||
|
redoHeight: () => {
|
||||||
|
getTableInstance().redoHeight();
|
||||||
|
},
|
||||||
|
setLoading: (loading: boolean) => {
|
||||||
|
getTableInstance().setLoading(loading);
|
||||||
|
},
|
||||||
|
getDataSource: () => {
|
||||||
|
return getTableInstance().getDataSource();
|
||||||
|
},
|
||||||
|
getColumns: ({ ignoreIndex = false }: { ignoreIndex?: boolean } = {}) => {
|
||||||
|
const columns = getTableInstance().getColumns({ ignoreIndex }) || [];
|
||||||
|
|
||||||
|
return columns;
|
||||||
|
},
|
||||||
|
setColumns: (columns: BasicColumn[]) => {
|
||||||
|
getTableInstance().setColumns(columns);
|
||||||
|
},
|
||||||
|
setTableData: (values: any[]) => {
|
||||||
|
return getTableInstance().setTableData(values);
|
||||||
|
},
|
||||||
|
setPagination: (info: Partial<PaginationProps>) => {
|
||||||
|
return getTableInstance().setPagination(info);
|
||||||
|
},
|
||||||
|
deleteSelectRowByKey: (key: string) => {
|
||||||
|
getTableInstance().deleteSelectRowByKey(key);
|
||||||
|
},
|
||||||
|
getSelectRowKeys: () => {
|
||||||
|
return getTableInstance().getSelectRowKeys();
|
||||||
|
},
|
||||||
|
getSelectRows: () => {
|
||||||
|
return getTableInstance().getSelectRows();
|
||||||
|
},
|
||||||
|
clearSelectedRowKeys: () => {
|
||||||
|
getTableInstance().clearSelectedRowKeys();
|
||||||
|
},
|
||||||
|
setSelectedRowKeys: (keys: string[] | number[]) => {
|
||||||
|
getTableInstance().setSelectedRowKeys(keys);
|
||||||
|
},
|
||||||
|
getPaginationRef: () => {
|
||||||
|
return getTableInstance().getPaginationRef();
|
||||||
|
},
|
||||||
|
} as TableActionType;
|
||||||
|
|
||||||
|
return [register, methods];
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
import { BasicTableProps } from '../types/table';
|
||||||
|
import { computed, Ref, onMounted, unref, ref, nextTick, ComputedRef, watch } from 'vue';
|
||||||
|
import { getViewportOffset } from '/@/utils/domUtils';
|
||||||
|
import { triggerWindowResize } from '/@/utils/event/triggerWindowResizeEvent';
|
||||||
|
import { isBoolean } from '/@/utils/is';
|
||||||
|
import { useTimeout } from '/@/hooks/core/useTimeout';
|
||||||
|
import { useWindowSizeFn } from '/@/hooks/event/useWindowSize';
|
||||||
|
import { useProps } from './useProps';
|
||||||
|
|
||||||
|
export function useTableScroll(refProps: ComputedRef<BasicTableProps>, tableElRef: Ref<any>) {
|
||||||
|
const { propsRef } = useProps(refProps);
|
||||||
|
|
||||||
|
const tableHeightRef: Ref<number | null> = ref(null);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => unref(propsRef).canResize,
|
||||||
|
() => {
|
||||||
|
redoHeight();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
function redoHeight() {
|
||||||
|
const { canResize } = unref(propsRef);
|
||||||
|
|
||||||
|
if (!canResize) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
calcTableHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function calcTableHeight(cb?: () => void) {
|
||||||
|
const { canResize, resizeHeightOffset, pagination, maxHeight } = unref(propsRef);
|
||||||
|
if (!canResize) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await nextTick();
|
||||||
|
const table = unref(tableElRef) as any;
|
||||||
|
|
||||||
|
if (!table) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tableEl: Element = table.$el;
|
||||||
|
if (!tableEl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const el: HTMLElement | null = tableEl.querySelector('.ant-table-thead ');
|
||||||
|
// const layoutMain: Element | null = document.querySelector('.default-layout__main ');
|
||||||
|
if (!el) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 表格距离底部高度
|
||||||
|
const { bottomIncludeBody } = getViewportOffset(el);
|
||||||
|
// 表格高度+距离底部高度-自定义偏移量
|
||||||
|
|
||||||
|
const paddingHeight = 32;
|
||||||
|
const borderHeight = 2 * 2;
|
||||||
|
// 分页器高度
|
||||||
|
|
||||||
|
// TODO 先固定20
|
||||||
|
const paginationHeight = 20;
|
||||||
|
// if (!isBoolean(pagination)) {
|
||||||
|
// const paginationDom = tableEl.querySelector('.ant-pagination') as HTMLElement;
|
||||||
|
// if (paginationDom) {
|
||||||
|
// const offsetHeight = paginationDom.offsetHeight;
|
||||||
|
// paginationHeight += offsetHeight || 0;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
let footerHeight = 0;
|
||||||
|
if (!isBoolean(pagination)) {
|
||||||
|
const footerEl = tableEl.querySelector('.ant-table-footer') as HTMLElement;
|
||||||
|
if (footerEl) {
|
||||||
|
const offsetHeight = footerEl.offsetHeight;
|
||||||
|
footerHeight += offsetHeight || 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let headerHeight = 0;
|
||||||
|
if (el) {
|
||||||
|
headerHeight = (el as HTMLElement).offsetHeight;
|
||||||
|
}
|
||||||
|
tableHeightRef.value =
|
||||||
|
bottomIncludeBody -
|
||||||
|
(resizeHeightOffset || 0) -
|
||||||
|
paddingHeight -
|
||||||
|
borderHeight -
|
||||||
|
paginationHeight -
|
||||||
|
footerHeight -
|
||||||
|
headerHeight;
|
||||||
|
useTimeout(() => {
|
||||||
|
tableHeightRef.value =
|
||||||
|
tableHeightRef.value! > maxHeight! ? (maxHeight as number) : tableHeightRef.value;
|
||||||
|
cb && cb();
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCanResize = computed(() => {
|
||||||
|
const { canResize, scroll } = unref(propsRef);
|
||||||
|
return canResize && !(scroll || {}).y;
|
||||||
|
});
|
||||||
|
|
||||||
|
useWindowSizeFn(calcTableHeight, 100);
|
||||||
|
|
||||||
|
// function clear() {
|
||||||
|
// window.clearInterval(timer);
|
||||||
|
// }
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (unref(getCanResize)) {
|
||||||
|
calcTableHeight();
|
||||||
|
const hasFixedLeft = (unref(propsRef).columns || []).some((item) => item.fixed === 'left');
|
||||||
|
// TODO antv table问题情况太多,只能先用下面方式定时器hack
|
||||||
|
useTimeout(() => {
|
||||||
|
calcTableHeight(() => {
|
||||||
|
// 有左侧固定列的时候才有问题
|
||||||
|
hasFixedLeft &&
|
||||||
|
useTimeout(() => {
|
||||||
|
triggerWindowResize();
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const getScrollRef = computed(() => {
|
||||||
|
const tableHeight = unref(tableHeightRef);
|
||||||
|
const { canResize, scroll } = unref(propsRef);
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: '100%',
|
||||||
|
y: canResize ? tableHeight : null,
|
||||||
|
scrollToFirstRowOnChange: false,
|
||||||
|
...scroll,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return { getScrollRef, redoHeight };
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
import { PaginationProps } from './types/pagination';
|
||||||
|
import { BasicColumn, FetchSetting } from './types/table';
|
||||||
|
import { TableCustomRecord, TableRowSelection } from 'ant-design-vue/types/table/table';
|
||||||
|
import { FormProps } from '/@/components/Form/index';
|
||||||
|
import { FETCH_SETTING } from './const';
|
||||||
|
|
||||||
|
// 注释看 types/table
|
||||||
|
export const basicProps = {
|
||||||
|
autoCreateKey: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
striped: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
showSummary: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
summaryFunc: {
|
||||||
|
type: [Function, Array] as PropType<(...arg: any[]) => any[]>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
|
||||||
|
canColDrag: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
isTreeTable: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
api: {
|
||||||
|
type: Function as PropType<(...arg: any[]) => Promise<any>>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
beforeFetch: {
|
||||||
|
type: Function as PropType<Fn>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
afterFetch: {
|
||||||
|
type: Function as PropType<Fn>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
handleSearchInfoFn: {
|
||||||
|
type: Function as PropType<Fn>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
fetchSetting: {
|
||||||
|
type: Object as PropType<FetchSetting>,
|
||||||
|
default: () => {
|
||||||
|
return FETCH_SETTING;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 立即请求接口
|
||||||
|
immediate: { type: Boolean as PropType<boolean>, default: true },
|
||||||
|
|
||||||
|
emptyDataIsShowTable: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
// 额外的请求参数
|
||||||
|
searchInfo: {
|
||||||
|
type: Object as PropType<any>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
// 使用搜索表单
|
||||||
|
useSearchForm: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
// 表单配置
|
||||||
|
formConfig: {
|
||||||
|
type: Object as PropType<Partial<FormProps>>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
type: [Array] as PropType<BasicColumn[]>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
showIndexColumn: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
indexColumnProps: {
|
||||||
|
type: Object as PropType<BasicColumn>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
actionColumn: {
|
||||||
|
type: Object as PropType<BasicColumn>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
ellipsis: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
canResize: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
clearSelectOnPageChange: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
resizeHeightOffset: {
|
||||||
|
type: Number as PropType<number>,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
rowSelection: {
|
||||||
|
type: Object as PropType<TableRowSelection<any> | null>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: [String, Function] as PropType<string | ((data: any) => any)>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
titleHelpMessage: {
|
||||||
|
type: [String, Array] as PropType<string | string[]>,
|
||||||
|
},
|
||||||
|
maxHeight: {
|
||||||
|
type: Number as PropType<number>,
|
||||||
|
},
|
||||||
|
dataSource: {
|
||||||
|
type: Array as PropType<any[]>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
rowKey: {
|
||||||
|
type: [String, Function] as PropType<string | ((record: any) => string)>,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
bordered: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
pagination: {
|
||||||
|
type: [Object, Boolean] as PropType<PaginationProps | boolean>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
|
||||||
|
loading: {
|
||||||
|
type: Boolean as PropType<boolean>,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
rowClassName: {
|
||||||
|
type: Function as PropType<(record: TableCustomRecord<any>, index: number) => string>,
|
||||||
|
},
|
||||||
|
|
||||||
|
scroll: {
|
||||||
|
type: Object as PropType<{ x: number | true; y: number }>,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
@import (reference) '../../../../design/index.less';
|
||||||
|
|
||||||
|
@prefix-cls: ~'editable-cell';
|
||||||
|
|
||||||
|
.@{prefix-cls} {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&__wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.2);
|
||||||
|
|
||||||
|
svg {
|
||||||
|
color: @primary-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__normal {
|
||||||
|
padding-right: 48px;
|
||||||
|
|
||||||
|
&-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 4px;
|
||||||
|
right: 0;
|
||||||
|
display: none;
|
||||||
|
width: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.@{prefix-cls}__normal-icon {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,228 @@
|
||||||
|
@import (reference) '../../../../design/index.less';
|
||||||
|
@border-color: hsla(0, 0%, 80.8%, 0.25);
|
||||||
|
|
||||||
|
.basic-table {
|
||||||
|
&-title {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-row__striped {
|
||||||
|
td {
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-img__preview {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
img {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-action {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-toolbar {
|
||||||
|
> * {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.resize-table-th {
|
||||||
|
position: relative !important;
|
||||||
|
|
||||||
|
.table-draggable-handle {
|
||||||
|
position: absolute;
|
||||||
|
right: -5px;
|
||||||
|
bottom: 0;
|
||||||
|
left: auto !important;
|
||||||
|
height: 100% !important;
|
||||||
|
cursor: col-resize;
|
||||||
|
transform: none !important;
|
||||||
|
touch-action: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-drag-body {
|
||||||
|
position: relative;
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drag-line td {
|
||||||
|
border-top: 2px dashed @primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-wrapper {
|
||||||
|
padding: 8px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 2px;
|
||||||
|
|
||||||
|
.ant-table-title {
|
||||||
|
padding: 0 0 10px 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table.ant-table-bordered .ant-table-title {
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
.ant-table {
|
||||||
|
&-title {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-thead > tr > th,
|
||||||
|
.ant-table-header {
|
||||||
|
background: #f1f3f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-tbody > tr.ant-table-row-selected td {
|
||||||
|
background: fade(@primary-color, 8%) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-bordered .ant-table-header > table,
|
||||||
|
.ant-table-bordered .ant-table-body > table,
|
||||||
|
.ant-table-bordered .ant-table-fixed-left table,
|
||||||
|
.ant-table-bordered .ant-table-fixed-right table {
|
||||||
|
border: 1px solid @border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-thead {
|
||||||
|
th {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-bordered .ant-table-tbody > tr > td {
|
||||||
|
border-bottom: 1px solid @border-color;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-right: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table.ant-table-bordered .ant-table-footer,
|
||||||
|
.ant-table.ant-table-bordered .ant-table-title {
|
||||||
|
border: 1px solid @border-color !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-bordered.ant-table-empty .ant-table-placeholder {
|
||||||
|
border: 1px solid @border-color !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table td {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-row-cell-last {
|
||||||
|
border-right: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-bordered .ant-table-thead > tr > th,
|
||||||
|
.ant-table-bordered .ant-table-tbody > tr > td {
|
||||||
|
border-right: 1px solid @border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-thead > tr > th,
|
||||||
|
.ant-table-tbody > tr > td {
|
||||||
|
padding: 9px 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-pagination {
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-body {
|
||||||
|
overflow-x: auto !important;
|
||||||
|
overflow-y: scroll !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-header {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
overflow-x: hidden !important;
|
||||||
|
overflow-y: scroll !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-fixed-right .ant-table-header {
|
||||||
|
border-left: 1px solid @border-color;
|
||||||
|
|
||||||
|
.ant-table-fixed {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-fixed-left {
|
||||||
|
.ant-table-header {
|
||||||
|
overflow-y: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-fixed {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-radio {
|
||||||
|
&-inner {
|
||||||
|
border-color: @text-color-base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-checkbox {
|
||||||
|
&:not(.ant-checkbox-checked) {
|
||||||
|
.ant-checkbox-inner {
|
||||||
|
border-color: @text-color-base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-bordered .ant-table-thead > tr:not(:last-child) > th,
|
||||||
|
.ant-table-tbody > tr > td {
|
||||||
|
word-break: break-word;
|
||||||
|
border-color: @border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-footer {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.ant-table-wrapper {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-body {
|
||||||
|
overflow-x: hidden !important;
|
||||||
|
overflow-y: scroll !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 12px 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-form-container {
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
.ant-form {
|
||||||
|
padding: 12px 12px 4px 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-wrapper {
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
export type ComponentType =
|
||||||
|
| 'Input'
|
||||||
|
| 'InputPassword'
|
||||||
|
| 'InputNumber'
|
||||||
|
| 'Select'
|
||||||
|
| 'Checkbox'
|
||||||
|
| 'CheckboxGroup'
|
||||||
|
| 'Switch';
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
import { VNodeChild } from 'vue';
|
||||||
|
import { PaginationRenderProps } from 'ant-design-vue/types/pagination';
|
||||||
|
export interface PaginationProps {
|
||||||
|
/**
|
||||||
|
* total number of data items
|
||||||
|
* @default 0
|
||||||
|
* @type number
|
||||||
|
*/
|
||||||
|
total?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default initial page number
|
||||||
|
* @default 1
|
||||||
|
* @type number
|
||||||
|
*/
|
||||||
|
defaultCurrent?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* current page number
|
||||||
|
* @type number
|
||||||
|
*/
|
||||||
|
current?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default number of data items per page
|
||||||
|
* @default 10
|
||||||
|
* @type number
|
||||||
|
*/
|
||||||
|
defaultPageSize?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* number of data items per page
|
||||||
|
* @type number
|
||||||
|
*/
|
||||||
|
pageSize?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to hide pager on single page
|
||||||
|
* @default false
|
||||||
|
* @type boolean
|
||||||
|
*/
|
||||||
|
hideOnSinglePage?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* determine whether pageSize can be changed
|
||||||
|
* @default false
|
||||||
|
* @type boolean
|
||||||
|
*/
|
||||||
|
showSizeChanger?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* specify the sizeChanger options
|
||||||
|
* @default ['10', '20', '30', '40']
|
||||||
|
* @type string[]
|
||||||
|
*/
|
||||||
|
pageSizeOptions?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* determine whether you can jump to pages directly
|
||||||
|
* @default false
|
||||||
|
* @type boolean
|
||||||
|
*/
|
||||||
|
showQuickJumper?: boolean | object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* to display the total number and range
|
||||||
|
* @type Function
|
||||||
|
*/
|
||||||
|
showTotal?: (total: number, range: [number, number]) => any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* specify the size of Pagination, can be set to small
|
||||||
|
* @default ''
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
size?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* whether to use simple mode
|
||||||
|
* @type boolean
|
||||||
|
*/
|
||||||
|
simple?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* to customize item innerHTML
|
||||||
|
* @type Function
|
||||||
|
*/
|
||||||
|
itemRender?: (props: PaginationRenderProps) => VNodeChild | JSX.Element;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,315 @@
|
||||||
|
import { VNodeChild } from 'vue';
|
||||||
|
import { PaginationProps } from './pagination';
|
||||||
|
import { FormProps } from '/@/components/Form/index';
|
||||||
|
import {
|
||||||
|
ExpandedRowRenderRecord,
|
||||||
|
PaginationConfig,
|
||||||
|
SorterResult,
|
||||||
|
TableCurrentDataSource,
|
||||||
|
TableCustomRecord,
|
||||||
|
TableRowSelection,
|
||||||
|
} from 'ant-design-vue/types/table/table';
|
||||||
|
import { ColumnProps } from 'ant-design-vue/types/table/column';
|
||||||
|
import { ComponentType } from './componentType';
|
||||||
|
export declare type SortOrder = 'ascend' | 'descend';
|
||||||
|
export interface ColumnFilterItem {
|
||||||
|
text?: string;
|
||||||
|
value?: string;
|
||||||
|
children?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RenderEditableCellParams {
|
||||||
|
dataIndex: string;
|
||||||
|
component?: ComponentType;
|
||||||
|
componentOn?: { [key: string]: Fn };
|
||||||
|
componentProps?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FetchParams {
|
||||||
|
searchInfo?: any;
|
||||||
|
page?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetColumnsParams {
|
||||||
|
ignoreIndex?: boolean;
|
||||||
|
}
|
||||||
|
export interface TableActionType {
|
||||||
|
reload: (opt?: FetchParams) => Promise<void>;
|
||||||
|
getSelectRows: () => any[];
|
||||||
|
clearSelectedRowKeys: () => void;
|
||||||
|
getSelectRowKeys: () => string[];
|
||||||
|
deleteSelectRowByKey: (key: string) => void;
|
||||||
|
setPagination: (info: Partial<PaginationProps>) => void;
|
||||||
|
setTableData: (values: any[]) => void;
|
||||||
|
getColumns: ({ ignoreIndex }?: GetColumnsParams) => BasicColumn[];
|
||||||
|
setColumns: (columns: BasicColumn[] | string[]) => void;
|
||||||
|
getDataSource: () => any[];
|
||||||
|
setLoading: (loading: boolean) => void;
|
||||||
|
setProps: (props: Partial<BasicTableProps>) => void;
|
||||||
|
redoHeight: () => void;
|
||||||
|
setSelectedRowKeys: (rowKeys: string[] | number[]) => void;
|
||||||
|
getPaginationRef: () => PaginationProps | boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FetchSetting {
|
||||||
|
// 请求接口当前页数
|
||||||
|
pageField: string;
|
||||||
|
// 每页显示多少条
|
||||||
|
sizeField: string;
|
||||||
|
// 请求结果列表字段 支持 a.b.c
|
||||||
|
listField: string;
|
||||||
|
// 请求结果总数字段 支持 a.b.c
|
||||||
|
totalField: string;
|
||||||
|
}
|
||||||
|
export interface BasicTableProps<T = any> {
|
||||||
|
// 斑马纹
|
||||||
|
striped?: boolean;
|
||||||
|
// 是否自动生成key
|
||||||
|
autoCreateKey?: boolean;
|
||||||
|
// 计算合计行的方法
|
||||||
|
summaryFunc?: (...arg: any) => any[];
|
||||||
|
// 是否显示合计行
|
||||||
|
showSummary?: boolean;
|
||||||
|
// 是否可拖拽列
|
||||||
|
canColDrag?: boolean;
|
||||||
|
// 是否树表
|
||||||
|
isTreeTable?: boolean;
|
||||||
|
// 接口请求对象
|
||||||
|
api?: (...arg: any) => Promise<any>;
|
||||||
|
// 请求之前处理参数
|
||||||
|
beforeFetch?: Fn;
|
||||||
|
// 自定义处理接口返回参数
|
||||||
|
afterFetch?: Fn;
|
||||||
|
// 查询条件请求之前处理
|
||||||
|
handleSearchInfoFn?: Fn;
|
||||||
|
// 请求接口配置
|
||||||
|
fetchSetting?: FetchSetting;
|
||||||
|
// 立即请求接口
|
||||||
|
immediate?: boolean;
|
||||||
|
// 在开起搜索表单的时候,如果没有数据是否显示表格
|
||||||
|
emptyDataIsShowTable?: boolean;
|
||||||
|
// 额外的请求参数
|
||||||
|
searchInfo?: any;
|
||||||
|
|
||||||
|
// 使用搜索表单
|
||||||
|
useSearchForm?: boolean;
|
||||||
|
// 表单配置
|
||||||
|
formConfig?: FormProps;
|
||||||
|
// 列配置
|
||||||
|
columns: BasicColumn[];
|
||||||
|
// 是否显示序号列
|
||||||
|
showIndexColumn?: boolean;
|
||||||
|
// 序号列配置
|
||||||
|
indexColumnProps?: BasicColumn;
|
||||||
|
actionColumn?: BasicColumn;
|
||||||
|
// 文本超过宽度是否显示。。。
|
||||||
|
ellipsis?: boolean;
|
||||||
|
// 是否可以自适应高度
|
||||||
|
canResize?: boolean;
|
||||||
|
// 自适应高度偏移, 计算结果-偏移量
|
||||||
|
resizeHeightOffset?: number;
|
||||||
|
|
||||||
|
// 在分页改变的时候清空选项
|
||||||
|
clearSelectOnPageChange?: boolean;
|
||||||
|
//
|
||||||
|
rowKey?: string | ((record: any) => string);
|
||||||
|
// 数据
|
||||||
|
dataSource?: any[];
|
||||||
|
// 标题右侧提示
|
||||||
|
titleHelpMessage?: string | string[];
|
||||||
|
// 表格滚动最大高度
|
||||||
|
maxHeight?: number;
|
||||||
|
// 是否显示边框
|
||||||
|
bordered?: boolean;
|
||||||
|
// 分页配置
|
||||||
|
pagination?: PaginationProps | boolean;
|
||||||
|
// loading加载
|
||||||
|
loading?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The column contains children to display
|
||||||
|
* @default 'children'
|
||||||
|
* @type string | string[]
|
||||||
|
*/
|
||||||
|
childrenColumnName?: string | string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override default table elements
|
||||||
|
* @type object
|
||||||
|
*/
|
||||||
|
components?: object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand all rows initially
|
||||||
|
* @default false
|
||||||
|
* @type boolean
|
||||||
|
*/
|
||||||
|
defaultExpandAllRows?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initial expanded row keys
|
||||||
|
* @type string[]
|
||||||
|
*/
|
||||||
|
defaultExpandedRowKeys?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current expanded row keys
|
||||||
|
* @type string[]
|
||||||
|
*/
|
||||||
|
expandedRowKeys?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expanded container render for each row
|
||||||
|
* @type Function
|
||||||
|
*/
|
||||||
|
expandedRowRender?: (record?: ExpandedRowRenderRecord<T>) => VNodeChild | JSX.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customize row expand Icon.
|
||||||
|
* @type Function | VNodeChild
|
||||||
|
*/
|
||||||
|
expandIcon?: Function | VNodeChild | JSX.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to expand row by clicking anywhere in the whole row
|
||||||
|
* @default false
|
||||||
|
* @type boolean
|
||||||
|
*/
|
||||||
|
expandRowByClick?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index of `expandIcon` which column will be inserted when `expandIconAsCell` is false. default 0
|
||||||
|
*/
|
||||||
|
expandIconColumnIndex?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table footer renderer
|
||||||
|
* @type Function | VNodeChild
|
||||||
|
*/
|
||||||
|
footer?: Function | VNodeChild | JSX.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indent size in pixels of tree data
|
||||||
|
* @default 15
|
||||||
|
* @type number
|
||||||
|
*/
|
||||||
|
indentSize?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i18n text including filter, sort, empty text, etc
|
||||||
|
* @default { filterConfirm: 'Ok', filterReset: 'Reset', emptyText: 'No Data' }
|
||||||
|
* @type object
|
||||||
|
*/
|
||||||
|
locale?: object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Row's className
|
||||||
|
* @type Function
|
||||||
|
*/
|
||||||
|
rowClassName?: (record: TableCustomRecord<T>) => string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Row selection config
|
||||||
|
* @type object
|
||||||
|
*/
|
||||||
|
rowSelection?: TableRowSelection<T>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set horizontal or vertical scrolling, can also be used to specify the width and height of the scroll area.
|
||||||
|
* It is recommended to set a number for x, if you want to set it to true,
|
||||||
|
* you need to add style .ant-table td { white-space: nowrap; }.
|
||||||
|
* @type object
|
||||||
|
*/
|
||||||
|
scroll?: { x?: number | true; y?: number };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to show table header
|
||||||
|
* @default true
|
||||||
|
* @type boolean
|
||||||
|
*/
|
||||||
|
showHeader?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of table
|
||||||
|
* @default 'default'
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
size?: 'default' | 'middle' | 'small' | 'large';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table title renderer
|
||||||
|
* @type Function | ScopedSlot
|
||||||
|
*/
|
||||||
|
title?: VNodeChild | JSX.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set props on per header row
|
||||||
|
* @type Function
|
||||||
|
*/
|
||||||
|
customHeaderRow?: (column: ColumnProps<T>, index: number) => object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set props on per row
|
||||||
|
* @type Function
|
||||||
|
*/
|
||||||
|
customRow?: (record: T, index: number) => object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `table-layout` attribute of table element
|
||||||
|
* `fixed` when header/columns are fixed, or using `column.ellipsis`
|
||||||
|
*
|
||||||
|
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout
|
||||||
|
* @version 1.5.0
|
||||||
|
*/
|
||||||
|
tableLayout?: 'auto' | 'fixed' | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the render container of dropdowns in table
|
||||||
|
* @param triggerNode
|
||||||
|
* @version 1.5.0
|
||||||
|
*/
|
||||||
|
getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data can be changed again before rendering.
|
||||||
|
* The default configuration of general user empty data.
|
||||||
|
* You can configured globally through [ConfigProvider](https://antdv.com/components/config-provider-cn/)
|
||||||
|
*
|
||||||
|
* @version 1.5.4
|
||||||
|
*/
|
||||||
|
transformCellText?: Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback executed when pagination, filters or sorter is changed
|
||||||
|
* @param pagination
|
||||||
|
* @param filters
|
||||||
|
* @param sorter
|
||||||
|
* @param currentDataSource
|
||||||
|
*/
|
||||||
|
onChange?: (
|
||||||
|
pagination: PaginationConfig,
|
||||||
|
filters: Partial<Record<keyof T, string[]>>,
|
||||||
|
sorter: SorterResult<T>,
|
||||||
|
extra: TableCurrentDataSource<T>
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback executed when the row expand icon is clicked
|
||||||
|
*
|
||||||
|
* @param expanded
|
||||||
|
* @param record
|
||||||
|
*/
|
||||||
|
onExpand?: (expande: boolean, record: T) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback executed when the expanded rows change
|
||||||
|
* @param expandedRows
|
||||||
|
*/
|
||||||
|
onExpandedRowsChange?: (expandedRows: string[] | number[]) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BasicColumn<T = any> extends ColumnProps<T> {
|
||||||
|
children?: BasicColumn[];
|
||||||
|
//
|
||||||
|
flag?: 'INDEX' | 'DEFAULT' | 'CHECKBOX' | 'RADIO' | 'ACTION';
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
export interface ActionItem {
|
||||||
|
on?: any;
|
||||||
|
label: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
color?: 'success' | 'error' | 'warning';
|
||||||
|
type?: string;
|
||||||
|
props?: any;
|
||||||
|
icon?: string;
|
||||||
|
popConfirm?: PopConfirm;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PopConfirm {
|
||||||
|
title: string;
|
||||||
|
okText?: string;
|
||||||
|
cancelText?: string;
|
||||||
|
confirm: any;
|
||||||
|
cancel?: any;
|
||||||
|
icon?: string;
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
body {
|
|
||||||
.ant-pagination {
|
.ant-pagination {
|
||||||
&.mini {
|
&.mini {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
|
@ -9,7 +8,7 @@ body {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
min-width: 20px;
|
min-width: 20px;
|
||||||
line-height: 17px;
|
line-height: 20px;
|
||||||
color: @border-color-shallow-dark;
|
color: @border-color-shallow-dark;
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
}
|
}
|
||||||
|
|
@ -95,4 +94,3 @@ body {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,23 @@ import { ContentEnum } from '/@/enums/appEnum';
|
||||||
import { appStore } from '/@/store/modules/app';
|
import { appStore } from '/@/store/modules/app';
|
||||||
// import { RouterView } from 'vue-router';
|
// import { RouterView } from 'vue-router';
|
||||||
import PageLayout from '/@/layouts/page/index';
|
import PageLayout from '/@/layouts/page/index';
|
||||||
|
import FrameLayout from '/@/layouts/iframe/index.vue';
|
||||||
|
|
||||||
|
import { useSetting } from '/@/hooks/core/useSetting';
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'DefaultLayoutContent',
|
name: 'DefaultLayoutContent',
|
||||||
setup() {
|
setup() {
|
||||||
|
const { projectSetting } = useSetting();
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const { getProjectConfig } = appStore;
|
const { getProjectConfig } = appStore;
|
||||||
const { contentMode } = getProjectConfig;
|
const { contentMode } = getProjectConfig;
|
||||||
|
|
||||||
const wrapClass = contentMode === ContentEnum.FULL ? 'full' : 'fixed';
|
const wrapClass = contentMode === ContentEnum.FULL ? 'full' : 'fixed';
|
||||||
return (
|
return (
|
||||||
<Layout.Content class={`layout-content ${wrapClass} `}>
|
<Layout.Content class={`layout-content ${wrapClass} `}>
|
||||||
{{
|
{{
|
||||||
default: () => <PageLayout />,
|
default: () => [<PageLayout />, projectSetting.canEmbedIFramePage && <FrameLayout />],
|
||||||
}}
|
}}
|
||||||
</Layout.Content>
|
</Layout.Content>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,7 @@ import { useTransition } from './useTransition';
|
||||||
|
|
||||||
import { RouterView, RouteLocation } from 'vue-router';
|
import { RouterView, RouteLocation } from 'vue-router';
|
||||||
import { tabStore } from '/@/store/modules/tab';
|
import { tabStore } from '/@/store/modules/tab';
|
||||||
import FrameLayout from '/@/layouts/iframe/index.vue';
|
|
||||||
|
|
||||||
import { useSetting } from '/@/hooks/core/useSetting';
|
|
||||||
// import { useRouter } from 'vue-router';
|
// import { useRouter } from 'vue-router';
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'PageLayout',
|
name: 'PageLayout',
|
||||||
|
|
@ -24,7 +22,6 @@ export default defineComponent({
|
||||||
const { on: transitionOn } = useTransition();
|
const { on: transitionOn } = useTransition();
|
||||||
on = transitionOn;
|
on = transitionOn;
|
||||||
}
|
}
|
||||||
const { projectSetting } = useSetting();
|
|
||||||
return () => {
|
return () => {
|
||||||
const {
|
const {
|
||||||
routerTransition,
|
routerTransition,
|
||||||
|
|
@ -35,8 +32,7 @@ export default defineComponent({
|
||||||
|
|
||||||
const openCache = openKeepAlive && show;
|
const openCache = openKeepAlive && show;
|
||||||
const cacheTabs = toRaw(tabStore.getKeepAliveTabsState) as string[];
|
const cacheTabs = toRaw(tabStore.getKeepAliveTabsState) as string[];
|
||||||
return (
|
return [
|
||||||
<div>
|
|
||||||
<RouterView>
|
<RouterView>
|
||||||
{{
|
{{
|
||||||
default: ({ Component, route }: { Component: any; route: RouteLocation }) => {
|
default: ({ Component, route }: { Component: any; route: RouteLocation }) => {
|
||||||
|
|
@ -60,10 +56,8 @@ export default defineComponent({
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
</RouterView>
|
</RouterView>,
|
||||||
{projectSetting.canEmbedIFramePage && <FrameLayout />}
|
];
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ import type { Router } from 'vue-router';
|
||||||
import NProgress from 'nprogress';
|
import NProgress from 'nprogress';
|
||||||
import 'nprogress/nprogress.css';
|
import 'nprogress/nprogress.css';
|
||||||
|
|
||||||
NProgress.inc(0.4);
|
|
||||||
NProgress.configure({ easing: 'ease', speed: 1000, showSpinner: false });
|
|
||||||
|
|
||||||
export function createProgressGuard(router: Router) {
|
export function createProgressGuard(router: Router) {
|
||||||
|
NProgress.inc(0.1);
|
||||||
|
NProgress.configure({ easing: 'ease', speed: 200, showSpinner: false });
|
||||||
|
|
||||||
router.beforeEach(async () => {
|
router.beforeEach(async () => {
|
||||||
NProgress.start();
|
NProgress.start();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,68 @@ const menu: MenuModule = {
|
||||||
path: '/click-out-side',
|
path: '/click-out-side',
|
||||||
name: 'ClickOutSide组件',
|
name: 'ClickOutSide组件',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/table',
|
||||||
|
name: '表格组件',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/basic',
|
||||||
|
name: '基础表格',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/treeTable',
|
||||||
|
name: '树形表格',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/fetchTable',
|
||||||
|
name: '远程加载',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/fixedColumn',
|
||||||
|
name: '固定列',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/customerCell',
|
||||||
|
name: '自定义列',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/formTable',
|
||||||
|
name: '开启搜索区域',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/useTable',
|
||||||
|
name: 'UseTable',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/refTable',
|
||||||
|
name: 'RefTable',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/multipleHeader',
|
||||||
|
name: '多级表头',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/mergeHeader',
|
||||||
|
name: '合并表头',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/expandTable',
|
||||||
|
name: '可展开表格',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/fixedHeight',
|
||||||
|
name: '定高/头部自定义',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/footerTable',
|
||||||
|
name: '表尾行合计',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/editCellTable',
|
||||||
|
name: '可编辑单元格',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/form',
|
path: '/form',
|
||||||
name: '表单组件',
|
name: '表单组件',
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,128 @@ export default {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/table',
|
||||||
|
name: 'TableDemo',
|
||||||
|
redirect: '/comp/table/basic',
|
||||||
|
meta: {
|
||||||
|
title: '表格组件',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'basic',
|
||||||
|
name: 'TableBasicDemo',
|
||||||
|
component: () => import('/@/views/demo/table/Basic.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '基础表格',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'treeTable',
|
||||||
|
name: 'TreeTableDemo',
|
||||||
|
component: () => import('/@/views/demo/table/TreeTable.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '树形表格',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'fetchTable',
|
||||||
|
name: 'FetchTableDemo',
|
||||||
|
component: () => import('/@/views/demo/table/FetchTable.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '远程加载示例',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'fixedColumn',
|
||||||
|
name: 'FixedColumnDemo',
|
||||||
|
component: () => import('/@/views/demo/table/FixedColumn.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '固定列',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'customerCell',
|
||||||
|
name: 'CustomerCellDemo',
|
||||||
|
component: () => import('/@/views/demo/table/CustomerCell.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '自定义列',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'formTable',
|
||||||
|
name: 'FormTableDemo',
|
||||||
|
component: () => import('/@/views/demo/table/FormTable.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '开启搜索区域',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'useTable',
|
||||||
|
name: 'UseTableDemo',
|
||||||
|
component: () => import('/@/views/demo/table/UseTable.vue'),
|
||||||
|
meta: {
|
||||||
|
title: 'UseTable',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'refTable',
|
||||||
|
name: 'RefTableDemo',
|
||||||
|
component: () => import('/@/views/demo/table/RefTable.vue'),
|
||||||
|
meta: {
|
||||||
|
title: 'RefTable',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'multipleHeader',
|
||||||
|
name: 'MultipleHeaderDemo',
|
||||||
|
component: () => import('/@/views/demo/table/MultipleHeader.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '多级表头',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'mergeHeader',
|
||||||
|
name: 'MergeHeaderDemo',
|
||||||
|
component: () => import('/@/views/demo/table/MergeHeader.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '合并表头',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'expandTable',
|
||||||
|
name: 'ExpandTableDemo',
|
||||||
|
component: () => import('/@/views/demo/table/ExpandTable.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '可展开表格',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'fixedHeight',
|
||||||
|
name: 'FixedHeightDemo',
|
||||||
|
component: () => import('/@/views/demo/table/FixedHeight.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '定高/头部自定义',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'footerTable',
|
||||||
|
name: 'FooterTableDemo',
|
||||||
|
component: () => import('/@/views/demo/table/FooterTable.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '表尾行合计',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'editCellTable',
|
||||||
|
name: 'EditCellTableDemo',
|
||||||
|
component: () => import('/@/views/demo/table/EditCellTable.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '可编辑单元格',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/tree',
|
path: '/tree',
|
||||||
name: 'TreeDemo',
|
name: 'TreeDemo',
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,19 @@
|
||||||
import type { App } from 'vue';
|
import type { App } from 'vue';
|
||||||
import { createStore, createLogger, Plugin } from 'vuex';
|
import {
|
||||||
|
createStore,
|
||||||
|
// createLogger, Plugin
|
||||||
|
} from 'vuex';
|
||||||
import { config } from 'vuex-module-decorators';
|
import { config } from 'vuex-module-decorators';
|
||||||
import { isDevMode } from '/@/utils/env';
|
import { isDevMode } from '/@/utils/env';
|
||||||
|
|
||||||
config.rawError = true;
|
config.rawError = true;
|
||||||
const isDev = isDevMode();
|
const isDev = isDevMode();
|
||||||
const plugins: Plugin<any>[] = isDev ? [createLogger()] : [];
|
// const plugins: Plugin<any>[] = isDev ? [createLogger()] : [];
|
||||||
|
|
||||||
const store = createStore({
|
const store = createStore({
|
||||||
modules: {},
|
modules: {},
|
||||||
strict: isDev,
|
strict: isDev,
|
||||||
plugins,
|
// plugins,
|
||||||
});
|
});
|
||||||
export function setupStore(app: App<Element>) {
|
export function setupStore(app: App<Element>) {
|
||||||
app.use(store);
|
app.use(store);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
declare module 'ant-design-vue/es/locale/zh_CN';
|
declare module 'ant-design-vue/es/locale/zh_CN';
|
||||||
|
declare module 'vue-draggable-resizable';
|
||||||
declare const React: string;
|
declare const React: string;
|
||||||
declare module '*.bmp' {
|
declare module '*.bmp' {
|
||||||
const src: string;
|
const src: string;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ import type { ProjectConfig } from '/@/types/config';
|
||||||
|
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
import { BasicEmpty } from '/@/components/Basic';
|
|
||||||
|
|
||||||
import { ThemeModeEnum } from '/@/enums/appEnum';
|
import { ThemeModeEnum } from '/@/enums/appEnum';
|
||||||
import { PROJ_CFG_KEY } from '/@/enums/cacheEnum';
|
import { PROJ_CFG_KEY } from '/@/enums/cacheEnum';
|
||||||
|
|
||||||
|
|
@ -59,10 +57,6 @@ export function useInitAppConfigStore() {
|
||||||
|
|
||||||
// Config Provider
|
// Config Provider
|
||||||
export function useConfigProvider() {
|
export function useConfigProvider() {
|
||||||
function renderEmpty() {
|
|
||||||
return <BasicEmpty />;
|
|
||||||
}
|
|
||||||
|
|
||||||
function transformCellText({ text }: { text: string }) {
|
function transformCellText({ text }: { text: string }) {
|
||||||
if (isNull(text) || isUnDef(text)) {
|
if (isNull(text) || isUnDef(text)) {
|
||||||
return ' - ';
|
return ' - ';
|
||||||
|
|
@ -70,7 +64,6 @@ export function useConfigProvider() {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
renderEmpty,
|
|
||||||
transformCellText,
|
transformCellText,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
<div class="flex justify-center p-4 items-center bg-gray-700">
|
<div class="flex justify-center p-4 items-center bg-gray-700">
|
||||||
<BasicDragVerify ref="el4" @success="handleSuccess">
|
<BasicDragVerify ref="el4" @success="handleSuccess">
|
||||||
<template v-slot:actionIcon="isPassing">
|
<template #actionIcon="isPassing">
|
||||||
<BugOutlined v-if="isPassing" />
|
<BugOutlined v-if="isPassing" />
|
||||||
<RightOutlined v-else />
|
<RightOutlined v-else />
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
<div class="flex justify-center p-4 items-center bg-gray-700">
|
<div class="flex justify-center p-4 items-center bg-gray-700">
|
||||||
<BasicDragVerify ref="el5" @success="handleSuccess">
|
<BasicDragVerify ref="el5" @success="handleSuccess">
|
||||||
<template v-slot:text="isPassing">
|
<template #text="isPassing">
|
||||||
<div v-if="isPassing">
|
<div v-if="isPassing">
|
||||||
<BugOutlined />
|
<BugOutlined />
|
||||||
成功
|
成功
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<BasicTable
|
||||||
|
title="基础示例"
|
||||||
|
titleHelpMessage="温馨提醒"
|
||||||
|
:columns="columns"
|
||||||
|
:dataSource="data"
|
||||||
|
:canResize="canResize"
|
||||||
|
:loading="loading"
|
||||||
|
:striped="striped"
|
||||||
|
:bordered="border"
|
||||||
|
:pagination="{ pageSize: 20 }"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<a-button type="primary" @click="toggleCanResize">
|
||||||
|
{{ !canResize ? '自适应高度' : '取消自适应' }}
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" @click="toggleBorder">
|
||||||
|
{{ !border ? '显示边框' : '隐藏边框' }}
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" @click="toggleLoading"> 开启loading </a-button>
|
||||||
|
<a-button type="primary" @click="toggleStriped">
|
||||||
|
{{ !striped ? '显示斑马纹' : '隐藏斑马纹' }}
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref } from 'vue';
|
||||||
|
import { BasicTable } from '/@/components/Table';
|
||||||
|
import { getBasicColumns, getBasicData } from './tableData';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BasicTable },
|
||||||
|
setup() {
|
||||||
|
const canResize = ref(false);
|
||||||
|
const loading = ref(false);
|
||||||
|
const striped = ref(true);
|
||||||
|
const border = ref(true);
|
||||||
|
function toggleCanResize() {
|
||||||
|
canResize.value = !canResize.value;
|
||||||
|
}
|
||||||
|
function toggleStriped() {
|
||||||
|
striped.value = !striped.value;
|
||||||
|
}
|
||||||
|
function toggleLoading() {
|
||||||
|
loading.value = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = false;
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
function toggleBorder() {
|
||||||
|
border.value = !border.value;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
columns: getBasicColumns(),
|
||||||
|
data: getBasicData(),
|
||||||
|
canResize,
|
||||||
|
loading,
|
||||||
|
striped,
|
||||||
|
border,
|
||||||
|
toggleStriped,
|
||||||
|
toggleCanResize,
|
||||||
|
toggleLoading,
|
||||||
|
toggleBorder,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<BasicTable @register="registerTable">
|
||||||
|
<template #id="{ record }"> ID: {{ record.id }} </template>
|
||||||
|
<template #no="{ record }"
|
||||||
|
><Tag color="green">{{ record.no }}</Tag>
|
||||||
|
</template>
|
||||||
|
<template #img>
|
||||||
|
<TableImg
|
||||||
|
:imgList="['https://picsum.photos/id/66/346/216', 'https://picsum.photos/id/67/346/216']"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { BasicTable, useTable, BasicColumn, TableImg } from '/@/components/Table';
|
||||||
|
import { Tag } from 'ant-design-vue';
|
||||||
|
import { demoListApi } from '/@/api/demo/table';
|
||||||
|
const columns: BasicColumn[] = [
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
slots: { customRender: 'id' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '姓名',
|
||||||
|
dataIndex: 'name',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '头像',
|
||||||
|
dataIndex: 'img',
|
||||||
|
width: 120,
|
||||||
|
slots: { customRender: 'img' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '地址',
|
||||||
|
dataIndex: 'address',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '编号',
|
||||||
|
dataIndex: 'no',
|
||||||
|
slots: { customRender: 'no' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开始时间',
|
||||||
|
dataIndex: 'beginTime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '结束时间',
|
||||||
|
dataIndex: 'endTime',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BasicTable, TableImg, Tag },
|
||||||
|
setup() {
|
||||||
|
const [registerTable] = useTable({
|
||||||
|
title: '自定义列内容',
|
||||||
|
api: demoListApi,
|
||||||
|
columns: columns,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
registerTable,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<BasicTable @register="registerTable">
|
||||||
|
<template #customId>
|
||||||
|
<EditTableHeaderIcon title="Id" />
|
||||||
|
</template>
|
||||||
|
<template #customName>
|
||||||
|
<EditTableHeaderIcon title="姓名" />
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import {
|
||||||
|
BasicTable,
|
||||||
|
useTable,
|
||||||
|
BasicColumn,
|
||||||
|
renderEditableCell,
|
||||||
|
EditTableHeaderIcon,
|
||||||
|
} from '/@/components/Table';
|
||||||
|
|
||||||
|
import { demoListApi } from '/@/api/demo/table';
|
||||||
|
const columns: BasicColumn[] = [
|
||||||
|
{
|
||||||
|
// title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
slots: { title: 'customId' },
|
||||||
|
customRender: renderEditableCell({ dataIndex: 'id' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// title: '姓名',
|
||||||
|
dataIndex: 'name',
|
||||||
|
slots: { title: 'customName' },
|
||||||
|
customRender: renderEditableCell({
|
||||||
|
dataIndex: 'name',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '地址',
|
||||||
|
dataIndex: 'address',
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BasicTable, EditTableHeaderIcon },
|
||||||
|
setup() {
|
||||||
|
const [registerTable] = useTable({
|
||||||
|
title: '可编辑单元格示例',
|
||||||
|
api: demoListApi,
|
||||||
|
columns: columns,
|
||||||
|
showIndexColumn: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
registerTable,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<BasicTable @register="registerTable">
|
||||||
|
<template #expandedRowRender="{ record }">
|
||||||
|
<span>No: {{ record.no }} </span>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { BasicTable, useTable } from '/@/components/Table';
|
||||||
|
import { getBasicColumns } from './tableData';
|
||||||
|
|
||||||
|
import { demoListApi } from '/@/api/demo/table';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BasicTable },
|
||||||
|
setup() {
|
||||||
|
const [registerTable] = useTable({
|
||||||
|
title: '可展开表格',
|
||||||
|
api: demoListApi,
|
||||||
|
titleHelpMessage: '不能与scroll共用',
|
||||||
|
columns: getBasicColumns(),
|
||||||
|
rowKey: 'id',
|
||||||
|
canResize: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
registerTable,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<BasicTable @register="registerTable">
|
||||||
|
<template #toolbar>
|
||||||
|
<a-button type="primary" @click="handleReloadCurrent"> 刷新当前页 </a-button>
|
||||||
|
<a-button type="primary" @click="handleReload"> 刷新并返回第一页 </a-button>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { BasicTable, useTable } from '/@/components/Table';
|
||||||
|
import { getBasicColumns } from './tableData';
|
||||||
|
|
||||||
|
import { demoListApi } from '/@/api/demo/table';
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BasicTable },
|
||||||
|
setup() {
|
||||||
|
const [registerTable, { reload }] = useTable({
|
||||||
|
title: '远程加载示例',
|
||||||
|
api: demoListApi,
|
||||||
|
columns: getBasicColumns(),
|
||||||
|
});
|
||||||
|
function handleReloadCurrent() {
|
||||||
|
reload();
|
||||||
|
// reload({
|
||||||
|
// searchInfo: 'xxx',
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleReload() {
|
||||||
|
reload({
|
||||||
|
page: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
registerTable,
|
||||||
|
handleReloadCurrent,
|
||||||
|
handleReload,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<BasicTable @register="registerTable">
|
||||||
|
<template #action>
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: '删除',
|
||||||
|
props: {
|
||||||
|
onClick: handleDelete,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
:dropDownActions="[
|
||||||
|
{
|
||||||
|
label: '启用',
|
||||||
|
props: {
|
||||||
|
onClick: handleOpen,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table';
|
||||||
|
|
||||||
|
import { demoListApi } from '/@/api/demo/table';
|
||||||
|
const columns: BasicColumn[] = [
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
fixed: 'left',
|
||||||
|
width: 280,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '姓名',
|
||||||
|
dataIndex: 'name',
|
||||||
|
width: 260,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '地址',
|
||||||
|
dataIndex: 'address',
|
||||||
|
width: 260,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '编号',
|
||||||
|
dataIndex: 'no',
|
||||||
|
width: 300,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开始时间',
|
||||||
|
width: 200,
|
||||||
|
dataIndex: 'beginTime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '结束时间',
|
||||||
|
dataIndex: 'endTime',
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BasicTable, TableAction },
|
||||||
|
setup() {
|
||||||
|
const [registerTable] = useTable({
|
||||||
|
title: 'TableAction组件及固定列示例',
|
||||||
|
api: demoListApi,
|
||||||
|
columns: columns,
|
||||||
|
rowSelection: { type: 'radio' },
|
||||||
|
actionColumn: {
|
||||||
|
width: 160,
|
||||||
|
title: 'Action',
|
||||||
|
dataIndex: 'action',
|
||||||
|
slots: { customRender: 'action' },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
function handleDelete() {
|
||||||
|
console.log('点击了删除');
|
||||||
|
}
|
||||||
|
function handleOpen() {
|
||||||
|
console.log('点击了启用');
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
registerTable,
|
||||||
|
handleDelete,
|
||||||
|
handleOpen,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<BasicTable @register="registerTable">
|
||||||
|
<template #customTitle>
|
||||||
|
<span>
|
||||||
|
姓名
|
||||||
|
<BaseHelp class="ml-2" text="姓名" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #customAddress>
|
||||||
|
地址
|
||||||
|
<FormOutlined class="ml-2" />
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { BasicTable, useTable } from '/@/components/Table';
|
||||||
|
import { getCustomHeaderColumns } from './tableData';
|
||||||
|
import { FormOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { demoListApi } from '/@/api/demo/table';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BasicTable, FormOutlined },
|
||||||
|
setup() {
|
||||||
|
const [registerTable] = useTable({
|
||||||
|
title: '定高/头部自定义',
|
||||||
|
api: demoListApi,
|
||||||
|
columns: getCustomHeaderColumns(),
|
||||||
|
canResize: false,
|
||||||
|
scroll: { y: 100 },
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
registerTable,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<BasicTable @register="registerTable" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { BasicTable, useTable } from '/@/components/Table';
|
||||||
|
import { getBasicColumns } from './tableData';
|
||||||
|
|
||||||
|
import { demoListApi } from '/@/api/demo/table';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BasicTable },
|
||||||
|
setup() {
|
||||||
|
function handleSummary(tableData: any[]) {
|
||||||
|
const totalNo = tableData.reduce((prev, next) => {
|
||||||
|
prev += next.no;
|
||||||
|
return prev;
|
||||||
|
}, 0);
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
_row: '合计',
|
||||||
|
_index: '平均值',
|
||||||
|
no: totalNo,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
_row: '合计',
|
||||||
|
_index: '平均值',
|
||||||
|
no: totalNo,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
const [registerTable] = useTable({
|
||||||
|
title: '表尾行合计示例',
|
||||||
|
api: demoListApi,
|
||||||
|
rowSelection: { type: 'checkbox' },
|
||||||
|
columns: getBasicColumns(),
|
||||||
|
showSummary: true,
|
||||||
|
summaryFunc: handleSummary,
|
||||||
|
scroll: { x: 2000 },
|
||||||
|
canResize: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
registerTable,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<template>
|
||||||
|
<BasicTable @register="registerTable" />
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { BasicTable, useTable } from '/@/components/Table';
|
||||||
|
import { getBasicColumns, getFormConfig } from './tableData';
|
||||||
|
|
||||||
|
import { demoListApi } from '/@/api/demo/table';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BasicTable },
|
||||||
|
setup() {
|
||||||
|
const [registerTable] = useTable({
|
||||||
|
title: '开启搜索区域',
|
||||||
|
api: demoListApi,
|
||||||
|
columns: getBasicColumns(),
|
||||||
|
useSearchForm: true,
|
||||||
|
formConfig: getFormConfig(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
registerTable,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<BasicTable @register="registerTable" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { BasicTable, useTable } from '/@/components/Table';
|
||||||
|
import { getMergeHeaderColumns } from './tableData';
|
||||||
|
|
||||||
|
import { demoListApi } from '/@/api/demo/table';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BasicTable },
|
||||||
|
setup() {
|
||||||
|
const [registerTable] = useTable({
|
||||||
|
title: '多级表头示例',
|
||||||
|
api: demoListApi,
|
||||||
|
columns: getMergeHeaderColumns(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
registerTable,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<BasicTable @register="registerTable" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { BasicTable, useTable } from '/@/components/Table';
|
||||||
|
import { getMultipleHeaderColumns } from './tableData';
|
||||||
|
|
||||||
|
import { demoListApi } from '/@/api/demo/table';
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BasicTable },
|
||||||
|
setup() {
|
||||||
|
const [registerTable] = useTable({
|
||||||
|
title: '多级表头示例',
|
||||||
|
api: demoListApi,
|
||||||
|
columns: getMultipleHeaderColumns(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
registerTable,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<div class="mb-4">
|
||||||
|
<a-button class="mr-2" @click="reloadTable">还原</a-button>
|
||||||
|
<a-button class="mr-2" @click="changeLoading">开启loading</a-button>
|
||||||
|
<a-button class="mr-2" @click="changeColumns">更改Columns</a-button>
|
||||||
|
<a-button class="mr-2" @click="getColumn">获取Columns</a-button>
|
||||||
|
<a-button class="mr-2" @click="getTableData">获取表格数据</a-button>
|
||||||
|
<a-button class="mr-2" @click="setPaginationInfo">跳转到第2页</a-button>
|
||||||
|
</div>
|
||||||
|
<div class="mb-4">
|
||||||
|
<a-button class="mr-2" @click="getSelectRowList">获取选中行</a-button>
|
||||||
|
<a-button class="mr-2" @click="getSelectRowKeyList">获取选中行Key</a-button>
|
||||||
|
<a-button class="mr-2" @click="setSelectedRowKeyList">设置选中行</a-button>
|
||||||
|
<a-button class="mr-2" @click="clearSelect">清空选中行</a-button>
|
||||||
|
<a-button class="mr-2" @click="getPagination">获取分页信息</a-button>
|
||||||
|
</div>
|
||||||
|
<BasicTable
|
||||||
|
:canResize="false"
|
||||||
|
title="RefTable示例"
|
||||||
|
titleHelpMessage="使用Ref调用表格内方法"
|
||||||
|
ref="tableRef"
|
||||||
|
:api="api"
|
||||||
|
:columns="columns"
|
||||||
|
rowKey="id"
|
||||||
|
:rowSelection="{ type: 'checkbox' }"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref, unref } from 'vue';
|
||||||
|
import { BasicTable, TableActionType } from '/@/components/Table';
|
||||||
|
import { getBasicColumns, getBasicShortColumns } from './tableData';
|
||||||
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
|
import { demoListApi } from '/@/api/demo/table';
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BasicTable },
|
||||||
|
setup() {
|
||||||
|
const tableRef = ref<Nullable<TableActionType>>(null);
|
||||||
|
const { createMessage } = useMessage();
|
||||||
|
|
||||||
|
function getTableAction() {
|
||||||
|
const tableAction = unref(tableRef);
|
||||||
|
if (!tableAction) {
|
||||||
|
throw new Error('tableAction is null');
|
||||||
|
}
|
||||||
|
return tableAction;
|
||||||
|
}
|
||||||
|
function changeLoading() {
|
||||||
|
getTableAction().setLoading(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
getTableAction().setLoading(false);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
function changeColumns() {
|
||||||
|
getTableAction().setColumns(getBasicShortColumns());
|
||||||
|
}
|
||||||
|
function reloadTable() {
|
||||||
|
getTableAction().setColumns(getBasicColumns());
|
||||||
|
|
||||||
|
getTableAction().reload({
|
||||||
|
page: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function getColumn() {
|
||||||
|
createMessage.info('请在控制台查看!');
|
||||||
|
console.log(getTableAction().getColumns());
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTableData() {
|
||||||
|
createMessage.info('请在控制台查看!');
|
||||||
|
console.log(getTableAction().getDataSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPagination() {
|
||||||
|
createMessage.info('请在控制台查看!');
|
||||||
|
console.log(getTableAction().getPaginationRef());
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPaginationInfo() {
|
||||||
|
getTableAction().setPagination({
|
||||||
|
current: 2,
|
||||||
|
});
|
||||||
|
getTableAction().reload();
|
||||||
|
}
|
||||||
|
function getSelectRowList() {
|
||||||
|
createMessage.info('请在控制台查看!');
|
||||||
|
console.log(getTableAction().getSelectRows());
|
||||||
|
}
|
||||||
|
function getSelectRowKeyList() {
|
||||||
|
createMessage.info('请在控制台查看!');
|
||||||
|
console.log(getTableAction().getSelectRowKeys());
|
||||||
|
}
|
||||||
|
function setSelectedRowKeyList() {
|
||||||
|
getTableAction().setSelectedRowKeys(['0', '1', '2']);
|
||||||
|
}
|
||||||
|
function clearSelect() {
|
||||||
|
getTableAction().clearSelectedRowKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
tableRef,
|
||||||
|
api: demoListApi,
|
||||||
|
columns: getBasicColumns(),
|
||||||
|
changeLoading,
|
||||||
|
changeColumns,
|
||||||
|
reloadTable,
|
||||||
|
getColumn,
|
||||||
|
getTableData,
|
||||||
|
getPagination,
|
||||||
|
setPaginationInfo,
|
||||||
|
getSelectRowList,
|
||||||
|
getSelectRowKeyList,
|
||||||
|
setSelectedRowKeyList,
|
||||||
|
clearSelect,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<BasicTable
|
||||||
|
:rowSelection="{ type: 'checkbox' }"
|
||||||
|
:isTreeTable="true"
|
||||||
|
title="树形表格"
|
||||||
|
titleHelpMessage="树形组件不能和序列号列同时存在"
|
||||||
|
:columns="columns"
|
||||||
|
:dataSource="data"
|
||||||
|
rowKey="id"
|
||||||
|
:indentSize="20"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { BasicTable } from '/@/components/Table';
|
||||||
|
import { getBasicColumns, getTreeTableData } from './tableData';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BasicTable },
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
columns: getBasicColumns(),
|
||||||
|
data: getTreeTableData(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,126 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-4">
|
||||||
|
<div class="mb-4">
|
||||||
|
<a-button class="mr-2" @click="reloadTable">还原</a-button>
|
||||||
|
<a-button class="mr-2" @click="changeLoading">开启loading</a-button>
|
||||||
|
<a-button class="mr-2" @click="changeColumns">更改Columns</a-button>
|
||||||
|
<a-button class="mr-2" @click="getColumn">获取Columns</a-button>
|
||||||
|
<a-button class="mr-2" @click="getTableData">获取表格数据</a-button>
|
||||||
|
<a-button class="mr-2" @click="setPaginationInfo">跳转到第2页</a-button>
|
||||||
|
</div>
|
||||||
|
<div class="mb-4">
|
||||||
|
<a-button class="mr-2" @click="getSelectRowList">获取选中行</a-button>
|
||||||
|
<a-button class="mr-2" @click="getSelectRowKeyList">获取选中行Key</a-button>
|
||||||
|
<a-button class="mr-2" @click="setSelectedRowKeyList">设置选中行</a-button>
|
||||||
|
<a-button class="mr-2" @click="clearSelect">清空选中行</a-button>
|
||||||
|
<a-button class="mr-2" @click="getPagination">获取分页信息</a-button>
|
||||||
|
</div>
|
||||||
|
<BasicTable @register="registerTable" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { BasicTable, useTable } from '/@/components/Table';
|
||||||
|
import { getBasicColumns, getBasicShortColumns } from './tableData';
|
||||||
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
|
import { demoListApi } from '/@/api/demo/table';
|
||||||
|
export default defineComponent({
|
||||||
|
components: { BasicTable },
|
||||||
|
setup() {
|
||||||
|
const { createMessage } = useMessage();
|
||||||
|
const [
|
||||||
|
registerTable,
|
||||||
|
{
|
||||||
|
setLoading,
|
||||||
|
setColumns,
|
||||||
|
getColumns,
|
||||||
|
getDataSource,
|
||||||
|
reload,
|
||||||
|
getPaginationRef,
|
||||||
|
setPagination,
|
||||||
|
getSelectRows,
|
||||||
|
getSelectRowKeys,
|
||||||
|
setSelectedRowKeys,
|
||||||
|
clearSelectedRowKeys,
|
||||||
|
},
|
||||||
|
] = useTable({
|
||||||
|
canResize: false,
|
||||||
|
title: 'useTable示例',
|
||||||
|
titleHelpMessage: '使用useTable调用表格内方法',
|
||||||
|
api: demoListApi,
|
||||||
|
columns: getBasicColumns(),
|
||||||
|
rowKey: 'id',
|
||||||
|
rowSelection: {
|
||||||
|
type: 'checkbox',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function changeLoading() {
|
||||||
|
setLoading(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setLoading(false);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
function changeColumns() {
|
||||||
|
setColumns(getBasicShortColumns());
|
||||||
|
}
|
||||||
|
function reloadTable() {
|
||||||
|
setColumns(getBasicColumns());
|
||||||
|
|
||||||
|
reload({
|
||||||
|
page: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function getColumn() {
|
||||||
|
createMessage.info('请在控制台查看!');
|
||||||
|
console.log(getColumns());
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTableData() {
|
||||||
|
createMessage.info('请在控制台查看!');
|
||||||
|
console.log(getDataSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPagination() {
|
||||||
|
createMessage.info('请在控制台查看!');
|
||||||
|
console.log(getPaginationRef());
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPaginationInfo() {
|
||||||
|
setPagination({
|
||||||
|
current: 2,
|
||||||
|
});
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
function getSelectRowList() {
|
||||||
|
createMessage.info('请在控制台查看!');
|
||||||
|
console.log(getSelectRows());
|
||||||
|
}
|
||||||
|
function getSelectRowKeyList() {
|
||||||
|
createMessage.info('请在控制台查看!');
|
||||||
|
console.log(getSelectRowKeys());
|
||||||
|
}
|
||||||
|
function setSelectedRowKeyList() {
|
||||||
|
setSelectedRowKeys(['0', '1', '2']);
|
||||||
|
}
|
||||||
|
function clearSelect() {
|
||||||
|
clearSelectedRowKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
registerTable,
|
||||||
|
changeLoading,
|
||||||
|
changeColumns,
|
||||||
|
reloadTable,
|
||||||
|
getColumn,
|
||||||
|
getTableData,
|
||||||
|
getPagination,
|
||||||
|
setPaginationInfo,
|
||||||
|
getSelectRowList,
|
||||||
|
getSelectRowKeyList,
|
||||||
|
setSelectedRowKeyList,
|
||||||
|
clearSelect,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,292 @@
|
||||||
|
import { FormProps, FormSchema } from '/@/components/Table';
|
||||||
|
import { BasicColumn } from '/@/components/Table/src/types/table';
|
||||||
|
|
||||||
|
export function getBasicColumns(): BasicColumn[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
width: 150,
|
||||||
|
dataIndex: 'id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '姓名',
|
||||||
|
dataIndex: 'name',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '地址',
|
||||||
|
dataIndex: 'address',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '编号',
|
||||||
|
dataIndex: 'no',
|
||||||
|
width: 80,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开始时间',
|
||||||
|
dataIndex: 'beginTime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '结束时间',
|
||||||
|
sorter: true,
|
||||||
|
dataIndex: 'endTime',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBasicShortColumns(): BasicColumn[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
width: 150,
|
||||||
|
dataIndex: 'id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '姓名',
|
||||||
|
dataIndex: 'name',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '地址',
|
||||||
|
dataIndex: 'address',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '编号',
|
||||||
|
dataIndex: 'no',
|
||||||
|
width: 80,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMultipleHeaderColumns(): BasicColumn[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '姓名',
|
||||||
|
dataIndex: 'name',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '地址',
|
||||||
|
dataIndex: 'address',
|
||||||
|
sorter: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: '编号',
|
||||||
|
dataIndex: 'no',
|
||||||
|
width: 120,
|
||||||
|
filters: [
|
||||||
|
{ text: 'Male', value: 'male' },
|
||||||
|
{ text: 'Female', value: 'female' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '开始时间',
|
||||||
|
dataIndex: 'beginTime',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '结束时间',
|
||||||
|
dataIndex: 'endTime',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCustomHeaderColumns(): BasicColumn[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// title: '姓名',
|
||||||
|
dataIndex: 'name',
|
||||||
|
width: 120,
|
||||||
|
slots: { title: 'customTitle' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// title: '地址',
|
||||||
|
dataIndex: 'address',
|
||||||
|
slots: { title: 'customAddress' },
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
title: '编号',
|
||||||
|
dataIndex: 'no',
|
||||||
|
width: 120,
|
||||||
|
filters: [
|
||||||
|
{ text: 'Male', value: 'male' },
|
||||||
|
{ text: 'Female', value: 'female' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开始时间',
|
||||||
|
dataIndex: 'beginTime',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '结束时间',
|
||||||
|
dataIndex: 'endTime',
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
const renderContent = ({ text, index }: { text: any; index: number }) => {
|
||||||
|
const obj: any = {
|
||||||
|
children: text,
|
||||||
|
attrs: {},
|
||||||
|
};
|
||||||
|
if (index === 9) {
|
||||||
|
obj.attrs.colSpan = 0;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
export function getMergeHeaderColumns(): BasicColumn[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
width: 300,
|
||||||
|
customRender: renderContent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '姓名',
|
||||||
|
dataIndex: 'name',
|
||||||
|
width: 300,
|
||||||
|
customRender: renderContent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '地址',
|
||||||
|
dataIndex: 'address',
|
||||||
|
colSpan: 2,
|
||||||
|
width: 120,
|
||||||
|
sorter: true,
|
||||||
|
customRender: ({ text, index }: { text: any; index: number }) => {
|
||||||
|
const obj: any = {
|
||||||
|
children: text,
|
||||||
|
attrs: {},
|
||||||
|
};
|
||||||
|
if (index === 2) {
|
||||||
|
obj.attrs.rowSpan = 2;
|
||||||
|
}
|
||||||
|
if (index === 3) {
|
||||||
|
obj.attrs.colSpan = 0;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '编号',
|
||||||
|
dataIndex: 'no',
|
||||||
|
colSpan: 0,
|
||||||
|
filters: [
|
||||||
|
{ text: 'Male', value: 'male' },
|
||||||
|
{ text: 'Female', value: 'female' },
|
||||||
|
],
|
||||||
|
customRender: renderContent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开始时间',
|
||||||
|
dataIndex: 'beginTime',
|
||||||
|
width: 200,
|
||||||
|
customRender: renderContent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '结束时间',
|
||||||
|
dataIndex: 'endTime',
|
||||||
|
width: 200,
|
||||||
|
customRender: renderContent,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
export const getAdvanceSchema = (itemNumber = 6): FormSchema[] => {
|
||||||
|
const arr: any = [];
|
||||||
|
for (let index = 0; index < itemNumber; index++) {
|
||||||
|
arr.push({
|
||||||
|
field: `field${index}`,
|
||||||
|
label: `字段${index}`,
|
||||||
|
component: 'Input',
|
||||||
|
colProps: {
|
||||||
|
xl: 12,
|
||||||
|
xxl: 8,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
};
|
||||||
|
export function getFormConfig(): Partial<FormProps> {
|
||||||
|
return {
|
||||||
|
labelWidth: 100,
|
||||||
|
schemas: getAdvanceSchema(6),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export function getBasicData() {
|
||||||
|
const data: any = (() => {
|
||||||
|
const arr: any = [];
|
||||||
|
for (let index = 0; index < 40; index++) {
|
||||||
|
arr.push({
|
||||||
|
id: `${index}`,
|
||||||
|
name: 'John Brown',
|
||||||
|
age: `1${index}`,
|
||||||
|
no: `${index + 10}`,
|
||||||
|
address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
|
||||||
|
beginTime: new Date().toLocaleString(),
|
||||||
|
endTime: new Date().toLocaleString(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
})();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTreeTableData() {
|
||||||
|
const data: any = (() => {
|
||||||
|
const arr: any = [];
|
||||||
|
for (let index = 0; index < 40; index++) {
|
||||||
|
arr.push({
|
||||||
|
id: `${index}`,
|
||||||
|
name: 'John Brown',
|
||||||
|
age: `1${index}`,
|
||||||
|
no: `${index + 10}`,
|
||||||
|
address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
|
||||||
|
beginTime: new Date().toLocaleString(),
|
||||||
|
endTime: new Date().toLocaleString(),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: `l2-${index}`,
|
||||||
|
name: 'John Brown',
|
||||||
|
age: `1${index}`,
|
||||||
|
no: `${index + 10}`,
|
||||||
|
address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
|
||||||
|
beginTime: new Date().toLocaleString(),
|
||||||
|
endTime: new Date().toLocaleString(),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: `l3-${index}`,
|
||||||
|
name: 'John Brown',
|
||||||
|
age: `1${index}`,
|
||||||
|
no: `${index + 10}`,
|
||||||
|
address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
|
||||||
|
beginTime: new Date().toLocaleString(),
|
||||||
|
endTime: new Date().toLocaleString(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
})();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue