layout02User.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. <template>
  2. <div>
  3. <!-- <div :class="widgetSize === 'M' ? 'user--list--bar--graph' : 'user--list--bar--graph small'"> -->
  4. <div :class="widgetSize === 'M' ? 'user--list--wrap user--list--bar--graph' : 'user--list--bar--graph small'">
  5. <!-- 헤더 영역 : S -->
  6. <div class="inner--header--wrap">
  7. <h2 class="inner--component--title none--after">
  8. 가입자
  9. </h2>
  10. <pagination
  11. :page-obj="pageObj"
  12. @chg_page="fnChgPage"
  13. >
  14. <template
  15. v-if="userItems && userItems.length > 0"
  16. #rightArea
  17. >
  18. <div class="btn--list--content">
  19. <v-btn
  20. class="custom-btn mini all--view--btn"
  21. @click="fnUserTotalClick"
  22. >
  23. <i class="icon" />전체보기
  24. </v-btn>
  25. </div>
  26. <div class="shape--selector">
  27. <v-btn
  28. class="custom-btn mini card--type--btn"
  29. :class="{ on: showType === 'CARD' }"
  30. @click="fnChangeShowType('CARD')"
  31. />
  32. <v-btn
  33. class="custom-btn mini list--type--btn"
  34. :class="{ on: showType === 'TABLE' }"
  35. @click="fnChangeShowType('TABLE')"
  36. />
  37. </div>
  38. </template>
  39. </pagination>
  40. </div>
  41. <!-- <div v-if="widgetSize === 'S'" /> -->
  42. <!-- 헤더 영역 : E -->
  43. <!-- Contents 영역 : S -->
  44. <div class="user--list--contents">
  45. <WidgetM
  46. v-if="showType === 'CARD' && widgetSize === 'M'"
  47. :items="userItems"
  48. />
  49. <WidgetS
  50. v-if="showType === 'CARD' && widgetSize === 'S'"
  51. :items="userItems"
  52. />
  53. <WidgetT
  54. v-if="showType === 'TABLE'"
  55. :items="userItems"
  56. :page-obj="pageObj"
  57. />
  58. </div>
  59. <!-- Contents 영역 : E -->
  60. </div>
  61. </div>
  62. </template>
  63. <script setup>
  64. /***********************
  65. * import
  66. ************************/
  67. import { useI18n } from "vue-i18n"
  68. import apiUrl from '@/composables/useApi';
  69. import useAxios from '@/composables/useAxios';
  70. import useUtil from '@/composables/useUtil';
  71. import pagination from "@/components/home/dashboard/common/pagination.vue"
  72. import WidgetM from "@/components/home/dashboard/layout02/user/layout02UserWidgetM.vue"
  73. import WidgetS from "@/components/home/dashboard/layout02/user/layout02UserWidgetS.vue"
  74. import WidgetT from "@/components/home/dashboard/layout02/user/layout02UserWidgetT.vue"
  75. import testJson from "../../test.json"
  76. /***********************
  77. * plugins inject
  78. ************************/
  79. const { $toast, $log, $dayjs, $eventBus } = useNuxtApp()
  80. // props
  81. const props = defineProps({
  82. config: {
  83. type: Object,
  84. default: () => {}
  85. },
  86. intervalTime: {
  87. type: Number,
  88. default: 5000
  89. }
  90. })
  91. // 참조가능 데이터 설정
  92. defineExpose({})
  93. // 발신 이벤트 선언
  94. const emit = defineEmits([""]);
  95. const i18n = useI18n();
  96. /***********************
  97. * data & created
  98. ************************/
  99. // 카드 / 리스트 구분
  100. const showType = ref('CARD'); // CARD or TABLE
  101. // TenantName
  102. const tenantName = computed(() => useAuthStore().getTenantName);
  103. // 설정된 위젯 사이즈 : M or S
  104. const widgetSize = computed(() => props.config?.widgetSize || 'M');
  105. // 위젯 사이즈별 표시 갯수
  106. const widgetListLimit = ref({
  107. S: 20, M: 8, T: 10,
  108. });
  109. // 페이징 정보
  110. const pageObj = ref( {
  111. page: 1, // 현재 페이지
  112. pageSize: widgetListLimit.value[widgetSize.value], // 테이블 조회 데이터 개수
  113. totalCnt: 0, // 전체 페이지
  114. })
  115. // 가입자 리스트
  116. const userItems = ref([]);
  117. /***********************
  118. * Methods
  119. ************************/
  120. const fnReset = () => {
  121. userItems.value = [];
  122. showType.value = 'CARD';
  123. pageObj.value.page = 1;
  124. pageObj.value.pageSize = widgetListLimit.value[widgetSize.value];
  125. pageObj.value.totalCnt = 0;
  126. }
  127. function fnGetUserList() {
  128. const params = {
  129. tenantName: tenantName.value,
  130. }
  131. useAxios().post(apiUrl.getUserList, params).then((res) => {
  132. const {resCode, resMsg, data} = res.data;
  133. if(resCode == 200) {
  134. // 테스트를 위한 테스트 코드 (삭제 필수)
  135. // fnParseData([...(data?.items || []), ...testJson.user.data.items])
  136. fnParseData(data.items || [])
  137. $log.debug("[dashboard][fnGetUserList][success]")
  138. } else {
  139. $log.debug("[dashboard][fnGetUserList][error]", `[${resCode}] ${resMsg}`);
  140. }
  141. }).catch((error)=>{
  142. // 테스트를 위한 테스트 코드 (삭제 필수)
  143. // fnParseData([...testJson.user.data.items])
  144. $log.debug("[dashboard][fnGetUserList][error]", error)
  145. useErrorHandler().fnSetCommErrorHandle(error, fnGetUserList)
  146. // 테스트 데이터 파싱
  147. }).finally(()=>{
  148. $log.debug("[dashboard][fnGetUserList][finished]")
  149. })
  150. }
  151. /**
  152. * 데이터 가공
  153. */
  154. function fnParseData(items = []) {
  155. // {tenantName: '',maxSubscriber: ,curSubscriber: ,expirationDate: '', maxAccount: ,currentAccountCount: ,maxSession: 100,currentConnectingCount: ,},
  156. userItems.value = [];
  157. if(!items || items.length < 1) {
  158. pageObj.value.totalCnt = 0;
  159. return;
  160. }
  161. let temp = [];
  162. // 정렬 적용
  163. temp = items.sort((a, b) => {
  164. const perA = fnGetPercentValue(a.maxSubscriber, a.curSubscriber);
  165. const perB = fnGetPercentValue(b.maxSubscriber, b.curSubscriber);
  166. return +perA < +perB ? 1 : (+perA > +perB ? -1 : 0);
  167. })
  168. // 페이징 적용
  169. pageObj.value.totalCnt = temp.length;
  170. temp = temp.filter((data, index) =>(index >= ((pageObj.value.page - 1) * pageObj.value.pageSize) && index < (pageObj.value.page * pageObj.value.pageSize)));
  171. // 데이터 가공
  172. userItems.value = temp.map((item, index) => {
  173. //percent
  174. const { maxSubscriber, curSubscriber } = item;
  175. const perSubscriber = fnGetPercentValue(maxSubscriber, curSubscriber);
  176. //심각도
  177. const level = fnGetLevel(perSubscriber);
  178. //차트 데이터
  179. const chartData = {
  180. datasets: [
  181. {
  182. data: [curSubscriber , maxSubscriber - curSubscriber],
  183. backgroundColor: fnGetChartColorSet(level),
  184. borderWidth: 0,
  185. }
  186. ]
  187. }
  188. //테이블 사용량 class
  189. const tablePercentClass = fnGetTablePercentClass(level);
  190. return {
  191. ...item,
  192. no: index+1,
  193. level,
  194. perSubscriber,
  195. chartData,
  196. tablePercentClass
  197. }
  198. })
  199. console.log("::: layout02User > parsed Data :: ", userItems.value )
  200. }
  201. /** make percent data */
  202. const fnGetPercentValue = (max, curr) => {
  203. return useUtil.toRoundFix((curr / max) * 100, 0);
  204. }
  205. const fnGetLevel = (per) => {
  206. if(per >= 95) return 'critical'; //critical
  207. else if(per >= 90) return 'major'; //major
  208. else if(per >= 85) return 'minor'; //minor
  209. else return 'normal'; //normal
  210. }
  211. /** 차트 데이터 > 컬러셋 */
  212. const fnGetChartColorSet = (level) => {
  213. if(level == 'critical') return ['#f00','#EAEAEA']; //critical
  214. else if(level == 'major') return ['#C96103','#EAEAEA']; //major
  215. else if(level == 'minor') return ['#DDA405','#EAEAEA']; //minor
  216. else return ['#2D8CFA','#EAEAEA']; //normal
  217. }
  218. /** 테이블 > 사용량 class */
  219. const fnGetTablePercentClass = (level) => {
  220. if(level == 'critical') return 'user--list--critical'; //critical
  221. else if(level == 'major') return 'user--list--major'; //major
  222. else if(level == 'minor') return 'user--list--minor'; //minor
  223. else return 'user--list--normal';
  224. }
  225. /** 카드형/목록형 Change Event */
  226. function fnChangeShowType(type) {
  227. pageObj.value.page = 1;
  228. pageObj.value.totalCnt = 0;
  229. if(type === 'TABLE') pageObj.value.pageSize = widgetListLimit.value.T;
  230. else pageObj.value.pageSize = widgetListLimit.value[widgetSize.value];
  231. fnGetUserList();
  232. showType.value = type;
  233. }
  234. /** 전체보기 open */
  235. function fnUserTotalClick() {
  236. const url = window.location.origin+'/view/home/user'
  237. const popupWindow = window.open(url, '_blank', 'width=' + screen.width + ',height=' + screen.height + ',fullscreen=yes')
  238. if (popupWindow) {
  239. popupWindow.focus()
  240. }
  241. }
  242. /**
  243. * 페이지 변경
  244. */
  245. function fnChgPage(page){
  246. pageObj.value.page = page
  247. fnGetUserList();
  248. }
  249. onMounted(() => fnGetUserList())
  250. // 위젯사이즈 변경 watch
  251. watch(() => widgetSize.value, () => {
  252. fnReset();
  253. fnGetUserList();
  254. }, {deep: true})
  255. </script>