refactor(admin-web): unify page headers with shared title card
Introduce .page-title-card style and migrate Images, Knowledge, KolDashboard, KolManage, KolProfile views to the shared header layout. Add subtitle copy for KOL dashboard and manage views. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -211,6 +211,7 @@ const enUS = {
|
||||
},
|
||||
manage: {
|
||||
title: "KOL Prompt Management",
|
||||
subtitle: "Manage refined template packages, prompts, platforms, variables, and publishing status.",
|
||||
packageTitle: "Packages",
|
||||
promptTitle: "Prompts",
|
||||
createPackage: "Create package",
|
||||
@@ -295,6 +296,7 @@ const enUS = {
|
||||
},
|
||||
dashboard: {
|
||||
title: "KOL Dashboard",
|
||||
subtitle: "Track subscriptions and generation metrics in real time.",
|
||||
totalSubs: "Total subscribed tenants",
|
||||
monthSubs: "New this month",
|
||||
totalUsage: "Total usage",
|
||||
|
||||
@@ -211,6 +211,7 @@ const zhCN = {
|
||||
},
|
||||
manage: {
|
||||
title: "KOL 提示词管理",
|
||||
subtitle: "管理精调模版订阅包与提示词,配置平台、变量和上下线状态。",
|
||||
packageTitle: "订阅包",
|
||||
promptTitle: "提示词",
|
||||
createPackage: "创建订阅包",
|
||||
@@ -295,6 +296,7 @@ const zhCN = {
|
||||
},
|
||||
dashboard: {
|
||||
title: "KOL 数据看板",
|
||||
subtitle: "实时查看订阅情况与生成数据统计。",
|
||||
totalSubs: "总订阅租户数",
|
||||
monthSubs: "本月新增",
|
||||
totalUsage: "总使用次数",
|
||||
|
||||
@@ -54,6 +54,47 @@ html, body, #app {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
.page-title-card {
|
||||
background: #fff;
|
||||
border: 1px solid #e6edf5;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.page-title-card__header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 24px;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.page-title-card__copy {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.page-title-card__copy h2 {
|
||||
margin: 0;
|
||||
color: #1a1a1a;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.page-title-card__copy p {
|
||||
margin: 6px 0 0;
|
||||
color: #8c8c8c;
|
||||
font-size: 13px;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.page-title-card__actions {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.table-actions-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -352,22 +352,13 @@ async function confirmDeleteImage(image: ImageAssetItem) {
|
||||
|
||||
<template>
|
||||
<div class="images-page">
|
||||
<div class="images-page__hero">
|
||||
<h2>{{ t("images.title") }}</h2>
|
||||
<p>{{ t("images.description") }}</p>
|
||||
</div>
|
||||
|
||||
<div class="images-main-card">
|
||||
<div class="images-toolbar">
|
||||
<div class="images-toolbar__left">
|
||||
<a-input-search
|
||||
v-model:value="searchKeyword"
|
||||
:placeholder="t('images.searchPlaceholder')"
|
||||
style="width: 300px"
|
||||
allow-clear
|
||||
/>
|
||||
<section class="page-title-card">
|
||||
<div class="page-title-card__header">
|
||||
<div class="page-title-card__copy">
|
||||
<h2>{{ t("images.title") }}</h2>
|
||||
<p>{{ t("images.description") }}</p>
|
||||
</div>
|
||||
<div class="images-toolbar__right">
|
||||
<div class="page-title-card__actions">
|
||||
<a-button type="primary" :disabled="imageUploadBusy" @click="triggerUpload">
|
||||
<template #icon><UploadOutlined /></template>
|
||||
{{ t("images.uploadBtn") }}
|
||||
@@ -383,6 +374,19 @@ async function confirmDeleteImage(image: ImageAssetItem) {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="images-main-card">
|
||||
<div class="images-toolbar">
|
||||
<div class="images-toolbar__left">
|
||||
<a-input-search
|
||||
v-model:value="searchKeyword"
|
||||
:placeholder="t('images.searchPlaceholder')"
|
||||
style="width: 300px"
|
||||
allow-clear
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="images-layout-inner">
|
||||
<aside class="images-sidebar">
|
||||
@@ -579,19 +583,6 @@ async function confirmDeleteImage(image: ImageAssetItem) {
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.images-page__hero h2 {
|
||||
margin: 0;
|
||||
color: #111827;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.images-page__hero p {
|
||||
margin: 0;
|
||||
color: #6b7280;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.images-main-card {
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
@@ -505,21 +505,24 @@ function closeItemDetail(): void {
|
||||
|
||||
<template>
|
||||
<div class="knowledge-page">
|
||||
<div class="knowledge-page__hero">
|
||||
<h2>知识库</h2>
|
||||
<p>
|
||||
通过上传文档,网站认证及任何与您的产品相关的包装及品牌故事内容;对各种格式的数据和资料信息来进行归纳,并结合生成文章
|
||||
</p>
|
||||
</div>
|
||||
<section class="page-title-card">
|
||||
<div class="page-title-card__header">
|
||||
<div class="page-title-card__copy">
|
||||
<h2>知识库</h2>
|
||||
<p>
|
||||
通过上传文档,网站认证及任何与您的产品相关的包装及品牌故事内容;对各种格式的数据和资料信息来进行归纳,并结合生成文章
|
||||
</p>
|
||||
</div>
|
||||
<div class="page-title-card__actions">
|
||||
<a-button type="primary" class="knowledge-add-btn" @click="openItemModal('document')">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
添加知识
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="knowledge-main-card">
|
||||
<div class="knowledge-toolbar">
|
||||
<a-button type="primary" class="knowledge-add-btn" @click="openItemModal('document')">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
添加知识
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<div class="knowledge-layout-inner">
|
||||
<aside class="knowledge-sidebar">
|
||||
<div class="knowledge-sidebar__header">
|
||||
@@ -736,25 +739,6 @@ function closeItemDetail(): void {
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.knowledge-page__hero {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.knowledge-page__hero h2 {
|
||||
margin: 0;
|
||||
color: #111827;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.knowledge-page__hero p {
|
||||
margin: 0;
|
||||
color: #6b7280;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.knowledge-main-card {
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
@@ -765,10 +749,6 @@ function closeItemDetail(): void {
|
||||
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.knowledge-toolbar {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.knowledge-add-btn {
|
||||
width: 120px;
|
||||
border-radius: 6px;
|
||||
|
||||
@@ -208,16 +208,20 @@ function refresh() {
|
||||
|
||||
<template>
|
||||
<div class="kol-dashboard-view">
|
||||
<div class="page-header">
|
||||
<div class="header-info">
|
||||
<h2 class="page-title">{{ t("kol.dashboard.title") }}</h2>
|
||||
<p class="page-desc">实时查看订阅情况与生成数据统计</p>
|
||||
<section class="page-title-card">
|
||||
<div class="page-title-card__header">
|
||||
<div class="page-title-card__copy">
|
||||
<h2>{{ t("kol.dashboard.title") }}</h2>
|
||||
<p>{{ t("kol.dashboard.subtitle") }}</p>
|
||||
</div>
|
||||
<div class="page-title-card__actions">
|
||||
<a-button @click="refresh">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
刷新
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<a-button @click="refresh">
|
||||
<template #icon><ReloadOutlined /></template>
|
||||
刷新
|
||||
</a-button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Stats Row -->
|
||||
<div class="stats-row">
|
||||
@@ -366,23 +370,6 @@ function refresh() {
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.page-title {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
margin: 0 0 4px 0;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
.page-desc {
|
||||
font-size: 14px;
|
||||
color: #8c8c8c;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Stats Row */
|
||||
.stats-row {
|
||||
display: grid;
|
||||
|
||||
@@ -224,6 +224,15 @@ function packageStatusLabel(status: string) {
|
||||
|
||||
<template>
|
||||
<div class="kol-manage-view">
|
||||
<section v-if="!editingPromptId" class="page-title-card">
|
||||
<div class="page-title-card__header">
|
||||
<div class="page-title-card__copy">
|
||||
<h2>{{ t("kol.manage.title") }}</h2>
|
||||
<p>{{ t("kol.manage.subtitle") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div v-if="editingPromptId" class="manage-content manage-content--editor">
|
||||
<div class="fullscreen-editor">
|
||||
<KolPromptEditor :prompt-id="editingPromptId" @back="handleCloseEditor" />
|
||||
@@ -401,6 +410,7 @@ function packageStatusLabel(status: string) {
|
||||
.kol-manage-view {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
height: calc(100vh - 120px);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,14 @@ const profileQuery = useQuery({
|
||||
|
||||
<template>
|
||||
<div class="kol-profile-view">
|
||||
<header class="page-header">
|
||||
<h2 class="page-title">{{ t("kol.profile.title") }}</h2>
|
||||
<p class="page-subtitle">{{ t("kol.profile.subtitle") }}</p>
|
||||
</header>
|
||||
<section class="page-title-card">
|
||||
<div class="page-title-card__header">
|
||||
<div class="page-title-card__copy">
|
||||
<h2>{{ t("kol.profile.title") }}</h2>
|
||||
<p>{{ t("kol.profile.subtitle") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<a-skeleton v-if="profileQuery.isPending.value" active avatar :paragraph="{ rows: 3 }" />
|
||||
<a-alert
|
||||
@@ -41,20 +45,4 @@ const profileQuery = useQuery({
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
}
|
||||
.page-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
.page-title {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
.page-subtitle {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
color: #8c8c8c;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user