diff --git a/GinSkeleton/api_doc.md b/GinSkeleton/api_doc.md index 1dc94ea..6d08c97 100644 --- a/GinSkeleton/api_doc.md +++ b/GinSkeleton/api_doc.md @@ -229,7 +229,7 @@ voc|form-data|string|必填|"" (示例内容在 storage/app/test/A13_221.txt 中 ---|---|---|---|--- doc|form-data|string|必填|"" background|form-data|string||"" -type|form-data|string|必填|"abstract"/"decorate"/"sequel_writing"/"rewrite_wrong"/"translate" +type|form-data|string|必填|"summary"/"decoration"/"correction"/"extension"/"translation" > 返回示例: ```json { diff --git a/GinSkeleton/app/http/validator/web/ai_doc.go/doc_refine.go b/GinSkeleton/app/http/validator/web/ai_doc.go/doc_refine.go index afc83f4..95a1aa7 100644 --- a/GinSkeleton/app/http/validator/web/ai_doc.go/doc_refine.go +++ b/GinSkeleton/app/http/validator/web/ai_doc.go/doc_refine.go @@ -16,7 +16,7 @@ type DocRefine struct { Background string `form:"background" json:"background" ` } -var Types = []string{"abstract", "decorate", "sequel_writing", "rewrite_wrong", "translate"} +var Types = []string{"summary", "decoration", "extension", "correction", "translation"} func (d DocRefine) CheckParams(context *gin.Context) { if err := context.ShouldBind(&d); err != nil { @@ -24,6 +24,7 @@ func (d DocRefine) CheckParams(context *gin.Context) { response.ValidatorError(context, err) return } + // 判断是否在类型中 t := d.Type isExit := false diff --git a/GinSkeleton/app/service/ai_model_cli/dor_cli.go b/GinSkeleton/app/service/ai_model_cli/dor_cli.go index e72c042..326e650 100644 --- a/GinSkeleton/app/service/ai_model_cli/dor_cli.go +++ b/GinSkeleton/app/service/ai_model_cli/dor_cli.go @@ -2,7 +2,6 @@ package ai_model_cli import ( "context" - "fmt" "goskeleton/app/global/variable" "strings" @@ -25,18 +24,17 @@ func RequestQianFan(cont *gin.Context) (r bool, c interface{}) { b := strings.TrimSpace(cont.PostForm("background")) d := strings.TrimSpace(cont.PostForm("doc")) switch t { - case "abstract": + case "summary": message = "请在这个背景下:" + b + "\n对下文进行概括,不要改变原有语言:" + d - case "decorate": + case "decoration": message = "请在这个背景下:" + b + "\n对下文进行润色,不要改变原有语言:" + d - case "sequel_writing": + case "extension": message = "请在这个背景下:" + b + "\n对下文进行续写,不要改变原有语言:" + d - case "rewrite_wrong": + case "correction": message = "请在这个背景下:" + b + "\n对下文进行改错,不要改变原有语言:" + d - case "translate": + case "translation": message = "请在这个背景下:" + b + "\n对下文进行翻译:" + d } - resp, _ := chat.Do( context.TODO(), &qianfan.ChatCompletionRequest{ @@ -45,6 +43,5 @@ func RequestQianFan(cont *gin.Context) (r bool, c interface{}) { }, }, ) - fmt.Println(resp.Result) return true, gin.H{"new_doc": resp.Result} } diff --git a/coeditor_frontend/package-lock.json b/coeditor_frontend/package-lock.json index 699079e..69fed48 100644 --- a/coeditor_frontend/package-lock.json +++ b/coeditor_frontend/package-lock.json @@ -19,6 +19,7 @@ "html-docx-js-typescript": "^0.1.5", "jquery": "^3.7.1", "jwt-decode": "^4.0.0", + "mitt": "^3.0.1", "vue": "^3.2.13", "vue-router": "^4.0.3", "vuex": "^4.0.0" @@ -4548,6 +4549,7 @@ "version": "1.0.7", "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -5665,6 +5667,7 @@ "version": "1.1.4", "resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -6014,6 +6017,7 @@ "version": "1.0.0", "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -6025,6 +6029,7 @@ "version": "1.3.0", "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, "engines": { "node": ">= 0.4" } @@ -7009,6 +7014,7 @@ "version": "1.1.2", "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7041,6 +7047,7 @@ "version": "1.2.4", "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -7139,6 +7146,7 @@ "version": "1.0.1", "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -7186,6 +7194,7 @@ "version": "1.0.2", "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -7197,6 +7206,7 @@ "version": "1.0.3", "resolved": "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -7208,6 +7218,7 @@ "version": "1.0.3", "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -7225,6 +7236,7 @@ "version": "2.0.2", "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -8656,6 +8668,11 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==" + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", @@ -8907,6 +8924,7 @@ "version": "1.13.2", "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.2.tgz", "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -10062,6 +10080,7 @@ "version": "6.13.0", "resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz", "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, "dependencies": { "side-channel": "^1.0.6" }, @@ -10656,6 +10675,7 @@ "version": "1.2.2", "resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -10725,6 +10745,7 @@ "version": "1.0.6", "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -11704,23 +11725,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url": { - "version": "0.11.4", - "resolved": "https://registry.npmmirror.com/url/-/url-0.11.4.tgz", - "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", - "dependencies": { - "punycode": "^1.4.1", - "qs": "^6.12.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/coeditor_frontend/package.json b/coeditor_frontend/package.json index 0254354..6a26985 100644 --- a/coeditor_frontend/package.json +++ b/coeditor_frontend/package.json @@ -19,6 +19,7 @@ "html-docx-js-typescript": "^0.1.5", "jquery": "^3.7.1", "jwt-decode": "^4.0.0", + "mitt": "^3.0.1", "vue": "^3.2.13", "vue-router": "^4.0.3", "vuex": "^4.0.0" diff --git a/coeditor_frontend/src/components/plugins.js b/coeditor_frontend/src/components/plugins.js index e77f49d..24cee5d 100644 --- a/coeditor_frontend/src/components/plugins.js +++ b/coeditor_frontend/src/components/plugins.js @@ -84,7 +84,7 @@ import { getUserConfigFromBackend, saveData } from './utils'; - +import mitt from 'mitt'; // 导出为docx插件 function exportWord(){ const pageContent = getPageContent(); @@ -197,9 +197,56 @@ class Export2PDF extends Plugin { } } -// 智能润色插件 -class Translation extends Plugin { - init() { + +// 智能润色发送消息 +function sendDORMsg(type, fullText) { + + // 获取选中的文本,用来进行后续操作 + const selectionText = window.getSelection().toString(); + if (selectionText.trim() === '') return; + const formData = new FormData(); + formData.append('doc', selectionText); + formData.append('background', fullText); + formData.append('type', type); + const requestOptions= { + method: 'POST', + body: formData + }; + + console.log("formData:", formData); + const store = window.store; + const res = {oldContent:selectionText, newContent:'...'}; + store.commit('setCurrentTag', type); + store.commit('addContentToTag', {tag:type, newContent:res}); + const index = store.getters.getCurrentindex; + console.log("index", index); + emitter.emit('show-refine-doc-sidebar', type); + + fetch("/web_api/admin/ai_doc/doc_refine", requestOptions) + .then(response => { + if (!response.ok) { + throw new Error("请求出错"); + } + + // 根据返回的数据格式进行相应处理,这里假设返回的数据是JSON格式,所以使用response.json()解析 + return response.json(); + }) + .then(data => { + + // console.log("useStore", store); + const newRes = {oldContent:selectionText, newContent:data.data.new_doc}; + store.commit('changeContentForTag', {tag:type, index:index, newContent:newRes}); + emitter.emit('show-refine-doc-sidebar', type); + }) + .catch(error => { + console.error("POST请求出错:", error); + }); + +} + + +class RefineDoc extends Plugin { + init() { // console.log('Translation initialized!'); this.editor.ui.componentFactory.add('translate', (locale) => { @@ -253,19 +300,14 @@ class Translation extends Plugin { addListToDropdown(dropdownView, items); dropdownView.on('execute', (eventInfo) => { - const { id, label } = eventInfo.source; - // 获取选中的文本,用来进行后续操作 - const selectionText = window.getSelection().toString(); - if (id === 'summary') { - // this.editor.execute('ExportToWord'); - console.log('Object (en):', label, selectionText); - } - }); + const id = eventInfo.source.id; + sendDORMsg(id, ''); + }); - return dropdownView; - }); - } -} + return dropdownView; + }); + } + } // 侧边栏按钮 class ToggleSideBar extends Plugin { @@ -448,7 +490,7 @@ function setConfig() { TodoList, Underline, Undo, - Export2Word, Translation, Export2PDF, ToggleSideBar, SaveButton + Export2Word, RefineDoc, Export2PDF, ToggleSideBar, SaveButton ], balloonToolbar: ['bold', 'italic', '|', 'link', 'insertImage', '|', 'bulletedList', 'numberedList'], //自定义设置字体 @@ -585,4 +627,6 @@ function setConfig() { translations: [translations] } } -export { Export2Word, Export2PDF, Translation, ToggleSideBar, setConfig }; \ No newline at end of file +const emitter = new mitt(); +export default emitter; +export {Export2Word, Export2PDF, RefineDoc, ToggleSideBar, setConfig}; diff --git a/coeditor_frontend/src/main.js b/coeditor_frontend/src/main.js index 5546580..e8bf438 100644 --- a/coeditor_frontend/src/main.js +++ b/coeditor_frontend/src/main.js @@ -7,6 +7,8 @@ import { CkeditorPlugin } from '@ckeditor/ckeditor5-vue'; const app = createApp(App); +window.store = store; + app.use(router); app.use(store); app.use(CkeditorPlugin); diff --git a/coeditor_frontend/src/public/sidebar.css b/coeditor_frontend/src/public/sidebar.css index 9bf8f56..f1e2135 100644 --- a/coeditor_frontend/src/public/sidebar.css +++ b/coeditor_frontend/src/public/sidebar.css @@ -124,4 +124,16 @@ padding: 10px; border-radius: 4px; background-color: #ecf0f1; +} +.message-answer { + margin: 5px 0; + padding: 10px; + border-radius: 4px; + background-color: rgb(189, 195, 199); +} +.message-answer pre { + white-space: pre-wrap; + /* 保留空白符,但允许自动换行 */ + word-wrap: break-word; + /* 允许长单词换行 */ } \ No newline at end of file diff --git a/coeditor_frontend/src/router/index.js b/coeditor_frontend/src/router/index.js index 464c2d6..ca52dc4 100644 --- a/coeditor_frontend/src/router/index.js +++ b/coeditor_frontend/src/router/index.js @@ -40,6 +40,12 @@ const routes = [ { path: '/:catchAll(.*)', redirect: '/404/', + }, + { + path: '/web_api/', + target:'http://localhost:14514/', + changeOrigin:true, //修改源 + rewrite:{'^/web_api/':''} } ] diff --git a/coeditor_frontend/src/store/index.js b/coeditor_frontend/src/store/index.js index 49ed985..cd0c08e 100644 --- a/coeditor_frontend/src/store/index.js +++ b/coeditor_frontend/src/store/index.js @@ -1,5 +1,6 @@ import { createStore } from 'vuex' import ModulerUser from './user'; +import ModulerRefineDoc from './refine_doc'; export default createStore({ state: { @@ -12,5 +13,6 @@ export default createStore({ }, modules: { user: ModulerUser, + refine_doc: ModulerRefineDoc } }) diff --git a/coeditor_frontend/src/store/refine_doc.js b/coeditor_frontend/src/store/refine_doc.js new file mode 100644 index 0000000..e84d31c --- /dev/null +++ b/coeditor_frontend/src/store/refine_doc.js @@ -0,0 +1,54 @@ + +const ModulerRefineDoc = { + state: { + current_tag: '', + contents: new Map() + }, + mutations: { + setCurrentTag(state, newTag) { + console.log("storetag", newTag); + state.current_tag = newTag; + }, + // 增加tag下的value数组里的内容的mutation方法 + addContentToTag(state, {tag, newContent}) { + console.log("tag, newContent", {tag, newContent}); + if (!state.contents.has(tag)) { + state.contents.set(tag, []); + } + state.contents.get(tag).push(newContent); + return state.contents.get(tag) - 1; + }, + // 修改tag下的value数组里的内容的mutation方法 + changeContentForTag(state, {tag, index, newContent}) { + if (!state.contents.has(tag)) { + state.contents.set(tag, []); + } + var tagContents = state.contents.get(tag); + console.log("oldtagc", tagContents, tagContents[index]); + if (tagContents[index]){ + state.contents.get(tag).splice(index,1,newContent); + } + }, + // 清空tag下的数组内容的mutation方法 + clearContentsForTag(state, tag) { + if (state.contents.has(tag)) { + state.contents.set(tag, []); + } + } + }, + getters: { + getCurrentTag(state) { + return state.current_tag; + }, + getCurrentContent(state) { + return state.contents.get(state.current_tag); + }, + getCurrentindex(state) { + return state.contents.get(state.current_tag).length - 1; + } + }, + modules: { + } +} + +export default ModulerRefineDoc; \ No newline at end of file diff --git a/coeditor_frontend/src/views/CkeditorView.vue b/coeditor_frontend/src/views/CkeditorView.vue index 72844d4..fc6f341 100644 --- a/coeditor_frontend/src/views/CkeditorView.vue +++ b/coeditor_frontend/src/views/CkeditorView.vue @@ -16,16 +16,16 @@
-