miaofuhao 10 kuukautta sitten
vanhempi
commit
cb41990fe8

+ 3 - 0
package.json

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

+ 38 - 4
src/assets/style.css

@@ -829,10 +829,6 @@ video {
829 829
   height: 400px;
830 830
 }
831 831
 
832
-.h-\[600px\] {
833
-  height: 600px;
834
-}
835
-
836 832
 .h-full {
837 833
   height: 100%;
838 834
 }
@@ -889,6 +885,10 @@ video {
889 885
   width: 24rem;
890 886
 }
891 887
 
888
+.w-\[100\%\] {
889
+  width: 100%;
890
+}
891
+
892 892
 .w-\[320px\] {
893 893
   width: 320px;
894 894
 }
@@ -1138,6 +1138,11 @@ video {
1138 1138
   background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1));
1139 1139
 }
1140 1140
 
1141
+.bg-blue-500 {
1142
+  --tw-bg-opacity: 1;
1143
+  background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));
1144
+}
1145
+
1141 1146
 .bg-gray-100 {
1142 1147
   --tw-bg-opacity: 1;
1143 1148
   background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
@@ -1168,6 +1173,11 @@ video {
1168 1173
   background-color: rgb(240 253 244 / var(--tw-bg-opacity, 1));
1169 1174
 }
1170 1175
 
1176
+.bg-green-500 {
1177
+  --tw-bg-opacity: 1;
1178
+  background-color: rgb(34 197 94 / var(--tw-bg-opacity, 1));
1179
+}
1180
+
1171 1181
 .bg-purple-50 {
1172 1182
   --tw-bg-opacity: 1;
1173 1183
   background-color: rgb(250 245 255 / var(--tw-bg-opacity, 1));
@@ -1232,6 +1242,11 @@ video {
1232 1242
   padding-right: 1rem;
1233 1243
 }
1234 1244
 
1245
+.py-2 {
1246
+  padding-top: 0.5rem;
1247
+  padding-bottom: 0.5rem;
1248
+}
1249
+
1235 1250
 .py-4 {
1236 1251
   padding-top: 1rem;
1237 1252
   padding-bottom: 1rem;
@@ -1270,6 +1285,10 @@ video {
1270 1285
   text-align: center;
1271 1286
 }
1272 1287
 
1288
+.text-right {
1289
+  text-align: right;
1290
+}
1291
+
1273 1292
 .align-top {
1274 1293
   vertical-align: top;
1275 1294
 }
@@ -1510,6 +1529,11 @@ video {
1510 1529
   transition-duration: 300ms;
1511 1530
 }
1512 1531
 
1532
+.hover\:bg-blue-600:hover {
1533
+  --tw-bg-opacity: 1;
1534
+  background-color: rgb(37 99 235 / var(--tw-bg-opacity, 1));
1535
+}
1536
+
1513 1537
 .hover\:bg-gray-100:hover {
1514 1538
   --tw-bg-opacity: 1;
1515 1539
   background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
@@ -1520,11 +1544,21 @@ video {
1520 1544
   background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
1521 1545
 }
1522 1546
 
1547
+.hover\:bg-green-600:hover {
1548
+  --tw-bg-opacity: 1;
1549
+  background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1));
1550
+}
1551
+
1523 1552
 .hover\:text-blue-800:hover {
1524 1553
   --tw-text-opacity: 1;
1525 1554
   color: rgb(30 64 175 / var(--tw-text-opacity, 1));
1526 1555
 }
1527 1556
 
1557
+.hover\:text-white:hover {
1558
+  --tw-text-opacity: 1;
1559
+  color: rgb(255 255 255 / var(--tw-text-opacity, 1));
1560
+}
1561
+
1528 1562
 .hover\:shadow-md:hover {
1529 1563
   --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
1530 1564
   --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
+