|
|
|
@ -227,6 +227,65 @@
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</section>
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<section v-show="currentStep === 5" class="step-panel">
|
|
|
|
|
|
|
|
<p class="task-desc task-desc--compact">
|
|
|
|
|
|
|
|
结合 RFM 用户群画像和重点用户画像的分析结果,进一步细分市场,寻找产品开发机会。请评估各细分市场的吸引力,并从不同细分用户的行为特征和需求痛点中提炼产品机会。
|
|
|
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="market-segment-toolbar">
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
<p class="section-eyebrow">用户细分</p>
|
|
|
|
|
|
|
|
<h4>细分市场分析表</h4>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="market-segment-toolbar__actions">
|
|
|
|
|
|
|
|
<el-button class="segment-action" :disabled="form.marketSegments.length >= MAX_MARKET_SEGMENTS" @click="addMarketSegment">
|
|
|
|
|
|
|
|
增加一行
|
|
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
<el-button class="segment-action segment-action--muted" :disabled="form.marketSegments.length <= 1" @click="removeMarketSegment">
|
|
|
|
|
|
|
|
删除一行
|
|
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<p class="market-segment-tip">可直接编辑表格内容,支持行扩展,最多 {{ MAX_MARKET_SEGMENTS }} 行。</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="market-segment-table-wrap">
|
|
|
|
|
|
|
|
<table class="market-segment-table">
|
|
|
|
|
|
|
|
<thead>
|
|
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
|
|
<th>细分市场</th>
|
|
|
|
|
|
|
|
<th>市场吸引力</th>
|
|
|
|
|
|
|
|
<th>需求痛点</th>
|
|
|
|
|
|
|
|
<th>行为特征</th>
|
|
|
|
|
|
|
|
<th>产品机会</th>
|
|
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
</thead>
|
|
|
|
|
|
|
|
<tbody>
|
|
|
|
|
|
|
|
<tr v-for="(segment, index) in form.marketSegments" :key="index">
|
|
|
|
|
|
|
|
<td>
|
|
|
|
|
|
|
|
<input v-model="segment.market" class="market-segment-input" placeholder="请输入细分市场" />
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
<td>
|
|
|
|
|
|
|
|
<el-radio-group v-model="segment.attractiveness" class="market-attractiveness">
|
|
|
|
|
|
|
|
<el-radio label="高">高</el-radio>
|
|
|
|
|
|
|
|
<el-radio label="中">中</el-radio>
|
|
|
|
|
|
|
|
<el-radio label="低">低</el-radio>
|
|
|
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
<td><textarea v-model="segment.painPoints" class="market-segment-textarea" placeholder="结合用户画像填写需求痛点" /></td>
|
|
|
|
|
|
|
|
<td><textarea v-model="segment.behaviorCharacteristics" class="market-segment-textarea" placeholder="填写该细分用户的行为特征" /></td>
|
|
|
|
|
|
|
|
<td><textarea v-model="segment.productOpportunity" class="market-segment-textarea" placeholder="提炼可切入的产品机会" /></td>
|
|
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
</tbody>
|
|
|
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="market-selection-block">
|
|
|
|
|
|
|
|
<p class="section-eyebrow">市场选择</p>
|
|
|
|
|
|
|
|
<h4>结合前面的数据分析,请说明团队应该针对哪些用户,开发什么样的产品。</h4>
|
|
|
|
|
|
|
|
<textarea v-model="form.marketSelection" class="market-selection-textarea" placeholder="请写明目标用户、核心需求和建议开发的产品方案" />
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<div v-if="steps.length" class="step-actions">
|
|
|
|
<div v-if="steps.length" class="step-actions">
|
|
|
|
<el-button class="step-action step-action--previous" :disabled="currentStep <= 1" @click="currentStep -= 1">
|
|
|
|
<el-button class="step-action step-action--previous" :disabled="currentStep <= 1" @click="currentStep -= 1">
|
|
|
|
<el-icon><ArrowLeft /></el-icon>
|
|
|
|
<el-icon><ArrowLeft /></el-icon>
|
|
|
|
@ -271,7 +330,7 @@ import TrainingAiSidebar from "@/views/components/TrainingAiSidebar.vue";
|
|
|
|
import TrainingMaterialButton from "@/views/components/TrainingMaterialButton.vue";
|
|
|
|
import TrainingMaterialButton from "@/views/components/TrainingMaterialButton.vue";
|
|
|
|
import TrainingTaskBrief from "@/views/components/TrainingTaskBrief.vue";
|
|
|
|
import TrainingTaskBrief from "@/views/components/TrainingTaskBrief.vue";
|
|
|
|
import { getTrainingTaskByKey } from "@/api/trainingTask";
|
|
|
|
import { getTrainingTaskByKey } from "@/api/trainingTask";
|
|
|
|
import { checkTargetUserProfileStepFour, checkTargetUserProfileStepOne, checkTargetUserProfileStepThree, checkTargetUserProfileStepTwo, getStudentTrainingAnswer, saveStudentTrainingAnswer, uploadStudentTrainingFile } from "@/api/studentTrainingAnswer";
|
|
|
|
import { checkTargetUserProfileStepFive, checkTargetUserProfileStepFour, checkTargetUserProfileStepOne, checkTargetUserProfileStepThree, checkTargetUserProfileStepTwo, getStudentTrainingAnswer, saveStudentTrainingAnswer, uploadStudentTrainingFile } from "@/api/studentTrainingAnswer";
|
|
|
|
|
|
|
|
|
|
|
|
const TASK_KEY = "target-user-profile";
|
|
|
|
const TASK_KEY = "target-user-profile";
|
|
|
|
const RFM_CHARTS = [
|
|
|
|
const RFM_CHARTS = [
|
|
|
|
@ -286,6 +345,8 @@ const RFM_INSIGHT_ROWS = [
|
|
|
|
{ dimension: "用户忠诚度", keyPoint: "F 分数分布反映的用户复购意愿如何?" },
|
|
|
|
{ dimension: "用户忠诚度", keyPoint: "F 分数分布反映的用户复购意愿如何?" },
|
|
|
|
{ dimension: "重点客户群特征", keyPoint: "哪些客户最值得关注?为什么?" },
|
|
|
|
{ dimension: "重点客户群特征", keyPoint: "哪些客户最值得关注?为什么?" },
|
|
|
|
];
|
|
|
|
];
|
|
|
|
|
|
|
|
const DEFAULT_FLOW_STEPS = ["RFM 用户分层分析", "RFM 数据可视化", "用户群体特点分析", "重点用户画像", "用户细分与市场选择"];
|
|
|
|
|
|
|
|
const MAX_MARKET_SEGMENTS = 6;
|
|
|
|
const { proxy } = getCurrentInstance();
|
|
|
|
const { proxy } = getCurrentInstance();
|
|
|
|
|
|
|
|
|
|
|
|
const taskConfig = ref(null);
|
|
|
|
const taskConfig = ref(null);
|
|
|
|
@ -427,12 +488,12 @@ function createKeyUserRecords() {
|
|
|
|
];
|
|
|
|
];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function createSegmentationRows() {
|
|
|
|
function createMarketSegments() {
|
|
|
|
return ["新锐白领", "精致妈妈", "都市银发", "继续补充", "继续补充"].map((market) => ({
|
|
|
|
return ["职场白领(25-35岁)", "精致妈妈(28-38岁)", "银发人群(50-65岁)", ""].map((market) => createEmptyMarketSegment(market));
|
|
|
|
market,
|
|
|
|
}
|
|
|
|
customerAnalysis: "",
|
|
|
|
|
|
|
|
productOpportunity: "",
|
|
|
|
function createEmptyMarketSegment(market = "") {
|
|
|
|
}));
|
|
|
|
return { market, attractiveness: "", painPoints: "", behaviorCharacteristics: "", productOpportunity: "" };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function createForm() {
|
|
|
|
function createForm() {
|
|
|
|
@ -445,12 +506,8 @@ function createForm() {
|
|
|
|
profileAnalysis: "",
|
|
|
|
profileAnalysis: "",
|
|
|
|
keyUserProfile: "",
|
|
|
|
keyUserProfile: "",
|
|
|
|
keyUserRecords: createKeyUserRecords(),
|
|
|
|
keyUserRecords: createKeyUserRecords(),
|
|
|
|
segmentationStrategy: "",
|
|
|
|
marketSegments: createMarketSegments(),
|
|
|
|
segmentationRows: createSegmentationRows(),
|
|
|
|
marketSelection: "",
|
|
|
|
coreFunctions: ["", "", ""],
|
|
|
|
|
|
|
|
priceMin: "",
|
|
|
|
|
|
|
|
priceMax: "",
|
|
|
|
|
|
|
|
conclusion: "",
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -481,7 +538,10 @@ const taskTitle = computed(() => taskConfig.value?.taskName || "目标用户画
|
|
|
|
const taskBackground = computed(() => taskConfig.value?.background || defaultBackground);
|
|
|
|
const taskBackground = computed(() => taskConfig.value?.background || defaultBackground);
|
|
|
|
const taskGoals = computed(() => parseArray(taskConfig.value?.objectives, defaultGoals));
|
|
|
|
const taskGoals = computed(() => parseArray(taskConfig.value?.objectives, defaultGoals));
|
|
|
|
const taskRequirement = computed(() => taskConfig.value?.requirements || defaultRequirement);
|
|
|
|
const taskRequirement = computed(() => taskConfig.value?.requirements || defaultRequirement);
|
|
|
|
const flowSteps = computed(() => parseArray(taskConfig.value?.steps, []));
|
|
|
|
const flowSteps = computed(() => {
|
|
|
|
|
|
|
|
const configuredSteps = parseArray(taskConfig.value?.steps, DEFAULT_FLOW_STEPS);
|
|
|
|
|
|
|
|
return configuredSteps.length >= DEFAULT_FLOW_STEPS.length ? configuredSteps : DEFAULT_FLOW_STEPS;
|
|
|
|
|
|
|
|
});
|
|
|
|
const steps = computed(() =>
|
|
|
|
const steps = computed(() =>
|
|
|
|
flowSteps.value.map((name, index) => ({
|
|
|
|
flowSteps.value.map((name, index) => ({
|
|
|
|
no: index + 1,
|
|
|
|
no: index + 1,
|
|
|
|
@ -558,16 +618,20 @@ function normalizeKeyUserRecords(records, legacyText = "") {
|
|
|
|
return defaults;
|
|
|
|
return defaults;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeSegmentationRows(rows, legacyText = "") {
|
|
|
|
function normalizeMarketSegments(rows, legacyRows = []) {
|
|
|
|
const defaults = createSegmentationRows();
|
|
|
|
const defaults = createMarketSegments();
|
|
|
|
if (Array.isArray(rows)) {
|
|
|
|
if (Array.isArray(rows) && rows.length) {
|
|
|
|
return defaults.map((item, index) => ({
|
|
|
|
return rows.slice(0, MAX_MARKET_SEGMENTS).map((item, index) => ({
|
|
|
|
...item,
|
|
|
|
...(defaults[index] || createEmptyMarketSegment()),
|
|
|
|
...(rows[index] || {}),
|
|
|
|
...(item || {}),
|
|
|
|
}));
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (legacyText) {
|
|
|
|
if (Array.isArray(legacyRows) && legacyRows.length) {
|
|
|
|
defaults[0].customerAnalysis = legacyText;
|
|
|
|
return legacyRows.slice(0, MAX_MARKET_SEGMENTS).map((item, index) => ({
|
|
|
|
|
|
|
|
...(defaults[index] || createEmptyMarketSegment()),
|
|
|
|
|
|
|
|
market: String(item?.market || defaults[index]?.market || ""),
|
|
|
|
|
|
|
|
productOpportunity: String(item?.productOpportunity || ""),
|
|
|
|
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return defaults;
|
|
|
|
return defaults;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -586,14 +650,10 @@ function applySavedAnswer(value) {
|
|
|
|
profileAnalysis: parsed.profileAnalysis || "",
|
|
|
|
profileAnalysis: parsed.profileAnalysis || "",
|
|
|
|
keyUserProfile: parsed.keyUserProfile || "",
|
|
|
|
keyUserProfile: parsed.keyUserProfile || "",
|
|
|
|
keyUserRecords: normalizeKeyUserRecords(parsed.keyUserRecords, parsed.keyUserProfile),
|
|
|
|
keyUserRecords: normalizeKeyUserRecords(parsed.keyUserRecords, parsed.keyUserProfile),
|
|
|
|
segmentationStrategy: parsed.segmentationStrategy || "",
|
|
|
|
marketSegments: normalizeMarketSegments(parsed.marketSegments, parsed.segmentationRows),
|
|
|
|
segmentationRows: normalizeSegmentationRows(parsed.segmentationRows, parsed.segmentationStrategy),
|
|
|
|
marketSelection: parsed.marketSelection || parsed.segmentationStrategy || "",
|
|
|
|
coreFunctions: Array.isArray(parsed.coreFunctions) ? ["", "", ""].map((item, index) => parsed.coreFunctions[index] || item) : ["", "", ""],
|
|
|
|
|
|
|
|
priceMin: parsed.priceMin || "",
|
|
|
|
|
|
|
|
priceMax: parsed.priceMax || "",
|
|
|
|
|
|
|
|
conclusion: parsed.conclusion || "",
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
currentStep.value = Math.min(Math.max(Number(parsed.currentStep || 1), 1), 4);
|
|
|
|
currentStep.value = Math.min(Math.max(Number(parsed.currentStep || 1), 1), steps.value.length || DEFAULT_FLOW_STEPS.length);
|
|
|
|
} catch (error) {
|
|
|
|
} catch (error) {
|
|
|
|
// 忽略历史异常数据。
|
|
|
|
// 忽略历史异常数据。
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -697,6 +757,16 @@ async function handleFileChange(event) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function addMarketSegment() {
|
|
|
|
|
|
|
|
if (form.value.marketSegments.length >= MAX_MARKET_SEGMENTS) return;
|
|
|
|
|
|
|
|
form.value.marketSegments.push(createEmptyMarketSegment());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function removeMarketSegment() {
|
|
|
|
|
|
|
|
if (form.value.marketSegments.length <= 1) return;
|
|
|
|
|
|
|
|
form.value.marketSegments.pop();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function handleChartFileChange(chart, event) {
|
|
|
|
async function handleChartFileChange(chart, event) {
|
|
|
|
const file = event.target.files?.[0];
|
|
|
|
const file = event.target.files?.[0];
|
|
|
|
if (!file) return;
|
|
|
|
if (!file) return;
|
|
|
|
@ -777,12 +847,8 @@ function buildAnswerPayload(status) {
|
|
|
|
profileAnalysis: form.value.profileAnalysis,
|
|
|
|
profileAnalysis: form.value.profileAnalysis,
|
|
|
|
keyUserProfile: form.value.keyUserProfile,
|
|
|
|
keyUserProfile: form.value.keyUserProfile,
|
|
|
|
keyUserRecords: form.value.keyUserRecords,
|
|
|
|
keyUserRecords: form.value.keyUserRecords,
|
|
|
|
segmentationStrategy: form.value.segmentationStrategy,
|
|
|
|
marketSegments: form.value.marketSegments,
|
|
|
|
segmentationRows: form.value.segmentationRows,
|
|
|
|
marketSelection: form.value.marketSelection,
|
|
|
|
coreFunctions: form.value.coreFunctions,
|
|
|
|
|
|
|
|
priceMin: form.value.priceMin,
|
|
|
|
|
|
|
|
priceMax: form.value.priceMax,
|
|
|
|
|
|
|
|
conclusion: form.value.conclusion,
|
|
|
|
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -813,6 +879,9 @@ async function persist(status = "IN_PROGRESS") {
|
|
|
|
if (status !== "RESET" && (currentStep.value === 4 || status === "SUBMITTED")) {
|
|
|
|
if (status !== "RESET" && (currentStep.value === 4 || status === "SUBMITTED")) {
|
|
|
|
await checkTargetUserProfileStepFour({ records: form.value.keyUserRecords });
|
|
|
|
await checkTargetUserProfileStepFour({ records: form.value.keyUserRecords });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status !== "RESET" && (currentStep.value === 5 || status === "SUBMITTED")) {
|
|
|
|
|
|
|
|
await checkTargetUserProfileStepFive({ segments: form.value.marketSegments, marketSelection: form.value.marketSelection });
|
|
|
|
|
|
|
|
}
|
|
|
|
await saveStudentTrainingAnswer(TASK_KEY, buildAnswerPayload(status));
|
|
|
|
await saveStudentTrainingAnswer(TASK_KEY, buildAnswerPayload(status));
|
|
|
|
proxy?.$modal?.msgSuccess(status === "SUBMITTED" ? "提交成功" : "保存成功");
|
|
|
|
proxy?.$modal?.msgSuccess(status === "SUBMITTED" ? "提交成功" : "保存成功");
|
|
|
|
} finally {
|
|
|
|
} finally {
|
|
|
|
@ -825,9 +894,7 @@ function saveCurrentProgress() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function goNext() {
|
|
|
|
async function goNext() {
|
|
|
|
if (currentStep.value === 1 || currentStep.value === 2 || currentStep.value === 3) {
|
|
|
|
|
|
|
|
await persist("IN_PROGRESS");
|
|
|
|
await persist("IN_PROGRESS");
|
|
|
|
}
|
|
|
|
|
|
|
|
currentStep.value += 1;
|
|
|
|
currentStep.value += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -848,13 +915,12 @@ function exportOutcome() {
|
|
|
|
`${record.title}(${record.code})\n用户:${record.user || ""}\n基础属性:${record.basicAttributes || ""}\n标签:${record.tags || ""}\n行为特征:\n${record.behavior || ""}\n需求痛点:\n${record.painPoints || ""}\n消费心理:\n${record.psychology || ""}`,
|
|
|
|
`${record.title}(${record.code})\n用户:${record.user || ""}\n基础属性:${record.basicAttributes || ""}\n标签:${record.tags || ""}\n行为特征:\n${record.behavior || ""}\n需求痛点:\n${record.painPoints || ""}\n消费心理:\n${record.psychology || ""}`,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.join("\n\n");
|
|
|
|
.join("\n\n");
|
|
|
|
const segmentationText = form.value.segmentationRows
|
|
|
|
const segmentationText = form.value.marketSegments
|
|
|
|
.map((row) => `${row.market || ""}\n客户分析:\n${row.customerAnalysis || ""}\n产品机会:\n${row.productOpportunity || ""}`)
|
|
|
|
.map((row) => `${row.market || ""}\n市场吸引力:${row.attractiveness || ""}\n需求痛点:\n${row.painPoints || ""}\n行为特征:\n${row.behaviorCharacteristics || ""}\n产品机会:\n${row.productOpportunity || ""}`)
|
|
|
|
.join("\n\n");
|
|
|
|
.join("\n\n");
|
|
|
|
const rfmInsightsText = form.value.rfmInsights.map((item) => `${item.dimension}:\n${item.analysis || ""}`).join("\n\n");
|
|
|
|
const rfmInsightsText = form.value.rfmInsights.map((item) => `${item.dimension}:\n${item.analysis || ""}`).join("\n\n");
|
|
|
|
const coreFunctionsText = form.value.coreFunctions.map((item, index) => `核心功能${index + 1}:${item || ""}`).join("\n");
|
|
|
|
|
|
|
|
const rfmChartsText = RFM_CHARTS.map((chart) => `${chart.title}:${form.value.rfmCharts[chart.id]?.url || "未上传"}`).join("\n");
|
|
|
|
const rfmChartsText = RFM_CHARTS.map((chart) => `${chart.title}:${form.value.rfmCharts[chart.id]?.url || "未上传"}`).join("\n");
|
|
|
|
const content = `目标用户画像\n\n任务流程:${flowSteps.value.join(" > ")}\n\nRFM 分层分析 Excel:${form.value.profileFileName || "未上传"}\n文件地址:${form.value.profileFileUrl || ""}\n\nRFM 可视化图表:\n${rfmChartsText}\n\nRFM 用户群体特点分析:\n${rfmInsightsText}\n\n重点用户画像:\n${keyUserRecordsText}\n\n用户细分与市场选择:\n${segmentationText}\n\n计划设计的核心功能:\n${coreFunctionsText}\n\n预计产品价格区间(元):${form.value.priceMin || ""} - ${form.value.priceMax || ""}\n\n分析结论:\n${form.value.conclusion || ""}`;
|
|
|
|
const content = `目标用户画像\n\n任务流程:${flowSteps.value.join(" > ")}\n\nRFM 分层分析 Excel:${form.value.profileFileName || "未上传"}\n文件地址:${form.value.profileFileUrl || ""}\n\nRFM 可视化图表:\n${rfmChartsText}\n\nRFM 用户群体特点分析:\n${rfmInsightsText}\n\n重点用户画像:\n${keyUserRecordsText}\n\n用户细分与市场选择:\n${segmentationText}\n\n市场选择结论:\n${form.value.marketSelection || ""}`;
|
|
|
|
const blob = new Blob([content], { type: "text/plain;charset=utf-8" });
|
|
|
|
const blob = new Blob([content], { type: "text/plain;charset=utf-8" });
|
|
|
|
const url = URL.createObjectURL(blob);
|
|
|
|
const url = URL.createObjectURL(blob);
|
|
|
|
const link = document.createElement("a");
|
|
|
|
const link = document.createElement("a");
|
|
|
|
@ -2086,6 +2152,153 @@ function exportOutcome() {
|
|
|
|
background: rgba(18, 85, 116, 0.78);
|
|
|
|
background: rgba(18, 85, 116, 0.78);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-segment-toolbar {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
|
|
gap: 18px;
|
|
|
|
|
|
|
|
margin-top: 26px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.section-eyebrow {
|
|
|
|
|
|
|
|
margin-bottom: 5px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
h4 {
|
|
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
|
|
color: #f0fbff;
|
|
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-segment-toolbar__actions {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-segment-toolbar__actions :deep(.segment-action) {
|
|
|
|
|
|
|
|
min-width: 104px;
|
|
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
|
|
border: 1px solid rgba(92, 224, 255, 0.7);
|
|
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
|
|
background: linear-gradient(95deg, #0b84bd, #096491);
|
|
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-segment-toolbar__actions :deep(.segment-action--muted) {
|
|
|
|
|
|
|
|
border-color: rgba(118, 176, 202, 0.55);
|
|
|
|
|
|
|
|
color: #cce7f5;
|
|
|
|
|
|
|
|
background: rgba(14, 73, 101, 0.76);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-segment-tip {
|
|
|
|
|
|
|
|
margin: 10px 0 16px;
|
|
|
|
|
|
|
|
color: #6ee3ff;
|
|
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-segment-table-wrap {
|
|
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
|
|
border: 1px solid rgba(0, 180, 255, 0.25);
|
|
|
|
|
|
|
|
border-radius: 18px;
|
|
|
|
|
|
|
|
background: rgba(1, 14, 26, 0.72);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-segment-table {
|
|
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
min-width: 1120px;
|
|
|
|
|
|
|
|
border-collapse: collapse;
|
|
|
|
|
|
|
|
table-layout: fixed;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
th,
|
|
|
|
|
|
|
|
td {
|
|
|
|
|
|
|
|
padding: 12px;
|
|
|
|
|
|
|
|
border-right: 1px solid rgba(77, 167, 220, 0.24);
|
|
|
|
|
|
|
|
border-bottom: 1px solid rgba(77, 167, 220, 0.24);
|
|
|
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
th {
|
|
|
|
|
|
|
|
color: #ecfbff;
|
|
|
|
|
|
|
|
background: linear-gradient(100deg, #158fc4, #08739f);
|
|
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
td:nth-child(1) { width: 18%; }
|
|
|
|
|
|
|
|
td:nth-child(2) { width: 15%; }
|
|
|
|
|
|
|
|
td:nth-child(n + 3) { width: 22.33%; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tr:last-child td { border-bottom: 0; }
|
|
|
|
|
|
|
|
th:last-child,
|
|
|
|
|
|
|
|
td:last-child { border-right: 0; }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-segment-input,
|
|
|
|
|
|
|
|
.market-segment-textarea,
|
|
|
|
|
|
|
|
.market-selection-textarea {
|
|
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
border: 1px solid rgba(67, 134, 166, 0.8);
|
|
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
|
|
color: #eaf7ff;
|
|
|
|
|
|
|
|
background: rgba(7, 29, 43, 0.92);
|
|
|
|
|
|
|
|
font-family: inherit;
|
|
|
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
&::placeholder { color: #7896a5; }
|
|
|
|
|
|
|
|
&:focus {
|
|
|
|
|
|
|
|
border-color: #5fe7ff;
|
|
|
|
|
|
|
|
box-shadow: 0 0 0 3px rgba(34, 207, 255, 0.14);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-segment-input {
|
|
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
|
|
padding: 0 10px;
|
|
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-segment-textarea {
|
|
|
|
|
|
|
|
min-height: 108px;
|
|
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
|
|
resize: vertical;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-attractiveness {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-attractiveness :deep(.el-radio) {
|
|
|
|
|
|
|
|
margin-right: 0;
|
|
|
|
|
|
|
|
color: #d9f2ff;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-selection-block {
|
|
|
|
|
|
|
|
margin-top: 34px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.section-eyebrow { margin-bottom: 8px; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
h4 {
|
|
|
|
|
|
|
|
margin: 0 0 14px;
|
|
|
|
|
|
|
|
color: #dcefff;
|
|
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
|
|
line-height: 1.7;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-selection-textarea {
|
|
|
|
|
|
|
|
min-height: 180px;
|
|
|
|
|
|
|
|
padding: 14px;
|
|
|
|
|
|
|
|
border-radius: 14px;
|
|
|
|
|
|
|
|
resize: vertical;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 1100px) {
|
|
|
|
@media (max-width: 1100px) {
|
|
|
|
.target-profile-page {
|
|
|
|
.target-profile-page {
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
@ -2102,6 +2315,11 @@ function exportOutcome() {
|
|
|
|
.product-reference {
|
|
|
|
.product-reference {
|
|
|
|
justify-content: flex-start;
|
|
|
|
justify-content: flex-start;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-segment-toolbar {
|
|
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 900px) {
|
|
|
|
@media (max-width: 900px) {
|
|
|
|
@ -2166,6 +2384,10 @@ function exportOutcome() {
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.market-segment-toolbar__actions {
|
|
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.interview-tabs {
|
|
|
|
.interview-tabs {
|
|
|
|
flex-direction: column;
|
|
|
|
flex-direction: column;
|
|
|
|
gap: 12px;
|
|
|
|
gap: 12px;
|
|
|
|
|