| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- @model Admin.ViewModels.Forum.Posts.List.ListViewModel
- @using Library.Helpers
- @{
- ViewData["Title"] = "게시글 목록";
- var pageIndex = (Model.Parameter.Page <= 0 ? 1 : Model.Parameter.Page);
- var perPage = (Model.Parameter.PerPage <= 0 ? 20 : Model.Parameter.PerPage);
- }
- <div class="container-fluid">
- <h3 class="mb-3">@ViewData["Title"]</h3>
- <partial name="_StatusMessage" />
- <div class="card mb-3">
- <div class="card-body">
- <form class="row gx-2 gy-2 align-items-end filter-bar">
- <div class="col-12 col-sm-6 col-md-auto">
- <label class="form-label mb-1 small">게시판 그룹</label>
- <select id="boardId" class="form-select form-select-sm w-100">
- <option value="">- 전체 -</option>
- @foreach (var g in (Model?.BoardList ?? Enumerable.Empty<SelectListItem>()))
- {
- var selected = ((Model?.Parameter?.BoardID?.ToString() ?? "") == (g.Value ?? ""));
- <option value="@g.Value" selected="@(selected)">@g.Text</option>
- }
- </select>
- </div>
- <div class="col-12 col-sm-6 col-md-auto">
- <label class="form-label mb-1 small">검색</label>
- <select id="search" class="form-select form-select-sm w-100">
- <option value="">- 전체 -</option>
- <option value="0" selected="@(Model?.Parameter.Search == 0)">제목</option>
- <option value="1" selected="@(Model?.Parameter.Search == 1)">내용</option>
- <option value="2" selected="@(Model?.Parameter.Search == 2)">작성자</option>
- <option value="3" selected="@(Model?.Parameter.Search == 3)">댓글</option>
- </select>
- </div>
- <div class="col-12 col-sm-6 col-md-4 col-lg-3">
- <label class="form-label mb-1 small">키워드</label>
- <input type="text" id="keyword" class="form-control form-control-sm w-100" value="@(Model?.Parameter.Keyword ?? "")" placeholder="검색어" />
- </div>
- <div class="col-12 col-sm-6 col-md-auto">
- <label class="form-label mb-1 small">기간</label>
- <div class="input-group input-group-sm">
- <input type="date" id="startAt" class="form-control" value="@(Model?.Parameter.StartAt ?? "")" />
- <span class="input-group-text">~</span>
- <input type="date" id="endAt" class="form-control" value="@(Model?.Parameter.EndAt ?? "")" />
- </div>
- </div>
- <div class="col-12 col-sm-6 col-md-auto">
- <label class="form-label mb-1 small">정렬</label>
- <select id="sort" class="form-select form-select-sm w-100">
- <option value="0" selected="@(Model?.Parameter.Sort == 0)">최신순</option>
- <option value="1" selected="@(Model?.Parameter.Sort == 1)">조회순</option>
- <option value="2" selected="@(Model?.Parameter.Sort == 2)">댓글순</option>
- <option value="3" selected="@(Model?.Parameter.Sort == 3)">공감순</option>
- </select>
- </div>
- <div class="col-12 col-md-auto">
- <label class="form-label mb-1 small d-block">상태</label>
- <div class="d-flex flex-wrap gap-2">
- <div class="form-check form-check-inline m-0">
- <input class="form-check-input" type="checkbox" id="isNotice" checked="@(Model?.Parameter.IsNotice == true)" />
- <label class="form-check-label small" for="isNotice">공지</label>
- </div>
- <div class="form-check form-check-inline m-0">
- <input class="form-check-input" type="checkbox" id="isSecret" checked="@(Model?.Parameter.IsSecret == true)" />
- <label class="form-check-label small" for="isSecret">비밀</label>
- </div>
- <div class="form-check form-check-inline m-0">
- <input class="form-check-input" type="checkbox" id="isReply" checked="@(Model?.Parameter.IsReply == true)" />
- <label class="form-check-label small" for="isReply">답글</label>
- </div>
- <div class="form-check form-check-inline m-0">
- <input class="form-check-input" type="checkbox" id="isDeleted" checked="@(Model?.Parameter.IsDeleted == true)" />
- <label class="form-check-label small" for="isDeleted">삭제</label>
- </div>
- </div>
- </div>
- <div class="col-6 col-sm-4 col-md-auto">
- <label class="form-label mb-1 small d-block"> </label>
- <button id="btnSearch" class="btn btn-sm btn-primary w-100">검색</button>
- </div>
-
- <div class="col-12 col-sm-auto ms-auto text-sm-end">
- <label class="form-label mb-1 small d-block"> </label>
- <div class="d-flex align-items-center justify-content-end gap-2">
- <select id="perPage" class="form-select form-select-sm w-auto">
- <option value="10" selected="@(Model?.Parameter.PerPage == 10)">10</option>
- <option value="20" selected="@(Model?.Parameter.PerPage == 20)">20</option>
- <option value="50" selected="@(Model?.Parameter.PerPage == 50)">50</option>
- <option value="100" selected="@(Model?.Parameter.PerPage == 100)">100</option>
- </select>
- <a id="btnCreate" class="btn btn-sm btn-success" href="/Forum/Post/Create">추가</a>
- </div>
- </div>
- </form>
- </div>
- </div>
- <div class="card">
- <div class="table-responsive">
- <table class="table table-sm table-hover align-middle mb-0 table-fix">
- <thead class="table-light">
- <tr>
- <th class="text-center" style="width:70px">No</th>
- <th class="col-subject" style="min-width:320px">제목</th>
- <th class="col-author" style="width:120px">작성자</th>
- <th class="text-end">조회</th>
- <th class="text-end">공감</th>
- <th class="text-end">비공감</th>
- <th class="text-end">댓글</th>
- <th class="text-center">첨부</th>
- <th class="col-date" style="width:150px">작성일</th>
- </tr>
- </thead>
- <tbody>
- @if (Model?.Data == null || Model.Data.Count == 0)
- {
- <tr>
- <td colspan="10" class="text-center text-muted py-4">데이터가 없습니다.</td>
- </tr>
- }
- else
- {
- foreach (var item in Model.Data)
- {
- <tr class="@(item.IsActive ? "table-primary" : (item.IsNotice ? "table-warning" : ""))">
- <td class="text-center">@item.No</td>
- <td>
- <div class="d-flex align-items-center gap-2">
- @if (!string.IsNullOrEmpty(item.Thumbnail))
- {
- <img src="@item.Thumbnail" alt="" style="width:36px;height:36px;object-fit:cover;border-radius:.5rem;" />
- }
- <div>
- <div>
- @if (item.IsNotice)
- {
- <span class="badge text-bg-warning me-1">공지</span>
- }
- @if (item.IsSecret)
- {
- <span class="badge text-bg-secondary me-1">비밀</span>
- }
- @if (item.IsReply)
- {
- <span class="badge text-bg-info me-1">답글</span>
- }
- @if (item.IsSpeaker)
- {
- <span class="badge text-bg-primary me-1">작성자</span>
- }
- @if (item.IsAnonymous)
- {
- <span class="badge text-bg-dark me-1">익명</span>
- }
- <a class="text-decoration-none" href="@item.EditURL">@item.Subject</a>
- </div>
- </div>
- </div>
- </td>
- <td>@(item.Name ?? item.SID ?? "-")</td>
- <td class="text-end">@item.Views</td>
- <td class="text-end">@item.Likes</td>
- <td class="text-end">@item.Dislikes</td>
- <td class="text-end">@item.Comments</td>
- <td class="text-center">
- <span title="이미지">@item.Images</span> /
- <span title="미디어">@item.Medias</span> /
- <span title="파일">@item.Files</span> /
- <span title="태그">@item.Tags</span>
- </td>
- <td>@item.CreatedAt</td>
- </tr>
- }
- }
- </tbody>
- </table>
- </div>
- </<br />
- <partial name="_Pagination" model="Model!.Pagination" />
- </div>
- </div>
- <style>
- .table-responsive {
- overflow-x: auto;
- }
- .table-fix th, .table-fix td {
- white-space: nowrap;
- vertical-align: middle;
- }
- .table-fix .col-subject {
- white-space: normal;
- min-width: 280px;
- }
- .table-fix .col-author {
- min-width: 140px;
- }
- .table-fix .col-date {
- min-width: 160px;
- }
- .table-fix .col-actions {
- min-width: 120px;
- }
- .table-fix td .attach-compact > span {
- margin-right: 6px;
- }
- </style>
- @section Scripts {
- <script>
- function updateQueryString(resetPage = true) {
- const qp = new URLSearchParams();
- qp.set("BoardGroupID", $("#boardGroupId").val() || "");
- qp.set("BoardID", $("#boardId").val() || "");
- const searchVal = $("#search").val();
- if (searchVal !== null && searchVal !== "") qp.set("Search", searchVal);
- qp.set("Keyword", $("#keyword").val() || "");
- qp.set("StartAt", $("#startAt").val() || "");
- qp.set("EndAt", $("#endAt").val() || "");
- const sortVal = $("#sort").val();
- if (sortVal !== null && sortVal !== "") qp.set("Sort", sortVal);
- if ($("#isNotice").is(":checked")) qp.set("IsNotice", "true");
- if ($("#isSecret").is(":checked")) qp.set("IsSecret", "true");
- if ($("#isReply").is(":checked")) qp.set("IsReply", "true");
- if ($("#isDeleted").is(":checked")) qp.set("IsDeleted","true");
- qp.set("PerPage", $("#perPage").val() || "10");
- qp.set("Page", resetPage ? "1" : "@pageIndex");
- window.location.href = window.location.pathname + "?" + qp.toString();
- }
- $("#btnSearch").on("click", function (e)
- {
- e.preventDefault(); updateQueryString(true);
- });
- $("#keyword,#startAt,#endAt").on("keyup", function (e)
- {
- if (e.key === "Enter") updateQueryString(true);
- });
- </script>
- }
|