Merge branch 'baidu:master' into master

This commit is contained in:
龙少 2022-08-10 20:31:02 +08:00 committed by GitHub
commit e389050762
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 628 additions and 165 deletions

View File

@ -534,60 +534,85 @@ Cards 模式支持 [Cards](./cards) 中的所有功能。
## 查询条件表单
大部分表格展示有对数据进行检索的需求CRUD 自身支持通过配置`filter`,实现查询条件过滤表单
大部分表格展示有对数据进行检索的需求CRUD 自身支持通过配置`filter`,实现查询条件过滤表单。`filter` 配置实际上同 [Form](./form/index) 组件,因此支持绝大部分`form`的功能。
`filter` 配置实际上同 [Form](./form/index) 组件,因此支持绝大部分`form`的功能
在条件搜索区的 `Engine` 输入框中输入任意值查询会发现结果中 `ID` 为 1 - 3 的 `Rendering engine` 列因为返回值中没有对应字段值,被错误填入了与 `filter` 中相同 `name` 的字段值,这是因为表格 Cell 通过[数据链](../../docs/concepts/datascope-and-datachain)获取到了上层数据域 `filter` 中相同字段的数据值。这种情况可以在 CRUD `columns` 对应列配置`"canAccessSuperData": false`禁止访问父级数据域(比如: `Platform`列)
```schema: scope="body"
{
"type": "crud",
"name": "crud",
"syncLocation": false,
"api": "/api/mock2/sample",
"filter": {
"api": "/api/mock2/crud/table4",
"filter": {
"debug": true,
"title": "条件搜索",
"body": [
{
"type": "flex",
"justify": "space-between",
"alignItems": "center",
"items": [
"type": "group",
"body": [
{
"type": "input-text",
"name": "keywords",
"label": "关键字",
"clearable": true,
"placeholder": "通过关键字搜索",
"size": "sm"
},
{
"type": "button",
"actionType": "drawer",
"icon": "fa fa-plus",
"label": "创建记录",
"target": "crud",
"closeOnOutside": true,
"drawer": {
"title": "创建记录",
"body": {
"type": "form",
"api": "post:/api/mock2/sample",
"body": [
{
"type": "input-text",
"name": "engine",
"label": "Engine"
},
{
"type": "input-text",
"name": "browser",
"label": "Browser"
}
]
}
}
"type": "input-text",
"name": "engine",
"label": "Engine",
"clearable": true,
"size": "sm"
},
{
"type": "input-text",
"name": "platform",
"label": "Platform",
"clearable": true,
"size": "sm"
}
]
}
],
actions: [
{
"type": "button",
"actionType": "drawer",
"icon": "fa fa-plus",
"label": "创建记录",
"target": "crud",
"closeOnOutside": true,
"drawer": {
"title": "创建记录",
"body": {
"type": "form",
"api": "post:/api/mock2/sample",
"body": [
{
"type": "input-text",
"name": "engine",
"label": "Engine"
},
{
"type": "input-text",
"name": "browser",
"label": "Browser"
}
]
}
}
},
{
"type": "reset",
"label": "重置"
},
{
"type": "submit",
"level": "primary",
"label": "查询"
}
]
},
"columns": [
@ -605,7 +630,8 @@ Cards 模式支持 [Cards](./cards) 中的所有功能。
},
{
"name": "platform",
"label": "Platform(s)"
"label": "Platform(s)",
"canAccessSuperData": false
},
{
"name": "version",

View File

@ -2,5 +2,5 @@
"packages": [
"packages/*"
],
"version": "2.1.1-beta.2"
"version": "2.1.1-beta.3"
}

View File

@ -0,0 +1,431 @@
/** 部分列字段没有没回值的CASE */
module.exports = function (req, res) {
const perPage = 10;
const page = req.query.page || 1;
let items = data.concat();
if (req.query.keywords) {
const keywords = req.query.keywords;
items = items.filter(function (item) {
return ~JSON.stringify(item).indexOf(keywords);
});
}
const validQueryKey = Object.keys(req.query).filter(
item => item !== 'keywords' && req.query[item] != null
);
if (validQueryKey.length > 0) {
items = items.filter(item =>
validQueryKey.every(key => !!~req.query[key].indexOf(item[key] || ''))
);
}
const ret = {
status: 0,
msg: 'ok',
data: {
count: items.length,
rows: items.concat().splice((page - 1) * perPage, perPage)
}
};
res.json(ret);
};
const data = [
{
browser: 'Internet Explorer 4.0',
platform: 'Win 95+',
version: '4',
grade: 'X'
},
{
browser: 'Internet Explorer 5.0',
platform: 'Win 95+',
version: '5',
grade: 'C'
},
{
browser: 'Internet Explorer 5.5',
platform: 'Win 95+',
version: '5.5',
grade: 'A'
},
{
engine: 'Trident',
browser: 'Internet Explorer 6',
version: '6',
grade: 'A'
},
{
engine: 'Trident',
browser: 'Internet Explorer 7',
version: '7',
grade: 'A'
},
{
engine: 'Trident',
browser: 'AOL browser (AOL desktop)',
platform: 'Win XP',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Firefox 1.0',
platform: 'Win 98+ / OSX.2+',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Firefox 1.5',
platform: 'Win 98+ / OSX.2+',
version: '1.8'
},
{
engine: 'Gecko',
browser: 'Firefox 2.0',
platform: 'Win 98+ / OSX.2+',
version: '1.8'
},
{
engine: 'Gecko',
browser: 'Firefox 3.0',
platform: 'Win 2k+ / OSX.3+',
version: '1.9',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Camino 1.0',
platform: 'OSX.2+',
version: '1.8',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Camino 1.5',
platform: 'OSX.3+',
version: '1.8',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Netscape 7.2',
platform: 'Win 95+ / Mac OS 8.6-9.2',
version: '1.7',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Netscape Browser 8',
platform: 'Win 98SE+',
version: '1.7',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Netscape Navigator 9',
platform: 'Win 98+ / OSX.2+',
version: '1.8',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Mozilla 1.0',
platform: 'Win 95+ / OSX.1+',
version: '1',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Mozilla 1.1',
platform: 'Win 95+ / OSX.1+',
version: '1.1',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Mozilla 1.2',
platform: 'Win 95+ / OSX.1+',
version: '1.2',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Mozilla 1.3',
platform: 'Win 95+ / OSX.1+',
version: '1.3',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Mozilla 1.4',
platform: 'Win 95+ / OSX.1+',
version: '1.4',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Mozilla 1.5',
platform: 'Win 95+ / OSX.1+',
version: '1.5',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Mozilla 1.6',
platform: 'Win 95+ / OSX.1+',
version: '1.6',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Mozilla 1.7',
platform: 'Win 98+ / OSX.1+',
version: '1.7',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Mozilla 1.8',
platform: 'Win 98+ / OSX.1+',
version: '1.8',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Seamonkey 1.1',
platform: 'Win 98+ / OSX.2+',
version: '1.8',
grade: 'A'
},
{
engine: 'Gecko',
browser: 'Epiphany 2.20',
platform: 'Gnome',
version: '1.8',
grade: 'A'
},
{
engine: 'Webkit',
browser: 'Safari 1.2',
platform: 'OSX.3',
version: '125.5',
grade: 'A'
},
{
engine: 'Webkit',
browser: 'Safari 1.3',
platform: 'OSX.3',
version: '312.8',
grade: 'A'
},
{
engine: 'Webkit',
browser: 'Safari 2.0',
platform: 'OSX.4+',
version: '419.3',
grade: 'A'
},
{
engine: 'Webkit',
browser: 'Safari 3.0',
platform: 'OSX.4+',
version: '522.1',
grade: 'A'
},
{
engine: 'Webkit',
browser: 'OmniWeb 5.5',
platform: 'OSX.4+',
version: '420',
grade: 'A'
},
{
engine: 'Webkit',
browser: 'iPod Touch / iPhone',
platform: 'iPod',
version: '420.1',
grade: 'A'
},
{
engine: 'Webkit',
browser: 'S60',
platform: 'S60',
version: '413',
grade: 'A'
},
{
engine: 'Presto',
browser: 'Opera 7.0',
platform: 'Win 95+ / OSX.1+',
version: '-',
grade: 'A'
},
{
engine: 'Presto',
browser: 'Opera 7.5',
platform: 'Win 95+ / OSX.2+',
version: '-',
grade: 'A'
},
{
engine: 'Presto',
browser: 'Opera 8.0',
platform: 'Win 95+ / OSX.2+',
version: '-',
grade: 'A'
},
{
engine: 'Presto',
browser: 'Opera 8.5',
platform: 'Win 95+ / OSX.2+',
version: '-',
grade: 'A'
},
{
engine: 'Presto',
browser: 'Opera 9.0',
platform: 'Win 95+ / OSX.3+',
version: '-',
grade: 'A'
},
{
engine: 'Presto',
browser: 'Opera 9.2',
platform: 'Win 88+ / OSX.3+',
version: '-',
grade: 'A'
},
{
engine: 'Presto',
browser: 'Opera 9.5',
platform: 'Win 88+ / OSX.3+',
version: '-',
grade: 'A'
},
{
engine: 'Presto',
browser: 'Opera for Wii',
platform: 'Wii',
version: '-',
grade: 'A'
},
{
engine: 'Presto',
browser: 'Nokia N800',
platform: 'N800',
version: '-',
grade: 'A'
},
{
engine: 'Presto',
browser: 'Nintendo DS browser',
platform: 'Nintendo DS',
version: '8.5',
grade: 'C'
},
{
engine: 'KHTML',
browser: 'Konqureror 3.1',
platform: 'KDE 3.1',
version: '3.1',
grade: 'C'
},
{
engine: 'KHTML',
browser: 'Konqureror 3.3',
platform: 'KDE 3.3',
version: '3.3',
grade: 'A'
},
{
engine: 'KHTML',
browser: 'Konqureror 3.5',
platform: 'KDE 3.5',
version: '3.5',
grade: 'A'
},
{
engine: 'Tasman',
browser: 'Internet Explorer 4.5',
platform: 'Mac OS 8-9',
version: '-',
grade: 'X'
},
{
engine: 'Tasman',
browser: 'Internet Explorer 5.1',
platform: 'Mac OS 7.6-9',
version: '1',
grade: 'C'
},
{
engine: 'Tasman',
browser: 'Internet Explorer 5.2',
platform: 'Mac OS 8-X',
version: '1',
grade: 'C'
},
{
engine: 'Misc',
browser: 'NetFront 3.1',
platform: 'Embedded devices',
version: '-',
grade: 'C'
},
{
engine: 'Misc',
browser: 'NetFront 3.4',
platform: 'Embedded devices',
version: '-',
grade: 'A'
},
{
engine: 'Misc',
browser: 'Dillo 0.8',
platform: 'Embedded devices',
version: '-',
grade: 'X'
},
{
engine: 'Misc',
browser: 'Links',
platform: 'Text only',
version: '-',
grade: 'X'
},
{
engine: 'Misc',
browser: 'Lynx',
platform: 'Text only',
version: '-',
grade: 'X'
},
{
engine: 'Misc',
browser: 'IE Mobile',
platform: 'Windows Mobile 6',
version: '-',
grade: 'C'
},
{
engine: 'Misc',
browser: 'PSP browser',
platform: 'PSP',
version: '-',
grade: 'C'
},
{
engine: 'Other browsers',
browser: 'All others',
platform: '-',
version: '-',
grade: 'U'
}
].map(function (item, index) {
return Object.assign({}, item, {
id: index + 1
});
});

View File

@ -1,6 +1,6 @@
{
"name": "amis-core",
"version": "2.1.1-beta.2",
"version": "2.1.1-beta.3",
"description": "amis-core",
"main": "lib/index.js",
"module": "esm/index.js",

View File

@ -547,7 +547,21 @@ export const CRUDStore = ServiceStore.named('CRUDStore')
}
import('papaparse').then((papaparse: any) => {
const csvText = papaparse.unparse(items);
// 将数据里的对象转成 json 字符串,不然输出的 csv 没法显示
const csvData = [];
for (const row of items) {
const rowData = {} as {[key: string]: any};
for (const key in row) {
const value = row[key];
if (typeof value === 'object') {
rowData[key] = JSON.stringify(value);
} else {
rowData[key] = value;
}
}
csvData.push(rowData);
}
const csvText = papaparse.unparse(csvData);
if (csvText) {
const blob = new Blob(
// 加上 BOM 这样 Excel 打开的时候就不会乱码

View File

@ -1472,10 +1472,14 @@ export function getScrollbarWidth() {
}
// 后续改用 FormulaExec['formula']
function resolveValueByName(data: any, name?: string) {
function resolveValueByName(
data: any,
name?: string,
canAccessSuper?: boolean
) {
return isPureVariable(name)
? resolveVariableAndFilter(name, data)
: resolveVariable(name, data);
: resolveVariable(name, data, canAccessSuper);
}
// 统一的获取 value 值方法
@ -1486,10 +1490,13 @@ export function getPropValue<
data?: any;
defaultValue?: any;
}
>(props: T, getter?: (props: T) => any) {
>(props: T, getter?: (props: T) => any, canAccessSuper?: boolean) {
const {name, value, data, defaultValue} = props;
return (
value ?? getter?.(props) ?? resolveValueByName(data, name) ?? defaultValue
value ??
getter?.(props) ??
resolveValueByName(data, name, canAccessSuper) ??
defaultValue
);
}

View File

@ -1,14 +1,22 @@
import {Evaluator, parse} from 'amis-formula';
import {getVariable} from './getVariable';
export function resolveVariable(path?: string, data: any = {}): any {
export function resolveVariable(
path?: string,
data: any = {},
canAccessSuper?: boolean
): any {
if (path === '&' || path == '$$') {
return data;
} else if (!path || typeof path !== 'string') {
return undefined;
} else if (!~path.indexOf(':')) {
// 简单用法直接用 getVariable
return getVariable(data, path[0] === '$' ? path.substring(1) : path);
return getVariable(
data,
path[0] === '$' ? path.substring(1) : path,
canAccessSuper
);
}
// window:xxx ls:xxx.xxx

View File

@ -1,6 +1,6 @@
{
"name": "amis-formula",
"version": "2.1.1-beta.2",
"version": "2.1.1-beta.3",
"description": "负责 amis 里面的表达式实现,内置公式,编辑器等",
"main": "lib/index.js",
"types": "lib/index.d.ts",

View File

@ -3,7 +3,7 @@
"main": "lib/index.js",
"module": "esm/index.js",
"types": "lib/index.d.ts",
"version": "2.1.1-beta.2",
"version": "2.1.1-beta.3",
"description": "",
"scripts": {
"build": "npm run clean-dist && NODE_ENV=production rollup -c ",
@ -33,7 +33,7 @@
}
},
"dependencies": {
"amis-core": "^2.1.1-beta.2",
"amis-core": "^2.1.1-beta.3",
"amis-formula": "^2.1.0",
"classnames": "2.3.1",
"codemirror": "^5.63.0",

View File

@ -10,19 +10,14 @@
@keyframes modalIn {
from {
opacity: 0;
width: 0;
height: 0;
bottom: -999px;
transform: translate3d(0, -300px, 0) scale(0.2);
}
}
@keyframes modalOut {
to {
opacity: 0;
opacity: 0;
width: 0;
height: 0;
bottom: -999px;
transform: translate3d(0, -300px, 0) scale(0.2);
}
}

View File

@ -961,9 +961,7 @@
}
> .#{$ns}Table-fixedTop {
.#{$ns}Table-fixedTop-shadow {
display: none;
}
display: none;
}
> .#{$ns}Table-footToolbar {

View File

@ -277,7 +277,7 @@ exports[`Renderer:range with min & max & step & joinValues 1`] = `
class="cxd-TplField"
>
<span>
The form
表单
</span>
</span>
</h3>
@ -293,18 +293,6 @@ exports[`Renderer:range with min & max & step & joinValues 1`] = `
style="display: none;"
type="submit"
/>
<pre>
<code
class="cxd-Form--debug"
>
{
"range": {
"min": 0.2,
"max": 0.8
}
}
</code>
</pre>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
@ -634,6 +622,22 @@ exports[`Renderer:range with min & max & step & joinValues 1`] = `
</div>
</form>
</div>
<div
class="cxd-Panel-footerWrap"
>
<div
class="cxd-Panel-btnToolbar cxd-Panel-footer"
>
<button
class="cxd-Button cxd-Button--primary"
type="submit"
>
<span>
Submit
</span>
</button>
</div>
</div>
<div
class="resize-sensor"
style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; overflow: scroll; z-index: -1; visibility: hidden;"

