게시판 작성 생성 - continue

This commit is contained in:
ckx6954 2024-12-16 16:14:47 +09:00
parent 994956b253
commit 243c2e0f05
11 changed files with 251 additions and 10 deletions

19
package-lock.json generated
View File

@ -9,6 +9,7 @@
"version": "0.0.0",
"dependencies": {
"@popperjs/core": "^2.11.8",
"@tinymce/tinymce-vue": "^5.1.1",
"@vueup/vue-quill": "^1.2.0",
"axios": "^1.7.9",
"bootstrap": "^5.3.3",
@ -1514,6 +1515,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@tinymce/tinymce-vue": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@tinymce/tinymce-vue/-/tinymce-vue-5.1.1.tgz",
"integrity": "sha512-iO57HOWesFOhsaqjA5Ea6sDvQBmJJH3/dq00Uvg7metlct2kLF+ctRgoDsetLt6gmeZ7COPftr814/XzqnJ/dg==",
"license": "MIT",
"dependencies": {
"tinymce": "^6.0.0 || ^5.5.1"
},
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/@types/estree": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
@ -4312,6 +4325,12 @@
"url": "https://opencollective.com/unts"
}
},
"node_modules/tinymce": {
"version": "6.8.5",
"resolved": "https://registry.npmjs.org/tinymce/-/tinymce-6.8.5.tgz",
"integrity": "sha512-qAL/FxL7cwZHj4BfaF818zeJJizK9jU5IQzTcSLL4Rj5MaJdiVblEj7aDr80VCV1w9h4Lak9hlnALhq/kVtN1g==",
"license": "MIT"
},
"node_modules/totalist": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",

View File

