@ -18,8 +18,8 @@
id = "toggleSidebarButton" > 打开 / 关闭侧边栏 < / e l - b u t t o n >
< div class = "sidebar" : class = "{ 'active': isSidebarOpen }" >
<!-- 侧边栏内容 -- >
< el -menu class = "sidebar-menu" : class = "{ 'active': isNavbarOpen }" >
< el -sub -menu index = "1" >
< el -menu class = "sidebar-menu" : class = "{ 'active': isNavbarOpen }" :collapse ="isNavbarOpen" >
< el -sub -menu index = "1" class = "horizontal-sub-menu" >
< template # title > 智能助手 < / template >
< el -menu -item index = "1-1" @click ="showContent('polish')" > 润 色 < / el -menu -item >
< el -menu -item index = "1-2" @click ="showContent('rewrite')" > 改 写 < / el -menu -item >
@ -27,12 +27,12 @@
< el -menu -item index = "1-4" @click ="showContent('edit')" > 修 改 < / el -menu -item >
< el -menu -item index = "1-5" @click ="showContent('translate')" > 翻 译 < / el -menu -item >
< / e l - s u b - m e n u >
< el -sub -menu index = "2" >
< el -sub -menu index = "2" class = "horizontal-sub-menu" >
< template # title > 图文转换 < / template >
< el -menu -item index = "2-1" @click ="showContent('ocr')" > OCR < / el -menu -item >
< el -menu -item index = "2-2" @click ="showContent('mindmap')" > 脑 图 生 成 < / el -menu -item >
< / e l - s u b - m e n u >
< el -sub -menu index = "3" >
< el -sub -menu index = "3" class = "horizontal-sub-menu" >
< template # title > 样式生成 < / template >
< el -menu -item index = "3-1" @click ="showContent('manual')" > 手 动 生 成 < / el -menu -item >
< el -menu -item index = "3-2" @click ="showContent('ai')" > 对 话 生 成 < / el -menu -item >
@ -40,7 +40,6 @@
< / e l - m e n u >
<!-- Content Sections -- >
< div v-if ="currentContent" class="content-section" >
< el -button icon = "el-icon-menu" @click ="toggleNavBar()" > 导 航 < / el -button >
<!-- Dynamic content based on navigation selection -- >
< div v-if ="currentContent === 'polish'" > 润 色 内 容 < / div >
< div v-if ="currentContent === 'rewrite'" > 改 写 内 容 < / div >
@ -49,7 +48,7 @@
< div v-if ="currentContent === 'translate'" > 翻 译 内 容 < / div >
< div v-if ="currentContent === 'ocr'" > OCR 内 容 < / div >
< div v-if ="currentContent === 'mindmap'" > 脑 图 生 成 内 容 < / div >
< div v-if ="currentContent === 'manual'" class="p-3" >
< div v-if ="currentContent === 'manual'" >
<!-- 手动输入表单 -- >
< el -form @submit.prevent ="submitForm" >
< el -col :span ="30" >
@ -269,12 +268,14 @@
Aa Bb Cc 上下 左右 12345 Aa Bb Cc 上下 左右 12345 Aa Bb Cc 上下 左右 12345
< / div >
< / div >
< div v-if ="currentContent === 'ai'" class="p-3" >
< div v-if ="currentContent === 'ai'" >
<!-- AI对话框 -- >
< div class = "chat-box border rounded p-3" >
< p v-for ="message in messages" :key="message.id" class="mb-1" > {{ message.text }} < / p >
< el -input v -model = " aiInput " @keyup.enter ="sendMessageToAI" placeholder = "请输入消息"
class = "w-100" > < / e l - i n p u t >
< div class = "chat-container" >
< div class = "messages" id = "messages" > < / div >
< div class = "input-area" >
< input type = "text" id = "userInput" placeholder = "输入您的消息..." >
< button @click ="sendMessage()" > 发 送 < / button >
< / div >
< / div >
< / div >
< / div >
@ -284,157 +285,16 @@
< / div >
< / div >
< / template >
< style >
/*侧边栏样式*/
. sidebar {
position : fixed ;
top : 0 ;
left : 0 ;
width : 350 px ;
height : 100 % ;
overflow - y : hidden ;
transition : transform 0.3 s ease ;
transform : translateX ( - 100 % ) ;
background - color : # f9f9f9 ;
padding - left : 8 px ;
/* 调整内边距,使文字右移 */
padding - right : 8 px ;
/* 调整内边距,使文字右移 */
z - index : 9 ;
}
. sidebar . active {
transform : translateX ( 0 ) ;
}
. sidebar - menu {
display : none ;
flex - direction : column ;
justify - content : space - between ;
}
. sidebar - menu . active {
display : block ;
}
. sidebar - menu . el - menu - item {
flex : 1 ;
text - align : left ;
}
. sidebar - menu . el - menu - item span {
display : block ;
padding : 10 px ;
background - color : # f5f5f5 ;
border - radius : 4 px ;
margin : 5 px ;
transition : background - color 0.3 s ;
}
. sidebar - menu . el - menu - item span : hover {
background - color : # e0e0e0 ;
}
. chat - box {
max - height : 350 px ;
overflow - y : auto ;
}
. preview {
margin - top : 20 px ;
/* 调整预览区与表单之间的距离 */
border : 1 px solid # ccc ;
/* 添加边框 */
padding : 10 px ;
/* 添加内边距 */
border - radius : 4 px ;
/* 添加圆角 */
}
. form - item {
margin - bottom : 1 px ;
/* 减小表单项之间的距离 */
}
< / style >
< script >
import {
DecoupledEditor ,
/ / C l a s s i c E d i t o r ,
AccessibilityHelp ,
Alignment ,
Autoformat ,
AutoImage ,
AutoLink ,
Autosave ,
BalloonToolbar ,
Base64UploadAdapter ,
BlockQuote ,
Bold ,
Code ,
CodeBlock ,
Essentials ,
FindAndReplace ,
FontBackgroundColor ,
FontColor ,
FontFamily ,
FontSize ,
GeneralHtmlSupport ,
Heading ,
Highlight ,
HorizontalLine ,
ImageBlock ,
ImageCaption ,
ImageInline ,
ImageInsert ,
ImageInsertViaUrl ,
ImageResize ,
ImageStyle ,
ImageTextAlternative ,
ImageToolbar ,
ImageUpload ,
Indent ,
IndentBlock ,
Italic ,
Link ,
LinkImage ,
List ,
ListProperties ,
Markdown ,
MediaEmbed ,
Mention ,
PageBreak ,
Paragraph ,
PasteFromMarkdownExperimental ,
PasteFromOffice ,
RemoveFormat ,
SelectAll ,
SpecialCharacters ,
SpecialCharactersArrows ,
SpecialCharactersCurrency ,
SpecialCharactersEssentials ,
SpecialCharactersLatin ,
SpecialCharactersMathematical ,
SpecialCharactersText ,
Strikethrough ,
Style ,
Subscript ,
Superscript ,
Table ,
TableCaption ,
TableCellProperties ,
TableColumnResize ,
TableProperties ,
TableToolbar ,
TextTransformation ,
TodoList ,
Underline ,
Undo ,
} from 'ckeditor5' ;
import translations from 'ckeditor5/translations/zh-cn.js' ;
import 'ckeditor5/ckeditor5.css' ;
import '../public/sidebar.css' ;
import { ElButton , ElInput , ElSelect , ElOption , ElForm , ElFormItem , ElMenu , ElMenuItem , ElColorPicker , ElSubMenu } from 'element-plus' ;
import { setConfig } from '../components/plugins'
/ / i m p o r t { g e t U s e r C o n f i g F r o m B a c k e n d , s a v e D a t a , g e t P a g e C o n t e n t , g e t A n d A p p l y U s e r S t y l e s } f r o m ' . / c o m p o n e n t s / u t i l s ' ;
import { getUserConfigFromBackend , saveData , getPageContent } from '../components/utils' ;
import { Export2PDF , Export2Word , ToggleSideBar , Translation } from '../components/plugins' ;
import { useStore } from 'vuex' ;
import router from '../router/index.js' ;
@ -466,256 +326,11 @@ export default {
wordSpacing : ''
} ,
previewStyle : { } ,
aiInput : '' , / / A I 输 入 的 内 容
messages : [ ] , / / 聊 天 记 录
} ;
} ,
mounted ( ) {
/ / 获 取 用 户 的 样 式 配 置
const userConfig = getUserConfigFromBackend ( ) ;
/ / 获 取 用 户 定 义 的 样 式 并 应 用
/ / g e t A n d A p p l y U s e r S t y l e s ( ) ;
this . config = {
toolbar : {
items : [
'undo' ,
'redo' ,
'|' ,
'heading' ,
'style' ,
'|' ,
'fontSize' ,
'fontFamily' ,
'fontColor' ,
'fontBackgroundColor' ,
'|' ,
'bold' ,
'italic' ,
'underline' ,
'|' ,
'link' ,
'insertImage' ,
'insertTable' ,
'highlight' ,
'codeBlock' ,
'blockquote' ,
'|' ,
'alignment' ,
'bulletedList' ,
'numberedList' ,
'outdent' ,
'indent' ,
'|' , 'ExportToWord' , 'ExportToPDF' , 'translate' , 'SideBar'
] ,
shouldNotGroupWhenFull : true
} ,
plugins : [
AccessibilityHelp ,
Alignment ,
Autoformat ,
AutoImage ,
AutoLink ,
Autosave ,
BalloonToolbar ,
Base64UploadAdapter ,
BlockQuote ,
Bold ,
Code ,
CodeBlock ,
Essentials ,
FindAndReplace ,
FontBackgroundColor ,
FontColor ,
FontFamily ,
FontSize ,
GeneralHtmlSupport ,
Heading ,
Highlight ,
HorizontalLine ,
ImageBlock ,
ImageCaption ,
ImageInline ,
ImageInsert ,
ImageInsertViaUrl ,
ImageResize ,
ImageStyle ,
ImageTextAlternative ,
ImageToolbar ,
ImageUpload ,
Indent ,
IndentBlock ,
Italic ,
Link ,
LinkImage ,
List ,
ListProperties ,
Markdown ,
MediaEmbed ,
Mention ,
PageBreak ,
Paragraph ,
PasteFromMarkdownExperimental ,
PasteFromOffice ,
RemoveFormat ,
SelectAll ,
SpecialCharacters ,
SpecialCharactersArrows ,
SpecialCharactersCurrency ,
SpecialCharactersEssentials ,
SpecialCharactersLatin ,
SpecialCharactersMathematical ,
SpecialCharactersText ,
Strikethrough ,
Style ,
Subscript ,
Superscript ,
Table ,
TableCaption ,
TableCellProperties ,
TableColumnResize ,
TableProperties ,
TableToolbar ,
TextTransformation ,
TodoList ,
Underline ,
Undo ,
Export2Word , Translation , Export2PDF , ToggleSideBar
] ,
balloonToolbar : [ 'bold' , 'italic' , '|' , 'link' , 'insertImage' , '|' , 'bulletedList' , 'numberedList' ] ,
/ / 自 定 义 设 置 字 体
fontFamily : {
/ / 自 定 义 字 体
options : userConfig . fontFamily . options ,
/ / 启 用 对 所 有 字 体 名 称 的 支 持
supportAllValues : true ,
} ,
fontSize : {
/ / 五 号 , 小 四 , 四 号 , 小 三 , 三 号 , 小 二 , 二 号
options : userConfig . fontSize . options ,
supportAllValues : true
} ,
heading : {
options : [
{
model : 'paragraph' ,
title : 'Paragraph' ,
class : 'ck-heading_paragraph'
} ,
{
model : 'heading1' ,
view : 'h1' ,
title : 'Heading 1' ,
class : 'ck-heading_heading1'
} ,
{
model : 'heading2' ,
view : 'h2' ,
title : 'Heading 2' ,
class : 'ck-heading_heading2'
} ,
{
model : 'heading3' ,
view : 'h3' ,
title : 'Heading 3' ,
class : 'ck-heading_heading3'
} ,
{
model : 'heading4' ,
view : 'h4' ,
title : 'Heading 4' ,
class : 'ck-heading_heading4'
} ,
{
model : 'heading5' ,
view : 'h5' ,
title : 'Heading 5' ,
class : 'ck-heading_heading5'
} ,
{
model : 'heading6' ,
view : 'h6' ,
title : 'Heading 6' ,
class : 'ck-heading_heading6'
}
]
} ,
htmlSupport : {
allow : [
{
name : /^.*$/ ,
styles : true ,
attributes : true ,
classes : true
}
]
} ,
image : {
toolbar : [
'toggleImageCaption' ,
'imageTextAlternative' ,
'|' ,
'imageStyle:inline' ,
'imageStyle:wrapText' ,
'imageStyle:breakText' ,
'|' ,
'resizeImage'
]
} ,
initialData :
'' ,
language : 'zh-cn' ,
link : {
addTargetToExternalLinks : true ,
defaultProtocol : 'https://' ,
decorators : {
toggleDownloadable : {
mode : 'manual' ,
label : 'Downloadable' ,
attributes : {
download : 'file'
}
}
}
} ,
list : {
properties : {
styles : true ,
startIndex : true ,
reversed : true
}
} ,
mention : {
feeds : [
{
marker : '@' ,
feed : [
/* See: https://ckeditor.com/docs/ckeditor5/latest/features/mentions.html */
]
}
]
} ,
menuBar : {
isVisible : true ,
removeItems : [ 'help' ] ,
} ,
placeholder : 'Type or paste your content here!' ,
/ / 用 户 可 以 自 定 义 和 管 理 样 式
style : {
definitions : userConfig . style . definitions
} ,
table : {
contentToolbar : [ 'tableColumn' , 'tableRow' , 'mergeTableCells' , 'tableProperties' , 'tableCellProperties' ]
} ,
autosave : {
waitingTime : 180000 , / / ( i n m s ) 3 m i n u t e s
save ( ) {
/ / T O D O s a v e
return saveData ( getPageContent ( ) ) ;
}
} ,
translations : [ translations ]
} ;
this . config = setConfig ( ) ;
this . isLayoutReady = true ;
} ,
methods : {
@ -726,8 +341,8 @@ export default {
this . $refs . editorToolbarElement . appendChild ( editor . ui . view . toolbar . element ) ;
this . $refs . editorMenuBarElement . appendChild ( editor . ui . view . menuBarView . element ) ;
/ / 这 里 向 后 端 获 取 要 打 开 文 件 地 内 容
const pageContent = this . store . state . user . filecontent ;
/ / c o n s t p a g e C o n t e n t = ' < h 2 > C o n g r a t u l a t i o n s o n s e t t i n g u p C K E d i t o r 5 ! 🎉 < / h 2 > \ n < p > \ n Y o u \ ' v e s u c c e s s f u l l y c r e a t e d a C K E d i t o r 5 p r o j e c t . T h i s p o w e r f u l t e x t e d i t o r w i l l e n h a n c e y o u r a p p l i c a t i o n , e n a b l i n g r i c h t e x t e d i t i n g \ n c a p a b i l i t i e s t h a t a r e c u s t o m i z a b l e a n d e a s y t o u s e . \ n < / p > \ n < h 3 > W h a t \ ' s n e x t ? < / h 3 > \ n < o l > \ n < l i > \ n < s t r o n g > I n t e g r a t e i n t o y o u r a p p < / s t r o n g > : t i m e t o b r i n g t h e e d i t i n g i n t o y o u r a p p l i c a t i o n . T a k e t h e c o d e y o u c r e a t e d a n d a d d t o y o u r \ n a p p l i c a t i o n . \ n < / l i > \ n < l i > \ n < s t r o n g > E x p l o r e f e a t u r e s : < / s t r o n g > E x p e r i m e n t w i t h d i f f e r e n t p l u g i n s a n d t o o l b a r o p t i o n s t o d i s c o v e r w h a t w o r k s b e s t f o r y o u r n e e d s . \ n < / l i > \ n < l i > \ n < s t r o n g > C u s t o m i z e y o u r e d i t o r : < / s t r o n g > T a i l o r t h e e d i t o r \ ' s c o n f i g u r a t i o n t o m a t c h y o u r a p p l i c a t i o n \ ' s s t y l e a n d r e q u i r e m e n t s . O r e v e n \ n w r i t e y o u r p l u g i n ! \ n < / l i > \ n < / o l > \ n < p > \ n K e e p e x p e r i m e n t i n g , a n d d o n \ ' t h e s i t a t e t o p u s h t h e b o u n d a r i e s o f w h a t y o u c a n a c h i e v e w i t h C K E d i t o r 5 . Y o u r f e e d b a c k i s i n v a l u a b l e t o u s \ n a s w e s t r i v e t o i m p r o v e a n d e v o l v e . H a p p y e d i t i n g ! \ n < / p > \ n < h 3 > H e l p f u l r e s o u r c e s < / h 3 > \ n < u l > \ n < l i > 📝 < a h r e f = " h t t p s : / / o r d e r s . c k e d i t o r . c o m / t r i a l / p r e m i u m - f e a t u r e s " > T r i a l s i g n u p < / a > , < / l i > \ n < l i > 📕 < a h r e f = " h t t p s : / / c k e d i t o r . c o m / d o c s / c k e d i t o r 5 / l a t e s t / i n s t a l l a t i o n / i n d e x . h t m l " > D o c u m e n t a t i o n < / a > , < / l i > \ n < l i > ⭐ ️ < a h r e f = " h t t p s : / / g i t h u b . c o m / c k e d i t o r / c k e d i t o r 5 " > G i t H u b < / a > ( s t a r u s i f y o u c a n ! ) , < / l i > \ n < l i > 🏠 < a h r e f = " h t t p s : / / c k e d i t o r . c o m " > C K E d i t o r H o m e p a g e < / a > , < / l i > \ n < l i > 🧑 💻 < a h r e f = " h t t p s : / / c k e d i t o r . c o m / c k e d i t o r - 5 / d e m o / " > C K E d i t o r 5 D e m o s < / a > , < / l i > \ n < / u l > \ n < h 3 > N e e d h e l p ? < / h 3 > \ n < p > \ n S e e t h i s t e x t , b u t t h e e d i t o r i s n o t s t a r t i n g u p ? C h e c k t h e b r o w s e r \ ' s c o n s o l e f o r c l u e s a n d g u i d a n c e . I t m a y b e r e l a t e d t o a n i n c o r r e c t \ n l i c e n s e k e y i f y o u u s e p r e m i u m f e a t u r e s o r a n o t h e r f e a t u r e - r e l a t e d r e q u i r e m e n t . I f y o u c a n n o t m a k e i t w o r k , f i l e a G i t H u b i s s u e , a n d w e \ n w i l l h e l p a s s o o n a s p o s s i b l e ! \ n < / p > \ n ' ;
/ / c o n s t p a g e C o n t e n t = t h i s . s t o r e . s t a t e . u s e r . f i l e c o n t e n t ;
const pageContent = '<h2>Congratulations on setting up CKEditor 5! 🎉</h2>\n<p>\n You\'ve successfully created a CKEditor 5 project. This powerful text editor will enhance your application, enabling rich text editing\n capabilities that are customizable and easy to use.\n</p>\n<h3>What\'s next?</h3>\n<ol>\n <li>\n <strong>Integrate into your app</strong>: time to bring the editing into your application. Take the code you created and add to your\n application.\n </li>\n <li>\n <strong>Explore features:</strong> Experiment with different plugins and toolbar options to discover what works best for your needs.\n </li>\n <li>\n <strong>Customize your editor:</strong> Tailor the editor\'s configuration to match your application\'s style and requirements. Or even\n write your plugin!\n </li>\n</ol>\n<p>\n Keep experimenting, and don\'t hesitate to push the boundaries of what you can achieve with CKEditor 5. Your feedback is invaluable to us\n as we strive to improve and evolve. Happy editing!\n</p>\n<h3>Helpful resources</h3>\n<ul>\n <li>📝 <a href="https://orders.ckeditor.com/trial/premium-features">Trial sign up</a>,</li>\n <li>📕 <a href="https://ckeditor.com/docs/ckeditor5/latest/installation/index.html">Documentation</a>,</li>\n <li>⭐️ <a href="https://github.com/ckeditor/ckeditor5">GitHub</a> (star us if you can!),</li>\n <li>🏠 <a href="https://ckeditor.com">CKEditor Homepage</a>,</li>\n <li>🧑💻 <a href="https://ckeditor.com/ckeditor-5/demo/">CKEditor 5 Demos</a>,</li>\n</ul>\n<h3>Need help?</h3>\n<p>\n See this text, but the editor is not starting up? Check the browser\'s console for clues and guidance. It may be related to an incorrect\n license key if you use premium features or another feature-related requirement. If you cannot make it work, file a GitHub issue, and we\n will help as soon as possible!\n</p>\n' ;
/ / 打 开 已 有 文 本 就 将 p a g e C o n t e n t 替 换
/ / T O D O
editor . setData ( pageContent ) ;
@ -738,13 +353,9 @@ export default {
this . isSidebarOpen = ! this . isSidebarOpen ;
this . isNavbarOpen = this . isSidebarOpen ;
} ,
toggleNavBar ( ) {
this . isNavbarOpen = ! this . isNavbarOpen ;
} ,
/ / 展 示 表 单
showContent ( formType ) {
this . currentContent = formType ;
this . isNavbarOpen = false ;
} ,
/ / 保 存 用 户 定 义 样 式
submitForm ( ) {
@ -779,15 +390,176 @@ export default {
}
}
} ,
/ / 调 用 大 模 型 A P I
sendMessageToAI ( ) {
/ / 假 设 这 里 有 一 个 A P I 可 以 发 送 消 息 给 A I 并 接 收 回 复
this . messages . push ( { text : this . aiInput } ) ;
this . aiInput = '' ; / / 清 空 输 入 框
/ / 模 拟 A I 回 复
/ / A I 生 成 样 式
displayMessage ( text , sender ) {
const messagesDiv = document . getElementById ( 'messages' ) ;
/ / 移 除 m e s s a g e s 中 的 按 钮
const previousButtonsMessage = messagesDiv . querySelectorAll ( '.preview-buttons' ) ;
previousButtonsMessage . forEach ( buttons => buttons . remove ( ) ) ;
const messageDiv = document . createElement ( 'div' ) ;
messageDiv . className = 'message' ;
/ / 使 用 p r e 元 素 来 格 式 化 显 示 t e x t
/ / 可 以 将 c s s h t m l 代 码 内 容 新 建 一 个 p r e s e t l a n g u a g e 更 好 地 展 示 输 出
const preElement = document . createElement ( 'pre' ) ;
preElement . textContent = text ;
messageDiv . appendChild ( preElement ) ;
messagesDiv . appendChild ( messageDiv ) ;
if ( sender === 'ai' ) {
/ / T O D O 从 返 回 文 本 中 提 取 出 c s s 部 分
preElement . textContent = ` 文心一言: \ n ` + preElement . textContent ;
messageDiv . style . backgroundColor = '#bdc3c7' ;
/ / p r e v i e w 区 域
const previewWrapper = document . createElement ( 'div' ) ;
previewWrapper . style . border = '1px solid #ccc' ;
previewWrapper . style . display = 'flow-root' ;
/ / 添 加 一 个 标 识 ' p r e v i e w ' 的 元 素
const previewLabel = document . createElement ( 'div' ) ;
previewLabel . textContent = 'preview' ;
previewWrapper . appendChild ( previewLabel ) ;
/ / 应 用 生 成 的 样 式 到 预 览 内 容
const previewStyle = document . createElement ( 'style' ) ;
/ / 对 返 回 文 本 进 行 处 理
/ / 提 取 其 中 c s s 代 码 , 以 c s s 开 头 , 但 不 需 要 ’ c s s ‘ , 最 后 一 个 } 结 尾
const cssRegex = /css([\s\S]*)\}/ ;
const cssMatch = cssRegex . exec ( text ) ;
if ( cssMatch ) {
previewStyle . textContent = cssMatch [ 0 ] . replace ( 'css' , '' ) ;
} else {
previewStyle . textContent = text ;
}
previewStyle . textContent = previewStyle . textContent . replace ( /\.ck-content/g , '' ) ;
document . head . appendChild ( previewStyle ) ;
/ / 预 览 的 内 容
let previewElement ;
/ / 提 取 e l e m e n t t a g 和 c l a s s n a m e
const styleRegex = /\.ck-content\s+([a-z]+)\.([a-z-]+)\s*\{/g ;
let match ;
const classNames = [ ] ;
while ( ( match = styleRegex . exec ( text ) ) !== null ) {
if ( ! previewElement ) {
previewElement = document . createElement ( match [ 1 ] ) ;
previewElement . textContent = 'AaBbCcDdEeFf' ;
previewWrapper . appendChild ( previewElement ) ;
}
classNames . push ( match [ 2 ] ) ;
}
if ( previewElement ) {
previewElement . className = classNames . join ( ' ' ) ;
}
messagesDiv . appendChild ( previewWrapper ) ;
/ / 创 建 按 钮 容 器
const buttonsMessageDiv = document . createElement ( 'div' ) ;
buttonsMessageDiv . className = 'preview-buttons' ;
buttonsMessageDiv . style . display = 'flex' ;
buttonsMessageDiv . style . justifyContent = 'flex-end' ;
buttonsMessageDiv . style . marginTop = '10px' ;
/ / 创 建 s a v e 按 钮
const saveButton = document . createElement ( 'el-button' ) ;
saveButton . innerHTML = '<svg t="1731509644125" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6346" width="20" height="20"><path d="M512 1024C229.248 1024 0 794.752 0 512S229.248 0 512 0s512 229.248 512 512-229.248 512-512 512z m0-938.666667C276.352 85.333333 85.333333 276.352 85.333333 512s191.018667 426.666667 426.666667 426.666667 426.666667-191.018667 426.666667-426.666667S747.648 85.333333 512 85.333333z m-3.413333 611.541334a34.944 34.944 0 0 1-9.386667 16.682666 38.058667 38.058667 0 0 1-30.72 11.050667 38.954667 38.954667 0 0 1-40.106667-27.946667L308.053333 576.426667a38.4 38.4 0 0 1 54.186667-54.229334l93.013333 93.184 190.293334-337.365333a42.666667 42.666667 0 0 1 58.88-16.426667c20.608 12.714667 27.392 39.466667 15.36 60.458667l-211.2 374.826667z" fill="#000000" p-id="6347"></path></svg>' ;
saveButton . style . marginLeft = '10px' ;
saveButton . style . width = '40px' ;
saveButton . style . height = '40px' ;
saveButton . onclick = ( ) => {
/ / s a v e
/ / T O D O 将 生 成 的 样 式 保 存 到 后 端
/ / 确 认 样 式 的 名 称 这 是 用 户 选 择 使 用 s t y l e 时 看 到 的
/ / s t y l e D e f i n i t i o n : [ n a m e : ' s t y l e N a m e ' , e l e m e n t : ' e l e m e n t ' , c l a s s e s : [ c l a s s N a m e ] ]
const styleName = prompt ( "请输入样式名称:" ) ;
/ / 构 造 s t y l e D e f i n i t o n 发 送 到 后 端
const styleDefinition = {
name : styleName ,
element : previewElement . tagName ,
classes : classNames
} ;
console . log ( styleDefinition ) ;
} ;
/ / 创 建 c l e a r 按 钮
const clearButton = document . createElement ( 'el-button' ) ;
clearButton . innerHTML = '<svg t="1731509926355" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8154" width="20" height="20"><path d="M1011.43552 981.92384l-68.4032-394.40384h23.10144c18.5856 0 33.54624-14.97088 33.54624-33.55648V306.16576c0-18.5856-14.97088-33.55648-33.54624-33.55648H648.6528V37.71392c0-18.5856-14.97088-33.55648-33.55648-33.55648H408.59648c-18.5856 0-33.55648 14.97088-33.55648 33.55648v234.88512H57.5488c-18.5856 0-33.54624 14.97088-33.54624 33.55648v247.79776c0 18.5856 14.97088 33.55648 33.54624 33.55648h23.10144L12.24704 981.9136c-0.38912 1.9456-0.512 3.87072-0.512 5.6832 0 18.5856 14.97088 33.54624 33.55648 33.54624h933.10976c1.93536 0 3.88096-0.12288 5.6832-0.512 18.31936-3.08224 30.57664-20.51072 27.35104-38.7072zM114.33984 362.94656h351.03744V94.50496h92.928v268.4416h351.03744v134.22592H114.33984V362.94656zM718.336 930.816V729.48736c0-5.6832-4.64896-10.33216-10.32192-10.33216h-61.952c-5.67296 0-10.32192 4.64896-10.32192 10.33216V930.816H387.9424V729.48736c0-5.6832-4.64896-10.33216-10.32192-10.33216h-61.952c-5.67296 0-10.32192 4.64896-10.32192 10.33216V930.816H112.78336l58.20416-335.55456h681.5744L910.76608 930.816H718.336z m0 0" fill="#2C2C2C" p-id="8155"></path></svg>' ;
clearButton . style . marginLeft = '10px' ;
clearButton . style . width = '40px' ;
clearButton . style . height = '40px' ;
clearButton . onclick = ( ) => {
/ / c l e a r 清 楚 当 前 所 有 的 m e s s a g e 和 按 钮
const messagesDiv = document . getElementById ( 'messages' ) ;
while ( messagesDiv . firstChild ) {
messagesDiv . removeChild ( messagesDiv . firstChild ) ;
}
/ / 清 除 添 加 的 s t y l e
document . head . removeChild ( previewStyle ) ;
} ;
/ / 显 示 按 钮
buttonsMessageDiv . appendChild ( saveButton ) ;
buttonsMessageDiv . appendChild ( clearButton ) ;
messagesDiv . appendChild ( buttonsMessageDiv ) ;
}
/ / m e s s a g e s D i v . s c r o l l T o p = m e s s a g e s D i v . s c r o l l H e i g h t ;
} ,
sendMessage ( ) {
const userInput = document . getElementById ( 'userInput' ) ;
const messageText = userInput . value ;
if ( messageText . trim ( ) === '' ) return ;
/ / D i s p l a y u s e r ' s m e s s a g e
this . displayMessage ( messageText , 'user' ) ;
/ / 向 后 端 调 用 A P I 并 接 受 r e s p o n s e
setTimeout ( ( ) => {
this . messages . push ( { text : '这是来自AI的回复' } ) ;
/ / S i m u l a t e A I r e s p o n s e
let formatedResponse = ` css
. ck - content p . marquee {
display : inline - block ;
white - space : nowrap ;
overflow : hidden ;
box - sizing : border - box ;
padding : 0.5 em ;
background : linear - gradient ( 90 deg , # ff7e5f , # feb47b ) ;
- webkit - background - clip : text ;
- webkit - text - fill - color : transparent ;
animation : marquee 10 s linear infinite ;
position : relative ;
}
@ keyframes marquee {
0 % {
transform : translateX ( 100 % ) ;
}
100 % {
transform : translateX ( - 100 % ) ;
}
}
. ck - content p . marquee : : selection {
background : rgba ( 255 , 255 , 255 , 0.3 ) ; /* Ensure text is readable when selected */
}
/* Container to make sure the marquee stays within bounds */
. ck - content . marquee - container {
overflow : hidden ;
white - space : nowrap ;
width : 100 % ; /* Adjust as needed */
}
请注意 , 由于使用了 inline - block , 文本框的长和宽会根据内容自动调整 。 同时 , 由于动画使用了 translateX 而不是 text - indent , 因此可以正确地处理不同长度的文本 。 另外 , 我添加了一个 . marquee - container 类 , 用于确保滚动文本保持在指定区域内 ( 例如 , 不超出其父容器的边界 ) 。 您需要将 p . marquee 元素放置在一个具有 . marquee - container 类的元素内 , 以确保动画效果正确 。
示例 HTML 结构 :
html
< div class = "ck-content" >
< div class = "marquee-container" >
< p class = "marquee" > 这是一个带有流水灯效果的文本框 , 它的宽度和高度会根据内容自动调整 。 < / p >
< / div >
< / div >
` ;
this . displayMessage ( formatedResponse , 'ai' ) ;
} , 1000 ) ;
userInput . value = '' ;
} ,
} ,
components : {