|
|
|
@ -18,8 +18,8 @@
|
|
|
|
|
id="toggleSidebarButton">打开/关闭侧边栏</el-button>
|
|
|
|
|
<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>
|
|
|
|
|
</el-sub-menu>
|
|
|
|
|
<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>
|
|
|
|
|
</el-sub-menu>
|
|
|
|
|
<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 @@
|
|
|
|
|
</el-menu>
|
|
|
|
|
<!-- 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"></el-input>
|
|
|
|
|
<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,158 +285,16 @@
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<style>
|
|
|
|
|
/*侧边栏样式*/
|
|
|
|
|
.sidebar {
|
|
|
|
|
position: fixed;
|
|
|
|
|
top: 0;
|
|
|
|
|
left: 0;
|
|
|
|
|
width: 350px;
|
|
|
|
|
height: 100%;
|
|
|
|
|
overflow-y: hidden;
|
|
|
|
|
transition: transform 0.3s ease;
|
|
|
|
|
transform: translateX(-100%);
|
|
|
|
|
background-color: #f9f9f9;
|
|
|
|
|
padding-left: 8px;
|
|
|
|
|
/* 调整内边距,使文字右移 */
|
|
|
|
|
padding-right: 8px;
|
|
|
|
|
/* 调整内边距,使文字右移 */
|
|
|
|
|
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: 10px;
|
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
margin: 5px;
|
|
|
|
|
transition: background-color 0.3s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.sidebar-menu .el-menu-item span:hover {
|
|
|
|
|
background-color: #e0e0e0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat-box {
|
|
|
|
|
max-height: 350px;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.preview {
|
|
|
|
|
margin-top: 20px;
|
|
|
|
|
/* 调整预览区与表单之间的距离 */
|
|
|
|
|
border: 1px solid #ccc;
|
|
|
|
|
/* 添加边框 */
|
|
|
|
|
padding: 10px;
|
|
|
|
|
/* 添加内边距 */
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
/* 添加圆角 */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form-item {
|
|
|
|
|
margin-bottom: 1px;
|
|
|
|
|
/* 减小表单项之间的距离 */
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
<script>
|
|
|
|
|
import {
|
|
|
|
|
DecoupledEditor,
|
|
|
|
|
// ClassicEditor,
|
|
|
|
|
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 { ElButton, ElInput, ElSelect, ElOption, ElForm, ElFormItem, ElMenu, ElMenuItem, ElColorPicker, ElSubMenu } from 'element-plus';
|
|
|
|
|
import '../public/sidebar.css';
|
|
|
|
|
import { ElButton, ElInput, ElSelect, ElOption, ElForm, ElFormItem, ElMenu, ElMenuItem, ElColorPicker, ElSubMenu, } from 'element-plus';
|
|
|
|
|
// import {getUserConfigFromBackend,saveData,getPageContent,getAndApplyUserStyles} from './components/utils';
|
|
|
|
|
import { getUserConfigFromBackend, saveData, getPageContent } from './components/utils';
|
|
|
|
|
import { Export2PDF, Export2Word, ToggleSideBar, Translation } from './components/plugins'
|
|
|
|
|
|
|
|
|
|
import { setConfig } from './components/plugins'
|
|
|
|
|
export default {
|
|
|
|
|
name: 'app',
|
|
|
|
|
data() {
|
|
|
|
@ -445,7 +304,6 @@ export default {
|
|
|
|
|
editor: DecoupledEditor,
|
|
|
|
|
// editor: ClassicEditor,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isSidebarOpen: false,// 侧边栏是否打开
|
|
|
|
|
isNavbarOpen: false,// 侧边栏是否打开
|
|
|
|
|
currentContent: '', // 当前侧边栏显示的表单
|
|
|
|
@ -469,251 +327,7 @@ export default {
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
mounted() {
|
|
|
|
|
// 获取用户的样式配置
|
|
|
|
|
const userConfig = getUserConfigFromBackend();
|
|
|
|
|
// 获取用户定义的样式并应用
|
|
|
|
|
// getAndApplyUserStyles();
|
|
|
|
|
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, // (in ms) 3minutes
|
|
|
|
|
save() {
|
|
|
|
|
// TODO save
|
|
|
|
|
return saveData(getPageContent());
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
translations: [translations]
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.config = setConfig();
|
|
|
|
|
this.isLayoutReady = true;
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
@ -735,13 +349,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() {
|
|
|
|
@ -760,8 +370,7 @@ export default {
|
|
|
|
|
cssClass += ` ${cssKey}: ${selectedStyles[key]};\n`;
|
|
|
|
|
}
|
|
|
|
|
cssClass += `}`;
|
|
|
|
|
|
|
|
|
|
console.log(cssClass); // 这里可以将cssClass发送到后端或其他处理逻辑
|
|
|
|
|
// TODO 保存样式到后端
|
|
|
|
|
alert(cssClass);
|
|
|
|
|
} else {
|
|
|
|
|
alert("类名不能为空!");
|
|
|
|
@ -776,20 +385,182 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 调用大模型API
|
|
|
|
|
sendMessageToAI() {
|
|
|
|
|
// 假设这里有一个API可以发送消息给AI并接收回复
|
|
|
|
|
this.messages.push({ text: this.aiInput });
|
|
|
|
|
this.aiInput = ''; // 清空输入框
|
|
|
|
|
// 模拟AI回复
|
|
|
|
|
// AI生成样式
|
|
|
|
|
displayMessage(text, sender) {
|
|
|
|
|
const messagesDiv = document.getElementById('messages');
|
|
|
|
|
|
|
|
|
|
// 移除 messages 中的按钮
|
|
|
|
|
const previousButtonsMessage = messagesDiv.querySelectorAll('.preview-buttons');
|
|
|
|
|
previousButtonsMessage.forEach(buttons => buttons.remove());
|
|
|
|
|
|
|
|
|
|
const messageDiv = document.createElement('div');
|
|
|
|
|
messageDiv.className = 'message';
|
|
|
|
|
// 使用 pre 元素来格式化显示 text
|
|
|
|
|
// 可以将css html代码内容新建一个pre set language 更好地展示输出
|
|
|
|
|
const preElement = document.createElement('pre');
|
|
|
|
|
preElement.textContent = text;
|
|
|
|
|
messageDiv.appendChild(preElement);
|
|
|
|
|
messagesDiv.appendChild(messageDiv);
|
|
|
|
|
|
|
|
|
|
if (sender === 'ai') {
|
|
|
|
|
// TODO 从返回文本中提取出css部分
|
|
|
|
|
preElement.textContent = `文心一言:\n` + preElement.textContent;
|
|
|
|
|
messageDiv.style.backgroundColor = '#bdc3c7';
|
|
|
|
|
|
|
|
|
|
// preview区域
|
|
|
|
|
const previewWrapper = document.createElement('div');
|
|
|
|
|
previewWrapper.style.border = '1px solid #ccc';
|
|
|
|
|
previewWrapper.style.display = 'flow-root';
|
|
|
|
|
// 添加一个标识 'preview' 的元素
|
|
|
|
|
const previewLabel = document.createElement('div');
|
|
|
|
|
previewLabel.textContent = 'preview';
|
|
|
|
|
previewWrapper.appendChild(previewLabel);
|
|
|
|
|
// 应用生成的样式到预览内容
|
|
|
|
|
const previewStyle = document.createElement('style');
|
|
|
|
|
// 对返回文本进行处理
|
|
|
|
|
// 提取其中css代码,以css开头,但不需要’css‘,最后一个}结尾
|
|
|
|
|
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;
|
|
|
|
|
// 提取element tag 和 class name
|
|
|
|
|
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';
|
|
|
|
|
// 创建 save 按钮
|
|
|
|
|
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 = () => {
|
|
|
|
|
// save
|
|
|
|
|
// TODO 将生成的样式保存到后端
|
|
|
|
|
// 确认样式的名称 这是用户选择使用style时看到的
|
|
|
|
|
// styleDefinition:[name: 'styleName',element: 'element',classes: [className]]
|
|
|
|
|
const styleName = prompt("请输入样式名称:");
|
|
|
|
|
// 构造styleDefiniton发送到后端
|
|
|
|
|
const styleDefinition = {
|
|
|
|
|
name: styleName,
|
|
|
|
|
element: previewElement.tagName,
|
|
|
|
|
classes: classNames
|
|
|
|
|
};
|
|
|
|
|
console.log(styleDefinition);
|
|
|
|
|
};
|
|
|
|
|
// 创建 clear 按钮
|
|
|
|
|
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 = () => {
|
|
|
|
|
// clear 清楚当前所有的message和按钮
|
|
|
|
|
const messagesDiv = document.getElementById('messages');
|
|
|
|
|
while (messagesDiv.firstChild) {
|
|
|
|
|
messagesDiv.removeChild(messagesDiv.firstChild);
|
|
|
|
|
}
|
|
|
|
|
// 清除添加的style
|
|
|
|
|
document.head.removeChild(previewStyle);
|
|
|
|
|
};
|
|
|
|
|
// 显示按钮
|
|
|
|
|
buttonsMessageDiv.appendChild(saveButton);
|
|
|
|
|
buttonsMessageDiv.appendChild(clearButton);
|
|
|
|
|
messagesDiv.appendChild(buttonsMessageDiv);
|
|
|
|
|
}
|
|
|
|
|
// messagesDiv.scrollTop = messagesDiv.scrollHeight;
|
|
|
|
|
},
|
|
|
|
|
sendMessage() {
|
|
|
|
|
const userInput = document.getElementById('userInput');
|
|
|
|
|
const messageText = userInput.value;
|
|
|
|
|
if (messageText.trim() === '') return;
|
|
|
|
|
|
|
|
|
|
// Display user's message
|
|
|
|
|
this.displayMessage(messageText, 'user');
|
|
|
|
|
|
|
|
|
|
// 向后端调用API并接受response
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
this.messages.push({ text: '这是来自AI的回复' });
|
|
|
|
|
// Simulate AI response
|
|
|
|
|
let formatedResponse = `css
|
|
|
|
|
.ck-content p.marquee {
|
|
|
|
|
display: inline-block;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
padding: 0.5em;
|
|
|
|
|
background: linear-gradient(90deg, #ff7e5f, #feb47b);
|
|
|
|
|
-webkit-background-clip: text;
|
|
|
|
|
-webkit-text-fill-color: transparent;
|
|
|
|
|
animation: marquee 10s 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: {
|
|
|
|
|
// 导入组件
|
|
|
|
|
ElButton, ElInput, ElSelect, ElOption, ElForm, ElFormItem, ElMenu, ElMenuItem, ElColorPicker, ElSubMenu
|
|
|
|
|
ElButton, ElInput, ElSelect, ElOption, ElForm, ElFormItem, ElMenu, ElMenuItem, ElColorPicker, ElSubMenu,
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|