SunEditor.vue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. <template>
  2. <div class="admin--suneditor-wrapper">
  3. <div ref="editorElement" class="admin--suneditor"></div>
  4. </div>
  5. </template>
  6. <script setup>
  7. import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
  8. import suneditor from 'suneditor'
  9. import 'suneditor/dist/css/suneditor.min.css'
  10. import plugins from 'suneditor/src/plugins'
  11. const props = defineProps({
  12. modelValue: {
  13. type: String,
  14. default: ''
  15. },
  16. height: {
  17. type: String,
  18. default: '400px'
  19. },
  20. placeholder: {
  21. type: String,
  22. default: '내용을 입력하세요...'
  23. }
  24. })
  25. const emit = defineEmits(['update:modelValue'])
  26. const editorElement = ref(null)
  27. let editorInstance = null
  28. onMounted(() => {
  29. if (editorElement.value) {
  30. editorInstance = suneditor.create(editorElement.value, {
  31. plugins: plugins,
  32. height: props.height,
  33. buttonList: [
  34. ['undo', 'redo'],
  35. ['font', 'fontSize', 'formatBlock'],
  36. ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'],
  37. ['fontColor', 'hiliteColor'],
  38. ['removeFormat'],
  39. ['outdent', 'indent'],
  40. ['align', 'horizontalRule', 'list', 'table'],
  41. ['link', 'image', 'video'],
  42. ['fullScreen', 'showBlocks', 'codeView'],
  43. ['preview', 'print']
  44. ],
  45. font: ['Arial', 'Courier New', 'Georgia', 'Tahoma', 'Trebuchet MS', 'Verdana', 'AudiType'],
  46. formats: ['p', 'div', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
  47. colorList: [
  48. '#ff0000', '#ff5e00', '#ffe400', '#abf200', '#00d8ff', '#0055ff', '#6600ff', '#ff00dd',
  49. '#000000', '#ffffff', '#888888', '#cccccc'
  50. ],
  51. imageResizing: true,
  52. imageHeightShow: true,
  53. imageWidth: '100%',
  54. imageUploadUrl: '/api/upload/image',
  55. placeholder: props.placeholder
  56. })
  57. // 초기값 설정
  58. if (props.modelValue) {
  59. editorInstance.setContents(props.modelValue)
  60. }
  61. // 내용 변경 이벤트
  62. editorInstance.onChange = (contents) => {
  63. emit('update:modelValue', contents)
  64. }
  65. }
  66. })
  67. // modelValue 변경 감지
  68. watch(() => props.modelValue, (newValue) => {
  69. if (editorInstance && editorInstance.getContents() !== newValue) {
  70. editorInstance.setContents(newValue || '')
  71. }
  72. })
  73. onBeforeUnmount(() => {
  74. if (editorInstance) {
  75. editorInstance.destroy()
  76. }
  77. })
  78. </script>
  79. <style scoped>
  80. .admin--suneditor-wrapper {
  81. width: 100%;
  82. }
  83. .admin--suneditor-wrapper :deep(.sun-editor) {
  84. background: var(--admin-bg-tertiary);
  85. border: 1px solid var(--admin-border-color);
  86. border-radius: 6px;
  87. }
  88. .admin--suneditor-wrapper :deep(.se-toolbar) {
  89. background: var(--admin-bg-secondary);
  90. border-bottom: 1px solid var(--admin-border-color);
  91. }
  92. .admin--suneditor-wrapper :deep(.se-btn) {
  93. color: var(--admin-text-secondary);
  94. }
  95. .admin--suneditor-wrapper :deep(.se-btn:hover) {
  96. background: var(--admin-bg-tertiary);
  97. color: var(--admin-text-primary);
  98. }
  99. .admin--suneditor-wrapper :deep(.se-wrapper) {
  100. background: var(--admin-bg-tertiary);
  101. color: var(--admin-text-primary);
  102. }
  103. .admin--suneditor-wrapper :deep(.se-wrapper-inner) {
  104. background: var(--admin-bg-tertiary);
  105. color: #ffffff;
  106. }
  107. .admin--suneditor-wrapper :deep(.se-wrapper-inner.se-wrapper-wysiwyg) {
  108. background: var(--admin-bg-tertiary);
  109. color: #ffffff !important;
  110. }
  111. /* 에디터 내부 모든 텍스트 요소 - 기본 흰색 */
  112. .admin--suneditor-wrapper :deep(.se-wrapper-inner p),
  113. .admin--suneditor-wrapper :deep(.se-wrapper-inner div),
  114. .admin--suneditor-wrapper :deep(.se-wrapper-inner span),
  115. .admin--suneditor-wrapper :deep(.se-wrapper-inner h1),
  116. .admin--suneditor-wrapper :deep(.se-wrapper-inner h2),
  117. .admin--suneditor-wrapper :deep(.se-wrapper-inner h3),
  118. .admin--suneditor-wrapper :deep(.se-wrapper-inner h4),
  119. .admin--suneditor-wrapper :deep(.se-wrapper-inner h5),
  120. .admin--suneditor-wrapper :deep(.se-wrapper-inner h6),
  121. .admin--suneditor-wrapper :deep(.se-wrapper-inner li),
  122. .admin--suneditor-wrapper :deep(.se-wrapper-inner ul),
  123. .admin--suneditor-wrapper :deep(.se-wrapper-inner ol),
  124. .admin--suneditor-wrapper :deep(.se-wrapper-inner blockquote),
  125. .admin--suneditor-wrapper :deep(.se-wrapper-inner pre),
  126. .admin--suneditor-wrapper :deep(.se-wrapper-inner a),
  127. .admin--suneditor-wrapper :deep(.se-wrapper-inner strong),
  128. .admin--suneditor-wrapper :deep(.se-wrapper-inner em),
  129. .admin--suneditor-wrapper :deep(.se-wrapper-inner code) {
  130. color: #ffffff;
  131. }
  132. .admin--suneditor-wrapper :deep(.se-placeholder) {
  133. color: var(--admin-text-muted) !important;
  134. }
  135. </style>