
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
04-04
File name
Commit message
Commit date
File name
Commit message
Commit date
<template>
<div class="search-wrap">
<div class="chart-info">
<p class="detail-text">
방문자 총
<span class="detail-bold blue">{{ totalCnt }}</span>
명
</p>
</div>
<div class="search-bar">
<div class="form-control sm cal">
<VueDatePicker
InlineOptions
placeholder="종료일"
locale="ko"
:enable-time-picker="false"
:format="formatDate"
v-model="searchDate.startDt"
@update:model-value="validateDate($event, 'startDt')"
/>
</div>
<!-- <input
type="date"
class="form-control sm"
v-model="searchDate.startDt"
@change="validateDate($event, 'startDt')"
/> -->
<div class="mark">~</div>
<div class="form-control sm cal">
<VueDatePicker
InlineOptions
placeholder="종료일"
locale="ko"
:enable-time-picker="false"
:format="formatDate"
v-model="searchDate.endDt"
@update:model-value="validateDate($event, 'endDt')"
/>
</div>
<!-- <input
type="date"
class="form-control sm"
v-model="searchDate.endDt"
@change="validateDate($event, 'endDt')"
/> -->
<button class="btn sm main" @click="axiosSelectList">
조회
</button>
<button class="btn sm tertiary ico-before ico-download" v-if="pageAuth.fileDwnldAuthrt == 'Y'" @click="fnDownload">
엑셀 다운로드
</button>
</div>
</div>
<div class="content-zone sch-full">
<div class="content">
<div class="scroll">
<div class="chart-zone mb30" ref="two">
<div class="chart-wrap" ref="chartdiv">
<ClusteredColumnChart :chartData="chartData" columnX="date" />
</div>
</div>
<div class="tbl-wrap overflow-y" ref="first">
<table class="tbl data mixing">
<colgroup>
<template v-for="(key, index) of chartData[0]" :key="index">
<col
v-if="index > 1"
:width="100 / chartData[0].length - 2 + '%'"
/>
</template>
</colgroup>
<thead class="sticky">
<tr>
<th rowspan="2" class="sticky top-0" >구분</th>
<th colspan="3" class="sticky top-0">사용자 구분</th>
</tr>
<tr>
<th class="sticky top-40">관리자</th>
<th class="sticky top-40">사용자</th>
<th class="sticky top-40">비로그인 사용자</th>
</tr>
</thead>
<tbody>
<tr v-for="(tr, index) of chartData" :key="index">
<td>{{ tr.date }}</td>
<td>{{ tr["관리자"] }}</td>
<td>{{ tr["사용자"] }}</td>
<td>{{ tr["비로그인 사용자"] }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</template>
<script>
import defaultAxios from "../../../../resources/js/defaultAxios";
import html2canvas from "html2canvas";
import ClusteredColumnChart from "../../../component/chart/ClusteredColumnChart.vue";
import statisticsDate from "../../../../resources/js/defaultDateParams";
// API
import { selectUserCntnStatsProc } from "../../../../resources/api/cntnStats";
export default {
mixins: [statisticsDate],
components: {
ClusteredColumnChart: ClusteredColumnChart,
},
data() {
return {
// 페이지 권한 객체
pageAuth: JSON.parse(localStorage.getItem("vuex")).pageAuth,
// 차트 데이터
chartData: [],
// 전체 수
totalCnt: 0,
};
},
created() {
this.axiosSelectList();
},
methods: {
// 사용자 접속 통계
async axiosSelectList() {
// 유효성 검사
if (this.searchDate.startDt == null || this.searchDate.startDt == "") {
alert("시작일을 선택하세요.");
this.searchDate.startDt = null;
return;
}
if (this.searchDate.endDt == null || this.searchDate.endDt == "") {
alert("종료일을 선택하세요.");
this.searchDate.endDt = null;
return;
}
// 데이터 세팅
let data = this.searchDate;
data["startDt"] = this.dateFormat(new Date(data["startDt"]));
data["endDt"] = this.dateFormat(new Date(data["endDt"]));
// 실행
try {
const response = await selectUserCntnStatsProc(data);
let datas = [];
for (let data of response.data.data.list) {
let newData = {};
newData["date"] = data["dates"];
for (let i = 0; i < data["authrt_nm"].length; i++) {
newData[data["authrt_nm"][i]] = data["cntn_nope"][i];
}
datas.push(newData);
}
this.chartData = datas;
this.totalCnt = response.data.data.totalCnt;
} catch (error) {
alert("에러가 발생했습니다.\n관리자에게 문의해주세요.");
}
},
// 다운로드
fnDownload() {
const vm = this;
const chartdiv = vm.$refs.chartdiv;
html2canvas(chartdiv).then(function (canvas) {
// 데이터 세팅
let cntnStats = [];
for (let item of vm.chartData) {
cntnStats.push({
date: item.date,
admin: item["관리자"],
user: item["사용자"],
none: item["비로그인 사용자"],
});
}
// 폼데이터
var formData = new FormData();
const cntnStatsToBlob = new Blob([JSON.stringify(cntnStats)], {
type: "application/json; charset=UTF-8",
});
formData.append("cntnStats", cntnStatsToBlob);
let imageData = canvas.toDataURL("image/png");
imageData.replace("data:image/png; base64, ", "");
const chartToBlob = new Blob([imageData], {
type: "application/json; charset=UTF-8",
});
formData.append("chart", chartToBlob);
// 실행
defaultAxios({
url: vm.$filters.ctxPath("/sys/cntnStats/excelDownload.file"),
method: "post",
headers: {
"Content-Type": "multipart/form-data; charset=UTF-8",
Authorization: vm.$store.state.authorization,
},
data: formData,
responseType: "blob",
})
.then((response) => {
const url = window.URL.createObjectURL(
new Blob([response.data], {
type: response.headers["content-type"],
})
);
let today = new Date().toISOString().substring(2, 10);
today = today.replace(/[^0-9]/g, "");
const link = document.createElement("a");
link.href = url;
link.setAttribute(
"download",
`[${today}]사용자접속통계_${vm.searchDate.startDt}_${vm.searchDate.endDt}.xlsx`
);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
})
.catch((error) => {
alert("에러가 발생했습니다.\n관리자에게 문의해주세요.");
});
});
},
// 날짜포맷
formatDate(date) {
const year = date.getFullYear();
const month = ('00' + (date.getMonth() + 1)).slice(-2);
const day = ('00' + date.getDate()).slice(-2);
return `${year}-${month}-${day}`;
},
updateHeight() {
this.$nextTick(() => {
const first = this.$refs.first;
const two = this.$refs.two;
let total = 0;
if (two) total += two.offsetHeight;
if (first) {
first.style.height = `calc(100% - ${total}px - 30px)`;
}
});
},
},
mounted() {
this.updateHeight();
// 창 크기 변경 시에도 대응하고 싶다면:
window.addEventListener('resize', this.updateHeight);
},
beforeUnmount() {
window.removeEventListener('resize', this.updateHeight);
},
};
</script>