闪电 10 miesięcy temu
rodzic
commit
c60e7bc516

+ 3 - 0
package.json

@@ -88,12 +88,15 @@
88 88
   "devDependencies": {
89 89
     "@vitejs/plugin-vue": "3.1.0",
90 90
     "@vue/compiler-sfc": "3.2.45",
91
+    "autoprefixer": "^10.4.20",
91 92
     "eslint-config-prettier": "^8.8.0",
92 93
     "eslint-plugin-prettier": "^4.2.1",
93 94
     "husky": "^8.0.0",
94 95
     "lodash": "^4.17.21",
96
+    "postcss": "^8.5.3",
95 97
     "prettier": "^2.8.8",
96 98
     "sass": "1.56.1",
99
+    "tailwindcss": "^3.4.17",
97 100
     "unplugin-auto-import": "0.11.4",
98 101
     "vite": "3.2.3",
99 102
     "vite-plugin-compression": "0.5.1",

+ 34 - 0
src/assets/style.css

@@ -1208,6 +1208,16 @@ video {
1208 1208
   background-color: rgb(254 252 232 / var(--tw-bg-opacity, 1));
1209 1209
 }
1210 1210
 
1211
+.bg-blue-500 {
1212
+  --tw-bg-opacity: 1;
1213
+  background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));
1214
+}
1215
+
1216
+.bg-green-500 {
1217
+  --tw-bg-opacity: 1;
1218
+  background-color: rgb(34 197 94 / var(--tw-bg-opacity, 1));
1219
+}
1220
+
1211 1221
 .bg-gradient-to-b {
1212 1222
   background-image: linear-gradient(to bottom, var(--tw-gradient-stops));
1213 1223
 }
@@ -1280,6 +1290,11 @@ video {
1280 1290
   padding-bottom: 1.5rem;
1281 1291
 }
1282 1292
 
1293
+.py-2 {
1294
+  padding-top: 0.5rem;
1295
+  padding-bottom: 0.5rem;
1296
+}
1297
+
1283 1298
 .pb-6 {
1284 1299
   padding-bottom: 1.5rem;
1285 1300
 }
@@ -1312,6 +1327,10 @@ video {
1312 1327
   text-align: center;
1313 1328
 }
1314 1329
 
1330
+.text-right {
1331
+  text-align: right;
1332
+}
1333
+
1315 1334
 .align-top {
1316 1335
   vertical-align: top;
1317 1336
 }
@@ -1567,11 +1586,26 @@ video {
1567 1586
   background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
1568 1587
 }
1569 1588
 
1589
+.hover\:bg-blue-600:hover {
1590
+  --tw-bg-opacity: 1;
1591
+  background-color: rgb(37 99 235 / var(--tw-bg-opacity, 1));
1592
+}
1593
+
1594
+.hover\:bg-green-600:hover {
1595
+  --tw-bg-opacity: 1;
1596
+  background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1));
1597
+}
1598
+
1570 1599
 .hover\:text-blue-800:hover {
1571 1600
   --tw-text-opacity: 1;
1572 1601
   color: rgb(30 64 175 / var(--tw-text-opacity, 1));
1573 1602
 }
1574 1603
 
1604
+.hover\:text-white:hover {
1605
+  --tw-text-opacity: 1;
1606
+  color: rgb(255 255 255 / var(--tw-text-opacity, 1));
1607
+}
1608
+
1575 1609
 .hover\:shadow-md:hover {
1576 1610
   --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
1577 1611
   --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);

+ 160 - 0
src/views/main/report/connectionVolumes/connectionVolumes.vue

