const signTemplate = document.createElement("template");
signTemplate.innerHTML = `
暂无数据
- End -
更多

`;
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) => `
`
)
.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; } }
};
})();