Skill: wwlyzzyorg/ppt-generator (version 1.0.0)

--- name: ppt-generator description: 将用户讲稿一键生成乔布斯风极简科技感竖屏HTML演示稿。当用户需要生成PPT、演示文稿、Slides、幻灯片，或要求科技风/极简风/乔布斯风格的演示时触发此技能。输出为单个可直接运行的HTML文件。 --- # PPT Generator 将讲稿转换为乔布斯风极简科技感竖屏HTML演示稿。 ## 设计哲学 - **极简主义** - 一屏只讲一件事 - **强视觉对比** - 深色背景 + 白色文字 - **高留白** - 禁止密集排版 - **强节奏感** - 让观众想继续看 ## 生成流程（必须严格遵循） ### Step 1: 读取讲稿 读取用户原始讲稿，不修改原稿内容。 ### Step 2: 生成提炼版讲稿 将内容精简、增强冲击力、适配演示场景，输出 Markdown 格式。 ### Step 3: 生成乔布斯风标题 为每个章节生成标题，必须满足： - ≤12 字 - 采用以下形式之一：对比式、问题式、断言式、数字式、比喻式 - 自检：是否让人想继续听？ ### Step 4: 设计幻灯片结构 规划页面顺序和类型，参考 [references/slide-types.md](references/slide-types.md)。 ### Step 5: 生成HTML 使用 [assets/template.html](assets/template.html) 作为基础模板生成完整HTML。 ### Step 6: 填充内容 添加动态背景光斑、交互逻辑、平滑切换动画。 ## 输出顺序（必须依次输出） 1. **提炼后的讲稿**（Markdown） 2. **幻灯片结构大纲** 3. **完整HTML代码** ## 视觉规范速查 | 项目 | 规范 | |------|------| | 比例 | 9:16 竖屏 | | 背景 | #000000 或 #0a0a0a + 模糊光斑动画 | | 主文字 | #ffffff | | 辅助文字 | #9ca3af | | 中文字体 | HarmonyOS Sans SC / 思源黑体 | | 英文字体 | Inter / Roboto | | 标题字重 | font-black / font-bold | | 正文字重 | font-light / font-normal | 详细规范见 [references/design-spec.md](references/design-spec.md)。 ## 交互要求 - 键盘 ← → 翻页 - 底部进度导航条 - 平滑切换动画 ## 技术栈 - TailwindCSS（国内CDN） - 复杂页面使用 Vue3（CDN） - 单个HTML文件，可直接打开运行 ## 严禁行为 - 堆字 / 密集排版 - 花哨配色 - 复杂图表 - 横屏比例 - 偏离极简科技风 ## 默认规则 - 未指定页数：自动生成 8~20 页 - 未指定风格：默认乔布斯风

