|
@@ -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>
|