Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Five-菜鸟级
TypeScript
提交
21a46a3d
T
TypeScript
项目概览
Five-菜鸟级
/
TypeScript
与 Fork 源项目一致
Fork自
inscode / TypeScript
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
TypeScript
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
21a46a3d
编写于
10月 29, 2025
作者:
Q
qq_41923622
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
2025-10-29 14:00:00 inscode
上级
b8232db6
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
275 addition
and
3 deletion
+275
-3
index.ts
index.ts
+275
-3
未找到文件。
index.ts
浏览文件 @
21a46a3d
const
s
:
string
=
"
欢迎来到 InsCode
"
;
/**
console
.
log
(
s
);
* 内容块类型定义(最小不可拆分单元,如段落、图片、表格等)
tsx
函数式
返回类型
JSX
.
Element
*/
interface
ContentBlock
{
id
:
string
;
// 内容块唯一标识
type
:
'
paragraph
'
|
'
image
'
|
'
table
'
;
// 内容块类型
height
:
number
;
// 内容块渲染高度(px)
content
:
string
;
// 内容块实际内容(简化示例)
}
/**
* 区域(Region)类型定义(管理连续的1-2页内容)
*/
interface
Region
{
id
:
string
;
// 区域唯一标识
startPage
:
number
;
// 起始页号
endPage
:
number
;
// 结束页号(startPage <= endPage <= startPage + 1)
contentBlocks
:
ContentBlock
[];
// 包含的内容块
totalHeight
:
number
;
// 区域内所有内容块总高度(px)
prevRegionId
?:
string
;
// 上一个区域ID(形成链表)
nextRegionId
?:
string
;
// 下一个区域ID
}
/**
* 区域管理器(核心控制器,处理区域拆分、合并、页号更新等逻辑)
*/
class
RegionManager
{
private
regions
:
Map
<
string
,
Region
>
;
// 存储所有区域(ID -> 区域)
private
pageHeight
:
number
;
// 单页高度(px,如A4约842px)
private
maxPagesPerRegion
:
number
=
2
;
// 每个区域最多包含的页数
constructor
(
pageHeight
:
number
=
842
)
{
this
.
regions
=
new
Map
();
this
.
pageHeight
=
pageHeight
;
}
/**
* 创建初始区域(文档首次加载时调用)
* @param initialBlocks 初始内容块列表
*/
createInitialRegions
(
initialBlocks
:
ContentBlock
[]):
void
{
let
currentRegion
:
Region
=
this
.
createEmptyRegion
(
1
);
// 从第1页开始
let
currentTotalHeight
=
0
;
for
(
const
block
of
initialBlocks
)
{
currentTotalHeight
+=
block
.
height
;
currentRegion
.
contentBlocks
.
push
(
block
);
currentRegion
.
totalHeight
=
currentTotalHeight
;
// 若当前区域总高度超过最大容量(maxPagesPerRegion页),拆分区域
if
(
currentTotalHeight
>
this
.
pageHeight
*
this
.
maxPagesPerRegion
)
{
const
newRegion
=
this
.
splitRegion
(
currentRegion
);
this
.
regions
.
set
(
currentRegion
.
id
,
currentRegion
);
currentRegion
=
newRegion
;
currentTotalHeight
=
currentRegion
.
totalHeight
;
// 重置为新区域的初始高度
}
}
// 添加最后一个区域
this
.
regions
.
set
(
currentRegion
.
id
,
currentRegion
);
}
/**
* 向指定区域添加内容块(模拟编辑操作)
* @param regionId 目标区域ID
* @param block 要添加的内容块
*/
addBlockToRegion
(
regionId
:
string
,
block
:
ContentBlock
):
void
{
const
region
=
this
.
regions
.
get
(
regionId
);
if
(
!
region
)
throw
new
Error
(
`Region
${
regionId
}
not found`
);
// 添加内容块并更新区域总高度
region
.
contentBlocks
.
push
(
block
);
region
.
totalHeight
+=
block
.
height
;
// 检查是否溢出,若溢出则拆分
if
(
region
.
totalHeight
>
this
.
pageHeight
*
this
.
maxPagesPerRegion
)
{
const
newRegion
=
this
.
splitRegion
(
region
);
this
.
regions
.
set
(
region
.
id
,
region
);
// 更新原区域
this
.
regions
.
set
(
newRegion
.
id
,
newRegion
);
// 添加新区域
this
.
updateSubsequentRegions
(
newRegion
);
// 更新后续区域页号
}
else
{
this
.
regions
.
set
(
regionId
,
region
);
// 未溢出,直接更新
}
}
/**
* 拆分溢出的区域
* @param overflowRegion 溢出的区域
* @returns 拆分后生成的新区域
*/
private
splitRegion
(
overflowRegion
:
Region
):
Region
{
// 1. 计算拆分点:找到第一个使累计高度 >= 单页高度的内容块
let
accumulatedHeight
=
0
;
let
splitIndex
=
-
1
;
for
(
let
i
=
0
;
i
<
overflowRegion
.
contentBlocks
.
length
;
i
++
)
{
const
block
=
overflowRegion
.
contentBlocks
[
i
];
accumulatedHeight
+=
block
.
height
;
if
(
accumulatedHeight
>=
this
.
pageHeight
)
{
splitIndex
=
i
;
break
;
}
}
if
(
splitIndex
===
-
1
)
{
// 特殊情况:所有内容块总高度 < 单页高度(理论上不会触发,因已判断溢出)
splitIndex
=
overflowRegion
.
contentBlocks
.
length
-
1
;
}
// 2. 拆分内容块(前半部分保留在原区域,后半部分移到新区域)
const
[
originalBlocks
,
newBlocks
]
=
[
overflowRegion
.
contentBlocks
.
slice
(
0
,
splitIndex
+
1
),
overflowRegion
.
contentBlocks
.
slice
(
splitIndex
+
1
),
];
// 3. 更新原区域
const
originalHeight
=
originalBlocks
.
reduce
((
sum
,
b
)
=>
sum
+
b
.
height
,
0
);
overflowRegion
.
contentBlocks
=
originalBlocks
;
overflowRegion
.
totalHeight
=
originalHeight
;
overflowRegion
.
endPage
=
overflowRegion
.
startPage
;
// 原区域缩减为1页
// 4. 创建新区域(承接原区域的后续内容)
const
newRegionId
=
`region-
${
Date
.
now
()}
-
${
Math
.
random
().
toString
(
36
).
slice
(
2
,
8
)}
`
;
const
newRegion
:
Region
=
{
id
:
newRegionId
,
startPage
:
overflowRegion
.
startPage
+
1
,
// 新区域起始页为原区域起始页+1
endPage
:
overflowRegion
.
startPage
+
1
,
// 初始为1页,后续可能扩展
contentBlocks
:
newBlocks
,
totalHeight
:
newBlocks
.
reduce
((
sum
,
b
)
=>
sum
+
b
.
height
,
0
),
prevRegionId
:
overflowRegion
.
id
,
nextRegionId
:
overflowRegion
.
nextRegionId
,
// 继承原区域的下一个区域
};
// 5. 更新原区域的下一个区域关联
if
(
overflowRegion
.
nextRegionId
)
{
const
nextRegion
=
this
.
regions
.
get
(
overflowRegion
.
nextRegionId
);
if
(
nextRegion
)
{
nextRegion
.
prevRegionId
=
newRegionId
;
this
.
regions
.
set
(
nextRegion
.
id
,
nextRegion
);
}
}
overflowRegion
.
nextRegionId
=
newRegionId
;
return
newRegion
;
}
/**
* 更新后续区域的页号(因拆分导致页码偏移时调用)
* @param newRegion 新生成的区域
*/
private
updateSubsequentRegions
(
newRegion
:
Region
):
void
{
let
currentRegionId
=
newRegion
.
nextRegionId
;
const
pageOffset
=
newRegion
.
endPage
-
newRegion
.
startPage
+
1
;
// 新区域占用的页数
while
(
currentRegionId
)
{
const
region
=
this
.
regions
.
get
(
currentRegionId
);
if
(
!
region
)
break
;
// 后续区域的页号整体后移
region
.
startPage
+=
pageOffset
;
region
.
endPage
+=
pageOffset
;
currentRegionId
=
region
.
nextRegionId
;
// 继续处理下一个区域
this
.
regions
.
set
(
region
.
id
,
region
);
}
}
/**
* 尝试合并相邻区域(当内容减少时)
* @param regionId 目标区域ID
*/
tryMergeRegions
(
regionId
:
string
):
void
{
const
currentRegion
=
this
.
regions
.
get
(
regionId
);
if
(
!
currentRegion
)
return
;
// 检查下一个区域是否可合并
if
(
currentRegion
.
nextRegionId
)
{
const
nextRegion
=
this
.
regions
.
get
(
currentRegion
.
nextRegionId
);
if
(
nextRegion
)
{
const
totalHeight
=
currentRegion
.
totalHeight
+
nextRegion
.
totalHeight
;
// 若合并后总高度 <= 最大容量(2页),则合并
if
(
totalHeight
<=
this
.
pageHeight
*
this
.
maxPagesPerRegion
)
{
this
.
mergeRegions
(
currentRegion
.
id
,
nextRegion
.
id
);
}
}
}
}
/**
* 合并两个相邻区域
* @param regionAId 前一个区域ID
* @param regionBId 后一个区域ID(必须是regionA的nextRegion)
*/
private
mergeRegions
(
regionAId
:
string
,
regionBId
:
string
):
void
{
const
regionA
=
this
.
regions
.
get
(
regionAId
);
const
regionB
=
this
.
regions
.
get
(
regionBId
);
if
(
!
regionA
||
!
regionB
||
regionA
.
nextRegionId
!==
regionBId
)
return
;
// 1. 合并内容块和高度
regionA
.
contentBlocks
=
[...
regionA
.
contentBlocks
,
...
regionB
.
contentBlocks
];
regionA
.
totalHeight
=
regionA
.
totalHeight
+
regionB
.
totalHeight
;
regionA
.
endPage
=
regionB
.
endPage
;
// 结束页更新为regionB的结束页
regionA
.
nextRegionId
=
regionB
.
nextRegionId
;
// 继承regionB的下一个区域
// 2. 更新原regionB的下一个区域关联
if
(
regionB
.
nextRegionId
)
{
const
nextRegion
=
this
.
regions
.
get
(
regionB
.
nextRegionId
);
if
(
nextRegion
)
{
nextRegion
.
prevRegionId
=
regionAId
;
this
.
regions
.
set
(
nextRegion
.
id
,
nextRegion
);
}
}
// 3. 删除regionB
this
.
regions
.
delete
(
regionBId
);
this
.
regions
.
set
(
regionAId
,
regionA
);
}
/**
* 创建空区域
* @param startPage 起始页号
* @returns 空区域实例
*/
private
createEmptyRegion
(
startPage
:
number
):
Region
{
return
{
id
:
`region-
${
Date
.
now
()}
-
${
Math
.
random
().
toString
(
36
).
slice
(
2
,
8
)}
`
,
startPage
,
endPage
:
startPage
,
// 初始为1页
contentBlocks
:
[],
totalHeight
:
0
,
};
}
/**
* 获取所有区域信息(用于调试/展示)
*/
getRegions
():
Region
[]
{
return
Array
.
from
(
this
.
regions
.
values
());
}
}
// ------------------------------
// 示例使用
// ------------------------------
function
demo
()
{
// 1. 初始化区域管理器(单页高度设为800px)
const
manager
=
new
RegionManager
(
800
);
// 2. 创建初始内容块(模拟一篇长文档,包含多个段落)
const
initialBlocks
:
ContentBlock
[]
=
[
{
id
:
'
b1
'
,
type
:
'
paragraph
'
,
height
:
300
,
content
:
'
第一段内容...
'
},
{
id
:
'
b2
'
,
type
:
'
paragraph
'
,
height
:
400
,
content
:
'
第二段内容...
'
},
{
id
:
'
b3
'
,
type
:
'
paragraph
'
,
height
:
500
,
content
:
'
第三段内容...
'
},
{
id
:
'
b4
'
,
type
:
'
paragraph
'
,
height
:
300
,
content
:
'
第四段内容...
'
},
];
// 3. 创建初始区域
manager
.
createInitialRegions
(
initialBlocks
);
console
.
log
(
'
初始区域状态:
'
,
manager
.
getRegions
());
// 4. 向第一个区域添加内容块(触发拆分)
const
firstRegionId
=
manager
.
getRegions
()[
0
].
id
;
manager
.
addBlockToRegion
(
firstRegionId
,
{
id
:
'
b5
'
,
type
:
'
image
'
,
height
:
700
,
content
:
'
一张大图...
'
});
console
.
log
(
'
添加内容块后的区域状态:
'
,
manager
.
getRegions
());
// 5. 尝试合并区域(模拟删除内容后触发)
manager
.
tryMergeRegions
(
firstRegionId
);
console
.
log
(
'
尝试合并后的区域状态:
'
,
manager
.
getRegions
());
}
// 执行示例
demo
();
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录