version: v5.2.0

This commit is contained in:
XiaoDaiGua-Ray 2025-06-06 21:28:56 +08:00
parent 0f2193cc14
commit c68491fca9
22 changed files with 783 additions and 399 deletions

View File

@ -1,3 +1,57 @@
## 5.2.0
一些破坏性更新,请谨慎更新。
## Feats
- 更新 `vue` 版本至 `3.5.16`
- 更新 `vite` 版本至 `6.3.5`
- `RTablePro` 组件相关
- `runTableRequest` 方法现在支持传递 `reset` 参数,配置是否重置分页请求
- `runTableRequest` 方法新增 `excludeParams` 配置项,允许排除指定的请求参数
- `onTablePaginationUpdate` 方法参数返回值由返回函数改为直接返回值
- 新增 `paginationPrefix` 配置项,允许自定义分页器前缀,在国际化需求可能会有用
- 新增 `flexAutoHeight` 配置项,默认关闭,允许配置表格是否自动继承高度,但是要结合 `css flex` 属性使用
> 如果你是使用 `NFlex` 组件结合 `RTablePro` 或者 `RTable` 组件使用,需要配置 `Flex` 组件的 `vertical` 属性,并且设置 `class``flex-vertical`,即可便捷实现该效果。否则你需要设置 `css flex` 相关属性(可以参考 Demo2的示例。
```tsx
import { RTablePro } from '@/components'
import { NFlex } from 'naive-ui'
const Demo1 = () => {
return (
<NFlex vertical class="flex-vertical">
<RTablePro flexAutoHeight />
</NFlex>
)
}
const Demo2 = () => {
return (
<div
class="flex-vertical"
style="height: 100%; display: flex; flex-direction: column;"
>
<RTablePro flexAutoHeight />
</div>
)
}
```
- 新增 `getDateByNaiveDatePicker` 方法,便捷获取 `naive-ui``DatePicker` 组件的日期值
- `Recordable` 类型新增 `symbol`, `number` 类型作为 `key` 支持
- `RCollapse` 组件相关
- 默认配置 `responsive` 配置项为 `screen` 响应模式
- 默认配置 `cols` 配置项为 `4 xs:1 s:2 m:2 l:4 xl:4 2xl:6`,虽然目前的预设已经足够使用,但你也可以高度自定义需求
- `types`
- 新增 `GlobalDataTableColumns` 类型,用于声明全局 `DataTableColumns` 类型
- 新增 `GlobalRecordable` 类型,用于声明全局 `Recordable` 类型
## Fixes
- 修复 `RTablePro` 组件 `print` 方法打印内容错误的问题
## 5.1.0 ## 5.1.0
## Feats ## Feats

View File

@ -51,7 +51,7 @@
"pinia": "^2.3.0", "pinia": "^2.3.0",
"pinia-plugin-persistedstate": "^4.2.0", "pinia-plugin-persistedstate": "^4.2.0",
"print-js": "^1.6.0", "print-js": "^1.6.0",
"vue": "^3.5.13", "vue": "^3.5.16",
"vue-demi": "0.14.10", "vue-demi": "0.14.10",
"vue-hooks-plus": "2.2.3", "vue-hooks-plus": "2.2.3",
"vue-i18n": "^9.13.1", "vue-i18n": "^9.13.1",
@ -97,7 +97,7 @@
"typescript": "5.6.3", "typescript": "5.6.3",
"unplugin-auto-import": "19.0.0", "unplugin-auto-import": "19.0.0",
"unplugin-vue-components": "0.28.0", "unplugin-vue-components": "0.28.0",
"vite": "6.3.3", "vite": "6.3.5",
"vite-bundle-analyzer": "0.16.0", "vite-bundle-analyzer": "0.16.0",
"vite-plugin-cdn2": "1.1.0", "vite-plugin-cdn2": "1.1.0",
"vite-plugin-ejs": "1.7.0", "vite-plugin-ejs": "1.7.0",

529
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -78,6 +78,19 @@ export default defineComponent({
return headerStyle return headerStyle
}) })
// 如果启用了 flexAutoHeight 属性,则自动继承高度
const flexAutoHeightStyle = computed(() => {
const { flexAutoHeight } = props
if (!flexAutoHeight) {
return null
}
return {
height: '100%',
flex: 1,
}
})
/** /**
* *
@ -249,6 +262,7 @@ export default defineComponent({
wrapperRef, wrapperRef,
propsPopselectValue, propsPopselectValue,
cardHeaderStyle, cardHeaderStyle,
flexAutoHeightStyle,
} }
}, },
render() { render() {
@ -262,6 +276,7 @@ export default defineComponent({
privateReactive, privateReactive,
propsPopselectValue, propsPopselectValue,
cardHeaderStyle, cardHeaderStyle,
flexAutoHeightStyle,
} = this } = this
const { class: className, ...restAttrs } = $attrs const { class: className, ...restAttrs } = $attrs
const { tool, combineRowProps, contextMenuSelect } = this const { tool, combineRowProps, contextMenuSelect } = this
@ -273,6 +288,8 @@ export default defineComponent({
title, title,
tableFlexHeight, tableFlexHeight,
cardProps, cardProps,
flexAutoHeight,
flexHeight,
...restProps ...restProps
} = $props } = $props
const { headerStyle, ...restCardProps } = cardProps ?? {} const { headerStyle, ...restCardProps } = cardProps ?? {}
@ -287,7 +304,8 @@ export default defineComponent({
ref="wrapperRef" ref="wrapperRef"
bordered={wrapperBordered} bordered={wrapperBordered}
class={className} class={className}
style={cardHeaderStyle} // flexAutoHeight 具有更高的优先级
style={Object.assign({}, cardHeaderStyle, flexAutoHeightStyle)}
> >
{{ {{
default: () => ( default: () => (
@ -298,12 +316,14 @@ export default defineComponent({
}} }}
{...(restProps as DataTableProps)} {...(restProps as DataTableProps)}
{...propsPopselectValue} {...propsPopselectValue}
flexHeight={flexAutoHeight ? true : flexHeight}
rowProps={combineRowProps.bind(this)} rowProps={combineRowProps.bind(this)}
size={privateReactive.size} size={privateReactive.size}
ref="rTableInst" ref="rTableInst"
style={{ style={{
height: height: flexAutoHeight
tableFlexHeight !== null && tableFlexHeight !== void 0 ? '100%'
: tableFlexHeight !== null && tableFlexHeight !== void 0
? completeSize(tableFlexHeight) ? completeSize(tableFlexHeight)
: null, : null,
}} }}

View File

@ -42,12 +42,12 @@ import type { PrintDomOptions } from '@/utils'
*/ */
const useTable = () => { const useTable = () => {
const tableRef = shallowRef<RTableInst>() const tableRef = shallowRef<RTableInst>()
let extra = {} as TableProvider const extraRef = shallowRef<TableProvider>({} as TableProvider)
const register: UseTableRegister = (inst, extraInfo) => { const register: UseTableRegister = (inst, extraInfo) => {
if (inst) { if (inst) {
tableRef.value = inst tableRef.value = inst
extra = extraInfo extraRef.value = extraInfo
} }
} }
@ -140,7 +140,7 @@ const useTable = () => {
* *
*/ */
const print = (options?: PrintDomOptions) => { const print = (options?: PrintDomOptions) => {
const { uuidWrapper } = extra const { uuidWrapper } = extraRef.value ?? {}
if (uuidWrapper) { if (uuidWrapper) {
const tableWrapperElement = document.getElementById(uuidWrapper) const tableWrapperElement = document.getElementById(uuidWrapper)
@ -165,6 +165,7 @@ const useTable = () => {
sort, sort,
print, print,
filter, filter,
config: extraRef,
}, },
] as const ] as const
} }

View File

@ -238,6 +238,17 @@ const props = {
type: [Function, Array] as PropType<MaybeArray<UseTableRegister>>, type: [Function, Array] as PropType<MaybeArray<UseTableRegister>>,
default: null, default: null,
}, },
/**
*
* @description
*
*
* @default false
*/
flexAutoHeight: {
type: Boolean,
default: false,
},
} as const } as const
export default props export default props

