WaterGisPageShell.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <template>
  2. <section class="water-gis-shell" :class="{ 'is-embedded': embedded }">
  3. <header class="gis-header">
  4. <div class="gis-heading">
  5. <p class="eyebrow">{{ eyebrow }}</p>
  6. <h2>{{ title }}</h2>
  7. <p v-if="subtitle" class="shell-subtitle">{{ subtitle }}</p>
  8. </div>
  9. <div class="header-actions">
  10. <slot name="actions" />
  11. </div>
  12. </header>
  13. <div class="gis-layout">
  14. <aside class="side-panel">
  15. <div class="side-panel-body">
  16. <div class="metric-grid">
  17. <slot name="metrics" />
  18. </div>
  19. <div class="panel-section controls-section">
  20. <slot name="controls" />
  21. </div>
  22. <div class="panel-section legend-panel">
  23. <slot name="legend" />
  24. </div>
  25. <div class="panel-section result-section">
  26. <slot name="results" />
  27. </div>
  28. </div>
  29. </aside>
  30. <main class="map-panel" v-loading="loading">
  31. <slot name="map" />
  32. </main>
  33. </div>
  34. <slot name="drawer" />
  35. </section>
  36. </template>
  37. <script setup>
  38. defineProps({
  39. eyebrow: { type: String, default: '' },
  40. title: { type: String, required: true },
  41. subtitle: { type: String, default: '' },
  42. loading: { type: Boolean, default: false },
  43. embedded: { type: Boolean, default: false }
  44. })
  45. </script>
  46. <style scoped>
  47. .water-gis-shell {
  48. min-height: 100%;
  49. padding: 18px;
  50. background: linear-gradient(180deg, #edf6ff 0%, #f5f7fb 100%);
  51. color: #1f3b57;
  52. }
  53. .water-gis-shell.is-embedded {
  54. min-height: auto;
  55. padding: 0;
  56. background: transparent;
  57. }
  58. .gis-header {
  59. display: flex;
  60. align-items: center;
  61. justify-content: space-between;
  62. gap: 18px;
  63. margin-bottom: 16px;
  64. }
  65. .eyebrow {
  66. margin: 0 0 3px;
  67. font-size: 11px;
  68. letter-spacing: .12em;
  69. color: #5c93c7;
  70. }
  71. .gis-header h2 {
  72. margin: 0;
  73. font-size: 22px;
  74. color: #173a5e;
  75. }
  76. .shell-subtitle {
  77. margin: 4px 0 0;
  78. font-size: 13px;
  79. color: #678197;
  80. }
  81. .header-actions {
  82. display: flex;
  83. align-items: center;
  84. gap: 10px;
  85. }
  86. .gis-layout {
  87. display: grid;
  88. grid-template-columns: minmax(280px, 330px) minmax(0, 1fr);
  89. gap: 16px;
  90. height: calc(100vh - 132px);
  91. min-height: 620px;
  92. }
  93. .is-embedded .gis-layout {
  94. height: clamp(560px, calc(100vh - 300px), 760px);
  95. }
  96. .side-panel,
  97. .map-panel {
  98. background: rgba(255, 255, 255, .94);
  99. border: 1px solid #dbe8f5;
  100. border-radius: 10px;
  101. box-shadow: 0 10px 28px rgba(31, 74, 121, .08);
  102. }
  103. .side-panel {
  104. display: flex;
  105. flex-direction: column;
  106. overflow: hidden;
  107. }
  108. .side-panel-body {
  109. height: 100%;
  110. display: flex;
  111. flex-direction: column;
  112. gap: 14px;
  113. padding: 16px;
  114. overflow-y: auto;
  115. }
  116. .metric-grid {
  117. display: grid;
  118. grid-template-columns: repeat(2, minmax(0, 1fr));
  119. gap: 8px;
  120. }
  121. .panel-section :deep(h3) {
  122. margin: 0 0 8px;
  123. font-size: 14px;
  124. color: #29567e;
  125. }
  126. .legend-panel {
  127. border-top: 1px solid #e4eef8;
  128. padding-top: 12px;
  129. }
  130. .result-section {
  131. flex: 1;
  132. min-height: 0;
  133. }
  134. .map-panel {
  135. position: relative;
  136. overflow: hidden;
  137. }
  138. @media (max-width: 1200px) {
  139. .gis-header {
  140. align-items: flex-start;
  141. flex-direction: column;
  142. }
  143. .gis-layout {
  144. grid-template-columns: 1fr;
  145. height: auto;
  146. }
  147. .is-embedded .gis-layout {
  148. height: auto;
  149. }
  150. .side-panel {
  151. min-height: 480px;
  152. }
  153. .map-panel {
  154. height: 560px;
  155. }
  156. .header-actions :deep(.search-input),
  157. .header-actions :deep(.type-select) {
  158. width: 180px;
  159. }
  160. }
  161. </style>