fix: WebUI 应用变更确认框改用 FlyonUI overlay 组件
原实现混用了 DaisyUI 的写法(<dialog class="modal"> + .modal-box), 而项目实际引入的是 FlyonUI:其 modal 由 HSOverlay 驱动,显示态靠 overlay-open 变体(&.open)生成,且该变体不会随 @plugin 自动注册 (Tailwind v4 只加载包内同名 flyonui.css,variants.css 被忽略)。 后果是 showModal() 只产生原生遮罩(页面变暗+其余按钮被锁), 对话框本身始终 opacity:0 不可见,也未发出任何请求。 本次改动: - modal 结构迁移为官方 overlay 结构,开合改用 HSOverlay.open/close, 取消/关闭按钮走 data-overlay 声明式关闭; - input.css 注册 overlay-open 变体(带注释说明不可删); - 顺带修正其余 DaisyUI 残留:tabs-border→tabs-bordered、 btn-ghost/badge-ghost/badge-neutral→btn-soft/badge-soft。
This commit is contained in:
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+17
-12
@@ -31,7 +31,7 @@ const STATE_BADGES = {
|
|||||||
leave_candidate: ['待发离职确认', 'badge-warning'],
|
leave_candidate: ['待发离职确认', 'badge-warning'],
|
||||||
pending_confirm: ['待人工确认离职', 'badge-warning'],
|
pending_confirm: ['待人工确认离职', 'badge-warning'],
|
||||||
confirmed_leave: ['已确认离职', 'badge-error'],
|
confirmed_leave: ['已确认离职', 'badge-error'],
|
||||||
deleted: ['已删除', 'badge-neutral'],
|
deleted: ['已删除', 'badge-soft'],
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------- 主题
|
// ---------------------------------------------------------------- 主题
|
||||||
@@ -246,7 +246,7 @@ function renderUsers() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$('#userRows').innerHTML = rows.map((u) => {
|
$('#userRows').innerHTML = rows.map((u) => {
|
||||||
const st = STATE_BADGES[u.state] || [u.state || '未知', 'badge-neutral'];
|
const st = STATE_BADGES[u.state] || [u.state || '未知', 'badge-soft'];
|
||||||
return `<tr>
|
return `<tr>
|
||||||
<td class="font-medium">${escapeHtml(u.uid)}</td>
|
<td class="font-medium">${escapeHtml(u.uid)}</td>
|
||||||
<td>${escapeHtml(u.name || '')}</td>
|
<td>${escapeHtml(u.name || '')}</td>
|
||||||
@@ -337,7 +337,7 @@ function renderPlan(plan) {
|
|||||||
const ops = plan.ops || [];
|
const ops = plan.ops || [];
|
||||||
$('#planRows').innerHTML = ops.map((op) => `
|
$('#planRows').innerHTML = ops.map((op) => `
|
||||||
<tr>
|
<tr>
|
||||||
<td><span class="badge ${OP_BADGES[op.kind] || 'badge-neutral'} badge-sm">${OP_LABELS[op.kind] || op.kind}</span></td>
|
<td><span class="badge ${OP_BADGES[op.kind] || 'badge-soft'} badge-sm">${OP_LABELS[op.kind] || op.kind}</span></td>
|
||||||
<td class="font-medium">${escapeHtml(op.target)}</td>
|
<td class="font-medium">${escapeHtml(op.target)}</td>
|
||||||
<td>${escapeHtml(op.detail)}</td>
|
<td>${escapeHtml(op.detail)}</td>
|
||||||
</tr>`).join('');
|
</tr>`).join('');
|
||||||
@@ -345,9 +345,18 @@ function renderPlan(plan) {
|
|||||||
$('#planEmpty').classList.toggle('hidden', ops.length > 0);
|
$('#planEmpty').classList.toggle('hidden', ops.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FlyonUI 的 overlay(modal)由 flyonui.js 的 HSOverlay 驱动:它切换 open/hidden class 来显隐。
|
||||||
|
// 不要改回原生 dialog.showModal()——那不会加上 .open,overlay-open 变体不生效,框就永远不可见。
|
||||||
|
function openApplyModal() {
|
||||||
|
if (window.HSOverlay) window.HSOverlay.open('#applyModal');
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeApplyModal() {
|
||||||
|
if (window.HSOverlay) window.HSOverlay.close('#applyModal');
|
||||||
|
}
|
||||||
|
|
||||||
async function applyPlan(force = false) {
|
async function applyPlan(force = false) {
|
||||||
const modal = document.getElementById('applyModal');
|
closeApplyModal();
|
||||||
if (modal && typeof modal.close === 'function') modal.close();
|
|
||||||
try {
|
try {
|
||||||
const d = await api('/api/sync', {
|
const d = await api('/api/sync', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -372,7 +381,7 @@ async function loadRuns() {
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="whitespace-nowrap">${fmtTime(r.startedAt)}</td>
|
<td class="whitespace-nowrap">${fmtTime(r.startedAt)}</td>
|
||||||
<td>${r.mode === 'dry-run'
|
<td>${r.mode === 'dry-run'
|
||||||
? '<span class="badge badge-ghost badge-sm">预览</span>'
|
? '<span class="badge badge-soft badge-sm">预览</span>'
|
||||||
: '<span class="badge badge-primary badge-sm">执行</span>'}</td>
|
: '<span class="badge badge-primary badge-sm">执行</span>'}</td>
|
||||||
<td>${r.trigger === 'schedule' ? '定时' : '手动'}</td>
|
<td>${r.trigger === 'schedule' ? '定时' : '手动'}</td>
|
||||||
<td>${r.status === 'success'
|
<td>${r.status === 'success'
|
||||||
@@ -443,14 +452,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
<div>删除用户 <strong>${s.deleteUser || 0}</strong></div>
|
<div>删除用户 <strong>${s.deleteUser || 0}</strong></div>
|
||||||
<div>新建分组 <strong>${s.createGroup || 0}</strong> · 加入分组 <strong>${s.addMember || 0}</strong> · 移出分组 <strong>${s.removeMember || 0}</strong></div>
|
<div>新建分组 <strong>${s.createGroup || 0}</strong> · 加入分组 <strong>${s.addMember || 0}</strong> · 移出分组 <strong>${s.removeMember || 0}</strong></div>
|
||||||
</div>`;
|
</div>`;
|
||||||
const modal = document.getElementById('applyModal');
|
openApplyModal();
|
||||||
if (modal && typeof modal.showModal === 'function') modal.showModal();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#applyCancel').addEventListener('click', () => {
|
// 「取消」与右上角关闭按钮走 data-overlay 声明式关闭,无需额外监听。
|
||||||
const modal = document.getElementById('applyModal');
|
|
||||||
if (modal && typeof modal.close === 'function') modal.close();
|
|
||||||
});
|
|
||||||
$('#applyConfirm').addEventListener('click', () => applyPlan(false));
|
$('#applyConfirm').addEventListener('click', () => applyPlan(false));
|
||||||
|
|
||||||
// 已有会话则直接进入主界面
|
// 已有会话则直接进入主界面
|
||||||
|
|||||||
Vendored
+27
-15
@@ -40,14 +40,14 @@
|
|||||||
<span class="hidden sm:inline text-sm text-base-content/50">飞书通讯录 → LLDAP</span>
|
<span class="hidden sm:inline text-sm text-base-content/50">飞书通讯录 → LLDAP</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-none flex items-center gap-2">
|
<div class="flex-none flex items-center gap-2">
|
||||||
<button id="themeToggle" class="btn btn-sm btn-ghost" title="切换明暗主题">主题</button>
|
<button id="themeToggle" class="btn btn-sm btn-soft" title="切换明暗主题">主题</button>
|
||||||
<button id="logoutBtn" class="btn btn-sm btn-outline">退出</button>
|
<button id="logoutBtn" class="btn btn-sm btn-outline">退出</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="max-w-7xl mx-auto p-4">
|
<main class="max-w-7xl mx-auto p-4">
|
||||||
<!-- 页签 -->
|
<!-- 页签 -->
|
||||||
<div class="tabs tabs-border mb-4" role="tablist">
|
<div class="tabs tabs-bordered mb-4" role="tablist">
|
||||||
<button class="tab tab-active" data-view="overview" role="tab">概览</button>
|
<button class="tab tab-active" data-view="overview" role="tab">概览</button>
|
||||||
<button class="tab" data-view="users" role="tab">用户</button>
|
<button class="tab" data-view="users" role="tab">用户</button>
|
||||||
<button class="tab" data-view="groups" role="tab">部门分组</button>
|
<button class="tab" data-view="groups" role="tab">部门分组</button>
|
||||||
@@ -227,21 +227,33 @@
|
|||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 应用变更的确认对话框 -->
|
<!-- 应用变更的确认对话框。
|
||||||
<dialog id="applyModal" class="modal">
|
必须用 FlyonUI 的 overlay 结构:容器是 .overlay.modal 的 <div>(HSOverlay 靠切换
|
||||||
<div class="modal-box">
|
open/hidden class 显隐,不会调用原生 dialog.showModal),显示态由 overlay-open 变体
|
||||||
<h3 class="text-lg font-semibold mb-2">确认应用变更</h3>
|
生成——所以 overlay-open:opacity-100 这个类不能删,否则对话框又会变回不可见。 -->
|
||||||
<p class="text-sm text-base-content/70 mb-4">
|
<div id="applyModal" class="overlay modal modal-middle overlay-open:opacity-100 hidden overlay-open:duration-300"
|
||||||
将对 LLDAP 执行下列变更。密码由 LLDAP 独占并交给 Authelia 管理,程序绝不写入;
|
role="dialog" tabindex="-1" aria-labelledby="applyModalTitle">
|
||||||
仅标记「已确认离职」的用户会被物理删除。
|
<div class="modal-dialog">
|
||||||
</p>
|
<div class="modal-content">
|
||||||
<div id="applyModalBody" class="text-sm mb-4"></div>
|
<div class="modal-header">
|
||||||
<div class="modal-action">
|
<h3 id="applyModalTitle" class="modal-title">确认应用变更</h3>
|
||||||
<button id="applyCancel" class="btn btn-ghost">取消</button>
|
<button type="button" class="btn btn-text btn-circle btn-sm absolute end-3 top-3"
|
||||||
<button id="applyConfirm" class="btn btn-primary">确认执行</button>
|
aria-label="关闭" data-overlay="#applyModal">✕</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p class="text-sm text-base-content/70 mb-4">
|
||||||
|
将对 LLDAP 执行下列变更。密码由 LLDAP 独占并交给 Authelia 管理,程序绝不写入;
|
||||||
|
仅标记「已确认离职」的用户会被物理删除。
|
||||||
|
</p>
|
||||||
|
<div id="applyModalBody" class="text-sm"></div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button id="applyCancel" type="button" class="btn btn-soft" data-overlay="#applyModal">取消</button>
|
||||||
|
<button id="applyConfirm" type="button" class="btn btn-primary">确认执行</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</dialog>
|
</div>
|
||||||
|
|
||||||
<script src="/static/flyonui.js"></script>
|
<script src="/static/flyonui.js"></script>
|
||||||
<script src="/static/app.js"></script>
|
<script src="/static/app.js"></script>
|
||||||
|
|||||||
+17
-12
@@ -31,7 +31,7 @@ const STATE_BADGES = {
|
|||||||
leave_candidate: ['待发离职确认', 'badge-warning'],
|
leave_candidate: ['待发离职确认', 'badge-warning'],
|
||||||
pending_confirm: ['待人工确认离职', 'badge-warning'],
|
pending_confirm: ['待人工确认离职', 'badge-warning'],
|
||||||
confirmed_leave: ['已确认离职', 'badge-error'],
|
confirmed_leave: ['已确认离职', 'badge-error'],
|
||||||
deleted: ['已删除', 'badge-neutral'],
|
deleted: ['已删除', 'badge-soft'],
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------- 主题
|
// ---------------------------------------------------------------- 主题
|
||||||
@@ -246,7 +246,7 @@ function renderUsers() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$('#userRows').innerHTML = rows.map((u) => {
|
$('#userRows').innerHTML = rows.map((u) => {
|
||||||
const st = STATE_BADGES[u.state] || [u.state || '未知', 'badge-neutral'];
|
const st = STATE_BADGES[u.state] || [u.state || '未知', 'badge-soft'];
|
||||||
return `<tr>
|
return `<tr>
|
||||||
<td class="font-medium">${escapeHtml(u.uid)}</td>
|
<td class="font-medium">${escapeHtml(u.uid)}</td>
|
||||||
<td>${escapeHtml(u.name || '')}</td>
|
<td>${escapeHtml(u.name || '')}</td>
|
||||||
@@ -337,7 +337,7 @@ function renderPlan(plan) {
|
|||||||
const ops = plan.ops || [];
|
const ops = plan.ops || [];
|
||||||
$('#planRows').innerHTML = ops.map((op) => `
|
$('#planRows').innerHTML = ops.map((op) => `
|
||||||
<tr>
|
<tr>
|
||||||
<td><span class="badge ${OP_BADGES[op.kind] || 'badge-neutral'} badge-sm">${OP_LABELS[op.kind] || op.kind}</span></td>
|
<td><span class="badge ${OP_BADGES[op.kind] || 'badge-soft'} badge-sm">${OP_LABELS[op.kind] || op.kind}</span></td>
|
||||||
<td class="font-medium">${escapeHtml(op.target)}</td>
|
<td class="font-medium">${escapeHtml(op.target)}</td>
|
||||||
<td>${escapeHtml(op.detail)}</td>
|
<td>${escapeHtml(op.detail)}</td>
|
||||||
</tr>`).join('');
|
</tr>`).join('');
|
||||||
@@ -345,9 +345,18 @@ function renderPlan(plan) {
|
|||||||
$('#planEmpty').classList.toggle('hidden', ops.length > 0);
|
$('#planEmpty').classList.toggle('hidden', ops.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FlyonUI 的 overlay(modal)由 flyonui.js 的 HSOverlay 驱动:它切换 open/hidden class 来显隐。
|
||||||
|
// 不要改回原生 dialog.showModal()——那不会加上 .open,overlay-open 变体不生效,框就永远不可见。
|
||||||
|
function openApplyModal() {
|
||||||
|
if (window.HSOverlay) window.HSOverlay.open('#applyModal');
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeApplyModal() {
|
||||||
|
if (window.HSOverlay) window.HSOverlay.close('#applyModal');
|
||||||
|
}
|
||||||
|
|
||||||
async function applyPlan(force = false) {
|
async function applyPlan(force = false) {
|
||||||
const modal = document.getElementById('applyModal');
|
closeApplyModal();
|
||||||
if (modal && typeof modal.close === 'function') modal.close();
|
|
||||||
try {
|
try {
|
||||||
const d = await api('/api/sync', {
|
const d = await api('/api/sync', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -372,7 +381,7 @@ async function loadRuns() {
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="whitespace-nowrap">${fmtTime(r.startedAt)}</td>
|
<td class="whitespace-nowrap">${fmtTime(r.startedAt)}</td>
|
||||||
<td>${r.mode === 'dry-run'
|
<td>${r.mode === 'dry-run'
|
||||||
? '<span class="badge badge-ghost badge-sm">预览</span>'
|
? '<span class="badge badge-soft badge-sm">预览</span>'
|
||||||
: '<span class="badge badge-primary badge-sm">执行</span>'}</td>
|
: '<span class="badge badge-primary badge-sm">执行</span>'}</td>
|
||||||
<td>${r.trigger === 'schedule' ? '定时' : '手动'}</td>
|
<td>${r.trigger === 'schedule' ? '定时' : '手动'}</td>
|
||||||
<td>${r.status === 'success'
|
<td>${r.status === 'success'
|
||||||
@@ -443,14 +452,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
<div>删除用户 <strong>${s.deleteUser || 0}</strong></div>
|
<div>删除用户 <strong>${s.deleteUser || 0}</strong></div>
|
||||||
<div>新建分组 <strong>${s.createGroup || 0}</strong> · 加入分组 <strong>${s.addMember || 0}</strong> · 移出分组 <strong>${s.removeMember || 0}</strong></div>
|
<div>新建分组 <strong>${s.createGroup || 0}</strong> · 加入分组 <strong>${s.addMember || 0}</strong> · 移出分组 <strong>${s.removeMember || 0}</strong></div>
|
||||||
</div>`;
|
</div>`;
|
||||||
const modal = document.getElementById('applyModal');
|
openApplyModal();
|
||||||
if (modal && typeof modal.showModal === 'function') modal.showModal();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#applyCancel').addEventListener('click', () => {
|
// 「取消」与右上角关闭按钮走 data-overlay 声明式关闭,无需额外监听。
|
||||||
const modal = document.getElementById('applyModal');
|
|
||||||
if (modal && typeof modal.close === 'function') modal.close();
|
|
||||||
});
|
|
||||||
$('#applyConfirm').addEventListener('click', () => applyPlan(false));
|
$('#applyConfirm').addEventListener('click', () => applyPlan(false));
|
||||||
|
|
||||||
// 已有会话则直接进入主界面
|
// 已有会话则直接进入主界面
|
||||||
|
|||||||
+27
-15
@@ -40,14 +40,14 @@
|
|||||||
<span class="hidden sm:inline text-sm text-base-content/50">飞书通讯录 → LLDAP</span>
|
<span class="hidden sm:inline text-sm text-base-content/50">飞书通讯录 → LLDAP</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-none flex items-center gap-2">
|
<div class="flex-none flex items-center gap-2">
|
||||||
<button id="themeToggle" class="btn btn-sm btn-ghost" title="切换明暗主题">主题</button>
|
<button id="themeToggle" class="btn btn-sm btn-soft" title="切换明暗主题">主题</button>
|
||||||
<button id="logoutBtn" class="btn btn-sm btn-outline">退出</button>
|
<button id="logoutBtn" class="btn btn-sm btn-outline">退出</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="max-w-7xl mx-auto p-4">
|
<main class="max-w-7xl mx-auto p-4">
|
||||||
<!-- 页签 -->
|
<!-- 页签 -->
|
||||||
<div class="tabs tabs-border mb-4" role="tablist">
|
<div class="tabs tabs-bordered mb-4" role="tablist">
|
||||||
<button class="tab tab-active" data-view="overview" role="tab">概览</button>
|
<button class="tab tab-active" data-view="overview" role="tab">概览</button>
|
||||||
<button class="tab" data-view="users" role="tab">用户</button>
|
<button class="tab" data-view="users" role="tab">用户</button>
|
||||||
<button class="tab" data-view="groups" role="tab">部门分组</button>
|
<button class="tab" data-view="groups" role="tab">部门分组</button>
|
||||||
@@ -227,21 +227,33 @@
|
|||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 应用变更的确认对话框 -->
|
<!-- 应用变更的确认对话框。
|
||||||
<dialog id="applyModal" class="modal">
|
必须用 FlyonUI 的 overlay 结构:容器是 .overlay.modal 的 <div>(HSOverlay 靠切换
|
||||||
<div class="modal-box">
|
open/hidden class 显隐,不会调用原生 dialog.showModal),显示态由 overlay-open 变体
|
||||||
<h3 class="text-lg font-semibold mb-2">确认应用变更</h3>
|
生成——所以 overlay-open:opacity-100 这个类不能删,否则对话框又会变回不可见。 -->
|
||||||
<p class="text-sm text-base-content/70 mb-4">
|
<div id="applyModal" class="overlay modal modal-middle overlay-open:opacity-100 hidden overlay-open:duration-300"
|
||||||
将对 LLDAP 执行下列变更。密码由 LLDAP 独占并交给 Authelia 管理,程序绝不写入;
|
role="dialog" tabindex="-1" aria-labelledby="applyModalTitle">
|
||||||
仅标记「已确认离职」的用户会被物理删除。
|
<div class="modal-dialog">
|
||||||
</p>
|
<div class="modal-content">
|
||||||
<div id="applyModalBody" class="text-sm mb-4"></div>
|
<div class="modal-header">
|
||||||
<div class="modal-action">
|
<h3 id="applyModalTitle" class="modal-title">确认应用变更</h3>
|
||||||
<button id="applyCancel" class="btn btn-ghost">取消</button>
|
<button type="button" class="btn btn-text btn-circle btn-sm absolute end-3 top-3"
|
||||||
<button id="applyConfirm" class="btn btn-primary">确认执行</button>
|
aria-label="关闭" data-overlay="#applyModal">✕</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p class="text-sm text-base-content/70 mb-4">
|
||||||
|
将对 LLDAP 执行下列变更。密码由 LLDAP 独占并交给 Authelia 管理,程序绝不写入;
|
||||||
|
仅标记「已确认离职」的用户会被物理删除。
|
||||||
|
</p>
|
||||||
|
<div id="applyModalBody" class="text-sm"></div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button id="applyCancel" type="button" class="btn btn-soft" data-overlay="#applyModal">取消</button>
|
||||||
|
<button id="applyConfirm" type="button" class="btn btn-primary">确认执行</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</dialog>
|
</div>
|
||||||
|
|
||||||
<script src="/static/flyonui.js"></script>
|
<script src="/static/flyonui.js"></script>
|
||||||
<script src="/static/app.js"></script>
|
<script src="/static/app.js"></script>
|
||||||
|
|||||||
@@ -42,6 +42,20 @@
|
|||||||
--color-success-content: #071505;
|
--color-success-content: #071505;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FlyonUI 的 overlay 变体没有随 @plugin 自动注册:Tailwind v4 只会加载包内与插件同名的
|
||||||
|
* flyonui.css,而 overlay-open 等 @custom-variant 定义在包根的 variants.css 里,不会被引入。
|
||||||
|
* 不在这里补上,HTML 里的 overlay-open:opacity-100 就编译不出任何规则,modal 打开后仍是
|
||||||
|
* opacity:0 的透明层(表现为「页面变暗+点不了别处,但对话框不可见」)。 */
|
||||||
|
@custom-variant overlay-open {
|
||||||
|
&.open {
|
||||||
|
@slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
.open & {
|
||||||
|
@slot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 少量自定义样式:表格可横向滚动,长 DN 不撑破布局。 */
|
/* 少量自定义样式:表格可横向滚动,长 DN 不撑破布局。 */
|
||||||
@layer components {
|
@layer components {
|
||||||
.idsync-dn {
|
.idsync-dn {
|
||||||
|
|||||||
Reference in New Issue
Block a user