feat(template-wizard): enhance competitor management and update UI messages
Frontend CI / Frontend (push) Successful in 3m27s
Frontend CI / Frontend (push) Successful in 3m27s
This commit is contained in:
@@ -882,12 +882,14 @@ const enUS = {
|
|||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
analyze: 'Analyze',
|
analyze: 'Analyze',
|
||||||
|
analyzeCompetitors: 'AI fill competitors',
|
||||||
addCompetitor: 'Add competitor',
|
addCompetitor: 'Add competitor',
|
||||||
addSection: 'Add section',
|
addSection: 'Add section',
|
||||||
addOutlineNode: 'Add node',
|
addOutlineNode: 'Add node',
|
||||||
addOutlineChild: 'Add child',
|
addOutlineChild: 'Add child',
|
||||||
favorite: 'Save',
|
favorite: 'Save',
|
||||||
saved: 'Saved',
|
saved: 'Saved',
|
||||||
|
unfavorite: 'Unsave',
|
||||||
submit: 'Submit and generate',
|
submit: 'Submit and generate',
|
||||||
},
|
},
|
||||||
review: {
|
review: {
|
||||||
@@ -937,8 +939,8 @@ const enUS = {
|
|||||||
'AI will use the brand question to organize the topic context and suggest reference targets.',
|
'AI will use the brand question to organize the topic context and suggest reference targets.',
|
||||||
},
|
},
|
||||||
assist: {
|
assist: {
|
||||||
analyzeTitle: 'AI is analyzing brand questions and competitors. Please wait…',
|
analyzeTitle: 'AI is filling competitor information. Please wait…',
|
||||||
analyzeTitleNoCompetitors: 'AI is analyzing brand questions and context. Please wait…',
|
analyzeTitleNoCompetitors: 'AI is filling competitor information. Please wait…',
|
||||||
titleTitle: 'AI is generating titles. Please wait…',
|
titleTitle: 'AI is generating titles. Please wait…',
|
||||||
outlineTitle: 'AI is generating the article outline. Please wait…',
|
outlineTitle: 'AI is generating the article outline. Please wait…',
|
||||||
analyzeStages: {
|
analyzeStages: {
|
||||||
@@ -946,7 +948,8 @@ const enUS = {
|
|||||||
keywords: 'Extracting keyword opportunities…',
|
keywords: 'Extracting keyword opportunities…',
|
||||||
questions: 'Organizing brand questions…',
|
questions: 'Organizing brand questions…',
|
||||||
competitors: 'Mapping competitors and websites…',
|
competitors: 'Mapping competitors and websites…',
|
||||||
context: 'Organizing the content context…',
|
context: 'Organizing brand and website context…',
|
||||||
|
refine: 'Merging and filtering competitor suggestions…',
|
||||||
},
|
},
|
||||||
titleStages: {
|
titleStages: {
|
||||||
context: 'Preparing the current brief…',
|
context: 'Preparing the current brief…',
|
||||||
@@ -970,9 +973,11 @@ const enUS = {
|
|||||||
missingOutline: 'Please select at least one outline section.',
|
missingOutline: 'Please select at least one outline section.',
|
||||||
missingGeneratedOutline: 'Please generate and confirm the article outline first.',
|
missingGeneratedOutline: 'Please generate and confirm the article outline first.',
|
||||||
customOutlineTooLong: 'Custom sections cannot exceed {count} characters.',
|
customOutlineTooLong: 'Custom sections cannot exceed {count} characters.',
|
||||||
|
selectBrandBeforeCompetitors: 'Choose a brand from the library before managing competitors.',
|
||||||
selectBrandBeforeFavorite: 'Choose a brand from the library before saving competitors.',
|
selectBrandBeforeFavorite: 'Choose a brand from the library before saving competitors.',
|
||||||
missingCompetitorName: 'Enter a competitor name before saving it to the library.',
|
missingCompetitorName: 'Enter a competitor name before saving it to the library.',
|
||||||
savedCompetitor: 'Competitor saved to the brand library.',
|
savedCompetitor: 'Competitor saved to the brand library.',
|
||||||
|
unsavedCompetitor: 'Competitor removed from the brand library.',
|
||||||
assistReady: 'AI analysis is ready. You can keep refining the draft.',
|
assistReady: 'AI analysis is ready. You can keep refining the draft.',
|
||||||
assistFailed: 'AI analysis failed. Please try again.',
|
assistFailed: 'AI analysis failed. Please try again.',
|
||||||
assistTimeout: 'AI analysis timed out. Please try again.',
|
assistTimeout: 'AI analysis timed out. Please try again.',
|
||||||
|
|||||||
@@ -839,12 +839,14 @@ const zhCN = {
|
|||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
analyze: "分析",
|
analyze: "分析",
|
||||||
|
analyzeCompetitors: "AI 补齐竞品",
|
||||||
addCompetitor: "添加竞品",
|
addCompetitor: "添加竞品",
|
||||||
addSection: "添加结构",
|
addSection: "添加结构",
|
||||||
addOutlineNode: "添加节点",
|
addOutlineNode: "添加节点",
|
||||||
addOutlineChild: "添加子节点",
|
addOutlineChild: "添加子节点",
|
||||||
favorite: "收藏",
|
favorite: "收藏",
|
||||||
saved: "已收藏",
|
saved: "已收藏",
|
||||||
|
unfavorite: "取消收藏",
|
||||||
submit: "提交并生成",
|
submit: "提交并生成",
|
||||||
},
|
},
|
||||||
review: {
|
review: {
|
||||||
@@ -891,8 +893,8 @@ const zhCN = {
|
|||||||
researchReportDescription: "AI 将基于品牌问题梳理主题背景,并生成参照对象参考",
|
researchReportDescription: "AI 将基于品牌问题梳理主题背景,并生成参照对象参考",
|
||||||
},
|
},
|
||||||
assist: {
|
assist: {
|
||||||
analyzeTitle: "AI 正在分析品牌问题和竞品,请稍后…",
|
analyzeTitle: "AI 正在补齐竞品信息,请稍后…",
|
||||||
analyzeTitleNoCompetitors: "AI 正在分析品牌问题和评测上下文,请稍后…",
|
analyzeTitleNoCompetitors: "AI 正在补齐竞品信息,请稍后…",
|
||||||
titleTitle: "AI 正在生成标题,请稍后…",
|
titleTitle: "AI 正在生成标题,请稍后…",
|
||||||
outlineTitle: "AI 正在生成文章大纲,请稍后…",
|
outlineTitle: "AI 正在生成文章大纲,请稍后…",
|
||||||
analyzeStages: {
|
analyzeStages: {
|
||||||
@@ -900,7 +902,8 @@ const zhCN = {
|
|||||||
keywords: "关键词提炼中…",
|
keywords: "关键词提炼中…",
|
||||||
questions: "品牌问题整理中…",
|
questions: "品牌问题整理中…",
|
||||||
competitors: "竞品与官网信息补充中…",
|
competitors: "竞品与官网信息补充中…",
|
||||||
context: "评测上下文整理中…",
|
context: "正在整理品牌与官网上下文…",
|
||||||
|
refine: "正在合并并筛选竞品列表…",
|
||||||
},
|
},
|
||||||
titleStages: {
|
titleStages: {
|
||||||
context: "正在整理当前内容上下文…",
|
context: "正在整理当前内容上下文…",
|
||||||
@@ -925,9 +928,11 @@ const zhCN = {
|
|||||||
missingOutline: "请至少选择一个文章结构段落",
|
missingOutline: "请至少选择一个文章结构段落",
|
||||||
missingGeneratedOutline: "请先生成并确认文章大纲",
|
missingGeneratedOutline: "请先生成并确认文章大纲",
|
||||||
customOutlineTooLong: "自定义结构不能超过 {count} 个字",
|
customOutlineTooLong: "自定义结构不能超过 {count} 个字",
|
||||||
|
selectBrandBeforeCompetitors: "请先从品牌库选择品牌后再管理竞品",
|
||||||
selectBrandBeforeFavorite: "请先从品牌库选择品牌后再收藏竞品",
|
selectBrandBeforeFavorite: "请先从品牌库选择品牌后再收藏竞品",
|
||||||
missingCompetitorName: "至少需要填写竞品名称后才能收藏",
|
missingCompetitorName: "至少需要填写竞品名称后才能收藏",
|
||||||
savedCompetitor: "竞品已收藏到品牌词库",
|
savedCompetitor: "竞品已收藏到品牌词库",
|
||||||
|
unsavedCompetitor: "已取消收藏该竞品",
|
||||||
assistReady: "AI 分析已完成,可以继续调整内容。",
|
assistReady: "AI 分析已完成,可以继续调整内容。",
|
||||||
assistFailed: "AI 分析失败,请稍后重试。",
|
assistFailed: "AI 分析失败,请稍后重试。",
|
||||||
assistTimeout: "AI 分析超时,请稍后重试。",
|
assistTimeout: "AI 分析超时,请稍后重试。",
|
||||||
|
|||||||
@@ -328,6 +328,7 @@ const showCompetitorsCard = computed(
|
|||||||
wizardConfig.value?.basic?.cards?.competitors?.visible !== false,
|
wizardConfig.value?.basic?.cards?.competitors?.visible !== false,
|
||||||
)
|
)
|
||||||
const canSaveCompetitorsToLibrary = computed(() => Boolean(selectedBrandId.value))
|
const canSaveCompetitorsToLibrary = computed(() => Boolean(selectedBrandId.value))
|
||||||
|
const canManageCompetitors = computed(() => Boolean(selectedBrandId.value))
|
||||||
const customOutlineMaxLength = computed(
|
const customOutlineMaxLength = computed(
|
||||||
() => wizardConfig.value?.outline?.custom_max_length ?? CUSTOM_OUTLINE_MAX_LENGTH,
|
() => wizardConfig.value?.outline?.custom_max_length ?? CUSTOM_OUTLINE_MAX_LENGTH,
|
||||||
)
|
)
|
||||||
@@ -434,27 +435,9 @@ const previewCardCopy = computed<TemplateCardCopy>(
|
|||||||
() => wizardConfig.value?.structure?.cards?.preview ?? {},
|
() => wizardConfig.value?.structure?.cards?.preview ?? {},
|
||||||
)
|
)
|
||||||
const analyzeButtonLabel = computed(
|
const analyzeButtonLabel = computed(
|
||||||
() => wizardConfig.value?.basic?.analyze_button_label || t('templates.wizard.actions.analyze'),
|
() => t('templates.wizard.actions.analyzeCompetitors'),
|
||||||
)
|
)
|
||||||
const aiBannerCopy = computed(() => {
|
const showBrandSummaryBox = computed(() => Boolean(selectedBrandId.value))
|
||||||
switch (templateDetail.value?.template_key) {
|
|
||||||
case 'product_review':
|
|
||||||
return {
|
|
||||||
title: t('templates.wizard.aiBanner.title'),
|
|
||||||
description: t('templates.wizard.aiBanner.productReviewDescription'),
|
|
||||||
}
|
|
||||||
case 'research_report':
|
|
||||||
return {
|
|
||||||
title: t('templates.wizard.aiBanner.title'),
|
|
||||||
description: t('templates.wizard.aiBanner.researchReportDescription'),
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return {
|
|
||||||
title: t('templates.wizard.aiBanner.title'),
|
|
||||||
description: t('templates.wizard.aiBanner.defaultDescription'),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const reviewAlertMessage = computed(
|
const reviewAlertMessage = computed(
|
||||||
() => wizardConfig.value?.review?.alert_message || t('templates.wizard.hints.async'),
|
() => wizardConfig.value?.review?.alert_message || t('templates.wizard.hints.async'),
|
||||||
)
|
)
|
||||||
@@ -483,11 +466,9 @@ const hasWizardDraftContent = computed(
|
|||||||
const assistStages = computed(() =>
|
const assistStages = computed(() =>
|
||||||
assistTaskKind.value === 'analyze'
|
assistTaskKind.value === 'analyze'
|
||||||
? [
|
? [
|
||||||
t('templates.wizard.assist.analyzeStages.brand'),
|
t('templates.wizard.assist.analyzeStages.context'),
|
||||||
t('templates.wizard.assist.analyzeStages.questions'),
|
t('templates.wizard.assist.analyzeStages.competitors'),
|
||||||
showCompetitorsCard.value
|
t('templates.wizard.assist.analyzeStages.refine'),
|
||||||
? t('templates.wizard.assist.analyzeStages.competitors')
|
|
||||||
: t('templates.wizard.assist.analyzeStages.context'),
|
|
||||||
]
|
]
|
||||||
: assistTaskKind.value === 'title'
|
: assistTaskKind.value === 'title'
|
||||||
? [
|
? [
|
||||||
@@ -507,9 +488,7 @@ const assistStages = computed(() =>
|
|||||||
)
|
)
|
||||||
const assistHeading = computed(() =>
|
const assistHeading = computed(() =>
|
||||||
assistTaskKind.value === 'analyze'
|
assistTaskKind.value === 'analyze'
|
||||||
? showCompetitorsCard.value
|
? t('templates.wizard.assist.analyzeTitle')
|
||||||
? t('templates.wizard.assist.analyzeTitle')
|
|
||||||
: t('templates.wizard.assist.analyzeTitleNoCompetitors')
|
|
||||||
: assistTaskKind.value === 'title'
|
: assistTaskKind.value === 'title'
|
||||||
? t('templates.wizard.assist.titleTitle')
|
? t('templates.wizard.assist.titleTitle')
|
||||||
: t('templates.wizard.assist.outlineTitle'),
|
: t('templates.wizard.assist.outlineTitle'),
|
||||||
@@ -827,6 +806,14 @@ function validateBasicInfo(): boolean {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validateAnalyzeInfo(): boolean {
|
||||||
|
if (!canManageCompetitors.value) {
|
||||||
|
message.warning(t('templates.wizard.messages.selectBrandBeforeCompetitors'))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
function validateStructure(): boolean {
|
function validateStructure(): boolean {
|
||||||
if (!finalTitle.value) {
|
if (!finalTitle.value) {
|
||||||
message.warning(t('templates.wizard.messages.missingTitle'))
|
message.warning(t('templates.wizard.messages.missingTitle'))
|
||||||
@@ -885,7 +872,7 @@ function handlePrev(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleAnalyze(): Promise<void> {
|
async function handleAnalyze(): Promise<void> {
|
||||||
if (!validateBasicInfo()) {
|
if (!validateAnalyzeInfo()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await runAnalyzeTask(true)
|
await runAnalyzeTask(true)
|
||||||
@@ -1092,6 +1079,10 @@ function applyAnalyzeResult(result: TemplateAnalyzeResult): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addCompetitorRow(): void {
|
function addCompetitorRow(): void {
|
||||||
|
if (!canManageCompetitors.value) {
|
||||||
|
message.warning(t('templates.wizard.messages.selectBrandBeforeCompetitors'))
|
||||||
|
return
|
||||||
|
}
|
||||||
competitorDrafts.value = [
|
competitorDrafts.value = [
|
||||||
...competitorDrafts.value,
|
...competitorDrafts.value,
|
||||||
{
|
{
|
||||||
@@ -1114,14 +1105,27 @@ async function handleFavoriteCompetitor(item: DraftCompetitor): Promise<void> {
|
|||||||
message.warning(t('templates.wizard.messages.selectBrandBeforeFavorite'))
|
message.warning(t('templates.wizard.messages.selectBrandBeforeFavorite'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!item.name.trim()) {
|
|
||||||
message.warning(t('templates.wizard.messages.missingCompetitorName'))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
competitorSavingKey.value = item.key
|
competitorSavingKey.value = item.key
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (item.saved && item.libraryId) {
|
||||||
|
await brandsApi.removeCompetitor(brandId, item.libraryId)
|
||||||
|
item.libraryId = undefined
|
||||||
|
item.saved = false
|
||||||
|
await Promise.all([
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['brands'] }),
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['brands', brandId, 'competitors'] }),
|
||||||
|
])
|
||||||
|
message.success(t('templates.wizard.messages.unsavedCompetitor'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!item.name.trim()) {
|
||||||
|
message.warning(t('templates.wizard.messages.missingCompetitorName'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
name: item.name.trim(),
|
name: item.name.trim(),
|
||||||
website: item.website.trim() || null,
|
website: item.website.trim() || null,
|
||||||
@@ -2423,26 +2427,7 @@ function onStructureDragEnd(): void {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-ai-banner">
|
<div v-if="showBrandSummaryBox" class="summary-box">
|
||||||
<div class="wizard-ai-banner__info">
|
|
||||||
<RobotOutlined class="wizard-ai-banner__icon" />
|
|
||||||
<div class="wizard-ai-banner__text">
|
|
||||||
<h4>{{ aiBannerCopy.title }}</h4>
|
|
||||||
<p>{{ aiBannerCopy.description }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<a-button
|
|
||||||
type="primary"
|
|
||||||
class="wizard-ai-banner__btn"
|
|
||||||
size="large"
|
|
||||||
:loading="assistBusy"
|
|
||||||
@click="handleAnalyze"
|
|
||||||
>
|
|
||||||
{{ analyzeButtonLabel }}
|
|
||||||
</a-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="summary-box">
|
|
||||||
<div class="summary-box__label">
|
<div class="summary-box__label">
|
||||||
{{ t('templates.wizard.sections.brandSummary') }}
|
{{ t('templates.wizard.sections.brandSummary') }}
|
||||||
</div>
|
</div>
|
||||||
@@ -2523,10 +2508,26 @@ function onStructureDragEnd(): void {
|
|||||||
</h3>
|
</h3>
|
||||||
<p>{{ competitorsCardCopy.hint || t('templates.wizard.hints.competitors') }}</p>
|
<p>{{ competitorsCardCopy.hint || t('templates.wizard.hints.competitors') }}</p>
|
||||||
</div>
|
</div>
|
||||||
<a-button type="default" @click="addCompetitorRow">
|
<div class="competitor-header-actions">
|
||||||
<template #icon><PlusOutlined /></template>
|
<a-button
|
||||||
{{ t('templates.wizard.actions.addCompetitor') }}
|
class="competitor-ai-button"
|
||||||
</a-button>
|
type="primary"
|
||||||
|
:loading="assistBusy"
|
||||||
|
:disabled="!canManageCompetitors"
|
||||||
|
@click="handleAnalyze"
|
||||||
|
>
|
||||||
|
<template #icon><RobotOutlined /></template>
|
||||||
|
{{ analyzeButtonLabel }}
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="default"
|
||||||
|
:disabled="!canManageCompetitors"
|
||||||
|
@click="addCompetitorRow"
|
||||||
|
>
|
||||||
|
<template #icon><PlusOutlined /></template>
|
||||||
|
{{ t('templates.wizard.actions.addCompetitor') }}
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="competitorDrafts.length > 0" class="competitor-table">
|
<div v-if="competitorDrafts.length > 0" class="competitor-table">
|
||||||
@@ -2570,7 +2571,7 @@ function onStructureDragEnd(): void {
|
|||||||
</template>
|
</template>
|
||||||
{{
|
{{
|
||||||
canSaveCompetitorsToLibrary && item.saved
|
canSaveCompetitorsToLibrary && item.saved
|
||||||
? t('templates.wizard.actions.saved')
|
? t('templates.wizard.actions.unfavorite')
|
||||||
: t('templates.wizard.actions.favorite')
|
: t('templates.wizard.actions.favorite')
|
||||||
}}
|
}}
|
||||||
</a-button>
|
</a-button>
|
||||||
@@ -3195,60 +3196,6 @@ function onStructureDragEnd(): void {
|
|||||||
gap: 18px;
|
gap: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wizard-ai-banner {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-top: 24px;
|
|
||||||
padding: 16px 20px;
|
|
||||||
border-radius: 16px;
|
|
||||||
background: linear-gradient(135deg, rgba(22, 119, 255, 0.04), rgba(22, 119, 255, 0.08));
|
|
||||||
border: 1px solid rgba(22, 119, 255, 0.15);
|
|
||||||
box-shadow: 0 4px 16px rgba(22, 119, 255, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizard-ai-banner__info {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizard-ai-banner__icon {
|
|
||||||
font-size: 28px;
|
|
||||||
background: linear-gradient(135deg, #1677ff, #36cfc9);
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizard-ai-banner__text h4 {
|
|
||||||
margin: 0 0 4px;
|
|
||||||
color: #1f2f4d;
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizard-ai-banner__text p {
|
|
||||||
margin: 0;
|
|
||||||
color: #6b7a99;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizard-ai-banner__btn {
|
|
||||||
border-radius: 10px;
|
|
||||||
font-weight: 600;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
padding: 0 24px;
|
|
||||||
background: linear-gradient(135deg, #1677ff, #0958d9);
|
|
||||||
border: none;
|
|
||||||
box-shadow: 0 4px 12px rgba(22, 119, 255, 0.2);
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizard-ai-banner__btn:hover {
|
|
||||||
transform: translateY(-1px);
|
|
||||||
box-shadow: 0 6px 16px rgba(22, 119, 255, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.summary-box {
|
.summary-box {
|
||||||
margin-top: 18px;
|
margin-top: 18px;
|
||||||
padding: 16px 18px;
|
padding: 16px 18px;
|
||||||
@@ -3272,6 +3219,34 @@ function onStructureDragEnd(): void {
|
|||||||
line-height: 1.7;
|
line-height: 1.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.competitor-header-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.competitor-ai-button {
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #1677ff;
|
||||||
|
box-shadow: 0 4px 12px rgba(22, 119, 255, 0.16);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.competitor-ai-button:hover:not([disabled]) {
|
||||||
|
background: #0958d9 !important;
|
||||||
|
box-shadow: 0 6px 16px rgba(22, 119, 255, 0.22);
|
||||||
|
}
|
||||||
|
|
||||||
|
.competitor-ai-button[disabled],
|
||||||
|
.competitor-ai-button.ant-btn-loading {
|
||||||
|
background: #f1f5f9 !important;
|
||||||
|
border: 1px solid #e2e8f0 !important;
|
||||||
|
color: #94a3b8 !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
.competitor-table {
|
.competitor-table {
|
||||||
border: 1px solid rgba(20, 44, 88, 0.08);
|
border: 1px solid rgba(20, 44, 88, 0.08);
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
@@ -3788,6 +3763,10 @@ function onStructureDragEnd(): void {
|
|||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.competitor-header-actions {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
.outline-grid {
|
.outline-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user