그누보드 게시판에 LMS 영상 게시판 만들기


1771385260_KHEVk6DNOk.webp

lms_update.skin.php
[code]
<?php
// 이 파일은 게시판 스킨 폴더 안에 위치합니다.
include_once('../../../../../common.php'); // 경로 주의: 스킨 폴더 위치에 따라 상위 이동 횟수 조절

if (!$is_member) die("ERROR:LOGIN");

$bo_table = preg_replace('/[^a-z0-9_]/i', '', $_POST['bo_table']);
$wr_id    = (int)$_POST['wr_id'];
$current  = (int)$_POST['current'];
$percent  = (int)$_POST['percent'];

if (!$bo_table || !$wr_id) die("ERROR:DATA");

// 테이블명 생성
$write_table = $g5['write_prefix'] . $bo_table;

// 진도율 100%를 넘지 않게 방어
if($percent > 100) $percent = 100;

// 업데이트 쿼리 (wr_9: 진도율, wr_10: 시청초)
// 로그인한 사용자의 글인지 확인하는 조건(mb_id)을 넣어야 타인이 내 진도를 못 바꿉니다.
$sql = " UPDATE {$write_table}
            SET wr_9 = '{$percent}',
                wr_10 = '{$current}'
          WHERE wr_id = '{$wr_id}' 
            AND mb_id = '{$member['mb_id']}' ";

if(sql_query($sql)) {
    echo "SUCCESS";
} else {
    echo "ERROR:SQL_FAIL";
}
?>
[/code]

view.php
[code]

<div class="video-container mb-3 position-relative" style="background:#000;">
    <video id="lectureVideo" width="100%" controls playsinline controlsList="nodownload" poster="<?php echo $board_skin_url; ?>/img/video_poster.jpg">
        <source src="<?php echo $view['link'][1];?>" type="video/mp4">
        브라우저가 video 태그를 지원하지 않습니다.
    </video>
</div>

<div class="alert alert-light border border-primary-subtle shadow-sm">
    <div class="d-flex justify-content-between align-items-center mb-1">
        <span class="fw-bold"><i class="fa fa-play-circle text-primary"></i> 학습 진행 상황</span>
        <span class="badge bg-primary"><span id="progressPercent"><?php echo (int)$write['wr_9']; ?></span>% 완료</span>
    </div>
    <div class="progress" style="height: 10px; background-color: #e9ecef;">
        <div id="progressBar" class="progress-bar progress-bar-striped progress-bar-animated" 
             role="progressbar" 
             style="width: <?php echo (int)$write['wr_9']; ?>%; transition: width 0.3s ease;">
        </div>
    </div>
</div>

