layout.html 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>{% block title %}家谱管理系统{% endblock %}</title>
  7. <!-- Local Bootstrap CSS -->
  8. <link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet">
  9. <!-- Local Bootstrap Icons CSS -->
  10. <link href="{{ url_for('static', filename='css/bootstrap-icons.min.css') }}" rel="stylesheet">
  11. <style>
  12. body { font-family: 'Microsoft YaHei', sans-serif; }
  13. .sidebar { min-height: 100vh; background-color: #343a40; color: white; }
  14. .sidebar a { color: rgba(255,255,255,.8); text-decoration: none; padding: 10px 20px; display: block; }
  15. .sidebar a:hover { background-color: #495057; color: white; }
  16. .sidebar a.active { background-color: #0d6efd; color: white; }
  17. .content-area { padding: 20px; }
  18. /* Watermark styles */
  19. .watermark-container {
  20. position: fixed;
  21. top: 0;
  22. left: 0;
  23. width: 100%;
  24. height: 100%;
  25. pointer-events: none;
  26. z-index: 9999;
  27. overflow: hidden;
  28. opacity: 0.08;
  29. }
  30. .watermark-text {
  31. position: absolute;
  32. font-size: 18px;
  33. color: #999;
  34. transform: rotate(-15deg);
  35. white-space: nowrap;
  36. font-weight: 500;
  37. letter-spacing: 2px;
  38. }
  39. .watermark-corner {
  40. position: fixed;
  41. bottom: 15px;
  42. right: 15px;
  43. font-size: 12px;
  44. color: #999;
  45. opacity: 0.4;
  46. text-align: right;
  47. z-index: 1000;
  48. pointer-events: none;
  49. }
  50. </style>
  51. {% block extra_css %}{% endblock %}
  52. </head>
  53. <body class="bg-light">
  54. <div class="container-fluid">
  55. <div class="row">
  56. {% if session.get('user_id') %}
  57. <!-- Sidebar -->
  58. <div class="col-md-2 sidebar d-none d-md-block">
  59. <div class="py-4 text-center border-bottom mb-4">
  60. <h4>家谱管理</h4>
  61. </div>
  62. <nav>
  63. <a href="{{ url_for('home') }}" class="{% if request.endpoint == 'home' %}active{% endif %}">
  64. <i class="bi bi-house me-2"></i> 系统首页
  65. </a>
  66. {% if session.get('is_super_admin') %}
  67. <a href="{{ url_for('pdf_management') }}" class="{% if request.endpoint == 'pdf_management' %}active{% endif %}">
  68. <i class="bi bi-book me-2"></i> 家谱管理
  69. </a>
  70. {% endif %}
  71. <a href="{{ url_for('index') }}" class="{% if request.endpoint == 'index' %}active{% endif %}">
  72. <i class="bi bi-file-earmark-arrow-up me-2"></i> 扫描件管理
  73. </a>
  74. <a href="{{ url_for('members') }}" class="{% if request.endpoint == 'members' %}active{% endif %}">
  75. <i class="bi bi-people me-2"></i> 成员列表
  76. </a>
  77. <a href="{{ url_for('tree') }}" class="{% if request.endpoint == 'tree' %}active{% endif %}">
  78. <i class="bi bi-diagram-3 me-2"></i> 家谱世系树状图
  79. </a>
  80. <a href="{{ url_for('lineage_query') }}" class="{% if request.endpoint == 'lineage_query' %}active{% endif %}">
  81. <i class="bi bi-tree me-2"></i> 世系查询
  82. </a>
  83. <a href="{{ url_for('settlements') }}" class="{% if request.endpoint == 'settlements' %}active{% endif %}">
  84. <i class="bi bi-globe me-2"></i> 聚落地图
  85. </a>
  86. <div class="mt-5 border-top pt-3">
  87. <p class="px-3 small text-muted">用户: {{ session['username'] }}</p>
  88. <a href="{{ url_for('logout') }}" class="text-danger">
  89. <i class="bi bi-box-arrow-right me-2"></i> 退出登录
  90. </a>
  91. </div>
  92. </nav>
  93. </div>
  94. {% endif %}
  95. <!-- Watermark -->
  96. <div class="watermark-container" id="watermarkContainer"></div>
  97. <div class="watermark-corner" id="watermarkCorner"></div>
  98. <!-- Main Content -->
  99. <div class="col-md-{% if session.get('user_id') %}10{% else %}12{% endif %} content-area">
  100. {% with messages = get_flashed_messages() %}
  101. {% if messages %}
  102. {% for message in messages %}
  103. <div class="alert alert-info alert-dismissible fade show" role="alert">
  104. {{ message }}
  105. <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
  106. </div>
  107. {% endfor %}
  108. {% endif %}
  109. {% endwith %}
  110. {% block content %}{% endblock %}
  111. </div>
  112. </div>
  113. </div>
  114. <!-- Local Bootstrap JS -->
  115. <script src="{{ url_for('static', filename='js/bootstrap.bundle.min.js') }}"></script>
  116. <!-- Watermark Script -->
  117. <script>
  118. document.addEventListener('DOMContentLoaded', function() {
  119. const username = "{{ session.get('username', '') }}";
  120. const container = document.getElementById('watermarkContainer');
  121. const corner = document.getElementById('watermarkCorner');
  122. function formatWatermarkText() {
  123. if (!username) return '';
  124. const now = new Date();
  125. const year = now.getFullYear();
  126. const month = String(now.getMonth() + 1).padStart(2, '0');
  127. const day = String(now.getDate()).padStart(2, '0');
  128. const hour = String(now.getHours()).padStart(2, '0');
  129. const minute = String(now.getMinutes()).padStart(2, '0');
  130. return `${username}_${year}${month}${day}_${hour}${minute}`;
  131. }
  132. // Generate tiled watermark
  133. if (container && username) {
  134. const cols = 6;
  135. const rows = 8;
  136. const cellWidth = window.innerWidth / cols;
  137. const cellHeight = window.innerHeight / rows;
  138. function updateTiledWatermark() {
  139. container.innerHTML = '';
  140. const watermarkText = formatWatermarkText();
  141. for (let i = 0; i < rows; i++) {
  142. for (let j = 0; j < cols; j++) {
  143. const span = document.createElement('span');
  144. span.className = 'watermark-text';
  145. span.textContent = watermarkText;
  146. span.style.left = (j * cellWidth + 20) + 'px';
  147. span.style.top = (i * cellHeight + 20) + 'px';
  148. container.appendChild(span);
  149. }
  150. }
  151. }
  152. updateTiledWatermark();
  153. setInterval(updateTiledWatermark, 60000);
  154. }
  155. // Update corner watermark
  156. function updateCornerWatermark() {
  157. if (corner && username) {
  158. corner.textContent = formatWatermarkText();
  159. }
  160. }
  161. updateCornerWatermark();
  162. setInterval(updateCornerWatermark, 1000);
  163. });
  164. </script>
  165. {% block extra_js %}{% endblock %}
  166. </body>
  167. </html>