File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
<template>
<div class="main-page">
<h1 class="visually-hidden">AI 통합지원센터 메인페이지</h1>
<section class="slide-zone relative" role="region">
<h2 class="visually-hidden">AI 통합지원센터 메인슬라이드</h2>
<div class="swiper mainSwiper" ref="mainSwiper">
<div class="swiper-wrapper">
<div class="swiper-slide relative slide1">
<div class="main-text white">
<div class="slide-content" @mouseover="pauseAutoplay" @mouseleave="resumeAutoplay">
<h3 class="text-ct mb30">AI 디지털교과서<br /><span>통합지원센터</span></h3>
<p class="text-ct box-title">
AI 디지털교과서 관련 최신 기술 동향 정보를 제공합니다.<br />
양질의 AI 디지털교과서 개발을 위해 기술적·행정적으로 지원합니다.<br />
개발사 AI 디지털교과서와 공공 포털 간 원활한 연계 체계를 지원합니다.<br />
양질의 AI 디지털교과서 개발을 위한 기술 표준과 정책을 연구합니다.
</p>
</div>
</div>
</div>
<div class="swiper-slide relative slide2">
<div class="main-text white">
<div class="slide-content" @mouseover="pauseAutoplay" @mouseleave="resumeAutoplay">
<h3 class="text-ct mb30">AI 디지털교과서<br /><span>개발 가이드라인</span></h3>
<p class="text-ct box-title">
세계에서 최초로 시도되는 국가 단위의 AI 디지털교과서 도입은<br />
학습자 중심의 맞춤형 학습 체제로의 전환을 위한 핵심 과제입니다.<br />
AI 디지털교과서 개발 가이드라인은 양질의 AI 디지털교과서 제작의 이정표 역할과 함께<br />
향후 AI 디지털교과서의 글로벌 표준 역할을 수행하게 될 것입니다.
</p>
</div>
</div>
</div>
<div class="swiper-slide relative slide3">
<div class="main-text white">
<div class="slide-content" @mouseover="pauseAutoplay" @mouseleave="resumeAutoplay">
<h3 class="text-ct mb30">모두의 눈높이에
맞춘<br /><span>AI 디지털교과서</span></h3>
<p class="text-ct box-title">
학생은 맞춤 학습 콘텐츠로 학습 자신감을 키워나가고,<br />
선생님은 데이터 기반으로 수업을 설계하여 학생과 정서적으로 더 깊게 교감하고,<br />
학부모는 자녀의 학습활동 정보를 통해 자녀를 이해하는,<br />
새로운 교육 현장으로 변화합니다.
</p>
</div>
</div>
</div>
<div class="swiper-slide relative slide4">
<div class="main-text white">
<div class="slide-content" @mouseover="pauseAutoplay" @mouseleave="resumeAutoplay">
<h3 class="text-ct mb30">디지털 기반<br /><span>교육혁신 방안</span></h3>
<p class="text-ct box-title">
학생 한 명 한 명을 소중한 인재로 키우기 위해,<br />
학생의 역량 및 학습 속도에 최적화된 학습 기회 제공<br />
디지털 대전환에 따라 AI 등 첨단 기술을 활용한 교수·학습 방법 혁신을 통해,<br />
‘모두를 위한 맞춤 교육’ 구현
</p>
</div>
</div>
</div>
<div class="swiper-slide relative slide5">
<div class="main-text white">
<div class="slide-content" @mouseover="pauseAutoplay" @mouseleave="resumeAutoplay">
<h3 class="text-ct mb30">AI
디지털교과서<br /><span>1:1 맞춤 교육시대</span></h3>
<p class="text-ct box-title">
‘모두를 위한 맞춤 교육’실현을 위한 「AI 디지털교과서 추진방안」 발표<br />
2025년 수학, 영어, 정보, 국어(특수교육) 교과에 우선 도입<br />
2028년까지 국어, 사회, 역사, 과학, 기술·가정 등으로 확대<br />
담당 교원 연수, 맞춤형 교수·학습방법 개발 등 학교 현장 안착을 위한 지원 추진
</p>
</div>
</div>
</div>
</div>
<div class="control flex justify-center align-center">
<div class="swiper-button-prev main-prev cursor"></div>
<div class="swiper-pagination"></div>
<div class="swiper-button-next main-next cursor"></div>
</div>
</div>
<div class="notice-zone radius">
<div class="w1280 content">
<div class="flex content">
<div class="gd- pl20 content no-title flex-column justify-center" style="width:15%">
<h2 class="content-title2 white" ><svg-icon type="mdi" :width="25" :height="25"
:path="noticePath" aria-hidden="true"></svg-icon> 공지사항</h2>
</div>
<div class="gd- pr20 content no-content" style="width:85%">
<div class="swiper noticeSwiper">
<div class="swiper-wrapper" v-if="InfoList.length > 0">
<div class="swiper-slide" v-for="(itm, indx) in InfoList" :key="indx"
@click="clearSearch()">
<router-link :to="'/aidt/BBS_MNG_0000000001/view.page?pageId=' + itm.bbsId"
class="content-sub-title white notice-content">
{{ itm.bbsTtl }}
</router-link>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="tec-zone pt100 pb100" role="region">
<div class="w1280">
<div class="flex">
<div class="gd-2">
<h2 class="main-title" @click="clearSearch()">
<router-link to="/aidt/technicalSupport/technicaldocument/list.page">기술문서</router-link>
</h2>
<p class="detail-text mb10">AI 디지털교과서 개발을 위한<br />최신 기술문서를 제공합니다.</p>
<div class="tech-navigation flex align-center">
<div class="swiper-button-prev tech-prev cursor mr10" aria-label="slide prev"></div>
<div class="swiper-button-next tech-next cursor mr10" aria-label="slide next"></div>
<button @click="toggleAutoplay" aria-label="slideStopButton" title="슬라이드 멈춤" id="slideStopButton"><svg-icon type="mdi"
:path="playPath" role="img" aria-labelledby="slideStopButton"></svg-icon></button>
</div>
</div>
<div class="gd-10">
<div class="swiper techSwiper" ref="techSwiper" v-if="techDocList.length > 0">
<div class="swiper-wrapper">
<div class="swiper-slide cursor" @click="clearSearch()">
<router-link to="/aidt/technicalSupport/guideline/view.page">
<img src="../../../../resources/img/aidtGuidline.png" alt="AI디지털교과서 개발가이드라인"
class="radius" />
</router-link>
</div>
<div class="swiper-slide cursor" v-for="(itm, indx) in techDocList" :key="indx">
<router-link
:to="'/aidt/technicalSupport/technicaldocument/view.page?pageId=' + itm.bbsId">
<img :src="$replaceImagePath(itm.ablstPathNm)" :alt="itm.techDocNm"
class="radius" />
</router-link>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="content-news-zone pt100 pb100 flex-column justify-center" style="min-height: 100vh;"
role="region">
<div class="w1280">
<div class="main-background flex justify-between align-start relative">
<div class="gd-3">
<h2 class="main-title" @clikc="clearSearch()">
<router-link to="/aidt/technicalSupport/technicaldocument/list.page" class=" white">콘텐츠 ·
뉴스룸</router-link>
</h2>
</div>
<div class="gd-8">
<div class="flex">
<div v-for="(itm, index) in ntclist" :key="index" class="gd-6 mb20">
<div class="news-item pd30 cursor" :style="getBackgroundStyle(index)"
@click="clearSearch()">
<router-link :to="'/aidt/BBS_MNG_0000000003/view.page?pageId=' + itm.bbsId">
<div class="content flex-column justify-between">
<div>
<h3 class="middle-title white mb30 ellipsis">{{ itm.bbsTtl }}</h3>
<p class="content-sub-title line3-ellipsis white">{{
removeTag(itm.bbsCn) }}
</p>
</div>
</div>
</router-link>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<div class="quick-menu">
<ul class="flex-column justify-end align-end">
<template v-for="(item, index) in menuItems" :key="index">
<li class="mb10 flex-column justify-center" @mouseenter="onMouseEnter($event, index)"
@mouseleave.stop="onMouseLeave($event)">
<div :class="{ hidden: hover === index }">
<h3 class="content-title2 white text-ct" style="word-break:break-all;">
{{ item.titleShort }}
</h3>
<p class="content-title2 white text-ct"><svg-icon type="mdi" :path="circleArrowPath"
aria-hidden="true"></svg-icon>
</p>
</div>
<div :class="{ hidden: hover !== index }">
<h3 class="content-title2 mb5 white">{{ item.titleFull }}</h3>
<p class="small-text mb15 white">{{ item.detail }}</p>
<button class="large-btn white quick-btn detail-text" :title="item.buttonText" @click="goToPage(item)">
{{ item.buttonText }}
<svg-icon type="mdi" :path="arrowPath" aria-hidden="true"></svg-icon>
</button>
</div>
</li>
</template>
</ul>
</div>
<div class="m-quick-menu">
<ul class="flex-column justify-end align-end">
<li v-for="(item, index) in menuItems" :key="index" class="mb10 flex-column justify-center"
@click="goToPage(item)">
<div :class="{ hidden: hover === index }">
<p class="content-title2 white text-ct" style="word-break:break-all;">
{{ item.titleShort }}
</p>
<!-- <p class="content-title2 white text-ct"><svg-icon type="mdi" :path="circleArrowPath"></svg-icon>
</p> -->
</div>
</li>
</ul>
</div>
</div>
</template>
<script>
import { mdiPlay, mdiPause, mdiBullhornOutline, mdiChevronRight, mdiChevronLeftCircleOutline, mdiRhombusSplit } from '@mdi/js';
import AOS from 'aos';
import 'aos/dist/aos.css';
import COMMON_UTIL from '../../../../resources/js/commonUtil';
import { sysListByPageProc } from "../../../../resources/api/popup";
import { findAll } from '../../../../resources/api/bbsCn.js'
import { PortalMainProc } from '../../../../resources/api/main.js'
import { defaultSearchParams } from '../../../../resources/js/defaultSearchParams';
import queryParams from '../../../../resources/js/queryParams';
import { toRaw } from 'vue';
import Swiper from 'swiper/bundle';
export default {
mixins: [queryParams],
data() {
return {
isPlaying: true,
playPath: mdiPause,
noticePath: mdiBullhornOutline,
arrowPath: mdiChevronRight,
circleArrowPath: mdiChevronLeftCircleOutline,
search: { ...defaultSearchParams },
resetSearch: { ...defaultSearchParams },
menuItems: [
{
titleShort: '교육・컨설팅',
titleFull: '교육・컨설팅',
detail: '개발사 교육·컨설팅 신청 바로가기',
buttonText: '신청하기',
url: '/aidt/tech/edu/list.page'
},
{
titleShort: '문의하기',
titleFull: '문의하기',
detail: 'AI 디지털교과서 개발 관련 문의 바로가기',
buttonText: '1:1 문의하기',
url: '/aidt/inquiry/mngr/list.page'
}
],
popup: null,
popupList: [],
ntclist: [], // 게시판 내용 목록
InfoList: [],
techDocList: [],
hoveredIndex: null,
hover: null,
previousIndex: null,
swiperInstance: null,
noticeSwiperInstance: null,
techSwiperInstance: null,
}
},
created() {
this.setMenuItems();
},
methods: {
// 메인슬라이드 초기화
mainSlide() {
this.swiperInstance = new Swiper('.mainSwiper', {
loop: true,
pagination: {
el: '.swiper-pagination',
type: 'bullets',
clickable: true,
},
navigation: {
nextEl: '.main-next',
prevEl: '.main-prev',
},
scrollbar: {
el: '.swiper-scrollbar',
},
keyboard: true,
effect: 'fade',
autoplay: {
delay: 5000,
},
});
this.swiperInstance.on('slideChange', this.handleSlideChange);
// 초기 슬라이드에 애니메이션
this.handleSlideChange();
},
//메인슬라이드 애니메이션
handleSlideChange() {
this.resetAnimation();
if (this.swiperInstance) {
const activeSlide = this.swiperInstance.slides[this.swiperInstance.activeIndex];
const mainText = activeSlide.querySelector('.slide-content');
if (mainText) {
mainText.classList.add('slide-up');
}
}
},
resetAnimation() {
if (this.swiperInstance) {
const slides = this.swiperInstance.slides;
slides.forEach(slide => {
const mainText = slide.querySelector('.slide-content');
if (mainText) {
mainText.classList.remove('slide-up');
}
});
}
},
// 공지사항 슬라이드 초기화
initNoticeSwiper() {
this.noticeSwiperInstance = new Swiper('.noticeSwiper', {
direction: "vertical",
loop: true,
keyboard: true,
effect: 'fade',
autoplay: {
delay: 5000,
disableOnInteraction: false,
},
});
this.noticeSwiperInstance.on('init', () => {
this.applyNoticeAnimation();
});
this.noticeSwiperInstance.on('slideChange', () => {
this.applyNoticeAnimation();
});
},
// 공지사항 슬라이드 애니메이션
applyNoticeAnimation() {
const swiper = this.noticeSwiperInstance;
swiper.slides.forEach(slide => {
const textElement = slide.querySelector('.notice-content');
if (textElement) {
textElement.style.opacity = '0';
}
});
const activeSlide = swiper.slides[swiper.activeIndex];
const activeTextElement = activeSlide.querySelector('.notice-content');
if (activeTextElement) {
activeTextElement.style.opacity = '1';
}
},
//기술문서 슬라이드 초기화
initTechSwiper() {
this.techSwiperInstance = new Swiper('.techSwiper', {
loop: true,
keyboard: true,
navigation: {
nextEl: '.tech-next',
prevEl: '.tech-prev',
},
spaceBetween: 0,
slidesPerView: 1,
breakpoints: {
500: {
slidesPerView: 2,
spaceBetween: 20,
},
768: {
slidesPerView: 3,
spaceBetween: 20,
},
1280: {
slidesPerView: 4,
spaceBetween: 20,
},
},
autoplay: {
delay: 3000,
disableOnInteraction: false,
},
});
},
// 퀵메뉴 문의하기 레벨에 따른 url
setMenuItems() {
this.menuItems = this.menuItems.map((item) => {
if (item.titleShort === '문의하기') {
const authrtTypeLvl = this.$store.state.authrtTypeLvl;
if (authrtTypeLvl === '1' || authrtTypeLvl === '2' || authrtTypeLvl === '3') {
item.url = '/aidt/inquiry/mngr/list.page';
} else if (authrtTypeLvl === '4') {
item.url = '/aidt/inquiry/ent/list.page';
} else {
item.url = null;
}
}
return item;
});
},
// 메인슬라이드 마우스 오버시 슬라이드 멈춤
onMouseEnter(event, index) {
event.stopPropagation();
this.hover = index;
},
// 메인슬라이드 마우스 떠날 시 슬라이드 시작
onMouseLeave(event) {
event.stopPropagation();
this.hover = null;
},
// 기술문서 슬라이드 control
toggleAutoplay: function () {
if (this.isPlaying) {
this.$refs.techSwiper.swiper.autoplay.stop();
this.playPath = mdiPlay
} else {
this.$refs.techSwiper.swiper.autoplay.start();
this.playPath = mdiPause
}
this.isPlaying = !this.isPlaying
},
pauseAutoplay(event) {
event.stopPropagation();
this.$refs.mainSwiper.swiper.autoplay.stop();
},
resumeAutoplay(event) {
event.stopPropagation();
this.$refs.mainSwiper.swiper.autoplay.start();
},
// 팝업 표시
openPopup() {
if (this.popupList != null && this.popupList.length > 0) {
for (let popup of this.popupList) {
const popupCookies = this.$cookies.get(popup.popupId);
const today = new Date().toDateString();
if (popupCookies !== today) {
window.open(
`/cmmn/popup.page?popupId=${popup.popupId}`,
"_blank",
`width=${popup.wdthLen}, height=${popup.vrtcLen}`
);
}
}
}
},
// 문의하기 페이지
goToPage(item) {
if (item.titleShort === '문의하기' && item.url === null) {
alert('기업 전용 페이지 입니다.');
} else {
this.saveQueryParams("queryParams", this.resetSearch); // 검색조건 초기화
if (item.url == '/aidt/inquiry/ent/list.page') {
this.$store.commit('setCurrentMenu', 'MENU_0000000039');
} else {
this.$store.commit('setCurrentMenu', 'MENU_0000000060');
}
this.$router.push(item.url);
}
},
async mainInit() {
this.search.id = 'BBS_MNG_0000000003'
this.$setLoading(true);
try {
const res = await findAll(toRaw(this.search));
this.ntclist = res.data.data.ntcList;
} catch (error) {
console.log('findAllError : ', error);
// alert('에러가 발생했습니다.\n시스템관리자에게 문의하세요.');
alert(this.$getCmmnMessage('err005'));
} finally {
this.$setLoading(false);
}
},
removeTag(data) {
return COMMON_UTIL.removeTag(data);
},
getBackgroundStyle(index) {
const url = this.$replaceImagePath(this.ntclist[index].ablstPathNm);
const bgImage = `
linear-gradient(
to right bottom,
rgba(0, 0, 0, 0) 0%,
rgba(0, 0, 0, 0.5) 25%,
rgba(0, 0, 0, 0.7) 50%,
rgba(0, 0, 0, 0.7) 100%
),
url(${url})
`;
return {
backgroundImage: bgImage,
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
};
},
clearSearch() {
this.saveQueryParams("queryParams", this.resetSearch); // 검색조건 초기화
},
// 공지사항 으로 이동
moveInfo(item) {
this.$router.push({
path: '/aidt/BBS_MNG_0000000001/view.page',
query: {
pageId: item.bbsId
},
});
},
// 기술문서
moveTechnical(item) {
this.$router.push({
path: '/aidt/BBS_MNG_0000000001/view.page',
query: {
pageId: item.bbsId
},
});
},
//─────axios─────┐
// 목록 조회
async axiosViewList(data) {
try {
this.$setLoading(true);
const response = await PortalMainProc();
this.popupList = response.data.data.popupList;
this.ntclist = response.data.data.newsList;
this.InfoList = response.data.data.announceList;
this.techDocList = response.data.data.techDocList;
this.openPopup();
} catch (error) {
// alert("에러가 발생했습니다.\n시스템관리자에게 문의하세요.");\
alert(this.$getCmmnMessage('err005'));
} finally {
this.$setLoading(false);
}
},
//─────axios─────┘
// Swiper 인스턴스 파괴
destroySwipers() {
if (this.swiperInstance) {
this.swiperInstance.destroy();
this.swiperInstance = null;
}
if (this.noticeSwiperInstance) {
this.noticeSwiperInstance.destroy();
this.noticeSwiperInstance = null;
}
if (this.techSwiperInstance) {
this.techSwiperInstance.destroy();
this.techSwiperInstance = null;
}
},
},
watch: {
InfoList: {
handler(newVal) {
if (newVal.length > 0) {
this.$nextTick(() => {
if (!this.noticeSwiperInstance) {
this.initNoticeSwiper();
} else {
this.applyNoticeAnimation();
}
});
}
},
immediate: true
},
techDocList: {
handler(newVal) {
if (newVal.length > 0) {
// 기존의 swiper 인스턴스가 있으면 파괴하고 다시 초기화
if (this.techSwiperInstance) {
this.techSwiperInstance.destroy();
}
this.$nextTick(() => {
this.initTechSwiper();
});
}
},
immediate: true,
},
},
components: {
'Swiper': Swiper
},
mounted() {
this.axiosViewList();
this.mainSlide();
},
unmounted() {
this.destroySwipers();
},
}
</script>