|
|
|
|
|
<template>
|
|
|
|
|
|
<div class="feature-conversion-page student-training-shell">
|
|
|
|
|
|
<main class="training-core">
|
|
|
|
|
|
<section class="task-header">
|
|
|
|
|
|
<div class="task-badge">市场洞察与需求分析</div>
|
|
|
|
|
|
<h1 class="task-title">{{ taskTitle }}</h1>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<TrainingTaskBrief
|
|
|
|
|
|
:background="taskBackground"
|
|
|
|
|
|
:goals="taskGoals"
|
|
|
|
|
|
:requirements="taskRequirement"
|
|
|
|
|
|
:show-material="false"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<section class="task-card">
|
|
|
|
|
|
<div class="workbench-head workbench-head--actions-only">
|
|
|
|
|
|
<div class="workbench-actions">
|
|
|
|
|
|
<TrainingMaterialButton :material-name="taskConfig?.materialName" :material-url="taskConfig?.materialUrl" />
|
|
|
|
|
|
<button type="button" class="outline-action" @click="exportOutcome">
|
|
|
|
|
|
<el-icon><Download /></el-icon>
|
|
|
|
|
|
导出实训成果
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<nav v-if="flowSteps.length" class="step-indicator" aria-label="需求转化为功能步骤">
|
|
|
|
|
|
<template v-for="(step, index) in flowSteps" :key="`${step}-${index}`">
|
|
|
|
|
|
<button
|
|
|
|
|
|
type="button"
|
|
|
|
|
|
:class="['step-tab', { active: form.activeStep === index + 1, complete: form.activeStep > index + 1 }]"
|
|
|
|
|
|
:aria-current="form.activeStep === index + 1 ? 'step' : undefined"
|
|
|
|
|
|
:aria-label="`第${index + 1}步:${step}`"
|
|
|
|
|
|
@click="setCurrentStep(index + 1)"
|
|
|
|
|
|
>
|
|
|
|
|
|
<span class="step-marker">{{ String(index + 1).padStart(2, '0') }}</span>
|
|
|
|
|
|
<span class="step-copy">
|
|
|
|
|
|
<strong class="step-name" :title="step">{{ step }}</strong>
|
|
|
|
|
|
<span class="step-action">{{ form.activeStep === index + 1 ? "当前步骤" : "点击切换" }} <span aria-hidden="true">→</span></span>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<span v-if="index < flowSteps.length - 1" class="step-connector" aria-hidden="true"></span>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
|
|
|
<section v-show="isSectionVisible(1)" class="step-card conversion-content">
|
|
|
|
|
|
<div v-if="activeStepName" class="step-title-row">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<p class="section-eyebrow">Step {{ String(form.activeStep).padStart(2, '0') }}</p>
|
|
|
|
|
|
<h3>{{ activeStepName }}</h3>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="conversion-intro">
|
|
|
|
|
|
<p>用户反馈通常混杂重复描述、情绪化表达、无关信息。请阅读案例资料中原始用户反馈,逐条进行场景洞察拆解,分析用户在什么时间、什么情境下产生该需求,背后的深层动机是什么,然后将用户语言转化为可执行的产品功能定义,填写以下需求转化表。</p>
|
|
|
|
|
|
<div class="conversion-row-actions">
|
|
|
|
|
|
<el-button type="primary" :disabled="form.rows.length >= MAX_CONVERSION_ROWS" @click="addConversionRow">增加一行</el-button>
|
|
|
|
|
|
<el-button type="primary" plain :disabled="form.rows.length <= MIN_CONVERSION_ROWS" @click="removeConversionRow">删除一行</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="conversion-table-wrap">
|
|
|
|
|
|
<table class="conversion-table">
|
|
|
|
|
|
<thead>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<th>序号</th>
|
|
|
|
|
|
<th>用户原声</th>
|
|
|
|
|
|
<th>场景洞察</th>
|
|
|
|
|
|
<th>转化后的功能定义</th>
|
|
|
|
|
|
<th>功能描述</th>
|
|
|
|
|
|
<th>技术指标/验收标准</th>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</thead>
|
|
|
|
|
|
<tbody>
|
|
|
|
|
|
<tr v-for="(row, index) in form.rows" :key="row.id">
|
|
|
|
|
|
<td>{{ index + 1 }}</td>
|
|
|
|
|
|
<td><textarea v-model="row.voice" :placeholder="index === 0 ? '示例:起夜需要温和照明,避免强光刺激' : '填写用户原声'"></textarea></td>
|
|
|
|
|
|
<td><textarea v-model="row.insight" :placeholder="index === 0 ? '示例:凌晨2-5点用户从深度睡眠中被尿意唤醒,处于半梦半醒状态,瞳孔对光线极其敏感' : '填写场景洞察'"></textarea></td>
|
|
|
|
|
|
<td><textarea v-model="row.definition" :placeholder="index === 0 ? '示例:起夜微光模式' : '填写转化后的功能定义'"></textarea></td>
|
|
|
|
|
|
<td><textarea v-model="row.description" :placeholder="index === 0 ? '示例:感应到用户起身时,自动开启亮度≤10%的暖黄地脚光,延迟3秒渐亮' : '填写功能描述'"></textarea></td>
|
|
|
|
|
|
<td><textarea v-model="row.acceptance" :placeholder="index === 0 ? '示例:亮度5-15流明可调,色温2700K,启动延时≤0.5秒,光通量渐升时间3±0.5秒' : '填写技术指标/验收标准'"></textarea></td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</tbody>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p class="conversion-limit-tip">至少 {{ MIN_CONVERSION_ROWS }} 行,最多 {{ MAX_CONVERSION_ROWS }} 行</p>
|
|
|
|
|
|
<div class="conversion-helper">
|
|
|
|
|
|
<h5>可参考以下方法:</h5>
|
|
|
|
|
|
<p>1. 自行阅读案例信息,将用户原声转化为需求,再通过需求分析转化为产品功能。</p>
|
|
|
|
|
|
<p>2. 使用通用 AI 大模型辅助完成场景洞察与功能转化,参考提示词见案例文档。</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p v-if="conversionValidationMessage" class="conversion-validation-message" role="status">{{ conversionValidationMessage }}</p>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<section v-show="isSectionVisible(2)" class="step-card conversion-content priority-content">
|
|
|
|
|
|
<div v-if="activeStepName" class="step-title-row">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<p class="section-eyebrow">Step {{ String(form.activeStep).padStart(2, '0') }}</p>
|
|
|
|
|
|
<h3>{{ activeStepName }}</h3>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
|
|
|
|
对于智能硬件,建议采用RICE 模型(Reach 覆盖范围、Impact 影响程度、Confidence 置信度、Effort 投入成本)进行量化打分,但必须加一个前置过滤器:合规与安全。并使用KANO模型辅助决策。
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<p>
|
|
|
|
|
|
必备属性(Must-be):如“跌倒检测”、“语音唤醒”。做不到用户会极度不满,做到了是理所应当。优先保障,不计成本投入稳定性。
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<p>
|
|
|
|
|
|
期望属性(Performance):如“续航时间”、“识别准确率”。做得越好用户越满意。在 BOM 成本允许范围内最大化。
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<p>
|
|
|
|
|
|
魅力属性(Delighters):如“情绪识别主动安慰”。没有用户无所谓,有了是惊喜。在核心功能稳定后,作为差异化卖点迭代。
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<p class="source-title">智能硬件需求优先级评估打分表模板:</p>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="conversion-table-wrap">
|
|
|
|
|
|
<table class="priority-template-table">
|
|
|
|
|
|
<thead>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<th>字段</th>
|
|
|
|
|
|
<th>说明</th>
|
|
|
|
|
|
<th>填写示例</th>
|
|
|
|
|
|
<th>来源/依据</th>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</thead>
|
|
|
|
|
|
<tbody>
|
|
|
|
|
|
<tr v-for="row in priorityTemplateRows" :key="row.field">
|
|
|
|
|
|
<td>{{ row.field }}</td>
|
|
|
|
|
|
<td v-html="row.description"></td>
|
|
|
|
|
|
<td v-html="row.example"></td>
|
|
|
|
|
|
<td>{{ row.source }}</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</tbody>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<p class="table-tip">请根据上一步骤需求转化后的功能定义,针对具体需求进行量化打分,填写以下打分表:</p>
|
|
|
|
|
|
<div class="conversion-table-wrap">
|
|
|
|
|
|
<table class="priority-score-table">
|
|
|
|
|
|
<thead>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<th>需求ID</th>
|
|
|
|
|
|
<th>需求名称</th>
|
|
|
|
|
|
<th>需求来源</th>
|
|
|
|
|
|
<th>KANO属性</th>
|
|
|
|
|
|
<th>Reach(覆盖范围)</th>
|
|
|
|
|
|
<th>Impact(影响程度)</th>
|
|
|
|
|
|
<th>Confidence(置信度)</th>
|
|
|
|
|
|
<th>Effort(投入成本)</th>
|
|
|
|
|
|
<th>RICE得分</th>
|
|
|
|
|
|
<th>合规性检查项</th>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</thead>
|
|
|
|
|
|
<tbody>
|
|
|
|
|
|
<tr v-for="row in form.scoreRows" :key="row.uid">
|
|
|
|
|
|
<td><textarea v-model="row.requirementId" aria-label="需求ID"></textarea></td>
|
|
|
|
|
|
<td><textarea v-model="row.name" aria-label="需求名称"></textarea></td>
|
|
|
|
|
|
<td><textarea v-model="row.source" aria-label="需求来源"></textarea></td>
|
|
|
|
|
|
<td><textarea v-model="row.kano" aria-label="KANO属性"></textarea></td>
|
|
|
|
|
|
<td><textarea v-model="row.reach" aria-label="Reach覆盖范围"></textarea></td>
|
|
|
|
|
|
<td><textarea v-model="row.impact" aria-label="Impact影响程度"></textarea></td>
|
|
|
|
|
|
<td><textarea v-model="row.confidence" aria-label="Confidence置信度"></textarea></td>
|
|
|
|
|
|
<td><textarea v-model="row.effort" aria-label="Effort投入成本"></textarea></td>
|
|
|
|
|
|
<td><textarea v-model="row.rice" aria-label="RICE得分"></textarea></td>
|
|
|
|
|
|
<td><textarea v-model="row.compliance" aria-label="合规性检查项"></textarea></td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</tbody>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<section v-show="isSectionVisible(3)" class="step-card conversion-content decision-content">
|
|
|
|
|
|
<div v-if="activeStepName" class="step-title-row">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<p class="section-eyebrow">Step {{ String(form.activeStep).padStart(2, '0') }}</p>
|
|
|
|
|
|
<h3>{{ activeStepName }}</h3>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p class="decision-intro">
|
|
|
|
|
|
假设项目首期 BOM 成本控制在 300 元以内,研发周期 4 个月。根据上一步骤完成的需求打分表,填写以下内容:
|
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
<label class="decision-field">
|
|
|
|
|
|
<span>P0(首期必做 - 生存线):不做这些,产品无法上市或会被立即退货。</span>
|
|
|
|
|
|
<textarea v-model="form.priorityDecision.p0" aria-label="P0首期必做"></textarea>
|
|
|
|
|
|
</label>
|
|
|
|
|
|
|
|
|
|
|
|
<label class="decision-field">
|
|
|
|
|
|
<span>P1(首期核心 - 竞争力):在成本允许下,最大化“期望属性”,提升性价比感知。</span>
|
|
|
|
|
|
<textarea v-model="form.priorityDecision.p1" aria-label="P1首期核心"></textarea>
|
|
|
|
|
|
</label>
|
|
|
|
|
|
|
|
|
|
|
|
<label class="decision-field">
|
|
|
|
|
|
<span>P2(二期迭代 - 差异化):虽然可以提升用户体验,但是成本较高,或者增加合规风险的。</span>
|
|
|
|
|
|
<textarea v-model="form.priorityDecision.p2" aria-label="P2二期迭代"></textarea>
|
|
|
|
|
|
</label>
|
|
|
|
|
|
|
|
|
|
|
|
<label class="decision-field">
|
|
|
|
|
|
<span>P3(暂缓/砍掉):需求伪命题,偏离核心场景</span>
|
|
|
|
|
|
<textarea v-model="form.priorityDecision.p3" aria-label="P3暂缓砍掉"></textarea>
|
|
|
|
|
|
</label>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<section v-show="isSectionVisible(4)" class="step-card conversion-content completion-content">
|
|
|
|
|
|
<div v-if="activeStepName" class="step-title-row">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<p class="section-eyebrow">Step {{ String(form.activeStep).padStart(2, '0') }}</p>
|
|
|
|
|
|
<h3>{{ activeStepName }}</h3>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>请检查需求转化、优先级评分和排序决策是否填写完整,再保存或提交本次实训成果。</p>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<div v-if="hasConfiguredSteps" class="step-navigation">
|
|
|
|
|
|
<button type="button" class="btn-nav" :disabled="form.activeStep === 1" @click="goPreviousStep">
|
|
|
|
|
|
<el-icon><ArrowLeft /></el-icon>
|
|
|
|
|
|
上一步
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button type="button" class="btn-nav btn-save" :disabled="saving" @click="saveCurrentProgress">
|
|
|
|
|
|
<el-icon><CircleCheck /></el-icon>
|
|
|
|
|
|
保存当前进度
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button type="button" class="btn-nav btn-primary" :disabled="form.activeStep === flowSteps.length" @click="goNextStep">
|
|
|
|
|
|
下一步
|
|
|
|
|
|
<el-icon><ArrowRight /></el-icon>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="training-actions">
|
|
|
|
|
|
<el-button class="training-action training-action--submit" :loading="saving" @click="submitTask">
|
|
|
|
|
|
提交任务
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
<el-button class="training-action training-action--reset" @click="resetTraining">
|
|
|
|
|
|
清空填写
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
</main>
|
|
|
|
|
|
|
|
|
|
|
|
<TrainingAiSidebar
|
|
|
|
|
|
study-tip="当前任务建议:先把用户原声还原成具体场景,再提炼痛点,最后写成可开发、可验收的功能定义。"
|
|
|
|
|
|
reference-title="需求转化参考"
|
|
|
|
|
|
reference-text="· 用户语言:愿望、抱怨、现象<br />· 场景洞察:谁在什么情况下遇到什么阻碍<br />· 工程语言:功能名称、触发条件、处理逻辑、验收指标"
|
|
|
|
|
|
assist-text="可以让 AI 帮你把每条用户原声拆成“场景洞察 + 功能定义 + 验收标准”,再人工检查是否可执行。"
|
|
|
|
|
|
:progress-items="progressItems"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
import { computed, getCurrentInstance, onMounted, ref } from "vue";
|
|
|
|
|
|
import { ArrowLeft, ArrowRight, CircleCheck, Download } from "@element-plus/icons-vue";
|
|
|
|
|
|
import TrainingAiSidebar from "@/views/components/TrainingAiSidebar.vue";
|
|
|
|
|
|
import TrainingMaterialButton from "@/views/components/TrainingMaterialButton.vue";
|
|
|
|
|
|
import TrainingTaskBrief from "@/views/components/TrainingTaskBrief.vue";
|
|
|
|
|
|
import { getTrainingTaskByKey } from "@/api/trainingTask";
|
|
|
|
|
|
import { checkFeatureConversionStepOne, getStudentTrainingAnswer, saveStudentTrainingAnswer } from "@/api/studentTrainingAnswer";
|
|
|
|
|
|
|
|
|
|
|
|
const TASK_KEY = "feature-conversion";
|
|
|
|
|
|
const MIN_CONVERSION_ROWS = 8;
|
|
|
|
|
|
const MAX_CONVERSION_ROWS = 12;
|
|
|
|
|
|
const { proxy } = getCurrentInstance();
|
|
|
|
|
|
|
|
|
|
|
|
const defaultRequirement =
|
|
|
|
|
|
"需求转化不是照搬用户原话,而是把模糊痛点翻译成可设计、可开发、可验收的功能。过程包括需求清洗、场景还原、功能定义、验收标准和优先级排序。";
|
|
|
|
|
|
const defaultBackground =
|
|
|
|
|
|
"假如你是某款智能产品的产品经理,在前期问卷调研和需求分析后,需要把收集到的用户需求转化为功能设计。你要成为需求的翻译者和决策者,而不是用户原话的传声筒。";
|
|
|
|
|
|
const defaultGoals = [
|
|
|
|
|
|
"学会梳理用户需求,剔除重复或低价值需求。",
|
|
|
|
|
|
"将用户语言转化为功能设计和工程语言。",
|
|
|
|
|
|
"能够对功能优先级进行排序。",
|
|
|
|
|
|
];
|
|
|
|
|
|
const priorityTemplateRows = [
|
|
|
|
|
|
{ field: "需求ID", description: "唯一编号,便于追踪", example: "REQ-2026-003", source: "内部系统生成" },
|
|
|
|
|
|
{ field: "需求名称", description: "清晰、无歧义的功能描述", example: "“儿童位置异常自动推送家长APP”", source: "用户访谈 / 客服反馈" },
|
|
|
|
|
|
{ field: "需求来源", description: "提出方(用户/销售/合规/研发)", example: "家长调研组 / 法务部", source: "-" },
|
|
|
|
|
|
{ field: "KANO属性", description: "分类:必备 / 期望 / 魅力", example: "必备属性", source: "基于KANO模型调研" },
|
|
|
|
|
|
{ field: "Reach(覆盖范围)", description: "本周期内受影响的用户数(估算)", example: "85,000(占目标用户群72%)", source: "市场数据 / DAU统计" },
|
|
|
|
|
|
{ field: "Impact(影响程度)", description: "单用户价值评分(1–5分)<br>5=显著提升留存/转化;1=无感知", example: "5(解决核心安全焦虑)", source: "专家评估 + 用户调研" },
|
|
|
|
|
|
{ field: "Confidence(置信度)", description: "对Reach/Impact预测的信心(0%–100%)", example: "90%(基于1,200份问卷)", source: "市场研究 / A/B测试" },
|
|
|
|
|
|
{ field: "Effort(投入成本)", description: "实现所需总人天(开发+测试+认证)", example: "45人天(含嵌入式+云端+认证)", source: "工程团队评估" },
|
|
|
|
|
|
{ field: "RICE得分", description: "计算公式:(Reach × Impact × Confidence)/ Effort<br>结果保留两位小数", example: "(85,000 × 5 × 0.9) / 45 = 8,500.00", source: "自动计算列" },
|
|
|
|
|
|
{
|
|
|
|
|
|
field: "合规性检查项",
|
|
|
|
|
|
description: "必须通过的强制项(任一不通过则直接降为P3或砍掉)",
|
|
|
|
|
|
example: "符合GB 46859-2025(儿童手表隐私权限)<br>□ 通过SRRC认证(无线模块)<br>□ 无未经加密的儿童位置上传<br>□ 内容池通过AI过滤(无不良信息)",
|
|
|
|
|
|
source: "法务/认证团队确认",
|
|
|
|
|
|
},
|
|
|
|
|
|
{ field: "BOM成本影响", description: "是否增加核心元器件(如GPS模组、安全芯片)", example: "是(+¥18/台)", source: "采购部评估" },
|
|
|
|
|
|
{ field: "DFM影响", description: "是否导致模具复杂度↑、良率↓", example: "否", source: "结构工程师确认" },
|
|
|
|
|
|
{ field: "供应链风险", description: "是否依赖长交期/单一供应商物料", example: "否(GPS模组有备选)", source: "供应链团队确认" },
|
|
|
|
|
|
{
|
|
|
|
|
|
field: "优先级等级",
|
|
|
|
|
|
description: "根据RICE得分与合规性综合判定:<br>P0:≥5,000 且合规全通过<br>P1:2,000–4,999 且合规通过<br>P2:<2,000 或部分合规待优化",
|
|
|
|
|
|
example: "P0",
|
|
|
|
|
|
source: "综合判定",
|
|
|
|
|
|
},
|
|
|
|
|
|
{ field: "建议动作", description: "是否纳入首期开发?是否需替代方案?", example: "纳入首期,同步启动SRRC认证预检", source: "——" },
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
const parentFeedback = [
|
|
|
|
|
|
"我家孩子总爱抢手机玩游戏,能不能让机器人把手机里的学习内容导进去,替代手机当学习工具?",
|
|
|
|
|
|
"孩子学拼音总是平翘舌不分,机器人能不能像老师那样纠正发音,还能出练习题测试?",
|
|
|
|
|
|
"机器人能不能记录孩子白天的日常,比如玩了什么游戏、学了什么儿歌,我直接就能看?",
|
|
|
|
|
|
"老人带孩子不会教英语,机器人能不能设定固定时间,比如每天晚上7点,主动跟孩子说英语、玩英语小游戏?",
|
|
|
|
|
|
"孩子害怕一个人睡,机器人能不能在床边播放轻柔的故事,还能感应孩子有没有踢被子,踢了就提醒盖被子?",
|
|
|
|
|
|
"孩子在家总爱乱扔玩具,机器人能不能当“小管家”,提醒孩子收拾玩具,还能跟孩子比赛谁收拾得快?",
|
|
|
|
|
|
"有时候加班晚回家,孩子会闹情绪,机器人能不能跟视频电话结合,我在手机上就能通过机器人跟孩子互动,还能远程控制机器人给孩子放动画片?",
|
|
|
|
|
|
"孩子总爱问“为什么”,我很多问题答不上来,机器人能不能像百科全书一样,不管天文地理都能给孩子讲明白,还要用孩子能听懂的话?",
|
|
|
|
|
|
"我家孩子有点内向,不爱跟别人说话,机器人能不能主动找孩子聊天,引导孩子表达自己的想法,比如“你今天最开心的事是什么呀?”",
|
|
|
|
|
|
"孩子写作业姿势不对,总是趴在桌子上,机器人能不能提醒孩子坐端正,要是不听还能告诉家长?",
|
|
|
|
|
|
"现在网上内容太杂,机器人能不能自动过滤掉暴力、恐怖的内容,只给孩子推送适合3-6岁看的内容?",
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
const childFeedback = [
|
|
|
|
|
|
"机器人能不能跟我一起玩躲猫猫,它来找我,我藏起来它能找到我!",
|
|
|
|
|
|
"我想要机器人会变魔术,比如能把我画的画变成动画片里的小人动起来!",
|
|
|
|
|
|
"机器人的声音能不能像佩奇一样,我还能让它变成奥特曼的声音跟我说话!",
|
|
|
|
|
|
"我要是不开心了,机器人能不能给我跳舞,还能唱我喜欢的《孤勇者》!",
|
|
|
|
|
|
"机器人能不能陪我搭积木,它要是看到我搭错了,就告诉我怎么搭才能搭得更高!",
|
|
|
|
|
|
"我想要机器人有好多好多表情,开心的时候笑,难过的时候哭,就像小朋友一样!",
|
|
|
|
|
|
"机器人能不能跟我一起养小宠物,比如养一只虚拟的小猫,我们一起喂它吃饭、给它洗澡!",
|
|
|
|
|
|
"我要是想爷爷奶奶了,机器人能不能直接帮我打电话给他们,不用我找妈妈拿手机!",
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
const taskConfig = ref(null);
|
|
|
|
|
|
const saving = ref(false);
|
|
|
|
|
|
const checkingConversion = ref(false);
|
|
|
|
|
|
const conversionValidationMessage = ref("");
|
|
|
|
|
|
|
|
|
|
|
|
function createRows(count = MIN_CONVERSION_ROWS) {
|
|
|
|
|
|
return Array.from({ length: count }, (_, index) => ({
|
|
|
|
|
|
id: index + 1,
|
|
|
|
|
|
voice: "",
|
|
|
|
|
|
insight: "",
|
|
|
|
|
|
definition: "",
|
|
|
|
|
|
description: "",
|
|
|
|
|
|
acceptance: "",
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function createScoreRows() {
|
|
|
|
|
|
return Array.from({ length: 5 }, (_, index) => ({
|
|
|
|
|
|
uid: index + 1,
|
|
|
|
|
|
requirementId: "",
|
|
|
|
|
|
name: "",
|
|
|
|
|
|
source: "",
|
|
|
|
|
|
kano: "",
|
|
|
|
|
|
reach: "",
|
|
|
|
|
|
impact: "",
|
|
|
|
|
|
confidence: "",
|
|
|
|
|
|
effort: "",
|
|
|
|
|
|
rice: "",
|
|
|
|
|
|
compliance: "",
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function createPriorityDecision() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
p0: "",
|
|
|
|
|
|
p1: "",
|
|
|
|
|
|
p2: "",
|
|
|
|
|
|
p3: "",
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function createForm() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
activeStep: 1,
|
|
|
|
|
|
productName: "",
|
|
|
|
|
|
rows: createRows(),
|
|
|
|
|
|
scoreRows: createScoreRows(),
|
|
|
|
|
|
priorityDecision: createPriorityDecision(),
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const form = ref(createForm());
|
|
|
|
|
|
|
|
|
|
|
|
const taskTitle = computed(() => taskConfig.value?.taskName || "需求转化为功能");
|
|
|
|
|
|
const taskBackground = computed(() => taskConfig.value?.background || defaultBackground);
|
|
|
|
|
|
const taskGoals = computed(() => parseArray(taskConfig.value?.objectives, defaultGoals));
|
|
|
|
|
|
const taskRequirement = computed(() => taskConfig.value?.requirements || defaultRequirement);
|
|
|
|
|
|
const flowSteps = computed(() => parseArray(taskConfig.value?.steps));
|
|
|
|
|
|
const hasConfiguredSteps = computed(() => flowSteps.value.length > 0);
|
|
|
|
|
|
const activeStepName = computed(() => flowSteps.value[form.value.activeStep - 1] || "");
|
|
|
|
|
|
|
|
|
|
|
|
const progressItems = computed(() => [
|
|
|
|
|
|
{ text: hasTableContent.value ? "进行中:需求转化表" : "待完成:需求转化表", status: hasTableContent.value ? "doing" : "" },
|
|
|
|
|
|
{ text: hasScoreContent.value ? "进行中:优先级打分表" : "待完成:优先级打分表", status: hasScoreContent.value ? "doing" : "" },
|
|
|
|
|
|
{ text: hasDecisionContent.value ? "进行中:优先级排序决策" : "待完成:优先级排序决策", status: hasDecisionContent.value ? "doing" : "" },
|
|
|
|
|
|
{ text: "待完成:提交实训成果", status: "" },
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
const hasTableContent = computed(() =>
|
|
|
|
|
|
form.value.rows.some((row) =>
|
|
|
|
|
|
["voice", "insight", "definition", "description", "acceptance"].some((key) => String(row[key] || "").trim())
|
|
|
|
|
|
)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const hasScoreContent = computed(() =>
|
|
|
|
|
|
form.value.scoreRows.some((row) =>
|
|
|
|
|
|
["requirementId", "name", "source", "kano", "reach", "impact", "confidence", "effort", "rice", "compliance"].some((key) =>
|
|
|
|
|
|
String(row[key] || "").trim()
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const hasDecisionContent = computed(() =>
|
|
|
|
|
|
["p0", "p1", "p2", "p3"].some((key) => String(form.value.priorityDecision?.[key] || "").trim())
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
await loadTaskConfig();
|
|
|
|
|
|
await loadSavedAnswer();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
async function loadTaskConfig() {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await getTrainingTaskByKey(TASK_KEY);
|
|
|
|
|
|
taskConfig.value = res?.data || null;
|
|
|
|
|
|
form.value.activeStep = normalizeActiveStep(form.value.activeStep);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
taskConfig.value = null;
|
|
|
|
|
|
form.value.activeStep = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function loadSavedAnswer() {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await getStudentTrainingAnswer(TASK_KEY);
|
|
|
|
|
|
const answer = res?.data;
|
|
|
|
|
|
if (answer?.step1Answer) {
|
|
|
|
|
|
applySavedAnswer(answer.step1Answer);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
// Keep local defaults when history cannot be loaded.
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function parseArray(value, fallback = []) {
|
|
|
|
|
|
if (Array.isArray(value)) return value.filter(Boolean);
|
|
|
|
|
|
if (!value) return fallback;
|
|
|
|
|
|
try {
|
|
|
|
|
|
const parsed = JSON.parse(value);
|
|
|
|
|
|
return Array.isArray(parsed) && parsed.length ? parsed : fallback;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const list = String(value)
|
|
|
|
|
|
.split(/[;;||\n]/)
|
|
|
|
|
|
.map((item) => item.trim())
|
|
|
|
|
|
.filter(Boolean);
|
|
|
|
|
|
return list.length ? list : fallback;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeActiveStep(value) {
|
|
|
|
|
|
if (!flowSteps.value.length) return 1;
|
|
|
|
|
|
const parsed = Number(value) || 1;
|
|
|
|
|
|
return Math.min(Math.max(parsed, 1), flowSteps.value.length);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function setCurrentStep(step) {
|
|
|
|
|
|
const targetStep = normalizeActiveStep(step);
|
|
|
|
|
|
if (targetStep > form.value.activeStep && form.value.activeStep === 1 && !(await persist("IN_PROGRESS"))) return;
|
|
|
|
|
|
form.value.activeStep = targetStep;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function isSectionVisible(section) {
|
|
|
|
|
|
return !hasConfiguredSteps.value || form.value.activeStep === section;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function goPreviousStep() {
|
|
|
|
|
|
await setCurrentStep(form.value.activeStep - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function goNextStep() {
|
|
|
|
|
|
await setCurrentStep(form.value.activeStep + 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function applySavedAnswer(value) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const parsed = JSON.parse(value);
|
|
|
|
|
|
if (!parsed || typeof parsed !== "object") return;
|
|
|
|
|
|
form.value = {
|
|
|
|
|
|
...createForm(),
|
|
|
|
|
|
...parsed,
|
|
|
|
|
|
rows: normalizeRows(parsed.rows),
|
|
|
|
|
|
scoreRows: normalizeScoreRows(parsed.scoreRows),
|
|
|
|
|
|
priorityDecision: normalizePriorityDecision(parsed.priorityDecision),
|
|
|
|
|
|
activeStep: normalizeActiveStep(parsed.activeStep),
|
|
|
|
|
|
};
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
// Ignore malformed historical answers.
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeRows(rows = []) {
|
|
|
|
|
|
const savedRows = Array.isArray(rows) ? rows : [];
|
|
|
|
|
|
const normalizedCount = Math.min(Math.max(savedRows.length, MIN_CONVERSION_ROWS), MAX_CONVERSION_ROWS);
|
|
|
|
|
|
return createRows(normalizedCount).map((row, index) => ({ ...row, ...(savedRows[index] || {}), id: row.id }));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function addConversionRow() {
|
|
|
|
|
|
if (form.value.rows.length >= MAX_CONVERSION_ROWS) {
|
|
|
|
|
|
proxy?.$modal?.msgWarning(`最多只能填写 ${MAX_CONVERSION_ROWS} 行`);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const nextId = Math.max(0, ...form.value.rows.map((row) => Number(row.id) || 0)) + 1;
|
|
|
|
|
|
form.value.rows.push({ id: nextId, voice: "", insight: "", definition: "", description: "", acceptance: "" });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function removeConversionRow() {
|
|
|
|
|
|
if (form.value.rows.length <= MIN_CONVERSION_ROWS) {
|
|
|
|
|
|
proxy?.$modal?.msgWarning(`至少需要填写 ${MIN_CONVERSION_ROWS} 行`);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
form.value.rows.pop();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function ensureConversionValid() {
|
|
|
|
|
|
if (checkingConversion.value) return false;
|
|
|
|
|
|
checkingConversion.value = true;
|
|
|
|
|
|
try {
|
|
|
|
|
|
const response = await checkFeatureConversionStepOne({ rows: form.value.rows });
|
|
|
|
|
|
const result = response?.data || {};
|
|
|
|
|
|
conversionValidationMessage.value = result.message || (result.valid ? "需求转化表填写完整。" : `请完整填写 ${MIN_CONVERSION_ROWS}-${MAX_CONVERSION_ROWS} 行需求转化信息。`);
|
|
|
|
|
|
return result.valid === true;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
conversionValidationMessage.value = error?.message || "需求转化表校验失败,请稍后重试。";
|
|
|
|
|
|
return false;
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
checkingConversion.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeScoreRows(rows = []) {
|
|
|
|
|
|
const savedRows = Array.isArray(rows) ? rows : [];
|
|
|
|
|
|
return createScoreRows().map((row, index) => ({
|
|
|
|
|
|
...row,
|
|
|
|
|
|
...(savedRows[index] || {}),
|
|
|
|
|
|
uid: row.uid,
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizePriorityDecision(value = {}) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
...createPriorityDecision(),
|
|
|
|
|
|
...(value && typeof value === "object" ? value : {}),
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function buildOutcome() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
taskKey: TASK_KEY,
|
|
|
|
|
|
taskId: taskConfig.value?.id || "",
|
|
|
|
|
|
taskName: taskTitle.value,
|
|
|
|
|
|
flowSteps: flowSteps.value,
|
|
|
|
|
|
productName: form.value.productName,
|
|
|
|
|
|
activeStep: form.value.activeStep,
|
|
|
|
|
|
rows: form.value.rows,
|
|
|
|
|
|
scoreRows: form.value.scoreRows,
|
|
|
|
|
|
priorityDecision: form.value.priorityDecision,
|
|
|
|
|
|
updatedAt: new Date().toISOString(),
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function buildAnswerPayload(status) {
|
|
|
|
|
|
const saveAction = status === "SUBMITTED" ? "SUBMIT" : status === "RESET" ? "RESET" : "SAVE";
|
|
|
|
|
|
return {
|
|
|
|
|
|
saveAction,
|
|
|
|
|
|
currentStep: form.value.activeStep,
|
|
|
|
|
|
step1Answer: JSON.stringify(buildOutcome()),
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function persist(status = "IN_PROGRESS") {
|
|
|
|
|
|
if (saving.value) return;
|
|
|
|
|
|
if (status !== "RESET" && form.value.activeStep === 1 && !(await ensureConversionValid())) return false;
|
|
|
|
|
|
saving.value = true;
|
|
|
|
|
|
try {
|
|
|
|
|
|
await saveStudentTrainingAnswer(TASK_KEY, buildAnswerPayload(status));
|
|
|
|
|
|
proxy?.$modal?.msgSuccess(status === "SUBMITTED" ? "提交成功" : "保存成功");
|
|
|
|
|
|
return true;
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
saving.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function saveCurrentProgress() {
|
|
|
|
|
|
return persist("IN_PROGRESS");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function submitTask() {
|
|
|
|
|
|
return persist("SUBMITTED");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function resetTraining() {
|
|
|
|
|
|
form.value = createForm();
|
|
|
|
|
|
await persist("RESET");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function exportOutcome() {
|
|
|
|
|
|
const blob = new Blob([JSON.stringify(buildOutcome(), null, 2)], { type: "application/json;charset=utf-8" });
|
|
|
|
|
|
const url = URL.createObjectURL(blob);
|
|
|
|
|
|
const link = document.createElement("a");
|
|
|
|
|
|
link.href = url;
|
|
|
|
|
|
link.download = `${taskTitle.value}-实训结果.json`;
|
|
|
|
|
|
link.click();
|
|
|
|
|
|
URL.revokeObjectURL(url);
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
|
.feature-conversion-page {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: minmax(0, 1fr) 320px;
|
|
|
|
|
|
gap: 22px;
|
|
|
|
|
|
min-height: calc(100vh - 76px);
|
|
|
|
|
|
padding: 24px;
|
|
|
|
|
|
color: #eaf7ff;
|
|
|
|
|
|
background:
|
|
|
|
|
|
radial-gradient(circle at 20% 4%, rgba(24, 151, 210, 0.18), transparent 34%),
|
|
|
|
|
|
linear-gradient(180deg, #05131f 0%, #07111b 100%);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.training-core {
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
padding: 28px;
|
|
|
|
|
|
border: 1px solid rgba(23, 145, 194, 0.56);
|
|
|
|
|
|
border-radius: 28px;
|
|
|
|
|
|
background: linear-gradient(180deg, rgba(4, 22, 34, 0.96), rgba(4, 15, 25, 0.98));
|
|
|
|
|
|
box-shadow: inset 0 1px 0 rgba(95, 232, 255, 0.16), 0 22px 44px rgba(0, 0, 0, 0.24);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-header {
|
|
|
|
|
|
margin-bottom: 18px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-badge {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
height: 28px;
|
|
|
|
|
|
padding: 0 14px;
|
|
|
|
|
|
border: 1px solid rgba(67, 209, 255, 0.72);
|
|
|
|
|
|
border-radius: 999px;
|
|
|
|
|
|
color: #d9f7ff;
|
|
|
|
|
|
background: rgba(14, 98, 139, 0.48);
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-title {
|
|
|
|
|
|
margin: 16px 0 0;
|
|
|
|
|
|
color: #f5fbff;
|
|
|
|
|
|
font-size: 30px;
|
|
|
|
|
|
line-height: 1.2;
|
|
|
|
|
|
letter-spacing: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.goal-bg,
|
|
|
|
|
|
.task-card {
|
|
|
|
|
|
border: 1px solid rgba(32, 149, 200, 0.58);
|
|
|
|
|
|
border-radius: 26px;
|
|
|
|
|
|
background: rgba(4, 31, 46, 0.72);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.goal-bg {
|
|
|
|
|
|
padding: 22px;
|
|
|
|
|
|
color: #c9ddec;
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
line-height: 1.8;
|
|
|
|
|
|
white-space: pre-line;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.goal-bg p,
|
|
|
|
|
|
.goal-bg ol {
|
|
|
|
|
|
margin: 8px 0 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.subtitle-icon {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
color: #eafaff;
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.subtitle-icon--spaced {
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-card {
|
|
|
|
|
|
margin-top: 22px;
|
|
|
|
|
|
padding: 24px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.workbench-head {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
gap: 16px;
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.section-eyebrow {
|
|
|
|
|
|
margin: 0 0 6px;
|
|
|
|
|
|
color: #67e6ff;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
text-transform: uppercase;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.workbench-head h3 {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
color: #f5fbff;
|
|
|
|
|
|
font-size: 22px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.ghost-action {
|
|
|
|
|
|
border-color: #2c83aa;
|
|
|
|
|
|
color: #dff7ff;
|
|
|
|
|
|
background: rgba(13, 64, 88, 0.62);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.product-field {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: 88px minmax(260px, 520px);
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
margin-bottom: 34px;
|
|
|
|
|
|
color: #e7f7ff;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.product-field input {
|
|
|
|
|
|
height: 38px;
|
|
|
|
|
|
padding: 0 12px;
|
|
|
|
|
|
border: 1px solid rgba(137, 189, 213, 0.82);
|
|
|
|
|
|
border-radius: 2px;
|
|
|
|
|
|
color: #f5fbff;
|
|
|
|
|
|
background: rgba(6, 22, 34, 0.86);
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.flow-steps {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 22px;
|
|
|
|
|
|
margin-bottom: 44px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.flow-pill {
|
|
|
|
|
|
min-width: 230px;
|
|
|
|
|
|
height: 58px;
|
|
|
|
|
|
border: 0;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
background: #1d9bd0;
|
|
|
|
|
|
font-size: 17px;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.flow-pill.active {
|
|
|
|
|
|
background: #20a4d9;
|
|
|
|
|
|
box-shadow: 0 0 0 2px rgba(113, 223, 255, 0.18);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.flow-arrow {
|
|
|
|
|
|
color: #d4dbe1;
|
|
|
|
|
|
font-size: 42px;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
letter-spacing: -8px;
|
|
|
|
|
|
transform: scaleX(0.72);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-content {
|
|
|
|
|
|
color: #d5e6f0;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
line-height: 1.75;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-content h4 {
|
|
|
|
|
|
margin: 0 0 14px;
|
|
|
|
|
|
color: #f5fbff;
|
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-content h5 {
|
|
|
|
|
|
margin: 16px 0 8px;
|
|
|
|
|
|
color: #eef9ff;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-content p {
|
|
|
|
|
|
margin: 4px 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-intro {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
gap: 22px;
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
padding: 18px 20px;
|
|
|
|
|
|
border-left: 3px solid #51dfff;
|
|
|
|
|
|
border-radius: 0 14px 14px 0;
|
|
|
|
|
|
background: linear-gradient(90deg, rgba(7, 95, 137, 0.28), rgba(4, 31, 49, 0.18));
|
|
|
|
|
|
|
|
|
|
|
|
> p {
|
|
|
|
|
|
max-width: 840px;
|
|
|
|
|
|
color: #c6dee9;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
line-height: 1.85;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-row-actions {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex: 0 0 auto;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
|
|
|
|
|
|
.el-button {
|
|
|
|
|
|
min-width: 112px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.indent {
|
|
|
|
|
|
padding-left: 24px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.source-title,
|
|
|
|
|
|
.table-tip {
|
|
|
|
|
|
margin-top: 20px !important;
|
|
|
|
|
|
color: #f0f8ff;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.feedback-grid {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
|
|
|
|
|
|
gap: 46px;
|
|
|
|
|
|
margin-top: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.feedback-grid section {
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.feedback-grid ol {
|
|
|
|
|
|
margin: 8px 0 0;
|
|
|
|
|
|
padding-left: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.feedback-grid li {
|
|
|
|
|
|
margin-bottom: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-table-wrap {
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
margin-top: 10px;
|
|
|
|
|
|
border: 1px solid rgba(139, 187, 208, 0.5);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-table {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
min-width: 1120px;
|
|
|
|
|
|
border-collapse: collapse;
|
|
|
|
|
|
table-layout: fixed;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-table th,
|
|
|
|
|
|
.conversion-table td {
|
|
|
|
|
|
border: 1px solid rgba(139, 187, 208, 0.5);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-table th {
|
|
|
|
|
|
height: 46px;
|
|
|
|
|
|
color: #f2fbff;
|
|
|
|
|
|
background: rgba(14, 76, 107, 0.72);
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-table th:first-child,
|
|
|
|
|
|
.conversion-table td:first-child {
|
|
|
|
|
|
width: 72px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-table td {
|
|
|
|
|
|
height: 78px;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
background: rgba(3, 18, 29, 0.38);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-table textarea {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 78px;
|
|
|
|
|
|
padding: 9px 10px;
|
|
|
|
|
|
border: 0;
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
resize: none;
|
|
|
|
|
|
color: #f4fbff;
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
font-family: inherit;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
line-height: 1.55;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-table textarea::placeholder {
|
|
|
|
|
|
color: #8fa4b1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-limit-tip {
|
|
|
|
|
|
margin: 12px 0 0 !important;
|
|
|
|
|
|
color: #ff958a;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-helper {
|
|
|
|
|
|
margin-top: 26px;
|
|
|
|
|
|
padding: 16px 18px;
|
|
|
|
|
|
border: 1px solid rgba(68, 163, 208, 0.3);
|
|
|
|
|
|
border-radius: 14px;
|
|
|
|
|
|
color: #b7d1de;
|
|
|
|
|
|
background: rgba(3, 27, 43, 0.4);
|
|
|
|
|
|
|
|
|
|
|
|
h5 {
|
|
|
|
|
|
margin: 0 0 4px;
|
|
|
|
|
|
color: #e8f9ff;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
p {
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
line-height: 1.8;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-validation-message {
|
|
|
|
|
|
margin: 14px 0 0 !important;
|
|
|
|
|
|
color: #ffbbb0;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.priority-content {
|
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.priority-template-table,
|
|
|
|
|
|
.priority-score-table {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
border-collapse: collapse;
|
|
|
|
|
|
table-layout: fixed;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.priority-template-table {
|
|
|
|
|
|
min-width: 1180px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.priority-score-table {
|
|
|
|
|
|
min-width: 1540px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.priority-template-table th,
|
|
|
|
|
|
.priority-template-table td,
|
|
|
|
|
|
.priority-score-table th,
|
|
|
|
|
|
.priority-score-table td {
|
|
|
|
|
|
border: 1px solid rgba(139, 187, 208, 0.58);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.priority-template-table th,
|
|
|
|
|
|
.priority-score-table th {
|
|
|
|
|
|
height: 42px;
|
|
|
|
|
|
padding: 6px 10px;
|
|
|
|
|
|
color: #f2fbff;
|
|
|
|
|
|
background: rgba(14, 76, 107, 0.72);
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.priority-template-table td {
|
|
|
|
|
|
min-height: 38px;
|
|
|
|
|
|
padding: 8px 10px;
|
|
|
|
|
|
color: #d8e8f1;
|
|
|
|
|
|
background: rgba(3, 18, 29, 0.38);
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
word-break: break-word;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.priority-template-table td:nth-child(2),
|
|
|
|
|
|
.priority-template-table td:nth-child(3) {
|
|
|
|
|
|
text-align: left;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.priority-score-table th {
|
|
|
|
|
|
white-space: normal;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.priority-score-table td {
|
|
|
|
|
|
height: 72px;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
background: rgba(3, 18, 29, 0.38);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.priority-score-table textarea {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 72px;
|
|
|
|
|
|
padding: 9px 10px;
|
|
|
|
|
|
border: 0;
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
resize: none;
|
|
|
|
|
|
color: #f4fbff;
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
font-family: inherit;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.decision-content {
|
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.decision-intro {
|
|
|
|
|
|
margin-bottom: 18px !important;
|
|
|
|
|
|
color: #d8e8f1;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.decision-field {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
margin-top: 30px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.decision-field span {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
|
color: #e7f7ff;
|
|
|
|
|
|
font-size: 17px;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.decision-field textarea {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
min-height: 210px;
|
|
|
|
|
|
padding: 14px 16px;
|
|
|
|
|
|
border: 1px solid rgba(139, 187, 208, 0.7);
|
|
|
|
|
|
border-radius: 2px;
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
resize: vertical;
|
|
|
|
|
|
color: #f4fbff;
|
|
|
|
|
|
background: rgba(3, 18, 29, 0.38);
|
|
|
|
|
|
font-family: inherit;
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
line-height: 1.65;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.decision-field textarea:focus {
|
|
|
|
|
|
border-color: rgba(90, 218, 255, 0.95);
|
|
|
|
|
|
box-shadow: 0 0 0 2px rgba(42, 173, 220, 0.18);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.training-actions {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
gap: 52px;
|
|
|
|
|
|
margin-top: 36px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.training-actions :deep(.training-action) {
|
|
|
|
|
|
min-width: 172px;
|
|
|
|
|
|
height: 64px;
|
|
|
|
|
|
padding: 0 28px;
|
|
|
|
|
|
border: 1px solid #2c83aa;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
color: #dff7ff;
|
|
|
|
|
|
background: rgba(13, 64, 88, 0.62);
|
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
|
font-size: 24px;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
line-height: 1;
|
|
|
|
|
|
letter-spacing: 0;
|
|
|
|
|
|
text-shadow: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.training-actions :deep(.training-action span) {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
color: inherit;
|
|
|
|
|
|
font-size: inherit;
|
|
|
|
|
|
line-height: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.training-actions :deep(.training-action--submit),
|
|
|
|
|
|
.training-actions :deep(.training-action--reset) {
|
|
|
|
|
|
border-color: #2c83aa;
|
|
|
|
|
|
color: #dff7ff;
|
|
|
|
|
|
background: rgba(13, 64, 88, 0.62);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.training-actions :deep(.training-action:hover:not(.is-disabled)) {
|
|
|
|
|
|
border-color: #46b5e7;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
background: rgba(18, 85, 116, 0.78);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 1100px) {
|
|
|
|
|
|
.feature-conversion-page {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.feedback-grid {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
gap: 18px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 760px) {
|
|
|
|
|
|
.feature-conversion-page {
|
|
|
|
|
|
padding: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.training-core {
|
|
|
|
|
|
padding: 18px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.product-field {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.flow-steps {
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.flow-pill,
|
|
|
|
|
|
.training-actions :deep(.training-action) {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.flow-arrow {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Student training standard: shared workbench hierarchy and controls. */
|
|
|
|
|
|
.feature-conversion-page {
|
|
|
|
|
|
grid-template-columns: minmax(720px, 1fr) 340px;
|
|
|
|
|
|
gap: 24px;
|
|
|
|
|
|
min-height: calc(100vh - 76px);
|
|
|
|
|
|
padding: 24px 24px 32px;
|
|
|
|
|
|
color: #eef5ff;
|
|
|
|
|
|
background: #06111d;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.training-core {
|
|
|
|
|
|
padding: 28px;
|
|
|
|
|
|
border: 1px solid rgba(0, 180, 255, 0.25);
|
|
|
|
|
|
border-radius: 36px;
|
|
|
|
|
|
background: rgba(8, 18, 28, 0.6);
|
|
|
|
|
|
box-shadow: inset 0 1px 0 rgba(169, 229, 255, 0.08), 0 22px 48px rgba(0, 0, 0, 0.22);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-header {
|
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-badge {
|
|
|
|
|
|
height: auto;
|
|
|
|
|
|
min-height: 28px;
|
|
|
|
|
|
padding: 4px 14px;
|
|
|
|
|
|
border-color: rgba(99, 217, 255, 0.55);
|
|
|
|
|
|
color: #dff5ff;
|
|
|
|
|
|
background: rgba(17, 126, 178, 0.36);
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
line-height: 1.4;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-title {
|
|
|
|
|
|
margin-top: 12px;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
font-size: 30px;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
line-height: 1.3;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-card,
|
|
|
|
|
|
.step-card {
|
|
|
|
|
|
border: 1px solid rgba(82, 174, 226, 0.42);
|
|
|
|
|
|
border-radius: 26px;
|
|
|
|
|
|
background: rgba(0, 25, 42, 0.64);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-card {
|
|
|
|
|
|
margin-top: 28px;
|
|
|
|
|
|
padding: 18px 22px 22px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.workbench-head {
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
gap: 18px;
|
|
|
|
|
|
margin-bottom: 22px;
|
|
|
|
|
|
padding-bottom: 18px;
|
|
|
|
|
|
border-bottom: 1px solid rgba(0, 180, 255, 0.2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.section-eyebrow {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
color: #71dfff;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
line-height: 1.4;
|
|
|
|
|
|
letter-spacing: 0.02em;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.workbench-head h3 {
|
|
|
|
|
|
margin: 4px 0 8px;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
font-size: 26px;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
line-height: 1.3;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.workbench-description {
|
|
|
|
|
|
max-width: 760px;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
color: #d7ecff;
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
|
line-height: 1.8;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.workbench-actions {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
margin-left: auto;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.outline-action {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
min-height: 40px;
|
|
|
|
|
|
padding: 0 18px;
|
|
|
|
|
|
border: 1px solid rgba(99, 217, 255, 0.55);
|
|
|
|
|
|
border-radius: 999px;
|
|
|
|
|
|
color: #e9fbff;
|
|
|
|
|
|
background: rgba(17, 126, 178, 0.36);
|
|
|
|
|
|
font: inherit;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: transform 0.18s ease, border-color 0.18s ease, background 0.18s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.outline-action:hover,
|
|
|
|
|
|
.outline-action:focus-visible {
|
|
|
|
|
|
border-color: rgba(116, 235, 255, 0.85);
|
|
|
|
|
|
background: rgba(18, 146, 204, 0.5);
|
|
|
|
|
|
transform: translateY(-1px);
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-indicator {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 0;
|
|
|
|
|
|
width: calc(100% + 24px);
|
|
|
|
|
|
min-height: 0;
|
|
|
|
|
|
margin: 0 -12px 32px;
|
|
|
|
|
|
padding: 18px 22px;
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
border: 1px solid rgba(0, 180, 255, 0.3);
|
|
|
|
|
|
border-radius: 18px;
|
|
|
|
|
|
background:
|
|
|
|
|
|
linear-gradient(90deg, rgba(6, 42, 61, 0.58), rgba(1, 18, 31, 0.42)),
|
|
|
|
|
|
rgba(0, 0, 0, 0.3);
|
|
|
|
|
|
box-shadow: inset 0 1px 0 rgba(145, 233, 255, 0.08);
|
|
|
|
|
|
scrollbar-width: thin;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-tab {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex: 1 0 145px;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
min-height: 66px;
|
|
|
|
|
|
padding: 8px 10px;
|
|
|
|
|
|
border: 1px solid rgba(68, 141, 177, 0.35);
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
color: #9ab3d0;
|
|
|
|
|
|
background: rgba(3, 27, 43, 0.52);
|
|
|
|
|
|
box-shadow: inset 0 1px 0 rgba(135, 221, 255, 0.04);
|
|
|
|
|
|
font: inherit;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
text-align: left;
|
|
|
|
|
|
transition: transform 0.2s ease, color 0.2s ease, border-color 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-tab:hover {
|
|
|
|
|
|
transform: translateY(-2px);
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
border-color: rgba(89, 223, 255, 0.82);
|
|
|
|
|
|
background: rgba(8, 92, 131, 0.52);
|
|
|
|
|
|
box-shadow: 0 7px 18px rgba(0, 0, 0, 0.24), inset 0 1px 0 rgba(152, 239, 255, 0.16);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-tab:hover .step-action {
|
|
|
|
|
|
color: #9bf4ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-tab:focus-visible {
|
|
|
|
|
|
outline: 2px solid rgba(92, 224, 255, 0.7);
|
|
|
|
|
|
outline-offset: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-tab.active {
|
|
|
|
|
|
border-color: rgba(89, 226, 255, 0.85);
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
background: linear-gradient(115deg, rgba(4, 109, 155, 0.78), rgba(5, 62, 102, 0.64));
|
|
|
|
|
|
box-shadow: 0 0 18px rgba(24, 183, 235, 0.22), inset 0 1px 0 rgba(176, 246, 255, 0.2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-marker {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
flex: 0 0 38px;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
width: 38px;
|
|
|
|
|
|
height: 38px;
|
|
|
|
|
|
border: 1px solid rgba(101, 176, 208, 0.6);
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
color: #a6c4d9;
|
|
|
|
|
|
background: rgba(3, 25, 40, 0.8);
|
|
|
|
|
|
box-shadow: inset 0 0 12px rgba(38, 174, 233, 0.08);
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
letter-spacing: 0.04em;
|
|
|
|
|
|
transition: border-color 0.2s ease, color 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-copy {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
gap: 4px;
|
|
|
|
|
|
margin-left: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-name {
|
|
|
|
|
|
display: -webkit-box;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
color: inherit;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
line-height: 1.25;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
-webkit-box-orient: vertical;
|
|
|
|
|
|
-webkit-line-clamp: 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-action {
|
|
|
|
|
|
color: #66b6d4;
|
|
|
|
|
|
font-size: 10px;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
letter-spacing: 0.06em;
|
|
|
|
|
|
line-height: 1;
|
|
|
|
|
|
transition: color 0.2s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-tab.active .step-marker {
|
|
|
|
|
|
border-color: #72e8ff;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
background: linear-gradient(135deg, #08b7e8, #1375d0);
|
|
|
|
|
|
box-shadow: 0 0 0 5px rgba(25, 179, 237, 0.14), 0 0 18px rgba(46, 208, 255, 0.58);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-tab.complete .step-marker {
|
|
|
|
|
|
border-color: rgba(84, 230, 221, 0.85);
|
|
|
|
|
|
color: #062b37;
|
|
|
|
|
|
background: #6ef0e1;
|
|
|
|
|
|
box-shadow: 0 0 12px rgba(79, 231, 218, 0.35);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-connector {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
flex: 0 1 40px;
|
|
|
|
|
|
min-width: 18px;
|
|
|
|
|
|
height: 2px;
|
|
|
|
|
|
margin: 0 8px;
|
|
|
|
|
|
overflow: visible;
|
|
|
|
|
|
background: rgba(98, 169, 201, 0.34);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-connector::after {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 50%;
|
|
|
|
|
|
right: -1px;
|
|
|
|
|
|
width: 6px;
|
|
|
|
|
|
height: 6px;
|
|
|
|
|
|
border-top: 1px solid #73b1ce;
|
|
|
|
|
|
border-right: 1px solid #73b1ce;
|
|
|
|
|
|
content: "";
|
|
|
|
|
|
transform: translateY(-50%) rotate(45deg);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-tab.complete + .step-connector {
|
|
|
|
|
|
background: linear-gradient(90deg, #6ef0e1, #1cb8e9);
|
|
|
|
|
|
box-shadow: 0 0 9px rgba(53, 218, 235, 0.46);
|
|
|
|
|
|
|
|
|
|
|
|
&::after {
|
|
|
|
|
|
border-color: #63e6f1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-card {
|
|
|
|
|
|
margin-top: 32px;
|
|
|
|
|
|
padding: 18px 22px 22px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.workbench-head + .step-card {
|
|
|
|
|
|
margin-top: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-card + .step-card {
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-title-row {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
gap: 18px;
|
|
|
|
|
|
margin-bottom: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-title-row h3 {
|
|
|
|
|
|
margin: 4px 0 0;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
font-size: 22px;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
line-height: 1.3;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-content {
|
|
|
|
|
|
color: #d7ecff;
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
line-height: 1.8;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-content h4 {
|
|
|
|
|
|
margin: 0 0 14px;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
font-size: 22px;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
line-height: 1.3;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-content h5,
|
|
|
|
|
|
.source-title,
|
|
|
|
|
|
.table-tip {
|
|
|
|
|
|
color: #dff5ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-content p {
|
|
|
|
|
|
margin: 0 0 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.product-field,
|
|
|
|
|
|
.decision-field {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
margin: 0 0 16px;
|
|
|
|
|
|
color: #dff5ff;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.product-field input,
|
|
|
|
|
|
.decision-field textarea,
|
|
|
|
|
|
.conversion-table textarea,
|
|
|
|
|
|
.priority-score-table textarea {
|
|
|
|
|
|
border: 1px solid rgba(45, 95, 126, 0.95);
|
|
|
|
|
|
border-radius: 14px;
|
|
|
|
|
|
color: #eef5ff;
|
|
|
|
|
|
background: #0f1a24;
|
|
|
|
|
|
font-family: inherit;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
line-height: 1.65;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.product-field input {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
width: min(100%, 680px);
|
|
|
|
|
|
min-height: 42px;
|
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
|
padding: 0 14px;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.product-field input:focus,
|
|
|
|
|
|
.decision-field textarea:focus,
|
|
|
|
|
|
.conversion-table textarea:focus,
|
|
|
|
|
|
.priority-score-table textarea:focus {
|
|
|
|
|
|
border-color: rgba(92, 224, 255, 0.7);
|
|
|
|
|
|
box-shadow: 0 0 0 3px rgba(0, 174, 255, 0.13);
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.feedback-grid {
|
|
|
|
|
|
gap: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.feedback-grid section,
|
|
|
|
|
|
.example-block {
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
border: 1px solid rgba(0, 180, 255, 0.22);
|
|
|
|
|
|
border-radius: 20px;
|
|
|
|
|
|
background: rgba(1, 14, 26, 0.72);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.feedback-grid li {
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
color: #d7ecff;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
line-height: 1.72;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-table-wrap {
|
|
|
|
|
|
margin-top: 12px;
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
border: 1px solid rgba(0, 180, 255, 0.22);
|
|
|
|
|
|
border-radius: 22px;
|
|
|
|
|
|
background: rgba(1, 14, 26, 0.72);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-table th,
|
|
|
|
|
|
.conversion-table td,
|
|
|
|
|
|
.priority-template-table th,
|
|
|
|
|
|
.priority-template-table td,
|
|
|
|
|
|
.priority-score-table th,
|
|
|
|
|
|
.priority-score-table td {
|
|
|
|
|
|
border-color: rgba(77, 167, 220, 0.2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-table th,
|
|
|
|
|
|
.priority-template-table th,
|
|
|
|
|
|
.priority-score-table th {
|
|
|
|
|
|
height: auto;
|
|
|
|
|
|
min-height: 46px;
|
|
|
|
|
|
padding: 12px;
|
|
|
|
|
|
color: #eaffff;
|
|
|
|
|
|
background: rgba(8, 55, 82, 0.98);
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 900;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-table td,
|
|
|
|
|
|
.priority-template-table td,
|
|
|
|
|
|
.priority-score-table td {
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
color: #d7f1ff;
|
|
|
|
|
|
background: rgba(1, 14, 26, 0.48);
|
|
|
|
|
|
vertical-align: top;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-table textarea,
|
|
|
|
|
|
.priority-score-table textarea {
|
|
|
|
|
|
height: 96px;
|
|
|
|
|
|
min-height: 38px;
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
resize: vertical;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.priority-template-table td {
|
|
|
|
|
|
color: #d7f1ff;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
line-height: 1.65;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.decision-field {
|
|
|
|
|
|
margin-top: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.decision-field span {
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
color: #dff5ff;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.decision-field textarea {
|
|
|
|
|
|
min-height: 110px;
|
|
|
|
|
|
padding: 12px 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.completion-content p {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-navigation {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
gap: 14px;
|
|
|
|
|
|
margin-top: 22px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.btn-nav {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
min-height: 40px;
|
|
|
|
|
|
padding: 0 18px;
|
|
|
|
|
|
border: 1px solid rgba(99, 217, 255, 0.55);
|
|
|
|
|
|
border-radius: 999px;
|
|
|
|
|
|
color: #e9fbff;
|
|
|
|
|
|
background: rgba(17, 126, 178, 0.36);
|
|
|
|
|
|
font: inherit;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.btn-nav.btn-primary,
|
|
|
|
|
|
.btn-nav.btn-save {
|
|
|
|
|
|
border-color: rgba(92, 224, 255, 0.7);
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
background: linear-gradient(95deg, #0b84bd, #096491);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.btn-nav:disabled {
|
|
|
|
|
|
cursor: not-allowed;
|
|
|
|
|
|
opacity: 0.45;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.training-actions {
|
|
|
|
|
|
margin-top: 36px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 1100px) {
|
|
|
|
|
|
.feature-conversion-page {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 900px) {
|
|
|
|
|
|
.feature-conversion-page {
|
|
|
|
|
|
padding: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.training-core {
|
|
|
|
|
|
padding: 18px;
|
|
|
|
|
|
border-radius: 24px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.workbench-head,
|
|
|
|
|
|
.workbench-actions {
|
|
|
|
|
|
align-items: stretch;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.workbench-actions,
|
|
|
|
|
|
.outline-action,
|
|
|
|
|
|
.step-navigation,
|
|
|
|
|
|
.btn-nav,
|
|
|
|
|
|
.training-actions :deep(.training-action) {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-indicator {
|
|
|
|
|
|
align-items: stretch;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
margin-right: 0;
|
|
|
|
|
|
margin-left: 0;
|
|
|
|
|
|
overflow: visible;
|
|
|
|
|
|
border-radius: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-tab {
|
|
|
|
|
|
flex: 0 0 auto;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-connector {
|
|
|
|
|
|
flex: 0 0 20px;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
width: 2px;
|
|
|
|
|
|
height: 20px;
|
|
|
|
|
|
margin-left: 29px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
writing-mode: vertical-rl;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.step-navigation {
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-intro,
|
|
|
|
|
|
.conversion-row-actions {
|
|
|
|
|
|
align-items: stretch;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.conversion-row-actions .el-button {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.workbench-head--actions-only {
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
margin-bottom: 18px;
|
|
|
|
|
|
padding-bottom: 0;
|
|
|
|
|
|
border-bottom: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
|
|
|