@@ -0,0 +1,160 @@
1
+<!-- 代码已包含 CSS:使用 TailwindCSS , 安装 TailwindCSS 后方可看到布局样式效果 -->
2
+
3
+<template>
4
+    <div class="min-h-screen bg-gray-50 p-6">
5
+      <div class="mx-auto">
6
+        <!-- 顶部搜索区域 -->
7
+        <div class="mb-6 flex items-center justify-between bg-white p-4 shadow-sm">
8
+          <div class="flex gap-4">
9
+            <button
10
+              v-for="(btn, index) in quickButtons"
11
+              :key="index"
12
+              :class="{
13
+                'bg-blue-500 text-white': selectedQuickBtn === btn.value,
14
+                'bg-gray-100 text-gray-600': selectedQuickBtn !== btn.value
15
+              }"
16
+              class="!rounded-button whitespace-nowrap px-4 py-2 transition-all hover:bg-blue-600 hover:text-white"
17
+              @click="handleQuickSelect(btn.value)"
18
+            >
19
+              {{ btn.label }}
20
+            </button>
21
+          </div>
22
+          <div class="flex items-center gap-4">
23
+            <el-date-picker
24
+              v-model="dateRange"
25
+              type="daterange"
26
+              range-separator="至"
27
+              start-placeholder="开始日期"
28
+              end-placeholder="结束日期"
29
+              :size="'default'"
30
+              @change="handleDateChange"
31
+            />
32
+            <button class="!rounded-button whitespace-nowrap bg-blue-500 px-4 py-2 text-white hover:bg-blue-600">
33
+              <el-icon class="mr-1"><Search /></el-icon>
34
+              查询
35
+            </button>
36
+          </div>
37
+        </div>
38
+  
39
+        <!-- 通话接通量统计 -->
40
+        <div class="mb-6 bg-white p-6 shadow-sm">
41
+          <div class="mb-4 flex items-center justify-between">
42
+            <h2 class="text-xl font-bold">通话接通量统计</h2>
43
+            <button class="!rounded-button whitespace-nowrap bg-green-500 px-4 py-2 text-white hover:bg-green-600">
44
+              <el-icon class="mr-1"><Download /></el-icon>
45
+              导出数据
46
+            </button>
47
+          </div>
48
+          <div class="h-[400px]">
49
+            <div ref="dailyFlowChart" class="h-full w-full"></div>
50
+          </div>
51
+        </div>
52
+
53
+      </div>
54
+    </div>
55
+  </template>
56
+  
57
+  <script lang="ts" setup>
58
+  import { ref, onMounted } from 'vue';
59
+  import { Search, Download } from '@element-plus/icons-vue';
60
+  import * as echarts from 'echarts';
61
+  import { getPageListData } from '@/api/main/system/system';
62
+
63
+  import type { EChartsOption } from 'echarts';
64
+  
65
+  const dateRange = ref([]);
66
+  const selectedQuickBtn = ref('30days');
67
+  
68
+  const quickButtons = [
69
+    { label: '今天', value: 'today' },
70
+    { label: '昨天', value: 'yesterday' },
71
+    { label: '近7天', value: '7days' },
72
+    { label: '近30天', value: '30days' },
73
+  ];
74
+  
75
+  const callVolumeChart = ref<HTMLElement | null>(null);
76
+  const dailyFlowChart = ref<HTMLElement | null>(null);
77
+  const monthlyFlowChart = ref<HTMLElement | null>(null);
78
+  
79
+  const totalYearlyFlow = ref(2456789);
80
+  
81
+  const handleQuickSelect = (value: string) => {
82
+    selectedQuickBtn.value = value;
83
+    // 处理快速选择逻辑
84
+  };
85
+  
86
+  const handleDateChange = () => {
87
+    // 处理日期变化逻辑
88
+  };
89
+  
90
+  onMounted(() => {
91
+    getDailyFlow()  // 日流量统计图表
92
+  
93
+  });
94
+  
95
+  // 日流量统计图表
96
+  function getDailyFlow(){
97
+
98
+    // getPageListData('/WorkReport/selectConnection').then(res => {
99
+        // console.log(res);
100
+        const dailyFlow = echarts.init(dailyFlowChart.value!);
101
+        const dailyFlowOption: EChartsOption = {
102
+            animation: false,
103
+            tooltip: {
104
+                trigger: 'axis'
105
+            },
106
+            grid: {
107
+                left: '3%',
108
+                right: '4%',
109
+                bottom: '3%',
110
+                containLabel: true
111
+            },
112
+            xAxis: {
113
+                type: 'category',
114
+                data: Array.from({length: 24}, (_, i) => `${i}:00`)
115
+            },
116
+            yAxis: {
117
+                type: 'value'
118
+            },
119
+            series: [{
120
+                name: '流量',
121
+                type: 'line',
122
+                smooth: true,
123
+                data: Array.from({length: 24}, () => Math.floor(Math.random() * 200 + 100)),
124
+                itemStyle: {
125
+                color: '#10B981'
126
+                },
127
+                areaStyle: {
128
+                color: {
129
+                    type: 'linear',
130
+                    x: 0,
131
+                    y: 0,
132
+                    x2: 0,
133
+                    y2: 1,
134
+                    colorStops: [{
135
+                    offset: 0,
136
+                    color: 'rgba(16, 185, 129, 0.2)'
137
+                    }, {
138
+                    offset: 1,
139
+                    color: 'rgba(16, 185, 129, 0)'
140
+                    }]
141
+                }
142
+                }
143
+            }]
144
+        };
145
+        dailyFlow.setOption(dailyFlowOption);
146
+        window.addEventListener('resize', () => {
147
+            dailyFlow.resize();
148
+        });
149
+    // });
150
+  }
151
+
152
+  </script>
153
+  
154
+  <style scoped>
155
+  .el-date-editor {
156
+    --el-date-editor-width: 320px;
157
+  }
158
+  </style>
159
+  
160
+  