View File

@ -54,6 +54,7 @@ export interface RTableInst extends Omit<DataTableInst, 'clearFilter'> {
* *
*/ */
print: (options?: PrintDomOptions) => void print: (options?: PrintDomOptions) => void
config: TableProvider
} }
export type OverridesTableColumn<T = Recordable> = C | DataTableColumn<T> export type OverridesTableColumn<T = Recordable> = C | DataTableColumn<T>

View File

@ -3,6 +3,8 @@ import { RCollapseGrid, RForm } from '@/components'
import formProps from '../../base/RForm/src/props' import formProps from '../../base/RForm/src/props'
import collapseGridProps from '../../base/RCollapseGrid/src/props' import collapseGridProps from '../../base/RCollapseGrid/src/props'
import type { GridProps } from 'naive-ui'
/** /**
* *
* @description * @description
@ -18,13 +20,17 @@ export default defineComponent({
default: true, default: true,
}, },
cols: { cols: {
type: Number, type: [Number, String] as PropType<GridProps['cols']>,
default: 4, default: '4 xs:1 s:2 m:2 l:4 xl:4 2xl:6',
}, },
bordered: { bordered: {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
responsive: {
type: String as PropType<GridProps['responsive']>,
default: 'screen',
},
}), }),
render() { render() {
const { $slots, $props } = this const { $slots, $props } = this

View File

@ -1,9 +1,10 @@
import { RTable } from '@/components' import { RTable } from '../../../base/RTable'
import props from './props' import props from './props'
import { useTable } from '@/components' import useTable from '../../../base/RTable/src/hooks/useTable'
import { call, removeDuplicateKeys } from '@/utils' import { call, removeDuplicateKeys } from '@/utils'
import { usePagination } from '@/hooks' import { usePagination } from '@/hooks'
import { omit } from 'lodash-es'
import type { TablePagination, TableRequestConfig, TableProInst } from './types' import type { TablePagination, TableRequestConfig, TableProInst } from './types'
@ -11,20 +12,7 @@ export default defineComponent({
name: 'RTablePro', name: 'RTablePro',
props, props,
setup(props) { setup(props) {
const [ const [register, tableFns] = useTable()
register,
{
clearFilters,
clearSorter,
downloadCsv,
filters,
page,
scrollTo,
sort,
print,
filter,
},
] = useTable()
const [ const [
paginationRef, paginationRef,
{ {
@ -36,16 +24,20 @@ export default defineComponent({
getItemCount, getItemCount,
}, },
] = usePagination(void 0, { ] = usePagination(void 0, {
prefix: (info) => `${info.itemCount}`, prefix: props.paginationPrefix,
}) })
const tableRequestRef = computed(() => props.request) const tableRequestRef = computed(() => props.request)
// 获取最新 statistics 和 pagination 值 // 获取最新 statistics 和 pagination 值
const update = (): TablePagination => { const update = (): TablePagination => {
const page = getPage()
const pageSize = getPageSize()
const itemCount = getItemCount()
return { return {
getItemCount, page,
getPage, pageSize,
getPageSize, itemCount,
} }
} }
@ -62,7 +54,7 @@ export default defineComponent({
const combineRequestParams = (extraConfig?: TableRequestConfig) => { const combineRequestParams = (extraConfig?: TableRequestConfig) => {
const config = Object.assign({}, props.requestConfig, extraConfig) const config = Object.assign({}, props.requestConfig, extraConfig)
const { formatRangeTime } = config const { formatRangeTime, excludeParams } = config
let params = config.params || {} let params = config.params || {}
// 转换时间范围,该功能仅支持 NDatePicker range 模式参数 // 转换时间范围,该功能仅支持 NDatePicker range 模式参数
@ -87,6 +79,11 @@ export default defineComponent({
params = removeDuplicateKeys(params) params = removeDuplicateKeys(params)
// 排除指定的请求参数
if (excludeParams) {
params = omit(params, excludeParams)
}
const requestParams = Object.assign({}, params, { const requestParams = Object.assign({}, params, {
page: getPage(), page: getPage(),
pageSize: getPageSize(), pageSize: getPageSize(),
@ -95,29 +92,27 @@ export default defineComponent({
return requestParams return requestParams
} }
// 会重置 pagination 的请求 // 会重置 pagination 的请求,默认会重置
const runResetPaginationRequest = (extraConfig?: TableRequestConfig) => { const runResetPaginationRequest = (
resetPagination() extraConfig?: TableRequestConfig,
reset = true,
) => {
if (reset) {
resetPagination()
}
const requestParams = combineRequestParams(extraConfig) const requestParams = combineRequestParams(extraConfig)
tableRequestRef.value?.(requestParams) tableRequestRef.value?.(requestParams)
} }
// 不会重置 pagination 的请求
const runRequest = (extraConfig?: TableRequestConfig) => {
const requestParams = combineRequestParams(extraConfig)
tableRequestRef.value?.(requestParams)
}
watchEffect(() => { watchEffect(() => {
setItemCount(props.paginationCount) setItemCount(props.paginationCount)
setCallback(() => { setCallback(() => {
const { manual } = props const { manual } = props
if (!manual) { if (!manual) {
runRequest() runResetPaginationRequest(void 0, false)
} }
emitTableUpdate() emitTableUpdate()
@ -129,21 +124,12 @@ export default defineComponent({
if (onRegister) { if (onRegister) {
call(onRegister, { call(onRegister, {
...tableFns,
getTablePagination: update, getTablePagination: update,
runTableRequest: runResetPaginationRequest, runTableRequest: runResetPaginationRequest,
clearFilters, getCurrentTableRequestParams: combineRequestParams,
clearSorter,
downloadCsv,
filters,
page,
scrollTo,
sort,
print,
filter,
getCurrentTableRequestParams:
combineRequestParams as TableProInst['getCurrentTableRequestParams'],
resetTablePagination: resetPagination, resetTablePagination: resetPagination,
}) } as unknown as TableProInst)
} }
}) })

View File

@ -1,3 +1,5 @@
import { printDom } from '@/utils'
import type { Recordable } from '@/types' import type { Recordable } from '@/types'
import type { TableProInst, TableRequestConfig } from '../types' import type { TableProInst, TableRequestConfig } from '../types'
import type { import type {
@ -48,6 +50,9 @@ export const useTablePro = () => {
getTableProInstance().getTablePagination.call(null) getTableProInstance().getTablePagination.call(null)
/** /**
*
* @param extraConfig
* @param reset
* *
* @description * @description
* *
@ -57,9 +62,13 @@ export const useTablePro = () => {
* TableRequestConfig props tableRequestConfig * TableRequestConfig props tableRequestConfig
* pagination * pagination
*/ */
const runTableRequest = <T extends Recordable>( const runTableRequest = <
extraConfig?: TableRequestConfig<T>, T extends Recordable,
) => getTableProInstance().runTableRequest.call(null, extraConfig) ExcludeParams extends keyof T = keyof T,
>(
extraConfig?: TableRequestConfig<T, ExcludeParams>,
reset?: boolean,
) => getTableProInstance().runTableRequest.call(null, extraConfig, reset)
/** /**
* *
@ -80,6 +89,8 @@ export const useTablePro = () => {
const clearSorter = () => getTableProInstance().clearSorter.call(null) const clearSorter = () => getTableProInstance().clearSorter.call(null)
/** /**
*
* @param options CSV
* *
* @description * @description
* CSV * CSV
@ -90,6 +101,8 @@ export const useTablePro = () => {
getTableProInstance().downloadCsv.call(null, options) getTableProInstance().downloadCsv.call(null, options)
/** /**
*
* @param filters
* *
* @description * @description
* *
@ -100,6 +113,8 @@ export const useTablePro = () => {
getTableProInstance().filters.call(null, filters) getTableProInstance().filters.call(null, filters)
/** /**
*
* @param page
* *
* @description * @description
* page * page
@ -109,6 +124,8 @@ export const useTablePro = () => {
const page = (page: number) => getTableProInstance().page.call(null, page) const page = (page: number) => getTableProInstance().page.call(null, page)
/** /**
*
* @param options
* *
* @description * @description
* *
@ -120,6 +137,9 @@ export const useTablePro = () => {
getTableProInstance().scrollTo(options as any) getTableProInstance().scrollTo(options as any)
/** /**
*
* @param columnKey
* @param order
* *
* @description * @description
* *
@ -130,28 +150,44 @@ export const useTablePro = () => {
getTableProInstance().sort.call(null, columnKey, order) getTableProInstance().sort.call(null, columnKey, order)
/** /**
*
* @param options
* *
* @description * @description
* *
*/ */
const print = (options?: PrintDomOptions) => const print = (options?: PrintDomOptions) => {
getTableProInstance().print.call(null, options) const { config } = getTableProInstance()
const { uuidWrapper } = config ?? {}
if (uuidWrapper) {
const tableWrapperElement = document.getElementById(uuidWrapper)
printDom(tableWrapperElement, options)
}
}
/** /**
* *
* @param extraConfig * @param extraConfig
* @param excludeParams
* *
* @description * @description
* *
*/ */
const getCurrentTableRequestParams = <T = Recordable>( const getCurrentTableRequestParams = <
extraConfig?: TableRequestConfig<T>, T extends Recordable,
ExcludeParams extends keyof T = keyof T,
>(
extraConfig?: TableRequestConfig<T, ExcludeParams>,
): T & Recordable => ): T & Recordable =>
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
getTableProInstance().getCurrentTableRequestParams.call(null, extraConfig) getTableProInstance().getCurrentTableRequestParams.call(null, extraConfig)
/** /**
*
* @param extraConfig
* *
* @description * @description
* *

View File

@ -2,7 +2,12 @@ import { tableProps } from '@/components'
import { omit } from 'lodash-es' import { omit } from 'lodash-es'
import type { PropType } from 'vue' import type { PropType } from 'vue'
import type { TableProInst, TablePagination, TableRequestConfig } from './types' import type {
TableProInst,
TablePagination,
TableRequestConfig,
PaginationPrefix,
} from './types'
import type { AnyFC } from '@/types' import type { AnyFC } from '@/types'
const props = { const props = {
@ -70,11 +75,10 @@ const props = {
* *
* *
* *
* @default {} * @default undefined
*/ */
requestConfig: { requestConfig: {
type: Object as PropType<TableRequestConfig>, type: Object as PropType<TableRequestConfig>,
default: () => ({}),
}, },
/** /**
* *
@ -101,6 +105,19 @@ const props = {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
/**
*
* @description
*
*
*
* @default (info) => `${info.itemCount}`
*/
paginationPrefix: {
type: Function as PropType<PaginationPrefix>,
default: (info: Parameters<NonNullable<PaginationPrefix>>[0]) =>
`${info.itemCount}`,
},
} }
export default props export default props

