feat: xavis ai_platform 기능 이전 및 ncue 환경 전환

xavis 소스·DB 스키마·활용사례/F-Scan/프롬프트 라이브러리 등 기능 반영.
@xavis.co.kr → @ncue.net, 관리자 토큰 ncue-admin, 런타임 data/ Git 추적 제외.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dsyoon
2026-05-26 22:27:48 +09:00
parent 7bee72f287
commit 073a8343dd
84 changed files with 10883 additions and 1043 deletions

View File

@@ -12,6 +12,7 @@
class="<%= (typeof aiExploreDevGuestRestricted !== 'undefined' && aiExploreDevGuestRestricted) ? 'ai-explore-page ai-explore-dev-guest' : 'ai-explore-page' %>"
>
<% var aiGuestDev = typeof aiExploreDevGuestRestricted !== 'undefined' && aiExploreDevGuestRestricted; %>
<% var _tclOk = typeof taskChecklistMenuAllowed !== 'undefined' && taskChecklistMenuAllowed; %>
<% var _opsLoggedIn = typeof opsUserEmail !== 'undefined' && opsUserEmail; %>
<div class="app-shell">
<%- include('partials/nav', { activeMenu: 'ai-explore', adminMode: typeof adminMode !== 'undefined' ? adminMode : false }) %>
@@ -42,21 +43,31 @@
aria-label="AI 서비스 제목·설명 검색"
<% if (aiGuestDev) { %>disabled aria-disabled="true"<% } %>
/>
<div class="ai-type-filters" role="radiogroup" aria-label="AI 타입 필터">
<label class="ai-type-filter-option">
<input type="radio" name="aiTypeFilter" value="all" checked <% if (aiGuestDev) { %>disabled aria-disabled="true"<% } %> />
<span>전체</span>
</label>
<label class="ai-type-filter-option">
<input type="radio" name="aiTypeFilter" value="general" <% if (aiGuestDev) { %>disabled aria-disabled="true"<% } %> />
<span>일반</span>
</label>
<label class="ai-type-filter-option">
<input type="radio" name="aiTypeFilter" value="xscan" <% if (aiGuestDev) { %>disabled aria-disabled="true"<% } %> />
<span>XScan</span>
</label>
<label class="ai-type-filter-option">
<input type="radio" name="aiTypeFilter" value="fscan" <% if (aiGuestDev) { %>disabled aria-disabled="true"<% } %> />
<span>FScan</span>
</label>
</div>
</form>
</section>
<section class="panel">
<h2>AI 서비스</h2>
<div class="ai-card-grid">
<a href="/ai-explore/prompts" class="ai-card ai-card-link">
<div class="ai-card-header">
<span class="status-chip public">공개중</span>
</div>
<h3>프롬프트</h3>
<p>업무별 기본 프롬프트를 모아 두고, 복사해 바로 활용할 수 있는 라이브러리입니다.</p>
<div class="tag-row"><span class="tag-chip">#프롬프트</span></div>
</a>
<% if (aiGuestDev) { %>
<article class="ai-card ai-card-disabled" aria-disabled="true">
<article class="ai-card ai-card-disabled" aria-disabled="true" data-ai-type="general">
<div class="ai-card-header">
<span class="status-chip public">공개중</span>
</div>
@@ -65,7 +76,7 @@
<div class="tag-row"><span class="tag-chip">#업무관리</span><span class="tag-chip">#회의록</span></div>
</article>
<% } else { %>
<a href="/ai-explore/meeting-minutes" class="ai-card ai-card-link">
<a href="/ai-explore/meeting-minutes" class="ai-card ai-card-link" data-ai-type="general">
<div class="ai-card-header">
<span class="status-chip public">공개중</span>
</div>
@@ -74,8 +85,9 @@
<div class="tag-row"><span class="tag-chip">#업무관리</span><span class="tag-chip">#회의록</span></div>
</a>
<% } %>
<% if (_tclOk) { %>
<% if (aiGuestDev) { %>
<article class="ai-card ai-card-disabled" aria-disabled="true">
<article class="ai-card ai-card-disabled" aria-disabled="true" data-ai-type="general">
<div class="ai-card-header">
<span class="status-chip public">공개중</span>
</div>
@@ -84,7 +96,7 @@
<div class="tag-row"><span class="tag-chip">#업무관리</span><span class="tag-chip">#체크리스트</span></div>
</article>
<% } else { %>
<a href="/ai-explore/task-checklist" class="ai-card ai-card-link">
<a href="/ai-explore/task-checklist" class="ai-card ai-card-link" data-ai-type="general">
<div class="ai-card-header">
<span class="status-chip public">공개중</span>
</div>
@@ -93,6 +105,45 @@
<div class="tag-row"><span class="tag-chip">#업무관리</span><span class="tag-chip">#체크리스트</span></div>
</a>
<% } %>
<% } %>
<% if (aiGuestDev) { %>
<article class="ai-card ai-card-disabled" aria-disabled="true" data-ai-type="general">
<div class="ai-card-header">
<span class="status-chip public">공개중</span>
</div>
<h3>일반 채팅</h3>
<p>ChatGPT를 이용한 채팅 서비스입니다.</p>
<div class="tag-row"><span class="tag-chip">#질의응답.</span><span class="tag-chip">ChatGPT</span></div>
</article>
<% } else { %>
<a href="/ai-explore/chat" class="ai-card ai-card-link" data-ai-type="general">
<div class="ai-card-header">
<span class="status-chip public">공개중</span>
</div>
<h3>일반 채팅</h3>
<p>ChatGPT를 이용한 채팅 서비스입니다.</p>
<div class="tag-row"><span class="tag-chip">#질의응답.</span><span class="tag-chip">ChatGPT</span></div>
</a>
<% } %>
<% if (aiGuestDev) { %>
<article class="ai-card ai-card-disabled" aria-disabled="true" data-ai-type="fscan">
<div class="ai-card-header">
<span class="status-chip public">공개중</span>
</div>
<h3>FSCAN 조사각 선정도우미</h3>
<p>검사 대상물 치수(H/W) 기반으로 FSCAN 시리즈 모델 선정을 돕는 도구입니다.</p>
<div class="tag-row"><span class="tag-chip">#FSCAN</span><span class="tag-chip">#선정도우미</span></div>
</article>
<% } else { %>
<a href="/ai-explore/fscan" class="ai-card ai-card-link" data-ai-type="fscan">
<div class="ai-card-header">
<span class="status-chip public">공개중</span>
</div>
<h3>FSCAN 조사각 선정도우미</h3>
<p>검사 대상물 치수(H/W) 기반으로 FSCAN 시리즈 모델 선정을 돕는 도구입니다.</p>
<div class="tag-row"><span class="tag-chip">#FSCAN</span><span class="tag-chip">#선정도우미</span></div>
</a>
<% } %>
</div>
</section>
</main>
@@ -109,6 +160,7 @@
if (devGuest) return;
var cards = grid.querySelectorAll(".ai-card");
var typeInputs = form.querySelectorAll('input[name="aiTypeFilter"]');
function cardTitleDescriptionText(el) {
var parts = [];
@@ -122,9 +174,14 @@
function applyFilter() {
var q = (input.value || "").trim().toLowerCase();
var checkedType = form.querySelector('input[name="aiTypeFilter"]:checked');
var selectedType = checkedType ? String(checkedType.value || "all") : "all";
cards.forEach(function (el) {
var text = cardTitleDescriptionText(el);
var show = !q || text.indexOf(q) !== -1;
var cardType = String(el.getAttribute("data-ai-type") || "general").toLowerCase();
var textMatched = !q || text.indexOf(q) !== -1;
var typeMatched = selectedType === "all" || cardType === selectedType;
var show = textMatched && typeMatched;
el.hidden = !show;
el.setAttribute("aria-hidden", show ? "false" : "true");
});
@@ -132,11 +189,16 @@
input.addEventListener("input", applyFilter);
input.addEventListener("search", applyFilter);
typeInputs.forEach(function (el) {
el.addEventListener("change", applyFilter);
});
form.addEventListener("submit", function (e) {
e.preventDefault();
applyFilter();
});
applyFilter();
})();
</script>
</body>