From 37368fe13fa2d30ac34deac7e746d8ec4575cc61 Mon Sep 17 00:00:00 2001 From: RockYang Date: Wed, 17 Jul 2024 10:23:02 +0800 Subject: [PATCH] support upload file from clipboard --- CHANGELOG.md | 9 ++++++ api/core/app_server.go | 2 +- web/public/images/ext/mp3.png | Bin 0 -> 812 bytes web/public/images/ext/mp4.png | Bin 0 -> 743 bytes web/src/components/LoginDialog.vue | 4 +-- web/src/store/system.js | 6 +++- web/src/utils/http.js | 2 ++ web/src/views/ChatPlus.vue | 44 +++++++++++++++++++++-------- web/src/views/ImageMj.vue | 8 +++++- 9 files changed, 59 insertions(+), 16 deletions(-) create mode 100644 web/public/images/ext/mp3.png create mode 100644 web/public/images/ext/mp4.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 20da1320..d7b9cc83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,13 @@ # 更新日志 +## v4.1.1 +* Bug修复:修复 GPT 模型 function call 调用后没有输出的问题 +* 功能新增:允许获取 License 授权用户可以自定义版权信息 +* 功能新增:聊天对话框支持粘贴剪切板内容来上传截图和文件 +* 功能优化:增加 session 和系统配置缓存,确保每个页面只进行一次 session 和 get system config 请求 +* 功能优化:在应用列表页面,无需先添加模型到用户工作区,可以直接使用 +* 功能新增:MJ 绘图失败的任务不会自动删除,而是会在列表页显示失败详细错误信息 +* 功能新增:增加 Suno 文生音乐页面功能 + ## v4.1.0 * bug修复:修复移动端修改聊天标题不生效的问题 * Bug修复:修复用户注册不显示用户名的问题 diff --git a/api/core/app_server.go b/api/core/app_server.go index 12a17567..7a378dd0 100644 --- a/api/core/app_server.go +++ b/api/core/app_server.go @@ -139,7 +139,7 @@ func authorizeMiddleware(s *AppServer, client *redis.Client) gin.HandlerFunc { if tokenString == "" { if needLogin(c) { - resp.ERROR(c, "You should put Authorization in request headers") + resp.NotAuth(c, "You should put Authorization in request headers") c.Abort() return } else { // 直接放行 diff --git a/web/public/images/ext/mp3.png b/web/public/images/ext/mp3.png new file mode 100644 index 0000000000000000000000000000000000000000..f2cdd7912585a65e0ffd56d380e31597b2d995a1 GIT binary patch literal 812 zcmV+{1JnG8P)Px%=1D|BRCr$PTU}BjF%bS5d|vbfjwe|-iSjO0-ax#;R*mnnCs9vg_5?0I%fw30 zPsITw9fqpRBzXe@Lx1`Dze8xP^)2o}$N=25KkM;p1>l8%*IzkSwj5Nyc)vq7+Ta;r z;fK6bF~;oT4-6<^0N!sg9T5v3%Tk5L{Nj;W0sLR!nSg05(pPe-NscS}Sl~tjPmu{< zimS1t^@4>TlEHI6OKl9}dV#kH4BtLblmS3HLpH#T34p|aqymGm0SdYbafv;eb2Qsm z8^8h=z^jSoY}+jLYJC7eX+V+2%PxVpk~yJU4-tTd&czx2)=7)22ks*S8i6N|cyJYz zlejx%_(W!_K_39vtG|bY=al^u*P1YGk~fW|4P0mdi1gP6pg!FZ@cWygG`eGjdIBCrx0T8Aa z_@)Ah0jDgxB^5|25M(5nY=9jIB_o)O;0c>A$qOVeki0;M1(D9(AU85~Spg=(KWz#n zKxW<>HUKRncPN7nr6kq~0}72)`5c(v# z900&61~A=V+TbblF?=5YYR%gkb+M;9j_Ub$pxdrLaSQ;i&j@;70zeuG27R0!e=ac~ zdIp5&yUb}5BFHV}h)xBYJeJ+|+*Bs-#JYC%z=8~9w qXM6!h13lLvP?CNC0000?P)Px%p-DtRRCr$Po83_YF%ZXhfdUX4fEi)NF0>PP1dG5Xgh%W|x^M=Zkp@HxP~wD} z!vlf+Uq~dm%e}JXl3(^Sw_z&z!zEuoMF6GOfckiThd@~M+tXC8K7MTy)tbov{!_+e zj@%f{l{`tcSPnX^RIV|ay%Vu_0G5OH)}*gS^A{!(H#Y)^8W2q&`he&J%N+&AZxa~+ z(XxNj3n>gX#`7T(s*O_N5b^+IQ?*P4fRf6}6-oni$|yl#=0%7;K&cC*!mL#9 z{WR+;Cde5{n}Gc8NiDEjIO)ofRc(S4CdeXB$#?-k5lue_?fd30`%v^;4cIBVa)wJI zC+IT(4I@uIQAhx3xU8t^iQK~H9*~4ThQ3*(b2LhXd;^eo*R%5v9suI#&@(}FV;L!jzbm}Rwx75# z0koq71pt@BQfy6Lh_}e(^#OXKtY~QC)Y!-gUJ?Kr-cWT82EaLv4mAPPq^vhdNhWZv zqYD}Ux+|#4@5^~>0x*w#%zPiDkN`>WN!;y#p!r3b~GcCOa Z`~WbTE~Jm1rT72<002ovPDHLkV1h)MI4S@D literal 0 HcmV?d00001 diff --git a/web/src/components/LoginDialog.vue b/web/src/components/LoginDialog.vue index a279b005..9efe98e2 100644 --- a/web/src/components/LoginDialog.vue +++ b/web/src/components/LoginDialog.vue @@ -241,8 +241,8 @@ watch(() => props.show, (newValue) => { const login = ref(true) const data = ref({ - username: "", - password: "", + username: process.env.VUE_APP_USER, + password: process.env.VUE_APP_PASS, repass: "", code: "", invite_code: "" diff --git a/web/src/store/system.js b/web/src/store/system.js index 0d1f64dc..6b6eee80 100644 --- a/web/src/store/system.js +++ b/web/src/store/system.js @@ -37,7 +37,11 @@ export function GetFileIcon(ext) { ".pptx": "ppt.png", ".md": "md.png", ".pdf": "pdf.png", - ".sql": "sql.png" + ".sql": "sql.png", + ".mp3": "mp3.png", + ".wav": "mp3.png", + ".mp4": "mp4.png", + ".avi": "mp4.png", } if (files[ext]) { return '/images/ext/' + files[ext] diff --git a/web/src/utils/http.js b/web/src/utils/http.js index a7d66715..f454a675 100644 --- a/web/src/utils/http.js +++ b/web/src/utils/http.js @@ -34,6 +34,8 @@ axios.interceptors.response.use( } else { removeUserToken() } + console.log(error.response.data) + error.response.data.message = "请先登录" return Promise.reject(error.response.data) } if (error.response.status === 400) { diff --git a/web/src/views/ChatPlus.vue b/web/src/views/ChatPlus.vue index b7770603..56f041bc 100644 --- a/web/src/views/ChatPlus.vue +++ b/web/src/views/ChatPlus.vue @@ -219,6 +219,7 @@ import {useSharedStore} from "@/store/sharedata"; import FileSelect from "@/components/FileSelect.vue"; import FileList from "@/components/FileList.vue"; import ChatSetting from "@/components/ChatSetting.vue"; +import axios from "axios"; const title = ref('ChatGPT-智能助手'); const models = ref([]) @@ -342,16 +343,6 @@ const initData = () => { }) }).catch(() => { loading.value = false - // 加载会话 - httpGet("/api/chat/list").then((res) => { - if (res.data) { - chatList.value = res.data; - allChats.value = res.data; - } - }).catch(() => { - ElMessage.error("加载会话列表失败!") - }) - // 加载模型 httpGet('/api/model/list',{id:roleId.value}).then(res => { models.value = res.data @@ -368,6 +359,37 @@ const initData = () => { ElMessage.error('获取聊天角色失败: ' + e.messages) }) }) + + inputRef.value.addEventListener('paste', (event) => { + const items = (event.clipboardData || window.clipboardData).items; + let fileFound = false; + loading.value = true + + for (let item of items) { + if (item.kind === 'file') { + const file = item.getAsFile(); + fileFound = true; + + const formData = new FormData(); + formData.append('file', file); + // 执行上传操作 + httpPost('/api/upload', formData).then((res) => { + files.value.push(res.data) + ElMessage.success({message: "上传成功", duration: 500}) + loading.value = false + }).catch((e) => { + ElMessage.error('文件上传失败:' + e.message) + loading.value = false + }) + + break; + } + } + + if (!fileFound) { + document.getElementById('status').innerText = 'No file found in paste data.'; + } + }); } const getRoleById = function (rid) { @@ -739,7 +761,7 @@ const onInput = (e) => { const autofillPrompt = (text) => { prompt.value = text inputRef.value.focus() - // sendMessage() + sendMessage() } // 发送消息 const sendMessage = function () { diff --git a/web/src/views/ImageMj.vue b/web/src/views/ImageMj.vue index fd84e8a4..553b5a73 100644 --- a/web/src/views/ImageMj.vue +++ b/web/src/views/ImageMj.vue @@ -492,7 +492,13 @@
任务失败
-
{{ slotProp.item['err_msg'] }}
+
+ + + +
删除