foliko 1.0.87 → 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 -108
  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/poster-plugin/README.md +304 -0
  12. package/.agent/plugins/poster-plugin/fonts/PatuaOne-Regular.ttf +0 -0
  13. package/.agent/plugins/poster-plugin/fonts//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
  14. 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
  15. package/.agent/plugins/poster-plugin/index.js +13 -0
  16. package/.agent/plugins/poster-plugin/package.json +28 -0
  17. package/.agent/plugins/poster-plugin/src/canvas.js +161 -0
  18. package/.agent/plugins/poster-plugin/src/components/arrow.js +84 -0
  19. package/.agent/plugins/poster-plugin/src/components/avatar.js +71 -0
  20. package/.agent/plugins/poster-plugin/src/components/badge.js +85 -0
  21. package/.agent/plugins/poster-plugin/src/components/card.js +88 -0
  22. package/.agent/plugins/poster-plugin/src/components/chart.js +127 -0
  23. package/.agent/plugins/poster-plugin/src/components/chip.js +88 -0
  24. package/.agent/plugins/poster-plugin/src/components/columns.js +107 -0
  25. package/.agent/plugins/poster-plugin/src/components/cta.js +85 -0
  26. package/.agent/plugins/poster-plugin/src/components/divider.js +55 -0
  27. package/.agent/plugins/poster-plugin/src/components/feature.js +85 -0
  28. package/.agent/plugins/poster-plugin/src/components/featureGrid.js +112 -0
  29. package/.agent/plugins/poster-plugin/src/components/grid.js +118 -0
  30. package/.agent/plugins/poster-plugin/src/components/imageFrame.js +155 -0
  31. package/.agent/plugins/poster-plugin/src/components/index.js +62 -0
  32. package/.agent/plugins/poster-plugin/src/components/listItem.js +146 -0
  33. package/.agent/plugins/poster-plugin/src/components/notification.js +123 -0
  34. package/.agent/plugins/poster-plugin/src/components/progress.js +79 -0
  35. package/.agent/plugins/poster-plugin/src/components/progressCircle.js +117 -0
  36. package/.agent/plugins/poster-plugin/src/components/quote.js +97 -0
  37. package/.agent/plugins/poster-plugin/src/components/rating.js +85 -0
  38. package/.agent/plugins/poster-plugin/src/components/star.js +70 -0
  39. package/.agent/plugins/poster-plugin/src/components/statCard.js +105 -0
  40. package/.agent/plugins/poster-plugin/src/components/stepper.js +118 -0
  41. package/.agent/plugins/poster-plugin/src/components/table.js +159 -0
  42. package/.agent/plugins/poster-plugin/src/components/tagCloud.js +78 -0
  43. package/.agent/plugins/poster-plugin/src/components/timeline.js +105 -0
  44. package/.agent/plugins/poster-plugin/src/components/watermark.js +52 -0
  45. package/.agent/plugins/poster-plugin/src/composer.js +1904 -0
  46. package/.agent/plugins/poster-plugin/src/elements/artText.js +60 -0
  47. package/.agent/plugins/poster-plugin/src/elements/background.js +52 -0
  48. package/.agent/plugins/poster-plugin/src/elements/circle.js +31 -0
  49. package/.agent/plugins/poster-plugin/src/elements/image.js +71 -0
  50. package/.agent/plugins/poster-plugin/src/elements/index.js +26 -0
  51. package/.agent/plugins/poster-plugin/src/elements/line.js +23 -0
  52. package/.agent/plugins/poster-plugin/src/elements/polygon.js +32 -0
  53. package/.agent/plugins/poster-plugin/src/elements/rectangle.js +32 -0
  54. package/.agent/plugins/poster-plugin/src/elements/svg.js +92 -0
  55. package/.agent/plugins/poster-plugin/src/elements/text.js +38 -0
  56. package/.agent/plugins/poster-plugin/src/fonts.js +118 -0
  57. package/.agent/plugins/poster-plugin/src/index.js +1659 -0
  58. package/.agent/plugins/poster-plugin/src/presets.js +36 -0
  59. package/.agent/plugins/poster-plugin/src/templates/business.js +60 -0
  60. package/.agent/plugins/poster-plugin/src/templates/gradient.js +64 -0
  61. package/.agent/plugins/poster-plugin/src/templates/index.js +43 -0
  62. package/.agent/plugins/poster-plugin/src/templates/modern.js +69 -0
  63. package/.agent/plugins/poster-plugin/src/templates/simple.js +58 -0
  64. package/.agent/plugins/poster-plugin/src/templates/social.js +62 -0
  65. package/.agent/plugins/poster-plugin/src/templates/tech.js +84 -0
  66. package/.agent/sessions/cli_default.json +24265 -0
  67. package/.agent/weixin.json +6 -0
  68. package/.claude/settings.local.json +5 -8
  69. package/CLAUDE.md +144 -108
  70. package/docs/CONTEXT_DESIGN.md +1596 -0
  71. package/examples/test-concurrent-chat.js +60 -60
  72. package/output/beef-love-poster.png +0 -0
  73. package/package.json +2 -2
  74. package/plugins/default-plugins.js +2 -1
  75. package/plugins/extension-executor-plugin.js +11 -0
  76. package/plugins/memory-plugin.js +984 -0
  77. package/plugins/session-plugin.js +57 -1
  78. package/plugins/weixin-plugin.js +24 -22
  79. package/skills/poster-guide/SKILL.md +743 -0
  80. package/skills/python-plugin-dev/SKILL.md +238 -238
  81. package/skills/skill-guide/SKILL.md +130 -108
  82. package/src/capabilities/skill-manager.js +99 -0
  83. package/src/core/agent-chat.js +538 -138
  84. package/src/core/agent-context.js +188 -0
  85. package/src/core/agent.js +6 -2
  86. package/src/core/context-manager.js +283 -0
  87. package/src/core/framework.js +264 -3
  88. package/src/core/plugin-manager.js +79 -2
  89. package/src/core/request-context.js +98 -0
  90. package/src/core/session-context.js +341 -0
  91. package/src/core/session-storage.js +274 -0
  92. package/src/executors/mcp-executor.js +2 -2
  93. package/src/utils/index.js +239 -67
  94. package/src/utils/plugin-helpers.js +17 -0
  95. package//346/265/267/346/212/245/346/217/222/344/273/266.md +621 -0
  96. package/.agent/plugins/__pycache__/test_plugin.cpython-312.pyc +0 -0
  97. package/.agent/plugins/temp-repo/LICENSE +0 -201
  98. package/.agent/plugins/temp-repo/puppeteer-plugin/README.md +0 -147
  99. package/.agent/plugins/temp-repo/puppeteer-plugin/index.js +0 -1418
  100. package/.agent/plugins/temp-repo/puppeteer-plugin/package.json +0 -9
  101. package/.agent/plugins/test_plugin.py +0 -304
  102. package/examples/test-chat-debug.js +0 -102
  103. package/examples/test-chat-result.js +0 -76
  104. package/examples/test-chat-stream-diff.js +0 -63
