mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
feat: AnchorNav组件支持树形结构 (#8969)
Co-authored-by: yanglu19 <yanglu19@baidu.com>
This commit is contained in:
parent
d9ace501e3
commit
d9fb3ddb75
@ -12,6 +12,8 @@ order: 68
|
|||||||
|
|
||||||
## 基本用法
|
## 基本用法
|
||||||
|
|
||||||
|
`6.1.0`及以上版本垂直方向支持配置子节点
|
||||||
|
|
||||||
```schema: scope="body"
|
```schema: scope="body"
|
||||||
{
|
{
|
||||||
"type": "anchor-nav",
|
"type": "anchor-nav",
|
||||||
@ -39,6 +41,24 @@ order: 68
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "工作信息",
|
"title": "工作信息",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"title": "工作信息-1",
|
||||||
|
"type": "form",
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "input-text",
|
||||||
|
"name": "workInfo1-1",
|
||||||
|
"label": "工作信息1-1:"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workInfo1-2",
|
||||||
|
"type": "input-text",
|
||||||
|
"label": "工作信息1-2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"body": [
|
"body": [
|
||||||
{
|
{
|
||||||
"type": "form",
|
"type": "form",
|
||||||
@ -60,6 +80,29 @@ order: 68
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "兴趣爱好",
|
"title": "兴趣爱好",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"title": "兴趣爱好1-1",
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "form",
|
||||||
|
"title": "兴趣爱好1-1",
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "input-text",
|
||||||
|
"name": "interest1-1",
|
||||||
|
"label": "interest1-1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "interest1-2",
|
||||||
|
"type": "input-text",
|
||||||
|
"label": "interest1-2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"body": [
|
"body": [
|
||||||
{
|
{
|
||||||
"type": "form",
|
"type": "form",
|
||||||
@ -235,6 +278,25 @@ order: 68
|
|||||||
{
|
{
|
||||||
"title": "工作信息",
|
"title": "工作信息",
|
||||||
"href": "work",
|
"href": "work",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"title": "工作信息-1",
|
||||||
|
"href": "work-1",
|
||||||
|
"type": "form",
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "input-text",
|
||||||
|
"name": "workInfo1-1",
|
||||||
|
"label": "工作信息1-1:"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workInfo1-2",
|
||||||
|
"type": "input-text",
|
||||||
|
"label": "工作信息1-2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"body": [
|
"body": [
|
||||||
{
|
{
|
||||||
"type": "form",
|
"type": "form",
|
||||||
@ -332,6 +394,24 @@ order: 68
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "工作信息",
|
"title": "工作信息",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"title": "工作信息-1",
|
||||||
|
"type": "form",
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "input-text",
|
||||||
|
"name": "workInfo1-1",
|
||||||
|
"label": "工作信息1-1:"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "workInfo1-2",
|
||||||
|
"type": "input-text",
|
||||||
|
"label": "工作信息1-2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"body": [
|
"body": [
|
||||||
{
|
{
|
||||||
"type": "form",
|
"type": "form",
|
||||||
@ -409,5 +489,5 @@ order: 68
|
|||||||
| active | `string` | | 需要定位的区域 |
|
| active | `string` | | 需要定位的区域 |
|
||||||
| links[x].title | `string` | | 区域 标题 |
|
| links[x].title | `string` | | 区域 标题 |
|
||||||
| links[x].href | `string` | | 区域 标识 |
|
| links[x].href | `string` | | 区域 标识 |
|
||||||
| links[x].body | [SchemaNode](../types/schemanode) | | 区域 内容区 |
|
| links[x].body | [SchemaNode](../types/schemanode) | | 区域 内容区,`6.1.0`及以上版本垂直方向支持配置子节点 |
|
||||||
| links[x].className | `string` | `"bg-white b-l b-r b-b wrapper-md"` | 区域成员 样式 |
|
| links[x].className | `string` | `"bg-white b-l b-r b-b wrapper-md"` | 区域成员 样式 |
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
> .#{$ns}AnchorNav-link {
|
> .#{$ns}AnchorNav-link {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
|
&.#{$ns}AnchorNav-link-child {
|
||||||
|
margin-left: px2rem(16px);
|
||||||
|
}
|
||||||
|
|
||||||
> a {
|
> a {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -84,7 +84,6 @@ export class AnchorNav extends React.Component<AnchorNavProps, AnchorNavState> {
|
|||||||
|
|
||||||
const sectionRootDom =
|
const sectionRootDom =
|
||||||
this.contentDom && (this.contentDom.current as HTMLElement);
|
this.contentDom && (this.contentDom.current as HTMLElement);
|
||||||
|
|
||||||
this.updateSectionOffset(sectionRootDom, false);
|
this.updateSectionOffset(sectionRootDom, false);
|
||||||
this.observer = new MutationObserver(() =>
|
this.observer = new MutationObserver(() =>
|
||||||
// TODO: 牺牲性能
|
// TODO: 牺牲性能
|
||||||
@ -185,7 +184,6 @@ export class AnchorNav extends React.Component<AnchorNavProps, AnchorNavState> {
|
|||||||
this.setState({fromSelect: true});
|
this.setState({fromSelect: true});
|
||||||
// 滚动到对应段落
|
// 滚动到对应段落
|
||||||
this.scrollToSection(key);
|
this.scrollToSection(key);
|
||||||
|
|
||||||
const sectionRootDom =
|
const sectionRootDom =
|
||||||
this.contentDom && (this.contentDom.current as HTMLElement);
|
this.contentDom && (this.contentDom.current as HTMLElement);
|
||||||
|
|
||||||
@ -215,11 +213,17 @@ export class AnchorNav extends React.Component<AnchorNavProps, AnchorNavState> {
|
|||||||
const {classnames: cx, active: activeProp} = this.props;
|
const {classnames: cx, active: activeProp} = this.props;
|
||||||
const {title, name} = link.props;
|
const {title, name} = link.props;
|
||||||
const active = activeProp === undefined && index === 0 ? name : activeProp;
|
const active = activeProp === undefined && index === 0 ? name : activeProp;
|
||||||
|
// 判断是否为子节点,子节点key为 <父节点索引>-<子节点索引>
|
||||||
|
const isChild = link.key?.split('-').length >= 2;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
className={cx('AnchorNav-link', active === name ? 'is-active' : '')}
|
className={cx(
|
||||||
key={index}
|
'AnchorNav-link',
|
||||||
|
isChild ? 'AnchorNav-link-child' : '',
|
||||||
|
String(active) === String(name) ? 'is-active' : ''
|
||||||
|
)}
|
||||||
|
key={link.key}
|
||||||
onClick={() => this.handleSelect(name)}
|
onClick={() => this.handleSelect(name)}
|
||||||
>
|
>
|
||||||
<a title={title}>{title}</a>
|
<a title={title}>{title}</a>
|
||||||
@ -234,11 +238,11 @@ export class AnchorNav extends React.Component<AnchorNavProps, AnchorNavState> {
|
|||||||
|
|
||||||
const {active: activeProp, classnames} = this.props;
|
const {active: activeProp, classnames} = this.props;
|
||||||
const name = section.props.name;
|
const name = section.props.name;
|
||||||
|
const key = section.key;
|
||||||
const active = activeProp === undefined && index === 0 ? name : activeProp;
|
const active = activeProp === undefined && index === 0 ? name : activeProp;
|
||||||
|
|
||||||
return React.cloneElement(section, {
|
return React.cloneElement(section, {
|
||||||
...section.props,
|
...section.props,
|
||||||
key: index,
|
key,
|
||||||
classnames,
|
classnames,
|
||||||
active
|
active
|
||||||
});
|
});
|
||||||
|
@ -206,3 +206,120 @@ test('Renderer:anchorNav with active', async () => {
|
|||||||
container.querySelector('.two .cxd-AnchorNav-link.is-active')
|
container.querySelector('.two .cxd-AnchorNav-link.is-active')
|
||||||
).toHaveTextContent('工作信息');
|
).toHaveTextContent('工作信息');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 4. 子菜单
|
||||||
|
test('Renderer:anchorNav with children', async () => {
|
||||||
|
const {container} = render(
|
||||||
|
amisRender(
|
||||||
|
{
|
||||||
|
type: 'page',
|
||||||
|
body: {
|
||||||
|
type: 'anchor-nav',
|
||||||
|
direction: 'horizontal',
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
title: '基本信息',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'form',
|
||||||
|
title: '基本信息',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'input-text',
|
||||||
|
name: 'name',
|
||||||
|
label: '姓名:'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'email',
|
||||||
|
type: 'input-email',
|
||||||
|
label: '邮箱:'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: '基本信息1-1',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'form',
|
||||||
|
title: '基本信息1-1',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'input-text',
|
||||||
|
name: 'cname1',
|
||||||
|
label: 'cname1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'caddress1',
|
||||||
|
type: 'input-text',
|
||||||
|
label: 'caddress1'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '基本信息1-2',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'form',
|
||||||
|
title: '基本信息1-2',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'input-text',
|
||||||
|
name: 'cname2',
|
||||||
|
label: 'cname2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'caddress2',
|
||||||
|
type: 'input-text',
|
||||||
|
label: 'caddress2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '工作信息',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'form',
|
||||||
|
title: '工作信息',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'input-text',
|
||||||
|
name: 'cname',
|
||||||
|
label: '公司名称:'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'caddress',
|
||||||
|
type: 'input-text',
|
||||||
|
label: '公司地址:'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
makeEnv({})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
await wait(500);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
container.querySelector('.cxd-AnchorNav-link-child')
|
||||||
|
).toHaveTextContent('基本信息1-1');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
container.querySelector('.cxd-AnchorNav-link.is-active')
|
||||||
|
).toHaveTextContent('基本信息');
|
||||||
|
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
@ -568,6 +568,565 @@ exports[`Renderer:anchorNav 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`Renderer:anchorNav with children 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="cxd-Page"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Page-content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Page-main"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Page-body"
|
||||||
|
role="page-body"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-AnchorNav cxd-AnchorNav--horizontal"
|
||||||
|
>
|
||||||
|
<ul
|
||||||
|
class="cxd-AnchorNav-link-wrap"
|
||||||
|
role="anchorlist"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
class="cxd-AnchorNav-link is-active"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
title="基本信息"
|
||||||
|
>
|
||||||
|
基本信息
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
class="cxd-AnchorNav-link cxd-AnchorNav-link-child"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
title="基本信息1-1"
|
||||||
|
>
|
||||||
|
基本信息1-1
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
class="cxd-AnchorNav-link cxd-AnchorNav-link-child"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
title="基本信息1-2"
|
||||||
|
>
|
||||||
|
基本信息1-2
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
class="cxd-AnchorNav-link"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
title="工作信息"
|
||||||
|
>
|
||||||
|
工作信息
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div
|
||||||
|
class="cxd-AnchorNav-section-wrap"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-AnchorNav-section"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel cxd-Panel--default cxd-Panel--form"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-heading"
|
||||||
|
>
|
||||||
|
<h3
|
||||||
|
class="cxd-Panel-title"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="cxd-TplField"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
基本信息
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-body"
|
||||||
|
>
|
||||||
|
<form
|
||||||
|
class="cxd-Form cxd-Form--normal"
|
||||||
|
novalidate=""
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
style="display: none;"
|
||||||
|
type="submit"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-item cxd-Form-item--normal"
|
||||||
|
data-role="form-item"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="cxd-Form-label"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<span
|
||||||
|
class="cxd-TplField"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
姓名:
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-control cxd-TextControl"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-TextControl-input"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
class=""
|
||||||
|
name="name"
|
||||||
|
placeholder=""
|
||||||
|
size="10"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-item cxd-Form-item--normal"
|
||||||
|
data-role="form-item"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="cxd-Form-label"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<span
|
||||||
|
class="cxd-TplField"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
邮箱:
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-control cxd-TextControl"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-TextControl-input"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
class=""
|
||||||
|
name="email"
|
||||||
|
placeholder=""
|
||||||
|
size="10"
|
||||||
|
type="email"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-footerWrap"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-btnToolbar cxd-Panel-footer"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="cxd-Button cxd-Button--primary cxd-Button--size-default"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
提交
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-AnchorNav-section"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel cxd-Panel--default cxd-Panel--form"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-heading"
|
||||||
|
>
|
||||||
|
<h3
|
||||||
|
class="cxd-Panel-title"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="cxd-TplField"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
基本信息1-1
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-body"
|
||||||
|
>
|
||||||
|
<form
|
||||||
|
class="cxd-Form cxd-Form--normal"
|
||||||
|
novalidate=""
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
style="display: none;"
|
||||||
|
type="submit"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-item cxd-Form-item--normal"
|
||||||
|
data-role="form-item"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="cxd-Form-label"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<span
|
||||||
|
class="cxd-TplField"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
cname1
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-control cxd-TextControl"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-TextControl-input"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
class=""
|
||||||
|
name="cname1"
|
||||||
|
placeholder=""
|
||||||
|
size="10"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-item cxd-Form-item--normal"
|
||||||
|
data-role="form-item"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="cxd-Form-label"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<span
|
||||||
|
class="cxd-TplField"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
caddress1
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-control cxd-TextControl"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-TextControl-input"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
class=""
|
||||||
|
name="caddress1"
|
||||||
|
placeholder=""
|
||||||
|
size="10"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-footerWrap"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-btnToolbar cxd-Panel-footer"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="cxd-Button cxd-Button--primary cxd-Button--size-default"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
提交
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-AnchorNav-section"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel cxd-Panel--default cxd-Panel--form"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-heading"
|
||||||
|
>
|
||||||
|
<h3
|
||||||
|
class="cxd-Panel-title"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="cxd-TplField"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
基本信息1-2
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-body"
|
||||||
|
>
|
||||||
|
<form
|
||||||
|
class="cxd-Form cxd-Form--normal"
|
||||||
|
novalidate=""
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
style="display: none;"
|
||||||
|
type="submit"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-item cxd-Form-item--normal"
|
||||||
|
data-role="form-item"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="cxd-Form-label"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<span
|
||||||
|
class="cxd-TplField"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
cname2
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-control cxd-TextControl"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-TextControl-input"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
class=""
|
||||||
|
name="cname2"
|
||||||
|
placeholder=""
|
||||||
|
size="10"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-item cxd-Form-item--normal"
|
||||||
|
data-role="form-item"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="cxd-Form-label"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<span
|
||||||
|
class="cxd-TplField"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
caddress2
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-control cxd-TextControl"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-TextControl-input"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
class=""
|
||||||
|
name="caddress2"
|
||||||
|
placeholder=""
|
||||||
|
size="10"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-footerWrap"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-btnToolbar cxd-Panel-footer"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="cxd-Button cxd-Button--primary cxd-Button--size-default"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
提交
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-AnchorNav-section"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel cxd-Panel--default cxd-Panel--form"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-heading"
|
||||||
|
>
|
||||||
|
<h3
|
||||||
|
class="cxd-Panel-title"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="cxd-TplField"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
工作信息
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-body"
|
||||||
|
>
|
||||||
|
<form
|
||||||
|
class="cxd-Form cxd-Form--normal"
|
||||||
|
novalidate=""
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
style="display: none;"
|
||||||
|
type="submit"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-item cxd-Form-item--normal"
|
||||||
|
data-role="form-item"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="cxd-Form-label"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<span
|
||||||
|
class="cxd-TplField"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
公司名称:
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-control cxd-TextControl"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-TextControl-input"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
class=""
|
||||||
|
name="cname"
|
||||||
|
placeholder=""
|
||||||
|
size="10"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-item cxd-Form-item--normal"
|
||||||
|
data-role="form-item"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="cxd-Form-label"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<span
|
||||||
|
class="cxd-TplField"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
公司地址:
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="cxd-Form-control cxd-TextControl"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-TextControl-input"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
class=""
|
||||||
|
name="caddress"
|
||||||
|
placeholder=""
|
||||||
|
size="10"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-footerWrap"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Panel-btnToolbar cxd-Panel-footer"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="cxd-Button cxd-Button--primary cxd-Button--size-default"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
提交
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`Renderer:anchorNav with horizontal 1`] = `
|
exports[`Renderer:anchorNav with horizontal 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
|
@ -3,7 +3,6 @@ import {Renderer, RendererProps} from 'amis-core';
|
|||||||
import {AnchorNav as CAnchorNav, AnchorNavSection} from 'amis-ui';
|
import {AnchorNav as CAnchorNav, AnchorNavSection} from 'amis-ui';
|
||||||
import {isVisible, autobind} from 'amis-core';
|
import {isVisible, autobind} from 'amis-core';
|
||||||
import {filter} from 'amis-core';
|
import {filter} from 'amis-core';
|
||||||
import find from 'lodash/find';
|
|
||||||
import {BaseSchema, SchemaClassName, SchemaCollection} from '../Schema';
|
import {BaseSchema, SchemaClassName, SchemaCollection} from '../Schema';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,6 +25,11 @@ export type AnchorNavSectionSchema = {
|
|||||||
* 内容
|
* 内容
|
||||||
*/
|
*/
|
||||||
body?: SchemaCollection;
|
body?: SchemaCollection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子节点
|
||||||
|
*/
|
||||||
|
children?: Array<AnchorNavSectionSchema>;
|
||||||
} & Omit<BaseSchema, 'type'>;
|
} & Omit<BaseSchema, 'type'>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,7 +77,7 @@ export interface AnchorNavProps
|
|||||||
sectionRender?: (
|
sectionRender?: (
|
||||||
section: AnchorNavSectionSchema,
|
section: AnchorNavSectionSchema,
|
||||||
props: AnchorNavProps,
|
props: AnchorNavProps,
|
||||||
index: number
|
index: number | string
|
||||||
) => JSX.Element;
|
) => JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +98,7 @@ export default class AnchorNav extends React.Component<
|
|||||||
renderSection?: (
|
renderSection?: (
|
||||||
section: AnchorNavSectionSchema,
|
section: AnchorNavSectionSchema,
|
||||||
props: AnchorNavProps,
|
props: AnchorNavProps,
|
||||||
index: number
|
index: number | string
|
||||||
) => JSX.Element;
|
) => JSX.Element;
|
||||||
|
|
||||||
constructor(props: AnchorNavProps) {
|
constructor(props: AnchorNavProps) {
|
||||||
@ -107,21 +111,43 @@ export default class AnchorNav extends React.Component<
|
|||||||
if (typeof props.active !== 'undefined') {
|
if (typeof props.active !== 'undefined') {
|
||||||
active = props.active;
|
active = props.active;
|
||||||
} else {
|
} else {
|
||||||
const section: AnchorNavSectionSchema = find(
|
let section: AnchorNavSectionSchema | null = this.getActiveSection(
|
||||||
links,
|
links,
|
||||||
section => section.href === props.active
|
props.active,
|
||||||
) as AnchorNavSectionSchema;
|
null
|
||||||
|
);
|
||||||
|
|
||||||
active =
|
active =
|
||||||
section && section.href
|
section && section.href
|
||||||
? section.href
|
? section.href
|
||||||
: (links[0] && links[0].href) || 0;
|
: (links[0] && links[0].href) || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
active
|
active
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取激活的内容区
|
||||||
|
getActiveSection(
|
||||||
|
links: Array<AnchorNavSectionSchema>,
|
||||||
|
active: string | number | undefined,
|
||||||
|
section: AnchorNavSectionSchema | null
|
||||||
|
) {
|
||||||
|
if (section) {
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
links.forEach(link => {
|
||||||
|
if (link.href === active) {
|
||||||
|
section = link;
|
||||||
|
} else {
|
||||||
|
if (link.children) {
|
||||||
|
this.getActiveSection(link.children, active, section);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
handleSelect(key: any) {
|
handleSelect(key: any) {
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -132,7 +158,6 @@ export default class AnchorNav extends React.Component<
|
|||||||
@autobind
|
@autobind
|
||||||
locateTo(index: number) {
|
locateTo(index: number) {
|
||||||
const {links} = this.props;
|
const {links} = this.props;
|
||||||
|
|
||||||
Array.isArray(links) &&
|
Array.isArray(links) &&
|
||||||
links[index] &&
|
links[index] &&
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -140,6 +165,46 @@ export default class AnchorNav extends React.Component<
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderSections(links: AnchorNavSectionSchema[], parentIdx?: string | number) {
|
||||||
|
const {
|
||||||
|
classnames: cx,
|
||||||
|
classPrefix: ns,
|
||||||
|
sectionRender,
|
||||||
|
render,
|
||||||
|
data
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
links = Array.isArray(links) ? links : [links];
|
||||||
|
let children: Array<JSX.Element | null> = [];
|
||||||
|
|
||||||
|
links.forEach((section, index) => {
|
||||||
|
if (isVisible(section, data)) {
|
||||||
|
// 若有子节点,key为parentIdx-index
|
||||||
|
let curIdx = (parentIdx ? parentIdx + '-' : '') + index;
|
||||||
|
|
||||||
|
children.push(
|
||||||
|
/** 内容区 */
|
||||||
|
<AnchorNavSection
|
||||||
|
{...(section as any)}
|
||||||
|
title={filter(section.title, data)}
|
||||||
|
key={curIdx}
|
||||||
|
name={section.href || curIdx}
|
||||||
|
>
|
||||||
|
{this.renderSection
|
||||||
|
? this.renderSection(section, this.props, curIdx)
|
||||||
|
: sectionRender
|
||||||
|
? sectionRender(section, this.props, curIdx)
|
||||||
|
: render(`section/${curIdx}`, section.body || '')}
|
||||||
|
</AnchorNavSection>
|
||||||
|
);
|
||||||
|
if (section.children) {
|
||||||
|
children.push(...this.renderSections(section.children, curIdx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return children.filter(item => !!item);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
classnames: cx,
|
classnames: cx,
|
||||||
@ -159,27 +224,7 @@ export default class AnchorNav extends React.Component<
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
links = Array.isArray(links) ? links : [links];
|
let children = this.renderSections(links);
|
||||||
let children: Array<JSX.Element | null> = [];
|
|
||||||
|
|
||||||
children = links
|
|
||||||
.map((section, index) =>
|
|
||||||
isVisible(section, data) ? (
|
|
||||||
<AnchorNavSection
|
|
||||||
{...(section as any)}
|
|
||||||
title={filter(section.title, data)}
|
|
||||||
key={index}
|
|
||||||
name={section.href || index}
|
|
||||||
>
|
|
||||||
{this.renderSection
|
|
||||||
? this.renderSection(section, this.props, index)
|
|
||||||
: sectionRender
|
|
||||||
? sectionRender(section, this.props, index)
|
|
||||||
: render(`section/${index}`, section.body || '')}
|
|
||||||
</AnchorNavSection>
|
|
||||||
) : null
|
|
||||||
)
|
|
||||||
.filter(item => !!item);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CAnchorNav
|
<CAnchorNav
|
||||||
|
Loading…
Reference in New Issue
Block a user