整理文件夹及架构,加入打印机页面,octo反代有问题
This commit is contained in:
@@ -21,8 +21,18 @@
|
||||
.card { border: none; border-radius: 0.75rem; overflow: hidden; }
|
||||
.card-header { border-bottom: 1px solid rgba(0,0,0,.05); background-color: transparent; }
|
||||
|
||||
.toast-container { margin-bottom: 20px; margin-right: 20px; }
|
||||
.toast { border-radius: 0.5rem; box-shadow: 0 0.5rem 1rem rgba(0,0,0,.15); opacity: 0.95; }
|
||||
.toast-container { position: fixed; top: 20px; left: 50%; transform: translateX(-50%); z-index: 1055; width: auto; max-width: 90%; pointer-events: none; }
|
||||
.toast { border-radius: 0.5rem; box-shadow: 0 0.5rem 1rem rgba(0,0,0,.25); opacity: 1 !important; pointer-events: auto; }
|
||||
|
||||
/* 页面切换动画 Page Transition */
|
||||
@keyframes pageFadeInSlide {
|
||||
0% { opacity: 0; transform: translateY(10px); }
|
||||
100% { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
main { animation: pageFadeInSlide 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; }
|
||||
|
||||
/* 提升 Accordion 折叠栏动画更平滑 */
|
||||
.collapsing { transition: height 0.35s cubic-bezier(0.25, 0.8, 0.25, 1) !important; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -150,12 +160,12 @@
|
||||
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4 mt-4 bg-light min-vh-100 pb-5">
|
||||
|
||||
<!-- Toast Notification Container -->
|
||||
<div class="toast-container position-fixed bottom-0 end-0 p-3" style="z-index: 1055;">
|
||||
<div class="toast-container" id="global-toast-container">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
{% set toast_class = 'bg-success text-white' if category == 'success' else 'bg-danger text-white' if category == 'danger' else 'bg-warning text-dark' if category == 'warning' else 'bg-primary text-white' %}
|
||||
<div class="toast align-items-center border-0 {{ toast_class }}" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="toast align-items-center border-0 {{ toast_class }} mb-2" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="d-flex">
|
||||
<div class="toast-body fw-medium">
|
||||
{{ message }}
|
||||
@@ -173,6 +183,41 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Global Custom Alert Modal -->
|
||||
<div class="modal fade" id="globalAlertModal" tabindex="-1" aria-hidden="true" style="z-index: 1060;">
|
||||
<div class="modal-dialog modal-dialog-centered modal-sm">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header bg-warning text-dark py-2">
|
||||
<h6 class="modal-title fw-bold" id="globalAlertTitle"><i class="bi bi-exclamation-triangle-fill me-2"></i>{{ _('Notice') }}</h6>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body fs-6 text-center py-4 text-break" id="globalAlertMessage">
|
||||
</div>
|
||||
<div class="modal-footer border-0 p-2 justify-content-center bg-light">
|
||||
<button type="button" class="btn btn-warning px-4 rounded-pill fw-bold" data-bs-dismiss="modal">{{ _('OK') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Global Custom Confirm Modal -->
|
||||
<div class="modal fade" id="globalConfirmModal" tabindex="-1" aria-hidden="true" style="z-index: 1060;">
|
||||
<div class="modal-dialog modal-dialog-centered modal-sm">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header bg-primary text-white py-2">
|
||||
<h6 class="modal-title fw-bold"><i class="bi bi-question-circle-fill me-2"></i>{{ _('Confirm') }}</h6>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body fs-6 text-center py-4 text-break" id="globalConfirmMessage">
|
||||
</div>
|
||||
<div class="modal-footer border-0 p-2 justify-content-center bg-light">
|
||||
<button type="button" class="btn btn-outline-secondary px-4 rounded-pill" data-bs-dismiss="modal">{{ _('Cancel') }}</button>
|
||||
<button type="button" class="btn btn-primary px-4 rounded-pill fw-bold" id="globalConfirmBtn">{{ _('Yes') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="{{ url_for('static', filename='js/bootstrap.bundle.min.js') }}"></script>
|
||||
<script>
|
||||
// Initialize Toasts automatically
|
||||
@@ -182,6 +227,53 @@
|
||||
return new bootstrap.Toast(toastEl, { delay: 3000 }).show()
|
||||
});
|
||||
});
|
||||
|
||||
// Global Utility: Show Toast dynamically
|
||||
window.showToast = function(msg, type='success', duration=3000) {
|
||||
const container = document.getElementById('global-toast-container');
|
||||
const toastClass = type === 'success' ? 'bg-success text-white' :
|
||||
type === 'danger' ? 'bg-danger text-white' :
|
||||
type === 'warning' ? 'bg-warning text-dark' : 'bg-primary text-white';
|
||||
|
||||
const html = `
|
||||
<div class="toast align-items-center border-0 ${toastClass} mb-2" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="d-flex">
|
||||
<div class="toast-body fw-medium">${msg}</div>
|
||||
<button type="button" class="btn-close ${type==='warning'?'':'btn-close-white'} me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
container.insertAdjacentHTML('beforeend', html);
|
||||
const ts = container.lastElementChild;
|
||||
new bootstrap.Toast(ts, { autohide: true, delay: duration }).show();
|
||||
ts.addEventListener('hidden.bs.toast', () => { ts.remove(); });
|
||||
};
|
||||
|
||||
// Override default alert
|
||||
window.customAlert = function(msg, title) {
|
||||
document.getElementById('globalAlertMessage').innerHTML = String(msg).replace(/\n/g, '<br>');
|
||||
if(title) document.getElementById('globalAlertTitle').innerHTML = '<i class="bi bi-info-circle-fill me-2"></i>' + title;
|
||||
else document.getElementById('globalAlertTitle').innerHTML = '<i class="bi bi-exclamation-triangle-fill me-2"></i>Notice';
|
||||
new bootstrap.Modal(document.getElementById('globalAlertModal')).show();
|
||||
};
|
||||
|
||||
// Override default confirm
|
||||
window.customConfirm = function(msg, onConfirm) {
|
||||
document.getElementById('globalConfirmMessage').innerHTML = String(msg).replace(/\n/g, '<br>');
|
||||
const modalEl = document.getElementById('globalConfirmModal');
|
||||
const modal = new bootstrap.Modal(modalEl);
|
||||
|
||||
// Clear previous event listener bindings
|
||||
const elClone = document.getElementById('globalConfirmBtn').cloneNode(true);
|
||||
document.getElementById('globalConfirmBtn').parentNode.replaceChild(elClone, document.getElementById('globalConfirmBtn'));
|
||||
|
||||
document.getElementById('globalConfirmBtn').addEventListener('click', function() {
|
||||
modal.hide();
|
||||
if(onConfirm) onConfirm();
|
||||
});
|
||||
|
||||
modal.show();
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user