
--- client/resources/css/admin.css
+++ client/resources/css/admin.css
... | ... | @@ -559,13 +559,11 @@ |
559 | 559 |
} |
560 | 560 |
|
561 | 561 |
/* 통계 */ |
562 |
-.chart-wrap { |
|
563 |
- padding: 30px; |
|
564 |
-} |
|
565 | 562 |
|
566 | 563 |
#chartdiv { |
567 | 564 |
width: 100%; |
568 | 565 |
height: 300px; |
566 |
+ /* background-color: #fff; */ |
|
569 | 567 |
} |
570 | 568 |
|
571 | 569 |
.table-zone table thead th { |
--- client/views/component/chart/LineChart.vue
+++ client/views/component/chart/LineChart.vue
... | ... | @@ -16,18 +16,7 @@ |
16 | 16 |
type: Array, |
17 | 17 |
required: true, |
18 | 18 |
}, |
19 |
- // categoryGroup: { |
|
20 |
- // type: String, |
|
21 |
- // required: true, |
|
22 |
- // }, |
|
23 |
- // colors: { |
|
24 |
- // type: Array, |
|
25 |
- // required: true, |
|
26 |
- // }, |
|
27 |
- // unit: { |
|
28 |
- // type: String, |
|
29 |
- // required: true, |
|
30 |
- // }, |
|
19 |
+ |
|
31 | 20 |
}, |
32 | 21 |
data() { |
33 | 22 |
return { |
... | ... | @@ -42,63 +31,66 @@ |
42 | 31 |
let root = am5.Root.new(this.$refs.chartdiv); |
43 | 32 |
root._logo.dispose(); |
44 | 33 |
|
45 |
- |
|
34 |
+ |
|
46 | 35 |
// Set themes |
47 | 36 |
// https://www.amcharts.com/docs/v5/concepts/themes/ |
48 |
- root.setThemes([ |
|
49 |
- am5themes_Animated.new(root) |
|
50 |
- ]); |
|
51 |
- |
|
37 |
+ root.setThemes([am5themes_Animated.new(root)]); |
|
52 | 38 |
|
53 | 39 |
// Create chart |
54 | 40 |
// https://www.amcharts.com/docs/v5/charts/xy-chart/ |
55 |
- let chart = root.container.children.push(am5xy.XYChart.new(root, { |
|
56 |
- panX: true, |
|
57 |
- panY: true, |
|
58 |
- wheelX: "panX", |
|
59 |
- wheelY: "zoomX", |
|
60 |
- pinchZoomX: true |
|
61 |
- })); |
|
62 |
- |
|
63 |
- chart.get("colors").set("step", 3); |
|
64 |
- |
|
65 |
- |
|
66 |
- // Add cursor |
|
67 |
- // https://www.amcharts.com/docs/v5/charts/xy-chart/cursor/ |
|
68 |
- let cursor = chart.set("cursor", am5xy.XYCursor.new(root, {})); |
|
69 |
- cursor.lineY.set("visible", false); |
|
70 |
- |
|
41 |
+ let chart = root.container.children.push( |
|
42 |
+ am5xy.XYChart.new(root, { |
|
43 |
+ panX: false, |
|
44 |
+ panY: false, |
|
45 |
+ wheelX: "panX", |
|
46 |
+ wheelY: "zoomX", |
|
47 |
+ layout: root.verticalLayout |
|
48 |
+ }) |
|
49 |
+ ); |
|
71 | 50 |
|
72 | 51 |
// Create axes |
73 | 52 |
// https://www.amcharts.com/docs/v5/charts/xy-chart/axes/ |
74 |
- let xAxis = chart.xAxes.push(am5xy.DateAxis.new(root, { |
|
75 |
- maxDeviation: 0.3, |
|
76 |
- baseInterval: { |
|
77 |
- timeUnit: "day", |
|
78 |
- count: 1 |
|
79 |
- }, |
|
80 |
- renderer: am5xy.AxisRendererX.new(root, {}), |
|
81 |
- tooltip: am5.Tooltip.new(root, {}) |
|
82 |
- })); |
|
53 |
+ let xRenderer = am5xy.AxisRendererX.new(root, {}); |
|
54 |
+ let xAxis = chart.xAxes.push( |
|
55 |
+ am5xy.CategoryAxis.new(root, { |
|
56 |
+ categoryField: "date", |
|
57 |
+ renderer: xRenderer, |
|
58 |
+ tooltip: am5.Tooltip.new(root, {}) |
|
59 |
+ }) |
|
60 |
+ ); |
|
61 |
+ xRenderer.grid.template.setAll({ |
|
62 |
+ location: 1 |
|
63 |
+ }) |
|
83 | 64 |
|
84 |
- let yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, { |
|
85 |
- maxDeviation: 0.3, |
|
86 |
- renderer: am5xy.AxisRendererY.new(root, {}) |
|
87 |
- })); |
|
65 |
+ xAxis.data.setAll(data); |
|
66 |
+ |
|
67 |
+ let yAxis = chart.yAxes.push( |
|
68 |
+ am5xy.ValueAxis.new(root, { |
|
69 |
+ min: 0, |
|
70 |
+ extraMax: 0.1, |
|
71 |
+ renderer: am5xy.AxisRendererY.new(root, { |
|
72 |
+ strokeOpacity: 0.1 |
|
73 |
+ }) |
|
74 |
+ }) |
|
75 |
+ ); |
|
76 |
+ |
|
88 | 77 |
|
89 | 78 |
|
90 | 79 |
// Add series |
91 | 80 |
Object.keys(data[0]).forEach((key, index) => { |
92 | 81 |
if (key !== "date") { |
93 | 82 |
let series = chart.series.push(am5xy.LineSeries.new(root, { |
94 |
- name: "Series " + (index + 1), |
|
83 |
+ |
|
84 |
+ name: key, |
|
95 | 85 |
xAxis: xAxis, |
96 | 86 |
yAxis: yAxis, |
97 | 87 |
valueYField: key, |
98 |
- valueXField: "date", |
|
88 |
+ categoryXField: "date", |
|
99 | 89 |
tooltip: am5.Tooltip.new(root, { |
100 |
- labelText: "{valueX}: {valueY}" |
|
90 |
+ pointerOrientation: "horizontal", |
|
91 |
+ labelText: "{categoryX}: {valueY}" |
|
101 | 92 |
}) |
93 |
+ |
|
102 | 94 |
})); |
103 | 95 |
|
104 | 96 |
series.strokes.template.setAll({ |
... | ... | @@ -111,16 +103,19 @@ |
111 | 103 |
date: item.date, |
112 | 104 |
[key]: item[key] |
113 | 105 |
}))); |
106 |
+ |
|
107 |
+ series.bullets.push(function () { |
|
108 |
+ return am5.Bullet.new(root, { |
|
109 |
+ sprite: am5.Circle.new(root, { |
|
110 |
+ strokeWidth: 3, |
|
111 |
+ stroke: series.get("stroke"), |
|
112 |
+ radius: 5, |
|
113 |
+ fill: root.interfaceColors.get("background") |
|
114 |
+ }) |
|
115 |
+ }); |
|
116 |
+ }); |
|
114 | 117 |
} |
115 | 118 |
}); |
116 |
- |
|
117 |
- // Set date fields |
|
118 |
- // https://www.amcharts.com/docs/v5/concepts/data/#Parsing_dates |
|
119 |
- root.dateFormatter.setAll({ |
|
120 |
- dateFormat: "yyyy-MM-dd", |
|
121 |
- dateFields: ["valueX"] |
|
122 |
- }); |
|
123 |
- |
|
124 | 119 |
|
125 | 120 |
|
126 | 121 |
// Make stuff animate on load |
--- client/views/component/chart/SingleBarChart.vue
+++ client/views/component/chart/SingleBarChart.vue
... | ... | @@ -1,5 +1,7 @@ |
1 | 1 |
<template> |
2 |
- <div class="chart-container" ref="chartdiv"></div> |
|
2 |
+ <div class="chart-wrap"> |
|
3 |
+ <div id="chartdiv" ref="chartdiv"></div> |
|
4 |
+ </div> |
|
3 | 5 |
</template> |
4 | 6 |
|
5 | 7 |
<script> |
... | ... | @@ -9,17 +11,20 @@ |
9 | 11 |
|
10 | 12 |
export default { |
11 | 13 |
props: { |
12 |
- data: { |
|
14 |
+ chartData: { |
|
13 | 15 |
type: Array, |
14 |
- required: true, |
|
16 |
+ default: [], |
|
17 |
+ // required: true, |
|
15 | 18 |
}, |
16 | 19 |
xField: { |
17 | 20 |
type: String, |
18 |
- required: true, |
|
21 |
+ default: null |
|
22 |
+ // required: true, |
|
19 | 23 |
}, |
20 | 24 |
yField: { |
21 | 25 |
type: String, |
22 |
- required: true, |
|
26 |
+ default: null |
|
27 |
+ // required: true, |
|
23 | 28 |
}, |
24 | 29 |
}, |
25 | 30 |
data() { |
... | ... | @@ -29,7 +34,16 @@ |
29 | 34 |
}, |
30 | 35 |
methods: { |
31 | 36 |
createChart(data, xField, yField) { |
32 |
- let root = am5.Root.new(this.$refs.chartdiv); |
|
37 |
+ let chartWarp = this.$refs["chartdiv"]; // 차트 상위 div ref 매칭 |
|
38 |
+ chartWarp.innerHTML = ""; // 차트 상위 div 내용 초기화 (기존 차트 삭제) |
|
39 |
+ let div = document.createElement("div"); // 차트를 담을 빈 div 생성 (차트 하위 div) |
|
40 |
+ div.style.width = "100%"; // 차트를 담을 div의 넓이 |
|
41 |
+ div.style.height = "100%"; // 차트를 담을 div의 높이 |
|
42 |
+ chartWarp.appendChild(div); // 차트 상위 div 안에 차트 하위 div를 추가 |
|
43 |
+ let root = am5.Root.new(div); // 차트 하위 div에 차트(root) 담기 |
|
44 |
+ this.charts = root; // 차트 정보 전역에 담기 |
|
45 |
+ |
|
46 |
+ // let root = am5.Root.new(this.$refs.chartdiv); |
|
33 | 47 |
root._logo.dispose(); |
34 | 48 |
// Set themes |
35 | 49 |
// https://www.amcharts.com/docs/v5/concepts/themes/ |
... | ... | @@ -101,24 +115,22 @@ |
101 | 115 |
// Make stuff animate on load |
102 | 116 |
series.appear(1000); |
103 | 117 |
chart.appear(1000, 100); |
104 |
- |
|
105 |
- return chart; |
|
106 |
- } |
|
118 |
+ this.chart = chart; |
|
119 |
+ }, |
|
120 |
+ |
|
107 | 121 |
|
108 | 122 |
}, |
109 | 123 |
watch: { |
110 |
- |
|
124 |
+ 'chartData': function (newData, oldData) { |
|
125 |
+ console.log("new:", newData, oldData); |
|
126 |
+ this.createChart(newData, this.xField, this.yField); |
|
127 |
+ }, |
|
111 | 128 |
}, |
112 | 129 |
mounted() { |
113 |
- this.chart = this.createChart(this.data, this.xField, this.yField); |
|
130 |
+ console.log("chart") |
|
131 |
+ //this.createChart(this.data, this.xField, this.yField); |
|
114 | 132 |
}, |
115 | 133 |
}; |
116 | 134 |
</script> |
117 | 135 |
|
118 |
-<style scoped> |
|
119 |
-.chart-container { |
|
120 |
- width: 100%; |
|
121 |
- height: 300px; |
|
122 |
-} |
|
123 |
-</style> |
|
124 | 136 |
(No newline at end of file) |
--- client/views/pages/admin/main/Amain.vue
+++ client/views/pages/admin/main/Amain.vue
... | ... | @@ -77,7 +77,7 @@ |
77 | 77 |
<div class="content"> |
78 | 78 |
<div class="main-content-title">페이지별 접속 통계</div> |
79 | 79 |
<div class="content-zone"> |
80 |
- <SingleBarChart :data="totalMenuData" xField="menu" yField="value" /> |
|
80 |
+ <SingleBarChart :chartData="accumulatePageAccess" xField="page_nm" yField="count"/> |
|
81 | 81 |
</div> |
82 | 82 |
</div> |
83 | 83 |
<div class="content"> |
... | ... | @@ -149,16 +149,6 @@ |
149 | 149 |
user_id: null, |
150 | 150 |
}, |
151 | 151 |
store: useStore(), |
152 |
- totalMenuData: [ |
|
153 |
- { menu: "통합지원센터란", value: 15 }, |
|
154 |
- { menu: "기술문서", value: 2 }, |
|
155 |
- { menu: "자료집", value: 4 }, |
|
156 |
- { menu: "기업홍보관", value: 7 }, |
|
157 |
- { menu: "공지사항", value: 9 }, |
|
158 |
- { menu: "홍보뉴스", value: 20 }, |
|
159 |
- { menu: "전문가협의체", value: 7 }, |
|
160 |
- ], |
|
161 |
- |
|
162 | 152 |
Page: [ |
163 | 153 |
{ menu: "통합지원센터란", value: null, divClass: "blue" , nameClass: "blue-sub-title main-sub-title", cntClass:"number blue-sub-title"}, |
164 | 154 |
{ menu: "기술문서", value: null, divClass: "blue" , nameClass: "blue-sub-title main-sub-title", cntClass:"number blue-sub-title"}, |
... | ... | @@ -190,6 +180,7 @@ |
190 | 180 |
'Content-Type': "application/json; charset=UTF-8", |
191 | 181 |
}, |
192 | 182 |
}).then(function (response) { |
183 |
+ |
|
193 | 184 |
vm.todayVisit = response.data.todayVisit; |
194 | 185 |
vm.accumulateMember = response.data.accumulateMember; |
195 | 186 |
vm.accumulateMatching = response.data.accumulateMatching; |
... | ... | @@ -205,14 +196,13 @@ |
205 | 196 |
} |
206 | 197 |
}; |
207 | 198 |
|
208 |
- for(let i = 0; i < vm.totalMenuData.length; i++) { |
|
209 |
- for(let j = 0; j < vm.accumulatePageAccess.length; j++) { |
|
210 |
- if(vm.totalMenuData[i].menu === vm.accumulatePageAccess[j].page_nm) { |
|
211 |
- vm.totalMenuData[i].value = vm.accumulatePageAccess[j].count; |
|
212 |
- } |
|
213 |
- } |
|
214 |
- }; |
|
215 |
- console.log(vm.totalMenuData) |
|
199 |
+ // for(let i = 0; i < vm.totalMenuData.length; i++) { |
|
200 |
+ // for(let j = 0; j < vm.accumulatePageAccess.length; j++) { |
|
201 |
+ // if(vm.totalMenuData[i].menu === vm.accumulatePageAccess[j].page_nm) { |
|
202 |
+ // vm.totalMenuData[i].value = vm.accumulatePageAccess[j].count; |
|
203 |
+ // } |
|
204 |
+ // } |
|
205 |
+ // }; |
|
216 | 206 |
}).catch(function (error) { |
217 | 207 |
console.log("error - ", error) |
218 | 208 |
alert("대시보드 조회 오류, 관리자에게 문의하세요."); |
... | ... | @@ -241,13 +231,16 @@ |
241 | 231 |
} |
242 | 232 |
|
243 | 233 |
}, |
244 |
- watch: {}, |
|
234 |
+ watch: { |
|
235 |
+ 'accumulatePageAccess':function(newData){ |
|
236 |
+ console.log("accumulatePageAccess",newData); |
|
237 |
+ } |
|
238 |
+ }, |
|
245 | 239 |
computed: {}, |
246 | 240 |
components: { |
247 | 241 |
'SingleBarChart': SingleBarChart |
248 | 242 |
}, |
249 | 243 |
mounted() { |
250 |
- console.log('amain') |
|
251 | 244 |
this.dashboard(); |
252 | 245 |
this.top5(); |
253 | 246 |
} |
--- client/views/pages/admin/statistics/Visit.vue
+++ client/views/pages/admin/statistics/Visit.vue
... | ... | @@ -65,43 +65,43 @@ |
65 | 65 |
data() { |
66 | 66 |
return { |
67 | 67 |
visitData: [{ |
68 |
- date: new Date(2019, 5, 12).getTime(), |
|
68 |
+ date: "2023-11-01", |
|
69 | 69 |
total_value: 100, |
70 | 70 |
value1: 50, |
71 | 71 |
value2: 48, |
72 | 72 |
value3: 58, |
73 | 73 |
}, { |
74 |
- date: new Date(2019, 5, 13).getTime(), |
|
74 |
+ date: "2023-11-02", |
|
75 | 75 |
total_value: 100, |
76 | 76 |
value1: 53, |
77 | 77 |
value2: 51, |
78 | 78 |
value3: 51, |
79 | 79 |
}, { |
80 |
- date: new Date(2019, 5, 14).getTime(), |
|
80 |
+ date: "2023-11-03", |
|
81 | 81 |
total_value: 100, |
82 | 82 |
value1: 56, |
83 | 83 |
value2: 58, |
84 | 84 |
value3: 58, |
85 | 85 |
}, { |
86 |
- date: new Date(2019, 5, 15).getTime(), |
|
86 |
+ date: "2023-11-04", |
|
87 | 87 |
total_value: 100, |
88 | 88 |
value1: 52, |
89 | 89 |
value2: 53, |
90 | 90 |
value3: 32, |
91 | 91 |
}, { |
92 |
- date: new Date(2019, 5, 16).getTime(), |
|
92 |
+ date: "2023-11-05", |
|
93 | 93 |
total_value: 100, |
94 | 94 |
value1: 48, |
95 | 95 |
value2: 44, |
96 | 96 |
value3: 44, |
97 | 97 |
}, { |
98 |
- date: new Date(2019, 5, 17).getTime(), |
|
98 |
+ date: "2023-11-06", |
|
99 | 99 |
total_value: 100, |
100 | 100 |
value1: 47, |
101 | 101 |
value2: 42, |
102 | 102 |
value3: 74, |
103 | 103 |
}, { |
104 |
- date: new Date(2019, 5, 18).getTime(), |
|
104 |
+ date: "2023-11-07", |
|
105 | 105 |
total_value: 100, |
106 | 106 |
value1: 59, |
107 | 107 |
value2: 55, |
--- client/views/pages/user/mypage/MatchingManager.vue
+++ client/views/pages/user/mypage/MatchingManager.vue
... | ... | @@ -74,7 +74,7 @@ |
74 | 74 |
<button class="red-btn small-btn" @click="pickCancelModal(item)">취소</button> |
75 | 75 |
</div> |
76 | 76 |
<div v-else> |
77 |
- <button class="inbox-btn-gray small-btn">거절됨</button> |
|
77 |
+ <button class="dark-gray-btn small-btn">거절됨</button> |
|
78 | 78 |
</div> |
79 | 79 |
</div> |
80 | 80 |
</div> |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?