mirror of
https://github.com/XiaoDaiGua-Ray/ray-template.git
synced 2025-04-05 07:03:00 +08:00
version: v4.9.3
This commit is contained in:
parent
3f7e3722fd
commit
fa8d52601f
25
CHANGELOG.md
25
CHANGELOG.md
@ -1,5 +1,30 @@
|
|||||||
# CHANGE LOG
|
# CHANGE LOG
|
||||||
|
|
||||||
|
## 4.9.3
|
||||||
|
|
||||||
|
## Feats
|
||||||
|
|
||||||
|
- 更新 `vue` 版本至 `3.4.38`
|
||||||
|
- 更新 `vite` 版本至 `5.4.1`
|
||||||
|
- 调整 `RCollapseGrid` 支持 `actionAlign` 配置型,配置按钮垂直方向,默认为 `end`
|
||||||
|
- `MenuTag` 组件
|
||||||
|
- 调整 `MenuTag` 滚动条样式,现在将它隐藏了
|
||||||
|
- 优化关闭按钮样式
|
||||||
|
- `RTable` 新增 `renderWrapperHeader` 配置项,配置外层容器 `header` 是否渲染
|
||||||
|
- `postcss` 配置 `not dead`,忽略兼容已经无需兼容的浏览器
|
||||||
|
- `RChart` 组件 `setOptions` 方法配置项默认不启用 `merge` 模式
|
||||||
|
- 调整 `header` 的样式,增加了一点点间隙
|
||||||
|
- `useDevice` 新增 `observer` 配置项,可以自定义观察回调
|
||||||
|
- 新增 `components-pro` 包,助力简化业务开发
|
||||||
|
- 新增 `RTablePro` 组件,大幅简化中后台带有过滤请求条件的表格显示业务
|
||||||
|
- 新增 `RCollapse` 组件,允许折叠过滤条件
|
||||||
|
|
||||||
|
## Fixes
|
||||||
|
|
||||||
|
- 移除 `postcss-px-to-viewport-8-plugin` 插件,使用 `postcss-px-to-viewport-8-with-include` 替换,修复 `include` 失效问题
|
||||||
|
- 修复 `useElementFullscreen` 在退出时,没有正确的回滚 `zIndex` 的问题
|
||||||
|
- 修复 `RChart` 配置 `setChartOptions` 不生效的问题
|
||||||
|
|
||||||
## 4.9.2
|
## 4.9.2
|
||||||
|
|
||||||
## Feats
|
## Feats
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ray-template",
|
"name": "ray-template",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "4.9.2",
|
"version": "4.9.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.0.0 || >=20.0.0",
|
"node": "^18.0.0 || >=20.0.0",
|
||||||
@ -48,7 +48,7 @@
|
|||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"pinia-plugin-persistedstate": "^3.2.0",
|
"pinia-plugin-persistedstate": "^3.2.0",
|
||||||
"print-js": "^1.6.0",
|
"print-js": "^1.6.0",
|
||||||
"vue": "^3.4.34",
|
"vue": "^3.4.38",
|
||||||
"vue-demi": "0.14.6",
|
"vue-demi": "0.14.6",
|
||||||
"vue-hooks-plus": "2.2.1",
|
"vue-hooks-plus": "2.2.1",
|
||||||
"vue-i18n": "^9.13.1",
|
"vue-i18n": "^9.13.1",
|
||||||
@ -85,14 +85,14 @@
|
|||||||
"husky": "8.0.3",
|
"husky": "8.0.3",
|
||||||
"lint-staged": "^15.1.0",
|
"lint-staged": "^15.1.0",
|
||||||
"postcss": "^8.4.31",
|
"postcss": "^8.4.31",
|
||||||
"postcss-px-to-viewport-8-plugin": "1.2.3",
|
"postcss-px-to-viewport-8-with-include": "1.2.2",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"sass": "1.71.1",
|
"sass": "1.71.1",
|
||||||
"svg-sprite-loader": "^6.0.11",
|
"svg-sprite-loader": "^6.0.11",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
"unplugin-auto-import": "^0.17.5",
|
"unplugin-auto-import": "^0.17.5",
|
||||||
"unplugin-vue-components": "^0.26.0",
|
"unplugin-vue-components": "^0.26.0",
|
||||||
"vite": "^5.3.5",
|
"vite": "^5.4.1",
|
||||||
"vite-bundle-analyzer": "0.9.4",
|
"vite-bundle-analyzer": "0.9.4",
|
||||||
"vite-plugin-cdn2": "1.1.0",
|
"vite-plugin-cdn2": "1.1.0",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
|
521
pnpm-lock.yaml
generated
521
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -8,31 +8,32 @@ module.exports = {
|
|||||||
'ff > 31',
|
'ff > 31',
|
||||||
'ie >= 8',
|
'ie >= 8',
|
||||||
'last 10 versions',
|
'last 10 versions',
|
||||||
|
'not dead',
|
||||||
],
|
],
|
||||||
grid: true,
|
grid: true,
|
||||||
},
|
},
|
||||||
// 为了适配 postcss8.x 版本的转换库
|
// 为了适配 postcss8.x 版本的转换库
|
||||||
'postcss-px-to-viewport-8-plugin': {
|
'postcss-px-to-viewport-8-with-include': {
|
||||||
inlinePxToViewport: true,
|
// 横屏时使用的视口宽度
|
||||||
/** 视窗的宽度(设计稿的宽度) */
|
landscapeWidth: 1920,
|
||||||
|
// 视窗的宽度(设计稿的宽度)
|
||||||
viewportWidth: 1920,
|
viewportWidth: 1920,
|
||||||
/** 视窗的高度(设计稿高度, 一般无需指定) */
|
// 指定 px 转换为视窗单位值的小数位数
|
||||||
viewportHeight: 1080,
|
|
||||||
/** 指定 px 转换为视窗单位值的小数位数 */
|
|
||||||
unitPrecision: 3,
|
unitPrecision: 3,
|
||||||
/** 指定需要转换成的视窗单位 */
|
// 指定需要转换成的视窗单位
|
||||||
viewportUnit: 'rem',
|
viewportUnit: 'vw',
|
||||||
/** 制定字体转换单位 */
|
// 制定字体转换单位
|
||||||
fontViewportUnit: 'rem',
|
fontViewportUnit: 'vw',
|
||||||
/** 指定不转换为视窗单位的类 */
|
// 指定不转换为视窗单位的类
|
||||||
selectorBlackList: ['.ignore'],
|
selectorBlackList: ['.ignore'],
|
||||||
/** 小于或等于 1px 不转换为视窗单位 */
|
// 小于或等于 1px 不转换为视窗单位
|
||||||
minPixelValue: 1,
|
minPixelValue: 1,
|
||||||
/** 允许在媒体查询中转换 px */
|
// 允许在媒体查询中转换 px
|
||||||
mediaQuery: false,
|
mediaQuery: false,
|
||||||
exclude: /(\/|\\)(node_modules)(\/|\\)/, // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
|
// 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
|
||||||
include: [/^src[/\\].*\.(vue|tsx|jsx|ts(?!d))$/],
|
exclude: /node_modules/,
|
||||||
preserve: true,
|
// 指定一个空的文件夹,避免影响到无需转换的文件
|
||||||
|
include: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
49
src/components-pro/RCollapse/Collapse.tsx
Normal file
49
src/components-pro/RCollapse/Collapse.tsx
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ray <https://github.com/XiaoDaiGua-Ray>
|
||||||
|
*
|
||||||
|
* @date 2024-05-16
|
||||||
|
*
|
||||||
|
* @workspace ray-template
|
||||||
|
*
|
||||||
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { RCollapseGrid, RForm } from '@/components'
|
||||||
|
|
||||||
|
import { collapseGridProps, formProps } from '@/components'
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 基于 RCollapseGrid 和 RForm 的折叠表单组件;
|
||||||
|
* 同样也继承了 RCollapseGrid 组件的缺点,必须使用 NFormItemGi, NGridItem 组件包裹表单项。
|
||||||
|
*/
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'RCollapse',
|
||||||
|
props: Object.assign(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
...collapseGridProps,
|
||||||
|
open: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
cols: {
|
||||||
|
type: Number,
|
||||||
|
default: 4,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
formProps,
|
||||||
|
),
|
||||||
|
render() {
|
||||||
|
const { $slots, $props } = this
|
||||||
|
const { labelPlacement, showFeedback, ...rest } = $props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RForm {...rest} labelPlacement="top" showFeedback={false}>
|
||||||
|
<RCollapseGrid {...rest}>{$slots}</RCollapseGrid>
|
||||||
|
</RForm>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
11
src/components-pro/RTablePro/index.ts
Normal file
11
src/components-pro/RTablePro/index.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import RTablePro from './src/TablePro'
|
||||||
|
import tableProProps from './src/props'
|
||||||
|
import { useTablePro } from './src/hooks/useTablePro'
|
||||||
|
|
||||||
|
import type { ExtractPropTypes } from 'vue'
|
||||||
|
|
||||||
|
type TableProProps = ExtractPropTypes<typeof tableProProps>
|
||||||
|
|
||||||
|
export type { TableProProps }
|
||||||
|
|
||||||
|
export { RTablePro, useTablePro, tableProProps }
|
179
src/components-pro/RTablePro/src/TablePro.tsx
Normal file
179
src/components-pro/RTablePro/src/TablePro.tsx
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ray <https://github.com/XiaoDaiGua-Ray>
|
||||||
|
*
|
||||||
|
* @date 2024-05-10
|
||||||
|
*
|
||||||
|
* @workspace ray-template
|
||||||
|
*
|
||||||
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { RTable } from '@/components'
|
||||||
|
|
||||||
|
import props from './props'
|
||||||
|
import { useTable } from '@/components'
|
||||||
|
import { call } from '@/utils'
|
||||||
|
import { usePagination } from '@/hooks'
|
||||||
|
|
||||||
|
import type { TablePagination, TableRequestConfig, TableProInst } from './types'
|
||||||
|
import type { Recordable } from '@/types'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'RTablePro',
|
||||||
|
props,
|
||||||
|
setup(props) {
|
||||||
|
const [register, { getTableInstance }] = useTable()
|
||||||
|
const [
|
||||||
|
paginationRef,
|
||||||
|
{
|
||||||
|
getPage,
|
||||||
|
getPageSize,
|
||||||
|
setCallback,
|
||||||
|
setItemCount,
|
||||||
|
getPagination,
|
||||||
|
resetPagination,
|
||||||
|
getItemCount,
|
||||||
|
},
|
||||||
|
] = usePagination(void 0, {
|
||||||
|
prefix: (info) => `共 ${info.itemCount} 条`,
|
||||||
|
})
|
||||||
|
const tableRequestRef = computed(() => props.request)
|
||||||
|
|
||||||
|
// 获取最新 statistics 和 pagination 值
|
||||||
|
const update = (): TablePagination => {
|
||||||
|
const pagination = getPagination()
|
||||||
|
|
||||||
|
return {
|
||||||
|
getItemCount,
|
||||||
|
getPage,
|
||||||
|
getPageSize,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 派发表格更新事件
|
||||||
|
const emitTableUpdate = () => {
|
||||||
|
const { onTablePaginationUpdate } = props
|
||||||
|
|
||||||
|
if (onTablePaginationUpdate) {
|
||||||
|
call(onTablePaginationUpdate, update())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并请求参数
|
||||||
|
const combineRequestParams = (extraConfig?: TableRequestConfig) => {
|
||||||
|
const config = Object.assign({}, props.requestConfig, extraConfig)
|
||||||
|
|
||||||
|
const { params, formatRangeTime } = config
|
||||||
|
|
||||||
|
// 转换时间范围,该功能仅支持 NDatePicker range 模式参数
|
||||||
|
if (formatRangeTime?.length && params) {
|
||||||
|
formatRangeTime.forEach((curr) => {
|
||||||
|
const { key, target } = curr
|
||||||
|
const val = params[key] as [number, number] | null
|
||||||
|
|
||||||
|
if (val && target?.length) {
|
||||||
|
const [start, end] = val
|
||||||
|
|
||||||
|
params[target[0]] = start
|
||||||
|
params[target[1]] = end
|
||||||
|
} else {
|
||||||
|
// 当传递时间参数被清空时,则清空对应 time key
|
||||||
|
params[key] = null
|
||||||
|
params[target[0]] = null
|
||||||
|
params[target[1]] = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestParams = Object.assign({}, params, {
|
||||||
|
page: getPage(),
|
||||||
|
pageSize: getPageSize(),
|
||||||
|
})
|
||||||
|
|
||||||
|
return requestParams
|
||||||
|
}
|
||||||
|
|
||||||
|
// 会重置 pagination 的请求
|
||||||
|
const runResetPaginationRequest = (extraConfig?: TableRequestConfig) => {
|
||||||
|
resetPagination()
|
||||||
|
|
||||||
|
const requestParams = combineRequestParams(extraConfig)
|
||||||
|
|
||||||
|
tableRequestRef.value?.(requestParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 不会重置 pagination 的请求
|
||||||
|
const runRequest = (extraConfig?: TableRequestConfig) => {
|
||||||
|
const requestParams = combineRequestParams(extraConfig)
|
||||||
|
|
||||||
|
tableRequestRef.value?.(requestParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
setItemCount(props.paginationCount)
|
||||||
|
setCallback(() => {
|
||||||
|
const { manual } = props
|
||||||
|
|
||||||
|
if (!manual) {
|
||||||
|
runRequest()
|
||||||
|
}
|
||||||
|
|
||||||
|
emitTableUpdate()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const { onRegister } = props
|
||||||
|
|
||||||
|
if (onRegister && getTableInstance()) {
|
||||||
|
const {
|
||||||
|
clearFilters,
|
||||||
|
clearSorter,
|
||||||
|
downloadCsv,
|
||||||
|
filters,
|
||||||
|
page,
|
||||||
|
scrollTo,
|
||||||
|
sort,
|
||||||
|
filter,
|
||||||
|
print,
|
||||||
|
} = getTableInstance()
|
||||||
|
|
||||||
|
call(onRegister, {
|
||||||
|
getTablePagination: update,
|
||||||
|
runTableRequest: runResetPaginationRequest,
|
||||||
|
clearFilters,
|
||||||
|
clearSorter,
|
||||||
|
downloadCsv,
|
||||||
|
filters,
|
||||||
|
page,
|
||||||
|
scrollTo,
|
||||||
|
sort,
|
||||||
|
filter,
|
||||||
|
print,
|
||||||
|
getCurrentTableRequestParams:
|
||||||
|
combineRequestParams as TableProInst['getCurrentTableRequestParams'],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
register,
|
||||||
|
paginationRef,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
const { register, $props, paginationRef, $slots } = this
|
||||||
|
const { onRegister, showPagination, ...rest } = $props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RTable
|
||||||
|
{...rest}
|
||||||
|
onRegister={register}
|
||||||
|
pagination={showPagination ? paginationRef : void 0}
|
||||||
|
>
|
||||||
|
{$slots}
|
||||||
|
</RTable>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
172
src/components-pro/RTablePro/src/hooks/useTablePro.ts
Normal file
172
src/components-pro/RTablePro/src/hooks/useTablePro.ts
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
import type { Recordable } from '@/types'
|
||||||
|
import type { TableProInst, TableRequestConfig } from '../types'
|
||||||
|
import type {
|
||||||
|
RTableInst,
|
||||||
|
CsvOptionsType,
|
||||||
|
FilterState,
|
||||||
|
ScrollToOptions,
|
||||||
|
ColumnKey,
|
||||||
|
SortOrder,
|
||||||
|
} from '@/components/RTable/src/types'
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 获取 TablePro 实例上的一些方法。
|
||||||
|
* 使用方法与 useTable 类似。
|
||||||
|
*/
|
||||||
|
export const useTablePro = () => {
|
||||||
|
const tableInst = ref<TableProInst>()
|
||||||
|
|
||||||
|
const register = (inst: TableProInst) => {
|
||||||
|
if (inst) {
|
||||||
|
tableInst.value = inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 获取 TablePro 实例。
|
||||||
|
*/
|
||||||
|
const getTableProInstance = () => {
|
||||||
|
if (!tableInst.value) {
|
||||||
|
throw new Error(
|
||||||
|
'[useTablePro]: table instance is not ready yet. if you are using useTablePro, please make sure you have called register method in onRegister event.',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tableInst.value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 获取 statistics, pagination 更新信息。
|
||||||
|
*/
|
||||||
|
const getTablePagination = () =>
|
||||||
|
getTableProInstance().getTablePagination.call(null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 手动触发表格请求,用于手动刷新表格。
|
||||||
|
* 如果设置了 manual 为 true,则需要手动调用该函数。
|
||||||
|
* 该函数会自动匹配 statistics, pagination 更新的值去请求。
|
||||||
|
*
|
||||||
|
* 允许手动配置 TableRequestConfig 参数,会自动合并 props tableRequestConfig 配置。
|
||||||
|
* 并且,运行该函数会重置 pagination 为初始状态。
|
||||||
|
*/
|
||||||
|
const runTableRequest = <T extends Recordable>(
|
||||||
|
extraConfig?: TableRequestConfig<T>,
|
||||||
|
) => getTableProInstance().runTableRequest.call(null, extraConfig)
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 清空所有 filter 状态。
|
||||||
|
*
|
||||||
|
* @see https://www.naiveui.com/zh-CN/dark/components/data-table#filter-and-sorter
|
||||||
|
*/
|
||||||
|
const clearFilters = () => getTableProInstance().clearFilters.call(null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 清空所有 sort 状态。
|
||||||
|
*
|
||||||
|
* @see https://www.naiveui.com/zh-CN/dark/components/data-table#filter-and-sorter
|
||||||
|
*/
|
||||||
|
const clearSorter = () => getTableProInstance().clearSorter.call(null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 下载 CSV。
|
||||||
|
*
|
||||||
|
* @see https://www.naiveui.com/zh-CN/dark/components/data-table#export-csv.vue
|
||||||
|
*/
|
||||||
|
const downloadCsv = (options?: CsvOptionsType) =>
|
||||||
|
getTableProInstance().downloadCsv.call(null, options)
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 设定表格当前的过滤器。
|
||||||
|
*
|
||||||
|
* @see https://www.naiveui.com/zh-CN/dark/components/data-table#filter-and-sorter
|
||||||
|
*/
|
||||||
|
const filters = (filters: FilterState | null) =>
|
||||||
|
getTableProInstance().filters.call(null, filters)
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 手动设置 page。
|
||||||
|
*
|
||||||
|
* @see https://www.naiveui.com/zh-CN/dark/components/data-table#DataTable-Methods
|
||||||
|
*/
|
||||||
|
const page = (page: number) => getTableProInstance().page.call(null, page)
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 滚动内容。
|
||||||
|
*
|
||||||
|
* @see https://www.naiveui.com/zh-CN/dark/components/data-table#DataTable-Methods
|
||||||
|
*/
|
||||||
|
const scrollTo: ScrollToOptions = (options) =>
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
getTableProInstance().scrollTo(options as any)
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 设定表格的过滤状态。
|
||||||
|
*
|
||||||
|
* @see https://www.naiveui.com/zh-CN/dark/components/data-table#DataTable-Methods
|
||||||
|
*/
|
||||||
|
const sort = (columnKey: ColumnKey, order: SortOrder) =>
|
||||||
|
getTableProInstance().sort.call(null, columnKey, order)
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 打印表格。
|
||||||
|
*/
|
||||||
|
const print = () => getTableProInstance().print.call(null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param extraConfig 额外请求合并配置项
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 获取当前内部表格请求参数。
|
||||||
|
*/
|
||||||
|
const getCurrentTableRequestParams = <T = Recordable>(
|
||||||
|
extraConfig?: TableRequestConfig<T>,
|
||||||
|
): T & Recordable =>
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
getTableProInstance().getCurrentTableRequestParams.call(null, extraConfig)
|
||||||
|
|
||||||
|
return [
|
||||||
|
register,
|
||||||
|
{
|
||||||
|
clearFilters,
|
||||||
|
getTableProInstance,
|
||||||
|
clearSorter,
|
||||||
|
downloadCsv,
|
||||||
|
filters,
|
||||||
|
page,
|
||||||
|
scrollTo,
|
||||||
|
sort,
|
||||||
|
getTablePagination,
|
||||||
|
runTableRequest,
|
||||||
|
print,
|
||||||
|
getCurrentTableRequestParams,
|
||||||
|
},
|
||||||
|
] as const
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UseTableProReturn = ReturnType<typeof useTablePro>
|
106
src/components-pro/RTablePro/src/props.ts
Normal file
106
src/components-pro/RTablePro/src/props.ts
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import { tableProps } from '@/components'
|
||||||
|
import { omit } from 'lodash-es'
|
||||||
|
|
||||||
|
import type { PropType } from 'vue'
|
||||||
|
import type { TableProInst, TablePagination, TableRequestConfig } from './types'
|
||||||
|
import type { AnyFC } from '@/types'
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
...omit(tableProps, ['pagination']),
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 分页总数。
|
||||||
|
*
|
||||||
|
* @default 1
|
||||||
|
*/
|
||||||
|
paginationCount: {
|
||||||
|
type: Number,
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 注册 useTablePro 钩子函数。
|
||||||
|
*
|
||||||
|
* @default undefined
|
||||||
|
*/
|
||||||
|
onRegister: {
|
||||||
|
type: Function as PropType<(inst: TableProInst) => void>,
|
||||||
|
default: void 0,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 是否需要手动控制表格的刷新。
|
||||||
|
* 如果设置为 true,在 Pagination 更新时,不会自动触发表格的刷新。
|
||||||
|
*
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
manual: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 刷新表格的请求函数。
|
||||||
|
* 该属性用于配置表格的刷新请求函数。
|
||||||
|
*
|
||||||
|
* 如果设置了该属性,则会在表格刷新时调用该函数。
|
||||||
|
*
|
||||||
|
* @default undefined
|
||||||
|
*/
|
||||||
|
request: {
|
||||||
|
type: Function as PropType<AnyFC>,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* pagination 更新时的回调函数。
|
||||||
|
*
|
||||||
|
* @default undefined
|
||||||
|
*/
|
||||||
|
onTablePaginationUpdate: {
|
||||||
|
type: Function as PropType<(pagination: TablePagination) => void>,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 请求函数的参数。
|
||||||
|
* 该属性用于配置请求函数的参数。
|
||||||
|
*
|
||||||
|
* @default {}
|
||||||
|
*/
|
||||||
|
requestConfig: {
|
||||||
|
type: Object as PropType<TableRequestConfig>,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 是否显示分页器。
|
||||||
|
* 如果需要显示分页器,则设置为 true。
|
||||||
|
*
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
showPagination: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 设置表格数据为异步状态。
|
||||||
|
* 当你使用该组件的时候,会默认认为你总是异步获取数据,所以重写了原组件的 remote,
|
||||||
|
* 现在 remote 默认为开启状态,也就是默认为 true。
|
||||||
|
*
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
remote: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default props
|
75
src/components-pro/RTablePro/src/types.ts
Normal file
75
src/components-pro/RTablePro/src/types.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import type { TableProps, RTableInst } from '@/components'
|
||||||
|
import type { UsePaginationReturn } from '@/hooks'
|
||||||
|
import type { Recordable } from '@/types'
|
||||||
|
|
||||||
|
export type FormatRangeTime = {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 请求参数中需要格式化的时间参数字段。
|
||||||
|
*/
|
||||||
|
key: string | number
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 后端接口中需要的起止时间参数字段。
|
||||||
|
*/
|
||||||
|
target: [string | number, string | number]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Pagination 分页配置。
|
||||||
|
*/
|
||||||
|
export type TablePagination = Pick<
|
||||||
|
UsePaginationReturn[1],
|
||||||
|
'getItemCount' | 'getPage' | 'getPageSize'
|
||||||
|
>
|
||||||
|
|
||||||
|
export interface TableRequestConfig<Params = Recordable> {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 请求参数。
|
||||||
|
* @default undefined
|
||||||
|
*/
|
||||||
|
params?: Params
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 格式化时间范围,该字段用于格式化时间范围。
|
||||||
|
* 并且仅支持 NDatePicker range 模式。
|
||||||
|
* 如果在请求的参数中,有时间段的字段,且需要格式化时间段,则需要配置该字段。
|
||||||
|
*
|
||||||
|
* @default undefined
|
||||||
|
*/
|
||||||
|
formatRangeTime?: FormatRangeTime[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TableProProps = Omit<TableProps, 'pagination'>
|
||||||
|
|
||||||
|
export interface TableProInst extends Omit<RTableInst, 'getTableInstance'> {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 获取 pagination 更新值。
|
||||||
|
*/
|
||||||
|
getTablePagination: () => TablePagination
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 手动触发表格请求,用于手动刷新表格。
|
||||||
|
*/
|
||||||
|
runTableRequest: (extraConfig?: TableRequestConfig) => void
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param extraConfig 额外请求合并配置项
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 获取当前内部表格请求参数。
|
||||||
|
*/
|
||||||
|
getCurrentTableRequestParams: <T = Recordable>(
|
||||||
|
extraConfig?: TableRequestConfig<T>,
|
||||||
|
) => TableRequestConfig<T>['params'] & Recordable
|
||||||
|
}
|
4
src/components-pro/index.ts
Normal file
4
src/components-pro/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import RCollapse from './RCollapse/Collapse'
|
||||||
|
|
||||||
|
export * from './RTablePro'
|
||||||
|
export { RCollapse }
|
@ -48,7 +48,7 @@ import type { DropdownProps, DropdownOption } from 'naive-ui'
|
|||||||
|
|
||||||
// setOption 默认配置项
|
// setOption 默认配置项
|
||||||
const defaultChartOptions = {
|
const defaultChartOptions = {
|
||||||
notMerge: false,
|
notMerge: true,
|
||||||
lazyUpdate: true,
|
lazyUpdate: true,
|
||||||
silent: false,
|
silent: false,
|
||||||
replaceMerge: [],
|
replaceMerge: [],
|
||||||
@ -434,8 +434,8 @@ export default defineComponent({
|
|||||||
const options = combineChartOptions(ndata)
|
const options = combineChartOptions(ndata)
|
||||||
const setOpt = Object.assign(
|
const setOpt = Object.assign(
|
||||||
{},
|
{},
|
||||||
props.setChartOptions,
|
|
||||||
defaultChartOptions,
|
defaultChartOptions,
|
||||||
|
props.setChartOptions,
|
||||||
)
|
)
|
||||||
|
|
||||||
// 如果 options 发生变动更新 echarts
|
// 如果 options 发生变动更新 echarts
|
||||||
|
@ -356,12 +356,12 @@ const props = {
|
|||||||
* @description
|
* @description
|
||||||
* 设置 setOptions 方法配置项。
|
* 设置 setOptions 方法配置项。
|
||||||
*
|
*
|
||||||
* @default {notMerge:false,lazyUpdate:true,silent:false,replaceMerge:[]}
|
* @default {notMerge:true,lazyUpdate:true,silent:false,replaceMerge:[]}
|
||||||
*/
|
*/
|
||||||
setChartOptions: {
|
setChartOptions: {
|
||||||
type: Object as PropType<SetOptionOpts>,
|
type: Object as PropType<SetOptionOpts>,
|
||||||
default: () => ({
|
default: () => ({
|
||||||
notMerge: false,
|
notMerge: true,
|
||||||
lazyUpdate: true,
|
lazyUpdate: true,
|
||||||
silent: false,
|
silent: false,
|
||||||
replaceMerge: [],
|
replaceMerge: [],
|
||||||
|
@ -20,4 +20,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ray-collapse-grid__suffix--btn {
|
||||||
|
align-self: var(--r-collapse-grid-action-align);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,13 @@ export default defineComponent({
|
|||||||
props,
|
props,
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const modelCollapsed = ref(!props.open)
|
const modelCollapsed = ref(!props.open)
|
||||||
|
const cssVars = computed(() => {
|
||||||
|
const cssVar = {
|
||||||
|
'--r-collapse-grid-action-align': props.actionAlign,
|
||||||
|
}
|
||||||
|
|
||||||
|
return cssVar
|
||||||
|
})
|
||||||
|
|
||||||
const collapseClick = () => {
|
const collapseClick = () => {
|
||||||
modelCollapsed.value = !modelCollapsed.value
|
modelCollapsed.value = !modelCollapsed.value
|
||||||
@ -68,11 +75,14 @@ export default defineComponent({
|
|||||||
modelCollapsed,
|
modelCollapsed,
|
||||||
collapseClick,
|
collapseClick,
|
||||||
CollapseIcon,
|
CollapseIcon,
|
||||||
|
cssVars,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
|
const { cssVars } = this
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NCard bordered={this.bordered}>
|
<NCard bordered={this.bordered} style={[cssVars]}>
|
||||||
{{
|
{{
|
||||||
default: () => (
|
default: () => (
|
||||||
<NGrid
|
<NGrid
|
||||||
@ -84,7 +94,7 @@ export default defineComponent({
|
|||||||
collapsedRows={this.collapsedRows}
|
collapsedRows={this.collapsedRows}
|
||||||
>
|
>
|
||||||
{this.$slots.default?.()}
|
{this.$slots.default?.()}
|
||||||
<NGridItem suffix class="ray-collapse-grid__suffix--btn">
|
<NGridItem suffix class={['ray-collapse-grid__suffix--btn']}>
|
||||||
<NFlex justify="end" align="center">
|
<NFlex justify="end" align="center">
|
||||||
{this.$slots.action?.()}
|
{this.$slots.action?.()}
|
||||||
{this.CollapseIcon()}
|
{this.CollapseIcon()}
|
||||||
|
@ -1,10 +1,21 @@
|
|||||||
import { gridProps } from 'naive-ui'
|
import { gridProps } from 'naive-ui'
|
||||||
|
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
import type { CollapseToggleText } from './types'
|
import type { CollapseToggleText, ActionAlignType } from './types'
|
||||||
import type { AnyFC, MaybeArray } from '@/types'
|
import type { AnyFC, MaybeArray } from '@/types'
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 自定义操作按钮区域按钮列排列方式。
|
||||||
|
*
|
||||||
|
* @default end
|
||||||
|
*/
|
||||||
|
actionAlign: {
|
||||||
|
type: String as PropType<ActionAlignType>,
|
||||||
|
default: 'end',
|
||||||
|
},
|
||||||
open: {
|
open: {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -1 +1,3 @@
|
|||||||
export type CollapseToggleText = [string | number, string | number]
|
export type CollapseToggleText = [string | number, string | number]
|
||||||
|
|
||||||
|
export type ActionAlignType = 'auto' | 'end' | 'center' | 'start'
|
||||||
|
@ -25,8 +25,6 @@ const useModal = () => {
|
|||||||
},
|
},
|
||||||
trigger: 'none',
|
trigger: 'none',
|
||||||
style: {
|
style: {
|
||||||
padding:
|
|
||||||
'0 var(--n-padding-left) var(--n-padding-bottom) var(--n-padding-left)',
|
|
||||||
width: 'auto',
|
width: 'auto',
|
||||||
height:
|
height:
|
||||||
'calc(100vh - 29px - var(--n-padding-bottom) - var(--n-padding-bottom) - var(--n-padding-top))',
|
'calc(100vh - 29px - var(--n-padding-bottom) - var(--n-padding-bottom) - var(--n-padding-top))',
|
||||||
|
@ -25,7 +25,11 @@ import { pick } from 'lodash-es'
|
|||||||
|
|
||||||
import type { DropdownOption, DataTableInst } from 'naive-ui'
|
import type { DropdownOption, DataTableInst } from 'naive-ui'
|
||||||
import type { ComponentSize } from '@/types'
|
import type { ComponentSize } from '@/types'
|
||||||
import type { C as CType, PropsComponentPopselectKeys } from './types'
|
import type {
|
||||||
|
C as CType,
|
||||||
|
PropsComponentPopselectKeys,
|
||||||
|
RTableInst,
|
||||||
|
} from './types'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'RTable',
|
name: 'RTable',
|
||||||
@ -34,7 +38,7 @@ export default defineComponent({
|
|||||||
setup(props, ctx) {
|
setup(props, ctx) {
|
||||||
const { expose, emit } = ctx
|
const { expose, emit } = ctx
|
||||||
|
|
||||||
const rTableInst = ref<DataTableInst>()
|
const rTableInst = ref<RTableInst>()
|
||||||
const wrapperRef = ref<HTMLElement>()
|
const wrapperRef = ref<HTMLElement>()
|
||||||
|
|
||||||
const uuidWrapper = uuid(16) // wrapper id
|
const uuidWrapper = uuid(16) // wrapper id
|
||||||
@ -147,7 +151,7 @@ export default defineComponent({
|
|||||||
const { toolOptions } = props
|
const { toolOptions } = props
|
||||||
|
|
||||||
return toolOptions
|
return toolOptions
|
||||||
?.filter(() => Boolean)
|
?.filter(Boolean)
|
||||||
.map((curr) => (typeof curr === 'function' ? curr() : curr))
|
.map((curr) => (typeof curr === 'function' ? curr() : curr))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,6 +255,7 @@ export default defineComponent({
|
|||||||
title,
|
title,
|
||||||
$slots,
|
$slots,
|
||||||
propsPopselectValue,
|
propsPopselectValue,
|
||||||
|
renderWrapperHeader,
|
||||||
} = this
|
} = this
|
||||||
const { class: className } = $attrs
|
const { class: className } = $attrs
|
||||||
const { tool, combineRowProps, contextMenuSelect } = this
|
const { tool, combineRowProps, contextMenuSelect } = this
|
||||||
@ -299,9 +304,11 @@ export default defineComponent({
|
|||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
header: renderNode(title, {
|
header: renderWrapperHeader
|
||||||
|
? renderNode(title, {
|
||||||
defaultElement: <div style="display: none;"></div>,
|
defaultElement: <div style="display: none;"></div>,
|
||||||
}),
|
})
|
||||||
|
: null,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
'header-extra': tool($props as any),
|
'header-extra': tool($props as any),
|
||||||
footer: () => $slots.tableFooter?.(),
|
footer: () => $slots.tableFooter?.(),
|
||||||
|
@ -280,7 +280,7 @@ const useCheckedRowKeys = <
|
|||||||
* 选中指定的 keys。
|
* 选中指定的 keys。
|
||||||
* 当你调用该方法时,会将 keys 与 data 中的 rows 进行比对,将匹配的 rows 添加到已选中的 rows 中。
|
* 当你调用该方法时,会将 keys 与 data 中的 rows 进行比对,将匹配的 rows 添加到已选中的 rows 中。
|
||||||
*
|
*
|
||||||
* 如果 multiple 为 false,那么只会选中一个 key;
|
* 如果 multiple 为 false,那么只会选中一个 key;重复的选择,将会以最后一次绑定的 key 为准。
|
||||||
* 所以,如果你需要选中多个 key,需要将 multiple 设置为 true。
|
* 所以,如果你需要选中多个 key,需要将 multiple 设置为 true。
|
||||||
*/
|
*/
|
||||||
const selectKey = (key: RowKey) => {
|
const selectKey = (key: RowKey) => {
|
||||||
|
@ -61,7 +61,6 @@ const useTable = () => {
|
|||||||
'[useTable]: table instance is not ready yet. if you are using useTable, please make sure you have called register method in onRegister event.',
|
'[useTable]: table instance is not ready yet. if you are using useTable, please make sure you have called register method in onRegister event.',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
console.log(tableRef.value)
|
|
||||||
|
|
||||||
return tableRef.value
|
return tableRef.value
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,18 @@ import type { Recordable } from '@/types'
|
|||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
...dataTableProps,
|
...dataTableProps,
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 是否渲染外层容器 header,默认渲染。
|
||||||
|
* 如果配置为 false,则不会显示外层容器的头部。
|
||||||
|
*
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
renderWrapperHeader: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
|
@ -47,7 +47,14 @@ export interface C extends DataTableBaseColumn {
|
|||||||
children?: C[]
|
children?: C[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RTableInst extends Omit<DataTableInst, 'clearFilter'> {}
|
export interface RTableInst extends Omit<DataTableInst, 'clearFilter'> {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 打印表格。
|
||||||
|
*/
|
||||||
|
print: () => void
|
||||||
|
}
|
||||||
|
|
||||||
export type OverridesTableColumn<T = Recordable> = C | DataTableColumn<T>
|
export type OverridesTableColumn<T = Recordable> = C | DataTableColumn<T>
|
||||||
|
|
||||||
|
@ -33,6 +33,13 @@ export interface UseDeviceOptions extends UseWindowSizeOptions {
|
|||||||
* @default 768
|
* @default 768
|
||||||
*/
|
*/
|
||||||
media?: number
|
media?: number
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 当尺寸更新后的回调函数。
|
||||||
|
*
|
||||||
|
* @default undefined
|
||||||
|
*/
|
||||||
observer?: Callback
|
observer?: Callback
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +79,7 @@ export function useDevice(options?: UseDeviceOptions) {
|
|||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
isTabletOrSmaller: readonly(isTabletOrSmaller),
|
isTabletOrSmaller: readonly(isTabletOrSmaller),
|
||||||
}
|
} as const
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UseDeviceReturnType = ReturnType<typeof useDevice>
|
export type UseDeviceReturnType = ReturnType<typeof useDevice>
|
||||||
|
@ -196,6 +196,9 @@ export const useElementFullscreen = (
|
|||||||
element.removeAttribute(ID_TAG)
|
element.removeAttribute(ID_TAG)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 回滚 z-index 值,避免无限增加
|
||||||
|
currentZIndex--
|
||||||
|
|
||||||
stopWatch()
|
stopWatch()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -55,7 +55,8 @@ $menuTagWrapperWidth: 76px;
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
& .ray-icon {
|
& .ray-icon {
|
||||||
transform: translate(-1px, 0px);
|
width: 11px !important;
|
||||||
|
height: 11px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +71,9 @@ $menuTagWrapperWidth: 76px;
|
|||||||
padding: 1px;
|
padding: 1px;
|
||||||
transition: all 0.3s var(--r-bezier);
|
transition: all 0.3s var(--r-bezier);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -490,6 +490,10 @@ export default defineComponent({
|
|||||||
{...{
|
{...{
|
||||||
id: uuidScrollBar,
|
id: uuidScrollBar,
|
||||||
}}
|
}}
|
||||||
|
themeOverrides={{
|
||||||
|
width: '0px',
|
||||||
|
height: '0px',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<NFlex
|
<NFlex
|
||||||
ref="menuTagSpaceRef"
|
ref="menuTagSpaceRef"
|
||||||
|
@ -162,7 +162,7 @@ export default defineComponent({
|
|||||||
))}
|
))}
|
||||||
{getBreadcrumbSwitch ? <Breadcrumb /> : null}
|
{getBreadcrumbSwitch ? <Breadcrumb /> : null}
|
||||||
</NFlex>
|
</NFlex>
|
||||||
<NFlex justify="end" align="center" size={[0, 0]} wrap={false}>
|
<NFlex justify="end" align="center" size={[4, 0]} wrap={false}>
|
||||||
{isRenderVNode(
|
{isRenderVNode(
|
||||||
<GlobalSearchButton
|
<GlobalSearchButton
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
|
@ -27,5 +27,6 @@
|
|||||||
"SvgIcon": "SVG Icon",
|
"SvgIcon": "SVG Icon",
|
||||||
"Table": "Table",
|
"Table": "Table",
|
||||||
"TemplateHooks": "Template Api",
|
"TemplateHooks": "Template Api",
|
||||||
"scrollReveal": "Scroll Reveal"
|
"scrollReveal": "Scroll Reveal",
|
||||||
|
"TablePro": "Table Pro"
|
||||||
}
|
}
|
||||||
|
@ -27,5 +27,6 @@
|
|||||||
"SvgIcon": "SVG 图标",
|
"SvgIcon": "SVG 图标",
|
||||||
"Table": "表格",
|
"Table": "表格",
|
||||||
"TemplateHooks": "模板内置 Api",
|
"TemplateHooks": "模板内置 Api",
|
||||||
"scrollReveal": "滚动动画"
|
"scrollReveal": "滚动动画",
|
||||||
|
"TablePro": "高级表格"
|
||||||
}
|
}
|
||||||
|
19
src/router/modules/demo/table-pro.ts
Normal file
19
src/router/modules/demo/table-pro.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { t } from '@/hooks/web/useI18n'
|
||||||
|
import { LAYOUT } from '@/router/constant'
|
||||||
|
|
||||||
|
import type { AppRouteRecordRaw } from '@/router/types'
|
||||||
|
|
||||||
|
const r: AppRouteRecordRaw = {
|
||||||
|
path: '/table-pro',
|
||||||
|
component: () => import('@/views/demo/TablePro'),
|
||||||
|
meta: {
|
||||||
|
i18nKey: t('menu.TablePro'),
|
||||||
|
icon: 'other',
|
||||||
|
order: 2,
|
||||||
|
extra: {
|
||||||
|
label: 'TablePro',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default r
|
470
src/views/demo/TablePro.tsx
Normal file
470
src/views/demo/TablePro.tsx
Normal file
@ -0,0 +1,470 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Ray <https://github.com/XiaoDaiGua-Ray>
|
||||||
|
*
|
||||||
|
* @date 2024-08-23
|
||||||
|
*
|
||||||
|
* @workspace ray-template
|
||||||
|
*
|
||||||
|
* @remark 今天也是元气满满撸代码的一天
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { RTablePro, RCollapse } from '@/components-pro'
|
||||||
|
import {
|
||||||
|
NFlex,
|
||||||
|
NTag,
|
||||||
|
NButton,
|
||||||
|
NFormItemGi,
|
||||||
|
NInput,
|
||||||
|
NCard,
|
||||||
|
NRadioGroup,
|
||||||
|
NRadioButton,
|
||||||
|
NFormItem,
|
||||||
|
NSelect,
|
||||||
|
NDatePicker,
|
||||||
|
} from 'naive-ui'
|
||||||
|
|
||||||
|
import { uuid } from '@/utils'
|
||||||
|
import { useHookPlusRequest } from '@/axios'
|
||||||
|
import Mock from 'mockjs'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
import { useTablePro } from '@/components-pro'
|
||||||
|
import { useCheckedRowKeys } from '@/components'
|
||||||
|
import { useDayjs } from '@/hooks'
|
||||||
|
|
||||||
|
import type { DataTableColumns } from 'naive-ui'
|
||||||
|
|
||||||
|
type RowData = {
|
||||||
|
key: number | string
|
||||||
|
name: string
|
||||||
|
age: number
|
||||||
|
address: string
|
||||||
|
tags: string[]
|
||||||
|
remark: string
|
||||||
|
status: string
|
||||||
|
statusText: string
|
||||||
|
signTimeEnd: number
|
||||||
|
signTimeStart: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ParamsRef
|
||||||
|
extends Partial<
|
||||||
|
Pick<RowData, 'name' | 'status' | 'signTimeStart' | 'signTimeEnd'>
|
||||||
|
> {
|
||||||
|
page?: number
|
||||||
|
pageSize?: number
|
||||||
|
RangeTime?: [number, number] | null
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BasicResponse<T = unknown> {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 返回数据。
|
||||||
|
*/
|
||||||
|
data: T
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 返回描述信息。
|
||||||
|
*/
|
||||||
|
message: string
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 返回状态码。
|
||||||
|
*/
|
||||||
|
code: number
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 额外的错误描述信息。
|
||||||
|
*/
|
||||||
|
exceptionMessage: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PaginationResponse<T = unknown> extends BasicResponse<T> {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 分页总条数。
|
||||||
|
*/
|
||||||
|
total: number
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 分页页数。
|
||||||
|
*/
|
||||||
|
pageSize: number
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 当前页数。
|
||||||
|
*/
|
||||||
|
page: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'TableProDemo',
|
||||||
|
setup() {
|
||||||
|
const { format } = useDayjs()
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* register: 注册表格实例
|
||||||
|
* runTableRequest: 获取 TablePro 内部管理的请求方法,会自动合并 page, pageSize 等参数,如果有。
|
||||||
|
* getUpdateInfo: 如果需要自定义请求情况,可以使用该方法获取最新的 page, pageSize 等参数。
|
||||||
|
*/
|
||||||
|
const [
|
||||||
|
tableProRegister,
|
||||||
|
{ runTableRequest, getCurrentTableRequestParams, print, downloadCsv },
|
||||||
|
] = useTablePro()
|
||||||
|
// 表格数据
|
||||||
|
const tableDataRef = ref<RowData[]>([])
|
||||||
|
// 表格列
|
||||||
|
const baseColumns: DataTableColumns<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 itemCountRef = ref(0)
|
||||||
|
// 查询条件
|
||||||
|
const conditionRef = ref<ParamsRef>({})
|
||||||
|
// 缓存模拟数据,不用关心
|
||||||
|
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 radioRef = ref({
|
||||||
|
pagination: true,
|
||||||
|
manual: false,
|
||||||
|
})
|
||||||
|
const [
|
||||||
|
checkedRowKeys,
|
||||||
|
{ checkedRowKeysBind, getKeys, getRows, clearKey, clearAll, selectKey },
|
||||||
|
] = useCheckedRowKeys(tableDataRef, baseColumns, {
|
||||||
|
rowKey: 'key',
|
||||||
|
onChange: (keys, rows, meta) => {},
|
||||||
|
})
|
||||||
|
|
||||||
|
const isNullOrUndefined = (value: unknown) => {
|
||||||
|
return value === null || value === void 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模拟请求
|
||||||
|
const getPersonList = (
|
||||||
|
params: ParamsRef,
|
||||||
|
): Promise<PaginationResponse<RowData[]>> => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const {
|
||||||
|
page = 1,
|
||||||
|
pageSize = 10,
|
||||||
|
name,
|
||||||
|
status,
|
||||||
|
signTimeStart,
|
||||||
|
signTimeEnd,
|
||||||
|
} = params || {}
|
||||||
|
let list: RowData[] = mockPersonList.value
|
||||||
|
const defaultLength = mockPersonList.value.length
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
list = list.filter((curr) => curr.name.includes(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
list = list.filter((curr) => curr.status === status)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signTimeStart && signTimeEnd) {
|
||||||
|
list = list.filter((curr) => {
|
||||||
|
return (
|
||||||
|
curr.signTimeStart >= signTimeStart &&
|
||||||
|
curr.signTimeEnd <= signTimeEnd
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
list = list.slice((page - 1) * pageSize, page * pageSize)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve({
|
||||||
|
code: 0,
|
||||||
|
data: list,
|
||||||
|
total:
|
||||||
|
isNullOrUndefined(status) &&
|
||||||
|
isNullOrUndefined(name) &&
|
||||||
|
(isNullOrUndefined(signTimeStart) ||
|
||||||
|
isNullOrUndefined(signTimeEnd))
|
||||||
|
? defaultLength
|
||||||
|
: list.length,
|
||||||
|
message: 'success',
|
||||||
|
page,
|
||||||
|
pageSize,
|
||||||
|
} as PaginationResponse<RowData[]>)
|
||||||
|
}, 1000)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const { run: runGetPersonList, loading: loadingGetPersonList } =
|
||||||
|
useHookPlusRequest(getPersonList, {
|
||||||
|
onSuccess: (res) => {
|
||||||
|
const { data, total } = res
|
||||||
|
|
||||||
|
tableDataRef.value = data
|
||||||
|
itemCountRef.value = total
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
tableDataRef,
|
||||||
|
baseColumns,
|
||||||
|
itemCountRef,
|
||||||
|
loadingGetPersonList,
|
||||||
|
runGetPersonList,
|
||||||
|
conditionRef,
|
||||||
|
radioRef,
|
||||||
|
runTableRequest,
|
||||||
|
tableProRegister,
|
||||||
|
print,
|
||||||
|
downloadCsv,
|
||||||
|
checkedRowKeysBind,
|
||||||
|
checkedRowKeys,
|
||||||
|
getKeys,
|
||||||
|
getRows,
|
||||||
|
clearKey,
|
||||||
|
clearAll,
|
||||||
|
selectKey,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
tableDataRef,
|
||||||
|
baseColumns,
|
||||||
|
itemCountRef,
|
||||||
|
loadingGetPersonList,
|
||||||
|
runGetPersonList,
|
||||||
|
conditionRef,
|
||||||
|
radioRef,
|
||||||
|
runTableRequest,
|
||||||
|
tableProRegister,
|
||||||
|
print,
|
||||||
|
downloadCsv,
|
||||||
|
checkedRowKeysBind,
|
||||||
|
getKeys,
|
||||||
|
getRows,
|
||||||
|
clearKey,
|
||||||
|
clearAll,
|
||||||
|
selectKey,
|
||||||
|
} = this
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NFlex vertical>
|
||||||
|
<RCollapse>
|
||||||
|
{{
|
||||||
|
default: () => (
|
||||||
|
<>
|
||||||
|
<NFormItemGi label="用户名">
|
||||||
|
<NInput v-model:value={conditionRef.name} clearable />
|
||||||
|
</NFormItemGi>
|
||||||
|
<NFormItemGi label="状态">
|
||||||
|
<NSelect
|
||||||
|
v-model:value={conditionRef.status}
|
||||||
|
clearable
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: '成功',
|
||||||
|
value: 'success',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '失败',
|
||||||
|
value: 'error',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</NFormItemGi>
|
||||||
|
<NFormItemGi label="登陆时间">
|
||||||
|
<NDatePicker
|
||||||
|
type="datetimerange"
|
||||||
|
v-model:value={conditionRef.RangeTime}
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</NFormItemGi>
|
||||||
|
<NFormItemGi label="演示折叠的条件框">
|
||||||
|
<NInput readonly placeholder="我只是为了占位" />
|
||||||
|
</NFormItemGi>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
action: () => (
|
||||||
|
<NFlex>
|
||||||
|
<NButton
|
||||||
|
type="primary"
|
||||||
|
onClick={() => runTableRequest()}
|
||||||
|
loading={loadingGetPersonList}
|
||||||
|
>
|
||||||
|
查询
|
||||||
|
</NButton>
|
||||||
|
</NFlex>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
</RCollapse>
|
||||||
|
<NCard title="常用高级拓展功能">
|
||||||
|
<NFlex>
|
||||||
|
<NFormItem label="分页">
|
||||||
|
<NRadioGroup v-model:value={radioRef.pagination}>
|
||||||
|
<NRadioButton value={true}>显示分页</NRadioButton>
|
||||||
|
<NRadioButton value={false}>隐藏分页</NRadioButton>
|
||||||
|
</NRadioGroup>
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="自动更新">
|
||||||
|
<NRadioGroup v-model:value={radioRef.manual}>
|
||||||
|
<NRadioButton value={false}>自动更新</NRadioButton>
|
||||||
|
<NRadioButton value={true}>取消自动</NRadioButton>
|
||||||
|
</NRadioGroup>
|
||||||
|
</NFormItem>
|
||||||
|
</NFlex>
|
||||||
|
</NCard>
|
||||||
|
<NCard title="useTablePro 部分方法">
|
||||||
|
<NFlex>
|
||||||
|
<NButton type="primary" onClick={print}>
|
||||||
|
打印
|
||||||
|
</NButton>
|
||||||
|
<NButton type="primary" onClick={() => downloadCsv()}>
|
||||||
|
下载 csv
|
||||||
|
</NButton>
|
||||||
|
</NFlex>
|
||||||
|
</NCard>
|
||||||
|
<NCard title="useCheckedRowKeys 部分方法">
|
||||||
|
<NFlex>
|
||||||
|
<NButton
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
const key = tableDataRef[1].key
|
||||||
|
|
||||||
|
selectKey(key)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
选中第二行
|
||||||
|
</NButton>
|
||||||
|
<NButton
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
const key = tableDataRef[1].key
|
||||||
|
|
||||||
|
clearKey(key)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
取消选中第二行
|
||||||
|
</NButton>
|
||||||
|
<NButton
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
tableDataRef?.forEach((curr) => selectKey(curr.key))
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
选中当前页面所有行
|
||||||
|
</NButton>
|
||||||
|
<NButton
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
clearAll()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
取消所有已选中行
|
||||||
|
</NButton>
|
||||||
|
</NFlex>
|
||||||
|
</NCard>
|
||||||
|
<RTablePro
|
||||||
|
onRegister={tableProRegister}
|
||||||
|
data={tableDataRef}
|
||||||
|
columns={baseColumns}
|
||||||
|
loading={loadingGetPersonList}
|
||||||
|
// 如果需要设置分页功能,则该参数必传
|
||||||
|
paginationCount={itemCountRef}
|
||||||
|
request={runGetPersonList}
|
||||||
|
requestConfig={{
|
||||||
|
params: conditionRef,
|
||||||
|
// 这是后台的统计字段,根据实际情况配置
|
||||||
|
formatRangeTime: [
|
||||||
|
{
|
||||||
|
key: 'RangeTime',
|
||||||
|
target: ['signTimeStart', 'signTimeEnd'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
showPagination={radioRef.pagination}
|
||||||
|
manual={radioRef.manual}
|
||||||
|
rowKey={(row) => row.key}
|
||||||
|
v-model:checkedRowKeys={this.checkedRowKeys}
|
||||||
|
onUpdateCheckedRowKeys={checkedRowKeysBind}
|
||||||
|
/>
|
||||||
|
</NFlex>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
Loading…
x
Reference in New Issue
Block a user