fix: make CMS content live and migrate to MySQL

This commit is contained in:
Codex User
2026-09-08 13:30:54 +08:00
parent 3a99ae30c5
commit 1088871eb9
15 changed files with 401 additions and 799 deletions
+6
View File
@@ -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
View File
@@ -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>
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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>)
}