mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-11-09 18:53:43 +08:00
支持在 Chat 页面显示,隐藏对话列表
This commit is contained in:
@@ -131,7 +131,8 @@ type SystemConfig struct {
|
|||||||
Title string `json:"title,omitempty"` // 网站标题
|
Title string `json:"title,omitempty"` // 网站标题
|
||||||
Slogan string `json:"slogan,omitempty"` // 网站 slogan
|
Slogan string `json:"slogan,omitempty"` // 网站 slogan
|
||||||
AdminTitle string `json:"admin_title,omitempty"` // 管理后台标题
|
AdminTitle string `json:"admin_title,omitempty"` // 管理后台标题
|
||||||
Logo string `json:"logo,omitempty"` // 方形 Logo
|
Logo string `json:"logo,omitempty"` // 圆形 Logo
|
||||||
|
BarLogo string `json:"bar_logo,omitempty"` // 条形 Logo
|
||||||
InitPower int `json:"init_power,omitempty"` // 新用户注册赠送算力值
|
InitPower int `json:"init_power,omitempty"` // 新用户注册赠送算力值
|
||||||
DailyPower int `json:"daily_power,omitempty"` // 每日签到赠送算力
|
DailyPower int `json:"daily_power,omitempty"` // 每日签到赠送算力
|
||||||
InvitePower int `json:"invite_power,omitempty"` // 邀请新用户赠送算力值
|
InvitePower int `json:"invite_power,omitempty"` // 邀请新用户赠送算力值
|
||||||
|
|||||||
@@ -92,6 +92,8 @@ func (h *ChatHandler) sendOpenAiMessage(
|
|||||||
|
|
||||||
if strings.HasPrefix(req.Model, "o1-") {
|
if strings.HasPrefix(req.Model, "o1-") {
|
||||||
content := fmt.Sprintf("AI 思考结束,耗时:%d 秒。\n\n", time.Now().Unix()-session.Start)
|
content := fmt.Sprintf("AI 思考结束,耗时:%d 秒。\n\n", time.Now().Unix()-session.Start)
|
||||||
|
contents = append(contents, "> AI 正在思考中...\n")
|
||||||
|
contents = append(contents, content)
|
||||||
utils.SendChunkMsg(ws, content)
|
utils.SendChunkMsg(ws, content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ func (h *WebsocketHandler) Client(c *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, chatModel)
|
logger.Error(err, chatModel)
|
||||||
}
|
}
|
||||||
|
session.Model.Id = chatModel.Id
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
h.chatHandler.ReqCancelFunc.Put(clientId, cancel)
|
h.chatHandler.ReqCancelFunc.Put(clientId, cancel)
|
||||||
err = h.chatHandler.sendMessage(ctx, session, chatRole, chatMessage.Content, client)
|
err = h.chatHandler.sendMessage(ctx, session, chatRole, chatMessage.Content, client)
|
||||||
|
|||||||
@@ -8,4 +8,7 @@ VUE_APP_KEY_PREFIX=GeekAI_DEV_
|
|||||||
VUE_APP_TITLE="Geek-AI 创作系统"
|
VUE_APP_TITLE="Geek-AI 创作系统"
|
||||||
VUE_APP_VERSION=v4.1.9
|
VUE_APP_VERSION=v4.1.9
|
||||||
VUE_APP_DOCS_URL=https://docs.geekai.me
|
VUE_APP_DOCS_URL=https://docs.geekai.me
|
||||||
VUE_APP_GIT_URL=https://github.com/yangjian102621/geekai
|
VUE_APP_GITHUB_URL=https://github.com/yangjian102621/geekai
|
||||||
|
VUE_APP_GITEE_URL=https://gitee.com/blackfox/geekai
|
||||||
|
VUE_APP_GITCODE_URL=https://gitcode.com/yangjian102621/geekai
|
||||||
|
|
||||||
|
|||||||
@@ -3,4 +3,6 @@ VUE_APP_WS_HOST=
|
|||||||
VUE_APP_KEY_PREFIX=GeekAI_
|
VUE_APP_KEY_PREFIX=GeekAI_
|
||||||
VUE_APP_VERSION=v4.1.9
|
VUE_APP_VERSION=v4.1.9
|
||||||
VUE_APP_DOCS_URL=https://docs.geekai.me
|
VUE_APP_DOCS_URL=https://docs.geekai.me
|
||||||
VUE_APP_GIT_URL=https://github.com/yangjian102621/geekai
|
VUE_APP_GITHUB_URL=https://github.com/yangjian102621/geekai
|
||||||
|
VUE_APP_GITEE_URL=https://gitee.com/blackfox/geekai
|
||||||
|
VUE_APP_GITCODE_URL=https://gitcode.com/yangjian102621/geekai
|
||||||
|
|||||||
BIN
web/public/images/bar_logo.png
Normal file
BIN
web/public/images/bar_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
@@ -30,14 +30,6 @@
|
|||||||
margin-bottom: 10px
|
margin-bottom: 10px
|
||||||
}
|
}
|
||||||
|
|
||||||
// 隐藏滚动条
|
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
width: 100%
|
width: 100%
|
||||||
overflow-y: scroll
|
overflow-y: scroll
|
||||||
@@ -130,9 +122,9 @@
|
|||||||
.chat-container {
|
.chat-container {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
background-color: var(--el-bg-color)
|
background-color: var(--chat-bg)
|
||||||
color var(--text-fb)
|
color var(--text-fb)
|
||||||
|
|
||||||
.chat-config {
|
.chat-config {
|
||||||
height 50px
|
height 50px
|
||||||
padding 10px 30px
|
padding 10px 30px
|
||||||
@@ -186,54 +178,33 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
position relative
|
position relative
|
||||||
background: var(--chat-bg)
|
background: var(--chat-bg)
|
||||||
|
display: flex;
|
||||||
::-webkit-scrollbar {
|
justify-content: center;
|
||||||
width: 12px /* 滚动条宽度 */
|
padding 0 20px
|
||||||
background #F1F1F1
|
max-width: 960px;
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
|
||||||
background-color: #e1e1e1;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
background-color: #c1c1c1;
|
|
||||||
border-radius 12px
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb:hover {
|
|
||||||
background-color: #A8A8A8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-box {
|
.chat-box {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
//border-bottom: 1px solid #4f4f4f
|
|
||||||
scrollbar-width: none; /* 隐藏滚动条(Firefox) */
|
|
||||||
-ms-overflow-style: none; /* 隐藏滚动条(IE、Edge) */
|
|
||||||
|
|
||||||
// 变量定义
|
// 变量定义
|
||||||
--content-font-size: 16px;
|
--content-font-size: 16px;
|
||||||
--content-color: #c1c1c1;
|
--content-color: #c1c1c1;
|
||||||
|
|
||||||
font-family: 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
|
font-family: 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
|
||||||
padding: 0 0 50px 0;
|
//padding: 0 0 50px 0;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
.chat-line {
|
.chat-line {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
::-webkit-scrollbar {
|
|
||||||
display: none; /* 隐藏滚动条(Webkit 浏览器) */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-box {
|
.input-box {
|
||||||
position absolute
|
position absolute
|
||||||
bottom 0
|
bottom 0
|
||||||
width 100%
|
width 100%
|
||||||
|
max-width: 800px;
|
||||||
|
|
||||||
.input-box-inner {
|
.input-box-inner {
|
||||||
display flex
|
display flex
|
||||||
@@ -363,11 +334,6 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#container::-webkit-scrollbar {
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,30 @@
|
|||||||
.layout{
|
.layout {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
.big-top-title{
|
|
||||||
|
.big-top-title {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
}
|
}
|
||||||
.top-collapse{
|
|
||||||
|
.top-collapse {
|
||||||
padding-top: 10px
|
padding-top: 10px
|
||||||
img{
|
|
||||||
|
img {
|
||||||
width 24px !important
|
width 24px !important
|
||||||
height: 24px !important
|
height: 24px !important
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.tab-box{
|
|
||||||
|
.tab-box {
|
||||||
align-items: center
|
align-items: center
|
||||||
background-color: var(--card-bg)
|
background-color: var(--card-bg)
|
||||||
|
border-right: 1px solid var(--line-box);
|
||||||
// height: 100%
|
// height: 100%
|
||||||
// position: fixed;
|
// position: fixed;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
.title{
|
|
||||||
|
.title {
|
||||||
font-size: 28px
|
font-size: 28px
|
||||||
height: 40px
|
height: 40px
|
||||||
width 120px
|
width 120px
|
||||||
@@ -26,106 +32,100 @@
|
|||||||
word-wrap break-all;
|
word-wrap break-all;
|
||||||
overflow hidden
|
overflow hidden
|
||||||
font-weight: 700
|
font-weight: 700
|
||||||
color:var(--text-theme-color)
|
color: var(--text-theme-color)
|
||||||
}
|
}
|
||||||
img{
|
|
||||||
|
img {
|
||||||
height: 44px
|
height: 44px
|
||||||
object-fit: cover
|
object-fit: cover
|
||||||
border-radius: 50%
|
border-radius: 50%
|
||||||
border: 2px solid #754ff6;
|
border: 2px solid #754ff6;
|
||||||
background: #fff
|
background: #fff
|
||||||
}
|
}
|
||||||
.marr{
|
|
||||||
|
.marr {
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.flex-center-col{
|
|
||||||
|
.flex-center-col {
|
||||||
display flex
|
display flex
|
||||||
align-items center
|
align-items center
|
||||||
flex-direction column
|
flex-direction column
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
font-size 22px
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-expand {
|
|
||||||
font-size 24px
|
font-size 24px
|
||||||
margin-bottom 10px
|
|
||||||
cursor pointer
|
cursor pointer
|
||||||
color var(--text-color)
|
color var(--text-color)
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-colspan {
|
.icon-new-chat {
|
||||||
font-size 18px
|
color #ffffff
|
||||||
margin-left 3px
|
|
||||||
cursor pointer
|
|
||||||
color var(--text-color)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.menu-list-collapse{
|
|
||||||
.flex-center-col{
|
.menu-list-collapse {
|
||||||
|
.flex-center-col {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
.menu-list-item{
|
|
||||||
|
.menu-list-item {
|
||||||
|
|
||||||
height: 38px;
|
height: 38px;
|
||||||
line-height: 38px;
|
line-height: 38px;
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
font-size 16px
|
font-size 16px
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-list-item:hover,
|
.menu-list-item:hover,
|
||||||
.active{
|
.active {
|
||||||
background: rgba(79, 89, 102, .122);
|
background: rgba(79, 89, 102, .122);
|
||||||
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
.el-icon{
|
|
||||||
|
.el-icon {
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.menu-title{
|
|
||||||
|
.menu-title {
|
||||||
font-size: 15px !important;
|
font-size: 15px !important;
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu-list {
|
||||||
|
width: 65px;
|
||||||
|
|
||||||
.openicon{
|
.svg-icon {
|
||||||
font-size: 40px;
|
svg {
|
||||||
color: #754ff6;
|
|
||||||
}
|
|
||||||
.menuIcon{
|
|
||||||
.openicon{
|
|
||||||
font-size: 28px;
|
|
||||||
color: #754ff6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.menu-list{
|
|
||||||
margin-top: 20px;
|
|
||||||
.svg-icon{
|
|
||||||
svg{
|
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.menu-list-item{
|
|
||||||
|
.menu-list-item {
|
||||||
// margin-bottom: 10px;
|
// margin-bottom: 10px;
|
||||||
margin: 0 8px 8px;
|
margin: 0 8px 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-weight: 550;
|
font-weight: 550;
|
||||||
&:hover{
|
color: var(--text-theme-color);
|
||||||
.el-icon{
|
|
||||||
|
&:hover {
|
||||||
|
.el-icon {
|
||||||
background: rgba(79, 89, 102, .122);
|
background: rgba(79, 89, 102, .122);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.el-icon{
|
|
||||||
|
.el-icon {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
@@ -136,96 +136,99 @@
|
|||||||
// width: 24px;
|
// width: 24px;
|
||||||
// height: 24px;
|
// height: 24px;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
&.active{
|
|
||||||
color: var(--text-color);
|
&.active {
|
||||||
|
color: var(--text-theme-color);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
filter: none !important;
|
|
||||||
.el-icon{
|
|
||||||
background: rgba(79, 89, 102, .122);
|
|
||||||
filter: invert(100%);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
.bot{
|
|
||||||
|
.bot {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 6px;
|
bottom: 6px;
|
||||||
|
width 65px;
|
||||||
|
|
||||||
}
|
}
|
||||||
.bot-line{
|
|
||||||
|
.bot-line {
|
||||||
width : 100%;
|
|
||||||
|
width: 100%;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
background: var(--line-box)
|
background: var(--line-box)
|
||||||
margin: 20px 0 10px 0;
|
margin: 20px 0 10px 0;
|
||||||
}
|
}
|
||||||
.menu-title{
|
|
||||||
|
.menu-title {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-house,
|
.icon-house,
|
||||||
.icon-github{
|
.icon-github {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
color: #754ff6;
|
color: #754ff6;
|
||||||
cursor pointer
|
cursor pointer
|
||||||
}
|
}
|
||||||
.menu-bot-item{
|
|
||||||
display: flex;
|
.menu-bot-item {
|
||||||
align-items: center;
|
display: flex;
|
||||||
justify-content: space-around;
|
align-items: center;
|
||||||
align-items: center;
|
justify-content: space-around;
|
||||||
a{
|
|
||||||
// margin-right: 46px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
::v-deep(.theme-box){
|
|
||||||
|
::v-deep(.theme-box) {
|
||||||
position: relative !important;
|
position: relative !important;
|
||||||
right: initial;
|
right: initial;
|
||||||
bottom: initial;
|
bottom: initial;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
line-height: 20px;
|
line-height: 18px;
|
||||||
.iconfont{
|
|
||||||
font-size: 15px !important;}
|
.iconfont {
|
||||||
|
font-size: 15px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.right-main{
|
|
||||||
|
.right-main {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
// background: #f5f7fd;
|
// background: #f5f7fd;
|
||||||
background: var(--theme-bg-all);
|
background: var(--theme-bg-all);
|
||||||
// background-image: linear-gradient(180deg, rgba(247, 232, 255, .54), rgba(191, 223, 255, .35));
|
// background-image: linear-gradient(180deg, rgba(247, 232, 255, .54), rgba(191, 223, 255, .35));
|
||||||
width: 100%;
|
width: 100%;
|
||||||
.loginMask{
|
|
||||||
|
.loginMask {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
}
|
}
|
||||||
.topheader{
|
|
||||||
|
.topheader {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 8px;
|
right: 8px;
|
||||||
z-index : 999;
|
z-index: 999;
|
||||||
top:0;
|
top: 0;
|
||||||
// width 100%;
|
// width 100%;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
.btn-go{
|
|
||||||
|
.btn-go {
|
||||||
background: #754ff6;
|
background: #754ff6;
|
||||||
margin: 10px 10px 0;
|
margin: 10px 10px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.el-popper {
|
.el-popper {
|
||||||
.more-menus {
|
.more-menus {
|
||||||
li {
|
li {
|
||||||
@@ -251,41 +254,48 @@
|
|||||||
background: rgba(79, 89, 102, 0.1);
|
background: rgba(79, 89, 102, 0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.setting-menus{
|
|
||||||
.title{
|
.setting-menus {
|
||||||
|
.title {
|
||||||
color: #222226;
|
color: #222226;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-icon,
|
.el-icon,
|
||||||
.iconfont{
|
.iconfont {
|
||||||
font-size: 18px
|
font-size: 18px
|
||||||
margin-right: 6px
|
margin-right: 6px
|
||||||
}
|
}
|
||||||
color: #222226;
|
color: #222226;
|
||||||
}
|
}
|
||||||
.username{
|
|
||||||
display: -webkit-box;
|
.username {
|
||||||
-webkit-box-orient: vertical;
|
display: -webkit-box;
|
||||||
overflow: hidden;
|
-webkit-box-orient: vertical;
|
||||||
-webkit-line-clamp: 1;
|
overflow: hidden;
|
||||||
|
-webkit-line-clamp: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
.rightHeightMax{
|
|
||||||
|
.rightHeightMax {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
max-height: 100vh;
|
max-height: 100vh;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
}
|
}
|
||||||
.rightHeight{
|
|
||||||
|
.rightHeight {
|
||||||
height: calc(100vh - 42px);
|
height: calc(100vh - 42px);
|
||||||
max-height: calc(100vh - 42px);
|
max-height: calc(100vh - 42px);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
.content{
|
|
||||||
|
.content {
|
||||||
padding-top: 42px;
|
padding-top: 42px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.content{
|
|
||||||
|
.content {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
--el-bg-color-overlay: rgba(17, 28, 68, 1);
|
--el-bg-color-overlay: rgba(17, 28, 68, 1);
|
||||||
--el-border-color-light: rgba(255, 255, 255, 0.2);
|
--el-border-color-light: rgba(255, 255, 255, 0.2);
|
||||||
--chat-content-bg:rgba(86, 86, 95, .2);
|
--chat-content-bg:rgba(86, 86, 95, .2);
|
||||||
--chat-content-bg-list:rgba(86, 86, 95, .2);
|
--chat-user-content-bg: #762AA4;
|
||||||
--hover-deep-color:#30323c;
|
--hover-deep-color:#30323c;
|
||||||
//layout
|
//layout
|
||||||
.more-menus li.moreTitle,
|
.more-menus li.moreTitle,
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
.setting-menus li .el-icon,
|
.setting-menus li .el-icon,
|
||||||
.setting-menus li .iconfont,
|
.setting-menus li .iconfont,
|
||||||
.layout .tab-box .menu-list-item{
|
.layout .tab-box .menu-list-item{
|
||||||
filter: invert(100%);
|
//filter: invert(100%);
|
||||||
}
|
}
|
||||||
.more-menus span.title{
|
.more-menus span.title{
|
||||||
color:#000;
|
color:#000;
|
||||||
|
|||||||
@@ -31,8 +31,8 @@
|
|||||||
--theme-text-primary: #000;
|
--theme-text-primary: #000;
|
||||||
--theme-text-color-secondary: #666;
|
--theme-text-color-secondary: #666;
|
||||||
--chat-content-bg:#f5f7fc;
|
--chat-content-bg:#f5f7fc;
|
||||||
|
--chat-user-content-bg: #e0dfff;
|
||||||
--chat-list-bg: #0302020a;
|
--chat-list-bg: #0302020a;
|
||||||
--chat-content-bg-list:#fff;
|
|
||||||
--chat-wel-bg:rgba(247, 247, 248, 1);
|
--chat-wel-bg:rgba(247, 247, 248, 1);
|
||||||
--hover-deep-color:#fff;
|
--hover-deep-color:#fff;
|
||||||
--el-bg-color-overlay: #fff;
|
--el-bg-color-overlay: #fff;
|
||||||
|
|||||||
@@ -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=1734934068681') format('woff2'),
|
src: url('iconfont.woff2?t=1736144380052') format('woff2'),
|
||||||
url('iconfont.woff?t=1734934068681') format('woff'),
|
url('iconfont.woff?t=1736144380052') format('woff'),
|
||||||
url('iconfont.ttf?t=1734934068681') format('truetype');
|
url('iconfont.ttf?t=1736144380052') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
@@ -13,6 +13,10 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-gitee:before {
|
||||||
|
content: "\e6d0";
|
||||||
|
}
|
||||||
|
|
||||||
.icon-redeem:before {
|
.icon-redeem:before {
|
||||||
content: "\e61a";
|
content: "\e61a";
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -5,6 +5,13 @@
|
|||||||
"css_prefix_text": "icon-",
|
"css_prefix_text": "icon-",
|
||||||
"description": "",
|
"description": "",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "6905420",
|
||||||
|
"name": "码云",
|
||||||
|
"font_class": "gitee",
|
||||||
|
"unicode": "e6d0",
|
||||||
|
"unicode_decimal": 59088
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"icon_id": "3624396",
|
"icon_id": "3624396",
|
||||||
"name": "兑换码",
|
"name": "兑换码",
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,22 +2,25 @@
|
|||||||
<div class="chat-line chat-line-prompt-list" v-if="listStyle === 'list'">
|
<div class="chat-line chat-line-prompt-list" v-if="listStyle === 'list'">
|
||||||
<div class="chat-line-inner">
|
<div class="chat-line-inner">
|
||||||
<div class="chat-icon">
|
<div class="chat-icon">
|
||||||
<img :src="data.icon" alt="User" />
|
<img :src="data.icon" alt="User"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="chat-item">
|
<div class="chat-item">
|
||||||
<div v-if="files.length > 0" class="file-list-box">
|
<div v-if="files.length > 0" class="file-list-box">
|
||||||
<div v-for="file in files">
|
<div v-for="file in files">
|
||||||
<div class="image" v-if="isImage(file.ext)">
|
<div class="image" v-if="isImage(file.ext)">
|
||||||
<el-image :src="file.url" fit="cover" />
|
<el-image :src="file.url" fit="cover"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="item" v-else>
|
<div class="item" v-else>
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<el-image :src="GetFileIcon(file.ext)" fit="cover" />
|
<el-image :src="GetFileIcon(file.ext)" fit="cover"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<el-link :href="file.url" target="_blank" style="--el-font-weight-primary: bold">{{ file.name }}</el-link>
|
<el-link :href="file.url" target="_blank" style="--el-font-weight-primary: bold">{{
|
||||||
|
file.name
|
||||||
|
}}
|
||||||
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<span>{{ GetFileType(file.ext) }}</span>
|
<span>{{ GetFileType(file.ext) }}</span>
|
||||||
@@ -30,7 +33,7 @@
|
|||||||
<div class="content" v-html="content"></div>
|
<div class="content" v-html="content"></div>
|
||||||
<div class="bar" v-if="data.created_at > 0">
|
<div class="bar" v-if="data.created_at > 0">
|
||||||
<span class="bar-item"
|
<span class="bar-item"
|
||||||
><el-icon><Clock /></el-icon> {{ dateFormat(data.created_at) }}</span
|
><el-icon><Clock/></el-icon> {{ dateFormat(data.created_at) }}</span
|
||||||
>
|
>
|
||||||
<span class="bar-item">tokens: {{ finalTokens }}</span>
|
<span class="bar-item">tokens: {{ finalTokens }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -41,22 +44,25 @@
|
|||||||
<div class="chat-line chat-line-prompt-chat" v-else>
|
<div class="chat-line chat-line-prompt-chat" v-else>
|
||||||
<div class="chat-line-inner">
|
<div class="chat-line-inner">
|
||||||
<div class="chat-icon">
|
<div class="chat-icon">
|
||||||
<img :src="data.icon" alt="User" />
|
<img :src="data.icon" alt="User"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="chat-item">
|
<div class="chat-item">
|
||||||
<div v-if="files.length > 0" class="file-list-box">
|
<div v-if="files.length > 0" class="file-list-box">
|
||||||
<div v-for="file in files">
|
<div v-for="file in files">
|
||||||
<div class="image" v-if="isImage(file.ext)">
|
<div class="image" v-if="isImage(file.ext)">
|
||||||
<el-image :src="file.url" fit="cover" />
|
<el-image :src="file.url" fit="cover"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="item" v-else>
|
<div class="item" v-else>
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<el-image :src="GetFileIcon(file.ext)" fit="cover" />
|
<el-image :src="GetFileIcon(file.ext)" fit="cover"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<el-link :href="file.url" target="_blank" style="--el-font-weight-primary: bold">{{ file.name }}</el-link>
|
<el-link :href="file.url" target="_blank" style="--el-font-weight-primary: bold">{{
|
||||||
|
file.name
|
||||||
|
}}
|
||||||
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<span>{{ GetFileType(file.ext) }}</span>
|
<span>{{ GetFileType(file.ext) }}</span>
|
||||||
@@ -71,7 +77,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="bar" v-if="data.created_at > 0">
|
<div class="bar" v-if="data.created_at > 0">
|
||||||
<span class="bar-item"
|
<span class="bar-item"
|
||||||
><el-icon><Clock /></el-icon> {{ dateFormat(data.created_at) }}</span
|
><el-icon><Clock/></el-icon> {{ dateFormat(data.created_at) }}</span
|
||||||
>
|
>
|
||||||
<!-- <span class="bar-item">tokens: {{ finalTokens }}</span>-->
|
<!-- <span class="bar-item">tokens: {{ finalTokens }}</span>-->
|
||||||
</div>
|
</div>
|
||||||
@@ -81,12 +87,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref } from "vue";
|
import {onMounted, ref} from "vue";
|
||||||
import { Clock } from "@element-plus/icons-vue";
|
import {Clock} from "@element-plus/icons-vue";
|
||||||
import { httpPost } from "@/utils/http";
|
import {httpPost} from "@/utils/http";
|
||||||
import hl from "highlight.js";
|
import hl from "highlight.js";
|
||||||
import { dateFormat, isImage, processPrompt } from "@/utils/libs";
|
import {dateFormat, isImage, processPrompt} from "@/utils/libs";
|
||||||
import { FormatFileSize, GetFileIcon, GetFileType } from "@/store/system";
|
import {FormatFileSize, GetFileIcon, GetFileType} from "@/store/system";
|
||||||
import emoji from "markdown-it-emoji";
|
import emoji from "markdown-it-emoji";
|
||||||
import mathjaxPlugin from "markdown-it-mathjax3";
|
import mathjaxPlugin from "markdown-it-mathjax3";
|
||||||
import MarkdownIt from "markdown-it";
|
import MarkdownIt from "markdown-it";
|
||||||
@@ -101,8 +107,8 @@ const md = new MarkdownIt({
|
|||||||
// 显示复制代码按钮
|
// 显示复制代码按钮
|
||||||
const copyBtn = `<span class="copy-code-btn" data-clipboard-action="copy" data-clipboard-target="#copy-target-${codeIndex}">复制</span>
|
const copyBtn = `<span class="copy-code-btn" data-clipboard-action="copy" data-clipboard-target="#copy-target-${codeIndex}">复制</span>
|
||||||
<textarea style="position: absolute;top: -9999px;left: -9999px;z-index: -9999;" id="copy-target-${codeIndex}">${str.replace(
|
<textarea style="position: absolute;top: -9999px;left: -9999px;z-index: -9999;" id="copy-target-${codeIndex}">${str.replace(
|
||||||
/<\/textarea>/g,
|
/<\/textarea>/g,
|
||||||
"</textarea>"
|
"</textarea>"
|
||||||
)}</textarea>`;
|
)}</textarea>`;
|
||||||
if (lang && hl.getLanguage(lang)) {
|
if (lang && hl.getLanguage(lang)) {
|
||||||
const langHtml = `<span class="lang-name">${lang}</span>`;
|
const langHtml = `<span class="lang-name">${lang}</span>`;
|
||||||
@@ -152,17 +158,18 @@ const processFiles = () => {
|
|||||||
const linkRegex = /(https?:\/\/\S+)/g;
|
const linkRegex = /(https?:\/\/\S+)/g;
|
||||||
const links = props.data.content.match(linkRegex);
|
const links = props.data.content.match(linkRegex);
|
||||||
if (links) {
|
if (links) {
|
||||||
httpPost("/api/upload/list", { urls: links })
|
httpPost("/api/upload/list", {urls: links})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
files.value = res.data.items;
|
files.value = res.data.items;
|
||||||
|
|
||||||
for (let link of links) {
|
for (let link of links) {
|
||||||
if (isExternalImg(link, files.value)) {
|
if (isExternalImg(link, files.value)) {
|
||||||
files.value.push({ url: link, ext: ".png" });
|
files.value.push({url: link, ext: ".png"});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
.catch(() => {
|
||||||
.catch(() => {});
|
});
|
||||||
|
|
||||||
for (let link of links) {
|
for (let link of links) {
|
||||||
content.value = content.value.replace(link, "");
|
content.value = content.value.replace(link, "");
|
||||||
@@ -177,11 +184,11 @@ const isExternalImg = (link, files) => {
|
|||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
@import '@/assets/css/markdown/vue.css';
|
@import '@/assets/css/markdown/vue.css';
|
||||||
.chat-page,.chat-export {
|
.chat-page, .chat-export {
|
||||||
.chat-line-prompt-list {
|
.chat-line-prompt-list {
|
||||||
|
|
||||||
background-color:var( --chat-content-bg-list);
|
background-color: var(--chat-content-bg-list);
|
||||||
color:var(--theme-text-color-primary);
|
color: var(--theme-text-color-primary);
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width 100%
|
width 100%
|
||||||
padding-bottom: 1.5rem;
|
padding-bottom: 1.5rem;
|
||||||
@@ -213,6 +220,7 @@ const isExternalImg = (link, files) => {
|
|||||||
.file-list-box {
|
.file-list-box {
|
||||||
display flex
|
display flex
|
||||||
flex-flow column
|
flex-flow column
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
display flex
|
display flex
|
||||||
flex-flow row
|
flex-flow row
|
||||||
@@ -225,13 +233,14 @@ const isExternalImg = (link, files) => {
|
|||||||
margin-bottom 10px
|
margin-bottom 10px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
display flex
|
display flex
|
||||||
flex-flow row
|
flex-flow row
|
||||||
border-radius 10px
|
border-radius 10px
|
||||||
background-color:var(--chat-content-bg);
|
background-color: var(--chat-content-bg);
|
||||||
border 1px solid #e3e3e3
|
border 1px solid #e3e3e3
|
||||||
color:var(--theme-text-color-primary);
|
color: var(--theme-text-color-primary);
|
||||||
padding 6px
|
padding 6px
|
||||||
margin-bottom 10px
|
margin-bottom 10px
|
||||||
|
|
||||||
@@ -241,14 +250,17 @@ const isExternalImg = (link, files) => {
|
|||||||
height 40px
|
height 40px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.body {
|
.body {
|
||||||
margin-left 8px
|
margin-left 8px
|
||||||
font-size 14px
|
font-size 14px
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-weight bold
|
font-weight bold
|
||||||
line-height 24px
|
line-height 24px
|
||||||
color #0D0D0D
|
color #0D0D0D
|
||||||
}
|
}
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
color #B4B4B4
|
color #B4B4B4
|
||||||
|
|
||||||
@@ -263,7 +275,7 @@ const isExternalImg = (link, files) => {
|
|||||||
.content {
|
.content {
|
||||||
word-break break-word;
|
word-break break-word;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
color:var(--theme-text-color-primary);
|
color: var(--theme-text-color-primary);
|
||||||
font-size: var(--content-font-size);
|
font-size: var(--content-font-size);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
@@ -336,11 +348,12 @@ const isExternalImg = (link, files) => {
|
|||||||
.chat-item {
|
.chat-item {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
max-width 60%
|
max-width calc(100% - 110px);
|
||||||
|
|
||||||
.file-list-box {
|
.file-list-box {
|
||||||
display flex
|
display flex
|
||||||
flex-flow column
|
flex-flow column
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
display flex
|
display flex
|
||||||
flex-flow row
|
flex-flow row
|
||||||
@@ -353,12 +366,13 @@ const isExternalImg = (link, files) => {
|
|||||||
margin-bottom 10px
|
margin-bottom 10px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
display flex
|
display flex
|
||||||
flex-flow row
|
flex-flow row
|
||||||
border-radius 10px
|
border-radius 10px
|
||||||
background-color:var(--chat-content-bg);
|
background-color: var(--chat-content-bg);
|
||||||
color:var(--theme-text-color-primary);
|
color: var(--theme-text-color-primary);
|
||||||
border 1px solid #e3e3e3
|
border 1px solid #e3e3e3
|
||||||
padding 6px
|
padding 6px
|
||||||
margin-bottom 10px
|
margin-bottom 10px
|
||||||
@@ -369,14 +383,17 @@ const isExternalImg = (link, files) => {
|
|||||||
height 40px
|
height 40px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.body {
|
.body {
|
||||||
margin-left 8px
|
margin-left 8px
|
||||||
font-size 14px
|
font-size 14px
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-weight bold
|
font-weight bold
|
||||||
line-height 24px
|
line-height 24px
|
||||||
color #0D0D0D
|
color #0D0D0D
|
||||||
}
|
}
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
color #B4B4B4
|
color #B4B4B4
|
||||||
|
|
||||||
@@ -392,35 +409,37 @@ const isExternalImg = (link, files) => {
|
|||||||
.content-wrapper {
|
.content-wrapper {
|
||||||
display flex
|
display flex
|
||||||
flex-flow row-reverse
|
flex-flow row-reverse
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
word-break break-word;
|
word-break break-word;
|
||||||
padding: 1rem
|
padding: 1rem
|
||||||
color var(--theme-text-primary);
|
color var(--theme-text-primary);
|
||||||
font-size: var(--content-font-size);
|
font-size: var(--content-font-size);
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background-color :var(--chat-content-bg);
|
background-color: var(--chat-user-content-bg);
|
||||||
border-radius: 10px 0 10px 10px;
|
border-radius: 10px 0 10px 10px;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
margin 10px 0
|
margin 10px 0
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
line-height 1.5
|
|
||||||
}
|
|
||||||
|
|
||||||
p:last-child {
|
|
||||||
margin-bottom: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
p:first-child {
|
|
||||||
margin-top 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
line-height 1.5
|
||||||
|
}
|
||||||
|
|
||||||
|
p:last-child {
|
||||||
|
margin-bottom: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
p:first-child {
|
||||||
|
margin-top 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.bar {
|
.bar {
|
||||||
padding 10px 10px 10px 0;
|
padding 10px 10px 10px 0;
|
||||||
|
|
||||||
|
|||||||
@@ -90,9 +90,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Clock, DocumentCopy, Refresh } from "@element-plus/icons-vue";
|
import {Clock, DocumentCopy, Refresh} from "@element-plus/icons-vue";
|
||||||
import { ElMessage } from "element-plus";
|
import {ElMessage} from "element-plus";
|
||||||
import { dateFormat, processContent } from "@/utils/libs";
|
import {dateFormat, processContent} from "@/utils/libs";
|
||||||
import hl from "highlight.js";
|
import hl from "highlight.js";
|
||||||
import emoji from "markdown-it-emoji";
|
import emoji from "markdown-it-emoji";
|
||||||
import mathjaxPlugin from "markdown-it-mathjax3";
|
import mathjaxPlugin from "markdown-it-mathjax3";
|
||||||
@@ -237,7 +237,6 @@ const reGenerate = (prompt) => {
|
|||||||
table {
|
table {
|
||||||
width 100%
|
width 100%
|
||||||
margin-bottom 1rem
|
margin-bottom 1rem
|
||||||
color #212529
|
|
||||||
border-collapse collapse;
|
border-collapse collapse;
|
||||||
border 1px solid #dee2e6;
|
border 1px solid #dee2e6;
|
||||||
background-color:var(--chat-content-bg);
|
background-color:var(--chat-content-bg);
|
||||||
@@ -266,7 +265,7 @@ const reGenerate = (prompt) => {
|
|||||||
padding: 0.8rem 1.5rem;
|
padding: 0.8rem 1.5rem;
|
||||||
color: var(--quote-text-color);
|
color: var(--quote-text-color);
|
||||||
border-left: 0.4rem solid #6b50e1; /* 紫色边框 */
|
border-left: 0.4rem solid #6b50e1; /* 紫色边框 */
|
||||||
font-size: 1.1rem;
|
font-size: 16px;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,7 +274,7 @@ const reGenerate = (prompt) => {
|
|||||||
|
|
||||||
.chat-line-reply-list {
|
.chat-line-reply-list {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background-color: var(--chat-list-bg);
|
background-color: var(--chat-content-bg);
|
||||||
color:var(--theme-text-color-primary);
|
color:var(--theme-text-color-primary);
|
||||||
width 100%
|
width 100%
|
||||||
padding-bottom: 1.5rem;
|
padding-bottom: 1.5rem;
|
||||||
@@ -376,7 +375,8 @@ const reGenerate = (prompt) => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
max-width 70%
|
width 100%
|
||||||
|
max-width calc(100% - 110px)
|
||||||
|
|
||||||
.content-wrapper {
|
.content-wrapper {
|
||||||
display flex
|
display flex
|
||||||
@@ -391,6 +391,7 @@ const reGenerate = (prompt) => {
|
|||||||
// background-color #F5F5F5
|
// background-color #F5F5F5
|
||||||
background-color :var(--chat-content-bg);
|
background-color :var(--chat-content-bg);
|
||||||
border-radius: 0 10px 10px 10px;
|
border-radius: 0 10px 10px 10px;
|
||||||
|
width 100%
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,14 +45,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { reactive, ref } from "vue";
|
import {reactive, ref} from "vue";
|
||||||
import { ElMessage } from "element-plus";
|
import {ElMessage} from "element-plus";
|
||||||
import { httpGet, httpPost } from "@/utils/http";
|
import {httpGet, httpPost} from "@/utils/http";
|
||||||
import { Delete, Plus } from "@element-plus/icons-vue";
|
import {Delete, Plus} from "@element-plus/icons-vue";
|
||||||
import { isImage, removeArrayItem } from "@/utils/libs";
|
import {isImage, removeArrayItem} from "@/utils/libs";
|
||||||
import { GetFileIcon } from "@/store/system";
|
import {GetFileIcon} from "@/store/system";
|
||||||
import { checkSession } from "@/store/cache";
|
import {checkSession} from "@/store/cache";
|
||||||
import { useSharedStore } from "@/store/sharedata";
|
import {useSharedStore} from "@/store/sharedata";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
userId: Number,
|
userId: Number,
|
||||||
});
|
});
|
||||||
@@ -151,6 +152,7 @@ const insertURL = (file) => {
|
|||||||
.file-upload-img {
|
.file-upload-img {
|
||||||
.iconfont {
|
.iconfont {
|
||||||
font-size: 19px;
|
font-size: 19px;
|
||||||
|
cursor pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,14 +14,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import {ref} from "vue";
|
||||||
import { httpGet } from "@/utils/http";
|
import {showMessageError} from "@/utils/dialog";
|
||||||
import { showMessageError } from "@/utils/dialog";
|
import {getLicenseInfo, getSystemInfo} from "@/store/cache";
|
||||||
import { getLicenseInfo, getSystemInfo } from "@/store/cache";
|
|
||||||
|
|
||||||
const title = ref("");
|
const title = ref("");
|
||||||
const version = ref(process.env.VUE_APP_VERSION);
|
const version = ref(process.env.VUE_APP_VERSION);
|
||||||
const gitURL = ref(process.env.VUE_APP_GIT_URL);
|
const gitURL = ref(process.env.VUE_APP_GITHUB_URL);
|
||||||
const copyRight = ref("");
|
const copyRight = ref("");
|
||||||
const license = ref({});
|
const license = ref({});
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="theme-box" @click="toggleTheme">
|
<div class="theme-box" @click="toggleTheme">
|
||||||
<span class="iconfont icon-yueliang">{{ themePage === "light" ? "" : "" }}</span>
|
<i class="iconfont" :class="themePage === 'light'?'icon-yueliang':'icon-taiyang'"></i>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref } from "vue";
|
import {ref} from "vue";
|
||||||
import { useSharedStore } from "@/store/sharedata";
|
import {useSharedStore} from "@/store/sharedata";
|
||||||
|
|
||||||
// 定义主题状态,初始值从 localStorage 获取
|
// 定义主题状态,初始值从 localStorage 获取
|
||||||
const store = useSharedStore();
|
const store = useSharedStore();
|
||||||
|
|||||||
@@ -58,9 +58,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref } from "vue";
|
import {onMounted, ref} from "vue";
|
||||||
import { ElMessage } from "element-plus";
|
import {ElMessage} from "element-plus";
|
||||||
import { getSystemInfo } from "@/store/cache";
|
import {getSystemInfo} from "@/store/cache";
|
||||||
|
|
||||||
const title = ref(process.env.VUE_APP_TITLE);
|
const title = ref(process.env.VUE_APP_TITLE);
|
||||||
const version = ref(process.env.VUE_APP_VERSION);
|
const version = ref(process.env.VUE_APP_VERSION);
|
||||||
@@ -132,7 +132,7 @@ const send = (text) => {
|
|||||||
line-height: 2.5rem
|
line-height: 2.5rem
|
||||||
font-weight 600
|
font-weight 600
|
||||||
margin-bottom: 4rem
|
margin-bottom: 4rem
|
||||||
color var( --theme-textcolor-normal)
|
color var(--text-color)
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-content {
|
.grid-content {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { defineStore } from "pinia";
|
import {defineStore} from "pinia";
|
||||||
import Storage from "good-storage";
|
import Storage from "good-storage";
|
||||||
|
|
||||||
export const useSharedStore = defineStore("shared", {
|
export const useSharedStore = defineStore("shared", {
|
||||||
@@ -9,6 +9,7 @@ export const useSharedStore = defineStore("shared", {
|
|||||||
socket: { conn: null, handlers: {} },
|
socket: { conn: null, handlers: {} },
|
||||||
theme: Storage.get("theme", "light"),
|
theme: Storage.get("theme", "light"),
|
||||||
isLogin: false,
|
isLogin: false,
|
||||||
|
chatListExtend: Storage.get("chat_list_extend", true),
|
||||||
}),
|
}),
|
||||||
getters: {},
|
getters: {},
|
||||||
actions: {
|
actions: {
|
||||||
@@ -29,6 +30,10 @@ export const useSharedStore = defineStore("shared", {
|
|||||||
}
|
}
|
||||||
this.socket.conn = value;
|
this.socket.conn = value;
|
||||||
},
|
},
|
||||||
|
setChatListExtend(value) {
|
||||||
|
this.chatListExtend = value;
|
||||||
|
Storage.set("chat_list_extend", value);
|
||||||
|
},
|
||||||
addMessageHandler(key, callback) {
|
addMessageHandler(key, callback) {
|
||||||
if (!this.socket.handlers[key]) {
|
if (!this.socket.handlers[key]) {
|
||||||
this.socket.handlers[key] = callback;
|
this.socket.handlers[key] = callback;
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="chat-page">
|
<div class="chat-page">
|
||||||
<el-container>
|
<el-container>
|
||||||
<el-aside>
|
<el-aside v-show="store.chatListExtend">
|
||||||
|
<div class="flex w-full justify-center pt-3 pb-3">
|
||||||
|
<img :src="logo" style="max-height: 40px" :alt="title" v-if="logo !== ''"/>
|
||||||
|
<h2 v-else>{{ title }}</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="media-page">
|
<div class="media-page">
|
||||||
<el-button @click="_newChat" type="primary" class="newChat">
|
<el-button @click="_newChat" type="primary" class="newChat">
|
||||||
<el-icon style="margin-right: 5px">
|
<i class="iconfont icon-new-chat mr-1"></i>
|
||||||
<Plus />
|
|
||||||
</el-icon>
|
|
||||||
新建对话
|
新建对话
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
@@ -19,7 +22,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</div>
|
</div>
|
||||||
<el-scrollbar :height="chatBoxHeight">
|
<el-scrollbar :height="chatListHeight">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<el-row v-for="chat in chatList" :key="chat.chat_id">
|
<el-row v-for="chat in chatList" :key="chat.chat_id">
|
||||||
<div :class="chat.chat_id === chatId ? 'chat-list-item active' : 'chat-list-item'" @click="loadChat(chat)">
|
<div :class="chat.chat_id === chatId ? 'chat-list-item active' : 'chat-list-item'" @click="loadChat(chat)">
|
||||||
@@ -111,7 +114,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="flex justify-center">
|
||||||
<div id="container" :style="{ height: mainWinHeight + 'px' }">
|
<div id="container" :style="{ height: mainWinHeight + 'px' }">
|
||||||
<div class="chat-box" id="chat-box" :style="{ height: chatBoxHeight + 'px' }">
|
<div class="chat-box" id="chat-box" :style="{ height: chatBoxHeight + 'px' }">
|
||||||
<div v-if="showHello">
|
<div v-if="showHello">
|
||||||
@@ -229,26 +232,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { nextTick, onMounted, onUnmounted, ref, watch } from "vue";
|
import {nextTick, onMounted, onUnmounted, ref, watch} from "vue";
|
||||||
import ChatPrompt from "@/components/ChatPrompt.vue";
|
import ChatPrompt from "@/components/ChatPrompt.vue";
|
||||||
import ChatReply from "@/components/ChatReply.vue";
|
import ChatReply from "@/components/ChatReply.vue";
|
||||||
import { Delete, Edit, InfoFilled, More, Plus, Promotion, Search, Share, VideoPause } from "@element-plus/icons-vue";
|
import {Delete, Edit, InfoFilled, More, Promotion, Search, Share, VideoPause} from "@element-plus/icons-vue";
|
||||||
import "highlight.js/styles/a11y-dark.css";
|
import "highlight.js/styles/a11y-dark.css";
|
||||||
import { isMobile, randString, removeArrayItem, UUID } from "@/utils/libs";
|
import {isMobile, randString, removeArrayItem, UUID} from "@/utils/libs";
|
||||||
import { ElMessage, ElMessageBox } from "element-plus";
|
import {ElMessage, ElMessageBox} from "element-plus";
|
||||||
import { httpGet, httpPost } from "@/utils/http";
|
import {httpGet, httpPost} from "@/utils/http";
|
||||||
import { useRouter } from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
import Clipboard from "clipboard";
|
import Clipboard from "clipboard";
|
||||||
import { checkSession, getClientId, getSystemInfo } from "@/store/cache";
|
import {checkSession, getClientId, getSystemInfo} from "@/store/cache";
|
||||||
import Welcome from "@/components/Welcome.vue";
|
import Welcome from "@/components/Welcome.vue";
|
||||||
import { useSharedStore } from "@/store/sharedata";
|
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 BackTop from "@/components/BackTop.vue";
|
import BackTop from "@/components/BackTop.vue";
|
||||||
import { closeLoading, showLoading, showMessageError } from "@/utils/dialog";
|
import {closeLoading, showLoading, showMessageError} from "@/utils/dialog";
|
||||||
|
import MarkdownIt from "markdown-it";
|
||||||
|
import emoji from "markdown-it-emoji";
|
||||||
|
|
||||||
const title = ref("GeekAI-智能助手");
|
const title = ref("GeekAI-智能助手");
|
||||||
|
const logo = ref("");
|
||||||
const models = ref([]);
|
const models = ref([]);
|
||||||
const modelID = ref(0);
|
const modelID = ref(0);
|
||||||
const chatData = ref([]);
|
const chatData = ref([]);
|
||||||
@@ -256,7 +262,7 @@ const allChats = ref([]); // 会话列表
|
|||||||
const chatList = ref(allChats.value);
|
const chatList = ref(allChats.value);
|
||||||
const mainWinHeight = ref(0); // 主窗口高度
|
const mainWinHeight = ref(0); // 主窗口高度
|
||||||
const chatBoxHeight = ref(0); // 聊天内容框高度
|
const chatBoxHeight = ref(0); // 聊天内容框高度
|
||||||
const leftBoxHeight = ref(0);
|
const chatListHeight = ref(0); // 聊天列表高度
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const loginUser = ref(null);
|
const loginUser = ref(null);
|
||||||
const roles = ref([]);
|
const roles = ref([]);
|
||||||
@@ -311,6 +317,7 @@ if (!chatId.value) {
|
|||||||
// 查询对话信息
|
// 查询对话信息
|
||||||
httpGet("/api/chat/detail", { chat_id: chatId.value })
|
httpGet("/api/chat/detail", { chat_id: chatId.value })
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
document.title = res.data.title;
|
||||||
roleId.value = res.data.role_id;
|
roleId.value = res.data.role_id;
|
||||||
modelID.value = res.data.model_id;
|
modelID.value = res.data.model_id;
|
||||||
})
|
})
|
||||||
@@ -324,14 +331,12 @@ getSystemInfo()
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
config.value = res.data;
|
config.value = res.data;
|
||||||
title.value = config.value.title;
|
title.value = config.value.title;
|
||||||
|
logo.value = res.data.bar_logo;
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
ElMessage.error("获取系统配置失败:" + e.message);
|
ElMessage.error("获取系统配置失败:" + e.message);
|
||||||
});
|
});
|
||||||
|
|
||||||
import MarkdownIt from "markdown-it";
|
|
||||||
import emoji from "markdown-it-emoji";
|
|
||||||
|
|
||||||
const md = new MarkdownIt({
|
const md = new MarkdownIt({
|
||||||
breaks: true,
|
breaks: true,
|
||||||
html: true,
|
html: true,
|
||||||
@@ -540,17 +545,10 @@ const getRoleById = function (rid) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const resizeElement = function () {
|
const resizeElement = function () {
|
||||||
chatBoxHeight.value = window.innerHeight - 101 - 82 - 38;
|
chatListHeight.value = window.innerHeight - 240;
|
||||||
// chatBoxHeight.value = window.innerHeight;
|
// chatBoxHeight.value = window.innerHeight;
|
||||||
|
mainWinHeight.value = window.innerHeight - 50;
|
||||||
// mainWinHeight.value = window.innerHeight - 101;
|
chatBoxHeight.value = window.innerHeight - 101 - 82 - 38;
|
||||||
mainWinHeight.value = window.innerHeight - 59;
|
|
||||||
|
|
||||||
// mainWinHeight.value = window.innerHeight;
|
|
||||||
|
|
||||||
// leftBoxHeight.value = window.innerHeight - 90 - 45 - 82;
|
|
||||||
// leftBoxHeight.value = window.innerHeight - 90 - 82;
|
|
||||||
leftBoxHeight.value = window.innerHeight - 90 - 100;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const _newChat = () => {
|
const _newChat = () => {
|
||||||
|
|||||||
@@ -1,28 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="layout">
|
<div class="layout">
|
||||||
<div class="tab-box">
|
<div class="tab-box">
|
||||||
<div class="flex-center-col big-top-title xxx">
|
<div class="flex-center-col pt-2 mb-2">
|
||||||
<div class="flex-center-col" @click="isCollapse = !isCollapse">
|
<div class="flex flex-center-col">
|
||||||
<el-tooltip content="展开菜单" placement="right" v-if="isCollapse">
|
<div class="menuIcon" @click="store.setChatListExtend(!store.chatListExtend)">
|
||||||
<i class="iconfont icon-expand"></i>
|
<el-tooltip content="隐藏对话列表" placement="right" v-if="store.chatListExtend">
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
<div class="flex" :class="{ 'top-collapse': !isCollapse }">
|
|
||||||
<div class="top-avatar flex">
|
|
||||||
<span class="title" v-if="!isCollapse">{{ title }}</span>
|
|
||||||
<el-tooltip :content="title" placement="right">
|
|
||||||
<img :src="logo" alt="" :class="{ marr: !isCollapse }" v-if="isCollapse" />
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
<div class="menuIcon xxx" @click="isCollapse = !isCollapse">
|
|
||||||
<el-tooltip content="关闭菜单" placement="right" v-if="!isCollapse">
|
|
||||||
<i class="iconfont icon-colspan"></i>
|
<i class="iconfont icon-colspan"></i>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
<el-tooltip content="展开对话列表" placement="right" v-else>
|
||||||
|
<i class="iconfont icon-expand"></i>
|
||||||
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="menu-list" :style="{ width: isCollapse ? '65px' : '170px' }" :class="{ 'menu-list-collapse': !isCollapse }">
|
<div class="menu-list">
|
||||||
<ul>
|
<ul>
|
||||||
<li
|
<li
|
||||||
class="menu-list-item flex-center-col"
|
class="menu-list-item flex-center-col"
|
||||||
@@ -31,29 +23,28 @@
|
|||||||
@click="changeNav(item)"
|
@click="changeNav(item)"
|
||||||
:class="item.url === curPath ? 'active' : ''"
|
:class="item.url === curPath ? 'active' : ''"
|
||||||
>
|
>
|
||||||
<span v-if="item.icon.startsWith('icon')" :class="{ 'mr-1 ml-2': !isCollapse }">
|
<span v-if="item.icon.startsWith('icon')">
|
||||||
<i class="iconfont" :class="item.icon"></i>
|
<i class="iconfont" :class="item.icon"></i>
|
||||||
</span>
|
</span>
|
||||||
<el-image :src="item.icon" class="el-icon ml-1" v-else />
|
<el-image :src="item.icon" class="el-icon ml-1" v-else />
|
||||||
<div class="menu-title" :class="{ 'menu-title-collapse': !isCollapse }">
|
<div class="menu-title">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<!-- 更多 -->
|
<!-- 更多 -->
|
||||||
<div class="bot" :style="{ width: isCollapse ? '65px' : '170px' }">
|
<div class="bot p-2">
|
||||||
<div class="bot-line"></div>
|
<div class="bot-line"></div>
|
||||||
|
<el-popover v-if="moreNavs.length > 0" placement="right-end" trigger="hover">
|
||||||
<el-popover v-if="moreNavs.length > 0" placement="right-end" trigger="hover">
|
<template #reference>
|
||||||
<template #reference>
|
<li class="menu-list-item flex-center-col">
|
||||||
<li class="menu-list-item flex-center-col">
|
<i class="iconfont icon-more"/>
|
||||||
<el-icon><CirclePlus /></el-icon>
|
</li>
|
||||||
<div class="menu-title">更多</div>
|
</template>
|
||||||
</li>
|
<template #default>
|
||||||
</template>
|
<ul class="more-menus">
|
||||||
<template #default>
|
<li
|
||||||
<ul class="more-menus">
|
|
||||||
<li
|
|
||||||
v-for="(item, index) in moreNavs"
|
v-for="(item, index) in moreNavs"
|
||||||
:key="item.url"
|
:key="item.url"
|
||||||
:class="{
|
:class="{
|
||||||
@@ -61,57 +52,52 @@
|
|||||||
moreTitle: index !== 3 && index !== 4,
|
moreTitle: index !== 3 && index !== 4,
|
||||||
twoTittle: index === 3 || index === 4,
|
twoTittle: index === 3 || index === 4,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<a @click="changeNav(item)">
|
<a @click="changeNav(item)">
|
||||||
<span v-if="item.icon.startsWith('icon')" class="mr-2">
|
<span v-if="item.icon.startsWith('icon')" class="mr-2">
|
||||||
<i class="iconfont" :class="item.icon"></i>
|
<i class="iconfont" :class="item.icon"></i>
|
||||||
</span>
|
</span>
|
||||||
<el-image :src="item.icon" style="width: 20px; height: 20px" v-else />
|
<el-image :src="item.icon" style="width: 20px; height: 20px" v-else/>
|
||||||
<span :class="item.url === curPath ? 'title active' : 'title'">{{ item.name }}</span>
|
<span :class="item.url === curPath ? 'title active' : 'title'">{{ item.name }}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
||||||
</el-popover>
|
|
||||||
<el-popover placement="right-end" trigger="hover" v-if="loginUser.id">
|
|
||||||
<template #reference>
|
|
||||||
<li class="menu-list-item flex-center-col">
|
|
||||||
<el-icon><Setting /></el-icon>
|
|
||||||
<div v-if="!isCollapse">设置</div>
|
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</ul>
|
||||||
<template #default>
|
</template>
|
||||||
<ul class="more-menus setting-menus">
|
</el-popover>
|
||||||
<li>
|
<el-popover placement="right-end" trigger="hover" v-if="loginUser.id">
|
||||||
<div @click="showConfigDialog = true" class="flex">
|
<template #reference>
|
||||||
<el-icon>
|
<li class="menu-list-item flex-center-col">
|
||||||
<UserFilled />
|
<i class="iconfont icon-config"/>
|
||||||
</el-icon>
|
</li>
|
||||||
<span class="username title">{{ loginUser.nickname }}</span>
|
</template>
|
||||||
</div>
|
<template #default>
|
||||||
</li>
|
<ul class="more-menus setting-menus">
|
||||||
<li>
|
<li>
|
||||||
<a @click="logout" class="flex">
|
<div @click="showConfigDialog = true" class="flex">
|
||||||
<i class="iconfont icon-logout"></i>
|
<el-icon>
|
||||||
<span class="title">退出登录</span>
|
<UserFilled/>
|
||||||
</a>
|
</el-icon>
|
||||||
</li>
|
<span class="username title">{{ loginUser.nickname }}</span>
|
||||||
</ul>
|
</div>
|
||||||
</template>
|
</li>
|
||||||
</el-popover>
|
<li>
|
||||||
<li class="menu-bot-item">
|
<a @click="logout" class="flex">
|
||||||
<a :href="gitURL" class="link-button" target="_blank" v-if="!license.de_copy && !isCollapse">
|
<i class="iconfont icon-logout"></i>
|
||||||
<i class="iconfont icon-github"></i>
|
<span class="title">退出登录</span>
|
||||||
</a>
|
</a>
|
||||||
|
</li>
|
||||||
<a @click="router.push('/')" class="link-button">
|
</ul>
|
||||||
<i class="iconfont icon-house"></i>
|
</template>
|
||||||
</a>
|
</el-popover>
|
||||||
|
<div class="menu-bot-item">
|
||||||
<ThemeChange />
|
<a @click="router.push('/')" class="link-button">
|
||||||
</li>
|
<i class="iconfont icon-house"></i>
|
||||||
|
</a>
|
||||||
|
<div class="pl-1">
|
||||||
|
<ThemeChange/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-scrollbar class="right-main">
|
<el-scrollbar class="right-main">
|
||||||
@@ -141,21 +127,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { CirclePlus, Setting, UserFilled } from "@element-plus/icons-vue";
|
import {UserFilled} from "@element-plus/icons-vue";
|
||||||
import ThemeChange from "@/components/ThemeChange.vue";
|
import ThemeChange from "@/components/ThemeChange.vue";
|
||||||
import { useRouter } from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
import { onMounted, ref, watch } from "vue";
|
import {onMounted, ref, watch} from "vue";
|
||||||
import { httpGet } from "@/utils/http";
|
import {httpGet} from "@/utils/http";
|
||||||
import { ElMessage } from "element-plus";
|
import {ElMessage} from "element-plus";
|
||||||
import { checkSession, getLicenseInfo, getSystemInfo } from "@/store/cache";
|
import {checkSession, getLicenseInfo, getSystemInfo} from "@/store/cache";
|
||||||
import { removeUserToken } from "@/store/session";
|
import {removeUserToken} from "@/store/session";
|
||||||
import { useSharedStore } from "@/store/sharedata";
|
import {useSharedStore} from "@/store/sharedata";
|
||||||
import ConfigDialog from "@/components/UserInfoDialog.vue";
|
import ConfigDialog from "@/components/UserInfoDialog.vue";
|
||||||
import { showMessageError } from "@/utils/dialog";
|
import {showMessageError} from "@/utils/dialog";
|
||||||
import LoginDialog from "@/components/LoginDialog.vue";
|
import LoginDialog from "@/components/LoginDialog.vue";
|
||||||
import { substr } from "@/utils/libs";
|
|
||||||
|
|
||||||
const isCollapse = ref(true);
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const logo = ref("");
|
const logo = ref("");
|
||||||
const mainNavs = ref([]);
|
const mainNavs = ref([]);
|
||||||
@@ -163,13 +147,11 @@ const moreNavs = ref([]);
|
|||||||
const curPath = ref();
|
const curPath = ref();
|
||||||
|
|
||||||
const title = ref("");
|
const title = ref("");
|
||||||
const avatarImg = ref("/images/avatar/default.jpg");
|
|
||||||
const store = useSharedStore();
|
const store = useSharedStore();
|
||||||
const loginUser = ref({});
|
const loginUser = ref({});
|
||||||
const routerViewKey = ref(0);
|
const routerViewKey = ref(0);
|
||||||
const showConfigDialog = ref(false);
|
const showConfigDialog = ref(false);
|
||||||
const license = ref({ de_copy: true });
|
const license = ref({ de_copy: true });
|
||||||
const gitURL = ref(process.env.VUE_APP_GIT_URL);
|
|
||||||
const showLoginDialog = ref(false);
|
const showLoginDialog = ref(false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -9,25 +9,24 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="menu-item">
|
<div class="menu-item">
|
||||||
<span v-if="!license.de_copy">
|
<span v-if="!license.de_copy">
|
||||||
<el-tooltip v-if="!license.de_copy" class="box-item" content="部署文档" placement="bottom">
|
<el-tooltip class="box-item" content="部署文档" placement="bottom">
|
||||||
<a :href="docsURL" class="link-button mr-2" target="_blank">
|
<a :href="docsURL" class="link-button mr-2" target="_blank">
|
||||||
<i class="iconfont icon-book"></i>
|
<i class="iconfont icon-book"></i>
|
||||||
</a>
|
</a>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip v-if="!license.de_copy" class="box-item" content="项目源码" placement="bottom">
|
<el-tooltip class="box-item" content="Github 源码" placement="bottom">
|
||||||
<a :href="gitURL" class="link-button" target="_blank">
|
<a :href="gitURL" class="link-button" target="_blank">
|
||||||
<i class="iconfont icon-github"></i>
|
<i class="iconfont icon-github"></i>
|
||||||
</a>
|
</a>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
<el-tooltip class="box-item" content="Gitee 源码" placement="bottom">
|
||||||
|
<a :href="gitURL" class="link-button" target="_blank">
|
||||||
|
<i class="iconfont icon-gitee"></i>
|
||||||
|
</a>
|
||||||
|
</el-tooltip>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span v-if="!isLogin">
|
<span v-if="!isLogin">
|
||||||
<!-- <el-button @click="router.push('/login')" class="shadow" round
|
|
||||||
>登录</el-button
|
|
||||||
>
|
|
||||||
<el-button @click="router.push('/register')" class="shadow" round
|
|
||||||
>注册</el-button
|
|
||||||
> -->
|
|
||||||
<el-button @click="router.push('/login')" class="btn-go animate__animated animate__pulse animate__infinite" round>登录/注册</el-button>
|
<el-button @click="router.push('/login')" class="btn-go animate__animated animate__pulse animate__infinite" round>登录/注册</el-button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -59,14 +58,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref } from "vue";
|
import {onMounted, ref} from "vue";
|
||||||
import { useRouter } from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
import FooterBar from "@/components/FooterBar.vue";
|
import FooterBar from "@/components/FooterBar.vue";
|
||||||
import ThemeChange from "@/components/ThemeChange.vue";
|
import ThemeChange from "@/components/ThemeChange.vue";
|
||||||
import { httpGet } from "@/utils/http";
|
import {httpGet} from "@/utils/http";
|
||||||
import { ElMessage } from "element-plus";
|
import {ElMessage} from "element-plus";
|
||||||
import { checkSession, getLicenseInfo, getSystemInfo } from "@/store/cache";
|
import {checkSession, getLicenseInfo, getSystemInfo} from "@/store/cache";
|
||||||
import { isMobile } from "@/utils/libs";
|
import {isMobile} from "@/utils/libs";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@@ -81,7 +80,7 @@ const license = ref({ de_copy: true });
|
|||||||
|
|
||||||
const isLogin = ref(false);
|
const isLogin = ref(false);
|
||||||
const docsURL = ref(process.env.VUE_APP_DOCS_URL);
|
const docsURL = ref(process.env.VUE_APP_DOCS_URL);
|
||||||
const gitURL = ref(process.env.VUE_APP_GIT_URL);
|
const gitURL = ref(process.env.VUE_APP_GITHUB_URL);
|
||||||
const navs = ref([]);
|
const navs = ref([]);
|
||||||
|
|
||||||
const iconMap = ref({
|
const iconMap = ref({
|
||||||
@@ -150,7 +149,6 @@ const setContent = () => {
|
|||||||
displayedChars.value = [];
|
displayedChars.value = [];
|
||||||
if (timer) clearInterval(timer);
|
if (timer) clearInterval(timer);
|
||||||
timer = setInterval(setContent, interTime.value);
|
timer = setInterval(setContent, interTime.value);
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
const nextChar = slogan.value.charAt(initAnimation.value.length);
|
const nextChar = slogan.value.charAt(initAnimation.value.length);
|
||||||
initAnimation.value += slogan.value.charAt(initAnimation.value.length); // 逐字符追加
|
initAnimation.value += slogan.value.charAt(initAnimation.value.length); // 逐字符追加
|
||||||
@@ -164,7 +162,7 @@ const setContent = () => {
|
|||||||
const rainbowColor = (index) => {
|
const rainbowColor = (index) => {
|
||||||
const hue = (index * 40) % 360; // 每个字符间隔40度,形成彩虹色
|
const hue = (index * 40) % 360; // 每个字符间隔40度,形成彩虹色
|
||||||
return `hsl(${hue}, 90%, 50%)`; // 色调(hue),饱和度(70%),亮度(50%)
|
return `hsl(${hue}, 90%, 50%)`; // 色调(hue),饱和度(70%),亮度(50%)
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
<el-form-item label="网站Slogan" prop="slogan">
|
<el-form-item label="网站Slogan" prop="slogan">
|
||||||
<el-input v-model="system['slogan']" />
|
<el-input v-model="system['slogan']" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="网站 LOGO" prop="logo">
|
<el-form-item label="圆形 LOGO" prop="logo">
|
||||||
<el-input v-model="system['logo']" placeholder="网站LOGO图片">
|
<el-input v-model="system['logo']" placeholder="正方形或者圆形 Logo">
|
||||||
<template #append>
|
<template #append>
|
||||||
<el-upload :auto-upload="true" :show-file-list="false" @click="beforeUpload('logo')" :http-request="uploadImg">
|
<el-upload :auto-upload="true" :show-file-list="false" @click="beforeUpload('logo')" :http-request="uploadImg">
|
||||||
<el-icon class="uploader-icon">
|
<el-icon class="uploader-icon">
|
||||||
@@ -26,7 +26,18 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="条形 LOGO" prop="logo">
|
||||||
|
<el-input v-model="system['bar_logo']" placeholder="长方形 Logo">
|
||||||
|
<template #append>
|
||||||
|
<el-upload :auto-upload="true" :show-file-list="false" @click="beforeUpload('bar_logo')"
|
||||||
|
:http-request="uploadImg">
|
||||||
|
<el-icon class="uploader-icon">
|
||||||
|
<UploadFilled/>
|
||||||
|
</el-icon>
|
||||||
|
</el-upload>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="label-title">
|
<div class="label-title">
|
||||||
@@ -359,17 +370,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, reactive, ref } from "vue";
|
import {onMounted, reactive, ref} from "vue";
|
||||||
import { httpGet, httpPost } from "@/utils/http";
|
import {httpGet, httpPost} from "@/utils/http";
|
||||||
import Compressor from "compressorjs";
|
import Compressor from "compressorjs";
|
||||||
import { ElMessage, ElMessageBox } from "element-plus";
|
import {ElMessage, ElMessageBox} from "element-plus";
|
||||||
import { CloseBold, InfoFilled, Select, UploadFilled } from "@element-plus/icons-vue";
|
import {CloseBold, InfoFilled, Select, UploadFilled} from "@element-plus/icons-vue";
|
||||||
import MdEditor from "md-editor-v3";
|
import MdEditor from "md-editor-v3";
|
||||||
import "md-editor-v3/lib/style.css";
|
import "md-editor-v3/lib/style.css";
|
||||||
import Menu from "@/views/admin/Menu.vue";
|
import Menu from "@/views/admin/Menu.vue";
|
||||||
import { copyObj, dateFormat } from "@/utils/libs";
|
import {copyObj, dateFormat} from "@/utils/libs";
|
||||||
import ItemsInput from "@/components/ui/ItemsInput.vue";
|
import ItemsInput from "@/components/ui/ItemsInput.vue";
|
||||||
import { useSharedStore } from "@/store/sharedata";
|
import {useSharedStore} from "@/store/sharedata";
|
||||||
|
|
||||||
const activeName = ref("basic");
|
const activeName = ref("basic");
|
||||||
const system = ref({ models: [] });
|
const system = ref({ models: [] });
|
||||||
|
|||||||
Reference in New Issue
Block a user