mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-11-16 22:23:42 +08:00
Compare commits
23 Commits
58e99976b3
...
7879459c3f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7879459c3f | ||
|
|
ad482dad7f | ||
|
|
dd675c9a9b | ||
|
|
f975f9b0b8 | ||
|
|
fbefe5b308 | ||
|
|
312abbc273 | ||
|
|
8ced447a14 | ||
|
|
f8e32148c8 | ||
|
|
2c899f6057 | ||
|
|
be799000ee | ||
|
|
22cb2270af | ||
|
|
4e440b7910 | ||
|
|
4e6f14cb9e | ||
|
|
8dc03a7509 | ||
|
|
57b1b44645 | ||
|
|
aa17a33093 | ||
|
|
80e27c40e9 | ||
|
|
8250e876a5 | ||
|
|
9f98491368 | ||
|
|
fe160f978b | ||
|
|
7da5b7163c | ||
|
|
cffc722622 | ||
|
|
a7baf1dc9e |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -14,3 +14,4 @@ logs
|
|||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
|
deploy/data
|
||||||
|
|||||||
12
CHANGELOG.md
12
CHANGELOG.md
@@ -1,5 +1,17 @@
|
|||||||
# 更新日志
|
# 更新日志
|
||||||
|
|
||||||
|
## v4.2.0
|
||||||
|
|
||||||
|
- 功能优化:优化聊天页面 Notice 组件样式,采用 Vuepress 文档样式
|
||||||
|
- Bug 修复:修复主题切换的组件显示异常问题
|
||||||
|
- 功能优化:支持 DeepSeek-R1 推理模型,优化推理样式输出
|
||||||
|
- 功能优化:优化 Suno 歌曲播放按钮样式,居中显示
|
||||||
|
- 功能优化:后台管理新增模型的时候,可以绑定所有的 API KEY,而不只是能绑定 Chat 类型的 API KEY
|
||||||
|
- 功能新增:新增每日签到功能,每日签到可以获得算力奖励
|
||||||
|
- 功能优化:兼容 OpenAI o3 系列模型
|
||||||
|
- 功能优化:API 默认开启允许跨域调用
|
||||||
|
- 功能优化:优化 docker-compose.yaml 配置,增加各容器依赖关系
|
||||||
|
|
||||||
## v4.1.9
|
## v4.1.9
|
||||||
|
|
||||||
- 功能优化:优化系统配置,移除已废弃的配置项
|
- 功能优化:优化系统配置,移除已废弃的配置项
|
||||||
|
|||||||
@@ -60,8 +60,6 @@ func (s *AppServer) Init(debug bool, client *redis.Client) {
|
|||||||
s.Engine.Use(errorHandler)
|
s.Engine.Use(errorHandler)
|
||||||
// 添加静态资源访问
|
// 添加静态资源访问
|
||||||
s.Engine.Static("/static", s.Config.StaticDir)
|
s.Engine.Static("/static", s.Config.StaticDir)
|
||||||
//启动服务
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *AppServer) Run(db *gorm.DB) error {
|
func (s *AppServer) Run(db *gorm.DB) error {
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ const (
|
|||||||
PowerInvite = PowerType(4) // 邀请奖励
|
PowerInvite = PowerType(4) // 邀请奖励
|
||||||
PowerRedeem = PowerType(5) // 众筹
|
PowerRedeem = PowerType(5) // 众筹
|
||||||
PowerGift = PowerType(6) // 系统赠送
|
PowerGift = PowerType(6) // 系统赠送
|
||||||
|
PowerSignIn = PowerType(7) // 每日签到
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t PowerType) String() string {
|
func (t PowerType) String() string {
|
||||||
@@ -111,6 +112,8 @@ func (t PowerType) String() string {
|
|||||||
return "赠送"
|
return "赠送"
|
||||||
case PowerInvite:
|
case PowerInvite:
|
||||||
return "邀请"
|
return "邀请"
|
||||||
|
case PowerSignIn:
|
||||||
|
return "签到"
|
||||||
}
|
}
|
||||||
return "其他"
|
return "其他"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,17 +97,19 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio
|
|||||||
}
|
}
|
||||||
|
|
||||||
var req = types.ApiRequest{
|
var req = types.ApiRequest{
|
||||||
Model: session.Model.Value,
|
Model: session.Model.Value,
|
||||||
|
Stream: session.Stream,
|
||||||
|
Temperature: session.Model.Temperature,
|
||||||
}
|
}
|
||||||
// 兼容 GPT-O1 模型
|
// 兼容 OpenAI 模型
|
||||||
if strings.HasPrefix(session.Model.Value, "o1-") {
|
if strings.HasPrefix(session.Model.Value, "o1-") ||
|
||||||
|
strings.HasPrefix(session.Model.Value, "o3-") ||
|
||||||
|
strings.HasPrefix(session.Model.Value, "gpt") {
|
||||||
utils.SendChunkMsg(ws, "> AI 正在思考...\n")
|
utils.SendChunkMsg(ws, "> AI 正在思考...\n")
|
||||||
req.Stream = session.Stream
|
req.MaxCompletionTokens = session.Model.MaxTokens
|
||||||
session.Start = time.Now().Unix()
|
session.Start = time.Now().Unix()
|
||||||
} else {
|
} else {
|
||||||
req.MaxTokens = session.Model.MaxTokens
|
req.MaxTokens = session.Model.MaxTokens
|
||||||
req.Temperature = session.Model.Temperature
|
|
||||||
req.Stream = session.Stream
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(session.Tools) > 0 && !strings.HasPrefix(session.Model.Value, "o1-") {
|
if len(session.Tools) > 0 && !strings.HasPrefix(session.Model.Value, "o1-") {
|
||||||
@@ -275,17 +277,17 @@ func (h *ChatHandler) Tokens(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 如果没有传入 text 字段,则说明是获取当前 reply 总的 token 消耗(带上下文)
|
// 如果没有传入 text 字段,则说明是获取当前 reply 总的 token 消耗(带上下文)
|
||||||
//if data.Text == "" && data.ChatId != "" {
|
if data.Text == "" && data.ChatId != "" {
|
||||||
// var item model.ChatMessage
|
var item model.ChatMessage
|
||||||
// userId, _ := c.Get(types.LoginUserID)
|
userId, _ := c.Get(types.LoginUserID)
|
||||||
// res := h.DB.Where("user_id = ?", userId).Where("chat_id = ?", data.ChatId).Last(&item)
|
res := h.DB.Where("user_id = ?", userId).Where("chat_id = ?", data.ChatId).Last(&item)
|
||||||
// if res.Error != nil {
|
if res.Error != nil {
|
||||||
// resp.ERROR(c, res.Error.Error())
|
resp.ERROR(c, res.Error.Error())
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
// resp.SUCCESS(c, item.Tokens)
|
resp.SUCCESS(c, item.Tokens)
|
||||||
// return
|
return
|
||||||
//}
|
}
|
||||||
|
|
||||||
tokens, err := utils.CalcTokens(data.Text, data.Model)
|
tokens, err := utils.CalcTokens(data.Text, data.Model)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -12,14 +12,16 @@ import (
|
|||||||
"geekai/core"
|
"geekai/core"
|
||||||
"geekai/core/types"
|
"geekai/core/types"
|
||||||
"geekai/service"
|
"geekai/service"
|
||||||
|
"geekai/store"
|
||||||
"geekai/store/model"
|
"geekai/store/model"
|
||||||
"geekai/store/vo"
|
"geekai/store/vo"
|
||||||
"geekai/utils"
|
"geekai/utils"
|
||||||
"geekai/utils/resp"
|
"geekai/utils/resp"
|
||||||
"github.com/imroc/req/v3"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/imroc/req/v3"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
|
|
||||||
@@ -32,6 +34,7 @@ type UserHandler struct {
|
|||||||
BaseHandler
|
BaseHandler
|
||||||
searcher *xdb.Searcher
|
searcher *xdb.Searcher
|
||||||
redis *redis.Client
|
redis *redis.Client
|
||||||
|
levelDB *store.LevelDB
|
||||||
licenseService *service.LicenseService
|
licenseService *service.LicenseService
|
||||||
captcha *service.CaptchaService
|
captcha *service.CaptchaService
|
||||||
userService *service.UserService
|
userService *service.UserService
|
||||||
@@ -42,6 +45,7 @@ func NewUserHandler(
|
|||||||
db *gorm.DB,
|
db *gorm.DB,
|
||||||
searcher *xdb.Searcher,
|
searcher *xdb.Searcher,
|
||||||
client *redis.Client,
|
client *redis.Client,
|
||||||
|
levelDB *store.LevelDB,
|
||||||
captcha *service.CaptchaService,
|
captcha *service.CaptchaService,
|
||||||
userService *service.UserService,
|
userService *service.UserService,
|
||||||
licenseService *service.LicenseService) *UserHandler {
|
licenseService *service.LicenseService) *UserHandler {
|
||||||
@@ -49,6 +53,7 @@ func NewUserHandler(
|
|||||||
BaseHandler: BaseHandler{DB: db, App: app},
|
BaseHandler: BaseHandler{DB: db, App: app},
|
||||||
searcher: searcher,
|
searcher: searcher,
|
||||||
redis: client,
|
redis: client,
|
||||||
|
levelDB: levelDB,
|
||||||
captcha: captcha,
|
captcha: captcha,
|
||||||
licenseService: licenseService,
|
licenseService: licenseService,
|
||||||
userService: userService,
|
userService: userService,
|
||||||
@@ -184,7 +189,7 @@ func (h *UserHandler) Register(c *gin.Context) {
|
|||||||
if h.App.SysConfig.InvitePower > 0 {
|
if h.App.SysConfig.InvitePower > 0 {
|
||||||
err := h.userService.IncreasePower(int(inviteCode.UserId), h.App.SysConfig.InvitePower, model.PowerLog{
|
err := h.userService.IncreasePower(int(inviteCode.UserId), h.App.SysConfig.InvitePower, model.PowerLog{
|
||||||
Type: types.PowerInvite,
|
Type: types.PowerInvite,
|
||||||
Model: "Invite",
|
Model: "Invite",
|
||||||
Remark: fmt.Sprintf("邀请用户注册奖励,金额:%d,邀请码:%s,新用户:%s", h.App.SysConfig.InvitePower, inviteCode.Code, user.Username),
|
Remark: fmt.Sprintf("邀请用户注册奖励,金额:%d,邀请码:%s,新用户:%s", h.App.SysConfig.InvitePower, inviteCode.Code, user.Username),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -712,3 +717,30 @@ func (h *UserHandler) BindEmail(c *gin.Context) {
|
|||||||
_ = h.redis.Del(c, key) // 删除短信验证码
|
_ = h.redis.Del(c, key) // 删除短信验证码
|
||||||
resp.SUCCESS(c)
|
resp.SUCCESS(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SignIn 每日签到
|
||||||
|
func (h *UserHandler) SignIn(c *gin.Context) {
|
||||||
|
// 获取当前日期
|
||||||
|
date := time.Now().Format("2006-01-02")
|
||||||
|
|
||||||
|
// 检查是否已经签到
|
||||||
|
userId := h.GetLoginUserId(c)
|
||||||
|
key := fmt.Sprintf("signin/%d/%s", userId, date)
|
||||||
|
var signIn bool
|
||||||
|
err := h.levelDB.Get(key, &signIn)
|
||||||
|
if err == nil && signIn {
|
||||||
|
resp.ERROR(c, "今日已签到,请明日再来!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 签到
|
||||||
|
h.levelDB.Put(key, true)
|
||||||
|
if h.App.SysConfig.DailyPower > 0 {
|
||||||
|
h.userService.IncreasePower(int(userId), h.App.SysConfig.DailyPower, model.PowerLog{
|
||||||
|
Type: types.PowerSignIn,
|
||||||
|
Model: "SignIn",
|
||||||
|
Remark: fmt.Sprintf("每日签到奖励,金额:%d", h.App.SysConfig.DailyPower),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
resp.SUCCESS(c)
|
||||||
|
}
|
||||||
|
|||||||
@@ -244,6 +244,7 @@ func main() {
|
|||||||
group.POST("resetPass", h.ResetPass)
|
group.POST("resetPass", h.ResetPass)
|
||||||
group.GET("clogin", h.CLogin)
|
group.GET("clogin", h.CLogin)
|
||||||
group.GET("clogin/callback", h.CLoginCallback)
|
group.GET("clogin/callback", h.CLoginCallback)
|
||||||
|
group.GET("signin", h.SignIn)
|
||||||
}),
|
}),
|
||||||
fx.Invoke(func(s *core.AppServer, h *handler.ChatHandler) {
|
fx.Invoke(func(s *core.AppServer, h *handler.ChatHandler) {
|
||||||
group := s.Engine.Group("/api/chat/")
|
group := s.Engine.Group("/api/chat/")
|
||||||
|
|||||||
@@ -3,9 +3,13 @@
|
|||||||
-- https://www.phpmyadmin.net/
|
-- https://www.phpmyadmin.net/
|
||||||
--
|
--
|
||||||
-- 主机: 127.0.0.1
|
-- 主机: 127.0.0.1
|
||||||
-- 生成日期: 2024-11-27 13:58:35
|
<<<<<<<< HEAD:database/geekai_plus-v4.1.9.sql
|
||||||
|
-- 生成日期: 2025-01-10 17:39:25
|
||||||
|
========
|
||||||
|
-- 生成日期: 2025-02-10 10:17:27
|
||||||
|
>>>>>>>> v4.2.0:database/geekai_plus-v4.2.0.sql
|
||||||
-- 服务器版本: 8.0.33
|
-- 服务器版本: 8.0.33
|
||||||
-- PHP 版本: 8.1.2-1ubuntu2.19
|
-- PHP 版本: 8.1.2-1ubuntu2.20
|
||||||
|
|
||||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||||
START TRANSACTION;
|
START TRANSACTION;
|
||||||
@@ -47,7 +51,7 @@ CREATE TABLE `chatgpt_admin_users` (
|
|||||||
--
|
--
|
||||||
|
|
||||||
INSERT INTO `chatgpt_admin_users` (`id`, `username`, `password`, `salt`, `status`, `last_login_at`, `last_login_ip`, `created_at`, `updated_at`) VALUES
|
INSERT INTO `chatgpt_admin_users` (`id`, `username`, `password`, `salt`, `status`, `last_login_at`, `last_login_ip`, `created_at`, `updated_at`) VALUES
|
||||||
(1, 'admin', '6d17e80c87d209efb84ca4b2e0824f549d09fac8b2e1cc698de5bb5e1d75dfd0', 'mmrql75o', 1, 1732672509, '::1', '2024-03-11 16:30:20', '2024-11-27 09:55:10');
|
(1, 'admin', '6d17e80c87d209efb84ca4b2e0824f549d09fac8b2e1cc698de5bb5e1d75dfd0', 'mmrql75o', 1, 1735174700, '::1', '2024-03-11 16:30:20', '2024-12-26 08:58:20');
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
@@ -149,6 +153,7 @@ CREATE TABLE `chatgpt_chat_items` (
|
|||||||
DROP TABLE IF EXISTS `chatgpt_chat_models`;
|
DROP TABLE IF EXISTS `chatgpt_chat_models`;
|
||||||
CREATE TABLE `chatgpt_chat_models` (
|
CREATE TABLE `chatgpt_chat_models` (
|
||||||
`id` int NOT NULL,
|
`id` int NOT NULL,
|
||||||
|
`type` varchar(10) NOT NULL DEFAULT 'chat' COMMENT '模型类型(chat,img)',
|
||||||
`name` varchar(50) NOT NULL COMMENT '模型名称',
|
`name` varchar(50) NOT NULL COMMENT '模型名称',
|
||||||
`value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '模型值',
|
`value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '模型值',
|
||||||
`sort_num` tinyint(1) NOT NULL COMMENT '排序数字',
|
`sort_num` tinyint(1) NOT NULL COMMENT '排序数字',
|
||||||
@@ -167,20 +172,41 @@ CREATE TABLE `chatgpt_chat_models` (
|
|||||||
-- 转存表中的数据 `chatgpt_chat_models`
|
-- 转存表中的数据 `chatgpt_chat_models`
|
||||||
--
|
--
|
||||||
|
|
||||||
INSERT INTO `chatgpt_chat_models` (`id`, `name`, `value`, `sort_num`, `enabled`, `power`, `temperature`, `max_tokens`, `max_context`, `open`, `key_id`, `created_at`, `updated_at`) VALUES
|
INSERT INTO `chatgpt_chat_models` (`id`, `type`, `name`, `value`, `sort_num`, `enabled`, `power`, `temperature`, `max_tokens`, `max_context`, `open`, `key_id`, `created_at`, `updated_at`) VALUES
|
||||||
(1, 'gpt-4o-mini', 'gpt-4o-mini', 1, 1, 1, 1.0, 1024, 16384, 1, 57, '2023-08-23 12:06:36', '2024-11-12 16:30:56'),
|
(1, 'chat', 'gpt-4o-mini', 'gpt-4o-mini', 1, 1, 1, 1.0, 1024, 16384, 1, 44, '2023-08-23 12:06:36', '2025-01-06 14:01:08'),
|
||||||
(15, 'GPT-4O(联网版本)', 'gpt-4o-all', 4, 1, 30, 1.0, 4096, 32768, 1, 57, '2024-01-15 11:32:52', '2024-11-12 17:53:49'),
|
(15, 'chat', 'GPT-4O(联网版本)', 'gpt-4o-all', 4, 1, 30, 1.0, 4096, 32768, 1, 57, '2024-01-15 11:32:52', '2025-01-06 14:01:08'),
|
||||||
(36, 'GPT-4O', 'gpt-4o', 3, 1, 15, 1.0, 4096, 16384, 1, 44, '2024-05-14 09:25:15', '2024-11-12 15:35:57'),
|
(36, 'chat', 'GPT-4O', 'gpt-4o', 3, 1, 15, 1.0, 4096, 16384, 1, 44, '2024-05-14 09:25:15', '2025-01-06 14:01:08'),
|
||||||
(39, 'Claude35-snonet', 'claude-3-5-sonnet-20240620', 5, 1, 2, 1.0, 4000, 200000, 1, 0, '2024-05-29 15:04:19', '2024-09-14 18:07:25'),
|
(39, 'chat', 'Claude35-snonet', 'claude-3-5-sonnet-20240620', 5, 1, 2, 1.0, 4000, 200000, 1, 0, '2024-05-29 15:04:19', '2025-01-06 14:01:08'),
|
||||||
(41, 'Suno对话模型', 'suno-v3.5', 7, 1, 10, 1.0, 1024, 8192, 1, 57, '2024-06-06 11:40:46', '2024-10-14 15:07:05'),
|
(41, 'chat', 'Suno对话模型', 'suno-v3.5', 7, 1, 10, 1.0, 1024, 8192, 1, 57, '2024-06-06 11:40:46', '2025-01-06 14:01:08'),
|
||||||
(42, 'DeekSeek', 'deepseek-chat', 8, 1, 1, 1.0, 4096, 32768, 1, 0, '2024-06-27 16:13:01', '2024-08-05 16:05:33'),
|
(42, 'chat', 'DeekSeek', 'deepseek-chat', 8, 1, 1, 1.0, 4096, 32768, 1, 57, '2024-06-27 16:13:01', '2025-01-06 14:11:51'),
|
||||||
(44, 'Claude3-opus', 'claude-3-opus-20240229', 6, 1, 5, 1.0, 4000, 128000, 1, 44, '2024-07-22 11:24:30', '2024-09-04 10:32:29'),
|
(44, 'chat', 'Claude3-opus', 'claude-3-opus-20240229', 6, 1, 5, 1.0, 4000, 128000, 1, 44, '2024-07-22 11:24:30', '2025-01-06 14:01:08'),
|
||||||
(46, 'gpt-3.5-turbo', 'gpt-3.5-turbo', 2, 1, 1, 1.0, 1024, 4096, 1, 73, '2024-07-22 13:53:41', '2024-09-13 18:00:47'),
|
(46, 'chat', 'gpt-3.5-turbo', 'gpt-3.5-turbo', 2, 1, 1, 1.0, 1024, 4096, 1, 75, '2024-07-22 13:53:41', '2025-01-08 10:33:07'),
|
||||||
(48, '彩票助手', 'gpt-4-gizmo-g-wmSivBgxo', 8, 1, 1, 0.9, 1024, 8192, 1, 57, '2024-09-05 14:17:14', '2024-09-05 14:17:14'),
|
<<<<<<<< HEAD:database/geekai_plus-v4.1.9.sql
|
||||||
(49, 'O1-mini', 'o1-mini', 9, 1, 2, 0.9, 1024, 8192, 1, 57, '2024-09-13 18:07:50', '2024-09-14 11:13:19'),
|
(48, 'chat', '彩票助手', 'gpt-4-gizmo-g-wmSivBgxo', 9, 1, 1, 0.9, 1024, 8192, 1, 57, '2024-09-05 14:17:14', '2025-01-06 14:01:08'),
|
||||||
(50, 'O1-preview', 'o1-preview', 10, 1, 5, 0.9, 1024, 8192, 1, 57, '2024-09-13 18:11:08', '2024-09-14 11:05:16'),
|
(49, 'chat', 'O1-mini', 'o1-mini', 10, 1, 2, 0.9, 1024, 8192, 1, 44, '2024-09-13 18:07:50', '2025-01-06 14:01:08'),
|
||||||
(51, 'O1-mini-all', 'o1-mini-all', 11, 1, 1, 0.9, 1024, 8192, 1, 57, '2024-09-29 11:40:52', '2024-09-29 11:40:52'),
|
(50, 'chat', 'O1-preview', 'o1-preview', 11, 1, 5, 0.9, 1024, 8192, 1, 44, '2024-09-13 18:11:08', '2025-01-06 14:01:08'),
|
||||||
(52, '通义千问', 'qwen-plus', 12, 1, 1, 0.9, 1024, 8192, 1, 80, '2024-11-19 08:38:14', '2024-11-19 09:06:42');
|
(51, 'chat', 'O1-mini-all', 'o1-mini-all', 12, 1, 1, 0.9, 1024, 8192, 1, 57, '2024-09-29 11:40:52', '2025-01-06 14:01:08'),
|
||||||
|
(52, 'chat', '通义千问', 'qwen-plus', 14, 1, 1, 0.9, 1024, 8192, 1, 80, '2024-11-19 08:38:14', '2025-01-06 14:01:08'),
|
||||||
|
(53, 'chat', 'OpenAI 高级语音', 'advanced-voice', 15, 1, 10, 0.9, 1024, 8192, 1, 44, '2024-12-20 10:34:45', '2025-01-06 14:01:08'),
|
||||||
|
(54, 'chat', 'Qwen2.5-14B-Instruct', 'Qwen2.5-14B-Instruct', 16, 1, 1, 0.9, 1024, 8192, 1, 81, '2024-12-25 14:53:17', '2025-01-06 14:01:08'),
|
||||||
|
(55, 'chat', 'Qwen2.5-7B-Instruct', 'Qwen2.5-7B-Instruct', 17, 1, 1, 0.9, 1024, 8192, 1, 81, '2024-12-25 15:15:49', '2025-01-06 14:01:08'),
|
||||||
|
(56, 'img', 'flux-1-schnell', 'flux-1-schnell', 18, 1, 1, 0.9, 1024, 8192, 1, 81, '2024-12-25 15:30:27', '2025-01-06 14:01:08'),
|
||||||
|
(57, 'img', 'dall-e-3', 'dall-e-3', 19, 1, 1, 0.9, 1024, 8192, 1, 57, '2024-12-25 16:54:06', '2025-01-06 14:01:08'),
|
||||||
|
(58, 'img', 'SD-3-medium', 'stable-diffusion-3-medium', 20, 1, 1, 0.9, 1024, 8192, 1, 81, '2024-12-27 10:03:28', '2025-01-06 14:01:08'),
|
||||||
|
(59, 'chat', 'O1-preview-all', 'O1-preview-all', 13, 1, 10, 0.9, 1024, 32000, 1, 57, '2025-01-06 14:01:04', '2025-01-06 14:01:08');
|
||||||
|
========
|
||||||
|
(49, 'chat', 'O1-mini', 'o1-mini', 10, 1, 2, 0.9, 1024, 8192, 1, 44, '2024-09-13 18:07:50', '2025-01-06 14:01:08'),
|
||||||
|
(50, 'chat', 'O1-preview', 'o1-preview', 11, 1, 5, 0.9, 1024, 8192, 1, 44, '2024-09-13 18:11:08', '2025-01-06 14:01:08'),
|
||||||
|
(51, 'chat', 'O1-mini-all', 'o1-mini-all', 12, 1, 1, 0.9, 1024, 8192, 1, 57, '2024-09-29 11:40:52', '2025-01-06 14:01:08'),
|
||||||
|
(53, 'chat', 'OpenAI 高级语音', 'advanced-voice', 15, 1, 10, 0.9, 1024, 8192, 1, 44, '2024-12-20 10:34:45', '2025-01-06 14:01:08'),
|
||||||
|
(55, 'chat', 'O3-mini', 'o3-mini', 17, 1, 5, 0.9, 1024, 8192, 1, 52, '2024-12-25 15:15:49', '2025-02-08 10:52:01'),
|
||||||
|
(56, 'img', 'flux-1-schnell', 'flux-1-schnell', 18, 1, 1, 0.9, 1024, 8192, 1, 81, '2024-12-25 15:30:27', '2025-01-06 14:01:08'),
|
||||||
|
(57, 'img', 'dall-e-3', 'dall-e-3', 19, 1, 1, 0.9, 1024, 8192, 1, 57, '2024-12-25 16:54:06', '2025-01-06 14:01:08'),
|
||||||
|
(58, 'img', 'SD-3-medium', 'stable-diffusion-3-medium', 20, 1, 1, 0.9, 1024, 8192, 1, 81, '2024-12-27 10:03:28', '2025-01-06 14:01:08'),
|
||||||
|
(59, 'chat', 'O1-preview-all', 'O1-preview-all', 13, 1, 10, 0.9, 1024, 32000, 1, 57, '2025-01-06 14:01:04', '2025-01-06 14:01:08'),
|
||||||
|
(60, 'chat', 'DeepSeek-R1-7B', 'deepseek-r1:7b', 20, 1, 1, 0.9, 1024, 8192, 1, 78, '2025-02-07 11:32:08', '2025-02-07 14:37:48'),
|
||||||
|
(61, 'chat', 'DeepSeek-R1-32B', 'deepseek-r1:32b', 21, 1, 1, 0.9, 1024, 8192, 1, 78, '2025-02-07 14:38:19', '2025-02-07 14:38:44');
|
||||||
|
>>>>>>>> v4.2.0:database/geekai_plus-v4.2.0.sql
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
@@ -247,8 +273,13 @@ CREATE TABLE `chatgpt_configs` (
|
|||||||
--
|
--
|
||||||
|
|
||||||
INSERT INTO `chatgpt_configs` (`id`, `marker`, `config_json`) VALUES
|
INSERT INTO `chatgpt_configs` (`id`, `marker`, `config_json`) VALUES
|
||||||
(1, 'system', '{\"title\":\"GeekAI 创作助手\",\"slogan\":\"我辈之人,先干为敬,让每一个人都能用好AI\",\"admin_title\":\"GeekAI 控制台\",\"logo\":\"/images/logo.png\",\"init_power\":100,\"invite_power\":200,\"vip_month_power\":1000,\"register_ways\":[\"username\",\"email\",\"mobile\"],\"enabled_register\":true,\"order_pay_timeout\":600,\"vip_info_text\":\"月度会员,年度会员每月赠送 1000 点算力,赠送算力当月有效当月没有消费完的算力不结余到下个月。 点卡充值的算力长期有效。\",\"mj_power\":20,\"mj_action_power\":5,\"sd_power\":5,\"dall_power\":10,\"suno_power\":10,\"luma_power\":120,\"wechat_card_url\":\"/images/wx.png\",\"enable_context\":true,\"context_deep\":10,\"sd_neg_prompt\":\"nsfw, paintings,low quality,easynegative,ng_deepnegative ,lowres,bad anatomy,bad hands,bad feet\",\"mj_mode\":\"fast\",\"index_bg_url\":\"color\",\"index_navs\":[1,5,13,19,9,12,6,20,8,10],\"copyright\":\"极客学长 © 2022- 2024 All rights reserved\",\"mark_map_text\":\"# GeekAI 演示站\\n\\n- 完整的开源系统,前端应用和后台管理系统皆可开箱即用。\\n- 基于 Websocket 实现,完美的打字机体验。\\n- 内置了各种预训练好的角色应用,轻松满足你的各种聊天和应用需求。\\n- 支持 OPenAI,Azure,文心一言,讯飞星火,清华 ChatGLM等多个大语言模型。\\n- 支持 MidJourney / Stable Diffusion AI 绘画集成,开箱即用。\\n- 支持使用个人微信二维码作为充值收费的支付渠道,无需企业支付通道。\\n- 已集成支付宝支付功能,微信支付,支持多种会员套餐和点卡购买功能。\\n- 集成插件 API 功能,可结合大语言模型的 function 功能开发各种强大的插件。\",\"enabled_verify\":false,\"email_white_list\":[\"qq.com\",\"163.com\",\"gmail.com\",\"hotmail.com\",\"126.com\",\"outlook.com\",\"foxmail.com\",\"yahoo.com\"],\"translate_model_id\":1}'),
|
<<<<<<<< HEAD:database/geekai_plus-v4.1.9.sql
|
||||||
(3, 'notice', '{\"sd_neg_prompt\":\"\",\"mj_mode\":\"\",\"index_bg_url\":\"\",\"index_navs\":null,\"copyright\":\"\",\"mark_map_text\":\"\",\"enabled_verify\":false,\"email_white_list\":null,\"translate_model_id\":0,\"content\":\"## v4.1.7 更新日志\\n\\n* Bug修复:手机邮箱相关的注册问题 [#IB0HS5](https://gitee.com/blackfox/geekai/issues/IB0HS5)\\n* Bug修复:音乐视频无法下载,思维导图下载后看不清文字[#IB0N2E](https://gitee.com/blackfox/geekai/issues/IB0N2E)\\n* 功能优化:保存所有AIGC任务的原始信息,程序启动之后自动将未执行的任务加入到 redis 队列\\n* 功能优化:失败的任务自动退回算力,而不需要在删除的时候再退回\\n* 功能新增:支持设置一个专门的模型来翻译提示词,提供 Mate 提示词生成功能\\n* Bug修复:修复图片对话的时候,上下文不起作用的Bug\\n* 功能新增:管理后台新增批量导出兑换码功能\\n\\n注意:当前站点仅为开源项目 \\u003ca style=\\\"color: #F56C6C\\\" href=\\\"https://github.com/yangjian102621/geekai\\\" target=\\\"_blank\\\"\\u003eGeekAI-Plus\\u003c/a\\u003e 的演示项目,本项目单纯就是给大家体验项目功能使用。\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n 如果觉得好用你就花几分钟自己部署一套,没有API KEY 的同学可以去下面几个推荐的中转站购买:\\n1、\\u003ca href=\\\"https://api.chat-plus.net\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.chat-plus.net\\u003c/a\\u003e\\n2、\\u003ca href=\\\"https://api.geekai.me\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.geekai.me\\u003c/a\\u003e\\n支持MidJourney,GPT,Claude,Google Gemmi,以及国内各个厂家的大模型,现在有超级优惠,价格远低于 OpenAI 官方。关于中转 API 的优势和劣势请参考 [中转API技术原理](https://docs.geekai.me/config/chat/#%E4%B8%AD%E8%BD%ACapi%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86)。GPT-3.5,GPT-4,DALL-E3 绘图......你都可以随意使用,无需魔法。\\n接入教程: \\u003ca href=\\\"https://docs.geekai.me\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://docs.geekai.me\\u003c/a\\u003e\\n本项目源码地址:\\u003ca href=\\\"https://github.com/yangjian102621/geekai\\\" target=\\\"_blank\\\"\\u003ehttps://github.com/yangjian102621/geekai\\u003c/a\\u003e\",\"updated\":true}');
|
(1, 'system', '{\"title\":\"GeekAI 创作助手\",\"slogan\":\"我辈之人,先干为敬,让每一个人都能用好AI\",\"admin_title\":\"GeekAI 控制台\",\"logo\":\"/images/logo.png\",\"bar_logo\":\"/images/bar_logo.png\",\"init_power\":100,\"daily_power\":1,\"invite_power\":200,\"vip_month_power\":1000,\"register_ways\":[\"username\",\"email\",\"mobile\"],\"enabled_register\":true,\"order_pay_timeout\":600,\"vip_info_text\":\"月度会员,年度会员每月赠送 1000 点算力,赠送算力当月有效当月没有消费完的算力不结余到下个月。 点卡充值的算力长期有效。\",\"mj_power\":20,\"mj_action_power\":5,\"sd_power\":5,\"dall_power\":10,\"suno_power\":10,\"luma_power\":120,\"advance_voice_power\":100,\"prompt_power\":1,\"wechat_card_url\":\"/images/wx.png\",\"enable_context\":true,\"context_deep\":10,\"sd_neg_prompt\":\"nsfw, paintings,low quality,easynegative,ng_deepnegative ,lowres,bad anatomy,bad hands,bad feet\",\"mj_mode\":\"fast\",\"index_navs\":[1,5,13,19,9,12,6,20,8,10],\"copyright\":\"极客学长\",\"icp\":\"粤ICP备19122051号\",\"mark_map_text\":\"# GeekAI 演示站\\n\\n- 完整的开源系统,前端应用和后台管理系统皆可开箱即用。\\n- 基于 Websocket 实现,完美的打字机体验。\\n- 内置了各种预训练好的角色应用,轻松满足你的各种聊天和应用需求。\\n- 支持 OPenAI,Azure,文心一言,讯飞星火,清华 ChatGLM等多个大语言模型。\\n- 支持 MidJourney / Stable Diffusion AI 绘画集成,开箱即用。\\n- 支持使用个人微信二维码作为充值收费的支付渠道,无需企业支付通道。\\n- 已集成支付宝支付功能,微信支付,支持多种会员套餐和点卡购买功能。\\n- 集成插件 API 功能,可结合大语言模型的 function 功能开发各种强大的插件。\",\"enabled_verify\":false,\"email_white_list\":[\"qq.com\",\"163.com\",\"gmail.com\",\"hotmail.com\",\"126.com\",\"outlook.com\",\"foxmail.com\",\"yahoo.com\"],\"translate_model_id\":1}'),
|
||||||
|
(3, 'notice', '{\"sd_neg_prompt\":\"\",\"mj_mode\":\"\",\"index_navs\":null,\"copyright\":\"\",\"icp\":\"\",\"mark_map_text\":\"\",\"enabled_verify\":false,\"email_white_list\":null,\"translate_model_id\":0,\"content\":\"## v4.1.9 更新日志\\n\\n- 功能优化:优化系统配置,移除已废弃的配置项\\n- 功能优化:GPT-O1 模型支持流式输出\\n- 功能优化:优化代码引用快样式,支持主题切换\\n- 功能优化:登录,注册页面允许替换用户自己的 Logo 和 Title\\n- Bug 修复:修复 OpenAI 实时语音通话没有检测用户算力不足的 Bug\\n- 功能新增:管理后台增加算力日志查询功能,支持按用户,按模型,按日期,按类型查询算力日志\\n- 功能优化:支持为模型绑定 Dalle 和 chat 类型的 API KEY\\n- 功能新增:支持管理后台设置 ICP 备案号\\n\\n注意:当前站点仅为开源项目 \\u003ca style=\\\"color: #F56C6C\\\" href=\\\"https://github.com/yangjian102621/geekai\\\" target=\\\"_blank\\\"\\u003eGeekAI-Plus\\u003c/a\\u003e 的演示项目,本项目单纯就是给大家体验项目功能使用。\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n 如果觉得好用你就花几分钟自己部署一套,没有API KEY 的同学可以去下面几个推荐的中转站购买:\\n1、\\u003ca href=\\\"https://api.chat-plus.net\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.chat-plus.net\\u003c/a\\u003e\\n2、\\u003ca href=\\\"https://api.geekai.me\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.geekai.me\\u003c/a\\u003e\\n支持MidJourney,GPT,Claude,Google Gemmi,以及国内各个厂家的大模型,现在有超级优惠,价格远低于 OpenAI 官方。关于中转 API 的优势和劣势请参考 [中转API技术原理](https://docs.geekai.me/config/chat/#%E4%B8%AD%E8%BD%ACapi%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86)。GPT-3.5,GPT-4,DALL-E3 绘图......你都可以随意使用,无需魔法。\\n接入教程: \\u003ca href=\\\"https://docs.geekai.me\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://docs.geekai.me\\u003c/a\\u003e\\n本项目源码地址:\\u003ca href=\\\"https://github.com/yangjian102621/geekai\\\" target=\\\"_blank\\\"\\u003ehttps://github.com/yangjian102621/geekai\\u003c/a\\u003e\",\"updated\":true}');
|
||||||
|
========
|
||||||
|
(1, 'system', '{\"title\":\"GeekAI 创作助手\",\"slogan\":\"我辈之人,先干为敬,让每一个人都能用好AI\",\"admin_title\":\"GeekAI 控制台\",\"logo\":\"/images/logo.png\",\"bar_logo\":\"/images/bar_logo.png\",\"init_power\":100,\"daily_power\":10,\"invite_power\":200,\"vip_month_power\":1000,\"register_ways\":[\"username\",\"email\",\"mobile\"],\"enabled_register\":true,\"order_pay_timeout\":600,\"vip_info_text\":\"月度会员,年度会员每月赠送 1000 点算力,赠送算力当月有效当月没有消费完的算力不结余到下个月。 点卡充值的算力长期有效。\",\"mj_power\":20,\"mj_action_power\":5,\"sd_power\":5,\"dall_power\":10,\"suno_power\":10,\"luma_power\":120,\"advance_voice_power\":100,\"prompt_power\":1,\"wechat_card_url\":\"/images/wx.png\",\"enable_context\":true,\"context_deep\":10,\"sd_neg_prompt\":\"nsfw, paintings,low quality,easynegative,ng_deepnegative ,lowres,bad anatomy,bad hands,bad feet\",\"mj_mode\":\"fast\",\"index_navs\":[1,5,13,19,9,12,6,20,8,10],\"copyright\":\"极客学长\",\"icp\":\"粤ICP备19122051号\",\"mark_map_text\":\"# GeekAI 演示站\\n\\n- 完整的开源系统,前端应用和后台管理系统皆可开箱即用。\\n- 基于 Websocket 实现,完美的打字机体验。\\n- 内置了各种预训练好的角色应用,轻松满足你的各种聊天和应用需求。\\n- 支持 OPenAI,Azure,文心一言,讯飞星火,清华 ChatGLM等多个大语言模型。\\n- 支持 MidJourney / Stable Diffusion AI 绘画集成,开箱即用。\\n- 支持使用个人微信二维码作为充值收费的支付渠道,无需企业支付通道。\\n- 已集成支付宝支付功能,微信支付,支持多种会员套餐和点卡购买功能。\\n- 集成插件 API 功能,可结合大语言模型的 function 功能开发各种强大的插件。\",\"enabled_verify\":false,\"email_white_list\":[\"qq.com\",\"163.com\",\"gmail.com\",\"hotmail.com\",\"126.com\",\"outlook.com\",\"foxmail.com\",\"yahoo.com\"],\"translate_model_id\":1}'),
|
||||||
|
(3, 'notice', '{\"sd_neg_prompt\":\"\",\"mj_mode\":\"\",\"index_navs\":null,\"copyright\":\"\",\"icp\":\"\",\"mark_map_text\":\"\",\"enabled_verify\":false,\"email_white_list\":null,\"translate_model_id\":0,\"content\":\"## v4.2.0 更新日志\\n\\n- 功能优化:优化聊天页面 Notice 组件样式,采用 Vuepress 文档样式\\n- Bug 修复:修复主题切换的组件显示异常问题\\n- 功能优化:支持 DeepSeek-R1 推理模型,优化推理样式输出\\n- 功能优化:优化 Suno 歌曲播放按钮样式,居中显示\\n- 功能优化:后台管理新增模型的时候,可以绑定所有的 API KEY,而不只是能绑定 Chat 类型的 API KEY\\n- 功能新增:新增每日签到功能,每日签到可以获得算力奖励\\n- 功能优化:兼容 OpenAI o3 系列模型\\n- 功能优化:API 默认开启允许跨域调用\\n\\n\\u003e **注意:** 当前站点仅为开源项目 \\u003ca style=\\\"color: #F56C6C\\\" href=\\\"https://github.com/yangjian102621/geekai\\\" target=\\\"_blank\\\"\\u003eGeekAI-Plus\\u003c/a\\u003e 的演示项目,本项目单纯就是给大家体验项目功能使用。\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n 如果觉得好用你就花几分钟自己部署一套,没有API KEY 的同学可以去下面几个推荐的中转站购买:\\n1、\\u003ca href=\\\"https://api.chat-plus.net\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.chat-plus.net\\u003c/a\\u003e\\n2、\\u003ca href=\\\"https://api.geekai.me\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.geekai.me\\u003c/a\\u003e\\n\\n支持MidJourney,GPT,Claude,Google Gemmi,以及国内各个厂家的大模型,现在有超级优惠,价格远低于 OpenAI 官方。关于中转 API 的优势和劣势请参考 [中转API技术原理](https://docs.geekai.me/config/chat/#%E4%B8%AD%E8%BD%ACapi%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86)。GPT-3.5,GPT-4,DALL-E3 绘图......你都可以随意使用,无需魔法。\\n接入教程: \\u003ca href=\\\"https://docs.geekai.me\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://docs.geekai.me\\u003c/a\\u003e\\n本项目源码地址:\\u003ca href=\\\"https://github.com/yangjian102621/geekai\\\" target=\\\"_blank\\\"\\u003ehttps://github.com/yangjian102621/geekai\\u003c/a\\u003e\",\"updated\":true}');
|
||||||
|
>>>>>>>> v4.2.0:database/geekai_plus-v4.2.0.sql
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
@@ -267,7 +298,7 @@ CREATE TABLE `chatgpt_dall_jobs` (
|
|||||||
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
||||||
`power` smallint NOT NULL COMMENT '消耗算力',
|
`power` smallint NOT NULL COMMENT '消耗算力',
|
||||||
`progress` smallint NOT NULL COMMENT '任务进度',
|
`progress` smallint NOT NULL COMMENT '任务进度',
|
||||||
`err_msg` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '错误信息',
|
`err_msg` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '错误信息',
|
||||||
`created_at` datetime NOT NULL
|
`created_at` datetime NOT NULL
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='DALLE 绘图任务表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='DALLE 绘图任务表';
|
||||||
|
|
||||||
@@ -370,20 +401,19 @@ CREATE TABLE `chatgpt_menus` (
|
|||||||
--
|
--
|
||||||
|
|
||||||
INSERT INTO `chatgpt_menus` (`id`, `name`, `icon`, `url`, `sort_num`, `enabled`) VALUES
|
INSERT INTO `chatgpt_menus` (`id`, `name`, `icon`, `url`, `sort_num`, `enabled`) VALUES
|
||||||
(1, 'AI 对话', '/images/menu/chat.png', '/chat', 1, 1),
|
(1, 'AI 对话', 'icon-chat', '/chat', 1, 1),
|
||||||
(5, 'MJ 绘画', '/images/menu/mj.png', '/mj', 2, 1),
|
(5, 'MJ 绘画', 'icon-mj', '/mj', 2, 1),
|
||||||
(6, 'SD 绘画', '/images/menu/sd.png', '/sd', 3, 1),
|
(6, 'SD 绘画', 'icon-sd', '/sd', 3, 1),
|
||||||
(7, '算力日志', '/images/menu/log.png', '/powerLog', 10, 1),
|
(7, '算力日志', 'icon-file', '/powerLog', 10, 1),
|
||||||
(8, '应用中心', '/images/menu/app.png', '/apps', 9, 1),
|
(8, '应用中心', 'icon-app', '/apps', 9, 1),
|
||||||
(9, '画廊', '/images/menu/img-wall.png', '/images-wall', 5, 1),
|
(9, '画廊', 'icon-image', '/images-wall', 5, 1),
|
||||||
(10, '会员计划', '/images/menu/member.png', '/member', 11, 1),
|
(10, '会员计划', 'icon-vip2', '/member', 11, 1),
|
||||||
(11, '分享计划', '/images/menu/share.png', '/invite', 12, 1),
|
(11, '分享计划', 'icon-share1', '/invite', 12, 1),
|
||||||
(12, '思维导图', '/images/menu/xmind.png', '/xmind', 8, 1),
|
(12, '思维导图', 'icon-xmind', '/xmind', 8, 1),
|
||||||
(13, 'DALLE', '/images/menu/dalle.png', '/dalle', 4, 1),
|
(13, 'DALLE', 'icon-dalle', '/dalle', 4, 1),
|
||||||
(14, '项目文档', '/images/menu/docs.png', 'https://docs.geekai.me', 13, 1),
|
(14, '项目文档', 'icon-book', 'https://docs.geekai.me', 13, 1),
|
||||||
(16, '极客论坛', '/images/menu/bbs.png', 'https://bbs.geekai.cn', 14, 1),
|
(19, 'Suno', 'icon-suno', '/suno', 6, 1),
|
||||||
(19, 'Suno', '/images/menu/suno.png', '/suno', 6, 1),
|
(20, 'Luma', 'icon-luma', '/luma', 7, 1);
|
||||||
(20, 'Luma', '/images/menu/luma.png', '/luma', 7, 1);
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
@@ -408,7 +438,7 @@ CREATE TABLE `chatgpt_mj_jobs` (
|
|||||||
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
||||||
`use_proxy` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否使用反代',
|
`use_proxy` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否使用反代',
|
||||||
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
||||||
`err_msg` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '错误信息',
|
`err_msg` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '错误信息',
|
||||||
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
||||||
`created_at` datetime NOT NULL
|
`created_at` datetime NOT NULL
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='MidJourney 任务表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='MidJourney 任务表';
|
||||||
@@ -526,7 +556,7 @@ CREATE TABLE `chatgpt_sd_jobs` (
|
|||||||
`params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '绘画参数json',
|
`params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '绘画参数json',
|
||||||
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
||||||
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
||||||
`err_msg` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '错误信息',
|
`err_msg` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '错误信息',
|
||||||
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
||||||
`created_at` datetime NOT NULL
|
`created_at` datetime NOT NULL
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Stable Diffusion 任务表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Stable Diffusion 任务表';
|
||||||
@@ -559,7 +589,7 @@ CREATE TABLE `chatgpt_suno_jobs` (
|
|||||||
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
||||||
`duration` smallint NOT NULL DEFAULT '0' COMMENT '歌曲时长',
|
`duration` smallint NOT NULL DEFAULT '0' COMMENT '歌曲时长',
|
||||||
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
||||||
`err_msg` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '错误信息',
|
`err_msg` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '错误信息',
|
||||||
`raw_data` text COMMENT '原始数据',
|
`raw_data` text COMMENT '原始数据',
|
||||||
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
||||||
`play_times` int DEFAULT NULL COMMENT '播放次数',
|
`play_times` int DEFAULT NULL COMMENT '播放次数',
|
||||||
@@ -602,7 +632,14 @@ CREATE TABLE `chatgpt_users` (
|
|||||||
--
|
--
|
||||||
|
|
||||||
INSERT INTO `chatgpt_users` (`id`, `username`, `mobile`, `email`, `nickname`, `password`, `avatar`, `salt`, `power`, `expired_time`, `status`, `chat_config_json`, `chat_roles_json`, `chat_models_json`, `last_login_at`, `vip`, `last_login_ip`, `openid`, `platform`, `created_at`, `updated_at`) VALUES
|
INSERT INTO `chatgpt_users` (`id`, `username`, `mobile`, `email`, `nickname`, `password`, `avatar`, `salt`, `power`, `expired_time`, `status`, `chat_config_json`, `chat_roles_json`, `chat_models_json`, `last_login_at`, `vip`, `last_login_ip`, `openid`, `platform`, `created_at`, `updated_at`) VALUES
|
||||||
(4, '18888888888', '18575670126', '', '极客学长', 'ccc3fb7ab61b8b5d096a4a166ae21d121fc38c71bbd1be6173d9ab973214a63b', 'http://localhost:5678/static/upload/2024/5/1715651569509929.png', 'ueedue5l', 13185, 0, 1, '{\"api_keys\":{\"Azure\":\"\",\"ChatGLM\":\"\",\"OpenAI\":\"\"}}', '[\"gpt\",\"programmer\",\"teacher\",\"psychiatrist\",\"lu_xun\",\"english_trainer\",\"translator\",\"red_book\",\"dou_yin\",\"weekly_report\",\"girl_friend\",\"steve_jobs\",\"elon_musk\",\"kong_zi\",\"draw_prompt_expert\",\"draw_prompt\",\"prompt_engineer\"]', '[1]', 1732676556, 1, '::1', 'oCs0t64FaOLfiTbHZpOqk3aUp_94', NULL, '2023-06-12 16:47:17', '2024-11-27 11:02:37');
|
<<<<<<<< HEAD:database/geekai_plus-v4.1.9.sql
|
||||||
|
(4, '18888888888', '18575670126', '', '极客学长', 'ccc3fb7ab61b8b5d096a4a166ae21d121fc38c71bbd1be6173d9ab973214a63b', 'http://localhost:5678/static/upload/2024/5/1715651569509929.png', 'ueedue5l', 12917, 0, 1, '{\"api_keys\":{\"Azure\":\"\",\"ChatGLM\":\"\",\"OpenAI\":\"\"}}', '[\"gpt\",\"programmer\",\"teacher\",\"psychiatrist\",\"lu_xun\",\"english_trainer\",\"translator\",\"red_book\",\"dou_yin\",\"weekly_report\",\"girl_friend\",\"steve_jobs\",\"elon_musk\",\"kong_zi\",\"draw_prompt_expert\",\"draw_prompt\",\"prompt_engineer\"]', '[1]', 1736391097, 1, '::1', '', NULL, '2023-06-12 16:47:17', '2025-01-09 10:51:38'),
|
||||||
|
========
|
||||||
|
(4, '18888888888', '18575670126', '', '极客学长', 'ccc3fb7ab61b8b5d096a4a166ae21d121fc38c71bbd1be6173d9ab973214a63b', 'http://localhost:5678/static/upload/2024/5/1715651569509929.png', 'ueedue5l', 12897, 0, 1, '{\"api_keys\":{\"Azure\":\"\",\"ChatGLM\":\"\",\"OpenAI\":\"\"}}', '[\"gpt\",\"programmer\",\"teacher\",\"psychiatrist\",\"lu_xun\",\"english_trainer\",\"translator\",\"red_book\",\"dou_yin\",\"weekly_report\",\"girl_friend\",\"steve_jobs\",\"elon_musk\",\"kong_zi\",\"draw_prompt_expert\",\"draw_prompt\",\"prompt_engineer\"]', '[1]', 1738897982, 1, '::1', '', NULL, '2023-06-12 16:47:17', '2025-02-07 11:13:03'),
|
||||||
|
>>>>>>>> v4.2.0:database/geekai_plus-v4.2.0.sql
|
||||||
|
(47, 'user1', '', '', '极客学长@202752', '4d3e57a01ae826531012e4ea6e17cbc45fea183467abe9813c379fb84916fb0a', '/images/avatar/user.png', 'ixl0nqa6', 300, 0, 1, '', '[\"gpt\"]', '', 0, 0, '', '', '', '2024-12-24 11:37:16', '2024-12-24 11:37:16'),
|
||||||
|
(48, 'wx@3659838859', '', '', '极客学长', 'cf6bbe381b23812d2b9fd423abe74003cecdd3b93809896eb573536ba6c500b3', 'https://thirdwx.qlogo.cn/mmopen/vi_32/uyxRMqZcEkb7fHouKXbNzxrnrvAttBKkwNlZ7yFibibRGiahdmsrZ3A1NKf8Fw5qJNJn4TXRmygersgEbibaSGd9Sg/132', '5rsy4iwg', 100, 0, 1, '', '[\"gpt\"]', '', 1736228927, 0, '172.22.11.200', 'oCs0t62472W19z2LOEKI1rWyCTTA', '', '2025-01-07 13:43:06', '2025-01-07 13:48:48'),
|
||||||
|
(49, 'wx@9502480897', '', '', 'AI探索君', 'd99fa8ba7da1455693b40e11d894a067416e758af2a75d7a3df4721b76cdbc8c', 'https://thirdwx.qlogo.cn/mmopen/vi_32/Zpcln1FZjcKxqtIyCsOTLGn16s7uIvwWfdkdsW6gbZg4r9sibMbic4jvrHmV7ux9nseTB5kBSnu1HSXr7zB8rTXg/132', 'fjclgsli', 100, 0, 1, '', '[\"gpt\"]', '', 0, 0, '', 'oCs0t64FaOLfiTbHZpOqk3aUp_94', '', '2025-01-07 14:05:31', '2025-01-07 14:05:31');
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
@@ -642,7 +679,7 @@ CREATE TABLE `chatgpt_video_jobs` (
|
|||||||
`water_url` varchar(512) DEFAULT NULL COMMENT '带水印的视频地址',
|
`water_url` varchar(512) DEFAULT NULL COMMENT '带水印的视频地址',
|
||||||
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
||||||
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
||||||
`err_msg` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '错误信息',
|
`err_msg` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '错误信息',
|
||||||
`raw_data` text COMMENT '原始数据',
|
`raw_data` text COMMENT '原始数据',
|
||||||
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
||||||
`created_at` datetime NOT NULL
|
`created_at` datetime NOT NULL
|
||||||
@@ -847,7 +884,11 @@ ALTER TABLE `chatgpt_chat_items`
|
|||||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_models`
|
-- 使用表AUTO_INCREMENT `chatgpt_chat_models`
|
||||||
--
|
--
|
||||||
ALTER TABLE `chatgpt_chat_models`
|
ALTER TABLE `chatgpt_chat_models`
|
||||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=53;
|
<<<<<<<< HEAD:database/geekai_plus-v4.1.9.sql
|
||||||
|
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=60;
|
||||||
|
========
|
||||||
|
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=62;
|
||||||
|
>>>>>>>> v4.2.0:database/geekai_plus-v4.2.0.sql
|
||||||
|
|
||||||
--
|
--
|
||||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_roles`
|
-- 使用表AUTO_INCREMENT `chatgpt_chat_roles`
|
||||||
@@ -943,7 +984,7 @@ ALTER TABLE `chatgpt_suno_jobs`
|
|||||||
-- 使用表AUTO_INCREMENT `chatgpt_users`
|
-- 使用表AUTO_INCREMENT `chatgpt_users`
|
||||||
--
|
--
|
||||||
ALTER TABLE `chatgpt_users`
|
ALTER TABLE `chatgpt_users`
|
||||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=47;
|
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=50;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- 使用表AUTO_INCREMENT `chatgpt_user_login_logs`
|
-- 使用表AUTO_INCREMENT `chatgpt_user_login_logs`
|
||||||
0
deploy/.gitignore → docker/.gitignore
vendored
0
deploy/.gitignore → docker/.gitignore
vendored
@@ -3,7 +3,7 @@ ProxyURL = ""
|
|||||||
MysqlDns = "root:mhSCk0NheGhmtsha@tcp(geekai-mysql:3306)/geekai_plus?charset=utf8mb4&collation=utf8mb4_unicode_ci&parseTime=True&loc=Local"
|
MysqlDns = "root:mhSCk0NheGhmtsha@tcp(geekai-mysql:3306)/geekai_plus?charset=utf8mb4&collation=utf8mb4_unicode_ci&parseTime=True&loc=Local"
|
||||||
StaticDir = "./static"
|
StaticDir = "./static"
|
||||||
StaticUrl = "/static"
|
StaticUrl = "/static"
|
||||||
TikaHost = "http://tika:9998"
|
TikaHost = "http://tika-geekai:9998"
|
||||||
|
|
||||||
[Session]
|
[Session]
|
||||||
SecretKey = "azyehq3ivunjhbntz78isj00i4hz2mt9xtddysfucxakadq4qbfrt0b7q3lnvg80"
|
SecretKey = "azyehq3ivunjhbntz78isj00i4hz2mt9xtddysfucxakadq4qbfrt0b7q3lnvg80"
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
-- https://www.phpmyadmin.net/
|
-- https://www.phpmyadmin.net/
|
||||||
--
|
--
|
||||||
-- 主机: 127.0.0.1
|
-- 主机: 127.0.0.1
|
||||||
-- 生成日期: 2025-01-10 17:39:25
|
-- 生成日期: 2025-02-10 10:17:27
|
||||||
-- 服务器版本: 8.0.33
|
-- 服务器版本: 8.0.33
|
||||||
-- PHP 版本: 8.1.2-1ubuntu2.20
|
-- PHP 版本: 8.1.2-1ubuntu2.20
|
||||||
|
|
||||||
@@ -177,18 +177,17 @@ INSERT INTO `chatgpt_chat_models` (`id`, `type`, `name`, `value`, `sort_num`, `e
|
|||||||
(42, 'chat', 'DeekSeek', 'deepseek-chat', 8, 1, 1, 1.0, 4096, 32768, 1, 57, '2024-06-27 16:13:01', '2025-01-06 14:11:51'),
|
(42, 'chat', 'DeekSeek', 'deepseek-chat', 8, 1, 1, 1.0, 4096, 32768, 1, 57, '2024-06-27 16:13:01', '2025-01-06 14:11:51'),
|
||||||
(44, 'chat', 'Claude3-opus', 'claude-3-opus-20240229', 6, 1, 5, 1.0, 4000, 128000, 1, 44, '2024-07-22 11:24:30', '2025-01-06 14:01:08'),
|
(44, 'chat', 'Claude3-opus', 'claude-3-opus-20240229', 6, 1, 5, 1.0, 4000, 128000, 1, 44, '2024-07-22 11:24:30', '2025-01-06 14:01:08'),
|
||||||
(46, 'chat', 'gpt-3.5-turbo', 'gpt-3.5-turbo', 2, 1, 1, 1.0, 1024, 4096, 1, 75, '2024-07-22 13:53:41', '2025-01-08 10:33:07'),
|
(46, 'chat', 'gpt-3.5-turbo', 'gpt-3.5-turbo', 2, 1, 1, 1.0, 1024, 4096, 1, 75, '2024-07-22 13:53:41', '2025-01-08 10:33:07'),
|
||||||
(48, 'chat', '彩票助手', 'gpt-4-gizmo-g-wmSivBgxo', 9, 1, 1, 0.9, 1024, 8192, 1, 57, '2024-09-05 14:17:14', '2025-01-06 14:01:08'),
|
|
||||||
(49, 'chat', 'O1-mini', 'o1-mini', 10, 1, 2, 0.9, 1024, 8192, 1, 44, '2024-09-13 18:07:50', '2025-01-06 14:01:08'),
|
(49, 'chat', 'O1-mini', 'o1-mini', 10, 1, 2, 0.9, 1024, 8192, 1, 44, '2024-09-13 18:07:50', '2025-01-06 14:01:08'),
|
||||||
(50, 'chat', 'O1-preview', 'o1-preview', 11, 1, 5, 0.9, 1024, 8192, 1, 44, '2024-09-13 18:11:08', '2025-01-06 14:01:08'),
|
(50, 'chat', 'O1-preview', 'o1-preview', 11, 1, 5, 0.9, 1024, 8192, 1, 44, '2024-09-13 18:11:08', '2025-01-06 14:01:08'),
|
||||||
(51, 'chat', 'O1-mini-all', 'o1-mini-all', 12, 1, 1, 0.9, 1024, 8192, 1, 57, '2024-09-29 11:40:52', '2025-01-06 14:01:08'),
|
(51, 'chat', 'O1-mini-all', 'o1-mini-all', 12, 1, 1, 0.9, 1024, 8192, 1, 57, '2024-09-29 11:40:52', '2025-01-06 14:01:08'),
|
||||||
(52, 'chat', '通义千问', 'qwen-plus', 14, 1, 1, 0.9, 1024, 8192, 1, 80, '2024-11-19 08:38:14', '2025-01-06 14:01:08'),
|
|
||||||
(53, 'chat', 'OpenAI 高级语音', 'advanced-voice', 15, 1, 10, 0.9, 1024, 8192, 1, 44, '2024-12-20 10:34:45', '2025-01-06 14:01:08'),
|
(53, 'chat', 'OpenAI 高级语音', 'advanced-voice', 15, 1, 10, 0.9, 1024, 8192, 1, 44, '2024-12-20 10:34:45', '2025-01-06 14:01:08'),
|
||||||
(54, 'chat', 'Qwen2.5-14B-Instruct', 'Qwen2.5-14B-Instruct', 16, 1, 1, 0.9, 1024, 8192, 1, 81, '2024-12-25 14:53:17', '2025-01-06 14:01:08'),
|
(55, 'chat', 'O3-mini', 'o3-mini', 17, 1, 5, 0.9, 1024, 8192, 1, 52, '2024-12-25 15:15:49', '2025-02-08 10:52:01'),
|
||||||
(55, 'chat', 'Qwen2.5-7B-Instruct', 'Qwen2.5-7B-Instruct', 17, 1, 1, 0.9, 1024, 8192, 1, 81, '2024-12-25 15:15:49', '2025-01-06 14:01:08'),
|
|
||||||
(56, 'img', 'flux-1-schnell', 'flux-1-schnell', 18, 1, 1, 0.9, 1024, 8192, 1, 81, '2024-12-25 15:30:27', '2025-01-06 14:01:08'),
|
(56, 'img', 'flux-1-schnell', 'flux-1-schnell', 18, 1, 1, 0.9, 1024, 8192, 1, 81, '2024-12-25 15:30:27', '2025-01-06 14:01:08'),
|
||||||
(57, 'img', 'dall-e-3', 'dall-e-3', 19, 1, 1, 0.9, 1024, 8192, 1, 57, '2024-12-25 16:54:06', '2025-01-06 14:01:08'),
|
(57, 'img', 'dall-e-3', 'dall-e-3', 19, 1, 1, 0.9, 1024, 8192, 1, 57, '2024-12-25 16:54:06', '2025-01-06 14:01:08'),
|
||||||
(58, 'img', 'SD-3-medium', 'stable-diffusion-3-medium', 20, 1, 1, 0.9, 1024, 8192, 1, 81, '2024-12-27 10:03:28', '2025-01-06 14:01:08'),
|
(58, 'img', 'SD-3-medium', 'stable-diffusion-3-medium', 20, 1, 1, 0.9, 1024, 8192, 1, 81, '2024-12-27 10:03:28', '2025-01-06 14:01:08'),
|
||||||
(59, 'chat', 'O1-preview-all', 'O1-preview-all', 13, 1, 10, 0.9, 1024, 32000, 1, 57, '2025-01-06 14:01:04', '2025-01-06 14:01:08');
|
(59, 'chat', 'O1-preview-all', 'O1-preview-all', 13, 1, 10, 0.9, 1024, 32000, 1, 57, '2025-01-06 14:01:04', '2025-01-06 14:01:08'),
|
||||||
|
(60, 'chat', 'DeepSeek-R1-7B', 'deepseek-r1:7b', 20, 1, 1, 0.9, 1024, 8192, 1, 78, '2025-02-07 11:32:08', '2025-02-07 14:37:48'),
|
||||||
|
(61, 'chat', 'DeepSeek-R1-32B', 'deepseek-r1:32b', 21, 1, 1, 0.9, 1024, 8192, 1, 78, '2025-02-07 14:38:19', '2025-02-07 14:38:44');
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
@@ -255,8 +254,8 @@ CREATE TABLE `chatgpt_configs` (
|
|||||||
--
|
--
|
||||||
|
|
||||||
INSERT INTO `chatgpt_configs` (`id`, `marker`, `config_json`) VALUES
|
INSERT INTO `chatgpt_configs` (`id`, `marker`, `config_json`) VALUES
|
||||||
(1, 'system', '{\"title\":\"GeekAI 创作助手\",\"slogan\":\"我辈之人,先干为敬,让每一个人都能用好AI\",\"admin_title\":\"GeekAI 控制台\",\"logo\":\"/images/logo.png\",\"bar_logo\":\"/images/bar_logo.png\",\"init_power\":100,\"daily_power\":1,\"invite_power\":200,\"vip_month_power\":1000,\"register_ways\":[\"username\",\"email\",\"mobile\"],\"enabled_register\":true,\"order_pay_timeout\":600,\"vip_info_text\":\"月度会员,年度会员每月赠送 1000 点算力,赠送算力当月有效当月没有消费完的算力不结余到下个月。 点卡充值的算力长期有效。\",\"mj_power\":20,\"mj_action_power\":5,\"sd_power\":5,\"dall_power\":10,\"suno_power\":10,\"luma_power\":120,\"advance_voice_power\":100,\"prompt_power\":1,\"wechat_card_url\":\"/images/wx.png\",\"enable_context\":true,\"context_deep\":10,\"sd_neg_prompt\":\"nsfw, paintings,low quality,easynegative,ng_deepnegative ,lowres,bad anatomy,bad hands,bad feet\",\"mj_mode\":\"fast\",\"index_navs\":[1,5,13,19,9,12,6,20,8,10],\"copyright\":\"极客学长\",\"icp\":\"粤ICP备19122051号\",\"mark_map_text\":\"# GeekAI 演示站\\n\\n- 完整的开源系统,前端应用和后台管理系统皆可开箱即用。\\n- 基于 Websocket 实现,完美的打字机体验。\\n- 内置了各种预训练好的角色应用,轻松满足你的各种聊天和应用需求。\\n- 支持 OPenAI,Azure,文心一言,讯飞星火,清华 ChatGLM等多个大语言模型。\\n- 支持 MidJourney / Stable Diffusion AI 绘画集成,开箱即用。\\n- 支持使用个人微信二维码作为充值收费的支付渠道,无需企业支付通道。\\n- 已集成支付宝支付功能,微信支付,支持多种会员套餐和点卡购买功能。\\n- 集成插件 API 功能,可结合大语言模型的 function 功能开发各种强大的插件。\",\"enabled_verify\":false,\"email_white_list\":[\"qq.com\",\"163.com\",\"gmail.com\",\"hotmail.com\",\"126.com\",\"outlook.com\",\"foxmail.com\",\"yahoo.com\"],\"translate_model_id\":1}'),
|
(1, 'system', '{\"title\":\"GeekAI 创作助手\",\"slogan\":\"我辈之人,先干为敬,让每一个人都能用好AI\",\"admin_title\":\"GeekAI 控制台\",\"logo\":\"/images/logo.png\",\"bar_logo\":\"/images/bar_logo.png\",\"init_power\":100,\"daily_power\":10,\"invite_power\":200,\"vip_month_power\":1000,\"register_ways\":[\"username\",\"email\",\"mobile\"],\"enabled_register\":true,\"order_pay_timeout\":600,\"vip_info_text\":\"月度会员,年度会员每月赠送 1000 点算力,赠送算力当月有效当月没有消费完的算力不结余到下个月。 点卡充值的算力长期有效。\",\"mj_power\":20,\"mj_action_power\":5,\"sd_power\":5,\"dall_power\":10,\"suno_power\":10,\"luma_power\":120,\"advance_voice_power\":100,\"prompt_power\":1,\"wechat_card_url\":\"/images/wx.png\",\"enable_context\":true,\"context_deep\":10,\"sd_neg_prompt\":\"nsfw, paintings,low quality,easynegative,ng_deepnegative ,lowres,bad anatomy,bad hands,bad feet\",\"mj_mode\":\"fast\",\"index_navs\":[1,5,13,19,9,12,6,20,8,10],\"copyright\":\"极客学长\",\"icp\":\"粤ICP备19122051号\",\"mark_map_text\":\"# GeekAI 演示站\\n\\n- 完整的开源系统,前端应用和后台管理系统皆可开箱即用。\\n- 基于 Websocket 实现,完美的打字机体验。\\n- 内置了各种预训练好的角色应用,轻松满足你的各种聊天和应用需求。\\n- 支持 OPenAI,Azure,文心一言,讯飞星火,清华 ChatGLM等多个大语言模型。\\n- 支持 MidJourney / Stable Diffusion AI 绘画集成,开箱即用。\\n- 支持使用个人微信二维码作为充值收费的支付渠道,无需企业支付通道。\\n- 已集成支付宝支付功能,微信支付,支持多种会员套餐和点卡购买功能。\\n- 集成插件 API 功能,可结合大语言模型的 function 功能开发各种强大的插件。\",\"enabled_verify\":false,\"email_white_list\":[\"qq.com\",\"163.com\",\"gmail.com\",\"hotmail.com\",\"126.com\",\"outlook.com\",\"foxmail.com\",\"yahoo.com\"],\"translate_model_id\":1}'),
|
||||||
(3, 'notice', '{\"sd_neg_prompt\":\"\",\"mj_mode\":\"\",\"index_navs\":null,\"copyright\":\"\",\"icp\":\"\",\"mark_map_text\":\"\",\"enabled_verify\":false,\"email_white_list\":null,\"translate_model_id\":0,\"content\":\"## v4.1.9 更新日志\\n\\n- 功能优化:优化系统配置,移除已废弃的配置项\\n- 功能优化:GPT-O1 模型支持流式输出\\n- 功能优化:优化代码引用快样式,支持主题切换\\n- 功能优化:登录,注册页面允许替换用户自己的 Logo 和 Title\\n- Bug 修复:修复 OpenAI 实时语音通话没有检测用户算力不足的 Bug\\n- 功能新增:管理后台增加算力日志查询功能,支持按用户,按模型,按日期,按类型查询算力日志\\n- 功能优化:支持为模型绑定 Dalle 和 chat 类型的 API KEY\\n- 功能新增:支持管理后台设置 ICP 备案号\\n\\n注意:当前站点仅为开源项目 \\u003ca style=\\\"color: #F56C6C\\\" href=\\\"https://github.com/yangjian102621/geekai\\\" target=\\\"_blank\\\"\\u003eGeekAI-Plus\\u003c/a\\u003e 的演示项目,本项目单纯就是给大家体验项目功能使用。\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n 如果觉得好用你就花几分钟自己部署一套,没有API KEY 的同学可以去下面几个推荐的中转站购买:\\n1、\\u003ca href=\\\"https://api.chat-plus.net\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.chat-plus.net\\u003c/a\\u003e\\n2、\\u003ca href=\\\"https://api.geekai.me\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.geekai.me\\u003c/a\\u003e\\n支持MidJourney,GPT,Claude,Google Gemmi,以及国内各个厂家的大模型,现在有超级优惠,价格远低于 OpenAI 官方。关于中转 API 的优势和劣势请参考 [中转API技术原理](https://docs.geekai.me/config/chat/#%E4%B8%AD%E8%BD%ACapi%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86)。GPT-3.5,GPT-4,DALL-E3 绘图......你都可以随意使用,无需魔法。\\n接入教程: \\u003ca href=\\\"https://docs.geekai.me\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://docs.geekai.me\\u003c/a\\u003e\\n本项目源码地址:\\u003ca href=\\\"https://github.com/yangjian102621/geekai\\\" target=\\\"_blank\\\"\\u003ehttps://github.com/yangjian102621/geekai\\u003c/a\\u003e\",\"updated\":true}');
|
(3, 'notice', '{\"sd_neg_prompt\":\"\",\"mj_mode\":\"\",\"index_navs\":null,\"copyright\":\"\",\"icp\":\"\",\"mark_map_text\":\"\",\"enabled_verify\":false,\"email_white_list\":null,\"translate_model_id\":0,\"content\":\"## v4.2.0 更新日志\\n\\n- 功能优化:优化聊天页面 Notice 组件样式,采用 Vuepress 文档样式\\n- Bug 修复:修复主题切换的组件显示异常问题\\n- 功能优化:支持 DeepSeek-R1 推理模型,优化推理样式输出\\n- 功能优化:优化 Suno 歌曲播放按钮样式,居中显示\\n- 功能优化:后台管理新增模型的时候,可以绑定所有的 API KEY,而不只是能绑定 Chat 类型的 API KEY\\n- 功能新增:新增每日签到功能,每日签到可以获得算力奖励\\n- 功能优化:兼容 OpenAI o3 系列模型\\n- 功能优化:API 默认开启允许跨域调用\\n\\n\\u003e **注意:** 当前站点仅为开源项目 \\u003ca style=\\\"color: #F56C6C\\\" href=\\\"https://github.com/yangjian102621/geekai\\\" target=\\\"_blank\\\"\\u003eGeekAI-Plus\\u003c/a\\u003e 的演示项目,本项目单纯就是给大家体验项目功能使用。\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n 如果觉得好用你就花几分钟自己部署一套,没有API KEY 的同学可以去下面几个推荐的中转站购买:\\n1、\\u003ca href=\\\"https://api.chat-plus.net\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.chat-plus.net\\u003c/a\\u003e\\n2、\\u003ca href=\\\"https://api.geekai.me\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.geekai.me\\u003c/a\\u003e\\n\\n支持MidJourney,GPT,Claude,Google Gemmi,以及国内各个厂家的大模型,现在有超级优惠,价格远低于 OpenAI 官方。关于中转 API 的优势和劣势请参考 [中转API技术原理](https://docs.geekai.me/config/chat/#%E4%B8%AD%E8%BD%ACapi%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86)。GPT-3.5,GPT-4,DALL-E3 绘图......你都可以随意使用,无需魔法。\\n接入教程: \\u003ca href=\\\"https://docs.geekai.me\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://docs.geekai.me\\u003c/a\\u003e\\n本项目源码地址:\\u003ca href=\\\"https://github.com/yangjian102621/geekai\\\" target=\\\"_blank\\\"\\u003ehttps://github.com/yangjian102621/geekai\\u003c/a\\u003e\",\"updated\":true}');
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
@@ -609,7 +608,7 @@ CREATE TABLE `chatgpt_users` (
|
|||||||
--
|
--
|
||||||
|
|
||||||
INSERT INTO `chatgpt_users` (`id`, `username`, `mobile`, `email`, `nickname`, `password`, `avatar`, `salt`, `power`, `expired_time`, `status`, `chat_config_json`, `chat_roles_json`, `chat_models_json`, `last_login_at`, `vip`, `last_login_ip`, `openid`, `platform`, `created_at`, `updated_at`) VALUES
|
INSERT INTO `chatgpt_users` (`id`, `username`, `mobile`, `email`, `nickname`, `password`, `avatar`, `salt`, `power`, `expired_time`, `status`, `chat_config_json`, `chat_roles_json`, `chat_models_json`, `last_login_at`, `vip`, `last_login_ip`, `openid`, `platform`, `created_at`, `updated_at`) VALUES
|
||||||
(4, '18888888888', '18575670126', '', '极客学长', 'ccc3fb7ab61b8b5d096a4a166ae21d121fc38c71bbd1be6173d9ab973214a63b', 'http://localhost:5678/static/upload/2024/5/1715651569509929.png', 'ueedue5l', 12917, 0, 1, '{\"api_keys\":{\"Azure\":\"\",\"ChatGLM\":\"\",\"OpenAI\":\"\"}}', '[\"gpt\",\"programmer\",\"teacher\",\"psychiatrist\",\"lu_xun\",\"english_trainer\",\"translator\",\"red_book\",\"dou_yin\",\"weekly_report\",\"girl_friend\",\"steve_jobs\",\"elon_musk\",\"kong_zi\",\"draw_prompt_expert\",\"draw_prompt\",\"prompt_engineer\"]', '[1]', 1736391097, 1, '::1', '', NULL, '2023-06-12 16:47:17', '2025-01-09 10:51:38'),
|
(4, '18888888888', '18575670126', '', '极客学长', 'ccc3fb7ab61b8b5d096a4a166ae21d121fc38c71bbd1be6173d9ab973214a63b', 'http://localhost:5678/static/upload/2024/5/1715651569509929.png', 'ueedue5l', 12897, 0, 1, '{\"api_keys\":{\"Azure\":\"\",\"ChatGLM\":\"\",\"OpenAI\":\"\"}}', '[\"gpt\",\"programmer\",\"teacher\",\"psychiatrist\",\"lu_xun\",\"english_trainer\",\"translator\",\"red_book\",\"dou_yin\",\"weekly_report\",\"girl_friend\",\"steve_jobs\",\"elon_musk\",\"kong_zi\",\"draw_prompt_expert\",\"draw_prompt\",\"prompt_engineer\"]', '[1]', 1738897982, 1, '::1', '', NULL, '2023-06-12 16:47:17', '2025-02-07 11:13:03'),
|
||||||
(47, 'user1', '', '', '极客学长@202752', '4d3e57a01ae826531012e4ea6e17cbc45fea183467abe9813c379fb84916fb0a', '/images/avatar/user.png', 'ixl0nqa6', 300, 0, 1, '', '[\"gpt\"]', '', 0, 0, '', '', '', '2024-12-24 11:37:16', '2024-12-24 11:37:16'),
|
(47, 'user1', '', '', '极客学长@202752', '4d3e57a01ae826531012e4ea6e17cbc45fea183467abe9813c379fb84916fb0a', '/images/avatar/user.png', 'ixl0nqa6', 300, 0, 1, '', '[\"gpt\"]', '', 0, 0, '', '', '', '2024-12-24 11:37:16', '2024-12-24 11:37:16'),
|
||||||
(48, 'wx@3659838859', '', '', '极客学长', 'cf6bbe381b23812d2b9fd423abe74003cecdd3b93809896eb573536ba6c500b3', 'https://thirdwx.qlogo.cn/mmopen/vi_32/uyxRMqZcEkb7fHouKXbNzxrnrvAttBKkwNlZ7yFibibRGiahdmsrZ3A1NKf8Fw5qJNJn4TXRmygersgEbibaSGd9Sg/132', '5rsy4iwg', 100, 0, 1, '', '[\"gpt\"]', '', 1736228927, 0, '172.22.11.200', 'oCs0t62472W19z2LOEKI1rWyCTTA', '', '2025-01-07 13:43:06', '2025-01-07 13:48:48'),
|
(48, 'wx@3659838859', '', '', '极客学长', 'cf6bbe381b23812d2b9fd423abe74003cecdd3b93809896eb573536ba6c500b3', 'https://thirdwx.qlogo.cn/mmopen/vi_32/uyxRMqZcEkb7fHouKXbNzxrnrvAttBKkwNlZ7yFibibRGiahdmsrZ3A1NKf8Fw5qJNJn4TXRmygersgEbibaSGd9Sg/132', '5rsy4iwg', 100, 0, 1, '', '[\"gpt\"]', '', 1736228927, 0, '172.22.11.200', 'oCs0t62472W19z2LOEKI1rWyCTTA', '', '2025-01-07 13:43:06', '2025-01-07 13:48:48'),
|
||||||
(49, 'wx@9502480897', '', '', 'AI探索君', 'd99fa8ba7da1455693b40e11d894a067416e758af2a75d7a3df4721b76cdbc8c', 'https://thirdwx.qlogo.cn/mmopen/vi_32/Zpcln1FZjcKxqtIyCsOTLGn16s7uIvwWfdkdsW6gbZg4r9sibMbic4jvrHmV7ux9nseTB5kBSnu1HSXr7zB8rTXg/132', 'fjclgsli', 100, 0, 1, '', '[\"gpt\"]', '', 0, 0, '', 'oCs0t64FaOLfiTbHZpOqk3aUp_94', '', '2025-01-07 14:05:31', '2025-01-07 14:05:31');
|
(49, 'wx@9502480897', '', '', 'AI探索君', 'd99fa8ba7da1455693b40e11d894a067416e758af2a75d7a3df4721b76cdbc8c', 'https://thirdwx.qlogo.cn/mmopen/vi_32/Zpcln1FZjcKxqtIyCsOTLGn16s7uIvwWfdkdsW6gbZg4r9sibMbic4jvrHmV7ux9nseTB5kBSnu1HSXr7zB8rTXg/132', 'fjclgsli', 100, 0, 1, '', '[\"gpt\"]', '', 0, 0, '', 'oCs0t64FaOLfiTbHZpOqk3aUp_94', '', '2025-01-07 14:05:31', '2025-01-07 14:05:31');
|
||||||
@@ -857,7 +856,7 @@ ALTER TABLE `chatgpt_chat_items`
|
|||||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_models`
|
-- 使用表AUTO_INCREMENT `chatgpt_chat_models`
|
||||||
--
|
--
|
||||||
ALTER TABLE `chatgpt_chat_models`
|
ALTER TABLE `chatgpt_chat_models`
|
||||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=60;
|
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=62;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_roles`
|
-- 使用表AUTO_INCREMENT `chatgpt_chat_roles`
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
version: '3'
|
version: "3"
|
||||||
services:
|
services:
|
||||||
# mysql
|
# mysql
|
||||||
geekai-mysql:
|
geekai-mysql:
|
||||||
@@ -9,14 +9,14 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- MYSQL_ROOT_PASSWORD=mhSCk0NheGhmtsha
|
- MYSQL_ROOT_PASSWORD=mhSCk0NheGhmtsha
|
||||||
ports:
|
ports:
|
||||||
- '3307:3306'
|
- "3307:3306"
|
||||||
volumes:
|
volumes:
|
||||||
- ./conf/mysql/my.cnf:/etc/mysql/my.cnf
|
- ./conf/mysql/my.cnf:/etc/mysql/my.cnf
|
||||||
- ./data/mysql/data:/var/lib/mysql
|
- ./data/mysql/data:/var/lib/mysql
|
||||||
- ./logs/mysql:/var/log/mysql
|
- ./logs/mysql:/var/log/mysql
|
||||||
- ./data/mysql/init.d:/docker-entrypoint-initdb.d/
|
- ./data/mysql/init.d:/docker-entrypoint-initdb.d/
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ['CMD', 'mysqladmin', 'ping', '-h', 'localhost']
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 10
|
retries: 10
|
||||||
@@ -30,9 +30,9 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./data/redis:/data
|
- ./data/redis:/data
|
||||||
ports:
|
ports:
|
||||||
- '6380:6379'
|
- "6380:6379"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ['CMD', 'redis-cli', 'ping']
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
interval: 3s
|
interval: 3s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 5
|
retries: 5
|
||||||
@@ -51,10 +51,10 @@ services:
|
|||||||
|
|
||||||
tika:
|
tika:
|
||||||
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/tika:latest
|
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/tika:latest
|
||||||
container_name: tika
|
container_name: geekai-tika
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- '9998:9998'
|
- "9999:9998"
|
||||||
|
|
||||||
# midjourney-proxy:
|
# midjourney-proxy:
|
||||||
# image: registry.cn-shenzhen.aliyuncs.com/geekmaster/midjourney-proxy:2.6.2
|
# image: registry.cn-shenzhen.aliyuncs.com/geekmaster/midjourney-proxy:2.6.2
|
||||||
@@ -67,7 +67,7 @@ services:
|
|||||||
|
|
||||||
# 后端 API 程序
|
# 后端 API 程序
|
||||||
geekai-api:
|
geekai-api:
|
||||||
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-api:v4.1.8-amd64
|
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-api:v4.2.0-amd64
|
||||||
container_name: geekai-api
|
container_name: geekai-api
|
||||||
restart: always
|
restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -80,8 +80,7 @@ services:
|
|||||||
- LOG_LEVEL=info
|
- LOG_LEVEL=info
|
||||||
- CONFIG_FILE=config.toml
|
- CONFIG_FILE=config.toml
|
||||||
ports:
|
ports:
|
||||||
- '5678:5678'
|
- "5678:5678"
|
||||||
- '9999:9999'
|
|
||||||
volumes:
|
volumes:
|
||||||
- /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime
|
- /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime
|
||||||
- ./conf/config.toml:/var/www/app/config.toml
|
- ./conf/config.toml:/var/www/app/config.toml
|
||||||
@@ -91,13 +90,13 @@ services:
|
|||||||
|
|
||||||
# 前端应用
|
# 前端应用
|
||||||
geekai-web:
|
geekai-web:
|
||||||
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-web:v4.1.8-amd64
|
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-web:v4.2.0-amd64
|
||||||
container_name: geekai-web
|
container_name: geekai-web
|
||||||
restart: always
|
restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- geekai-api
|
- geekai-api
|
||||||
ports:
|
ports:
|
||||||
- '8080:8080'
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- ./logs/nginx:/var/log/nginx
|
- ./logs/nginx:/var/log/nginx
|
||||||
- ./conf/nginx/conf.d:/etc/nginx/conf.d
|
- ./conf/nginx/conf.d:/etc/nginx/conf.d
|
||||||
@@ -6,7 +6,7 @@ VUE_APP_ADMIN_USER=admin
|
|||||||
VUE_APP_ADMIN_PASS=admin123
|
VUE_APP_ADMIN_PASS=admin123
|
||||||
VUE_APP_KEY_PREFIX=GeekAI_DEV_
|
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.2.0
|
||||||
VUE_APP_DOCS_URL=https://docs.geekai.me
|
VUE_APP_DOCS_URL=https://docs.geekai.me
|
||||||
VUE_APP_GITHUB_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_GITEE_URL=https://gitee.com/blackfox/geekai
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
VUE_APP_API_HOST=
|
VUE_APP_API_HOST=
|
||||||
VUE_APP_WS_HOST=
|
VUE_APP_WS_HOST=
|
||||||
VUE_APP_KEY_PREFIX=GeekAI_
|
VUE_APP_KEY_PREFIX=GeekAI_
|
||||||
|
VUE_APP_VERSION=v4.2.0
|
||||||
VUE_APP_TITLE="Geek-AI 创作系统"
|
VUE_APP_TITLE="Geek-AI 创作系统"
|
||||||
VUE_APP_VERSION=v4.1.9
|
|
||||||
VUE_APP_DOCS_URL=https://docs.geekai.me
|
VUE_APP_DOCS_URL=https://docs.geekai.me
|
||||||
VUE_APP_GITHUB_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_GITEE_URL=https://gitee.com/blackfox/geekai
|
||||||
|
|||||||
@@ -92,6 +92,29 @@ const connect = () => {
|
|||||||
});
|
});
|
||||||
store.setSocket(_socket);
|
store.setSocket(_socket);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 打印 banner
|
||||||
|
const banner = `
|
||||||
|
|
||||||
|
.oooooo. oooo .o. ooooo
|
||||||
|
d8P' 'Y8b 888 .888. 888
|
||||||
|
888 .ooooo. .ooooo. 888 oooo .8"888. 888
|
||||||
|
888 d88' 88b d88' 88b 888 .8P' .8' 888. 888
|
||||||
|
888 ooooo 888ooo888 888ooo888 888888. .88ooo8888. 888
|
||||||
|
'88. .88' 888 .o 888 .o 888 88b. .8' 888. 888
|
||||||
|
Y8bood8P' Y8bod8P' Y8bod8P' o888o o888o o88o o8888o o888o
|
||||||
|
|
||||||
|
`;
|
||||||
|
console.log("%c" + banner + "", "color: purple;font-size: 18px;");
|
||||||
|
|
||||||
|
console.log("%c感谢大家为 GeekAI 做出的卓越贡献!", "color: green;font-size: 40px;font-family: '微软雅黑';");
|
||||||
|
console.log(
|
||||||
|
"%c项目源码:https://github.com/yangjian102621/geekai %c 您的 star 对我们非常重要!",
|
||||||
|
"color: green;font-size: 20px;font-family: '微软雅黑';",
|
||||||
|
"color: red;font-size: 20px;font-family: '微软雅黑';"
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("%c 愿你出走半生,归来仍是少年!大奉武夫许七安,前来凿阵!", "color: #7c39ed;font-size: 18px;font-family: '微软雅黑';");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
|
|||||||
@@ -132,11 +132,6 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
// img{
|
|
||||||
// width: 24px;
|
|
||||||
// height: 24px;
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
@@ -183,19 +178,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep(.theme-box) {
|
|
||||||
position: relative !important;
|
|
||||||
right: initial;
|
|
||||||
bottom: initial;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
line-height: 18px;
|
|
||||||
|
|
||||||
.iconfont {
|
|
||||||
font-size: 15px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.right-main {
|
.right-main {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
// background: #f5f7fd;
|
// background: #f5f7fd;
|
||||||
@@ -246,18 +228,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(79, 89, 102, 0.1);
|
background: rgba(183, 176, 255, 0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
li.active {
|
li.active {
|
||||||
background: rgba(79, 89, 102, 0.1);
|
background: rgba(183, 176, 255, 0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.setting-menus {
|
.setting-menus {
|
||||||
.title {
|
.title {
|
||||||
color: #222226;
|
color: var(--text-theme-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-icon,
|
.el-icon,
|
||||||
@@ -265,7 +247,7 @@
|
|||||||
font-size: 18px
|
font-size: 18px
|
||||||
margin-right: 6px
|
margin-right: 6px
|
||||||
}
|
}
|
||||||
color: #222226;
|
color: var(--text-theme-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.username {
|
.username {
|
||||||
|
|||||||
@@ -1,238 +1,239 @@
|
|||||||
.chat-line {
|
.chat-line,
|
||||||
ol, ul {
|
.notice-dialog {
|
||||||
margin: 0.8em 0;
|
ol,
|
||||||
list-style: normal;
|
ul {
|
||||||
}
|
margin: 0.8em 0;
|
||||||
a {
|
list-style: normal;
|
||||||
|
}
|
||||||
color :var(--a-link-color);
|
a {
|
||||||
text-decoration: underline;
|
color: var(--a-link-color);
|
||||||
|
text-decoration: underline;
|
||||||
padding: 0 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1,
|
padding: 0 2px;
|
||||||
h2,
|
}
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
position: relative;
|
|
||||||
margin-top: 1rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
font-weight: bold;
|
|
||||||
line-height: 1.4;
|
|
||||||
cursor: text;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1:hover a.anchor,
|
h1,
|
||||||
h2:hover a.anchor,
|
h2,
|
||||||
h3:hover a.anchor,
|
h3,
|
||||||
h4:hover a.anchor,
|
h4,
|
||||||
h5:hover a.anchor,
|
h5,
|
||||||
h6:hover a.anchor {
|
h6 {
|
||||||
text-decoration: none;
|
position: relative;
|
||||||
}
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 1.4;
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
|
||||||
h1 tt,
|
h1:hover a.anchor,
|
||||||
h1 code {
|
h2:hover a.anchor,
|
||||||
font-size: inherit !important;
|
h3:hover a.anchor,
|
||||||
}
|
h4:hover a.anchor,
|
||||||
|
h5:hover a.anchor,
|
||||||
|
h6:hover a.anchor {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
h2 tt,
|
h1 tt,
|
||||||
h2 code {
|
h1 code {
|
||||||
font-size: inherit !important;
|
font-size: inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 tt,
|
h2 tt,
|
||||||
h3 code {
|
h2 code {
|
||||||
font-size: inherit !important;
|
font-size: inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
h4 tt,
|
h3 tt,
|
||||||
h4 code {
|
h3 code {
|
||||||
font-size: inherit !important;
|
font-size: inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
h5 tt,
|
h4 tt,
|
||||||
h5 code {
|
h4 code {
|
||||||
font-size: inherit !important;
|
font-size: inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
h6 tt,
|
h5 tt,
|
||||||
h6 code {
|
h5 code {
|
||||||
font-size: inherit !important;
|
font-size: inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 a,
|
h6 tt,
|
||||||
h3 a {
|
h6 code {
|
||||||
color: #34495e;
|
font-size: inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h2 a,
|
||||||
padding-bottom: .4rem;
|
h3 a {
|
||||||
font-size: 2.2rem;
|
color: #34495e;
|
||||||
line-height: 1.3;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
h1 {
|
||||||
font-size: 1.75rem;
|
padding-bottom: 0.4rem;
|
||||||
line-height: 1.225;
|
font-size: 2.2rem;
|
||||||
margin: 35px 0 15px;
|
line-height: 1.3;
|
||||||
padding-bottom: 0.5em;
|
}
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
h2 {
|
||||||
font-size: 1.4rem;
|
font-size: 1.75rem;
|
||||||
line-height: 1.43;
|
line-height: 1.225;
|
||||||
margin: 20px 0 7px;
|
margin: 35px 0 15px;
|
||||||
}
|
padding-bottom: 0.5em;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
h4 {
|
h3 {
|
||||||
font-size: 1.2rem;
|
font-size: 1.4rem;
|
||||||
}
|
line-height: 1.43;
|
||||||
|
margin: 20px 0 7px;
|
||||||
|
}
|
||||||
|
|
||||||
h5 {
|
h4 {
|
||||||
font-size: 1rem;
|
font-size: 1.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
h6 {
|
h5 {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
color: #777;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
p,
|
h6 {
|
||||||
blockquote,
|
font-size: 1rem;
|
||||||
ul,
|
color: #777;
|
||||||
ol,
|
}
|
||||||
dl,
|
|
||||||
table {
|
|
||||||
margin: 0.8em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
li > ol,
|
p,
|
||||||
li > ul {
|
blockquote,
|
||||||
margin: 0 0;
|
ul,
|
||||||
}
|
ol,
|
||||||
|
dl,
|
||||||
|
table {
|
||||||
|
margin: 0.8em 0;
|
||||||
|
}
|
||||||
|
|
||||||
hr {
|
li > ol,
|
||||||
height: 2px;
|
li > ul {
|
||||||
padding: 0;
|
margin: 0 0;
|
||||||
margin: 16px 0;
|
}
|
||||||
background-color: #e7e7e7;
|
|
||||||
border: 0 none;
|
|
||||||
overflow: hidden;
|
|
||||||
box-sizing: content-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
body > h2:first-child {
|
hr {
|
||||||
margin-top: 0;
|
height: 2px;
|
||||||
padding-top: 0;
|
padding: 0;
|
||||||
}
|
margin: 16px 0;
|
||||||
|
background-color: #e7e7e7;
|
||||||
|
border: 0 none;
|
||||||
|
overflow: hidden;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
body > h1:first-child {
|
body > h2:first-child {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
body > h1:first-child + h2 {
|
body > h1:first-child {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
body > h3:first-child,
|
body > h1:first-child + h2 {
|
||||||
body > h4:first-child,
|
margin-top: 0;
|
||||||
body > h5:first-child,
|
padding-top: 0;
|
||||||
body > h6:first-child {
|
}
|
||||||
margin-top: 0;
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:first-child h1,
|
body > h3:first-child,
|
||||||
a:first-child h2,
|
body > h4:first-child,
|
||||||
a:first-child h3,
|
body > h5:first-child,
|
||||||
a:first-child h4,
|
body > h6:first-child {
|
||||||
a:first-child h5,
|
margin-top: 0;
|
||||||
a:first-child h6 {
|
padding-top: 0;
|
||||||
margin-top: 0;
|
}
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 p,
|
a:first-child h1,
|
||||||
h2 p,
|
a:first-child h2,
|
||||||
h3 p,
|
a:first-child h3,
|
||||||
h4 p,
|
a:first-child h4,
|
||||||
h5 p,
|
a:first-child h5,
|
||||||
h6 p {
|
a:first-child h6 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
li p.first {
|
h1 p,
|
||||||
display: inline-block;
|
h2 p,
|
||||||
}
|
h3 p,
|
||||||
|
h4 p,
|
||||||
|
h5 p,
|
||||||
|
h6 p {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
ul,
|
li p.first {
|
||||||
ol {
|
display: inline-block;
|
||||||
padding-left: 30px;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ul:first-child,
|
ul,
|
||||||
ol:first-child {
|
ol {
|
||||||
margin-top: 0;
|
padding-left: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul:last-child,
|
ul:first-child,
|
||||||
ol:last-child {
|
ol:first-child {
|
||||||
margin-bottom: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
blockquote {
|
ul:last-child,
|
||||||
border-left: 4px solid #42b983;
|
ol:last-child {
|
||||||
padding: 10px 15px;
|
margin-bottom: 0;
|
||||||
color: #777;
|
}
|
||||||
background-color: rgba(66, 185, 131, .1);
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
blockquote {
|
||||||
padding: 0;
|
border-left: 4px solid #42b983;
|
||||||
word-break: initial;
|
padding: 10px 15px;
|
||||||
}
|
color: #777;
|
||||||
|
background-color: rgba(66, 185, 131, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
table tr {
|
table {
|
||||||
border-top: 1px solid #dfe2e5;
|
padding: 0;
|
||||||
margin: 0;
|
word-break: initial;
|
||||||
padding: 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
table tr:nth-child(2n),
|
table tr {
|
||||||
thead {
|
border-top: 1px solid #dfe2e5;
|
||||||
background-color: #fafafa;
|
margin: 0;
|
||||||
}
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
table tr th {
|
table tr:nth-child(2n),
|
||||||
font-weight: bold;
|
thead {
|
||||||
border: 1px solid #dfe2e5;
|
background-color: #fafafa;
|
||||||
border-bottom: 0;
|
}
|
||||||
text-align: left;
|
|
||||||
margin: 0;
|
|
||||||
padding: 6px 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table tr td {
|
table tr th {
|
||||||
border: 1px solid #dfe2e5;
|
font-weight: bold;
|
||||||
text-align: left;
|
border: 1px solid #dfe2e5;
|
||||||
margin: 0;
|
border-bottom: 0;
|
||||||
padding: 6px 13px;
|
text-align: left;
|
||||||
}
|
margin: 0;
|
||||||
|
padding: 6px 13px;
|
||||||
|
}
|
||||||
|
|
||||||
table tr th:first-child,
|
table tr td {
|
||||||
table tr td:first-child {
|
border: 1px solid #dfe2e5;
|
||||||
margin-top: 0;
|
text-align: left;
|
||||||
}
|
margin: 0;
|
||||||
|
padding: 6px 13px;
|
||||||
|
}
|
||||||
|
|
||||||
table tr th:last-child,
|
table tr th:first-child,
|
||||||
table tr td:last-child {
|
table tr td:first-child {
|
||||||
margin-bottom: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table tr th:last-child,
|
||||||
|
table tr td:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -243,6 +243,9 @@
|
|||||||
opacity 0
|
opacity 0
|
||||||
transform: translate(-50%, 0px);
|
transform: translate(-50%, 0px);
|
||||||
transition opacity 0.3s ease 0s
|
transition opacity 0.3s ease 0s
|
||||||
|
display flex
|
||||||
|
justify-content center
|
||||||
|
align-items center
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
//filter: invert(100%);
|
//filter: invert(100%);
|
||||||
}
|
}
|
||||||
.more-menus span.title{
|
.more-menus span.title{
|
||||||
color:#000;
|
color: var(--text-theme-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 操作按钮
|
// 操作按钮
|
||||||
@@ -89,4 +89,7 @@
|
|||||||
// 引用快样式
|
// 引用快样式
|
||||||
--quote-bg-color: #1F243F;
|
--quote-bg-color: #1F243F;
|
||||||
--quote-text-color: #fff;
|
--quote-text-color: #fff;
|
||||||
|
|
||||||
|
// el-dialog 阴影
|
||||||
|
--el-box-shadow: 0 0 15px rgba(107, 80, 225, 0.8);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,27 +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
|
<el-link :href="file.url" target="_blank" style="--el-font-weight-primary: bold">{{
|
||||||
:href="file.url"
|
file.name
|
||||||
target="_blank"
|
}}
|
||||||
style="--el-font-weight-primary: bold"
|
</el-link>
|
||||||
>{{ file.name }}</el-link
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<span>{{ GetFileType(file.ext) }}</span>
|
<span>{{ GetFileType(file.ext) }}</span>
|
||||||
@@ -35,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>
|
||||||
@@ -46,27 +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
|
<el-link :href="file.url" target="_blank" style="--el-font-weight-primary: bold">{{
|
||||||
:href="file.url"
|
file.name
|
||||||
target="_blank"
|
}}
|
||||||
style="--el-font-weight-primary: bold"
|
</el-link>
|
||||||
>{{ file.name }}</el-link
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<span>{{ GetFileType(file.ext) }}</span>
|
<span>{{ GetFileType(file.ext) }}</span>
|
||||||
@@ -81,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>
|
||||||
@@ -91,15 +87,15 @@
|
|||||||
</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";
|
||||||
|
|
||||||
const md = new MarkdownIt({
|
const md = new MarkdownIt({
|
||||||
breaks: true,
|
breaks: true,
|
||||||
@@ -107,91 +103,83 @@ const md = new MarkdownIt({
|
|||||||
linkify: true,
|
linkify: true,
|
||||||
typographer: true,
|
typographer: true,
|
||||||
highlight: function (str, lang) {
|
highlight: function (str, lang) {
|
||||||
const codeIndex = parseInt(Date.now()) + Math.floor(Math.random() * 10000000)
|
const codeIndex = parseInt(Date.now()) + Math.floor(Math.random() * 10000000);
|
||||||
// 显示复制代码按钮
|
// 显示复制代码按钮
|
||||||
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>`;
|
||||||
// 处理代码高亮
|
// 处理代码高亮
|
||||||
const preCode = hl.highlight(lang, str, true).value
|
const preCode = hl.highlight(lang, str, true).value;
|
||||||
// 将代码包裹在 pre 中
|
// 将代码包裹在 pre 中
|
||||||
return `<pre class="code-container"><code class="language-${lang} hljs">${preCode}</code>${copyBtn} ${langHtml}</pre>`
|
return `<pre class="code-container"><code class="language-${lang} hljs">${preCode}</code>${copyBtn} ${langHtml}</pre>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理代码高亮
|
// 处理代码高亮
|
||||||
const preCode = md.utils.escapeHtml(str)
|
const preCode = md.utils.escapeHtml(str);
|
||||||
// 将代码包裹在 pre 中
|
// 将代码包裹在 pre 中
|
||||||
return `<pre class="code-container"><code class="language-${lang} hljs">${preCode}</code>${copyBtn}</pre>`
|
return `<pre class="code-container"><code class="language-${lang} hljs">${preCode}</code>${copyBtn}</pre>`;
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
md.use(mathjaxPlugin)
|
md.use(mathjaxPlugin);
|
||||||
md.use(emoji)
|
md.use(emoji);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: {
|
default: {
|
||||||
content: '',
|
content: "",
|
||||||
created_at: '',
|
created_at: "",
|
||||||
tokens: 0,
|
tokens: 0,
|
||||||
model: '',
|
model: "",
|
||||||
icon: '',
|
icon: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
listStyle: {
|
listStyle: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'list',
|
default: "list",
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
const finalTokens = ref(props.data.tokens)
|
const finalTokens = ref(props.data.tokens);
|
||||||
const content = ref(processPrompt(props.data.content))
|
const content = ref(processPrompt(props.data.content));
|
||||||
const files = ref([])
|
const files = ref([]);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
processFiles()
|
processFiles();
|
||||||
})
|
});
|
||||||
|
|
||||||
const processFiles = () => {
|
const processFiles = () => {
|
||||||
if (!props.data.content) {
|
if (!props.data.content) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const linkRegex = /(https?:\/\/\S+)/g
|
const linkRegex = /(https?:\/\/\S+)/g;
|
||||||
const links = props.data.content.match(linkRegex)
|
const links = props.data.content.match(linkRegex);
|
||||||
const urlPrefix = `${window.location.protocol}//${window.location.host}`
|
|
||||||
if (links) {
|
if (links) {
|
||||||
const _links = links.map((link) => {
|
httpPost("/api/upload/list", {urls: links})
|
||||||
if (link.startsWith(urlPrefix)) {
|
.then((res) => {
|
||||||
return link.replace(urlPrefix, '')
|
files.value = res.data.items;
|
||||||
}
|
|
||||||
return link
|
|
||||||
})
|
|
||||||
// 合并数组并去重
|
|
||||||
const urls = [...new Set([...links, ..._links])]
|
|
||||||
httpPost('/api/upload/list', { urls: urls })
|
|
||||||
.then((res) => {
|
|
||||||
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, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
content.value = md.render(content.value.trim())
|
content.value = md.render(content.value.trim());
|
||||||
}
|
};
|
||||||
const isExternalImg = (link, files) => {
|
const isExternalImg = (link, files) => {
|
||||||
return isImage(link) && !files.find((file) => file.url === link)
|
return isImage(link) && !files.find((file) => file.url === link);
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
|
|||||||
@@ -1,26 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="theme-box" @click="toggleTheme">
|
<div class="theme-box" @click="toggleTheme" :class="size">
|
||||||
<i class="iconfont" :class="themePage === 'light' ? 'icon-yueliang' : 'icon-taiyang'"></i>
|
<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";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
size: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// 定义主题状态,初始值从 localStorage 获取
|
// 定义主题状态,初始值从 localStorage 获取
|
||||||
const store = useSharedStore()
|
const store = useSharedStore();
|
||||||
const themePage = ref(store.theme || 'light')
|
const themePage = ref(store.theme || "light");
|
||||||
|
|
||||||
// 切换主题函数
|
// 切换主题函数
|
||||||
const toggleTheme = () => {
|
const toggleTheme = () => {
|
||||||
themePage.value = themePage.value === 'light' ? 'dark' : 'light'
|
themePage.value = themePage.value === "light" ? "dark" : "light";
|
||||||
store.setTheme(themePage.value) // 保存主题
|
store.setTheme(themePage.value); // 保存主题
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
@import '@/assets/iconfont/iconfont.css'
|
|
||||||
.theme-box{
|
.theme-box{
|
||||||
z-index :111
|
z-index :111
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -49,4 +55,17 @@ const toggleTheme = () => {
|
|||||||
transition: transform 0.3s ease;
|
transition: transform 0.3s ease;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme-box.small {
|
||||||
|
position: relative !important;
|
||||||
|
right: initial;
|
||||||
|
bottom: initial;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 18px;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 15px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog class="config-dialog" v-model="showDialog" :close-on-click-modal="true" :before-close="close" style="max-width: 400px" title="账户信息">
|
<el-dialog class="config-dialog" v-model="showDialog" :close-on-click-modal="true" :before-close="close" style="max-width: 400px" title="账户信息">
|
||||||
<div class="flex-center-col p-4 pt-0" id="user-info">
|
<div class="flex-center-col pl-4 pr-4" id="user-info">
|
||||||
<user-profile @hide="close" />
|
<user-profile @hide="close" />
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|||||||
@@ -25,6 +25,9 @@
|
|||||||
<el-form-item label="剩余算力">
|
<el-form-item label="剩余算力">
|
||||||
<el-text type="warning">{{ user["power"] }}</el-text>
|
<el-text type="warning">{{ user["power"] }}</el-text>
|
||||||
<el-tag type="info" size="small" class="ml-2 cursor-pointer" @click="gotoLog">算力日志</el-tag>
|
<el-tag type="info" size="small" class="ml-2 cursor-pointer" @click="gotoLog">算力日志</el-tag>
|
||||||
|
<el-tooltip :content="`每日签到可获得 ${systemConfig.daily_power} 算力`" placement="top" v-if="systemConfig.daily_power > 0">
|
||||||
|
<el-button type="primary" size="small" @click="signIn" class="ml-2">签到</el-button>
|
||||||
|
</el-tooltip>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="会员到期时间" v-if="user['expired_time'] > 0">
|
<el-form-item label="会员到期时间" v-if="user['expired_time'] > 0">
|
||||||
<el-tag type="danger">{{ dateFormat(user["expired_time"]) }}</el-tag>
|
<el-tag type="danger">{{ dateFormat(user["expired_time"]) }}</el-tag>
|
||||||
@@ -44,8 +47,9 @@ import { ElMessage } from "element-plus";
|
|||||||
import { Plus } from "@element-plus/icons-vue";
|
import { Plus } from "@element-plus/icons-vue";
|
||||||
import Compressor from "compressorjs";
|
import Compressor from "compressorjs";
|
||||||
import { dateFormat } from "@/utils/libs";
|
import { dateFormat } from "@/utils/libs";
|
||||||
import { checkSession } from "@/store/cache";
|
import { checkSession, getSystemInfo } from "@/store/cache";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
|
import { showMessageError, showMessageOK } from "@/utils/dialog";
|
||||||
const user = ref({
|
const user = ref({
|
||||||
vip: false,
|
vip: false,
|
||||||
username: "演示数据",
|
username: "演示数据",
|
||||||
@@ -56,6 +60,7 @@ const user = ref({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const vipImg = ref("/images/menu/member.png");
|
const vipImg = ref("/images/menu/member.png");
|
||||||
|
const systemConfig = ref({});
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const emits = defineEmits(["hide"]);
|
const emits = defineEmits(["hide"]);
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -73,6 +78,10 @@ onMounted(() => {
|
|||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
getSystemInfo().then((res) => {
|
||||||
|
systemConfig.value = res.data;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const afterRead = (file) => {
|
const afterRead = (file) => {
|
||||||
@@ -112,6 +121,17 @@ const gotoLog = () => {
|
|||||||
router.push("/powerLog");
|
router.push("/powerLog");
|
||||||
emits("hide", false);
|
emits("hide", false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const signIn = () => {
|
||||||
|
httpGet("/api/user/signin")
|
||||||
|
.then(() => {
|
||||||
|
showMessageOK("签到成功");
|
||||||
|
user.value.power += systemConfig.value.daily_power;
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
showMessageError(e.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
|
|||||||
@@ -8,236 +8,248 @@
|
|||||||
/**
|
/**
|
||||||
* Util lib functions
|
* Util lib functions
|
||||||
*/
|
*/
|
||||||
import {showConfirmDialog} from "vant";
|
import { showConfirmDialog } from "vant";
|
||||||
|
|
||||||
// generate a random string
|
// generate a random string
|
||||||
export function randString(length) {
|
export function randString(length) {
|
||||||
const str = "0123456789abcdefghijklmnopqrstuvwxyz"
|
const str = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||||
const size = str.length
|
const size = str.length;
|
||||||
let buf = []
|
let buf = [];
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
const rand = Math.random() * size
|
const rand = Math.random() * size;
|
||||||
buf.push(str.charAt(rand))
|
buf.push(str.charAt(rand));
|
||||||
}
|
}
|
||||||
return buf.join("")
|
return buf.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function UUID() {
|
export function UUID() {
|
||||||
let d = new Date().getTime();
|
let d = new Date().getTime();
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
||||||
const r = (d + Math.random() * 16) % 16 | 0;
|
const r = (d + Math.random() * 16) % 16 | 0;
|
||||||
d = Math.floor(d / 16);
|
d = Math.floor(d / 16);
|
||||||
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
|
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否是移动设备
|
// 判断是否是移动设备
|
||||||
export function isMobile() {
|
export function isMobile() {
|
||||||
const userAgent = navigator.userAgent;
|
const userAgent = navigator.userAgent;
|
||||||
const mobileRegex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile|mobile|CriOS/i;
|
const mobileRegex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile|mobile|CriOS/i;
|
||||||
return mobileRegex.test(userAgent);
|
return mobileRegex.test(userAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 格式化日期
|
// 格式化日期
|
||||||
export function dateFormat(timestamp, format) {
|
export function dateFormat(timestamp, format) {
|
||||||
if (!timestamp) {
|
if (!timestamp) {
|
||||||
return '';
|
return "";
|
||||||
} else if (timestamp < 9680917502) {
|
} else if (timestamp < 9680917502) {
|
||||||
timestamp = timestamp * 1000;
|
timestamp = timestamp * 1000;
|
||||||
}
|
}
|
||||||
let year, month, day, HH, mm, ss;
|
let year, month, day, HH, mm, ss;
|
||||||
let time = new Date(timestamp);
|
let time = new Date(timestamp);
|
||||||
let timeDate;
|
let timeDate;
|
||||||
year = time.getFullYear(); // 年
|
year = time.getFullYear(); // 年
|
||||||
month = time.getMonth() + 1; // 月
|
month = time.getMonth() + 1; // 月
|
||||||
day = time.getDate(); // 日
|
day = time.getDate(); // 日
|
||||||
HH = time.getHours(); // 时
|
HH = time.getHours(); // 时
|
||||||
mm = time.getMinutes(); // 分
|
mm = time.getMinutes(); // 分
|
||||||
ss = time.getSeconds(); // 秒
|
ss = time.getSeconds(); // 秒
|
||||||
|
|
||||||
month = month < 10 ? '0' + month : month;
|
month = month < 10 ? "0" + month : month;
|
||||||
day = day < 10 ? '0' + day : day;
|
day = day < 10 ? "0" + day : day;
|
||||||
HH = HH < 10 ? '0' + HH : HH; // 时
|
HH = HH < 10 ? "0" + HH : HH; // 时
|
||||||
mm = mm < 10 ? '0' + mm : mm; // 分
|
mm = mm < 10 ? "0" + mm : mm; // 分
|
||||||
ss = ss < 10 ? '0' + ss : ss; // 秒
|
ss = ss < 10 ? "0" + ss : ss; // 秒
|
||||||
|
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case 'yyyy':
|
case "yyyy":
|
||||||
timeDate = String(year);
|
timeDate = String(year);
|
||||||
break;
|
break;
|
||||||
case 'yyyy-MM':
|
case "yyyy-MM":
|
||||||
timeDate = year + '-' + month;
|
timeDate = year + "-" + month;
|
||||||
break;
|
break;
|
||||||
case 'yyyy-MM-dd':
|
case "yyyy-MM-dd":
|
||||||
timeDate = year + '-' + month + '-' + day;
|
timeDate = year + "-" + month + "-" + day;
|
||||||
break;
|
break;
|
||||||
case 'yyyy/MM/dd':
|
case "yyyy/MM/dd":
|
||||||
timeDate = year + '/' + month + '/' + day;
|
timeDate = year + "/" + month + "/" + day;
|
||||||
break;
|
break;
|
||||||
case 'yyyy-MM-dd HH:mm:ss':
|
case "yyyy-MM-dd HH:mm:ss":
|
||||||
timeDate = year + '-' + month + '-' + day + ' ' + HH + ':' + mm + ':' + ss;
|
timeDate = year + "-" + month + "-" + day + " " + HH + ":" + mm + ":" + ss;
|
||||||
break;
|
break;
|
||||||
case 'HH:mm:ss':
|
case "HH:mm:ss":
|
||||||
timeDate = HH + ':' + mm + ':' + ss;
|
timeDate = HH + ":" + mm + ":" + ss;
|
||||||
break;
|
break;
|
||||||
case 'MM':
|
case "MM":
|
||||||
timeDate = String(month);
|
timeDate = String(month);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
timeDate = year + '-' + month + '-' + day + ' ' + HH + ':' + mm + ':' + ss;
|
timeDate = year + "-" + month + "-" + day + " " + HH + ":" + mm + ":" + ss;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return timeDate;
|
return timeDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatTime(time) {
|
export function formatTime(time) {
|
||||||
const minutes = Math.floor(time / 60);
|
const minutes = Math.floor(time / 60);
|
||||||
const seconds = Math.floor(time % 60);
|
const seconds = Math.floor(time % 60);
|
||||||
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
|
return `${minutes}:${seconds < 10 ? "0" : ""}${seconds}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断数组中是否包含某个元素
|
// 判断数组中是否包含某个元素
|
||||||
export function arrayContains(array, value, compare) {
|
export function arrayContains(array, value, compare) {
|
||||||
if (!array) {
|
if (!array) {
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof compare !== 'function') {
|
|
||||||
compare = function (v1, v2) {
|
|
||||||
return v1 === v2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let i = 0; i < array.length; i++) {
|
|
||||||
if (compare(array[i], value)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof compare !== "function") {
|
||||||
|
compare = function (v1, v2) {
|
||||||
|
return v1 === v2;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
for (let i = 0; i < array.length; i++) {
|
||||||
|
if (compare(array[i], value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除数组中指定的元素
|
// 删除数组中指定的元素
|
||||||
export function removeArrayItem(array, value, compare) {
|
export function removeArrayItem(array, value, compare) {
|
||||||
if (typeof compare !== 'function') {
|
if (typeof compare !== "function") {
|
||||||
compare = function (v1, v2) {
|
compare = function (v1, v2) {
|
||||||
return v1 === v2;
|
return v1 === v2;
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
for (let i = 0; i < array.length; i++) {
|
||||||
|
if (compare(array[i], value)) {
|
||||||
|
array.splice(i, 1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < array.length; i++) {
|
}
|
||||||
if (compare(array[i], value)) {
|
return array;
|
||||||
array.splice(i, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return array;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 渲染输入的换行符
|
// 渲染输入的换行符
|
||||||
export function renderInputText(text) {
|
export function renderInputText(text) {
|
||||||
const replaceRegex = /(\n\r|\r\n|\r|\n)/g;
|
const replaceRegex = /(\n\r|\r\n|\r|\n)/g;
|
||||||
text = text || '';
|
text = text || "";
|
||||||
return text.replace(replaceRegex, "<br/>");
|
return text.replace(replaceRegex, "<br/>");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 拷贝对象
|
// 拷贝对象
|
||||||
export function copyObj(origin) {
|
export function copyObj(origin) {
|
||||||
return JSON.parse(JSON.stringify(origin));
|
return JSON.parse(JSON.stringify(origin));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function disabledDate(time) {
|
export function disabledDate(time) {
|
||||||
return time.getTime() < Date.now()
|
return time.getTime() < Date.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 字符串截取
|
// 字符串截取
|
||||||
export function substr(str, length) {
|
export function substr(str, length) {
|
||||||
let result = ''
|
let result = "";
|
||||||
let count = 0
|
let count = 0;
|
||||||
|
|
||||||
for (let i = 0; i < str.length; i++) {
|
for (let i = 0; i < str.length; i++) {
|
||||||
const char = str.charAt(i)
|
const char = str.charAt(i);
|
||||||
const charCode = str.charCodeAt(i);
|
const charCode = str.charCodeAt(i);
|
||||||
|
|
||||||
// 判断字符是否为中文字符
|
// 判断字符是否为中文字符
|
||||||
if (charCode >= 0x4e00 && charCode <= 0x9fff) {
|
if (charCode >= 0x4e00 && charCode <= 0x9fff) {
|
||||||
// 中文字符算两个字符
|
// 中文字符算两个字符
|
||||||
count += 2
|
count += 2;
|
||||||
} else {
|
} else {
|
||||||
count++
|
count++;
|
||||||
}
|
|
||||||
|
|
||||||
if (count <= length) {
|
|
||||||
result += char
|
|
||||||
} else {
|
|
||||||
result += " ..."
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
if (count <= length) {
|
||||||
|
result += char;
|
||||||
|
} else {
|
||||||
|
result += " ...";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isImage(url) {
|
export function isImage(url) {
|
||||||
const expr = /\.(jpg|jpeg|png|gif|bmp|svg)$/i;
|
const expr = /\.(jpg|jpeg|png|gif|bmp|svg)$/i;
|
||||||
return expr.test(url);
|
return expr.test(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function processContent(content) {
|
export function processContent(content) {
|
||||||
if (!content) {
|
if (!content) {
|
||||||
return ""
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果是图片链接地址,则直接替换成图片标签
|
// 如果是图片链接地址,则直接替换成图片标签
|
||||||
const linkRegex = /(https?:\/\/\S+)/g;
|
const linkRegex = /(https?:\/\/\S+)/g;
|
||||||
const links = content.match(linkRegex);
|
const links = content.match(linkRegex);
|
||||||
if (links) {
|
if (links) {
|
||||||
for (let link of links) {
|
for (let link of links) {
|
||||||
if (isImage(link)) {
|
if (isImage(link)) {
|
||||||
const index = content.indexOf(link)
|
const index = content.indexOf(link);
|
||||||
if (content.substring(index - 1, 2) !== "]") {
|
if (content.substring(index - 1, 2) !== "]") {
|
||||||
content = content.replace(link, "\n\n")
|
content = content.replace(link, "\n\n");
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return content
|
}
|
||||||
|
// 处理推理标签
|
||||||
|
if (content.includes("<think>")) {
|
||||||
|
content = content.replace(/<think>(.*?)<\/think>/gs, (match, content) => {
|
||||||
|
if (content.length > 10) {
|
||||||
|
return `<blockquote>${content}</blockquote>`;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
content = content.replace(/<think>(.*?)$/gs, (match, content) => {
|
||||||
|
if (content.length > 10) {
|
||||||
|
return `<blockquote>${content}</blockquote>`;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function processPrompt(prompt) {
|
export function processPrompt(prompt) {
|
||||||
return prompt.replace(/&/g, "&")
|
return prompt.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||||
.replace(/</g, "<")
|
|
||||||
.replace(/>/g, ">");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否为微信浏览器
|
// 判断是否为微信浏览器
|
||||||
export function isWeChatBrowser() {
|
export function isWeChatBrowser() {
|
||||||
return /MicroMessenger/i.test( navigator.userAgent);
|
return /MicroMessenger/i.test(navigator.userAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showLoginDialog(router) {
|
export function showLoginDialog(router) {
|
||||||
showConfirmDialog({
|
showConfirmDialog({
|
||||||
title: '登录',
|
title: "登录",
|
||||||
message:
|
message: "此操作需要登录才能进行,前往登录?",
|
||||||
'此操作需要登录才能进行,前往登录?',
|
})
|
||||||
}).then(() => {
|
.then(() => {
|
||||||
router.push("/mobile/login")
|
router.push("/mobile/login");
|
||||||
}).catch(() => {
|
})
|
||||||
// on cancel
|
.catch(() => {
|
||||||
|
// on cancel
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const replaceImg =(img) => {
|
export const replaceImg = (img) => {
|
||||||
if (!img.startsWith("http")) {
|
if (!img.startsWith("http")) {
|
||||||
img = `${location.protocol}//${location.host}/${img}`
|
img = `${location.protocol}//${location.host}/${img}`;
|
||||||
}
|
}
|
||||||
const devHost = process.env.VUE_APP_API_HOST
|
const devHost = process.env.VUE_APP_API_HOST;
|
||||||
const localhost = "http://localhost:5678"
|
const localhost = "http://localhost:5678";
|
||||||
if (img.includes(localhost)) {
|
if (img.includes(localhost)) {
|
||||||
return img?.replace(localhost, devHost)
|
return img?.replace(localhost, devHost);
|
||||||
}
|
}
|
||||||
return img
|
return img;
|
||||||
}
|
};
|
||||||
export function isChrome() {
|
export function isChrome() {
|
||||||
const userAgent = navigator.userAgent.toLowerCase();
|
const userAgent = navigator.userAgent.toLowerCase();
|
||||||
return /chrome/.test(userAgent) && !/edg/.test(userAgent);
|
return /chrome/.test(userAgent) && !/edg/.test(userAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<el-container>
|
<el-container>
|
||||||
<el-aside v-show="store.chatListExtend">
|
<el-aside v-show="store.chatListExtend">
|
||||||
<div class="flex w-full justify-center pt-3 pb-3">
|
<div class="flex w-full justify-center pt-3 pb-3">
|
||||||
<img :src="logo" style="max-height: 40px" :alt="title" v-if="logo !== ''"/>
|
<img :src="logo" style="max-height: 40px" :alt="title" v-if="logo !== ''" />
|
||||||
<h2 v-else>{{ title }}</h2>
|
<h2 v-else>{{ title }}</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -194,7 +194,7 @@
|
|||||||
</el-container>
|
</el-container>
|
||||||
|
|
||||||
<el-dialog v-model="showNotice" :show-close="true" class="notice-dialog" title="网站公告">
|
<el-dialog v-model="showNotice" :show-close="true" class="notice-dialog" title="网站公告">
|
||||||
<div class="notice p-4">
|
<div class="notice">
|
||||||
<div v-html="notice"></div>
|
<div v-html="notice"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -232,24 +232,24 @@
|
|||||||
</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, 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 MarkdownIt from "markdown-it";
|
||||||
import emoji from "markdown-it-emoji";
|
import emoji from "markdown-it-emoji";
|
||||||
|
|
||||||
@@ -977,6 +977,7 @@ const realtimeChat = () => {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="stylus">
|
<style lang="stylus">
|
||||||
|
@import '@/assets/css/markdown/vue.css';
|
||||||
.notice-dialog {
|
.notice-dialog {
|
||||||
.el-dialog__header {
|
.el-dialog__header {
|
||||||
padding-bottom 0
|
padding-bottom 0
|
||||||
@@ -985,6 +986,10 @@ const realtimeChat = () => {
|
|||||||
.el-dialog__body {
|
.el-dialog__body {
|
||||||
padding 0 20px
|
padding 0 20px
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: 20px 0 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
ol, ul {
|
ol, ul {
|
||||||
padding-left 10px
|
padding-left 10px
|
||||||
}
|
}
|
||||||
@@ -995,7 +1000,7 @@ const realtimeChat = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
list-style disc
|
list-style inside
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -320,6 +320,7 @@ onMounted(() => {
|
|||||||
models.value = res.data;
|
models.value = res.data;
|
||||||
selectedModel.value = models.value[0];
|
selectedModel.value = models.value[0];
|
||||||
params.value.model_id = selectedModel.value.id;
|
params.value.model_id = selectedModel.value.id;
|
||||||
|
changeModel(selectedModel.value);
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
showMessageError("获取模型列表失败:" + e.message);
|
showMessageError("获取模型列表失败:" + e.message);
|
||||||
|
|||||||
@@ -39,25 +39,25 @@
|
|||||||
<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"/>
|
<i class="iconfont icon-more" />
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
<template #default>
|
<template #default>
|
||||||
<ul class="more-menus">
|
<ul class="more-menus">
|
||||||
<li
|
<li
|
||||||
v-for="(item, index) in moreNavs"
|
v-for="(item, index) in moreNavs"
|
||||||
:key="item.url"
|
:key="item.url"
|
||||||
:class="{
|
:class="{
|
||||||
active: item.url === curPath,
|
active: item.url === curPath,
|
||||||
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>
|
</li>
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
<el-popover placement="right-end" trigger="hover" v-if="loginUser.id">
|
<el-popover placement="right-end" trigger="hover" v-if="loginUser.id">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<li class="menu-list-item flex-center-col">
|
<li class="menu-list-item flex-center-col">
|
||||||
<i class="iconfont icon-config"/>
|
<i class="iconfont icon-config" />
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
<template #default>
|
<template #default>
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
<li>
|
<li>
|
||||||
<div @click="showConfigDialog = true" class="flex">
|
<div @click="showConfigDialog = true" class="flex">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<UserFilled/>
|
<UserFilled />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<span class="username title">{{ loginUser.nickname }}</span>
|
<span class="username title">{{ loginUser.nickname }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
<i class="iconfont icon-house"></i>
|
<i class="iconfont icon-house"></i>
|
||||||
</a>
|
</a>
|
||||||
<div class="pl-1">
|
<div class="pl-1">
|
||||||
<ThemeChange/>
|
<ThemeChange size="small" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -133,17 +133,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {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 {computed, onMounted, ref, watch} from "vue";
|
import { computed, 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";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -188,7 +188,7 @@ const getFirstPathSegment = (url) => {
|
|||||||
|
|
||||||
const stars = computed(() => {
|
const stars = computed(() => {
|
||||||
return 1000;
|
return 1000;
|
||||||
})
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => store.showLoginDialog,
|
() => store.showLoginDialog,
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ const types = ref([
|
|||||||
{ label: "Suno文生歌", value: "suno" },
|
{ label: "Suno文生歌", value: "suno" },
|
||||||
{ label: "Luma视频", value: "luma" },
|
{ label: "Luma视频", value: "luma" },
|
||||||
{ label: "Realtime API", value: "realtime" },
|
{ label: "Realtime API", value: "realtime" },
|
||||||
|
{ label: "其他", value: "other" },
|
||||||
]);
|
]);
|
||||||
const isEdit = ref(false);
|
const isEdit = ref(false);
|
||||||
const clipboard = ref(null);
|
const clipboard = ref(null);
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ const type = ref([
|
|||||||
|
|
||||||
// 获取 API KEY
|
// 获取 API KEY
|
||||||
const apiKeys = ref([]);
|
const apiKeys = ref([]);
|
||||||
httpGet("/api/admin/apikey/list?type=chat|dalle")
|
httpGet("/api/admin/apikey/list")
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
apiKeys.value = res.data;
|
apiKeys.value = res.data;
|
||||||
})
|
})
|
||||||
@@ -345,13 +345,6 @@ const remove = function (row) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cell {
|
|
||||||
.copy-model {
|
|
||||||
margin-left 6px
|
|
||||||
cursor pointer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-select {
|
.el-select {
|
||||||
width: 100%
|
width: 100%
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user