@ -12,6 +12,7 @@
},
"dependencies": {
"@popperjs/core": "^2.11.8",
"@tinymce/tinymce-vue": "^5.1.1",
"@vueup/vue-quill": "^1.2.0",
"axios": "^1.7.9",
"bootstrap": "^5.3.3",

View File

@ -1 +1,11 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
{
"name": "",
"short_name": "",
"icons": [
{ "src": "/img/favicon/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/img/favicon/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" }
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

View File

@ -0,0 +1,69 @@
<template>
<Editor :api-key="editorKey" :init="init" />
</template>
<script setup>
import Editor from '@tinymce/tinymce-vue';
import { reactive } from 'vue';
const editorKey = '71nhna4fusscfsf8qvo9cg3ul4uydwt346izxa6ra6zwjsz7';
const init = reactive({
toolbar_mode: 'sliding',
plugins: [
// Core editing features
'anchor',
'autolink',
'charmap',
'codesample',
'emoticons',
'image',
'link',
'lists',
'media',
'searchreplace',
'table',
'visualblocks',
'wordcount',
// Your account includes a free trial of TinyMCE premium features
// Try the most popular premium features until Dec 30, 2024:
'checklist',
'mediaembed',
'casechange',
'export',
'formatpainter',
'pageembed',
'a11ychecker',
'tinymcespellchecker',
'permanentpen',
'powerpaste',
'advtable',
'advcode',
'editimage',
'advtemplate',
'ai',
'mentions',
'tinycomments',
'tableofcontents',
'footnotes',
'mergetags',
'autocorrect',
'typography',
'inlinecss',
],
toolbar:
'undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | link image media table mergetags | addcomment showcomments | spellcheckdialog a11ycheck typography | align lineheight | checklist numlist bullist indent outdent | emoticons charmap | removeformat',
tinycomments_mode: 'embedded',
tinycomments_author: 'Author name',
mergetags_list: [
{ value: 'First.Name', title: 'First Name' },
{ value: 'Email', title: 'Email' },
],
ai_request: (request, respondWith) => respondWith.string(() => Promise.reject('See docs to implement AI Assistant')),
});
</script>
<style>
.tox-statusbar{
display: none !important;
}
</style>

View File

@ -0,0 +1,14 @@
<template>
<div class="mb-4 row">
<label for="html5-email-input" class="col-md-2 col-form-label"> 첨부파일 </label>
<div class="col-md-10">
<input class="form-control" type="file" id="formFileMultiple" multiple />
</div>
</div>
</template>
<script setup>
</script>
<style>
</style>

View File

@ -0,0 +1,60 @@
<template>
<div class="mb-4 row">
<label for="html5-text-input" class="col-md-2 col-form-label">
{{ $props.title }}
<span :class="$props.isEssential ? 'text-red' : 'none'">*</span>
</label>
<div class="col-md-10">
<input class="form-control" :type="$props.type" @input="updateInput" :value="$props.value" :maxLength="$props.maxlength" />
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
const prop = defineProps({
title: {
type: String,
default: '라벨',
required: true,
},
isEssential: {
type: Boolean,
default: false,
required: false,
},
type: {
type: String,
default: 'text',
required: false,
},
value: {
type: String,
default: '',
require: false,
},
maxlength: {
type: Number,
default: 30,
required: false,
},
});
const emits = defineEmits(['inputVal'])
const updateInput = function (event) {
//Type Number maxlength
if (event.target.value.length > prop.maxlength) {
event.target.value = event.target.value.slice(0, prop.maxlength);
}
emits('inputVal', event.target.value);
};
</script>
<style>
.none {
display: none;
}
</style>

View File

@ -0,0 +1,21 @@
<template>
<div class="mb-4 row">
<label for="html5-email-input" class="col-md-2 col-form-label">
카테고리
<span class="text-red">*</span>
</label>
<div class="col-md-10">
<select class="form-select" id="exampleFormControlSelect1" aria-label="Default select example">
<option selected value="1">자유</option>
<option value="1">임시</option>
<option value="2">공지</option>
</select>
</div>
</div>
</template>
<script setup>
</script>
<style>
</style>

View File

@ -38,7 +38,7 @@
<div class="text-truncate" data-i18n="Analytics">Main</div>
</RouterLink>
</li>
<li class="menu-item" :class="$route.path == '/board' ? 'active' : '' ">
<li class="menu-item" :class="$route.path.includes('/board') ? 'active' : '' ">
<RouterLink class="menu-link" to="board" >
<i class="menu-icon tf-icons bx bx-layout"></i>
<div class="text-truncate" data-i18n="Analytics">Board</div>

View File

@ -9,4 +9,7 @@ const pinia = createPinia()
pinia.use(piniaPersist)
const app = createApp(App)
app.use(router).use(pinia).use(dayjs).mount('#app')
app.use(router)
.use(pinia)
.use(dayjs)
.mount('#app')

View File

@ -5,28 +5,23 @@ import BoardWrite from '@v/board/BoardWrite.vue';
const routes = [
{
path: '/',
name : 'main',
component: () => import('@v/MainView.vue'),
// meta: { requiresAuth: true }
},
{
path: '/board',
name : 'board',
component: () => import('@v/board/TheBoard.vue'),
children : [
{
path : '',
name : 'boardList',
component : () => import('@v/board/BoardList.vue')
},
{
path : 'write',
name : 'boardWrite',
component : () => import('@v/board/BoardWrite.vue')
},
{
path : 'get/:id',
name : 'boardView',
component : () => import('@v/board/BoardView.vue')
}
]

View File

@ -1,11 +1,60 @@
<template>
dasdasdas
<div class="container-xxl flex-grow-1 container-p-y">
<div class="card">
<div class="pb-4 rounded-top">
<div class="container py-12 px-xl-10 px-4" style="padding-bottom: 0px !important">
<h3 class="text-center mb-2 mt-4"> 작성</h3>
</div>
</div>
<div class="col-xl-6">
<!-- HTML5 Inputs -->
<div class="card mb-6">
<div class="card-body">
<FormInput title="제목" :is-essential="true" @input-val="title = $event"/>
<FormSelect/>
<FormInput title="비밀번호" type="password" :is-essential="true" @input-val="password = $event"/>
<FormFile />
<div class="mb-4">
<label for="html5-tel-input" class="col-md-2 col-form-label">
내용
<span class="text-red">*</span>
</label>
<div class="col-md-12">
<QEditor />
</div>
</div>
<div class="mb-4 d-flex justify-content-end">
<button type="button" class="btn btn-info right">목록</button>
<button type="button" class="btn btn-primary ms-1">작성</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import QEditor from '@c/editor/QEditor.vue';
import FormInput from '@c/input/FormInput.vue';
import FormSelect from '@c/input/FormSelect.vue';
import FormFile from '@c/input/FormFile.vue';
import { ref } from 'vue';
const title = ref('');
const password = ref('');
</script>
<style>
.text-red {
color: red;
text-align: center;
}
</style>