feat: add tenant and user management with migrations, handlers, and tests
- Implemented tenant and user management features including: - Tenant creation and management with associated migrations. - User creation and management with associated migrations. - Tenant membership management with associated migrations. - Platform user roles management with associated migrations. - Quota management with associated migrations. - Article and template management with associated migrations. - Added HTTP handlers for templates and workspaces. - Created tests for protected and public routes. - Introduced a script to check tenant scope in SQL queries. - Documented task plan for backend completion and frontend foundation.
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import { createI18n } from "vue-i18n";
|
||||
|
||||
import enUS from "./messages/en-US";
|
||||
import zhCN from "./messages/zh-CN";
|
||||
|
||||
export const LOCALE_STORAGE_KEY = "geo.admin.locale";
|
||||
export const SUPPORTED_LOCALES = ["zh-CN", "en-US"] as const;
|
||||
|
||||
export type AppLocale = (typeof SUPPORTED_LOCALES)[number];
|
||||
|
||||
function resolveLocale(): AppLocale {
|
||||
if (typeof window === "undefined") {
|
||||
return "zh-CN";
|
||||
}
|
||||
|
||||
const stored = window.localStorage.getItem(LOCALE_STORAGE_KEY);
|
||||
if (stored && SUPPORTED_LOCALES.includes(stored as AppLocale)) {
|
||||
return stored as AppLocale;
|
||||
}
|
||||
|
||||
const browserLocale = window.navigator.language;
|
||||
if (browserLocale.startsWith("zh")) {
|
||||
return "zh-CN";
|
||||
}
|
||||
|
||||
return "en-US";
|
||||
}
|
||||
|
||||
export const i18n = createI18n({
|
||||
legacy: false,
|
||||
locale: resolveLocale(),
|
||||
fallbackLocale: "en-US",
|
||||
messages: {
|
||||
"zh-CN": zhCN,
|
||||
"en-US": enUS,
|
||||
},
|
||||
});
|
||||
|
||||
export function setAppLocale(locale: AppLocale): void {
|
||||
i18n.global.locale.value = locale;
|
||||
if (typeof window !== "undefined") {
|
||||
window.localStorage.setItem(LOCALE_STORAGE_KEY, locale);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,363 @@
|
||||
const enUS = {
|
||||
app: {
|
||||
name: "GEO Console",
|
||||
loginIntro: "A workspace for brand assets and GEO content operations.",
|
||||
},
|
||||
locale: {
|
||||
"zh-CN": "Simplified Chinese",
|
||||
"en-US": "English",
|
||||
},
|
||||
common: {
|
||||
cancel: "Cancel",
|
||||
close: "Close",
|
||||
confirm: "Confirm",
|
||||
create: "Create",
|
||||
edit: "Edit",
|
||||
delete: "Delete",
|
||||
reset: "Reset",
|
||||
refresh: "Refresh",
|
||||
search: "Search",
|
||||
save: "Save",
|
||||
next: "Next",
|
||||
previous: "Previous",
|
||||
submit: "Submit",
|
||||
submitGenerate: "Generate",
|
||||
actions: "Actions",
|
||||
title: "Title",
|
||||
description: "Description",
|
||||
website: "Website",
|
||||
wordCount: "Words",
|
||||
createdAt: "Created At",
|
||||
updatedAt: "Updated At",
|
||||
status: "Status",
|
||||
required: "Required",
|
||||
noData: "No data",
|
||||
optional: "Optional",
|
||||
preview: "Preview",
|
||||
details: "Details",
|
||||
versions: "Versions",
|
||||
total: "Total",
|
||||
balance: "Balance",
|
||||
used: "Used",
|
||||
source: "Source",
|
||||
templateType: "Template",
|
||||
generateStatus: "Generation",
|
||||
publishStatus: "Publish",
|
||||
selectPlease: "Please select",
|
||||
inputPlease: "Please input",
|
||||
upgrade: "Upgrade",
|
||||
},
|
||||
nav: {
|
||||
workspace: "Workspace",
|
||||
articleCreation: "Article Creation",
|
||||
templates: "Templates",
|
||||
custom: "Custom Generation",
|
||||
optimize: "Optimization",
|
||||
media: "Media",
|
||||
brandManagement: "Brand Management",
|
||||
brands: "Brand Library",
|
||||
tracking: "Tracking",
|
||||
trackingDetail: "Data Details",
|
||||
contentManagement: "Content Management",
|
||||
knowledge: "Knowledge Base",
|
||||
},
|
||||
auth: {
|
||||
welcomeBack: "Welcome back",
|
||||
tenantAdminLogin: "Tenant Admin Login",
|
||||
loginAndEnter: "Sign in to workspace",
|
||||
email: "Email",
|
||||
password: "Password",
|
||||
defaultTestAccount: "Default account",
|
||||
defaultTestPassword: "Default password",
|
||||
},
|
||||
shell: {
|
||||
localeLabel: "Language",
|
||||
quotaTitle: "Plan & Quota",
|
||||
quotaStatus: "Healthy",
|
||||
remainingQuota: "Article quota",
|
||||
resetAt: "Reset at",
|
||||
userFallback: "Admin",
|
||||
logout: "Logout",
|
||||
planFallback: "Free Plan",
|
||||
},
|
||||
route: {
|
||||
login: {
|
||||
title: "Welcome back",
|
||||
description: "Sign in with a real tenant account.",
|
||||
},
|
||||
workspace: {
|
||||
title: "Workspace",
|
||||
description: "Template shortcuts, overview data, and recent generations in one place.",
|
||||
},
|
||||
templates: {
|
||||
title: "Template Creation",
|
||||
description: "Filter existing articles, choose templates, and trigger new generation tasks.",
|
||||
},
|
||||
custom: {
|
||||
title: "Custom Generation",
|
||||
description: "No matching backend APIs exist in this repository yet.",
|
||||
},
|
||||
optimize: {
|
||||
title: "Article Optimization",
|
||||
description: "No matching backend APIs exist in this repository yet.",
|
||||
},
|
||||
media: {
|
||||
title: "Media Management",
|
||||
description: "No matching backend APIs exist in this repository yet.",
|
||||
},
|
||||
brands: {
|
||||
title: "Brand Library",
|
||||
description: "Manage keywords, question sets, and competitors around each brand.",
|
||||
},
|
||||
tracking: {
|
||||
title: "Data Details",
|
||||
description: "No matching backend APIs exist in this repository yet.",
|
||||
},
|
||||
knowledge: {
|
||||
title: "Knowledge Base",
|
||||
description: "No matching backend APIs exist in this repository yet.",
|
||||
},
|
||||
},
|
||||
workspace: {
|
||||
eyebrow: "Dashboard",
|
||||
metrics: {
|
||||
articles: "Generated",
|
||||
published: "Published",
|
||||
brands: "Brands",
|
||||
platforms: "Platforms",
|
||||
},
|
||||
sections: {
|
||||
templates: "Article Templates",
|
||||
recent: "Recent Generations",
|
||||
overview: "Overview",
|
||||
quota: "Plan & Quota",
|
||||
},
|
||||
actions: {
|
||||
enterTemplates: "Open Templates",
|
||||
},
|
||||
quota: {
|
||||
remaining: "Remaining quota",
|
||||
total: "Total quota",
|
||||
used: "Used quota",
|
||||
},
|
||||
emptyTemplates: "No template cards available yet",
|
||||
noRecentArticles: "No recent generations yet",
|
||||
},
|
||||
templateMeta: {
|
||||
top_x_article: {
|
||||
eyebrow: "Ranked Content",
|
||||
helper: "Good for listicles, comparisons, and recommendation-driven output.",
|
||||
accent: "Top X",
|
||||
action: "Create ranking",
|
||||
},
|
||||
product_review: {
|
||||
eyebrow: "Product Review",
|
||||
helper: "Good for benefits, trade-offs, and suitability analysis.",
|
||||
accent: "Review",
|
||||
action: "Start review",
|
||||
},
|
||||
research_report: {
|
||||
eyebrow: "Research Report",
|
||||
helper: "Good for longer analysis, trends, and market insight.",
|
||||
accent: "Report",
|
||||
action: "Create report",
|
||||
},
|
||||
brand_search_expansion: {
|
||||
eyebrow: "Brand Expansion",
|
||||
helper: "Expand brand plus search intent into a richer GEO article.",
|
||||
accent: "GEO",
|
||||
action: "Expand",
|
||||
},
|
||||
default: {
|
||||
eyebrow: "Content Template",
|
||||
helper: "This template is already usable and can go straight into generation.",
|
||||
accent: "Ready",
|
||||
action: "Open template",
|
||||
},
|
||||
},
|
||||
status: {
|
||||
generate: {
|
||||
draft: "Draft",
|
||||
generating: "Generating",
|
||||
running: "Running",
|
||||
completed: "Completed",
|
||||
failed: "Failed",
|
||||
},
|
||||
publish: {
|
||||
unpublished: "Unpublished",
|
||||
publishing: "Publishing",
|
||||
published: "Published",
|
||||
publish_success: "Published",
|
||||
publish_failed: "Failed",
|
||||
pending_review: "Pending Review",
|
||||
},
|
||||
sourceType: {
|
||||
template: "Template generation",
|
||||
},
|
||||
},
|
||||
templates: {
|
||||
eyebrow: "Article Creation",
|
||||
actions: {
|
||||
batchGenerate: "Batch generate",
|
||||
chooseTemplate: "Choose template",
|
||||
},
|
||||
filters: {
|
||||
template: "Template",
|
||||
publishStatus: "Publish status",
|
||||
generateStatus: "Generation status",
|
||||
keyword: "Search",
|
||||
keywordPlaceholder: "Search by article title",
|
||||
unsupportedDate: "Date range filtering is not available in the current backend yet.",
|
||||
},
|
||||
list: {
|
||||
count: "{count} articles",
|
||||
empty: "No articles have been created yet.",
|
||||
preview: "Preview",
|
||||
versions: "Versions",
|
||||
deleteConfirm: "Delete this article?",
|
||||
deleteSuccess: "Article deleted.",
|
||||
deleteError: "Failed to delete article.",
|
||||
},
|
||||
picker: {
|
||||
title: "Choose the template you want to use",
|
||||
viewExample: "View example",
|
||||
},
|
||||
wizard: {
|
||||
drawerTitle: "Template generation",
|
||||
steps: {
|
||||
basic: "Basic info",
|
||||
basicDesc: "Language, template fields, and brand context",
|
||||
structure: "Structure",
|
||||
structureDesc: "Title, key points, and outline",
|
||||
generate: "Generate",
|
||||
generateDesc: "Review and submit the task",
|
||||
},
|
||||
sections: {
|
||||
templateFields: "Template fields",
|
||||
brandContext: "Brand context",
|
||||
language: "Language",
|
||||
brandInfo: "Brand",
|
||||
keywords: "Keywords",
|
||||
competitors: "Competitors",
|
||||
chooseTitle: "Choose a title",
|
||||
customTitle: "Custom title",
|
||||
structure: "Article structure",
|
||||
keyPoints: "Key points",
|
||||
review: "Review",
|
||||
notes: "Notes",
|
||||
inputParams: "Input params",
|
||||
},
|
||||
hints: {
|
||||
brandContext: "Optional. Selecting a brand pulls in keywords and competitor context.",
|
||||
competitorEmpty: "No competitors are available under this brand yet.",
|
||||
customTitle: "Use this field if you want to override the title manually.",
|
||||
keyPoints: "Add any key messages, angles, or style notes here.",
|
||||
async: "The backend creates the article and task first, then completes content generation asynchronously.",
|
||||
},
|
||||
review: {
|
||||
templateName: "Template",
|
||||
articleTitle: "Article title",
|
||||
brandContext: "Brand context",
|
||||
outline: "Outline",
|
||||
currentTemplate: "Current template",
|
||||
promptVisibility: "Prompt visibility",
|
||||
selectedKeywords: "Selected keywords",
|
||||
selectedCompetitors: "Selected competitors",
|
||||
},
|
||||
localeOptions: {
|
||||
zh: "Simplified Chinese",
|
||||
en: "English",
|
||||
},
|
||||
promptVisible: "Prompt visible",
|
||||
promptSealed: "Prompt sealed",
|
||||
messages: {
|
||||
requiredField: "Please fill in {field} first.",
|
||||
missingTitle: "Please choose or enter an article title.",
|
||||
missingOutline: "Please select at least one outline section.",
|
||||
submitted: "Generation task submitted. Refreshing article data.",
|
||||
},
|
||||
},
|
||||
},
|
||||
article: {
|
||||
drawerTitle: "Article details",
|
||||
preview: "Content preview",
|
||||
versionHistory: "Version history",
|
||||
untitled: "Untitled article",
|
||||
noContent: "This article does not have generated content yet.",
|
||||
meta: {
|
||||
templateType: "Template",
|
||||
currentVersion: "Current version",
|
||||
source: "Source label",
|
||||
wordCount: "Word count",
|
||||
},
|
||||
versionUntitled: "Untitled version",
|
||||
},
|
||||
brands: {
|
||||
eyebrow: "Brand Library",
|
||||
title: "Brand Library",
|
||||
description: "Manage keywords, question sets, and competitor assets around each brand.",
|
||||
railTitle: "Brands",
|
||||
selectBrand: "Pick a brand to continue managing keywords and question sets.",
|
||||
newBrand: "New brand",
|
||||
editBrand: "Edit brand",
|
||||
deleteBrand: "Delete brand",
|
||||
tabs: {
|
||||
keywords: "Keywords",
|
||||
competitors: "Competitors",
|
||||
},
|
||||
sections: {
|
||||
keywords: "Keywords",
|
||||
questions: "Question set",
|
||||
competitors: "Competitor library",
|
||||
versions: "Version history",
|
||||
},
|
||||
actions: {
|
||||
newKeyword: "New keyword",
|
||||
newQuestion: "New question",
|
||||
newCompetitor: "New competitor",
|
||||
viewVersions: "View versions",
|
||||
},
|
||||
empty: {
|
||||
brands: "No brand data yet. Create your first brand to start.",
|
||||
questions: "No questions under this keyword yet.",
|
||||
competitors: "No competitors under this brand yet.",
|
||||
},
|
||||
form: {
|
||||
brandName: "Brand name",
|
||||
brandDescription: "Brand description",
|
||||
keywordName: "Keyword",
|
||||
questionText: "Question text",
|
||||
competitorName: "Competitor name",
|
||||
competitorWebsite: "Competitor website",
|
||||
competitorDescription: "Competitor description",
|
||||
competitorLines: "Product lines",
|
||||
competitorLinesHint: "Separate multiple product lines with commas.",
|
||||
},
|
||||
messages: {
|
||||
createBrand: "Brand created.",
|
||||
updateBrand: "Brand updated.",
|
||||
deleteBrand: "Brand deleted.",
|
||||
createKeyword: "Keyword created.",
|
||||
updateKeyword: "Keyword updated.",
|
||||
deleteKeyword: "Keyword deleted.",
|
||||
createQuestion: "Question created.",
|
||||
updateQuestion: "Question updated.",
|
||||
deleteQuestion: "Question deleted.",
|
||||
createCompetitor: "Competitor created.",
|
||||
updateCompetitor: "Competitor updated.",
|
||||
deleteCompetitor: "Competitor deleted.",
|
||||
chooseBrand: "Please choose a brand first.",
|
||||
chooseKeyword: "Please choose a keyword first.",
|
||||
},
|
||||
},
|
||||
featureStub: {
|
||||
eyebrow: "Feature Placeholder",
|
||||
currentStatus: "Current status",
|
||||
nextPriority: "Next priority",
|
||||
integrationStrategy: "Integration strategy",
|
||||
currentStatusText: "The page shell is ready with navigation and auth guard support.",
|
||||
integrationStrategyText: "Keep the UI aligned with tenant-api envelopes and wire real read flows before write flows.",
|
||||
},
|
||||
} as const;
|
||||
|
||||
export default enUS;
|
||||
@@ -0,0 +1,363 @@
|
||||
const zhCN = {
|
||||
app: {
|
||||
name: "GEO工具平台",
|
||||
loginIntro: "面向企业的品牌资产管理与内容生产协作系统",
|
||||
},
|
||||
locale: {
|
||||
"zh-CN": "中文简体",
|
||||
"en-US": "English",
|
||||
},
|
||||
common: {
|
||||
cancel: "取消",
|
||||
close: "关闭",
|
||||
confirm: "确认",
|
||||
create: "新建",
|
||||
edit: "编辑",
|
||||
delete: "删除",
|
||||
reset: "重置",
|
||||
refresh: "刷新数据",
|
||||
search: "搜索",
|
||||
save: "保存",
|
||||
next: "下一步",
|
||||
previous: "上一步",
|
||||
submit: "提交",
|
||||
submitGenerate: "提交生成",
|
||||
actions: "操作",
|
||||
title: "标题",
|
||||
description: "描述",
|
||||
website: "官网",
|
||||
wordCount: "字数",
|
||||
createdAt: "创建时间",
|
||||
updatedAt: "更新时间",
|
||||
status: "状态",
|
||||
required: "必填",
|
||||
noData: "暂无数据",
|
||||
optional: "可选",
|
||||
preview: "预览",
|
||||
details: "详情",
|
||||
versions: "版本记录",
|
||||
total: "总量",
|
||||
balance: "剩余",
|
||||
used: "已使用",
|
||||
source: "来源",
|
||||
templateType: "模版类型",
|
||||
generateStatus: "生成状态",
|
||||
publishStatus: "发布状态",
|
||||
selectPlease: "请选择",
|
||||
inputPlease: "请输入",
|
||||
upgrade: "去升级",
|
||||
},
|
||||
nav: {
|
||||
workspace: "工作台",
|
||||
articleCreation: "文章创作",
|
||||
templates: "模版创作",
|
||||
custom: "自定义生成",
|
||||
optimize: "文章优化",
|
||||
media: "媒体管理",
|
||||
brandManagement: "品牌管理",
|
||||
brands: "品牌词库",
|
||||
tracking: "数据追踪",
|
||||
trackingDetail: "数据详情",
|
||||
contentManagement: "内容管理",
|
||||
knowledge: "知识库",
|
||||
},
|
||||
auth: {
|
||||
welcomeBack: "欢迎回来",
|
||||
tenantAdminLogin: "租户后台登录",
|
||||
loginAndEnter: "登录并进入工作台",
|
||||
email: "邮箱",
|
||||
password: "密码",
|
||||
defaultTestAccount: "默认测试账号",
|
||||
defaultTestPassword: "默认测试密码",
|
||||
},
|
||||
shell: {
|
||||
localeLabel: "语言",
|
||||
quotaTitle: "套餐与额度",
|
||||
quotaStatus: "状态正常",
|
||||
remainingQuota: "生成文章",
|
||||
resetAt: "重置时间",
|
||||
userFallback: "管理员",
|
||||
logout: "退出",
|
||||
planFallback: "免费版",
|
||||
},
|
||||
route: {
|
||||
login: {
|
||||
title: "欢迎回来",
|
||||
description: "使用真实租户账号登录 GEO 工具平台。",
|
||||
},
|
||||
workspace: {
|
||||
title: "工作台",
|
||||
description: "模板入口、数据总览和最近生成都集中在这里。",
|
||||
},
|
||||
templates: {
|
||||
title: "模版创作",
|
||||
description: "筛选已有文章、选择模版并发起新一轮内容生成。",
|
||||
},
|
||||
custom: {
|
||||
title: "自定义生成",
|
||||
description: "当前仓库还没有匹配的后端接口,页面暂保持为设计占位。",
|
||||
},
|
||||
optimize: {
|
||||
title: "文章优化",
|
||||
description: "当前仓库还没有匹配的后端接口,页面暂保持为设计占位。",
|
||||
},
|
||||
media: {
|
||||
title: "媒体管理",
|
||||
description: "当前仓库还没有匹配的后端接口,页面暂保持为设计占位。",
|
||||
},
|
||||
brands: {
|
||||
title: "品牌词库",
|
||||
description: "围绕品牌维护关键词、问题集和竞品信息。",
|
||||
},
|
||||
tracking: {
|
||||
title: "数据详情",
|
||||
description: "当前仓库还没有匹配的后端接口,页面暂保持为设计占位。",
|
||||
},
|
||||
knowledge: {
|
||||
title: "知识库",
|
||||
description: "当前仓库还没有匹配的后端接口,页面暂保持为设计占位。",
|
||||
},
|
||||
},
|
||||
workspace: {
|
||||
eyebrow: "Dashboard",
|
||||
metrics: {
|
||||
articles: "生成数",
|
||||
published: "发布数",
|
||||
brands: "品牌数",
|
||||
platforms: "媒体平台数",
|
||||
},
|
||||
sections: {
|
||||
templates: "文章模版类型",
|
||||
recent: "最近生成",
|
||||
overview: "数据总览",
|
||||
quota: "套餐与额度",
|
||||
},
|
||||
actions: {
|
||||
enterTemplates: "进入模版创作",
|
||||
},
|
||||
quota: {
|
||||
remaining: "剩余生成额度",
|
||||
total: "总额度",
|
||||
used: "已使用",
|
||||
},
|
||||
emptyTemplates: "暂无模版卡片数据",
|
||||
noRecentArticles: "暂无最近生成内容",
|
||||
},
|
||||
templateMeta: {
|
||||
top_x_article: {
|
||||
eyebrow: "榜单内容",
|
||||
helper: "排序推荐类文章,适合快节奏种草和结构化比较。",
|
||||
accent: "Top X",
|
||||
action: "创建榜单",
|
||||
},
|
||||
product_review: {
|
||||
eyebrow: "单品评测",
|
||||
helper: "突出卖点、优缺点与适用人群,适合高转化内容。",
|
||||
accent: "评测稿",
|
||||
action: "发起评测",
|
||||
},
|
||||
research_report: {
|
||||
eyebrow: "研究报告",
|
||||
helper: "更长、更专业的分析内容,适合趋势和行业洞察。",
|
||||
accent: "深度稿",
|
||||
action: "创建报告",
|
||||
},
|
||||
brand_search_expansion: {
|
||||
eyebrow: "品牌扩写",
|
||||
helper: "把品牌词和搜索需求扩展成更完整的问答式内容。",
|
||||
accent: "GEO",
|
||||
action: "继续扩写",
|
||||
},
|
||||
default: {
|
||||
eyebrow: "内容模版",
|
||||
helper: "当前模版已经可用,可直接进入生成流程。",
|
||||
accent: "Ready",
|
||||
action: "进入模版",
|
||||
},
|
||||
},
|
||||
status: {
|
||||
generate: {
|
||||
draft: "草稿",
|
||||
generating: "生成中",
|
||||
running: "运行中",
|
||||
completed: "已完成",
|
||||
failed: "生成失败",
|
||||
},
|
||||
publish: {
|
||||
unpublished: "未发布",
|
||||
publishing: "发布中",
|
||||
published: "发布成功",
|
||||
publish_success: "发布成功",
|
||||
publish_failed: "发布失败",
|
||||
pending_review: "待审核",
|
||||
},
|
||||
sourceType: {
|
||||
template: "模版单次生成",
|
||||
},
|
||||
},
|
||||
templates: {
|
||||
eyebrow: "Article Creation",
|
||||
actions: {
|
||||
batchGenerate: "批量生成文章",
|
||||
chooseTemplate: "选择模版创作",
|
||||
},
|
||||
filters: {
|
||||
template: "模版类型",
|
||||
publishStatus: "发布状态",
|
||||
generateStatus: "生成状态",
|
||||
keyword: "搜索文章",
|
||||
keywordPlaceholder: "请输入标题内容搜索",
|
||||
unsupportedDate: "当前后端尚未提供按时间范围筛选",
|
||||
},
|
||||
list: {
|
||||
count: "共 {count} 篇文章",
|
||||
empty: "还未创建文章,暂无相关数据~",
|
||||
preview: "预览正文",
|
||||
versions: "查看版本",
|
||||
deleteConfirm: "确认删除这篇文章吗?",
|
||||
deleteSuccess: "文章已删除",
|
||||
deleteError: "删除文章失败",
|
||||
},
|
||||
picker: {
|
||||
title: "选择你需要的模版创作",
|
||||
viewExample: "查看示例",
|
||||
},
|
||||
wizard: {
|
||||
drawerTitle: "模版生成",
|
||||
steps: {
|
||||
basic: "基本信息",
|
||||
basicDesc: "语言、模版字段与品牌上下文",
|
||||
structure: "文章结构",
|
||||
structureDesc: "标题方案、关键要点与结构段落",
|
||||
generate: "生成文章",
|
||||
generateDesc: "确认参数并提交生成任务",
|
||||
},
|
||||
sections: {
|
||||
templateFields: "模版字段",
|
||||
brandContext: "品牌上下文",
|
||||
language: "文章语言",
|
||||
brandInfo: "品牌信息",
|
||||
keywords: "关键词",
|
||||
competitors: "竞品列表",
|
||||
chooseTitle: "选择文章标题",
|
||||
customTitle: "自定义标题",
|
||||
structure: "文章结构",
|
||||
keyPoints: "文章关键要点",
|
||||
review: "提交前确认",
|
||||
notes: "生成说明",
|
||||
inputParams: "输入参数",
|
||||
},
|
||||
hints: {
|
||||
brandContext: "可选。选择后会自动带出关键词与竞品信息。",
|
||||
competitorEmpty: "当前品牌下暂无竞品数据",
|
||||
customTitle: "如需手动改写,可在这里输入最终标题",
|
||||
keyPoints: "补充希望文章强调的卖点、观点或风格要求",
|
||||
async: "后端会立即创建文章和任务记录,再异步完成正文生成。提交成功后,列表会自动刷新。",
|
||||
},
|
||||
review: {
|
||||
templateName: "模版名称",
|
||||
articleTitle: "文章标题",
|
||||
brandContext: "品牌上下文",
|
||||
outline: "结构段落",
|
||||
currentTemplate: "当前模版",
|
||||
promptVisibility: "Prompt 可见性",
|
||||
selectedKeywords: "已选关键词",
|
||||
selectedCompetitors: "已选竞品",
|
||||
},
|
||||
localeOptions: {
|
||||
zh: "中文简体",
|
||||
en: "English",
|
||||
},
|
||||
promptVisible: "Prompt 可见",
|
||||
promptSealed: "Prompt 已封装",
|
||||
messages: {
|
||||
requiredField: "请先填写 {field}",
|
||||
missingTitle: "请先选择或输入文章标题",
|
||||
missingOutline: "请至少选择一个文章结构段落",
|
||||
submitted: "生成任务已提交,正在刷新文章列表。",
|
||||
},
|
||||
},
|
||||
},
|
||||
article: {
|
||||
drawerTitle: "文章详情",
|
||||
preview: "正文预览",
|
||||
versionHistory: "版本记录",
|
||||
untitled: "未命名文章",
|
||||
noContent: "当前文章还没有正文内容",
|
||||
meta: {
|
||||
templateType: "模版类型",
|
||||
currentVersion: "当前版本",
|
||||
source: "生成来源",
|
||||
wordCount: "文章字数",
|
||||
},
|
||||
versionUntitled: "未命名版本",
|
||||
},
|
||||
brands: {
|
||||
eyebrow: "Brand Library",
|
||||
title: "品牌词库",
|
||||
description: "通过品牌名称和品牌相关信息维护关键词、问题集和竞品资产。",
|
||||
railTitle: "品牌库",
|
||||
selectBrand: "选择品牌后即可继续维护关键词和问题集。",
|
||||
newBrand: "新建品牌",
|
||||
editBrand: "编辑品牌",
|
||||
deleteBrand: "删除品牌",
|
||||
tabs: {
|
||||
keywords: "关键词",
|
||||
competitors: "竞品库",
|
||||
},
|
||||
sections: {
|
||||
keywords: "关键词",
|
||||
questions: "问题集",
|
||||
competitors: "竞品库",
|
||||
versions: "版本记录",
|
||||
},
|
||||
actions: {
|
||||
newKeyword: "新建关键词",
|
||||
newQuestion: "新建问题",
|
||||
newCompetitor: "新建竞品",
|
||||
viewVersions: "查看版本",
|
||||
},
|
||||
empty: {
|
||||
brands: "还没有品牌数据,先创建一个品牌。",
|
||||
questions: "当前关键词下暂无问题集。",
|
||||
competitors: "当前品牌下暂无竞品数据。",
|
||||
},
|
||||
form: {
|
||||
brandName: "品牌名称",
|
||||
brandDescription: "品牌描述",
|
||||
keywordName: "关键词名称",
|
||||
questionText: "问题内容",
|
||||
competitorName: "竞品名称",
|
||||
competitorWebsite: "竞品官网",
|
||||
competitorDescription: "竞品描述",
|
||||
competitorLines: "重点产品线",
|
||||
competitorLinesHint: "使用英文逗号分隔多个产品线",
|
||||
},
|
||||
messages: {
|
||||
createBrand: "品牌已创建",
|
||||
updateBrand: "品牌已更新",
|
||||
deleteBrand: "品牌已删除",
|
||||
createKeyword: "关键词已创建",
|
||||
updateKeyword: "关键词已更新",
|
||||
deleteKeyword: "关键词已删除",
|
||||
createQuestion: "问题已创建",
|
||||
updateQuestion: "问题已更新",
|
||||
deleteQuestion: "问题已删除",
|
||||
createCompetitor: "竞品已创建",
|
||||
updateCompetitor: "竞品已更新",
|
||||
deleteCompetitor: "竞品已删除",
|
||||
chooseBrand: "请先选择品牌",
|
||||
chooseKeyword: "请先选择关键词",
|
||||
},
|
||||
},
|
||||
featureStub: {
|
||||
eyebrow: "Feature Placeholder",
|
||||
currentStatus: "当前状态",
|
||||
nextPriority: "下一步重点",
|
||||
integrationStrategy: "联调策略",
|
||||
currentStatusText: "页面壳子已经接入主导航和鉴权守卫,后续可以直接在这里落真实交互。",
|
||||
integrationStrategyText: "保持与 tenant-api 的响应结构对齐,先做真实读接口,再逐个补写接口和表单流。",
|
||||
},
|
||||
} as const;
|
||||
|
||||
export default zhCN;
|
||||
Reference in New Issue
Block a user