
--- client/resources/api/category.js
+++ client/resources/api/category.js
... | ... | @@ -1,6 +1,11 @@ |
1 | 1 |
import apiClient from "./index"; |
2 | 2 |
|
3 | 3 |
// 카테고리 목록 조회 (검색조건 없음) |
4 |
-export const findAllCategoryProc = () => { |
|
4 |
+export const findAllByNullProc = () => { |
|
5 | 5 |
return apiClient.get(`/category/findAllByNull.json`); |
6 |
+} |
|
7 |
+ |
|
8 |
+// 카테고리 목록 조회 (검색조건 있음) |
|
9 |
+export const findAllCategoryProc = () => { |
|
10 |
+ return apiClient.get(`/category/findAllCategory.json`); |
|
6 | 11 |
}(파일 끝에 줄바꿈 문자 없음) |
+++ client/resources/css/ckeditor.css
... | ... | @@ -0,0 +1,9 @@ |
1 | +.ck.ck-editor { | |
2 | + width: 100%; | |
3 | +} | |
4 | + | |
5 | +.ck.ck-content { | |
6 | + width: 100%; | |
7 | + height: 425px; | |
8 | + box-sizing: border-box; | |
9 | +}(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/component/EditorComponent.vue
... | ... | @@ -0,0 +1,172 @@ |
1 | +<template> | |
2 | + <ckeditor v-if="editor && config" :model-value="editorContent" :editor="editor" :config="config" @update:model-value="updateContents" /> | |
3 | +</template> | |
4 | +<script> | |
5 | +/** | |
6 | + * This configuration was generated using the CKEditor 5 Builder. You can modify it anytime using this link: | |
7 | + * https://ckeditor.com/ckeditor-5/builder/#installation/NoNgNARATAdAzPCkCMAGKIAcmCsrdwghzICcUqqyyALESDnKXFKW6djTdkhANYB7JKjDBkYEZIlhkAXUggAZmxwBjVRFlA== | |
8 | + */ | |
9 | + | |
10 | +import { Ckeditor } from '@ckeditor/ckeditor5-vue'; | |
11 | + | |
12 | +import { | |
13 | + ClassicEditor, | |
14 | + Alignment, | |
15 | + AutoLink, | |
16 | + BlockQuote, | |
17 | + Bold, | |
18 | + Essentials, | |
19 | + FontBackgroundColor, | |
20 | + FontColor, | |
21 | + FontFamily, | |
22 | + FontSize, | |
23 | + HorizontalLine, | |
24 | + ImageEditing, | |
25 | + ImageUtils, | |
26 | + Indent, | |
27 | + IndentBlock, | |
28 | + Italic, | |
29 | + Link, | |
30 | + Paragraph, | |
31 | + RemoveFormat, | |
32 | + Strikethrough, | |
33 | + Subscript, | |
34 | + Superscript, | |
35 | + Table, | |
36 | + TableCaption, | |
37 | + TableCellProperties, | |
38 | + TableColumnResize, | |
39 | + TableProperties, | |
40 | + TableToolbar, | |
41 | + TextPartLanguage, | |
42 | + Underline, | |
43 | +} from 'ckeditor5'; | |
44 | + | |
45 | +import translations from 'ckeditor5/translations/ko.js'; | |
46 | + | |
47 | +import 'ckeditor5/ckeditor5.css'; | |
48 | + | |
49 | +/** | |
50 | + * Create a free account with a trial: https://portal.ckeditor.com/checkout?plan=free | |
51 | + */ | |
52 | +const LICENSE_KEY = 'GPL'; // or <YOUR_LICENSE_KEY>. | |
53 | + | |
54 | +export default { | |
55 | + name: 'EditorComponent', | |
56 | + components: { | |
57 | + Ckeditor | |
58 | + }, | |
59 | + props: { | |
60 | + contents: { | |
61 | + type: String, | |
62 | + default: '' | |
63 | + } | |
64 | + }, | |
65 | + emits: ['update:contents'], | |
66 | + data() { | |
67 | + return { | |
68 | + isLayoutReady: false, | |
69 | + editor: ClassicEditor, | |
70 | + }; | |
71 | + }, | |
72 | + computed: { | |
73 | + editorContent() { | |
74 | + // contents가 null 또는 undefined인 경우 빈 문자열 반환 | |
75 | + return this.contents || ''; | |
76 | + }, | |
77 | + config() { | |
78 | + if (!this.isLayoutReady) { | |
79 | + return null; | |
80 | + } | |
81 | + | |
82 | + return { | |
83 | + toolbar: { | |
84 | + items: [ | |
85 | + 'fontSize', | |
86 | + 'fontFamily', | |
87 | + 'fontColor', | |
88 | + 'fontBackgroundColor', | |
89 | + '|', | |
90 | + 'bold', | |
91 | + 'italic', | |
92 | + 'underline', | |
93 | + 'strikethrough', | |
94 | + 'subscript', | |
95 | + 'superscript', | |
96 | + 'removeFormat', | |
97 | + '|', | |
98 | + 'horizontalLine', | |
99 | + 'link', | |
100 | + 'insertTable', | |
101 | + 'blockQuote', | |
102 | + '|', | |
103 | + 'alignment', | |
104 | + '|', | |
105 | + 'outdent', | |
106 | + 'indent' | |
107 | + ], | |
108 | + shouldNotGroupWhenFull: true | |
109 | + }, | |
110 | + plugins: [ | |
111 | + Alignment, | |
112 | + AutoLink, | |
113 | + BlockQuote, | |
114 | + Bold, | |
115 | + Essentials, | |
116 | + FontBackgroundColor, | |
117 | + FontColor, | |
118 | + FontFamily, | |
119 | + FontSize, | |
120 | + HorizontalLine, | |
121 | + ImageEditing, | |
122 | + ImageUtils, | |
123 | + Indent, | |
124 | + IndentBlock, | |
125 | + Italic, | |
126 | + Link, | |
127 | + Paragraph, | |
128 | + RemoveFormat, | |
129 | + Strikethrough, | |
130 | + Subscript, | |
131 | + Superscript, | |
132 | + Table, | |
133 | + TableCaption, | |
134 | + TableCellProperties, | |
135 | + TableColumnResize, | |
136 | + TableProperties, | |
137 | + TableToolbar, | |
138 | + TextPartLanguage, | |
139 | + Underline, | |
140 | + ], | |
141 | + fontFamily: { | |
142 | + supportAllValues: true | |
143 | + }, | |
144 | + fontSize: { | |
145 | + options: [10, 12, 14, 'default', 18, 20, 22], | |
146 | + supportAllValues: true | |
147 | + }, | |
148 | + language: 'ko', | |
149 | + licenseKey: LICENSE_KEY, | |
150 | + link: { | |
151 | + addTargetToExternalLinks: true, | |
152 | + defaultProtocol: 'https://', | |
153 | + }, | |
154 | + placeholder: '내용을 입력하세요.', | |
155 | + table: { | |
156 | + contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties'] | |
157 | + }, | |
158 | + translations: [translations], | |
159 | + }; | |
160 | + } | |
161 | + }, | |
162 | + mounted() { | |
163 | + this.isLayoutReady = true; | |
164 | + }, | |
165 | + methods: { | |
166 | + updateContents(data) { | |
167 | + // 에디터 내용이 변경될 때 부모 컴포넌트에 알림 | |
168 | + this.$emit('update:contents', data); | |
169 | + } | |
170 | + } | |
171 | +}; | |
172 | +</script>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/component/modal/CategorySelectModal.vue
... | ... | @@ -0,0 +1,66 @@ |
1 | +<template> | |
2 | + <div class="modal-overlay" @click="closeModal"> | |
3 | + <div class="modal-content" @click.stop> | |
4 | + <div class="flex-sp-bw mb-20"> | |
5 | + <h2>카테고리 조회</h2> | |
6 | + <button @click="closeModal" class="closebtn">✕</button> | |
7 | + </div> | |
8 | + <div class="modal-search flex-center mb-20"> | |
9 | + <input type="text" placeholder="카테고리명을 입력하세요."> | |
10 | + <button class="search-btn"><img :src="searchicon" alt=""> | |
11 | + <p>검색</p> | |
12 | + </button> | |
13 | + </div> | |
14 | + <table class="mb-10"> | |
15 | + <thead> | |
16 | + <tr> | |
17 | + <th>카테고리 항목</th> | |
18 | + <th>선택</th> | |
19 | + </tr> | |
20 | + </thead> | |
21 | + <tbody> | |
22 | + <tr v-for="item in items" :key="item.id"> | |
23 | + <!-- Category 칼럼 --> | |
24 | + <td> {{ item.category }} </td> | |
25 | + <!-- Checkbox 칼럼 --> | |
26 | + <td> | |
27 | + <input type="checkbox" v-model="item.selected" /> | |
28 | + </td> | |
29 | + </tr> | |
30 | + </tbody> | |
31 | + </table> | |
32 | + <div class="flex-end mb-30"><button class="register-b " @click="registerCategories">등록</button></div> | |
33 | + <div class="pagination"> | |
34 | + <!-- Previous and Next Page Buttons --> | |
35 | + <button> | |
36 | + <DoubleLeftOutlined /> | |
37 | + </button> | |
38 | + <button @click="previousPage" :disabled="currentPage === 1"> | |
39 | + <LeftOutlined /> | |
40 | + </button> | |
41 | + <button class="page-number clicked">1</button> | |
42 | + <button @click="nextPage" :disabled="currentPage === totalPages"> | |
43 | + <RightOutlined /> | |
44 | + </button> | |
45 | + <button> | |
46 | + <DoubleRightOutlined /> | |
47 | + </button> | |
48 | + </div> | |
49 | + </div> | |
50 | + </div> | |
51 | +</template> | |
52 | +<script> | |
53 | +// 모달 사용 용례 | |
54 | +// selectedCtgries: 부모 요소에 저장된 '선택한 카테고리' 목록 | |
55 | +// @toggleModal: 모달 열고 닫는 함수 (호출만 해도 됨/열려있는 경우 닫힘, 닫혀있는 경우 열림) | |
56 | +export default { | |
57 | + name: 'CategorySelectModal', | |
58 | + props: { | |
59 | + selectedCtgries: { | |
60 | + type: Array, | |
61 | + default: [], | |
62 | + } | |
63 | + }, | |
64 | +} | |
65 | +</script> | |
66 | +<style></style>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/index.html
+++ client/views/index.html
... | ... | @@ -5,12 +5,6 @@ |
5 | 5 |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
6 | 6 |
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> |
7 | 7 |
<meta name="description" content="Node Vue Web"> |
8 |
- <link rel="stylesheet" href="../client/resources/css/common/common.css"> |
|
9 |
- <link rel="stylesheet" href="../client/resources/css/common/font.css"> |
|
10 |
- <link rel="stylesheet" href="../client/resources/css/user/board.css"> |
|
11 |
- <link rel="stylesheet" href="../client/resources/css/user/layout.css"> |
|
12 |
- <link rel="stylesheet" href="../client/resources/css/user/main.css"> |
|
13 |
- <link rel="stylesheet" href="../client/resources/css/user/sub.css"> |
|
14 | 8 |
<title>구미시 디지털 아카이브</title> |
15 | 9 |
</head> |
16 | 10 |
<body> |
--- client/views/index.js
+++ client/views/index.js
... | ... | @@ -4,6 +4,15 @@ |
4 | 4 |
import Store from "./pages/AppStore.js"; |
5 | 5 |
import Router from "./pages/AppRouter.js"; |
6 | 6 |
|
7 |
+// Style import |
|
8 |
+import '../resources/css/common/common.css'; |
|
9 |
+import '../resources/css/common/font.css'; |
|
10 |
+import '../resources/css/user/board.css'; |
|
11 |
+import '../resources/css/user/layout.css'; |
|
12 |
+import '../resources/css/user/main.css'; |
|
13 |
+import '../resources/css/user/sub.css'; |
|
14 |
+import '../resources/css/ckeditor.css'; |
|
15 |
+ |
|
7 | 16 |
async function initVueApp() { |
8 | 17 |
const vue = createApp(App) |
9 | 18 |
.use(Router) |
--- client/views/pages/user/PicHistoryInsert.vue
+++ client/views/pages/user/PicHistoryInsert.vue
... | ... | @@ -1,221 +1,174 @@ |
1 | 1 |
<template> |
2 |
- <div class="content"> |
|
3 |
- <div class="sub-title-area mb-30"> |
|
4 |
- <h2>사진 기록물</h2> |
|
5 |
- <div class="breadcrumb-list"> |
|
6 |
- <ul> |
|
7 |
- <li><img :src="homeicon" alt="Home Icon"> |
|
8 |
- <p>기록물</p> |
|
9 |
- </li> |
|
10 |
- <li><img :src="righticon" alt=""></li> |
|
11 |
- <li>사진 기록물</li> |
|
12 |
- </ul> |
|
13 |
- </div> |
|
14 |
- </div> |
|
15 |
- <form action="" class="insert-form mb-50"> |
|
16 |
- <dl> |
|
17 |
- <dd> |
|
18 |
- <label for="id" class="require">제목</label> |
|
19 |
- <div class="wfull"><input type="text" id="id" value="" placeholder="제목을 입력하세요."></div> |
|
20 |
- </dd> |
|
21 |
- <div class="hr"></div> |
|
22 |
- <dd> |
|
23 |
- <label for="year">생산연도</label> |
|
24 |
- <input type="text" id="year" value="" placeholder="생산연도를 입력하세요"> |
|
25 |
- |
|
26 |
- </dd> |
|
27 |
- <div class="hr"></div> |
|
28 |
- <dd> |
|
29 |
- <label for="address">주소</label> |
|
30 |
- <div class="wfull"><input type="text" id="address" value="" placeholder="주소를 입력하세요"></div> |
|
31 |
- |
|
32 |
- </dd> |
|
33 |
- <div class="hr"></div> |
|
34 |
- <dd> |
|
35 |
- <label for="text">내용</label> |
|
36 |
- <textarea name="" id=""></textarea> |
|
37 |
- |
|
38 |
- </dd> |
|
39 |
- <div class="hr"></div> |
|
40 |
- <dd> |
|
41 |
- <label for="category" class="flex align-center"> |
|
42 |
- <p>카테고리</p><button type="button" class="category-add" @click="openModal">추가하기</button> |
|
43 |
- </label> |
|
44 |
- <ul class="category"> |
|
45 |
- <li v-for="(category, index) in selectedCategories" :key="index" > |
|
46 |
- {{ category }} |
|
47 |
- <button type="button" class="cancel" @click="removeCategory(index)"><b>✕</b></button> |
|
48 |
- </li> |
|
49 |
- </ul> |
|
50 |
- |
|
51 |
- </dd> |
|
52 |
- <div class="hr"></div> |
|
53 |
- <dd> |
|
54 |
- <label for="file" class="require">파일</label> |
|
55 |
- <ul class="wfull"> |
|
56 |
- <li class="flex align-center"> |
|
57 |
- <p>파일첨부</p> |
|
58 |
- <div class="invalid-feedback"><img :src="erroricon" alt=""><span>첨부파일은 10건까지 등록 가능하며, 건당 최대 |
|
59 |
- 100MB를 초과할 수 없습니다.</span></div> |
|
60 |
- </li> |
|
61 |
- <li class="file-insert"> |
|
62 |
- <input type="file" id="fileInput" class="file-input" multiple @change="showFileNames"> |
|
63 |
- <label for="fileInput" class="file-label mb-20"> |
|
64 |
- <div class="flex-center align-center"><img :src="fileicon" alt=""> |
|
65 |
- <p>파일첨부하기</p> |
|
66 |
- </div> |
|
67 |
- <p>파일을 첨부하시려면 이 영역으로 파일을 끌고 오거나 클릭해주세요</p> |
|
68 |
- </label> |
|
69 |
- <p class="mb-10">파일목록</p> |
|
70 |
- <div id="fileNames" class="file-names"> |
|
71 |
- <span v-if="fileNames.length === 0">선택된 파일이 없습니다.</span> |
|
72 |
- <div v-for="(file, index) in fileNames" :key="index" class="flex-sp-bw mb-5 file-wrap"> |
|
73 |
- <div class="file-name"> |
|
74 |
- <!-- Corrected here: Use file.icon instead of fileicons.img --> |
|
75 |
- <img :src="file.icon" alt="fileicon"> |
|
76 |
- <p>{{ file.name }}</p> |
|
77 |
- </div> |
|
78 |
- <button type="button" class="cancel" @click="removeFile(index)"><b>✕</b></button> |
|
79 |
- </div> |
|
80 |
- </div> |
|
81 |
- </li> |
|
82 |
- |
|
83 |
- </ul> |
|
84 |
- |
|
85 |
- </dd> |
|
86 |
- </dl> |
|
87 |
- </form> |
|
88 |
- |
|
89 |
- <div class="btn-group flex-center"> |
|
90 |
- <button class="cancel">취소</button> |
|
91 |
- <button class="register">등록</button> |
|
92 |
- </div> |
|
93 |
- <div v-if="isModalOpen" class="modal-overlay" @click="closeModal"> |
|
94 |
- <div class="modal-content" @click.stop> |
|
95 |
- <div class="flex-sp-bw mb-20"> |
|
96 |
- <h2>카테고리 조회</h2> |
|
97 |
- <button @click="closeModal" class="closebtn">✕</button> |
|
2 |
+ <div class="content"> |
|
3 |
+ <div class="sub-title-area mb-30"> |
|
4 |
+ <h2>사진 기록물</h2> |
|
5 |
+ <div class="breadcrumb-list"> |
|
6 |
+ <ul> |
|
7 |
+ <li><img :src="homeicon" alt="Home Icon"> |
|
8 |
+ <p>기록물</p> |
|
9 |
+ </li> |
|
10 |
+ <li><img :src="righticon" alt=""></li> |
|
11 |
+ <li>사진 기록물</li> |
|
12 |
+ </ul> |
|
13 |
+ </div> |
|
14 |
+ </div> |
|
15 |
+ <form action="" class="insert-form mb-50"> |
|
16 |
+ <dl> |
|
17 |
+ <dd> |
|
18 |
+ <label for="id" class="require">제목</label> |
|
19 |
+ <div class="wfull"><input type="text" id="id" placeholder="제목을 입력하세요."></div> |
|
20 |
+ </dd> |
|
21 |
+ <div class="hr"></div> |
|
22 |
+ <dd> |
|
23 |
+ <label for="year">생산연도</label> |
|
24 |
+ <input type="text" id="year" placeholder="생산연도를 입력하세요"> |
|
25 |
+ </dd> |
|
26 |
+ <div class="hr"></div> |
|
27 |
+ <dd> |
|
28 |
+ <label for="address">주소</label> |
|
29 |
+ <div class="wfull"><input type="text" id="address" placeholder="주소를 입력하세요"></div> |
|
30 |
+ </dd> |
|
31 |
+ <div class="hr"></div> |
|
32 |
+ <dd> |
|
33 |
+ <label for="text">내용</label> |
|
34 |
+ <div class="wfull"> |
|
35 |
+ <EditorComponent :contents="insertDTO.cn" /> |
|
36 |
+ </div> |
|
37 |
+ </dd> |
|
38 |
+ <div class="hr"></div> |
|
39 |
+ <dd> |
|
40 |
+ <label for="category" class="flex align-center"> |
|
41 |
+ <p>카테고리</p><button type="button" class="category-add" @click="openModal">추가하기</button> |
|
42 |
+ </label> |
|
43 |
+ <ul class="category"> |
|
44 |
+ <li v-for="(category, index) in selectedCtgries" :key="index"> {{ category }} <button type="button" class="cancel" @click="removeCategory(index)"><b>✕</b></button> |
|
45 |
+ </li> |
|
46 |
+ </ul> |
|
47 |
+ </dd> |
|
48 |
+ <div class="hr"></div> |
|
49 |
+ <dd> |
|
50 |
+ <label for="file" class="require">파일</label> |
|
51 |
+ <ul class="wfull"> |
|
52 |
+ <li class="flex align-center"> |
|
53 |
+ <p>파일첨부</p> |
|
54 |
+ <div class="invalid-feedback"><img :src="erroricon" alt=""><span>첨부파일은 10건까지 등록 가능하며, 건당 최대 100MB를 초과할 수 없습니다.</span></div> |
|
55 |
+ </li> |
|
56 |
+ <li class="file-insert"> |
|
57 |
+ <input type="file" id="fileInput" class="file-input" multiple @change="showFileNames"> |
|
58 |
+ <label for="fileInput" class="file-label mb-20"> |
|
59 |
+ <div class="flex-center align-center"><img :src="fileicon" alt=""> |
|
60 |
+ <p>파일첨부하기</p> |
|
98 | 61 |
</div> |
99 |
- <div class="modal-search flex-center mb-20"> |
|
100 |
- <input type="text" placeholder="카테고리명을 입력하세요."> |
|
101 |
- <button class="search-btn"><img :src="searchicon" alt=""> |
|
102 |
- <p>검색</p> |
|
103 |
- </button> |
|
62 |
+ <p>파일을 첨부하시려면 이 영역으로 파일을 끌고 오거나 클릭해주세요</p> |
|
63 |
+ </label> |
|
64 |
+ <p class="mb-10">파일목록</p> |
|
65 |
+ <div id="fileNames" class="file-names"> |
|
66 |
+ <span v-if="fileNames.length === 0">선택된 파일이 없습니다.</span> |
|
67 |
+ <div v-for="(file, index) in fileNames" :key="index" class="flex-sp-bw mb-5 file-wrap"> |
|
68 |
+ <div class="file-name"> |
|
69 |
+ <!-- Corrected here: Use file.icon instead of fileicons.img --> |
|
70 |
+ <img :src="file.icon" alt="fileicon"> |
|
71 |
+ <p>{{ file.name }}</p> |
|
72 |
+ </div> |
|
73 |
+ <button type="button" class="cancel" @click="removeFile(index)"><b>✕</b></button> |
|
104 | 74 |
</div> |
105 |
- <table class="mb-10"> |
|
106 |
- <thead> |
|
107 |
- <tr> |
|
108 |
- <th>카테고리 항목</th> |
|
109 |
- <th>선택</th> |
|
110 |
- </tr> |
|
111 |
- </thead> |
|
112 |
- <tbody> |
|
113 |
- <tr v-for="item in items" :key="item.id"> |
|
114 |
- <!-- Category 칼럼 --> |
|
115 |
- <td> |
|
116 |
- {{ item.category }} |
|
117 |
- </td> |
|
118 |
- <!-- Checkbox 칼럼 --> |
|
119 |
- <td> |
|
120 |
- <input type="checkbox" v-model="item.selected" /> |
|
121 |
- </td> |
|
122 |
- </tr> |
|
123 |
- </tbody> |
|
124 |
- </table> |
|
125 |
- <div class="flex-end mb-30"><button class="register-b " @click="registerCategories">등록</button></div> |
|
126 |
- <div class="pagination"> |
|
127 |
- |
|
128 |
- <!-- Previous and Next Page Buttons --> |
|
129 |
- <button> |
|
130 |
- <DoubleLeftOutlined /> |
|
131 |
- </button> |
|
132 |
- <button @click="previousPage" :disabled="currentPage === 1"> |
|
133 |
- <LeftOutlined /> |
|
134 |
- </button> |
|
135 |
- <button class="page-number clicked">1</button> |
|
136 |
- <button @click="nextPage" :disabled="currentPage === totalPages"> |
|
137 |
- <RightOutlined /> |
|
138 |
- </button> |
|
139 |
- <button> |
|
140 |
- <DoubleRightOutlined /> |
|
141 |
- </button> |
|
142 |
- </div> |
|
143 |
- </div> |
|
144 |
- </div> |
|
145 |
- </div> |
|
146 |
- <div v-if="isModalOpen" class="modal-overlay" @click="closeModal"> |
|
147 |
- <div class="modal-content" @click.stop> |
|
148 |
- <h2>모달 제목</h2> |
|
149 |
- <p>모달의 내용이 여기에 들어갑니다.</p> |
|
150 |
- <button @click="closeModal">닫기</button> |
|
75 |
+ </div> |
|
76 |
+ </li> |
|
77 |
+ </ul> |
|
78 |
+ </dd> |
|
79 |
+ </dl> |
|
80 |
+ </form> |
|
81 |
+ <div class="btn-group flex-center"> |
|
82 |
+ <button class="cancel">취소</button> |
|
83 |
+ <button class="register">등록</button> |
|
151 | 84 |
</div> |
152 | 85 |
</div> |
86 |
+ <CategorySelectModal v-if="isModalOpen" :selectedCtgries="selectedCtgries" @toggleModal="fnToggleModal" /> |
|
153 | 87 |
</template> |
154 | 88 |
<script> |
155 | 89 |
import { DoubleLeftOutlined, LeftOutlined, RightOutlined, DoubleRightOutlined } from '@ant-design/icons-vue'; |
90 |
+// COMPONENT |
|
91 |
+import EditorComponent from '../../component/EditorComponent.vue'; |
|
92 |
+import CategorySelectModal from '../../component/modal/CategorySelectModal.vue'; |
|
156 | 93 |
|
157 | 94 |
export default { |
158 |
- components: { |
|
159 |
- DoubleLeftOutlined, |
|
160 |
- LeftOutlined, |
|
161 |
- RightOutlined, |
|
162 |
- DoubleRightOutlined, |
|
163 |
- }, |
|
95 |
+ components: { |
|
96 |
+ DoubleLeftOutlined, |
|
97 |
+ LeftOutlined, |
|
98 |
+ RightOutlined, |
|
99 |
+ DoubleRightOutlined, |
|
100 |
+ EditorComponent, CategorySelectModal, |
|
101 |
+ }, |
|
164 | 102 |
|
165 |
- data() { |
|
166 |
- return { |
|
167 |
- items: [ |
|
168 |
- { id: 1, category: '카테고리 1', selected: false }, |
|
169 |
- { id: 2, category: '카테고리 2', selected: false }, |
|
170 |
- { id: 3, category: '카테고리 3', selected: false }, |
|
171 |
- ], |
|
172 |
- isModalOpen: false, |
|
173 |
- // Define the image sources |
|
174 |
- homeicon: 'client/resources/images/icon/home.png', |
|
175 |
- erroricon: 'client/resources/images/icon/error.png', |
|
176 |
- righticon: 'client/resources/images/icon/right.png', |
|
177 |
- fileicon: 'client/resources/images/icon/file.png', |
|
178 |
- searchicon: 'client/resources/images/icon/search.png', |
|
179 |
- fileNames: [], |
|
180 |
- selectedCategories: [], |
|
181 |
- }; |
|
103 |
+ data() { |
|
104 |
+ return { |
|
105 |
+ // Define the image sources |
|
106 |
+ homeicon: 'client/resources/images/icon/home.png', |
|
107 |
+ erroricon: 'client/resources/images/icon/error.png', |
|
108 |
+ righticon: 'client/resources/images/icon/right.png', |
|
109 |
+ fileicon: 'client/resources/images/icon/file.png', |
|
110 |
+ searchicon: 'client/resources/images/icon/search.png', |
|
111 |
+ |
|
112 |
+ isModalOpen: false, |
|
113 |
+ |
|
114 |
+ items: [ |
|
115 |
+ { id: 1, category: '카테고리 1', selected: false }, |
|
116 |
+ { id: 2, category: '카테고리 2', selected: false }, |
|
117 |
+ { id: 3, category: '카테고리 3', selected: false }, |
|
118 |
+ ], |
|
119 |
+ fileNames: [], |
|
120 |
+ insertDTO: { |
|
121 |
+ sj: null, //제목 |
|
122 |
+ cn: null, //내용 |
|
123 |
+ adres: null, // 주소 |
|
124 |
+ prdctnYear: null, // 생산연도 |
|
125 |
+ ty: 'P', // 타입 ( P: 사진, V: 영상 ) |
|
126 |
+ multipartFiles: null, // 첨부파일 정보 |
|
127 |
+ ctgryIds: null, // 카테고리 정보 |
|
128 |
+ }, |
|
129 |
+ |
|
130 |
+ files: [], |
|
131 |
+ selectedCtgries: [], // 카테고리 목록 |
|
132 |
+ }; |
|
133 |
+ }, |
|
134 |
+ computed: { |
|
135 |
+ filteredItems() { |
|
136 |
+ // This could be modified to support filtering based on searchQuery |
|
137 |
+ return this.items.filter(item => |
|
138 |
+ item.category.includes(this.searchQuery) |
|
139 |
+ ); |
|
140 |
+ } |
|
141 |
+ }, |
|
142 |
+ created() { |
|
143 |
+ }, |
|
144 |
+ methods: { |
|
145 |
+ registerCategories() { |
|
146 |
+ // Add selected categories to the displayed list |
|
147 |
+ this.selectedCtgries = this.items |
|
148 |
+ .filter(item => item.selected) |
|
149 |
+ .map(item => item.category); |
|
150 |
+ this.closeModal(); // Close modal after registration |
|
182 | 151 |
}, |
183 |
- computed: { |
|
184 |
- filteredItems() { |
|
185 |
- // This could be modified to support filtering based on searchQuery |
|
186 |
- return this.items.filter(item => |
|
187 |
- item.category.includes(this.searchQuery) |
|
188 |
- ); |
|
189 |
- } |
|
152 |
+ removeCategory(index) { |
|
153 |
+ // Remove category from the list |
|
154 |
+ this.selectedCtgries.splice(index, 1); |
|
190 | 155 |
}, |
191 |
- methods: { |
|
192 |
- registerCategories() { |
|
193 |
- // Add selected categories to the displayed list |
|
194 |
- this.selectedCategories = this.items |
|
195 |
- .filter(item => item.selected) |
|
196 |
- .map(item => item.category); |
|
197 |
- this.closeModal(); // Close modal after registration |
|
198 |
- }, |
|
199 |
- removeCategory(index) { |
|
200 |
- // Remove category from the list |
|
201 |
- this.selectedCategories.splice(index, 1); |
|
202 |
- }, |
|
203 |
- searchCategories() { |
|
204 |
- // You can implement search logic if needed |
|
205 |
- }, |
|
206 |
- nextPage() { |
|
207 |
- if (this.currentPage < this.totalPages) { |
|
208 |
- this.currentPage++; |
|
209 |
- } |
|
210 |
- }, |
|
211 |
- previousPage() { |
|
212 |
- if (this.currentPage > 1) { |
|
213 |
- this.currentPage--; |
|
214 |
- } |
|
215 |
- }, |
|
216 |
- showFileNames(event) { |
|
217 |
- const files = event.target.files; |
|
218 |
- this.fileNames = []; // Clear previous file names |
|
156 |
+ searchCategories() { |
|
157 |
+ // You can implement search logic if needed |
|
158 |
+ }, |
|
159 |
+ nextPage() { |
|
160 |
+ if (this.currentPage < this.totalPages) { |
|
161 |
+ this.currentPage++; |
|
162 |
+ } |
|
163 |
+ }, |
|
164 |
+ previousPage() { |
|
165 |
+ if (this.currentPage > 1) { |
|
166 |
+ this.currentPage--; |
|
167 |
+ } |
|
168 |
+ }, |
|
169 |
+ showFileNames(event) { |
|
170 |
+ const files = event.target.files; |
|
171 |
+ this.fileNames = []; // Clear previous file names |
|
219 | 172 |
|
220 | 173 |
for (let i = 0; i < files.length; i++) { |
221 | 174 |
const file = files[i]; |
... | ... | @@ -253,7 +206,7 @@ |
253 | 206 |
// 모달 닫기 |
254 | 207 |
closeModal() { |
255 | 208 |
this.isModalOpen = false; |
256 |
- } |
|
209 |
+ }, |
|
257 | 210 |
} |
258 | 211 |
}; |
259 | 212 |
</script> |
--- client/views/pages/user/TotalSearch.vue
+++ client/views/pages/user/TotalSearch.vue
... | ... | @@ -123,7 +123,7 @@ |
123 | 123 |
<script> |
124 | 124 |
// 통합 검색 |
125 | 125 |
import { findAllDatas } from "../../../resources/api/main"; |
126 |
-import { findAllCategoryProc } from "../../../resources/api/category"; // 카테고리 목록 검색 |
|
126 |
+import { findAllByNullProc } from "../../../resources/api/category"; // 카테고리 목록 검색 |
|
127 | 127 |
|
128 | 128 |
export default { |
129 | 129 |
data() { |
... | ... | @@ -202,7 +202,7 @@ |
202 | 202 |
// 카테고리 목록 조회 |
203 | 203 |
async fnFindCategorys() { |
204 | 204 |
try { |
205 |
- const response = await findAllCategoryProc(); |
|
205 |
+ const response = await findAllByNullProc(); |
|
206 | 206 |
this.categorys = response.data.data.ctgry; |
207 | 207 |
} catch (error) { |
208 | 208 |
this.categorys = []; // 카테고리 목록 초기화 |
--- package.json
+++ package.json
... | ... | @@ -4,8 +4,10 @@ |
4 | 4 |
"@ant-design/icons-vue": "^7.0.1", |
5 | 5 |
"@babel/cli": "^7.22.10", |
6 | 6 |
"@babel/core": "^7.22.10", |
7 |
+ "@ckeditor/ckeditor5-vue": "^7.3.0", |
|
7 | 8 |
"axios": "^1.6.8", |
8 | 9 |
"babel-loader": "^9.1.3", |
10 |
+ "ckeditor5": "^44.3.0", |
|
9 | 11 |
"css-loader": "6.7.1", |
10 | 12 |
"express": "4.18.1", |
11 | 13 |
"express-http-proxy": "^2.0.0", |
... | ... | @@ -13,7 +15,7 @@ |
13 | 15 |
"fs": "0.0.1-security", |
14 | 16 |
"new-line": "^1.1.1", |
15 | 17 |
"swiper": "^11.2.5", |
16 |
- "vue": "3.2.40", |
|
18 |
+ "vue": "3.5.13", |
|
17 | 19 |
"vue-loader": "^17.2.2", |
18 | 20 |
"vue-router": "^4.3.2", |
19 | 21 |
"vue3-youtube": "^0.1.9", |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?