foliko 1.0.86 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/.agent/data/default.json +3 -4310
  2. package/.agent/data/plugins-state.json +34 -1
  3. package/.agent/mcp_config.json +0 -1
  4. package/.agent/memory/core.md +1 -0
  5. package/.agent/memory/project/mnn93ogy-ypjn27.md +9 -0
  6. package/.agent/memory/project/mnn98fqy-5nhc1u.md +25 -0
  7. package/.agent/memory/user/mnm67t9m-x8rekk.md +9 -0
  8. package/.agent/memory/user/mnn5mmqh-w6aktx.md +11 -0
  9. package/.agent/memory/user/mnnbfhhn-dk1bd1.md +22 -0
  10. package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
  11. package/.agent/plugins/marknative/index.js +2 -7
  12. package/.agent/plugins/poster-plugin/README.md +304 -0
  13. package/.agent/plugins/poster-plugin/fonts/PatuaOne-Regular.ttf +0 -0
  14. package/.agent/plugins/poster-plugin/fonts//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
  15. package/.agent/plugins/poster-plugin/fonts//345/276/256/350/275/257/351/233/205/351/273/221/347/262/227/344/275/223.ttf +0 -0
  16. package/.agent/plugins/poster-plugin/index.js +13 -0
  17. package/.agent/plugins/poster-plugin/package.json +28 -0
  18. package/.agent/plugins/poster-plugin/src/canvas.js +161 -0
  19. package/.agent/plugins/poster-plugin/src/components/arrow.js +84 -0
  20. package/.agent/plugins/poster-plugin/src/components/avatar.js +71 -0
  21. package/.agent/plugins/poster-plugin/src/components/badge.js +85 -0
  22. package/.agent/plugins/poster-plugin/src/components/card.js +88 -0
  23. package/.agent/plugins/poster-plugin/src/components/chart.js +127 -0
  24. package/.agent/plugins/poster-plugin/src/components/chip.js +88 -0
  25. package/.agent/plugins/poster-plugin/src/components/columns.js +107 -0
  26. package/.agent/plugins/poster-plugin/src/components/cta.js +85 -0
  27. package/.agent/plugins/poster-plugin/src/components/divider.js +55 -0
  28. package/.agent/plugins/poster-plugin/src/components/feature.js +85 -0
  29. package/.agent/plugins/poster-plugin/src/components/featureGrid.js +112 -0
  30. package/.agent/plugins/poster-plugin/src/components/grid.js +118 -0
  31. package/.agent/plugins/poster-plugin/src/components/imageFrame.js +155 -0
  32. package/.agent/plugins/poster-plugin/src/components/index.js +62 -0
  33. package/.agent/plugins/poster-plugin/src/components/listItem.js +146 -0
  34. package/.agent/plugins/poster-plugin/src/components/notification.js +123 -0
  35. package/.agent/plugins/poster-plugin/src/components/progress.js +79 -0
  36. package/.agent/plugins/poster-plugin/src/components/progressCircle.js +117 -0
  37. package/.agent/plugins/poster-plugin/src/components/quote.js +97 -0
  38. package/.agent/plugins/poster-plugin/src/components/rating.js +85 -0
  39. package/.agent/plugins/poster-plugin/src/components/star.js +70 -0
  40. package/.agent/plugins/poster-plugin/src/components/statCard.js +105 -0
  41. package/.agent/plugins/poster-plugin/src/components/stepper.js +118 -0
  42. package/.agent/plugins/poster-plugin/src/components/table.js +159 -0
  43. package/.agent/plugins/poster-plugin/src/components/tagCloud.js +78 -0
  44. package/.agent/plugins/poster-plugin/src/components/timeline.js +105 -0
  45. package/.agent/plugins/poster-plugin/src/components/watermark.js +52 -0
  46. package/.agent/plugins/poster-plugin/src/composer.js +1904 -0
  47. package/.agent/plugins/poster-plugin/src/elements/artText.js +60 -0
  48. package/.agent/plugins/poster-plugin/src/elements/background.js +52 -0
  49. package/.agent/plugins/poster-plugin/src/elements/circle.js +31 -0
  50. package/.agent/plugins/poster-plugin/src/elements/image.js +71 -0
  51. package/.agent/plugins/poster-plugin/src/elements/index.js +26 -0
  52. package/.agent/plugins/poster-plugin/src/elements/line.js +23 -0
  53. package/.agent/plugins/poster-plugin/src/elements/polygon.js +32 -0
  54. package/.agent/plugins/poster-plugin/src/elements/rectangle.js +32 -0
  55. package/.agent/plugins/poster-plugin/src/elements/svg.js +92 -0
  56. package/.agent/plugins/poster-plugin/src/elements/text.js +38 -0
  57. package/.agent/plugins/poster-plugin/src/fonts.js +118 -0
  58. package/.agent/plugins/poster-plugin/src/index.js +1659 -0
  59. package/.agent/plugins/poster-plugin/src/presets.js +36 -0
  60. package/.agent/plugins/poster-plugin/src/templates/business.js +60 -0
  61. package/.agent/plugins/poster-plugin/src/templates/gradient.js +64 -0
  62. package/.agent/plugins/poster-plugin/src/templates/index.js +43 -0
  63. package/.agent/plugins/poster-plugin/src/templates/modern.js +69 -0
  64. package/.agent/plugins/poster-plugin/src/templates/simple.js +58 -0
  65. package/.agent/plugins/poster-plugin/src/templates/social.js +62 -0
  66. package/.agent/plugins/poster-plugin/src/templates/tech.js +84 -0
  67. package/.agent/sessions/cli_default.json +24265 -0
  68. package/.agent/weixin.json +6 -0
  69. package/.claude/settings.local.json +176 -171
  70. package/CLAUDE.md +144 -108
  71. package/docs/CONTEXT_DESIGN.md +1596 -0
  72. package/examples/test-concurrent-chat.js +60 -0
  73. package/examples/test-long-chat.js +77 -0
  74. package/examples/test-session-chat.js +93 -0
  75. package/output/beef-love-poster.png +0 -0
  76. package/package.json +2 -2
  77. package/plugins/default-plugins.js +2 -1
  78. package/plugins/extension-executor-plugin.js +11 -0
  79. package/plugins/memory-plugin.js +984 -0
  80. package/plugins/session-plugin.js +78 -1
  81. package/plugins/weixin-plugin.js +24 -22
  82. package/skills/poster-guide/SKILL.md +743 -0
  83. package/skills/python-plugin-dev/SKILL.md +238 -238
  84. package/skills/skill-guide/SKILL.md +130 -108
  85. package/src/capabilities/skill-manager.js +99 -0
  86. package/src/core/agent-chat.js +627 -180
  87. package/src/core/agent-context.js +188 -0
  88. package/src/core/agent.js +9 -63
  89. package/src/core/context-manager.js +283 -0
  90. package/src/core/framework.js +264 -3
  91. package/src/core/plugin-manager.js +79 -2
  92. package/src/core/request-context.js +98 -0
  93. package/src/core/session-context.js +341 -0
  94. package/src/core/session-storage.js +274 -0
  95. package/src/executors/mcp-executor.js +2 -2
  96. package/src/utils/index.js +239 -67
  97. package/src/utils/plugin-helpers.js +17 -0
  98. package//346/265/267/346/212/245/346/217/222/344/273/266.md +621 -0
  99. package/.agent/plugins/__pycache__/test_plugin.cpython-312.pyc +0 -0
  100. package/.agent/plugins/temp-repo/LICENSE +0 -201
  101. package/.agent/plugins/temp-repo/puppeteer-plugin/README.md +0 -147
  102. package/.agent/plugins/temp-repo/puppeteer-plugin/index.js +0 -1418
  103. package/.agent/plugins/temp-repo/puppeteer-plugin/package.json +0 -9
  104. package/.agent/plugins/test_plugin.py +0 -304
