feat: add ads/sponsor/captcha modules and polish home & chat UI

This commit is contained in:
2026-09-23 04:39:58 +08:00
parent 96314893bb
commit c1f6a6636b
27 changed files with 4278 additions and 121 deletions

View File

@@ -0,0 +1,73 @@
"use client";
import { useEffect, useRef, useState, type CSSProperties } from "react";
type AdTextProps = {
title: string;
textColor?: string;
bgColor?: string;
href?: string;
className?: string;
};
/**
* 文字广告:仅当文字宽度超出容器时才启用跑马灯滚动,
* 能完整显示时居中静止。结构与样式复用侧栏 .j13-ad-text。
*/
export function AdText({ title, textColor, bgColor, href, className = "" }: AdTextProps) {
const trackRef = useRef<HTMLSpanElement>(null);
const [overflow, setOverflow] = useState(false);
useEffect(() => {
const track = trackRef.current;
if (!track) return;
const measure = () => {
const run = track.querySelector<HTMLElement>(".j13-ad-text-run");
const container = track.parentElement;
if (!run || !container) return;
setOverflow(run.scrollWidth > container.clientWidth);
};
measure();
window.addEventListener("resize", measure);
return () => window.removeEventListener("resize", measure);
}, [title]);
const cls = `j13-ad-text${overflow ? " is-overflow" : ""}${className ? ` ${className}` : ""}`;
const style: CSSProperties = { color: textColor, background: bgColor };
const inner = (
<span
className={`j13-ad-text-track${overflow ? " is-overflow" : ""}`}
ref={trackRef}
>
<span className="j13-ad-text-run">{title}</span>
{overflow ? (
<span className="j13-ad-text-run" aria-hidden>
{title}
</span>
) : null}
</span>
);
if (href) {
return (
<a
href={href}
target="_blank"
rel="noopener noreferrer sponsored"
className={cls}
style={style}
data-tip={title}
>
{inner}
</a>
);
}
return (
<span className={cls} style={style} data-tip={title}>
{inner}
</span>
);
}
export default AdText;