fix: make CMS content live and migrate to MySQL
This commit is contained in:
+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>
|
||||
|
||||
@@ -53,7 +53,6 @@ export default function CaseDetail() {
|
||||
<div className="container">
|
||||
<div className="card" style={{ borderLeft: '4px solid #163E70' }}>
|
||||
<h3>案例叙事 · 9段固定插槽</h3>
|
||||
<p style={{ fontSize: 12, color: '#64748b' }}>CMS 仅替换插槽文本,不改结构。未确认字段统一占位。</p>
|
||||
</div>
|
||||
|
||||
<div style={{ marginTop: 20, display: 'grid', gap: 16 }}>
|
||||
@@ -67,8 +66,6 @@ export default function CaseDetail() {
|
||||
|
||||
<div className="card" style={{ marginTop: 16, background: '#f8fafc' }}>
|
||||
<h3>关联维度(预留)</h3>
|
||||
<p style={{ fontSize: 13, color: '#64748b' }}>关联价值:{c.fourValuesInvolved?.join(', ') || '【占位】待关联'}</p>
|
||||
<p style={{ fontSize: 13, color: '#64748b' }}>关联服务:{c.serviceIds?.join(', ') || '【占位】待关联'}</p>
|
||||
</div>
|
||||
|
||||
<div style={{ marginTop: 16, display: 'flex', gap: 10, flexWrap: 'wrap' }}>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Link } from 'react-router-dom'
|
||||
import { CASES as FALLBACK_CASES } from '@/data/mock'
|
||||
import { useCMS, getCMSCases } from '@/services/cms'
|
||||
import { useCMS, useCMSTexts, getCMSCases } from '@/services/cms'
|
||||
import GlobalCTA from '@/components/Layout/GlobalCTA'
|
||||
|
||||
export default function Cases() {
|
||||
const { data: CASES } = useCMS(getCMSCases, FALLBACK_CASES)
|
||||
const { data: texts } = useCMSTexts()
|
||||
return (
|
||||
<div>
|
||||
<div className="page-header">
|
||||
@@ -16,7 +17,7 @@ export default function Cases() {
|
||||
/ 实践案例
|
||||
</div>
|
||||
<h1>实践案例</h1>
|
||||
<p>固定叙事插槽 9 段式结构,业务数据与布局解耦,未来由 CMS 接管。无虚构数据,未确认统一占位。</p>
|
||||
<p>{texts['cases.header_description'] || '通过原状、目标、差距、根因、介入、路径、行动、结果与迭代,看见企业进化过程。'}</p>
|
||||
</div>
|
||||
</div>
|
||||
<section className="section">
|
||||
@@ -27,20 +28,10 @@ export default function Cases() {
|
||||
<div style={{ fontSize: 11, color: '#0f6b5b', fontWeight: 800, letterSpacing: '0.08em' }}>CASE · {c.status.toUpperCase()}</div>
|
||||
<h3 style={{ marginTop: 6 }}>{c.title}</h3>
|
||||
<p>{c.summary}</p>
|
||||
<div className="placeholder" style={{ marginTop: 10, fontSize: 12 }}>
|
||||
权重 {c.sortWeight} · 上下架 {c.status} · 预留排序
|
||||
</div>
|
||||
<span style={{ fontSize: 12, color: '#163E70', fontWeight: 700, marginTop: 10, display: 'inline-block' }}>查看完整叙事 →</span>
|
||||
<span style={{ fontSize: 12, color: '#163E70', fontWeight: 700, marginTop: 10, display: 'inline-block' }}>{texts['cases.detail_link'] || '查看完整叙事'} →</span>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<div className="card" style={{ marginTop: 20, background: '#fff7e6', borderColor: '#f59e0b' }}>
|
||||
<strong style={{ color: '#92400e' }}>案例叙事模板插槽(固定 9 段)</strong>
|
||||
<p style={{ fontSize: 13, color: '#78350f', marginTop: 6 }}>
|
||||
企业原状 → 企业目标 → 现存差距 → 根因 → 阿美巴介入 → 进化路径 → 落地动作 → 阶段结果 → 持续迭代
|
||||
</p>
|
||||
<p style={{ fontSize: 12, color: '#92400e', marginTop: 4 }}>CMS 接管后,编辑仅替换插槽内容,不改页面结构。</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<GlobalCTA />
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { useCMSTexts } from '@/services/cms'
|
||||
|
||||
export default function Contact() {
|
||||
const { data: texts } = useCMSTexts()
|
||||
const [form, setForm] = useState({ name: '', company: '', phone: '', need: '' })
|
||||
const [submitted, setSubmitted] = useState(false)
|
||||
const [error, setError] = useState('')
|
||||
@@ -64,7 +66,7 @@ export default function Contact() {
|
||||
<input
|
||||
value={form.company}
|
||||
onChange={e => setForm({ ...form, company: e.target.value })}
|
||||
placeholder="【占位】选填"
|
||||
placeholder={texts['contact.company_placeholder'] || '选填'}
|
||||
style={{ width: '100%', marginTop: 6, padding: '10px 12px', border: '1px solid #e2e8f0', borderRadius: 8 }}
|
||||
/>
|
||||
</label>
|
||||
@@ -83,7 +85,7 @@ export default function Contact() {
|
||||
<textarea
|
||||
value={form.need}
|
||||
onChange={e => setForm({ ...form, need: e.target.value })}
|
||||
placeholder="请简述你的企业现状与期望(占位)"
|
||||
placeholder={texts['contact.need_placeholder'] || '请简述你的企业现状与期望'}
|
||||
rows={3}
|
||||
style={{ width: '100%', marginTop: 6, padding: '10px 12px', border: '1px solid #e2e8f0', borderRadius: 8 }}
|
||||
/>
|
||||
@@ -93,16 +95,12 @@ export default function Contact() {
|
||||
</button>
|
||||
{submitted && <div style={{ fontSize: 13, color: '#0f6b5b', background: '#ecfdf5', padding: 10, borderRadius: 8 }}>已提交,顾问将尽快联系。</div>}
|
||||
{error && <div style={{ fontSize: 13, color: '#be123c', background: '#fff1f2', padding: 10, borderRadius: 8 }}>{error}</div>}
|
||||
<p style={{ fontSize: 11, color: '#94a3b8' }}>提交即视为同意隐私与合规说明(占位)。</p>
|
||||
<p style={{ fontSize: 11, color: '#94a3b8' }}>{texts['contact.privacy_note'] || '提交即视为同意隐私与合规说明。'}</p>
|
||||
</form>
|
||||
</div>
|
||||
<div style={{ display: 'grid', gap: 16, alignContent: 'start' }}>
|
||||
<div className="card">
|
||||
<h3>其他通道</h3>
|
||||
<p style={{ fontSize: 13, color: '#475569' }}>电话、邮箱、地址等待业务确认后灌入。</p>
|
||||
<div className="placeholder" style={{ marginTop: 10 }}>
|
||||
【占位|待业务确认】商务电话 / 企业邮箱 / 办公地址 / 企业微信二维码
|
||||
</div>
|
||||
</div>
|
||||
<div className="card">
|
||||
<h3>快速路径</h3>
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Link, useNavigate } from 'react-router-dom'
|
||||
import { useCMSTexts } from '@/services/cms'
|
||||
|
||||
type Q = { id:string, group_key:string, group_name:string, type:string, title:string, options:any[], sort_order:number }
|
||||
const STORAGE_KEY='diagnosis_progress'
|
||||
|
||||
export default function Diagnosis(){
|
||||
const { data: texts } = useCMSTexts()
|
||||
const [questions,setQuestions]=useState<Q[]>([])
|
||||
const [answers,setAnswers]=useState<Record<string,any>>({})
|
||||
const [idx,setIdx]=useState(0)
|
||||
@@ -52,7 +54,7 @@ export default function Diagnosis(){
|
||||
}
|
||||
|
||||
if(loading) return <div className="container section">加载问卷... <2s</div>
|
||||
if(!q) return <div className="container section">暂无题目,请联系管理员在CMS后台配置</div>
|
||||
if(!q) return <div className="container section">暂无可用题目,请稍后再试。</div>
|
||||
|
||||
const isAnswered = answers[q.id]!==undefined
|
||||
|
||||
@@ -94,7 +96,7 @@ export default function Diagnosis(){
|
||||
<button className="btn btn-ghost" onClick={prevQ} disabled={idx===0}>上一步</button>
|
||||
<button className="btn btn-primary" style={{flex:1}} onClick={nextQ} disabled={!isAnswered}>{idx===questions.length-1?'提交生成报告':'下一步'}</button>
|
||||
</div>
|
||||
<div style={{fontSize:11, color:'#94a3b8', marginTop:8}}>禁止开放题必填 · 采用区间选择 · 不收集敏感财务数据</div>
|
||||
<div style={{fontSize:11, color:'#94a3b8', marginTop:8}}>{texts['diagnosis.input_note'] || '采用区间选择,不收集敏感财务数据。'}</div>
|
||||
</div>
|
||||
<div style={{marginTop:12, display:'flex', gap:10}}>
|
||||
<Link to="/self-check" className="btn btn-ghost">返回轻量对照</Link>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { useParams, Link } from 'react-router-dom'
|
||||
import { AMB_STATUS_META } from '@/data/mock'
|
||||
import { useCMS, getCMSAmb } from '@/services/cms'
|
||||
import { useCMS, useCMSTexts, getCMSAmb } from '@/services/cms'
|
||||
import GlobalCTA from '@/components/Layout/GlobalCTA'
|
||||
|
||||
export default function AmbDetail() {
|
||||
const { status } = useParams()
|
||||
const { data: ambMeta } = useCMS(getCMSAmb, AMB_STATUS_META)
|
||||
const { data: texts } = useCMSTexts()
|
||||
const meta = ambMeta[status as string]
|
||||
|
||||
if (!meta) {
|
||||
@@ -35,7 +36,7 @@ export default function AmbDetail() {
|
||||
</div>
|
||||
<h1>{meta.label}</h1>
|
||||
<p>{meta.description}</p>
|
||||
<p style={{ fontSize: 12, color: 'rgba(255,255,255,0.6)', marginTop: 8 }}>不绑定规模 · 支持跨维度不同状态</p>
|
||||
<p style={{ fontSize: 12, color: 'rgba(255,255,255,0.6)', marginTop: 8 }}>{texts['evolution.amb_detail_meta'] || '不绑定规模 · 支持跨维度不同状态'}</p>
|
||||
</div>
|
||||
</div>
|
||||
<section className="section">
|
||||
@@ -47,9 +48,6 @@ export default function AmbDetail() {
|
||||
<li key={t}>{t}</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="placeholder" style={{ marginTop: 12 }}>
|
||||
【占位|待业务确认】该状态的完整特征、风险、进化建议、案例映射待业务确认后灌入。
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ marginTop: 16, display: 'flex', gap: 10 }}>
|
||||
<Link to="/evolution" className="btn btn-ghost">
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { useParams, Link } from 'react-router-dom'
|
||||
import { FOUR_VALUES as FALLBACK_FOUR } from '@/data/mock'
|
||||
import { useCMS, getCMSFourValues } from '@/services/cms'
|
||||
import { useCMS, useCMSTexts, getCMSFourValues } from '@/services/cms'
|
||||
import GlobalCTA from '@/components/Layout/GlobalCTA'
|
||||
|
||||
export default function ValuesDetail() {
|
||||
const { data: FOUR_VALUES } = useCMS(getCMSFourValues, FALLBACK_FOUR)
|
||||
const { data: texts } = useCMSTexts()
|
||||
const { key } = useParams()
|
||||
const value = FOUR_VALUES.find(v => v.key === key)
|
||||
|
||||
@@ -35,7 +36,7 @@ export default function ValuesDetail() {
|
||||
</div>
|
||||
<h1>{value.name}</h1>
|
||||
<p>{value.summary}</p>
|
||||
<p style={{ fontSize: 12, color: 'rgba(255,255,255,0.6)', marginTop: 8 }}>观察坐标 · 非售卖产品 · CMS预留字段已就绪</p>
|
||||
<p style={{ fontSize: 12, color: 'rgba(255,255,255,0.6)', marginTop: 8 }}>{texts['evolution.value_detail_meta'] || '观察坐标 · 非售卖产品 · 用于理解企业真实位置'}</p>
|
||||
</div>
|
||||
</div>
|
||||
<section className="section">
|
||||
@@ -49,11 +50,7 @@ export default function ValuesDetail() {
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<div className="placeholder" style={{ marginTop: 16 }}>
|
||||
{value.description}
|
||||
<br />
|
||||
【占位|待业务确认】此价值坐标的完整阐述、评估要点、典型表现需由知识母盘灌入。
|
||||
</div>
|
||||
<div className="placeholder" style={{ marginTop: 16 }}>{value.description}</div>
|
||||
</div>
|
||||
<div style={{ marginTop: 16, display: 'flex', gap: 10 }}>
|
||||
<Link to="/evolution" className="btn btn-ghost">
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { FOUR_VALUES as FALLBACK_FOUR, AMB_STATUS_META } from '@/data/mock'
|
||||
import { useCMS, getCMSFourValues, getCMSAmb } from '@/services/cms'
|
||||
import { useCMS, useCMSTexts, getCMSFourValues, getCMSAmb } from '@/services/cms'
|
||||
import GlobalCTA from '@/components/Layout/GlobalCTA'
|
||||
|
||||
export default function Evolution() {
|
||||
const { data: FOUR_VALUES } = useCMS(getCMSFourValues, FALLBACK_FOUR)
|
||||
const { data: AMB_META } = useCMS(getCMSAmb, AMB_STATUS_META)
|
||||
const { data: texts } = useCMSTexts()
|
||||
const text = (key: string, fallback: string) => texts[key] || fallback
|
||||
const [foldValues, setFoldValues] = useState(false)
|
||||
const [foldAmb, setFoldAmb] = useState(false)
|
||||
|
||||
@@ -20,12 +22,12 @@ export default function Evolution() {
|
||||
</Link>{' '}
|
||||
/ 企业进化
|
||||
</div>
|
||||
<h1>企业进化</h1>
|
||||
<h1>{text('evolution.header_title', '企业进化')}</h1>
|
||||
<p>
|
||||
内部顺序强制:<strong>企业进化思想 → 四大价值坐标 → A/M/B 状态坐标</strong>,顺序不可调换。
|
||||
{text('evolution.header_description', '内部顺序强制:企业进化思想 → 四大价值坐标 → A/M/B 状态坐标,顺序不可调换。')}
|
||||
</p>
|
||||
<p style={{ fontSize: 12, color: 'rgba(255,255,255,0.6)', marginTop: 8 }}>
|
||||
V1.1 FINAL 冻结顺序,任何调换需登记台账延后二期。
|
||||
{text('evolution.header_note', '从进化思想到价值坐标,再到状态坐标,逐层看清企业位置。')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -33,22 +35,17 @@ export default function Evolution() {
|
||||
{/* 1. 企业进化思想 */}
|
||||
<section className="section" id="idea">
|
||||
<div className="container">
|
||||
<p className="eyebrow">01 — 企业进化思想</p>
|
||||
<h2 className="h2">进化是持续迭代,而非一次性变革</h2>
|
||||
<p className="desc">
|
||||
企业进化强调在不确定环境中,通过机制与人的双重迭代,实现组织的自适应与自进化。拒绝“规模决定论”,强调价值维度独立观察。
|
||||
</p>
|
||||
<p className="eyebrow">{text('evolution.idea_eyebrow', '01 — 企业进化思想')}</p>
|
||||
<h2 className="h2">{text('evolution.idea_title', '进化是持续迭代,而非一次性变革')}</h2>
|
||||
<p className="desc">{text('evolution.idea_description', '企业进化强调在不确定环境中,通过机制与人的双重迭代,实现组织的自适应与自进化。拒绝规模决定论,强调价值维度独立观察。')}</p>
|
||||
<div className="card" style={{ marginTop: 16 }}>
|
||||
<h3>核心主张(占位)</h3>
|
||||
<h3>{text('evolution.idea_core_title', '核心主张')}</h3>
|
||||
<ul style={{ paddingLeft: 18, fontSize: 14, color: '#475569', lineHeight: 2 }}>
|
||||
<li>经营即进化:战略、组织、机制、人的协同进化</li>
|
||||
<li>坐标而非标签:用价值与状态观察,而非给企业贴标签</li>
|
||||
<li>陪跑而非交付:共创机制,陪跑落地,复盘迭代</li>
|
||||
<li>【占位|待业务确认】更多思想阐述由知识母盘灌入</li>
|
||||
<li>{text('evolution.idea_bullet_1', '经营即进化:战略、组织、机制、人的协同进化')}</li>
|
||||
<li>{text('evolution.idea_bullet_2', '坐标而非标签:用价值与状态观察,而非给企业贴标签')}</li>
|
||||
<li>{text('evolution.idea_bullet_3', '陪跑而非交付:共创机制,陪跑落地,复盘迭代')}</li>
|
||||
<li>{text('evolution.idea_bullet_4', '持续复盘迭代,让每一次行动都沉淀为组织能力')}</li>
|
||||
</ul>
|
||||
<div className="placeholder" style={{ marginTop: 12 }}>
|
||||
【占位|待业务确认】此段需业务方确认最终表述,一期仅保留结构。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -58,9 +55,9 @@ export default function Evolution() {
|
||||
<div className="container">
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 12 }}>
|
||||
<div>
|
||||
<p className="eyebrow">02 — 四大价值坐标</p>
|
||||
<h2 className="h2">观察坐标,非售卖产品</h2>
|
||||
<p className="desc">四大价值定位为观察坐标,不能包装成售卖产品。用于看清企业在各维度的真实位置。</p>
|
||||
<p className="eyebrow">{text('evolution.values_eyebrow', '02 — 四大价值坐标')}</p>
|
||||
<h2 className="h2">{text('evolution.values_title', '观察坐标,非售卖产品')}</h2>
|
||||
<p className="desc">{text('evolution.values_description', '四大价值定位为观察坐标,用于看清企业在各维度的真实位置。')}</p>
|
||||
</div>
|
||||
<button className="foldable-trigger" onClick={() => setFoldValues(!foldValues)} style={{ width: 'auto' }}>
|
||||
{foldValues ? '收起' : '展开'}价值详情 <span>{foldValues ? '−' : '+'}</span>
|
||||
@@ -123,9 +120,9 @@ export default function Evolution() {
|
||||
<div className="container">
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 12 }}>
|
||||
<div>
|
||||
<p className="eyebrow">03 — A/M/B 状态坐标</p>
|
||||
<h2 className="h2">A / M / B 不绑定规模</h2>
|
||||
<p className="desc">支持同一企业不同价值维度处于不同状态;拒绝“规模决定状态”的包装。</p>
|
||||
<p className="eyebrow">{text('evolution.amb_eyebrow', '03 — A/M/B 状态坐标')}</p>
|
||||
<h2 className="h2">{text('evolution.amb_title', 'A / M / B 不绑定规模')}</h2>
|
||||
<p className="desc">{text('evolution.amb_description', '支持同一企业不同价值维度处于不同状态,拒绝规模决定状态的包装。')}</p>
|
||||
</div>
|
||||
<button className="foldable-trigger" onClick={() => setFoldAmb(!foldAmb)} style={{ width: 'auto' }}>
|
||||
{foldAmb ? '收起' : '展开'}状态详情 <span>{foldAmb ? '−' : '+'}</span>
|
||||
@@ -150,13 +147,8 @@ export default function Evolution() {
|
||||
</div>
|
||||
|
||||
<div className="card" style={{ marginTop: 20, background: '#f8fafc' }}>
|
||||
<h3>跨维度状态示例(占位)</h3>
|
||||
<p style={{ fontSize: 13, color: '#64748b' }}>
|
||||
示例:某企业 · 战略价值 A / 组织价值 M / 经营价值 B / 人的价值 M。说明同一企业可在不同坐标处不同状态,需分维度干预。
|
||||
</p>
|
||||
<div className="placeholder" style={{ marginTop: 10 }}>
|
||||
【占位|待业务确认】真实示例需脱敏后灌入,一期仅示意结构。
|
||||
</div>
|
||||
<h3>{text('evolution.amb_example_title', '跨维度状态示例')}</h3>
|
||||
<p style={{ fontSize: 13, color: '#64748b' }}>{text('evolution.amb_example_description', '示例:某企业 · 战略价值 A / 组织价值 M / 经营价值 B / 人的价值 M。说明同一企业可在不同坐标处不同状态,需分维度干预。')}</p>
|
||||
</div>
|
||||
|
||||
<div style={{ marginTop: 16, display: 'flex', gap: 10, flexWrap: 'wrap' }}>
|
||||
|
||||
@@ -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
-19
@@ -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,35 @@ 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>为观察系,陪跑企业构建可复制、可持续的增长经营体系。
|
||||
<br />
|
||||
<span style={{ color: '#f59e0b' }}>一期为骨架与占位,不虚构业务数据。</span>
|
||||
{text('home.description', '以“企业进化”为主线,以四大价值坐标与 A/M/B 状态坐标为观察系,陪跑企业构建可复制、可持续的增长经营体系。')}
|
||||
</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 +74,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 +151,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,8 +174,8 @@ export default function Home() {
|
||||
<div className="container">
|
||||
<div className="section-heading">
|
||||
<p className="eyebrow">Services</p>
|
||||
<h2 className="h2">产品服务 · 下一步行动</h2>
|
||||
<p className="desc">禁止电商商城逻辑;重心是“下一步如何行动”。标准产品预留价格,定制展示“咨询/获取方案”。</p>
|
||||
<h2 className="h2">{text('home.services_title', '产品服务 · 下一步行动')}</h2>
|
||||
<p className="desc">{text('home.services_note', '围绕下一步行动提供标准产品与定制陪跑服务。')}</p>
|
||||
</div>
|
||||
<div className="grid-3">
|
||||
{services.map(s => (
|
||||
@@ -204,7 +203,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">
|
||||
|
||||
@@ -54,9 +54,6 @@ export default function InsightDetail() {
|
||||
{b.type === 'placeholder' && <div className="placeholder">{b.placeholderNote}</div>}
|
||||
</div>
|
||||
))}
|
||||
<div className="placeholder" style={{ marginTop: 12 }}>
|
||||
【占位|待业务确认】正文由 CMS 接管,编辑仅替换 contentBlocks,不改布局。
|
||||
</div>
|
||||
</article>
|
||||
<div style={{ marginTop: 16, display: 'flex', gap: 10 }}>
|
||||
<Link to="/insights" className="btn btn-ghost">
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Link } from 'react-router-dom'
|
||||
import { INSIGHTS as FALLBACK_INSIGHTS } from '@/data/mock'
|
||||
import { useCMS, getCMSInsights } from '@/services/cms'
|
||||
import { useCMS, useCMSTexts, getCMSInsights } from '@/services/cms'
|
||||
import GlobalCTA from '@/components/Layout/GlobalCTA'
|
||||
|
||||
export default function Insights() {
|
||||
const { data: INSIGHTS } = useCMS(getCMSInsights, FALLBACK_INSIGHTS)
|
||||
const { data: texts } = useCMSTexts()
|
||||
return (
|
||||
<div>
|
||||
<div className="page-header">
|
||||
@@ -13,13 +14,10 @@ export default function Insights() {
|
||||
<Link to="/" style={{ color: 'rgba(255,255,255,0.8)' }}>
|
||||
首页
|
||||
</Link>{' '}
|
||||
/ 认知观察
|
||||
</div>
|
||||
<h1>认知观察</h1>
|
||||
<p>围绕企业进化、价值坐标、A/M/B 与方法论的持续观察与沉淀。</p>
|
||||
<div className="placeholder" style={{ marginTop: 12 }}>
|
||||
【占位|待业务确认】文章由知识母盘定稿后灌入,一期仅保留结构与占位。
|
||||
/ {texts['insights.title'] || '认知观察'}
|
||||
</div>
|
||||
<h1>{texts['insights.title'] || '认知观察'}</h1>
|
||||
<p>{texts['insights.header_description'] || '围绕企业进化、价值坐标、A/M/B 与方法论的持续观察与沉淀。'}</p>
|
||||
</div>
|
||||
</div>
|
||||
<section className="section">
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { useParams, Link } from 'react-router-dom'
|
||||
import { METHODS as FALLBACK_METHODS } from '@/data/mock'
|
||||
import { useCMS, getCMSMethods } from '@/services/cms'
|
||||
import { useCMS, useCMSTexts, getCMSMethods } from '@/services/cms'
|
||||
import GlobalCTA from '@/components/Layout/GlobalCTA'
|
||||
|
||||
export default function MethodDetail() {
|
||||
const { data: METHODS } = useCMS(getCMSMethods, FALLBACK_METHODS)
|
||||
const { data: texts } = useCMSTexts()
|
||||
const { slug } = useParams()
|
||||
const item = METHODS.find(m => m.slug === slug)
|
||||
if (!item)
|
||||
@@ -26,7 +27,7 @@ export default function MethodDetail() {
|
||||
</Link>{' '}
|
||||
/{' '}
|
||||
<Link to="/methods" style={{ color: 'rgba(255,255,255,0.8)' }}>
|
||||
方法与能力
|
||||
{texts['methods.title'] || '方法与能力'}
|
||||
</Link>{' '}
|
||||
/ {item.title}
|
||||
</div>
|
||||
@@ -37,22 +38,19 @@ export default function MethodDetail() {
|
||||
<section className="section">
|
||||
<div className="container">
|
||||
<div className="card">
|
||||
<h3>关键步骤</h3>
|
||||
<h3>{texts['methods.detail_steps_title'] || '关键步骤'}</h3>
|
||||
<ol style={{ paddingLeft: 18, lineHeight: 2, fontSize: 14 }}>
|
||||
{item.steps?.map(s => (
|
||||
<li key={s}>{s}</li>
|
||||
))}
|
||||
</ol>
|
||||
<div className="placeholder" style={{ marginTop: 12 }}>
|
||||
【占位|待业务确认】完整方法阐述、工具清单、交付物清单待灌入。
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ marginTop: 16, display: 'flex', gap: 10 }}>
|
||||
<Link to="/methods" className="btn btn-ghost">
|
||||
← 返回
|
||||
</Link>
|
||||
<Link to="/contact" className="btn btn-primary">
|
||||
咨询获取方案
|
||||
{texts['global_cta.primary'] || '咨询获取方案'}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Link } from 'react-router-dom'
|
||||
import { METHODS as FALLBACK_METHODS } from '@/data/mock'
|
||||
import { useCMS, getCMSMethods } from '@/services/cms'
|
||||
import { useCMS, useCMSTexts, getCMSMethods } from '@/services/cms'
|
||||
import GlobalCTA from '@/components/Layout/GlobalCTA'
|
||||
|
||||
export default function Methods() {
|
||||
const { data: METHODS } = useCMS(getCMSMethods, FALLBACK_METHODS)
|
||||
const { data: texts } = useCMSTexts()
|
||||
return (
|
||||
<div>
|
||||
<div className="page-header">
|
||||
@@ -15,11 +16,8 @@ export default function Methods() {
|
||||
</Link>{' '}
|
||||
/ 方法与能力
|
||||
</div>
|
||||
<h1>方法与能力</h1>
|
||||
<p>方法决定路径,能力决定落地。二者闭环,支撑企业进化。</p>
|
||||
<div className="placeholder" style={{ marginTop: 12 }}>
|
||||
【占位|待业务确认】方法论体系、工具、交付标准待知识母盘灌入。
|
||||
</div>
|
||||
<h1>{texts['methods.title'] || '方法与能力'}</h1>
|
||||
<p>{texts['methods.header_description'] || '方法决定路径,能力决定落地。二者闭环,支撑企业进化。'}</p>
|
||||
</div>
|
||||
</div>
|
||||
<section className="section">
|
||||
@@ -27,7 +25,7 @@ export default function Methods() {
|
||||
<div className="grid-2">
|
||||
{METHODS.map(m => (
|
||||
<Link key={m.id} to={`/methods/${m.slug}`} className="card" style={{ display: 'block' }}>
|
||||
<p className="eyebrow">{m.group === 'method' ? '方法' : '能力'}</p>
|
||||
<p className="eyebrow">{m.group === 'method' ? (texts['methods.method_label'] || '方法') : (texts['methods.capability_label'] || '能力')}</p>
|
||||
<h3>{m.title}</h3>
|
||||
<p>{m.summary}</p>
|
||||
{m.steps && (
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useState } from 'react'
|
||||
import { useState, useMemo } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import GlobalCTA from '@/components/Layout/GlobalCTA'
|
||||
import { useCMS, useCMSTexts, getCMSSelfCheck } from '@/services/cms'
|
||||
|
||||
type CheckItem = { id: string; question: string; dimension: string }
|
||||
type CheckItem = { id: string; question: string; dimension: string; options?: string[] }
|
||||
|
||||
const CHECK_ITEMS: CheckItem[] = [
|
||||
{ id: 'q1', question: '战略方向在团队中是否清晰一致?', dimension: '战略价值' },
|
||||
@@ -12,6 +13,15 @@ const CHECK_ITEMS: CheckItem[] = [
|
||||
]
|
||||
|
||||
export default function SelfCheck() {
|
||||
const { data: cmsCheck } = useCMS(getCMSSelfCheck, null)
|
||||
const { data: texts } = useCMSTexts()
|
||||
const items = useMemo(() => {
|
||||
try {
|
||||
const parsed = JSON.parse(cmsCheck?.questions || '[]')
|
||||
if (!Array.isArray(parsed) || !parsed.length) return CHECK_ITEMS
|
||||
return parsed.map((item: any, index: number) => ({ id: item.id || `q${index + 1}`, question: item.q || item.question || '', dimension: item.dimension || `价值维度 ${index + 1}`, options: item.options }))
|
||||
} catch { return CHECK_ITEMS }
|
||||
}, [cmsCheck])
|
||||
const [answers, setAnswers] = useState<Record<string, string>>({})
|
||||
const [showResult, setShowResult] = useState(false)
|
||||
|
||||
@@ -29,9 +39,9 @@ export default function SelfCheck() {
|
||||
</div>
|
||||
<h1>看看你的企业</h1>
|
||||
<p>
|
||||
轻量自我对照工具,帮助你快速定位在四大价值 × A/M/B 的大致位置。
|
||||
{cmsCheck?.guide || '轻量自我对照工具,帮助你快速定位在四大价值 × A/M/B 的大致位置。'}
|
||||
<br />
|
||||
<strong style={{ color: '#fde68a' }}>一期禁止长问卷、复杂评分、自动诊断报告。</strong>仅做轻量对照,深度诊断需线下陪跑。
|
||||
<strong style={{ color: '#fde68a' }}>{texts['selfcheck.header_note'] || '仅做轻量对照,深度诊断需线下陪跑。'}</strong>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -39,17 +49,19 @@ export default function SelfCheck() {
|
||||
<section className="section">
|
||||
<div className="container" style={{ maxWidth: 720 }}>
|
||||
<div className="card">
|
||||
<h3>轻量对照(4 题)</h3>
|
||||
<h3>轻量对照({items.length} 题)</h3>
|
||||
<p style={{ fontSize: 13, color: '#64748b' }}>每题选择最贴近现状的选项,结果仅作自我对照参考,不生成诊断报告。</p>
|
||||
<div style={{ marginTop: 16, display: 'grid', gap: 16 }}>
|
||||
{CHECK_ITEMS.map(item => (
|
||||
{items.map(item => (
|
||||
<div key={item.id} style={{ border: '1px solid #e2e8f0', borderRadius: 10, padding: 16 }}>
|
||||
<div style={{ fontSize: 12, color: '#0f6b5b', fontWeight: 800 }}>{item.dimension}</div>
|
||||
<div style={{ fontWeight: 700, marginTop: 4 }}>{item.question}</div>
|
||||
<div style={{ display: 'flex', gap: 8, marginTop: 10, flexWrap: 'wrap' }}>
|
||||
{['A 较清晰/顺畅', 'M 部分卡点', 'B 待构建'].map(opt => (
|
||||
{(item.options || ['A 较清晰/顺畅', 'M 部分卡点', 'B 待构建']).map((opt: any) => {
|
||||
const label = typeof opt === 'string' ? opt : opt.label
|
||||
return (
|
||||
<label
|
||||
key={opt}
|
||||
key={label}
|
||||
style={{
|
||||
border: answers[item.id] === opt ? '1px solid #163E70' : '1px solid #e2e8f0',
|
||||
background: answers[item.id] === opt ? '#eff6ff' : '#fff',
|
||||
@@ -59,10 +71,11 @@ export default function SelfCheck() {
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
<input type="radio" name={item.id} value={opt} checked={answers[item.id] === opt} onChange={() => set(item.id, opt)} style={{ marginRight: 6 }} />
|
||||
{opt}
|
||||
<input type="radio" name={item.id} value={label} checked={answers[item.id] === label} onChange={() => set(item.id, label)} style={{ marginRight: 6 }} />
|
||||
{label}
|
||||
</label>
|
||||
))}
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
@@ -71,21 +84,21 @@ export default function SelfCheck() {
|
||||
<button className="btn btn-primary" style={{ width: '100%', marginTop: 20 }} onClick={() => setShowResult(true)}>
|
||||
查看轻量对照结果
|
||||
</button>
|
||||
<p style={{ fontSize: 11, color: '#94a3b8', marginTop: 8, textAlign: 'center' }}>一期不做自动诊断报告,结果仅本地展示,不存储。</p>
|
||||
<p style={{ fontSize: 11, color: '#94a3b8', marginTop: 8, textAlign: 'center' }}>{texts['selfcheck.storage_note'] || '结果仅本地展示,不存储。'}</p>
|
||||
</div>
|
||||
|
||||
{showResult && (
|
||||
<div className="card" style={{ marginTop: 16, background: '#f8fafc' }}>
|
||||
<h3>对照结果(占位示意)</h3>
|
||||
<h3>{texts['selfcheck.result_title'] || '对照结果'}</h3>
|
||||
<p style={{ fontSize: 13, color: '#475569' }}>
|
||||
基于你的选择,系统提示关注维度:
|
||||
{cmsCheck?.logic_text || '基于你的选择,系统提示关注维度:'}
|
||||
<br />
|
||||
{Object.entries(answers)
|
||||
.map(([k, v]) => `${CHECK_ITEMS.find(i => i.id === k)?.dimension}:${v}`)
|
||||
.map(([k, v]) => `${items.find(i => i.id === k)?.dimension}:${v}`)
|
||||
.join(';') || '(请选择后再查看)'}
|
||||
</p>
|
||||
<div className="placeholder" style={{ marginTop: 10 }}>
|
||||
【占位|一期不做复杂评分】此处仅为轻量对照提示,不生成诊断报告。深度诊断请预约陪跑。
|
||||
{texts['selfcheck.result_note'] || cmsCheck?.next_guide || '此处仅为轻量对照提示,不生成诊断报告。深度诊断请预约陪跑。'}
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: 10, marginTop: 12, flexWrap: 'wrap' }}>
|
||||
<Link to="/contact" className="btn btn-primary">
|
||||
|
||||
@@ -56,9 +56,6 @@ export default function ServiceDetail() {
|
||||
深度定制服务不展示价格,请 <Link to="/contact">咨询/获取方案</Link>
|
||||
</div>
|
||||
)}
|
||||
<div className="placeholder" style={{ marginTop: 12 }}>
|
||||
【占位|待业务确认】交付物、周期、适合对象、服务流程等待灌入。禁止购物车/库存逻辑。
|
||||
</div>
|
||||
<Link to="/contact" className="btn btn-primary" style={{ marginTop: 16, width: '100%' }}>
|
||||
{s.ctaText} →
|
||||
</Link>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Link } from 'react-router-dom'
|
||||
import { SERVICES as FALLBACK_SERVICES } from '@/data/mock'
|
||||
import { useCMS, getCMSServices } from '@/services/cms'
|
||||
import { useCMS, useCMSTexts, getCMSServices } from '@/services/cms'
|
||||
import GlobalCTA from '@/components/Layout/GlobalCTA'
|
||||
|
||||
export default function Services() {
|
||||
const { data: SERVICES } = useCMS(getCMSServices, FALLBACK_SERVICES)
|
||||
const { data: texts } = useCMSTexts()
|
||||
return (
|
||||
<div>
|
||||
<div className="page-header">
|
||||
@@ -13,15 +14,10 @@ export default function Services() {
|
||||
<Link to="/" style={{ color: 'rgba(255,255,255,0.8)' }}>
|
||||
首页
|
||||
</Link>{' '}
|
||||
/ 产品服务
|
||||
</div>
|
||||
<h1>产品服务</h1>
|
||||
<p>
|
||||
禁止电商商城逻辑;重心是“下一步如何行动”,而非货品陈列。标准产品预留价格字段,深度定制展示「咨询/获取方案」。
|
||||
</p>
|
||||
<div className="placeholder" style={{ marginTop: 12 }}>
|
||||
【占位|待业务确认】服务定价、交付清单、周期等需业务确认后灌入。
|
||||
/ {texts['services.title'] || '产品服务'}
|
||||
</div>
|
||||
<h1>{texts['services.title'] || '产品服务'}</h1>
|
||||
<p>{texts['services.header_description'] || '围绕下一步行动展示标准产品与定制陪跑服务。'}</p>
|
||||
</div>
|
||||
</div>
|
||||
<section className="section">
|
||||
@@ -30,7 +26,7 @@ export default function Services() {
|
||||
{SERVICES.map(s => (
|
||||
<div key={s.id} className="card" style={{ display: 'flex', flexDirection: 'column' }}>
|
||||
<div style={{ fontSize: 11, letterSpacing: '0.08em', color: s.serviceType === 'standard' ? '#163E70' : '#0f6b5b', fontWeight: 800 }}>
|
||||
{s.serviceType === 'standard' ? '标准产品' : '深度定制'}
|
||||
{s.serviceType === 'standard' ? (texts['services.standard_label'] || '标准产品') : (texts['services.custom_label'] || '深度定制')}
|
||||
</div>
|
||||
<h3 style={{ marginTop: 6 }}>{s.title}</h3>
|
||||
<p>{s.summary}</p>
|
||||
@@ -47,7 +43,7 @@ export default function Services() {
|
||||
¥{(s.price / 1000).toFixed(2)}k <span style={{ fontSize: 12, fontWeight: 400 }}>{s.priceUnit}</span>
|
||||
</div>
|
||||
) : (
|
||||
<div style={{ fontSize: 13, color: '#0f6b5b', fontWeight: 700 }}>咨询/获取方案(无价格)</div>
|
||||
<div style={{ fontSize: 13, color: '#0f6b5b', fontWeight: 700 }}>{texts['services.custom_cta'] || '咨询/获取方案(无价格)'}</div>
|
||||
)}
|
||||
{s.priceNote && <div style={{ fontSize: 11, color: '#94a3b8' }}>{s.priceNote}</div>}
|
||||
<Link to={`/services/${s.slug}`} className="btn btn-primary" style={{ width: '100%', marginTop: 10 }}>
|
||||
|
||||
Reference in New Issue
Block a user