Browse Source

add:markdown完善AI功能

master
prr 6 months ago
parent
commit
9b4e1bf5cc
  1. 68
      frontend/public/markdown/katex/dialog.css
  2. 1
      frontend/public/markdown/katex/loader.svg
  3. 212
      frontend/public/markdown/scripts/index.js

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

@ -1,18 +1,20 @@
.hide {
display: none;
display: none !important;
}
#aiDialog {
position: absolute;
top: 10%;
left: 10%;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
z-index: 3;
}
.ai-markdown-dialog {
width: 40%;
min-width: 150px;
height: 300px;
margin: 50px auto;
float: right;
margin: 50px;
padding: 10px;
border-radius: 5px;
background-color: #ebf9fb;
@ -24,6 +26,9 @@
height: 40px;
line-height: 40px;
}
.ai-content-box {
position: relative;
}
.ai-dialog-content {
width: 100%;
height: 200px;
@ -31,9 +36,62 @@
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 {
width: 50px;
min-width: 50px;
border-color: rgb(181, 181, 247);
border-radius: 3px;
background-color: #fff;

1
frontend/public/markdown/katex/loader.svg

@ -0,0 +1 @@
<svg t="1732761705789" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7310" width="32" height="32"><path d="M546.462897 266.292966c-73.410207 0-133.15531-59.727448-133.155311-133.137656C413.307586 59.762759 473.05269 0 546.462897 0c73.410207 0 133.12 59.727448 133.12 133.15531 0 73.410207-59.709793 133.137655-133.12 133.137656z m-283.453794 105.736827c-67.054345 0-121.626483-54.554483-121.626482-121.644138s54.572138-121.644138 121.626482-121.644138a121.767724 121.767724 0 0 1 121.608828 121.644138c0 67.054345-54.554483 121.644138-121.608828 121.644138zM142.547862 647.185655A107.343448 107.343448 0 0 1 35.310345 539.895172a107.343448 107.343448 0 0 1 107.237517-107.237517 107.343448 107.343448 0 0 1 107.219862 107.237517 107.343448 107.343448 0 0 1-107.219862 107.272828z m120.461241 272.595862a91.047724 91.047724 0 0 1-90.941793-90.959448 91.065379 91.065379 0 0 1 90.924138-90.941793 91.065379 91.065379 0 0 1 90.941793 90.941793c0 50.14069-40.783448 90.959448-90.924138 90.959448zM546.462897 1024a79.518897 79.518897 0 0 1-79.448276-79.448276c0-43.820138 35.645793-79.448276 79.448276-79.448276a79.518897 79.518897 0 0 1 79.43062 79.448276c0 43.820138-35.628138 79.448276-79.448276 79.448276z m287.744-134.285241a64.194207 64.194207 0 0 1-64.123587-64.123587 64.194207 64.194207 0 0 1 64.123587-64.123586 64.194207 64.194207 0 0 1 64.123586 64.123586 64.194207 64.194207 0 0 1-64.123586 64.123587z m117.848275-296.695173a52.683034 52.683034 0 0 1-52.612413-52.612414 52.683034 52.683034 0 0 1 52.612413-52.630069 52.70069 52.70069 0 0 1 52.630069 52.612414 52.718345 52.718345 0 0 1-52.630069 52.630069z m-158.667034-338.696827a40.818759 40.818759 0 1 0 81.655172 0.017655 40.818759 40.818759 0 0 0-81.655172 0z" fill="#76c9f5" p-id="7311"></path></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

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

@ -114,13 +114,38 @@ var exportDataHook = Cherry.createMenuHook('导出', {
class AiDialogClass {
actionArr = {
creation_leader: "生成大纲",
creation_builder: "根据主题和提纲进行撰写",
creation_continuation: "续写",
creation_optimization: "优化",
creation_proofreading: "纠错",
creation_summarize: "总结",
creation_translation: "翻译"
creation_leader: {
title: '文章选择',
btn: ['aiCancle', 'aiOutline']
},
creation_builder: {
title: '大纲',
btn: ['aiAdd', 'aiReplace', 'aiCancle', 'aiArticle']
},
article: {
title: '文章',
btn: ['aiAdd', 'aiReplace', 'aiCancle', 'checkOutline']
},
creation_continuation: {
title: '续写',
btn: ['aiAdd', 'aiReplace', 'aiCancle']
},
creation_optimization: {
title: '优化',
btn: ['aiAdd', 'aiReplace', 'aiCancle']
},
creation_proofreading: {
title: '纠错',
btn: ['aiAdd', 'aiReplace', 'aiCancle']
},
creation_summarize: {
title: '总结',
btn: ['aiAdd', 'aiReplace', 'aiCancle']
},
creation_translation: {
title: '翻译',
btn: ['aiAdd', 'aiReplace', 'aiCancle']
}
}
buttons = [
{
@ -148,7 +173,17 @@ class AiDialogClass {
action: 'aiArticle',
method: this.createAiArticle
},
{
title: '查看大纲',
action: 'checkOutline',
method: this.cheakAiContent
}
]
outline = {
title: '',
content: '',
category: ''
}
constructor() {
this.container = document.querySelector('#aiDialog')
this.createDialog()
@ -159,18 +194,37 @@ class AiDialogClass {
dialog.innerHTML = `
<div class="ai-markdown-dialog" style="padding: 0px 15px;">
<div class="ai-dialog-title">${this.action}</div>
<textarea class="ai-dialog-content" readonly></textarea>
<div class="button-box">
<button class="ai-dialog-button" data-type="aiAdd">追加</button>
<button class="ai-dialog-button" data-type="aiReplace">替换</button>
<button class="ai-dialog-button" data-type="aiCancle">取消</button>
<div class="ai-content-box">
<div class="ai-mask"><i id="aiLoader"></i></div>
<textarea class="ai-dialog-content" ></textarea>
</div>
<div class="button-box hide">
<button class="ai-dialog-button" data-type="aiReplace">生成大纲</button>
<button class="ai-dialog-button" data-type="aiCancle">取消</button>
<div class="ai-outline-choose hide">
<div>
<label for="">标题</label>
<input id="aiTitle" type="text" placeholder="请输入标题">
</div>
<div>
<label for="">分类</label>
<select name="articleClassification" id="aiSelect">
<option value="论文">论文</option>
<option value="合同">合同</option>
<option value="项目">项目</option>
<option value="投标">投标</option>
<option value="招标">招标</option>
<option value="散文">散文</option>
<option value="产品说明">产品说明</option>
<option value="销售计划">销售计划</option>
<option value="年度计划">年度计划</option>
<option value="战略规划">战略规划</option>
</select>
</div>
</div>
<div class="button-box hide">
<div class="button-box">
<button class="ai-dialog-button" data-type="aiOutline">生成大纲</button>
<button class="ai-dialog-button" id="checkOutline" data-type="checkOutline">修改大纲</button>
<button class="ai-dialog-button" data-type="aiArticle">生成文章</button>
<button class="ai-dialog-button" data-type="aiAdd">追加</button>
<button class="ai-dialog-button" data-type="aiReplace">替换</button>
<button class="ai-dialog-button" data-type="aiCancle">取消</button>
</div>
</div>`
@ -182,70 +236,114 @@ class AiDialogClass {
const actionType = item.getAttribute('data-type')
const btn = this.buttons.find(item => item.action == actionType)
if (btn && btn.method) {
btn.method(this.container)
btn.method(this.container, this)
}
})
})
}
// 打开弹窗
openDialog(action) {
this.container.classList.remove('hide')
const title = 'AI - ' + this.actionArr[action].title
this.container.querySelector('.ai-dialog-title').innerText = title
this.addButton(action)
}
// 添加不同按钮
// 根据不同选择,展示不同弹窗
addButton(action) {
let pos = 0
action == '大纲' ? pos = 1 : pos = 0
const btnArr = Array.from(this.container.querySelectorAll('.button-box'))
for (let i = 0; i < btnArr.length; i++) {
if (i == pos) {
btnArr[i].classList.remove('hide')
}else {
btnArr[i].classList.add('hide')
if (action == 'creation_leader') {
this.container.querySelector('.ai-outline-choose').classList.remove('hide')
this.container.querySelector('.ai-content-box').classList.add('hide')
} else {
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')
if (this.actionArr[action].btn.indexOf(actionType) !== -1) {
item.classList.remove('hide')
} else {
item.classList.add('hide')
}
}
})
}
// 点击不同按钮生成不同弹窗
showDialog(action, content) {
// 将内容放入textarea中
putInTextarea(action, content) {
// this.sendRequest(action,content)
this.container.querySelector('textarea').value = content
this.addButton(action)
this.container.querySelector('.ai-mask').classList.add('hide')
}
// 发送请求
sendRequest(action, data) {
let title = 'ai助手'
Object.keys(this.actionArr).forEach(item => {
if (item == action) {
title = 'AI' + this.actionArr[item]
}
})
this.container.querySelector('.ai-dialog-title').innerText = title
window.parent.postMessage({
type: 'aiCreater',
data,
action
}, '*')
this.container.classList.remove('hide')
if (action !== 'creation_leader') {
window.parent.postMessage({
type: 'aiCreater',
data,
action
}, '*')
}
this.openDialog(action)
}
// 关闭弹窗
closeDialog(dialog) {
dialog.querySelector('textarea').value = ''
this.outline = {
title: '',
content: '',
category: ''
}
dialog?.classList.add('hide')
}
// 追加
addAiContent(dialog) {
addAiContent(dialog, that) {
const content = dialog.querySelector('textarea').value
// cherry.insert(content,false)
cherry.setMarkdown(content)
// this.closeDialog(dialog)
cherry.insert(content,false)
that.closeDialog(dialog)
}
// 替换
replaceAiContent() {
console.log('替换');
replaceAiContent(dialog, that) {
const content = dialog.querySelector('textarea').value
cherry.setMarkdown(content)
that.closeDialog(dialog)
}
// 生成大纲
createAiOutline() {
console.log('生成大纲');
createAiOutline(dialog, that) {
that.addButton('creation_leader')
const content = {
title: dialog.querySelector('#aiTitle').value,
category: dialog.querySelector('#aiSelect').value
}
that.outline.title = content.title
that.outline.category = content.category
if (content.title !== '' ) {
window.parent.postMessage({
type: 'aiCreater',
data: content,
action: 'creation_leader'
}, '*')
that.openDialog('creation_builder')
}
}
// 生成文章
createAiArticle() {
console.log('生成文章');
createAiArticle(dialog, that) {
const data = {
outline: dialog.querySelector('textarea').value,
title: that.outline.title || 'AI - 文章'
}
that.outline.content = data.outline
window.parent.postMessage({
type: 'aiCreater',
data,
action: 'creation_builder'
}, '*')
that.openDialog('article')
}
//查看大纲
cheakAiContent(dialog, that) {
that.openDialog('creation_builder')
dialog.querySelector('textarea').value = that.outline.content
dialog.querySelector('.ai-mask').classList.add('hide')
}
}
const aiDialog = new AiDialogClass()
@ -255,7 +353,6 @@ var aiEditMenu = Cherry.createMenuHook('AI', {
noIcon: true,
name: '优化',
onclick: () => {
console.log(' AI优化', cherry.getMarkdown());
aiDialog.sendRequest('creation_optimization', cherry.getMarkdown())
}
},
@ -291,6 +388,7 @@ var aiEditMenu = Cherry.createMenuHook('AI', {
noIcon: true,
name: '大纲',
onclick: () => {
// aiDialog.showDialog()
aiDialog.sendRequest('creation_leader', cherry.getMarkdown())
}
}
@ -581,7 +679,7 @@ const eventHandler = (e) => {
cherry.setMarkdown(content);
}
if (eventData.type == 'aiReciver') {
aiDialog.showDialog(eventData.action, eventData.data)
aiDialog.putInTextarea(eventData.action, eventData.data)
}
}
window.addEventListener('load', () => {

Loading…
Cancel
Save