foliko 1.1.7 → 1.1.9

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 (113) hide show
  1. package/.agent/agents/poster-expert.md +228 -0
  2. package/.agent/data/default.json +10 -0
  3. package/.agent/data/plugins-state.json +1 -1
  4. package/.agent/mcp_config.json +0 -6
  5. package/.agent/plugins/test-plugin.py +15 -0
  6. package/.agent/plugins/test_nested_plugin.py +85 -0
  7. package/.agent/sessions/cli_default.json +83 -803
  8. package/.agent/sessions/weixin_o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat.json +189 -0
  9. package/.claude/settings.local.json +8 -1
  10. package/cli/src/ui/chat-ui.js +32 -21
  11. package/foliko_poster.png +0 -0
  12. package/output/business_poster_final.png +0 -0
  13. package/output/emoji_test_v2.png +0 -0
  14. package/output/foliko-ai-launch-poster.png +0 -0
  15. package/output/foliko-poster.png +0 -0
  16. package/output/muji_style_poster.png +0 -0
  17. package/output/new_product_launch.png +0 -0
  18. package/output/news_poster_625yi_subsidy.png +0 -0
  19. package/output/tech_future_2026.png +0 -0
  20. package/output/tech_future_poster.png +0 -0
  21. package/package.json +2 -2
  22. package/plugins/default-plugins.js +60 -7
  23. package/plugins/extension-executor-plugin.js +32 -22
  24. package/plugins/feishu-plugin.js +2 -2
  25. package/plugins/python-plugin-loader.js +461 -40
  26. package/plugins/python-plugin-loader.js.bak +856 -0
  27. package/plugins/subagent-plugin.js +0 -121
  28. package/plugins/telegram-plugin.js +2 -2
  29. package/plugins/weixin-plugin.js +40 -31
  30. package/poster.png +0 -0
  31. package/skills/foliko-dev/SKILL.md +6 -0
  32. package/skills/python-plugin-dev/SKILL.md +124 -2
  33. package/src/core/agent-chat.js +220 -281
  34. package/src/core/agent.js +127 -29
  35. package/src/executors/mcp-executor.js +282 -26
  36. package/src/utils/plugin-helpers.js +22 -4
  37. package/system.md +362 -109
  38. package/test-scan.js +18 -0
  39. package/.agent/memory/feedback/mnt7jrlt-d67qs7.md +0 -15
  40. package/.agent/memory/feedback/mnt88ja3-al4fuy.md +0 -9
  41. package/.agent/plugins/poster-plugin/README.md +0 -304
  42. package/.agent/plugins/poster-plugin/emojis/rocket.png +0 -1
  43. package/.agent/plugins/poster-plugin/fonts/PatuaOne-Regular.ttf +0 -0
  44. package/.agent/plugins/poster-plugin/fonts/SegoeUI Emoji.ttf +0 -0
  45. package/.agent/plugins/poster-plugin/fonts//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
  46. 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
  47. package/.agent/plugins/poster-plugin/index.js +0 -13
  48. package/.agent/plugins/poster-plugin/package.json +0 -29
  49. package/.agent/plugins/poster-plugin/src/canvas.js +0 -224
  50. package/.agent/plugins/poster-plugin/src/components/arrow.js +0 -84
  51. package/.agent/plugins/poster-plugin/src/components/avatar.js +0 -71
  52. package/.agent/plugins/poster-plugin/src/components/badge.js +0 -85
  53. package/.agent/plugins/poster-plugin/src/components/barcode.js +0 -120
  54. package/.agent/plugins/poster-plugin/src/components/bubble.js +0 -153
  55. package/.agent/plugins/poster-plugin/src/components/button.js +0 -124
  56. package/.agent/plugins/poster-plugin/src/components/card.js +0 -88
  57. package/.agent/plugins/poster-plugin/src/components/chart.js +0 -127
  58. package/.agent/plugins/poster-plugin/src/components/chip.js +0 -88
  59. package/.agent/plugins/poster-plugin/src/components/columns.js +0 -107
  60. package/.agent/plugins/poster-plugin/src/components/cta.js +0 -87
  61. package/.agent/plugins/poster-plugin/src/components/divider.js +0 -55
  62. package/.agent/plugins/poster-plugin/src/components/feature.js +0 -85
  63. package/.agent/plugins/poster-plugin/src/components/featureGrid.js +0 -117
  64. package/.agent/plugins/poster-plugin/src/components/frame.js +0 -230
  65. package/.agent/plugins/poster-plugin/src/components/grid.js +0 -118
  66. package/.agent/plugins/poster-plugin/src/components/highlightText.js +0 -144
  67. package/.agent/plugins/poster-plugin/src/components/icon.js +0 -94
  68. package/.agent/plugins/poster-plugin/src/components/imageFrame.js +0 -155
  69. package/.agent/plugins/poster-plugin/src/components/index.js +0 -81
  70. package/.agent/plugins/poster-plugin/src/components/listItem.js +0 -147
  71. package/.agent/plugins/poster-plugin/src/components/notification.js +0 -123
  72. package/.agent/plugins/poster-plugin/src/components/progress.js +0 -79
  73. package/.agent/plugins/poster-plugin/src/components/progressCircle.js +0 -117
  74. package/.agent/plugins/poster-plugin/src/components/qrcode.js +0 -74
  75. package/.agent/plugins/poster-plugin/src/components/quote.js +0 -97
  76. package/.agent/plugins/poster-plugin/src/components/rating.js +0 -85
  77. package/.agent/plugins/poster-plugin/src/components/ribbon.js +0 -193
  78. package/.agent/plugins/poster-plugin/src/components/seal.js +0 -146
  79. package/.agent/plugins/poster-plugin/src/components/star.js +0 -70
  80. package/.agent/plugins/poster-plugin/src/components/statCard.js +0 -105
  81. package/.agent/plugins/poster-plugin/src/components/stepper.js +0 -118
  82. package/.agent/plugins/poster-plugin/src/components/table.js +0 -167
  83. package/.agent/plugins/poster-plugin/src/components/tagCloud.js +0 -85
  84. package/.agent/plugins/poster-plugin/src/components/timeline.js +0 -117
  85. package/.agent/plugins/poster-plugin/src/components/watermark.js +0 -52
  86. package/.agent/plugins/poster-plugin/src/composer.js +0 -2146
  87. package/.agent/plugins/poster-plugin/src/elements/artText.js +0 -60
  88. package/.agent/plugins/poster-plugin/src/elements/background.js +0 -84
  89. package/.agent/plugins/poster-plugin/src/elements/circle.js +0 -31
  90. package/.agent/plugins/poster-plugin/src/elements/image.js +0 -28
  91. package/.agent/plugins/poster-plugin/src/elements/index.js +0 -28
  92. package/.agent/plugins/poster-plugin/src/elements/line.js +0 -23
  93. package/.agent/plugins/poster-plugin/src/elements/polygon.js +0 -63
  94. package/.agent/plugins/poster-plugin/src/elements/rectangle.js +0 -32
  95. package/.agent/plugins/poster-plugin/src/elements/richText.js +0 -230
  96. package/.agent/plugins/poster-plugin/src/elements/svg.js +0 -108
  97. package/.agent/plugins/poster-plugin/src/elements/text.js +0 -109
  98. package/.agent/plugins/poster-plugin/src/fonts.js +0 -243
  99. package/.agent/plugins/poster-plugin/src/index.js +0 -2081
  100. package/.agent/plugins/poster-plugin/src/presets.js +0 -36
  101. package/.agent/plugins/poster-plugin/src/templates/business.js +0 -60
  102. package/.agent/plugins/poster-plugin/src/templates/gradient.js +0 -64
  103. package/.agent/plugins/poster-plugin/src/templates/index.js +0 -43
  104. package/.agent/plugins/poster-plugin/src/templates/modern.js +0 -69
  105. package/.agent/plugins/poster-plugin/src/templates/simple.js +0 -58
  106. package/.agent/plugins/poster-plugin/src/templates/social.js +0 -62
  107. package/.agent/plugins/poster-plugin/src/templates/tech.js +0 -84
  108. package/.agent/plugins/poster-plugin/src/utils/imageLoader.js +0 -84
  109. package/.agent/plugins/poster-plugin/test-background.svg +0 -1
  110. package/.agent/plugins/poster-plugin/test-full-poster.svg +0 -2
  111. package/.agent/plugins/poster-plugin/test-image.png +0 -0
  112. package/.agent/plugins/poster-plugin/yarn.lock +0 -1007
  113. package/output/zen_silence.png +0 -0