<script>
$(function() {
    const video = document.getElementById('lectureVideo');
    const UPDATE_URL = "<?php echo $board_skin_url; ?>/lms_update.skin.php";
    
    // 초기 설정값
    const conf = {
        bo_table: "<?php echo $bo_table; ?>",
        wr_id: "<?php echo $wr_id; ?>",
        lastSavedTime: <?php echo (int)$write['wr_10']; ?>,
        maxPercent: <?php echo (int)$write['wr_9']; ?>
    };

    let trackedMaxTime = conf.lastSavedTime; // 시청한 최대 지점 (초단위)
    let isInitialized = false;

    // 1. 영상 로드 시 이어보기 및 최대 지점 설정
    video.addEventListener('loadedmetadata', function() {
        if (!isInitialized) {
            if (conf.lastSavedTime > 5) {
                if(confirm("이전에 시청하던 지점부터 이어서 보시겠습니까?")) {
                    video.currentTime = conf.lastSavedTime;
                    trackedMaxTime = conf.lastSavedTime;
                }
            }
            isInitialized = true;
        }
    });

    // 2. 앞으로 건너뛰기(Seeking) 제한 로직
    video.addEventListener('seeking', function() {
        if (video.currentTime > trackedMaxTime + 1) { // 1초 정도의 오차 허용
            alert("학습하지 않은 구간으로는 건너뛸 수 없습니다.");
            video.currentTime = trackedMaxTime;
        }
    });

    // 3. 시간 업데이트 시 최대 시청 지점 갱신 및 진도 계산
    video.addEventListener('timeupdate', function() {
        if (!video.seeking) {
            if (video.currentTime > trackedMaxTime) {
                trackedMaxTime = video.currentTime;
            }
        }

        const current = Math.floor(video.currentTime);
        const duration = Math.floor(video.duration);
        
        if (duration > 0) {
            let livePercent = Math.floor((trackedMaxTime / duration) * 100);
            if (livePercent > conf.maxPercent) {
                conf.maxPercent = livePercent > 100 ? 100 : livePercent;
                $('#progressPercent').text(conf.maxPercent);
                $('#progressBar').css('width', conf.maxPercent + '%');
            }
        }
    });

    // 4. 데이터 전송 함수 (AJAX 및 Beacon)
    function sendLmsData(isBeacon = false) {
        const current = Math.floor(video.currentTime);
        const percent = conf.maxPercent;

        if (isBeacon) {
            // 페이지 이탈 시 비동기 전송 보장
            const formData = new FormData();
            formData.append('bo_table', conf.bo_table);
            formData.append('wr_id', conf.wr_id);
            formData.append('current', current);
            formData.append('percent', percent);
            navigator.sendBeacon(UPDATE_URL, formData);
        } else {
            // 일반 자동 저장
            $.ajax({
                url: UPDATE_URL,
                type: 'POST',
                data: {
                    bo_table: conf.bo_table,
                    wr_id: conf.wr_id,
                    current: current,
                    percent: percent
                },
                dataType: 'json'
            });
        }
    }

    // 10초마다 자동 저장
    const saveInterval = setInterval(function() {
        if (!video.paused) sendLmsData();
    }, 10000);

    // 페이지 이탈 시 (창 닫기, 뒤로가기 등) 즉시 저장
    window.addEventListener('visibilitychange', function() {
        if (document.visibilityState === 'hidden') {
            sendLmsData(true);
        }
    });
});
</script>
[/code]

간단하게 영상도 마지막 본 상태에서 재생도 가능합니다.

기본틀이니 각자 영상 진행율 저장하는 DB 만들고 연동하면 될듯 싶네요
100% 수료증 발급 페이지 만들고 하면 응 나름 
영상은 네이버 영상 무료로 업로드 가능합니다 그쪽을 이용하시면될듯싶습니다.

ex) https://tv.naver.com/embed/코드번호?autoPlay=true 영상 업로드후 LMS 영상 재생해주는 홈페이지가 몇군데 있습니다.

첨부파일

view_comment.skin.php (10.6 KB) 2회 2026-02-19 17:26
list.skin.php (11.7 KB) 1회 2026-02-19 17:26
lms_update.skin.php (1.2 KB) 0회 2026-02-19 17:26
4명이 반응했습니다
|

댓글 2개

좋아요. 감사 합니다.

고금 스킬 알려주셔서 감사합니다

학습 진행 상황과 봤던 시점부터 다시보기 기능 잘 이용하도록 하겠습니다

댓글을 작성하시려면 로그인이 필요합니다.

그누보드5 팁자료실

+
제목 글쓴이 날짜 조회
3년 전 조회 5,397
어제 조회 70
4일 전 조회 65
4일 전 조회 61
1주 전 조회 98
1주 전 조회 103
1주 전 조회 150
1주 전 조회 211
1주 전 조회 248
1주 전 조회 405
2주 전 조회 511
3주 전 조회 706
3주 전 조회 671
3주 전 조회 636
1개월 전 조회 942
1개월 전 조회 883
1개월 전 조회 855
1개월 전 조회 933
1개월 전 조회 1,020
1개월 전 조회 1,006
1개월 전 조회 994
1개월 전 조회 994
2개월 전 조회 1,172
2개월 전 조회 1,171
2개월 전 조회 1,051
2개월 전 조회 991
2개월 전 조회 1,229
2개월 전 조회 1,139
2개월 전 조회 975
2개월 전 조회 1,266
2개월 전 조회 1,226