Browse Source

change markdown ai

master
godo 6 months ago
parent
commit
f1642e0f14
  1. 1
      frontend/components.d.ts
  2. 3
      frontend/public/markdown/index.html
  3. 101
      frontend/public/markdown/katex/dialog.css
  4. 233
      frontend/public/markdown/scripts/dialog.css
  5. 67
      frontend/public/markdown/scripts/index.js
  6. 160
      frontend/public/markdown/scripts/modal.js

1
frontend/components.d.ts

@ -69,7 +69,6 @@ declare module 'vue' {
ElCarousel: typeof import('element-plus/es')['ElCarousel']
ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
ElCol: typeof import('element-plus/es')['ElCol']
ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
ElContainer: typeof import('element-plus/es')['ElContainer']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDrawer: typeof import('element-plus/es')['ElDrawer']

3
frontend/public/markdown/index.html

@ -33,7 +33,7 @@
<link rel="stylesheet" type="text/css" href="./dist/cherry-markdown.min.css">
<link rel="stylesheet" href="./katex/katex.min.css"
integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+" crossorigin="anonymous">
<link rel="stylesheet" href="./katex/dialog.css">
<link rel="stylesheet" href="./scripts/dialog.css">
</head>
<body>
@ -44,6 +44,7 @@
<!--<script src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.js" integrity="sha384-g7c+Jr9ZivxKLnZTDUhnkOnsh30B4H0rpLUpJ4jAIKs4fnJI+sEnkvrMWph2EDg4" crossorigin="anonymous"></script>-->
<script src="./dist/cherry-markdown.min.js"></script>
<script src="./scripts/pinyin/pinyin_dist.js"></script>
<script src="./scripts/modal.js"></script>
<script src="./scripts/index.js"></script>
</body>

101
frontend/public/markdown/katex/dialog.css

@ -1,101 +0,0 @@
.hide {
display: none !important;
}
#aiDialog {
position: absolute;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
z-index: 3;
}
.ai-markdown-dialog {
width: 40%;
min-width: 150px;
height: 300px;
float: right;
margin: 50px;
padding: 10px;
border-radius: 5px;
background-color: #ebf9fb;
box-shadow: 0px 5px 5px #e3dfdf;
text-align: center;
}
.ai-dialog-title {
width: 100%;
height: 40px;
line-height: 40px;
}
.ai-content-box {
position: relative;
}
.ai-dialog-content {
width: 100%;
height: 200px;
resize: none;
outline: none;
border-radius: 5px;
border-color: rgb(203, 203, 203);
box-sizing: border-box;
}
.ai-outline-choose {
width: 100%;
height: 200px;
padding: 20px;
margin: 10px 0;
background-color: #fff;
border: 1px solid #e0dfdf;
border-radius: 5px;
box-sizing: border-box;
}
.ai-outline-choose select,
.ai-outline-choose input {
display: inline-block;
width: 80%;
height: 30px;
padding: 0 10px;
margin: 10px 0;
appearance: none;
background-color: #fff;
background-image: none;
border-radius: 4px;
border: 1px solid #ebebeb;
box-sizing: border-box;
color: #606266;
line-height: 27px;
outline: none;
}
.ai-mask {
position: absolute;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 200px;
background-color: rgba(0, 0, 0, .1);
}
#aiLoader {
width: 32px;
height: 32px;
background-image: url('./loader.svg');
animation: rotate 2s linear infinite;
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.ai-dialog-button {
min-width: 50px;
border-color: rgb(181, 181, 247);
border-radius: 3px;
background-color: #fff;
}
.ai-dialog-button:hover {
background-color: #ceecfb;
}

233
frontend/public/markdown/scripts/dialog.css

