Files
PC-Light-Forum/component/sign-in/sign-in.js
DESKTOP-RQ919RC\Pc 6ce06b133a refactor(components): 重构图片资源引用方式,使用动态路径
将静态图片路径改为从valueUrl动态获取,统一管理图片资源路径
添加新的SVG图标资源
修复BI组件401未授权时的登录跳转逻辑
优化签到组件图片资源路径
2025-12-08 19:09:04 +08:00

411 lines
47 KiB
JavaScript

const signTemplate = document.createElement("template");
signTemplate.innerHTML = `<style> .flexflex { display: flex; } .flexcenter { display: flex; justify-content: center; align-items: center; } .flexjcenter { display: flex; justify-content: center; } .flexacenter { display: flex; align-items: center; } .flexcolumn { display: flex; flex-direction: column; } .flex1 { flex: 1; } .signInBox-mask { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 10005; background-color: rgba(0, 0, 0, 0.5); display: none; } .signInBox-mask * { margin: 0; padding: 0; box-sizing: border-box; font-family: "PingFangSC-Regular", "PingFang SC", sans-serif; font-weight: 400; font-style: normal; word-break: break-word; } .signInBox-mask a { text-decoration: none; color: unset; } .signInBox-mask .signInBox { width: 1060px; background-color: #fff; border-radius: 20px; position: relative; filter: drop-shadow(0 -5px 0 #f7c308); } .signInBox-mask .signInBox .signInBox-head { position: relative; height: 64px; border-bottom: 1px dotted #d7d7d7; } .signInBox-mask .signInBox .signInBox-head .header-bi { width: 83px; height: 99px; position: absolute; top: -61px; left: 50%; transform: translateX(-50%); } .signInBox-mask .signInBox .signInBox-head .header-halo { width: 160px; height: 154px; position: absolute; top: -89px; left: 50%; transform: translateX(-50%); } .signInBox-mask .signInBox .signInBox-head .header-cross { width: 18px; height: 18px; position: absolute; top: 10px; right: 10px; cursor: pointer; } .signInBox-mask .signInBox .signInBox-content { align-items: flex-start; height: 595px; } .signInBox-mask .signInBox .signInBox-content .left-box { width: 50%; max-width: 538px; padding: 20px 30px 40px; border-right: 1px dotted #d7d7d7; display: flex; flex-direction: column; align-items: center; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header { width: 100%; font-size: 15px; color: #555555; line-height: 40px; margin-bottom: 16px; position: relative; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header .bi-img { width: 25px; height: 30px; margin-right: 7px; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header .bi-value { font-family: Arial-Black, "Arial Black", sans-serif; font-weight: 900; font-style: normal; font-size: 28px; color: #000000; margin-right: 7px; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header .bi-text { font-size: 15px; color: #555555; line-height: normal; margin-top: 8px; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header .bi-rule { margin-left: auto; cursor: pointer; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring { position: absolute; left: 0; top: 0; z-index: 1; width: 100%; height: 100%; background-color: #fdda55; padding: 20px; border-radius: 20px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring::after { content: ""; position: absolute; top: 26px; left: -11px; width: 0; height: 0; transform: translateX(-50%); border: 12px solid #000; border-top-color: transparent; border-bottom-color: transparent; border-left-color: transparent; border-right-color: #fdda55; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring .rule-box { background-color: #fff; -moz-box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.07058824); -webkit-box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.07058824); box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.07058824); border-radius: 20px; height: 100%; flex-direction: column; padding-bottom: 62px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring .rule-box .rule-header { font-weight: 650; font-size: 24px; color: #ab8705; text-align: center; font-family: "PingFangSC-Semibold", "PingFang SC Semibold", "PingFang SC", sans-serif; padding-top: 37px; position: relative; z-index: 1; margin-bottom: 14px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring .rule-box .rule-header::after { content: ""; display: block; position: absolute; bottom: -4px; left: 50%; transform: translateX(-50%); width: 120px; height: 22px; background-color: #fdeeb7; border-radius: 219px; z-index: -1; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring .rule-box .rule-list { flex-direction: column; margin: 0 23px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring .rule-box .rule-list .rule-item .rule-item-icon { width: 52px; height: 52px; background-color: #f6f6f6; border: 1px solid #ebebeb; border-radius: 20px; -moz-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.11764706); -webkit-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.11764706); box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.11764706); margin-right: 30px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring .rule-box .rule-list .rule-item .rule-item-img { width: 30px; height: 36px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring .rule-box .rule-list .rule-item .rule-item-text { color: #333; line-height: 28px; font-size: 16px; padding: 40px 0; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring .rule-box .rule-list .rule-item:not(:last-of-type) .rule-item-text { border-bottom: 1px dotted #ebebeb; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring .rule-box .rule-close { font-family: "PingFangSC-Regular", "PingFang SC", sans-serif; font-weight: 400; font-style: normal; font-size: 15px; color: #555555; text-decoration: underline; margin: 0 auto; line-height: normal; width: max-content; cursor: pointer; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box { width: 100%; max-width: 477px; min-width: min-content; height: 479px; background-color: #fbfbfb; border-radius: 12px; flex-direction: column; padding: 38px 23px 0; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .sign-in-text { color: #555555; line-height: 28px; font-size: 14px; font-family: "PingFangSC-Regular", "PingFang SC", sans-serif; margin-bottom: 21px; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .sign-in-text .sign-in-value { font-family: "PingFangSC-Semibold", "PingFang SC Semibold", "PingFang SC", sans-serif; font-weight: 650; color: #000000; margin: 0 5px; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar { margin: 0 0 14px; display: grid; grid-template-columns: repeat(7, minmax(40px, 1fr)); justify-items: center; gap: 10px; width: 100%; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item { width: 40px; height: 40px; border-radius: 50%; margin-bottom: 10px; font-size: 17px; color: #aaaaaa; position: relative; box-sizing: border-box; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item:not(:nth-child(7n)) { margin-right: 0; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item.formerly { background-color: #f6f6f6; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item.already { background-color: #fdeeb7; color: #deae07; border: none; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item.already .yellow-tick { width: 14px; height: 14px; display: block; position: absolute; top: -2px; right: -2px; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item .yellow-tick { display: none; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item.today { border: 1px solid #deae07; color: #deae07; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .sign-in-btn { height: 48px; border-radius: 219px; background-color: #f7c308; color: #fff; font-size: 20px; cursor: pointer; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .sign-in-btn.already { background-color: #fdeeb7; color: #deae07; font-size: 16px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box { margin: 0 15px; border-radius: 20px; font-family: "PingFangSC-Regular", "PingFang SC", sans-serif; font-weight: 400; color: #555555; font-size: 15px; flex-direction: column; height: inherit; position: relative; overflow: hidden; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-scroll-wrapper { overflow: auto; flex: 1; display: flex; flex-direction: column; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-header { padding: 24px 30px 9px; font-size: 14px; line-height: 28px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-header .sign-in-header-value { font-weight: 650; color: #000000; margin: 0 5px; border-bottom: 1px dotted #ebebeb; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list { display: none; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item { padding: 11px 0 0 30px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item:not(:last-of-type) .sign-in-info { border-bottom: 1px dotted #ebebeb; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item .sign-in-index { color: #aaaaaa; font-size: 15px; width: 40px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item .sign-in-avatar { width: 24px; height: 24px; border-radius: 50%; margin-right: 10px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item .sign-in-info { padding-bottom: 9px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item .sign-in-info:not(:last-of-type) { border-bottom: 1px dotted #ebebeb; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item .sign-in-info .sign-in-info-left { flex-direction: column; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item .sign-in-info .sign-in-name { color: #555555; font-size: 14px; margin-bottom: 3px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item .sign-in-info .sign-in-name .sign-in-my { margin-left: 10px; width: 20px; height: 20px; background-color: #f0f2f5; border: 1px solid #d7d7d7; border-radius: 5px; font-size: 12px; color: #7f7f7f; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item .sign-in-info .sign-in-time { color: #aaaaaa; font-size: 13px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item .sign-in-value { border-radius: 50%; margin-right: 20px; width: 40px; height: 40px; background-color: #fdeeb7; font-family: PingFangSC-Regular, "PingFang SC", sans-serif; font-weight: 400; font-style: normal; font-size: 16px; color: #deae07; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-finish { font-size: 13px; color: #d7d7d7; padding-top: 10px; padding-bottom: 10px; display: none; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-more { color: #333333; font-size: 14px; padding-top: 10px; padding-bottom: 10px; cursor: pointer; display: none; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-more .sign-in-more-icon { width: 14px; height: 14px; margin-left: 6px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .discuss-list-no { flex-direction: column; display: none; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .discuss-list-no .empty-icon { width: 101px; height: 120px; margin-bottom: 15px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .discuss-list-no .discuss-list-no-text { font-size: 12px; color: #555555; line-height: 22px; } .signInBox-mask .succeed-mask { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; display: none; } .signInBox-mask .succeed-mask .succeed-box { width: 263px; background-color: rgba(0, 0, 0, 0.70588235); border-radius: 43px; padding-bottom: 29px; position: relative; z-index: 1; animation: succeedShow 0.3s, succeedHide 0.3s; animation-delay: 0s, 1.8s; } .signInBox-mask .succeed-mask .succeed-box .succeed-icon { width: 100px; height: 100px; background-color: #fbf7e9; border: 1px solid #fdda55; border-radius: 10px; -moz-box-shadow: 3px 3px 5px #fdeeb7; -webkit-box-shadow: 3px 3px 5px #fdeeb7; box-shadow: 3px 3px 5px #fdeeb7; flex-direction: column; position: relative; margin-top: -48px; margin-bottom: 31px; } .signInBox-mask .succeed-mask .succeed-box .succeed-icon .succeed-icon-bj { width: 220px; height: 211px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: -1; } .signInBox-mask .succeed-mask .succeed-box .succeed-icon .succeed-icon-header-dot { width: 6px; height: 16px; background-color: #f7c308; border-radius: 24px; position: absolute; top: -6px; } .signInBox-mask .succeed-mask .succeed-box .succeed-icon .succeed-icon-header-dot-left { left: 20px; } .signInBox-mask .succeed-mask .succeed-box .succeed-icon .succeed-icon-header-dot-right { left: 74px; } .signInBox-mask .succeed-mask .succeed-box .succeed-icon .succeed-icon-header { height: 24px; background-color: rgba(253, 223, 109, 0.77647059); border-radius: 10px 10px 0 0; } .signInBox-mask .succeed-mask .succeed-box .succeed-icon .succeed-icon-dot { flex-wrap: wrap; padding-top: 16px; padding-left: 15px; } .signInBox-mask .succeed-mask .succeed-box .succeed-icon .succeed-icon-dot .succeed-icon-dot-item { width: 10px; height: 10px; border-radius: 50%; background-color: #f7c308; margin-right: 10px; margin-bottom: 10px; } .signInBox-mask .succeed-mask .succeed-box .succeed-icon .yellow-tick-box { position: absolute; width: 40px; height: 40px; right: -10px; bottom: -10px; z-index: 1; } .signInBox-mask .succeed-mask .succeed-box .succeed-icon .yellow-tick-box .yellow-tick-circle { position: absolute; left: -5px; top: -5px; width: 50px; height: 50px; z-index: -1; } .signInBox-mask .succeed-mask .succeed-box .succeed-icon .yellow-tick-box .yellow-tick-faint-yellow { width: 19px; height: 16px; } .signInBox-mask .succeed-mask .succeed-box .succeed-award-list { color: #fff; font-size: 16px; line-height: 28px; } .signInBox-mask .succeed-mask .succeed-box .succeed-award-list .succeed-award-item { display: none; } .signInBox-mask .succeed-mask .succeed-box .succeed-award-list .succeed-award-item:not(:last-of-type) { margin-bottom: 12px; } .signInBox-mask .succeed-mask .succeed-box .succeed-award-list .succeed-award-item .succeed-award-name { margin-right: 9px; } .signInBox-mask .succeed-mask .succeed-box .succeed-award-list .succeed-award-item .succeed-award-value { height: 22px; padding: 0 13.5px; background-color: #f6f6f6; border-radius: 20px; font-size: 18px; letter-spacing: 1px; font-family: "PingFangSC-Semibold", "PingFang SC Semibold", "PingFang SC", sans-serif; color: #deae07; font-weight: 650; } @keyframes succeedShow { 0% { transform: scale(0); } 100% { transform: scale(1); } } @keyframes succeedHide { 0% { transform: scale(1); } 100% { transform: scale(0); display: none; } } @media screen and (max-width: 1200px) { .signInBox-mask .signInBox { width: 95%; max-width: 1060px; } } @media screen and (max-width: 768px) { .signInBox-mask { align-items: flex-end; /* Align box to bottom */ } .signInBox-mask .signInBox { width: 100%; /* Full width */ max-width: none; /* Remove max width */ height: 90vh; border-radius: 20px 20px 0 0; /* Rounded top corners only */ margin: 0; /* No margins */ display: flex; flex-direction: column; /* overflow-y: hidden; */ /* Container fixed, inner scrolls */ } .signInBox-mask .signInBox .signInBox-head { flex-shrink: 0; } .signInBox-mask .signInBox .signInBox-content { flex-direction: column; height: 0; /* Allow growing */ flex: 1; align-items: stretch; } .signInBox-mask .signInBox .signInBox-content .left-box { width: 100%; height: auto; /* Let it grow */ flex: 0 0 auto; /* Don't shrink below content */ border-right: none; border-bottom: 1px dotted #d7d7d7; padding: 15px 20px; /* Restore comfortable padding */ display: flex; flex-direction: column; align-items: center; justify-content: center; overflow: visible; /* Default overflow */ max-width: inherit; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header { width: 100%; justify-content: center; flex-shrink: 0; margin-bottom: 16px; /* Restore margin */ transform: none; /* Restore size */ } .signInBox-mask .signInBox .signInBox-content .left-box .content-header .outer-ring { left: 50%; top: 50%; transform: translate(-50%, -50%); width: 90%; height: auto; max-height: 80vh; border-radius: 20px; background-color: rgba(253, 218, 85, 0.95); position: fixed; z-index: 10010; overflow: hidden; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header .outer-ring::after { display: none; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header .outer-ring .rule-box { padding-bottom: 30px; height: auto; max-height: 100%; display: flex; flex-direction: column; overflow: hidden; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header .outer-ring .rule-box .rule-list { overflow-y: auto; flex: 1; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header .outer-ring .rule-box .rule-header { font-size: 20px; padding-top: 25px; margin-bottom: 10px; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header .outer-ring .rule-box .rule-header::after { width: 100px; height: 18px; bottom: -2px; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header .outer-ring .rule-box .rule-list .rule-item .rule-item-icon { width: 42px; height: 42px; margin-right: 15px; border-radius: 12px; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header .outer-ring .rule-box .rule-list .rule-item .rule-item-img { width: 24px; height: 28px; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header .outer-ring .rule-box .rule-list .rule-item .rule-item-text { font-size: 14px; line-height: 24px; padding: 20px 0; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box { max-width: 100%; height: auto; padding: 0; /* Remove all padding */ padding: 10px 0; /* Add vertical margin */ flex-shrink: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; width: 100%; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .sign-in-text { margin-bottom: 15px; /* Restore margin */ font-size: 14px; /* Restore font size */ line-height: 28px; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar { display: grid; grid-template-columns: repeat(7, 1fr); /* Force 7 columns */ gap: 1.5%; /* Relative gap */ width: 100%; /* Full width */ max-width: none; /* Remove limit */ justify-items: center; /* Center items in their cells */ margin-bottom: 15px; /* Restore margin */ } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item { width: 100%; /* Fill grid cell */ max-width: 40px; /* Limit max size to original desktop size */ aspect-ratio: 1; /* Keep square */ height: auto; /* Auto height based on width */ line-height: normal; /* Reset line-height */ display: flex; /* Use flex for centering content */ align-items: center; justify-content: center; font-size: min(14px, 3vw); /* Fluid font size */ margin: 0; /* Grid handles spacing */ border-width: 1px; /* Default border width */ } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .sign-in-btn { height: 40px; /* Reduced height */ font-size: 16px; /* Adjusted font size */ width: auto; /* Restore width */ min-width: auto; padding: 0 30px; /* Add padding for auto width */ } /* Adjust border width for 'today' item to be relative if possible, but px is usually safer for borders. We can use thin/medium or keep 1px as it's already quite thin. Let's keep 1px but ensure box-sizing handles it well. */ .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item.today { border-width: 1px; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item.already .yellow-tick { width: 30%; /* Relative tick size */ height: 30%; top: -5%; right: -5%; } /* Remove previous margin overrides as grid handles it */ .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item:not(:nth-child(7n)) { margin-right: 0; } /* List Styling Adjustments */ .signInBox-mask .signInBox .signInBox-content .sign-in-box { width: 100%; height: auto; /* Auto height */ flex: 1; /* Take remaining height */ margin: 0; padding: 0 20px; display: flex; flex-direction: column; /* overflow: hidden; */ } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-header { padding: 15px 10px; /* Compact header */ font-size: 13px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item { padding: 8px 0 0 10px; /* Compact item padding */ } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item .sign-in-index { font-size: 13px; width: 30px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item .sign-in-value { width: 32px; height: 32px; font-size: 14px; margin-right: 10px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item .sign-in-info .sign-in-name { font-size: 13px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item .sign-in-info .sign-in-time { font-size: 12px; } } @media screen and (max-width: 480px) { .signInBox-mask .signInBox .signInBox-head .header-bi { width: 60px; height: 72px; top: -45px; } .signInBox-mask .signInBox .signInBox-head .header-halo { width: 120px; height: 115px; top: -65px; } .signInBox-mask .signInBox .signInBox-content .left-box { padding: 15px; } .signInBox-mask .signInBox .signInBox-content .left-box .content-header .bi-value { font-size: 24px; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box { padding: 20px 5px; /* Very tight padding for mobile */ } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1.5%; /* Relative gap */ justify-items: center; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item { width: 100%; max-width: none; /* Fully fluid */ aspect-ratio: 1; height: auto; font-size: 4vw; /* Large relative font for mobile */ margin: 0; /* display: none; Remove hide default */ border-width: 1px; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item.already .yellow-tick { width: 35%; /* Larger relative tick for mobile */ height: 35%; } /* .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item.show-mobile { display: flex; } Remove show logic */ /* Override any previous margin settings */ .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .calendar .calendar-item:not(:nth-child(7n)) { margin-right: 0; } .signInBox-mask .signInBox .signInBox-content .left-box .calendar-box .sign-in-btn { height: 36px; font-size: 15px; margin-top: 10px; } /* Adjust Success Modal for mobile */ .signInBox-mask .succeed-mask .succeed-box { transform: scale(0.9); } /* Further compact list for mobile */ .signInBox-mask .signInBox .signInBox-content .sign-in-box .sign-in-list .sign-in-item .sign-in-value { width: 28px; height: 28px; font-size: 13px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring .rule-box .rule-header { font-size: 18px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring .rule-box .rule-list .rule-item .rule-item-icon { width: 36px; height: 36px; margin-right: 10px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring .rule-box .rule-list .rule-item .rule-item-img { width: 20px; height: 24px; } .signInBox-mask .signInBox .signInBox-content .sign-in-box .outer-ring .rule-box .rule-list .rule-item .rule-item-text { font-size: 13px; padding: 15px 0; } }</style><div class="signInBox-mask flexcenter"> <div class="signInBox"> <div class="signInBox-head"> <img class="header-halo" src="https://app.gter.net/image/gter/commonCom/sign-in/img/halo-icon.png"> <img class="header-bi" src="https://app.gter.net/image/gter/commonCom/sign-in/img/coin-icon.png"> <img class="header-cross" src="https://app.gter.net/image/gter/commonCom/sign-in/img/cross-icon.png"> </div> <div class="signInBox-content flexflex"> <div class="left-box"> <div class="content-header flexacenter"> <img class="bi-img" src="https://app.gter.net/image/gter/commonCom/sign-in/img/coin-icon.png"> <div class="bi-value" data-field="integral">0</div> <div class="bi-text">寄托币</div> <div class="bi-rule">签到规则</div> </div> <div class="calendar-box flexflex"> <div class="sign-in-text">本月已签到 <span class="sign-in-value" data-field="signnum">0</span> 天,共领 <span class="sign-in-value" data-field="signreward">0</span> 寄托币<span class="diligent" hidden>,次月可获寄托勤务兵勋章</span></div> <div class="calendar flexflex" data-list="calendar"></div> <div class="sign-in-btn flexcenter" data-action="sign">立即签到</div> <!-- <div v-else-if="issign == 1" class="sign-in-btn flexcenter already">今天已签到,明天记得来哦~</div> --> </div> </div> <div class="sign-in-box flex1 flexflex"> <div class="sign-in-scroll-wrapper flex1 flexcolumn"> <div class="sign-in-header flexflex">今日已签到 <div class="sign-in-header-value" data-field="todaycount">0</div>人 </div> <div class="discuss-list-no flexcenter flex1"> <img class="empty-icon" src="https://app.gter.net/image/gter/commonCom/sign-in/img/empty-icon.png"> <div class="discuss-list-no-text">- 暂无数据 -</div> </div> <div class="sign-in-list"></div> <div class="sign-in-finish flexcenter">- End -</div> <div class="sign-in-more flexcenter">更多 <img class="sign-in-more-icon" src="https://app.gter.net/image/gter/commonCom/sign-in/img/arrows-circle-black.png"></div> </div> <div class="outer-ring" hidden> <div class="rule-box flexflex"> <div class="rule-header">签到规则</div> <div class="rule-list flexflex" data-list="tips"></div> <div class="flex1"></div> <div class="rule-close">关闭</div> </div> </div> </div> </div> </div> <!-- 签到成功 --> <div class="succeed-mask flexcenter"> <div class="succeed-box flexcenter flexcolumn"> <div class="succeed-icon flexflex"> <img class="succeed-icon-bj" src="https://app.gter.net/image/gter/commonCom/sign-in/img/halo-icon.png"> <div class="succeed-icon-header-dot succeed-icon-header-dot-left"></div> <div class="succeed-icon-header-dot succeed-icon-header-dot-right"></div> <div class="succeed-icon-header"></div> <div class="succeed-icon-dot flexflex"> <div class="succeed-icon-dot-item" v-for="index in 8" :key="index"></div> </div> <div class="yellow-tick-box flexcenter"> <img class="yellow-tick-circle" src="https://app.gter.net/image/gter/commonCom/sign-in/img/circle-yellow.svg"> <img class="yellow-tick-faint-yellow" src="https://app.gter.net/image/gter/commonCom/sign-in/img/tick-faint-yellow.svg"> </div> </div> <div class="succeed-award-list flexcolumn flexacenter"> <div class="succeed-award-item flexacenter reward" v-if="reward != 0"> <div class="succeed-award-name">随机奖励</div> <div class="succeed-award-value flexcenter">+{{ reward }}</div> </div> <div class="succeed-award-item flexacenter extra_reward" v-if="extra_reward != 0"> <div class="succeed-award-name">额外奖励</div> <div class="succeed-award-value flexcenter">+{{ extra_reward }}</div> </div> </div> </div> </div></div>`;
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.totalDaysInMonth = 0;
this.currentDay = 0;
this.list = [];
this.showPage = 1;
this.listEl = this.shadowRoot.querySelector(".signInBox-mask .signInBox-content .sign-in-list");
this.listNoEl = this.shadowRoot.querySelector(".signInBox-mask .signInBox-content .discuss-list-no");
this.moreEl = this.shadowRoot.querySelector(".signInBox-mask .signInBox-content .sign-in-more");
this.finishEl = this.shadowRoot.querySelector(".signInBox-mask .signInBox-content .sign-in-finish");
this.bindUI();
this.computeMonth();
// this.init();
// this.getList();
this.headerCross = this.shadowRoot.querySelector(".signInBox-mask .signInBox .header-cross");
this.headerCross.addEventListener("click", () => {
document.body.style.overflow = "";
document.body.style.paddingRight = "";
this.shadowRoot.querySelector(".signInBox-mask").style.display = "none";
});
window.signInComponent = this;
}
connectedCallback() {}
attributeChangedCallback(name, oldVal, newVal) {
const el = this.shadowRoot.querySelector(`[data-field="${name}"]`);
if (el) el.textContent = newVal || "0";
}
renderList(list, type = "push") {
let itemAll = ``;
list.forEach((item) => {
itemAll += `<div class="sign-in-item flexflex">
<div class="sign-in-index">${item.rank || ""}</div>
<a href="https://f.gter.net/u${item.uniqid ? "/" + item.uniqid : ""}" target="_blank"><img class="sign-in-avatar" src="${item.avatar || ""}"></a>
<div class="sign-in-info flex1 flexacenter">
<div class="sign-in-info-left flex1">
<a class="sign-in-name flexacenter" href="https://f.gter.net/u${item.uniqid ? "/" + item.uniqid : ""}" target="_blank">${item.nickname || ""}</a>
<div class="sign-in-time">${item.timestamp || ""}</div>
</div>
<div class="sign-in-value flexcenter">+${item.reward || 0}</div>
</div>
</div>`;
});
if (type == "push") {
this.listEl.innerHTML += itemAll;
} else if (type == "unshift") {
this.listEl.innerHTML = itemAll + this.listEl.innerHTML;
}
this.listEl.style.display = "block";
setTimeout(() => {
const itemArr = this.listEl.querySelectorAll(".sign-in-item");
if (this.list.length > itemArr.length) {
this.moreEl.style.display = "flex";
this.finishEl.style.display = "none";
} else {
this.moreEl.style.display = "none";
this.finishEl.style.display = "flex";
}
}, 0);
}
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);
const dayOfWeek = firstDayOfMonth.getDay();
this.dayOfWeek = dayOfWeek; // Store for renderCalendar
const items = [];
for (let i = 0; i < dayOfWeek; i++) {
items.push(`<div class="calendar-item flexcenter row-0 show-mobile"></div>`);
}
const box = this.shadowRoot.querySelector('[data-list="calendar"]');
box.innerHTML = items.join("");
const currentDate = new Date();
const currentMonth = currentDate.getMonth() + 1;
const currentYear = currentDate.getFullYear();
this.currentDay = currentDate.getDate();
this.totalDaysInMonth = new Date(currentYear, currentMonth, 0).getDate();
}
init() {
const mask = this.shadowRoot.querySelector(".signInBox-mask");
mask.style.display = "none";
this.fetchGet("https://api.gter.net/v2/api/forum/getSignInfo").then((res) => {
if (res.code != 200) return;
mask.style.display = "flex";
const data = res.data || {};
this.setField("integral", Number(data.integral) || 0);
this.setField("signnum", data.signnum || 0);
this.setField("signreward", data.signreward || 0);
this.issign = data.issign;
if (data.issign == 1) {
const signBtn = this.shadowRoot.querySelector('[data-action="sign"]');
signBtn.textContent = "今天已签到,明天记得来哦~";
signBtn.classList.add("already");
}
// Determine today logic before rendering calendar
this.renderCalendar(data.list || {});
if (data.signnum >= 25) this.shadowRoot.querySelector(".diligent").hidden = false;
const tipsBox = this.shadowRoot.querySelector('[data-list="tips"]');
const tips = data.tips || [];
tipsBox.innerHTML = tips
.map(
(t, i) => `
<div class="rule-item flexacenter">
<div class="rule-item-icon flexcenter">
<img class="rule-item-img" src="${i == 0 ? "https://app.gter.net/image/gter/commonCom/sign-in/img/bi.png" : "https://app.gter.net/image/gter/commonCom/sign-in/img/hardworking-icon.png"}">
</div>
<div class="rule-item-text flex1">${t}</div>
</div>`
)
.join("");
this.isInit = true;
this.getList();
const scrollWidth = window.innerWidth - document.documentElement.clientWidth;
document.body.style.overflow = "hidden";
document.body.style.paddingRight = `${scrollWidth}px`;
});
}
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"]');
// Calculate today's row index
const todayIndex = this.dayOfWeek + this.currentDay - 1;
const todayRow = Math.floor(todayIndex / 7);
// Determine visible rows for mobile
const visibleRows = new Set();
if (todayRow > 0) {
visibleRows.add(todayRow);
visibleRows.add(todayRow - 1);
} else {
visibleRows.add(0);
visibleRows.add(1);
}
const items = [];
// Add placeholders
for (let i = 0; i < this.dayOfWeek; i++) {
const row = 0; // Placeholders always in row 0 (since dayOfWeek < 7)
const showMobile = visibleRows.has(row) ? "show-mobile" : "";
items.push(`<div class="calendar-item flexcenter row-${row} ${showMobile}"></div>`);
}
for (let i = 1; i <= this.totalDaysInMonth; i++) {
let type = 0;
let name = "";
const key = this.pad(i);
if (list[key]) {
type = 2;
name = `+${list[key]}`;
} else if (this.currentDay > i) type = 1;
else if (this.currentDay == i) type = 3;
if (!name) name = this.currentDay == i ? "今" : i;
const cls = { 1: "formerly", 2: "already", 3: "today" }[type] || "";
const index = this.dayOfWeek + i - 1;
const row = Math.floor(index / 7);
const showMobile = visibleRows.has(row) ? "show-mobile" : "";
items.push(`<div class="calendar-item flexcenter ${cls} row-${row} ${showMobile}">${name}<img class="yellow-tick" src="https://app.gter.net/image/gter/commonCom/sign-in/img/yellow-tick.svg"></div>`);
}
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.list = data.list || [];
let showList = this.list.slice(0, 10) || [];
if (!Array.isArray(data.my)) {
showList.unshift(data.my);
}
if (showList.length > 0) this.renderList(showList);
this.setField("todaycount", data.todaycount || 0);
if (this.list.length > showList.length) {
this.moreEl.style.display = "flex";
this.finishEl.style.display = "none";
this.moreEl.onclick = () => this.moreList();
} else if (this.list.length == 0) {
this.listNoEl.style.display = "flex";
this.finishEl.style.display = "none";
} else {
this.moreEl.style.display = "none";
this.finishEl.style.display = "flex";
}
});
}
moreList() {
const showList = this.list.slice(this.showPage * 20 - 10, this.showPage * 20 + 10);
this.showPage += 1;
this.renderList(showList);
}
postSign() {
console.log('document.querySelector(".sign-in")', document.querySelector(".sign-in"));
if (this.issign == 1) {
creationAlertBox("error", "今天已签到,明天记得来哦~");
return;
}
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.renderList([myItem], "unshift");
this.cutSucceed(data.reward, data.extra_reward);
localStorage.setItem("signInState", this.currentDate());
const todayItem = this.shadowRoot.querySelector(".calendar-item.today");
todayItem.classList.remove("today");
todayItem.classList.add("already");
todayItem.innerHTML = `+${rewardT}<img class="yellow-tick" src="https://app.gter.net/image/gter/commonCom/sign-in/img/yellow-tick.svg">`;
this.issign = 1;
const signBtn = this.shadowRoot.querySelector('[data-action="sign"]');
signBtn.textContent = "今天已签到,明天记得来哦~";
signBtn.classList.add("already");
const sign = document.querySelector(".sign-in");
sign.classList.add("sign-in-already");
sign.classList.remove("sign-in-no");
});
}
cutSucceed(reward, extra_reward) {
const mask = this.shadowRoot.querySelector(".succeed-mask");
if (!mask) return;
mask.style.display = "flex";
if (reward > 0) {
const rewardEl = mask.querySelector(".reward");
rewardEl.querySelector(".succeed-award-value").textContent = `+${reward}`;
rewardEl.style.display = "flex";
}
if (extra_reward > 0) {
const extra_rewardEl = mask.querySelector(".extra_reward");
extra_rewardEl.querySelector(".succeed-award-value").textContent = `+${extra_reward}`;
extra_rewardEl.style.display = "flex";
}
setTimeout(() => (mask.style.display = "none"), 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())}`;
}
getScriptParameter(paramName) {
const currentScript = document.currentScript;
if (currentScript && currentScript.src) {
const url = new URL(currentScript.src, window.location.origin);
return url.searchParams.get(paramName);
}
return null;
}
fetchPost(url, data = {}) {
return new Promise((resolve) => {
if (data) data["v"] = this.getScriptParameter("v") || "v2";
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);
} else if (xhr.status === 401) {
if (typeof ajax_login === "function") ajax_login();
else window.open("https://passport.gter.net/?referer=" + escape(location.href), "_self");
}
};
xhr.send(JSON.stringify(data));
});
}
fetchGet(url) {
return new Promise((resolve) => {
const paramSymbol = url.includes("?") ? "&" : "?";
url = `${url}${paramSymbol}v=${this.getScriptParameter("v") || "v2"}`;
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);
} else if (xhr.status === 401) {
if (typeof ajax_login === "function") ajax_login();
else window.open("https://passport.gter.net/?referer=" + escape(location.href), "_self");
}
};
xhr.send();
});
}
open() {
if (this.isInit) {
this.shadowRoot.querySelector(".signInBox-mask").style.display = "flex";
const scrollWidth = window.innerWidth - document.documentElement.clientWidth;
document.body.style.overflow = "hidden";
document.body.style.paddingRight = `${scrollWidth}px`;
} else {
this.init();
}
}
// 静态方法,用于在外部调用组件初始化 type normal 展示正常的投币和列表 unlock 解锁插入币弹窗 或者 币不足
static initComponent() {
if (window.signInComponent) {
window.signInComponent.open();
return true;
}
const el = document.createElement("sign-in-box");
document.body.appendChild(el);
window.signInComponent = el;
el.open();
return true;
}
}
if (!customElements.get("sign-in-box")) customElements.define("sign-in-box", SignInBox);
window.SignInComponent = SignInBox;