View File

@ -1,5 +1,5 @@
import React = require('react');
import {render, fireEvent} from '@testing-library/react';
import {render, fireEvent, screen, waitFor} from '@testing-library/react';
import '../../../src';
import {render as amisRender} from '../../../src';
import {makeEnv, wait} from '../../helper';
@ -233,13 +233,15 @@ test('Renderer:range with tooltipVisible & tooltipPlacement', async () => {
});
test('Renderer:range with min & max & step & joinValues', async () => {
const onSubmit = jest.fn();
const submitBtnText = 'Submit';
const {container} = render(
amisRender(
{
type: 'form',
debug: true,
api: '/api/xxx',
controls: [
submitText: submitBtnText,
api: '/api/mock/saveForm?waitSeconds=1',
body: [
{
type: 'input-range',
name: 'range',
@ -250,11 +252,9 @@ test('Renderer:range with min & max & step & joinValues', async () => {
showInput: true,
joinValues: false
}
],
title: 'The form',
actions: []
]
},
{},
{onSubmit},
makeEnv({})
)
);
@ -280,13 +280,23 @@ test('Renderer:range with min & max & step & joinValues', async () => {
).getAttribute('style')
).toContain('width: 60%; left: 20%;');
expect((container.querySelector('.cxd-Form--debug') as Element).innerHTML)
.toBe(`{
"range": {
"min": 0.2,
"max": 0.8
}
}`);
await wait(500);
const submitBtn = screen.getByRole('button', {name: submitBtnText});
await waitFor(() => {
expect(submitBtn).toBeInTheDocument();
});
fireEvent.click(submitBtn);
await wait(500);
const formData = onSubmit.mock.calls[0][0];
expect(onSubmit).toHaveBeenCalled();
expect(formData).toEqual({
range: {
min: 0.2,
max: 0.8
}
});
expect(container).toMatchSnapshot();
});

View File

@ -1,6 +1,6 @@
{
"name": "amis",
"version": "2.1.1-beta.2",
"version": "2.1.1-beta.3",
"description": "一种MIS页面生成工具",
"main": "lib/index.js",
"module": "esm/index.js",
@ -40,8 +40,8 @@
]
},
"dependencies": {
"amis-core": "^2.1.1-beta.2",
"amis-ui": "^2.1.1-beta.2",
"amis-core": "^2.1.1-beta.3",
"amis-ui": "^2.1.1-beta.3",
"ansi-to-react": "^6.1.6",
"attr-accept": "2.2.2",
"blueimp-canvastoblob": "2.1.0",

View File

@ -1092,10 +1092,12 @@ export default class FormTable extends React.Component<TableProps, TableState> {
*/
@autobind
handlePristineChange(data: Record<string, any>, rowIndex: string) {
const {needConfirm} = this.props;
const index = Number(rowIndex);
this.setState(
prevState => {
const items = cloneDeep(prevState.items);
const index = Number(rowIndex);
if (
Number.isInteger(index) &&
@ -1109,7 +1111,11 @@ export default class FormTable extends React.Component<TableProps, TableState> {
return null;
},
() => {
this.emitValue();
if (needConfirm === false) {
this.emitValue();
} else {
Number.isInteger(index) && this.startEdit(index, true);
}
}
);
}

View File

@ -66,6 +66,7 @@ export class TableCell extends React.Component<RendererProps> {
className: innerClassName,
type: (column && column.type) || 'plain'
};
const canAccessSuperData = schema?.canAccessSuperData !== false;
// 如果本来就是 type 为 button不要删除其他情况下都应该删除。
if (schema.type !== 'button' && schema.type !== 'dropdown-button') {
@ -77,7 +78,8 @@ export class TableCell extends React.Component<RendererProps> {
: render('field', schema, {
...omit(rest, Object.keys(schema)),
inputOnly: true,
value,
/** value没有返回值时设置默认值避免错误获取到父级数据域的值 */
value: canAccessSuperData ? value : value ?? '',
data
});

View File

@ -165,6 +165,11 @@ export type TableColumnObject = {
* , inputTable
*/
unique?: boolean;
/**
* true
*/
canAccessSuperData?: boolean;
};
export type TableColumnWithType = SchemaObject & TableColumnObject;
@ -293,6 +298,11 @@ export interface TableSchema extends BaseSchema {
* searchable属性值
*/
autoGenerateFilter?: boolean;
/**
* false
*/
canAccessSuperData?: boolean;
}
export interface TableProps extends RendererProps {
@ -606,7 +616,6 @@ export default class Table extends React.Component<TableProps, object> {
}
componentDidMount() {
const {autoFillHeight, classPrefix: ns} = this.props;
const currentNode = findDOMNode(this) as HTMLElement;
// 获取小于所有子元素高度之和的父元素
let parent: HTMLElement | Window | null = getScrollParent(
@ -633,11 +642,6 @@ export default class Table extends React.Component<TableProps, object> {
this.affixDetect();
parent.addEventListener('scroll', this.affixDetect);
if (autoFillHeight) {
document
.querySelector<HTMLElement>(`.${ns}Table-content`)!
.addEventListener('scroll', this.affixDetect);
}
window.addEventListener('resize', this.affixDetect);
this.updateAutoFillHeight();
window.addEventListener('resize', this.updateAutoFillHeight);
@ -812,15 +816,10 @@ export default class Table extends React.Component<TableProps, object> {
}
componentWillUnmount() {
const {formItem, autoFillHeight, classPrefix: ns} = this.props;
const {formItem} = this.props;
const parent = this.parentNode;
parent && parent.removeEventListener('scroll', this.affixDetect);
if (autoFillHeight) {
document
.querySelector<HTMLElement>(`.${ns}Table-content`)!
.addEventListener('scroll', this.affixDetect);
}
window.removeEventListener('resize', this.affixDetect);
window.removeEventListener('resize', this.updateAutoFillHeight);
(this.updateTableInfoLazy as any).cancel();
@ -1061,81 +1060,44 @@ export default class Table extends React.Component<TableProps, object> {
return store.selectedRows.map(item => item.data);
}
/**
* Table-fixedTop
*/
affixDetect() {
const {
affixHeader,
classPrefix: ns,
affixOffsetTop,
env,
autoFillHeight
} = this.props;
if (!(affixHeader || autoFillHeight) || !this.table) {
// if (!this.props.affixHeader || !this.table || this.props.autoFillHeight) {
affixDetect() {
if (!this.props.affixHeader || !this.table || this.props.autoFillHeight) {
return;
}
const ns = this.props.classPrefix;
const dom = findDOMNode(this) as HTMLElement;
const clip = (this.table as HTMLElement).getBoundingClientRect();
const offsetY =
this.props.affixOffsetTop ?? this.props.env.affixOffsetTop ?? 0;
const headingHeight =
dom.querySelector(`.${ns}Table-heading`)?.getBoundingClientRect()
.height || 0;
const headerHeight =
dom.querySelector(`.${ns}Table-headToolbar`)?.getBoundingClientRect()
.height || 0;
const affixed =
clip.top - headerHeight - headingHeight < offsetY &&
clip.top + clip.height - 40 > offsetY;
const affixedDom = dom.querySelector(`.${ns}Table-fixedTop`) as HTMLElement;
const affixedShadowDom = dom.querySelector(
`.${ns}Table-fixedTop-shadow`
) as HTMLElement;
const affixedDomHeight =
getComputedStyle(affixedDom).getPropertyValue('height');
if (autoFillHeight) {
//! 解决 sticky 不兼容的问题
const tableContentDom = document.querySelector<HTMLElement>(
`.${ns}Table-content`
)!;
const clip = tableContentDom.getBoundingClientRect();
const tableHeaderClip = affixedDom
.querySelector(`.${ns}Table-wrapper`)!
.getBoundingClientRect();
const offsetHeight =
affixedDom.getBoundingClientRect().height - tableHeaderClip.height;
const offsetY = clip.top - offsetHeight;
affixedDom.style.cssText += `top: ${offsetY}px;width: ${clip.width}px`;
affixedDom.classList.add('in');
} else {
// 配置了 affixHeader
const clip = (this.table as HTMLElement).getBoundingClientRect();
const offsetY = affixOffsetTop ?? env.affixOffsetTop ?? 0;
const headingHeight =
dom.querySelector(`.${ns}Table-heading`)?.getBoundingClientRect()
.height || 0;
const affixedShadowDom = dom.querySelector(
`.${ns}Table-fixedTop-shadow`
) as HTMLElement;
const affixed =
clip.top - headerHeight - headingHeight < offsetY &&
clip.top + clip.height - 40 > offsetY;
affixedDom.style.cssText += `top: ${offsetY}px;width: ${
(this.table.parentNode as HTMLElement).offsetWidth
}px`;
affixedShadowDom.style.cssText += `top: ${affixedDomHeight};width: ${
(this.table.parentNode as HTMLElement).offsetWidth
}px`;
const preStatus = affixedDom.classList.contains('in');
affixed
? affixedDom.classList.add('in')
: affixedDom.classList.remove('in');
// 出现affixHeader时重新计算列表宽度
if (!preStatus && affixed) {
this.updateTableInfoLazy();
}
}
affixedDom.style.cssText += `top: ${offsetY}px;width: ${
(this.table.parentNode as HTMLElement).offsetWidth
}px`;
affixedShadowDom.style.cssText += `top: ${affixedDomHeight};width: ${
(this.table.parentNode as HTMLElement).offsetWidth
}px`;
affixed
? affixedDom.classList.add('in')
: affixedDom.classList.remove('in');
// store.markHeaderAffix(clip.top < offsetY && (clip.top + clip.height - 40) > offsetY);
}