@@ -1,36 +0,0 @@
1
- /**
2
- * 预设尺寸配置
3
- */
4
-
5
- const PRESETS = {
6
- // 海报
7
- poster_a4: { width: 2480, height: 3508, name: 'A4海报 (300dpi)' },
8
- poster_square: { width: 2000, height: 2000, name: '方形海报' },
9
- poster_16_9: { width: 1920, height: 1080, name: '16:9海报' },
10
- poster_4_3: { width: 1600, height: 1200, name: '4:3海报' },
11
- poster_9_16: { width: 1080, height: 1920, name: '9:16竖版海报' },
12
-
13
- // Banner
14
- banner_1920x500: { width: 1920, height: 500, name: '网站Banner' },
15
- banner_1200x400: { width: 1200, height: 400, name: '电商Banner' },
16
- banner_750x300: { width: 750, height: 300, name: '移动端Banner' },
17
- banner_468x60: { width: 468, height: 60, name: '小横幅' },
18
- banner_twitter: { width: 1500, height: 500, name: 'Twitter封面' },
19
-
20
- // 社交媒体
21
- social_instagram: { width: 1080, height: 1080, name: 'Instagram正方形' },
22
- social_story: { width: 1080, height: 1920, name: 'Instagram Story' },
23
- social_facebook: { width: 1200, height: 630, name: 'Facebook封面' },
24
- social_linkedin: { width: 1200, height: 627, name: 'LinkedIn封面' },
25
- social_youtube: { width: 2560, height: 1440, name: 'YouTube封面' },
26
-
27
- // 宣传图
28
- promo_900x500: { width: 900, height: 500, name: '宣传图' },
29
- promo_500x500: { width: 500, height: 500, name: '正方宣传图' },
30
- promo_300x250: { width: 300, height: 250, name: '矩形广告' },
31
-
32
- // 名片
33
- card_standard: { width: 1058, height: 640, name: '标准名片 (300dpi)' },
34
- }
35
-
36
- module.exports = PRESETS
@@ -1,60 +0,0 @@
1
- /**
2
- * Business(商务专业风格)模板
3
- * 使用组件化方式实现
4
- */
5
-
6
- const { createFromConfig } = require('../composer')
7
-
8
- /**
9
- * 应用商务风格模板
10
- */
11
- async function applyBusinessTemplate(project, canvas, args) {
12
- const { title, subtitle, background, accentColor } = args
13
- const cx = canvas.width / 2
14
-
15
- const bg = background || '#1e3a5f'
16
- const accent = accentColor || '#c9a227'
17
-
18
- const titleFontSize = Math.min(100, canvas.width / 12)
19
- const subtitleFontSize = Math.min(36, canvas.width / 28)
20
-
21
- const components = [
22
- // 背景
23
- { type: 'background', color: bg },
24
-
25
- // 顶部装饰线
26
- { type: 'line', x1: 100, y1: 150, x2: canvas.width - 100, y2: 150, stroke: accent, strokeWidth: 4 },
27
-
28
- // 左侧装饰条
29
- { type: 'rectangle', x: 80, y: 150, width: 8, height: canvas.height - 300, fill: accent },
30
-
31
- // 主标题
32
- {
33
- type: 'artText',
34
- text: title,
35
- x: cx,
36
- y: canvas.height / 2 - 20,
37
- fontSize: titleFontSize,
38
- gradient: { colors: ['#ffffff', '#e0e0e0'] },
39
- shadow: { color: 'rgba(0,0,0,0.3)', blur: 10 }
40
- },
41
-
42
- // 副标题
43
- ...(subtitle ? [{
44
- type: 'text',
45
- text: subtitle,
46
- x: cx,
47
- y: canvas.height / 2 + 60,
48
- fontSize: subtitleFontSize,
49
- color: '#cccccc',
50
- align: 'center'
51
- }] : []),
52
-
53
- // 底部装饰线
54
- { type: 'line', x1: 100, y1: canvas.height - 150, x2: canvas.width - 100, y2: canvas.height - 150, stroke: accent, strokeWidth: 4 }
55
- ]
56
-
57
- return await createFromConfig(project, canvas, { components })
58
- }
59
-
60
- module.exports = applyBusinessTemplate
@@ -1,64 +0,0 @@
1
- /**
2
- * Gradient(渐变风格)模板
3
- */
4
-
5
- const { createFromConfig } = require('../composer')
6
-
7
- /**
8
- * 应用渐变风格模板
9
- */
10
- async function applyGradientTemplate(project, canvas, args) {
11
- const { title, subtitle, background, accentColor } = args
12
- const cx = canvas.width / 2
13
- const cy = canvas.height / 2
14
-
15
- const bg = background || '#667eea'
16
- const accent = accentColor || '#764ba2'
17
-
18
- const titleFontSize = Math.min(120, canvas.width / 10)
19
-
20
- const components = [
21
- // 渐变背景
22
- {
23
- type: 'background',
24
- gradient: {
25
- type: 'radial',
26
- colors: [bg, accent, '#1a1a2e']
27
- }
28
- },
29
-
30
- // 装饰圆形
31
- { type: 'circle', cx: canvas.width * 0.2, cy: canvas.height * 0.2, rx: 100, fill: '#ffffff', opacity: 0.1 },
32
- { type: 'circle', cx: canvas.width * 0.8, cy: canvas.height * 0.7, rx: 150, fill: '#ffffff', opacity: 0.08 },
33
- { type: 'circle', cx: canvas.width * 0.5, cy: canvas.height * 0.9, rx: 200, fill: '#000000', opacity: 0.2 },
34
-
35
- // 主标题
36
- {
37
- type: 'artText',
38
- text: title,
39
- x: cx,
40
- y: cy - 20,
41
- fontSize: titleFontSize,
42
- gradient: { colors: ['#ffffff', '#e0e0e0'] },
43
- shadow: { color: 'rgba(0,0,0,0.5)', blur: 20 }
44
- },
45
-
46
- // 副标题
47
- ...(subtitle ? [{
48
- type: 'text',
49
- text: subtitle,
50
- x: cx,
51
- y: cy + 80,
52
- fontSize: 36,
53
- color: '#ffffff',
54
- align: 'center'
55
- }] : []),
56
-
57
- // 底部装饰线
58
- { type: 'line', x1: cx - 150, y1: cy + 150, x2: cx + 150, y2: cy + 150, stroke: '#ffffff', strokeWidth: 2, opacity: 0.5 }
59
- ]
60
-
61
- return await createFromConfig(project, canvas, { components })
62
- }
63
-
64
- module.exports = applyGradientTemplate
@@ -1,43 +0,0 @@
1
- /**
2
- * 模板模块导出
3
- */
4
-
5
- const applyModernTemplate = require('./modern')
6
- const applyBusinessTemplate = require('./business')
7
- const applySocialTemplate = require('./social')
8
- const applySimpleTemplate = require('./simple')
9
- const applyTechTemplate = require('./tech')
10
- const applyGradientTemplate = require('./gradient')
11
-
12
- const TEMPLATES = {
13
- modern: applyModernTemplate,
14
- business: applyBusinessTemplate,
15
- social: applySocialTemplate,
16
- simple: applySimpleTemplate,
17
- tech: applyTechTemplate,
18
- gradient: applyGradientTemplate,
19
- }
20
-
21
- /**
22
- * 应用模板
23
- */
24
- async function applyTemplate(project, canvas, templateName, args) {
25
- const templateFn = TEMPLATES[templateName]
26
- if (!templateFn) {
27
- throw new Error(`Unknown template: ${templateName}. Available: ${Object.keys(TEMPLATES).join(', ')}`)
28
- }
29
- return await templateFn(project, canvas, args)
30
- }
31
-
32
- /**
33
- * 获取可用模板列表
34
- */
35
- function getAvailableTemplates() {
36
- return Object.keys(TEMPLATES)
37
- }
38
-
39
- module.exports = {
40
- applyTemplate,
41
- getAvailableTemplates,
42
- TEMPLATES,
43
- }
@@ -1,69 +0,0 @@
1
- /**
2
- * Modern(现代科技风格)模板
3
- * 使用组件化方式实现
4
- */
5
-
6
- const { createFromConfig } = require('../composer')
7
-
8
- /**
9
- * 应用现代风格模板
10
- */
11
- async function applyModernTemplate(project, canvas, args) {
12
- const { title, subtitle, background, accentColor } = args
13
- const cx = canvas.width / 2
14
- const cy = canvas.height / 2
15
-
16
- const bg = background || '#1a1a2e'
17
- const accent = accentColor || '#00d9ff'
18
-
19
- // 计算装饰圆形位置
20
- const circle1X = canvas.width * 0.85
21
- const circle1Y = canvas.height * 0.15
22
- const circle2X = canvas.width * 0.1
23
- const circle2Y = canvas.height * 0.85
24
- const circle3X = canvas.width * 0.9
25
- const circle3Y = canvas.height * 0.8
26
-
27
- // 计算字体大小
28
- const titleFontSize = Math.min(120, canvas.width / 10)
29
- const subtitleFontSize = Math.min(40, canvas.width / 25)
30
-
31
- const components = [
32
- // 背景
33
- { type: 'background', color: bg },
34
-
35
- // 装饰圆形
36
- { type: 'circle', cx: circle1X, cy: circle1Y, rx: 200, fill: accent, opacity: 0.2 },
37
- { type: 'circle', cx: circle2X, cy: circle2Y, rx: 150, fill: accent, opacity: 0.15 },
38
- { type: 'circle', cx: circle3X, cy: circle3Y, rx: 100, fill: '#00ff88', opacity: 0.1 },
39
-
40
- // 艺术标题
41
- {
42
- type: 'artText',
43
- text: title,
44
- x: cx,
45
- y: cy - 30,
46
- fontSize: titleFontSize,
47
- gradient: { colors: [accent, '#00ff88'] },
48
- shadow: { color: accent, blur: 20 }
49
- },
50
-
51
- // 副标题
52
- ...(subtitle ? [{
53
- type: 'text',
54
- text: subtitle,
55
- x: cx,
56
- y: cy + 80,
57
- fontSize: subtitleFontSize,
58
- color: '#aaaaaa',
59
- align: 'center'
60
- }] : []),
61
-
62
- // 分隔线
63
- { type: 'line', x1: cx - 200, y1: cy + 50, x2: cx + 200, y2: cy + 50, stroke: accent, strokeWidth: 2 }
64
- ]
65
-
66
- return await createFromConfig(project, canvas, { components })
67
- }
68
-
69
- module.exports = applyModernTemplate
@@ -1,58 +0,0 @@
1
- /**
2
- * Simple(简约留白风格)模板
3
- * 使用组件化方式实现
4
- */
5
-
6
- const { createFromConfig } = require('../composer')
7
-
8
- /**
9
- * 应用简约风格模板
10
- */
11
- async function applySimpleTemplate(project, canvas, args) {
12
- const { title, subtitle, background, accentColor } = args
13
- const cx = canvas.width / 2
14
- const cy = canvas.height / 2
15
-
16
- const bg = background || '#f5f5f5'
17
- const accent = accentColor || '#333333'
18
-
19
- const titleFontSize = Math.min(100, canvas.width / 12)
20
- const subtitleFontSize = Math.min(36, canvas.width / 28)
21
-
22
- const components = [
23
- // 背景
24
- { type: 'background', color: bg },
25
-
26
- // 装饰线条
27
- { type: 'line', x1: cx - 100, y1: cy - 80, x2: cx + 100, y2: cy - 80, stroke: accent, strokeWidth: 1 },
28
-
29
- // 主标题
30
- {
31
- type: 'artText',
32
- text: title,
33
- x: cx,
34
- y: cy - 20,
35
- fontSize: titleFontSize,
36
- gradient: { colors: [accent, '#666666'] },
37
- shadow: { color: 'rgba(0,0,0,0.1)', blur: 5 }
38
- },
39
-
40
- // 副标题
41
- ...(subtitle ? [{
42
- type: 'text',
43
- text: subtitle,
44
- x: cx,
45
- y: cy + 60,
46
- fontSize: subtitleFontSize,
47
- color: '#666666',
48
- align: 'center'
49
- }] : []),
50
-
51
- // 装饰线条
52
- { type: 'line', x1: cx - 100, y1: cy + 100, x2: cx + 100, y2: cy + 100, stroke: accent, strokeWidth: 1 }
53
- ]
54
-
55
- return await createFromConfig(project, canvas, { components })
56
- }
57
-
58
- module.exports = applySimpleTemplate
@@ -1,62 +0,0 @@
1
- /**
2
- * Social(社交媒体风格)模板
3
- * 使用组件化方式实现
4
- */
5
-
6
- const { createFromConfig } = require('../composer')
7
-
8
- /**
9
- * 应用社交媒体风格模板
10
- */
11
- async function applySocialTemplate(project, canvas, args) {
12
- const { title, subtitle, background, accentColor } = args
13
- const cx = canvas.width / 2
14
- const cy = canvas.height / 2
15
-
16
- const bg = background || '#2d3436'
17
- const accent = accentColor || '#e84393'
18
-
19
- const titleFontSize = Math.min(72, canvas.width / 14)
20
- const subtitleFontSize = Math.min(32, canvas.width / 30)
21
- const frameRadius = Math.min(250, canvas.width / 3)
22
-
23
- const components = [
24
- // 背景
25
- { type: 'background', color: bg },
26
-
27
- // 中心圆形边框
28
- { type: 'circle', cx: cx, cy: cy - 50, rx: frameRadius, stroke: accent, strokeWidth: 6, fill: 'transparent' },
29
- { type: 'circle', cx: cx, cy: cy - 50, rx: frameRadius - 20, stroke: accent, strokeWidth: 1, opacity: 0.5, fill: 'transparent' },
30
-
31
- // 主标题
32
- {
33
- type: 'artText',
34
- text: title,
35
- x: cx,
36
- y: cy - 30,
37
- fontSize: titleFontSize,
38
- gradient: { colors: ['#ffffff', '#e0e0e0'] },
39
- shadow: { color: accent, blur: 15 }
40
- },
41
-
42
- // 副标题
43
- ...(subtitle ? [{
44
- type: 'text',
45
- text: subtitle,
46
- x: cx,
47
- y: cy + 40,
48
- fontSize: subtitleFontSize,
49
- color: '#dddddd',
50
- align: 'center'
51
- }] : []),
52
-
53
- // 底部装饰点
54
- { type: 'circle', cx: cx - 30, cy: cy + 120, rx: 5, fill: accent, opacity: 0.5 },
55
- { type: 'circle', cx: cx, cy: cy + 120, rx: 5, fill: accent, opacity: 0.7 },
56
- { type: 'circle', cx: cx + 30, cy: cy + 120, rx: 5, fill: accent, opacity: 0.9 }
57
- ]
58
-
59
- return await createFromConfig(project, canvas, { components })
60
- }
61
-
62
- module.exports = applySocialTemplate
@@ -1,84 +0,0 @@
1
- /**
2
- * Tech(科技感)模板
3
- */
4
-
5
- const { createFromConfig } = require('../composer')
6
-
7
- /**
8
- * 应用科技风格模板
9
- */
10
- async function applyTechTemplate(project, canvas, args) {
11
- const { title, subtitle, background, accentColor } = args
12
- const cx = canvas.width / 2
13
- const cy = canvas.height / 2
14
-
15
- const bg = background || '#0a0a0a'
16
- const accent = accentColor || '#00ff00'
17
-
18
- const titleFontSize = Math.min(100, canvas.width / 12)
19
- const subtitleFontSize = Math.min(32, canvas.width / 28)
20
-
21
- // 计算网格位置
22
- const gridItems = []
23
- const cols = 5
24
- const rows = 3
25
- const gridWidth = canvas.width * 0.8
26
- const gridHeight = canvas.height * 0.3
27
- const cellWidth = gridWidth / cols
28
- const cellHeight = gridHeight / rows
29
- const gridX = (canvas.width - gridWidth) / 2
30
- const gridY = canvas.height * 0.7
31
-
32
- for (let i = 0; i < cols; i++) {
33
- for (let j = 0; j < rows; j++) {
34
- gridItems.push({
35
- type: 'rectangle',
36
- x: gridX + i * cellWidth,
37
- y: gridY + j * cellHeight,
38
- width: cellWidth - 10,
39
- height: cellHeight - 10,
40
- stroke: accent,
41
- strokeWidth: 0.5,
42
- opacity: 0.3
43
- })
44
- }
45
- }
46
-
47
- const components = [
48
- // 背景
49
- { type: 'background', color: bg },
50
-
51
- // 顶部装饰线
52
- { type: 'line', x1: 0, y1: 50, x2: canvas.width * 0.3, y2: 50, stroke: accent, strokeWidth: 2 },
53
- { type: 'line', x1: canvas.width * 0.7, y1: 50, x2: canvas.width, y2: 50, stroke: accent, strokeWidth: 2 },
54
-
55
- // 主标题(霓虹效果)
56
- {
57
- type: 'artText',
58
- text: title,
59
- x: cx,
60
- y: cy,
61
- fontSize: titleFontSize,
62
- gradient: { colors: [accent, '#00ffff'] },
63
- shadow: { color: accent, blur: 30 }
64
- },
65
-
66
- // 副标题
67
- ...(subtitle ? [{
68
- type: 'text',
69
- text: subtitle,
70
- x: cx,
71
- y: cy + 80,
72
- fontSize: subtitleFontSize,
73
- color: '#888888',
74
- align: 'center'
75
- }] : []),
76
-
77
- // 网格装饰
78
- ...gridItems
79
- ]
80
-
81
- return await createFromConfig(project, canvas, { components })
82
- }
83
-
84
- module.exports = applyTechTemplate
@@ -1,84 +0,0 @@
1
- /**
2
- * 图片加载工具 - 使用 canvas loadImage 加载图片(仅支持本地路径)
3
- */
4
-
5
- const { loadImage } = require('canvas')
6
- const paper = require('paper')
7
- const fs = require('fs')
8
- const path = require('path')
9
-
10
- /**
11
- * 解析图片源(仅支持本地路径)
12
- * @param {string} src - 图片源
13
- * @returns {Promise<{path: string, type: 'local'}>}
14
- */
15
- async function resolveImageSource(src) {
16
- if (!src) {
17
- throw new Error('Image source is required')
18
- }
19
-
20
- // 确保 src 是字符串
21
- if (typeof src !== 'string') {
22
- throw new Error('Image source must be a string')
23
- }
24
-
25
- // 本地路径
26
- let absolutePath = src
27
- if (!path.isAbsolute(absolutePath)) {
28
- absolutePath = path.join(process.cwd(), absolutePath)
29
- }
30
-
31
- if (!fs.existsSync(absolutePath)) {
32
- throw new Error(`图片文件不存在: ${absolutePath}`)
33
- }
34
-
35
- return { path: absolutePath, type: 'local' }
36
- }
37
-
38
- /**
39
- * 加载图片并创建 Paper.js Raster
40
- * @param {paper.Project} project - Paper.js 项目
41
- * @param {string} src - 图片源
42
- * @param {Object} bounds - 边界 {x, y, width?, height?}
43
- * @param {number} opacity - 透明度
44
- * @returns {Promise<{raster: paper.Raster, cleanup: function}>}
45
- */
46
- async function loadImageAsRaster(project, src, bounds = {}, opacity = 1) {
47
- const { x = 0, y = 0, width, height } = bounds
48
-
49
- // 解析图片源
50
- const { path: imgPath } = await resolveImageSource(src)
51
-
52
- // 使用 canvas loadImage 加载
53
- const imageData = await loadImage(imgPath)
54
-
55
- // 创建 Paper.js Raster
56
- const raster = new paper.Raster(imageData)
57
-
58
- // 添加到项目的活动层
59
- if (project && project.activeLayer) {
60
- project.activeLayer.addChild(raster)
61
- }
62
-
63
- // 设置位置和尺寸
64
- if (width && height) {
65
- raster.bounds = new paper.Rectangle(x, y, width, height)
66
- } else if (width) {
67
- const scale = width / raster.width
68
- raster.bounds = new paper.Rectangle(x, y, width, raster.height * scale)
69
- } else if (height) {
70
- const scale = height / raster.height
71
- raster.bounds = new paper.Rectangle(x, y, raster.width * scale, height)
72
- } else {
73
- raster.position = new paper.Point(x, y)
74
- }
75
-
76
- if (opacity !== undefined) raster.opacity = opacity
77
-
78
- return { raster, cleanup: () => {} }
79
- }
80
-
81
- module.exports = {
82
- loadImageAsRaster,
83
- resolveImageSource,
84
- }
@@ -1 +0,0 @@
1
- <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="800" height="600" viewBox="0,0,800,600"><g fill="#ffffff" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="sans-serif" font-weight="normal" font-size="40" text-anchor="middle" style="mix-blend-mode: normal"><text x="400" y="300">背景图片测试</text></g></svg>