<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>原神升级计划数据表</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
body {
background: #0b1b2c;
}
}
header {
width: 100vw;
height: 40px;
display: flex;
justify-content: space-between;
align-items: center;
background-color: #cbcbcb;
/* logo */
figure.logo {
width: 262px;
height: 50px;
/* 缩小 */
transform: scale(0.8);
margin-top: 2px;
margin-left: -15px;
border-radius: 50%;
background: #f30303;
box-shadow: inset 4px 4px 4px rgba(255, 255, 255, 0.6),
inset -4px -4px 5px rgba(0, 0, 0, 0.6);
z-index: 99;
figcaption {
background: hsl(0, 0%, 0%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-weight: bold;
box-shadow: inset 4px 4px 4px rgba(255, 255, 255, 0.6), inset -4px -4px 5px rgba(0, 0, 0, 0.6);
letter-spacing: -3px;
line-height: 45px;
border-radius: 50%;
font-size: 40px;
width: 152px;
}
.my_name1 {
text-shadow: 1px 1px 1px rgba(255, 255, 255, 0.726);
clip-path: polygon(0% 0%, 100% 0%, 100% 50%, 0% 50%);
transform: translate(35%, 0%);
-webkit-text-stroke: #fffbfb 1px;
}
.my_name2 {
text-shadow: 1px 1px 1px hsla(160, 100%, 37%, 0.555);
clip-path: polygon(0% 50%, 100% 50%, 100% 100%, 0% 100%);
transform: translate(35%, -93%);
-webkit-text-stroke: #ffffff 1px;
}
img {
width: 60px;
height: 35px;
border-radius: 50%;
transition: transform 0.3s ease;
position: absolute;
&:hover {
transform: scale(1.3);
filter: drop-shadow(0 0 0.3em #ff0202);
}
}
.kong {
margin-top: 7px;
margin-left: 200px;
}
.ying {
top: 7px;
margin-left: 2px;
}
}
/* 时间 */
time {
background: -webkit-linear-gradient(315deg, #e1ff00 50%, #ff0000);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-size: 1.5rem;
font-weight: 900;
text-shadow: 2px -1px 8px rgba(250, 80, 193, 0.323);
sub {
-webkit-text-fill-color: #cfd601;
text-shadow: 1px 1px 1px #100000;
font-size: 1rem;
}
}
/* 全屏还原关闭按钮 */
menu {
display: flex;
button {
background: none;
border: none;
}
img {
width: 35px;
margin-top: 5px;
margin-right: 5px;
cursor: pointer;
&:hover {
transform: scale(1.2);
padding: 5px;
background: #ffd000;
}
}
button:nth-child(2) {
display: none;
/* 放大镜效果 */
transform: scale(1.16);
}
}
}
main {
display: flex;
align-items: center;
align-items: flex-start;
#countdownContainer {
display: flex;
flex-direction: column;
align-items: flex-end;
button {
font-size: 1.5rem;
color: hsl(0, 0%, 100%);
text-shadow: 1px 1px 1px #100000;
cursor: pointer;
border-radius: 3px;
background-color: #67c23a;
border: none;
margin: 5px;
padding: 3px;
}
button:first-child {
margin-top: 35px;
}
dialog {
transform: translate(180%, 80%);
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
background-color: #f3f3f3;
}
dialog::backdrop {
/* 模糊背景 */
backdrop-filter: blur(2px);
}
}
#characterTableContainer {
margin: 10px;
}
table {
border-collapse: collapse;
span {
color: #ffffff;
text-shadow: 1px 1px 1px #030303;
}
th,
td {
text-align: center;
padding: 8px;
border: 1px solid #ddd;
}
th {
background-color: #9f9e9e;
/* -webkit-text-stroke:#fffbfb 1px; */
}
td {
color: hsl(0, 0%, 100%);
text-shadow: 1px 1px 1px #030303;
}
.editable {
cursor: pointer;
/* 改变鼠标样式为指针 */
transition: background-color 0.3s;
/* 添加过渡效果 */
&:hover {
background-color: #000000;
padding: 5px;
/* 确保悬停时的padding与正常状态一致 */
transition: background-color 0.3s ease, padding 0.3s ease;
/* 添加过渡效果,使变化更平滑 */
}
}
}
}
#dialogAddCharacter {
transform: translate(120%, 10%);
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
background-color: #f3f3f3;
}
</style>
</head>
<body>
<header>
<figure class="logo">
<a href="https://blog.csdn.net/lulei5153?spm=1011.2415.3001.5343" title="与妖为邻CSDN博客" target="_blank">
<img class="kong" src="file:///D:/img/icon.ico" alt="与妖为邻">
</a>
<figcaption class="my_name1">与妖为邻</figcaption>
<figcaption class="my_name2">与妖为邻</figcaption>
<a href="file:///D:/web/html%E9%A6%96%E9%A1%B5/%E5%A4%87%E5%BF%98%E5%BD%95.html" class="home_page"
title="首页" target="_blank">
<img class="ying" src="file:///D:/img/ying.png" alt="与妖为邻">
</a>
</figure>
<time datetime="2024-07-10" title="2024-07-10" id="dateTime">2024-07-10</time>
<iframe class="tianqi" frameborder="0" width="280" height="36" scrolling="no" hspace="0"
src="https://i.tianqi.com/?c=code&id=99"></iframe>
<menu>
<button class="fullScreen" type="button"><img src="file:///D:/img/全屏.svg" alt="全屏"
onclick="fullScreen()"></button>
<button class="exitFullScreen" type="button"><img src="file:///D:/img/还原.svg" alt="还原"
onclick="exitFullScreen()"></button>
<button type="button"><img src="file:///D:/img/关闭.svg" alt="关闭" onclick="closeAll()"></button>
</menu>
</header>
<main>
<div id="countdownContainer"></div>
<div id="characterTableContainer">
<dialog id="dialogAddCharacter">
<form id="addCharacterForm">
<label for="element">元素:</label>
<select id="element" name="element">
<option value="火">火</option>
<option value="水">水</option>
<option value="风">风</option>
<option value="雷">雷</option>
<option value="草">草</option>
<option value="冰">冰</option>
<option value="岩">岩</option>
</select>
<button type="submit" style="float: right;">关闭</button><br><br>
<label for="role">角色:</label>
<input type="text" id="role" name="role"><br><br>
<label for="level">等级:</label>
<input type="number" id="level" name="level"><br><br>
<label for="constellation">命座:</label>
<select id="constellation" name="constellation">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
</select><br><br>
<label for="talent">天赋:</label>
<input type="text" id="talent" name="talent"><br><br>
<label for="note">备注:</label>
<input type="text" id="note" name="note"><br><br>
<button type="button" onclick="addCharacter()"
style="display: block; margin: 5px auto;">添加角色</button><br>
</form>
</dialog>
<table id="characterTable"></table>
</div>
</main>
<script>
const current_time = document.getElementById("dateTime");
function showTime() {
const now = new Date();
const time = `${now.getFullYear()}-${("0" + (now.getMonth() + 1)).slice(-2)}-${("0" + now.getDate()).slice(-2)}<sub id='sub'>${["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"][now.getDay()]}</sub> ${("0" + now.getHours()).slice(-2)}:${("0" + now.getMinutes()).slice(-2)}:${("0" + now.getSeconds()).slice(-2)}`;
current_time.innerHTML = time;
}
setInterval(showTime, 1000);
function fullScreen() {
const elem = document.documentElement;
['requestFullscreen', 'mozRequestFullScreen', 'webkitRequestFullscreen', 'msRequestFullscreen'].forEach(method => elem[method] && elem[method]());
}
function exitFullScreen() {
['exitFullscreen', 'mozCancelFullScreen', 'webkitExitFullscreen', 'msExitFullscreen'].forEach(method => document[method] && document[method]());
}
document.addEventListener("fullscreenchange", () => {
document.fullscreenElement ? [fullScreenBtn.style.display = "none", exitFullScreenBtn.style.display = "block"] : [fullScreenBtn.style.display = "block", exitFullScreenBtn.style.display = "none"];
});
function closeAll() {
window.close();
}
const countdownContainer = document.getElementById('countdownContainer');
function createCountdownElement(id) {
const button = document.createElement('button');
button.textContent = `第${id}个倒计时`;
button.id = `countdownElement${id}`;
button.onclick = () => document.getElementById(`dialogCountdownElement${id}`).showModal();
const dialog = document.createElement('dialog');
dialog.id = `dialogCountdownElement${id}`;
const form = document.createElement('form');
form.method = 'dialog';
const messageDiv = document.createElement('div');
messageDiv.appendChild(document.createElement('label')).textContent = '更改提示信息:';
messageDiv.appendChild(document.createElement('input')).type = 'text';
messageDiv.lastChild.id = `message${id}`;
messageDiv.lastChild.value = '距离2024年国庆节还有:';
const targetDateDiv = document.createElement('div');
targetDateDiv.appendChild(document.createElement('label')).textContent = '更改目标日期:';
targetDateDiv.appendChild(document.createElement('input')).type = 'datetime-local';
targetDateDiv.lastChild.id = `targetDate${id}`;
form.appendChild(messageDiv);
form.appendChild(targetDateDiv);
form.appendChild(document.createElement('button')).type = 'submit';
form.lastChild.textContent = '关闭';
form.lastChild.style.display = 'block';
form.lastChild.style.margin = '5px auto';
dialog.appendChild(form);
countdownContainer.appendChild(button);
countdownContainer.appendChild(dialog);
}
for (let i = 1; i <= 4; i++) createCountdownElement(i);
const countdownData = {
1: { message: 'message1', targetDate: 'targetDate1' },
2: { message: 'message2', targetDate: 'targetDate2' },
3: { message: 'message3', targetDate: 'targetDate3' },
4: { message: 'message4', targetDate: 'targetDate4' }
};
window.onload = () => Object.keys(countdownData).forEach(id => {
const message = localStorage.getItem(countdownData[id].message);
const targetDate = localStorage.getItem(countdownData[id].targetDate);
if (message) document.getElementById(countdownData[id].message).value = message;
if (targetDate) document.getElementById(countdownData[id].targetDate).value = targetDate;
});
function saveData(id) {
const message = document.getElementById(countdownData[id].message).value;
const targetDate = document.getElementById(countdownData[id].targetDate).value;
localStorage.setItem(countdownData[id].message, message);
localStorage.setItem(countdownData[id].targetDate, targetDate);
}
Object.keys(countdownData).forEach(id => {
document.getElementById(countdownData[id].message).addEventListener('input', () => saveData(id));
document.getElementById(countdownData[id].targetDate).addEventListener('input', () => saveData(id));
});
function showCountdown(id) {
const message = document.getElementById(countdownData[id].message).value;
const targetDateInput = document.getElementById(countdownData[id].targetDate);
const targetDateValue = targetDateInput.value;
const now = new Date();
let targetDate = targetDateValue ? new Date(targetDateValue) : new Date(2024, 9, 1);
const diff = targetDate - now;
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
document.getElementById(`countdownElement${id}`).innerHTML = `${message}${days}天${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
}
Object.keys(countdownData).forEach(id => {
showCountdown(id);
setInterval(() => showCountdown(id), 1000);
});
let data = JSON.parse(localStorage.getItem('genshinData')) || [];
const characterTable = document.getElementById("characterTable");
function renderTable() {
characterTable.innerHTML = `
<caption>
<button type="button" onclick="dialogAddCharacter.show()" style="float: left;">添加角色</button>
<span>原神升级计划数据表</span>
<button type="button" onclick="deleteSelectedRows()" style="float: right;">删除选中</button>
</caption>
<tr>
<th>序号</th>
<th>元素</th>
<th>角色</th>
<th>等级</th>
<th>命座</th>
<th style="width:100px;">天赋</th>
<th style="width:400px;">备注</th>
<th>选择</th>
</tr>
`;
let row = 1;
let lastElement = null;
data.forEach((elementData, i) => elementData.characters.forEach((character, j) => {
const newRow = characterTable.insertRow();
newRow.insertCell().textContent = row++;
if (elementData.element !== lastElement) {
const elementCell = newRow.insertCell();
elementCell.rowSpan = elementData.characters.length;
elementCell.textContent = elementData.element;
lastElement = elementData.element;
}
newRow.insertCell().textContent = character.role;
newRow.insertCell().innerHTML = `<span class="editable" onclick="editField('level', ${i}, ${j})">${character.level}</span>`;
newRow.insertCell().innerHTML = `<span class="editable" onclick="editField('constellation', ${i}, ${j})">${character.constellation}</span>`;
newRow.insertCell().innerHTML = `<span class="editable" onclick="editField('talent', ${i}, ${j})">${character.talent}</span>`;
newRow.insertCell().innerHTML = `<span class="editable" onclick="editField('note', ${i}, ${j})">${character.note}</span>`;
newRow.style.backgroundColor = getElementColor(elementData.element);
newRow.insertCell().innerHTML = `<input type="checkbox" ${character.selected ? 'checked' : ''} onchange="updateCheckboxStatus(this, ${i}, ${j})">`;
}));
}
function getElementColor(element) {
switch (element) {
case "火": return "#FF0000";
case "水": return "#0000FF";
case "风": return "#00FFFF";
case "雷": return "#800080";
case "草": return "#008000";
case "冰": return "#ADD8E6";
case "岩": return "#FFFF00";
default: return "#FFFFFF";
}
}
renderTable();
function addCharacter() {
const element = document.getElementById("element").value;
const role = document.getElementById("role").value;
const level = document.getElementById("level").value;
const constellation = document.getElementById("constellation").value;
const talent = document.getElementById("talent").value;
const note = document.getElementById("note").value;
if (!element || !role || !level || !constellation || !talent || !note) {
alert("请填写所有字段");
return;
}
const newCharacter = { role, level: parseInt(level), constellation, talent, note };
let elementExists = false;
data.forEach(d => {
if (d.element === element) {
d.characters.push(newCharacter);
elementExists = true;
}
});
if (!elementExists) data.push({ element, characters: [newCharacter] });
localStorage.setItem('genshinData', JSON.stringify(data));
renderTable();
document.getElementById("element").value = "";
document.getElementById("role").value = "";
document.getElementById("level").value = "";
document.getElementById("constellation").value = "";
document.getElementById("talent").value = "";
document.getElementById("note").value = "";
}
function updateCheckboxStatus(checkbox, elementIndex, characterIndex) {
data[elementIndex].characters[characterIndex].selected = checkbox.checked;
localStorage.setItem('genshinData', JSON.stringify(data));
}
function deleteSelectedRows() {
data = data.filter(elementData => {
elementData.characters = elementData.characters.filter(character => !character.selected);
return elementData.characters.length > 0;
});
localStorage.setItem('genshinData', JSON.stringify(data));
renderTable();
}
function editField(field, elementIndex, characterIndex) {
const newValue = prompt("请输入新的值:", data[elementIndex].characters[characterIndex][field]);
if (newValue !== null) {
data[elementIndex].characters[characterIndex][field] = newValue;
localStorage.setItem('genshinData', JSON.stringify(data));
renderTable();
}
}
</script>
</body>
</html>