+ 251 - 0
src/views/main/report/connectionVolumes/connectionVolumesBF.vue

@@ -0,0 +1,251 @@
1
+<!-- 代码已包含 CSS:使用 TailwindCSS , 安装 TailwindCSS 后方可看到布局样式效果 -->
2
+
3
+<template>
4
+  <div class="min-h-screen bg-gray-50 p-6">
5
+    <div class="mx-auto max-w-7xl">
6
+      <!-- 顶部搜索区域 -->
7
+      <div class="mb-6 flex items-center justify-between bg-white p-4 shadow-sm">
8
+        <div class="flex gap-4">
9
+          <button
10
+            v-for="(btn, index) in quickButtons"
11
+            :key="index"
12
+            :class="{
13
+              'bg-blue-500 text-white': selectedQuickBtn === btn.value,
14
+              'bg-gray-100 text-gray-600': selectedQuickBtn !== btn.value
15
+            }"
16
+            class="!rounded-button whitespace-nowrap px-4 py-2 transition-all hover:bg-blue-600 hover:text-white"
17
+            @click="handleQuickSelect(btn.value)"
18
+          >
19
+            {{ btn.label }}
20
+          </button>
21
+        </div>
22
+        <div class="flex items-center gap-4">
23
+          <el-date-picker
24
+            v-model="dateRange"
25
+            type="daterange"
26
+            range-separator="至"
27
+            start-placeholder="开始日期"
28
+            end-placeholder="结束日期"
29
+            :size="'default'"
30
+            @change="handleDateChange"
31
+          />
32
+          <button class="!rounded-button whitespace-nowrap bg-blue-500 px-4 py-2 text-white hover:bg-blue-600">
33
+            <el-icon class="mr-1"><Search /></el-icon>
34
+            查询
35
+          </button>
36
+        </div>
37
+      </div>
38
+
39
+      <!-- 通话接通量统计 -->
40
+      <div class="mb-6 bg-white p-6 shadow-sm">
41
+        <div class="mb-4 flex items-center justify-between">
42
+          <h2 class="text-xl font-bold">通话接通量统计</h2>
43
+          <button class="!rounded-button whitespace-nowrap bg-green-500 px-4 py-2 text-white hover:bg-green-600">
44
+            <el-icon class="mr-1"><Download /></el-icon>
45
+            导出数据
46
+          </button>
47
+        </div>
48
+        <div class="h-[400px]">
49
+          <div ref="callVolumeChart" class="h-full w-full"></div>
50
+        </div>
51
+      </div>
52
+
53
+      <!-- 日流量统计 -->
54
+      <div class="mb-6 bg-white p-6 shadow-sm">
55
+        <div class="mb-4 flex items-center justify-between">
56
+          <h2 class="text-xl font-bold">日流量统计</h2>
57
+          <div class="text-sm text-gray-500">最近24小时数据</div>
58
+        </div>
59
+        <div class="h-[300px]">
60
+          <div ref="dailyFlowChart" class="h-full w-full"></div>
61
+        </div>
62
+      </div>
63
+
64
+      <!-- 月流量统计 -->
65
+      <div class="bg-white p-6 shadow-sm">
66
+        <div class="mb-4 flex items-center justify-between">
67
+          <h2 class="text-xl font-bold">月流量统计</h2>
68
+          <div class="text-sm text-gray-500">{{ new Date().getFullYear() }}年度数据</div>
69
+        </div>
70
+        <div class="h-[300px]">
71
+          <div ref="monthlyFlowChart" class="h-full w-full"></div>
72
+        </div>
73
+        <div class="mt-4 text-right text-sm text-gray-600">
74
+          年度总流量:{{ totalYearlyFlow.toLocaleString() }} 次
75
+        </div>
76
+      </div>
77
+    </div>
78
+  </div>
79
+</template>
80
+
81
+<script lang="ts" setup>
82
+import { ref, onMounted } from 'vue';
83
+import { Search, Download } from '@element-plus/icons-vue';
84
+import * as echarts from 'echarts';
85
+import type { EChartsOption } from 'echarts';
86
+
87
+const dateRange = ref([]);
88
+const selectedQuickBtn = ref('30days');
89
+
90
+const quickButtons = [
91
+  { label: '今天', value: 'today' },
92
+  { label: '昨天', value: 'yesterday' },
93
+  { label: '近7天', value: '7days' },
94
+  { label: '近30天', value: '30days' },
95
+];
96
+
97
+const callVolumeChart = ref<HTMLElement | null>(null);
98
+const dailyFlowChart = ref<HTMLElement | null>(null);
99
+const monthlyFlowChart = ref<HTMLElement | null>(null);
100
+
101
+const totalYearlyFlow = ref(2456789);
102
+
103
+const handleQuickSelect = (value: string) => {
104
+  selectedQuickBtn.value = value;
105
+  // 处理快速选择逻辑
106
+};
107
+
108
+const handleDateChange = () => {
109
+  // 处理日期变化逻辑
110
+};
111
+
112
+onMounted(() => {
113
+  // 通话接通量统计图表
114
+  const callVolume = echarts.init(callVolumeChart.value!);
115
+  const callVolumeOption: EChartsOption = {
116
+    animation: false,
117
+    tooltip: {
118
+      trigger: 'axis',
119
+      axisPointer: {
120
+        type: 'shadow'
121
+      }
122
+    },
123
+    grid: {
124
+      left: '3%',
125
+      right: '4%',
126
+      bottom: '3%',
127
+      containLabel: true
128
+    },
129
+    xAxis: {
130
+      type: 'category',
131
+      data: Array.from({length: 30}, (_, i) => {
132
+        const date = new Date();
133
+        date.setDate(date.getDate() - (29 - i));
134
+        return `${date.getMonth() + 1}/${date.getDate()}`;
135
+      }),
136
+      axisLabel: {
137
+        interval: 2
138
+      }
139
+    },
140
+    yAxis: {
141
+      type: 'value'
142
+    },
143
+    series: [{
144
+      name: '接通量',
145
+      type: 'bar',
146
+      data: Array.from({length: 30}, () => Math.floor(Math.random() * 1000 + 500)),
147
+      label: {
148
+        show: true,
149
+        position: 'top'
150
+      },
151
+      itemStyle: {
152
+        color: '#60A5FA'
153
+      }
154
+    }]
155
+  };
156
+  callVolume.setOption(callVolumeOption);
157
+
158
+  // 日流量统计图表
159
+  const dailyFlow = echarts.init(dailyFlowChart.value!);
160
+  const dailyFlowOption: EChartsOption = {
161
+    animation: false,
162
+    tooltip: {
163
+      trigger: 'axis'
164
+    },
165
+    grid: {
166
+      left: '3%',
167
+      right: '4%',
168
+      bottom: '3%',
169
+      containLabel: true
170
+    },
171
+    xAxis: {
172
+      type: 'category',
173
+      data: Array.from({length: 24}, (_, i) => `${i}:00`)
174
+    },
175
+    yAxis: {
176
+      type: 'value'
177
+    },
178
+    series: [{
179
+      name: '流量',
180
+      type: 'line',
181
+      smooth: true,
182
+      data: Array.from({length: 24}, () => Math.floor(Math.random() * 200 + 100)),
183
+      itemStyle: {
184
+        color: '#10B981'
185
+      },
186
+      areaStyle: {
187
+        color: {
188
+          type: 'linear',
189
+          x: 0,
190
+          y: 0,
191
+          x2: 0,
192
+          y2: 1,
193
+          colorStops: [{
194
+            offset: 0,
195
+            color: 'rgba(16, 185, 129, 0.2)'
196
+          }, {
197
+            offset: 1,
198
+            color: 'rgba(16, 185, 129, 0)'
199
+          }]
200
+        }
201
+      }
202
+    }]
203
+  };
204
+  dailyFlow.setOption(dailyFlowOption);
205
+
206
+  // 月流量统计图表
207
+  const monthlyFlow = echarts.init(monthlyFlowChart.value!);
208
+  const monthlyFlowOption: EChartsOption = {
209
+    animation: false,
210
+    tooltip: {
211
+      trigger: 'axis'
212
+    },
213
+    grid: {
214
+      left: '3%',
215
+      right: '4%',
216
+      bottom: '3%',
217
+      containLabel: true
218
+    },
219
+    xAxis: {
220
+      type: 'category',
221
+      data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
222
+    },
223
+    yAxis: {
224
+      type: 'value'
225
+    },
226
+    series: [{
227
+      name: '月流量',
228
+      type: 'bar',
229
+      data: Array.from({length: 12}, () => Math.floor(Math.random() * 20000 + 15000)),
230
+      itemStyle: {
231
+        color: '#8B5CF6'
232
+      }
233
+    }]
234
+  };
235
+  monthlyFlow.setOption(monthlyFlowOption);
236
+
237
+  // 响应式处理
238
+  window.addEventListener('resize', () => {
239
+    callVolume.resize();
240
+    dailyFlow.resize();
241
+    monthlyFlow.resize();
242
+  });
243
+});
244
+</script>
245
+
246
+<style scoped>
247
+.el-date-editor {
248
+  --el-date-editor-width: 320px;
249
+}
250
+</style>
251
+