feat: attachments manage function is ready
@ -155,7 +155,6 @@ func authorizeMiddleware(s *AppServer, client *redis.Client) gin.HandlerFunc {
|
|||||||
c.Request.URL.Path == "/api/mj/notify" ||
|
c.Request.URL.Path == "/api/mj/notify" ||
|
||||||
c.Request.URL.Path == "/api/invite/hits" ||
|
c.Request.URL.Path == "/api/invite/hits" ||
|
||||||
c.Request.URL.Path == "/api/sd/jobs" ||
|
c.Request.URL.Path == "/api/sd/jobs" ||
|
||||||
c.Request.URL.Path == "/api/upload" ||
|
|
||||||
strings.HasPrefix(c.Request.URL.Path, "/api/test") ||
|
strings.HasPrefix(c.Request.URL.Path, "/api/test") ||
|
||||||
strings.HasPrefix(c.Request.URL.Path, "/api/function/") ||
|
strings.HasPrefix(c.Request.URL.Path, "/api/function/") ||
|
||||||
strings.HasPrefix(c.Request.URL.Path, "/api/sms/") ||
|
strings.HasPrefix(c.Request.URL.Path, "/api/sms/") ||
|
||||||
|
@ -3,9 +3,13 @@ package handler
|
|||||||
import (
|
import (
|
||||||
"chatplus/core"
|
"chatplus/core"
|
||||||
"chatplus/service/oss"
|
"chatplus/service/oss"
|
||||||
|
"chatplus/store/model"
|
||||||
|
"chatplus/store/vo"
|
||||||
|
"chatplus/utils"
|
||||||
"chatplus/utils/resp"
|
"chatplus/utils/resp"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UploadHandler struct {
|
type UploadHandler struct {
|
||||||
@ -27,5 +31,40 @@ func (h *UploadHandler) Upload(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userId := h.GetLoginUserId(c)
|
||||||
|
res := h.db.Create(&model.File{
|
||||||
|
UserId: userId,
|
||||||
|
Name: file.Name,
|
||||||
|
URL: file.URL,
|
||||||
|
Ext: file.Ext,
|
||||||
|
Size: file.Size,
|
||||||
|
CreatedAt: time.Time{},
|
||||||
|
})
|
||||||
|
if res.Error != nil || res.RowsAffected == 0 {
|
||||||
|
resp.ERROR(c, "error with update database: "+res.Error.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
resp.SUCCESS(c, file)
|
resp.SUCCESS(c, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *UploadHandler) List(c *gin.Context) {
|
||||||
|
userId := h.GetLoginUserId(c)
|
||||||
|
var items []model.File
|
||||||
|
var files = make([]vo.File, 0)
|
||||||
|
h.db.Debug().Where("user_id = ?", userId).Find(&items)
|
||||||
|
if len(items) > 0 {
|
||||||
|
for _, v := range items {
|
||||||
|
var file vo.File
|
||||||
|
err := utils.CopyObject(v, &file)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
file.CreatedAt = v.CreatedAt.Unix()
|
||||||
|
files = append(files, file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.SUCCESS(c, files)
|
||||||
|
}
|
||||||
|
@ -214,6 +214,7 @@ func main() {
|
|||||||
}),
|
}),
|
||||||
fx.Invoke(func(s *core.AppServer, h *handler.UploadHandler) {
|
fx.Invoke(func(s *core.AppServer, h *handler.UploadHandler) {
|
||||||
s.Engine.POST("/api/upload", h.Upload)
|
s.Engine.POST("/api/upload", h.Upload)
|
||||||
|
s.Engine.GET("/api/upload/list", h.List)
|
||||||
}),
|
}),
|
||||||
fx.Invoke(func(s *core.AppServer, h *handler.SmsHandler) {
|
fx.Invoke(func(s *core.AppServer, h *handler.SmsHandler) {
|
||||||
group := s.Engine.Group("/api/sms/")
|
group := s.Engine.Group("/api/sms/")
|
||||||
|
@ -66,6 +66,7 @@ func (s AliYunOss) PutFile(ctx *gin.Context, name string) (File, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return File{
|
return File{
|
||||||
|
Name: file.Filename,
|
||||||
URL: fmt.Sprintf("%s/%s", s.config.Domain, objectKey),
|
URL: fmt.Sprintf("%s/%s", s.config.Domain, objectKey),
|
||||||
Ext: fileExt,
|
Ext: fileExt,
|
||||||
Size: file.Size,
|
Size: file.Size,
|
||||||
|
@ -41,6 +41,7 @@ func (s LocalStorage) PutFile(ctx *gin.Context, name string) (File, error) {
|
|||||||
|
|
||||||
ext := filepath.Ext(file.Filename)
|
ext := filepath.Ext(file.Filename)
|
||||||
return File{
|
return File{
|
||||||
|
Name: file.Filename,
|
||||||
URL: utils.GenUploadUrl(s.config.BasePath, s.config.BaseURL, path),
|
URL: utils.GenUploadUrl(s.config.BasePath, s.config.BaseURL, path),
|
||||||
Ext: ext,
|
Ext: ext,
|
||||||
Size: file.Size,
|
Size: file.Size,
|
||||||
|
@ -87,6 +87,7 @@ func (s MiniOss) PutFile(ctx *gin.Context, name string) (File, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return File{
|
return File{
|
||||||
|
Name: file.Filename,
|
||||||
URL: fmt.Sprintf("%s/%s/%s", s.config.Domain, s.config.Bucket, info.Key),
|
URL: fmt.Sprintf("%s/%s/%s", s.config.Domain, s.config.Bucket, info.Key),
|
||||||
Ext: fileExt,
|
Ext: fileExt,
|
||||||
Size: file.Size,
|
Size: file.Size,
|
||||||
|
@ -74,6 +74,7 @@ func (s QinNiuOss) PutFile(ctx *gin.Context, name string) (File, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return File{
|
return File{
|
||||||
|
Name: file.Filename,
|
||||||
URL: fmt.Sprintf("%s/%s", s.config.Domain, ret.Key),
|
URL: fmt.Sprintf("%s/%s", s.config.Domain, ret.Key),
|
||||||
Ext: fileExt,
|
Ext: fileExt,
|
||||||
Size: file.Size,
|
Size: file.Size,
|
||||||
|
@ -3,9 +3,10 @@ package oss
|
|||||||
import "github.com/gin-gonic/gin"
|
import "github.com/gin-gonic/gin"
|
||||||
|
|
||||||
type File struct {
|
type File struct {
|
||||||
Size int64
|
Name string `json:"name"`
|
||||||
URL string
|
Size int64 `json:"size"`
|
||||||
Ext string
|
URL string `json:"url"`
|
||||||
|
Ext string `json:"ext"`
|
||||||
}
|
}
|
||||||
type Uploader interface {
|
type Uploader interface {
|
||||||
PutFile(ctx *gin.Context, name string) (File, error)
|
PutFile(ctx *gin.Context, name string) (File, error)
|
||||||
|
@ -5,6 +5,7 @@ import "time"
|
|||||||
type File struct {
|
type File struct {
|
||||||
Id uint `gorm:"primarykey;column:id"`
|
Id uint `gorm:"primarykey;column:id"`
|
||||||
UserId uint
|
UserId uint
|
||||||
|
Name string
|
||||||
URL string
|
URL string
|
||||||
Ext string
|
Ext string
|
||||||
Size int64
|
Size int64
|
||||||
|
@ -3,6 +3,7 @@ package vo
|
|||||||
type File struct {
|
type File struct {
|
||||||
Id uint
|
Id uint
|
||||||
UserId uint `json:"user_id"`
|
UserId uint `json:"user_id"`
|
||||||
|
Name string `json:"name"`
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
Ext string `json:"ext"`
|
Ext string `json:"ext"`
|
||||||
Size int64 `json:"size"`
|
Size int64 `json:"size"`
|
@ -9,4 +9,5 @@ CREATE TABLE `chatgpt_plus`.`chatgpt_files` (
|
|||||||
`created_at` DATETIME NOT NULL COMMENT '创建时间' ,
|
`created_at` DATETIME NOT NULL COMMENT '创建时间' ,
|
||||||
PRIMARY KEY (`id`)) ENGINE = InnoDB COMMENT = '用户文件表';
|
PRIMARY KEY (`id`)) ENGINE = InnoDB COMMENT = '用户文件表';
|
||||||
|
|
||||||
ALTER TABLE `chatgpt_files` ADD `size` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '文件大小' AFTER `ext`;
|
ALTER TABLE `chatgpt_files` ADD `size` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '文件大小' AFTER `ext`;
|
||||||
|
ALTER TABLE `chatgpt_files` ADD `name` VARCHAR(100) NOT NULL COMMENT '文件名' AFTER `user_id`;
|
BIN
web/public/images/ext/doc.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
web/public/images/ext/file.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
web/public/images/ext/md.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
web/public/images/ext/pdf.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
web/public/images/ext/ppt.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
web/public/images/ext/sql.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
web/public/images/ext/txt.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
web/public/images/ext/xls.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
@ -213,6 +213,11 @@
|
|||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
}
|
}
|
||||||
|
#app .common-layout .el-main .right-box #container .input-box .input-container .select-file {
|
||||||
|
position: absolute;
|
||||||
|
right: 48px;
|
||||||
|
top: 20px;
|
||||||
|
}
|
||||||
#app .common-layout .el-main .right-box #container .input-box .input-container .send-btn {
|
#app .common-layout .el-main .right-box #container .input-box .input-container .send-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 12px;
|
right: 12px;
|
||||||
|
@ -279,6 +279,12 @@ $borderColor = #4676d0;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.select-file {
|
||||||
|
position absolute;
|
||||||
|
right 48px;
|
||||||
|
top 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.send-btn {
|
.send-btn {
|
||||||
position absolute;
|
position absolute;
|
||||||
right 12px;
|
right 12px;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 4125778 */
|
font-family: "iconfont"; /* Project id 4125778 */
|
||||||
src: url('iconfont.woff2?t=1703124384910') format('woff2'),
|
src: url('iconfont.woff2?t=1705313263366') format('woff2'),
|
||||||
url('iconfont.woff?t=1703124384910') format('woff'),
|
url('iconfont.woff?t=1705313263366') format('woff'),
|
||||||
url('iconfont.ttf?t=1703124384910') format('truetype');
|
url('iconfont.ttf?t=1705313263366') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
@ -13,6 +13,38 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-xls:before {
|
||||||
|
content: "\e678";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-file:before {
|
||||||
|
content: "\e62f";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-doc:before {
|
||||||
|
content: "\e6c2";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-pdf:before {
|
||||||
|
content: "\e6c3";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-ppt:before {
|
||||||
|
content: "\e642";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-txt:before {
|
||||||
|
content: "\e644";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-sql:before {
|
||||||
|
content: "\e65b";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-md:before {
|
||||||
|
content: "\e63a";
|
||||||
|
}
|
||||||
|
|
||||||
.icon-loading:before {
|
.icon-loading:before {
|
||||||
content: "\e627";
|
content: "\e627";
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,62 @@
|
|||||||
"css_prefix_text": "icon-",
|
"css_prefix_text": "icon-",
|
||||||
"description": "",
|
"description": "",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "12600976",
|
||||||
|
"name": "xls",
|
||||||
|
"font_class": "xls",
|
||||||
|
"unicode": "e678",
|
||||||
|
"unicode_decimal": 59000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "3750429",
|
||||||
|
"name": "file",
|
||||||
|
"font_class": "file",
|
||||||
|
"unicode": "e62f",
|
||||||
|
"unicode_decimal": 58927
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "4318810",
|
||||||
|
"name": "doc",
|
||||||
|
"font_class": "doc",
|
||||||
|
"unicode": "e6c2",
|
||||||
|
"unicode_decimal": 59074
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "4318811",
|
||||||
|
"name": "pdf",
|
||||||
|
"font_class": "pdf",
|
||||||
|
"unicode": "e6c3",
|
||||||
|
"unicode_decimal": 59075
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "4628503",
|
||||||
|
"name": "ppt",
|
||||||
|
"font_class": "ppt",
|
||||||
|
"unicode": "e642",
|
||||||
|
"unicode_decimal": 58946
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "6233095",
|
||||||
|
"name": "txt",
|
||||||
|
"font_class": "txt",
|
||||||
|
"unicode": "e644",
|
||||||
|
"unicode_decimal": 58948
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "12600910",
|
||||||
|
"name": "sql",
|
||||||
|
"font_class": "sql",
|
||||||
|
"unicode": "e65b",
|
||||||
|
"unicode_decimal": 58971
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "31260974",
|
||||||
|
"name": "md",
|
||||||
|
"font_class": "md",
|
||||||
|
"unicode": "e63a",
|
||||||
|
"unicode_decimal": 58938
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"icon_id": "1278349",
|
"icon_id": "1278349",
|
||||||
"name": "loading",
|
"name": "loading",
|
||||||
|
171
web/src/components/FileSelect.vue
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
<template>
|
||||||
|
<el-container class="file-list-box">
|
||||||
|
<el-button class="file-upload-img" @click="fetchFiles">
|
||||||
|
<el-icon>
|
||||||
|
<PictureFilled/>
|
||||||
|
</el-icon>
|
||||||
|
</el-button>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
v-model="show"
|
||||||
|
:close-on-click-modal="true"
|
||||||
|
:show-close="true"
|
||||||
|
:width="800"
|
||||||
|
title="文件管理"
|
||||||
|
>
|
||||||
|
|
||||||
|
<div class="file-list">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="3">
|
||||||
|
<div class="grid-content">
|
||||||
|
<el-upload
|
||||||
|
class="avatar-uploader"
|
||||||
|
:auto-upload="true"
|
||||||
|
:show-file-list="false"
|
||||||
|
:http-request="afterRead"
|
||||||
|
>
|
||||||
|
<el-icon class="avatar-uploader-icon">
|
||||||
|
<Plus/>
|
||||||
|
</el-icon>
|
||||||
|
</el-upload>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="3" v-for="file in fileList">
|
||||||
|
<div class="grid-content">
|
||||||
|
<el-tooltip
|
||||||
|
class="box-item"
|
||||||
|
effect="dark"
|
||||||
|
:content="file.name"
|
||||||
|
placement="top">
|
||||||
|
<el-image :src="file.url" fit="fill" v-if="isImage(file.ext)" @click="insertURL(file.url)"/>
|
||||||
|
<el-image :src="getFileIcon(file.ext)" fit="fill" v-else @click="insertURL(file.url)"/>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</el-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {ref} from "vue";
|
||||||
|
import {ElMessage} from "element-plus";
|
||||||
|
import {httpGet, httpPost} from "@/utils/http";
|
||||||
|
import {PictureFilled, Plus} from "@element-plus/icons-vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
userId: String,
|
||||||
|
});
|
||||||
|
const emits = defineEmits(['selected']);
|
||||||
|
const show = ref(false)
|
||||||
|
const fileList = ref([])
|
||||||
|
|
||||||
|
const fetchFiles = () => {
|
||||||
|
show.value = true
|
||||||
|
httpGet("/api/upload/list").then(res => {
|
||||||
|
fileList.value = res.data
|
||||||
|
}).catch(() => {
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const isImage = (ext) => {
|
||||||
|
const expr = /\.(jpg|jpeg|png|gif|bmp|svg)$/i;
|
||||||
|
return expr.test(ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getFileIcon = (ext) => {
|
||||||
|
const files = {
|
||||||
|
".docx": "doc.png",
|
||||||
|
".doc": "doc.png",
|
||||||
|
".xls": "xls.png",
|
||||||
|
".xlsx": "xls.png",
|
||||||
|
".ppt": "ppt.png",
|
||||||
|
".pptx": "ppt.png",
|
||||||
|
".md": "md.png",
|
||||||
|
".pdf": "pdf.png",
|
||||||
|
".sql": "sql.png"
|
||||||
|
}
|
||||||
|
if (files[ext]) {
|
||||||
|
return '/images/ext/' + files[ext]
|
||||||
|
}
|
||||||
|
|
||||||
|
return '/images/ext/file.png'
|
||||||
|
}
|
||||||
|
|
||||||
|
const afterRead = (file) => {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', file.file, file.name);
|
||||||
|
// 执行上传操作
|
||||||
|
httpPost('/api/upload', formData).then((res) => {
|
||||||
|
fileList.value.unshift(res.data)
|
||||||
|
ElMessage.success({message: "上传成功", duration: 500})
|
||||||
|
}).catch((e) => {
|
||||||
|
ElMessage.error('图片上传失败:' + e.message)
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
const insertURL = (url) => {
|
||||||
|
show.value = false
|
||||||
|
emits('selected', url)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus">
|
||||||
|
|
||||||
|
.file-list-box {
|
||||||
|
.file-upload-img {
|
||||||
|
padding: 8px 5px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #19c37d;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog {
|
||||||
|
|
||||||
|
.el-dialog__body {
|
||||||
|
//padding 0
|
||||||
|
|
||||||
|
.file-list {
|
||||||
|
|
||||||
|
.grid-content {
|
||||||
|
margin-bottom 10px
|
||||||
|
|
||||||
|
.avatar-uploader {
|
||||||
|
width 100%
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border 1px dashed #e1e1e1
|
||||||
|
border-radius 6px
|
||||||
|
|
||||||
|
.el-upload {
|
||||||
|
width 100%
|
||||||
|
height 80px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-image {
|
||||||
|
height 80px
|
||||||
|
border 1px solid #ffffff
|
||||||
|
border-radius 6px
|
||||||
|
cursor pointer
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border 1px solid #20a0ff
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
color #20a0ff
|
||||||
|
font-size 40px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -7,6 +7,7 @@
|
|||||||
:auto-upload="true"
|
:auto-upload="true"
|
||||||
:show-file-list="false"
|
:show-file-list="false"
|
||||||
:http-request="afterRead"
|
:http-request="afterRead"
|
||||||
|
accept=".png,.jpg,.jpeg,.bmp"
|
||||||
>
|
>
|
||||||
<el-avatar v-if="user.avatar" :src="user.avatar" shape="circle" :size="100"/>
|
<el-avatar v-if="user.avatar" :src="user.avatar" shape="circle" :size="100"/>
|
||||||
<el-icon v-else class="avatar-uploader-icon">
|
<el-icon v-else class="avatar-uploader-icon">
|
||||||
|
@ -187,6 +187,9 @@
|
|||||||
:rows="2"
|
:rows="2"
|
||||||
placeholder="按 Enter 键发送消息,使用 Ctrl + Enter 换行"
|
placeholder="按 Enter 键发送消息,使用 Ctrl + Enter 换行"
|
||||||
/>
|
/>
|
||||||
|
<span class="select-file">
|
||||||
|
<file-select v-if="isLogin" :user-id="loginUser.id" @selected="insertURL"/>
|
||||||
|
</span>
|
||||||
<span class="send-btn">
|
<span class="send-btn">
|
||||||
<el-button @click="sendMessage">
|
<el-button @click="sendMessage">
|
||||||
<el-icon><Promotion/></el-icon>
|
<el-icon><Promotion/></el-icon>
|
||||||
@ -290,6 +293,7 @@ import ConfigDialog from "@/components/ConfigDialog.vue";
|
|||||||
import {checkSession} from "@/action/session";
|
import {checkSession} from "@/action/session";
|
||||||
import Welcome from "@/components/Welcome.vue";
|
import Welcome from "@/components/Welcome.vue";
|
||||||
import ChatMidJourney from "@/components/ChatMidJourney.vue";
|
import ChatMidJourney from "@/components/ChatMidJourney.vue";
|
||||||
|
import FileSelect from "@/components/FileSelect.vue";
|
||||||
|
|
||||||
const title = ref('ChatGPT-智能助手');
|
const title = ref('ChatGPT-智能助手');
|
||||||
const models = ref([])
|
const models = ref([])
|
||||||
@ -875,6 +879,11 @@ const notShow = () => {
|
|||||||
localStorage.setItem(showNoticeKey.value + loginUser.value.username, true)
|
localStorage.setItem(showNoticeKey.value + loginUser.value.username, true)
|
||||||
showDemoNotice.value = false
|
showDemoNotice.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 插入文件路径
|
||||||
|
const insertURL = (url) => {
|
||||||
|
prompt.value += " " + url + " "
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="stylus">
|
<style scoped lang="stylus">
|
||||||
|