工作室介绍,开工(
This commit is contained in:
@@ -6,6 +6,80 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.intro-about {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.intro-about::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
html:has(body.intro-about) {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
html:has(body.intro-about)::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.intro-about .site-header,
|
||||||
|
body.intro-about .site-footer {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.intro-about .hero-section {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.intro-about .about-theme-toggle {
|
||||||
|
position: fixed;
|
||||||
|
top: 18px;
|
||||||
|
right: 18px;
|
||||||
|
z-index: 40;
|
||||||
|
width: 72px;
|
||||||
|
height: 72px;
|
||||||
|
background: transparent !important;
|
||||||
|
border: none !important;
|
||||||
|
border-radius: 0;
|
||||||
|
color: color-mix(in srgb, var(--text-primary) 82%, var(--color-primary) 18%);
|
||||||
|
box-shadow: none;
|
||||||
|
backdrop-filter: none;
|
||||||
|
-webkit-backdrop-filter: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.intro-about .about-theme-toggle::before {
|
||||||
|
display: none;
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.intro-about .about-theme-toggle svg {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.intro-about .about-theme-toggle:hover,
|
||||||
|
body.intro-about .about-theme-toggle:focus-visible {
|
||||||
|
background: transparent !important;
|
||||||
|
border: none !important;
|
||||||
|
color: color-mix(in srgb, var(--text-primary) 72%, var(--color-primary) 28%);
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.intro-about .about-theme-toggle:hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.intro-about .about-theme-toggle:hover::before,
|
||||||
|
body.intro-about .about-theme-toggle:focus-visible::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.hero-section {
|
.hero-section {
|
||||||
padding: 40px 0;
|
padding: 40px 0;
|
||||||
background-color: var(--bg-body);
|
background-color: var(--bg-body);
|
||||||
@@ -131,7 +205,10 @@ html:not([data-theme="dark"]) .hero-waves {
|
|||||||
|
|
||||||
.hero-title {
|
.hero-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
gap: clamp(2px, 0.6vw, 10px);
|
||||||
margin: 0 0 1.2rem;
|
margin: 0 0 1.2rem;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
--hero-title-gradient: linear-gradient(135deg, var(--text-primary) 0%, var(--color-primary) 100%);
|
--hero-title-gradient: linear-gradient(135deg, var(--text-primary) 0%, var(--color-primary) 100%);
|
||||||
@@ -442,6 +519,11 @@ html:not([data-theme="dark"]) .hero-title-svg::before {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
|
body.intro-about .about-theme-toggle {
|
||||||
|
top: 12px;
|
||||||
|
right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.hero-title {
|
.hero-title {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,15 +15,15 @@
|
|||||||
let rafId = null;
|
let rafId = null;
|
||||||
|
|
||||||
const waveDefs = [
|
const waveDefs = [
|
||||||
{ yRatio: 0.3, amplitude: 22, wavelength: 940, speed: 0.5, alpha: 0.98 },
|
{ yRatio: 0.3, amplitude: 24, wavelength: 940, speed: 0.5, alpha: 0.98 },
|
||||||
{ yRatio: 0.45, amplitude: 16, wavelength: 1020, speed: 0.58, alpha: 0.92 },
|
{ yRatio: 0.45, amplitude: 14, wavelength: 1020, speed: 0.58, alpha: 0.92 },
|
||||||
{ yRatio: 0.65, amplitude: 14, wavelength: 1160, speed: 0.6, alpha: 0.9 },
|
{ yRatio: 0.65, amplitude: 10, wavelength: 1160, speed: 0.6, alpha: 0.9 },
|
||||||
];
|
];
|
||||||
|
|
||||||
const palettes = {
|
const palettes = {
|
||||||
light: {
|
light: {
|
||||||
gradient: ['#e8f3ff', '#cfe6fb', '#558ec1', '#2476af', '#2b6fb3'],
|
gradient: ['#d6e8fa', '#a7c8e8', '#6f9fc8', '#4f84b6', '#376e9f'],
|
||||||
waves: ['rgba(170, 215, 245, 0.91)', 'rgba(120, 185, 230, 0.93)', 'rgba(80, 155, 210, 0.95)'],
|
waves: ['rgba(124, 167, 205, 0.96)', 'rgba(90, 143, 190, 0.97)', 'rgba(62, 118, 169, 0.98)'],
|
||||||
},
|
},
|
||||||
dark: {
|
dark: {
|
||||||
gradient: ['#0d1117', '#111d2b', '#14334d', '#17507a', '#1b6aa6'],
|
gradient: ['#0d1117', '#111d2b', '#14334d', '#17507a', '#1b6aa6'],
|
||||||
|
|||||||
+167
-16
@@ -3,38 +3,189 @@
|
|||||||
if (!hero) return;
|
if (!hero) return;
|
||||||
|
|
||||||
const body = document.body;
|
const body = document.body;
|
||||||
const desktopQuery = window.matchMedia('(min-width: 900px)');
|
const header = document.querySelector('.site-header');
|
||||||
let hasScrolled = false;
|
const titleSvg = hero.querySelector('.hero-title-svg');
|
||||||
|
const scrollIndicator = hero.querySelector('.hero-scroll-indicator');
|
||||||
|
const scrollArrow = scrollIndicator ? scrollIndicator.querySelector('.scroll-arrow') : null;
|
||||||
|
const scrollText = scrollIndicator ? scrollIndicator.querySelector('.scroll-text') : null;
|
||||||
|
|
||||||
const applyState = () => {
|
const desktopQuery = window.matchMedia('(min-width: 900px)');
|
||||||
|
const reducedMotionQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
|
||||||
|
const anime = window.anime;
|
||||||
|
const hasAnime = typeof anime === 'function';
|
||||||
|
|
||||||
|
let arrowPulse = null;
|
||||||
|
let didIntro = false;
|
||||||
|
let ticking = false;
|
||||||
|
|
||||||
|
const stopArrowPulse = () => {
|
||||||
|
if (!arrowPulse) return;
|
||||||
|
arrowPulse.pause();
|
||||||
|
arrowPulse = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const startArrowPulse = () => {
|
||||||
|
if (!hasAnime || reducedMotionQuery.matches || !scrollArrow) return;
|
||||||
|
stopArrowPulse();
|
||||||
|
scrollArrow.style.animation = 'none';
|
||||||
|
anime.remove(scrollArrow);
|
||||||
|
anime.set(scrollArrow, {
|
||||||
|
translateY: 0,
|
||||||
|
opacity: 0.5,
|
||||||
|
rotate: 45,
|
||||||
|
});
|
||||||
|
arrowPulse = anime({
|
||||||
|
targets: scrollArrow,
|
||||||
|
translateY: [0, 6, 0],
|
||||||
|
opacity: [0.5, 1, 0.5],
|
||||||
|
rotate: 45,
|
||||||
|
duration: 1600,
|
||||||
|
easing: 'easeInOutSine',
|
||||||
|
loop: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearInlineState = () => {
|
||||||
|
if (header) {
|
||||||
|
header.style.transform = '';
|
||||||
|
}
|
||||||
|
if (scrollIndicator) {
|
||||||
|
scrollIndicator.style.opacity = '';
|
||||||
|
scrollIndicator.style.transform = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const animateScrollState = (isAtTop) => {
|
||||||
|
if (!hasAnime || reducedMotionQuery.matches) return;
|
||||||
|
|
||||||
|
if (header) {
|
||||||
|
anime.remove(header);
|
||||||
|
anime({
|
||||||
|
targets: header,
|
||||||
|
translateY: isAtTop ? '-100%' : '0%',
|
||||||
|
duration: isAtTop ? 500 : 380,
|
||||||
|
easing: isAtTop ? 'easeInOutCubic' : 'easeOutCubic',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scrollIndicator) {
|
||||||
|
anime.remove(scrollIndicator);
|
||||||
|
anime({
|
||||||
|
targets: scrollIndicator,
|
||||||
|
opacity: isAtTop ? 1 : 0,
|
||||||
|
duration: isAtTop ? 380 : 260,
|
||||||
|
easing: isAtTop ? 'easeOutCubic' : 'easeOutQuad',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const applyState = (animated) => {
|
||||||
if (!desktopQuery.matches) {
|
if (!desktopQuery.matches) {
|
||||||
body.classList.remove('home-hero-initial', 'home-hero-scrolled');
|
body.classList.remove('home-hero-initial', 'home-hero-scrolled');
|
||||||
|
stopArrowPulse();
|
||||||
|
clearInlineState();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasScrolled || window.scrollY > 6) {
|
const isAtTop = window.scrollY <= 6;
|
||||||
body.classList.remove('home-hero-initial');
|
body.classList.toggle('home-hero-initial', isAtTop);
|
||||||
body.classList.add('home-hero-scrolled');
|
body.classList.toggle('home-hero-scrolled', !isAtTop);
|
||||||
} else {
|
|
||||||
body.classList.add('home-hero-initial');
|
if (animated) {
|
||||||
body.classList.remove('home-hero-scrolled');
|
animateScrollState(isAtTop);
|
||||||
|
} else if (hasAnime) {
|
||||||
|
if (header) {
|
||||||
|
anime.remove(header);
|
||||||
|
}
|
||||||
|
if (scrollIndicator) {
|
||||||
|
anime.remove(scrollIndicator);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isAtTop) {
|
||||||
|
startArrowPulse();
|
||||||
|
} else {
|
||||||
|
stopArrowPulse();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const playIntro = () => {
|
||||||
|
if (didIntro || !hasAnime || reducedMotionQuery.matches || !desktopQuery.matches || window.scrollY > 6) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
didIntro = true;
|
||||||
|
if (titleSvg) {
|
||||||
|
anime.set(titleSvg, { opacity: 0, translateY: 14, scale: 1.01 });
|
||||||
|
}
|
||||||
|
if (scrollArrow) {
|
||||||
|
anime.set(scrollArrow, { opacity: 0, translateY: 8, rotate: 45 });
|
||||||
|
}
|
||||||
|
if (scrollText) {
|
||||||
|
anime.set(scrollText, { opacity: 0, translateY: 8 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeline = anime.timeline({
|
||||||
|
easing: 'easeOutCubic',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (titleSvg) {
|
||||||
|
timeline.add({
|
||||||
|
targets: titleSvg,
|
||||||
|
opacity: 1,
|
||||||
|
translateY: -8,
|
||||||
|
scale: 1.06,
|
||||||
|
duration: 860,
|
||||||
|
easing: 'easeOutExpo',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scrollArrow || scrollText) {
|
||||||
|
timeline.add({
|
||||||
|
targets: [scrollArrow, scrollText].filter(Boolean),
|
||||||
|
opacity: (el) => (el === scrollArrow ? [0, 1] : [0, 1]),
|
||||||
|
translateY: 0,
|
||||||
|
rotate: (el) => (el === scrollArrow ? 45 : 0),
|
||||||
|
duration: 420,
|
||||||
|
delay: anime.stagger(80),
|
||||||
|
}, '-=300');
|
||||||
|
}
|
||||||
|
|
||||||
|
timeline.finished.then(() => {
|
||||||
|
startArrowPulse();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onScroll = () => {
|
const onScroll = () => {
|
||||||
hasScrolled = window.scrollY > 6;
|
if (ticking) return;
|
||||||
applyState();
|
ticking = true;
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
applyState(true);
|
||||||
|
ticking = false;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onResize = () => {
|
const onResize = () => {
|
||||||
if (!desktopQuery.matches) {
|
applyState(false);
|
||||||
hasScrolled = false;
|
|
||||||
}
|
|
||||||
applyState();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
applyState();
|
const onReducedMotionChange = () => {
|
||||||
|
if (reducedMotionQuery.matches) {
|
||||||
|
stopArrowPulse();
|
||||||
|
if (scrollArrow) {
|
||||||
|
scrollArrow.style.animation = 'none';
|
||||||
|
}
|
||||||
|
} else if (window.scrollY <= 6 && desktopQuery.matches) {
|
||||||
|
startArrowPulse();
|
||||||
|
}
|
||||||
|
applyState(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
applyState(false);
|
||||||
|
playIntro();
|
||||||
|
|
||||||
window.addEventListener('scroll', onScroll, { passive: true });
|
window.addEventListener('scroll', onScroll, { passive: true });
|
||||||
window.addEventListener('resize', onResize);
|
window.addEventListener('resize', onResize);
|
||||||
desktopQuery.addEventListener('change', onResize);
|
desktopQuery.addEventListener('change', onResize);
|
||||||
|
reducedMotionQuery.addEventListener('change', onReducedMotionChange);
|
||||||
})();
|
})();
|
||||||
|
|||||||
+106
-5
@@ -1,5 +1,30 @@
|
|||||||
const themeToggle = document.querySelector('.theme-toggle');
|
const themeToggles = document.querySelectorAll('.theme-toggle');
|
||||||
const html = document.documentElement;
|
const html = document.documentElement;
|
||||||
|
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
|
||||||
|
const supportsViewTransition = typeof document.startViewTransition === 'function';
|
||||||
|
const viewTransitionStyleId = 'itstudio-view-transition-style';
|
||||||
|
let isThemeTransitioning = false;
|
||||||
|
|
||||||
|
function ensureViewTransitionStyles() {
|
||||||
|
if (!supportsViewTransition || document.getElementById(viewTransitionStyleId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.id = viewTransitionStyleId;
|
||||||
|
style.textContent = `
|
||||||
|
::view-transition-old(root),
|
||||||
|
::view-transition-new(root) {
|
||||||
|
animation: none;
|
||||||
|
mix-blend-mode: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
::view-transition-group(root) {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
}
|
||||||
|
|
||||||
function updateLogoColor(theme) {
|
function updateLogoColor(theme) {
|
||||||
const logoText = document.querySelector('#logo-text-cn');
|
const logoText = document.querySelector('#logo-text-cn');
|
||||||
@@ -21,19 +46,95 @@ function getPreferredTheme() {
|
|||||||
function setTheme(theme) {
|
function setTheme(theme) {
|
||||||
html.setAttribute('data-theme', theme);
|
html.setAttribute('data-theme', theme);
|
||||||
localStorage.setItem('theme', theme);
|
localStorage.setItem('theme', theme);
|
||||||
|
themeToggles.forEach((toggle) => {
|
||||||
|
toggle.setAttribute('aria-pressed', theme === 'dark' ? 'true' : 'false');
|
||||||
|
});
|
||||||
updateLogoColor(theme);
|
updateLogoColor(theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialTheme = getPreferredTheme();
|
const initialTheme = getPreferredTheme();
|
||||||
setTheme(initialTheme);
|
setTheme(initialTheme);
|
||||||
|
ensureViewTransitionStyles();
|
||||||
|
|
||||||
if (themeToggle) {
|
function getToggleCenter(toggle) {
|
||||||
themeToggle.addEventListener('click', () => {
|
if (!toggle) {
|
||||||
|
return {
|
||||||
|
x: window.innerWidth / 2,
|
||||||
|
y: window.innerHeight / 2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const rect = toggle.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
x: rect.left + rect.width / 2,
|
||||||
|
y: rect.top + rect.height / 2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTransitionOrigin(event, toggle) {
|
||||||
|
const hasPointerPoint = Number.isFinite(event.clientX) && Number.isFinite(event.clientY) && (event.clientX !== 0 || event.clientY !== 0);
|
||||||
|
if (hasPointerPoint) {
|
||||||
|
return {
|
||||||
|
x: event.clientX,
|
||||||
|
y: event.clientY,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return getToggleCenter(toggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRevealRadius(x, y) {
|
||||||
|
const maxX = Math.max(x, window.innerWidth - x);
|
||||||
|
const maxY = Math.max(y, window.innerHeight - y);
|
||||||
|
return Math.hypot(maxX, maxY);
|
||||||
|
}
|
||||||
|
|
||||||
|
function switchThemeWithScatter(theme, origin) {
|
||||||
|
if (isThemeTransitioning || prefersReducedMotion.matches || !supportsViewTransition) {
|
||||||
|
setTheme(theme);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isThemeTransitioning = true;
|
||||||
|
const x = origin.x;
|
||||||
|
const y = origin.y;
|
||||||
|
const endRadius = getRevealRadius(x, y);
|
||||||
|
const clipFrom = `circle(0px at ${x}px ${y}px)`;
|
||||||
|
const clipTo = `circle(${endRadius}px at ${x}px ${y}px)`;
|
||||||
|
|
||||||
|
const transition = document.startViewTransition(() => {
|
||||||
|
setTheme(theme);
|
||||||
|
});
|
||||||
|
|
||||||
|
transition.ready
|
||||||
|
.then(() => {
|
||||||
|
document.documentElement.animate(
|
||||||
|
{
|
||||||
|
clipPath: [clipFrom, clipTo],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: 650,
|
||||||
|
easing: 'cubic-bezier(0.22, 1, 0.36, 1)',
|
||||||
|
pseudoElement: '::view-transition-new(root)',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
.finally(() => {
|
||||||
|
transition.finished.finally(() => {
|
||||||
|
isThemeTransitioning = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
themeToggles.forEach((themeToggle) => {
|
||||||
|
themeToggle.addEventListener('click', (event) => {
|
||||||
const currentTheme = html.getAttribute('data-theme');
|
const currentTheme = html.getAttribute('data-theme');
|
||||||
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
||||||
setTheme(newTheme);
|
const origin = getTransitionOrigin(event, themeToggle);
|
||||||
|
switchThemeWithScatter(newTheme, origin);
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
|
||||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
||||||
if (!localStorage.getItem('theme')) {
|
if (!localStorage.getItem('theme')) {
|
||||||
|
|||||||
Vendored
+8
File diff suppressed because one or more lines are too long
+3
-2
@@ -124,8 +124,9 @@ function itstudio_enqueue_scripts() {
|
|||||||
|
|
||||||
if ($is_about) {
|
if ($is_about) {
|
||||||
wp_enqueue_style('itstudio-about-hero', get_template_directory_uri() . '/assets/css/about-hero.css', array('itstudio-content'), '2.1.2');
|
wp_enqueue_style('itstudio-about-hero', get_template_directory_uri() . '/assets/css/about-hero.css', array('itstudio-content'), '2.1.2');
|
||||||
wp_enqueue_script('itstudio-about-hero-waves', get_template_directory_uri() . '/assets/js/hero-waves.js', array(), '1.0.0', true);
|
wp_enqueue_script('itstudio-animejs', get_template_directory_uri() . '/assets/js/vendor/anime.min.js', array(), '3.2.2', true);
|
||||||
wp_enqueue_script('itstudio-about-hero', get_template_directory_uri() . '/assets/js/home-hero.js', array(), '1.0.0', true);
|
wp_enqueue_script('itstudio-about-hero-waves', get_template_directory_uri() . '/assets/js/hero-waves.js', array('itstudio-animejs'), '1.0.0', true);
|
||||||
|
wp_enqueue_script('itstudio-about-hero', get_template_directory_uri() . '/assets/js/home-hero.js', array('itstudio-animejs'), '1.0.0', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 仅在便民服务页加载(包含 /services fallback)
|
// 仅在便民服务页加载(包含 /services fallback)
|
||||||
|
|||||||
+21
-211
@@ -6,6 +6,27 @@ get_header();
|
|||||||
<main class="site-main">
|
<main class="site-main">
|
||||||
<canvas class="hero-waves" aria-hidden="true"></canvas>
|
<canvas class="hero-waves" aria-hidden="true"></canvas>
|
||||||
<section class="hero-section">
|
<section class="hero-section">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="theme-toggle about-theme-toggle"
|
||||||
|
aria-label="Toggle Theme"
|
||||||
|
data-cn-aria-label="切换主题"
|
||||||
|
data-en-aria-label="Toggle Theme">
|
||||||
|
<svg class="sun-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||||
|
<circle cx="12" cy="12" r="5"></circle>
|
||||||
|
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||||||
|
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||||||
|
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||||||
|
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||||||
|
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||||||
|
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||||||
|
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||||||
|
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||||||
|
</svg>
|
||||||
|
<svg class="moon-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||||
|
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="hero-content">
|
<div class="hero-content">
|
||||||
<h1 class="hero-title">
|
<h1 class="hero-title">
|
||||||
@@ -19,217 +40,6 @@ get_header();
|
|||||||
<span class="scroll-text" data-cn="向下滑动开始" data-en="Scroll to begin"></span>
|
<span class="scroll-text" data-cn="向下滑动开始" data-en="Scroll to begin"></span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="services-section">
|
|
||||||
<div class="container">
|
|
||||||
<div class="services-provided">
|
|
||||||
<h2 data-cn="# 服务提供" data-en="# Our Services"></h2>
|
|
||||||
<div class="services-grid-box">
|
|
||||||
<a href="#" class="service-item service-resources">
|
|
||||||
<div class="service-icon">
|
|
||||||
<svg class="service-symbol" viewBox="0 0 72 72" fill="none" aria-hidden="true">
|
|
||||||
<circle class="svc-soft" cx="36" cy="36" r="24" />
|
|
||||||
<path class="svc-stroke" d="M17 24h14l4 5h20a4 4 0 0 1 4 4v22a4 4 0 0 1-4 4H17a4 4 0 0 1-4-4V28a4 4 0 0 1 4-4z" />
|
|
||||||
<rect class="svc-soft-strong" x="23" y="33" width="26" height="17" rx="2.6" />
|
|
||||||
<path class="svc-accent" d="M28 38h16M28 43h12M28 48h9" />
|
|
||||||
<path class="svc-muted" d="M51 35v13M51 48l3-3M51 48l-3-3" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<span data-cn="资源站" data-en="Resources"></span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="#" class="service-item service-mirror">
|
|
||||||
<div class="service-icon">
|
|
||||||
<svg class="service-symbol" viewBox="0 0 72 72" fill="none" aria-hidden="true">
|
|
||||||
<circle class="svc-soft" cx="36" cy="36" r="24" />
|
|
||||||
<circle class="svc-stroke" cx="36" cy="36" r="17" />
|
|
||||||
<path class="svc-muted" d="M19 36h34M36 19c5 4.7 7.8 10.5 7.8 17S41 48.3 36 53M36 19c-5 4.7-7.8 10.5-7.8 17S31 48.3 36 53" />
|
|
||||||
<path class="svc-accent" d="M50 29l7 7-7 7" />
|
|
||||||
<path class="svc-accent" d="M57 36H45" />
|
|
||||||
<path class="svc-accent" d="M22 43l-7-7 7-7" />
|
|
||||||
<path class="svc-accent" d="M15 36h12" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<span data-cn="校内镜像站" data-en="Mirror Site"></span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="#" class="service-item service-git">
|
|
||||||
<div class="service-icon">
|
|
||||||
<svg class="service-symbol" viewBox="0 0 72 72" fill="none" aria-hidden="true">
|
|
||||||
<circle class="svc-soft" cx="36" cy="36" r="24" />
|
|
||||||
<rect class="svc-stroke" x="12" y="19" width="30" height="30" rx="4" />
|
|
||||||
<path class="svc-muted" d="M17 27h20M17 33h14" />
|
|
||||||
<circle class="svc-dot" cx="49" cy="24" r="3" />
|
|
||||||
<circle class="svc-dot" cx="49" cy="37" r="3" />
|
|
||||||
<circle class="svc-dot" cx="56" cy="47" r="3" />
|
|
||||||
<path class="svc-accent" d="M41 24h8" />
|
|
||||||
<path class="svc-accent" d="M49 24v13" />
|
|
||||||
<path class="svc-accent" d="M49 37c4 0 7 3 7 7" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<span data-cn="代码托管" data-en="Git Hosting"></span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="#" class="service-item service-minecraft">
|
|
||||||
<div class="service-icon">
|
|
||||||
<svg class="service-symbol" viewBox="0 0 72 72" fill="none" aria-hidden="true">
|
|
||||||
<circle class="svc-soft" cx="36" cy="36" r="24" />
|
|
||||||
<path class="svc-stroke" d="M36 15l20 11v23L36 60 16 49V26l20-11z" />
|
|
||||||
<path class="svc-muted" d="M16 26l20 11 20-11M36 60V37" />
|
|
||||||
<path class="svc-accent" d="M20 23h32" />
|
|
||||||
<rect class="svc-soft-strong" x="24" y="40" width="6" height="6" rx="1.2" />
|
|
||||||
<rect class="svc-soft-strong" x="34" y="43" width="5" height="5" rx="1.1" />
|
|
||||||
<rect class="svc-dot" x="43" y="39" width="6" height="6" rx="1.2" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<span data-cn="Minecraft服务器" data-en="Minecraft Server"></span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="#" class="service-item service-forum">
|
|
||||||
<div class="service-icon">
|
|
||||||
<svg class="service-symbol" viewBox="0 0 72 72" fill="none" aria-hidden="true">
|
|
||||||
<circle class="svc-soft" cx="36" cy="36" r="24" />
|
|
||||||
<path class="svc-stroke" d="M11 28a6 6 0 0 1 6-6h22a6 6 0 0 1 6 6v13a6 6 0 0 1-6 6H28l-8 7v-7h-3a6 6 0 0 1-6-6V28z" />
|
|
||||||
<path class="svc-accent" d="M36 19a6 6 0 0 1 6-6h13a6 6 0 0 1 6 6v9a6 6 0 0 1-6 6h-5l-4 4v-4h-4a6 6 0 0 1-6-6v-9z" />
|
|
||||||
<circle class="svc-dot" cx="24" cy="35" r="1.8" />
|
|
||||||
<circle class="svc-dot" cx="31" cy="35" r="1.8" />
|
|
||||||
<circle class="svc-dot" cx="46" cy="24" r="1.7" />
|
|
||||||
<circle class="svc-dot" cx="52" cy="24" r="1.7" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<span data-cn="OUC论坛" data-en="OUC Forum"></span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="#" class="service-item service-repair">
|
|
||||||
<div class="service-icon">
|
|
||||||
<svg class="service-symbol" viewBox="0 0 72 72" fill="none" aria-hidden="true">
|
|
||||||
<circle class="svc-soft" cx="36" cy="36" r="24" />
|
|
||||||
<rect class="svc-stroke" x="11" y="18" width="37" height="25" rx="4" />
|
|
||||||
<path class="svc-muted" d="M29.5 43v6M22 49h15" />
|
|
||||||
<path class="svc-accent" d="M38 24.5a4.7 4.7 0 0 0-6.5 6.6l-7.2 7.2 3.4 3.4 7.2-7.2a4.7 4.7 0 0 0 6.6-6.5l-3 3-2.6-2.6 2.1-3z" />
|
|
||||||
<path class="svc-accent" d="M50 19l10 10" />
|
|
||||||
<circle class="svc-dot" cx="55" cy="24" r="2" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<span data-cn="电脑维修" data-en="PC Repair"></span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="#" class="service-item service-workshop">
|
|
||||||
<div class="service-icon">
|
|
||||||
<svg class="service-symbol" viewBox="0 0 72 72" fill="none" aria-hidden="true">
|
|
||||||
<circle class="svc-soft" cx="36" cy="36" r="24" />
|
|
||||||
<rect class="svc-stroke" x="12" y="17" width="48" height="36" rx="5" />
|
|
||||||
<path class="svc-muted" d="M12 30h48M24 12v10M48 12v10" />
|
|
||||||
<rect class="svc-soft-strong" x="24" y="36" width="24" height="13" rx="3" />
|
|
||||||
<path class="svc-accent" d="M29 42l4 4 9-9" />
|
|
||||||
<circle class="svc-dot" cx="22" cy="24" r="1.8" />
|
|
||||||
<circle class="svc-dot" cx="30" cy="24" r="1.8" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<span data-cn="五八工坊预约" data-en="Workshop Booking"></span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="#" class="service-item service-campus">
|
|
||||||
<div class="service-icon">
|
|
||||||
<svg class="service-symbol" viewBox="0 0 72 72" fill="none" aria-hidden="true">
|
|
||||||
<circle class="svc-soft" cx="36" cy="36" r="24" />
|
|
||||||
<path class="svc-stroke" d="M36 14l18 8v14c0 12-7 20-18 25-11-5-18-13-18-25V22l18-8z" />
|
|
||||||
<path class="svc-muted" d="M36 24c-4.5 0-8 3.5-8 8 0 5.5 8 13 8 13s8-7.5 8-13c0-4.5-3.5-8-8-8z" />
|
|
||||||
<circle class="svc-soft-strong" cx="36" cy="32" r="3.2" />
|
|
||||||
<circle class="svc-soft-strong" cx="52" cy="22" r="5.2" />
|
|
||||||
<path class="svc-accent" d="M49.5 22H54.5M52 19.5v5" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<span data-cn="OUC便民服务" data-en="OUC Services"></span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="content-section">
|
|
||||||
<div class="container">
|
|
||||||
<div class="content-grid">
|
|
||||||
<div class="announcements-column">
|
|
||||||
<h2 data-cn="# 公告通知" data-en="# Announcements"></h2>
|
|
||||||
<div class="post-list">
|
|
||||||
<?php
|
|
||||||
$announcements = new WP_Query(array(
|
|
||||||
'post_type' => 'announcement',
|
|
||||||
'post_status' => 'publish',
|
|
||||||
'posts_per_page' => 5,
|
|
||||||
'orderby' => 'date',
|
|
||||||
'order' => 'DESC',
|
|
||||||
'ignore_sticky_posts' => true,
|
|
||||||
'no_found_rows' => true
|
|
||||||
));
|
|
||||||
|
|
||||||
if ($announcements->have_posts()) :
|
|
||||||
while ($announcements->have_posts()) : $announcements->the_post();
|
|
||||||
?>
|
|
||||||
<article class="post-item">
|
|
||||||
<div class="post-content-wrapper">
|
|
||||||
<h3 class="post-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
|
|
||||||
<div class="post-excerpt">
|
|
||||||
<?php the_excerpt(); ?>
|
|
||||||
</div>
|
|
||||||
<div class="post-meta">
|
|
||||||
<span class="post-author"><?php echo get_the_author(); ?></span>
|
|
||||||
<time datetime="<?php echo get_the_date('c'); ?>"><?php echo get_the_date('Y年m月d日'); ?></time>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
<?php
|
|
||||||
endwhile;
|
|
||||||
wp_reset_postdata();
|
|
||||||
else :
|
|
||||||
?>
|
|
||||||
<p data-cn="暂无公告" data-en="No announcements found."></p>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="blog-column">
|
|
||||||
<h2 data-cn="# 技术博客" data-en="# Blog"></h2>
|
|
||||||
<div class="post-list">
|
|
||||||
<?php
|
|
||||||
$blogs = new WP_Query(array(
|
|
||||||
'post_type' => 'post',
|
|
||||||
'post_status' => 'publish',
|
|
||||||
'posts_per_page' => 5,
|
|
||||||
'orderby' => 'date',
|
|
||||||
'order' => 'DESC',
|
|
||||||
'ignore_sticky_posts' => true,
|
|
||||||
'no_found_rows' => true
|
|
||||||
));
|
|
||||||
|
|
||||||
if ($blogs->have_posts()) :
|
|
||||||
while ($blogs->have_posts()) : $blogs->the_post();
|
|
||||||
?>
|
|
||||||
<article class="post-item">
|
|
||||||
<div class="post-content-wrapper">
|
|
||||||
<h3 class="post-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
|
|
||||||
<div class="post-excerpt">
|
|
||||||
<?php the_excerpt(); ?>
|
|
||||||
</div>
|
|
||||||
<div class="post-meta">
|
|
||||||
<span class="post-author"><?php echo get_the_author(); ?></span>
|
|
||||||
<time datetime="<?php echo get_the_date('c'); ?>"><?php echo get_the_date('Y年m月d日'); ?></time>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
<?php
|
|
||||||
endwhile;
|
|
||||||
wp_reset_postdata();
|
|
||||||
else :
|
|
||||||
?>
|
|
||||||
<p data-cn="暂无博客文章" data-en="No blog posts found."></p>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<?php get_footer(); ?>
|
<?php get_footer(); ?>
|
||||||
|
|||||||
Reference in New Issue
Block a user