View File

@ -1,5 +1,5 @@
import type { TableProps, RTableInst } from '@/components' import type { TableProps, RTableInst } from '@/components'
import type { UsePaginationReturn } from '@/hooks' import type { UsePaginationOptions } from '@/hooks'
import type { Recordable } from '@/types' import type { Recordable } from '@/types'
export type FormatRangeTime = { export type FormatRangeTime = {
@ -22,12 +22,18 @@ export type FormatRangeTime = {
* @description * @description
* Pagination * Pagination
*/ */
export type TablePagination = Pick< export interface TablePagination {
UsePaginationReturn[1], page: number
'getItemCount' | 'getPage' | 'getPageSize' pageSize: number
> itemCount: number
}
export interface TableRequestConfig<Params = Recordable> { export type PaginationPrefix = UsePaginationOptions['prefix']
export interface TableRequestConfig<
Params = Recordable,
ExcludeParams extends keyof Params = keyof Params,
> {
/** /**
* *
* @description * @description
@ -45,6 +51,14 @@ export interface TableRequestConfig<Params = Recordable> {
* @default undefined * @default undefined
*/ */
formatRangeTime?: FormatRangeTime[] formatRangeTime?: FormatRangeTime[]
/**
*
* @description
*
*
* @default undefined
*/
excludeParams?: ExcludeParams[]
} }
export type TableProProps = Omit<TableProps, 'pagination'> export type TableProProps = Omit<TableProps, 'pagination'>
@ -54,28 +68,67 @@ export interface TableProInst extends Omit<RTableInst, 'getTableInstance'> {
* *
* @description * @description
* pagination * pagination
*
* @example
* const [register, { getTablePagination }] = useTablePro()
*
* // 获取当前 pagination 的值
* const pagination = getTablePagination()
*/ */
getTablePagination: () => TablePagination getTablePagination: () => TablePagination
/** /**
*
* @param extraConfig
* @param reset
* *
* @description * @description
* *
*
* @example
* const [register, { runTableRequest }] = useTablePro()
*
* // 重置分页请求
* runTableRequest(void 0, true)
* runTableRequest()
* // 不重置分页请求
* runTableRequest(void 0, false)
*/ */
runTableRequest: (extraConfig?: TableRequestConfig) => void runTableRequest: <
T extends Recordable,
ExcludeParams extends keyof T = keyof T,
>(
extraConfig?: TableRequestConfig<T, ExcludeParams>,
reset?: boolean,
) => void
/** /**
* *
* @param extraConfig * @param extraConfig
* *
* @description * @description
* *
*
* @example
* const [register, { getCurrentTableRequestParams }] = useTablePro()
*
* // 获取当前内部表格请求参数
* const params = getCurrentTableRequestParams()
*/ */
getCurrentTableRequestParams: <T = Recordable>( getCurrentTableRequestParams: <
extraConfig?: TableRequestConfig<T>, T extends Recordable,
) => TableRequestConfig<T>['params'] & Recordable ExcludeParams extends keyof T = keyof T,
>(
extraConfig?: TableRequestConfig<T, ExcludeParams>,
) => TableRequestConfig<T, ExcludeParams>['params'] & Recordable
/** /**
* *
* @description * @description
* *
*
* @example
* const [register, { resetTablePagination }] = useTablePro()
*
* // 重置表格分页为初始化状态,即第 1 页,每页 10 条数据
* resetTablePagination()
*/ */
resetTablePagination: () => void resetTablePagination: () => void
} }

View File

@ -8,7 +8,7 @@
& .r-layout-full__viewer-content { & .r-layout-full__viewer-content {
height: var(--layout-content-height); height: var(--layout-content-height);
padding: 16px; padding: 8px 16px;
& .n-scrollbar-container { & .n-scrollbar-container {
height: 100%; height: 100%;

View File

@ -9,8 +9,10 @@
"Doc": "Doc", "Doc": "Doc",
"DocLocal": "Doc (China)", "DocLocal": "Doc (China)",
"DocLocalInside": "Docinside", "DocLocalInside": "Docinside",
"DraggableCard": "Draggable Card",
"Echart": "Chart", "Echart": "Chart",
"Error": "Error Page", "Error": "Error Page",
"Flow": "Flow",
"Form": "Form", "Form": "Form",
"Mock": "Mock", "Mock": "Mock",
"Modal": "Modal", "Modal": "Modal",
@ -26,9 +28,8 @@
"Segment": "Segment", "Segment": "Segment",
"SvgIcon": "SVG Icon", "SvgIcon": "SVG Icon",
"Table": "Table", "Table": "Table",
"TemplateHooks": "Template Api", "TableAutoHeight": "Table Auto Height",
"scrollReveal": "Scroll Reveal",
"TablePro": "Table Pro", "TablePro": "Table Pro",
"Flow": "Flow", "TemplateHooks": "Template Api",
"DraggableCard": "Draggable Card" "scrollReveal": "Scroll Reveal"
} }

View File

@ -9,8 +9,10 @@
"Doc": "文档", "Doc": "文档",
"DocLocal": "文档 (加速地址)", "DocLocal": "文档 (加速地址)",
"DocLocalInside": "文档(内嵌)", "DocLocalInside": "文档(内嵌)",
"DraggableCard": "拖拽卡片",
"Echart": "可视化", "Echart": "可视化",
"Error": "错误页", "Error": "错误页",
"Flow": "流程图",
"Form": "表单", "Form": "表单",
"Mock": "Mock 数据", "Mock": "Mock 数据",
"Modal": "模态框", "Modal": "模态框",
@ -26,9 +28,8 @@
"Segment": "分段器", "Segment": "分段器",
"SvgIcon": "SVG 图标", "SvgIcon": "SVG 图标",
"Table": "表格", "Table": "表格",
"TemplateHooks": "模板内置 Api", "TableAutoHeight": "自适应高度表格",
"scrollReveal": "滚动动画",
"TablePro": "高级表格", "TablePro": "高级表格",
"Flow": "流程图", "TemplateHooks": "模板内置 Api",
"DraggableCard": "拖拽卡片" "scrollReveal": "滚动动画"
} }

View File

@ -0,0 +1,20 @@
import { t } from '@/hooks/web/useI18n'
import { LAYOUT } from '@/router/constant'
import type { AppRouteRecordRaw } from '@/router/types'
const axios: AppRouteRecordRaw = {
path: '/table-auto-height',
name: 'RTableAutoHeight',
component: () => import('@/views/demo/table-auto-height'),
meta: {
i18nKey: t('menu.TableAutoHeight'),
icon: 'other',
order: 3,
extra: {
label: 'new',
},
},
}
export default axios

View File

@ -40,3 +40,7 @@
.n-input-number { .n-input-number {
width: 100%; width: 100%;
} }
.n-flex.flex-vertical {
height: 100%;
}

View File

@ -7,8 +7,10 @@ import type {
DialogApi, DialogApi,
LoadingBarApi, LoadingBarApi,
NotificationApi, NotificationApi,
DataTableColumns,
} from 'naive-ui' } from 'naive-ui'
import type { NativeElements, ReservedProps, VNode } from 'vue' import type { NativeElements, ReservedProps, VNode } from 'vue'
import type { Recordable } from './modules/helper'
export declare global { export declare global {
declare interface UnknownObjectKey { declare interface UnknownObjectKey {
@ -69,4 +71,8 @@ export declare global {
msCrypto: Crypto msCrypto: Crypto
} }
declare interface GlobalDataTableColumns<T> extends DataTableColumns<T> {}
declare type GlobalRecordable<T> = Recordable<T>
} }

View File

@ -1,5 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
type RecordKey = string | number | symbol
/** /**
* *
* @description * @description
@ -47,8 +49,10 @@ export type ConditionalPick<Base, Condition> = Pick<
* *
* @example * @example
* const A: Recordable = { a: 1, b: [] } * const A: Recordable = { a: 1, b: [] }
* const B : Recordable = { 1: '1', b: '2' }
* const C : Recordable = { [Symbol('a')]: 'a' }
*/ */
export type Recordable<T = any> = Record<string, T> export type Recordable<T = any> = Record<RecordKey, T>
/** /**
* *

View File

@ -0,0 +1,40 @@
type ValueType = number | [number, number] | null
export function getDateByNaiveDatePicker<
T extends ValueType = ValueType,
V extends boolean = boolean,
>(
value: T,
isRange: V,
): V extends true ? (T extends null ? [null, null] : T) : T
/**
*
* @param value date value
* @param isRange date picker type props is range type
*
* @description
* naive date picker value
*
* 使 BDatePicker type range true false
*
* @example
* // s1: null, e1: null
* const [s1, e1] = getDateByNaiveDatePicker(null, true)
* // s2: null
* const s2 = getDateByNaiveDatePicker(null, false)
* // s3: new Date().getTime()
* const s3 = getDateByNaiveDatePicker(new Date().getTime(), false)
* // s4: new Date().getTime(), e4: new Date().getTime()
* const [s4, e4] = getDateByNaiveDatePicker(
* [new Date().getTime(), new Date().getTime()],
* true,
* )
*/
export function getDateByNaiveDatePicker(value: ValueType, isRange: boolean) {
if (value === null) {
return isRange ? [null, null] : null
}
return value
}

View File

@ -11,3 +11,4 @@ export * from './c'
export { positionSelectedMenuItem } export { positionSelectedMenuItem }
export { updateObjectValue } from './update-object-value' export { updateObjectValue } from './update-object-value'
export { removeDuplicateKeys } from './remove-duplicate-keys' export { removeDuplicateKeys } from './remove-duplicate-keys'
export { getDateByNaiveDatePicker } from './get-date-by-naive-date-picker'

View File

@ -0,0 +1,223 @@
import { RTablePro, RCollapse } from '@/components'
import {
NFlex,
NFormItemGi,
NInput,
NSelect,
NDatePicker,
NButton,
NTag,
NSwitch,
} from 'naive-ui'
import dayjs from 'dayjs'
import { uuid } from '@/utils'
import Mock from 'mockjs'
import { useDayjs } from '@/hooks'
type RowData = {
key: number | string
name: string
age: number
address: string
tags: string[]
remark: string
status: string
statusText: string
signTimeEnd: number
signTimeStart: number
}
export default defineComponent({
name: 'TableAutoHeight',
setup() {
const { format } = useDayjs()
const baseColumns = ref<GlobalDataTableColumns<RowData>>([
{
type: 'selection',
},
{
title: 'Name',
key: 'name',
},
{
title: 'Sign Status',
key: 'statusText',
},
{
title: 'Sign Time',
key: 'signTimeStart',
render: (row: RowData) =>
format(row.signTimeStart) + ' ~ ' + format(row.signTimeEnd),
},
{
title: 'Age',
key: 'age',
},
{
title: 'Address',
key: 'address',
},
{
title: 'Tags',
key: 'tags',
render: (row: RowData) => {
const tags = row.tags.map((tagKey) => {
return (
<NTag type="info" bordered={false} style="margin-right: 6px">
{tagKey}
</NTag>
)
})
return tags
},
},
{
title: 'Remark',
key: 'remark',
},
])
const mockPersonList = ref<RowData[]>(
(() => {
const length = 30
const list: RowData[] = []
const time = dayjs().valueOf()
for (let i = 0; i < length; i++) {
list.push({
key: uuid(),
name: Mock.Random.cname(),
age: i + 20,
address: Mock.Random.city(),
tags: ['nice', 'developer'],
remark: '我是一条很长很长的备注',
status: i % 2 === 0 ? 'success' : 'error',
statusText: i % 2 === 0 ? '在线' : '离线',
signTimeStart: dayjs(time)
.add(i * 2, 'year')
.valueOf(),
signTimeEnd: dayjs(time)
.add(i + 5, 'day')
.valueOf(),
})
}
return list
})(),
)
const switchRef = ref({
footer: false,
action: false,
flexAutoHeight: true,
})
return {
mockPersonList,
baseColumns,
switchRef,
}
},
render() {
const { mockPersonList, baseColumns, switchRef } = this
return (
<NFlex vertical class="flex-vertical">
<RCollapse bordered>
{{
default: () => (
<>
<NFormItemGi label="用户名">
<NInput clearable />
</NFormItemGi>
<NFormItemGi label="状态">
<NSelect
clearable
options={[
{
label: '成功',
value: 'success',
},
{
label: '失败',
value: 'error',
},
]}
/>
</NFormItemGi>
<NFormItemGi label="登陆时间">
<NDatePicker type="datetimerange" clearable />
</NFormItemGi>
<NFormItemGi label="演示折叠的条件框">
<NInput clearable />
</NFormItemGi>
<NFormItemGi label="演示折叠的条件框">
<NInput clearable />
</NFormItemGi>
<NFormItemGi label="演示折叠的条件框">
<NInput clearable />
</NFormItemGi>
<NFormItemGi label="演示折叠的条件框">
<NInput clearable />
</NFormItemGi>
<NFormItemGi label="演示折叠的条件框">
<NInput clearable />
</NFormItemGi>
<NFormItemGi label="演示折叠的条件框">
<NInput clearable />
</NFormItemGi>
</>
),
action: () => (
<NFlex>
<NButton type="primary"></NButton>
</NFlex>
),
}}
</RCollapse>
<RTablePro
data={mockPersonList}
v-model:columns={baseColumns}
showPagination
paginationCount={mockPersonList.length}
remote={false}
flexAutoHeight={switchRef.flexAutoHeight}
title={
<NFlex>
<NFlex align="center">
<NButton text focusable={false}>
</NButton>
<NSwitch v-model:value={switchRef.flexAutoHeight} />
</NFlex>
<NFlex align="center">
<NButton text focusable={false}>
</NButton>
<NSwitch v-model:value={switchRef.footer} />
</NFlex>
<NFlex align="center">
<NButton text focusable={false}>
</NButton>
<NSwitch v-model:value={switchRef.action} />
</NFlex>
</NFlex>
}
>
{{
tableFooter: () =>
switchRef.footer
? '表格的底部内容区域插槽,有时候你可能会用上'
: null,
tableAction: () =>
switchRef.action
? '表格的操作区域内容插槽,有时候可能会用上'
: null,
}}
</RTablePro>
</NFlex>
)
},
})