1/* 2 * Structural templates for content-managed pages. 3 * Keep copy in zh-CN.js and visual decisions in enterprise-theme.css. 4 */ 5(() => { 6 const DIAGRAM_IMAGES_ZH = { 7 'home-ai-consult': { 8 src: 'assets/media/diagrams/home-ai-consult-diagram.1.9.23165519.webp', 9 width: 1232, 10 height: 520, 11 alt: 'æç¥å¨è¯¢ä¸ FDE å ±åæ¶æ' 12 }, 13 'home-ecosystem': { 14 src: 'assets/media/diagrams/home-ecosystem-diagram.1.9.23165519.webp', 15 width: 1232, 16 height: 566, 17 alt: 'é¶ä¸ä¸ç©çæç©éµââååå ±èµ¢ï¼ä»·å¼åå¢' 18 } 19 }; 20 const DIAGRAM_IMAGES_EN = { 21 'home-ai-consult': { 22 src: 'assets/media/diagrams/home-ai-consult-diagram-en.1.9.23165519.webp', 23 width: 1232, 24 height: 560, 25 alt: 'Strategy Advisory and FDE co-creation architecture' 26 }, 27 'home-ecosystem': { 28 src: 'assets/media/diagrams/home-ecosystem-diagram-en.1.9.23165519.webp', 29 width: 1232, 30 height: 610, 31 alt: '01.AI Ecosystem Partnership â Co-develop solutions. Co-create value.' 32 } 33 }; 34 const isEnglishSite = (document.documentElement.lang || '').toLowerCase().startsWith('en'); 35 const defaultDiagramImages = isEnglishSite ? DIAGRAM_IMAGES_EN : DIAGRAM_IMAGES_ZH; 36 37 const mount = document.querySelector('[data-content-page]'); 38 const site = window.OAI_SITE_CONTENT; 39 if (!mount || !site) return; 40 41 const pageKey = mount.dataset.contentPage; 42 const page = site[pageKey]; 43 const shared = site.shared; 44 if (!page) return; 45 document.body.classList.add(`content-page-${pageKey}`); 46 47 const basePath = window.OAI_SITE_BASE_PATH || ''; 48 const asset = (path) => { 49 if (!path) return ''; 50 if (/^(?:https?:|mailto:|tel:|#|\/)/.test(path) || path.startsWith('../')) return path; 51 return `${basePath}${path}`; 52 }; 53 const diagramImage = (id, className = 'diagram-export reveal d1') => { 54 const registry = window.OAI_DIAGRAM_IMAGES || defaultDiagramImages; 55 const item = registry[id]; 56 if (!item) return ''; 57 return `<div class="${className}"><img src="${escape(asset(item.src))}" alt="${escape(item.alt)}" width="${item.width}" height="${item.height}" loading="lazy"></div>`; 58 }; 59 const escape = (value) => String(value).replace(/[&<>"']/g, (character) => ({ 60 '&': '&', 61 '<': '<', 62 '>': '>', 63 '"': '"', 64 "'": ''' 65 }[character])); 66 const multiline = (value) => escape(value).replace(/\n/g, '<br>'); 67 const segments = (items) => items.map((item) => 68 item.accent ? `<em>${escape(item.text)}</em>` : escape(item.text) 69 ).join(''); 70 const heroDescription = (value) => 71 escape(value).replace(/ä¸å·ä½å·¥ç¨/g, '<span class="hero-sub-highlight">ä¸å·ä½å·¥ç¨</span>'); 72 const arrow = window.OAI_ICON ? window.OAI_ICON('oai-arrow-right', 'sm') : '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>'; 73 const arrowLeft = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M19 12H5M12 5l-7 7 7 7"/></svg>'; 74 const icon = (id) => (window.OAI_ICON ? window.OAI_ICON(id, 'lg') : ''); 75 const solutionIcons = ['oai-layout-dashboard', 'oai-landmark', 'oai-handshake']; 76 const valueIcons = ['oai-target', 'oai-boxes', 'oai-rocket', 'oai-refresh-cw']; 77 const external = (item) => item.external ? ' target="_blank" rel="noopener" class="external"' : ''; 78 const button = (item, kind) => 79 `<a href="${escape(item.href)}" class="btn ${kind}${item.external ? ' external' : ''}"${item.external ? ' target="_blank" rel="noopener"' : ''}>${escape(item.label)}${kind !== 'btn-accent' ? arrow : ''}</a>`; 80 const currentYear = () => String(new Date().getFullYear()); 81 const formatCopyright = (value) => 82 escape(String(value).replace(/\{year\}/g, currentYear())); 83 const logoMarkup = () => `<img class="nav-logo-img" src="${escape(asset(shared.logo || 'branding/logo.png'))}" alt="01.AI">`; 84 85 function navigation(active, dark) { 86 const language = shared.language || {}; 87 const languageHref = language[pageKey] || language.default || `en/${pageKey === 'home' ? 'index' : 'enterprise'}.html`; 88 const languageLabel = language.label || 'EN'; 89 const languageAria = language.aria || 'Switch language'; 90 const languageLink = `<a href="${escape(languageHref)}" class="nav-lang" aria-label="${escape(languageAria)}">${escape(languageLabel)}</a>`; 91 const drawerLanguageLink = `<a href="${escape(languageHref)}" class="nav-drawer-lang" aria-label="${escape(languageAria)}">${escape(languageLabel)}</a>`; 92 const linkAttrs = (item) => item.external ? ' target="_blank" rel="noopener"' : ''; 93 const productSeries = (series) => series.clickable === false 94 ? `<span class="product-menu-series is-static" aria-disabled="true"><strong>${escape(series.label)}</strong></span>` 95 : `<a href="${escape(series.href)}
95" class="product-menu-series"${linkAttrs(series)}><strong>${escape(series.label)}</strong></a>`; 96 const drawerSeries = (series) => series.clickable === false 97 ? `<span class="drawer-series is-static" aria-disabled="true">${escape(series.label)}</span>` 98 : `<a href="${escape(series.href)}" class="drawer-series"${linkAttrs(series)}>${escape(series.label)}</a>`; 99 const productMenu = (menu) => menu.map((series) => ` 100 <section class="product-menu-group"> 101 ${productSeries(series)} 102 ${(series.children || []).length ? `<div class="product-menu-children"> 103 ${(series.children || []).map((link) => ` 104 <a href="${escape(link.href)}" class="product-menu-child"${linkAttrs(link)}> 105 <strong>${escape(link.label)}</strong> 106 </a> 107 `).join('')} 108 </div>` : ''} 109 </section> 110 `).join(''); 111 const navigation = shared.nav.map((item) => { 112 const menu = item.menu && shared[item.menu]; 113 if (menu && menu.length) { 114 const isProductMenu = item.menu === 'productMenu'; 115 const dropLinks = isProductMenu 116 ? productMenu(menu) 117 : menu.map((link) => `<a href="${escape(link.href)}"${linkAttrs(link)}>${escape(link.label)}</a>`).join(''); 118 const triggerClass = `${active === item.key ? 'active ' : ''}primary nav-trigger`; 119 const trigger = item.href && item.href !== '#' 120 ? `<a href="${escape(item.href)}" class="${triggerClass}" aria-haspopup="true">${escape(item.label)}</a>` 121 : `<button type="button" class="${triggerClass}" aria-haspopup="true">${escape(item.label)}</button>`; 122 return `<div class="nav-dd${isProductMenu ? ' product-nav-dd' : ''}">${trigger}<div class="nav-dd-panel${isProductMenu ? ' nav-product-panel' : ''}">${dropLinks}</div></div>`; 123 } 124 return `<a href="${escape(item.href)}"${active === item.key ? ' class="active"' : ''}>${escape(item.label)}</a>`; 125 }).join(''); 126 const drawer = shared.nav.map((item) => { 127 if (item.menu === 'productMenu') { 128 const productRoot = item.href && item.href !== '#' 129 ? `<a href="${escape(item.href)}" class="drawer-series">${escape(item.label)}</a>` 130 : ''; 131 return `${productRoot}${shared[item.menu].map((series) => ` 132 ${drawerSeries(series)} 133 ${(series.children || []).map((link) => `<a href="${escape(link.href)}" class="drawer-sub"${linkAttrs(link)}>${escape(link.label)}</a>`).join('')} 134 `).join('')}`; 135 } 136 if (item.menu === 'caseMenu') { 137 const caseSeries = item.href && item.href !== '#' 138 ? `<a href="${escape(item.href)}" class="drawer-series">${escape(item.label)}</a>` 139 : `<a class="drawer-series is-static" aria-disabled="true">${escape(item.label)}</a>`; 140 return `${caseSeries} 141 ${shared[item.menu].map((link) => `<a href="${escape(link.href)}" class="drawer-sub">${escape(link.label)}</a>`).join('')}`; 142 } 143 if (item.menu && shared[item.menu]) { 144 const genericSeries = item.href && item.href !== '#' 145 ? `<a href="${escape(item.href)}" class="drawer-series">${escape(item.label)}</a>` 146 : `<a class="drawer-series is-static" aria-disabled="true">${escape(item.label)}</a>`; 147 return `${genericSeries} 148 ${shared[item.menu].map((link) => `<a href="${escape(link.href)}" class="drawer-sub"${linkAttrs(link)}>${escape(link.label)}</a>`).join('')}`; 149 } 150 return `<a href="${escape(item.href)}">${escape(item.label)}</a>`; 151 }).join(''); 152 return ` 153 <nav class="nav${dark ? ' on-dark' : ''}" id="nav"> 154 <div class="nav-left"><a href="${escape(shared.homeHref || './')}" class="nav-logo">${logoMarkup()}</a></div> 155 <div class="nav-center">${navigation}</div> 156 <div class="nav-right">${languageLink}<a href="${escape(shared.actions.demo.href)}" class="nav-cta"><span class="nav-cta-label" data-mobile-label="${escape(shared.actions.demo.mobileLabel || shared.actions.demo.label)}">${escape(shared.actions.demo.label)}</span></a><button class="nav-ham" id="ham" aria-label="${escape(shared.menuLabel || 'èå')}"><span></span><span></span><span></span></button></div> 157 </nav> 158 <div class="nav-drawer" id="drawer">${drawer}<div class="nav-drawer-foot">${drawerLanguageLink}${button(shared.actions.demo, 'btn-primary')}</div></div>`; 159 } 160 161 function announcement(content) { 162 if (!content.notice) return ''; 163 return `<div class="home-announcement"><span>${escape(content.notice.label)}</span>
163<p>${escape(content.notice.text)}</p></div>`; 164 } 165 166 function footer() { 167 const columns = shared.footerColumns.map((column) => ` 168 <div class="ft-col"><h5>${escape(column.label)}</h5><ul>${column.links.map((link) => 169 `<li><a href="${escape(link.href)}"${link.businessPartnership ? ' data-business-partnership' : link.topic ? ` data-quick="${escape(link.topic)}"` : ''}${external(link)}>${escape(link.label)}</a></li>` 170 ).join('')}</ul></div>`).join(''); 171 const registrations = shared.registrations.map((item) => { 172 if (typeof item === 'string') return `<span>${escape(item)}</span>`; 173 const icon = item.icon ? `<img class="ft-legal-icon" src="${escape(item.icon)}" alt="" loading="lazy">` : ''; 174 return `<a href="${escape(item.href)}" target="_blank" rel="noopener">${icon}${escape(item.label)}</a>`; 175 }).join('<span>|</span>'); 176 return ` 177 <footer class="ft ft-compact"><div class="ft-inner"><div class="ft-grid"> 178 <div class="ft-brand"><div class="nav-logo">${logoMarkup()}</div><p>${escape(shared.footerStatement)}</p></div> 179 ${columns} 180 </div><div class="ft-bottom"><div class="ft-legal"><span>${formatCopyright(shared.copyright)}</span>${registrations ? `<span>|</span>${registrations}` : ''}</div><div class="mono t-small text-on-dark-dim">${escape(shared.location)}</div></div></div></footer>`; 181 } 182 183 function hero(content, secondaryAction) { 184 const secondaryButton = secondaryAction ? button(secondaryAction, 'btn-ghost') : ''; 185 const note = content.hero.ctaNote ? `<p class="hero-contact-note">${escape(content.hero.ctaNote)}</p>` : ''; 186 const variant = content.page === 'home' ? ' home-hero' : ''; 187 const slides = content.hero.slides || []; 188 const media = slides.length 189 ? `<div class="hero-backdrops" aria-hidden="true">${slides.map((slide, index) => 190 `<div class="hero-backdrop${index === 0 ? ' is-active' : ''}" data-hero-backdrop="${index}"><img src="${escape(asset(slide.media))}" alt=""></div>` 191 ).join('')}<div class="hero-media-shade"></div></div>` 192 : content.hero.media ? `<div class="hero-media" aria-hidden="true"><img src="${escape(asset(content.hero.media))}" alt=""><div class="hero-media-shade"></div></div>` : ''; 193 const selector = slides.length && content.page !== 'home' ? `<div class="industry-selector" aria-label="${escape(shared.industryAria || 'è¦çè¡ä¸åºæ¯')}"> 194 <div class="industry-selector-label">${escape(shared.industryLabel || 'è¦çè¡ä¸')}</div> 195 <div class="industry-tabs" role="tablist">${slides.map((slide, index) => 196 `<button class="industry-tab${index === 0 ? ' is-active' : ''}" type="button" role="tab" aria-selected="${index === 0}" tabindex="${index === 0 ? '0' : '-1'}" data-hero-slide="${index}">${escape(slide.label)}</button>` 197 ).join('')}</div> 198 </div>` : ''; 199 const metrics = ''; 200 const summary = content.page === 'home' 201 ? `<div class="hero-summary"><p class="hero-sub">${heroDescription(content.hero.description)}</p><div class="hero-actions">${button(shared.actions.demo, 'btn-accent')}${secondaryButton}</div>${note}</div>${selector}` 202 : `<p class="hero-sub">${escape(content.hero.description)}</p><div class="hero-actions">${button(shared.actions.demo, 'btn-accent')}${secondaryButton}</div>${note}`; 203 const eyebrow = content.page === 'home' ? '' : `<div class="eyebrow on-dark">${escape(content.eyebrow)}</div>`; 204 const scrollCue = content.page === 'home' 205 ? `<a href="#home-products" class="hero-scroll-cue" aria-label="${escape(shared.scrollCueAria || 'å䏿µè§æ´å¤å 容')}"><i aria-hidden="true"></i></a>` 206 : ''; 207 return ` 208 <section class="hero${variant} bg-night">${media}<div class="hero-grid"></div><div class="hero-content"> 209 <div class="hero-copy"> 210 ${eyebrow} 211 <h1 class="hero-display">${content.hero.lines.map((line) => `<span class="line">${segments(line)}</span>`).join('')}</h1> 212 ${summary} 213 </div> 214 ${metrics} 215 </div>${scrollCue}</section>`; 216 } 217 218 function sectionHead(content, showEyebrow = true) { 219 const eyebrow = showEyebrow ? `<div class="eyebrow">${escape(content.eyebrow)}</div>` : ''; 220 const description = content.description ? `<p class="sec-head-desc">${escape(content.description)}</p>` : ''; 221 return `<div class="sec-head reveal"><div class="sec-head-title">${eyebrow}<h2>${segments(content.title)}</h2></div>${description}</div>`; 222 } 223 224 function closeSection(content, surface = 'bg-paper') { 225 const note = content.note ? `<p class="final-note">${escape(content.note)}</p>` : ''; 226 return ` 227 <section class="section tight ${surface}"><div class="wrap"><div class="reveal centered max-xl final-cta"> 228 <h2 class="t-h2">${segments(content.title)}</h2> 229 <p class="t-lead mt-5 max-md mx-auto">${escape(content.description)}</p> 230 ${note} 231 <div class="flex gap-3 justify-center fwrap mt-7">${button(shared.actions.demo, 'btn-primary')}</div> 232 </div></div></section>`; 233 } 234 235 function aiConsultSubcard(item) { 236 return `<div class="home-ai-consult-subcard"> 237 <h4>${escape(item.title)}</h4> 238 <p>${escape(item.text)}</p> 239 </div>`; 240 } 241 242 function aiConsultPanel(panel) { 243 return `<article class="home-ai-consult-panel"> 244 <div class="home-ai-consult-panel-head">
245 <span class="home-ai-consult-badge oai-icon-box" aria-hidden="true">${window.OAI_ICON ? window.OAI_ICON(panel.icon, 'sm') : icon(panel.icon)}</span> 246 <div> 247 <h3>${escape(panel.title)}</h3> 248 <p class="home-ai-consult-panel-tag">${escape(panel.tagline)}</p> 249 </div> 250 </div> 251 <p class="home-ai-consult-panel-lead">${escape(panel.text)}</p> 252 <div class="home-ai-consult-subcards">${panel.items.map(aiConsultSubcard).join('')}</div> 253 </article>`; 254 } 255 256 function renderAiConsultDiagramMarkup(data) { 257 const diagram = data.diagram; 258 return ` 259 <div class="home-ai-consult-shell reveal d1"> 260 <header class="home-ai-consult-head"> 261 <div class="home-ai-consult-headline"> 262 <h2> 263 <span class="home-ai-consult-title-accent">${segments(data.title)}</span> 264 <span class="home-ai-consult-title-sub">${escape(data.subtitle)}</span> 265 </h2> 266 </div> 267 <p class="home-ai-consult-intro">${escape(data.intro)}</p> 268 </header> 269 <div class="home-ai-consult-canvas" aria-label="${escape(data.ariaLabel || 'æç¥å¨è¯¢ä¸ FDE å ±åæ¶æ')}"> 270 <svg class="home-ai-consult-connectors" viewBox="0 0 1200 500" preserveAspectRatio="none" aria-hidden="true"> 271 <defs> 272 <linearGradient id="home-consult-flow-in" x1="0" y1="0" x2="1" y2="0"><stop offset="0" stop-color="#315f49" stop-opacity=".28"/><stop offset=".72" stop-color="#8fe85d" stop-opacity=".82"/><stop offset="1" stop-color="#c8f64a"/></linearGradient> 273 <linearGradient id="home-consult-flow-out" x1="0" y1="0" x2="1" y2="0"><stop offset="0" stop-color="#c8f64a"/><stop offset="1" stop-color="#5fbd62" stop-opacity=".4"/></linearGradient> 274 <linearGradient id="home-consult-flow-mid-in" gradientUnits="userSpaceOnUse" x1="286" y1="250" x2="470" y2="250"><stop offset="0" stop-color="#8fbd61" stop-opacity=".95"/><stop offset=".72" stop-color="#a8e95d"/><stop offset="1" stop-color="#c8f64a"/></linearGradient> 275 <linearGradient id="home-consult-flow-mid-out" gradientUnits="userSpaceOnUse" x1="730" y1="250" x2="914" y2="250"><stop offset="0" stop-color="#c8f64a"/><stop offset="1" stop-color="#8fbd61" stop-opacity=".95"/></linearGradient> 276 <filter id="home-consult-flow-glow" x="-30%" y="-30%" width="160%" height="160%"><feGaussianBlur stdDeviation="5" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter> 277 </defs> 278 <g class="flow-lines" fill="none" stroke="url(#home-consult-flow-in)" stroke-width="10" stroke-linecap="round" filter="url(#home-consult-flow-glow)"> 279 <path class="flow-mid" d="M286 250 H470" stroke="url(#home-consult-flow-mid-in)"/> 280 </g> 281 <g class="flow-lines" fill="none" stroke="url(#home-consult-flow-out)" stroke-width="10" stroke-linecap="round" filter="url(#home-consult-flow-glow)"> 282 <path class="flow-mid" d="M730 250 H914" stroke="url(#home-consult-flow-mid-out)"/> 283 </g> 284 </svg> 285 ${aiConsultPanel(diagram.left)} 286 <div class="home-ai-consult-center"> 287 <span class="home-ai-consult-pill">${escape(diagram.center.pill)}</span> 288 <div class="home-ai-consult-ring"> 289 ${diagram.center.core.map((line) => `<span>${escape(line)}</span>`).join('')} 290 </div> 291 <p class="home-ai-consult-center-note">${escape(diagram.center.note)}</p> 292 </div> 293 ${aiConsultPanel(diagram.right)} 294 </div> 295 <footer class="home-ai-consult-foot"> 296 <p>${escape(data.footer)}</p> 297 ${button(shared.actions.demo, 'btn-accent')} 298 </footer> 299 </div>`; 300 } 301 302 function renderAiConsultDiagram(data) { 303 if (window.OAI_USE_DIAGRAM_IMAGES === false) { 304 return renderAiConsultDiagramMarkup(data); 305 } 306 return ` 307 <div class="home-ai-consult-shell reveal d1"> 308 <header class="home-ai-consult-head"> 309 <div class="home-ai-consult-headline"> 310 <h2>
311 <span class="home-ai-consult-title-accent">${segments(data.title)}</span> 312 <span class="home-ai-consult-title-sub">${escape(data.subtitle)}</span> 313 </h2> 314 </div> 315 <p class="home-ai-consult-intro">${escape(data.intro)}</p> 316 </header> 317 ${diagramImage('home-ai-consult')} 318 <footer class="home-ai-consult-foot"> 319 <p>${escape(data.footer)}</p> 320 ${button(shared.actions.demo, 'btn-accent')} 321 </footer> 322 </div>`; 323 } 324 325 function renderEcosystemSectionMarkup(data) { 326 const partnerCard = (item) => ` 327 <article class="home-ecosystem-partner home-ecosystem-partner--${escape(item.slot)}"> 328 <span class="home-ecosystem-partner-icon oai-icon-box" aria-hidden="true">${window.OAI_ICON ? window.OAI_ICON(item.icon, 'md') : icon(item.icon)}</span> 329 <h3>${escape(item.title)}</h3> 330 </article>`; 331 const tierRow = (item, index) => ` 332 <div class="home-ecosystem-tier-row home-ecosystem-tier-row--${index + 1}"> 333 <div class="home-ecosystem-tier-bar"> 334 <strong>${escape(item.name)}</strong> 335 <span>${escape(item.threshold)}</span> 336 </div> 337 <div class="home-ecosystem-tier-benefit"> 338 <p>${escape(item.text)}</p> 339 </div> 340 </div>`; 341 return ` 342 <div class="home-ecosystem-map reveal d1"> 343 <section class="home-ecosystem-block" aria-label="${escape(data.partners.label)}"> 344 <div class="home-ecosystem-block-label">${escape(data.partners.label)}</div> 345 <div class="home-ecosystem-partners-body"> 346 ${data.partners.items.map(partnerCard).join('')} 347 <div class="home-ecosystem-hub"> 348 ${(Array.isArray(data.partners.hub) ? data.partners.hub : [data.partners.hub]).map((line) => `<p>${escape(line)}</p>`).join('')} 349 </div> 350 </div> 351 </section> 352 <section class="home-ecosystem-block" aria-label="${escape(data.tiers.label)}"> 353 <div class="home-ecosystem-block-label">${escape(data.tiers.label)}</div> 354 <div class="home-ecosystem-tiers-body"> 355 ${data.tiers.items.map(tierRow).join('')} 356 </div> 357 </section> 358 </div> 359 ${data.cta ? `<div class="home-ecosystem-action reveal d2">${button(data.cta, 'btn-accent')}</div>` : ''}`; 360 } 361 362 /* Preserved markup for export regen â see renderEcosystemSectionMarkup. */ 363 function renderEcosystemSection(data) { 364 if (window.OAI_USE_DIAGRAM_IMAGES === false) { 365 return renderEcosystemSectionMarkup(data); 366 } 367 return ` 368 ${diagramImage('home-ecosystem')} 369 ${data.cta ? `<div class="home-ecosystem-action reveal d2">${button(data.cta, 'btn-accent')}</div>` : ''}`; 370 } 371 372 function renderHome() { 373 const solutions = page.solutions.items.map((item, index) => ` 374 <article class="solution-card"> 375 <span class="oai-icon-box oai-icon-box--home">${icon(solutionIcons[index])}</span> 376 <h3>${escape(item.title)}</h3> 377 <p>${escape(item.text)}</p> 378 <ul class="split-list">${item.points.map((point) => `<li>${escape(point)}</li>`).join('')}</ul> 379 <a href="${escape(item.href)}" class="solution-link">${escape(shared.productLearnMore || 'äºè§£äº§å')} ${arrow}</a> 380 </article>`).join(''); 381 const customers = ` 382 <div class="home-solution-tabs reveal d1" data-home-solution-tabs> 383 <div class="home-solution-selector industry-selector" aria-label="${escape(shared.solutionAria || 'åºæ¯æ¹æ¡åç±»')}"> 384 <div class="home-solution-tablist industry-tabs" role="tablist"> 385 ${page.customers.items.map((item, index) => ` 386 <button class="home-solution-tab industry-tab${index === 0 ? ' is-active' : ''}" type="button" role="tab" id="home-solution-tab-${index}" aria-selected="${index === 0 ? 'true' : 'false'}" aria-controls="home-solution-panel-${index}" tabindex="${index === 0 ? '0' : '-1'}" data-home-solution-tab="${index}">${escape(item.label)}</button> 387 `).join('')} 388 </div> 389 </div> 390 <div class="home-solution-panels"> 391 ${page.customers.items.map((item, index) => ` 392 <article class="home-solution-panel${index === 0 ? ' is-active' : ''}" role="tabpanel" id="home-solution-panel-${index}" aria-labelledby="home-solution-tab-${index}" ${index === 0 ? '' : 'hidden'} data-home-solution-panel="${index}"> 393 <div class="home-solution-copy"> 394 <p class="home-solution-scenario">${escape(item.label)}</p> 395 <h3>${escape(item.text)}</h3> 396 <a href="${escape(item.href)}" class="home-solution-link">${escape(shared.learnMore || 'äºè§£æ¹æ¡')} ${arrow}</a> 397 </div> 398 <figure class="home-solution-media"> 399 <img src="${escape(asset(item.media))}" alt="${escape(item.label)}${escape(shared.solutionAltSuffix || 'åºæ¯æ¹æ¡')}"> 400 </figure> 401 </article> 402 `).join('')} 403 </div> 404 </div>`; 405 const valueItems = page.value.items.map((item, index) => ` 406 <article class="ai-value-card">
407 <span class="oai-icon-box oai-icon-box--home">${icon(valueIcons[index])}</span> 408 <h3>${escape(item.title)}</h3> 409 <p>${escape(item.text)}</p> 410 </article>`).join(''); 411 const newsCards = (page.news.items || []).slice(0, 3).map((item) => ` 412 <a href="${escape(item.href)}" class="home-news-card"${item.external ? ' target="_blank" rel="noopener"' : ''}> 413 <figure class="home-news-thumb"> 414 <img src="${escape(asset(item.media))}" alt=""> 415 </figure> 416 <div class="home-news-body"> 417 <h3>${escape(item.title)}</h3> 418 <p>${escape(item.date)} â</p> 419 </div> 420 </a>`).join(''); 421 const aiConsultingDiagram = renderAiConsultDiagram(page.aiConsulting); 422 const aboutMilestones = page.aboutHome.milestones.map((item) => ` 423 <article class="home-about-milestone"> 424 <time>${escape(item.date)}</time> 425 <div> 426 <h3>${escape(item.title)}</h3> 427 <p>${escape(item.text)}</p> 428 </div> 429 </article>`).join(''); 430 return ` 431 ${navigation('home', true)} 432 ${hero(page)} 433 <section class="section bg-paper home-customers" id="home-products"><div class="wrap">${sectionHead(page.solutions, false)} 434 <div class="solution-grid reveal d1">${solutions}</div> 435 </div></section> 436 <section class="section bg-night home-ai-consulting" id="home-ai-consulting"><div class="wrap">${aiConsultingDiagram}</div></section> 437 <section class="section snug bg-paper home-solutions" id="home-industry-solutions"><div class="wrap">${sectionHead(page.customers, false)} 438 ${customers} 439 </div></section> 440 <section class="section bg-night home-ai-value" id="one-project"><div class="wrap">${sectionHead(page.value, false)} 441 <div class="ai-value-grid reveal d1">${valueItems}</div> 442 <div class="home-ai-value-action reveal d2"><a href="${escape(page.value.more.href)}" class="home-ai-value-more">${escape(page.value.more.label)} ${arrow}</a></div> 443 </div></section> 444 <section class="section bg-night home-news"><div class="wrap">${sectionHead(page.news, false)} 445 <div class="home-news-grid reveal d1">${newsCards}</div> 446 <div class="home-news-action reveal d2"><a href="${escape(page.news.more.href)}" class="home-news-more">${escape(page.news.more.label)} ${arrow}</a></div> 447 </div></section> 448 <section class="section tight bg-paper home-about"><div class="wrap">${sectionHead(page.aboutHome, false)} 449 <div class="home-about-layout reveal d1"> 450 <div class="home-about-intro"> 451 ${page.aboutHome.intro.map((text) => `<p>${escape(text)}</p>`).join('')} 452 <a href="${escape(page.aboutHome.more.href)}" class="home-about-more">${escape(page.aboutHome.more.label)} ${arrow}</a> 453 </div> 454 <div class="home-about-milestones">${aboutMilestones}</div> 455 </div> 456 </div></section> 457 ${footer()}`; 458 } 459 460 function renderEnterprise() { 461 const productVisual = (item) => ` 462 <div class="product-visual product-visual-${escape(item.visual || item.id)} reveal d1" aria-label="${escape(item.name)} ${escape(shared.visualPlaceholder || '产åè§è§å ä½')}"> 463 <div class="product-visual-top"> 464 <span>${escape(item.name)}</span> 465 <span>${escape(item.tagline)}</span> 466 </div> 467 <div class="product-orbit" aria-hidden="true"> 468 <span class="orb orb-a"></span> 469 <span class="orb orb-b"></span> 470 <span class="orb orb-c"></span> 471 <span class="orb-center"></span> 472 <span class="orbit-line line-a"></span> 473 <span class="orbit-line line-b"></span> 474 <span class="orbit-line line-c"></span> 475 </div> 476 <div class="product-visual-bottom"> 477 <span>INPUT</span> 478 <span>ANALYZE</span> 479 <span>ACT</span> 480 </div> 481 </div>`; 482 const products = page.products.map((item) => ` 483 <section class="section ${item.theme === 'night' ? 'bg-night' : 'bg-paper'} enterprise-product enterprise-product-${escape(item.id)}" id="${escape(item.id)}"> 484 <div class="wrap"> 485 <div class="product-layout"> 486 <div class="product-copy reveal"> 487 <div class="eyebrow">${escape(item.eyebrow)}</div> 488 <h2>${segments(item.title)}</h2> 489 <p class="product-tagline">${escape(item.tagline)}</p> 490 <p class="product-lead">${escape(item.description)}</p> 491 <a href="${escape(item.ctaHref)}" class="btn ${item.theme === 'night' ? 'btn-primary' : 'btn-accent'}">${escape(item.cta)}</a> 492 </div> 493 ${productVisual(item)} 494 </div> 495 </div> 496 </section>`).join(''); 497 const stages = page.delivery.stages.map((item) => ` 498 <div class="delivery-step"> 499 <div class="delivery-code">${escape(item.code)}</div> 500 <h3>${escape(item.title)}</h3> 501 <p>${escape(item.text)}</p> 502 </div>`).join(''); 503 return ` 504 ${navigation('enterprise', true)} 505 ${hero(page)} 506 ${products} 507 <section class="section bg-night enterprise-delivery"><div class="wrap">${sectionHead(page.delivery)}<div class="delivery-grid reveal d1">${stages}</div></div></section> 508 ${closeSection(page.close, 'bg-night')} 509 ${footer()}`; 510 } 511 512 if (pageKey === 'home') {
513 // Skip client re-render when the markup was already baked at build time 514 // (scripts/prerender.js sets data-prerendered). Interactive enhancements 515 // below still run against the prerendered DOM. 516 if (!mount.dataset.prerendered) mount.innerHTML = renderHome(); 517 window.OAIEnhanceDiagramExports?.(); 518 if (window.location.hash) { 519 window.requestAnimationFrame(() => { 520 const target = document.querySelector(window.location.hash); 521 if (target) target.scrollIntoView(); 522 }); 523 } 524 } 525})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.