manual save(2026-01-29 14:41)

This commit is contained in:
SiteAgent Bot
2026-01-29 14:41:36 +08:00
parent ca2732a97c
commit 8b600a5c89
10 changed files with 609 additions and 2 deletions

View File

@@ -0,0 +1,2 @@
%PDF-1.4
% placeholder file

View File

@@ -0,0 +1,20 @@
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="32" y="32" width="448" height="448" rx="48" fill="#F8FAFC"/>
<rect x="72" y="72" width="368" height="368" rx="24" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="8"/>
<rect x="112" y="112" width="96" height="96" rx="16" fill="#1E3A8A"/>
<rect x="304" y="112" width="96" height="96" rx="16" fill="#1E3A8A"/>
<rect x="112" y="304" width="96" height="96" rx="16" fill="#1E3A8A"/>
<rect x="232" y="232" width="48" height="48" rx="10" fill="#D4AF37"/>
<rect x="304" y="256" width="24" height="24" rx="6" fill="#1E3A8A"/>
<rect x="352" y="304" width="56" height="56" rx="14" fill="#1E3A8A"/>
<rect x="280" y="336" width="40" height="40" rx="10" fill="#D4AF37"/>
<path d="M160 142H128V174H160V142Z" fill="#F8FAFC"/>
<path d="M352 142H320V174H352V142Z" fill="#F8FAFC"/>
<path d="M160 334H128V366H160V334Z" fill="#F8FAFC"/>
<path d="M120 440H392" stroke="#CBD5E1" stroke-width="6" stroke-linecap="round"/>
<text x="256" y="470" text-anchor="middle" font-family="system-ui, -apple-system, Segoe UI, Roboto, Arial" font-size="18" fill="#64748B">QR PLACEHOLDER</text>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -3,6 +3,8 @@ import { motion, AnimatePresence } from 'framer-motion'
import { Home } from './pages/Home' import { Home } from './pages/Home'
import { About } from './pages/About' import { About } from './pages/About'
import { Services } from './pages/Services' import { Services } from './pages/Services'
import { HighTechEnterprise } from './pages/HighTechEnterprise'
import { ServiceDetail } from './pages/ServiceDetail'
import { News } from './pages/News' import { News } from './pages/News'
import { Contact } from './pages/Contact' import { Contact } from './pages/Contact'
import { Cases } from './pages/Cases' import { Cases } from './pages/Cases'
@@ -71,6 +73,8 @@ function App() {
<Route path="/" element={<PageWrapper><Home /></PageWrapper>} /> <Route path="/" element={<PageWrapper><Home /></PageWrapper>} />
<Route path="/about" element={<PageWrapper><About /></PageWrapper>} /> <Route path="/about" element={<PageWrapper><About /></PageWrapper>} />
<Route path="/services" element={<PageWrapper><Services /></PageWrapper>} /> <Route path="/services" element={<PageWrapper><Services /></PageWrapper>} />
<Route path="/services/:serviceId" element={<PageWrapper><ServiceDetail /></PageWrapper>} />
<Route path="/services/tech-service/high-tech-enterprise" element={<PageWrapper><HighTechEnterprise /></PageWrapper>} />
<Route path="/cases" element={<PageWrapper><Cases /></PageWrapper>} /> <Route path="/cases" element={<PageWrapper><Cases /></PageWrapper>} />
<Route path="/news" element={<PageWrapper><News /></PageWrapper>} /> <Route path="/news" element={<PageWrapper><News /></PageWrapper>} />
<Route path="/learning" element={<PageWrapper><Learning /></PageWrapper>} /> <Route path="/learning" element={<PageWrapper><Learning /></PageWrapper>} />
@@ -82,6 +86,8 @@ function App() {
<Route path="/en" element={<PageWrapper><Home /></PageWrapper>} /> <Route path="/en" element={<PageWrapper><Home /></PageWrapper>} />
<Route path="/en/about" element={<PageWrapper><About /></PageWrapper>} /> <Route path="/en/about" element={<PageWrapper><About /></PageWrapper>} />
<Route path="/en/services" element={<PageWrapper><Services /></PageWrapper>} /> <Route path="/en/services" element={<PageWrapper><Services /></PageWrapper>} />
<Route path="/en/services/:serviceId" element={<PageWrapper><ServiceDetail /></PageWrapper>} />
<Route path="/en/services/tech-service/high-tech-enterprise" element={<PageWrapper><HighTechEnterprise /></PageWrapper>} />
<Route path="/en/cases" element={<PageWrapper><Cases /></PageWrapper>} /> <Route path="/en/cases" element={<PageWrapper><Cases /></PageWrapper>} />
<Route path="/en/news" element={<PageWrapper><News /></PageWrapper>} /> <Route path="/en/news" element={<PageWrapper><News /></PageWrapper>} />
<Route path="/en/learning" element={<PageWrapper><Learning /></PageWrapper>} /> <Route path="/en/learning" element={<PageWrapper><Learning /></PageWrapper>} />

View File

@@ -1,7 +1,8 @@
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { TrendingUp, Cpu, Building2, Briefcase, ArrowRight } from 'lucide-react'; import { TrendingUp, Cpu, Building2, Briefcase, ArrowRight, Wrench } from 'lucide-react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { SERVICES } from '../../lib/constants'; import { SERVICES } from '../../lib/constants';
import { getLocaleFromPathname, withLocalePath } from '../../lib/i18n'
/** /**
* ServicesSection 组件 - 核心业务展示区域 * ServicesSection 组件 - 核心业务展示区域
@@ -12,8 +13,10 @@ const ServiceCard: React.FC<{
service: typeof SERVICES[0]; service: typeof SERVICES[0];
index: number; index: number;
}> = ({ service, index }) => { }> = ({ service, index }) => {
const locale = getLocaleFromPathname(window.location.pathname)
const iconMap: Record<string, React.ComponentType<{ size?: number; className?: string }>> = { const iconMap: Record<string, React.ComponentType<{ size?: number; className?: string }>> = {
TrendingUp, TrendingUp,
Wrench,
Cpu, Cpu,
Building2, Building2,
Briefcase, Briefcase,
@@ -58,7 +61,7 @@ const ServiceCard: React.FC<{
{/* 了解更多链接 */} {/* 了解更多链接 */}
<Link <Link
to={`/services/${service.id}`} to={withLocalePath(locale, `/services/${service.id}`)}
className="relative z-10 inline-flex items-center gap-2 text-primary font-medium group-hover:text-primary-light transition-colors" className="relative z-10 inline-flex items-center gap-2 text-primary font-medium group-hover:text-primary-light transition-colors"
> >

View File

@@ -0,0 +1,152 @@
import React, { useEffect, useId, useMemo, useState } from 'react'
import { X, QrCode, ShieldCheck } from 'lucide-react'
import { grantDownloadAccess } from '../lib/downloadGate'
type PaymentMethod = 'wechat' | 'alipay'
export type PaymentQrModalProps = {
open: boolean
onClose: () => void
downloadKey: string
title: string
amountCny?: number
qrImageSrc?: string
onPaid: () => void
}
function getDefaultQrImageSrc(): string {
// Placeholder SVG kept in public/ so it can be swapped easily later.
return '/images/placeholder-qr.svg'
}
export const PaymentQrModal: React.FC<PaymentQrModalProps> = ({
open,
onClose,
downloadKey,
title,
amountCny = 1,
qrImageSrc,
onPaid,
}) => {
const dialogTitleId = useId()
const [method, setMethod] = useState<PaymentMethod>('wechat')
const qrSrc = useMemo(() => qrImageSrc ?? getDefaultQrImageSrc(), [qrImageSrc])
useEffect(() => {
if (!open) return
const onKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') onClose()
}
window.addEventListener('keydown', onKeyDown)
return () => window.removeEventListener('keydown', onKeyDown)
}, [onClose, open])
if (!open) return null
return (
<div className="fixed inset-0 z-[100]">
<div className="absolute inset-0 bg-black/50" aria-hidden="true" onClick={onClose} />
<div className="absolute inset-0 flex items-center justify-center p-4">
<div
role="dialog"
aria-modal="true"
aria-labelledby={dialogTitleId}
className="w-full max-w-lg rounded-2xl bg-white shadow-xl border border-gray-100 overflow-hidden"
>
<div className="flex items-center justify-between px-6 py-4 border-b border-gray-100">
<div>
<div id={dialogTitleId} className="text-base font-semibold text-primary-dark">
</div>
<div className="text-xs text-gray-500 mt-1">{title}</div>
</div>
<button
type="button"
onClick={onClose}
className="w-9 h-9 inline-flex items-center justify-center rounded-lg text-gray-600 hover:bg-gray-50"
aria-label="关闭"
>
<X size={18} />
</button>
</div>
<div className="px-6 py-5">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
<div className="inline-flex items-center gap-2 text-sm text-gray-700">
<QrCode size={18} className="text-primary" />
<span><span className="font-semibold text-primary-dark">{amountCny} </span></span>
</div>
<div className="inline-flex rounded-xl bg-gray-50 p-1 border border-gray-100">
<button
type="button"
onClick={() => setMethod('wechat')}
className={`px-3 py-2 rounded-lg text-sm font-medium transition-colors ${
method === 'wechat' ? 'bg-white text-primary shadow-sm' : 'text-gray-600 hover:text-primary'
}`}
>
</button>
<button
type="button"
onClick={() => setMethod('alipay')}
className={`px-3 py-2 rounded-lg text-sm font-medium transition-colors ${
method === 'alipay' ? 'bg-white text-primary shadow-sm' : 'text-gray-600 hover:text-primary'
}`}
>
</button>
</div>
</div>
<div className="mt-5 grid sm:grid-cols-[1fr_180px] gap-4 items-start">
<div className="rounded-2xl bg-background border border-gray-100 p-4">
<div className="text-sm font-semibold text-primary-dark"></div>
<ol className="mt-2 text-sm text-gray-600 space-y-2 list-decimal pl-5">
<li></li>
<li>使 App </li>
<li></li>
</ol>
<div className="mt-4 flex items-start gap-2 text-xs text-gray-500">
<ShieldCheck size={16} className="mt-0.5 text-accent-dark" />
<p></p>
</div>
</div>
<div className="rounded-2xl border border-gray-100 bg-white p-4">
<div className="aspect-square rounded-xl overflow-hidden bg-gray-50 border border-gray-100">
<img src={qrSrc} alt={`${method === 'wechat' ? '微信' : '支付宝'}收款码`} className="w-full h-full object-contain" />
</div>
<div className="mt-3 text-center text-xs text-gray-500">{method === 'wechat' ? '微信扫码' : '支付宝扫码'}</div>
</div>
</div>
</div>
<div className="px-6 py-4 border-t border-gray-100 flex items-center justify-between gap-3">
<button
type="button"
onClick={onClose}
className="px-4 py-2 rounded-xl text-sm font-medium text-gray-700 hover:bg-gray-50"
>
</button>
<button
type="button"
onClick={() => {
grantDownloadAccess(downloadKey, method)
onPaid()
}}
className="px-4 py-2 rounded-xl text-sm font-medium text-white bg-primary hover:bg-primary-light"
>
</button>
</div>
</div>
</div>
</div>
)
}
export default PaymentQrModal

