Files
yakpanel-core/YakPanel/templates/default/unsubscribe.html
2026-04-07 02:04:22 +05:30

252 lines
7.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Unsubscribe</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.unsubscribe-container {
background-color: #fff;
padding: 40px;
border-radius: 10px;
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
width: 350px;
}
h2 {
font-size: 24px;
margin-bottom: 20px;
color: #444;
}
.options {
margin: 20px 0;
}
.options label {
display: flex;
align-items: center;
margin: 15px 0;
font-size: 16px;
}
input[type="checkbox"] {
margin-right: 10px;
width: 18px;
height: 18px;
border-radius: 50%;
accent-color:#20a53a;
}
button {
padding: 12px 0px;
background-color: #20a53a;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s ease;
width: 100%;
}
button:hover {
background-color: #25b942;
}
/* loading效果 */
.loading {
position: absolute;
display: none;
align-items: center;
background-color: white;
padding: 10px 40px;
border-radius: 10px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}
.spinner {
border: 8px solid rgba(0, 0, 0, 0.1);
border-left-color: #3498db;
border-radius: 50%;
width: 20px;
height: 20px;
margin-right: 15px;
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.icon {
font-size: 20px;
margin-right: 10px;
}
</style>
</head>
<body>
<div id="loading" class="loading">
<div class="spinner"></div>
<p>Loading...</p>
</div>
<div id="success-message" class="loading">
<div class="icon">✔️</div>
<p id="tips_success"></p>
</div>
<div id="error-message" class="loading">
<div class="icon"></div>
<p id="tips_error"></p>
</div>
<div class="unsubscribe-container" id="container">
<h2>Are you sure to unsubscribe?</h2>
<div class="options" id="reasonOptions">
<label><input type="checkbox" id="selectAll">Select All</label>
</div>
<button onclick="confirmUnsubscribe()">Sure</button>
</div>
<script>
// 维护用原生写法Network reasons不引入jq\layer
function showSuccess(value) {
const successBox = document.getElementById('success-message');
const containerBox = document.getElementById('container');
const tips = document.getElementById('tips_success')
tips.textContent = value
containerBox.style.display = 'none';
successBox.style.display = 'flex';
}
function showError(value) {
const errorBox = document.getElementById('error-message');
const tips = document.getElementById('tips_error')
tips.textContent = value
errorBox.style.display = 'flex';
setTimeout(() => {
errorBox.style.display = 'none';
}, 2000);
}
// 获取页面传参
function getQueryParams() {
const params = {};
const queryString = window.location.search.substring(1);
const regex = /([^&=]+)=([^&]*)/g;
let m;
while (m = regex.exec(queryString)) {
params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
}
return params;
}
var params; // 参数
window.onload = function() {
params = getQueryParams();
requestType({email:this.params.email});
}
// 渲染页面类型
function renderType(data) {
const reasonOptionsDiv = document.getElementById('reasonOptions');
data.forEach(reason => {
const label = document.createElement('label');
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.name = 'reason';
checkbox.value = reason.id;
label.appendChild(checkbox);
label.appendChild(document.createTextNode(reason.mail_type));
reasonOptionsDiv.appendChild(label);
});
// 绑定全选复选框事件
const selectAllCheckbox = document.getElementById('selectAll');
selectAllCheckbox.addEventListener('change', () => {
const checkboxes = document.querySelectorAll('input[name="reason"]');
checkboxes.forEach(checkbox => {
checkbox.checked = selectAllCheckbox.checked; // 同步选中状态
});
});
// 监测其他复选框的选中状态
reasonOptionsDiv.addEventListener('change', () => {
const checkboxes = document.querySelectorAll('input[name="reason"]');
const allChecked = Array.from(checkboxes).every(checkbox => checkbox.checked);
selectAllCheckbox.checked = allChecked; // 更新全选复选框的状态
});
}
// 请求取消订阅类型
function requestType(reqData) {
document.getElementById('loading').style.display = 'flex';
fetch(params.url_type, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams(reqData).toString()
})
.then(response => response.json())
.then(data => {
if (data.status){
this.renderType(data.msg);
}else{
this.showError(data.msg)
}
})
.catch((err) => {
this.showError(err)
})
.finally(() => {
document.getElementById('loading').style.display = 'none';
});
}
// 请求取消订阅
function requestApi(value) {
document.getElementById('loading').style.display = 'flex';
const data = {
jwt: params.jwt,
id: value
};
fetch(params.url_unsubscribe, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams(data).toString()
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then((res) => {
if(res.status){
this.showSuccess(res.msg)
}else{
this.showError(res.msg)
}
})
.catch((err) => {
this.showError(err)
})
.finally(() => {
document.getElementById('loading').style.display = 'none';
});
}
// 确认取消事件
function confirmUnsubscribe() {
const selectedReasons = Array.from(document.querySelectorAll('input[name="reason"]:checked'))
.map(checkbox => checkbox.value)
.join(',');
if (!selectedReasons) {
this.showError('Please select at least one')
return;
}
requestApi(selectedReasons);
}
</script>
</body>
</html>