Merge branch 'main' of http://113.45.67.59:3003/qiuchenfan/news
This commit is contained in:
commit
10506e6295
|
|
@ -0,0 +1,101 @@
|
|||
import React, { useState } from 'react';
|
||||
import { usePopupManager } from './Popup';
|
||||
|
||||
// 单独的“添加飘窗”表单弹窗组件
|
||||
const AddPopupForm = () => {
|
||||
const { addPopup } = usePopupManager();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [formData, setFormData] = useState({
|
||||
title: '',
|
||||
description: '',
|
||||
backgroundImage: '',
|
||||
});
|
||||
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData((prev) => ({ ...prev, [name]: value }));
|
||||
};
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (!formData.title.trim() || !formData.description.trim()) return;
|
||||
addPopup({
|
||||
title: formData.title,
|
||||
description: formData.description,
|
||||
backgroundImage: formData.backgroundImage || undefined,
|
||||
});
|
||||
setIsOpen(false);
|
||||
setFormData({ title: '', description: '', backgroundImage: '' });
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
onClick={() => setIsOpen(true)}
|
||||
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition"
|
||||
>
|
||||
+ 添加飘窗
|
||||
</button>
|
||||
{isOpen && (
|
||||
<div className="fixed inset-0 bg-black bg-opacity-40 flex items-center justify-center z-50 p-4">
|
||||
<div className="bg-white rounded-lg w-full max-w-md p-6 relative">
|
||||
<button
|
||||
onClick={() => setIsOpen(false)}
|
||||
className="absolute top-3 right-3 text-gray-500 hover:text-gray-800"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
<h2 className="text-xl font-bold mb-4">添加飘窗</h2>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<input
|
||||
name="title"
|
||||
placeholder="标题"
|
||||
value={formData.title}
|
||||
onChange={handleChange}
|
||||
className="w-full mb-3 px-3 py-2 border rounded"
|
||||
required
|
||||
/>
|
||||
<input
|
||||
name="backgroundImage"
|
||||
placeholder="背景图 URL(可选)"
|
||||
type="url"
|
||||
value={formData.backgroundImage}
|
||||
onChange={handleChange}
|
||||
className="w-full mb-3 px-3 py-2 border rounded"
|
||||
/>
|
||||
<textarea
|
||||
name="description"
|
||||
placeholder="详细说明"
|
||||
value={formData.description}
|
||||
onChange={handleChange}
|
||||
rows={3}
|
||||
className="w-full mb-4 px-3 py-2 border rounded"
|
||||
required
|
||||
|
||||
/>
|
||||
|
||||
<div className="flex justify-end gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsOpen(false)}
|
||||
className="px-3 py-1.5 border rounded"
|
||||
>
|
||||
取消
|
||||
</button>
|
||||
<button type="submit" className="px-3 py-1.5 bg-blue-600 text-white rounded">
|
||||
创建
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</>
|
||||
|
||||
);
|
||||
|
||||
};
|
||||
export default AddPopupForm;
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
// src/components/FloatingPopupManager.tsx
|
||||
import React, { useState, createContext, useContext, type ReactNode } from 'react';
|
||||
|
||||
type PopupItem = {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
backgroundImage?: string;
|
||||
};
|
||||
|
||||
type PopupContextType = {
|
||||
addPopup: (popup: Omit<PopupItem, 'id'>) => void;
|
||||
};
|
||||
|
||||
const PopupContext = createContext<PopupContextType | undefined>(undefined);
|
||||
|
||||
export const usePopupManager = () => {
|
||||
const context = useContext(PopupContext);
|
||||
if (!context) {
|
||||
throw new Error('usePopupManager must be used within a PopupProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
export const FloatingPopupManager: React.FC<{ children: ReactNode }> = ({ children }) => {
|
||||
const [popups, setPopups] = useState<PopupItem[]>([]);
|
||||
|
||||
const addPopup = (popup: Omit<PopupItem, 'id'>) => {
|
||||
const newPopup: PopupItem = {
|
||||
...popup,
|
||||
id: Date.now().toString(),
|
||||
};
|
||||
setPopups((prev) => [...prev, newPopup]);
|
||||
};
|
||||
|
||||
const removePopup = (id: string) => {
|
||||
setPopups((prev) => prev.filter((p) => p.id !== id));
|
||||
};
|
||||
|
||||
return (
|
||||
<PopupContext.Provider value={{ addPopup }}>
|
||||
{children}
|
||||
|
||||
{/* 渲染所有飘窗 */}
|
||||
<div className="fixed bottom-4 right-4 space-y-3 z-[9999] pointer-events-none">
|
||||
{popups.map((popup, index) => (
|
||||
<div
|
||||
key={popup.id}
|
||||
className="pointer-events-auto relative bg-white shadow-xl rounded-lg w-80 overflow-hidden border border-gray-200"
|
||||
style={{
|
||||
transform: `translateY(${index * 12}px)`,
|
||||
}}
|
||||
>
|
||||
{/* 背景区域 */}
|
||||
{popup.backgroundImage ? (
|
||||
<div className="h-32 w-full overflow-hidden">
|
||||
<img
|
||||
src={popup.backgroundImage}
|
||||
alt=""
|
||||
className="w-full h-full object-cover opacity-90"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="h-32 bg-gradient-to-r from-blue-500 to-indigo-600"></div>
|
||||
)}
|
||||
|
||||
{/* 内容 */}
|
||||
<div className="p-4">
|
||||
<div className="flex justify-between items-start">
|
||||
<h3 className="text-lg font-bold text-gray-800">{popup.title}</h3>
|
||||
<button
|
||||
onClick={() => removePopup(popup.id)}
|
||||
className="text-gray-500 hover:text-gray-800 text-xl font-bold"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
<p className="mt-2 text-gray-600 text-sm">{popup.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</PopupContext.Provider>
|
||||
);
|
||||
};
|
||||
|
|
@ -55,7 +55,7 @@ const Train = () => {
|
|||
{ src: '/images/carousel-3.jpg', colSpan: 2, link: 'https://www.baidu.com' },
|
||||
{ src: '/images/carousel-4.jpg', colSpan: 3, link: 'https://www.baidu.com' },
|
||||
{ src: '/logo/logo2.png', colSpan: 1, link: '' },
|
||||
{ src: '/images/carousel-5.jpg', colSpan: 1, link: 'https://www.baidu.com' },
|
||||
{ src: '/images/carousel-5.jpg', colSpan: 2, link: 'https://www.baidu.com' },
|
||||
{ src: '/images/carousel-7.jpg', colSpan: 3, link: 'https://www.baidu.com' },
|
||||
];
|
||||
{/* 弹性 默认纵向 大屏横向 */ }
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import { Hotline } from "@/components/news/body/FireNews/Hotline";
|
|||
import { AutoCarouselDemo } from "@/components/AutoCarousel";
|
||||
import Footer from "@/components/news/footer/footer";
|
||||
import Train from "@/components/news/body/Train";
|
||||
import AddPopupForm from "@/components/news/body/PopupfloatingMangement/AddPopup";
|
||||
|
||||
|
||||
export function meta( ) {
|
||||
return [
|
||||
|
|
@ -44,6 +46,8 @@ export default function Home() {
|
|||
</div>
|
||||
<Footer />
|
||||
<Train />
|
||||
<AddPopupForm />
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue