Преглед изворни кода

feat: 新增六顶思考帽工具

1.  新增六顶思考帽工具类型832并配置多语言文案
2.  添加六顶思考帽详情组件与横幅图片
3.  在工具栏中集成六顶思考帽工具入口
4.  更新各处工具类型映射表与工具列表
lsc пре 1 недеља
родитељ
комит
9545ef6caf

BIN
src/assets/img/sixHatBanner.jpg


+ 1 - 0
src/components/CollapsibleToolbar/cocolearnCom/KwlDetail.vue

@@ -381,6 +381,7 @@ const handleAddToSlide = () => {
   overflow: hidden;
   // width: 100%;
   height: 140px;
+  min-height: 140px;
   position: relative;
   box-sizing: border-box;
 

+ 796 - 0
src/components/CollapsibleToolbar/cocolearnCom/SixHatDetail.vue

@@ -0,0 +1,796 @@
+<template>
+  <div class="six-hat-detail">
+    <!-- 头部导航 -->
+    <div class="detail-header">
+      <div class="back-btn" @click="$emit('back')">
+        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+          <path d="M15 18l-6-6 6-6" />
+        </svg>
+      </div>
+      <div class="detail-title">{{ lang.ssSixHatTitle }}</div>
+    </div>
+
+    <!-- Banner 区域 -->
+    <div class="detail-banner">
+      <img :src="sixHat" :alt="lang.ssSixHatTitle" />
+      <div class="tool-overly"></div>
+      <div class="tool-icon-badge">
+        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+          <path d="M9 18h6M10 22h4M12 2a7 7 0 00-4 12.7c.6.5 1 1.3 1 2.3h6c0-1 .4-1.8 1-2.3A7 7 0 0012 2z"></path>
+        </svg>
+      </div>
+    </div>
+
+    <!-- 描述与标签 -->
+    <div class="detail-desc-row">
+      <div class="detail-desc-text">{{ lang.ssSixHatDesc }}</div>
+      <div class="help-icon" @mouseenter="showHelp = true" @mouseleave="showHelp = false">
+        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+          <circle cx="12" cy="12" r="10" />
+          <path d="M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3" />
+          <line x1="12" y1="17" x2="12.01" y2="17" />
+        </svg>
+        <!-- 帮助气泡 -->
+        <div v-if="showHelp" class="help-tooltip">
+          <div class="help-title">{{ lang.ssSixHatUsageScenario }}</div>
+          <div class="help-text">{{ lang.ssSixHatScenarioText }}</div>
+          <div class="help-title">{{ lang.ssSixHatSteps }}</div>
+          <div class="help-list">
+            <div class="help-step"><span class="step-num">1</span><span>{{ lang.ssSixHatStep1 }}</span></div>
+            <div class="help-step"><span class="step-num">2</span><span>{{ lang.ssSixHatStep2 }}</span></div>
+            <div class="help-step"><span class="step-num">3</span><span>{{ lang.ssSixHatStep3 }}</span></div>
+            <div class="help-step"><span class="step-num">4</span><span>{{ lang.ssSixHatStep4 }}</span></div>
+            <div class="help-step"><span class="step-num">5</span><span>{{ lang.ssSixHatStep5 }}</span></div>
+            <div class="help-step"><span class="step-num">6</span><span>{{ lang.ssSixHatStep6 }}</span></div>
+          </div>
+          <div class="help-source">{{ lang.ssSixHatSource }}</div>
+          <div class="help-purpose">{{ lang.ssSixHatPurpose }}</div>
+        </div>
+      </div>
+    </div>
+    <div class="detail-tags">
+      <span class="detail-tag">{{ lang.ssSixHatGradeRange }}</span>
+    </div>
+
+    <!-- 工具配置区 -->
+    <div class="config-section">
+      <div class="config-title">{{ lang.ssKwlToolConfig }}</div>
+      <div class="config-subtitle">{{ lang.ssKwlConfigSubtitle }}</div>
+    </div>
+
+    <!-- 配置项卡片 -->
+    <div class="config-card">
+      <!-- 工具内容由使用者配置 -->
+      <div class="config-row config-row-highlight">
+        <div class="form-text-block">
+          <div class="form-label">{{ lang.ssSixHatUserConfig }}</div>
+          <div class="form-sublabel">{{ lang.ssSixHatUserConfigDesc }}</div>
+        </div>
+        <div class="toggle-switch" :class="{ active: formData.enableContentConfigurable }"
+          @click="formData.enableContentConfigurable = !formData.enableContentConfigurable">
+          <div class="toggle-thumb"></div>
+        </div>
+      </div>
+
+      <!-- 小组合作 -->
+      <div class="config-row">
+        <div class="form-text-block">
+          <div class="form-label">{{ lang.ssSixHatGroupWork }}</div>
+          <div class="form-sublabel">{{ lang.ssSixHatGroupWorkDesc }}</div>
+        </div>
+        <div class="toggle-switch" :class="{ active: formData.enableMemberSelect }"
+          @click="formData.enableMemberSelect = !formData.enableMemberSelect">
+          <div class="toggle-thumb"></div>
+        </div>
+      </div>
+
+      <!-- 默认展开操作提示 -->
+      <div class="config-row">
+        <div class="form-text-block">
+          <div class="form-label">{{ lang.ssKwlShowHowTo }}</div>
+          <div class="form-sublabel">{{ lang.ssKwlShowHowToDesc }}</div>
+        </div>
+        <div class="toggle-switch" :class="{ active: formData.autoExpandHowTo }"
+          @click="formData.autoExpandHowTo = !formData.autoExpandHowTo">
+          <div class="toggle-thumb"></div>
+        </div>
+      </div>
+
+      <!-- 高级配置 -->
+      <div class="advanced-section">
+        <div class="advanced-header" @click="showAdvanced = !showAdvanced">
+          <span class="advanced-title">{{ lang.ssKwlAdvanced }}</span>
+          <svg class="advanced-arrow" :class="{ expanded: showAdvanced }" width="16" height="16" viewBox="0 0 24 24"
+            fill="none" stroke="currentColor" stroke-width="2">
+            <polyline points="6 9 12 15 18 9" />
+          </svg>
+        </div>
+
+        <div v-if="showAdvanced" class="advanced-body">
+          <!-- 显示计时器 -->
+          <div class="config-row config-row-borderless">
+            <div class="form-text-block">
+              <div class="form-label">{{ lang.ssSixHatShowTimer }}</div>
+            </div>
+            <div class="toggle-switch" :class="{ active: formData.timerEnabled }"
+              @click="formData.timerEnabled = !formData.timerEnabled">
+              <div class="toggle-thumb"></div>
+            </div>
+          </div>
+
+          <!-- 计时时长 -->
+          <div v-if="formData.timerEnabled" class="timer-duration">
+            <div class="duration-label">{{ lang.ssSixHatTimerDuration }}</div>
+            <div class="duration-options">
+              <div v-for="item in timerOptions" :key="item" class="duration-chip"
+                :class="{ active: !customTimerActive && formData.timerDuration === item }"
+                @click="selectTimerDuration(item)">
+                {{ item }}{{ lang.ssSixHatTimerSeconds }}
+              </div>
+              <div class="duration-chip" :class="{ active: customTimerActive }" @click="selectCustomTimer">
+                {{ lang.ssCustom }}
+              </div>
+            </div>
+            <!-- 自定义时长输入 -->
+            <div v-if="customTimerActive" class="custom-timer">
+              <input v-model="customTimerInput" type="number" min="10" max="3600" step="10"
+                @change="handleCustomTimerInput" @keyup.enter="handleCustomTimerInput" />
+              <span class="custom-unit">{{ lang.ssSixHatTimerSeconds }}</span>
+            </div>
+          </div>
+
+          <!-- 思考帽选择 -->
+          <div class="hats-select">
+            <div class="duration-label">{{ lang.ssSixHatSelectHats }}</div>
+            <div class="hats-options">
+              <div v-for="hat in hatList" :key="hat.key" class="hat-chip"
+                :class="[`hat-${hat.key}`, { active: formData.hats.includes(hat.key) }]"
+                @click="toggleHat(hat.key)">
+                <span class="hat-dot"></span>
+                {{ hat.label }}
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 添加到幻灯片按钮 -->
+    <div class="footer-btn">
+      <div class="add-btn" @click="handleAddToSlide">{{ lang.ssKwlAddToSlide }}</div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive } from 'vue'
+import sixHat from '@/assets/img/sixHatBanner.jpg'
+import { lang } from '@/main'
+
+const emit = defineEmits<{
+  (e: 'back'): void
+  (e: 'add', data: any): void
+}>()
+
+const showHelp = ref(false)
+const showAdvanced = ref(false)
+
+const timerOptions = [30, 60, 120, 180, 300]
+const customTimerActive = ref(false)
+const customTimerInput = ref<number>(60)
+
+const hatList = [
+  { key: 'white', label: lang.ssSixHatWhite },
+  { key: 'red', label: lang.ssSixHatRed },
+  { key: 'black', label: lang.ssSixHatBlack },
+  { key: 'yellow', label: lang.ssSixHatYellow },
+  { key: 'green', label: lang.ssSixHatGreen },
+  { key: 'blue', label: lang.ssSixHatBlue }
+]
+
+const formData = reactive({
+  stage: 'member',
+  isSetting: true,
+  members: [] as string[],
+  scenario: '',
+  timerEnabled: true,
+  timerDuration: 60,
+  timerCustomValue: 60,
+  hats: ['white', 'red', 'black', 'yellow', 'green', 'blue'] as string[],
+  hatContent: {} as Record<string, string>,
+  enableMemberSelect: false,
+  enableContentConfigurable: true,
+  autoExpandHowTo: false,
+  customScenario: '',
+  customTimerEnabled: true,
+  customTimerDuration: 60,
+  customHats: null as string[] | null
+})
+
+const CUSTOM_TIMER_MIN = 10
+const CUSTOM_TIMER_MAX = 3600
+
+const selectTimerDuration = (value: number) => {
+  customTimerActive.value = false
+  formData.timerDuration = value
+  formData.timerCustomValue = value
+}
+
+const selectCustomTimer = () => {
+  customTimerActive.value = true
+  applyCustomTimer()
+}
+
+const applyCustomTimer = () => {
+  formData.timerCustomValue = customTimerInput.value
+  formData.timerDuration = customTimerInput.value
+}
+
+const handleCustomTimerInput = () => {
+  let val = Number(customTimerInput.value)
+  if (!val || Number.isNaN(val)) val = 60
+  val = Math.round(val)
+  val = Math.max(CUSTOM_TIMER_MIN, Math.min(CUSTOM_TIMER_MAX, val))
+  customTimerInput.value = val
+  applyCustomTimer()
+}
+
+const toggleHat = (key: string) => {
+  const index = formData.hats.indexOf(key)
+  if (index > -1) {
+    // 至少保留一顶帽子
+    if (formData.hats.length === 1) return
+    formData.hats.splice(index, 1)
+  }
+  else {
+    // 按固定顺序插入,保持帽子次序
+    const order = hatList.map(h => h.key)
+    formData.hats.push(key)
+    formData.hats.sort((a, b) => order.indexOf(a) - order.indexOf(b))
+  }
+}
+
+const handleAddToSlide = () => {
+  emit('add', {
+    ...formData,
+    members: [...formData.members],
+    hats: [...formData.hats],
+    hatContent: { ...formData.hatContent }
+  })
+}
+</script>
+
+<style lang="scss" scoped>
+.six-hat-detail {
+  display: flex;
+  flex-direction: column;
+  height: calc(100% - 75px);
+  overflow-y: auto;
+  overflow-x: hidden;
+  padding: 0 0 20px;
+}
+
+/* 头部 */
+.detail-header {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  padding: 0 14px;
+  position: sticky;
+  top: 0;
+  background: #fff;
+  z-index: 10;
+  margin-bottom: 20px;
+
+  .back-btn {
+    width: 32px;
+    height: 32px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 8px;
+    cursor: pointer;
+    color: #6b7280;
+    transition: all 0.2s ease;
+
+    &:hover {
+      background: #f3f4f6;
+      color: #374151;
+    }
+  }
+
+  .detail-title {
+    font-size: 16px;
+    font-weight: 600;
+    color: #1f2937;
+  }
+}
+
+/* Banner */
+.detail-banner {
+  margin: 0 14px 14px;
+  border-radius: 12px;
+  overflow: hidden;
+  height: 140px;
+  min-height: 140px;
+  position: relative;
+  box-sizing: border-box;
+
+  .tool-overly {
+    position: absolute;
+    inset: 0;
+    background-color: #f59e0b;
+    opacity: .35;
+    pointer-events: none;
+  }
+
+  .tool-icon-badge {
+    position: absolute;
+    top: 10px;
+    left: 10px;
+    width: 32px;
+    height: 32px;
+    border-radius: 8px;
+    background: rgba(255, 255, 255, 0.95);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
+
+    svg {
+      width: 18px;
+      height: 18px;
+      color: #f59e0b;
+    }
+  }
+
+  img {
+    width: 100%;
+    height: 140px;
+    object-fit: cover;
+    display: block;
+  }
+}
+
+/* 描述 */
+.detail-desc-row {
+  display: flex;
+  align-items: flex-start;
+  gap: 8px;
+  padding: 0 14px;
+
+  .detail-desc-text {
+    flex: 1;
+    font-size: 13px;
+    color: #4b5563;
+    line-height: 1.6;
+  }
+
+  .help-icon {
+    position: relative;
+    color: #9ca3af;
+    cursor: pointer;
+    flex-shrink: 0;
+    margin-top: 2px;
+
+    &:hover {
+      color: #FF9300;
+    }
+
+    .help-tooltip {
+      position: absolute;
+      top: 100%;
+      right: 0;
+      margin-top: 8px;
+      width: 250px;
+      background: #fff;
+      border: 1px solid #e5e7eb;
+      border-radius: 10px;
+      padding: 14px;
+      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
+      z-index: 100;
+
+      .help-title {
+        font-size: 13px;
+        font-weight: 600;
+        color: #1f2937;
+        margin-bottom: 4px;
+        margin-top: 8px;
+
+        &:first-child {
+          margin-top: 0;
+        }
+      }
+
+      .help-text {
+        font-size: 12px;
+        color: #6b7280;
+        margin-bottom: 4px;
+      }
+
+      .help-list {
+        font-size: 12px;
+        color: #4b5563;
+        line-height: 1.6;
+
+        .help-step {
+          display: flex;
+          align-items: flex-start;
+          gap: 8px;
+          padding: 3px 0;
+
+          .step-num {
+            flex-shrink: 0;
+            width: 18px;
+            height: 18px;
+            margin-top: 1px;
+            border-radius: 50%;
+            background: #FF9300;
+            color: #fff;
+            font-size: 11px;
+            font-weight: 600;
+            line-height: 1;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+          }
+        }
+      }
+
+      .help-source,
+      .help-purpose {
+        font-size: 11px;
+        color: #9ca3af;
+        margin-top: 8px;
+        line-height: 1.5;
+      }
+    }
+  }
+}
+
+.detail-tags {
+  display: flex;
+  gap: 6px;
+  padding: 10px 14px 0;
+
+  .detail-tag {
+    display: inline-block;
+    padding: 3px 10px;
+    font-size: 11px;
+    color: #3b82f6;
+    background: #eff6ff;
+    border-radius: 4px;
+    font-weight: 500;
+  }
+}
+
+/* 配置区 */
+.config-section {
+  padding: 20px 14px 12px;
+
+  .config-title {
+    font-size: 16px;
+    font-weight: 600;
+    color: #1f2937;
+    margin-bottom: 6px;
+  }
+
+  .config-subtitle {
+    font-size: 12px;
+    color: #6b7280;
+    line-height: 1.6;
+  }
+}
+
+/* 配置卡片 */
+.config-card {
+  margin: 0 14px;
+  background: #f8f9fb;
+  border-radius: 14px;
+  padding: 8px 14px;
+}
+
+.config-row {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: 12px;
+  padding: 16px 0;
+  border-bottom: 1px solid #eceef2;
+
+  &:last-child {
+    border-bottom: none;
+  }
+
+  .form-label {
+    font-size: 14px;
+    font-weight: 500;
+    color: #374151;
+  }
+
+  .form-sublabel {
+    font-size: 12px;
+    color: #9ca3af;
+    margin-top: 3px;
+    line-height: 1.5;
+  }
+
+  &.config-row-borderless {
+    border-bottom: none;
+    padding-bottom: 8px;
+  }
+}
+
+/* 使用者配置高亮行 */
+.config-row-highlight {
+  background: #fff4e8;
+  border-radius: 12px;
+  border-bottom: none;
+  padding: 16px;
+  margin: 6px 0;
+
+  .form-label {
+    color: #1f2937;
+    font-weight: 600;
+  }
+
+  .form-sublabel {
+    color: #b0825c;
+  }
+}
+
+/* 开关 */
+.toggle-switch {
+  width: 44px;
+  height: 24px;
+  border-radius: 12px;
+  background: #d1d5db;
+  position: relative;
+  cursor: pointer;
+  transition: background 0.25s ease;
+  flex-shrink: 0;
+
+  .toggle-thumb {
+    width: 20px;
+    height: 20px;
+    border-radius: 50%;
+    background: #fff;
+    position: absolute;
+    top: 2px;
+    left: 2px;
+    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
+    transition: transform 0.25s ease;
+  }
+
+  &.active {
+    background: #FF9300;
+
+    .toggle-thumb {
+      transform: translateX(20px);
+    }
+  }
+}
+
+/* 高级配置 */
+.advanced-section {
+  .advanced-header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 12px 0;
+    cursor: pointer;
+
+    .advanced-title {
+      font-size: 14px;
+      font-weight: 600;
+      color: #6b7280;
+    }
+
+    .advanced-arrow {
+      color: #9ca3af;
+      transition: transform 0.2s ease;
+
+      &.expanded {
+        transform: rotate(180deg);
+      }
+    }
+  }
+
+  .advanced-body {
+    display: flex;
+    flex-direction: column;
+  }
+}
+
+/* 计时时长 / 帽子选择 */
+.timer-duration,
+.hats-select {
+  padding: 4px 0 14px;
+
+  .duration-label {
+    font-size: 13px;
+    font-weight: 500;
+    color: #374151;
+    margin-bottom: 10px;
+  }
+}
+
+.duration-options {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px;
+}
+
+.duration-chip {
+  padding: 6px 14px;
+  font-size: 12px;
+  color: #6b7280;
+  background: #fff;
+  border: 1px solid #e5e7eb;
+  border-radius: 999px;
+  cursor: pointer;
+  transition: all 0.2s ease;
+
+  &:hover {
+    border-color: #FF9300;
+    color: #FF9300;
+  }
+
+  &.active {
+    background: #FF9300;
+    border-color: #FF9300;
+    color: #fff;
+    font-weight: 600;
+  }
+}
+
+/* 自定义时长输入 */
+.custom-timer {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  margin-top: 10px;
+
+  input {
+    width: 96px;
+    padding: 8px 12px;
+    border: 1px solid #e5e7eb;
+    border-radius: 10px;
+    font-size: 13px;
+    color: #374151;
+    background: #fff;
+    outline: none;
+    transition: border-color 0.2s ease;
+    box-sizing: border-box;
+
+    &::placeholder {
+      color: #9ca3af;
+    }
+
+    &:focus {
+      border-color: #FF9300;
+    }
+
+    // 隐藏 number 输入框的上下箭头
+    &::-webkit-outer-spin-button,
+    &::-webkit-inner-spin-button {
+      -webkit-appearance: none;
+      margin: 0;
+    }
+
+    &[type='number'] {
+      -moz-appearance: textfield;
+      appearance: textfield;
+    }
+  }
+
+  .custom-unit {
+    font-size: 13px;
+    color: #6b7280;
+  }
+}
+
+.hats-options {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px;
+}
+
+.hat-chip {
+  display: inline-flex;
+  align-items: center;
+  gap: 6px;
+  padding: 6px 12px;
+  font-size: 12px;
+  color: #9ca3af;
+  background: #fff;
+  border: 1px solid #e5e7eb;
+  border-radius: 999px;
+  cursor: pointer;
+  transition: all 0.2s ease;
+
+  .hat-dot {
+    width: 10px;
+    height: 10px;
+    border-radius: 50%;
+    background: #d1d5db;
+    transition: background 0.2s ease;
+  }
+
+  &.hat-white.active {
+    color: #374151;
+    border-color: #d1d5db;
+    background: #fff;
+
+    .hat-dot { background: #f3f4f6; border: 1px solid #d1d5db; }
+  }
+
+  &.hat-red.active {
+    color: #ef4444;
+    border-color: #fecaca;
+    background: #fef2f2;
+
+    .hat-dot { background: #ef4444; }
+  }
+
+  &.hat-black.active {
+    color: #fff;
+    border-color: #374151;
+    background: #4b5563;
+
+    .hat-dot { background: #1f2937; }
+  }
+
+  &.hat-yellow.active {
+    color: #b45309;
+    border-color: #fde68a;
+    background: #fffbeb;
+
+    .hat-dot { background: #f59e0b; }
+  }
+
+  &.hat-green.active {
+    color: #15803d;
+    border-color: #bbf7d0;
+    background: #f0fdf4;
+
+    .hat-dot { background: #22c55e; }
+  }
+
+  &.hat-blue.active {
+    color: #1d4ed8;
+    border-color: #bfdbfe;
+    background: #eff6ff;
+
+    .hat-dot { background: #3b82f6; }
+  }
+}
+
+/* 底部按钮 */
+.footer-btn {
+  padding: 16px 14px 0;
+
+  .add-btn {
+    width: 100%;
+    padding: 14px;
+    background: #FF9300;
+    color: #fff;
+    font-size: 15px;
+    font-weight: 600;
+    text-align: center;
+    border-radius: 12px;
+    cursor: pointer;
+    transition: all 0.2s ease;
+
+    &:hover {
+      background: #f57c00;
+      transform: translateY(-1px);
+      box-shadow: 0 4px 12px rgba(255, 147, 0, 0.3);
+    }
+
+    &:active {
+      transform: translateY(0);
+    }
+  }
+}
+</style>

+ 2 - 1
src/components/CollapsibleToolbar/componets/aiChat.vue

@@ -1,4 +1,4 @@
-<template>
+<template>
   <div class="ai-chat-container">
     <div class="message-quick-box">
       <div class="message-quick-box-item" :class="{ 'active': isQuickActions.includes('quick') }">
@@ -583,6 +583,7 @@ const sendAction = async (action: string) => {
       79: lang.ssPhoto,
       84: lang.ssFile,
       831: lang.ssKwlTitle,
+      832: lang.ssSixHatTitle,
     }
     return typeMap[type || 0] || lang.ssUnknown
   }

+ 3 - 1
src/components/CollapsibleToolbar/index.vue

@@ -294,6 +294,7 @@ const getTypeLabel = (type?: number) => {
     79: lang.ssPhoto,
     84: lang.ssFile,
     831: lang.ssKwlTitle,
+    832: lang.ssKwlTitle,
   }
   return typeMap[type || 0] || lang.ssUnknown
 }
@@ -307,7 +308,8 @@ const getTypeClass = (type?: number) => {
     74: 'type-video',
     75: 'type-bilibili',
     76: 'type-app-center',
-    831: 'type-kwl'
+    831: 'type-kwl',
+    832: 'type-kwl-title'
   }
   return classMap[type || 0] || 'type-default'
 }

+ 52 - 3
src/components/CollapsibleToolbar/index2.vue

@@ -737,7 +737,7 @@
           </svg>
         </div>
       </div>
-      <div class="submenu-item-box2" v-if="!showKwlDetail">
+      <div class="submenu-item-box2" v-if="!showKwlDetail && !showSixHatDetail">
         <div class="tool-card kwl-card" @click="handleToolClick('kwl')">
           <div class="tool-banner">
             <img :src="kwl" :alt="lang.ssKwlTitle" />
@@ -759,8 +759,30 @@
               <span>{{ lang.ssClickToViewDetail }}</span>
           </div>
         </div>
+        <div class="tool-card six-hat-card" @click="handleToolClick('sixHat')" v-show="false">
+          <div class="tool-banner">
+            <img :src="sixHat" :alt="lang.ssSixHatTitle" />
+            <div class="tool-overly"></div>
+            <div class="tool-icon-badge">
+              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+                <path d="M9 18h6M10 22h4M12 2a7 7 0 00-4 12.7c.6.5 1 1.3 1 2.3h6c0-1 .4-1.8 1-2.3A7 7 0 0012 2z"></path>
+              </svg>
+            </div>
+          </div>
+          <div class="tool-info">
+            <div class="tool-title">{{ lang.ssSixHatTitle }}</div>
+            <div class="tool-desc">{{ lang.ssSixHatDesc }}</div>
+            <div class="tool-tags">
+              <span class="tool-tag">{{ lang.ssSixHatGradeRange }}</span>
+            </div>
+          </div>
+          <div class="tool-hover-overlay">
+              <span>{{ lang.ssClickToViewDetail }}</span>
+          </div>
+        </div>
       </div>
-      <KwlDetail :banner="kwl" v-else @back="showKwlDetail = false" @add="handleKwlAdd" />
+      <KwlDetail :banner="kwl" v-else-if="showKwlDetail" @back="showKwlDetail = false" @add="handleKwlAdd" />
+      <SixHatDetail v-else @back="showSixHatDetail = false" @add="handleSixHatAdd" />
     </div>
 
 
@@ -789,7 +811,9 @@ import toolPhoto from '@/assets/img/tool_photo.png'
 import toolFile from '@/assets/img/tool_file.png'
 import axios from '@/services/config'
 import kwl from '@/assets/img/kwlBanner.jpg'
+import sixHat from '@/assets/img/sixHatBanner.jpg'
 import KwlDetail from './cocolearnCom/KwlDetail.vue'
+import SixHatDetail from './cocolearnCom/SixHatDetail.vue'
 
 interface ContentItem {
   tool?: number
@@ -834,6 +858,7 @@ const activeSubmenu = ref<string | null>(props.onlyEnglish ? 'english' : null)
 const contentList = ref<ContentItem[]>([])
 const hoveredTool = ref<string | null>(null)
 const showKwlDetail = ref(false)
+const showSixHatDetail = ref(false)
 const webpageUrl = ref('')
 const isLoading = ref(false)
 const isValidUrl = ref<boolean | null>(null) // null: 未输入, true: 有效, false: 无效
@@ -1176,6 +1201,9 @@ const handleToolClick = _.debounce((tool: string) => {
   else if (tool === 'kwl') {
     showKwlDetail.value = true
   }
+  else if (tool === 'sixHat') {
+    showSixHatDetail.value = true
+  }
 }, 300)
 
 const handleKwlAdd = (data: any) => {
@@ -1188,6 +1216,14 @@ const handleKwlAdd = (data: any) => {
   parentWindow?.addTool2?.(831, data)
 }
 
+const handleSixHatAdd = (data: any) => {
+  interface ParentWindowWithToolList extends Window {
+    addTool2?: (id: number, data: any) => void;
+  }
+  const parentWindow = window.parent as ParentWindowWithToolList
+  parentWindow?.addTool2?.(832, data)
+}
+
 const loadContentList = () => {
   try {
     interface ParentWindowWithToolList extends Window {
@@ -1207,7 +1243,7 @@ const insertContent = (item: ContentItem) => {
   createFrameElement(item.url, item.tool)
 }
 
-const toolTypeArray = ref([45, 15, 78, 79, 84, 831])
+const toolTypeArray = ref([45, 15, 78, 79, 84, 831, 832])
 
 const addContent = (data: ContentItem, type: number) => {
   // contentList.value.push(data)
@@ -1279,6 +1315,7 @@ const getTypeLabel = (type?: number) => {
     79: lang.ssPhoto,
     84: lang.ssFile,
     831: lang.ssKwlTitle,
+    832: lang.ssSixHatTitle,
   }
   return typeMap[type || 0] || lang.ssUnknown
 }
@@ -1293,6 +1330,7 @@ const getTypeClass = (type?: number) => {
     75: 'type-bilibili',
     76: 'type-app-center',
     831: 'type-kwl',
+    832: 'type-six-hat',
     84: 'type-file',
   }
   return classMap[type || 0] || 'type-default'
@@ -2107,6 +2145,17 @@ const addAiWeb = async (code: string) => {
   }
 }
 
+// 六顶思考帽专属样式(琥珀色主题)
+.six-hat-card {
+  .tool-icon-badge svg{
+    color: #f59e0b;
+  }
+
+  .tool-overly {
+    background-color: #f59e0b;
+  }
+}
+
 .submenu-upload {
   display: flex;
   align-items: center;

+ 2 - 0
src/views/Editor/CanvasTool/WebpageInput.vue

@@ -112,6 +112,7 @@ const getTypeLabel = (type: number) => {
     79: lang.ssPhoto,
     84: lang.ssFile,
     831: lang.ssKwlTitle,
+    832: lang.ssSixHatTitle,
   }
   return typeMap[type] || lang.ssUnknown
 }
@@ -127,6 +128,7 @@ const getTypeClass = (type: number) => {
     75: 'type-bilibili',
     76: 'type-app-center',
     831: 'type-kwl',
+    832: 'type-kwl-title',
   }
   return classMap[type] || 'type-default'
 }

+ 1 - 0
src/views/Editor/CanvasTool/index2.vue

@@ -415,6 +415,7 @@ const getTypeLabel = (type: number) => {
     79: lang.ssPhoto,
     84: lang.ssFile,
     831: lang.ssKwlTitle,
+    832: lang.ssSixHatTitle,
   }
   return typeMap[type] || lang.ssUnknown
 }

+ 1 - 1
src/views/Student/index.vue

@@ -595,7 +595,7 @@ type WorkItem = {
   [key: string]: any
 }
 const workArray = ref<WorkItem[]>([])
-const toolTypeArray = ref<number[]>([45, 15, 73, 72, 78, 79, 831, 84])
+const toolTypeArray = ref<number[]>([45, 15, 73, 72, 78, 79, 831, 832, 84])
 
 // 作业弹窗相关
 const selectedWork = ref<any>(null)

+ 1 - 0
src/views/components/element/FrameElement/BaseFrameElement.vue

@@ -191,6 +191,7 @@ const getTypeLabel = (type: number): string => {
     84: 'ssFile',
     [ARTICLE_READING_TOOL_TYPE]: 'ssArticleReadingTool',
     831: 'ssKwlTitle',
+    832: 'ssSixHatTitle',
   }
   const key = typeMap[type]
   return (key ? lang[key] : lang.ssUnknown) as string

+ 28 - 0
src/views/lang/cn.json

@@ -1092,6 +1092,34 @@
   "ssKwlWant": "W-想知",
   "ssKwlLearned": "L-已学",
   "ssKwlReflection": "学习反思",
+  "ssSixHatTitle": "六顶思考帽",
+  "ssSixHatDesc": "通过六种不同思维角色(白帽-事实、红帽-情感、黑帽-风险、黄帽-优点、绿帽-创意、蓝帽-控制)进行全面思考",
+  "ssSixHatGradeRange": "初中-高中",
+  "ssSixHatUsageScenario": "使用场景",
+  "ssSixHatScenarioText": "学生独立使用六顶思考帽从多角度分析问题",
+  "ssSixHatSteps": "操作步骤",
+  "ssSixHatStep1": "白帽思考:收集客观事实和数据",
+  "ssSixHatStep2": "红帽思考:表达直觉和情感反应",
+  "ssSixHatStep3": "黑帽思考:识别风险和潜在问题",
+  "ssSixHatStep4": "黄帽思考:寻找优点和积极面",
+  "ssSixHatStep5": "绿帽思考:提出创新想法和方案",
+  "ssSixHatStep6": "蓝帽思考:总结思考过程和结论",
+  "ssSixHatSource": "来源:爱德华·德博诺(Edward de Bono)1985年提出的平行思维训练法",
+  "ssSixHatPurpose": "目的:让学生轮流从六种思维角色出发看待同一个问题,避免争论式思维,进行更全面的分析",
+  "ssSixHatUserConfig": "工具内容由使用者配置",
+  "ssSixHatUserConfigDesc": "学生打开时会先自己设置,下方相关配置项由学生决定",
+  "ssSixHatGroupWork": "小组合作",
+  "ssSixHatGroupWorkDesc": "关闭则不显示小组成员和负责人功能",
+  "ssSixHatShowTimer": "显示计时器",
+  "ssSixHatTimerDuration": "计时时长",
+  "ssSixHatTimerSeconds": "秒",
+  "ssSixHatSelectHats": "思考帽选择",
+  "ssSixHatWhite": "白帽·事实",
+  "ssSixHatRed": "红帽·情感",
+  "ssSixHatBlack": "黑帽·风险",
+  "ssSixHatYellow": "黄帽·优点",
+  "ssSixHatGreen": "绿帽·创意",
+  "ssSixHatBlue": "蓝帽·控制",
   "ssFile": "文件上传",
   "ssClickToPreview": "点击预览",
   "ssClickToOpen": "点击打开"

+ 28 - 0
src/views/lang/en.json

@@ -1092,6 +1092,34 @@
   "ssKwlWant": "W-Want to know",
   "ssKwlLearned": "L-Learned",
   "ssKwlReflection": "Learning Reflection",
+  "ssSixHatTitle": "Six Thinking Hats",
+  "ssSixHatDesc": "Think comprehensively through six different thinking roles (White-Facts, Red-Emotions, Black-Risks, Yellow-Benefits, Green-Creativity, Blue-Control)",
+  "ssSixHatGradeRange": "Middle-High School",
+  "ssSixHatUsageScenario": "Usage Scenario",
+  "ssSixHatScenarioText": "Students independently use the Six Thinking Hats to analyze problems from multiple perspectives",
+  "ssSixHatSteps": "Steps",
+  "ssSixHatStep1": "White Hat: Gather objective facts and data",
+  "ssSixHatStep2": "Red Hat: Express intuition and emotional reactions",
+  "ssSixHatStep3": "Black Hat: Identify risks and potential problems",
+  "ssSixHatStep4": "Yellow Hat: Find strengths and positive aspects",
+  "ssSixHatStep5": "Green Hat: Propose innovative ideas and solutions",
+  "ssSixHatStep6": "Blue Hat: Summarize the thinking process and conclusions",
+  "ssSixHatSource": "Source: The parallel thinking training method proposed by Edward de Bono in 1985",
+  "ssSixHatPurpose": "Purpose: Let students take turns viewing the same problem from six thinking roles, avoiding argumentative thinking for more comprehensive analysis",
+  "ssSixHatUserConfig": "Tool content configured by users",
+  "ssSixHatUserConfigDesc": "Students configure it themselves when opening; related options below are decided by students",
+  "ssSixHatGroupWork": "Group Collaboration",
+  "ssSixHatGroupWorkDesc": "When off, group members and leader features are hidden",
+  "ssSixHatShowTimer": "Show Timer",
+  "ssSixHatTimerDuration": "Timer Duration",
+  "ssSixHatTimerSeconds": "sec",
+  "ssSixHatSelectHats": "Select Hats",
+  "ssSixHatWhite": "White·Facts",
+  "ssSixHatRed": "Red·Emotion",
+  "ssSixHatBlack": "Black·Risks",
+  "ssSixHatYellow": "Yellow·Benefits",
+  "ssSixHatGreen": "Green·Creativity",
+  "ssSixHatBlue": "Blue·Control",
   "ssFile": "File Upload",
   "ssClickToPreview": "Click to Preview",
   "ssClickToOpen": "Click to Open"

+ 28 - 0
src/views/lang/hk.json

@@ -1092,6 +1092,34 @@
   "ssKwlWant": "W-想知",
   "ssKwlLearned": "L-已學",
   "ssKwlReflection": "學習反思",
+  "ssSixHatTitle": "六頂思考帽",
+  "ssSixHatDesc": "透過六種不同思維角色(白帽-事實、紅帽-情感、黑帽-風險、黃帽-優點、綠帽-創意、藍帽-控制)進行全面思考",
+  "ssSixHatGradeRange": "初中-高中",
+  "ssSixHatUsageScenario": "使用場景",
+  "ssSixHatScenarioText": "學生獨立使用六頂思考帽從多角度分析問題",
+  "ssSixHatSteps": "操作步驟",
+  "ssSixHatStep1": "白帽思考:收集客觀事實和數據",
+  "ssSixHatStep2": "紅帽思考:表達直覺和情感反應",
+  "ssSixHatStep3": "黑帽思考:識別風險和潛在問題",
+  "ssSixHatStep4": "黃帽思考:尋找優點和積極面",
+  "ssSixHatStep5": "綠帽思考:提出創新想法和方案",
+  "ssSixHatStep6": "藍帽思考:總結思考過程和結論",
+  "ssSixHatSource": "來源:愛德華·德博諾(Edward de Bono)1985年提出的平行思維訓練法",
+  "ssSixHatPurpose": "目的:讓學生輪流從六種思維角色出發看待同一個問題,避免爭論式思維,進行更全面的分析",
+  "ssSixHatUserConfig": "工具內容由使用者配置",
+  "ssSixHatUserConfigDesc": "學生打開時會先自己設置,下方相關配置項由學生決定",
+  "ssSixHatGroupWork": "小組合作",
+  "ssSixHatGroupWorkDesc": "關閉則不顯示小組成員和負責人功能",
+  "ssSixHatShowTimer": "顯示計時器",
+  "ssSixHatTimerDuration": "計時時長",
+  "ssSixHatTimerSeconds": "秒",
+  "ssSixHatSelectHats": "思考帽選擇",
+  "ssSixHatWhite": "白帽·事實",
+  "ssSixHatRed": "紅帽·情感",
+  "ssSixHatBlack": "黑帽·風險",
+  "ssSixHatYellow": "黃帽·優點",
+  "ssSixHatGreen": "綠帽·創意",
+  "ssSixHatBlue": "藍帽·控制",
   "ssFile": "文件上傳",
   "ssClickToPreview": "點擊預覽",
   "ssClickToOpen": "點擊打開"