ソースを参照

Merge branch 'employeeScreen' of https://git.sundot.cn/chongqing/chongqing-web into employeeScreen

lixiangrui 1 ヶ月 前
コミット
beba78a00a

+ 226 - 0
src/views/portraitManagement/components/PentagonGroup.vue

@@ -0,0 +1,226 @@
1
+<template>
2
+  <div class="pentagon-group">
3
+    <div
4
+      v-for="(item, index) in items"
5
+      :key="index"
6
+      class="pentagon-item"
7
+      :class="{ 'middle': item.isMiddle }"
8
+    >
9
+      <svg class="pentagon-svg" viewBox="0 0 300 200" preserveAspectRatio="none">
10
+        <defs>
11
+          <linearGradient :id="`bgGradient-${index}`" x1="0%" y1="0%" x2="100%" y2="100%">
12
+            <stop offset="0%" :stop-color="item.bgGradientStart || 'rgba(33,33,58,0.95)'" />
13
+            <stop offset="100%" :stop-color="item.bgGradientEnd || 'rgba(15,70,250,0.15)'" />
14
+          </linearGradient>
15
+          <linearGradient :id="`borderGradient-${index}`" x1="0%" y1="0%" x2="100%" y2="100%">
16
+            <stop offset="0%" :stop-color="item.edgeGradients?.top?.start || '#0f46fa'" />
17
+            <stop offset="50%" :stop-color="item.edgeGradients?.right?.start || '#bd03fb'" />
18
+            <stop offset="100%" :stop-color="item.edgeGradients?.bottom?.start || '#7eff7e'" />
19
+          </linearGradient>
20
+          <filter :id="`glow-${index}`">
21
+            <feGaussianBlur stdDeviation="2" result="coloredBlur" />
22
+            <feMerge>
23
+              <feMergeNode in="coloredBlur" />
24
+              <feMergeNode in="SourceGraphic" />
25
+            </feMerge>
26
+          </filter>
27
+        </defs>
28
+        <path
29
+          :d="getQuadPath(item.vertices, item.isMiddle, index)"
30
+          :fill="`url(#bgGradient-${index})`"
31
+        />
32
+        <path
33
+          :d="getQuadPath(item.vertices, item.isMiddle, index)"
34
+          fill="none"
35
+          :stroke="`url(#borderGradient-${index})`"
36
+          stroke-width="3"
37
+          :filter="`url(#glow-${index})`"
38
+        />
39
+      </svg>
40
+      <div class="card-content">
41
+        <div class="icon-wrapper" :class="{ 'large': item.isMiddle }">
42
+          <span v-if="item.icon" class="icon-emoji">{{ item.icon }}</span>
43
+        </div>
44
+        <div class="text-wrapper">
45
+          <div class="value">{{ item.value }}</div>
46
+          <div class="label" v-if="item.label">{{ item.label }}</div>
47
+        </div>
48
+      </div>
49
+    </div>
50
+  </div>
51
+</template>
52
+
53
+<script setup>
54
+const props = defineProps({
55
+  items: {
56
+    type: Array,
57
+    default: () => []
58
+  }
59
+})
60
+
61
+const getVertices = (vertices, isMiddle, index) => {
62
+  if (vertices) {
63
+    return vertices
64
+  } else if (isMiddle) {
65
+    return {
66
+      topLeft: { x: 20, y: 0 },
67
+      topRight: { x: 280, y: 0 },
68
+      bottomRight: { x: 300, y: 200 },
69
+      bottomLeft: { x: 0, y: 200 }
70
+    }
71
+  } else {
72
+    if (index === 0) {
73
+      return {
74
+        topLeft: { x: 0, y: 0 },
75
+        topRight: { x: 300, y: 0 },
76
+        bottomRight: { x: 280, y: 200 },
77
+        bottomLeft: { x: 0, y: 200 }
78
+      }
79
+    } else if (index === 1) {
80
+      return {
81
+        topLeft: { x: 20, y: 0 },
82
+        topRight: { x: 320, y: 0 },
83
+        bottomRight: { x: 300, y: 200 },
84
+        bottomLeft: { x: 0, y: 200 }
85
+      }
86
+    } else if (index === 3) {
87
+      return {
88
+        topLeft: { x: -20, y: 0 },
89
+        topRight: { x: 300, y: 0 },
90
+        bottomRight: { x: 320, y: 200 },
91
+        bottomLeft: { x: 0, y: 200 }
92
+      }
93
+    } else {
94
+      return {
95
+        topLeft: { x: 20, y: 0 },
96
+        topRight: { x: 300, y: 0 },
97
+        bottomRight: { x: 300, y: 200 },
98
+        bottomLeft: { x: 40, y: 200 }
99
+      }
100
+    }
101
+  }
102
+}
103
+
104
+const getQuadPath = (vertices, isMiddle, index) => {
105
+  const v = getVertices(vertices, isMiddle, index)
106
+  return `M ${v.topLeft.x} ${v.topLeft.y} L ${v.topRight.x} ${v.topRight.y} L ${v.bottomRight.x} ${v.bottomRight.y} L ${v.bottomLeft.x} ${v.bottomLeft.y} Z`
107
+}
108
+</script>
109
+
110
+<style lang="scss" scoped>
111
+.pentagon-group {
112
+  display: flex;
113
+  justify-content: center;
114
+  align-items: stretch;
115
+  gap: 0;
116
+  padding: 20px;
117
+  position: relative;
118
+  z-index: 10;
119
+  width: 100%;
120
+}
121
+
122
+.pentagon-item {
123
+  position: relative;
124
+  flex: 1;
125
+  min-width: 0;
126
+  height: 160px;
127
+  display: flex;
128
+  align-items: center;
129
+  justify-content: center;
130
+
131
+  &.middle {
132
+    flex: 1.3;
133
+    height: 200px;
134
+    z-index: 5;
135
+    margin: 0 -5px;
136
+
137
+    .card-content {
138
+      flex-direction: column;
139
+
140
+      .icon-wrapper {
141
+        margin-right: 0;
142
+        margin-bottom: 15px;
143
+      }
144
+
145
+      .text-wrapper {
146
+        align-items: center;
147
+      }
148
+
149
+      .value {
150
+        font-size: 32px;
151
+      }
152
+
153
+      .label {
154
+        font-size: 18px;
155
+      }
156
+    }
157
+  }
158
+
159
+  .pentagon-svg {
160
+    position: absolute;
161
+    width: 100%;
162
+    height: 100%;
163
+    top: 0;
164
+    left: 0;
165
+    display: block;
166
+    overflow: visible;
167
+  }
168
+
169
+  .card-content {
170
+    position: relative;
171
+    z-index: 1;
172
+    display: flex;
173
+    flex-direction: row;
174
+    align-items: center;
175
+    justify-content: center;
176
+    padding: 15px 25px;
177
+    gap: 15px;
178
+
179
+    .icon-wrapper {
180
+      width: 50px;
181
+      height: 50px;
182
+      border-radius: 50%;
183
+      background: linear-gradient(135deg, #0f46fa, #bd03fb);
184
+      display: flex;
185
+      align-items: center;
186
+      justify-content: center;
187
+      box-shadow: 0 0 15px rgba(15, 70, 250, 0.5);
188
+      flex-shrink: 0;
189
+
190
+      &.large {
191
+        width: 80px;
192
+        height: 80px;
193
+      }
194
+
195
+      .icon-emoji {
196
+        font-size: 24px;
197
+        line-height: 1;
198
+
199
+        .large & {
200
+          font-size: 36px;
201
+        }
202
+      }
203
+    }
204
+
205
+    .text-wrapper {
206
+      display: flex;
207
+      flex-direction: column;
208
+      align-items: flex-start;
209
+    }
210
+
211
+    .value {
212
+      font-size: 40px;
213
+      font-weight: bold;
214
+      color: #fff;
215
+      text-shadow: 0 0 12px rgba(15, 70, 250, 0.8);
216
+      line-height: 1;
217
+    }
218
+
219
+    .label {
220
+      font-size: 14px;
221
+      color: #a0c4ff;
222
+      margin-top: 5px;
223
+    }
224
+  }
225
+}
226
+</style>

+ 6 - 4
src/views/portraitManagement/components/page.vue

@@ -22,10 +22,13 @@ const props = defineProps({
22 22
 
23 23
 <style lang="scss" scoped>
24 24
 .bg {
25
-  height: 100vh;
26 25
   width: 100%;
26
+  min-height: 100vh;
27 27
   position: relative;
28 28
   background-image: url('@/assets/dataBigScreen/bg.png');
29
+  background-repeat: repeat-y;
30
+  background-size: 100% auto;
31
+  background-position: top center;
29 32
   &::before {
30 33
     content: '';
31 34
     position: absolute;
@@ -35,12 +38,11 @@ const props = defineProps({
35 38
     z-index: 1;
36 39
   }
37 40
   .page {
38
-    content: '';
39
-    position: absolute;
40
-    inset: 0;
41
+    position: relative;
41 42
     z-index: 2;
42 43
     display: flex;
43 44
     flex-direction: column;
45
+    min-height: 100vh;
44 46
   }
45 47
   .title {
46 48
     height: 88px;

+ 0 - 0
src/views/portraitManagement/deptProfile/index.vue


File diff suppressed because it is too large
+ 1177 - 0
src/views/portraitManagement/groupProfile/index.vue


+ 0 - 0
src/views/portraitManagement/stationProfile/index.vue


+ 0 - 0
src/views/portraitManagement/teamProfile/index.vue