chore: 重写初始提交(清空历史,整理后全量提交)
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
|
||||
<link rel="stylesheet" href="./../../themes/default/dialog.css?7dab4ea0">
|
||||
<script type="text/javascript" src="../internal.js?df5a6b9e"></script>
|
||||
<style type="text/css">
|
||||
[v-cloak] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
width: 620px;
|
||||
padding: 10px;
|
||||
height: 399px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
font-size: 13px;
|
||||
}
|
||||
.wrapper .input::placeholder{
|
||||
color:#999;
|
||||
}
|
||||
|
||||
.ai-operate {
|
||||
display: block;
|
||||
min-width: 8em;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
line-height: 30px;
|
||||
background: var(--edui-color-border);
|
||||
color: #111;
|
||||
border-radius: 15px;
|
||||
padding: 0 10px;
|
||||
margin: 5px 5px 0 0;
|
||||
}
|
||||
|
||||
.ai-operate:hover {
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, .1);
|
||||
}
|
||||
|
||||
.btn.primary:hover {
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, .2);
|
||||
}
|
||||
|
||||
.close:hover {
|
||||
color: red !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper" id="app" v-cloak>
|
||||
|
||||
<div>
|
||||
<div v-if="selectText"
|
||||
style="line-height:30px;padding:0 10px;border-radius:5px;margin-bottom:10px;display:inline-flex;align-items:center;">
|
||||
<div style="margin-right:5px;">
|
||||
<i class="edui-iconfont edui-icon-outline" style="font-size:18px;"></i>
|
||||
</div>
|
||||
<div style="text-overflow:ellipsis;white-space:nowrap;overflow:hidden;max-width:550px;">
|
||||
{{ selectText }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex" style="padding: 5px; border-radius: 30px; box-shadow: 0 0 10px #CCC;">
|
||||
<div class="flex-grow">
|
||||
<input type="text" v-model="inputText"
|
||||
class="input"
|
||||
style="width:540px;border-color:transparent;font-size:14px;"
|
||||
placeholder="告诉 AI 下一步应该如何?比如:帮我翻译成英语"/>
|
||||
</div>
|
||||
<div class="flex-shrink-0" style="width:32px;padding-right:5px;">
|
||||
<a href="javascript:;" class="btn primary"
|
||||
@click="doSubmit"
|
||||
style="width:30px;text-align:center;padding:0;border-radius:50%;">
|
||||
<i v-if="loading" class="edui-iconfont edui-icon-refresh"
|
||||
style="display:inline-block;animation:spin 2s linear infinite;"></i>
|
||||
<i v-else class="edui-iconfont edui-icon-right-direction"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="resultHtml || resultError"
|
||||
style="border-top:1px solid #F2F2F2;margin-top:10px;padding-top:10px;">
|
||||
<div v-if="resultError"
|
||||
style="color:red;background:rgba(255,0,0,0.1);margin-bottom:10px;padding:10px;border-radius:10px;">
|
||||
{{ resultError }}
|
||||
</div>
|
||||
<div class="flex flex-items-center" style="height:30px;">
|
||||
<div class="flex-grow">
|
||||
<i class="edui-iconfont edui-icon-robot" style="font-size:16px;"></i>
|
||||
以下为生成的结果
|
||||
</div>
|
||||
<div>
|
||||
<a v-if="!loading" @click="doInsert" href="javascript:;" class="btn sm">
|
||||
<i class="edui-iconfont edui-icon-page-break"></i>
|
||||
插入
|
||||
</a>
|
||||
<a v-if="!loading&&selectText" @click="doReplace" href="javascript:;" class="btn sm">
|
||||
<i class="edui-iconfont edui-icon-eraser"></i>
|
||||
替换
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="margin-top:10px;background:rgba(0,0,0,0.03);padding:10px;border-radius:10px;overflow:auto;"
|
||||
:style="{height:resultHeight}"
|
||||
>
|
||||
<div class="ub-html" v-html="resultHtml"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else
|
||||
style="border-top:1px solid #F2F2F2;margin-top:10px;padding-top:10px;">
|
||||
<div v-if="functions.length" style="color:#999;">
|
||||
<i class="edui-iconfont edui-icon-bell" style="font-size:16px;"></i>
|
||||
提示:您可以在上面输入文字生成内容 或 选择下方的操作
|
||||
</div>
|
||||
<div v-else style="color:#999;">
|
||||
<i class="edui-iconfont edui-icon-bell" style="font-size:16px;"></i>
|
||||
提示:您可以在上面输入文字生成内容
|
||||
</div>
|
||||
<div style="padding-top:10px;display:flex;">
|
||||
<a href="javascript:;" v-for="f in functions"
|
||||
@click="doSubmitFunction(f)"
|
||||
class="ai-operate">
|
||||
<span v-html="f.text"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script src="../../third-party/vue.js?1f65e021"></script>
|
||||
<script src="../../third-party/showdown.js?d5372104"></script>
|
||||
<script src="../../third-party/jquery-1.10.2.js?628072e7"></script>
|
||||
<script type="text/javascript" src="../../third-party/clipboard/clipboard.js?555edf0a"></script>
|
||||
<script type="text/javascript" src="./ai.js?eb799e7f"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
var aiConfig=editor.getOpt("ai");var aiFunctions=editor.getOpt("aiFunctions");var isMultiLine=function(text){return text.indexOf("\n")!==-1};var fetchStream=function(url,option,onStream,onFinish){fetch(url,Object.assign({method:"POST"},option)).then(response=>{if(!response.ok){onFinish({code:-1,msg:`HTTP error! status: ${response.status}`});return}const reader=response.body.getReader();const decoder=new TextDecoder("utf-8");let buffer="";const textList=[];function processChunk(chunk){buffer+=decoder.decode(chunk,{stream:true});const lines=buffer.split("\n");for(let line of lines){line=line.trim();if(line.startsWith("data:")){const jsonStr=line.replace("data:","").trim();if(jsonStr==="[DONE]"){onFinish({code:0,msg:"ok",data:{text:textList.join("")}});return}try{let text=null;const data=JSON.parse(jsonStr);if(data.choices&&data.choices.length>0&&data.choices[0].delta){text=data.choices[0].delta.content}else if(data.type){if(data.type==="error"){onFinish({code:-1,msg:data.data});return}else if(data.type==="end"){onFinish({code:0,msg:"ok",data:{text:textList.join("")}});return}else if(data.type==="data"){text=data.data}}if(text!==null){textList.push(text);onStream({code:0,msg:"ok",data:{text:text}})}else{onFinish({code:-1,msg:"No text found!"});console.log("data:",data)}}catch(e){onFinish({code:-1,msg:"JSON parse error!"+e})}}}buffer=lines.pop()||""}function read(){reader.read().then(({done,value})=>{if(done){if(buffer)processChunk(new Uint8Array);return}processChunk(value);read()}).catch(error=>{onFinish({code:-1,msg:"Stream error!"+error})})}read()}).catch(error=>{onFinish({code:-1,msg:"Request error!"+error})})};var openAiCompletion=function(url,param,option){option=Object.assign({body:null},option);if(!option.body){option.body={model:aiConfig.driverConfig.model,messages:[{role:"user",content:param.promptText}],stream:true}}fetchStream(url,{headers:{Authorization:`Bearer ${aiConfig.driverConfig.key}`,"Content-Type":"application/json"},body:JSON.stringify(option.body)},param.onStream,param.onFinish)};var drivers={ModStart:function(param){openAiCompletion(aiConfig.driverConfig.url,param,{body:{prompt:param.promptText}})},OpenAi:function(param){openAiCompletion(aiConfig.driverConfig.url||"https://api.openai.com/v1/engines/davinci/completions",param)},DeepSeek:function(param){openAiCompletion(aiConfig.driverConfig.url||"https://api.deepseek.com/chat/completions",param)}};function getRequest(driver){if(aiConfig.driverRequest){return aiConfig.driverRequest}if(driver in drivers){return drivers[driver]}return null}var converter=new window.showdown.Converter;var Ai={runtime:{range:null},init:function(){new Vue({el:"#app",data:{loading:false,selectText:"",inputText:"",promptText:"",resultText:"",resultError:"",functions:[]},mounted:function(){Ai.runtime.range=editor.selection.getRange();var cloneContents=Ai.runtime.range.cloneContents();if(cloneContents){this.selectText=cloneContents.textContent.trim()}else{this.selectText=""}this.buildFunctions()},computed:{resultHtml:function(){if(!this.resultText){return""}return converter.makeHtml(this.resultText)},resultHeight:function(){let height=255;if(this.selectText){height-=45}if(this.resultError){height-=45}return height+"px"}},methods:{buildFunctions:function(){var enableParam={selectText:this.selectText};this.functions=aiFunctions.map(function(f){if(!f.enable(enableParam)){return null}f.prompt=f.prompt.replace(/\{selectText\}/g,enableParam.selectText);return f}).filter(function(f){return!!f})},doSubmit:function(){if(this.loading){return}if(this.inputText){if(this.selectText){this.promptText=this.selectText+"\n\n"+this.inputText}else{this.promptText=this.inputText}}if(!this.promptText){editor.tipError("请输入内容");return}this.loading=true;this.resultError="";this.resultText="";var driverRequest=getRequest(aiConfig.driver);if(!driverRequest){editor.tipError("未找到驱动");return}driverRequest({promptText:this.promptText,onStream:res=>{if(res.code){this.resultError=res.msg;return}this.resultText+=res.data.text},onFinish:res=>{this.loading=false;if(res.code){this.resultError=res.msg;return}this.resultText=res.data.text}})},doSubmitFunction:function(f){this.promptText=f.prompt;this.doSubmit()},doInsert:function(){editor.fireEvent("saveScene");if(this.selectText){if(isMultiLine(this.resultText)){Ai.runtime.range.insertNode(document.createRange().createContextualFragment(this.resultHtml))}else{Ai.runtime.range.insertNode(document.createTextNode(this.resultText))}}else{if(isMultiLine(this.resultText)){editor.execCommand("insertHtml",this.resultHtml)}else{editor.execCommand("insertHtml",this.resultText)}}dialog.close(true)},doReplace:function(){editor.fireEvent("saveScene");Ai.runtime.range.deleteContents();if(isMultiLine(this.resultText)){Ai.runtime.range.insertNode(document.createRange().createContextualFragment(this.resultHtml))}else{Ai.runtime.range.insertNode(document.createTextNode(this.resultText))}dialog.close(true)}}})}};utils.domReady(function(){Ai.init()});
|
||||
Reference in New Issue
Block a user