@ -0,0 +1,233 @@
.hide {
display: none !important;
}
#aiDialog {
position: absolute;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
z-index: 3;
}
.ai-markdown-dialog {
width: 40%;
min-width: 150px;
height: 300px;
float: right;
margin: 50px;
padding: 10px;
border-radius: 5px;
background-color: #ffffff; /* 更改为白色 */
box-shadow: 0px 5px 5px #e3dfdf;
text-align: center;
}
.ai-dialog-title {
width: 100%;
height: 40px;
line-height: 40px;
color: #333333; /* 文字颜色调整为深色 */
}
.ai-content-box {
position: relative;
}
.ai-dialog-content {
width: 100%;
height: 200px;
resize: none;
outline: none;
border-radius: 5px;
border-color: #dcdcdc; /* 边框颜色调整为浅灰色 */
box-sizing: border-box;
}
.ai-outline-choose {
width: 100%;
height: 200px;
padding: 20px;
margin: 10px 0;
background-color: #ffffff; /* 背景颜色调整为白色 */
border: 1px solid #dcdcdc; /* 边框颜色调整为浅灰色 */
border-radius: 5px;
box-sizing: border-box;
}
.ai-outline-choose select,
.ai-outline-choose input {
display: inline-block;
width: 80%;
height: 30px;
padding: 0 10px;
margin: 10px 0;
appearance: none;
background-color: #ffffff; /* 背景颜色调整为白色 */
background-image: none;
border-radius: 4px;
border: 1px solid #dcdcdc; /* 边框颜色调整为浅灰色 */
box-sizing: border-box;
color: #333333; /* 文字颜色调整为深色 */
line-height: 27px;
outline: none;
}
.ai-mask {
position: absolute;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 200px;
background-color: rgba(255, 255, 255, 0.8); /* 背景颜色调整为半透明白色 */
}
#aiLoader {
width: 32px;
height: 32px;
background-image: url('./loader.svg');
animation: rotate 2s linear infinite;
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.ai-dialog-button {
min-width: 55px; /* 减小最小宽度 */
padding: 5px 8px; /* 减少内边距 */
margin:0 5px;
border: 1px solid #0078d4; /* 边框颜色调整为蓝色 */
border-radius: 4px; /* 边角稍微圆润一些 */
background: linear-gradient(145deg, #ffffff, #f0f8ff); /* 更亮的渐变背景 */
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); /* 更柔和的阴影 */
font-size: 14px; /* 调整字体大小 */
color: #333333; /* 文字颜色调整为深色 */
cursor: pointer;
transition: background 0.3s, box-shadow 0.2s, transform 0.2s; /* 平滑过渡效果 */
}
.ai-dialog-button:hover {
background: linear-gradient(145deg, #f0f8ff, #e6f3ff); /* 悬停时的更亮渐变背景 */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 略微加深阴影 */
transform: scale(1.02); /* 微微放大 */
}
.ai-dialog-button:active {
background: linear-gradient(145deg, #e6f3ff, #f0f8ff); /* 按下时的更亮渐变背景 */
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); /* 减轻阴影 */
transform: scale(0.98); /* 微微缩小 */
}
/* 模态对话框的基本样式 */
.modal {
position: fixed;
z-index: 9999;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(255, 255, 255, 0.8); /* 背景颜色调整为半透明白色 */
}
/* 模态对话框的内容区域 */
.modal-content {
background-color: #ffffff; /* 背景颜色调整为白色 */
margin: 15% auto;
padding: 20px;
border-radius: 5px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
width: 60%;
max-width: 500px;
border: none;
}
/* 关闭按钮 */
.modal-close {
color: #333333; /* 文字颜色调整为深色 */
float: right;
font-size: 28px;
font-weight: bold;
cursor: pointer;
transition: color 0.3s;
margin-top: -10px;
margin-right: -10px;
}
.modal-close:hover,
.modal-close:focus {
color: #000000; /* 鼠标悬停时文字颜色调整为黑色 */
text-decoration: none;
}
/* 按钮通用样式 */
.modal-button-group {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 20px;
/* 添加一定的顶部间距 */
}
.modal-button {
padding: 10px 30px;
margin: 0;
/* 移除外边距 */
cursor: pointer;
border: none;
border-radius: 8px;
/* 较大的圆角 */
font-size: 16px;
transition: background-color 0.3s, transform 0.2s, box-shadow 0.2s;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
/* 添加轻微的阴影 */
}
/* 确定按钮 */
.modal-button-ok {
border: 1px solid #0078d4; /* 边框颜色调整为蓝色 */
border-radius: 4px; /* 边角稍微圆润一些 */
background: linear-gradient(145deg, #ffffff, #f0f8ff); /* 更亮的渐变背景 */
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); /* 更柔和的阴影 */
font-size: 14px; /* 调整字体大小 */
color: #333333; /* 文字颜色调整为深色 */
cursor: pointer;
transition: background 0.3s, box-shadow 0.2s, transform 0.2s; /* 平滑过渡效果 */
}
.modal-button-ok:hover {
background: linear-gradient(145deg, #f0f8ff, #e6f3ff); /* 悬停时的更亮渐变背景 */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 略微加深阴影 */
transform: scale(1.02); /* 微微放大 */
}
/* 取消按钮 */
.modal-button-cancel {
background-color: #e53935; /* 背景颜色保持不变 */
color: #ffffff; /* 文字颜色调整为白色 */
}
.modal-button-cancel:hover {
background-color: #c62828; /* 鼠标悬停时背景颜色调整为深红色 */
transform: scale(1.05);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
/* 加深阴影 */
}
/* 标题样式 */
#modal-title {
font-size: 18px;
color: #333333; /* 文字颜色调整为深色 */
margin-bottom: 10px;
}
/* 内容样式 */
#modal-content {
font-size: 16px;
color: #333333; /* 文字颜色调整为深色 */
text-align: center;
justify-content: center;
align-items: center;
margin-bottom: 20px;
line-height: 1.5;
}

