活动及套餐包余额购买

This commit is contained in:
lyp 2025-08-07 10:10:19 +08:00
parent a3e0c07467
commit 5b0f18bc3c
4 changed files with 145 additions and 27 deletions

View File

@ -127,7 +127,7 @@ import active from '../../static/active.gif'
import { DownOutlined, UserOutlined, QuestionCircleOutlined, BellOutlined, KeyOutlined, LogoutOutlined, GiftOutlined, AccountBookOutlined, ContainerOutlined, MenuFoldOutlined, UsergroupAddOutlined, TableOutlined } from "@ant-design/icons";
import {
useContext, useEffect, useState,
// useRef
useRef
} from "react";
import {
put, get,
@ -159,6 +159,40 @@ import NoticeModal from '../../components/NoticeModal/NoticeModal.tsx';
// import { log } from 'console';
// import HeadCouponModal from '../../components/CouponModal/HeadCouponModal.tsx'
export default function Head() {
const activeBtnRef = useRef<HTMLDivElement>(null);
// 计算元素中心点坐标的函数
const calculateCenterPoint = () => {
// 先检查 ref 是否存在,避免 null 错误
if (activeBtnRef.current) {
const rect = activeBtnRef.current.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
// setCenterPoint({ x: centerX, y: centerY });
// console.log(`元素中心点坐标: (${centerX}, ${centerY})`);
dispath({
type: 'upCenterPoint',
val: { x: centerX, y: centerY }
})
}
};
// 组件挂载后计算一次(确保元素已渲染)
useEffect(() => {
calculateCenterPoint();
// 监听窗口大小变化,重新计算(如果元素位置可能因窗口变化而改变)
const handleResize = () => {
calculateCenterPoint();
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
// const currentUrl = window.location.href;
// const formRef = useRef<HTMLFormElement>(null);
// const triggerFormSubmit = () => {
@ -166,6 +200,8 @@ export default function Head() {
// formRef.current.submit();
// }
// };
// lyp
const [form] = Form.useForm<any>();
const [isUpdateWxUsernamePhone, setIsUpdateWxUsernamePhone] = useState(false); // 绑定手机号号弹窗
@ -383,6 +419,7 @@ export default function Head() {
// const [packageType, setPackageType] = useState('')
const packNum = redxuState.packNum
const phoneModal = redxuState.phoneModal
const activityImgShow = redxuState.activityImgShow //是否显示互动图片
// const activityModal = redxuState.activityModal
// const packItems: MenuProps['items'] = [
// {
@ -1285,10 +1322,13 @@ export default function Head() {
{/* <div className="right" style={{backgroundImage: `url(${headRightBg})`}}> */}
<div className="right">
<div style={{
marginRight: 20,
cursor:'pointer'
}}
<div
ref={activeBtnRef}
style={{
marginRight: 20,
cursor: 'pointer',
display:activityImgShow ? 'unset' : 'none',
}}
onClick={() => {
// setActivityModal(true)
dispath({

View File

@ -234,9 +234,9 @@ newRequest.interceptors.response.use(
// 下载发票
export const downloadInvoice = (id: string) => {
return `${operatorPluginBaseUrl}/operator-plugin/route/file/download/false/${id}`
// return `${operatorPluginBaseUrl}/operator-plugin/route/file/download/false/${id}`
//测试
// return `http://192.168.0.115:8099/operator-plugin/route/file/download/false/${id}`
return `http://192.168.0.115:8099/operator-plugin/route/file/download/false/${id}`
};

View File

@ -105,6 +105,7 @@ import noFirImg from '../../static/noFir.png'
export default function Index() {
// 活动图片
const [activityImg, setActivityImg] = useState('')
// 活动名称
@ -135,6 +136,12 @@ export default function Index() {
val: true,
})
}
if (!res.title) {
dispath({
type: 'setActivityImgShow',
val: false,
})
}
setActivityImg(downloadInvoice(res.image))
setActivityTitle(res.title)
setActivityText(res.help)
@ -287,6 +294,42 @@ export default function Index() {
const redxuState: any = useSelector(state => state)
const phoneModal = redxuState.phoneModal
const activityModal = redxuState.activityModal
const centerPoint = redxuState.centerPoint
// 动画状态管理----------------------------------------------
const [isClosing, setIsClosing] = useState(false);
const animationDuration = 300; // 动画持续时间(毫秒)
// 定义收缩的目标坐标(固定点)- 可以根据需求调整
// const targetPosition = {
// x: 50, // 目标X坐标从左侧开始计算
// y: 50 // 目标Y坐标从顶部开始计算
// };
const handleClose = () => {
// 开始关闭动画
setIsClosing(true);
// 动画结束后执行状态更新
setTimeout(() => {
dispath({
type: 'setActivityModal',
val: false,
});
// 当勾选"近期不再提示"时设置cookie
if (activityChecked) {
const date = new Date();
date.setDate(date.getDate() + activityCycle);
document.cookie = `closeActivityModal=${activityCycle}; expires=${date.toUTCString()}; path=/`;
}
// 重置关闭状态,为下次显示做准备
setIsClosing(false);
}, animationDuration);
}
// 动画完毕 ---------------------------------------
// const belongArray = redxuState.belongArray
//监听cookie里面如果有closeActivityModal这个值 则打印这个值
@ -2010,7 +2053,7 @@ export default function Index() {
// 获取cookie里面的closeActivityModal的值
// console.log(closeActivityModal);
}, []);
useEffect(() => {
// loactionStorage里的activeMenu
@ -4757,10 +4800,31 @@ export default function Index() {
<div className='couponMask-box'
style={{
display: activityModal && (location.pathname == '/' || location.pathname.includes('/home')) ? 'unset' : 'none',
zIndex: 100
zIndex: 98,
// 动画
pointerEvents: isClosing ? 'none' : 'auto', // 动画期间不响应鼠标事件
}}
>
<div className='couponMask' >
<div className='couponMask'
// 动画
style={{
// position: 'absolute',
position: 'absolute',
// 初始位置:居中显示(保持不变)
top: isClosing ? centerPoint.y : '50%', // 关闭时top直接设为目标点y坐标
left: isClosing ? centerPoint.x - 80 : '50%', // 关闭时left直接设为目标点x坐标
// 关键用translate(-50%, -50%)确保元素中心点与目标点对齐
transform: isClosing
? 'translate(-50%, -50%) scale(0.1)' // 关闭时:缩放到目标点(中心点对齐)
: 'translate(-50%, -50%) scale(1)', // 初始时:居中显示
opacity: isClosing ? 0 : 1,
transition: `all ${animationDuration}ms cubic-bezier(0.25, 0.46, 0.45, 0.94)`,
zIndex: 101,
}}
>
<div style={{
// background: 'skyblue',
// 背景图设置为activityImg
@ -4792,19 +4856,19 @@ export default function Index() {
).then(() => {
messageApi.success('邀请码已复制到剪贴板');
}).catch(() => {
messageApi.error('复制失败,请手动复制');
messageApi.error('复制失败');
});
} else {
// 兼容旧浏览器
const input = document.createElement('input');
input.value = 'http://127.0.0.1:5500/Register.html?code=' + activityCode;
input.value = 'http://127.0.0.1:5500/Register.html?code=' + activityCode;
document.body.appendChild(input);
input.select();
try {
document.execCommand('copy');
messageApi.success('邀请码已复制到剪贴板');
} catch {
messageApi.error('复制失败,请手动复制');
messageApi.error('复制失败');
}
document.body.removeChild(input);
}
@ -4832,18 +4896,23 @@ export default function Index() {
</div>
<div className='activityMask-close' onClick={() => {
dispath({
type: 'setActivityModal',
val: false,
})
// 当activityChecked为true时 再cooke中存入一个维持activityCycle天数的值
if (activityChecked) {
const date = new Date();
date.setDate(date.getDate() + activityCycle);
document.cookie = `closeActivityModal=${activityCycle}; expires=${date.toUTCString()}; path=/`;
}
}}>
<div className='activityMask-close' onClick={
// () => {
// dispath({
// type: 'setActivityModal',
// val: false,
// })
// // 当activityChecked为true时 再cooke中存入一个维持activityCycle天数的值
// if (activityChecked) {
// const date = new Date();
// date.setDate(date.getDate() + activityCycle);
// document.cookie = `closeActivityModal=${activityCycle}; expires=${date.toUTCString()}; path=/`;
// }
// }
// 动画
handleClose
}>
<CloseOutlined />
</div>
</div>

View File

@ -29,7 +29,10 @@ const baseState = {
replaceArray: [],
replaceTotal: 0,
newReplace: false,
activityModal:false, //活动弹窗
activityModal: false, //活动弹窗
activityImgShow: true, //活动图片是否展示
// 坐标
centerPoint: { x: 0, y: 0 },
}
// 创建仓库
@ -98,9 +101,15 @@ const reducer = (state = baseState, action: any) => {
if (action.type == 'newReplace') {
nstate.newReplace = action.val
}
if (action.type == 'setActivityModal') {
if (action.type == 'setActivityModal') {
nstate.activityModal = action.val
}
if (action.type == 'upCenterPoint') {
nstate.centerPoint = action.val
}
if (action.type == 'setActivityImgShow') {
nstate.activityImgShow = action.val
}
return nstate
}
const store = createStore(reducer)