This commit is contained in:
eric
2025-12-18 01:54:18 -06:00
parent dcd31ad5b4
commit 956e108268
4 changed files with 21777 additions and 53 deletions

View File

@@ -125,7 +125,7 @@ const config = {
},
},
// 允许特定域名访问
allowedHosts: ["nomadro.com", "localhost", ".nomadro.com","hackrobot.cn",".hackrobot.cn"], // 允许所有 *.nomadyt.com 子域访问
allowedHosts: ["nomadro.com", "localhost", ".nomadro.com","hackrobot.cn",".hackrobot.cn",".ngrok-free.app"], // 允许所有 *.nomadyt.com 子域访问
},
htmlPluginOption: {
favicon: path.resolve(__dirname, "..", "src", "images", "avatar.jpg"), // 同样处理 favicon 路径

21501
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -20,6 +20,7 @@
<script>
<%= htmlWebpackPlugin.options.script %>
</script>
<script src="https://unpkg.com/pocketbase/dist/pocketbase.umd.js"></script>
<!-- 禁止缓存 -->
<meta
http-equiv="Cache-Control"

View File

@@ -66,9 +66,19 @@ import planet from "../../images/avatar.jpg";
import book from "../../images/book.svg";
import youtubesvg from "../../images/youtube.svg";
// PocketBase 配置
const PB_URL = 'https://pocketbase.hackrobot.cn';
const pb = new PocketBase(PB_URL);
// export default class Index extends Component {
const Index = () => {
const [vip, setvip] = useState(window.localStorage.getItem("vip"));
// const [vip, setvip] = useState(window.localStorage.getItem("vip"));
const [paidType, setPaidType] = useState(null); // 新增:支付类型 'vip' | 'book' | null
const [userName, setUserName] = useState(Taro.getStorageSync('userName') || null); // 新增
const [loading, setLoading] = useState(true); // 新增:加载状态
const [current, setcurrent] = useState(0);
const [openId, setopenId] = useState(null);
const [wxid, setwxid] = useState(null);
@@ -87,7 +97,7 @@ const Index = () => {
const [bookpay, setbookpay] = useState(0);
const [isWeChat, setisWeChat] = useState(false);
const [markText, setmarkText] = useState(vip == 1 ? index : index);
const [markText, setmarkText] = useState(paidType ? index : index);
const [headers, setHeaders] = useState([]); // 存储所有 <h1> 的内容
const contentRef = useRef(null); // 用于获取渲染后的 DOM
@@ -181,7 +191,7 @@ const Index = () => {
let nowUrl = window.location.href;
window.localStorage.removeItem("openid");
let payUrl = `https://payjs.cn/api/openid?mchid=1561724891&callback_url=${nowUrl}`;
window.location.href = payUrl;
// window.location.href = payUrl;
}
};
@@ -201,7 +211,7 @@ const Index = () => {
}
}
},
complete: function (finy) {},
complete: function (finy) { },
});
};
@@ -271,9 +281,9 @@ const Index = () => {
header: {
"Content-Type": "application/json",
},
success: function (res) {},
fail: function (err) {},
complete: function (finy) {},
success: function (res) { },
fail: function (err) { },
complete: function (finy) { },
});
};
@@ -292,9 +302,9 @@ const Index = () => {
header: {
"Content-Type": "application/json",
},
success: function (res) {},
fail: function (err) {},
complete: function (finy) {},
success: function (res) { },
fail: function (err) { },
complete: function (finy) { },
});
};
@@ -302,9 +312,8 @@ const Index = () => {
const tgMessage = () => {
Taro.request({
method: "GET",
url: `${
process.env.TARO_API_API
}/tgMessage?openid=${window.localStorage.getItem("openid")}`, //仅为示例,并非真实的接口地址
url: `${process.env.TARO_API_API
}/tgMessage?openid=${window.localStorage.getItem("openid")}`, //仅为示例,并非真实的接口地址
// url: "https://pay.hackrobot.cn${process.env.TARO_API_API}/payh5", //仅为示例,并非真实的接口地址
success: function (res) {
console.log("访问提醒发送成功");
@@ -312,16 +321,151 @@ const Index = () => {
});
};
// 入群申请
// 保存 userName 到本地
const saveUserName = (name) => {
Taro.setStorageSync('userName', name);
setUserName(name);
};
// 获取本地 userName
const getLocalUserName = () => {
return Taro.getStorageSync('userName') || null;
};
// 检查本地是否已有支付类型
const getLocalPaidType = () => {
return Taro.getStorageSync('paidType') || null;
};
// 保存支付类型到本地
const savePaidType = (type) => {
Taro.setStorageSync('paidType', type);
setPaidType(type);
};
// 查询 PocketBase 是否支付过
const checkPaymentFromPB = async (userId) => {
// window.alert('查询pocketbase')
try {
// 查询 payments 表中该 user_id 的记录,按创建时间倒序(最新的一笔)
const records = await pb.collection('payments').getList(1, 1, {
filter: `user_id = "${userId}"`,
sort: '-created', // 最新支付优先
});
if (records.items.length > 0) {
const latestType = records.items[0].type; // 取最新一笔的 type
const dbUserId = records.items[0].user_id; // 数据库里的真实 user_id
// window.alert('latestType', dbUserId)
savePaidType(latestType);
saveUserName(dbUserId); // ← 关键:缓存数据库里的 user_id 作为 userName
console.log('从 PocketBase 查询到已支付:', latestType);
return latestType;
} else {
// window.alert('未找到支付记录')
console.log('未找到支付记录');
savePaidType(null);
return null;
}
} catch (err) {
// window.alert('查询 PocketBase 失败', err)
console.error('查询 PocketBase 失败:', err);
// 网络错误时不影响本地缓存,使用本地旧值
return getLocalPaidType();
} finally {
}
};
// useEffect(() => {
// // 生成userId
// getOrCreateUserId(); // ← 新增:获取 userId
// let inwechat = isWeChatFun();
// if (inwechat) {
// // 获取openId
// getOpenid();
// } else {
// // window.alert('不在微信')
// }
// }, []);
// 清空所有本地存储(测试专用)
const clearAllStorage = () => {
try {
// 清空 Taro 的 storage推荐方式
Taro.clearStorageSync();
// 同时清空 window.localStorageH5 环境兼容)
if (typeof window !== 'undefined' && window.localStorage) {
window.localStorage.clear();
}
// 可选:手动清除你知道的关键字段,防止残留
Taro.removeStorageSync('userId');
Taro.removeStorageSync('paidType');
Taro.removeStorageSync('userName');
Taro.removeStorageSync('openid');
Taro.removeStorageSync('wxid');
// 状态重置
setPaidType(null);
setUserName(null);
setLoading(false);
Taro.showToast({
title: '本地存储已清空',
icon: 'success',
duration: 2000,
});
// 可选:刷新页面让效果立即生效
setTimeout(() => {
// window.location.reload();
}, 1000);
} catch (error) {
console.error('清空存储失败:', error);
Taro.showToast({
title: '清空失败',
icon: 'none',
});
}
};
useEffect(() => {
let inwechat = isWeChatFun();
if (inwechat) {
// 获取openId
getOpenid();
} else {
// window.alert('不在微信')
}
// 判断是否在微信
isWeChatFun()
// 测试用=>清除缓存
// clearAllStorage()
const init = async () => {
getOrCreateUserId(); // 确保 userId 存在
const localType = getLocalPaidType();
const localUserName = getLocalUserName();
if (localType && localUserName) {
setPaidType(localType);
setUserName(localUserName);
setLoading(false);
console.log('使用本地缓存:', localType, localUserName);
return;
}
const userId = Taro.getStorageSync('userId');
if (userId) {
await checkPaymentFromPB(userId);
} else {
setLoading(false);
}
};
init();
}, []);
useEffect(() => {
@@ -363,7 +507,7 @@ const Index = () => {
});
};
const payh5 = (type, total_fee = 1000) => {
const payh51111 = (type, total_fee = 1000) => {
// console.log("111");
Taro.request({
method: "POST",
@@ -408,7 +552,7 @@ const Index = () => {
window.localStorage.setItem("password", "123456");
WeixinJSBridge.call("closeWindow");
} else {
window.alert("支付取消/失败");
// window.alert("支付取消/失败");
}
}
);
@@ -416,6 +560,81 @@ const Index = () => {
});
};
// 生成或获取 userId修改为无下划线
const getOrCreateUserId = () => {
let userId = Taro.getStorageSync("userId");
if (!userId) {
// 修改这里:去掉下划线
userId = `user${Date.now()}`; // 示例user1766043770158
Taro.setStorageSync("userId", userId);
console.log('新生成 userId:', userId);
}
return userId;
};
const payh5 = (type, total_fee = 1000) => {
const userId = getOrCreateUserId(); // ← 新增:获取 userId
Taro.request({
method: "POST",
url: `${process.env.TARO_API_API}/payh5`,
data: {
total_fee: total_fee,
type: type,
// callback_url 临时不传
user_id: userId, // ← 新增字段
},
header: {
"content-type": "application/json",
},
success: (res) => {
if (res.data?.status === "ok" && res.data?.xorpay_params) {
// 1. 乐观更新:立即缓存 paidType用户看到“加载中”或直接显示已支付
// savePaidType(type);
// saveUserName(userId); // ← 乐观缓存当前 userId
// Taro.showToast({
// title: "正在跳转支付,请稍后...",
// icon: "loading",
// duration: 2000,
// });
// 创建隐藏 form POST 到 XorPay
const form = document.createElement("form");
form.method = "POST";
form.action = res.data.xorpay_url;
form.style.display = "none";
for (const key in res.data.xorpay_params) {
const input = document.createElement("input");
input.type = "hidden";
input.name = key;
input.value = res.data.xorpay_params[key];
form.appendChild(input);
}
document.body.appendChild(form);
form.submit();
// 2. 可选:提交后清理 form避免内存泄漏
setTimeout(() => {
document.body.removeChild(form);
}, 1000);
} else {
Taro.showToast({
title: "支付发起失败",
icon: "none",
});
}
},
fail: () => {
Taro.showToast({
title: "网络错误",
icon: "none",
});
},
});
};
const goRead = () => {
Taro.navigateTo({
url: "/pages/book/index",
@@ -423,7 +642,9 @@ const Index = () => {
};
const handleCopyUsername = () => {
Taro.setClipboardData({
data: window.localStorage.getItem("username"), // 复制账号
// data: window.localStorage.getItem("userId"), // 复制账号
data: userName || '',
success: () => {
Taro.showToast({
title: "账号已复制",
@@ -506,7 +727,6 @@ const Index = () => {
<View className="cardItem_left">
<Image className="cardItem_left_img" src={group}></Image>
{/* <Image className="cardItem_left_img" src={planet}></Image> */}
</View>
<View className="cardItem_right">
<View className="cardItem_rightUp">不只云手机</View>
@@ -519,22 +739,45 @@ const Index = () => {
className="markdown-body markVip" // 添加 GitHub Markdown 主题类
dangerouslySetInnerHTML={{
// __html: marked(markText),
__html: marked(vip == 1 ? index : index),
__html: marked(paidType ? index : index),
}}
></View>
<View className="left_btn">
{vip != 1 ? (
{paidType === 'vip' ? (
<View className="vipcode">
<View
onClick={() => {
window.location.href = `https://qun.hackrobot.cn`;
}}
>
{/* 👉星球地址: memos.hackrobot.org */}
👉星球地址: qun.hackrobot.cn
</View>
<View>账号:{Taro.getStorageSync('userName')}</View>
<Button onClick={handleCopyUsername}>复制账号</Button>
<View>密码:{"123456"}</View>{" "}
{/* <View>
添加
<span style={{ color: "green" }}>微信好友: hackrobot</span>
</View> */}
{/* <Image className="vipcodeImg" src={hackrobot}></Image> */}
{/* <View>获取 账号</View> */}
</View>
) : (
<AtButton
onClick={() => {
// md页面
// goRead();
if (vip == 1) {
// window.alert("paidType---", paidType)
if (paidType) {
return false;
} else {
// window.alert('isWeChat--', isWeChat)
if (!!isWeChat) {
//98元
payh5("vip", 18800);
payh5("vip", 10);
} else {
window.location.href = `https://mp.weixin.qq.com/s/16xcMIgxEEGBPY7fanNq0g`;
}
@@ -547,27 +790,6 @@ const Index = () => {
>
{`${"加 入 交 流"}`}
</AtButton>
) : (
<View className="vipcode">
<View
onClick={() => {
window.location.href = `https://qun.hackrobot.cn`;
}}
>
{/* 👉星球地址: memos.hackrobot.org */}
👉星球地址: qun.hackrobot.cn
</View>
<View>账号:{window.localStorage.getItem("username")}</View>
<Button onClick={handleCopyUsername}>复制账号</Button>
<View>密码:{"123456"}</View>{" "}
{/* <View>
添加
<span style={{ color: "green" }}>微信好友: hackrobot</span>
</View> */}
{/* <Image className="vipcodeImg" src={hackrobot}></Image> */}
{/* <View>获取 账号</View> */}
</View>
)}
</View>
</View>
@@ -576,7 +798,7 @@ const Index = () => {
className="book_img"
// style="width: 40%px;height:100%;background: #fff;"
src={touxiang}
// src={phone2}
// src={phone2}
/>
</View>
</View>
@@ -588,7 +810,7 @@ const Index = () => {
// style="width: 40%px;height:100%;background: #fff;"
// src={book}
src={laptop}
// src={phone2}
// src={phone2}
/>
<View className="bookImg_text">无人直播</View>
</View>