* {
box-sizing: border-box;
}
.active {
color: blue;
}
.content {
background-color: #fff;
width: 500px;
}
效果如上。
import { Layout, Table } from "antd";
import { ColumnsType } from "antd/lib/table";
import React, { useEffect, useState } from "react";
import { Anchor } from "antd";
import "./MyAnchor.less";
const { Link } = Anchor;
const { Content } = Layout;
export default function MyAnchoe() {
const [active, setActive] = useState(0);
interface DataType {
key: React.Key;
interfaceNm: string;
resourceNm: number;
permission: string;
}
const columns: ColumnsType<DataType> = [
{
title: "接口路径",
dataIndex: "interfaceNm",
render: (text: string) => <a>{text}</a>,
},
{
title: "接口名称",
dataIndex: "resourceNm",
},
{
title: "状态",
dataIndex: "permission",
},
];
let list: any = [];
const rowSelection = {
onSelectAll: (selected: any, selectedRows: any, changeRows: any) => {
interfaceList.map((a: any) => {
a.permissionRestInfList.map((b: any) => {
changeRows.map((c: any) => {
if (c.key === b.key) {
b.isChecked = selected;
}
return b;
});
return a;
});
});
for (let i = 0; i < interfaceList.length; i++) {
for (
let j = 0;
j < interfaceList[i].permissionRestInfList.length;
j++
) {
if (interfaceList[i].permissionRestInfList[j].isChecked) {
list.push(interfaceList[i].permissionRestInfList[j]);
}
}
}
},
onSelect: (
record: any,
selected: any,
selectedRows: any,
nativeEvent: any
) => {
interfaceList.map((i: any) => {
i.permissionRestInfList.map((j: any) => {
if (record.key === j.key) {
j.isChecked = !j.isChecked;
}
return j;
});
return i;
});
for (let i = 0; i < interfaceList.length; i++) {
for (
let j = 0;
j < interfaceList[i].permissionRestInfList.length;
j++
) {
if (interfaceList[i].permissionRestInfList[j].isChecked) {
list.push(interfaceList[i].permissionRestInfList[j]);
}
}
}
},
getCheckboxProps: (record: DataType) => ({
disabled: record.permission === "1",
permission: record.permission,
}),
};
const interfaceList: any = [
{
permissionRestInfList: [
{
checkCustomAuth: "1",
checkOffLine: "1",
customMade: "0",
interfaceNm: "tax/v2/TXDECINF/申报明细查询",
key: "tax/v2/TXDECINF/申报明细查询",
onLineOrNot: "1",
permission: "0",
resourceId: 16,
resourceNm: "个税服务",
restId: "v2/TTXDECINF",
restNm: "申报明细查询",
serviceId: "tax",
},
{
checkCustomAuth: "1",
checkOffLine: "1",
customMade: "0",
interfaceNm: "usermanage/OPPSTUPT/修改岗位",
key: "usermanage/OPPSTUPT/修改岗位",
onLineOrNot: "1",
permission: "0",
resourceId: 16,
resourceNm: "个税服务",
restId: "OPPSTUPT",
restNm: "修改岗位",
serviceId: "usermanage",
},
{
checkCustomAuth: "1",
checkOffLine: "1",
customMade: "0",
interfaceNm: "usermanage/OPPSTUPT/增加岗位",
key: "usermanage/OPPSTUPT/增加岗位",
onLineOrNot: "1",
permission: "0",
resourceId: 16,
resourceNm: "个税服务",
restId: "OPPSTUPT",
restNm: "增加岗位",
serviceId: "usermanage",
},
],
resourceNm: "个税服务",
},
{
permissionRestInfList: [
{
interfaceNm: "tax/v2/TXDECINF/申报明细查询1",
key: "tax/v2/TXDECINF/申报明细查询1",
onLineOrNot: "1",
permission: "0",
resourceId: 16,
resourceNm: "嘻嘻嘻",
restId: "v2/TTXDECINF",
restNm: "申报明细查询1",
serviceId: "tax",
},
{
interfaceNm: "usermanage/OPPSTUPT/修改岗位1",
key: "usermanage/OPPSTUPT/修改岗位1",
onLineOrNot: "1",
permission: "0",
resourceId: 16,
resourceNm: "嘻嘻嘻",
restId: "OPPSTUPT",
restNm: "修改岗位1",
serviceId: "usermanage",
},
{
checkCustomAuth: "1",
checkOffLine: "1",
customMade: "0",
interfaceNm: "usermanage/OPPSTUPT/增加岗位2",
key: "usermanage/OPPSTUPT/增加岗位2",
onLineOrNot: "1",
permission: "0",
resourceId: 16,
resourceNm: "嘻嘻嘻",
restId: "OPPSTUPT",
restNm: "增加岗位2",
serviceId: "usermanage",
},
],
resourceNm: "嘻嘻嘻",
},
{
permissionRestInfList: [
{
interfaceNm: "tax/v2/TXDECINF/申报明细查询3",
key: "tax/v2/TXDECINF/申报明细查询3",
onLineOrNot: "1",
permission: "0",
resourceId: 16,
resourceNm: "琪琪",
restId: "v2/TTXDECINF",
restNm: "申报明细查询3",
serviceId: "tax",
},
{
interfaceNm: "usermanage/OPPSTUPT/修改岗位4",
key: "usermanage/OPPSTUPT/修改岗位4",
onLineOrNot: "1",
permission: "0",
resourceId: 16,
resourceNm: "琪琪",
restId: "OPPSTUPT",
restNm: "修改岗位4",
serviceId: "usermanage",
},
{
interfaceNm: "usermanage/OPPSTUPT/增加岗位4",
key: "usermanage/OPPSTUPT/增加岗位4",
onLineOrNot: "1",
permission: "0",
resourceId: 16,
resourceNm: "琪琪",
restId: "OPPSTUPT",
restNm: "增加岗位4",
serviceId: "usermanage",
},
],
resourceNm: "琪琪",
},
{
permissionRestInfList: [
{
interfaceNm: "password/OPPSTUPT/哈哈哈查询",
key: "password/OPPSTUPT/哈哈哈查询",
onLineOrNot: "1",
permission: "0",
resourceId: 16,
resourceNm: "哈哈哈",
restId: "OPPSTUPT",
restNm: "哈哈哈查询",
serviceId: "password",
},
{
interfaceNm: "password/OPPSTUPT/哈哈哈修改",
key: "password/OPPSTUPT/哈哈哈修改",
onLineOrNot: "1",
permission: "1",
resourceId: 16,
resourceNm: "哈哈哈",
restId: "OPPSTUPT",
restNm: "哈哈哈修改",
serviceId: "password",
},
{
interfaceNm: "password/OPPSTUPT/哈哈哈增加",
key: "password/OPPSTUPT/哈哈哈增加",
onLineOrNot: "1",
permission: "0",
resourceId: 16,
resourceNm: "哈哈哈",
restId: "OPPSTUPT",
restNm: "哈哈哈增加",
serviceId: "password",
},
],
resourceNm: "哈哈哈",
},
];
const catalog = ["个税服务", "嘻嘻嘻", "琪琪", "哈哈哈"];
useEffect(() => {
interfaceList.map((el: any) => {
el.permissionRestInfList.map((item: any) => {
return (item.isChecked = false);
});
return el;
});
}, []);
useEffect(() => {
window.addEventListener("scroll", onScroll, false);
return () => window.removeEventListener("scroll", onScroll);
}, []);
const onScroll = () => {
// 获取所有锚点元素
const navContents = document.querySelectorAll(".content p");
console.log('na',navContents);
// 所有锚点元素的 offsetTop
const offsetTopArr: any = [];
navContents.forEach((item: any) => {
offsetTopArr.push(item.offsetTop);
});
// 获取当前文档流的 scrollTop
const scrollTop =
document.documentElement.scrollTop || document.body.scrollTop;
console.log("scrollTop", scrollTop);
console.log("offsetTopArr", offsetTopArr);
// 定义当前点亮的导航下标
let navIndex = 0;
for (let n = 0; n < offsetTopArr.length; n++) {
// 如果 scrollTop 大于等于第n个元素的 offsetTop 则说明 n-1 的内容已经完全不可见
// 那么此时导航索引就应该是n了
if (scrollTop >= offsetTopArr[n]) {
navIndex = n;
}
if (
scrollTop + document.documentElement.clientHeight ===
document.documentElement.scrollHeight
) {
navIndex = offsetTopArr.length - 1;
}
}
console.log("navIndex", navIndex);
setActive(navIndex);
};
const scrollTo = (index: number, item: any) => {
// 获取目标的 offsetTop
// css选择器是从 1 开始计数,我们是从 0 开始,所以要 +1
setActive(index);
// const target = document.querySelector(
// `.content p:nth-child(${index + 1})`
// ) as HTMLElement;
const target = document.getElementById(item) as HTMLElement;
console.log("target", target);
const targetOffsetTop = target.offsetTop;
console.log("aa", targetOffsetTop);
// 获取当前 offsetTop
let scrollTop =
document.documentElement.scrollTop || document.body.scrollTop;
// 定义一次跳 50 个像素,数字越大跳得越快,但是会有掉帧得感觉,步子迈大了会扯到蛋
console.log("scrollTop", scrollTop);
const STEP = 50;
// 判断是往下滑还是往上滑
if (scrollTop > targetOffsetTop) {
// 往上滑
smoothUp();
} else {
// 往下滑
smoothDown();
}
// 定义往下滑函数
function smoothDown() {
// 如果当前 scrollTop 小于 targetOffsetTop 说明视口还没滑到指定位置
if (scrollTop < targetOffsetTop) {
// 如果和目标相差距离大于等于 STEP 就跳 STEP
// 否则直接跳到目标点,目标是为了防止跳过了。
if (targetOffsetTop - scrollTop >= STEP) {
scrollTop += STEP;
} else {
scrollTop = targetOffsetTop;
}
document.body.scrollTop = scrollTop;
document.documentElement.scrollTop = scrollTop;
// 关于 requestAnimationFrame 可以自己查一下,在这种场景下,相比 setInterval 性价比更高
requestAnimationFrame(smoothDown);
}
}
// 定义往上滑函数
function smoothUp() {
if (scrollTop > targetOffsetTop) {
if (scrollTop - targetOffsetTop >= STEP) {
scrollTop -= STEP;
} else {
scrollTop = targetOffsetTop;
}
document.body.scrollTop = scrollTop;
document.documentElement.scrollTop = scrollTop;
requestAnimationFrame(smoothUp);
}
}
};
//点击锚点跳转方法
const jump = (item: any, index: any) => {
setActive(index);
let doc = document.getElementById(item);
console.log("doc", doc);
doc?.scrollIntoView({
behavior: "smooth",
block: "center",
inline: "center",
});
};
return (
<>
<div style={{ display: "flex" }}>
<div
style={{
width: "300px",
margin: "24px",
position: "fixed",
top: "0",
left: "0",
zIndex: "auto",
}}
>
{catalog.map((j: string, index) => (
<div
key={index}
onClick={() => scrollTo(index, j)}
className={active === index ? "active" : ""}
// onClick={() => jump(j, index)}
>
{j}
</div>
))}
</div>
<div
style={{ width: "600px", marginLeft: "200px" }}
className="content"
>
{interfaceList.map((i: any, index1: any) => (
<div key={index1} id={i.resourceNm}>
<p>{i.resourceNm}</p>
<Table
rowSelection={{
type: "checkbox",
...rowSelection,
}}
columns={columns}
dataSource={i.permissionRestInfList}
/>
</div>
))}
</div>
</div>
</>
);
}
* {
box-sizing: border-box;
}
.active {
color: blue;
}
.content {
background-color: #fff;
width: 500px;
}