const signTemplate = document.createElement("template"); signTemplate.innerHTML = `
0
寄托币
签到规则
`; class SignInBox extends HTMLElement { static get observedAttributes() { return ["integral", "signnum", "signreward", "todaycount"]; } constructor() { super(); this.attachShadow({ mode: "open" }); this.shadowRoot.appendChild(signTemplate.content.cloneNode(true)); this._state = { dayOfWeek: 0, totalDaysInMonth: 0, currentDay: 0, list: [], showList: [], showPage: 1, issign: 0, }; this._bindUI(); this._computeMonth(); this._init(); this._getList(); } connectedCallback() { window.signInBox = this; } attributeChangedCallback(name, oldVal, newVal) { const el = this.shadowRoot.querySelector(`[data-field="${name}"]`); if (el) el.textContent = newVal || "0"; } setUsers(list) { const box = this.shadowRoot.querySelector('[data-list="users"]'); box.innerHTML = list .map( (item) => `
${item.rank || ""}
` ) .join(""); } _bindUI() { const ruleBtn = this.shadowRoot.querySelector(".bi-rule"); const ruleBox = this.shadowRoot.querySelector(".outer-ring"); ruleBtn.addEventListener("click", () => (ruleBox.hidden = !ruleBox.hidden)); const ruleClose = this.shadowRoot.querySelector(".rule-close"); ruleClose.addEventListener("click", () => (ruleBox.hidden = true)); const signBtn = this.shadowRoot.querySelector('[data-action="sign"]'); if (signBtn) signBtn.addEventListener("click", () => this._postSign()); } _pad(n) { return String(n).padStart(2, "0"); } _computeMonth() { const firstDayOfMonth = new Date(); firstDayOfMonth.setDate(1); this._state.dayOfWeek = firstDayOfMonth.getDay(); const currentDate = new Date(); const currentMonth = currentDate.getMonth() + 1; const currentYear = currentDate.getFullYear(); this._state.currentDay = currentDate.getDate(); this._state.totalDaysInMonth = new Date(currentYear, currentMonth, 0).getDate(); } _init() { this._fetchGet("https://api.gter.net/v2/api/forum/getSignInfo").then((res) => { if (res.code != 200) return; const data = res.data || {}; this._renderCalendar(data.list || {}); this._setField("integral", Number(data.integral) || 0); this._setField("signnum", data.signnum || 0); this._setField("signreward", data.signreward || 0); this._state.issign = data.issign || 0; const tipsBox = this.shadowRoot.querySelector('[data-list="tips"]'); const tips = data.tips || []; tipsBox.innerHTML = tips .map( (t, i) => `
${t}
` ) .join(""); }); } _setField(name, value) { const el = this.shadowRoot.querySelector(`[data-field="${name}"]`); if (el) el.textContent = value; } _renderCalendar(list) { const box = this.shadowRoot.querySelector('[data-list="calendar"]'); const items = []; for (let i = 1; i <= this._state.totalDaysInMonth; i++) { let type = 0; let name = ""; const key = this._pad(i); if (list[key]) { type = 2; name = `+${list[key]}`; } else if (this._state.currentDay > i) type = 1; else if (this._state.currentDay == i) type = 3; if (!name) name = this._state.currentDay == i ? "今" : i; const cls = { 1: "formerly", 2: "already", 3: "today" }[type] || ""; items.push(`
${name}
`); } box.innerHTML = items.join(""); } _getList() { this._fetchGet("https://api.gter.net/v2/api/forum/getSignRankList").then((res) => { if (res.code != 200) return; const data = res.data || {}; this._state.list = data.list || []; this._state.showList = this._state.list.slice(0, 10); this.setUsers(this._state.showList); this._setField("todaycount", data.todaycount || 0); const more = this.shadowRoot.querySelector(".sign-in-more"); const finish = this.shadowRoot.querySelector(".sign-in-finish"); if (this._state.list.length > this._state.showList.length) { more.hidden = false; finish.hidden = true; more.onclick = () => this._moreList(); } else { more.hidden = true; finish.hidden = false; } }); } _moreList() { const arr = this._state.list.slice(this._state.showPage * 20 - 10, this._state.showPage * 20 + 10); this._state.showList = this._state.showList.concat(arr); this._state.showPage++; this.setUsers(this._state.showList); const more = this.shadowRoot.querySelector(".sign-in-more"); const finish = this.shadowRoot.querySelector(".sign-in-finish"); if (this._state.list.length > this._state.showList.length) { more.hidden = false; finish.hidden = true; } else { more.hidden = true; finish.hidden = false; } } _postSign() { const user = window.userInfoWin; if (!user || (user?.uin <= 0 && user?.uid <= 0)) { creationAlertBox("error", "没有绑定寄托账号"); showWindow("login", "https://passport.gter.net/login/ajax", "get", -1, { cover: true }); return; } this._fetchPost("https://api.gter.net/v2/api/forum/sign").then((res) => { if (res.code != 200) { creationAlertBox("error", res.message); return; } const data = res.data || {}; const rewardT = data.extra_reward * 1 + data.reward * 1 || 0; this._setField("integral", (Number(this.shadowRoot.querySelector('[data-field="integral"]').textContent) || 0) + rewardT); this._setField("signnum", (Number(this.shadowRoot.querySelector('[data-field="signnum"]').textContent) || 0) + 1); this._setField("signreward", (Number(this.shadowRoot.querySelector('[data-field="signreward"]').textContent) || 0) + rewardT); const myItem = { avatar: user.avatar || "", uniqid: user.uniqid || "", nickname: user.nickname || "匿名用户", rank: data.rank || 1, reward: rewardT, timestamp: this._currentDateTime() }; this._state.showList.unshift(myItem); this.setUsers(this._state.showList); this._cutSucceed(); localStorage.setItem("signInState", this._currentDate()); }); } _cutSucceed() { const mask = this.shadowRoot.querySelector(".succeed-mask"); if (!mask) return; mask.hidden = false; setTimeout(() => (mask.hidden = true), 1800); } _currentDate() { const now = new Date(); return `${now.getFullYear()}-${this._pad(now.getMonth() + 1)}-${this._pad(now.getDate())}`; } _currentDateTime() { const d = new Date(); return `${d.getFullYear()}-${this._pad(d.getMonth() + 1)}-${this._pad(d.getDate())} ${this._pad(d.getHours())}:${this._pad(d.getMinutes())}:${this._pad(d.getSeconds())}`; } _fetchPost(url, data = {}) { return new Promise((resolve) => { const xhr = new XMLHttpRequest(); xhr.responseType = "json"; xhr.withCredentials = true; xhr.open("POST", url, true); xhr.setRequestHeader("Content-Type", "application/json"); if (["127.0.0.1", "localhost", "192.168.18.219"].includes(location.hostname)) xhr.setRequestHeader("Authorization", "3b01343c65e3b2fa3ce32ae26feb3a9b"); xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { resolve(xhr.response); } }; xhr.send(JSON.stringify(data)); }); } _fetchGet(url) { return new Promise((resolve) => { const xhr = new XMLHttpRequest(); xhr.withCredentials = true; xhr.open("GET", url, true); if (["127.0.0.1", "localhost", "192.168.18.219"].includes(location.hostname)) xhr.setRequestHeader("Authorization", "3b01343c65e3b2fa3ce32ae26feb3a9b"); xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { let response = xhr.response; try { response = JSON.parse(response); } catch {} resolve(response); } }; xhr.send(); }); } } if (!customElements.get("sign-in-box")) customElements.define("sign-in-box", SignInBox); window.signInBoxClass = SignInBox; // 工厂:按需创建与打开 (function(){ let instance = null; window.signInBox = { _init(){ if (!instance){ instance = document.createElement('sign-in-box'); document.body.appendChild(instance); } const mask = instance.shadowRoot.querySelector('.signInBox-mask'); if (mask) mask.hidden = false; instance._init(); }, close(){ if (instance){ const mask = instance.shadowRoot.querySelector('.signInBox-mask'); if (mask) mask.hidden = true; } } }; })();