path: assets/template.html
content: <!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>演示文稿</title>
  
  <!-- TailwindCSS CDN -->
  <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/tailwindcss/3.0.23/tailwind.min.js"></script>
  
  <!-- 字体 -->
  <link href="https://fonts.loli.net/css2?family=Inter:wght@300;400;700;900&display=swap" rel="stylesheet">
  <link href="https://fonts.loli.net/css2?family=Noto+Sans+SC:wght@300;400;700;900&display=swap" rel="stylesheet">
  
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      font-family: 'Noto Sans SC', 'Inter', sans-serif;
      background: #000;
      color: #fff;
      overflow: hidden;
    }
    
    /* 幻灯片容器 */
    .slides-container {
      width: 100vw;
      height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
      background: #0a0a0a;
    }
    
    /* 单个幻灯片 */
    .slide {
      width: 100%;
      height: 100%;
      max-width: 450px;
      max-height: 800px;
      aspect-ratio: 9/16;
      position: absolute;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      padding: 2rem;
      opacity: 0;
      transform: translateX(100%);
      transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
      overflow: hidden;
      background: linear-gradient(180deg, #0a0a0a 0%, #000000 100%);
    }
    
    .slide.active {
      opacity: 1;
      transform: translateX(0);
    }
    
    .slide.prev {
      opacity: 0;
      transform: translateX(-100%);
    }
    
    /* 动态光斑 */
    .light-spot {
      position: absolute;
      border-radius: 50%;
      filter: blur(100px);
      opacity: 0.3;
      pointer-events: none;
    }
    
    .light-spot-1 {
      width: 300px;
      height: 300px;
      background: #3b82f6;
      top: -100px;
      right: -100px;
      animation: float1 20s ease-in-out infinite;
    }
    
    .light-spot-2 {
      width: 250px;
      height: 250px;
      background: #8b5cf6;
      bottom: -80px;
      left: -80px;
      animation: float2 25s ease-in-out infinite;
    }
    
    .light-spot-3 {
      width: 200px;
      height: 200px;
      background: #06b6d4;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      animation: float3 18s ease-in-out infinite;
    }
    
    @keyframes float1 {
      0%, 100% { transform: translate(0, 0); }
      25% { transform: translate(-50px, 30px); }
      50% { transform: translate(30px, 50px); }
      75% { transform: translate(50px, -20px); }
    }
    
    @keyframes float2 {
      0%, 100% { transform: translate(0, 0); }
      33% { transform: translate(40px, -40px); }
      66% { transform: translate(-30px, 30px); }
    }
    
    @keyframes float3 {
      0%, 100% { transform: translate(-50%, -50%) scale(1); }
      50% { transform: translate(-50%, -50%) scale(1.2); }
    }
    
    /* 内容层 */
    .slide-content {
      position: relative;
      z-index: 10;
      text-align: center;
      width: 100%;
    }
    
    /* 进度条 */
    .progress-bar {
      position: fixed;
      bottom: 20px;
      left: 50%;
      transform: translateX(-50%);
      display: flex;
      gap: 8px;
      z-index: 100;
    }
    
    .progress-dot {
      width: 8px;
      height: 8px;
      border-radius: 50%;
      background: rgba(255,255,255,0.3);
      cursor: pointer;
      transition: all 0.3s;
    }
    
    .progress-dot.active {
      background: #fff;
      transform: scale(1.3);
    }
    
    .progress-dot:hover {
      background: rgba(255,255,255,0.6);
    }
    
    /* 页码 */
    .page-number {
      position: fixed;
      bottom: 50px;
      left: 50%;
      transform: translateX(-50%);
      font-size: 0.875rem;
      color: rgba(255,255,255,0.4);
      z-index: 100;
    }
  </style>
</head>
<body>
  <div class="slides-container">
    
    <!-- 幻灯片 1: 封面页 -->
    <div class="slide active">
      <div class="light-spot light-spot-1"></div>
      <div class="light-spot light-spot-2"></div>
      <div class="slide-content">
        <h1 class="text-5xl font-black mb-6 leading-tight">主标题</h1>
        <p class="text-xl font-light text-gray-400">副标题</p>
      </div>
    </div>
    
    <!-- 幻灯片 2: 标题冲击页 -->
    <div class="slide">
      <div class="light-spot light-spot-2"></div>
      <div class="light-spot light-spot-3"></div>
      <div class="slide-content">
        <h1 class="text-4xl font-black leading-tight">
          冲击力标题<br>第二行
        </h1>
      </div>
    </div>
    
    <!-- 幻灯片 3: 金句强调页 -->
    <div class="slide">
      <div class="light-spot light-spot-1"></div>
      <div class="light-spot light-spot-3"></div>
      <div class="slide-content">
        <span class="text-6xl text-gray-600 block mb-2">"</span>
        <p class="text-2xl font-bold mb-6">金句内容</p>
        <span class="text-lg font-light text-gray-500">— 来源</span>
      </div>
    </div>
    
    <!-- 幻灯片 4: 结尾行动页 -->
    <div class="slide">
      <div class="light-spot light-spot-1"></div>
      <div class="light-spot light-spot-2"></div>
      <div class="light-spot light-spot-3"></div>
      <div class="slide-content">
        <h1 class="text-3xl font-bold mb-8">总结金句</h1>
        <p class="text-xl font-light text-gray-400">行动号召</p>
      </div>
    </div>
    
  </div>
  
  <!-- 进度条 -->
  <div class="progress-bar" id="progressBar"></div>
  
  <!-- 页码 -->
  <div class="page-number" id="pageNumber">1 / 4</div>
  
  <script>
    const slides = document.querySelectorAll('.slide');
    const progressBar = document.getElementById('progressBar');
    const pageNumber = document.getElementById('pageNumber');
    let currentSlide = 0;
    
    // 初始化进度条
    slides.forEach((_, index) => {
      const dot = document.createElement('div');
      dot.className = `progress-dot ${index === 0 ? 'active' : ''}`;
      dot.addEventListener('click', () => goToSlide(index));
      progressBar.appendChild(dot);
    });
    
    function updateSlides() {
      slides.forEach((slide, index) => {
        slide.classList.remove('active', 'prev');
        if (index === currentSlide) {
          slide.classList.add('active');
        } else if (index < currentSlide) {
          slide.classList.add('prev');
        }
      });
      
      // 更新进度条
      document.querySelectorAll('.progress-dot').forEach((dot, index) => {
        dot.classList.toggle('active', index === currentSlide);
      });
      
      // 更新页码
      pageNumber.textContent = `${currentSlide + 1} / ${slides.length}`;
    }
    
    function nextSlide() {
      if (currentSlide < slides.length - 1) {
        currentSlide++;
        updateSlides();
      }
    }
    
    function prevSlide() {
      if (currentSlide > 0) {
        currentSlide--;
        updateSlides();
      }
    }
    
    function goToSlide(index) {
      currentSlide = index;
      updateSlides();
    }
    
    // 键盘控制
    document.addEventListener('keydown', (e) => {
      if (e.key === 'ArrowRight' || e.key === ' ') {
        nextSlide();
      } else if (e.key === 'ArrowLeft') {
        prevSlide();
      }
    });
    
    // 触摸滑动支持
    let touchStartX = 0;
    document.addEventListener('touchstart', (e) => {
      touchStartX = e.touches[0].clientX;
    });
    
    document.addEventListener('touchend', (e) => {
      const touchEndX = e.changedTouches[0].clientX;
      const diff = touchStartX - touchEndX;
      if (Math.abs(diff) > 50) {
        if (diff > 0) nextSlide();
        else prevSlide();
      }
    });
  </script>
</body>
</html>


path: agents/openai.yaml
content: interface:
  display_name: "PPT Generator"
  short_description: "将讲稿一键生成乔布斯风极简科技感竖屏HTML演示稿"
  default_prompt: "请根据我的讲稿生成科技风PPT"


path: references/slide-types.md
content: # 幻灯片页面类型

## 1. 封面页

用于演示开场。

**结构：**
- 超大主标题（font-black，居中）
- 副标语（font-light，灰色）
- 系列标识/Logo（可选）

**示例：**
```html
<div class="slide cover">
  <h1 class="text-5xl font-black text-white mb-6">重新定义效率</h1>
  <p class="text-xl font-light text-gray-400">AI时代的工作方式</p>
</div>
```

---

## 2. 标题冲击页

用于章节开始或重点强调。

**结构：**
- 单行/双行大标题
- 几乎无正文（最多一行辅助文字）

**示例：**
```html
<div class="slide impact">
  <h1 class="text-4xl font-black text-white text-center">
    不是更努力<br>而是更聪明
  </h1>
</div>
```

---

## 3. 金句强调页

用于引用、名言、核心观点。

**结构：**
- 大引号装饰
- 金句内容（font-bold）
- 来源/出处（font-light，灰色）

**示例：**
```html
<div class="slide quote">
  <span class="text-6xl text-gray-600">"</span>
  <p class="text-2xl font-bold text-white my-6">
    简单比复杂更难
  </p>
  <span class="text-lg font-light text-gray-500">— Steve Jobs</span>
</div>
```

---

## 4. 步骤说明页

用于流程、方法、操作指南。

**结构：**
- 动词型大标题
- 简洁说明（1-2行）
- 可选：步骤编号

**示例：**
```html
<div class="slide step">
  <span class="text-6xl font-black text-blue-500 mb-4">01</span>
  <h2 class="text-3xl font-bold text-white mb-4">明确目标</h2>
  <p class="text-lg font-light text-gray-400">
    先问自己：这件事最重要的结果是什么？
  </p>
</div>
```

---

## 5. 对比页

用于展示变化、差异、前后对比。

**结构：**
- 左右或上下分栏
- 对比元素使用不同颜色标识
- 简洁文字说明

**示例：**
```html
<div class="slide compare">
  <div class="text-center mb-8">
    <span class="text-red-400 line-through text-xl">传统方式</span>
  </div>
  <div class="text-center">
    <span class="text-green-400 text-3xl font-bold">全新体验</span>
  </div>
</div>
```

---

## 6. 数据展示页

用于关键数字、统计、成果。

**结构：**
- 超大数字（font-black）
- 单位/说明（font-light）
- 简短解释

**示例：**
```html
<div class="slide data">
  <span class="text-7xl font-black text-white">10x</span>
  <p class="text-xl font-light text-gray-400 mt-4">效率提升</p>
</div>
```

---

## 7. 列表页

用于多点说明，但必须保持极简。

**结构：**
- 标题
- 3-5 个要点（不能更多）
- 每个要点 ≤10 字

**示例：**
```html
<div class="slide list">
  <h2 class="text-2xl font-bold text-white mb-8">三个原则</h2>
  <ul class="space-y-6 text-xl">
    <li class="text-gray-300">• 少即是多</li>
    <li class="text-gray-300">• 专注核心</li>
    <li class="text-gray-300">• 持续迭代</li>
  </ul>
</div>
```

---

## 8. 结尾行动页

用于演示结束，呼吁行动。

**结构：**
- 总结金句
- 行动号召（CTA）
- 联系方式/二维码（可选）

**示例：**
```html
<div class="slide ending">
  <h1 class="text-3xl font-bold text-white mb-8">
    现在就开始改变
  </h1>
  <p class="text-xl font-light text-gray-400">
    扫码获取更多信息
  </p>
</div>
```

---

## 页面选择指南

| 内容类型 | 推荐页面类型 |
|---------|-------------|
| 演示开场 | 封面页 |
| 章节分隔 | 标题冲击页 |
| 核心观点 | 金句强调页 |
| 操作步骤 | 步骤说明页 |
| 前后对比 | 对比页 |
| 关键数据 | 数据展示页 |
| 多点说明 | 列表页（≤5点）|
| 演示结束 | 结尾行动页 |


path: references/design-spec.md
content: # 设计规范详细文档

## 背景效果

### 主背景
- 主色：#000000 或 #0a0a0a
- 深色渐变底色

### 动态光斑（必须包含）
每页必须包含 1~3 个模糊光斑：

```css
.light-spot {
  position: absolute;
  width: 300px;
  height: 300px;
  border-radius: 50%;
  filter: blur(100px);
  opacity: 0.3;
  animation: float 20s ease-in-out infinite;
}

.light-spot-1 { background: #3b82f6; }  /* 蓝色 */
.light-spot-2 { background: #8b5cf6; }  /* 紫色 */
.light-spot-3 { background: #06b6d4; }  /* 青色 */

@keyframes float {
  0%, 100% { transform: translate(0, 0); }
  25% { transform: translate(50px, -30px); }
  50% { transform: translate(-30px, 50px); }
  75% { transform: translate(-50px, -20px); }
}
```

## 字体加载（国内CDN）

```html
<!-- HarmonyOS Sans SC -->
<link href="https://s1.hdslb.com/bfs/static/jinkela/long/font/regular.css" rel="stylesheet">

<!-- 思源黑体备选 -->
<link href="https://fonts.loli.net/css2?family=Noto+Sans+SC:wght@300;400;700;900&display=swap" rel="stylesheet">

<!-- Inter 英文字体 -->
<link href="https://fonts.loli.net/css2?family=Inter:wght@300;400;700;900&display=swap" rel="stylesheet">
```

## 排版层级

```css
/* H1 超大标题 */
.slide-title {
  font-size: 3rem;      /* 48px */
  font-weight: 900;     /* font-black */
  line-height: 1.2;
  color: #ffffff;
}

/* H2 副标题 */
.slide-subtitle {
  font-size: 1.5rem;    /* 24px */
  font-weight: 700;     /* font-bold */
  color: #ffffff;
}

/* P 说明文字 */
.slide-text {
  font-size: 1.125rem;  /* 18px */
  font-weight: 300;     /* font-light */
  color: #9ca3af;
}
```

## 间距规范

- 元素间距：space-y-8 以上（32px+）
- 页面内边距：p-8 或 p-12
- 内容居中：flex items-center justify-center

## 页面容器

```css
.slide {
  width: 100%;
  height: 100vh;
  aspect-ratio: 9/16;
  max-width: 450px;      /* 竖屏限制 */
  margin: 0 auto;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 2rem;
}
```

## 切换动画

```css
.slide {
  opacity: 0;
  transform: translateX(100%);
  transition: all 0.5s ease-out;
}

.slide.active {
  opacity: 1;
  transform: translateX(0);
}

.slide.prev {
  transform: translateX(-100%);
}
```


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)