mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-02 03:48:13 +08:00
feat: table view 组件 (#2139)
* 更新 snapshot * feat: datetime 组件时间支持可点选 (#2100) * 文档和一些小修改 (#2107) * jssdk 支持 hash路由改造 * 更新文档 * default value 和 value 逻辑优化 * 优化 value 的处理逻辑 * 同步值应该固定某一种模式 * name 干脆支持 filter 好了 * 更新的时候获取数据不一致 * 修复 qrcode 获取值方式 * columns 有可能不是数组 * feat: 增加 table-view 初步 * 修复 ECharts 编辑器的问题 * 方便编辑器编辑 Co-authored-by: 2betop <2betop.cn@gmail.com> Co-authored-by: Allen <yupeng.cqupt@qq.com> Co-authored-by: RickCole <rickcole21@outlook.com>
This commit is contained in:
parent
8364a8e142
commit
56e9602869
143
docs/zh-CN/components/table-view.md
Normal file
143
docs/zh-CN/components/table-view.md
Normal file
@ -0,0 +1,143 @@
|
||||
---
|
||||
title: Table View 表格展现
|
||||
description:
|
||||
type: 0
|
||||
group: ⚙ 组件
|
||||
menuName: Table View 表格展现
|
||||
icon:
|
||||
order: 68
|
||||
---
|
||||
|
||||
> 1.2.0 及以上版本才有此功能
|
||||
|
||||
通过表格的方式来展现数据,和 [table](./table) 的不同之处:
|
||||
|
||||
- 数据源要求不同
|
||||
- table 的数据源需要是多行的数据,最典型的就是来自某个数据库的表
|
||||
- table view 的数据源可以来自各种固定的数据,比如单元格的某一列是来自某个变量
|
||||
- 功能不同
|
||||
- table 只能用来做数据表的展现
|
||||
- table view 除了展现复杂的报表,还能用来进行布局
|
||||
- 合并单元格方式不同
|
||||
- table 的合并单元格需要依赖数据
|
||||
- table view 的合并单元格是手动指定的,因此可以支持不规则的数据格式
|
||||
|
||||
## 基本用法
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "service",
|
||||
"data": {
|
||||
"beijing": "20",
|
||||
"tianjing": "19"
|
||||
},
|
||||
"body": [
|
||||
{
|
||||
"type": "table-view",
|
||||
"trs": [
|
||||
{
|
||||
"background": "#F7F7F7",
|
||||
"tds": [
|
||||
{
|
||||
"body": {
|
||||
"type": "tpl",
|
||||
"tpl": "地区"
|
||||
}
|
||||
},
|
||||
{
|
||||
"body": {
|
||||
"type": "tpl",
|
||||
"tpl": "城市"
|
||||
}
|
||||
},
|
||||
{
|
||||
"body": {
|
||||
"type": "tpl",
|
||||
"tpl": "销量"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tds": [
|
||||
{
|
||||
"rowspan": 2,
|
||||
"body": {
|
||||
"type": "tpl",
|
||||
"tpl": " 华北"
|
||||
}
|
||||
},
|
||||
{
|
||||
"body": {
|
||||
"type": "tpl",
|
||||
"tpl": "北京"
|
||||
}
|
||||
},
|
||||
{
|
||||
"body": {
|
||||
"type": "tpl",
|
||||
"tpl": "${beijing}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tds": [
|
||||
{
|
||||
"body": {
|
||||
"type": "tpl",
|
||||
"tpl": "天津"
|
||||
}
|
||||
},
|
||||
{
|
||||
"body": {
|
||||
"type": "tpl",
|
||||
"tpl": "${tianjing}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
可以看到 table view 需要手动进行单元格合并,因此更适合使用可视化编辑器进行编辑。
|
||||
|
||||
## 设置项
|
||||
|
||||
table view 的设置项有三层,可以分别对表格级别、行级别、单元格级别进行设置。
|
||||
|
||||
### 表格设置项
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
| ----------- | --------------- | ----------------------------------------------------- | ---------------- |
|
||||
| width | `number/string` | '100%' | |
|
||||
| padding | `number/string` | 'var(--TableCell-paddingY) var(--TableCell-paddingX)' | 单元格默认内间距 |
|
||||
| border | `boolean` | true | 是否显示边框 |
|
||||
| borderColor | `string` | `var(--borderColor)` | 边框颜色 |
|
||||
| trs | | | 参考下面的行设置 |
|
||||
|
||||
### 行设置
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
| ---------- | --------------- | ------ | -------------------- |
|
||||
| height | `number/string` | | |
|
||||
| background | `string` | | 行背景色 |
|
||||
| tds | | | 参考下面的单元格设置 |
|
||||
|
||||
### 单元格设置
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
| ---------- | ----------------------------------------- | -------------- | ---------------------------------------------------------------- |
|
||||
| background | `string` | | 单元格背景色 |
|
||||
| color | `string` | | 单元格文字颜色 |
|
||||
| bold | `boolean` | false | 单元格文字是否加粗 |
|
||||
| width | `number/string` | | 单元格宽度,只需要设置第一行 |
|
||||
| padding | `number/string` | 集成表格的设置 | 单元格内间距 |
|
||||
| align | `string` | `left` | 单元格内的水平对齐,可以是 `left`、`center`、`right` |
|
||||
| valign | `string` | `middle` | 单元格内的垂直对齐,可以是 `top`、`middle`、`bottom`、`baseline` |
|
||||
| colspan | `number` | | 单元格水平跨几行 |
|
||||
| rowspan | `number` | | 单元格垂直跨几列 |
|
||||
| body | [SchemaNode](../../docs/types/schemanode) | | 其它 amis 设置 |
|
@ -564,9 +564,9 @@ export const components = [
|
||||
path: '/zh-CN/components/form/input-quarter-range',
|
||||
getComponent: () =>
|
||||
// @ts-ignore
|
||||
import('../../docs/zh-CN/components/form/input-quarter-range.md').then(
|
||||
makeMarkdownRenderer
|
||||
)
|
||||
import(
|
||||
'../../docs/zh-CN/components/form/input-quarter-range.md'
|
||||
).then(makeMarkdownRenderer)
|
||||
},
|
||||
{
|
||||
label: 'Radios 单选框',
|
||||
@ -764,6 +764,15 @@ export const components = [
|
||||
makeMarkdownRenderer
|
||||
)
|
||||
},
|
||||
{
|
||||
label: 'Table View 表格视图',
|
||||
path: '/zh-CN/components/table-view',
|
||||
getComponent: () =>
|
||||
// @ts-ignore
|
||||
import('../../docs/zh-CN/components/table-view.md').then(
|
||||
makeMarkdownRenderer
|
||||
)
|
||||
},
|
||||
{
|
||||
label: 'Card 卡片',
|
||||
path: '/zh-CN/components/card',
|
||||
|
@ -26,7 +26,7 @@ const LazyComponent = lazyData(
|
||||
([title, legend, Global, Axis, polar, tooltip, toolbox, series]) => {
|
||||
return ({renderFormItems}: any) => {
|
||||
return renderFormItems({
|
||||
controls: [
|
||||
body: [
|
||||
createHierarchy('config', [
|
||||
{
|
||||
type: 'tabs',
|
||||
@ -37,39 +37,39 @@ const LazyComponent = lazyData(
|
||||
tabs: [
|
||||
{
|
||||
title: '图表',
|
||||
controls: [series]
|
||||
body: [series]
|
||||
},
|
||||
{
|
||||
title: '标题',
|
||||
controls: [title]
|
||||
body: [title]
|
||||
},
|
||||
{
|
||||
title: '图例',
|
||||
controls: [legend]
|
||||
body: [legend]
|
||||
},
|
||||
{
|
||||
title: 'X 轴',
|
||||
controls: Axis('x')
|
||||
body: Axis('x')
|
||||
},
|
||||
{
|
||||
title: 'Y 轴',
|
||||
controls: Axis('y')
|
||||
body: Axis('y')
|
||||
},
|
||||
{
|
||||
title: '极标',
|
||||
controls: [polar]
|
||||
body: [polar]
|
||||
},
|
||||
{
|
||||
title: '提示框',
|
||||
controls: [tooltip]
|
||||
body: [tooltip]
|
||||
},
|
||||
{
|
||||
title: '工具栏',
|
||||
controls: [toolbox]
|
||||
body: [toolbox]
|
||||
},
|
||||
{
|
||||
title: '全局',
|
||||
controls: [Global]
|
||||
body: [Global]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ export const createHierarchy = (name: string, controls: any[]) => {
|
||||
label: '',
|
||||
noBorder: true,
|
||||
multiLine: true,
|
||||
controls: controls
|
||||
items: controls
|
||||
};
|
||||
};
|
||||
|
||||
@ -159,7 +159,7 @@ export const fieldSet = (
|
||||
collapsable: true,
|
||||
collapsed: collapsed,
|
||||
mountOnEnter: true,
|
||||
controls: controls
|
||||
body: controls
|
||||
};
|
||||
};
|
||||
|
||||
@ -172,7 +172,7 @@ export const visibleOn = (visibleOn: string, controls: any[]) => {
|
||||
return {
|
||||
type: 'container',
|
||||
visibleOn: visibleOn,
|
||||
controls: controls
|
||||
body: controls
|
||||
};
|
||||
};
|
||||
|
||||
@ -192,7 +192,7 @@ export const number = (
|
||||
step: number = 1
|
||||
) => {
|
||||
const control: any = {
|
||||
type: 'number',
|
||||
type: 'input-number',
|
||||
name: name,
|
||||
label: label
|
||||
};
|
||||
@ -230,7 +230,7 @@ export const text = (
|
||||
defaultText?: string
|
||||
) => {
|
||||
const control: any = {
|
||||
type: 'text',
|
||||
type: 'input-text',
|
||||
name: name,
|
||||
label: label
|
||||
};
|
||||
@ -321,13 +321,13 @@ export const viewportControl = (
|
||||
visibleOn: `(typeof this.${name} === "undefined") || ((typeof this.${name} === "string") && (this.${name}.indexOf("%") === -1))`
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
type: 'input-number',
|
||||
name: name,
|
||||
label: label,
|
||||
visibleOn: `(typeof this.${name} === "number")`
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
type: 'input-text',
|
||||
name: name,
|
||||
label: label,
|
||||
visibleOn: `(typeof this.${name} === "string") && (this.${name}.indexOf("%") !== -1)`
|
||||
@ -347,7 +347,7 @@ export const viewport = (scope: string, label: string) => {
|
||||
collapsable: true,
|
||||
collapsed: true,
|
||||
mountOnEnter: true,
|
||||
controls: [
|
||||
body: [
|
||||
...viewportControl(
|
||||
`${scope}left`,
|
||||
`${label}离容器左侧的距离`,
|
||||
@ -414,7 +414,7 @@ export const origin = (label: string) => {
|
||||
*/
|
||||
export const formatter = (label: string) => {
|
||||
return {
|
||||
type: 'text',
|
||||
type: 'input-text',
|
||||
name: 'formatter',
|
||||
label: `格式化${label}文本`
|
||||
};
|
||||
@ -560,9 +560,9 @@ export const numberOrArray = (
|
||||
return [
|
||||
{
|
||||
type: 'group',
|
||||
controls: [
|
||||
body: [
|
||||
{
|
||||
type: 'number',
|
||||
type: 'input-number',
|
||||
name: name,
|
||||
hiddenOn: `Array.isArray(this.${name})`,
|
||||
label: label
|
||||
@ -582,7 +582,7 @@ export const numberOrArray = (
|
||||
},
|
||||
|
||||
{
|
||||
type: 'array',
|
||||
type: 'input-array',
|
||||
name: name,
|
||||
label: label,
|
||||
labelRemark:
|
||||
@ -591,7 +591,7 @@ export const numberOrArray = (
|
||||
minLength: 2,
|
||||
maxLength: 4,
|
||||
items: {
|
||||
type: 'number'
|
||||
type: 'input-number'
|
||||
}
|
||||
}
|
||||
];
|
||||
@ -616,21 +616,21 @@ export const vector = (
|
||||
) => {
|
||||
return [
|
||||
{
|
||||
type: 'array',
|
||||
type: 'input-array',
|
||||
name: name,
|
||||
label: label,
|
||||
visibleOn: `Array.isArray(this.${name})`,
|
||||
minLength: 2,
|
||||
maxLength: 4,
|
||||
items: {
|
||||
type: 'number'
|
||||
type: 'input-number'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'group',
|
||||
controls: [
|
||||
body: [
|
||||
{
|
||||
type: 'number',
|
||||
type: 'input-number',
|
||||
name: name,
|
||||
hiddenOn: `Array.isArray(this.${name})`,
|
||||
label: label
|
||||
@ -667,7 +667,7 @@ export const shadowControls = (scope: string) => {
|
||||
collapsable: true,
|
||||
collapsed: true,
|
||||
mountOnEnter: true,
|
||||
controls: [
|
||||
body: [
|
||||
color(`${scope}shadowColor`, '阴影颜色'),
|
||||
number(`${scope}shadowBlur`, '阴影模糊大小'),
|
||||
number(`${scope}shadowOffsetX`, '阴影水平方向上的偏移距离'),
|
||||
@ -692,7 +692,7 @@ export const keywordOrNumber = (
|
||||
) => {
|
||||
return {
|
||||
type: 'group',
|
||||
controls: [
|
||||
body: [
|
||||
{
|
||||
type: 'switch',
|
||||
label: labelForSwitch,
|
||||
@ -712,7 +712,7 @@ export const keywordOrNumber = (
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
type: 'input-number',
|
||||
name: name,
|
||||
visibleOn: `typeof(this.${name}) === 'number'`,
|
||||
label: label
|
||||
@ -746,7 +746,7 @@ export const keywordOrString = (
|
||||
) => {
|
||||
return {
|
||||
type: 'group',
|
||||
controls: [
|
||||
body: [
|
||||
{
|
||||
type: 'switch',
|
||||
label: labelForSwitch,
|
||||
@ -767,7 +767,7 @@ export const keywordOrString = (
|
||||
labelRemark: remark
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
type: 'input-text',
|
||||
name: name,
|
||||
visibleOn: `this.${name} && ${JSON.stringify(
|
||||
keywordList
|
||||
@ -835,7 +835,7 @@ export const objectOrArray = (
|
||||
multiLine: true,
|
||||
visibleOn: `typeof(this.${name}) === 'undefined' || !Array.isArray(this.${name})`,
|
||||
multiple: false,
|
||||
controls: controls
|
||||
items: controls
|
||||
},
|
||||
{
|
||||
type: 'combo',
|
||||
@ -845,7 +845,7 @@ export const objectOrArray = (
|
||||
multiLine: true,
|
||||
visibleOn: `Array.isArray(this.${name})`,
|
||||
multiple: true,
|
||||
controls: controls
|
||||
items: controls
|
||||
}
|
||||
];
|
||||
};
|
||||
@ -973,7 +973,7 @@ export const numberOrPercentage = (
|
||||
return [
|
||||
{
|
||||
type: 'group',
|
||||
controls: [
|
||||
body: [
|
||||
{
|
||||
type: 'switch',
|
||||
label: labelForSwitch,
|
||||
@ -999,13 +999,13 @@ export const numberOrPercentage = (
|
||||
: undefined
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
type: 'input-number',
|
||||
name: name,
|
||||
visibleOn: `typeof(this.${name}) === 'number'`,
|
||||
label: label
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
type: 'input-text',
|
||||
name: name,
|
||||
label: label,
|
||||
visibleOn: `typeof(this.${name}) === 'undefined' || typeof(this.${name}) === 'string'`
|
||||
@ -1025,7 +1025,7 @@ export const textStyleControls = (scope: string, label: string) => {
|
||||
type: 'fieldSet',
|
||||
title: label,
|
||||
collapsable: true,
|
||||
controls: [
|
||||
body: [
|
||||
color('color', `${label}文字的颜色`),
|
||||
select('fontStyle', `${label}文字字体的风格`, [
|
||||
'normal',
|
||||
@ -1039,7 +1039,7 @@ export const textStyleControls = (scope: string, label: string) => {
|
||||
['normal', 'bold', 'bolder', 'lighter']
|
||||
),
|
||||
{
|
||||
type: 'text',
|
||||
type: 'input-text',
|
||||
name: 'fontFamily',
|
||||
label: `${label}文字的字体`,
|
||||
options: [
|
||||
|
@ -12,9 +12,9 @@ export default {
|
||||
tabs: [
|
||||
{
|
||||
title: '主题',
|
||||
controls: [
|
||||
body: [
|
||||
{
|
||||
type: 'array',
|
||||
type: 'input-array',
|
||||
name: 'color',
|
||||
label: '调色盘颜色列表',
|
||||
labelRemark:
|
||||
@ -41,15 +41,15 @@ export default {
|
||||
},
|
||||
{
|
||||
title: '动画',
|
||||
controls: [animation(null, false)]
|
||||
body: [animation(null, false)]
|
||||
},
|
||||
{
|
||||
title: '文字样式',
|
||||
controls: [textStyleControls('textStyle', '全局文字')]
|
||||
body: [textStyleControls('textStyle', '全局文字')]
|
||||
},
|
||||
{
|
||||
title: '其它',
|
||||
controls: [
|
||||
body: [
|
||||
text(
|
||||
'blendMode',
|
||||
'图形的混合模式',
|
||||
|
@ -18,19 +18,19 @@ export default {
|
||||
{
|
||||
title: '基础',
|
||||
className: 'echarts-tab',
|
||||
controls: [createHierarchy('legend', buildOptions('', legendOptions))]
|
||||
body: [createHierarchy('legend', buildOptions('', legendOptions))]
|
||||
},
|
||||
{
|
||||
title: '位置',
|
||||
controls: [createHierarchy('legend', [viewport('', '图例')])]
|
||||
body: [createHierarchy('legend', [viewport('', '图例')])]
|
||||
},
|
||||
{
|
||||
title: '样式',
|
||||
controls: [createHierarchy('legend', commonStyle('', '图例'))]
|
||||
body: [createHierarchy('legend', commonStyle('', '图例'))]
|
||||
},
|
||||
{
|
||||
title: '文字样式',
|
||||
controls: [
|
||||
body: [
|
||||
createHierarchy('legend', [
|
||||
textStyleControls('textStyle', '图例'),
|
||||
textStyleControls('pageTextStyle', '图例页信息')
|
||||
@ -39,7 +39,7 @@ export default {
|
||||
},
|
||||
{
|
||||
title: '数据',
|
||||
controls: [createHierarchy('legend', [])]
|
||||
body: [createHierarchy('legend', [])]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -22,15 +22,15 @@ export default {
|
||||
tabs: [
|
||||
{
|
||||
title: '坐标系',
|
||||
controls: buildOptions('polar.', polarOptions)
|
||||
body: buildOptions('polar.', polarOptions)
|
||||
},
|
||||
{
|
||||
title: '径向轴',
|
||||
controls: buildOptions('radiusAxis.', radiusAxisOptions)
|
||||
body: buildOptions('radiusAxis.', radiusAxisOptions)
|
||||
},
|
||||
{
|
||||
title: '角度轴',
|
||||
controls: buildOptions('angleAxis.', angleAxisOptions)
|
||||
body: buildOptions('angleAxis.', angleAxisOptions)
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -21,7 +21,7 @@ const buildSerieOptions = (type: string, options: any) => {
|
||||
return {
|
||||
type: 'container',
|
||||
visibleOn: `this.type == "${type}"`,
|
||||
controls: buildOptions('', options)
|
||||
body: buildOptions('', options)
|
||||
};
|
||||
};
|
||||
|
||||
@ -35,7 +35,7 @@ export default {
|
||||
multiLine: true,
|
||||
multiple: true,
|
||||
addButtonText: '新增系列',
|
||||
controls: [
|
||||
items: [
|
||||
select('type', '图表类型', [
|
||||
'line',
|
||||
'bar',
|
||||
@ -45,11 +45,11 @@ export default {
|
||||
'gauge'
|
||||
]),
|
||||
{
|
||||
type: 'array',
|
||||
type: 'input-array',
|
||||
name: 'data', //TODO: 目前只支持一维
|
||||
label: '数据',
|
||||
items: {
|
||||
type: 'number'
|
||||
type: 'input-number'
|
||||
}
|
||||
},
|
||||
buildSerieOptions('line', lineOptions),
|
||||
|
@ -19,19 +19,19 @@ export default {
|
||||
{
|
||||
title: '内容',
|
||||
className: 'echarts-tab',
|
||||
controls: [createHierarchy('title', buildOptions('', titleOptions))]
|
||||
body: [createHierarchy('title', buildOptions('', titleOptions))]
|
||||
},
|
||||
{
|
||||
title: '位置',
|
||||
controls: [createHierarchy('legend', [viewport('', '标题')])]
|
||||
body: [createHierarchy('legend', [viewport('', '标题')])]
|
||||
},
|
||||
{
|
||||
title: '样式',
|
||||
controls: [createHierarchy('title', commonStyle('', '标题'))]
|
||||
body: [createHierarchy('title', commonStyle('', '标题'))]
|
||||
},
|
||||
{
|
||||
title: '文字样式',
|
||||
controls: [
|
||||
body: [
|
||||
createHierarchy('title', [
|
||||
textStyleControls('textStyle', '主标题'),
|
||||
textStyleControls('subtextStyle', '副标题')
|
||||
|
@ -14,11 +14,11 @@ export default {
|
||||
tabs: [
|
||||
{
|
||||
title: '基础',
|
||||
controls: buildOptions('toolbox.', toolboxOptions)
|
||||
body: buildOptions('toolbox.', toolboxOptions)
|
||||
},
|
||||
{
|
||||
title: '位置',
|
||||
controls: [viewport('toolbox.', '标题')]
|
||||
body: [viewport('toolbox.', '标题')]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -23,7 +23,7 @@ export default {
|
||||
tabs: [
|
||||
{
|
||||
title: '基础',
|
||||
controls: buildOptions('tooltip.', tooltipOptions)
|
||||
body: buildOptions('tooltip.', tooltipOptions)
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -307,6 +307,7 @@ export type SchemaType =
|
||||
| 'transfer'
|
||||
| 'input-tree'
|
||||
| 'tree-select'
|
||||
| 'table-view'
|
||||
|
||||
// 原生 input 类型
|
||||
| 'native-date'
|
||||
|
@ -10,7 +10,7 @@ const isMobile = (window as any).matchMedia?.('(max-width: 768px)').matches
|
||||
: false;
|
||||
|
||||
addSchemaFilter(function (schema: Schema, renderer, props?: any) {
|
||||
if (schema.mobile && isMobile) {
|
||||
if (schema && schema.mobile && isMobile) {
|
||||
return {...schema, ...schema.mobile};
|
||||
}
|
||||
|
||||
|
@ -159,6 +159,7 @@ import './renderers/Carousel';
|
||||
import './renderers/AnchorNav';
|
||||
import './renderers/Steps';
|
||||
import './renderers/Markdown';
|
||||
import './renderers/TableView';
|
||||
|
||||
import Scoped, {ScopedContext} from './Scoped';
|
||||
|
||||
|
217
src/renderers/TableView.tsx
Normal file
217
src/renderers/TableView.tsx
Normal file
@ -0,0 +1,217 @@
|
||||
/**
|
||||
* @file 用于表格类型的展现效果,界面可定制化能力更强
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {Renderer, RendererProps} from '../factory';
|
||||
import {Api, SchemaNode, Schema, Action} from '../types';
|
||||
import {isVisible} from '../utils/helper';
|
||||
import {BaseSchema, SchemaObject} from '../Schema';
|
||||
|
||||
// 为了方便编辑器,目前考虑不区分 th 和 td,但因为可以控制展现,所以能实现一样的效果,同时后续这个组件还承担复杂布局的功能,不适合用 th
|
||||
export type TdObject = {
|
||||
/**
|
||||
* 单元格背景色
|
||||
*/
|
||||
background?: string;
|
||||
|
||||
/**
|
||||
* 单元格文字颜色
|
||||
*/
|
||||
color?: string;
|
||||
|
||||
/**
|
||||
* 单元格文字是否加粗
|
||||
*/
|
||||
bold?: boolean;
|
||||
|
||||
/**
|
||||
* 单元格的内边距
|
||||
*/
|
||||
padding?: number;
|
||||
|
||||
/**
|
||||
* 单元格宽度
|
||||
*/
|
||||
width?: number;
|
||||
|
||||
/**
|
||||
* 单元格内的组件
|
||||
*/
|
||||
body?: SchemaObject;
|
||||
|
||||
/**
|
||||
* 水平对齐
|
||||
*/
|
||||
align?: 'left' | 'center' | 'right' | 'justify';
|
||||
|
||||
/**
|
||||
* 垂直对齐
|
||||
*/
|
||||
valign?: 'top' | 'middle' | 'bottom' | 'baseline';
|
||||
|
||||
/**
|
||||
* 跨几行
|
||||
*/
|
||||
colspan?: number;
|
||||
|
||||
/**
|
||||
* 跨几列
|
||||
*/
|
||||
rowspan?: number;
|
||||
};
|
||||
|
||||
export type TrObject = {
|
||||
/**
|
||||
* 行背景色
|
||||
*/
|
||||
background: string;
|
||||
|
||||
/**
|
||||
* 行高度
|
||||
*/
|
||||
height: number;
|
||||
|
||||
/**
|
||||
* 单元格配置
|
||||
*/
|
||||
tds: TdObject[];
|
||||
};
|
||||
|
||||
/**
|
||||
* 表格展现渲染器
|
||||
* 文档:https://baidu.gitee.io/amis/docs/components/table-view
|
||||
*/
|
||||
export interface TableViewSchema extends BaseSchema {
|
||||
/**
|
||||
* 指定为 table-view 展示类型
|
||||
*/
|
||||
type: 'table-view';
|
||||
|
||||
/**
|
||||
* table 容器宽度,默认是 auto
|
||||
*/
|
||||
width?: number | string;
|
||||
|
||||
/**
|
||||
* 默认单元格内边距
|
||||
*/
|
||||
padding?: number | string;
|
||||
|
||||
/**
|
||||
* 是否显示边框
|
||||
*/
|
||||
border?: boolean;
|
||||
|
||||
/**
|
||||
* 边框颜色
|
||||
*/
|
||||
borderColor?: string;
|
||||
|
||||
/**
|
||||
* 行设置
|
||||
*/
|
||||
trs: TrObject[];
|
||||
}
|
||||
|
||||
export interface TableViewProps
|
||||
extends RendererProps,
|
||||
Omit<TableViewSchema, 'type' | 'className'> {
|
||||
itemRender?: (
|
||||
item: any,
|
||||
key: number,
|
||||
length: number,
|
||||
props: any
|
||||
) => JSX.Element;
|
||||
}
|
||||
|
||||
const defaultPadding = 'var(--TableCell-paddingY) var(--TableCell-paddingX)';
|
||||
|
||||
export default class TableView extends React.Component<TableViewProps, object> {
|
||||
static defaultProps: Partial<TableViewProps> = {
|
||||
padding: defaultPadding,
|
||||
width: '100%',
|
||||
border: true,
|
||||
borderColor: 'var(--borderColor)'
|
||||
};
|
||||
|
||||
constructor(props: TableViewProps) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
renderTd(td: TdObject, colIndex: number, rowIndex: number) {
|
||||
const {border, borderColor, render} = this.props;
|
||||
const key = `td-${colIndex}`;
|
||||
let styleBorder;
|
||||
if (border) {
|
||||
styleBorder = `1px solid ${borderColor}`;
|
||||
}
|
||||
return (
|
||||
<td
|
||||
style={{
|
||||
border: styleBorder,
|
||||
color: td.color,
|
||||
fontWeight: td.bold ? 'bold' : 'normal',
|
||||
background: td.background,
|
||||
padding: td.padding || defaultPadding,
|
||||
width: td.width || 'auto',
|
||||
textAlign: td.align || 'left',
|
||||
verticalAlign: td.valign || 'center'
|
||||
}}
|
||||
align={td.align}
|
||||
valign={td.valign}
|
||||
rowSpan={td.rowspan}
|
||||
colSpan={td.colspan}
|
||||
key={key}
|
||||
>
|
||||
{render('td', td.body || '')}
|
||||
</td>
|
||||
);
|
||||
}
|
||||
|
||||
renderTds(tds: TdObject[], rowIndex: number) {
|
||||
return tds.map((td, colIndex) => this.renderTd(td, colIndex, rowIndex));
|
||||
}
|
||||
|
||||
renderTr(tr: TrObject, rowIndex: number) {
|
||||
const key = `tr-${rowIndex}`;
|
||||
return (
|
||||
<tr style={{height: tr.height, background: tr.background}} key={key}>
|
||||
{this.renderTds(tr.tds, rowIndex)}
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
renderTrs(trs: TrObject[]) {
|
||||
const tr = trs.map((tr, rowIndex) => this.renderTr(tr, rowIndex));
|
||||
return tr;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
width,
|
||||
border,
|
||||
borderColor,
|
||||
trs,
|
||||
classnames: cx,
|
||||
className
|
||||
} = this.props;
|
||||
let styleBorder;
|
||||
if (border) {
|
||||
styleBorder = `1px solid ${borderColor}`;
|
||||
}
|
||||
return (
|
||||
<table
|
||||
className={cx('TableView', className)}
|
||||
style={{width: width, border: styleBorder, borderCollapse: 'collapse'}}
|
||||
>
|
||||
<tbody>{this.renderTrs(trs)}</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Renderer({
|
||||
type: 'table-view'
|
||||
})
|
||||
export class TableViewRenderer extends TableView {}
|
Loading…
Reference in New Issue
Block a user