67
frontend/public/markdown/scripts/index.js

@ -1,4 +1,5 @@
var markdownTitle = ""
let aiSelected = ""
var CustomHookA = Cherry.createSyntaxHook('codeBlock', Cherry.constants.HOOKS_TYPE_LIST.PAR, {
makeHtml(str) {
console.warn('custom hook', 'hello');
@ -78,7 +79,7 @@ var exportDataHook = Cherry.createMenuHook('导出', {
// noIcon: true,
// name: 'PPTX',
// onclick: () => {
// }
// },
{
@ -137,7 +138,7 @@ class AiDialogClass {
creation_proofreading: {
title: '纠错',
btn: ['aiAdd', 'aiReplace', 'aiCancle']
},
},
creation_summarize: {
title: '总结',
btn: ['aiAdd', 'aiReplace', 'aiCancle']
@ -179,7 +180,7 @@ class AiDialogClass {
method: this.cheakAiContent
}
]
outline = {
outline = {
title: '',
content: '',
category: ''
@ -229,7 +230,7 @@ class AiDialogClass {
</div>
</div>`
this.container.appendChild(dialog)
// 绑定事件
// 绑定事件
const aiOptions = Array.from(this.container.querySelectorAll('.ai-dialog-button'))
aiOptions.forEach(item => {
item.addEventListener('click', () => {
@ -240,11 +241,11 @@ class AiDialogClass {
}
})
})
}
}
// 打开弹窗
openDialog(action) {
this.container.classList.remove('hide')
const title = 'AI - ' + this.actionArr[action].title
const title = 'AI - ' + this.actionArr[action].title
this.container.querySelector('.ai-dialog-title').innerText = title
this.addButton(action)
}
@ -257,7 +258,7 @@ class AiDialogClass {
this.container.querySelector('.ai-outline-choose').classList.add('hide')
this.container.querySelector('.ai-content-box').classList.remove('hide')
this.container.querySelector('.ai-mask').classList.remove('hide')
}
}
const buttonArr = Array.from(this.container.querySelectorAll('.ai-dialog-button'))
buttonArr.forEach(item => {
const actionType = item.getAttribute('data-type')
@ -298,7 +299,7 @@ class AiDialogClass {
// 追加
addAiContent(dialog, that) {
const content = dialog.querySelector('textarea').value
cherry.insert(content,false)
cherry.insert(content, false)
that.closeDialog(dialog)
}
// 替换
@ -316,13 +317,19 @@ class AiDialogClass {
}
that.outline.title = content.title
that.outline.category = content.category
if (content.title !== '' ) {
if (content.title !== '') {
window.parent.postMessage({
type: 'aiCreater',
data: content,
action: 'creation_leader'
}, '*')
that.openDialog('creation_builder')
}else{
showModal({
titleText: '提示',
contentText: "请输入标题",
showOk: true
});
}
}
// 生成文章
@ -347,49 +354,60 @@ class AiDialogClass {
}
}
const aiDialog = new AiDialogClass()
const aiTips = (action) => {
if (aiSelected == "") {
showModal({
titleText: '提示',
contentText: "请选择内容",
showOk: true
});
return;
}
aiDialog.sendRequest(action, aiSelected)
}
var aiEditMenu = Cherry.createMenuHook('AI', {
subMenuConfig: [
{
noIcon: true,
name: '优化',
onclick: () => {
aiDialog.sendRequest('creation_optimization', cherry.getMarkdown())
aiTips("creation_optimization")
}
},
{
noIcon: true,
name: '纠错',
onclick: () => {
aiDialog.sendRequest('creation_proofreading', cherry.getMarkdown())
aiTips("creation_proofreading")
}
},
{
noIcon: true,
name: '续写',
onclick: () => {
aiDialog.sendRequest('creation_continuation', cherry.getMarkdown())
aiTips("creation_continuation")
}
},
{
noIcon: true,
name: '翻译',
onclick: () => {
aiDialog.sendRequest('creation_translation', cherry.getMarkdown())
aiTips("creation_translation")
}
},
{
noIcon: true,
name: '总结',
onclick: () => {
aiDialog.sendRequest('creation_summarize', cherry.getMarkdown())
aiTips("creation_summarize")
}
},
{
noIcon: true,
name: '大纲',
onclick: () => {
// aiDialog.showDialog()
aiDialog.sendRequest('creation_leader', cherry.getMarkdown())
aiDialog.openDialog('creation_leader')
//aiDialog.sendRequest('creation_leader', cherry.getMarkdown())
}
}
]
@ -594,6 +612,12 @@ var basicConfig = {
console.log("onClickPreview", event);
},
},
event: {
selectionChange: ({ selections, lastSelections, info }) => {
aiSelected = lastSelections[0]
//console.log(aiSelected)
},
},
editor: {
id: 'cherry-text',
name: 'cherry-text',
@ -612,10 +636,7 @@ var basicConfig = {
};
var config = Object.assign({}, basicConfig, { value: "" });
window.cherry = new Cherry(config);
// fetch('./markdown/basic.md').then((response) => response.text()).then((value) => {
// var config = Object.assign({}, basicConfig, { value: value });
// window.cherry = new Cherry(config);
// });
const debouncedHandleKeyDown = (event) => {
// 确保仅在我们的按钮获得焦点时处理快捷键
@ -649,7 +670,7 @@ function decodeBase64(base64String) {
// 将二进制字符串转换为TypedArray
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
bytes[i] = binaryString.charCodeAt(i);
}
// 将TypedArray转换为字符串
@ -669,13 +690,13 @@ const eventHandler = (e) => {
return;
}
let content = data.content;
if (isBase64(content)) {
content = decodeBase64(content);
} else if (content instanceof ArrayBuffer) {
content = new TextDecoder('utf-8').decode(content);
}
cherry.setMarkdown(content);
}
if (eventData.type == 'aiReciver') {

160
frontend/public/markdown/scripts/modal.js

@ -0,0 +1,160 @@
let currentZIndex = 1000; // 初始 z-index 值
// 动态生成模态对话框的 HTML 结构
function createModal() {
const modal = document.createElement('div');
modal.className = 'modal';
modal.id = `modal-${currentZIndex}`; // 添加唯一 ID
const modalContent = document.createElement('div');
modalContent.className = 'modal-content';
const closeBtn = document.createElement('span');
closeBtn.className = 'modal-close';
closeBtn.innerHTML = '&times;';
const title = document.createElement('h2');
title.id = 'modal-title';
const contentContainer = document.createElement('div');
contentContainer.id = 'modal-content-container';
const btnGroup = document.createElement('div');
btnGroup.className = 'modal-button-group';
const okButton = document.createElement('button');
okButton.id = 'ok-button';
okButton.className = 'modal-button modal-button-ok';
okButton.textContent = '确定';
const cancelButton = document.createElement('button');
cancelButton.id = 'cancel-button';
cancelButton.className = 'modal-button modal-button-cancel';
cancelButton.textContent = '取消';
modalContent.appendChild(closeBtn);
modalContent.appendChild(title);
modalContent.appendChild(contentContainer);
btnGroup.appendChild(okButton);
btnGroup.appendChild(cancelButton);
modalContent.appendChild(btnGroup);
modal.appendChild(modalContent);
// 设置初始 z-index
modal.style.zIndex = currentZIndex;
return modal;
}
// 显示模态对话框
function showModal(options) {
const modal = createModal();
document.body.appendChild(modal);
const title = modal.querySelector('#modal-title');
const contentContainer = modal.querySelector('#modal-content-container');
const okButton = modal.querySelector('#ok-button');
const cancelButton = modal.querySelector('#cancel-button');
title.textContent = options.titleText || '标题';
// 清空旧的内容
while (contentContainer.firstChild) {
contentContainer.removeChild(contentContainer.firstChild);
}
// 插入内容或自定义 HTML
if (options.contentText) {
const content = document.createElement('p');
content.textContent = options.contentText;
contentContainer.appendChild(content);
} else if (options.contentHtml) {
contentContainer.innerHTML = options.contentHtml;
}
if (!options.showOk) {
okButton.style.display = "none";
} else {
okButton.style.display = "block";
}
if (!options.showCancel) {
cancelButton.style.display = "none";
} else {
cancelButton.style.display = "block";
}
// 关闭模态对话框
function closeModal() {
modal.remove();
}
// 当用户点击关闭按钮时
const closeBtn = modal.querySelector('.modal-close');
closeBtn.onclick = function() {
closeModal();
}
// 当用户点击确定按钮时
okButton.onclick = function() {
if (typeof options.onOkClick === 'function') {
const shouldClose = options.onOkClick();
if (shouldClose !== false) {
closeModal();
}
} else {
closeModal();
}
}
// 当用户点击取消按钮时
cancelButton.onclick = function() {
if (typeof options.onCancelClick === 'function') {
options.onCancelClick();
}
closeModal();
}
// 当用户点击模态对话框外部时
modal.onclick = function(event) {
if (event.target === modal) {
closeModal();
}
}
// 更新当前最高的 z-index
currentZIndex++;
}
// 示例: 调用 showModal 函数并传递确定和取消按钮的回调函数
// showModal({
// titleText: '提示',
// content: '你确定要继续吗?',
// showOk: true,
// showCancel: true,
// onOkClick: function() {
// alert('您点击了确定按钮');
// },
// onCancelClick: function() {
// alert('您点击了取消按钮');
// }
// });
// 创建第二个模态框
// setTimeout(function() {
// showModal({
// titleText: '回复',
// contentHtml: '<textarea id="reply" style="width:100%;height:200px;"></textarea>',
// showOk: true,
// onOkClick: function() {
// var reply = document.getElementById('reply').value;
// if (reply == '') {
// showModal({
// titleText: '提示',
// content: '回复内容不能为空',
// showOk: true
// })
// return false; // 阻止关闭模态框
// }
// }
// });
// }, 2000);
Loading…
Cancel
Save