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,155 @@
1
+ /**
2
+ * 图片框组件 - 带装饰边框的图片
3
+ */
4
+ const createImageFrame = (ctx) => ({
5
+ /**
6
+ * @param {Object} params
7
+ * @param {string} params.src - 图片路径或URL
8
+ * @param {number} params.x - X坐标
9
+ * @param {number} params.y - Y坐标
10
+ * @param {number} params.width - 图片宽度
11
+ * @param {number} params.height - 图片高度
12
+ * @param {string} [params.borderColor='#ffffff'] - 边框颜色
13
+ * @param {number} [params.borderWidth=3] - 边框宽度
14
+ * @param {string} [params.outerColor='#1a1a2e'] - 外边框颜色
15
+ * @param {number} [params.outerWidth=6] - 外边框宽度
16
+ * @param {number} [params.shadowBlur=0] - 阴影模糊
17
+ * @param {number} [params.shadowOffsetX=0] - 阴影X偏移
18
+ * @param {number} [params.shadowOffsetY=0] - 阴影Y偏移
19
+ * @param {string} [params.shadowColor='rgba(0,0,0,0.3)'] - 阴影颜色
20
+ * @param {number} [params.radius=0] - 圆角半径
21
+ * @param {string} [params.overlayColor] - 叠加颜色
22
+ * @param {number} [params.overlayOpacity=0] - 叠加透明度
23
+ * @param {string} [params.fit='cover'] - 图片填充方式: cover, contain, fill
24
+ */
25
+ async draw({
26
+ src,
27
+ x,
28
+ y,
29
+ width,
30
+ height,
31
+ borderColor = '#ffffff',
32
+ borderWidth = 3,
33
+ outerColor = '#1a1a2e',
34
+ outerWidth = 6,
35
+ shadowBlur = 0,
36
+ shadowOffsetX = 0,
37
+ shadowOffsetY = 0,
38
+ shadowColor = 'rgba(0,0,0,0.3)',
39
+ radius = 0,
40
+ overlayColor,
41
+ overlayOpacity = 0,
42
+ fit = 'cover'
43
+ }) {
44
+ // 绘制外边框(装饰层)
45
+ if (outerWidth > 0) {
46
+ ctx.fillStyle = outerColor
47
+ await _roundRect(ctx, x - outerWidth, y - outerWidth, width + outerWidth * 2, height + outerWidth * 2, radius + outerWidth)
48
+ ctx.fill()
49
+ }
50
+
51
+ // 绘制内边框
52
+ if (borderWidth > 0) {
53
+ ctx.fillStyle = borderColor
54
+ await _roundRect(ctx, x - borderWidth, y - borderWidth, width + borderWidth * 2, height + borderWidth * 2, radius + borderWidth)
55
+ ctx.fill()
56
+ }
57
+
58
+ // 绘制阴影
59
+ if (shadowBlur > 0) {
60
+ ctx.shadowColor = shadowColor
61
+ ctx.shadowBlur = shadowBlur
62
+ ctx.shadowOffsetX = shadowOffsetX
63
+ ctx.shadowOffsetY = shadowOffsetY
64
+ }
65
+
66
+ // 加载并绘制图片
67
+ const image = await _loadImage(src)
68
+ const imgWidth = image.width
69
+ const imgHeight = image.height
70
+ const imgRatio = imgWidth / imgHeight
71
+ const boxRatio = width / height
72
+
73
+ let drawX = x, drawY = y, drawW = width, drawH = height
74
+
75
+ if (fit === 'cover') {
76
+ if (imgRatio > boxRatio) {
77
+ drawH = height
78
+ drawW = height * imgRatio
79
+ drawX = x - (drawW - width) / 2
80
+ } else {
81
+ drawW = width
82
+ drawH = width / imgRatio
83
+ drawY = y - (drawH - height) / 2
84
+ }
85
+ } else if (fit === 'contain') {
86
+ if (imgRatio > boxRatio) {
87
+ drawW = width
88
+ drawH = width / imgRatio
89
+ drawY = y + (height - drawH) / 2
90
+ } else {
91
+ drawH = height
92
+ drawW = height * imgRatio
93
+ drawX = x + (width - drawW) / 2
94
+ }
95
+ }
96
+
97
+ // 裁剪并绘制图片
98
+ ctx.save()
99
+ await _roundRect(ctx, x, y, width, height, radius)
100
+ ctx.clip()
101
+ ctx.drawImage(image, drawX, drawY, drawW, drawH)
102
+ ctx.restore()
103
+
104
+ // 重置阴影
105
+ ctx.shadowColor = 'transparent'
106
+ ctx.shadowBlur = 0
107
+ ctx.shadowOffsetX = 0
108
+ ctx.shadowOffsetY = 0
109
+
110
+ // 叠加颜色
111
+ if (overlayColor && overlayOpacity > 0) {
112
+ ctx.fillStyle = overlayColor
113
+ ctx.globalAlpha = overlayOpacity
114
+ await _roundRect(ctx, x, y, width, height, radius)
115
+ ctx.fill()
116
+ ctx.globalAlpha = 1
117
+ }
118
+ }
119
+ })
120
+
121
+ // 辅助函数:圆角矩形
122
+ async function _roundRect(ctx, x, y, width, height, radius) {
123
+ const r = Math.min(radius, width / 2, height / 2)
124
+ ctx.beginPath()
125
+ ctx.moveTo(x + r, y)
126
+ ctx.lineTo(x + width - r, y)
127
+ ctx.quadraticCurveTo(x + width, y, x + width, y + r)
128
+ ctx.lineTo(x + width, y + height - r)
129
+ ctx.quadraticCurveTo(x + width, y + height, x + width - r, y + height)
130
+ ctx.lineTo(x + r, y + height)
131
+ ctx.quadraticCurveTo(x, y + height, x, y + height - r)
132
+ ctx.lineTo(x, y + r)
133
+ ctx.quadraticCurveTo(x, y, x + r, y)
134
+ ctx.closePath()
135
+ }
136
+
137
+ // 辅助函数:加载图片
138
+ async function _loadImage(src) {
139
+ return new Promise((resolve, reject) => {
140
+ const img = new Image()
141
+ img.crossOrigin = 'anonymous'
142
+ img.onload = () => resolve(img)
143
+ img.onerror = (e) => {
144
+ // 尝试 data URL 格式
145
+ if (src.startsWith('data:')) {
146
+ img.src = src
147
+ } else {
148
+ reject(new Error(`Failed to load image: ${src}`))
149
+ }
150
+ }
151
+ img.src = src
152
+ })
153
+ }
154
+
155
+ module.exports = createImageFrame
@@ -0,0 +1,62 @@
1
+ /**
2
+ * 高级组件模块导出
3
+ */
4
+
5
+ const createCard = require('./card')
6
+ const createBadge = require('./badge')
7
+ const createCTA = require('./cta')
8
+ const createFeature = require('./feature')
9
+ const createFeatureGrid = require('./featureGrid')
10
+ const createDivider = require('./divider')
11
+ const createAvatar = require('./avatar')
12
+ const createProgress = require('./progress')
13
+ const createRating = require('./rating')
14
+ const createQuote = require('./quote')
15
+ const createStatCard = require('./statCard')
16
+ const createTagCloud = require('./tagCloud')
17
+ const createStepper = require('./stepper')
18
+ const createTimeline = require('./timeline')
19
+ const { createListItem, createList } = require('./listItem')
20
+ const createNotification = require('./notification')
21
+ const createImageFrame = require('./imageFrame')
22
+ const createColumns = require('./columns')
23
+ const createGrid = require('./grid')
24
+ const createStar = require('./star')
25
+ const createArrow = require('./arrow')
26
+ const createProgressCircle = require('./progressCircle')
27
+ const createChip = require('./chip')
28
+ const createChart = require('./chart')
29
+ const createWatermark = require('./watermark')
30
+ const createTable = require('./table')
31
+
32
+ module.exports = {
33
+ // 原有组件
34
+ createCard,
35
+ createBadge,
36
+ createCTA,
37
+ createFeature,
38
+ createFeatureGrid,
39
+ createDivider,
40
+ createAvatar,
41
+ createProgress,
42
+ createRating,
43
+ createQuote,
44
+ createStatCard,
45
+ createTagCloud,
46
+ createStepper,
47
+ createTimeline,
48
+ createListItem,
49
+ createList,
50
+ createNotification,
51
+ createImageFrame,
52
+ createColumns,
53
+ createGrid,
54
+ // 新增组件
55
+ createStar,
56
+ createArrow,
57
+ createProgressCircle,
58
+ createChip,
59
+ createChart,
60
+ createWatermark,
61
+ createTable,
62
+ }
@@ -0,0 +1,146 @@
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.icon - 图标
17
+ * @param {string} args.title - 标题
18
+ * @param {string} args.description - 描述
19
+ * @param {string} args.badge - 徽章文字
20
+ * @param {string} args.badgeColor - 徽章颜色
21
+ * @param {string} args.iconColor - 图标颜色
22
+ * @param {string} args.background - 背景色
23
+ * @param {string} args.borderColor - 边框颜色
24
+ * @param {number} args.height - 高度
25
+ * @param {number} args.radius - 圆角半径
26
+ */
27
+ function createListItem(project, canvas, args) {
28
+ const {
29
+ x, y,
30
+ width = 400,
31
+ icon = '→',
32
+ title,
33
+ description,
34
+ badge,
35
+ badgeColor = '#6366f1',
36
+ iconColor = '#6366f1',
37
+ background = '#ffffff',
38
+ borderColor = '#e5e7eb',
39
+ height = 60,
40
+ radius = 8,
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(borderColor)
53
+ bg.strokeWidth = 1
54
+ elements.push({ type: 'rectangle', id: bg.id })
55
+
56
+ // 绘制图标
57
+ const iconText = new paper.PointText({
58
+ point: [x + 15, y + height / 2 + 6],
59
+ content: icon,
60
+ fontSize: 20,
61
+ fillColor: new paper.Color(iconColor),
62
+ justification: 'center',
63
+ })
64
+ elements.push({ type: 'text', id: iconText.id })
65
+
66
+ // 绘制标题
67
+ const titleText = new paper.PointText({
68
+ point: [x + 50, y + height / 2 - 5],
69
+ content: title || 'List Item',
70
+ fontSize: 16,
71
+ fillColor: new paper.Color('#1e293b'),
72
+ justification: 'left',
73
+ })
74
+ elements.push({ type: 'text', id: titleText.id })
75
+
76
+ // 绘制描述
77
+ if (description) {
78
+ const descText = new paper.PointText({
79
+ point: [x + 50, y + height / 2 + 15],
80
+ content: description,
81
+ fontSize: 12,
82
+ fillColor: new paper.Color('#64748b'),
83
+ justification: 'left',
84
+ })
85
+ elements.push({ type: 'text', id: descText.id })
86
+ }
87
+
88
+ // 绘制徽章
89
+ if (badge) {
90
+ const badgeWidth = badge.length * 10 + 20
91
+ const badgeX = x + width - badgeWidth - 15
92
+ const badgeY = y + (height - 24) / 2
93
+
94
+ const badgeBg = new paper.Path.Rectangle({
95
+ point: [badgeX, badgeY],
96
+ size: [badgeWidth, 24],
97
+ radius: 12,
98
+ })
99
+ badgeBg.fillColor = new paper.Color(badgeColor)
100
+ elements.push({ type: 'rectangle', id: badgeBg.id })
101
+
102
+ const badgeText = new paper.PointText({
103
+ point: [badgeX + badgeWidth / 2, badgeY + 16],
104
+ content: badge,
105
+ fontSize: 12,
106
+ fillColor: new paper.Color('#ffffff'),
107
+ justification: 'center',
108
+ })
109
+ elements.push({ type: 'text', id: badgeText.id })
110
+ }
111
+
112
+ return { success: true, elements }
113
+ }
114
+
115
+ /**
116
+ * 创建列表(多个列表项)
117
+ */
118
+ function createList(project, canvas, args) {
119
+ const {
120
+ x, y,
121
+ items = [],
122
+ gap = 10,
123
+ width = 400,
124
+ ...rest
125
+ } = args
126
+
127
+ const elements = []
128
+ let currentY = y
129
+
130
+ for (const item of items) {
131
+ const result = createListItem(project, canvas, {
132
+ x, y: currentY, width, ...item, ...rest,
133
+ })
134
+ elements.push(...result.elements)
135
+ currentY += 60 + gap
136
+ }
137
+
138
+ return {
139
+ success: true,
140
+ elements,
141
+ height: currentY - y,
142
+ }
143
+ }
144
+
145
+ module.exports = createListItem
146
+ module.exports.createList = createList
@@ -0,0 +1,123 @@
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.type - 类型: success, warning, error, info
17
+ * @param {string} args.title - 标题
18
+ * @param {string} args.message - 消息内容
19
+ * @param {boolean} args.showIcon - 是否显示图标
20
+ * @param {number} args.radius - 圆角半径
21
+ */
22
+ function createNotification(project, canvas, args) {
23
+ const {
24
+ x, y,
25
+ width = 360,
26
+ type = 'info',
27
+ title,
28
+ message,
29
+ showIcon = true,
30
+ radius = 12,
31
+ } = args
32
+
33
+ // 类型配置
34
+ const config = {
35
+ success: {
36
+ icon: '✓',
37
+ bgColor: '#dcfce7',
38
+ iconColor: '#22c55e',
39
+ borderColor: '#22c55e',
40
+ },
41
+ warning: {
42
+ icon: '⚠',
43
+ bgColor: '#fef9c3',
44
+ iconColor: '#eab308',
45
+ borderColor: '#eab308',
46
+ },
47
+ error: {
48
+ icon: '✕',
49
+ bgColor: '#fee2e2',
50
+ iconColor: '#ef4444',
51
+ borderColor: '#ef4444',
52
+ },
53
+ info: {
54
+ icon: 'ℹ',
55
+ bgColor: '#dbeafe',
56
+ iconColor: '#3b82f6',
57
+ borderColor: '#3b82f6',
58
+ },
59
+ }
60
+
61
+ const c = config[type] || config.info
62
+ const padding = 16
63
+ const lineHeight = 22
64
+ const iconSize = 24
65
+ const height = padding * 2 + (title ? lineHeight + 8 : 0) + (message ? lineHeight : 0)
66
+
67
+ const elements = []
68
+
69
+ // 绘制背景
70
+ const bg = new paper.Path.Rectangle({
71
+ point: [x, y],
72
+ size: [width, height],
73
+ radius: radius,
74
+ })
75
+ bg.fillColor = new paper.Color(c.bgColor)
76
+ bg.strokeColor = new paper.Color(c.borderColor)
77
+ bg.strokeWidth = 1
78
+ elements.push({ type: 'rectangle', id: bg.id })
79
+
80
+ // 绘制图标
81
+ if (showIcon) {
82
+ const iconText = new paper.PointText({
83
+ point: [x + padding + iconSize / 2, y + padding + iconSize / 2 + 6],
84
+ content: c.icon,
85
+ fontSize: iconSize,
86
+ fillColor: new paper.Color(c.iconColor),
87
+ justification: 'center',
88
+ })
89
+ elements.push({ type: 'text', id: iconText.id })
90
+ }
91
+
92
+ const textX = showIcon ? x + padding + iconSize + 12 : x + padding
93
+ let currentY = y + padding
94
+
95
+ // 绘制标题
96
+ if (title) {
97
+ const titleText = new paper.PointText({
98
+ point: [textX, currentY + 18],
99
+ content: title,
100
+ fontSize: 16,
101
+ fillColor: new paper.Color('#1e293b'),
102
+ justification: 'left',
103
+ })
104
+ elements.push({ type: 'text', id: titleText.id })
105
+ currentY += lineHeight + 8
106
+ }
107
+
108
+ // 绘制消息
109
+ if (message) {
110
+ const msgText = new paper.PointText({
111
+ point: [textX, currentY + 16],
112
+ content: message,
113
+ fontSize: 14,
114
+ fillColor: new paper.Color('#475569'),
115
+ justification: 'left',
116
+ })
117
+ elements.push({ type: 'text', id: msgText.id })
118
+ }
119
+
120
+ return { success: true, elements }
121
+ }
122
+
123
+ module.exports = createNotification
@@ -0,0 +1,79 @@
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 {number} args.value - 进度值 0-100
18
+ * @param {string} args.trackColor - 轨道颜色
19
+ * @param {string} args.fillColor - 填充颜色
20
+ * @param {number} args.radius - 圆角半径
21
+ * @param {boolean} args.showLabel - 是否显示标签
22
+ * @param {string} args.label - 标签文字
23
+ */
24
+ function createProgress(project, canvas, args) {
25
+ const {
26
+ x, y,
27
+ width = 300,
28
+ height = 20,
29
+ value = 50,
30
+ trackColor = '#e0e0e0',
31
+ fillColor = '#6366f1',
32
+ radius = 10,
33
+ showLabel = false,
34
+ label,
35
+ } = args
36
+
37
+ const elements = []
38
+
39
+ // 绘制轨道
40
+ const track = new paper.Path.Rectangle({
41
+ point: [x, y],
42
+ size: [width, height],
43
+ radius: radius,
44
+ })
45
+ track.fillColor = new paper.Color(trackColor)
46
+ elements.push({ type: 'rectangle', id: track.id })
47
+
48
+ // 绘制进度
49
+ const progressWidth = (value / 100) * width
50
+ if (progressWidth > 0) {
51
+ const fill = new paper.Path.Rectangle({
52
+ point: [x, y],
53
+ size: [progressWidth, height],
54
+ radius: radius,
55
+ })
56
+ fill.fillColor = new paper.Color(fillColor)
57
+ elements.push({ type: 'rectangle', id: fill.id })
58
+ }
59
+
60
+ // 显示标签
61
+ if (showLabel && label) {
62
+ const labelText = new paper.PointText({
63
+ point: [x + width / 2, y - 8],
64
+ content: label,
65
+ fontSize: 14,
66
+ fillColor: new paper.Color('#666666'),
67
+ justification: 'center',
68
+ })
69
+ elements.push({ type: 'text', id: labelText.id })
70
+ }
71
+
72
+ return {
73
+ success: true,
74
+ elements,
75
+ value,
76
+ }
77
+ }
78
+
79
+ module.exports = createProgress
@@ -0,0 +1,117 @@
1
+ /**
2
+ * 环形进度条组件
3
+ */
4
+
5
+ const paper = require('paper')
6
+
7
+ /**
8
+ * 创建环形进度条组件
9
+ */
10
+ function createProgressCircle(project, canvas, params) {
11
+ const {
12
+ cx,
13
+ cy,
14
+ radius,
15
+ value,
16
+ strokeWidth = 10,
17
+ trackColor = '#e5e7eb',
18
+ fillColor = '#3b82f6',
19
+ backgroundColor,
20
+ showLabel = true,
21
+ labelColor,
22
+ startAngle = -90
23
+ } = params
24
+
25
+ const elements = []
26
+
27
+ // 绘制背景圆(可选)
28
+ if (backgroundColor) {
29
+ const bgCircle = new paper.Path.Circle({
30
+ center: [cx, cy],
31
+ radius: radius + strokeWidth / 2
32
+ })
33
+ bgCircle.fillColor = new paper.Color(backgroundColor)
34
+ if (project && project.activeLayer) {
35
+ project.activeLayer.addChild(bgCircle)
36
+ }
37
+ elements.push({ type: 'path', id: bgCircle.id })
38
+ }
39
+
40
+ // 绘制轨道(背景环)
41
+ const trackCircle = new paper.Path.Circle({
42
+ center: [cx, cy],
43
+ radius: radius
44
+ })
45
+ trackCircle.fillColor = null
46
+ trackCircle.strokeColor = new paper.Color(trackColor)
47
+ trackCircle.strokeWidth = strokeWidth
48
+ if (project && project.activeLayer) {
49
+ project.activeLayer.addChild(trackCircle)
50
+ }
51
+ elements.push({ type: 'path', id: trackCircle.id })
52
+
53
+ // 绘制进度弧线
54
+ if (value > 0 && value <= 100) {
55
+ const percentage = value / 100
56
+ const arcAngle = percentage * 360
57
+
58
+ // 转换为弧度
59
+ const startRad = startAngle * Math.PI / 180
60
+ const endRad = (startAngle + arcAngle) * Math.PI / 180
61
+
62
+ // 创建进度弧线路径
63
+ const progressArc = new paper.Path()
64
+
65
+ // 添加起点
66
+ progressArc.moveTo(
67
+ cx + radius * Math.cos(startRad),
68
+ cy + radius * Math.sin(startRad)
69
+ )
70
+
71
+ // 添加弧线上的点(用多个点模拟圆弧)
72
+ const segments = 36
73
+ const angleStep = (endRad - startRad) / segments
74
+ for (let i = 1; i <= segments; i++) {
75
+ const angle = startRad + angleStep * i
76
+ progressArc.lineTo(
77
+ cx + radius * Math.cos(angle),
78
+ cy + radius * Math.sin(angle)
79
+ )
80
+ }
81
+
82
+ progressArc.strokeColor = new paper.Color(fillColor)
83
+ progressArc.strokeWidth = strokeWidth
84
+ progressArc.strokeCap = 'round'
85
+
86
+ if (project && project.activeLayer) {
87
+ project.activeLayer.addChild(progressArc)
88
+ }
89
+ elements.push({ type: 'path', id: progressArc.id })
90
+ }
91
+
92
+ // 绘制标签文字
93
+ if (showLabel) {
94
+ const textColor = labelColor || fillColor
95
+ const fontSize = Math.min(Math.max(Math.round(radius * 0.35), 12), 48)
96
+ const label = new paper.PointText({
97
+ point: [cx, cy + fontSize * 0.35],
98
+ content: `${Math.round(value)}%`,
99
+ fontSize: fontSize,
100
+ fillColor: new paper.Color(textColor),
101
+ justification: 'center',
102
+ fontWeight: 'bold'
103
+ })
104
+ if (project && project.activeLayer) {
105
+ project.activeLayer.addChild(label)
106
+ }
107
+ elements.push({ type: 'text', id: label.id })
108
+ }
109
+
110
+ return {
111
+ success: true,
112
+ elements,
113
+ type: 'progressCircle'
114
+ }
115
+ }
116
+
117
+ module.exports = createProgressCircle