Add industry solution pages
This commit is contained in:
BIN
public/solutions/agent-operations-final.png
Normal file
BIN
public/solutions/agent-operations-final.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
BIN
public/solutions/investment-research-final.png
Normal file
BIN
public/solutions/investment-research-final.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 MiB |
BIN
public/solutions/media-distribution-final.png
Normal file
BIN
public/solutions/media-distribution-final.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
52
src/app/(site)/solutions/[slug]/page.tsx
Normal file
52
src/app/(site)/solutions/[slug]/page.tsx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import type { Metadata } from "next";
|
||||||
|
import { notFound } from "next/navigation";
|
||||||
|
import { SubpageShell } from "@/components/subpage-shell";
|
||||||
|
import { SolutionDetail } from "@/components/solution-detail";
|
||||||
|
import {
|
||||||
|
getSolutionBySlug,
|
||||||
|
getSolutionSlugs,
|
||||||
|
} from "@/content/solutions";
|
||||||
|
import { pageMetadata } from "@/lib/site-metadata";
|
||||||
|
|
||||||
|
type SolutionRouteProps = {
|
||||||
|
params: Promise<{
|
||||||
|
slug: string;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function generateStaticParams() {
|
||||||
|
return getSolutionSlugs().map((slug) => ({ slug }));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function generateMetadata({
|
||||||
|
params,
|
||||||
|
}: SolutionRouteProps): Promise<Metadata> {
|
||||||
|
const { slug } = await params;
|
||||||
|
const solution = getSolutionBySlug(slug);
|
||||||
|
|
||||||
|
if (!solution) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return pageMetadata({
|
||||||
|
title: solution.title,
|
||||||
|
description: solution.lead,
|
||||||
|
path: solution.href,
|
||||||
|
keywords: [solution.title, "AI Agent", "行业解决方案", "海宇数科"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function SolutionPage({ params }: SolutionRouteProps) {
|
||||||
|
const { slug } = await params;
|
||||||
|
const solution = getSolutionBySlug(slug);
|
||||||
|
|
||||||
|
if (!solution) {
|
||||||
|
notFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SubpageShell>
|
||||||
|
<SolutionDetail solution={solution} />
|
||||||
|
</SubpageShell>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,22 +2,24 @@ import type { Metadata } from "next";
|
|||||||
import { SubpageShell } from "@/components/subpage-shell";
|
import { SubpageShell } from "@/components/subpage-shell";
|
||||||
import { PageHero } from "@/components/page-hero";
|
import { PageHero } from "@/components/page-hero";
|
||||||
import { SectionEnterprise } from "@/components/section-enterprise";
|
import { SectionEnterprise } from "@/components/section-enterprise";
|
||||||
import { site } from "@/content/site";
|
import { solutionOverview } from "@/content/solutions";
|
||||||
import { pageMetadata } from "@/lib/site-metadata";
|
import { pageMetadata } from "@/lib/site-metadata";
|
||||||
|
|
||||||
const s = site.enterprise;
|
|
||||||
|
|
||||||
export const metadata: Metadata = pageMetadata({
|
export const metadata: Metadata = pageMetadata({
|
||||||
title: s.title,
|
title: solutionOverview.title,
|
||||||
description: s.lead,
|
description: solutionOverview.lead,
|
||||||
path: "/solutions",
|
path: "/solutions",
|
||||||
keywords: ["企业数字化", "解决方案", "大模型", "海宇数科"],
|
keywords: ["企业方案", "行业解决方案", "AI Agent", "海宇数科"],
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function SolutionsPage() {
|
export default function SolutionsPage() {
|
||||||
return (
|
return (
|
||||||
<SubpageShell>
|
<SubpageShell>
|
||||||
<PageHero eyebrow={s.eyebrow} title={s.title} lead={s.lead} />
|
<PageHero
|
||||||
|
eyebrow={solutionOverview.eyebrow}
|
||||||
|
title={solutionOverview.title}
|
||||||
|
lead={solutionOverview.lead}
|
||||||
|
/>
|
||||||
<SectionEnterprise />
|
<SectionEnterprise />
|
||||||
</SubpageShell>
|
</SubpageShell>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { MetadataRoute } from "next";
|
import type { MetadataRoute } from "next";
|
||||||
import { getAllNewsSlugs, getNewsBySlug } from "@/content/news-articles";
|
import { getAllNewsSlugs, getNewsBySlug } from "@/content/news-articles";
|
||||||
|
import { getSolutionSlugs } from "@/content/solutions";
|
||||||
import { canonicalAbsoluteUrl } from "@/lib/site-url";
|
import { canonicalAbsoluteUrl } from "@/lib/site-url";
|
||||||
|
|
||||||
export default function sitemap(): MetadataRoute.Sitemap {
|
export default function sitemap(): MetadataRoute.Sitemap {
|
||||||
@@ -24,6 +25,13 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
|||||||
priority: path === "/" ? 1 : 0.9,
|
priority: path === "/" ? 1 : 0.9,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const solutionEntries: MetadataRoute.Sitemap = getSolutionSlugs().map((slug) => ({
|
||||||
|
url: canonicalAbsoluteUrl(`/solutions/${slug}`),
|
||||||
|
lastModified: now,
|
||||||
|
changeFrequency: "weekly" as const,
|
||||||
|
priority: 0.85,
|
||||||
|
}));
|
||||||
|
|
||||||
const newsEntries: MetadataRoute.Sitemap = getAllNewsSlugs().map((slug) => {
|
const newsEntries: MetadataRoute.Sitemap = getAllNewsSlugs().map((slug) => {
|
||||||
const article = getNewsBySlug(slug);
|
const article = getNewsBySlug(slug);
|
||||||
const lastModified = article?.date
|
const lastModified = article?.date
|
||||||
@@ -37,5 +45,5 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
return [...staticEntries, ...newsEntries];
|
return [...staticEntries, ...solutionEntries, ...newsEntries];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,22 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { motion, useReducedMotion } from "motion/react";
|
import { motion, useReducedMotion } from "motion/react";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
const easeOut = [0.22, 1, 0.36, 1] as const;
|
const easeOut = [0.22, 1, 0.36, 1] as const;
|
||||||
|
|
||||||
|
function useCanAnimate() {
|
||||||
|
const reduceMotion = useReducedMotion();
|
||||||
|
const [mounted, setMounted] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setMounted(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return mounted && !reduceMotion;
|
||||||
|
}
|
||||||
|
|
||||||
type ScrollRevealProps = {
|
type ScrollRevealProps = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
@@ -18,9 +30,9 @@ export function ScrollReveal({
|
|||||||
className,
|
className,
|
||||||
delay = 0,
|
delay = 0,
|
||||||
}: ScrollRevealProps) {
|
}: ScrollRevealProps) {
|
||||||
const reduceMotion = useReducedMotion();
|
const canAnimate = useCanAnimate();
|
||||||
|
|
||||||
if (reduceMotion) {
|
if (!canAnimate) {
|
||||||
return <div className={className}>{children}</div>;
|
return <div className={className}>{children}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,9 +56,9 @@ type ScrollRevealHeroProps = {
|
|||||||
|
|
||||||
/** 首屏进入页面时播放一次 */
|
/** 首屏进入页面时播放一次 */
|
||||||
export function ScrollRevealHero({ children, className }: ScrollRevealHeroProps) {
|
export function ScrollRevealHero({ children, className }: ScrollRevealHeroProps) {
|
||||||
const reduceMotion = useReducedMotion();
|
const canAnimate = useCanAnimate();
|
||||||
|
|
||||||
if (reduceMotion) {
|
if (!canAnimate) {
|
||||||
return <div className={className}>{children}</div>;
|
return <div className={className}>{children}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,9 +86,9 @@ export function ScrollRevealItem({
|
|||||||
className,
|
className,
|
||||||
index = 0,
|
index = 0,
|
||||||
}: ScrollRevealItemProps) {
|
}: ScrollRevealItemProps) {
|
||||||
const reduceMotion = useReducedMotion();
|
const canAnimate = useCanAnimate();
|
||||||
|
|
||||||
if (reduceMotion) {
|
if (!canAnimate) {
|
||||||
return <div className={className}>{children}</div>;
|
return <div className={className}>{children}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,46 @@
|
|||||||
import { site } from "@/content/site";
|
import Image from "next/image";
|
||||||
|
import Link from "next/link";
|
||||||
import { SectionIntro } from "@/components/section-intro";
|
import { SectionIntro } from "@/components/section-intro";
|
||||||
|
import { solutionCards, solutionOverview } from "@/content/solutions";
|
||||||
|
|
||||||
export function SectionEnterprise() {
|
export function SectionEnterprise() {
|
||||||
const s = site.enterprise;
|
|
||||||
return (
|
return (
|
||||||
<section className="band-light band-section" id="solutions">
|
<section className="band-light band-section" id="solutions">
|
||||||
<div className="container-site section-stack">
|
<div className="container-site section-stack">
|
||||||
<SectionIntro eyebrow={s.eyebrow} title={s.title} lead={s.lead} />
|
<SectionIntro
|
||||||
|
eyebrow={solutionOverview.eyebrow}
|
||||||
|
title={solutionOverview.title}
|
||||||
|
lead={solutionOverview.lead}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="grid gap-5 sm:grid-cols-2 lg:grid-cols-3">
|
<div className="solution-card-grid">
|
||||||
{s.solutions.map((item) => (
|
{solutionCards.map((item) => (
|
||||||
<article key={item.title} className="card-on-light flex flex-col gap-4">
|
<article key={item.id} className="solution-card card-on-light">
|
||||||
<h3 className="type-display-md text-balance text-ink">{item.title}</h3>
|
<Link href={item.href} className="solution-card__media">
|
||||||
<p className="type-body-md text-body">{item.body}</p>
|
<Image
|
||||||
|
src={item.image}
|
||||||
|
alt={item.imageAlt}
|
||||||
|
fill
|
||||||
|
loading={item.id === "digital-enterprise" ? "eager" : "lazy"}
|
||||||
|
sizes="(min-width: 1024px) 25vw, (min-width: 640px) 50vw, 100vw"
|
||||||
|
className="solution-card__image"
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
<div className="solution-card__body">
|
||||||
|
<p className="type-caption-strong text-accent">{item.eyebrow}</p>
|
||||||
|
<h3 className="solution-card__title type-display-md text-balance text-ink">
|
||||||
|
<Link href={item.href}>{item.title}</Link>
|
||||||
|
</h3>
|
||||||
|
<p className="solution-card__lead type-body-md text-body">{item.lead}</p>
|
||||||
|
<ul className="solution-card__tags" aria-label={`${item.title}能力标签`}>
|
||||||
|
{item.tags.map((tag) => (
|
||||||
|
<li key={tag}>{tag}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<Link href={item.href} className="solution-card__link">
|
||||||
|
查看方案
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
</article>
|
</article>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -73,16 +73,41 @@ export function SiteHeader() {
|
|||||||
aria-label="主导航"
|
aria-label="主导航"
|
||||||
>
|
>
|
||||||
<ul className="nav-island-menu__list">
|
<ul className="nav-island-menu__list">
|
||||||
{site.nav.map((item) => (
|
{site.nav.map((item) => {
|
||||||
<li key={item.href}>
|
const children = "children" in item ? item.children : undefined;
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
key={item.href}
|
||||||
|
className={
|
||||||
|
children
|
||||||
|
? "nav-island-menu__item nav-island-menu__item--has-menu"
|
||||||
|
: "nav-island-menu__item"
|
||||||
|
}
|
||||||
|
>
|
||||||
<Link
|
<Link
|
||||||
href={resolveSiteHref(item.href)}
|
href={resolveSiteHref(item.href)}
|
||||||
className="nav-island-menu__link"
|
className="nav-island-menu__link"
|
||||||
|
aria-haspopup={children ? "menu" : undefined}
|
||||||
>
|
>
|
||||||
{item.label}
|
{item.label}
|
||||||
</Link>
|
</Link>
|
||||||
|
{children ? (
|
||||||
|
<div className="nav-dropdown" role="menu">
|
||||||
|
{children.map((child) => (
|
||||||
|
<Link
|
||||||
|
key={child.href}
|
||||||
|
href={resolveSiteHref(child.href)}
|
||||||
|
className="nav-dropdown__link"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
{child.label}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</li>
|
</li>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
@@ -122,7 +147,9 @@ export function SiteHeader() {
|
|||||||
>
|
>
|
||||||
<nav aria-label="移动端主导航">
|
<nav aria-label="移动端主导航">
|
||||||
<ul className="nav-mobile-drawer__list">
|
<ul className="nav-mobile-drawer__list">
|
||||||
{site.nav.map((item) => (
|
{site.nav.map((item) => {
|
||||||
|
const children = "children" in item ? item.children : undefined;
|
||||||
|
return (
|
||||||
<li key={item.href}>
|
<li key={item.href}>
|
||||||
<Link
|
<Link
|
||||||
href={resolveSiteHref(item.href)}
|
href={resolveSiteHref(item.href)}
|
||||||
@@ -131,8 +158,24 @@ export function SiteHeader() {
|
|||||||
>
|
>
|
||||||
{item.label}
|
{item.label}
|
||||||
</Link>
|
</Link>
|
||||||
|
{children ? (
|
||||||
|
<ul className="nav-mobile-drawer__sublist">
|
||||||
|
{children.map((child) => (
|
||||||
|
<li key={child.href}>
|
||||||
|
<Link
|
||||||
|
href={resolveSiteHref(child.href)}
|
||||||
|
className="nav-mobile-drawer__sublink"
|
||||||
|
onClick={() => setMenuOpen(false)}
|
||||||
|
>
|
||||||
|
{child.label}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
) : null}
|
||||||
</li>
|
</li>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
<li className="nav-mobile-drawer__cta-row">
|
<li className="nav-mobile-drawer__cta-row">
|
||||||
<a
|
<a
|
||||||
href="/#contact"
|
href="/#contact"
|
||||||
|
|||||||
131
src/components/solution-detail.tsx
Normal file
131
src/components/solution-detail.tsx
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
import Image from "next/image";
|
||||||
|
import Link from "next/link";
|
||||||
|
import type { SolutionPage } from "@/content/solutions";
|
||||||
|
|
||||||
|
type SolutionDetailProps = {
|
||||||
|
solution: SolutionPage;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function SolutionDetail({ solution }: SolutionDetailProps) {
|
||||||
|
return (
|
||||||
|
<article className="solution-detail-page">
|
||||||
|
<section className="solution-detail-hero band-light band-section">
|
||||||
|
<div className="container-site solution-detail-hero__layout">
|
||||||
|
<div className="solution-detail-hero__copy">
|
||||||
|
<Link
|
||||||
|
href="/solutions"
|
||||||
|
className="page-hero__back type-caption-strong text-body no-underline hover:no-underline w-fit"
|
||||||
|
>
|
||||||
|
← 返回企业方案
|
||||||
|
</Link>
|
||||||
|
<p className="section-eyebrow">{solution.eyebrow}</p>
|
||||||
|
<h1 className="solution-detail-hero__title type-display-xl text-balance text-ink">
|
||||||
|
{solution.title}
|
||||||
|
</h1>
|
||||||
|
<p className="type-lead text-body">{solution.lead}</p>
|
||||||
|
<p className="solution-detail-hero__summary type-body-md text-body">
|
||||||
|
{solution.summary}
|
||||||
|
</p>
|
||||||
|
<div className="solution-detail-hero__actions">
|
||||||
|
<a href="/#contact" className="btn-primary no-underline hover:no-underline">
|
||||||
|
联系我们
|
||||||
|
</a>
|
||||||
|
<Link
|
||||||
|
href="/solutions"
|
||||||
|
className="btn-outline no-underline hover:no-underline"
|
||||||
|
>
|
||||||
|
查看全部方案
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="solution-detail-visual">
|
||||||
|
<div className="solution-detail-visual__image">
|
||||||
|
<Image
|
||||||
|
src={solution.image}
|
||||||
|
alt={solution.imageAlt}
|
||||||
|
fill
|
||||||
|
priority
|
||||||
|
sizes="(min-width: 992px) 48vw, 100vw"
|
||||||
|
className="solution-detail-visual__img"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<dl className="solution-detail-stats">
|
||||||
|
{solution.stats.map((stat) => (
|
||||||
|
<div key={stat.label} className="solution-detail-stat">
|
||||||
|
<dt>{stat.label}</dt>
|
||||||
|
<dd>{stat.value}</dd>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="band-muted band-section">
|
||||||
|
<div className="container-site section-stack">
|
||||||
|
<header className="measure-title flex flex-col gap-4">
|
||||||
|
<p className="type-eyebrow section-eyebrow">Workflow</p>
|
||||||
|
<h2 className="type-display-xl text-ink">从输入到执行的业务闭环</h2>
|
||||||
|
</header>
|
||||||
|
<ol className="solution-workflow">
|
||||||
|
{solution.workflow.map((step, index) => (
|
||||||
|
<li key={step} className="solution-workflow__item">
|
||||||
|
<span className="solution-workflow__no">
|
||||||
|
{String(index + 1).padStart(2, "0")}
|
||||||
|
</span>
|
||||||
|
<span className="solution-workflow__label">{step}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="band-light band-section">
|
||||||
|
<div className="container-site section-stack">
|
||||||
|
<header className="measure-title flex flex-col gap-4">
|
||||||
|
<p className="type-eyebrow section-eyebrow">Capability</p>
|
||||||
|
<h2 className="type-display-xl text-ink">核心能力</h2>
|
||||||
|
</header>
|
||||||
|
<div className="solution-capability-grid">
|
||||||
|
{solution.capabilities.map((item) => (
|
||||||
|
<article key={item.title} className="solution-capability card-on-light">
|
||||||
|
<h3 className="type-display-md text-ink">{item.title}</h3>
|
||||||
|
<p className="type-body-md text-body">{item.body}</p>
|
||||||
|
</article>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="band-muted band-section">
|
||||||
|
<div className="container-site solution-detail-columns">
|
||||||
|
<div className="solution-list-panel">
|
||||||
|
<p className="type-eyebrow section-eyebrow">Scenario</p>
|
||||||
|
<h2 className="type-display-md text-ink">适用场景</h2>
|
||||||
|
<ul>
|
||||||
|
{solution.scenarios.map((item) => (
|
||||||
|
<li key={item}>{item}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="solution-list-panel">
|
||||||
|
<p className="type-eyebrow section-eyebrow">Output</p>
|
||||||
|
<h2 className="type-display-md text-ink">交付保障</h2>
|
||||||
|
<ul>
|
||||||
|
{solution.outputs.map((item) => (
|
||||||
|
<li key={item}>{item}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{solution.note ? (
|
||||||
|
<aside className="solution-note">
|
||||||
|
<p className="type-caption-strong">合规提示</p>
|
||||||
|
<p>{solution.note}</p>
|
||||||
|
</aside>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { solutionNavItems } from "@/content/solutions";
|
||||||
|
|
||||||
export const site = {
|
export const site = {
|
||||||
brand: "海宇数科",
|
brand: "海宇数科",
|
||||||
tagline: "企业级大模型服务与智能报告平台",
|
tagline: "企业级大模型服务与智能报告平台",
|
||||||
@@ -33,7 +35,7 @@ export const site = {
|
|||||||
{ label: "智能报告", href: "/reports" },
|
{ label: "智能报告", href: "/reports" },
|
||||||
{ label: "Agent 技能", href: "/agents" },
|
{ label: "Agent 技能", href: "/agents" },
|
||||||
{ label: "模型能力", href: "/models" },
|
{ label: "模型能力", href: "/models" },
|
||||||
{ label: "企业方案", href: "/solutions" },
|
{ label: "企业方案", href: "/solutions", children: solutionNavItems },
|
||||||
{ label: "AI 资讯", href: "/news" },
|
{ label: "AI 资讯", href: "/news" },
|
||||||
],
|
],
|
||||||
hero: {
|
hero: {
|
||||||
@@ -487,7 +489,10 @@ export const site = {
|
|||||||
{
|
{
|
||||||
title: "方案",
|
title: "方案",
|
||||||
links: [
|
links: [
|
||||||
{ label: "企业数字化", href: "/solutions" },
|
{ label: "企业数字化解决方案", href: "/solutions" },
|
||||||
|
{ label: "新媒体内容分发智能体", href: "/solutions/media-distribution" },
|
||||||
|
{ label: "股市投研情报智能体", href: "/solutions/investment-research" },
|
||||||
|
{ label: "多平台自动运营智能体", href: "/solutions/agent-operations" },
|
||||||
{ label: "控制台", href: "https://console.haiyushuke.com" },
|
{ label: "控制台", href: "https://console.haiyushuke.com" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
226
src/content/solutions.ts
Normal file
226
src/content/solutions.ts
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
export type SolutionNavItem = {
|
||||||
|
label: string;
|
||||||
|
href: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SolutionCard = {
|
||||||
|
id: string;
|
||||||
|
eyebrow: string;
|
||||||
|
title: string;
|
||||||
|
href: string;
|
||||||
|
lead: string;
|
||||||
|
image: string;
|
||||||
|
imageAlt: string;
|
||||||
|
tags: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SolutionPage = SolutionCard & {
|
||||||
|
slug: string;
|
||||||
|
summary: string;
|
||||||
|
stats: Array<{
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
}>;
|
||||||
|
workflow: string[];
|
||||||
|
capabilities: Array<{
|
||||||
|
title: string;
|
||||||
|
body: string;
|
||||||
|
}>;
|
||||||
|
scenarios: string[];
|
||||||
|
outputs: string[];
|
||||||
|
note?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const solutionNavItems: SolutionNavItem[] = [
|
||||||
|
{ label: "企业数字化解决方案", href: "/solutions/digital-enterprise" },
|
||||||
|
{ label: "新媒体内容分发智能体", href: "/solutions/media-distribution" },
|
||||||
|
{ label: "股市投研情报智能体", href: "/solutions/investment-research" },
|
||||||
|
{ label: "多平台自动运营智能体", href: "/solutions/agent-operations" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const solutionOverview = {
|
||||||
|
eyebrow: "企业方案",
|
||||||
|
title: "AI Agent 行业解决方案",
|
||||||
|
lead: "从通用企业数字化底座,到内容分发、投研情报与自动运营,把可重复的信息处理流程封装成可运行、可审计、可接入的业务智能体。",
|
||||||
|
};
|
||||||
|
|
||||||
|
const deliveryOutputs = [
|
||||||
|
"一对一部署 Agent",
|
||||||
|
"对接大模型",
|
||||||
|
"一对一指导",
|
||||||
|
"按需定制",
|
||||||
|
"稳定交付",
|
||||||
|
"24 小时持续运行",
|
||||||
|
];
|
||||||
|
|
||||||
|
const digitalEnterprisePage: SolutionPage = {
|
||||||
|
id: "digital-enterprise",
|
||||||
|
slug: "digital-enterprise",
|
||||||
|
eyebrow: "通用方案",
|
||||||
|
title: "企业数字化解决方案",
|
||||||
|
href: "/solutions/digital-enterprise",
|
||||||
|
lead: "将大模型能力嵌入 ERP、数据中台与协同办公流程,形成可落地的经营分析、合规风控与客户洞察能力。",
|
||||||
|
summary:
|
||||||
|
"面向企业已有系统和业务流程,将智能报告、知识问答、流程自动化和数据洞察能力接入日常经营,让 AI 成为可审计、可协同、可持续运行的企业能力底座。",
|
||||||
|
image: "/banner.png",
|
||||||
|
imageAlt: "企业数字化解决方案示意图",
|
||||||
|
tags: ["经营分析", "合规风控", "客户洞察"],
|
||||||
|
stats: [
|
||||||
|
{ value: "ERP", label: "业务系统接入" },
|
||||||
|
{ value: "BI", label: "经营分析看板" },
|
||||||
|
{ value: "Agent", label: "智能体流程编排" },
|
||||||
|
],
|
||||||
|
workflow: ["需求梳理", "系统接入", "模型编排", "流程上线", "持续优化"],
|
||||||
|
capabilities: [
|
||||||
|
{
|
||||||
|
title: "经营分析中枢",
|
||||||
|
body: "统一指标口径,自动生成经营看板、数据解读和管理层报告,减少人工汇总成本。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "合规与风控助手",
|
||||||
|
body: "支持制度文档问答、合同要点提取、异常条款提示和风险复核流转。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "客户成功洞察",
|
||||||
|
body: "从工单、通话记录和客户反馈中提炼风险信号、续约建议和跟进动作。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "既有系统融合",
|
||||||
|
body: "围绕 ERP、数据中台、知识库和协同办公系统做轻量接入,不替代已有系统。",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
scenarios: ["经营数据分析", "合同与制度核验", "客户续约洞察", "企业知识库问答"],
|
||||||
|
outputs: deliveryOutputs,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const solutionPages: SolutionPage[] = [
|
||||||
|
digitalEnterprisePage,
|
||||||
|
{
|
||||||
|
id: "media-distribution",
|
||||||
|
slug: "media-distribution",
|
||||||
|
eyebrow: "新媒体方案",
|
||||||
|
title: "新媒体内容分发智能体",
|
||||||
|
href: "/solutions/media-distribution",
|
||||||
|
lead: "面向多平台内容运营团队,统一完成选题排期、内容生成、平台适配、账号发布与异常追踪。",
|
||||||
|
summary:
|
||||||
|
"把公众号、知乎、头条、百家号、CSDN、掘金等平台的发布规则和账号流程集中管理,让团队从反复搬运和格式调整中释放出来。",
|
||||||
|
image: "/solutions/media-distribution-final.png",
|
||||||
|
imageAlt: "新媒体内容分发智能体仪表盘示意图",
|
||||||
|
tags: ["内容编排", "多平台分发", "发布追踪"],
|
||||||
|
stats: [
|
||||||
|
{ value: "6+", label: "平台能力矩阵" },
|
||||||
|
{ value: "92%", label: "执行成功率看板" },
|
||||||
|
{ value: "7x24", label: "任务队列巡检" },
|
||||||
|
],
|
||||||
|
workflow: ["排期导入", "AI 生成", "平台适配", "安全发布", "数据回写"],
|
||||||
|
capabilities: [
|
||||||
|
{
|
||||||
|
title: "多平台内容适配",
|
||||||
|
body: "根据不同平台的标题、封面、标签、正文长度与链接规则,自动生成可发布版本。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "账号与会话管理",
|
||||||
|
body: "统一管理多账号身份、登录状态、发布节奏与异常提醒,降低人工切换成本。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "生成预览与人工确认",
|
||||||
|
body: "发布前集中预览标题、封面和正文,关键内容保留人工确认节点。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "发布历史可追踪",
|
||||||
|
body: "沉淀发布记录、失败原因、平台反馈与任务日志,方便团队复盘和审计。",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
scenarios: ["品牌内容矩阵运营", "知识型长文分发", "技术社区同步发布", "活动内容定时推送"],
|
||||||
|
outputs: deliveryOutputs,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "investment-research",
|
||||||
|
slug: "investment-research",
|
||||||
|
eyebrow: "投研方案",
|
||||||
|
title: "股市投研情报智能体",
|
||||||
|
href: "/solutions/investment-research",
|
||||||
|
lead: "面向投研、财经内容与股票社群场景,自动聚合公告、舆情、行情与信号,输出可追溯的机会卡片。",
|
||||||
|
summary:
|
||||||
|
"把公告快讯、社区讨论、行情异动和因子信号接入同一个情报中枢,帮助团队更快发现值得复核的信息线索。",
|
||||||
|
image: "/solutions/investment-research-final.png",
|
||||||
|
imageAlt: "股市投研情报智能体仪表盘示意图",
|
||||||
|
tags: ["公告雷达", "舆情热度", "信号复核"],
|
||||||
|
stats: [
|
||||||
|
{ value: "24h", label: "公告与舆情巡检" },
|
||||||
|
{ value: "S/A/B", label: "线索分层评分" },
|
||||||
|
{ value: "0 荐股", label: "合规定位" },
|
||||||
|
],
|
||||||
|
workflow: ["数据接入", "信息雷达", "因子判断", "机会卡片", "复盘反馈"],
|
||||||
|
capabilities: [
|
||||||
|
{
|
||||||
|
title: "信息雷达层",
|
||||||
|
body: "聚合公告、财经快讯、社区舆情、行情快照与回看因子,形成统一情报入口。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "前置信号评分",
|
||||||
|
body: "按热度、时效、证据来源、利好利空与风险提示,对候选线索进行分层。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "群消息与看板推送",
|
||||||
|
body: "把重要公告、异动线索和复核按钮推送到社群或内部看板,减少人工盯盘压力。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "反馈闭环",
|
||||||
|
body: "沉淀用户反馈、关注股、误报原因与后续表现,用于优化下一轮信号判断。",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
scenarios: ["股票社群信息推送", "财经内容选题发现", "投研线索初筛", "公告与舆情巡检"],
|
||||||
|
outputs: deliveryOutputs,
|
||||||
|
note: "本方案用于信息整理、线索发现与辅助分析,不提供荐股、收益承诺或证券投资建议。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "agent-operations",
|
||||||
|
slug: "agent-operations",
|
||||||
|
eyebrow: "运营方案",
|
||||||
|
title: "多平台自动运营智能体",
|
||||||
|
href: "/solutions/agent-operations",
|
||||||
|
lead: "面向获客、曝光、招聘和私域运营场景,自动识别线索意图、生成回复、沉淀客户并触发人工复核。",
|
||||||
|
summary:
|
||||||
|
"把小红书、抖音、BOSS直聘、微信等平台的重复运营动作串成闭环,让 AI 先完成扫描、判断、回复草稿和客户入库。",
|
||||||
|
image: "/solutions/agent-operations-final.png",
|
||||||
|
imageAlt: "多平台自动运营智能体流程示意图",
|
||||||
|
tags: ["线索发现", "自动回复", "客户沉淀"],
|
||||||
|
stats: [
|
||||||
|
{ value: "4 类", label: "平台运营场景" },
|
||||||
|
{ value: "83%", label: "任务进度追踪" },
|
||||||
|
{ value: "CSV", label: "客户数据导出" },
|
||||||
|
],
|
||||||
|
workflow: ["线索发现", "意图识别", "自动触达", "客户入库", "持续跟进"],
|
||||||
|
capabilities: [
|
||||||
|
{
|
||||||
|
title: "线索发现与意图判断",
|
||||||
|
body: "扫描评论区、私信、候选人沟通和互动线索,判断是否值得进入跟进队列。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "自动回复与触达",
|
||||||
|
body: "结合上下文生成回复草稿,支持自动执行或人工确认后执行。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "客户库沉淀",
|
||||||
|
body: "把平台来源、需求标签、沟通状态与后续动作写入客户库,避免线索流失。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "风控与人工复核",
|
||||||
|
body: "关键动作保留人工审核,支持频率限制、失败恢复、日志追踪与一键导出。",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
scenarios: ["小红书评论找客", "抖音互动曝光", "招聘候选筛选", "微信私域跟进"],
|
||||||
|
outputs: deliveryOutputs,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const solutionCards: SolutionCard[] = solutionPages;
|
||||||
|
|
||||||
|
export function getSolutionBySlug(slug: string) {
|
||||||
|
return solutionPages.find((solution) => solution.slug === slug);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSolutionSlugs() {
|
||||||
|
return solutionPages.map((solution) => solution.slug);
|
||||||
|
}
|
||||||
@@ -332,6 +332,344 @@
|
|||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.solution-card-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--spacing-xl);
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width >= 640px) {
|
||||||
|
.solution-card-grid {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width >= 1180px) {
|
||||||
|
.solution-card-grid {
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-card.card-on-light {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-card__media {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: var(--color-canvas-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-card__image {
|
||||||
|
object-fit: cover;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-card:hover .solution-card__image {
|
||||||
|
transform: scale(1.018);
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-card__body {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-md);
|
||||||
|
padding: var(--spacing-xl);
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-card__title {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-card__title a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-card__title a:hover {
|
||||||
|
color: var(--color-accent-ink);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-card__lead {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-card__tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: var(--spacing-xs);
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-card__tags li {
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
background-color: var(--color-canvas-muted);
|
||||||
|
color: var(--color-accent-soft);
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1;
|
||||||
|
padding: 6px var(--spacing-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-card__link {
|
||||||
|
align-self: flex-start;
|
||||||
|
color: var(--color-accent-ink);
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-card__link:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-page {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-hero__layout {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--spacing-4xl);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width >= 992px) {
|
||||||
|
.solution-detail-hero__layout {
|
||||||
|
grid-template-columns: minmax(0, 0.82fr) minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-hero__copy {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-lg);
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-hero__title {
|
||||||
|
margin: 0;
|
||||||
|
max-width: 14em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-hero__summary {
|
||||||
|
margin: 0;
|
||||||
|
max-width: 40rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-hero__actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: var(--spacing-md);
|
||||||
|
margin-top: var(--spacing-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-visual {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-md);
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-visual__image {
|
||||||
|
position: relative;
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
background-color: var(--color-canvas-muted);
|
||||||
|
box-shadow: var(--shadow-surface-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-visual__img {
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-stats {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--spacing-md);
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width < 640px) {
|
||||||
|
.solution-detail-stats {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-stat {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-xs);
|
||||||
|
padding: var(--spacing-lg);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
background-color: var(--color-canvas);
|
||||||
|
box-shadow: var(--shadow-field);
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-stat dt {
|
||||||
|
color: var(--color-body-light);
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-stat dd {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--color-ink);
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-workflow {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--spacing-md);
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width >= 768px) {
|
||||||
|
.solution-workflow {
|
||||||
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-workflow__item {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-lg);
|
||||||
|
min-height: 120px;
|
||||||
|
padding: var(--spacing-xl);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
background-color: var(--color-canvas);
|
||||||
|
box-shadow: var(--shadow-field);
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-workflow__no {
|
||||||
|
color: var(--color-accent-ink);
|
||||||
|
font-family: var(--font-mono-caps);
|
||||||
|
font-size: 12px;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-workflow__label {
|
||||||
|
color: var(--color-ink);
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.35;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-capability-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--spacing-xl);
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width >= 768px) {
|
||||||
|
.solution-capability-grid {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-capability {
|
||||||
|
min-height: 172px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-capability h3,
|
||||||
|
.solution-capability p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-columns {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--spacing-xl);
|
||||||
|
align-items: stretch;
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width >= 900px) {
|
||||||
|
.solution-detail-columns {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-detail-columns:has(.solution-note) {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-list-panel,
|
||||||
|
.solution-note {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-md);
|
||||||
|
padding: var(--spacing-2xl);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
background-color: var(--color-canvas);
|
||||||
|
box-shadow: var(--shadow-surface);
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-list-panel h2,
|
||||||
|
.solution-note p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-list-panel ul {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-sm);
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-list-panel li {
|
||||||
|
position: relative;
|
||||||
|
padding-left: var(--spacing-lg);
|
||||||
|
color: var(--color-body);
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-list-panel li::before {
|
||||||
|
position: absolute;
|
||||||
|
top: 0.62em;
|
||||||
|
left: 0;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: var(--radius-full);
|
||||||
|
background-color: var(--color-accent-ink);
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-note {
|
||||||
|
background-color: var(--color-accent-wash);
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution-note p:last-child {
|
||||||
|
color: var(--color-body);
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
.news-list-card {
|
.news-list-card {
|
||||||
transition: box-shadow 0.2s ease;
|
transition: box-shadow 0.2s ease;
|
||||||
}
|
}
|
||||||
@@ -1496,15 +1834,29 @@
|
|||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-island-menu__list > li {
|
.nav-island-menu__item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav-island-menu__item--has-menu {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-island-menu__item--has-menu::after {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: -10px;
|
||||||
|
left: -10px;
|
||||||
|
height: 18px;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
.nav-island-menu__link {
|
.nav-island-menu__link {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
padding-inline: 12px;
|
padding-inline: 12px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
@@ -1514,11 +1866,81 @@
|
|||||||
transition: color 0.2s ease;
|
transition: color 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav-island-menu__item--has-menu > .nav-island-menu__link::after {
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-right: 1.5px solid currentColor;
|
||||||
|
border-bottom: 1.5px solid currentColor;
|
||||||
|
content: "";
|
||||||
|
opacity: 0.72;
|
||||||
|
transform: translateY(-2px) rotate(45deg);
|
||||||
|
transition: transform 0.18s ease, opacity 0.18s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-island-menu__item--has-menu:hover > .nav-island-menu__link::after,
|
||||||
|
.nav-island-menu__item--has-menu:focus-within > .nav-island-menu__link::after {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(1px) rotate(225deg);
|
||||||
|
}
|
||||||
|
|
||||||
.nav-island-menu__link:hover {
|
.nav-island-menu__link:hover {
|
||||||
color: var(--color-accent-ink);
|
color: var(--color-accent-ink);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav-dropdown {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 8px);
|
||||||
|
left: 50%;
|
||||||
|
z-index: 10;
|
||||||
|
display: grid;
|
||||||
|
width: max-content;
|
||||||
|
min-width: 220px;
|
||||||
|
gap: 2px;
|
||||||
|
padding: var(--spacing-sm);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
background-color: rgb(255 255 255 / 0.96);
|
||||||
|
box-shadow: var(--shadow-surface-hover);
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translate(-50%, -4px);
|
||||||
|
visibility: hidden;
|
||||||
|
transition:
|
||||||
|
opacity 0.18s ease 0.12s,
|
||||||
|
transform 0.18s ease 0.12s,
|
||||||
|
visibility 0s linear 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-island-menu__item--has-menu:hover .nav-dropdown,
|
||||||
|
.nav-island-menu__item--has-menu:focus-within .nav-dropdown {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
|
transform: translate(-50%, 0);
|
||||||
|
visibility: visible;
|
||||||
|
transition-delay: 0.04s, 0.04s, 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-dropdown__link {
|
||||||
|
display: block;
|
||||||
|
padding: 10px var(--spacing-lg);
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
color: var(--color-ink);
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.25;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
text-decoration: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition:
|
||||||
|
background-color 0.15s ease,
|
||||||
|
color 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-dropdown__link:hover {
|
||||||
|
color: var(--color-accent-ink);
|
||||||
|
background-color: var(--color-accent-wash);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
.nav-island-actions {
|
.nav-island-actions {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
@@ -1638,6 +2060,34 @@
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav-mobile-drawer__sublist {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
margin: 0 0 var(--spacing-xs);
|
||||||
|
padding: 0 0 0 var(--spacing-lg);
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-mobile-drawer__sublink {
|
||||||
|
display: block;
|
||||||
|
padding: 9px var(--spacing-lg);
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
color: var(--color-body);
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.35;
|
||||||
|
text-decoration: none;
|
||||||
|
transition:
|
||||||
|
background-color 0.15s ease,
|
||||||
|
color 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-mobile-drawer__sublink:hover {
|
||||||
|
color: var(--color-accent-ink);
|
||||||
|
background-color: var(--color-accent-wash);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
.nav-mobile-drawer__cta-row {
|
.nav-mobile-drawer__cta-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
Reference in New Issue
Block a user