fix: make CMS content live and migrate to MySQL
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Link } from 'react-router-dom'
|
||||
import { useCMSTexts } from '@/services/cms'
|
||||
|
||||
interface Props {
|
||||
title?: string
|
||||
@@ -17,6 +18,11 @@ export default function GlobalCTA({
|
||||
secondaryLabel = '看看你的企业',
|
||||
secondaryTo = '/self-check',
|
||||
}: Props) {
|
||||
const { data: texts } = useCMSTexts()
|
||||
title = texts['global_cta.title'] || title
|
||||
desc = texts['global_cta.description'] || desc
|
||||
primaryLabel = texts['global_cta.primary'] || primaryLabel
|
||||
secondaryLabel = texts['global_cta.secondary'] || secondaryLabel
|
||||
return (
|
||||
<section className="cta-band">
|
||||
<div className="container">
|
||||
|
||||
+11
-20
@@ -1,10 +1,12 @@
|
||||
import { Link } from 'react-router-dom'
|
||||
import GlobalCTA from '@/components/Layout/GlobalCTA'
|
||||
import { useCMS, getCMSAmeba } from '@/services/cms'
|
||||
import { useCMS, useCMSTexts, getCMSAmeba } from '@/services/cms'
|
||||
|
||||
export default function Ameba() {
|
||||
const { data } = useCMS(getCMSAmeba, null)
|
||||
const { data: texts } = useCMSTexts()
|
||||
const content = data || {}
|
||||
const text = (key: string, fallback: string) => texts[key] || fallback
|
||||
return (
|
||||
<div>
|
||||
<div className="page-header">
|
||||
@@ -13,13 +15,10 @@ export default function Ameba() {
|
||||
<Link to="/" style={{ color: 'rgba(255,255,255,0.8)' }}>
|
||||
首页
|
||||
</Link>{' '}
|
||||
/ 阿美巴
|
||||
</div>
|
||||
<h1>阿美巴</h1>
|
||||
<p>{content.brand_position || '以企业进化经营哲学为底色,坚持“利他、务实、陪跑”。不做纸上谈兵,只做可落地、可量化、有结果的实操辅导。'}</p>
|
||||
<div className="placeholder" style={{ marginTop: 16 }}>
|
||||
【占位|待业务确认】团队介绍、资质、里程碑、价值观等由知识母盘灌入。专家网络仅作辅助信任证据,不作为核心支柱。
|
||||
/ {text('ameba.header_title', '阿美巴')}
|
||||
</div>
|
||||
<h1>{text('ameba.header_title', '阿美巴')}</h1>
|
||||
<p>{content.brand_position || text('ameba.header_description', '以企业进化经营哲学为底色,坚持利他、务实、陪跑,帮助企业把方法落到经营现场。')}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -27,18 +26,12 @@ export default function Ameba() {
|
||||
<div className="container">
|
||||
<div className="grid-2">
|
||||
<div className="card">
|
||||
<h3>经营哲学</h3>
|
||||
<h3>{text('ameba.philosophy_title', '经营哲学')}</h3>
|
||||
<p>{content.philosophy || '阿米巴哲学本土化实践,强调人人经营、数据透明、持续改善。'}</p>
|
||||
<div className="placeholder" style={{ marginTop: 12 }}>
|
||||
【占位】哲学主张、原则、行为准则待确认。
|
||||
</div>
|
||||
</div>
|
||||
<div className="card">
|
||||
<h3>服务理念</h3>
|
||||
<h3>{text('ameba.practice_title', '服务理念')}</h3>
|
||||
<p>{content.practice || '教练式陪跑:顾问入企,手把手带教,体系化交付 SOP 与工具包。'}</p>
|
||||
<div className="placeholder" style={{ marginTop: 12 }}>
|
||||
【占位】陪跑模式、交付标准待确认。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -46,14 +39,12 @@ export default function Ameba() {
|
||||
|
||||
<section className="section section-muted">
|
||||
<div className="container">
|
||||
<h2 className="h2">我们是谁 · 占位</h2>
|
||||
<h2 className="h2">{text('ameba.about_title', '我们是谁')}</h2>
|
||||
<div className="card">
|
||||
<p className="desc">
|
||||
成都阿美巴企业管理咨询有限公司,专注体系化增长落地。核心团队十年以上实战经验,覆盖制造、服务、科技、商贸等领域。
|
||||
{text('ameba.about_text', '围绕企业进化与体系化增长,提供长期、务实、可复盘的企业管理咨询服务。')}
|
||||
</p>
|
||||
<div className="placeholder" style={{ marginTop: 12 }}>
|
||||
{content.mission || '【占位|待业务确认】公司简介、团队、资质证书、合作客户 LOGO 墙均待业务方提供定稿素材。'}
|
||||
</div>
|
||||
{content.mission && <div className="placeholder" style={{ marginTop: 12 }}>{content.mission}</div>}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
.hero-copy h1 { font-size: 40px; font-weight: 900; line-height: 1.15; margin: 8px 0 14px; }
|
||||
.hero-desc { color: rgba(255,255,255,0.82); font-size: 15px; line-height: 1.8; max-width: 560px; }
|
||||
.hero-actions { display: flex; gap: 12px; margin-top: 20px; flex-wrap: wrap; }
|
||||
.hero-actions .btn-ghost { color: #fff; border-color: rgba(255,255,255,0.55); background: rgba(255,255,255,0.08); }
|
||||
.hero-actions .btn-ghost:hover { color: #163E70; background: #fff; border-color: #fff; }
|
||||
.hero-trust { margin-top: 16px; font-size: 12px; color: rgba(255,255,255,0.6); border-top: 1px solid rgba(255,255,255,0.12); padding-top: 12px; }
|
||||
.visual-card { background: #fff; color: var(--text); border-radius: 16px; padding: 24px; box-shadow: 0 20px 60px rgba(0,0,0,0.2); }
|
||||
.visual-title { font-weight: 800; color: var(--primary); margin-bottom: 16px; }
|
||||
|
||||
+18
-17
@@ -1,7 +1,7 @@
|
||||
import { Link } from 'react-router-dom'
|
||||
import GlobalCTA from '@/components/Layout/GlobalCTA'
|
||||
import { FOUR_VALUES as FALLBACK_FOUR, SERVICES as FALLBACK_SERVICES, CASES as FALLBACK_CASES, INSIGHTS as FALLBACK_INSIGHTS } from '@/data/mock'
|
||||
import { useCMS, getCMSFourValues, getCMSServices, getCMSCases, getCMSInsights } from '@/services/cms'
|
||||
import { useCMS, useCMSTexts, getCMSFourValues, getCMSServices, getCMSCases, getCMSInsights } from '@/services/cms'
|
||||
import './home.css'
|
||||
|
||||
export default function Home() {
|
||||
@@ -9,36 +9,37 @@ export default function Home() {
|
||||
const { data: services } = useCMS(getCMSServices, FALLBACK_SERVICES)
|
||||
const { data: cases } = useCMS(getCMSCases, FALLBACK_CASES)
|
||||
const { data: insights } = useCMS(getCMSInsights, FALLBACK_INSIGHTS)
|
||||
const { data: texts } = useCMSTexts()
|
||||
const text = (key: string, fallback: string) => texts[key] || fallback
|
||||
const heroTitle = text('home.title', '让企业进化\n被看见、被度量、被落地').split('\n')
|
||||
return (
|
||||
<div className="home">
|
||||
{/* 首屏:3秒识别品牌 */}
|
||||
<section className="hero-home">
|
||||
<div className="container hero-home-inner">
|
||||
<div className="hero-copy">
|
||||
<p className="eyebrow">阿美巴 · 企业进化陪跑</p>
|
||||
<p className="eyebrow">{text('home.eyebrow', '阿美巴 · 企业进化陪跑')}</p>
|
||||
<h1>
|
||||
让企业进化
|
||||
<br />
|
||||
被看见、被度量、被落地
|
||||
{heroTitle.map((line, i) => <span key={i}>{i > 0 && <br />}{line}</span>)}
|
||||
</h1>
|
||||
<p className="hero-desc">
|
||||
以“企业进化”为主线,以<strong>四大价值坐标</strong>与<strong> A/M/B 状态坐标</strong>为观察系,陪跑企业构建可复制、可持续的增长经营体系。
|
||||
{text('home.description', '以“企业进化”为主线,以四大价值坐标与 A/M/B 状态坐标为观察系,陪跑企业构建可复制、可持续的增长经营体系。')}
|
||||
<br />
|
||||
<span style={{ color: '#f59e0b' }}>一期为骨架与占位,不虚构业务数据。</span>
|
||||
<span style={{ color: '#f59e0b' }}>{text('home.notice', '以真实业务内容为准,后台发布后前台即时生效。')}</span>
|
||||
</p>
|
||||
<div className="hero-actions">
|
||||
<Link to="/diagnosis" className="btn btn-primary">
|
||||
开始企业进化诊断
|
||||
{text('home.primary_cta', '开始企业进化诊断')}
|
||||
</Link>
|
||||
<Link to="/contact" className="btn btn-secondary">
|
||||
咨询获取方案
|
||||
{text('home.secondary_cta', '咨询获取方案')}
|
||||
</Link>
|
||||
<Link to="/self-check" className="btn btn-ghost">
|
||||
轻量对照
|
||||
{text('home.light_cta', '轻量对照')}
|
||||
</Link>
|
||||
</div>
|
||||
<div className="hero-trust">
|
||||
<span>30秒理解主张:进化思想 → 价值坐标 → 状态坐标 → 行动路径</span>
|
||||
<span>{text('home.trust', '30秒理解主张:进化思想 → 价值坐标 → 状态坐标 → 行动路径')}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="hero-visual">
|
||||
@@ -75,15 +76,15 @@ export default function Home() {
|
||||
<div className="container">
|
||||
<div className="section-heading">
|
||||
<p className="eyebrow">Ameba</p>
|
||||
<h2 className="h2">关于阿美巴</h2>
|
||||
<h2 className="h2">{text('home.about_title', '关于阿美巴')}</h2>
|
||||
<p className="desc">克制理性的企业服务风格,以方法与陪跑见长,非培训话术与AI噱头。</p>
|
||||
</div>
|
||||
<div className="card" style={{ display: 'flex', justifyContent: 'space-between', gap: 16, alignItems: 'center', flexWrap: 'wrap' }}>
|
||||
<p className="desc" style={{ maxWidth: 640 }}>
|
||||
阿美巴以企业进化经营哲学为底色,结合中国中小企业实际,提供从诊断到落地陪跑的全链路服务。
|
||||
{text('home.about_text', '阿美巴以企业进化经营哲学为底色,结合中国中小企业实际,提供从诊断到落地陪跑的全链路服务。')}
|
||||
<br />
|
||||
<span className="placeholder" style={{ display: 'inline-block', marginTop: 8 }}>
|
||||
【占位|待业务确认】品牌故事、创始团队、使命愿景等由知识母盘灌入。
|
||||
{text('home.about_note', '品牌故事、创始团队、使命愿景等内容请在后台配置。')}
|
||||
</span>
|
||||
</p>
|
||||
<Link to="/ameba" className="btn btn-secondary">
|
||||
@@ -152,7 +153,7 @@ export default function Home() {
|
||||
<div className="container">
|
||||
<div className="section-heading">
|
||||
<p className="eyebrow">Cases</p>
|
||||
<h2 className="h2">实践案例(占位)</h2>
|
||||
<h2 className="h2">{text('home.cases_title', '实践案例')}</h2>
|
||||
<p className="desc">固定叙事插槽:原状 → 目标 → 差距 → 根因 → 介入 → 路径 → 动作 → 结果 → 迭代。无虚构数据。</p>
|
||||
</div>
|
||||
<div className="grid-2">
|
||||
@@ -175,7 +176,7 @@ export default function Home() {
|
||||
<div className="container">
|
||||
<div className="section-heading">
|
||||
<p className="eyebrow">Services</p>
|
||||
<h2 className="h2">产品服务 · 下一步行动</h2>
|
||||
<h2 className="h2">{text('home.services_title', '产品服务 · 下一步行动')}</h2>
|
||||
<p className="desc">禁止电商商城逻辑;重心是“下一步如何行动”。标准产品预留价格,定制展示“咨询/获取方案”。</p>
|
||||
</div>
|
||||
<div className="grid-3">
|
||||
@@ -204,7 +205,7 @@ export default function Home() {
|
||||
<div className="container">
|
||||
<div className="section-heading">
|
||||
<p className="eyebrow">Insights</p>
|
||||
<h2 className="h2">认知观察</h2>
|
||||
<h2 className="h2">{text('home.insights_title', '认知观察')}</h2>
|
||||
<p className="desc">围绕进化思想、价值坐标、A/M/B 的观察与思考。</p>
|
||||
</div>
|
||||
<div className="grid-2">
|
||||
|
||||
+7
-1
@@ -20,6 +20,7 @@ export interface CMSPublicData {
|
||||
ameba: any
|
||||
evolution_thought: any
|
||||
self_check: any
|
||||
texts: Record<string, string>
|
||||
}
|
||||
|
||||
let cache: CMSPublicData | null = null
|
||||
@@ -28,7 +29,7 @@ let pending: Promise<CMSPublicData | null> | null = null
|
||||
export async function fetchCMSPublic(): Promise<CMSPublicData | null> {
|
||||
if (cache) return cache
|
||||
if (pending) return pending
|
||||
pending = fetch(CMS_PUBLIC).then(async r=>{
|
||||
pending = fetch(`${CMS_PUBLIC}${CMS_PUBLIC.includes('?') ? '&' : '?'}t=${Date.now()}`, { cache: 'no-store' }).then(async r=>{
|
||||
if(!r.ok) throw new Error('cms fetch '+r.status)
|
||||
const j=await r.json()
|
||||
if(j.code!==0) throw new Error(j.msg)
|
||||
@@ -171,6 +172,7 @@ export async function getCMSMethods(): Promise<MethodCapability[]>{ const d=awai
|
||||
export async function getCMSAmb(): Promise<Record<string, AmbStatusMeta>>{ const d=await fetchCMSPublic(); return normalizeAmb(d?.amb_states as any) }
|
||||
export async function getCMSConfig(){ const d=await fetchCMSPublic(); return d?.config || null }
|
||||
export async function getCMSAmeba(){ const d=await fetchCMSPublic(); return d?.ameba || null }
|
||||
export async function getCMSTexts(){ const d=await fetchCMSPublic(); return d?.texts || {} }
|
||||
|
||||
// Hook for React
|
||||
import { useEffect, useState } from 'react'
|
||||
@@ -184,3 +186,7 @@ export function useCMS<T>(loader: ()=>Promise<T>, fallback: T){
|
||||
},[])
|
||||
return {data, loading}
|
||||
}
|
||||
|
||||
export function useCMSTexts(){
|
||||
return useCMS(getCMSTexts, {} as Record<string, string>)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user