@@ -0,0 +1,84 @@
1
+ /**
2
+ * 箭头组件
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建箭头组件
9
+ */
10
+ function createArrow(project, canvas, params) {
11
+ const {
12
+ x1, y1, x2, y2,
13
+ color = '#333333',
14
+ strokeWidth = 2,
15
+ headSize = 12,
16
+ style = 'solid',
17
+ direction = 'end'
18
+ } = params
19
+
20
+ const elements = []
21
+
22
+ // 创建主线
23
+ const line = new paper.Path.Line({
24
+ from: [x1, y1],
25
+ to: [x2, y2]
26
+ })
27
+ line.strokeColor = new paper.Color(color)
28
+ line.strokeWidth = strokeWidth
29
+ if (style === 'dashed') {
30
+ line.dashArray = [10, 5]
31
+ }
32
+
33
+ if (project && project.activeLayer) {
34
+ project.activeLayer.addChild(line)
35
+ }
36
+ elements.push({ type: 'line', id: line.id })
37
+
38
+ // 创建箭头头部
39
+ function createArrowHead(x, y, angle) {
40
+ const path = new paper.Path()
41
+ const angle1 = angle + Math.PI * 0.8
42
+ const angle2 = angle - Math.PI * 0.8
43
+
44
+ path.moveTo(x, y)
45
+ path.lineTo(
46
+ x + headSize * Math.cos(angle1),
47
+ y + headSize * Math.sin(angle1)
48
+ )
49
+ path.moveTo(x, y)
50
+ path.lineTo(
51
+ x + headSize * Math.cos(angle2),
52
+ y + headSize * Math.sin(angle2)
53
+ )
54
+
55
+ path.strokeColor = new paper.Color(color)
56
+ path.strokeWidth = strokeWidth
57
+ path.strokeCap = 'round'
58
+
59
+ if (project && project.activeLayer) {
60
+ project.activeLayer.addChild(path)
61
+ }
62
+ return path
63
+ }
64
+
65
+ const angle = Math.atan2(y2 - y1, x2 - x1)
66
+
67
+ if (direction === 'end' || direction === 'both') {
68
+ const head = createArrowHead(x2, y2, angle)
69
+ elements.push({ type: 'path', id: head.id })
70
+ }
71
+
72
+ if (direction === 'start' || direction === 'both') {
73
+ const head = createArrowHead(x1, y1, angle + Math.PI)
74
+ elements.push({ type: 'path', id: head.id })
75
+ }
76
+
77
+ return {
78
+ success: true,
79
+ elements,
80
+ type: 'arrow'
81
+ }
82
+ }
83
+
84
+ module.exports = createArrow
@@ -0,0 +1,71 @@
1
+ /**
2
+ * 头像组件
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建头像
9
+ *
10
+ * @param {Object} project - Paper.js 项目
11
+ * @param {Object} canvas - 画布对象
12
+ * @param {Object} args - 组件参数
13
+ * @param {number} args.x - 圆心X坐标
14
+ * @param {number} args.y - 圆心Y坐标
15
+ * @param {number} args.size - 头像大小
16
+ * @param {string} args.src - 图片路径(可选,不提供则显示首字母)
17
+ * @param {string} args.initials - 首字母(无图片时显示)
18
+ * @param {string} args.background - 背景色
19
+ * @param {string} args.border - 边框颜色
20
+ * @param {number} args.borderWidth - 边框宽度
21
+ * @param {string} args.color - 文字颜色
22
+ */
23
+ function createAvatar(project, canvas, args) {
24
+ const {
25
+ x, y,
26
+ size = 80,
27
+ src,
28
+ initials,
29
+ background = '#6366f1',
30
+ border,
31
+ borderWidth = 0,
32
+ color = '#ffffff',
33
+ } = args
34
+
35
+ const elements = []
36
+ const radius = size / 2
37
+
38
+ // 绘制圆形背景
39
+ const circle = new paper.Path.Circle({
40
+ center: [x, y],
41
+ radius: radius,
42
+ })
43
+ circle.fillColor = new paper.Color(background)
44
+
45
+ if (border) {
46
+ circle.strokeColor = new paper.Color(border)
47
+ circle.strokeWidth = borderWidth
48
+ }
49
+
50
+ elements.push({ type: 'circle', id: circle.id })
51
+
52
+ // 如果没有图片,显示首字母
53
+ if (!src && initials) {
54
+ const text = new paper.PointText({
55
+ point: [x, y + size / 6],
56
+ content: initials.charAt(0).toUpperCase(),
57
+ fontSize: size * 0.4,
58
+ fillColor: new paper.Color(color),
59
+ justification: 'center',
60
+ })
61
+ elements.push({ type: 'text', id: text.id })
62
+ }
63
+
64
+ return {
65
+ success: true,
66
+ elements,
67
+ size,
68
+ }
69
+ }
70
+
71
+ module.exports = createAvatar
@@ -0,0 +1,85 @@
1
+ /**
2
+ * 徽章/标签组件
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建徽章组件
9
+ *
10
+ * @param {Object} project - Paper.js 项目
11
+ * @param {Object} canvas - 画布对象
12
+ * @param {Object} args - 组件参数
13
+ * @param {number} args.x - X坐标(居中时使用)
14
+ * @param {number} args.y - Y坐标
15
+ * @param {string} args.text - 徽章文字
16
+ * @param {string} args.background - 背景色
17
+ * @param {string} args.color - 文字颜色
18
+ * @param {string} args.border - 边框颜色
19
+ * @param {number} args.fontSize - 字体大小
20
+ * @param {string} args.align - 对齐方式: left, center, right
21
+ * @param {number} args.padding - 内边距
22
+ * @param {number} args.radius - 圆角半径
23
+ */
24
+ function createBadge(project, canvas, args) {
25
+ const {
26
+ x, y,
27
+ text,
28
+ background = '#007bff',
29
+ color = '#ffffff',
30
+ border,
31
+ fontSize = 18,
32
+ align = 'center',
33
+ padding = 15,
34
+ radius = 4,
35
+ } = args
36
+
37
+ const elements = []
38
+
39
+ // 计算文字宽度(估算)
40
+ const textWidth = text.length * fontSize * 0.6
41
+ const badgeWidth = textWidth + padding * 2
42
+ const badgeHeight = fontSize + padding * 2
43
+
44
+ // 计算X位置
45
+ let badgeX = x
46
+ if (align === 'center') {
47
+ badgeX = x - badgeWidth / 2
48
+ } else if (align === 'right') {
49
+ badgeX = x - badgeWidth
50
+ }
51
+
52
+ // 绘制徽章背景
53
+ const badge = new paper.Path.Rectangle({
54
+ point: [badgeX, y],
55
+ size: [badgeWidth, badgeHeight],
56
+ radius: radius,
57
+ })
58
+ badge.fillColor = new paper.Color(background)
59
+
60
+ if (border) {
61
+ badge.strokeColor = new paper.Color(border)
62
+ badge.strokeWidth = 1
63
+ }
64
+
65
+ elements.push({ type: 'rectangle', id: badge.id })
66
+
67
+ // 绘制文字
68
+ const badgeText = new paper.PointText({
69
+ point: [badgeX + badgeWidth / 2, y + badgeHeight / 2 + fontSize / 3],
70
+ content: text,
71
+ fontSize: fontSize,
72
+ fillColor: new paper.Color(color),
73
+ justification: 'center',
74
+ })
75
+ elements.push({ type: 'text', id: badgeText.id })
76
+
77
+ return {
78
+ success: true,
79
+ elements,
80
+ width: badgeWidth,
81
+ height: badgeHeight,
82
+ }
83
+ }
84
+
85
+ module.exports = createBadge
@@ -0,0 +1,88 @@
1
+ /**
2
+ * 卡片组件
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建卡片组件
9
+ *
10
+ * @param {Object} project - Paper.js 项目
11
+ * @param {Object} canvas - 画布对象
12
+ * @param {Object} args - 组件参数
13
+ * @param {number} args.x - 卡片X坐标
14
+ * @param {number} args.y - 卡片Y坐标
15
+ * @param {number} args.width - 卡片宽度
16
+ * @param {number} args.height - 卡片高度
17
+ * @param {string} args.background - 背景色
18
+ * @param {string} args.border - 边框颜色
19
+ * @param {number} args.borderWidth - 边框宽度
20
+ * @param {number} args.radius - 圆角半径
21
+ * @param {string} args.title - 标题文字
22
+ * @param {number} args.titleSize - 标题字体大小
23
+ * @param {string} args.titleColor - 标题颜色
24
+ * @param {string} args.subtitle - 副标题
25
+ * @param {number} args.subtitleSize - 副标题字体大小
26
+ * @param {string} args.subtitleColor - 副标题颜色
27
+ * @param {number} args.padding - 内边距
28
+ */
29
+ function createCard(project, canvas, args) {
30
+ const {
31
+ x, y, width, height,
32
+ background, border, borderWidth, radius,
33
+ title, titleSize, titleColor,
34
+ subtitle, subtitleSize, subtitleColor,
35
+ padding = 20,
36
+ } = args
37
+
38
+ const elements = []
39
+
40
+ // 绘制卡片背景
41
+ const card = new paper.Path.Rectangle({
42
+ point: [x, y],
43
+ size: [width, height],
44
+ radius: radius || 0,
45
+ })
46
+
47
+ if (background) {
48
+ card.fillColor = new paper.Color(background)
49
+ } else {
50
+ card.fillColor = new paper.Color('#ffffff')
51
+ }
52
+
53
+ if (border) {
54
+ card.strokeColor = new paper.Color(border)
55
+ card.strokeWidth = borderWidth || 1
56
+ }
57
+
58
+ elements.push({ type: 'rectangle', id: card.id })
59
+
60
+ // 绘制标题
61
+ if (title) {
62
+ const titleText = new paper.PointText({
63
+ point: [x + padding, y + padding + (titleSize || 24)],
64
+ content: title,
65
+ fontSize: titleSize || 24,
66
+ fillColor: new paper.Color(titleColor || '#000000'),
67
+ justification: 'left',
68
+ })
69
+ elements.push({ type: 'text', id: titleText.id })
70
+ }
71
+
72
+ // 绘制副标题
73
+ if (subtitle) {
74
+ const titleHeight = title ? (titleSize || 24) + padding : padding
75
+ const subtitleText = new paper.PointText({
76
+ point: [x + padding, y + titleHeight + (subtitleSize || 16) + 10],
77
+ content: subtitle,
78
+ fontSize: subtitleSize || 16,
79
+ fillColor: new paper.Color(subtitleColor || '#666666'),
80
+ justification: 'left',
81
+ })
82
+ elements.push({ type: 'text', id: subtitleText.id })
83
+ }
84
+
85
+ return { success: true, elements }
86
+ }
87
+
88
+ module.exports = createCard
@@ -0,0 +1,127 @@
1
+ /**
2
+ * 图表组件
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建图表组件
9
+ */
10
+ function createChart(project, canvas, params) {
11
+ const {
12
+ type = 'bar',
13
+ x,
14
+ y,
15
+ width,
16
+ height,
17
+ data = [],
18
+ barColor = '#3b82f6',
19
+ showLabels = true,
20
+ showValues = true,
21
+ barGap = 4
22
+ } = params
23
+
24
+ const elements = []
25
+
26
+ if (type === 'bar' && data.length > 0) {
27
+ const maxValue = Math.max(...data.map(d => d.value))
28
+ const barCount = data.length
29
+ const totalGap = barGap * (barCount - 1)
30
+ const barWidth = (width - totalGap) / barCount
31
+ const labelHeight = showLabels ? 24 : 0
32
+ const valueHeight = showValues ? 20 : 0
33
+ const chartHeight = height - labelHeight - valueHeight - 10
34
+
35
+ data.forEach((item, index) => {
36
+ const barHeight = (item.value / maxValue) * chartHeight
37
+ const barX = x + index * (barWidth + barGap)
38
+ const barY = y + height - labelHeight - valueHeight - barHeight - 5
39
+ const color = item.color || barColor
40
+
41
+ const bar = new paper.Path.Rectangle({
42
+ point: [barX, barY],
43
+ size: [barWidth, barHeight],
44
+ radius: [4, 4, 0, 0]
45
+ })
46
+ bar.fillColor = new paper.Color(color)
47
+ if (project && project.activeLayer) {
48
+ project.activeLayer.addChild(bar)
49
+ }
50
+ elements.push({ type: 'path', id: bar.id })
51
+
52
+ if (showValues) {
53
+ const valueText = new paper.PointText({
54
+ point: [barX + barWidth / 2, barY - 8],
55
+ content: String(item.value),
56
+ fontSize: 12,
57
+ fillColor: new paper.Color('#666666'),
58
+ justification: 'center'
59
+ })
60
+ if (project && project.activeLayer) {
61
+ project.activeLayer.addChild(valueText)
62
+ }
63
+ elements.push({ type: 'text', id: valueText.id })
64
+ }
65
+
66
+ if (showLabels) {
67
+ const labelText = new paper.PointText({
68
+ point: [barX + barWidth / 2, y + height - 8],
69
+ content: item.label || '',
70
+ fontSize: 11,
71
+ fillColor: new paper.Color('#333333'),
72
+ justification: 'center'
73
+ })
74
+ if (project && project.activeLayer) {
75
+ project.activeLayer.addChild(labelText)
76
+ }
77
+ elements.push({ type: 'text', id: labelText.id })
78
+ }
79
+ })
80
+ } else if (type === 'pie' && data.length > 0) {
81
+ const cx = x + width / 2
82
+ const cy = y + height / 2
83
+ const radius = Math.min(width, height) / 2 - 10
84
+ const total = data.reduce((sum, d) => sum + d.value, 0)
85
+ let currentAngle = -90
86
+ const colors = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#ec4899', '#06b6d4', '#84cc16']
87
+
88
+ data.forEach((item, index) => {
89
+ const percentage = item.value / total
90
+ const endAngle = currentAngle + percentage * 360
91
+ const path = new paper.Path()
92
+ path.moveTo(cx, cy)
93
+ path.arc([cx, cy], radius, currentAngle * Math.PI / 180, endAngle * Math.PI / 180)
94
+ path.closePath()
95
+ path.fillColor = new paper.Color(item.color || colors[index % colors.length])
96
+ if (project && project.activeLayer) {
97
+ project.activeLayer.addChild(path)
98
+ }
99
+ elements.push({ type: 'path', id: path.id })
100
+
101
+ if (showLabels && percentage > 0.05) {
102
+ const midAngle = (currentAngle + endAngle) / 2
103
+ const midRad = midAngle * Math.PI / 180
104
+ const labelX = cx + radius * 0.7 * Math.cos(midRad)
105
+ const labelY = cy + radius * 0.7 * Math.sin(midRad)
106
+ const labelText = new paper.PointText({
107
+ point: [labelX, labelY + 4],
108
+ content: `${Math.round(percentage * 100)}%`,
109
+ fontSize: 11,
110
+ fillColor: new paper.Color('#ffffff'),
111
+ justification: 'center',
112
+ fontWeight: 'bold'
113
+ })
114
+ if (project && project.activeLayer) {
115
+ project.activeLayer.addChild(labelText)
116
+ }
117
+ elements.push({ type: 'text', id: labelText.id })
118
+ }
119
+
120
+ currentAngle = endAngle
121
+ })
122
+ }
123
+
124
+ return { success: true, elements, type: 'chart' }
125
+ }
126
+
127
+ module.exports = createChart
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Chip 标签组件
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建 Chip 标签组件
9
+ */
10
+ function createChip(project, canvas, params) {
11
+ const {
12
+ x,
13
+ y,
14
+ text,
15
+ background = '#e0e0e0',
16
+ color = '#333333',
17
+ borderColor,
18
+ fontSize = 12,
19
+ padding = 12,
20
+ radius = 16,
21
+ icon
22
+ } = params
23
+
24
+ const elements = []
25
+
26
+ // 计算尺寸
27
+ const textWidth = text.length * fontSize * 0.6
28
+ const iconWidth = icon ? fontSize : 0
29
+ const totalWidth = padding * 2 + textWidth + iconWidth + 4
30
+ const height = fontSize + padding * 2
31
+ const rectX = x - totalWidth / 2
32
+ const rectY = y - height / 2
33
+
34
+ // 绘制背景
35
+ const bg = new paper.Path.Rectangle({
36
+ point: [rectX, rectY],
37
+ size: [totalWidth, height],
38
+ radius: radius
39
+ })
40
+ bg.fillColor = new paper.Color(background)
41
+ if (borderColor) {
42
+ bg.strokeColor = new paper.Color(borderColor)
43
+ bg.strokeWidth = 1
44
+ }
45
+ if (project && project.activeLayer) {
46
+ project.activeLayer.addChild(bg)
47
+ }
48
+ elements.push({ type: 'path', id: bg.id })
49
+
50
+ // 绘制图标
51
+ if (icon) {
52
+ const iconText = new paper.PointText({
53
+ point: [rectX + padding + iconWidth / 2, y + fontSize / 3],
54
+ content: icon,
55
+ fontSize: fontSize + 2,
56
+ fillColor: new paper.Color(color),
57
+ justification: 'center'
58
+ })
59
+ if (project && project.activeLayer) {
60
+ project.activeLayer.addChild(iconText)
61
+ }
62
+ elements.push({ type: 'text', id: iconText.id })
63
+ }
64
+
65
+ // 绘制文字
66
+ const textX = icon ? rectX + padding + iconWidth + 4 + textWidth / 2 : x
67
+ const label = new paper.PointText({
68
+ point: [textX, y + fontSize / 3],
69
+ content: text,
70
+ fontSize: fontSize,
71
+ fillColor: new paper.Color(color),
72
+ justification: 'center'
73
+ })
74
+ if (project && project.activeLayer) {
75
+ project.activeLayer.addChild(label)
76
+ }
77
+ elements.push({ type: 'text', id: label.id })
78
+
79
+ return {
80
+ success: true,
81
+ elements,
82
+ width: totalWidth,
83
+ height,
84
+ type: 'chip'
85
+ }
86
+ }
87
+
88
+ module.exports = createChip
@@ -0,0 +1,107 @@
1
+ /**
2
+ * 分栏布局组件
3
+ * 支持左右分栏、三栏、四栏等多种布局
4
+ */
5
+
6
+ const createColumns = (ctx) => ({
7
+ /**
8
+ * @param {Object} params
9
+ * @param {number} params.x - 起始X坐标
10
+ * @param {number} params.y - 起始Y坐标
11
+ * @param {number} params.width - 总宽度
12
+ * @param {number} params.height - 总高度
13
+ * @param {number} [params.columns=2] - 列数
14
+ * @param {number} [params.gap=20] - 列间距
15
+ * @param {string} [params.background] - 背景色
16
+ * @param {string} [params.borderColor] - 边框颜色
17
+ * @param {number} [params.borderWidth] - 边框宽度
18
+ * @param {number} [params.radius=0] - 圆角
19
+ * @param {Array} [params.items] - 列内容配置 [{widthRatio, content}]
20
+ * @param {string} [params.direction='horizontal'] - 排列方向: horizontal, vertical
21
+ * @param {string} [params.align='top'] - 垂直对齐: top, center, bottom
22
+ */
23
+ draw({
24
+ x,
25
+ y,
26
+ width,
27
+ height,
28
+ columns = 2,
29
+ gap = 20,
30
+ background,
31
+ borderColor,
32
+ borderWidth = 1,
33
+ radius = 0,
34
+ items = [],
35
+ direction = 'horizontal',
36
+ align = 'top'
37
+ }) {
38
+ const elements = []
39
+
40
+ // 计算每列宽度
41
+ const totalGap = gap * (columns - 1)
42
+ const columnWidth = (width - totalGap) / columns
43
+
44
+ // 绘制背景
45
+ if (background) {
46
+ const bg = new ctx.Path.Rectangle({
47
+ point: [x, y],
48
+ size: [width, height],
49
+ radius: radius
50
+ })
51
+ bg.fillColor = new ctx.Color(background)
52
+ elements.push({ type: 'rectangle', id: bg.id })
53
+ }
54
+
55
+ // 绘制边框
56
+ if (borderColor && borderWidth > 0) {
57
+ const border = new ctx.Path.Rectangle({
58
+ point: [x, y],
59
+ size: [width, height],
60
+ radius: radius
61
+ })
62
+ border.fillColor = new ctx.Color('transparent')
63
+ border.strokeColor = new ctx.Color(borderColor)
64
+ border.strokeWidth = borderWidth
65
+ elements.push({ type: 'rectangle', id: border.id })
66
+ }
67
+
68
+ // 生成分割线
69
+ for (let i = 1; i < columns; i++) {
70
+ const lineX = x + columnWidth * i + gap * (i - 1) + gap / 2
71
+ const line = new ctx.Path.Line({
72
+ from: [lineX, y + 20],
73
+ to: [lineX, y + height - 20]
74
+ })
75
+ line.strokeColor = new ctx.Color('#e0e0e0')
76
+ line.strokeWidth = 1
77
+ elements.push({ type: 'line', id: line.id })
78
+ }
79
+
80
+ // 返回列位置信息
81
+ const columnPositions = []
82
+ for (let i = 0; i < columns; i++) {
83
+ const colX = x + (columnWidth + gap) * i
84
+ const colY = align === 'center' ? y + (height - height) / 2 : align === 'bottom' ? y + height - height : y
85
+
86
+ columnPositions.push({
87
+ index: i,
88
+ x: colX,
89
+ y: colY,
90
+ width: columnWidth,
91
+ height: height
92
+ })
93
+ }
94
+
95
+ return {
96
+ success: true,
97
+ elements,
98
+ columnPositions,
99
+ columnWidth,
100
+ totalWidth: width,
101
+ totalHeight: height,
102
+ type: 'columns'
103
+ }
104
+ }
105
+ })
106
+
107
+ module.exports = createColumns