This commit is contained in:
2025-08-11 15:55:11 +09:00
parent d0abec2f4b
commit 3a0a29ec02
15 changed files with 338 additions and 159 deletions
@@ -3439,4 +3439,5 @@ button.small,
right: 10px;
font-size: 20px;
cursor: pointer;
}
}
+127 -67
View File
@@ -14,90 +14,150 @@ function initEditor(useEditor) {
baseData.firstPostLat = serverData.firstPostLat;
baseData.firstPostLon = serverData.firstPostLon;
baseData.writeTime = serverData.writeTime;
baseData.originId = serverData.originId;
getLocation();
setEditorHeight();
window.addEventListener('resize', setEditorHeight);
var Font = Quill.import('formats/font');
Font.whitelist = ['sans-serif', 'serif', 'monospace', 'arial', 'georgia', 'comic-sans-ms', 'courier-new', 'roboto', 'playfair-display'];
Quill.register(Font, true);
Quill.register({ 'modules/table-better': QuillTableBetter }, true);
quill = new Quill(editorContainer, {
theme: 'snow',
modules: useEditor ? {
toolbar: {
container: [
[{ font: Font.whitelist }],
[{ 'size': ['small', false, 'large', 'huge'] }],
['bold', 'italic', 'underline', 'strike'],
[{ 'color': [] }, { 'background': [] }],
[{ 'header': 1 }, { 'header': 2 }, 'blockquote', 'code-block'],
[{ 'script': 'sub'}, { 'script': 'super' }],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'indent': '-1'}, { 'indent': '+1' }],
['link', 'image', 'video'],
['table-better'],
[{ 'direction': 'rtl' }],
[{ 'align': [] }],
['clean']
],
handlers: {
image: function () {
selectLocalImage();
},
video: function () {
selectLocalVideo()
}
}
},
'table-better': {
language: 'en_US',
toolbarTable: true
},
keyboard: {
bindings: QuillTableBetter.keyboardBindings
}
} : {toolbar : false, toolbarTable: false},
readOnly: !useEditor
});
loadContent(serverData.content);
if (!useEditor) {
editorContainer.classList.add('readonly-mode');
} else {
editorContainer.classList.remove('readonly-mode');
}
console.log("quill", quill);
}
function isDelta(content) {
try {
// Delta는 JSON이면서 'ops'라는 키를 포함
var Font = Quill.import('formats/font');
Font.whitelist = ['sans-serif', 'serif', 'monospace', 'arial', 'georgia', 'comic-sans-ms', 'courier-new', 'roboto', 'playfair-display'];
Quill.register(Font, true);
Quill.register({ 'modules/table-better': QuillTableBetter }, true);
quill = new Quill(editorContainer, {
theme: 'snow',
modules: useEditor ? {
toolbar: {
container: [
[{ font: Font.whitelist }],
[{ 'size': ['small', false, 'large', 'huge'] }],
['bold', 'italic', 'underline', 'strike'],
[{ 'color': [] }, { 'background': [] }],
[{ 'header': 1 }, { 'header': 2 }, 'blockquote', 'code-block'],
[{ 'script': 'sub'}, { 'script': 'super' }],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'indent': '-1'}, { 'indent': '+1' }],
['link', 'image', 'video'],
['table-better'],
[{ 'direction': 'rtl' }],
[{ 'align': [] }],
['clean']
],
handlers: {
image: function () {
selectLocalImage();
},
video: function () {
selectLocalVideo()
}
}
},
'table-better': {
language: 'en_US',
toolbarTable: true
},
keyboard: {
bindings: QuillTableBetter.keyboardBindings
}
} : {toolbar : false, toolbarTable: false},
readOnly: !useEditor
});
loadContent(serverData.content);
if (!useEditor) {
editorContainer.classList.add('readonly-mode');
} else {
editorContainer.classList.remove('readonly-mode');
}
console.log("quill", quill);
}catch (e) { }
try {
document.querySelector("#title_field").textContent = baseData.title
}catch (e) { }
try {
document.getElementById('location_field').textContent = "Lat: " + baseData.firstPostLat + ", Lon: " + baseData.firstPostLon;
var requestOptions = {
method: 'GET',
};
fetch("https://api.geoapify.com/v1/geocode/reverse?lat="+baseData.firstPostLat+"&lon="+baseData.firstPostLon+"&apiKey=2b37a75bb0754086b5a1c4a7c3173ee8", requestOptions)
.then(response => response.json())
.then(function(result) {
try {
document.getElementById('location_field').textContent = result.features[0].properties.formatted
} catch (e) {
document.getElementById('location_field').innerHTML = "Lat: " + baseData.firstPostLat + "<br> Lon: " + baseData.firstPostLon;
}
})
.catch(error => console.log('error', error));
}catch (e) { }
}
function parseDelta(content) {
try {
if (typeof content === "string") {
content = JSON.parse(content);
const obj = JSON.parse(content);
if (obj && typeof obj === "object" && Array.isArray(obj.ops)) {
return obj; // 유효한 Delta 객체
}
} else if (content && typeof content === "object" && Array.isArray(content.ops)) {
return content; // 이미 Delta 객체 형태
}
return typeof content === "object" && content.ops !== undefined;
} catch (e) {
return false; // JSON 파싱 실패하면 마크업(HTML)으로 간주
// JSON 파싱 실패HTML로 간주
}
return null; // Delta 아님
}
function loadEditor() {
location.href = getMainPath() + '/blog/editor/' + serverData.id;
}
function loadContent(content) {
if (isDelta(content)) {
quill.setContents(content); // Delta 데이터라면 setContents
console.log("content >>> ", content);
const delta = parseDelta(content);
if (delta) {
quill.setContents(delta);
} else {
quill.clipboard.dangerouslyPasteHTML(content); // HTML 데이터라면 dangerouslyPasteHTML
quill.clipboard.dangerouslyPasteHTML(content);
}
}
function save() {
onclickWrite(serverData.enc ,serverData.keyword,quill.getContents())
onclickWrite(serverData.enc ,serverData.keyword,JSON.stringify(quill.getContents()))
}
function parseDeltaContent(deltaString) {
let textContent = "";
let mediaLinks = [];
try {
const delta = JSON.parse(deltaString); // Delta 문자열 → 객체
if (delta && Array.isArray(delta.ops)) {
delta.ops.forEach(op => {
if (op.insert) {
if (typeof op.insert === "string") {
textContent += op.insert;
} else if (typeof op.insert === "object") {
if (op.insert.image) {
mediaLinks.push(op.insert.image);
}
if (op.insert.video) {
mediaLinks.push(op.insert.video);
}
}
}
});
}
} catch (e) {
console.error("Delta JSON parse error:", e);
}
return { text: textContent.trim(), media: mediaLinks };
}
function selectLocalImage() {
// 이미지 URL 입력 받기
const url = prompt("이미지 URL을 입력하거나 빈칸으로 두시면 파일 업로드를 합니다.");
@@ -237,8 +297,8 @@ function onclickWrite(type, keyword, html) {
if (hasValues) {
baseData.title = encodeURIComponent(title_field.value)
baseData.content = encodeURIComponent(html)
baseData.firstPostLat = encodeURIComponent(currentLat)
baseData.firstPostLon = encodeURIComponent(currentLon)
baseData.modifyLat = encodeURIComponent(currentLat)
baseData.modifyLon = encodeURIComponent(currentLon)
}
let uploadUrl = getMainPath() + "/blog/post.bjx";
if(confirm(JSON.stringify(baseData) + "\n해당 내용으로\n유저 등록 하실??")) {
+3 -3
View File
@@ -419,16 +419,16 @@ function submitLoginForm() {
let user_id = document.getElementById('loginId')
let user_pw = document.getElementById('loginPassword')
let rememberMe = document.getElementById('rememberMe')
console.log(rememberMe.value)
let data = {
'user_id': user_id.value,
'user_pw': user_pw.value,
'rememberMe' : rememberMe.value,
'rememberMe' : rememberMe.value === "on",
}
postLogin(getMainPath()+"/user/login.bjx",user_pw.data,JSON.stringify(data),user_pw.data, function (data) {
closePopup()
alert("data >> " + data)
if (data.isOk) {
document.cookie = "access=" + data.token.split(";")[0]+";"
window.sessionStorage.setItem("REFRESH",data.refresh.split(";")[0])
document.location.replace(location.href)
} else {
if (data.resultCode === 7100) {
@@ -27,10 +27,11 @@
<th:block layout:fragment="content" id="content">
<section class="wrapper style2" >
<th:block th:if="${PERMISSION == 'OK'}">
<th:block sec:authorize="isAuthenticated()">
<div class="container" >
<header class="major">
<h3><label for="title_field"><input id="title_field" th:value="${srcPost.title}"></label></h3>
<h3><label for="title_field"><input id="title_field" th:value="${srcPost.title}" style="width:100%; max-width:100%; box-sizing:border-box;
border:none; outline:none; text-align:center;"></label></h3>
<p th:text="${#temporals.format(T(java.time.Instant).ofEpochMilli(srcPost.writeTime).atZone(T(java.time.ZoneId).systemDefault()).toLocalDateTime(), 'yyyy-MM-dd HH:mm:ss')}"></p>
</header>
</div>
@@ -42,6 +43,7 @@
<h1>권한이 없는 뎁쇼?!</h1>
</th:block>
<th:block sec:authorize="isAuthenticated()">
<div id="editor" ></div>
<div class="write_controllbox">
<div class="write_option btn-example" to="#popLayer1" onclick="openPopup(this)" ></div>
@@ -18,6 +18,7 @@
<script th:inline="javascript">
var serverData = {
id: [[${srcPost != null and srcPost.id != null} ? ${srcPost.id} : 0]],
originId: [[${srcPost != null and srcPost.originId != null} ? ${srcPost.originId} : 0]],
title: /*[[${srcPost != null and srcPost.title != null} ? ${srcPost.title} : '']]*/,
content: /*[[${srcPost != null and srcPost.content != null} ? ${srcPost.content} : '']]*/,
firstPostLat: [[${srcPost != null and srcPost.firstPostLat != null} ? ${srcPost.firstPostLat} : 0]],