@@ -0,0 +1,97 @@
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 {string} args.text - 引用文字
17
+ * @param {string} args.author - 作者
18
+ * @param {string} args.background - 背景色
19
+ * @param {string} args.borderColor - 左边框颜色
20
+ * @param {number} args.borderWidth - 左边框宽度
21
+ * @param {number} args.padding - 内边距
22
+ * @param {number} args.radius - 圆角半径
23
+ * @param {string} args.textColor - 文字颜色
24
+ * @param {string} args.authorColor - 作者颜色
25
+ * @param {number} args.fontSize - 字体大小
26
+ */
27
+ function createQuote(project, canvas, args) {
28
+ const {
29
+ x, y,
30
+ width = 400,
31
+ text,
32
+ author,
33
+ background = '#f8fafc',
34
+ borderColor = '#6366f1',
35
+ borderWidth = 4,
36
+ padding = 20,
37
+ radius = 8,
38
+ textColor = '#1e293b',
39
+ authorColor = '#64748b',
40
+ fontSize = 18,
41
+ } = args
42
+
43
+ const elements = []
44
+
45
+ // 绘制背景
46
+ const bg = new paper.Path.Rectangle({
47
+ point: [x, y],
48
+ size: [width, author ? 80 + fontSize * 2 : 40 + fontSize * 1.5],
49
+ radius: radius,
50
+ })
51
+ bg.fillColor = new paper.Color(background)
52
+ elements.push({ type: 'rectangle', id: bg.id })
53
+
54
+ // 绘制左边框
55
+ const border = new paper.Path.Rectangle({
56
+ point: [x, y],
57
+ size: [borderWidth, author ? 80 + fontSize * 2 : 40 + fontSize * 1.5],
58
+ })
59
+ border.fillColor = new paper.Color(borderColor)
60
+ elements.push({ type: 'rectangle', id: border.id })
61
+
62
+ // 绘制引用符号
63
+ const quoteMark = new paper.PointText({
64
+ point: [x + padding + 10, y + padding + fontSize],
65
+ content: '"',
66
+ fontSize: fontSize * 2,
67
+ fillColor: new paper.Color(borderColor),
68
+ justification: 'left',
69
+ })
70
+ elements.push({ type: 'text', id: quoteMark.id })
71
+
72
+ // 绘制引用文字
73
+ const quoteText = new paper.PointText({
74
+ point: [x + padding + 30, y + padding + fontSize * 1.5],
75
+ content: text,
76
+ fontSize: fontSize,
77
+ fillColor: new paper.Color(textColor),
78
+ justification: 'left',
79
+ })
80
+ elements.push({ type: 'text', id: quoteText.id })
81
+
82
+ // 绘制作者
83
+ if (author) {
84
+ const authorText = new paper.PointText({
85
+ point: [x + padding, y + padding + fontSize * 2.5 + 10],
86
+ content: `— ${author}`,
87
+ fontSize: fontSize * 0.8,
88
+ fillColor: new paper.Color(authorColor),
89
+ justification: 'left',
90
+ })
91
+ elements.push({ type: 'text', id: authorText.id })
92
+ }
93
+
94
+ return { success: true, elements }
95
+ }
96
+
97
+ module.exports = createQuote
@@ -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 {number} args.value - 评分值 0-5
16
+ * @param {number} args.max - 最大值,默认5
17
+ * @param {number} args.size - 星星大小
18
+ * @param {string} args.filledColor - 填充颜色
19
+ * @param {string} args.emptyColor - 空心颜色
20
+ * @param {number} args.gap - 星星间距
21
+ */
22
+ function createRating(project, canvas, args) {
23
+ const {
24
+ x, y,
25
+ value = 4,
26
+ max = 5,
27
+ size = 24,
28
+ filledColor = '#fbbf24',
29
+ emptyColor = '#e5e7eb',
30
+ gap = 4,
31
+ } = args
32
+
33
+ const elements = []
34
+
35
+ for (let i = 0; i < max; i++) {
36
+ const starX = x + i * (size + gap)
37
+ const filled = i < Math.floor(value)
38
+ const partial = !filled && i < value
39
+
40
+ // 绘制星星(使用多边形)
41
+ const star = createStar(project, starX + size / 2, y + size / 2, size / 2, size / 4, 5)
42
+ star.fillColor = new paper.Color(partial ? filledColor : emptyColor)
43
+ star.opacity = partial ? value - Math.floor(value) : 1
44
+ elements.push({ type: 'polygon', id: star.id })
45
+
46
+ if (partial) {
47
+ // 半星效果用填充色覆盖一半
48
+ const halfStar = createStar(project, starX + size / 2, y + size / 2, size / 2, size / 4, 5)
49
+ const clipPath = new paper.Path.Rectangle({
50
+ point: [starX, y],
51
+ size: [size / 2, size],
52
+ })
53
+ halfStar.fillColor = new paper.Color(filledColor)
54
+ halfStar.opacity = 1
55
+ elements.push({ type: 'polygon', id: halfStar.id })
56
+ }
57
+ }
58
+
59
+ return {
60
+ success: true,
61
+ elements,
62
+ value,
63
+ }
64
+ }
65
+
66
+ /**
67
+ * 创建星星形状
68
+ */
69
+ function createStar(project, cx, cy, outerRadius, innerRadius, points) {
70
+ const star = new paper.Path()
71
+ const step = Math.PI / points
72
+
73
+ for (let i = 0; i < 2 * points; i++) {
74
+ const radius = i % 2 === 0 ? outerRadius : innerRadius
75
+ const angle = i * step - Math.PI / 2
76
+ const x = cx + Math.cos(angle) * radius
77
+ const y = cy + Math.sin(angle) * radius
78
+ star.add(new paper.Point(x, y))
79
+ }
80
+
81
+ star.closed = true
82
+ return star
83
+ }
84
+
85
+ module.exports = createRating
@@ -0,0 +1,70 @@
1
+ /**
2
+ * 星形组件 - 支持多角星形
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建星形组件
9
+ * @param {Object} project - Paper.js 项目
10
+ * @param {Object} canvas - 画布对象
11
+ * @param {Object} params - 组件参数
12
+ */
13
+ function createStar(project, canvas, params) {
14
+ const {
15
+ cx,
16
+ cy,
17
+ points = 5,
18
+ innerRadius: providedInnerRadius,
19
+ outerRadius,
20
+ fill,
21
+ stroke,
22
+ strokeWidth = 1,
23
+ opacity = 1,
24
+ rotation = 0
25
+ } = params
26
+
27
+ // 计算内半径
28
+ const innerRadius = providedInnerRadius || outerRadius * 0.4
29
+
30
+ // 创建星形路径
31
+ const path = new paper.Path()
32
+ const angleStep = Math.PI / points
33
+
34
+ for (let i = 0; i < points * 2; i++) {
35
+ const radius = i % 2 === 0 ? outerRadius : innerRadius
36
+ const angle = i * angleStep - Math.PI / 2 + (rotation * Math.PI / 180)
37
+ const x = cx + radius * Math.cos(angle)
38
+ const y = cy + radius * Math.sin(angle)
39
+
40
+ if (i === 0) {
41
+ path.moveTo(x, y)
42
+ } else {
43
+ path.lineTo(x, y)
44
+ }
45
+ }
46
+ path.closePath()
47
+
48
+ // 设置样式
49
+ if (fill) {
50
+ path.fillColor = new paper.Color(fill)
51
+ }
52
+ if (stroke) {
53
+ path.strokeColor = new paper.Color(stroke)
54
+ path.strokeWidth = strokeWidth
55
+ }
56
+ path.opacity = opacity
57
+
58
+ // 关键:将元素添加到活动层
59
+ if (project && project.activeLayer) {
60
+ project.activeLayer.addChild(path)
61
+ }
62
+
63
+ return {
64
+ success: true,
65
+ elements: [{ type: 'path', id: path.id }],
66
+ type: 'star'
67
+ }
68
+ }
69
+
70
+ module.exports = createStar
@@ -0,0 +1,105 @@
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.label - 标签
18
+ * @param {string} args.value - 数值
19
+ * @param {string} args.change - 变化值(如 "+12.5%")
20
+ * @param {boolean} args.positive - 变化是否为正
21
+ * @param {string} args.icon - 图标
22
+ * @param {string} args.iconColor - 图标颜色
23
+ * @param {string} args.background - 背景色
24
+ * @param {string} args.border - 边框颜色
25
+ * @param {number} args.radius - 圆角半径
26
+ */
27
+ function createStatCard(project, canvas, args) {
28
+ const {
29
+ x, y,
30
+ width = 200,
31
+ height = 120,
32
+ label = 'Total Users',
33
+ value = '10,000',
34
+ change,
35
+ positive = true,
36
+ icon,
37
+ iconColor = '#6366f1',
38
+ background = '#ffffff',
39
+ border = '#e5e7eb',
40
+ radius = 12,
41
+ } = args
42
+
43
+ const elements = []
44
+
45
+ // 绘制背景
46
+ const bg = new paper.Path.Rectangle({
47
+ point: [x, y],
48
+ size: [width, height],
49
+ radius: radius,
50
+ })
51
+ bg.fillColor = new paper.Color(background)
52
+ bg.strokeColor = new paper.Color(border)
53
+ bg.strokeWidth = 1
54
+ elements.push({ type: 'rectangle', id: bg.id })
55
+
56
+ // 绘制图标
57
+ if (icon) {
58
+ const iconText = new paper.PointText({
59
+ point: [x + 20, y + 35],
60
+ content: icon,
61
+ fontSize: 24,
62
+ fillColor: new paper.Color(iconColor),
63
+ justification: 'left',
64
+ })
65
+ elements.push({ type: 'text', id: iconText.id })
66
+ }
67
+
68
+ // 绘制标签
69
+ const labelText = new paper.PointText({
70
+ point: [x + 20, y + 50 + (icon ? 10 : 0)],
71
+ content: label,
72
+ fontSize: 14,
73
+ fillColor: new paper.Color('#64748b'),
74
+ justification: 'left',
75
+ })
76
+ elements.push({ type: 'text', id: labelText.id })
77
+
78
+ // 绘制数值
79
+ const valueText = new paper.PointText({
80
+ point: [x + 20, y + 75 + (icon ? 10 : 0)],
81
+ content: value,
82
+ fontSize: 28,
83
+ fillColor: new paper.Color('#1e293b'),
84
+ justification: 'left',
85
+ })
86
+ elements.push({ type: 'text', id: valueText.id })
87
+
88
+ // 绘制变化值
89
+ if (change) {
90
+ const changeColor = positive ? '#22c55e' : '#ef4444'
91
+ const changeIcon = positive ? '↑' : '↓'
92
+ const changeText = new paper.PointText({
93
+ point: [x + 20, y + 95 + (icon ? 10 : 0)],
94
+ content: `${changeIcon} ${change}`,
95
+ fontSize: 14,
96
+ fillColor: new paper.Color(changeColor),
97
+ justification: 'left',
98
+ })
99
+ elements.push({ type: 'text', id: changeText.id })
100
+ }
101
+
102
+ return { success: true, elements }
103
+ }
104
+
105
+ module.exports = createStatCard
@@ -0,0 +1,118 @@
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 {Array} args.steps - 步骤数组 [{title, description}]
17
+ * @param {number} args.currentStep - 当前步骤(从0开始)
18
+ * @param {string} args.activeColor - 激活颜色
19
+ * @param {string} args.inactiveColor - 未激活颜色
20
+ * @param {string} args.completedColor - 已完成颜色
21
+ * @param {number} args.circleSize - 圆圈大小
22
+ */
23
+ function createStepper(project, canvas, args) {
24
+ const {
25
+ x, y,
26
+ width = 600,
27
+ steps = [],
28
+ currentStep = 0,
29
+ activeColor = '#6366f1',
30
+ inactiveColor = '#e5e7eb',
31
+ completedColor = '#22c55e',
32
+ circleSize = 40,
33
+ } = args
34
+
35
+ const elements = []
36
+ const stepWidth = steps.length > 1 ? width / (steps.length - 1) : width
37
+ const lineY = y + circleSize / 2
38
+
39
+ // 绘制连接线
40
+ if (steps.length > 1) {
41
+ const line = new paper.Path.Line({
42
+ from: [x + circleSize / 2, lineY],
43
+ to: [x + width - circleSize / 2, lineY],
44
+ strokeColor: new paper.Color(inactiveColor),
45
+ strokeWidth: 2,
46
+ })
47
+ elements.push({ type: 'line', id: line.id })
48
+
49
+ // 绘制已完成部分的覆盖线
50
+ if (currentStep > 0) {
51
+ const completedLine = new paper.Path.Line({
52
+ from: [x + circleSize / 2, lineY],
53
+ to: [x + circleSize / 2 + (currentStep) * stepWidth, lineY],
54
+ strokeColor: new paper.Color(completedColor),
55
+ strokeWidth: 2,
56
+ })
57
+ elements.push({ type: 'line', id: completedLine.id })
58
+ }
59
+ }
60
+
61
+ // 绘制每个步骤
62
+ for (let i = 0; i < steps.length; i++) {
63
+ const stepX = steps.length > 1 ? x + i * stepWidth : x
64
+ const step = steps[i]
65
+ let color = inactiveColor
66
+
67
+ if (i < currentStep) {
68
+ color = completedColor
69
+ } else if (i === currentStep) {
70
+ color = activeColor
71
+ }
72
+
73
+ // 绘制圆圈
74
+ const circle = new paper.Path.Circle({
75
+ center: [stepX + circleSize / 2, lineY],
76
+ radius: circleSize / 2,
77
+ })
78
+ circle.fillColor = new paper.Color(color)
79
+ elements.push({ type: 'circle', id: circle.id })
80
+
81
+ // 绘制步骤编号或勾选
82
+ const icon = i < currentStep ? '✓' : String(i + 1)
83
+ const iconText = new paper.PointText({
84
+ point: [stepX + circleSize / 2, lineY + circleSize / 6],
85
+ content: icon,
86
+ fontSize: 16,
87
+ fillColor: new paper.Color('#ffffff'),
88
+ justification: 'center',
89
+ })
90
+ elements.push({ type: 'text', id: iconText.id })
91
+
92
+ // 绘制标题
93
+ const titleText = new paper.PointText({
94
+ point: [stepX + circleSize / 2, y + circleSize + 20],
95
+ content: step.title || `Step ${i + 1}`,
96
+ fontSize: 14,
97
+ fillColor: new paper.Color(i <= currentStep ? '#1e293b' : '#94a3b8'),
98
+ justification: 'center',
99
+ })
100
+ elements.push({ type: 'text', id: titleText.id })
101
+
102
+ // 绘制描述
103
+ if (step.description) {
104
+ const descText = new paper.PointText({
105
+ point: [stepX + circleSize / 2, y + circleSize + 38],
106
+ content: step.description,
107
+ fontSize: 11,
108
+ fillColor: new paper.Color('#94a3b8'),
109
+ justification: 'center',
110
+ })
111
+ elements.push({ type: 'text', id: descText.id })
112
+ }
113
+ }
114
+
115
+ return { success: true, elements }
116
+ }
117
+
118
+ module.exports = createStepper
@@ -0,0 +1,159 @@
1
+ /**
2
+ * 表格组件
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建表格组件
9
+ */
10
+ function createTable(project, canvas, params) {
11
+ const {
12
+ x,
13
+ y,
14
+ width,
15
+ columns = [],
16
+ rows = [],
17
+ rowHeight = 36,
18
+ headerBg = '#f0f0f0',
19
+ headerColor = '#333333',
20
+ borderColor = '#e0e0e0',
21
+ cellColor = '#333333',
22
+ fontSize = 12,
23
+ headerFontSize = 13,
24
+ striped = true,
25
+ stripeColor = '#fafafa'
26
+ } = params
27
+
28
+ const elements = []
29
+
30
+ if (columns.length === 0) {
31
+ return { success: true, elements, type: 'table' }
32
+ }
33
+
34
+ const totalHeight = rowHeight * (rows.length + 1)
35
+
36
+ // 绘制外边框
37
+ const outerBorder = new paper.Path.Rectangle({
38
+ point: [x, y],
39
+ size: [width, totalHeight]
40
+ })
41
+ outerBorder.fillColor = new paper.Color('transparent')
42
+ outerBorder.strokeColor = new paper.Color(borderColor)
43
+ outerBorder.strokeWidth = 1
44
+ if (project && project.activeLayer) {
45
+ project.activeLayer.addChild(outerBorder)
46
+ }
47
+ elements.push({ type: 'path', id: outerBorder.id })
48
+
49
+ // 绘制表头背景
50
+ const headerBgRect = new paper.Path.Rectangle({
51
+ point: [x, y],
52
+ size: [width, rowHeight]
53
+ })
54
+ headerBgRect.fillColor = new paper.Color(headerBg)
55
+ headerBgRect.strokeColor = new paper.Color(borderColor)
56
+ headerBgRect.strokeWidth = 0.5
57
+ if (project && project.activeLayer) {
58
+ project.activeLayer.addChild(headerBgRect)
59
+ }
60
+ elements.push({ type: 'path', id: headerBgRect.id })
61
+
62
+ // 绘制表头
63
+ let currentX = x
64
+ columns.forEach((col, index) => {
65
+ const colWidth = col.width || (width / columns.length)
66
+
67
+ // 列分隔线
68
+ if (index > 0) {
69
+ const line = new paper.Path.Line({
70
+ from: [currentX, y],
71
+ to: [currentX, y + totalHeight]
72
+ })
73
+ line.strokeColor = new paper.Color(borderColor)
74
+ line.strokeWidth = 0.5
75
+ if (project && project.activeLayer) {
76
+ project.activeLayer.addChild(line)
77
+ }
78
+ elements.push({ type: 'line', id: line.id })
79
+ }
80
+
81
+ // 表头文字
82
+ const headerText = new paper.PointText({
83
+ point: [currentX + colWidth / 2, y + rowHeight / 2 + fontSize / 3],
84
+ content: col.title || '',
85
+ fontSize: headerFontSize,
86
+ fillColor: new paper.Color(headerColor),
87
+ justification: col.align || 'center',
88
+ fontWeight: 'bold'
89
+ })
90
+ if (project && project.activeLayer) {
91
+ project.activeLayer.addChild(headerText)
92
+ }
93
+ elements.push({ type: 'text', id: headerText.id })
94
+
95
+ currentX += colWidth
96
+ })
97
+
98
+ // 绘制数据行
99
+ rows.forEach((row, rowIndex) => {
100
+ const rowY = y + rowHeight * (rowIndex + 1)
101
+
102
+ // 斑马纹背景
103
+ if (striped && rowIndex % 2 === 1) {
104
+ const stripeBg = new paper.Path.Rectangle({
105
+ point: [x, rowY],
106
+ size: [width, rowHeight]
107
+ })
108
+ stripeBg.fillColor = new paper.Color(stripeColor)
109
+ stripeBg.strokeColor = new paper.Color(borderColor)
110
+ stripeBg.strokeWidth = 0.5
111
+ if (project && project.activeLayer) {
112
+ project.activeLayer.addChild(stripeBg)
113
+ }
114
+ elements.push({ type: 'path', id: stripeBg.id })
115
+ }
116
+
117
+ // 行分隔线
118
+ const rowLine = new paper.Path.Line({
119
+ from: [x, rowY],
120
+ to: [x + width, rowY]
121
+ })
122
+ rowLine.strokeColor = new paper.Color(borderColor)
123
+ rowLine.strokeWidth = 0.5
124
+ if (project && project.activeLayer) {
125
+ project.activeLayer.addChild(rowLine)
126
+ }
127
+ elements.push({ type: 'line', id: rowLine.id })
128
+
129
+ // 单元格
130
+ let cellX = x
131
+ columns.forEach((col, colIndex) => {
132
+ const colWidth = col.width || (width / columns.length)
133
+ const cellValue = row[colIndex] || ''
134
+ const cellText = new paper.PointText({
135
+ point: [cellX + colWidth / 2, rowY + rowHeight / 2 + fontSize / 3],
136
+ content: String(cellValue),
137
+ fontSize: fontSize,
138
+ fillColor: new paper.Color(cellColor),
139
+ justification: col.align || 'center'
140
+ })
141
+ if (project && project.activeLayer) {
142
+ project.activeLayer.addChild(cellText)
143
+ }
144
+ elements.push({ type: 'text', id: cellText.id })
145
+
146
+ cellX += colWidth
147
+ })
148
+ })
149
+
150
+ return {
151
+ success: true,
152
+ elements,
153
+ width,
154
+ height: totalHeight,
155
+ type: 'table'
156
+ }
157
+ }
158
+
159
+ module.exports = createTable
@@ -0,0 +1,78 @@
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 {Array} args.tags - 标签数组 [{text, color, bgColor}]
16
+ * @param {number} args.fontSize - 字体大小
17
+ * @param {number} args.padding - 标签内边距
18
+ * @param {number} args.gap - 标签间距
19
+ * @param {number} args.maxWidth - 最大宽度(自动换行)
20
+ */
21
+ function createTagCloud(project, canvas, args) {
22
+ const {
23
+ x, y,
24
+ tags = [],
25
+ fontSize = 14,
26
+ padding = 12,
27
+ gap = 10,
28
+ maxWidth = 400,
29
+ } = args
30
+
31
+ const elements = []
32
+ let currentX = x
33
+ let currentY = y
34
+ let rowHeight = 0
35
+
36
+ for (const tag of tags) {
37
+ const textWidth = tag.text.length * fontSize * 0.6
38
+ const tagWidth = textWidth + padding * 2
39
+ const tagHeight = fontSize + padding * 2
40
+
41
+ // 换行处理
42
+ if (currentX + tagWidth > x + maxWidth && currentX > x) {
43
+ currentX = x
44
+ currentY += rowHeight + gap
45
+ rowHeight = 0
46
+ }
47
+
48
+ // 绘制标签背景
49
+ const tagBg = new paper.Path.Rectangle({
50
+ point: [currentX, currentY],
51
+ size: [tagWidth, tagHeight],
52
+ radius: tagHeight / 2,
53
+ })
54
+ tagBg.fillColor = new paper.Color(tag.bgColor || '#e0e7ff')
55
+ elements.push({ type: 'rectangle', id: tagBg.id })
56
+
57
+ // 绘制标签文字
58
+ const tagText = new paper.PointText({
59
+ point: [currentX + tagWidth / 2, currentY + tagHeight / 2 + fontSize / 3],
60
+ content: tag.text,
61
+ fontSize: fontSize,
62
+ fillColor: new paper.Color(tag.color || '#4338ca'),
63
+ justification: 'center',
64
+ })
65
+ elements.push({ type: 'text', id: tagText.id })
66
+
67
+ currentX += tagWidth + gap
68
+ rowHeight = Math.max(rowHeight, tagHeight)
69
+ }
70
+
71
+ return {
72
+ success: true,
73
+ elements,
74
+ height: rowHeight,
75
+ }
76
+ }
77
+
78
+ module.exports = createTagCloud