support upload file from clipboard

This commit is contained in:
RockYang 2024-07-17 10:23:02 +08:00
parent 246b023624
commit 37368fe13f
9 changed files with 59 additions and 16 deletions

View File

@ -1,4 +1,13 @@
# 更新日志 # 更新日志
## v4.1.1
* Bug修复修复 GPT 模型 function call 调用后没有输出的问题
* 功能新增:允许获取 License 授权用户可以自定义版权信息
* 功能新增:聊天对话框支持粘贴剪切板内容来上传截图和文件
* 功能优化:增加 session 和系统配置缓存,确保每个页面只进行一次 session 和 get system config 请求
* 功能优化:在应用列表页面,无需先添加模型到用户工作区,可以直接使用
* 功能新增MJ 绘图失败的任务不会自动删除,而是会在列表页显示失败详细错误信息
* 功能新增:增加 Suno 文生音乐页面功能
## v4.1.0 ## v4.1.0
* bug修复修复移动端修改聊天标题不生效的问题 * bug修复修复移动端修改聊天标题不生效的问题
* Bug修复修复用户注册不显示用户名的问题 * Bug修复修复用户注册不显示用户名的问题

View File

@ -139,7 +139,7 @@ func authorizeMiddleware(s *AppServer, client *redis.Client) gin.HandlerFunc {
if tokenString == "" { if tokenString == "" {
if needLogin(c) { 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() c.Abort()
return return
} else { // 直接放行 } else { // 直接放行

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 B

View File

@ -241,8 +241,8 @@ watch(() => props.show, (newValue) => {
const login = ref(true) const login = ref(true)
const data = ref({ const data = ref({
username: "", username: process.env.VUE_APP_USER,
password: "", password: process.env.VUE_APP_PASS,
repass: "", repass: "",
code: "", code: "",
invite_code: "" invite_code: ""

View File

@ -37,7 +37,11 @@ export function GetFileIcon(ext) {
".pptx": "ppt.png", ".pptx": "ppt.png",
".md": "md.png", ".md": "md.png",
".pdf": "pdf.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]) { if (files[ext]) {
return '/images/ext/' + files[ext] return '/images/ext/' + files[ext]

View File

@ -34,6 +34,8 @@ axios.interceptors.response.use(
} else { } else {
removeUserToken() removeUserToken()
} }
console.log(error.response.data)
error.response.data.message = "请先登录"
return Promise.reject(error.response.data) return Promise.reject(error.response.data)
} }
if (error.response.status === 400) { if (error.response.status === 400) {

View File

@ -219,6 +219,7 @@ import {useSharedStore} from "@/store/sharedata";
import FileSelect from "@/components/FileSelect.vue"; import FileSelect from "@/components/FileSelect.vue";
import FileList from "@/components/FileList.vue"; import FileList from "@/components/FileList.vue";
import ChatSetting from "@/components/ChatSetting.vue"; import ChatSetting from "@/components/ChatSetting.vue";
import axios from "axios";
const title = ref('ChatGPT-智能助手'); const title = ref('ChatGPT-智能助手');
const models = ref([]) const models = ref([])
@ -342,16 +343,6 @@ const initData = () => {
}) })
}).catch(() => { }).catch(() => {
loading.value = false 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 => { httpGet('/api/model/list',{id:roleId.value}).then(res => {
models.value = res.data models.value = res.data
@ -368,6 +359,37 @@ const initData = () => {
ElMessage.error('获取聊天角色失败: ' + e.messages) 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) { const getRoleById = function (rid) {
@ -739,7 +761,7 @@ const onInput = (e) => {
const autofillPrompt = (text) => { const autofillPrompt = (text) => {
prompt.value = text prompt.value = text
inputRef.value.focus() inputRef.value.focus()
// sendMessage() sendMessage()
} }
// //
const sendMessage = function () { const sendMessage = function () {

View File

@ -492,7 +492,13 @@
<div class="image-slot"> <div class="image-slot">
<div class="err-msg-container"> <div class="err-msg-container">
<div class="title">任务失败</div> <div class="title">任务失败</div>
<div class="text">{{ slotProp.item['err_msg'] }}</div> <div class="text">
<el-popover title="错误详情" trigger="hover" :width="250" :content="slotProp.item['err_msg']" placement="top">
<template #reference>
{{ slotProp.item['err_msg'] }}
</template>
</el-popover>
</div>
</div> </div>
<el-button type="danger" @click="removeImage(slotProp.item)">删除</el-button> <el-button type="danger" @click="removeImage(slotProp.item)">删除</el-button>
</div> </div>