View File

@@ -34,6 +34,7 @@ export const NAVIGATION_MENU = [
export const FOOTER_LINKS = { export const FOOTER_LINKS = {
products: [ products: [
{ label: '金融服务', path: '/services/finance' }, { label: '金融服务', path: '/services/finance' },
{ label: '科技服务', path: '/services/tech-service' },
{ label: '科技研发', path: '/services/tech' }, { label: '科技研发', path: '/services/tech' },
{ label: '产业投资', path: '/services/investment' }, { label: '产业投资', path: '/services/investment' },
{ label: '咨询服务', path: '/services/consulting' }, { label: '咨询服务', path: '/services/consulting' },
@@ -85,6 +86,14 @@ export const SERVICES = [
icon: 'TrendingUp', icon: 'TrendingUp',
features: ['财富管理', '投资顾问', '资产配置', '风险管理'], features: ['财富管理', '投资顾问', '资产配置', '风险管理'],
}, },
{
id: 'tech-service',
title: '科技服务',
description:
'围绕企业创新与资质建设,提供高新技术企业认定、研发管理体系辅导、科技项目申报等科技服务。',
icon: 'Wrench',
features: ['高新技术企业认定', '科技项目申报', '研发管理辅导', '资质与合规'],
},
{ {
id: 'tech', id: 'tech',
title: '科技研发', title: '科技研发',

42
src/lib/downloadGate.ts Normal file
View File

@@ -0,0 +1,42 @@
type DownloadGatePayload = {
key: string
paidAt: string
amountCny: number
method: 'wechat' | 'alipay'
}
const STORAGE_PREFIX = 'downloadGate:'
export function hasDownloadAccess(key: string): boolean {
try {
const raw = localStorage.getItem(`${STORAGE_PREFIX}${key}`)
if (!raw) return false
const parsed = JSON.parse(raw) as DownloadGatePayload
return parsed?.key === key && parsed.amountCny >= 1
} catch {
return false
}
}
export function grantDownloadAccess(key: string, method: DownloadGatePayload['method']): void {
const payload: DownloadGatePayload = {
key,
paidAt: new Date().toISOString(),
amountCny: 1,
method,
}
try {
localStorage.setItem(`${STORAGE_PREFIX}${key}`, JSON.stringify(payload))
} catch {
// ignore
}
}
export function revokeDownloadAccess(key: string): void {
try {
localStorage.removeItem(`${STORAGE_PREFIX}${key}`)
} catch {
// ignore
}
}

View File

@@ -0,0 +1,175 @@
import React, { useCallback, useMemo, useState } from 'react'
import { motion } from 'framer-motion'
import { FileText, Download, Lock, CheckCircle2 } from 'lucide-react'
import { Header } from '../components/Header'
import { Footer } from '../components/Footer'
import { usePageMeta } from '../hooks/usePageMeta'
import { getLocaleFromPathname, withLocalePath } from '../lib/i18n'
import { hasDownloadAccess } from '../lib/downloadGate'
import { PaymentQrModal } from '../components/PaymentQrModal'
const DOWNLOAD_KEY = 'htech-application-2026'
const FILE_NAME = '2026年高新技术企业认定申请表.pdf'
const FILE_PATH = '/downloads/2026-high-tech-enterprise-application-form.pdf'
function startFileDownload(absoluteOrPublicPath: string, fileName?: string) {
const a = document.createElement('a')
a.href = absoluteOrPublicPath
if (fileName) a.download = fileName
a.rel = 'noopener'
document.body.appendChild(a)
a.click()
a.remove()
}
export const HighTechEnterprise: React.FC = () => {
const locale = getLocaleFromPathname(window.location.pathname)
const [payOpen, setPayOpen] = useState(false)
const [downloadUnlocked, setDownloadUnlocked] = useState(() => hasDownloadAccess(DOWNLOAD_KEY))
usePageMeta({
title: locale === 'en' ? 'High-tech enterprise certification' : '高新技术企业认定要求',
description:
locale === 'en'
? 'High-tech enterprise certification requirements and download of the 2026 application form.'
: '高新技术企业认定的核心要求说明,并提供 2026 年申请表下载入口。',
locale,
})
const alreadyPaid = downloadUnlocked
const handleDownloadClick = useCallback(() => {
if (hasDownloadAccess(DOWNLOAD_KEY)) {
setDownloadUnlocked(true)
startFileDownload(FILE_PATH, FILE_NAME)
return
}
setPayOpen(true)
}, [])
const breadcrumbHref = useMemo(() => withLocalePath(locale, '/services'), [locale])
return (
<motion.div className="min-h-screen bg-background" initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
<Header />
<main>
<section className="pt-32 pb-10 bg-white border-b border-gray-100">
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
<a href={breadcrumbHref} className="text-sm text-gray-500 hover:text-primary">
{locale === 'en' ? 'Back to Services' : '返回服务范围'}
</a>
<h1 className="mt-3 text-3xl md:text-4xl font-semibold text-primary-dark">
{locale === 'en' ? 'High-tech enterprise certification requirements' : '高新技术企业认定要求'}
</h1>
<p className="mt-4 text-gray-600 leading-relaxed">
{locale === 'en'
? 'This page provides a simplified overview. Replace with official materials later.'
: '本页为精简版概览,便于用户快速理解核心要求;后续可替换为完整政策解读与本地政策细则。'}
</p>
</div>
</section>
<section className="py-12">
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid lg:grid-cols-[1fr_360px] gap-8 items-start">
<article className="bg-white rounded-2xl border border-gray-100 p-6 md:p-8">
<h2 className="text-xl font-semibold text-primary-dark">{locale === 'en' ? 'Key points' : '核心要点(示例)'}</h2>
<div className="mt-5 space-y-4 text-sm text-gray-700 leading-relaxed">
<div className="flex gap-3">
<CheckCircle2 className="mt-0.5 text-accent-dark" size={18} />
<p>
{locale === 'en'
? 'Intellectual property, R&D activity, and revenue structure are commonly reviewed items.'
: '常见审核关注:知识产权布局、研发活动真实性、收入结构与高新产品(服务)比例等。'}
</p>
</div>
<div className="flex gap-3">
<CheckCircle2 className="mt-0.5 text-accent-dark" size={18} />
<p>
{locale === 'en'
? 'R&D expense accounting should be consistent and traceable.'
: '研发费用归集口径需一致、可追溯,建议提前建立台账与证据链。'}
</p>
</div>
<div className="flex gap-3">
<CheckCircle2 className="mt-0.5 text-accent-dark" size={18} />
<p>
{locale === 'en'
? 'Policies differ by region; always follow the latest local rules.'
: '各地细则可能存在差异,实际申报以最新的本地政策与平台要求为准。'}
</p>
</div>
</div>
<hr className="my-8 border-gray-100" />
<h3 className="text-lg font-semibold text-primary-dark">{locale === 'en' ? 'Downloads' : '资料下载'}</h3>
<p className="mt-2 text-sm text-gray-600">
{locale === 'en'
? 'Download requires a 1 CNY payment via WeChat/Alipay.'
: '下载需支付 1 元(微信/支付宝均可)。'}
</p>
<div className="mt-4 rounded-2xl border border-gray-100 bg-background p-4 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
<div className="flex items-start gap-3">
<div className="w-10 h-10 rounded-xl bg-white border border-gray-100 flex items-center justify-center">
<FileText size={20} className="text-primary" />
</div>
<div>
<div className="text-sm font-semibold text-primary-dark">{FILE_NAME}</div>
<div className="mt-1 text-xs text-gray-500">PDF · {locale === 'en' ? 'Form template' : '申请表模板'}</div>
</div>
</div>
<button
type="button"
onClick={handleDownloadClick}
className="inline-flex items-center justify-center gap-2 px-5 py-3 rounded-xl text-sm font-medium text-white bg-primary hover:bg-primary-light transition-colors"
aria-label="下载申请表"
>
{alreadyPaid ? <Download size={18} /> : <Lock size={18} />}
{alreadyPaid ? (locale === 'en' ? 'Download' : '下载') : locale === 'en' ? 'Pay & download' : '付费下载'}
</button>
</div>
</article>
<aside className="bg-white rounded-2xl border border-gray-100 p-6">
<div className="text-sm font-semibold text-primary-dark">{locale === 'en' ? 'Service scope' : '对应服务'}</div>
<p className="mt-2 text-sm text-gray-600 leading-relaxed">
{locale === 'en'
? 'Tech services: certification guidance, R&D accounting, and application material preparation.'
: '科技服务:认定辅导、研发费用归集、申报材料梳理与答疑支持。'}
</p>
<div className="mt-4 rounded-xl bg-background border border-gray-100 p-4 text-xs text-gray-500 leading-relaxed">
{locale === 'en'
? 'Note: Payment is a front-end placeholder for now and does not verify actual payment.'
: '提示:当前“支付”仅为前端占位演示,不具备真实收款与到账校验能力。上线真实付费需对接支付回调与服务端验签。'}
</div>
</aside>
</div>
</div>
</section>
</main>
<Footer />
<PaymentQrModal
open={payOpen}
onClose={() => setPayOpen(false)}
downloadKey={DOWNLOAD_KEY}
title={FILE_NAME}
amountCny={1}
onPaid={() => {
setDownloadUnlocked(true)
setPayOpen(false)
startFileDownload(FILE_PATH, FILE_NAME)
}}
/>
</motion.div>
)
}
export default HighTechEnterprise

106
src/pages/ServiceDetail.tsx Normal file
View File

@@ -0,0 +1,106 @@
import React, { useMemo } from 'react'
import { useParams } from 'react-router-dom'
import { motion } from 'framer-motion'
import { ArrowRight, CheckCircle2, FileText } from 'lucide-react'
import { Header } from '../components/Header'
import { Footer } from '../components/Footer'
import { SERVICES } from '../lib/constants'
import { getLocaleFromPathname, withLocalePath } from '../lib/i18n'
import { usePageMeta } from '../hooks/usePageMeta'
export const ServiceDetail: React.FC = () => {
const locale = getLocaleFromPathname(window.location.pathname)
const { serviceId } = useParams<{ serviceId: string }>()
const service = useMemo(() => SERVICES.find((s) => s.id === serviceId), [serviceId])
usePageMeta({
title: service ? (locale === 'en' ? 'Service' : service.title) : locale === 'en' ? 'Service' : '服务',
description: service?.description,
locale,
})
const backHref = useMemo(() => withLocalePath(locale, '/services'), [locale])
if (!service) {
return (
<motion.div className="min-h-screen bg-background" initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
<Header />
<main className="pt-32 pb-16">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<a href={backHref} className="text-sm text-gray-500 hover:text-primary">
{locale === 'en' ? 'Back to Services' : '返回服务范围'}
</a>
<h1 className="mt-4 text-3xl font-semibold text-primary-dark">{locale === 'en' ? 'Service not found' : '未找到该服务'}</h1>
<p className="mt-3 text-gray-600">{locale === 'en' ? 'Please check the URL.' : '请检查访问路径是否正确。'}</p>
</div>
</main>
<Footer />
</motion.div>
)
}
const isTechService = service.id === 'tech-service'
const highTechHref = withLocalePath(locale, '/services/tech-service/high-tech-enterprise')
return (
<motion.div className="min-h-screen bg-background" initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
<Header />
<main>
<section className="pt-32 pb-10 bg-white border-b border-gray-100">
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
<a href={backHref} className="text-sm text-gray-500 hover:text-primary">
{locale === 'en' ? 'Back to Services' : '返回服务范围'}
</a>
<h1 className="mt-3 text-3xl md:text-4xl font-semibold text-primary-dark">{service.title}</h1>
<p className="mt-4 text-gray-600 leading-relaxed">{service.description}</p>
</div>
</section>
<section className="py-12">
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="bg-white rounded-2xl border border-gray-100 p-6 md:p-8">
<h2 className="text-xl font-semibold text-primary-dark">{locale === 'en' ? 'What we provide' : '我们提供'}</h2>
<div className="mt-5 grid sm:grid-cols-2 gap-3">
{service.features.map((f) => (
<div key={f} className="flex items-start gap-3 rounded-xl bg-background border border-gray-100 p-4">
<CheckCircle2 size={18} className="mt-0.5 text-accent-dark" />
<div className="text-sm text-gray-700">{f}</div>
</div>
))}
</div>
{isTechService && (
<div className="mt-8 rounded-2xl border border-gray-100 bg-background p-5">
<div className="flex items-start justify-between gap-4">
<div>
<div className="flex items-center gap-2 text-sm font-semibold text-primary-dark">
<FileText size={18} className="text-primary" />
</div>
<p className="mt-2 text-sm text-gray-600 leading-relaxed">
2026 1
</p>
</div>
<a
href={highTechHref}
className="inline-flex items-center justify-center gap-2 px-4 py-2 rounded-xl text-sm font-medium text-white bg-primary hover:bg-primary-light transition-colors"
>
<ArrowRight size={18} />
</a>
</div>
</div>
)}
</div>
</div>
</section>
</main>
<Footer />
</motion.div>
)
}
export default ServiceDetail

View File

@@ -5,6 +5,7 @@ import {
Cpu, Cpu,
Building2, Building2,
Briefcase, Briefcase,
Wrench,
CheckCircle, CheckCircle,
Target, Target,
BarChart3, BarChart3,
@@ -45,6 +46,38 @@ const serviceDetails = {
{ step: '04', title: '持续跟踪', desc: '定期调整和优化投资组合' }, { step: '04', title: '持续跟踪', desc: '定期调整和优化投资组合' },
], ],
}, },
techService: {
description:
'科技服务聚焦企业创新能力建设与资质合规,提供高新技术企业认定辅导、申报材料梳理、研发费用归集与体系完善等支持,帮助企业更高效地完成申报与长期管理。',
features: [
{
icon: Wrench,
title: '认定辅导',
desc: '对照政策要求梳理差距,形成可落地的提升与申报路径',
},
{
icon: Shield,
title: '研发体系建设',
desc: '完善研发管理制度、知识产权与成果转化台账,提升持续合规能力',
},
{
icon: BarChart3,
title: '费用归集与核算',
desc: '辅助研发费用归集口径与台账搭建,降低申报风险',
},
{
icon: Target,
title: '项目申报与匹配',
desc: '结合企业业务方向,进行科技项目匹配与材料准备',
},
],
process: [
{ step: '01', title: '资质诊断', desc: '梳理现状,评估达标差距与可行路径' },
{ step: '02', title: '材料梳理', desc: '搭建目录清单,统一口径与证据链' },
{ step: '03', title: '申报提交', desc: '按节点推进提交与补正,提升通过率' },
{ step: '04', title: '后续管理', desc: '建立持续合规机制与年度复盘' },
],
},
tech: { tech: {
description: '我们聚焦人工智能、大数据、云计算等前沿技术,为企业提供全方位的数字化转型解决方案。', description: '我们聚焦人工智能、大数据、云计算等前沿技术,为企业提供全方位的数字化转型解决方案。',
features: [ features: [
@@ -144,6 +177,7 @@ const partners = [
const categories = [ const categories = [
{ id: 'all', label: '全部' }, { id: 'all', label: '全部' },
{ id: 'finance', label: '金融服务' }, { id: 'finance', label: '金融服务' },
{ id: 'techService', label: '科技服务' },
{ id: 'tech', label: '科技研发' }, { id: 'tech', label: '科技研发' },
{ id: 'investment', label: '产业投资' }, { id: 'investment', label: '产业投资' },
{ id: 'consulting', label: '咨询服务' }, { id: 'consulting', label: '咨询服务' },
@@ -270,6 +304,7 @@ export const Services: React.FC = () => {
{SERVICES.map((service, index) => { {SERVICES.map((service, index) => {
const iconMap: Record<string, React.ComponentType<{ size?: number; className?: string }>> = { const iconMap: Record<string, React.ComponentType<{ size?: number; className?: string }>> = {
TrendingUp, TrendingUp,
Wrench,
Cpu, Cpu,
Building2, Building2,
Briefcase, Briefcase,
@@ -433,6 +468,63 @@ export const Services: React.FC = () => {
</div> </div>
</motion.div> </motion.div>
</div> </div>
{/* 科技服务 */}
<div className="grid lg:grid-cols-2 gap-12 items-center mb-20">
<motion.div
initial={{ opacity: 0, x: -30 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
>
<span className="inline-block px-4 py-1 bg-accent/20 text-accent-dark text-sm font-semibold rounded-full mb-4">
</span>
<h3 className="text-2xl font-bold text-primary-dark mb-6">
</h3>
<p className="text-gray-600 leading-relaxed mb-8">
{serviceDetails.techService.description}
</p>
<div className="grid sm:grid-cols-2 gap-4 mb-8">
{serviceDetails.techService.features.map((feature, index) => (
<div key={index} className="flex items-start gap-3 p-4 bg-background rounded-xl">
<div className="p-2 bg-primary/10 rounded-lg">
<feature.icon size={20} className="text-primary" />
</div>
<div>
<h4 className="font-medium text-primary-dark text-sm">{feature.title}</h4>
<p className="text-xs text-gray-500 mt-1">{feature.desc}</p>
</div>
</div>
))}
</div>
<a
href={locale === 'en' ? '/en/services/tech-service' : '/services/tech-service'}
className="inline-flex items-center justify-center px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary-light transition-colors"
>
</a>
</motion.div>
<motion.div
className="relative"
initial={{ opacity: 0, x: 30 }}
whileInView={{ opacity: 1, x: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6 }}
>
<div className="aspect-square rounded-2xl overflow-hidden shadow-xl">
<img
src="https://images.unsplash.com/photo-1526378722430-5c37f7f116aa?w=800&h=800&fit=crop"
alt="科技服务 - 高新技术企业认定与申报支持"
className="w-full h-full object-cover hover:scale-105 transition-transform duration-500"
/>
</div>
</motion.div>
</div>
</div> </div>
</section> </section>