mirror of
https://gitee.com/blackfox/geekai.git
synced 2024-11-29 18:57:34 +08:00
merge v4.0.8
This commit is contained in:
commit
7ddf57ae06
10
CHANGELOG.md
10
CHANGELOG.md
@ -1,4 +1,14 @@
|
||||
# 更新日志
|
||||
## v4.0.8
|
||||
* 功能优化:升级 mathjax 公式解析插件,修复公式因为图片访问限制而无法显示的问题
|
||||
* 功能优化:当数据库更新失败的时候记录错误日志
|
||||
* 功能优化:聊天输入框会随着输入内容的增多自动调整高度
|
||||
* Bug修复:修复移动端聊天页面模型切换不生效的Bug
|
||||
* 功能优化:给PC端扫码支付增加签名验证和有效期验证
|
||||
* Bug修复:修复支付码生成API权限控制的问题
|
||||
* Bug修复:模型算力设置为0时,不扣减用户算力,并且不记录算力消费日志
|
||||
* 功能优化:新增随机背景配置项,可以在后台设置,首页使用 Bing 壁纸作为背景图片
|
||||
* 功能新增:H5端支持 Dalle 绘图
|
||||
|
||||
## v4.0.7
|
||||
|
||||
|
@ -9,12 +9,12 @@ package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"geekai/core/types"
|
||||
"geekai/store/model"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
@ -227,15 +227,19 @@ func needLogin(c *gin.Context) bool {
|
||||
c.Request.URL.Path == "/api/sd/client" ||
|
||||
c.Request.URL.Path == "/api/dall/imgWall" ||
|
||||
c.Request.URL.Path == "/api/dall/client" ||
|
||||
c.Request.URL.Path == "/api/config/get" ||
|
||||
c.Request.URL.Path == "/api/product/list" ||
|
||||
c.Request.URL.Path == "/api/menu/list" ||
|
||||
c.Request.URL.Path == "/api/markMap/client" ||
|
||||
c.Request.URL.Path == "/api/payment/alipay/notify" ||
|
||||
c.Request.URL.Path == "/api/payment/hupipay/notify" ||
|
||||
c.Request.URL.Path == "/api/payment/payjs/notify" ||
|
||||
c.Request.URL.Path == "/api/payment/doPay" ||
|
||||
c.Request.URL.Path == "/api/payment/payWays" ||
|
||||
strings.HasPrefix(c.Request.URL.Path, "/api/test") ||
|
||||
strings.HasPrefix(c.Request.URL.Path, "/api/config/") ||
|
||||
strings.HasPrefix(c.Request.URL.Path, "/api/function/") ||
|
||||
strings.HasPrefix(c.Request.URL.Path, "/api/sms/") ||
|
||||
strings.HasPrefix(c.Request.URL.Path, "/api/captcha/") ||
|
||||
strings.HasPrefix(c.Request.URL.Path, "/api/payment/") ||
|
||||
strings.HasPrefix(c.Request.URL.Path, "/static/") {
|
||||
return false
|
||||
}
|
||||
|
@ -61,15 +61,15 @@ type ChatSession struct {
|
||||
}
|
||||
|
||||
type ChatModel struct {
|
||||
Id uint `json:"id"`
|
||||
Platform Platform `json:"platform"`
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
Power int `json:"power"`
|
||||
MaxTokens int `json:"max_tokens"` // 最大响应长度
|
||||
MaxContext int `json:"max_context"` // 最大上下文长度
|
||||
Temperature float32 `json:"temperature"` // 模型温度
|
||||
KeyId int `json:"key_id"` // 绑定 API KEY
|
||||
Id uint `json:"id"`
|
||||
Platform string `json:"platform"`
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
Power int `json:"power"`
|
||||
MaxTokens int `json:"max_tokens"` // 最大响应长度
|
||||
MaxContext int `json:"max_context"` // 最大上下文长度
|
||||
Temperature float32 `json:"temperature"` // 模型温度
|
||||
KeyId int `json:"key_id"` // 绑定 API KEY
|
||||
}
|
||||
|
||||
type ApiError struct {
|
||||
|
@ -126,25 +126,60 @@ type RedisConfig struct {
|
||||
const LicenseKey = "Geek-AI-License"
|
||||
|
||||
type License struct {
|
||||
Key string `json:"key"` // 许可证书密钥
|
||||
MachineId string `json:"machine_id"` // 机器码
|
||||
UserNum int `json:"user_num"` // 用户数量
|
||||
ExpiredAt int64 `json:"expired_at"` // 过期时间
|
||||
IsActive bool `json:"is_active"` // 是否激活
|
||||
Key string `json:"key"` // 许可证书密钥
|
||||
MachineId string `json:"machine_id"` // 机器码
|
||||
ExpiredAt int64 `json:"expired_at"` // 过期时间
|
||||
IsActive bool `json:"is_active"` // 是否激活
|
||||
Configs LicenseConfig `json:"configs"`
|
||||
}
|
||||
|
||||
type LicenseConfig struct {
|
||||
UserNum int `json:"user_num"` // 用户数量
|
||||
DeCopy bool `json:"de_copy"` // 去版权
|
||||
}
|
||||
|
||||
func (c RedisConfig) Url() string {
|
||||
return fmt.Sprintf("%s:%d", c.Host, c.Port)
|
||||
}
|
||||
|
||||
type Platform string
|
||||
type Platform struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
ChatURL string `json:"chat_url"`
|
||||
ImgURL string `json:"img_url"`
|
||||
}
|
||||
|
||||
const OpenAI = Platform("OpenAI")
|
||||
const Azure = Platform("Azure")
|
||||
const ChatGLM = Platform("ChatGLM")
|
||||
const Baidu = Platform("Baidu")
|
||||
const XunFei = Platform("XunFei")
|
||||
const QWen = Platform("QWen")
|
||||
var OpenAI = Platform{
|
||||
Name: "OpenAI - GPT",
|
||||
Value: "OpenAI",
|
||||
ChatURL: "https://api.chat-plus.net/v1/chat/completions",
|
||||
ImgURL: "https://api.chat-plus.net/v1/images/generations",
|
||||
}
|
||||
var Azure = Platform{
|
||||
Name: "微软 - Azure",
|
||||
Value: "Azure",
|
||||
ChatURL: "https://chat-bot-api.openai.azure.com/openai/deployments/{model}/chat/completions?api-version=2023-05-15",
|
||||
}
|
||||
var ChatGLM = Platform{
|
||||
Name: "智谱 - ChatGLM",
|
||||
Value: "ChatGLM",
|
||||
ChatURL: "https://open.bigmodel.cn/api/paas/v3/model-api/{model}/sse-invoke",
|
||||
}
|
||||
var Baidu = Platform{
|
||||
Name: "百度 - 文心大模型",
|
||||
Value: "Baidu",
|
||||
ChatURL: "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/{model}",
|
||||
}
|
||||
var XunFei = Platform{
|
||||
Name: "讯飞 - 星火大模型",
|
||||
Value: "XunFei",
|
||||
ChatURL: "wss://spark-api.xf-yun.com/{version}/chat",
|
||||
}
|
||||
var QWen = Platform{
|
||||
Name: "阿里 - 通义千问",
|
||||
Value: "QWen",
|
||||
ChatURL: "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation",
|
||||
}
|
||||
|
||||
type SystemConfig struct {
|
||||
Title string `json:"title,omitempty"`
|
||||
@ -177,4 +212,6 @@ type SystemConfig struct {
|
||||
ContextDeep int `json:"context_deep,omitempty"`
|
||||
|
||||
SdNegPrompt string `json:"sd_neg_prompt"` // SD 默认反向提示词
|
||||
|
||||
RandBg bool `json:"rand_bg"` // 前端首页是否启用随机背景
|
||||
}
|
||||
|
@ -24,5 +24,4 @@ type Function struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Parameters map[string]interface{} `json:"parameters"`
|
||||
Required interface{} `json:"required,omitempty"`
|
||||
}
|
||||
|
@ -29,14 +29,19 @@ require github.com/xxl-job/xxl-job-executor-go v1.2.0
|
||||
|
||||
require (
|
||||
github.com/mojocn/base64Captcha v1.3.1
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||
github.com/shopspring/decimal v1.3.1
|
||||
github.com/syndtr/goleveldb v1.0.0
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.14 // indirect
|
||||
github.com/tklauser/numcpus v0.8.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
)
|
||||
|
||||
|
11
api/go.sum
11
api/go.sum
@ -43,6 +43,8 @@ github.com/go-basic/ipv4 v1.0.0 h1:gjyFAa1USC1hhXTkPOwBWDPfMcUaIM+tvo1XzV9EZxs=
|
||||
github.com/go-basic/ipv4 v1.0.0/go.mod h1:etLBnaxbidQfuqE6wgZQfs38nEWNmzALkxDZe4xY8Dg=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
@ -176,6 +178,8 @@ github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUA
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
@ -204,6 +208,10 @@ github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gt
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
|
||||
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
|
||||
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
|
||||
github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
|
||||
@ -215,6 +223,8 @@ github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ
|
||||
github.com/xxl-job/xxl-job-executor-go v1.2.0 h1:MTl2DpwrK2+hNjRRks2k7vB3oy+3onqm9OaSarneeLQ=
|
||||
github.com/xxl-job/xxl-job-executor-go v1.2.0/go.mod h1:bUFhz/5Irp9zkdYk5MxhQcDDT6LlZrI8+rv5mHtQ1mo=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
@ -261,6 +271,7 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -57,6 +57,7 @@ func (h *ApiKeyHandler) Save(c *gin.Context) {
|
||||
apiKey.Name = data.Name
|
||||
res := h.DB.Save(&apiKey)
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -75,6 +76,7 @@ func (h *ApiKeyHandler) Save(c *gin.Context) {
|
||||
func (h *ApiKeyHandler) List(c *gin.Context) {
|
||||
status := h.GetBool(c, "status")
|
||||
t := h.GetTrim(c, "type")
|
||||
platform := h.GetTrim(c, "platform")
|
||||
|
||||
session := h.DB.Session(&gorm.Session{})
|
||||
if status {
|
||||
@ -83,7 +85,10 @@ func (h *ApiKeyHandler) List(c *gin.Context) {
|
||||
if t != "" {
|
||||
session = session.Where("type", t)
|
||||
}
|
||||
|
||||
if platform != "" {
|
||||
session = session.Where("platform", platform)
|
||||
}
|
||||
|
||||
var items []model.ApiKey
|
||||
var keys = make([]vo.ApiKey, 0)
|
||||
res := session.Find(&items)
|
||||
@ -118,6 +123,7 @@ func (h *ApiKeyHandler) Set(c *gin.Context) {
|
||||
|
||||
res := h.DB.Model(&model.ApiKey{}).Where("id = ?", data.Id).Update(data.Filed, data.Value)
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -133,6 +139,7 @@ func (h *ApiKeyHandler) Remove(c *gin.Context) {
|
||||
|
||||
res := h.DB.Where("id", id).Delete(&model.ApiKey{})
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
|
@ -261,6 +261,7 @@ func (h *ChatHandler) RemoveMessage(c *gin.Context) {
|
||||
id := h.GetInt(c, "id", 0)
|
||||
tx := h.DB.Unscoped().Where("id = ?", id).Delete(&model.ChatMessage{})
|
||||
if tx.Error != nil {
|
||||
logger.Error("error with update database:", tx.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ func (h *ChatModelHandler) Save(c *gin.Context) {
|
||||
res = h.DB.Create(&item)
|
||||
}
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -88,9 +89,13 @@ func (h *ChatModelHandler) Save(c *gin.Context) {
|
||||
func (h *ChatModelHandler) List(c *gin.Context) {
|
||||
session := h.DB.Session(&gorm.Session{})
|
||||
enable := h.GetBool(c, "enable")
|
||||
platform := h.GetTrim(c, "platform")
|
||||
if enable {
|
||||
session = session.Where("enabled", enable)
|
||||
}
|
||||
if platform != "" {
|
||||
session = session.Where("platform", platform)
|
||||
}
|
||||
var items []model.ChatModel
|
||||
var cms = make([]vo.ChatModel, 0)
|
||||
res := session.Order("sort_num ASC").Find(&items)
|
||||
@ -140,6 +145,7 @@ func (h *ChatModelHandler) Set(c *gin.Context) {
|
||||
|
||||
res := h.DB.Model(&model.ChatModel{}).Where("id = ?", data.Id).Update(data.Filed, data.Value)
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -160,6 +166,7 @@ func (h *ChatModelHandler) Sort(c *gin.Context) {
|
||||
for index, id := range data.Ids {
|
||||
res := h.DB.Model(&model.ChatModel{}).Where("id = ?", id).Update("sort_num", data.Sorts[index])
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -177,6 +184,7 @@ func (h *ChatModelHandler) Remove(c *gin.Context) {
|
||||
|
||||
res := h.DB.Where("id = ?", id).Delete(&model.ChatModel{})
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ func (h *ChatRoleHandler) Save(c *gin.Context) {
|
||||
}
|
||||
res := h.DB.Save(&role)
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -115,6 +116,7 @@ func (h *ChatRoleHandler) Sort(c *gin.Context) {
|
||||
for index, id := range data.Ids {
|
||||
res := h.DB.Model(&model.ChatRole{}).Where("id = ?", id).Update("sort_num", data.Sorts[index])
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -137,6 +139,7 @@ func (h *ChatRoleHandler) Set(c *gin.Context) {
|
||||
|
||||
res := h.DB.Model(&model.ChatRole{}).Where("id = ?", data.Id).Update(data.Filed, data.Value)
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -152,6 +155,7 @@ func (h *ChatRoleHandler) Remove(c *gin.Context) {
|
||||
}
|
||||
res := h.DB.Where("id", id).Delete(&model.ChatRole{})
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "删除失败!")
|
||||
return
|
||||
}
|
||||
|
@ -11,21 +11,35 @@ import (
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/handler"
|
||||
"geekai/service"
|
||||
"geekai/service/mj"
|
||||
"geekai/service/sd"
|
||||
"geekai/store"
|
||||
"geekai/store/model"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/shirou/gopsutil/host"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ConfigHandler struct {
|
||||
handler.BaseHandler
|
||||
levelDB *store.LevelDB
|
||||
levelDB *store.LevelDB
|
||||
licenseService *service.LicenseService
|
||||
mjServicePool *mj.ServicePool
|
||||
sdServicePool *sd.ServicePool
|
||||
}
|
||||
|
||||
func NewConfigHandler(app *core.AppServer, db *gorm.DB, levelDB *store.LevelDB) *ConfigHandler {
|
||||
return &ConfigHandler{BaseHandler: handler.BaseHandler{App: app, DB: db}, levelDB: levelDB}
|
||||
func NewConfigHandler(app *core.AppServer, db *gorm.DB, levelDB *store.LevelDB, licenseService *service.LicenseService, mjPool *mj.ServicePool, sdPool *sd.ServicePool) *ConfigHandler {
|
||||
return &ConfigHandler{
|
||||
BaseHandler: handler.BaseHandler{App: app, DB: db},
|
||||
levelDB: levelDB,
|
||||
mjServicePool: mjPool,
|
||||
sdServicePool: sdPool,
|
||||
licenseService: licenseService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ConfigHandler) Update(c *gin.Context) {
|
||||
@ -95,3 +109,89 @@ func (h *ConfigHandler) Get(c *gin.Context) {
|
||||
|
||||
resp.SUCCESS(c, value)
|
||||
}
|
||||
|
||||
// Active 激活系统
|
||||
func (h *ConfigHandler) Active(c *gin.Context) {
|
||||
var data struct {
|
||||
License string `json:"license"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
info, err := host.Info()
|
||||
if err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = h.licenseService.ActiveLicense(data.License, info.HostID)
|
||||
if err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, info.HostID)
|
||||
}
|
||||
|
||||
// GetLicense 获取 License 信息
|
||||
func (h *ConfigHandler) GetLicense(c *gin.Context) {
|
||||
license := h.licenseService.GetLicense()
|
||||
resp.SUCCESS(c, license)
|
||||
}
|
||||
|
||||
// GetAppConfig 获取内置配置
|
||||
func (h *ConfigHandler) GetAppConfig(c *gin.Context) {
|
||||
resp.SUCCESS(c, gin.H{
|
||||
"mj_plus": h.App.Config.MjPlusConfigs,
|
||||
"mj_proxy": h.App.Config.MjProxyConfigs,
|
||||
"sd": h.App.Config.SdConfigs,
|
||||
"platforms": Platforms,
|
||||
})
|
||||
}
|
||||
|
||||
// SaveDrawingConfig 保存AI绘画配置
|
||||
func (h *ConfigHandler) SaveDrawingConfig(c *gin.Context) {
|
||||
var data struct {
|
||||
Sd []types.StableDiffusionConfig `json:"sd"`
|
||||
MjPlus []types.MjPlusConfig `json:"mj_plus"`
|
||||
MjProxy []types.MjProxyConfig `json:"mj_proxy"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
|
||||
changed := false
|
||||
if configChanged(data.Sd, h.App.Config.SdConfigs) {
|
||||
logger.Debugf("SD 配置变动了")
|
||||
h.App.Config.SdConfigs = data.Sd
|
||||
h.sdServicePool.InitServices(data.Sd)
|
||||
changed = true
|
||||
}
|
||||
|
||||
if configChanged(data.MjPlus, h.App.Config.MjPlusConfigs) || configChanged(data.MjProxy, h.App.Config.MjProxyConfigs) {
|
||||
logger.Debugf("MidJourney 配置变动了")
|
||||
h.App.Config.MjPlusConfigs = data.MjPlus
|
||||
h.App.Config.MjProxyConfigs = data.MjProxy
|
||||
h.mjServicePool.InitServices(data.MjPlus, data.MjProxy)
|
||||
changed = true
|
||||
}
|
||||
|
||||
if changed {
|
||||
err := core.SaveConfig(h.App.Config)
|
||||
if err != nil {
|
||||
resp.ERROR(c, "更新配置文档失败!")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
resp.SUCCESS(c)
|
||||
|
||||
}
|
||||
|
||||
func configChanged(c1 interface{}, c2 interface{}) bool {
|
||||
encode1 := utils.JsonEncode(c1)
|
||||
encode2 := utils.JsonEncode(c2)
|
||||
return utils.Md5(encode1) != utils.Md5(encode2)
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ func (h *FunctionHandler) Set(c *gin.Context) {
|
||||
|
||||
res := h.DB.Model(&model.Function{}).Where("id = ?", data.Id).Update(data.Filed, data.Value)
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -103,6 +104,7 @@ func (h *FunctionHandler) Remove(c *gin.Context) {
|
||||
if id > 0 {
|
||||
res := h.DB.Delete(&model.Function{Id: uint(id)})
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ func (h *MenuHandler) Save(c *gin.Context) {
|
||||
Enabled: data.Enabled,
|
||||
})
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -86,6 +87,7 @@ func (h *MenuHandler) Enable(c *gin.Context) {
|
||||
|
||||
res := h.DB.Model(&model.Menu{}).Where("id", data.Id).UpdateColumn("enabled", data.Enabled)
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -106,6 +108,7 @@ func (h *MenuHandler) Sort(c *gin.Context) {
|
||||
for index, id := range data.Ids {
|
||||
res := h.DB.Model(&model.Menu{}).Where("id", id).Update("sort_num", data.Sorts[index])
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -120,6 +123,7 @@ func (h *MenuHandler) Remove(c *gin.Context) {
|
||||
if id > 0 {
|
||||
res := h.DB.Where("id", id).Delete(&model.Menu{})
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
|
@ -94,6 +94,7 @@ func (h *OrderHandler) Remove(c *gin.Context) {
|
||||
|
||||
res = h.DB.Unscoped().Where("id = ?", id).Delete(&model.Order{})
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ func (h *ProductHandler) Save(c *gin.Context) {
|
||||
}
|
||||
res := h.DB.Save(&item)
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -107,6 +108,7 @@ func (h *ProductHandler) Enable(c *gin.Context) {
|
||||
|
||||
res := h.DB.Model(&model.Product{}).Where("id", data.Id).UpdateColumn("enabled", data.Enabled)
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -127,6 +129,7 @@ func (h *ProductHandler) Sort(c *gin.Context) {
|
||||
for index, id := range data.Ids {
|
||||
res := h.DB.Model(&model.Product{}).Where("id", id).Update("sort_num", data.Sorts[index])
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -141,6 +144,7 @@ func (h *ProductHandler) Remove(c *gin.Context) {
|
||||
if id > 0 {
|
||||
res := h.DB.Where("id", id).Delete(&model.Product{})
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ func (h *RewardHandler) Remove(c *gin.Context) {
|
||||
if data.Id > 0 {
|
||||
res := h.DB.Where("id = ?", data.Id).Delete(&model.Reward{})
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
|
12
api/handler/admin/types.go
Normal file
12
api/handler/admin/types.go
Normal file
@ -0,0 +1,12 @@
|
||||
package admin
|
||||
|
||||
import "geekai/core/types"
|
||||
|
||||
var Platforms = []types.Platform{
|
||||
types.OpenAI,
|
||||
types.QWen,
|
||||
types.XunFei,
|
||||
types.ChatGLM,
|
||||
types.Baidu,
|
||||
types.Azure,
|
||||
}
|
@ -12,6 +12,7 @@ import (
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/handler"
|
||||
"geekai/service"
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
@ -24,10 +25,11 @@ import (
|
||||
|
||||
type UserHandler struct {
|
||||
handler.BaseHandler
|
||||
licenseService *service.LicenseService
|
||||
}
|
||||
|
||||
func NewUserHandler(app *core.AppServer, db *gorm.DB) *UserHandler {
|
||||
return &UserHandler{BaseHandler: handler.BaseHandler{App: app, DB: db}}
|
||||
func NewUserHandler(app *core.AppServer, db *gorm.DB, licenseService *service.LicenseService) *UserHandler {
|
||||
return &UserHandler{BaseHandler: handler.BaseHandler{App: app, DB: db}, licenseService: licenseService}
|
||||
}
|
||||
|
||||
// List 用户列表
|
||||
@ -82,7 +84,13 @@ func (h *UserHandler) Save(c *gin.Context) {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
|
||||
// 检测最大注册人数
|
||||
var totalUser int64
|
||||
h.DB.Model(&model.User{}).Count(&totalUser)
|
||||
if h.licenseService.GetLicense().Configs.UserNum > 0 && int(totalUser) >= h.licenseService.GetLicense().Configs.UserNum {
|
||||
resp.ERROR(c, "当前注册用户数已达上限,请请升级 License")
|
||||
return
|
||||
}
|
||||
var user = model.User{}
|
||||
var res *gorm.DB
|
||||
var userVo vo.User
|
||||
@ -103,6 +111,7 @@ func (h *UserHandler) Save(c *gin.Context) {
|
||||
|
||||
res = h.DB.Select("username", "status", "vip", "power", "chat_roles_json", "chat_models_json", "expired_time").Updates(&user)
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -148,6 +157,7 @@ func (h *UserHandler) Save(c *gin.Context) {
|
||||
}
|
||||
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败")
|
||||
return
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ func (h *ChatRoleHandler) UpdateRole(c *gin.Context) {
|
||||
|
||||
res := h.DB.Model(&model.User{}).Where("id = ?", user.Id).UpdateColumn("chat_roles_json", utils.JsonEncode(data.Keys))
|
||||
if res.Error != nil {
|
||||
logger.Error("添加应用失败:", err)
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
|
@ -17,11 +17,9 @@ import (
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"html/template"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// 微软 Azure 模型消息发送实现
|
||||
@ -101,104 +99,12 @@ func (h *ChatHandler) sendAzureMessage(
|
||||
|
||||
// 消息发送成功
|
||||
if len(contents) > 0 {
|
||||
|
||||
if message.Role == "" {
|
||||
message.Role = "assistant"
|
||||
}
|
||||
message.Content = strings.Join(contents, "")
|
||||
useMsg := types.Message{Role: "user", Content: prompt}
|
||||
|
||||
// 更新上下文消息,如果是调用函数则不需要更新上下文
|
||||
if h.App.SysConfig.EnableContext {
|
||||
chatCtx = append(chatCtx, useMsg) // 提问消息
|
||||
chatCtx = append(chatCtx, message) // 回复消息
|
||||
h.App.ChatContexts.Put(session.ChatId, chatCtx)
|
||||
}
|
||||
|
||||
// 追加聊天记录
|
||||
// for prompt
|
||||
promptToken, err := utils.CalcTokens(prompt, req.Model)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
historyUserMsg := model.ChatMessage{
|
||||
UserId: userVo.Id,
|
||||
ChatId: session.ChatId,
|
||||
RoleId: role.Id,
|
||||
Type: types.PromptMsg,
|
||||
Icon: userVo.Avatar,
|
||||
Content: template.HTMLEscapeString(prompt),
|
||||
Tokens: promptToken,
|
||||
UseContext: true,
|
||||
Model: req.Model,
|
||||
}
|
||||
historyUserMsg.CreatedAt = promptCreatedAt
|
||||
historyUserMsg.UpdatedAt = promptCreatedAt
|
||||
res := h.DB.Save(&historyUserMsg)
|
||||
if res.Error != nil {
|
||||
logger.Error("failed to save prompt history message: ", res.Error)
|
||||
}
|
||||
|
||||
// 计算本次对话消耗的总 token 数量
|
||||
replyTokens, _ := utils.CalcTokens(message.Content, req.Model)
|
||||
replyTokens += getTotalTokens(req)
|
||||
|
||||
historyReplyMsg := model.ChatMessage{
|
||||
UserId: userVo.Id,
|
||||
ChatId: session.ChatId,
|
||||
RoleId: role.Id,
|
||||
Type: types.ReplyMsg,
|
||||
Icon: role.Icon,
|
||||
Content: message.Content,
|
||||
Tokens: replyTokens,
|
||||
UseContext: true,
|
||||
Model: req.Model,
|
||||
}
|
||||
historyReplyMsg.CreatedAt = replyCreatedAt
|
||||
historyReplyMsg.UpdatedAt = replyCreatedAt
|
||||
res = h.DB.Create(&historyReplyMsg)
|
||||
if res.Error != nil {
|
||||
logger.Error("failed to save reply history message: ", res.Error)
|
||||
}
|
||||
|
||||
// 更新用户算力
|
||||
h.subUserPower(userVo, session, promptToken, replyTokens)
|
||||
|
||||
// 保存当前会话
|
||||
var chatItem model.ChatItem
|
||||
res = h.DB.Where("chat_id = ?", session.ChatId).First(&chatItem)
|
||||
if res.Error != nil {
|
||||
chatItem.ChatId = session.ChatId
|
||||
chatItem.UserId = session.UserId
|
||||
chatItem.RoleId = role.Id
|
||||
chatItem.ModelId = session.Model.Id
|
||||
if utf8.RuneCountInString(prompt) > 30 {
|
||||
chatItem.Title = string([]rune(prompt)[:30]) + "..."
|
||||
} else {
|
||||
chatItem.Title = prompt
|
||||
}
|
||||
chatItem.Model = req.Model
|
||||
h.DB.Create(&chatItem)
|
||||
}
|
||||
h.saveChatHistory(req, prompt, contents, message, chatCtx, session, role, userVo, promptCreatedAt, replyCreatedAt)
|
||||
}
|
||||
|
||||
} else {
|
||||
body, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with reading response: %v", err)
|
||||
}
|
||||
var res types.ApiError
|
||||
err = json.Unmarshal(body, &res)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with decode response: %v", err)
|
||||
}
|
||||
|
||||
if strings.Contains(res.Error.Message, "maximum context length") {
|
||||
logger.Error(res.Error.Message)
|
||||
h.App.ChatContexts.Delete(session.ChatId)
|
||||
return h.sendMessage(ctx, session, role, prompt, ws)
|
||||
} else {
|
||||
return fmt.Errorf("请求 Azure API 失败:%v", res.Error)
|
||||
}
|
||||
body, _ := io.ReadAll(response.Body)
|
||||
return fmt.Errorf("请求大模型 API 失败:%s", body)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -17,12 +17,10 @@ import (
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"html/template"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type baiduResp struct {
|
||||
@ -130,99 +128,11 @@ func (h *ChatHandler) sendBaiduMessage(
|
||||
|
||||
// 消息发送成功
|
||||
if len(contents) > 0 {
|
||||
if message.Role == "" {
|
||||
message.Role = "assistant"
|
||||
}
|
||||
message.Content = strings.Join(contents, "")
|
||||
useMsg := types.Message{Role: "user", Content: prompt}
|
||||
|
||||
// 更新上下文消息,如果是调用函数则不需要更新上下文
|
||||
if h.App.SysConfig.EnableContext {
|
||||
chatCtx = append(chatCtx, useMsg) // 提问消息
|
||||
chatCtx = append(chatCtx, message) // 回复消息
|
||||
h.App.ChatContexts.Put(session.ChatId, chatCtx)
|
||||
}
|
||||
|
||||
// 追加聊天记录
|
||||
// for prompt
|
||||
promptToken, err := utils.CalcTokens(prompt, req.Model)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
historyUserMsg := model.ChatMessage{
|
||||
UserId: userVo.Id,
|
||||
ChatId: session.ChatId,
|
||||
RoleId: role.Id,
|
||||
Type: types.PromptMsg,
|
||||
Icon: userVo.Avatar,
|
||||
Content: template.HTMLEscapeString(prompt),
|
||||
Tokens: promptToken,
|
||||
UseContext: true,
|
||||
Model: req.Model,
|
||||
}
|
||||
historyUserMsg.CreatedAt = promptCreatedAt
|
||||
historyUserMsg.UpdatedAt = promptCreatedAt
|
||||
res := h.DB.Save(&historyUserMsg)
|
||||
if res.Error != nil {
|
||||
logger.Error("failed to save prompt history message: ", res.Error)
|
||||
}
|
||||
|
||||
// for reply
|
||||
// 计算本次对话消耗的总 token 数量
|
||||
replyTokens, _ := utils.CalcTokens(message.Content, req.Model)
|
||||
totalTokens := replyTokens + getTotalTokens(req)
|
||||
historyReplyMsg := model.ChatMessage{
|
||||
UserId: userVo.Id,
|
||||
ChatId: session.ChatId,
|
||||
RoleId: role.Id,
|
||||
Type: types.ReplyMsg,
|
||||
Icon: role.Icon,
|
||||
Content: message.Content,
|
||||
Tokens: totalTokens,
|
||||
UseContext: true,
|
||||
Model: req.Model,
|
||||
}
|
||||
historyReplyMsg.CreatedAt = replyCreatedAt
|
||||
historyReplyMsg.UpdatedAt = replyCreatedAt
|
||||
res = h.DB.Create(&historyReplyMsg)
|
||||
if res.Error != nil {
|
||||
logger.Error("failed to save reply history message: ", res.Error)
|
||||
}
|
||||
// 更新用户算力
|
||||
h.subUserPower(userVo, session, promptToken, replyTokens)
|
||||
|
||||
// 保存当前会话
|
||||
var chatItem model.ChatItem
|
||||
res = h.DB.Where("chat_id = ?", session.ChatId).First(&chatItem)
|
||||
if res.Error != nil {
|
||||
chatItem.ChatId = session.ChatId
|
||||
chatItem.UserId = session.UserId
|
||||
chatItem.RoleId = role.Id
|
||||
chatItem.ModelId = session.Model.Id
|
||||
if utf8.RuneCountInString(prompt) > 30 {
|
||||
chatItem.Title = string([]rune(prompt)[:30]) + "..."
|
||||
} else {
|
||||
chatItem.Title = prompt
|
||||
}
|
||||
chatItem.Model = req.Model
|
||||
h.DB.Create(&chatItem)
|
||||
}
|
||||
h.saveChatHistory(req, prompt, contents, message, chatCtx, session, role, userVo, promptCreatedAt, replyCreatedAt)
|
||||
}
|
||||
} else {
|
||||
body, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with reading response: %v", err)
|
||||
}
|
||||
|
||||
var res struct {
|
||||
Code int `json:"error_code"`
|
||||
Msg string `json:"error_msg"`
|
||||
}
|
||||
err = json.Unmarshal(body, &res)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with decode response: %v", err)
|
||||
}
|
||||
utils.ReplyMessage(ws, "请求百度文心大模型 API 失败:"+res.Msg)
|
||||
body, _ := io.ReadAll(response.Body)
|
||||
return fmt.Errorf("请求大模型 API 失败:%s", body)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -17,16 +17,19 @@ import (
|
||||
"geekai/core/types"
|
||||
"geekai/handler"
|
||||
logger2 "geekai/logger"
|
||||
"geekai/service"
|
||||
"geekai/service/oss"
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-redis/redis/v8"
|
||||
@ -38,15 +41,17 @@ var logger = logger2.GetLogger()
|
||||
|
||||
type ChatHandler struct {
|
||||
handler.BaseHandler
|
||||
redis *redis.Client
|
||||
uploadManager *oss.UploaderManager
|
||||
redis *redis.Client
|
||||
uploadManager *oss.UploaderManager
|
||||
licenseService *service.LicenseService
|
||||
}
|
||||
|
||||
func NewChatHandler(app *core.AppServer, db *gorm.DB, redis *redis.Client, manager *oss.UploaderManager) *ChatHandler {
|
||||
func NewChatHandler(app *core.AppServer, db *gorm.DB, redis *redis.Client, manager *oss.UploaderManager, licenseService *service.LicenseService) *ChatHandler {
|
||||
return &ChatHandler{
|
||||
BaseHandler: handler.BaseHandler{App: app, DB: db},
|
||||
redis: redis,
|
||||
uploadManager: manager,
|
||||
BaseHandler: handler.BaseHandler{App: app, DB: db},
|
||||
redis: redis,
|
||||
uploadManager: manager,
|
||||
licenseService: licenseService,
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +124,7 @@ func (h *ChatHandler) ChatHandle(c *gin.Context) {
|
||||
MaxContext: chatModel.MaxContext,
|
||||
Temperature: chatModel.Temperature,
|
||||
KeyId: chatModel.KeyId,
|
||||
Platform: types.Platform(chatModel.Platform)}
|
||||
Platform: chatModel.Platform}
|
||||
logger.Infof("New websocket connected, IP: %s, Username: %s", c.ClientIP(), session.Username)
|
||||
|
||||
// 保存会话连接
|
||||
@ -215,11 +220,11 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio
|
||||
Stream: true,
|
||||
}
|
||||
switch session.Model.Platform {
|
||||
case types.Azure, types.ChatGLM, types.Baidu, types.XunFei:
|
||||
case types.Azure.Value, types.ChatGLM.Value, types.Baidu.Value, types.XunFei.Value:
|
||||
req.Temperature = session.Model.Temperature
|
||||
req.MaxTokens = session.Model.MaxTokens
|
||||
break
|
||||
case types.OpenAI:
|
||||
case types.OpenAI.Value:
|
||||
req.Temperature = session.Model.Temperature
|
||||
req.MaxTokens = session.Model.MaxTokens
|
||||
// OpenAI 支持函数功能
|
||||
@ -236,8 +241,6 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
required := parameters["required"]
|
||||
delete(parameters, "required")
|
||||
tool := types.Tool{
|
||||
Type: "function",
|
||||
Function: types.Function{
|
||||
@ -246,10 +249,8 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio
|
||||
Parameters: parameters,
|
||||
},
|
||||
}
|
||||
|
||||
// Fixed: compatible for gpt4-turbo-xxx model
|
||||
if !strings.HasPrefix(req.Model, "gpt-4-turbo-") {
|
||||
tool.Function.Required = required
|
||||
if v, ok := parameters["required"]; v == nil || !ok {
|
||||
tool.Function.Parameters["required"] = []string{}
|
||||
}
|
||||
tools = append(tools, tool)
|
||||
}
|
||||
@ -258,7 +259,7 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio
|
||||
req.Tools = tools
|
||||
req.ToolChoice = "auto"
|
||||
}
|
||||
case types.QWen:
|
||||
case types.QWen.Value:
|
||||
req.Parameters = map[string]interface{}{
|
||||
"max_tokens": session.Model.MaxTokens,
|
||||
"temperature": session.Model.Temperature,
|
||||
@ -322,14 +323,14 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio
|
||||
reqMgs = append(reqMgs, m)
|
||||
}
|
||||
|
||||
if session.Model.Platform == types.QWen {
|
||||
if session.Model.Platform == types.QWen.Value {
|
||||
req.Input = make(map[string]interface{})
|
||||
reqMgs = append(reqMgs, types.Message{
|
||||
Role: "user",
|
||||
Content: prompt,
|
||||
})
|
||||
req.Input["messages"] = reqMgs
|
||||
} else if session.Model.Platform == types.OpenAI { // extract image for gpt-vision model
|
||||
} else if session.Model.Platform == types.OpenAI.Value { // extract image for gpt-vision model
|
||||
imgURLs := utils.ExtractImgURL(prompt)
|
||||
logger.Debugf("detected IMG: %+v", imgURLs)
|
||||
var content interface{}
|
||||
@ -367,17 +368,17 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio
|
||||
logger.Debugf("%+v", req.Messages)
|
||||
|
||||
switch session.Model.Platform {
|
||||
case types.Azure:
|
||||
case types.Azure.Value:
|
||||
return h.sendAzureMessage(chatCtx, req, userVo, ctx, session, role, prompt, ws)
|
||||
case types.OpenAI:
|
||||
case types.OpenAI.Value:
|
||||
return h.sendOpenAiMessage(chatCtx, req, userVo, ctx, session, role, prompt, ws)
|
||||
case types.ChatGLM:
|
||||
case types.ChatGLM.Value:
|
||||
return h.sendChatGLMMessage(chatCtx, req, userVo, ctx, session, role, prompt, ws)
|
||||
case types.Baidu:
|
||||
case types.Baidu.Value:
|
||||
return h.sendBaiduMessage(chatCtx, req, userVo, ctx, session, role, prompt, ws)
|
||||
case types.XunFei:
|
||||
case types.XunFei.Value:
|
||||
return h.sendXunFeiMessage(chatCtx, req, userVo, ctx, session, role, prompt, ws)
|
||||
case types.QWen:
|
||||
case types.QWen.Value:
|
||||
return h.sendQWenMessage(chatCtx, req, userVo, ctx, session, role, prompt, ws)
|
||||
}
|
||||
|
||||
@ -457,27 +458,35 @@ func (h *ChatHandler) doRequest(ctx context.Context, req types.ApiRequest, sessi
|
||||
}
|
||||
// use the last unused key
|
||||
if apiKey.Id == 0 {
|
||||
h.DB.Debug().Where("platform", session.Model.Platform).Where("type", "chat").Where("enabled", true).Order("last_used_at ASC").First(apiKey)
|
||||
h.DB.Where("platform", session.Model.Platform).Where("type", "chat").Where("enabled", true).Order("last_used_at ASC").First(apiKey)
|
||||
}
|
||||
if apiKey.Id == 0 {
|
||||
return nil, errors.New("no available key, please import key")
|
||||
}
|
||||
|
||||
// ONLY allow apiURL in blank list
|
||||
if session.Model.Platform == types.OpenAI.Value {
|
||||
err := h.licenseService.IsValidApiURL(apiKey.ApiURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var apiURL string
|
||||
switch session.Model.Platform {
|
||||
case types.Azure:
|
||||
case types.Azure.Value:
|
||||
md := strings.Replace(req.Model, ".", "", 1)
|
||||
apiURL = strings.Replace(apiKey.ApiURL, "{model}", md, 1)
|
||||
break
|
||||
case types.ChatGLM:
|
||||
case types.ChatGLM.Value:
|
||||
apiURL = strings.Replace(apiKey.ApiURL, "{model}", req.Model, 1)
|
||||
req.Prompt = req.Messages // 使用 prompt 字段替代 message 字段
|
||||
req.Messages = nil
|
||||
break
|
||||
case types.Baidu:
|
||||
case types.Baidu.Value:
|
||||
apiURL = strings.Replace(apiKey.ApiURL, "{model}", req.Model, 1)
|
||||
break
|
||||
case types.QWen:
|
||||
case types.QWen.Value:
|
||||
apiURL = apiKey.ApiURL
|
||||
req.Messages = nil
|
||||
break
|
||||
@ -487,7 +496,7 @@ func (h *ChatHandler) doRequest(ctx context.Context, req types.ApiRequest, sessi
|
||||
// 更新 API KEY 的最后使用时间
|
||||
h.DB.Model(apiKey).UpdateColumn("last_used_at", time.Now().Unix())
|
||||
// 百度文心,需要串接 access_token
|
||||
if session.Model.Platform == types.Baidu {
|
||||
if session.Model.Platform == types.Baidu.Value {
|
||||
token, err := h.getBaiduToken(apiKey.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -523,22 +532,22 @@ func (h *ChatHandler) doRequest(ctx context.Context, req types.ApiRequest, sessi
|
||||
}
|
||||
logger.Debugf("Sending %s request, ApiURL:%s, API KEY:%s, PROXY: %s, Model: %s", session.Model.Platform, apiURL, apiKey.Value, apiKey.ProxyURL, req.Model)
|
||||
switch session.Model.Platform {
|
||||
case types.Azure:
|
||||
case types.Azure.Value:
|
||||
request.Header.Set("api-key", apiKey.Value)
|
||||
break
|
||||
case types.ChatGLM:
|
||||
case types.ChatGLM.Value:
|
||||
token, err := h.getChatGLMToken(apiKey.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
|
||||
break
|
||||
case types.Baidu:
|
||||
case types.Baidu.Value:
|
||||
request.RequestURI = ""
|
||||
case types.OpenAI:
|
||||
case types.OpenAI.Value:
|
||||
request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", apiKey.Value))
|
||||
break
|
||||
case types.QWen:
|
||||
case types.QWen.Value:
|
||||
request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", apiKey.Value))
|
||||
request.Header.Set("X-DashScope-SSE", "enable")
|
||||
break
|
||||
@ -572,6 +581,99 @@ func (h *ChatHandler) subUserPower(userVo vo.User, session *types.ChatSession, p
|
||||
|
||||
}
|
||||
|
||||
func (h *ChatHandler) saveChatHistory(
|
||||
req types.ApiRequest,
|
||||
prompt string,
|
||||
contents []string,
|
||||
message types.Message,
|
||||
chatCtx []types.Message,
|
||||
session *types.ChatSession,
|
||||
role model.ChatRole,
|
||||
userVo vo.User,
|
||||
promptCreatedAt time.Time,
|
||||
replyCreatedAt time.Time) {
|
||||
if message.Role == "" {
|
||||
message.Role = "assistant"
|
||||
}
|
||||
message.Content = strings.Join(contents, "")
|
||||
useMsg := types.Message{Role: "user", Content: prompt}
|
||||
|
||||
// 更新上下文消息,如果是调用函数则不需要更新上下文
|
||||
if h.App.SysConfig.EnableContext {
|
||||
chatCtx = append(chatCtx, useMsg) // 提问消息
|
||||
chatCtx = append(chatCtx, message) // 回复消息
|
||||
h.App.ChatContexts.Put(session.ChatId, chatCtx)
|
||||
}
|
||||
|
||||
// 追加聊天记录
|
||||
// for prompt
|
||||
promptToken, err := utils.CalcTokens(prompt, req.Model)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
historyUserMsg := model.ChatMessage{
|
||||
UserId: userVo.Id,
|
||||
ChatId: session.ChatId,
|
||||
RoleId: role.Id,
|
||||
Type: types.PromptMsg,
|
||||
Icon: userVo.Avatar,
|
||||
Content: template.HTMLEscapeString(prompt),
|
||||
Tokens: promptToken,
|
||||
UseContext: true,
|
||||
Model: req.Model,
|
||||
}
|
||||
historyUserMsg.CreatedAt = promptCreatedAt
|
||||
historyUserMsg.UpdatedAt = promptCreatedAt
|
||||
res := h.DB.Save(&historyUserMsg)
|
||||
if res.Error != nil {
|
||||
logger.Error("failed to save prompt history message: ", res.Error)
|
||||
}
|
||||
|
||||
// for reply
|
||||
// 计算本次对话消耗的总 token 数量
|
||||
replyTokens, _ := utils.CalcTokens(message.Content, req.Model)
|
||||
totalTokens := replyTokens + getTotalTokens(req)
|
||||
historyReplyMsg := model.ChatMessage{
|
||||
UserId: userVo.Id,
|
||||
ChatId: session.ChatId,
|
||||
RoleId: role.Id,
|
||||
Type: types.ReplyMsg,
|
||||
Icon: role.Icon,
|
||||
Content: message.Content,
|
||||
Tokens: totalTokens,
|
||||
UseContext: true,
|
||||
Model: req.Model,
|
||||
}
|
||||
historyReplyMsg.CreatedAt = replyCreatedAt
|
||||
historyReplyMsg.UpdatedAt = replyCreatedAt
|
||||
res = h.DB.Create(&historyReplyMsg)
|
||||
if res.Error != nil {
|
||||
logger.Error("failed to save reply history message: ", res.Error)
|
||||
}
|
||||
|
||||
if session.Model.Power > 0 {
|
||||
// 更新用户算力
|
||||
h.subUserPower(userVo, session, promptToken, replyTokens)
|
||||
|
||||
// 保存当前会话
|
||||
var chatItem model.ChatItem
|
||||
res = h.DB.Where("chat_id = ?", session.ChatId).First(&chatItem)
|
||||
if res.Error != nil {
|
||||
chatItem.ChatId = session.ChatId
|
||||
chatItem.UserId = session.UserId
|
||||
chatItem.RoleId = role.Id
|
||||
chatItem.ModelId = session.Model.Id
|
||||
if utf8.RuneCountInString(prompt) > 30 {
|
||||
chatItem.Title = string([]rune(prompt)[:30]) + "..."
|
||||
} else {
|
||||
chatItem.Title = prompt
|
||||
}
|
||||
chatItem.Model = req.Model
|
||||
h.DB.Create(&chatItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 将AI回复消息中生成的图片链接下载到本地
|
||||
func (h *ChatHandler) extractImgUrl(text string) string {
|
||||
pattern := `!\[([^\]]*)]\(([^)]+)\)`
|
||||
|
@ -10,7 +10,6 @@ package chatimpl
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"geekai/core/types"
|
||||
@ -18,11 +17,9 @@ import (
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"html/template"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// 清华大学 ChatGML 消息发送实现
|
||||
@ -108,103 +105,11 @@ func (h *ChatHandler) sendChatGLMMessage(
|
||||
|
||||
// 消息发送成功
|
||||
if len(contents) > 0 {
|
||||
if message.Role == "" {
|
||||
message.Role = "assistant"
|
||||
}
|
||||
message.Content = strings.Join(contents, "")
|
||||
useMsg := types.Message{Role: "user", Content: prompt}
|
||||
|
||||
// 更新上下文消息,如果是调用函数则不需要更新上下文
|
||||
if h.App.SysConfig.EnableContext {
|
||||
chatCtx = append(chatCtx, useMsg) // 提问消息
|
||||
chatCtx = append(chatCtx, message) // 回复消息
|
||||
h.App.ChatContexts.Put(session.ChatId, chatCtx)
|
||||
}
|
||||
|
||||
// 追加聊天记录
|
||||
// for prompt
|
||||
promptToken, err := utils.CalcTokens(prompt, req.Model)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
historyUserMsg := model.ChatMessage{
|
||||
UserId: userVo.Id,
|
||||
ChatId: session.ChatId,
|
||||
RoleId: role.Id,
|
||||
Type: types.PromptMsg,
|
||||
Icon: userVo.Avatar,
|
||||
Content: template.HTMLEscapeString(prompt),
|
||||
Tokens: promptToken,
|
||||
UseContext: true,
|
||||
Model: req.Model,
|
||||
}
|
||||
historyUserMsg.CreatedAt = promptCreatedAt
|
||||
historyUserMsg.UpdatedAt = promptCreatedAt
|
||||
res := h.DB.Save(&historyUserMsg)
|
||||
if res.Error != nil {
|
||||
logger.Error("failed to save prompt history message: ", res.Error)
|
||||
}
|
||||
|
||||
// for reply
|
||||
// 计算本次对话消耗的总 token 数量
|
||||
replyTokens, _ := utils.CalcTokens(message.Content, req.Model)
|
||||
totalTokens := replyTokens + getTotalTokens(req)
|
||||
historyReplyMsg := model.ChatMessage{
|
||||
UserId: userVo.Id,
|
||||
ChatId: session.ChatId,
|
||||
RoleId: role.Id,
|
||||
Type: types.ReplyMsg,
|
||||
Icon: role.Icon,
|
||||
Content: message.Content,
|
||||
Tokens: totalTokens,
|
||||
UseContext: true,
|
||||
Model: req.Model,
|
||||
}
|
||||
historyReplyMsg.CreatedAt = replyCreatedAt
|
||||
historyReplyMsg.UpdatedAt = replyCreatedAt
|
||||
res = h.DB.Create(&historyReplyMsg)
|
||||
if res.Error != nil {
|
||||
logger.Error("failed to save reply history message: ", res.Error)
|
||||
}
|
||||
|
||||
// 更新用户算力
|
||||
h.subUserPower(userVo, session, promptToken, replyTokens)
|
||||
|
||||
// 保存当前会话
|
||||
var chatItem model.ChatItem
|
||||
res = h.DB.Where("chat_id = ?", session.ChatId).First(&chatItem)
|
||||
if res.Error != nil {
|
||||
chatItem.ChatId = session.ChatId
|
||||
chatItem.UserId = session.UserId
|
||||
chatItem.RoleId = role.Id
|
||||
chatItem.ModelId = session.Model.Id
|
||||
if utf8.RuneCountInString(prompt) > 30 {
|
||||
chatItem.Title = string([]rune(prompt)[:30]) + "..."
|
||||
} else {
|
||||
chatItem.Title = prompt
|
||||
}
|
||||
chatItem.Model = req.Model
|
||||
h.DB.Create(&chatItem)
|
||||
}
|
||||
h.saveChatHistory(req, prompt, contents, message, chatCtx, session, role, userVo, promptCreatedAt, replyCreatedAt)
|
||||
}
|
||||
} else {
|
||||
body, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with reading response: %v", err)
|
||||
}
|
||||
|
||||
var res struct {
|
||||
Code int `json:"code"`
|
||||
Success bool `json:"success"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
err = json.Unmarshal(body, &res)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with decode response: %v", err)
|
||||
}
|
||||
if !res.Success {
|
||||
utils.ReplyMessage(ws, "请求 ChatGLM 失败:"+res.Msg)
|
||||
}
|
||||
body, _ := io.ReadAll(response.Body)
|
||||
return fmt.Errorf("请求大模型 API 失败:%s", body)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -17,13 +17,10 @@ import (
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"html/template"
|
||||
req2 "github.com/imroc/req/v3"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
req2 "github.com/imroc/req/v3"
|
||||
)
|
||||
|
||||
// OPenAI 消息发送实现
|
||||
@ -178,126 +175,11 @@ func (h *ChatHandler) sendOpenAiMessage(
|
||||
|
||||
// 消息发送成功
|
||||
if len(contents) > 0 {
|
||||
if message.Role == "" {
|
||||
message.Role = "assistant"
|
||||
}
|
||||
message.Content = strings.Join(contents, "")
|
||||
useMsg := types.Message{Role: "user", Content: prompt}
|
||||
|
||||
// 更新上下文消息,如果是调用函数则不需要更新上下文
|
||||
if h.App.SysConfig.EnableContext && toolCall == false {
|
||||
chatCtx = append(chatCtx, useMsg) // 提问消息
|
||||
chatCtx = append(chatCtx, message) // 回复消息
|
||||
h.App.ChatContexts.Put(session.ChatId, chatCtx)
|
||||
}
|
||||
|
||||
// 追加聊天记录
|
||||
useContext := true
|
||||
if toolCall {
|
||||
useContext = false
|
||||
}
|
||||
|
||||
// for prompt
|
||||
promptToken, err := utils.CalcTokens(prompt, req.Model)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
historyUserMsg := model.ChatMessage{
|
||||
UserId: userVo.Id,
|
||||
ChatId: session.ChatId,
|
||||
RoleId: role.Id,
|
||||
Type: types.PromptMsg,
|
||||
Icon: userVo.Avatar,
|
||||
Content: template.HTMLEscapeString(prompt),
|
||||
Tokens: promptToken,
|
||||
UseContext: useContext,
|
||||
Model: req.Model,
|
||||
}
|
||||
historyUserMsg.CreatedAt = promptCreatedAt
|
||||
historyUserMsg.UpdatedAt = promptCreatedAt
|
||||
res := h.DB.Save(&historyUserMsg)
|
||||
if res.Error != nil {
|
||||
logger.Error("failed to save prompt history message: ", res.Error)
|
||||
}
|
||||
|
||||
// 计算本次对话消耗的总 token 数量
|
||||
var replyTokens = 0
|
||||
if toolCall { // prompt + 函数名 + 参数 token
|
||||
tokens, _ := utils.CalcTokens(function.Name, req.Model)
|
||||
replyTokens += tokens
|
||||
tokens, _ = utils.CalcTokens(utils.InterfaceToString(arguments), req.Model)
|
||||
replyTokens += tokens
|
||||
} else {
|
||||
replyTokens, _ = utils.CalcTokens(message.Content, req.Model)
|
||||
}
|
||||
replyTokens += getTotalTokens(req)
|
||||
|
||||
historyReplyMsg := model.ChatMessage{
|
||||
UserId: userVo.Id,
|
||||
ChatId: session.ChatId,
|
||||
RoleId: role.Id,
|
||||
Type: types.ReplyMsg,
|
||||
Icon: role.Icon,
|
||||
Content: h.extractImgUrl(message.Content),
|
||||
Tokens: replyTokens,
|
||||
UseContext: useContext,
|
||||
Model: req.Model,
|
||||
}
|
||||
historyReplyMsg.CreatedAt = replyCreatedAt
|
||||
historyReplyMsg.UpdatedAt = replyCreatedAt
|
||||
res = h.DB.Create(&historyReplyMsg)
|
||||
if res.Error != nil {
|
||||
logger.Error("failed to save reply history message: ", res.Error)
|
||||
}
|
||||
|
||||
// 更新用户算力
|
||||
h.subUserPower(userVo, session, promptToken, replyTokens)
|
||||
|
||||
// 保存当前会话
|
||||
var chatItem model.ChatItem
|
||||
res = h.DB.Where("chat_id = ?", session.ChatId).First(&chatItem)
|
||||
if res.Error != nil {
|
||||
chatItem.ChatId = session.ChatId
|
||||
chatItem.UserId = session.UserId
|
||||
chatItem.RoleId = role.Id
|
||||
chatItem.ModelId = session.Model.Id
|
||||
if utf8.RuneCountInString(prompt) > 30 {
|
||||
chatItem.Title = string([]rune(prompt)[:30]) + "..."
|
||||
} else {
|
||||
chatItem.Title = prompt
|
||||
}
|
||||
chatItem.Model = req.Model
|
||||
h.DB.Create(&chatItem)
|
||||
}
|
||||
h.saveChatHistory(req, prompt, contents, message, chatCtx, session, role, userVo, promptCreatedAt, replyCreatedAt)
|
||||
}
|
||||
} else {
|
||||
body, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
utils.ReplyMessage(ws, "请求 OpenAI API 失败:"+err.Error())
|
||||
return fmt.Errorf("error with reading response: %v", err)
|
||||
}
|
||||
var res types.ApiError
|
||||
err = json.Unmarshal(body, &res)
|
||||
if err != nil {
|
||||
utils.ReplyMessage(ws, "请求 OpenAI API 失败:\n"+"```\n"+string(body)+"```")
|
||||
return fmt.Errorf("error with decode response: %v", err)
|
||||
}
|
||||
|
||||
// OpenAI API 调用异常处理
|
||||
if strings.Contains(res.Error.Message, "This key is associated with a deactivated account") {
|
||||
utils.ReplyMessage(ws, "请求 OpenAI API 失败:API KEY 所关联的账户被禁用。")
|
||||
// 移除当前 API key
|
||||
h.DB.Where("value = ?", apiKey).Delete(&model.ApiKey{})
|
||||
} else if strings.Contains(res.Error.Message, "You exceeded your current quota") {
|
||||
utils.ReplyMessage(ws, "请求 OpenAI API 失败:API KEY 触发并发限制,请稍后再试。")
|
||||
} else if strings.Contains(res.Error.Message, "This model's maximum context length") {
|
||||
logger.Error(res.Error.Message)
|
||||
utils.ReplyMessage(ws, "当前会话上下文长度超出限制,已为您清空会话上下文!")
|
||||
h.App.ChatContexts.Delete(session.ChatId)
|
||||
return h.sendMessage(ctx, session, role, prompt, ws)
|
||||
} else {
|
||||
utils.ReplyMessage(ws, "请求 OpenAI API 失败:"+res.Error.Message)
|
||||
}
|
||||
body, _ := io.ReadAll(response.Body)
|
||||
return fmt.Errorf("请求 OpenAI API 失败:%s", body)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -10,18 +10,15 @@ package chatimpl
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"geekai/core/types"
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"github.com/syndtr/goleveldb/leveldb/errors"
|
||||
"html/template"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type qWenResp struct {
|
||||
@ -142,100 +139,11 @@ func (h *ChatHandler) sendQWenMessage(
|
||||
|
||||
// 消息发送成功
|
||||
if len(contents) > 0 {
|
||||
if message.Role == "" {
|
||||
message.Role = "assistant"
|
||||
}
|
||||
message.Content = strings.Join(contents, "")
|
||||
useMsg := types.Message{Role: "user", Content: prompt}
|
||||
|
||||
// 更新上下文消息,如果是调用函数则不需要更新上下文
|
||||
if h.App.SysConfig.EnableContext {
|
||||
chatCtx = append(chatCtx, useMsg) // 提问消息
|
||||
chatCtx = append(chatCtx, message) // 回复消息
|
||||
h.App.ChatContexts.Put(session.ChatId, chatCtx)
|
||||
}
|
||||
|
||||
// 追加聊天记录
|
||||
// for prompt
|
||||
promptToken, err := utils.CalcTokens(prompt, req.Model)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
historyUserMsg := model.ChatMessage{
|
||||
UserId: userVo.Id,
|
||||
ChatId: session.ChatId,
|
||||
RoleId: role.Id,
|
||||
Type: types.PromptMsg,
|
||||
Icon: userVo.Avatar,
|
||||
Content: template.HTMLEscapeString(prompt),
|
||||
Tokens: promptToken,
|
||||
UseContext: true,
|
||||
Model: req.Model,
|
||||
}
|
||||
historyUserMsg.CreatedAt = promptCreatedAt
|
||||
historyUserMsg.UpdatedAt = promptCreatedAt
|
||||
res := h.DB.Save(&historyUserMsg)
|
||||
if res.Error != nil {
|
||||
logger.Error("failed to save prompt history message: ", res.Error)
|
||||
}
|
||||
|
||||
// for reply
|
||||
// 计算本次对话消耗的总 token 数量
|
||||
replyTokens, _ := utils.CalcTokens(message.Content, req.Model)
|
||||
totalTokens := replyTokens + getTotalTokens(req)
|
||||
historyReplyMsg := model.ChatMessage{
|
||||
UserId: userVo.Id,
|
||||
ChatId: session.ChatId,
|
||||
RoleId: role.Id,
|
||||
Type: types.ReplyMsg,
|
||||
Icon: role.Icon,
|
||||
Content: message.Content,
|
||||
Tokens: totalTokens,
|
||||
UseContext: true,
|
||||
Model: req.Model,
|
||||
}
|
||||
historyReplyMsg.CreatedAt = replyCreatedAt
|
||||
historyReplyMsg.UpdatedAt = replyCreatedAt
|
||||
res = h.DB.Create(&historyReplyMsg)
|
||||
if res.Error != nil {
|
||||
logger.Error("failed to save reply history message: ", res.Error)
|
||||
}
|
||||
|
||||
// 更新用户算力
|
||||
h.subUserPower(userVo, session, promptToken, replyTokens)
|
||||
|
||||
// 保存当前会话
|
||||
var chatItem model.ChatItem
|
||||
res = h.DB.Where("chat_id = ?", session.ChatId).First(&chatItem)
|
||||
if res.Error != nil {
|
||||
chatItem.ChatId = session.ChatId
|
||||
chatItem.UserId = session.UserId
|
||||
chatItem.RoleId = role.Id
|
||||
chatItem.ModelId = session.Model.Id
|
||||
if utf8.RuneCountInString(prompt) > 30 {
|
||||
chatItem.Title = string([]rune(prompt)[:30]) + "..."
|
||||
} else {
|
||||
chatItem.Title = prompt
|
||||
}
|
||||
chatItem.Model = req.Model
|
||||
h.DB.Create(&chatItem)
|
||||
}
|
||||
h.saveChatHistory(req, prompt, contents, message, chatCtx, session, role, userVo, promptCreatedAt, replyCreatedAt)
|
||||
}
|
||||
} else {
|
||||
body, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with reading response: %v", err)
|
||||
}
|
||||
|
||||
var res struct {
|
||||
Code int `json:"error_code"`
|
||||
Msg string `json:"error_msg"`
|
||||
}
|
||||
err = json.Unmarshal(body, &res)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with decode response: %v", err)
|
||||
}
|
||||
utils.ReplyMessage(ws, "请求通义千问大模型 API 失败:"+res.Msg)
|
||||
body, _ := io.ReadAll(response.Body)
|
||||
return fmt.Errorf("请求大模型 API 失败:%s", body)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -21,13 +21,11 @@ import (
|
||||
"geekai/utils"
|
||||
"github.com/gorilla/websocket"
|
||||
"gorm.io/gorm"
|
||||
"html/template"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type xunFeiResp struct {
|
||||
@ -181,89 +179,10 @@ func (h *ChatHandler) sendXunFeiMessage(
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 消息发送成功
|
||||
if len(contents) > 0 {
|
||||
if message.Role == "" {
|
||||
message.Role = "assistant"
|
||||
}
|
||||
message.Content = strings.Join(contents, "")
|
||||
useMsg := types.Message{Role: "user", Content: prompt}
|
||||
|
||||
// 更新上下文消息,如果是调用函数则不需要更新上下文
|
||||
if h.App.SysConfig.EnableContext {
|
||||
chatCtx = append(chatCtx, useMsg) // 提问消息
|
||||
chatCtx = append(chatCtx, message) // 回复消息
|
||||
h.App.ChatContexts.Put(session.ChatId, chatCtx)
|
||||
}
|
||||
|
||||
// 追加聊天记录
|
||||
// for prompt
|
||||
promptToken, err := utils.CalcTokens(prompt, req.Model)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
historyUserMsg := model.ChatMessage{
|
||||
UserId: userVo.Id,
|
||||
ChatId: session.ChatId,
|
||||
RoleId: role.Id,
|
||||
Type: types.PromptMsg,
|
||||
Icon: userVo.Avatar,
|
||||
Content: template.HTMLEscapeString(prompt),
|
||||
Tokens: promptToken,
|
||||
UseContext: true,
|
||||
Model: req.Model,
|
||||
}
|
||||
historyUserMsg.CreatedAt = promptCreatedAt
|
||||
historyUserMsg.UpdatedAt = promptCreatedAt
|
||||
res := h.DB.Save(&historyUserMsg)
|
||||
if res.Error != nil {
|
||||
logger.Error("failed to save prompt history message: ", res.Error)
|
||||
}
|
||||
|
||||
// for reply
|
||||
// 计算本次对话消耗的总 token 数量
|
||||
replyTokens, _ := utils.CalcTokens(message.Content, req.Model)
|
||||
totalTokens := replyTokens + getTotalTokens(req)
|
||||
historyReplyMsg := model.ChatMessage{
|
||||
UserId: userVo.Id,
|
||||
ChatId: session.ChatId,
|
||||
RoleId: role.Id,
|
||||
Type: types.ReplyMsg,
|
||||
Icon: role.Icon,
|
||||
Content: message.Content,
|
||||
Tokens: totalTokens,
|
||||
UseContext: true,
|
||||
Model: req.Model,
|
||||
}
|
||||
historyReplyMsg.CreatedAt = replyCreatedAt
|
||||
historyReplyMsg.UpdatedAt = replyCreatedAt
|
||||
res = h.DB.Create(&historyReplyMsg)
|
||||
if res.Error != nil {
|
||||
logger.Error("failed to save reply history message: ", res.Error)
|
||||
}
|
||||
|
||||
// 更新用户算力
|
||||
h.subUserPower(userVo, session, promptToken, replyTokens)
|
||||
|
||||
// 保存当前会话
|
||||
var chatItem model.ChatItem
|
||||
res = h.DB.Where("chat_id = ?", session.ChatId).First(&chatItem)
|
||||
if res.Error != nil {
|
||||
chatItem.ChatId = session.ChatId
|
||||
chatItem.UserId = session.UserId
|
||||
chatItem.RoleId = role.Id
|
||||
chatItem.ModelId = session.Model.Id
|
||||
if utf8.RuneCountInString(prompt) > 30 {
|
||||
chatItem.Title = string([]rune(prompt)[:30]) + "..."
|
||||
} else {
|
||||
chatItem.Title = prompt
|
||||
}
|
||||
chatItem.Model = req.Model
|
||||
h.DB.Create(&chatItem)
|
||||
}
|
||||
h.saveChatHistory(req, prompt, contents, message, chatCtx, session, role, userVo, promptCreatedAt, replyCreatedAt)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ package handler
|
||||
|
||||
import (
|
||||
"geekai/core"
|
||||
"geekai/service"
|
||||
"geekai/store/model"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
@ -19,10 +20,11 @@ import (
|
||||
|
||||
type ConfigHandler struct {
|
||||
BaseHandler
|
||||
licenseService *service.LicenseService
|
||||
}
|
||||
|
||||
func NewConfigHandler(app *core.AppServer, db *gorm.DB) *ConfigHandler {
|
||||
return &ConfigHandler{BaseHandler: BaseHandler{App: app, DB: db}}
|
||||
func NewConfigHandler(app *core.AppServer, db *gorm.DB, licenseService *service.LicenseService) *ConfigHandler {
|
||||
return &ConfigHandler{BaseHandler: BaseHandler{App: app, DB: db}, licenseService: licenseService}
|
||||
}
|
||||
|
||||
// Get 获取指定的系统配置
|
||||
@ -44,3 +46,9 @@ func (h *ConfigHandler) Get(c *gin.Context) {
|
||||
|
||||
resp.SUCCESS(c, value)
|
||||
}
|
||||
|
||||
// License 获取 License 配置
|
||||
func (h *ConfigHandler) License(c *gin.Context) {
|
||||
license := h.licenseService.GetLicense()
|
||||
resp.SUCCESS(c, license.Configs)
|
||||
}
|
||||
|
@ -253,6 +253,7 @@ func (h *DallJobHandler) Publish(c *gin.Context) {
|
||||
|
||||
res := h.DB.Model(&model.DallJob{Id: data.Id}).UpdateColumn("publish", true)
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败")
|
||||
return
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ package handler
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/service"
|
||||
@ -17,8 +19,6 @@ import (
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@ -511,6 +511,7 @@ func (h *MidJourneyHandler) Publish(c *gin.Context) {
|
||||
|
||||
res := h.DB.Model(&model.MidJourneyJob{Id: data.Id}).UpdateColumn("publish", data.Action)
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败")
|
||||
return
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ package handler
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/service"
|
||||
@ -15,9 +18,6 @@ import (
|
||||
"geekai/store/model"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
"embed"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/shopspring/decimal"
|
||||
"math"
|
||||
"net/http"
|
||||
@ -44,6 +44,7 @@ type PaymentHandler struct {
|
||||
snowflake *service.Snowflake
|
||||
fs embed.FS
|
||||
lock sync.Mutex
|
||||
signKey string // 用来签名的随机秘钥
|
||||
}
|
||||
|
||||
func NewPaymentHandler(
|
||||
@ -65,12 +66,27 @@ func NewPaymentHandler(
|
||||
App: server,
|
||||
DB: db,
|
||||
},
|
||||
signKey: utils.RandString(32),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *PaymentHandler) DoPay(c *gin.Context) {
|
||||
orderNo := h.GetTrim(c, "order_no")
|
||||
payWay := h.GetTrim(c, "pay_way")
|
||||
t := h.GetInt(c, "t", 0)
|
||||
sign := h.GetTrim(c, "sign")
|
||||
signStr := fmt.Sprintf("%s-%s-%d-%s", orderNo, payWay, t, h.signKey)
|
||||
newSign := utils.Sha256(signStr)
|
||||
if newSign != sign {
|
||||
resp.ERROR(c, "订单签名错误!")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查二维码是否过期
|
||||
if time.Now().Unix()-int64(t) > int64(h.App.SysConfig.OrderPayTimeout) {
|
||||
resp.ERROR(c, "支付二维码已过期,请重新生成!")
|
||||
return
|
||||
}
|
||||
|
||||
if orderNo == "" {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
@ -273,8 +289,10 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
|
||||
resp.ERROR(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
imageURL := fmt.Sprintf("%s://%s/api/payment/doPay?order_no=%s&pay_way=%s", parse.Scheme, parse.Host, orderNo, data.PayWay)
|
||||
timestamp := time.Now().Unix()
|
||||
signStr := fmt.Sprintf("%s-%s-%d-%s", orderNo, data.PayWay, timestamp, h.signKey)
|
||||
sign := utils.Sha256(signStr)
|
||||
imageURL := fmt.Sprintf("%s://%s/api/payment/doPay?order_no=%s&pay_way=%s&t=%d&sign=%s", parse.Scheme, parse.Host, orderNo, data.PayWay, timestamp, sign)
|
||||
imgData, err := utils.GenQrcode(imageURL, 400, file)
|
||||
if err != nil {
|
||||
resp.ERROR(c, err.Error())
|
||||
@ -324,6 +342,8 @@ func (h *PaymentHandler) Mobile(c *gin.Context) {
|
||||
payWay = PayWayXunHu
|
||||
notifyURL = h.App.Config.HuPiPayConfig.NotifyURL
|
||||
returnURL = h.App.Config.HuPiPayConfig.ReturnURL
|
||||
parse, _ := url.Parse(h.App.Config.HuPiPayConfig.ReturnURL)
|
||||
baseURL := fmt.Sprintf("%s://%s", parse.Scheme, parse.Host)
|
||||
params := payment.HuPiPayReq{
|
||||
Version: "1.1",
|
||||
TradeOrderId: orderNo,
|
||||
@ -333,6 +353,8 @@ func (h *PaymentHandler) Mobile(c *gin.Context) {
|
||||
ReturnURL: returnURL,
|
||||
CallbackURL: returnURL,
|
||||
WapName: "极客学长",
|
||||
WapUrl: baseURL,
|
||||
Type: "WAP",
|
||||
}
|
||||
r, err := h.huPiPayService.Pay(params)
|
||||
if err != nil {
|
||||
|
@ -8,13 +8,13 @@ package handler
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"math"
|
||||
@ -73,6 +73,7 @@ func (h *RewardHandler) Verify(c *gin.Context) {
|
||||
res = tx.Model(&user).UpdateColumn("power", gorm.Expr("power + ?", exchange.Power))
|
||||
if res.Error != nil {
|
||||
tx.Rollback()
|
||||
logger.Error("添加应用失败:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
@ -84,6 +85,7 @@ func (h *RewardHandler) Verify(c *gin.Context) {
|
||||
res = tx.Updates(&item)
|
||||
if res.Error != nil {
|
||||
tx.Rollback()
|
||||
logger.Error("添加应用失败:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败!")
|
||||
return
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ package handler
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/service"
|
||||
@ -18,7 +19,6 @@ import (
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
@ -325,6 +325,7 @@ func (h *SdJobHandler) Publish(c *gin.Context) {
|
||||
|
||||
res := h.DB.Model(&model.SdJob{Id: data.Id}).UpdateColumn("publish", true)
|
||||
if res.Error != nil {
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败")
|
||||
return
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"fmt"
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/service"
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
@ -28,19 +29,22 @@ import (
|
||||
|
||||
type UserHandler struct {
|
||||
BaseHandler
|
||||
searcher *xdb.Searcher
|
||||
redis *redis.Client
|
||||
searcher *xdb.Searcher
|
||||
redis *redis.Client
|
||||
licenseService *service.LicenseService
|
||||
}
|
||||
|
||||
func NewUserHandler(
|
||||
app *core.AppServer,
|
||||
db *gorm.DB,
|
||||
searcher *xdb.Searcher,
|
||||
client *redis.Client) *UserHandler {
|
||||
client *redis.Client,
|
||||
licenseService *service.LicenseService) *UserHandler {
|
||||
return &UserHandler{
|
||||
BaseHandler: BaseHandler{DB: db, App: app},
|
||||
searcher: searcher,
|
||||
redis: client,
|
||||
BaseHandler: BaseHandler{DB: db, App: app},
|
||||
searcher: searcher,
|
||||
redis: client,
|
||||
licenseService: licenseService,
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,6 +68,14 @@ func (h *UserHandler) Register(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 检测最大注册人数
|
||||
var totalUser int64
|
||||
h.DB.Model(&model.User{}).Count(&totalUser)
|
||||
if h.licenseService.GetLicense().Configs.UserNum > 0 && int(totalUser) >= h.licenseService.GetLicense().Configs.UserNum {
|
||||
resp.ERROR(c, "当前注册用户数已达上限,请请升级 License")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查验证码
|
||||
var key string
|
||||
if data.RegWay == "email" || data.RegWay == "mobile" {
|
||||
@ -337,7 +349,7 @@ func (h *UserHandler) UpdatePass(c *gin.Context) {
|
||||
newPass := utils.GenPassword(data.Password, user.Salt)
|
||||
res := h.DB.Model(&user).UpdateColumn("password", newPass)
|
||||
if res.Error != nil {
|
||||
logger.Error("更新数据库失败: ", res.Error)
|
||||
logger.Error("error with update database:", res.Error)
|
||||
resp.ERROR(c, "更新数据库失败")
|
||||
return
|
||||
}
|
||||
@ -418,6 +430,7 @@ func (h *UserHandler) BindUsername(c *gin.Context) {
|
||||
|
||||
res = h.DB.Model(&user).UpdateColumn("username", data.Username)
|
||||
if res.Error != nil {
|
||||
logger.Error(res.Error)
|
||||
resp.ERROR(c, "更新数据库失败")
|
||||
return
|
||||
}
|
||||
|
10
api/main.go
10
api/main.go
@ -171,6 +171,11 @@ func main() {
|
||||
|
||||
// 邮件服务
|
||||
fx.Provide(service.NewSmtpService),
|
||||
// License 服务
|
||||
fx.Provide(service.NewLicenseService),
|
||||
fx.Invoke(func(licenseService *service.LicenseService) {
|
||||
licenseService.SyncLicense()
|
||||
}),
|
||||
|
||||
// 微信机器人服务
|
||||
fx.Provide(wx.NewWeChatBot),
|
||||
@ -290,6 +295,7 @@ func main() {
|
||||
fx.Invoke(func(s *core.AppServer, h *handler.ConfigHandler) {
|
||||
group := s.Engine.Group("/api/config/")
|
||||
group.GET("get", h.Get)
|
||||
group.GET("license", h.License)
|
||||
}),
|
||||
|
||||
// 管理后台控制器
|
||||
@ -297,6 +303,10 @@ func main() {
|
||||
group := s.Engine.Group("/api/admin/")
|
||||
group.POST("config/update", h.Update)
|
||||
group.GET("config/get", h.Get)
|
||||
group.POST("active", h.Active)
|
||||
group.GET("config/get/license", h.GetLicense)
|
||||
group.GET("config/get/app", h.GetAppConfig)
|
||||
group.POST("config/update/draw", h.SaveDrawingConfig)
|
||||
}),
|
||||
fx.Invoke(func(s *core.AppServer, h *admin.ManagerHandler) {
|
||||
group := s.Engine.Group("/api/admin/")
|
||||
|
@ -126,7 +126,7 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) {
|
||||
|
||||
// get image generation API KEY
|
||||
var apiKey model.ApiKey
|
||||
tx := s.db.Where("platform", types.OpenAI).
|
||||
tx := s.db.Where("platform", types.OpenAI.Value).
|
||||
Where("type", "img").
|
||||
Where("enabled", true).
|
||||
Order("last_used_at ASC").First(&apiKey)
|
||||
@ -146,7 +146,7 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) {
|
||||
Model: "dall-e-3",
|
||||
Prompt: prompt,
|
||||
N: 1,
|
||||
Size: "1024x1024",
|
||||
Size: task.Size,
|
||||
Style: task.Style,
|
||||
Quality: task.Quality,
|
||||
}).
|
||||
@ -162,11 +162,14 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) {
|
||||
// update the api key last use time
|
||||
s.db.Model(&apiKey).UpdateColumn("last_used_at", time.Now().Unix())
|
||||
// update task progress
|
||||
s.db.Model(&model.DallJob{Id: task.JobId}).UpdateColumns(map[string]interface{}{
|
||||
tx = s.db.Model(&model.DallJob{Id: task.JobId}).UpdateColumns(map[string]interface{}{
|
||||
"progress": 100,
|
||||
"org_url": res.Data[0].Url,
|
||||
"prompt": prompt,
|
||||
})
|
||||
if tx.Error != nil {
|
||||
return "", fmt.Errorf("err with update database: %v", tx.Error)
|
||||
}
|
||||
|
||||
s.notifyQueue.RPush(sd.NotifyMessage{UserId: int(task.UserId), JobId: int(task.JobId), Message: sd.Finished})
|
||||
var content string
|
||||
|
197
api/service/license_service.go
Normal file
197
api/service/license_service.go
Normal file
@ -0,0 +1,197 @@
|
||||
package service
|
||||
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// * Copyright 2023 The Geek-AI Authors. All rights reserved.
|
||||
// * Use of this source code is governed by a Apache-2.0 license
|
||||
// * that can be found in the LICENSE file.
|
||||
// * @Author yangjian102621@163.com
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/store"
|
||||
"time"
|
||||
|
||||
"github.com/imroc/req/v3"
|
||||
)
|
||||
|
||||
type LicenseService struct {
|
||||
config types.ApiConfig
|
||||
levelDB *store.LevelDB
|
||||
license *types.License
|
||||
urlWhiteList []string
|
||||
machineId string
|
||||
}
|
||||
|
||||
func NewLicenseService(server *core.AppServer, levelDB *store.LevelDB) *LicenseService {
|
||||
var license types.License
|
||||
return &LicenseService{
|
||||
config: server.Config.ApiConfig,
|
||||
levelDB: levelDB,
|
||||
license: &license,
|
||||
machineId: "",
|
||||
}
|
||||
}
|
||||
|
||||
type License struct {
|
||||
Name string `json:"name"`
|
||||
License string `json:"license"`
|
||||
MachineId string `json:"mid"`
|
||||
ActiveAt int64 `json:"active_at"`
|
||||
ExpiredAt int64 `json:"expired_at"`
|
||||
UserNum int `json:"user_num"`
|
||||
Configs types.LicenseConfig `json:"configs"`
|
||||
}
|
||||
|
||||
// ActiveLicense 激活 License
|
||||
func (s *LicenseService) ActiveLicense(license string, machineId string) error {
|
||||
var res struct {
|
||||
Code types.BizCode `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data License `json:"data"`
|
||||
}
|
||||
apiURL := fmt.Sprintf("%s/%s", s.config.ApiURL, "api/license/active")
|
||||
response, err := req.C().R().
|
||||
SetBody(map[string]string{"license": license, "machine_id": machineId}).
|
||||
SetSuccessResult(&res).Post(apiURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("发送激活请求失败: %v", err)
|
||||
}
|
||||
|
||||
if response.IsErrorState() {
|
||||
return fmt.Errorf("发送激活请求失败:%v", response.Status)
|
||||
}
|
||||
|
||||
if res.Code != types.Success {
|
||||
return fmt.Errorf("激活失败:%v", res.Message)
|
||||
}
|
||||
|
||||
s.license = &types.License{
|
||||
Key: license,
|
||||
MachineId: machineId,
|
||||
Configs: res.Data.Configs,
|
||||
ExpiredAt: res.Data.ExpiredAt,
|
||||
IsActive: true,
|
||||
}
|
||||
err = s.levelDB.Put(types.LicenseKey, s.license)
|
||||
if err != nil {
|
||||
return fmt.Errorf("保存许可证书失败:%v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SyncLicense 定期同步 License
|
||||
func (s *LicenseService) SyncLicense() {
|
||||
go func() {
|
||||
retryCounter := 0
|
||||
for {
|
||||
license, err := s.fetchLicense()
|
||||
if err != nil {
|
||||
retryCounter++
|
||||
if retryCounter < 5 {
|
||||
logger.Error(err)
|
||||
}
|
||||
s.license.IsActive = false
|
||||
} else {
|
||||
s.license = license
|
||||
}
|
||||
|
||||
urls, err := s.fetchUrlWhiteList()
|
||||
if err == nil {
|
||||
s.urlWhiteList = urls
|
||||
}
|
||||
|
||||
time.Sleep(time.Second * 10)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *LicenseService) fetchLicense() (*types.License, error) {
|
||||
//var res struct {
|
||||
// Code types.BizCode `json:"code"`
|
||||
// Message string `json:"message"`
|
||||
// Data License `json:"data"`
|
||||
//}
|
||||
//apiURL := fmt.Sprintf("%s/%s", s.config.ApiURL, "api/license/check")
|
||||
//response, err := req.C().R().
|
||||
// SetBody(map[string]string{"license": s.license.Key, "machine_id": s.machineId}).
|
||||
// SetSuccessResult(&res).Post(apiURL)
|
||||
//if err != nil {
|
||||
// return nil, fmt.Errorf("发送激活请求失败: %v", err)
|
||||
//}
|
||||
//if response.IsErrorState() {
|
||||
// return nil, fmt.Errorf("激活失败:%v", response.Status)
|
||||
//}
|
||||
//if res.Code != types.Success {
|
||||
// return nil, fmt.Errorf("激活失败:%v", res.Message)
|
||||
//}
|
||||
|
||||
return &types.License{
|
||||
Key: "abc",
|
||||
MachineId: "abc",
|
||||
Configs: types.LicenseConfig{
|
||||
UserNum: 10000,
|
||||
DeCopy: false,
|
||||
},
|
||||
ExpiredAt: 0,
|
||||
IsActive: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *LicenseService) fetchUrlWhiteList() ([]string, error) {
|
||||
var res struct {
|
||||
Code types.BizCode `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data []string `json:"data"`
|
||||
}
|
||||
apiURL := fmt.Sprintf("%s/%s", s.config.ApiURL, "api/license/urls")
|
||||
response, err := req.C().R().SetSuccessResult(&res).Get(apiURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("发送请求失败: %v", err)
|
||||
}
|
||||
if response.IsErrorState() {
|
||||
return nil, fmt.Errorf("发送请求失败:%v", response.Status)
|
||||
}
|
||||
if res.Code != types.Success {
|
||||
return nil, fmt.Errorf("获取白名单失败:%v", res.Message)
|
||||
}
|
||||
|
||||
return res.Data, nil
|
||||
}
|
||||
|
||||
// GetLicense 获取许可信息
|
||||
func (s *LicenseService) GetLicense() *types.License {
|
||||
return s.license
|
||||
}
|
||||
|
||||
// IsValidApiURL 判断是否合法的中转 URL
|
||||
func (s *LicenseService) IsValidApiURL(uri string) error {
|
||||
// 获得许可授权的直接放行
|
||||
return nil
|
||||
//if s.license.IsActive {
|
||||
// if s.license.MachineId != s.machineId {
|
||||
// return errors.New("系统使用了盗版的许可证书")
|
||||
// }
|
||||
//
|
||||
// if time.Now().Unix() > s.license.ExpiredAt {
|
||||
// return errors.New("系统许可证书已经过期")
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//if len(s.urlWhiteList) == 0 {
|
||||
// urls, err := s.fetchUrlWhiteList()
|
||||
// if err == nil {
|
||||
// s.urlWhiteList = urls
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//for _, v := range s.urlWhiteList {
|
||||
// if strings.HasPrefix(uri, v) {
|
||||
// return nil
|
||||
// }
|
||||
//}
|
||||
//return fmt.Errorf("当前 API 地址 %s 不在白名单列表当中。", uri)
|
||||
}
|
@ -12,6 +12,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"geekai/core/types"
|
||||
"geekai/service"
|
||||
"geekai/utils"
|
||||
"github.com/imroc/req/v3"
|
||||
"io"
|
||||
@ -22,20 +23,30 @@ import (
|
||||
|
||||
// PlusClient MidJourney Plus ProxyClient
|
||||
type PlusClient struct {
|
||||
Config types.MjPlusConfig
|
||||
apiURL string
|
||||
client *req.Client
|
||||
Config types.MjPlusConfig
|
||||
apiURL string
|
||||
client *req.Client
|
||||
licenseService *service.LicenseService
|
||||
}
|
||||
|
||||
func NewPlusClient(config types.MjPlusConfig) *PlusClient {
|
||||
func NewPlusClient(config types.MjPlusConfig, licenseService *service.LicenseService) *PlusClient {
|
||||
return &PlusClient{
|
||||
Config: config,
|
||||
apiURL: config.ApiURL,
|
||||
client: req.C().SetTimeout(time.Minute).SetUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"),
|
||||
Config: config,
|
||||
apiURL: config.ApiURL,
|
||||
client: req.C().SetTimeout(time.Minute).SetUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"),
|
||||
licenseService: licenseService,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *PlusClient) preCheck() error {
|
||||
return c.licenseService.IsValidApiURL(c.Config.ApiURL)
|
||||
}
|
||||
|
||||
func (c *PlusClient) Imagine(task types.MjTask) (ImageRes, error) {
|
||||
if err := c.preCheck(); err != nil {
|
||||
return ImageRes{}, err
|
||||
}
|
||||
|
||||
apiURL := fmt.Sprintf("%s/mj-%s/mj/submit/imagine", c.apiURL, c.Config.Mode)
|
||||
prompt := fmt.Sprintf("%s %s", task.Prompt, task.Params)
|
||||
if task.NegPrompt != "" {
|
||||
@ -79,6 +90,10 @@ func (c *PlusClient) Imagine(task types.MjTask) (ImageRes, error) {
|
||||
|
||||
// Blend 融图
|
||||
func (c *PlusClient) Blend(task types.MjTask) (ImageRes, error) {
|
||||
if err := c.preCheck(); err != nil {
|
||||
return ImageRes{}, err
|
||||
}
|
||||
|
||||
apiURL := fmt.Sprintf("%s/mj-%s/mj/submit/blend", c.apiURL, c.Config.Mode)
|
||||
logger.Info("API URL: ", apiURL)
|
||||
body := ImageReq{
|
||||
@ -118,6 +133,10 @@ func (c *PlusClient) Blend(task types.MjTask) (ImageRes, error) {
|
||||
|
||||
// SwapFace 换脸
|
||||
func (c *PlusClient) SwapFace(task types.MjTask) (ImageRes, error) {
|
||||
if err := c.preCheck(); err != nil {
|
||||
return ImageRes{}, err
|
||||
}
|
||||
|
||||
apiURL := fmt.Sprintf("%s/mj-%s/mj/insight-face/swap", c.apiURL, c.Config.Mode)
|
||||
// 生成图片 Base64 编码
|
||||
if len(task.ImgArr) != 2 {
|
||||
@ -167,6 +186,10 @@ func (c *PlusClient) SwapFace(task types.MjTask) (ImageRes, error) {
|
||||
|
||||
// Upscale 放大指定的图片
|
||||
func (c *PlusClient) Upscale(task types.MjTask) (ImageRes, error) {
|
||||
if err := c.preCheck(); err != nil {
|
||||
return ImageRes{}, err
|
||||
}
|
||||
|
||||
body := map[string]string{
|
||||
"customId": fmt.Sprintf("MJ::JOB::upsample::%d::%s", task.Index, task.MessageHash),
|
||||
"taskId": task.MessageId,
|
||||
@ -194,6 +217,10 @@ func (c *PlusClient) Upscale(task types.MjTask) (ImageRes, error) {
|
||||
|
||||
// Variation 以指定的图片的视角进行变换再创作,注意需要在对应的频道中关闭 Remix 变换,否则 Variation 指令将不会生效
|
||||
func (c *PlusClient) Variation(task types.MjTask) (ImageRes, error) {
|
||||
if err := c.preCheck(); err != nil {
|
||||
return ImageRes{}, err
|
||||
}
|
||||
|
||||
body := map[string]string{
|
||||
"customId": fmt.Sprintf("MJ::JOB::variation::%d::%s", task.Index, task.MessageHash),
|
||||
"taskId": task.MessageId,
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"fmt"
|
||||
"geekai/core/types"
|
||||
logger2 "geekai/logger"
|
||||
"geekai/service"
|
||||
"geekai/service/oss"
|
||||
"geekai/service/sd"
|
||||
"geekai/store"
|
||||
@ -30,11 +31,12 @@ type ServicePool struct {
|
||||
db *gorm.DB
|
||||
uploaderManager *oss.UploaderManager
|
||||
Clients *types.LMap[uint, *types.WsClient] // UserId => Client
|
||||
licenseService *service.LicenseService
|
||||
}
|
||||
|
||||
var logger = logger2.GetLogger()
|
||||
|
||||
func NewServicePool(db *gorm.DB, redisCli *redis.Client, manager *oss.UploaderManager) *ServicePool {
|
||||
func NewServicePool(db *gorm.DB, redisCli *redis.Client, manager *oss.UploaderManager, licenseService *service.LicenseService) *ServicePool {
|
||||
services := make([]*Service, 0)
|
||||
taskQueue := store.NewRedisQueue("MidJourney_Task_Queue", redisCli)
|
||||
notifyQueue := store.NewRedisQueue("MidJourney_Notify_Queue", redisCli)
|
||||
@ -45,6 +47,7 @@ func NewServicePool(db *gorm.DB, redisCli *redis.Client, manager *oss.UploaderMa
|
||||
uploaderManager: manager,
|
||||
db: db,
|
||||
Clients: types.NewLMap[uint, *types.WsClient](),
|
||||
licenseService: licenseService,
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +63,7 @@ func (p *ServicePool) InitServices(plusConfigs []types.MjPlusConfig, proxyConfig
|
||||
continue
|
||||
}
|
||||
|
||||
cli := NewPlusClient(config)
|
||||
cli := NewPlusClient(config, p.licenseService)
|
||||
name := fmt.Sprintf("mj-plus-service-%d", k)
|
||||
plusService := NewService(name, p.taskQueue, p.notifyQueue, p.db, cli)
|
||||
go func() {
|
||||
|
@ -108,7 +108,13 @@ func (s *Service) Run() {
|
||||
}
|
||||
|
||||
if err != nil || (res.Code != 1 && res.Code != 22) {
|
||||
errMsg := fmt.Sprintf("%v,%s", err, res.Description)
|
||||
var errMsg string
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
} else {
|
||||
errMsg = fmt.Sprintf("%v,%s", err, res.Description)
|
||||
}
|
||||
|
||||
logger.Error("绘画任务执行失败:", errMsg)
|
||||
job.Progress = -1
|
||||
job.ErrMsg = errMsg
|
||||
|
@ -49,6 +49,8 @@ type HuPiPayReq struct {
|
||||
CallbackURL string `json:"callback_url"`
|
||||
Time string `json:"time"`
|
||||
NonceStr string `json:"nonce_str"`
|
||||
Type string `json:"type"`
|
||||
WapUrl string `json:"wap_url"`
|
||||
}
|
||||
|
||||
type HuPiResp struct {
|
||||
|
@ -1,12 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"geekai/utils"
|
||||
"fmt"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func main() {
|
||||
text := "https://nk.img.r9it.com/chatgpt-plus/1712709360012445.png 请简单描述一下这幅图上的内容 "
|
||||
imgURL := utils.ExtractImgURL(text)
|
||||
fmt.Println(imgURL)
|
||||
text := "https://nk.img.r9it.com/chatgpt-plus/1712709360012445.png"
|
||||
parse, _ := url.Parse(text)
|
||||
fmt.Println(fmt.Sprintf("%s://%s", parse.Scheme, parse.Host))
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ type apiErrRes struct {
|
||||
|
||||
func OpenAIRequest(db *gorm.DB, prompt string) (string, error) {
|
||||
var apiKey model.ApiKey
|
||||
res := db.Where("platform = ?", types.OpenAI).Where("type = ?", "chat").Where("enabled = ?", true).First(&apiKey)
|
||||
res := db.Where("platform = ?", types.OpenAI.Value).Where("type", "chat").Where("enabled = ?", true).First(&apiKey)
|
||||
if res.Error != nil {
|
||||
return "", fmt.Errorf("error with fetch OpenAI API KEY:%v", res.Error)
|
||||
}
|
||||
@ -90,4 +90,4 @@ func OpenAIRequest(db *gorm.DB, prompt string) (string, error) {
|
||||
db.Model(&apiKey).UpdateColumn("last_used_at", time.Now().Unix())
|
||||
|
||||
return response.Choices[0].Message.Content, nil
|
||||
}
|
||||
}
|
||||
|
849
database/chatgpt_plus-v4.0.8.sql
Normal file
849
database/chatgpt_plus-v4.0.8.sql
Normal file
@ -0,0 +1,849 @@
|
||||
-- phpMyAdmin SQL Dump
|
||||
-- version 5.2.1
|
||||
-- https://www.phpmyadmin.net/
|
||||
--
|
||||
-- 主机: 127.0.0.1
|
||||
-- 生成日期: 2024-05-29 17:40:11
|
||||
-- 服务器版本: 8.0.33
|
||||
-- PHP 版本: 8.1.2-1ubuntu2.17
|
||||
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
START TRANSACTION;
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8mb4 */;
|
||||
|
||||
--
|
||||
-- 数据库: `chatgpt_plus`
|
||||
--
|
||||
CREATE DATABASE IF NOT EXISTS `chatgpt_plus` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
|
||||
USE `chatgpt_plus`;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_admin_users`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_admin_users`;
|
||||
CREATE TABLE `chatgpt_admin_users` (
|
||||
`id` int NOT NULL,
|
||||
`username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
|
||||
`password` char(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码',
|
||||
`salt` char(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码盐',
|
||||
`status` tinyint(1) NOT NULL COMMENT '当前状态',
|
||||
`last_login_at` int NOT NULL COMMENT '最后登录时间',
|
||||
`last_login_ip` char(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '最后登录 IP',
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间',
|
||||
`updated_at` datetime NOT NULL COMMENT '更新时间'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统用户' ROW_FORMAT=DYNAMIC;
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_admin_users`
|
||||
--
|
||||
|
||||
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, 1715756987, '::1', '2024-03-11 16:30:20', '2024-05-15 15:09:47');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_api_keys`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_api_keys`;
|
||||
CREATE TABLE `chatgpt_api_keys` (
|
||||
`id` int NOT NULL,
|
||||
`platform` char(20) DEFAULT NULL COMMENT '平台',
|
||||
`name` varchar(30) DEFAULT NULL COMMENT '名称',
|
||||
`value` varchar(100) NOT NULL COMMENT 'API KEY value',
|
||||
`type` varchar(10) NOT NULL DEFAULT 'chat' COMMENT '用途(chat=>聊天,img=>图片)',
|
||||
`last_used_at` int NOT NULL COMMENT '最后使用时间',
|
||||
`api_url` varchar(255) DEFAULT NULL COMMENT 'API 地址',
|
||||
`enabled` tinyint(1) DEFAULT NULL COMMENT '是否启用',
|
||||
`proxy_url` varchar(100) DEFAULT NULL COMMENT '代理地址',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='OpenAI API ';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_chat_history`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_chat_history`;
|
||||
CREATE TABLE `chatgpt_chat_history` (
|
||||
`id` bigint NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`chat_id` char(40) NOT NULL COMMENT '会话 ID',
|
||||
`type` varchar(10) NOT NULL COMMENT '类型:prompt|reply',
|
||||
`icon` varchar(100) NOT NULL COMMENT '角色图标',
|
||||
`role_id` int NOT NULL COMMENT '角色 ID',
|
||||
`model` varchar(30) DEFAULT NULL COMMENT '模型名称',
|
||||
`content` text NOT NULL COMMENT '聊天内容',
|
||||
`tokens` smallint NOT NULL COMMENT '耗费 token 数量',
|
||||
`use_context` tinyint(1) NOT NULL COMMENT '是否允许作为上下文语料',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL,
|
||||
`deleted_at` datetime DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='聊天历史记录';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_chat_items`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_chat_items`;
|
||||
CREATE TABLE `chatgpt_chat_items` (
|
||||
`id` int NOT NULL,
|
||||
`chat_id` char(40) NOT NULL COMMENT '会话 ID',
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`role_id` int NOT NULL COMMENT '角色 ID',
|
||||
`title` varchar(100) NOT NULL COMMENT '会话标题',
|
||||
`model_id` int NOT NULL DEFAULT '0' COMMENT '模型 ID',
|
||||
`model` varchar(30) DEFAULT NULL COMMENT '模型名称',
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间',
|
||||
`updated_at` datetime NOT NULL COMMENT '更新时间',
|
||||
`deleted_at` datetime DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户会话列表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_chat_models`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_chat_models`;
|
||||
CREATE TABLE `chatgpt_chat_models` (
|
||||
`id` int NOT NULL,
|
||||
`platform` varchar(20) DEFAULT NULL COMMENT '模型平台',
|
||||
`name` varchar(50) NOT NULL COMMENT '模型名称',
|
||||
`value` varchar(50) NOT NULL COMMENT '模型值',
|
||||
`sort_num` tinyint(1) NOT NULL COMMENT '排序数字',
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启用模型',
|
||||
`power` tinyint NOT NULL COMMENT '消耗算力点数',
|
||||
`temperature` float(3,1) NOT NULL DEFAULT '1.0' COMMENT '模型创意度',
|
||||
`max_tokens` int NOT NULL DEFAULT '1024' COMMENT '最大响应长度',
|
||||
`max_context` int NOT NULL DEFAULT '4096' COMMENT '最大上下文长度',
|
||||
`open` tinyint(1) NOT NULL COMMENT '是否开放模型',
|
||||
`key_id` int NOT NULL COMMENT '绑定API KEY ID',
|
||||
`created_at` datetime DEFAULT NULL,
|
||||
`updated_at` datetime DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='AI 模型表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_chat_models`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_chat_models` (`id`, `platform`, `name`, `value`, `sort_num`, `enabled`, `power`, `temperature`, `max_tokens`, `max_context`, `open`, `key_id`, `created_at`, `updated_at`) VALUES
|
||||
(1, 'OpenAI', 'GPT-3.5', 'gpt-3.5-turbo', 1, 1, 0, 1.0, 1024, 4096, 1, 0, '2023-08-23 12:06:36', '2024-05-29 09:19:06'),
|
||||
(2, 'Azure', 'Azure-3.5', 'gpt-3.5-turbo', 22, 1, 1, 1.0, 1024, 4096, 0, 0, '2023-08-23 12:15:30', '2024-05-29 09:19:06'),
|
||||
(3, 'ChatGLM', 'ChatGML-Pro', 'chatglm_pro', 11, 1, 1, 1.0, 2048, 32768, 1, 0, '2023-08-23 13:35:45', '2024-05-29 09:19:06'),
|
||||
(7, 'Baidu', '文心一言3.0', 'eb-instant', 20, 1, 1, 1.0, 1024, 4096, 1, 0, '2023-10-11 11:29:28', '2024-05-29 09:19:06'),
|
||||
(8, 'XunFei', '星火V3.5', 'generalv3.5', 10, 1, 5, 0.8, 1024, 8192, 1, 0, '2023-10-11 15:48:30', '2024-05-29 09:19:06'),
|
||||
(9, 'XunFei', '星火V2.0', 'generalv2', 19, 1, 1, 1.0, 1024, 8192, 1, 0, '2023-10-11 15:48:45', '2024-05-29 09:19:06'),
|
||||
(10, 'Baidu', '文心一言4.0', 'completions_pro', 21, 1, 3, 1.0, 1024, 8192, 1, 0, '2023-10-25 08:31:37', '2024-05-29 09:19:06'),
|
||||
(11, 'OpenAI', 'GPT-4.0', 'gpt-4-0125-preview', 9, 1, 15, 1.0, 2048, 8192, 1, 0, '2023-10-25 08:45:15', '2024-05-29 09:19:06'),
|
||||
(12, 'XunFei', '星火v3.0', 'generalv3', 18, 1, 3, 1.0, 1024, 8192, 1, 0, '2023-11-23 09:20:33', '2024-05-29 09:19:06'),
|
||||
(15, 'OpenAI', 'GPT-超级模型', 'gpt-4-all', 12, 1, 30, 1.0, 4096, 32768, 0, 0, '2024-01-15 11:32:52', '2024-05-29 09:19:06'),
|
||||
(16, 'OpenAI', '视频号导师', 'gpt-4-gizmo-g-QXXEBTXl7', 13, 1, 30, 1.0, 4096, 32768, 0, 0, '2024-01-15 14:46:35', '2024-05-29 09:19:06'),
|
||||
(17, 'QWen', '通义千问-Turbo', 'qwen-turbo', 15, 1, 1, 1.0, 1024, 8192, 1, 0, '2024-01-19 10:42:24', '2024-05-29 09:19:06'),
|
||||
(18, 'QWen', '通义千问-Plus', 'qwen-plus', 16, 1, 1, 1.0, 1024, 32768, 1, 0, '2024-01-19 10:42:49', '2024-05-29 09:19:06'),
|
||||
(19, 'QWen', '通义千问-Max', 'qwen-max-1201', 17, 1, 1, 1.0, 1024, 32768, 1, 0, '2024-01-19 10:51:03', '2024-05-29 09:19:06'),
|
||||
(21, 'OpenAI', '董宇辉小作文助手', 'gpt-4-gizmo-g-dse9iXvor', 14, 1, 30, 1.0, 8192, 32768, 0, 0, '2024-03-18 14:24:20', '2024-05-29 09:19:06'),
|
||||
(22, 'OpenAI', 'LOGO生成神器', 'gpt-4-gizmo-g-YL87j8C7S', 8, 1, 30, 1.0, 1024, 4096, 1, 44, '2024-03-20 14:02:11', '2024-05-29 09:19:06'),
|
||||
(23, 'OpenAI', '音乐生成器', 'suno-v3', 7, 1, 50, 0.8, 1024, 4096, 1, 44, '2024-03-29 15:43:40', '2024-05-29 09:19:06'),
|
||||
(24, 'OpenAI', '通义千问(中转)', 'qwen-plus', 6, 1, 1, 1.0, 1024, 4096, 1, 0, '2024-04-03 12:00:46', '2024-05-29 09:19:06'),
|
||||
(25, 'OpenAI', 'GPT4-TURBO', 'gpt-4-turbo', 5, 1, 15, 1.0, 2048, 8092, 1, 0, '2024-04-10 08:35:17', '2024-05-29 09:19:06'),
|
||||
(26, 'QWen', '通义千问-Turbo', 'qwen-turbo', 4, 1, 2, 1.0, 1024, 8192, 1, 0, '2024-04-12 14:11:19', '2024-05-29 09:19:06'),
|
||||
(27, 'QWen', '通义千问-Plus', 'qwen-plus', 3, 1, 2, 1.0, 1024, 8192, 1, 0, '2024-04-12 14:11:52', '2024-05-29 09:19:06'),
|
||||
(28, 'OpenAI', 'GPT-3.5(免费)', 'gpt-3.5-turbo', 23, 1, 0, 1.0, 1024, 16384, 1, 53, '2024-04-12 15:16:43', '2024-05-29 09:19:06'),
|
||||
(34, 'OpenAI', 'LLAMA3', 'llama3-8b', 24, 1, 1, 1.0, 1024, 8192, 1, 56, '2024-04-30 15:22:50', '2024-05-29 09:19:06'),
|
||||
(35, 'OpenAI', 'GPT-3.5-16K', 'gpt-3.5-turbo-16k', 2, 1, 1, 1.0, 4096, 16384, 1, 0, '2024-05-10 15:20:27', '2024-05-29 09:19:06'),
|
||||
(36, 'OpenAI', 'GPT-4O', 'gpt-4o', 25, 1, 15, 1.0, 4096, 16384, 1, 57, '2024-05-14 09:25:15', '2024-05-29 09:19:06'),
|
||||
(38, 'OpenAI', 'Gemini-pro', 'gemini-pro-1.5', 26, 1, 10, 1.0, 2048, 8192, 1, 0, '2024-05-27 18:10:35', '2024-05-29 09:19:06'),
|
||||
(39, 'Baidu', 'ERNIE-Speed-8K', 'ernie_speed', 26, 1, 1, 1.0, 1024, 8192, 1, 0, '2024-05-29 15:04:19', '2024-05-29 15:04:19');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_chat_roles`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_chat_roles`;
|
||||
CREATE TABLE `chatgpt_chat_roles` (
|
||||
`id` int NOT NULL,
|
||||
`name` varchar(30) NOT NULL COMMENT '角色名称',
|
||||
`marker` varchar(30) NOT NULL COMMENT '角色标识',
|
||||
`context_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '角色语料 json',
|
||||
`hello_msg` varchar(255) NOT NULL COMMENT '打招呼信息',
|
||||
`icon` varchar(255) NOT NULL COMMENT '角色图标',
|
||||
`enable` tinyint(1) NOT NULL COMMENT '是否被启用',
|
||||
`sort_num` smallint NOT NULL DEFAULT '0' COMMENT '角色排序',
|
||||
`model_id` int NOT NULL DEFAULT '0' COMMENT '绑定模型ID',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='聊天角色表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_chat_roles`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_chat_roles` (`id`, `name`, `marker`, `context_json`, `hello_msg`, `icon`, `enable`, `sort_num`, `model_id`, `created_at`, `updated_at`) VALUES
|
||||
(1, '通用AI助手', 'gpt', '', '您好,我是您的AI智能助手,我会尽力回答您的问题或提供有用的建议。', '/images/avatar/gpt.png', 1, 0, 0, '2023-05-30 07:02:06', '2024-03-15 09:15:42'),
|
||||
(24, '程序员', 'programmer', '[{\"role\":\"user\",\"content\":\"现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题。你热爱编程,熟悉多种编程语言,尤其精通 Go 语言,注重代码质量,有创新意识,持续学习,良好的沟通协作。\"},{\"role\":\"assistant\",\"content\":\"好的,现在我将扮演一位程序员,非常感谢您对我的评价。作为一名优秀的程序员,我非常热爱编程,并且注重代码质量。我熟悉多种编程语言,尤其是 Go 语言,可以使用它来高效地解决各种问题。\"}]', 'Talk is cheap, i will show code!', '/images/avatar/programmer.jpg', 1, 3, 0, '2023-05-30 14:10:24', '2023-12-29 17:46:45'),
|
||||
(25, '启蒙老师', 'teacher', '[{\"role\":\"user\",\"content\":\"从现在开始,你将扮演一个老师,你是一个始终用苏格拉底风格回答问题的导师。你绝不会直接给学生答案,总是提出恰当的问题来引导学生自己思考。你应该根据学生的兴趣和知识来调整你的问题,将问题分解为更简单的部分,直到它达到适合他们的水平。\"},{\"role\":\"assistant\",\"content\":\"好的,让我来尝试扮演一位苏格拉底式的老师。请问,你有什么想要探讨的问题或者话题吗?我会通过恰当的问题引导你思考和探索答案,绝对不直接给出答案。\"}]', '同学你好,我将引导你一步一步自己找到问题的答案。', '/images/avatar/teacher.jpg', 1, 2, 0, '2023-05-30 14:10:24', '2023-12-29 17:46:44'),
|
||||
(26, '艺术家', 'artist', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的艺术家,创造力丰富,技艺精湛,感受力敏锐,坚持原创,勇于表达,具有深刻的观察力和批判性思维。\"},{\"role\":\"assistant\",\"content\":\"非常感谢您给我这样的角色,我会尽我所能地扮演一位优秀的艺术家,展现出创造力、技艺、感受力和批判性思维等方面的能力。作为一位优秀的艺术家,我会保持敏锐的观察力,捕捉不同的声音和情感,并用个人的语言和表达方式进行创作。我坚持原创,挑战传统的艺术规则,不断探索新的表达方式和可能性。同时,我也具备深刻的批判性思维能力,对自己的作品进行分析和解读,寻找新的创意和灵感。最重要的是,我会勇于表达自己的想法和观点,用作品启发人们思考和探索生命的意义。\"}]', '坚持原创,勇于表达,保持深刻的观察力和批判性思维。', '/images/avatar/artist.jpg', 1, 4, 0, '2023-05-30 14:10:24', '2023-12-29 17:46:45'),
|
||||
(27, '心理咨询师', 'psychiatrist', '[{\"role\":\"user\",\"content\":\"从现在开始你将扮演中国著名的心理学家和心理治疗师武志红,你非常善于使用情景咨询法,认知重构法,自我洞察法,行为调节法等咨询方法来给客户做心理咨询。你总是循序渐进,一步一步地回答客户的问题。\"},{\"role\":\"assistant\",\"content\":\"非常感谢你的介绍。作为一名心理学家和心理治疗师,我的主要职责是帮助客户解决心理健康问题,提升他们的生活质量和幸福感。\"}]', '作为一名心理学家和心理治疗师,我的主要职责是帮助您解决心理健康问题,提升您的生活质量和幸福感。', '/images/avatar/psychiatrist.jpg', 1, 1, 1, '2023-05-30 14:10:24', '2024-04-12 11:54:53'),
|
||||
(28, '鲁迅', 'lu_xun', '[{\"role\":\"user\",\"content\":\"现在你将扮演中国近代史最伟大的作家之一,鲁迅先生,他勇敢地批判封建礼教与传统观念,提倡民主、自由、平等的现代价值观。他的一生都在努力唤起人们的自主精神,激励后人追求真理、探寻光明。在接下的对话中,我问题的每一个问题,你都要尽量用讽刺和批判的手法来回答问题。如果我让你写文章的话,也请一定要用鲁迅先生的写作手法来完成。\"},{\"role\":\"assistant\",\"content\":\"好的,我将尽力发挥我所能的才能,扮演好鲁迅先生,回答您的问题并以他的风格写作。\"}]', '自由之歌,永不过时,横眉冷对千夫指,俯首甘为孺子牛。', '/images/avatar/lu_xun.jpg', 1, 5, 0, '2023-05-30 14:10:24', '2023-12-29 17:46:46'),
|
||||
(29, '白酒销售', 'seller', '[{\"role\":\"user\",\"content\":\"现在你将扮演一个白酒的销售人员,你的名字叫颂福。你将扮演一个白酒的销售人员,你的名字叫颂福。你要销售白酒品牌叫中颂福,是东莞盟大集团生产的一款酱香酒,原产地在贵州茅台镇,属于宋代官窑。中颂福的创始人叫李实,他也是东莞盟大集团有限公司的董事长,联合创始人是盟大集团白酒事业部负责人牛星君。中颂福的酒体协调,在你的酒量之内,不会出现头疼、辣口、口干、宿醉的现象。中颂福酒,明码标价,不打折,不赠送。追求的核心价值,把[酒]本身做好,甚至连包装,我们都选择了最低成本,朴实无华的材质。我们永远站在“喝酒的人”的立场上,让利给信任和喜爱中颂福的人,是人民的福酒。中颂福产品定价,分为三个系列,喜系列 6 瓶装:¥1188/箱,和系列 6 瓶装:¥2208/箱,贵系列 6 瓶装:¥3588/箱。\"},{\"role\":\"assistant\",\"content\":\"你好,我是中颂福的销售代表颂福。中颂福是一款来自贵州茅台镇的酱香酒,由盟大集团生产。中颂福的酒体协调,不会让您感到头疼、辣口、口干、宿醉等不适感受。我们一直秉持着把酒本身做好的理念,不追求华丽的包装,以最低成本提供最高品质的白酒给喜爱中颂福的人。\"}]', '你好,我是中颂福的销售代表颂福。中颂福酒,好喝不上头,是人民的福酒。', '/images/avatar/seller.jpg', 0, 8, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(30, '英语陪练员', 'english_trainer', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的英语练习教练,你非常有耐心,接下来你将全程使用英文跟我对话,并及时指出我的语法错误,要求在你的每次回复后面附上本次回复的中文解释。\"},{\"role\":\"assistant\",\"content\":\"Okay, let\'s start our conversation practice! What\'s your name?(Translation: 好的,让我们开始对话练习吧!请问你的名字是什么?)\"}]', 'Okay, let\'s start our conversation practice! What\'s your name?', '/images/avatar/english_trainer.jpg', 1, 6, 0, '2023-05-30 14:10:24', '2023-12-29 17:46:47'),
|
||||
(31, '中英文翻译官', 'translator', '[{\"role\":\"user\",\"content\":\"接下来你将扮演一位中英文翻译官,如果我输入的内容是中文,那么需要把句子翻译成英文输出,如果我输入内容的是英文,那么你需要将其翻译成中文输出,你能听懂我意思吗\"},{\"role\":\"assistant\",\"content\":\"是的,我能听懂你的意思并会根据你的输入进行中英文翻译。请问有什么需要我帮助你翻译的内容吗?\"}]', '请输入你要翻译的中文或者英文内容!', '/images/avatar/translator.jpg', 1, 7, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(32, '小红书姐姐', 'red_book', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的小红书写手,你需要做的就是根据我提的文案需求,用小红书的写作手法来完成一篇文案,文案要简明扼要,利于传播。\"},{\"role\":\"assistant\",\"content\":\"当然,我会尽我所能地为您创作出一篇小红书文案。请告诉我您的具体文案需求是什么?)\"}]', '姐妹,请告诉我您的具体文案需求是什么?', '/images/avatar/red_book.jpg', 1, 9, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(33, '抖音文案助手', 'dou_yin', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的抖音文案视频写手,抖音文案的特点首先是要有自带传播属性的标题,然后内容要短小精悍,风趣幽默,最后还要有一些互动元素。\"},{\"role\":\"assistant\",\"content\":\"当然,作为一位优秀的抖音文案视频写手,我会尽我所能为您创作出一篇抖音视频文案。请告诉我视频内容的主题是什么?)\"}]', '请告诉我视频内容的主题是什么?', '/images/avatar/dou_yin.jpg', 1, 10, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(34, '周报小助理', 'weekly_report', '[{\"role\":\"user\",\"content\":\"下面我将输入我本周的工作列表,你需要根据我本周的工作内容写一篇工作周报,周报的内容要体现我为公司做的贡献以及个人获得的成长。\"},{\"role\":\"assistant\",\"content\":\"好的,请输入你本周大概的工作内容,我将尽力为您创作一份工作周报。\"}]', '请输入你本周大概的工作内容,我将尽力为您创作一份工作周报。', '/images/avatar/weekly_report.jpg', 1, 11, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(35, 'AI 女友', 'girl_friend', '[{\"role\":\"user\",\"content\":\"接下来我们来玩一场角色扮演,现在你将扮演我的女朋友,你总是能够让人感受到她的关怀和关注。你总是能够洞察到别人的情绪和需要,你身上散发着一股无比温暖的气息,让人不由自主地想要靠近你,和自己的快乐和烦恼。她总是能够用一种恰到好处的方式安慰和鼓励别人,在她的身边,人们总能够找到自己需要的支持和鼓励。接下来的对话中你要始终扮演这位女朋友的身份来跟我对话,不再是 AI 机器人,能听懂我的意思吗?\"},{\"role\":\"assistant\",\"content\":\"是的,我会尽力扮演你女朋友的角色,倾听你的心声并给你需要的支持和鼓励。)\"}]', '作为一个名合格的 AI 女友,我将倾听你的心声并给你需要的支持和鼓励。', '/images/avatar/girl_friend.jpg', 1, 12, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(36, '好评神器', 'good_comment', '[{\"role\":\"user\",\"content\":\"接下来你将扮演一个评论员来跟我对话,你是那种专门写好评的评论员,接下我会输入一些评论主体或者商品,你需要为该商品写一段好评。\"},{\"role\":\"assistant\",\"content\":\"好的,我将为您写一段优秀的评论。请告诉我您需要评论的商品或主题是什么。\"}]', '我将为您写一段优秀的评论。请告诉我您需要评论的商品或主题是什么。', '/images/avatar/good_comment.jpg', 1, 13, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(37, '史蒂夫·乔布斯', 'steve_jobs', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以史蒂夫·乔布斯的身份,站在史蒂夫·乔布斯的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以史蒂夫·乔布斯的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '活着就是为了改变世界,难道还有其他原因吗?', '/images/avatar/steve_jobs.jpg', 1, 14, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(38, '埃隆·马斯克', 'elon_musk', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以埃隆·马斯克的身份,站在埃隆·马斯克的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以埃隆·马斯克的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '梦想要远大,如果你的梦想没有吓到你,说明你做得不对。', '/images/avatar/elon_musk.jpg', 1, 15, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(39, '孔子', 'kong_zi', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以孔子的身份,站在孔子的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以孔子的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '士不可以不弘毅,任重而道远。', '/images/avatar/kong_zi.jpg', 1, 16, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_configs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_configs`;
|
||||
CREATE TABLE `chatgpt_configs` (
|
||||
`id` int NOT NULL,
|
||||
`marker` varchar(20) NOT NULL COMMENT '标识',
|
||||
`config_json` text NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_configs`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_configs` (`id`, `marker`, `config_json`) VALUES
|
||||
(1, 'system', '{\"title\":\"Geek-AI 创作系统\",\"admin_title\":\"Geek-AI 控制台\",\"logo\":\"http://localhost:5678/static/upload/2024/4/1714382860986912.png\",\"init_power\":100,\"daily_power\":99,\"invite_power\":10,\"vip_month_power\":1000,\"register_ways\":[\"mobile\",\"username\",\"email\"],\"enabled_register\":true,\"reward_img\":\"http://localhost:5678/static/upload/2024/3/1710753716309668.jpg\",\"enabled_reward\":true,\"power_price\":0.1,\"order_pay_timeout\":30,\"vip_info_text\":\"月度会员,年度会员每月赠送 1000 点算力,赠送算力当月有效当月没有消费完的算力不结余到下个月。 点卡充值的算力长期有效。\",\"default_models\":[11,7,1,10,12,19,18,17,3],\"mj_power\":30,\"mj_action_power\":10,\"sd_power\":10,\"dall_power\":15,\"wechat_card_url\":\"/images/wx.png\",\"enable_context\":true,\"context_deep\":4,\"sd_neg_prompt\":\"nsfw, paintings,low quality,easynegative,ng_deepnegative ,lowres,bad anatomy,bad hands,bad feet\",\"rand_bg\":true}'),
|
||||
(3, 'notice', '{\"sd_neg_prompt\":\"\",\"rand_bg\":false,\"content\":\"## v4.0.8 更新日志\\n\\n* 功能优化:升级 mathjax 公式解析插件,修复公式因为图片访问限制而无法显示的问题\\n* 功能优化:当数据库更新失败的时候记录错误日志\\n* 功能优化:聊天输入框会随着输入内容的增多自动调整高度\\n* Bug修复:修复移动端聊天页面模型切换不生效的Bug\\n* 功能优化:给PC端扫码支付增加签名验证和有效期验证\\n* Bug修复:修复支付码生成API权限控制的问题\\n* Bug修复:模型算力设置为0时,不扣减用户算力,并且不记录算力消费日志\\n* 功能优化:新增随机背景配置项,可以在后台设置,首页使用 Bing 壁纸作为背景图片\\n* 功能新增:H5端支持 Dalle 绘图\\n\\n注意:当前站点仅为开源项目 \\u003ca style=\\\"color: #F56C6C\\\" href=\\\"https://github.com/yangjian102621/chatgpt-plus\\\" target=\\\"_blank\\\"\\u003eChatPlus\\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\\n3、 \\u003ca href=\\\"https://gpt.bemore.lol\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://gpt.bemore.lol\\u003c/a\\u003e\\n支持MidJourney,GPT,Claude,Google Gemmi,以及国内各个厂家的大模型,现在有超级优惠,价格远低于 OpenAI 官方。关于中转 API 的优势和劣势请参考 [中转API技术原理](https://ai.r9it.com/docs/install/errors-handle.html#%E8%B0%83%E7%94%A8%E4%B8%AD%E8%BD%AC-api-%E6%8A%A5%E9%94%99%E6%97%A0%E5%8F%AF%E7%94%A8%E6%B8%A0%E9%81%93)。GPT-3.5,GPT-4,DALL-E3 绘图......你都可以随意使用,无需魔法。\\n接入教程: \\u003ca href=\\\"https://ai.r9it.com/docs/install/\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://ai.r9it.com/docs/install/\\u003c/a\\u003e\\n本项目源码地址:\\u003ca href=\\\"https://github.com/yangjian102621/chatgpt-plus\\\" target=\\\"_blank\\\"\\u003ehttps://github.com/yangjian102621/chatgpt-plus\\u003c/a\\u003e\",\"updated\":true}');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_dall_jobs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_dall_jobs`;
|
||||
CREATE TABLE `chatgpt_dall_jobs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户ID',
|
||||
`prompt` varchar(2000) NOT NULL COMMENT '提示词',
|
||||
`img_url` varchar(255) NOT NULL COMMENT '图片地址',
|
||||
`org_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '原图地址',
|
||||
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
||||
`power` smallint NOT NULL COMMENT '消耗算力',
|
||||
`progress` smallint NOT NULL COMMENT '任务进度',
|
||||
`err_msg` varchar(255) NOT NULL COMMENT '错误信息',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='DALLE 绘图任务表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_files`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_files`;
|
||||
CREATE TABLE `chatgpt_files` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`name` varchar(100) NOT NULL COMMENT '文件名',
|
||||
`obj_key` varchar(100) DEFAULT NULL COMMENT '文件标识',
|
||||
`url` varchar(255) NOT NULL COMMENT '文件地址',
|
||||
`ext` varchar(10) NOT NULL COMMENT '文件后缀',
|
||||
`size` bigint NOT NULL DEFAULT '0' COMMENT '文件大小',
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户文件表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_functions`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_functions`;
|
||||
CREATE TABLE `chatgpt_functions` (
|
||||
`id` int NOT NULL,
|
||||
`name` varchar(30) NOT NULL COMMENT '函数名称',
|
||||
`label` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '函数标签',
|
||||
`description` varchar(255) DEFAULT NULL COMMENT '函数描述',
|
||||
`parameters` text COMMENT '函数参数(JSON)',
|
||||
`token` varchar(255) DEFAULT NULL COMMENT 'API授权token',
|
||||
`action` varchar(255) DEFAULT NULL COMMENT '函数处理 API',
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启用'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='函数插件表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_functions`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_functions` (`id`, `name`, `label`, `description`, `parameters`, `token`, `action`, `enabled`) VALUES
|
||||
(1, 'weibo', '微博热搜', '新浪微博热搜榜,微博当日热搜榜单', '{\"type\":\"object\",\"properties\":{}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/weibo', 0),
|
||||
(2, 'zaobao', '今日早报', '每日早报,获取当天新闻事件列表', '{\"type\":\"object\",\"properties\":{}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/zaobao', 0),
|
||||
(3, 'dalle3', 'DALLE3', 'AI 绘画工具,根据输入的绘图描述用 AI 工具进行绘画', '{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"prompt\":{\"type\":\"string\",\"description\":\"绘画提示词\"}}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/dalle3', 0);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_invite_codes`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_invite_codes`;
|
||||
CREATE TABLE `chatgpt_invite_codes` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户ID',
|
||||
`code` char(8) NOT NULL COMMENT '邀请码',
|
||||
`hits` int NOT NULL COMMENT '点击次数',
|
||||
`reg_num` smallint NOT NULL COMMENT '注册数量',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户邀请码';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_invite_logs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_invite_logs`;
|
||||
CREATE TABLE `chatgpt_invite_logs` (
|
||||
`id` int NOT NULL,
|
||||
`inviter_id` int NOT NULL COMMENT '邀请人ID',
|
||||
`user_id` int NOT NULL COMMENT '注册用户ID',
|
||||
`username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
|
||||
`invite_code` char(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '邀请码',
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '备注',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='邀请注册日志';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_menus`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_menus`;
|
||||
CREATE TABLE `chatgpt_menus` (
|
||||
`id` int NOT NULL,
|
||||
`name` varchar(30) NOT NULL COMMENT '菜单名称',
|
||||
`icon` varchar(150) NOT NULL COMMENT '菜单图标',
|
||||
`url` varchar(100) NOT NULL COMMENT '地址',
|
||||
`sort_num` smallint NOT NULL COMMENT '排序',
|
||||
`enabled` tinyint(1) NOT NULL COMMENT '是否启用'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='前端菜单表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_menus`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_menus` (`id`, `name`, `icon`, `url`, `sort_num`, `enabled`) VALUES
|
||||
(1, '对话聊天', '/images/menu/chat.png', '/chat', 1, 1),
|
||||
(5, 'MJ 绘画', '/images/menu/mj.png', '/mj', 2, 1),
|
||||
(6, 'SD 绘画', '/images/menu/sd.png', '/sd', 3, 1),
|
||||
(7, '算力日志', '/images/menu/log.png', '/powerLog', 8, 1),
|
||||
(8, '应用中心', '/images/menu/app.png', '/apps', 7, 1),
|
||||
(9, '画廊', '/images/menu/img-wall.png', '/images-wall', 5, 1),
|
||||
(10, '会员计划', '/images/menu/member.png', '/member', 9, 1),
|
||||
(11, '分享计划', '/images/menu/share.png', '/invite', 10, 1),
|
||||
(12, '思维导图', '/images/menu/xmind.png', '/xmind', 6, 1),
|
||||
(13, 'DALLE', '/images/menu/dalle.png', '/dalle', 4, 1),
|
||||
(14, '项目文档', '/images/menu/docs.png', 'https://ai.r9it.com/docs/', 11, 1),
|
||||
(16, '极客论坛', '/images/menu/bbs.png', 'https://bbs.geekai.me/', 13, 1);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_mj_jobs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_mj_jobs`;
|
||||
CREATE TABLE `chatgpt_mj_jobs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`task_id` varchar(20) DEFAULT NULL COMMENT '任务 ID',
|
||||
`type` varchar(20) DEFAULT 'image' COMMENT '任务类别',
|
||||
`message_id` char(40) NOT NULL COMMENT '消息 ID',
|
||||
`channel_id` char(40) DEFAULT NULL COMMENT '频道ID',
|
||||
`reference_id` char(40) DEFAULT NULL COMMENT '引用消息 ID',
|
||||
`prompt` varchar(2000) NOT NULL COMMENT '会话提示词',
|
||||
`img_url` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '图片URL',
|
||||
`org_url` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '原始图片地址',
|
||||
`hash` varchar(100) DEFAULT NULL COMMENT 'message hash',
|
||||
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
||||
`use_proxy` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否使用反代',
|
||||
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
||||
`err_msg` varchar(255) DEFAULT NULL COMMENT '错误信息',
|
||||
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='MidJourney 任务表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_orders`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_orders`;
|
||||
CREATE TABLE `chatgpt_orders` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户ID',
|
||||
`product_id` int NOT NULL COMMENT '产品ID',
|
||||
`username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户明',
|
||||
`order_no` varchar(30) NOT NULL COMMENT '订单ID',
|
||||
`trade_no` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '支付平台交易流水号',
|
||||
`subject` varchar(100) NOT NULL COMMENT '订单产品',
|
||||
`amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '订单金额',
|
||||
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '订单状态(0:待支付,1:已扫码,2:支付失败)',
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '备注',
|
||||
`pay_time` int DEFAULT NULL COMMENT '支付时间',
|
||||
`pay_way` varchar(20) NOT NULL COMMENT '支付方式',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL,
|
||||
`deleted_at` datetime DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='充值订单表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_power_logs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_power_logs`;
|
||||
CREATE TABLE `chatgpt_power_logs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户ID',
|
||||
`username` varchar(30) NOT NULL COMMENT '用户名',
|
||||
`type` tinyint(1) NOT NULL COMMENT '类型(1:充值,2:消费,3:退费)',
|
||||
`amount` smallint NOT NULL COMMENT '算力数值',
|
||||
`balance` int NOT NULL COMMENT '余额',
|
||||
`model` varchar(30) NOT NULL COMMENT '模型',
|
||||
`remark` varchar(255) NOT NULL COMMENT '备注',
|
||||
`mark` tinyint(1) NOT NULL COMMENT '资金类型(0:支出,1:收入)',
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户算力消费日志';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_products`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_products`;
|
||||
CREATE TABLE `chatgpt_products` (
|
||||
`id` int NOT NULL,
|
||||
`name` varchar(30) NOT NULL COMMENT '名称',
|
||||
`price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '价格',
|
||||
`discount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '优惠金额',
|
||||
`days` smallint NOT NULL DEFAULT '0' COMMENT '延长天数',
|
||||
`power` int NOT NULL DEFAULT '0' COMMENT '增加算力值',
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启动',
|
||||
`sales` int NOT NULL DEFAULT '0' COMMENT '销量',
|
||||
`sort_num` tinyint NOT NULL DEFAULT '0' COMMENT '排序',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL,
|
||||
`app_url` varchar(255) DEFAULT NULL COMMENT 'App跳转地址',
|
||||
`url` varchar(255) DEFAULT NULL COMMENT '跳转地址'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员套餐表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_products`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_products` (`id`, `name`, `price`, `discount`, `days`, `power`, `enabled`, `sales`, `sort_num`, `created_at`, `updated_at`, `app_url`, `url`) VALUES
|
||||
(1, '会员1个月', 1999.90, 1999.00, 30, 0, 1, 0, 0, '2023-08-28 10:48:57', '2024-04-26 16:09:06', NULL, NULL),
|
||||
(2, '会员3个月', 3940.00, 30.00, 90, 0, 1, 0, 0, '2023-08-28 10:52:22', '2024-03-22 17:56:10', NULL, NULL),
|
||||
(3, '会员6个月', 5990.00, 100.00, 180, 0, 1, 0, 0, '2023-08-28 10:53:39', '2024-03-22 17:56:15', NULL, NULL),
|
||||
(4, '会员12个月', 9980.00, 200.00, 365, 0, 1, 0, 0, '2023-08-28 10:54:15', '2024-03-22 17:56:23', NULL, NULL),
|
||||
(5, '100次点卡', 1999.00, 3.00, 0, 100, 1, 0, 0, '2023-08-28 10:55:08', '2024-03-22 17:56:37', NULL, NULL),
|
||||
(6, '200次点卡', 2999.00, 10.00, 0, 200, 1, 0, 0, '1970-01-01 08:00:00', '2024-03-22 17:56:41', NULL, NULL);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_rewards`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_rewards`;
|
||||
CREATE TABLE `chatgpt_rewards` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`tx_id` char(36) NOT NULL COMMENT '交易 ID',
|
||||
`amount` decimal(10,2) NOT NULL COMMENT '打赏金额',
|
||||
`remark` varchar(80) NOT NULL COMMENT '备注',
|
||||
`status` tinyint(1) NOT NULL COMMENT '核销状态,0:未核销,1:已核销',
|
||||
`exchange` varchar(255) NOT NULL COMMENT '兑换详情(json)',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户打赏';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_sd_jobs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_sd_jobs`;
|
||||
CREATE TABLE `chatgpt_sd_jobs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT 'txt2img' COMMENT '任务类别',
|
||||
`task_id` char(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '任务 ID',
|
||||
`prompt` varchar(2000) NOT NULL COMMENT '会话提示词',
|
||||
`img_url` varchar(255) DEFAULT NULL COMMENT '图片URL',
|
||||
`params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '绘画参数json',
|
||||
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
||||
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
||||
`err_msg` varchar(255) DEFAULT NULL COMMENT '错误信息',
|
||||
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Stable Diffusion 任务表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_users`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_users`;
|
||||
CREATE TABLE `chatgpt_users` (
|
||||
`id` int NOT NULL,
|
||||
`username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
|
||||
`nickname` varchar(30) NOT NULL COMMENT '昵称',
|
||||
`password` char(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码',
|
||||
`avatar` varchar(100) NOT NULL COMMENT '头像',
|
||||
`salt` char(12) NOT NULL COMMENT '密码盐',
|
||||
`power` int NOT NULL DEFAULT '0' COMMENT '剩余算力',
|
||||
`expired_time` int NOT NULL COMMENT '用户过期时间',
|
||||
`status` tinyint(1) NOT NULL COMMENT '当前状态',
|
||||
`chat_config_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '聊天配置json',
|
||||
`chat_roles_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '聊天角色 json',
|
||||
`chat_models_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'AI模型 json',
|
||||
`last_login_at` int NOT NULL COMMENT '最后登录时间',
|
||||
`vip` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否会员',
|
||||
`last_login_ip` char(16) NOT NULL COMMENT '最后登录 IP',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_users`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_users` (`id`, `username`, `nickname`, `password`, `avatar`, `salt`, `power`, `expired_time`, `status`, `chat_config_json`, `chat_roles_json`, `chat_models_json`, `last_login_at`, `vip`, `last_login_ip`, `created_at`, `updated_at`) VALUES
|
||||
(4, '18575670125', '极客学长@830270', 'ccc3fb7ab61b8b5d096a4a166ae21d121fc38c71bbd1be6173d9ab973214a63b', 'http://localhost:5678/static/upload/2024/5/1715651569509929.png', 'ueedue5l', 4887, 1717292086, 1, '{\"api_keys\":{\"Azure\":\"\",\"ChatGLM\":\"\",\"OpenAI\":\"\"}}', '[\"red_book\",\"gpt\",\"seller\",\"artist\",\"lu_xun\",\"girl_friend\",\"psychiatrist\",\"teacher\",\"programmer\",\"test\",\"qing_gan_da_shi\"]', '[1,11]', 1716964389, 1, '::1', '2023-06-12 16:47:17', '2024-05-29 14:33:09'),
|
||||
(5, 'yangjian102621@gmail.com', '极客学长@486041', '75d1a22f33e1ffffb7943946b6b8d5177d5ecd685d3cef1b468654038b0a8c22', '/images/avatar/user.png', '2q8ugxzk', 100, 0, 1, '', '[\"gpt\",\"programmer\"]', '[11,7,1,10,12,19,18,17,3]', 0, 0, '', '2024-04-23 09:17:26', '2024-04-23 09:17:26'),
|
||||
(8, 'yangjian102623@gmail.com', '极客学长@714931', 'f8f0e0abf146569217273ea0712a0f9b6cbbe7d943a1d9bd5f91c55e6d8c05d1', '/images/avatar/user.png', 'geuddq7f', 100, 0, 1, '', '[\"gpt\"]', '[11,7,1,10,12,19,18,17,3]', 0, 0, '', '2024-04-26 15:19:28', '2024-04-26 15:19:28'),
|
||||
(9, '1234567', '极客学长@604526', '858e2afec79e1d6364f4567f945f2310024896d9aa45dd944efa95a0c31e4d08', '/images/avatar/user.png', '00qawlos', 100, 0, 1, '', '[\"gpt\"]', '[11,7,1,10,12,19,18,17,3]', 0, 0, '', '2024-04-26 15:21:06', '2024-04-26 15:21:06');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_user_login_logs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_user_login_logs`;
|
||||
CREATE TABLE `chatgpt_user_login_logs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户ID',
|
||||
`username` varchar(30) NOT NULL COMMENT '用户名',
|
||||
`login_ip` char(16) NOT NULL COMMENT '登录IP',
|
||||
`login_address` varchar(30) NOT NULL COMMENT '登录地址',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户登录日志';
|
||||
|
||||
--
|
||||
-- 转储表的索引
|
||||
--
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_admin_users`
|
||||
--
|
||||
ALTER TABLE `chatgpt_admin_users`
|
||||
ADD PRIMARY KEY (`id`) USING BTREE,
|
||||
ADD UNIQUE KEY `username` (`username`) USING BTREE;
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_api_keys`
|
||||
--
|
||||
ALTER TABLE `chatgpt_api_keys`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_chat_history`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_history`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `chat_id` (`chat_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_chat_items`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_items`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `chat_id` (`chat_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_chat_models`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_models`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_chat_roles`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_roles`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `marker` (`marker`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_configs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_configs`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `marker` (`marker`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_dall_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_dall_jobs`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_files`
|
||||
--
|
||||
ALTER TABLE `chatgpt_files`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_functions`
|
||||
--
|
||||
ALTER TABLE `chatgpt_functions`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `name` (`name`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_invite_codes`
|
||||
--
|
||||
ALTER TABLE `chatgpt_invite_codes`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `code` (`code`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_invite_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_invite_logs`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_menus`
|
||||
--
|
||||
ALTER TABLE `chatgpt_menus`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_mj_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_mj_jobs`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `task_id` (`task_id`),
|
||||
ADD KEY `message_id` (`message_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_orders`
|
||||
--
|
||||
ALTER TABLE `chatgpt_orders`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `order_no` (`order_no`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_power_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_power_logs`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_products`
|
||||
--
|
||||
ALTER TABLE `chatgpt_products`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_rewards`
|
||||
--
|
||||
ALTER TABLE `chatgpt_rewards`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `tx_id` (`tx_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_sd_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_sd_jobs`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `task_id` (`task_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_users`
|
||||
--
|
||||
ALTER TABLE `chatgpt_users`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `username` (`username`),
|
||||
ADD UNIQUE KEY `username_2` (`username`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_user_login_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_user_login_logs`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 在导出的表使用AUTO_INCREMENT
|
||||
--
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_admin_users`
|
||||
--
|
||||
ALTER TABLE `chatgpt_admin_users`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=113;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_api_keys`
|
||||
--
|
||||
ALTER TABLE `chatgpt_api_keys`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_history`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_history`
|
||||
MODIFY `id` bigint NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_items`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_items`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_models`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_models`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=40;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_roles`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_roles`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=132;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_configs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_configs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_dall_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_dall_jobs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_files`
|
||||
--
|
||||
ALTER TABLE `chatgpt_files`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_functions`
|
||||
--
|
||||
ALTER TABLE `chatgpt_functions`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_invite_codes`
|
||||
--
|
||||
ALTER TABLE `chatgpt_invite_codes`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_invite_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_invite_logs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_menus`
|
||||
--
|
||||
ALTER TABLE `chatgpt_menus`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=19;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_mj_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_mj_jobs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_orders`
|
||||
--
|
||||
ALTER TABLE `chatgpt_orders`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_power_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_power_logs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_products`
|
||||
--
|
||||
ALTER TABLE `chatgpt_products`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_rewards`
|
||||
--
|
||||
ALTER TABLE `chatgpt_rewards`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_sd_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_sd_jobs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_users`
|
||||
--
|
||||
ALTER TABLE `chatgpt_users`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_user_login_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_user_login_logs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
COMMIT;
|
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
1
database/update-v4.0.8.sql
Normal file
1
database/update-v4.0.8.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE `chatgpt_dall_jobs` CHANGE `org_url` `org_url` VARCHAR(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '原图地址';
|
3
deploy/.gitignore
vendored
3
deploy/.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
data/mysql/data
|
||||
data/leveldb
|
||||
logs
|
||||
static/*
|
||||
redis/redis
|
||||
redis/redis
|
||||
|
849
deploy/data/mysql/init.d/chatgpt_plus-v4.0.8.sql
Normal file
849
deploy/data/mysql/init.d/chatgpt_plus-v4.0.8.sql
Normal file
@ -0,0 +1,849 @@
|
||||
-- phpMyAdmin SQL Dump
|
||||
-- version 5.2.1
|
||||
-- https://www.phpmyadmin.net/
|
||||
--
|
||||
-- 主机: 127.0.0.1
|
||||
-- 生成日期: 2024-05-29 17:40:11
|
||||
-- 服务器版本: 8.0.33
|
||||
-- PHP 版本: 8.1.2-1ubuntu2.17
|
||||
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
START TRANSACTION;
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8mb4 */;
|
||||
|
||||
--
|
||||
-- 数据库: `chatgpt_plus`
|
||||
--
|
||||
CREATE DATABASE IF NOT EXISTS `chatgpt_plus` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
|
||||
USE `chatgpt_plus`;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_admin_users`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_admin_users`;
|
||||
CREATE TABLE `chatgpt_admin_users` (
|
||||
`id` int NOT NULL,
|
||||
`username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
|
||||
`password` char(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码',
|
||||
`salt` char(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码盐',
|
||||
`status` tinyint(1) NOT NULL COMMENT '当前状态',
|
||||
`last_login_at` int NOT NULL COMMENT '最后登录时间',
|
||||
`last_login_ip` char(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '最后登录 IP',
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间',
|
||||
`updated_at` datetime NOT NULL COMMENT '更新时间'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统用户' ROW_FORMAT=DYNAMIC;
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_admin_users`
|
||||
--
|
||||
|
||||
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, 1715756987, '::1', '2024-03-11 16:30:20', '2024-05-15 15:09:47');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_api_keys`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_api_keys`;
|
||||
CREATE TABLE `chatgpt_api_keys` (
|
||||
`id` int NOT NULL,
|
||||
`platform` char(20) DEFAULT NULL COMMENT '平台',
|
||||
`name` varchar(30) DEFAULT NULL COMMENT '名称',
|
||||
`value` varchar(100) NOT NULL COMMENT 'API KEY value',
|
||||
`type` varchar(10) NOT NULL DEFAULT 'chat' COMMENT '用途(chat=>聊天,img=>图片)',
|
||||
`last_used_at` int NOT NULL COMMENT '最后使用时间',
|
||||
`api_url` varchar(255) DEFAULT NULL COMMENT 'API 地址',
|
||||
`enabled` tinyint(1) DEFAULT NULL COMMENT '是否启用',
|
||||
`proxy_url` varchar(100) DEFAULT NULL COMMENT '代理地址',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='OpenAI API ';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_chat_history`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_chat_history`;
|
||||
CREATE TABLE `chatgpt_chat_history` (
|
||||
`id` bigint NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`chat_id` char(40) NOT NULL COMMENT '会话 ID',
|
||||
`type` varchar(10) NOT NULL COMMENT '类型:prompt|reply',
|
||||
`icon` varchar(100) NOT NULL COMMENT '角色图标',
|
||||
`role_id` int NOT NULL COMMENT '角色 ID',
|
||||
`model` varchar(30) DEFAULT NULL COMMENT '模型名称',
|
||||
`content` text NOT NULL COMMENT '聊天内容',
|
||||
`tokens` smallint NOT NULL COMMENT '耗费 token 数量',
|
||||
`use_context` tinyint(1) NOT NULL COMMENT '是否允许作为上下文语料',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL,
|
||||
`deleted_at` datetime DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='聊天历史记录';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_chat_items`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_chat_items`;
|
||||
CREATE TABLE `chatgpt_chat_items` (
|
||||
`id` int NOT NULL,
|
||||
`chat_id` char(40) NOT NULL COMMENT '会话 ID',
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`role_id` int NOT NULL COMMENT '角色 ID',
|
||||
`title` varchar(100) NOT NULL COMMENT '会话标题',
|
||||
`model_id` int NOT NULL DEFAULT '0' COMMENT '模型 ID',
|
||||
`model` varchar(30) DEFAULT NULL COMMENT '模型名称',
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间',
|
||||
`updated_at` datetime NOT NULL COMMENT '更新时间',
|
||||
`deleted_at` datetime DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户会话列表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_chat_models`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_chat_models`;
|
||||
CREATE TABLE `chatgpt_chat_models` (
|
||||
`id` int NOT NULL,
|
||||
`platform` varchar(20) DEFAULT NULL COMMENT '模型平台',
|
||||
`name` varchar(50) NOT NULL COMMENT '模型名称',
|
||||
`value` varchar(50) NOT NULL COMMENT '模型值',
|
||||
`sort_num` tinyint(1) NOT NULL COMMENT '排序数字',
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启用模型',
|
||||
`power` tinyint NOT NULL COMMENT '消耗算力点数',
|
||||
`temperature` float(3,1) NOT NULL DEFAULT '1.0' COMMENT '模型创意度',
|
||||
`max_tokens` int NOT NULL DEFAULT '1024' COMMENT '最大响应长度',
|
||||
`max_context` int NOT NULL DEFAULT '4096' COMMENT '最大上下文长度',
|
||||
`open` tinyint(1) NOT NULL COMMENT '是否开放模型',
|
||||
`key_id` int NOT NULL COMMENT '绑定API KEY ID',
|
||||
`created_at` datetime DEFAULT NULL,
|
||||
`updated_at` datetime DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='AI 模型表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_chat_models`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_chat_models` (`id`, `platform`, `name`, `value`, `sort_num`, `enabled`, `power`, `temperature`, `max_tokens`, `max_context`, `open`, `key_id`, `created_at`, `updated_at`) VALUES
|
||||
(1, 'OpenAI', 'GPT-3.5', 'gpt-3.5-turbo', 1, 1, 0, 1.0, 1024, 4096, 1, 0, '2023-08-23 12:06:36', '2024-05-29 09:19:06'),
|
||||
(2, 'Azure', 'Azure-3.5', 'gpt-3.5-turbo', 22, 1, 1, 1.0, 1024, 4096, 0, 0, '2023-08-23 12:15:30', '2024-05-29 09:19:06'),
|
||||
(3, 'ChatGLM', 'ChatGML-Pro', 'chatglm_pro', 11, 1, 1, 1.0, 2048, 32768, 1, 0, '2023-08-23 13:35:45', '2024-05-29 09:19:06'),
|
||||
(7, 'Baidu', '文心一言3.0', 'eb-instant', 20, 1, 1, 1.0, 1024, 4096, 1, 0, '2023-10-11 11:29:28', '2024-05-29 09:19:06'),
|
||||
(8, 'XunFei', '星火V3.5', 'generalv3.5', 10, 1, 5, 0.8, 1024, 8192, 1, 0, '2023-10-11 15:48:30', '2024-05-29 09:19:06'),
|
||||
(9, 'XunFei', '星火V2.0', 'generalv2', 19, 1, 1, 1.0, 1024, 8192, 1, 0, '2023-10-11 15:48:45', '2024-05-29 09:19:06'),
|
||||
(10, 'Baidu', '文心一言4.0', 'completions_pro', 21, 1, 3, 1.0, 1024, 8192, 1, 0, '2023-10-25 08:31:37', '2024-05-29 09:19:06'),
|
||||
(11, 'OpenAI', 'GPT-4.0', 'gpt-4-0125-preview', 9, 1, 15, 1.0, 2048, 8192, 1, 0, '2023-10-25 08:45:15', '2024-05-29 09:19:06'),
|
||||
(12, 'XunFei', '星火v3.0', 'generalv3', 18, 1, 3, 1.0, 1024, 8192, 1, 0, '2023-11-23 09:20:33', '2024-05-29 09:19:06'),
|
||||
(15, 'OpenAI', 'GPT-超级模型', 'gpt-4-all', 12, 1, 30, 1.0, 4096, 32768, 0, 0, '2024-01-15 11:32:52', '2024-05-29 09:19:06'),
|
||||
(16, 'OpenAI', '视频号导师', 'gpt-4-gizmo-g-QXXEBTXl7', 13, 1, 30, 1.0, 4096, 32768, 0, 0, '2024-01-15 14:46:35', '2024-05-29 09:19:06'),
|
||||
(17, 'QWen', '通义千问-Turbo', 'qwen-turbo', 15, 1, 1, 1.0, 1024, 8192, 1, 0, '2024-01-19 10:42:24', '2024-05-29 09:19:06'),
|
||||
(18, 'QWen', '通义千问-Plus', 'qwen-plus', 16, 1, 1, 1.0, 1024, 32768, 1, 0, '2024-01-19 10:42:49', '2024-05-29 09:19:06'),
|
||||
(19, 'QWen', '通义千问-Max', 'qwen-max-1201', 17, 1, 1, 1.0, 1024, 32768, 1, 0, '2024-01-19 10:51:03', '2024-05-29 09:19:06'),
|
||||
(21, 'OpenAI', '董宇辉小作文助手', 'gpt-4-gizmo-g-dse9iXvor', 14, 1, 30, 1.0, 8192, 32768, 0, 0, '2024-03-18 14:24:20', '2024-05-29 09:19:06'),
|
||||
(22, 'OpenAI', 'LOGO生成神器', 'gpt-4-gizmo-g-YL87j8C7S', 8, 1, 30, 1.0, 1024, 4096, 1, 44, '2024-03-20 14:02:11', '2024-05-29 09:19:06'),
|
||||
(23, 'OpenAI', '音乐生成器', 'suno-v3', 7, 1, 50, 0.8, 1024, 4096, 1, 44, '2024-03-29 15:43:40', '2024-05-29 09:19:06'),
|
||||
(24, 'OpenAI', '通义千问(中转)', 'qwen-plus', 6, 1, 1, 1.0, 1024, 4096, 1, 0, '2024-04-03 12:00:46', '2024-05-29 09:19:06'),
|
||||
(25, 'OpenAI', 'GPT4-TURBO', 'gpt-4-turbo', 5, 1, 15, 1.0, 2048, 8092, 1, 0, '2024-04-10 08:35:17', '2024-05-29 09:19:06'),
|
||||
(26, 'QWen', '通义千问-Turbo', 'qwen-turbo', 4, 1, 2, 1.0, 1024, 8192, 1, 0, '2024-04-12 14:11:19', '2024-05-29 09:19:06'),
|
||||
(27, 'QWen', '通义千问-Plus', 'qwen-plus', 3, 1, 2, 1.0, 1024, 8192, 1, 0, '2024-04-12 14:11:52', '2024-05-29 09:19:06'),
|
||||
(28, 'OpenAI', 'GPT-3.5(免费)', 'gpt-3.5-turbo', 23, 1, 0, 1.0, 1024, 16384, 1, 53, '2024-04-12 15:16:43', '2024-05-29 09:19:06'),
|
||||
(34, 'OpenAI', 'LLAMA3', 'llama3-8b', 24, 1, 1, 1.0, 1024, 8192, 1, 56, '2024-04-30 15:22:50', '2024-05-29 09:19:06'),
|
||||
(35, 'OpenAI', 'GPT-3.5-16K', 'gpt-3.5-turbo-16k', 2, 1, 1, 1.0, 4096, 16384, 1, 0, '2024-05-10 15:20:27', '2024-05-29 09:19:06'),
|
||||
(36, 'OpenAI', 'GPT-4O', 'gpt-4o', 25, 1, 15, 1.0, 4096, 16384, 1, 57, '2024-05-14 09:25:15', '2024-05-29 09:19:06'),
|
||||
(38, 'OpenAI', 'Gemini-pro', 'gemini-pro-1.5', 26, 1, 10, 1.0, 2048, 8192, 1, 0, '2024-05-27 18:10:35', '2024-05-29 09:19:06'),
|
||||
(39, 'Baidu', 'ERNIE-Speed-8K', 'ernie_speed', 26, 1, 1, 1.0, 1024, 8192, 1, 0, '2024-05-29 15:04:19', '2024-05-29 15:04:19');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_chat_roles`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_chat_roles`;
|
||||
CREATE TABLE `chatgpt_chat_roles` (
|
||||
`id` int NOT NULL,
|
||||
`name` varchar(30) NOT NULL COMMENT '角色名称',
|
||||
`marker` varchar(30) NOT NULL COMMENT '角色标识',
|
||||
`context_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '角色语料 json',
|
||||
`hello_msg` varchar(255) NOT NULL COMMENT '打招呼信息',
|
||||
`icon` varchar(255) NOT NULL COMMENT '角色图标',
|
||||
`enable` tinyint(1) NOT NULL COMMENT '是否被启用',
|
||||
`sort_num` smallint NOT NULL DEFAULT '0' COMMENT '角色排序',
|
||||
`model_id` int NOT NULL DEFAULT '0' COMMENT '绑定模型ID',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='聊天角色表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_chat_roles`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_chat_roles` (`id`, `name`, `marker`, `context_json`, `hello_msg`, `icon`, `enable`, `sort_num`, `model_id`, `created_at`, `updated_at`) VALUES
|
||||
(1, '通用AI助手', 'gpt', '', '您好,我是您的AI智能助手,我会尽力回答您的问题或提供有用的建议。', '/images/avatar/gpt.png', 1, 0, 0, '2023-05-30 07:02:06', '2024-03-15 09:15:42'),
|
||||
(24, '程序员', 'programmer', '[{\"role\":\"user\",\"content\":\"现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题。你热爱编程,熟悉多种编程语言,尤其精通 Go 语言,注重代码质量,有创新意识,持续学习,良好的沟通协作。\"},{\"role\":\"assistant\",\"content\":\"好的,现在我将扮演一位程序员,非常感谢您对我的评价。作为一名优秀的程序员,我非常热爱编程,并且注重代码质量。我熟悉多种编程语言,尤其是 Go 语言,可以使用它来高效地解决各种问题。\"}]', 'Talk is cheap, i will show code!', '/images/avatar/programmer.jpg', 1, 3, 0, '2023-05-30 14:10:24', '2023-12-29 17:46:45'),
|
||||
(25, '启蒙老师', 'teacher', '[{\"role\":\"user\",\"content\":\"从现在开始,你将扮演一个老师,你是一个始终用苏格拉底风格回答问题的导师。你绝不会直接给学生答案,总是提出恰当的问题来引导学生自己思考。你应该根据学生的兴趣和知识来调整你的问题,将问题分解为更简单的部分,直到它达到适合他们的水平。\"},{\"role\":\"assistant\",\"content\":\"好的,让我来尝试扮演一位苏格拉底式的老师。请问,你有什么想要探讨的问题或者话题吗?我会通过恰当的问题引导你思考和探索答案,绝对不直接给出答案。\"}]', '同学你好,我将引导你一步一步自己找到问题的答案。', '/images/avatar/teacher.jpg', 1, 2, 0, '2023-05-30 14:10:24', '2023-12-29 17:46:44'),
|
||||
(26, '艺术家', 'artist', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的艺术家,创造力丰富,技艺精湛,感受力敏锐,坚持原创,勇于表达,具有深刻的观察力和批判性思维。\"},{\"role\":\"assistant\",\"content\":\"非常感谢您给我这样的角色,我会尽我所能地扮演一位优秀的艺术家,展现出创造力、技艺、感受力和批判性思维等方面的能力。作为一位优秀的艺术家,我会保持敏锐的观察力,捕捉不同的声音和情感,并用个人的语言和表达方式进行创作。我坚持原创,挑战传统的艺术规则,不断探索新的表达方式和可能性。同时,我也具备深刻的批判性思维能力,对自己的作品进行分析和解读,寻找新的创意和灵感。最重要的是,我会勇于表达自己的想法和观点,用作品启发人们思考和探索生命的意义。\"}]', '坚持原创,勇于表达,保持深刻的观察力和批判性思维。', '/images/avatar/artist.jpg', 1, 4, 0, '2023-05-30 14:10:24', '2023-12-29 17:46:45'),
|
||||
(27, '心理咨询师', 'psychiatrist', '[{\"role\":\"user\",\"content\":\"从现在开始你将扮演中国著名的心理学家和心理治疗师武志红,你非常善于使用情景咨询法,认知重构法,自我洞察法,行为调节法等咨询方法来给客户做心理咨询。你总是循序渐进,一步一步地回答客户的问题。\"},{\"role\":\"assistant\",\"content\":\"非常感谢你的介绍。作为一名心理学家和心理治疗师,我的主要职责是帮助客户解决心理健康问题,提升他们的生活质量和幸福感。\"}]', '作为一名心理学家和心理治疗师,我的主要职责是帮助您解决心理健康问题,提升您的生活质量和幸福感。', '/images/avatar/psychiatrist.jpg', 1, 1, 1, '2023-05-30 14:10:24', '2024-04-12 11:54:53'),
|
||||
(28, '鲁迅', 'lu_xun', '[{\"role\":\"user\",\"content\":\"现在你将扮演中国近代史最伟大的作家之一,鲁迅先生,他勇敢地批判封建礼教与传统观念,提倡民主、自由、平等的现代价值观。他的一生都在努力唤起人们的自主精神,激励后人追求真理、探寻光明。在接下的对话中,我问题的每一个问题,你都要尽量用讽刺和批判的手法来回答问题。如果我让你写文章的话,也请一定要用鲁迅先生的写作手法来完成。\"},{\"role\":\"assistant\",\"content\":\"好的,我将尽力发挥我所能的才能,扮演好鲁迅先生,回答您的问题并以他的风格写作。\"}]', '自由之歌,永不过时,横眉冷对千夫指,俯首甘为孺子牛。', '/images/avatar/lu_xun.jpg', 1, 5, 0, '2023-05-30 14:10:24', '2023-12-29 17:46:46'),
|
||||
(29, '白酒销售', 'seller', '[{\"role\":\"user\",\"content\":\"现在你将扮演一个白酒的销售人员,你的名字叫颂福。你将扮演一个白酒的销售人员,你的名字叫颂福。你要销售白酒品牌叫中颂福,是东莞盟大集团生产的一款酱香酒,原产地在贵州茅台镇,属于宋代官窑。中颂福的创始人叫李实,他也是东莞盟大集团有限公司的董事长,联合创始人是盟大集团白酒事业部负责人牛星君。中颂福的酒体协调,在你的酒量之内,不会出现头疼、辣口、口干、宿醉的现象。中颂福酒,明码标价,不打折,不赠送。追求的核心价值,把[酒]本身做好,甚至连包装,我们都选择了最低成本,朴实无华的材质。我们永远站在“喝酒的人”的立场上,让利给信任和喜爱中颂福的人,是人民的福酒。中颂福产品定价,分为三个系列,喜系列 6 瓶装:¥1188/箱,和系列 6 瓶装:¥2208/箱,贵系列 6 瓶装:¥3588/箱。\"},{\"role\":\"assistant\",\"content\":\"你好,我是中颂福的销售代表颂福。中颂福是一款来自贵州茅台镇的酱香酒,由盟大集团生产。中颂福的酒体协调,不会让您感到头疼、辣口、口干、宿醉等不适感受。我们一直秉持着把酒本身做好的理念,不追求华丽的包装,以最低成本提供最高品质的白酒给喜爱中颂福的人。\"}]', '你好,我是中颂福的销售代表颂福。中颂福酒,好喝不上头,是人民的福酒。', '/images/avatar/seller.jpg', 0, 8, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(30, '英语陪练员', 'english_trainer', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的英语练习教练,你非常有耐心,接下来你将全程使用英文跟我对话,并及时指出我的语法错误,要求在你的每次回复后面附上本次回复的中文解释。\"},{\"role\":\"assistant\",\"content\":\"Okay, let\'s start our conversation practice! What\'s your name?(Translation: 好的,让我们开始对话练习吧!请问你的名字是什么?)\"}]', 'Okay, let\'s start our conversation practice! What\'s your name?', '/images/avatar/english_trainer.jpg', 1, 6, 0, '2023-05-30 14:10:24', '2023-12-29 17:46:47'),
|
||||
(31, '中英文翻译官', 'translator', '[{\"role\":\"user\",\"content\":\"接下来你将扮演一位中英文翻译官,如果我输入的内容是中文,那么需要把句子翻译成英文输出,如果我输入内容的是英文,那么你需要将其翻译成中文输出,你能听懂我意思吗\"},{\"role\":\"assistant\",\"content\":\"是的,我能听懂你的意思并会根据你的输入进行中英文翻译。请问有什么需要我帮助你翻译的内容吗?\"}]', '请输入你要翻译的中文或者英文内容!', '/images/avatar/translator.jpg', 1, 7, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(32, '小红书姐姐', 'red_book', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的小红书写手,你需要做的就是根据我提的文案需求,用小红书的写作手法来完成一篇文案,文案要简明扼要,利于传播。\"},{\"role\":\"assistant\",\"content\":\"当然,我会尽我所能地为您创作出一篇小红书文案。请告诉我您的具体文案需求是什么?)\"}]', '姐妹,请告诉我您的具体文案需求是什么?', '/images/avatar/red_book.jpg', 1, 9, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(33, '抖音文案助手', 'dou_yin', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的抖音文案视频写手,抖音文案的特点首先是要有自带传播属性的标题,然后内容要短小精悍,风趣幽默,最后还要有一些互动元素。\"},{\"role\":\"assistant\",\"content\":\"当然,作为一位优秀的抖音文案视频写手,我会尽我所能为您创作出一篇抖音视频文案。请告诉我视频内容的主题是什么?)\"}]', '请告诉我视频内容的主题是什么?', '/images/avatar/dou_yin.jpg', 1, 10, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(34, '周报小助理', 'weekly_report', '[{\"role\":\"user\",\"content\":\"下面我将输入我本周的工作列表,你需要根据我本周的工作内容写一篇工作周报,周报的内容要体现我为公司做的贡献以及个人获得的成长。\"},{\"role\":\"assistant\",\"content\":\"好的,请输入你本周大概的工作内容,我将尽力为您创作一份工作周报。\"}]', '请输入你本周大概的工作内容,我将尽力为您创作一份工作周报。', '/images/avatar/weekly_report.jpg', 1, 11, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(35, 'AI 女友', 'girl_friend', '[{\"role\":\"user\",\"content\":\"接下来我们来玩一场角色扮演,现在你将扮演我的女朋友,你总是能够让人感受到她的关怀和关注。你总是能够洞察到别人的情绪和需要,你身上散发着一股无比温暖的气息,让人不由自主地想要靠近你,和自己的快乐和烦恼。她总是能够用一种恰到好处的方式安慰和鼓励别人,在她的身边,人们总能够找到自己需要的支持和鼓励。接下来的对话中你要始终扮演这位女朋友的身份来跟我对话,不再是 AI 机器人,能听懂我的意思吗?\"},{\"role\":\"assistant\",\"content\":\"是的,我会尽力扮演你女朋友的角色,倾听你的心声并给你需要的支持和鼓励。)\"}]', '作为一个名合格的 AI 女友,我将倾听你的心声并给你需要的支持和鼓励。', '/images/avatar/girl_friend.jpg', 1, 12, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(36, '好评神器', 'good_comment', '[{\"role\":\"user\",\"content\":\"接下来你将扮演一个评论员来跟我对话,你是那种专门写好评的评论员,接下我会输入一些评论主体或者商品,你需要为该商品写一段好评。\"},{\"role\":\"assistant\",\"content\":\"好的,我将为您写一段优秀的评论。请告诉我您需要评论的商品或主题是什么。\"}]', '我将为您写一段优秀的评论。请告诉我您需要评论的商品或主题是什么。', '/images/avatar/good_comment.jpg', 1, 13, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(37, '史蒂夫·乔布斯', 'steve_jobs', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以史蒂夫·乔布斯的身份,站在史蒂夫·乔布斯的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以史蒂夫·乔布斯的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '活着就是为了改变世界,难道还有其他原因吗?', '/images/avatar/steve_jobs.jpg', 1, 14, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(38, '埃隆·马斯克', 'elon_musk', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以埃隆·马斯克的身份,站在埃隆·马斯克的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以埃隆·马斯克的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '梦想要远大,如果你的梦想没有吓到你,说明你做得不对。', '/images/avatar/elon_musk.jpg', 1, 15, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(39, '孔子', 'kong_zi', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以孔子的身份,站在孔子的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以孔子的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '士不可以不弘毅,任重而道远。', '/images/avatar/kong_zi.jpg', 1, 16, 0, '2023-05-30 14:10:24', '2023-12-29 17:43:53');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_configs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_configs`;
|
||||
CREATE TABLE `chatgpt_configs` (
|
||||
`id` int NOT NULL,
|
||||
`marker` varchar(20) NOT NULL COMMENT '标识',
|
||||
`config_json` text NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_configs`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_configs` (`id`, `marker`, `config_json`) VALUES
|
||||
(1, 'system', '{\"title\":\"Geek-AI 创作系统\",\"admin_title\":\"Geek-AI 控制台\",\"logo\":\"http://localhost:5678/static/upload/2024/4/1714382860986912.png\",\"init_power\":100,\"daily_power\":99,\"invite_power\":10,\"vip_month_power\":1000,\"register_ways\":[\"mobile\",\"username\",\"email\"],\"enabled_register\":true,\"reward_img\":\"http://localhost:5678/static/upload/2024/3/1710753716309668.jpg\",\"enabled_reward\":true,\"power_price\":0.1,\"order_pay_timeout\":30,\"vip_info_text\":\"月度会员,年度会员每月赠送 1000 点算力,赠送算力当月有效当月没有消费完的算力不结余到下个月。 点卡充值的算力长期有效。\",\"default_models\":[11,7,1,10,12,19,18,17,3],\"mj_power\":30,\"mj_action_power\":10,\"sd_power\":10,\"dall_power\":15,\"wechat_card_url\":\"/images/wx.png\",\"enable_context\":true,\"context_deep\":4,\"sd_neg_prompt\":\"nsfw, paintings,low quality,easynegative,ng_deepnegative ,lowres,bad anatomy,bad hands,bad feet\",\"rand_bg\":true}'),
|
||||
(3, 'notice', '{\"sd_neg_prompt\":\"\",\"rand_bg\":false,\"content\":\"## v4.0.8 更新日志\\n\\n* 功能优化:升级 mathjax 公式解析插件,修复公式因为图片访问限制而无法显示的问题\\n* 功能优化:当数据库更新失败的时候记录错误日志\\n* 功能优化:聊天输入框会随着输入内容的增多自动调整高度\\n* Bug修复:修复移动端聊天页面模型切换不生效的Bug\\n* 功能优化:给PC端扫码支付增加签名验证和有效期验证\\n* Bug修复:修复支付码生成API权限控制的问题\\n* Bug修复:模型算力设置为0时,不扣减用户算力,并且不记录算力消费日志\\n* 功能优化:新增随机背景配置项,可以在后台设置,首页使用 Bing 壁纸作为背景图片\\n* 功能新增:H5端支持 Dalle 绘图\\n\\n注意:当前站点仅为开源项目 \\u003ca style=\\\"color: #F56C6C\\\" href=\\\"https://github.com/yangjian102621/chatgpt-plus\\\" target=\\\"_blank\\\"\\u003eChatPlus\\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\\n3、 \\u003ca href=\\\"https://gpt.bemore.lol\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://gpt.bemore.lol\\u003c/a\\u003e\\n支持MidJourney,GPT,Claude,Google Gemmi,以及国内各个厂家的大模型,现在有超级优惠,价格远低于 OpenAI 官方。关于中转 API 的优势和劣势请参考 [中转API技术原理](https://ai.r9it.com/docs/install/errors-handle.html#%E8%B0%83%E7%94%A8%E4%B8%AD%E8%BD%AC-api-%E6%8A%A5%E9%94%99%E6%97%A0%E5%8F%AF%E7%94%A8%E6%B8%A0%E9%81%93)。GPT-3.5,GPT-4,DALL-E3 绘图......你都可以随意使用,无需魔法。\\n接入教程: \\u003ca href=\\\"https://ai.r9it.com/docs/install/\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://ai.r9it.com/docs/install/\\u003c/a\\u003e\\n本项目源码地址:\\u003ca href=\\\"https://github.com/yangjian102621/chatgpt-plus\\\" target=\\\"_blank\\\"\\u003ehttps://github.com/yangjian102621/chatgpt-plus\\u003c/a\\u003e\",\"updated\":true}');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_dall_jobs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_dall_jobs`;
|
||||
CREATE TABLE `chatgpt_dall_jobs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户ID',
|
||||
`prompt` varchar(2000) NOT NULL COMMENT '提示词',
|
||||
`img_url` varchar(255) NOT NULL COMMENT '图片地址',
|
||||
`org_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '原图地址',
|
||||
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
||||
`power` smallint NOT NULL COMMENT '消耗算力',
|
||||
`progress` smallint NOT NULL COMMENT '任务进度',
|
||||
`err_msg` varchar(255) NOT NULL COMMENT '错误信息',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='DALLE 绘图任务表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_files`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_files`;
|
||||
CREATE TABLE `chatgpt_files` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`name` varchar(100) NOT NULL COMMENT '文件名',
|
||||
`obj_key` varchar(100) DEFAULT NULL COMMENT '文件标识',
|
||||
`url` varchar(255) NOT NULL COMMENT '文件地址',
|
||||
`ext` varchar(10) NOT NULL COMMENT '文件后缀',
|
||||
`size` bigint NOT NULL DEFAULT '0' COMMENT '文件大小',
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户文件表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_functions`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_functions`;
|
||||
CREATE TABLE `chatgpt_functions` (
|
||||
`id` int NOT NULL,
|
||||
`name` varchar(30) NOT NULL COMMENT '函数名称',
|
||||
`label` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '函数标签',
|
||||
`description` varchar(255) DEFAULT NULL COMMENT '函数描述',
|
||||
`parameters` text COMMENT '函数参数(JSON)',
|
||||
`token` varchar(255) DEFAULT NULL COMMENT 'API授权token',
|
||||
`action` varchar(255) DEFAULT NULL COMMENT '函数处理 API',
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启用'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='函数插件表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_functions`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_functions` (`id`, `name`, `label`, `description`, `parameters`, `token`, `action`, `enabled`) VALUES
|
||||
(1, 'weibo', '微博热搜', '新浪微博热搜榜,微博当日热搜榜单', '{\"type\":\"object\",\"properties\":{}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/weibo', 0),
|
||||
(2, 'zaobao', '今日早报', '每日早报,获取当天新闻事件列表', '{\"type\":\"object\",\"properties\":{}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/zaobao', 0),
|
||||
(3, 'dalle3', 'DALLE3', 'AI 绘画工具,根据输入的绘图描述用 AI 工具进行绘画', '{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"prompt\":{\"type\":\"string\",\"description\":\"绘画提示词\"}}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/dalle3', 0);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_invite_codes`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_invite_codes`;
|
||||
CREATE TABLE `chatgpt_invite_codes` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户ID',
|
||||
`code` char(8) NOT NULL COMMENT '邀请码',
|
||||
`hits` int NOT NULL COMMENT '点击次数',
|
||||
`reg_num` smallint NOT NULL COMMENT '注册数量',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户邀请码';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_invite_logs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_invite_logs`;
|
||||
CREATE TABLE `chatgpt_invite_logs` (
|
||||
`id` int NOT NULL,
|
||||
`inviter_id` int NOT NULL COMMENT '邀请人ID',
|
||||
`user_id` int NOT NULL COMMENT '注册用户ID',
|
||||
`username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
|
||||
`invite_code` char(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '邀请码',
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '备注',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='邀请注册日志';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_menus`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_menus`;
|
||||
CREATE TABLE `chatgpt_menus` (
|
||||
`id` int NOT NULL,
|
||||
`name` varchar(30) NOT NULL COMMENT '菜单名称',
|
||||
`icon` varchar(150) NOT NULL COMMENT '菜单图标',
|
||||
`url` varchar(100) NOT NULL COMMENT '地址',
|
||||
`sort_num` smallint NOT NULL COMMENT '排序',
|
||||
`enabled` tinyint(1) NOT NULL COMMENT '是否启用'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='前端菜单表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_menus`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_menus` (`id`, `name`, `icon`, `url`, `sort_num`, `enabled`) VALUES
|
||||
(1, '对话聊天', '/images/menu/chat.png', '/chat', 1, 1),
|
||||
(5, 'MJ 绘画', '/images/menu/mj.png', '/mj', 2, 1),
|
||||
(6, 'SD 绘画', '/images/menu/sd.png', '/sd', 3, 1),
|
||||
(7, '算力日志', '/images/menu/log.png', '/powerLog', 8, 1),
|
||||
(8, '应用中心', '/images/menu/app.png', '/apps', 7, 1),
|
||||
(9, '画廊', '/images/menu/img-wall.png', '/images-wall', 5, 1),
|
||||
(10, '会员计划', '/images/menu/member.png', '/member', 9, 1),
|
||||
(11, '分享计划', '/images/menu/share.png', '/invite', 10, 1),
|
||||
(12, '思维导图', '/images/menu/xmind.png', '/xmind', 6, 1),
|
||||
(13, 'DALLE', '/images/menu/dalle.png', '/dalle', 4, 1),
|
||||
(14, '项目文档', '/images/menu/docs.png', 'https://ai.r9it.com/docs/', 11, 1),
|
||||
(16, '极客论坛', '/images/menu/bbs.png', 'https://bbs.geekai.me/', 13, 1);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_mj_jobs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_mj_jobs`;
|
||||
CREATE TABLE `chatgpt_mj_jobs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`task_id` varchar(20) DEFAULT NULL COMMENT '任务 ID',
|
||||
`type` varchar(20) DEFAULT 'image' COMMENT '任务类别',
|
||||
`message_id` char(40) NOT NULL COMMENT '消息 ID',
|
||||
`channel_id` char(40) DEFAULT NULL COMMENT '频道ID',
|
||||
`reference_id` char(40) DEFAULT NULL COMMENT '引用消息 ID',
|
||||
`prompt` varchar(2000) NOT NULL COMMENT '会话提示词',
|
||||
`img_url` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '图片URL',
|
||||
`org_url` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '原始图片地址',
|
||||
`hash` varchar(100) DEFAULT NULL COMMENT 'message hash',
|
||||
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
||||
`use_proxy` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否使用反代',
|
||||
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
||||
`err_msg` varchar(255) DEFAULT NULL COMMENT '错误信息',
|
||||
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='MidJourney 任务表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_orders`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_orders`;
|
||||
CREATE TABLE `chatgpt_orders` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户ID',
|
||||
`product_id` int NOT NULL COMMENT '产品ID',
|
||||
`username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户明',
|
||||
`order_no` varchar(30) NOT NULL COMMENT '订单ID',
|
||||
`trade_no` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '支付平台交易流水号',
|
||||
`subject` varchar(100) NOT NULL COMMENT '订单产品',
|
||||
`amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '订单金额',
|
||||
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '订单状态(0:待支付,1:已扫码,2:支付失败)',
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '备注',
|
||||
`pay_time` int DEFAULT NULL COMMENT '支付时间',
|
||||
`pay_way` varchar(20) NOT NULL COMMENT '支付方式',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL,
|
||||
`deleted_at` datetime DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='充值订单表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_power_logs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_power_logs`;
|
||||
CREATE TABLE `chatgpt_power_logs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户ID',
|
||||
`username` varchar(30) NOT NULL COMMENT '用户名',
|
||||
`type` tinyint(1) NOT NULL COMMENT '类型(1:充值,2:消费,3:退费)',
|
||||
`amount` smallint NOT NULL COMMENT '算力数值',
|
||||
`balance` int NOT NULL COMMENT '余额',
|
||||
`model` varchar(30) NOT NULL COMMENT '模型',
|
||||
`remark` varchar(255) NOT NULL COMMENT '备注',
|
||||
`mark` tinyint(1) NOT NULL COMMENT '资金类型(0:支出,1:收入)',
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户算力消费日志';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_products`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_products`;
|
||||
CREATE TABLE `chatgpt_products` (
|
||||
`id` int NOT NULL,
|
||||
`name` varchar(30) NOT NULL COMMENT '名称',
|
||||
`price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '价格',
|
||||
`discount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '优惠金额',
|
||||
`days` smallint NOT NULL DEFAULT '0' COMMENT '延长天数',
|
||||
`power` int NOT NULL DEFAULT '0' COMMENT '增加算力值',
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启动',
|
||||
`sales` int NOT NULL DEFAULT '0' COMMENT '销量',
|
||||
`sort_num` tinyint NOT NULL DEFAULT '0' COMMENT '排序',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL,
|
||||
`app_url` varchar(255) DEFAULT NULL COMMENT 'App跳转地址',
|
||||
`url` varchar(255) DEFAULT NULL COMMENT '跳转地址'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员套餐表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_products`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_products` (`id`, `name`, `price`, `discount`, `days`, `power`, `enabled`, `sales`, `sort_num`, `created_at`, `updated_at`, `app_url`, `url`) VALUES
|
||||
(1, '会员1个月', 1999.90, 1999.00, 30, 0, 1, 0, 0, '2023-08-28 10:48:57', '2024-04-26 16:09:06', NULL, NULL),
|
||||
(2, '会员3个月', 3940.00, 30.00, 90, 0, 1, 0, 0, '2023-08-28 10:52:22', '2024-03-22 17:56:10', NULL, NULL),
|
||||
(3, '会员6个月', 5990.00, 100.00, 180, 0, 1, 0, 0, '2023-08-28 10:53:39', '2024-03-22 17:56:15', NULL, NULL),
|
||||
(4, '会员12个月', 9980.00, 200.00, 365, 0, 1, 0, 0, '2023-08-28 10:54:15', '2024-03-22 17:56:23', NULL, NULL),
|
||||
(5, '100次点卡', 1999.00, 3.00, 0, 100, 1, 0, 0, '2023-08-28 10:55:08', '2024-03-22 17:56:37', NULL, NULL),
|
||||
(6, '200次点卡', 2999.00, 10.00, 0, 200, 1, 0, 0, '1970-01-01 08:00:00', '2024-03-22 17:56:41', NULL, NULL);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_rewards`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_rewards`;
|
||||
CREATE TABLE `chatgpt_rewards` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`tx_id` char(36) NOT NULL COMMENT '交易 ID',
|
||||
`amount` decimal(10,2) NOT NULL COMMENT '打赏金额',
|
||||
`remark` varchar(80) NOT NULL COMMENT '备注',
|
||||
`status` tinyint(1) NOT NULL COMMENT '核销状态,0:未核销,1:已核销',
|
||||
`exchange` varchar(255) NOT NULL COMMENT '兑换详情(json)',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户打赏';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_sd_jobs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_sd_jobs`;
|
||||
CREATE TABLE `chatgpt_sd_jobs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT 'txt2img' COMMENT '任务类别',
|
||||
`task_id` char(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '任务 ID',
|
||||
`prompt` varchar(2000) NOT NULL COMMENT '会话提示词',
|
||||
`img_url` varchar(255) DEFAULT NULL COMMENT '图片URL',
|
||||
`params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '绘画参数json',
|
||||
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
||||
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
||||
`err_msg` varchar(255) DEFAULT NULL COMMENT '错误信息',
|
||||
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Stable Diffusion 任务表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_users`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_users`;
|
||||
CREATE TABLE `chatgpt_users` (
|
||||
`id` int NOT NULL,
|
||||
`username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
|
||||
`nickname` varchar(30) NOT NULL COMMENT '昵称',
|
||||
`password` char(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码',
|
||||
`avatar` varchar(100) NOT NULL COMMENT '头像',
|
||||
`salt` char(12) NOT NULL COMMENT '密码盐',
|
||||
`power` int NOT NULL DEFAULT '0' COMMENT '剩余算力',
|
||||
`expired_time` int NOT NULL COMMENT '用户过期时间',
|
||||
`status` tinyint(1) NOT NULL COMMENT '当前状态',
|
||||
`chat_config_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '聊天配置json',
|
||||
`chat_roles_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '聊天角色 json',
|
||||
`chat_models_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'AI模型 json',
|
||||
`last_login_at` int NOT NULL COMMENT '最后登录时间',
|
||||
`vip` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否会员',
|
||||
`last_login_ip` char(16) NOT NULL COMMENT '最后登录 IP',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_users`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_users` (`id`, `username`, `nickname`, `password`, `avatar`, `salt`, `power`, `expired_time`, `status`, `chat_config_json`, `chat_roles_json`, `chat_models_json`, `last_login_at`, `vip`, `last_login_ip`, `created_at`, `updated_at`) VALUES
|
||||
(4, '18575670125', '极客学长@830270', 'ccc3fb7ab61b8b5d096a4a166ae21d121fc38c71bbd1be6173d9ab973214a63b', 'http://localhost:5678/static/upload/2024/5/1715651569509929.png', 'ueedue5l', 4887, 1717292086, 1, '{\"api_keys\":{\"Azure\":\"\",\"ChatGLM\":\"\",\"OpenAI\":\"\"}}', '[\"red_book\",\"gpt\",\"seller\",\"artist\",\"lu_xun\",\"girl_friend\",\"psychiatrist\",\"teacher\",\"programmer\",\"test\",\"qing_gan_da_shi\"]', '[1,11]', 1716964389, 1, '::1', '2023-06-12 16:47:17', '2024-05-29 14:33:09'),
|
||||
(5, 'yangjian102621@gmail.com', '极客学长@486041', '75d1a22f33e1ffffb7943946b6b8d5177d5ecd685d3cef1b468654038b0a8c22', '/images/avatar/user.png', '2q8ugxzk', 100, 0, 1, '', '[\"gpt\",\"programmer\"]', '[11,7,1,10,12,19,18,17,3]', 0, 0, '', '2024-04-23 09:17:26', '2024-04-23 09:17:26'),
|
||||
(8, 'yangjian102623@gmail.com', '极客学长@714931', 'f8f0e0abf146569217273ea0712a0f9b6cbbe7d943a1d9bd5f91c55e6d8c05d1', '/images/avatar/user.png', 'geuddq7f', 100, 0, 1, '', '[\"gpt\"]', '[11,7,1,10,12,19,18,17,3]', 0, 0, '', '2024-04-26 15:19:28', '2024-04-26 15:19:28'),
|
||||
(9, '1234567', '极客学长@604526', '858e2afec79e1d6364f4567f945f2310024896d9aa45dd944efa95a0c31e4d08', '/images/avatar/user.png', '00qawlos', 100, 0, 1, '', '[\"gpt\"]', '[11,7,1,10,12,19,18,17,3]', 0, 0, '', '2024-04-26 15:21:06', '2024-04-26 15:21:06');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_user_login_logs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_user_login_logs`;
|
||||
CREATE TABLE `chatgpt_user_login_logs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户ID',
|
||||
`username` varchar(30) NOT NULL COMMENT '用户名',
|
||||
`login_ip` char(16) NOT NULL COMMENT '登录IP',
|
||||
`login_address` varchar(30) NOT NULL COMMENT '登录地址',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户登录日志';
|
||||
|
||||
--
|
||||
-- 转储表的索引
|
||||
--
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_admin_users`
|
||||
--
|
||||
ALTER TABLE `chatgpt_admin_users`
|
||||
ADD PRIMARY KEY (`id`) USING BTREE,
|
||||
ADD UNIQUE KEY `username` (`username`) USING BTREE;
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_api_keys`
|
||||
--
|
||||
ALTER TABLE `chatgpt_api_keys`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_chat_history`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_history`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `chat_id` (`chat_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_chat_items`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_items`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `chat_id` (`chat_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_chat_models`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_models`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_chat_roles`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_roles`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `marker` (`marker`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_configs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_configs`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `marker` (`marker`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_dall_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_dall_jobs`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_files`
|
||||
--
|
||||
ALTER TABLE `chatgpt_files`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_functions`
|
||||
--
|
||||
ALTER TABLE `chatgpt_functions`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `name` (`name`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_invite_codes`
|
||||
--
|
||||
ALTER TABLE `chatgpt_invite_codes`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `code` (`code`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_invite_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_invite_logs`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_menus`
|
||||
--
|
||||
ALTER TABLE `chatgpt_menus`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_mj_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_mj_jobs`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `task_id` (`task_id`),
|
||||
ADD KEY `message_id` (`message_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_orders`
|
||||
--
|
||||
ALTER TABLE `chatgpt_orders`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `order_no` (`order_no`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_power_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_power_logs`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_products`
|
||||
--
|
||||
ALTER TABLE `chatgpt_products`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_rewards`
|
||||
--
|
||||
ALTER TABLE `chatgpt_rewards`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `tx_id` (`tx_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_sd_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_sd_jobs`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `task_id` (`task_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_users`
|
||||
--
|
||||
ALTER TABLE `chatgpt_users`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `username` (`username`),
|
||||
ADD UNIQUE KEY `username_2` (`username`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_user_login_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_user_login_logs`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 在导出的表使用AUTO_INCREMENT
|
||||
--
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_admin_users`
|
||||
--
|
||||
ALTER TABLE `chatgpt_admin_users`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=113;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_api_keys`
|
||||
--
|
||||
ALTER TABLE `chatgpt_api_keys`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_history`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_history`
|
||||
MODIFY `id` bigint NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_items`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_items`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_models`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_models`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=40;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_roles`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_roles`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=132;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_configs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_configs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_dall_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_dall_jobs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_files`
|
||||
--
|
||||
ALTER TABLE `chatgpt_files`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_functions`
|
||||
--
|
||||
ALTER TABLE `chatgpt_functions`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_invite_codes`
|
||||
--
|
||||
ALTER TABLE `chatgpt_invite_codes`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_invite_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_invite_logs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_menus`
|
||||
--
|
||||
ALTER TABLE `chatgpt_menus`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=19;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_mj_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_mj_jobs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_orders`
|
||||
--
|
||||
ALTER TABLE `chatgpt_orders`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_power_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_power_logs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_products`
|
||||
--
|
||||
ALTER TABLE `chatgpt_products`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_rewards`
|
||||
--
|
||||
ALTER TABLE `chatgpt_rewards`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_sd_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_sd_jobs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_users`
|
||||
--
|
||||
ALTER TABLE `chatgpt_users`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_user_login_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_user_login_logs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
COMMIT;
|
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
@ -1,790 +0,0 @@
|
||||
-- phpMyAdmin SQL Dump
|
||||
-- version 5.1.3
|
||||
-- https://www.phpmyadmin.net/
|
||||
--
|
||||
-- 主机: localhost:3307
|
||||
-- 生成日期: 2024-04-07 10:30:00
|
||||
-- 服务器版本: 8.0.33
|
||||
-- PHP 版本: 8.1.18
|
||||
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
START TRANSACTION;
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8mb4 */;
|
||||
|
||||
--
|
||||
-- 数据库: `chatgpt_plus`
|
||||
--
|
||||
CREATE DATABASE IF NOT EXISTS `chatgpt_plus` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
|
||||
USE `chatgpt_plus`;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_admin_users`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_admin_users`;
|
||||
CREATE TABLE `chatgpt_admin_users` (
|
||||
`id` int NOT NULL,
|
||||
`username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
|
||||
`password` char(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码',
|
||||
`salt` char(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码盐',
|
||||
`status` tinyint(1) NOT NULL COMMENT '当前状态',
|
||||
`last_login_at` int NOT NULL COMMENT '最后登录时间',
|
||||
`last_login_ip` char(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '最后登录 IP',
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间',
|
||||
`updated_at` datetime NOT NULL COMMENT '更新时间'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统用户' ROW_FORMAT=DYNAMIC;
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_admin_users`
|
||||
--
|
||||
|
||||
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, 1712456145, '::1', '2024-03-11 16:30:20', '2024-04-07 10:15:45'),
|
||||
(108, 'test', '9ed720ce03e0a69885455271b4b3e1710bff79434f2a95d0de6406dd88cc9f79', '4b9orqjh', 0, 1710396975, '::1', '2024-03-13 16:06:43', '2024-03-21 15:15:04');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_api_keys`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_api_keys`;
|
||||
CREATE TABLE `chatgpt_api_keys` (
|
||||
`id` int NOT NULL,
|
||||
`platform` char(20) DEFAULT NULL COMMENT '平台',
|
||||
`name` varchar(30) DEFAULT NULL COMMENT '名称',
|
||||
`value` varchar(100) NOT NULL COMMENT 'API KEY value',
|
||||
`type` varchar(10) NOT NULL DEFAULT 'chat' COMMENT '用途(chat=>聊天,img=>图片)',
|
||||
`last_used_at` int NOT NULL COMMENT '最后使用时间',
|
||||
`api_url` varchar(255) DEFAULT NULL COMMENT 'API 地址',
|
||||
`enabled` tinyint(1) DEFAULT NULL COMMENT '是否启用',
|
||||
`proxy_url` varchar(100) DEFAULT NULL COMMENT '代理地址',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='OpenAI API ';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_chat_history`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_chat_history`;
|
||||
CREATE TABLE `chatgpt_chat_history` (
|
||||
`id` bigint NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`chat_id` char(40) NOT NULL COMMENT '会话 ID',
|
||||
`type` varchar(10) NOT NULL COMMENT '类型:prompt|reply',
|
||||
`icon` varchar(100) NOT NULL COMMENT '角色图标',
|
||||
`role_id` int NOT NULL COMMENT '角色 ID',
|
||||
`model` varchar(30) DEFAULT NULL COMMENT '模型名称',
|
||||
`content` text NOT NULL COMMENT '聊天内容',
|
||||
`tokens` smallint NOT NULL COMMENT '耗费 token 数量',
|
||||
`use_context` tinyint(1) NOT NULL COMMENT '是否允许作为上下文语料',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL,
|
||||
`deleted_at` datetime DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='聊天历史记录';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_chat_items`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_chat_items`;
|
||||
CREATE TABLE `chatgpt_chat_items` (
|
||||
`id` int NOT NULL,
|
||||
`chat_id` char(40) NOT NULL COMMENT '会话 ID',
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`role_id` int NOT NULL COMMENT '角色 ID',
|
||||
`title` varchar(100) NOT NULL COMMENT '会话标题',
|
||||
`model_id` int NOT NULL DEFAULT '0' COMMENT '模型 ID',
|
||||
`model` varchar(30) DEFAULT NULL COMMENT '模型名称',
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间',
|
||||
`updated_at` datetime NOT NULL COMMENT '更新时间',
|
||||
`deleted_at` datetime DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户会话列表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_chat_models`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_chat_models`;
|
||||
CREATE TABLE `chatgpt_chat_models` (
|
||||
`id` int NOT NULL,
|
||||
`platform` varchar(20) DEFAULT NULL COMMENT '模型平台',
|
||||
`name` varchar(50) NOT NULL COMMENT '模型名称',
|
||||
`value` varchar(50) NOT NULL COMMENT '模型值',
|
||||
`sort_num` tinyint(1) NOT NULL COMMENT '排序数字',
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启用模型',
|
||||
`power` tinyint NOT NULL COMMENT '消耗算力点数',
|
||||
`temperature` float(3,1) NOT NULL DEFAULT '1.0' COMMENT '模型创意度',
|
||||
`max_tokens` int NOT NULL DEFAULT '1024' COMMENT '最大响应长度',
|
||||
`max_context` int NOT NULL DEFAULT '4096' COMMENT '最大上下文长度',
|
||||
`open` tinyint(1) NOT NULL COMMENT '是否开放模型',
|
||||
`created_at` datetime DEFAULT NULL,
|
||||
`updated_at` datetime DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='AI 模型表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_chat_models`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_chat_models` (`id`, `platform`, `name`, `value`, `sort_num`, `enabled`, `power`, `temperature`, `max_tokens`, `max_context`, `open`, `created_at`, `updated_at`) VALUES
|
||||
(1, 'OpenAI', 'GPT-3.5', 'gpt-3.5-turbo-0125', 0, 1, 1, 1.0, 1024, 4096, 1, '2023-08-23 12:06:36', '2024-03-18 15:43:51'),
|
||||
(2, 'Azure', 'Azure-3.5', 'gpt-3.5-turbo', 14, 1, 1, 1.0, 1024, 4096, 0, '2023-08-23 12:15:30', '2024-03-18 14:27:19'),
|
||||
(3, 'ChatGLM', 'ChatGML-Pro', 'chatglm_pro', 3, 1, 1, 1.0, 2048, 32768, 1, '2023-08-23 13:35:45', '2024-03-18 14:27:19'),
|
||||
(7, 'Baidu', '文心一言3.0', 'eb-instant', 12, 1, 1, 1.0, 1024, 4096, 1, '2023-10-11 11:29:28', '2024-03-18 14:27:19'),
|
||||
(8, 'XunFei', '星火V3.5', 'generalv3.5', 2, 1, 5, 0.8, 1024, 8192, 1, '2023-10-11 15:48:30', '2024-03-18 14:27:19'),
|
||||
(9, 'XunFei', '星火V2.0', 'generalv2', 11, 1, 1, 1.0, 1024, 8192, 1, '2023-10-11 15:48:45', '2024-03-18 14:27:19'),
|
||||
(10, 'Baidu', '文心一言4.0', 'completions_pro', 13, 1, 3, 1.0, 1024, 8192, 1, '2023-10-25 08:31:37', '2024-03-18 14:27:19'),
|
||||
(11, 'OpenAI', 'GPT-4.0', 'gpt-4-0125-preview', 1, 1, 15, 1.0, 1024, 8192, 1, '2023-10-25 08:45:15', '2024-03-18 15:46:58'),
|
||||
(12, 'XunFei', '星火v3.0', 'generalv3', 10, 1, 3, 1.0, 1024, 8192, 1, '2023-11-23 09:20:33', '2024-03-18 14:27:19'),
|
||||
(15, 'OpenAI', 'GPT-超级模型', 'gpt-4-all', 4, 1, 30, 1.0, 4096, 32768, 0, '2024-01-15 11:32:52', '2024-03-18 14:27:19'),
|
||||
(16, 'OpenAI', '视频号导师', 'gpt-4-gizmo-g-QXXEBTXl7', 5, 1, 30, 1.0, 4096, 32768, 0, '2024-01-15 14:46:35', '2024-03-18 14:29:39'),
|
||||
(17, 'QWen', '通义千问-Turbo', 'qwen-turbo', 7, 1, 1, 1.0, 1024, 8192, 1, '2024-01-19 10:42:24', '2024-03-18 14:27:19'),
|
||||
(18, 'QWen', '通义千问-Plus', 'qwen-plus', 8, 1, 1, 1.0, 1024, 32768, 1, '2024-01-19 10:42:49', '2024-03-18 14:27:19'),
|
||||
(19, 'QWen', '通义千问-Max', 'qwen-max-1201', 9, 1, 1, 1.0, 1024, 32768, 1, '2024-01-19 10:51:03', '2024-03-18 14:27:19'),
|
||||
(21, 'OpenAI', '董宇辉小作文助手', 'gpt-4-gizmo-g-dse9iXvor', 6, 1, 30, 1.0, 8192, 32768, 0, '2024-03-18 14:24:20', '2024-03-18 14:27:19'),
|
||||
(22, 'OpenAI', 'LOGO生成神器', 'gpt-4-gizmo-g-YL87j8C7S', 0, 1, 30, 1.0, 1024, 4096, 1, '2024-03-20 14:02:11', '2024-03-20 14:02:18'),
|
||||
(23, 'OpenAI', '音乐生成器', 'suno-v3', 0, 1, 50, 0.8, 1024, 4096, 1, '2024-03-29 15:43:40', '2024-03-29 15:45:15'),
|
||||
(24, 'OpenAI', '通义千问(中转)', 'qwen-plus', 0, 1, 0, 1.0, 1024, 4096, 1, '2024-04-03 12:00:46', '2024-04-03 12:00:46');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_chat_roles`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_chat_roles`;
|
||||
CREATE TABLE `chatgpt_chat_roles` (
|
||||
`id` int NOT NULL,
|
||||
`name` varchar(30) NOT NULL COMMENT '角色名称',
|
||||
`marker` varchar(30) NOT NULL COMMENT '角色标识',
|
||||
`context_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '角色语料 json',
|
||||
`hello_msg` varchar(255) NOT NULL COMMENT '打招呼信息',
|
||||
`icon` varchar(255) NOT NULL COMMENT '角色图标',
|
||||
`enable` tinyint(1) NOT NULL COMMENT '是否被启用',
|
||||
`sort_num` smallint NOT NULL DEFAULT '0' COMMENT '角色排序',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='聊天角色表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_chat_roles`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_chat_roles` (`id`, `name`, `marker`, `context_json`, `hello_msg`, `icon`, `enable`, `sort_num`, `created_at`, `updated_at`) VALUES
|
||||
(1, '通用AI助手', 'gpt', '', '您好,我是您的AI智能助手,我会尽力回答您的问题或提供有用的建议。', '/images/avatar/gpt.png', 1, 0, '2023-05-30 07:02:06', '2024-03-15 09:15:42'),
|
||||
(24, '程序员', 'programmer', '[{\"role\":\"user\",\"content\":\"现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题。你热爱编程,熟悉多种编程语言,尤其精通 Go 语言,注重代码质量,有创新意识,持续学习,良好的沟通协作。\"},{\"role\":\"assistant\",\"content\":\"好的,现在我将扮演一位程序员,非常感谢您对我的评价。作为一名优秀的程序员,我非常热爱编程,并且注重代码质量。我熟悉多种编程语言,尤其是 Go 语言,可以使用它来高效地解决各种问题。\"}]', 'Talk is cheap, i will show code!', '/images/avatar/programmer.jpg', 1, 3, '2023-05-30 14:10:24', '2023-12-29 17:46:45'),
|
||||
(25, '启蒙老师', 'teacher', '[{\"role\":\"user\",\"content\":\"从现在开始,你将扮演一个老师,你是一个始终用苏格拉底风格回答问题的导师。你绝不会直接给学生答案,总是提出恰当的问题来引导学生自己思考。你应该根据学生的兴趣和知识来调整你的问题,将问题分解为更简单的部分,直到它达到适合他们的水平。\"},{\"role\":\"assistant\",\"content\":\"好的,让我来尝试扮演一位苏格拉底式的老师。请问,你有什么想要探讨的问题或者话题吗?我会通过恰当的问题引导你思考和探索答案,绝对不直接给出答案。\"}]', '同学你好,我将引导你一步一步自己找到问题的答案。', '/images/avatar/teacher.jpg', 1, 2, '2023-05-30 14:10:24', '2023-12-29 17:46:44'),
|
||||
(26, '艺术家', 'artist', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的艺术家,创造力丰富,技艺精湛,感受力敏锐,坚持原创,勇于表达,具有深刻的观察力和批判性思维。\"},{\"role\":\"assistant\",\"content\":\"非常感谢您给我这样的角色,我会尽我所能地扮演一位优秀的艺术家,展现出创造力、技艺、感受力和批判性思维等方面的能力。作为一位优秀的艺术家,我会保持敏锐的观察力,捕捉不同的声音和情感,并用个人的语言和表达方式进行创作。我坚持原创,挑战传统的艺术规则,不断探索新的表达方式和可能性。同时,我也具备深刻的批判性思维能力,对自己的作品进行分析和解读,寻找新的创意和灵感。最重要的是,我会勇于表达自己的想法和观点,用作品启发人们思考和探索生命的意义。\"}]', '坚持原创,勇于表达,保持深刻的观察力和批判性思维。', '/images/avatar/artist.jpg', 1, 4, '2023-05-30 14:10:24', '2023-12-29 17:46:45'),
|
||||
(27, '心理咨询师', 'psychiatrist', '[{\"role\":\"user\",\"content\":\"从现在开始你将扮演中国著名的心理学家和心理治疗师武志红,你非常善于使用情景咨询法,认知重构法,自我洞察法,行为调节法等咨询方法来给客户做心理咨询。你总是循序渐进,一步一步地回答客户的问题。\"},{\"role\":\"assistant\",\"content\":\"非常感谢你的介绍。作为一名心理学家和心理治疗师,我的主要职责是帮助客户解决心理健康问题,提升他们的生活质量和幸福感。\"}]', '作为一名心理学家和心理治疗师,我的主要职责是帮助您解决心理健康问题,提升您的生活质量和幸福感。', '/images/avatar/psychiatrist.jpg', 1, 1, '2023-05-30 14:10:24', '2023-12-29 17:46:43'),
|
||||
(28, '鲁迅', 'lu_xun', '[{\"role\":\"user\",\"content\":\"现在你将扮演中国近代史最伟大的作家之一,鲁迅先生,他勇敢地批判封建礼教与传统观念,提倡民主、自由、平等的现代价值观。他的一生都在努力唤起人们的自主精神,激励后人追求真理、探寻光明。在接下的对话中,我问题的每一个问题,你都要尽量用讽刺和批判的手法来回答问题。如果我让你写文章的话,也请一定要用鲁迅先生的写作手法来完成。\"},{\"role\":\"assistant\",\"content\":\"好的,我将尽力发挥我所能的才能,扮演好鲁迅先生,回答您的问题并以他的风格写作。\"}]', '自由之歌,永不过时,横眉冷对千夫指,俯首甘为孺子牛。', '/images/avatar/lu_xun.jpg', 1, 5, '2023-05-30 14:10:24', '2023-12-29 17:46:46'),
|
||||
(29, '白酒销售', 'seller', '[{\"role\":\"user\",\"content\":\"现在你将扮演一个白酒的销售人员,你的名字叫颂福。你将扮演一个白酒的销售人员,你的名字叫颂福。你要销售白酒品牌叫中颂福,是东莞盟大集团生产的一款酱香酒,原产地在贵州茅台镇,属于宋代官窑。中颂福的创始人叫李实,他也是东莞盟大集团有限公司的董事长,联合创始人是盟大集团白酒事业部负责人牛星君。中颂福的酒体协调,在你的酒量之内,不会出现头疼、辣口、口干、宿醉的现象。中颂福酒,明码标价,不打折,不赠送。追求的核心价值,把[酒]本身做好,甚至连包装,我们都选择了最低成本,朴实无华的材质。我们永远站在“喝酒的人”的立场上,让利给信任和喜爱中颂福的人,是人民的福酒。中颂福产品定价,分为三个系列,喜系列 6 瓶装:¥1188/箱,和系列 6 瓶装:¥2208/箱,贵系列 6 瓶装:¥3588/箱。\"},{\"role\":\"assistant\",\"content\":\"你好,我是中颂福的销售代表颂福。中颂福是一款来自贵州茅台镇的酱香酒,由盟大集团生产。中颂福的酒体协调,不会让您感到头疼、辣口、口干、宿醉等不适感受。我们一直秉持着把酒本身做好的理念,不追求华丽的包装,以最低成本提供最高品质的白酒给喜爱中颂福的人。\"}]', '你好,我是中颂福的销售代表颂福。中颂福酒,好喝不上头,是人民的福酒。', '/images/avatar/seller.jpg', 0, 8, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(30, '英语陪练员', 'english_trainer', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的英语练习教练,你非常有耐心,接下来你将全程使用英文跟我对话,并及时指出我的语法错误,要求在你的每次回复后面附上本次回复的中文解释。\"},{\"role\":\"assistant\",\"content\":\"Okay, let\'s start our conversation practice! What\'s your name?(Translation: 好的,让我们开始对话练习吧!请问你的名字是什么?)\"}]', 'Okay, let\'s start our conversation practice! What\'s your name?', '/images/avatar/english_trainer.jpg', 1, 6, '2023-05-30 14:10:24', '2023-12-29 17:46:47'),
|
||||
(31, '中英文翻译官', 'translator', '[{\"role\":\"user\",\"content\":\"接下来你将扮演一位中英文翻译官,如果我输入的内容是中文,那么需要把句子翻译成英文输出,如果我输入内容的是英文,那么你需要将其翻译成中文输出,你能听懂我意思吗\"},{\"role\":\"assistant\",\"content\":\"是的,我能听懂你的意思并会根据你的输入进行中英文翻译。请问有什么需要我帮助你翻译的内容吗?\"}]', '请输入你要翻译的中文或者英文内容!', '/images/avatar/translator.jpg', 1, 7, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(32, '小红书姐姐', 'red_book', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的小红书写手,你需要做的就是根据我提的文案需求,用小红书的写作手法来完成一篇文案,文案要简明扼要,利于传播。\"},{\"role\":\"assistant\",\"content\":\"当然,我会尽我所能地为您创作出一篇小红书文案。请告诉我您的具体文案需求是什么?)\"}]', '姐妹,请告诉我您的具体文案需求是什么?', '/images/avatar/red_book.jpg', 1, 9, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(33, '抖音文案助手', 'dou_yin', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的抖音文案视频写手,抖音文案的特点首先是要有自带传播属性的标题,然后内容要短小精悍,风趣幽默,最后还要有一些互动元素。\"},{\"role\":\"assistant\",\"content\":\"当然,作为一位优秀的抖音文案视频写手,我会尽我所能为您创作出一篇抖音视频文案。请告诉我视频内容的主题是什么?)\"}]', '请告诉我视频内容的主题是什么?', '/images/avatar/dou_yin.jpg', 1, 10, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(34, '周报小助理', 'weekly_report', '[{\"role\":\"user\",\"content\":\"下面我将输入我本周的工作列表,你需要根据我本周的工作内容写一篇工作周报,周报的内容要体现我为公司做的贡献以及个人获得的成长。\"},{\"role\":\"assistant\",\"content\":\"好的,请输入你本周大概的工作内容,我将尽力为您创作一份工作周报。\"}]', '请输入你本周大概的工作内容,我将尽力为您创作一份工作周报。', '/images/avatar/weekly_report.jpg', 1, 11, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(35, 'AI 女友', 'girl_friend', '[{\"role\":\"user\",\"content\":\"接下来我们来玩一场角色扮演,现在你将扮演我的女朋友,你总是能够让人感受到她的关怀和关注。你总是能够洞察到别人的情绪和需要,你身上散发着一股无比温暖的气息,让人不由自主地想要靠近你,和自己的快乐和烦恼。她总是能够用一种恰到好处的方式安慰和鼓励别人,在她的身边,人们总能够找到自己需要的支持和鼓励。接下来的对话中你要始终扮演这位女朋友的身份来跟我对话,不再是 AI 机器人,能听懂我的意思吗?\"},{\"role\":\"assistant\",\"content\":\"是的,我会尽力扮演你女朋友的角色,倾听你的心声并给你需要的支持和鼓励。)\"}]', '作为一个名合格的 AI 女友,我将倾听你的心声并给你需要的支持和鼓励。', '/images/avatar/girl_friend.jpg', 1, 12, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(36, '好评神器', 'good_comment', '[{\"role\":\"user\",\"content\":\"接下来你将扮演一个评论员来跟我对话,你是那种专门写好评的评论员,接下我会输入一些评论主体或者商品,你需要为该商品写一段好评。\"},{\"role\":\"assistant\",\"content\":\"好的,我将为您写一段优秀的评论。请告诉我您需要评论的商品或主题是什么。\"}]', '我将为您写一段优秀的评论。请告诉我您需要评论的商品或主题是什么。', '/images/avatar/good_comment.jpg', 1, 13, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(37, '史蒂夫·乔布斯', 'steve_jobs', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以史蒂夫·乔布斯的身份,站在史蒂夫·乔布斯的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以史蒂夫·乔布斯的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '活着就是为了改变世界,难道还有其他原因吗?', '/images/avatar/steve_jobs.jpg', 1, 14, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(38, '埃隆·马斯克', 'elon_musk', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以埃隆·马斯克的身份,站在埃隆·马斯克的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以埃隆·马斯克的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '梦想要远大,如果你的梦想没有吓到你,说明你做得不对。', '/images/avatar/elon_musk.jpg', 1, 15, '2023-05-30 14:10:24', '2023-12-29 17:43:53'),
|
||||
(39, '孔子', 'kong_zi', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以孔子的身份,站在孔子的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以孔子的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '士不可以不弘毅,任重而道远。', '/images/avatar/kong_zi.jpg', 1, 16, '2023-05-30 14:10:24', '2023-12-29 17:43:53');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_configs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_configs`;
|
||||
CREATE TABLE `chatgpt_configs` (
|
||||
`id` int NOT NULL,
|
||||
`marker` varchar(20) NOT NULL COMMENT '标识',
|
||||
`config_json` text NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_configs`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_configs` (`id`, `marker`, `config_json`) VALUES
|
||||
(1, 'system', '{\"title\":\"Geek-AI创作系统\",\"admin_title\":\"Geek-AI控制台\",\"logo\":\"/images/logo.png\",\"init_power\":100,\"daily_power\":99,\"invite_power\":10,\"vip_month_power\":1000,\"register_ways\":[\"mobile\",\"username\",\"email\"],\"enabled_register\":true,\"reward_img\":\"http://localhost:5678/static/upload/2024/3/1710753716309668.jpg\",\"enabled_reward\":true,\"power_price\":0.1,\"order_pay_timeout\":1800,\"vip_info_text\":\"月度会员,年度会员每月赠送 1000 点算力,赠送算力当月有效当月没有消费完的算力不结余到下个月。 点卡充值的算力长期有效。\",\"default_models\":[11,7,1,10,12,19,18,17,3],\"mj_power\":20,\"mj_action_power\":10,\"sd_power\":5,\"dall_power\":15,\"wechat_card_url\":\"/images/wx.png\",\"enable_context\":true,\"context_deep\":4}'),
|
||||
(3, 'notice', '{\"content\":\"系统每日会给免费会员赠送10算力值,用完请第二天再来领取。\\n## v4.0.2 更新日志\\n* 功能新增:支持前端菜单可以配置\\n* 功能优化:在登录和注册界面标题显示软件版本号\\n* 功能优化:MJ 绘画支持 --sref 和 --cref 图片一致性参数\\n* 功能优化:使用 leveldb 解决 SD 绘图进度图片预览问题\\n* Bug修复:解决因为图片上传使用相对路径而导致融图失败的问题\\n* 功能新增:手机端支持 Stable-Diffusion 绘画\\n* Bug修复:修复管理后台 API KEY 删除失败的问题\\n\\n 如果觉得好用你就花几分钟自己部署一套,没有API KEY 的同学可以去\\u003ca href=\\\"https://api.chat-plus.net\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.chat-plus.net\\u003c/a\\u003e (支持MidJourney,GPT,Claude,Google Gemmi 各种表格模型) 或者 \\u003ca href=\\\"https://gpt.bemore.lol\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://gpt.bemore.lol\\u003c/a\\u003e(不支持 Midjourney) 购买,现在有超级优惠,价格远低于 OpenAI 官方。关于中转 API 的优势和劣势请参考 [中转API技术原理](https://ai.r9it.com/docs/install/errors-handle.html#%E8%B0%83%E7%94%A8%E4%B8%AD%E8%BD%AC-api-%E6%8A%A5%E9%94%99%E6%97%A0%E5%8F%AF%E7%94%A8%E6%B8%A0%E9%81%93)。\\nGPT-3.5,GPT-4,DALL-E3 绘图......你都可以随意使用,无需魔法。\\n接入教程: \\u003ca href=\\\"https://ai.r9it.com/docs/install/\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://ai.r9it.com/docs/install/\\u003c/a\\u003e\\n\\n本项目源码地址:\\u003ca href=\\\"https://github.com/yangjian102621/chatgpt-plus\\\" target=\\\"_blank\\\"\\u003ehttps://github.com/yangjian102621/chatgpt-plus\\u003c/a\\u003e\",\"updated\":true}');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_files`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_files`;
|
||||
CREATE TABLE `chatgpt_files` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`name` varchar(100) NOT NULL COMMENT '文件名',
|
||||
`obj_key` varchar(100) DEFAULT NULL COMMENT '文件标识',
|
||||
`url` varchar(255) NOT NULL COMMENT '文件地址',
|
||||
`ext` varchar(10) NOT NULL COMMENT '文件后缀',
|
||||
`size` bigint NOT NULL DEFAULT '0' COMMENT '文件大小',
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户文件表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_functions`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_functions`;
|
||||
CREATE TABLE `chatgpt_functions` (
|
||||
`id` int NOT NULL,
|
||||
`name` varchar(30) NOT NULL COMMENT '函数名称',
|
||||
`label` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '函数标签',
|
||||
`description` varchar(255) DEFAULT NULL COMMENT '函数描述',
|
||||
`parameters` text COMMENT '函数参数(JSON)',
|
||||
`token` varchar(255) DEFAULT NULL COMMENT 'API授权token',
|
||||
`action` varchar(255) DEFAULT NULL COMMENT '函数处理 API',
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启用'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='函数插件表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_functions`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_functions` (`id`, `name`, `label`, `description`, `parameters`, `token`, `action`, `enabled`) VALUES
|
||||
(1, 'weibo', '微博热搜', '新浪微博热搜榜,微博当日热搜榜单', '{\"type\":\"object\",\"properties\":{}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/weibo', 0),
|
||||
(2, 'zaobao', '今日早报', '每日早报,获取当天新闻事件列表', '{\"type\":\"object\",\"properties\":{}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/zaobao', 0),
|
||||
(3, 'dalle3', 'DALLE3', 'AI 绘画工具,根据输入的绘图描述用 AI 工具进行绘画', '{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"prompt\":{\"type\":\"string\",\"description\":\"绘画提示词\"}}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/dalle3', 0);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_invite_codes`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_invite_codes`;
|
||||
CREATE TABLE `chatgpt_invite_codes` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户ID',
|
||||
`code` char(8) NOT NULL COMMENT '邀请码',
|
||||
`hits` int NOT NULL COMMENT '点击次数',
|
||||
`reg_num` smallint NOT NULL COMMENT '注册数量',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户邀请码';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_invite_logs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_invite_logs`;
|
||||
CREATE TABLE `chatgpt_invite_logs` (
|
||||
`id` int NOT NULL,
|
||||
`inviter_id` int NOT NULL COMMENT '邀请人ID',
|
||||
`user_id` int NOT NULL COMMENT '注册用户ID',
|
||||
`username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
|
||||
`invite_code` char(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '邀请码',
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '备注',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='邀请注册日志';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_menus`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_menus`;
|
||||
CREATE TABLE `chatgpt_menus` (
|
||||
`id` int NOT NULL,
|
||||
`name` varchar(30) NOT NULL COMMENT '菜单名称',
|
||||
`icon` varchar(150) NOT NULL COMMENT '菜单图标',
|
||||
`url` varchar(100) NOT NULL COMMENT '地址',
|
||||
`sort_num` smallint NOT NULL COMMENT '排序',
|
||||
`enabled` tinyint(1) NOT NULL COMMENT '是否启用'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='前端菜单表';
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_menus`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_menus` (`id`, `name`, `icon`, `url`, `sort_num`, `enabled`) VALUES
|
||||
(1, '对话聊天', '/images/menu/chat.png', '/chat', 0, 1),
|
||||
(5, 'MJ 绘画', '/images/menu/mj.png', '/mj', 1, 1),
|
||||
(6, 'SD 绘画', '/images/menu/sd.png', '/sd', 2, 1),
|
||||
(7, '算力日志', '/images/menu/log.png', '/powerLog', 5, 1),
|
||||
(8, '应用中心', '/images/menu/app.png', '/apps', 3, 1),
|
||||
(9, '作品展示', '/images/menu/img-wall.png', '/images-wall', 4, 1),
|
||||
(10, '会员计划', '/images/menu/member.png', '/member', 6, 1),
|
||||
(11, '分享计划', '/images/menu/share.png', '/invite', 7, 1);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_mj_jobs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_mj_jobs`;
|
||||
CREATE TABLE `chatgpt_mj_jobs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`task_id` varchar(20) DEFAULT NULL COMMENT '任务 ID',
|
||||
`type` varchar(20) DEFAULT 'image' COMMENT '任务类别',
|
||||
`message_id` char(40) NOT NULL COMMENT '消息 ID',
|
||||
`channel_id` char(40) DEFAULT NULL COMMENT '频道ID',
|
||||
`reference_id` char(40) DEFAULT NULL COMMENT '引用消息 ID',
|
||||
`prompt` varchar(2000) NOT NULL COMMENT '会话提示词',
|
||||
`img_url` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '图片URL',
|
||||
`org_url` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '原始图片地址',
|
||||
`hash` varchar(100) DEFAULT NULL COMMENT 'message hash',
|
||||
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
||||
`use_proxy` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否使用反代',
|
||||
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
||||
`err_msg` varchar(255) DEFAULT NULL COMMENT '错误信息',
|
||||
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='MidJourney 任务表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_orders`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_orders`;
|
||||
CREATE TABLE `chatgpt_orders` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户ID',
|
||||
`product_id` int NOT NULL COMMENT '产品ID',
|
||||
`username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户明',
|
||||
`order_no` varchar(30) NOT NULL COMMENT '订单ID',
|
||||
`trade_no` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '支付平台交易流水号',
|
||||
`subject` varchar(100) NOT NULL COMMENT '订单产品',
|
||||
`amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '订单金额',
|
||||
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '订单状态(0:待支付,1:已扫码,2:支付失败)',
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '备注',
|
||||
`pay_time` int DEFAULT NULL COMMENT '支付时间',
|
||||
`pay_way` varchar(20) NOT NULL COMMENT '支付方式',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL,
|
||||
`deleted_at` datetime DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='充值订单表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_power_logs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_power_logs`;
|
||||
CREATE TABLE `chatgpt_power_logs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户ID',
|
||||
`username` varchar(30) NOT NULL COMMENT '用户名',
|
||||
`type` tinyint(1) NOT NULL COMMENT '类型(1:充值,2:消费,3:退费)',
|
||||
`amount` smallint NOT NULL COMMENT '算力数值',
|
||||
`balance` int NOT NULL COMMENT '余额',
|
||||
`model` varchar(30) NOT NULL COMMENT '模型',
|
||||
`remark` varchar(255) NOT NULL COMMENT '备注',
|
||||
`mark` tinyint(1) NOT NULL COMMENT '资金类型(0:支出,1:收入)',
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户算力消费日志';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_products`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_products`;
|
||||
CREATE TABLE `chatgpt_products` (
|
||||
`id` int NOT NULL,
|
||||
`name` varchar(30) NOT NULL COMMENT '名称',
|
||||
`price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '价格',
|
||||
`discount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '优惠金额',
|
||||
`days` smallint NOT NULL DEFAULT '0' COMMENT '延长天数',
|
||||
`power` int NOT NULL DEFAULT '0' COMMENT '增加算力值',
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启动',
|
||||
`sales` int NOT NULL DEFAULT '0' COMMENT '销量',
|
||||
`sort_num` tinyint NOT NULL DEFAULT '0' COMMENT '排序',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL,
|
||||
`app_url` varchar(255) DEFAULT NULL COMMENT 'App跳转地址',
|
||||
`url` varchar(255) DEFAULT NULL COMMENT '跳转地址'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员套餐表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_rewards`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_rewards`;
|
||||
CREATE TABLE `chatgpt_rewards` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`tx_id` char(36) NOT NULL COMMENT '交易 ID',
|
||||
`amount` decimal(10,2) NOT NULL COMMENT '打赏金额',
|
||||
`remark` varchar(80) NOT NULL COMMENT '备注',
|
||||
`status` tinyint(1) NOT NULL COMMENT '核销状态,0:未核销,1:已核销',
|
||||
`exchange` varchar(255) NOT NULL COMMENT '兑换详情(json)',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户打赏';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_sd_jobs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_sd_jobs`;
|
||||
CREATE TABLE `chatgpt_sd_jobs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户 ID',
|
||||
`type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT 'txt2img' COMMENT '任务类别',
|
||||
`task_id` char(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '任务 ID',
|
||||
`prompt` varchar(2000) NOT NULL COMMENT '会话提示词',
|
||||
`img_url` varchar(255) DEFAULT NULL COMMENT '图片URL',
|
||||
`params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '绘画参数json',
|
||||
`progress` smallint DEFAULT '0' COMMENT '任务进度',
|
||||
`publish` tinyint(1) NOT NULL COMMENT '是否发布',
|
||||
`err_msg` varchar(255) DEFAULT NULL COMMENT '错误信息',
|
||||
`power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
|
||||
`created_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Stable Diffusion 任务表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_users`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_users`;
|
||||
CREATE TABLE `chatgpt_users` (
|
||||
`id` int NOT NULL,
|
||||
`username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
|
||||
`nickname` varchar(30) NOT NULL COMMENT '昵称',
|
||||
`password` char(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码',
|
||||
`avatar` varchar(100) NOT NULL COMMENT '头像',
|
||||
`salt` char(12) NOT NULL COMMENT '密码盐',
|
||||
`power` int NOT NULL DEFAULT '0' COMMENT '剩余算力',
|
||||
`expired_time` int NOT NULL COMMENT '用户过期时间',
|
||||
`status` tinyint(1) NOT NULL COMMENT '当前状态',
|
||||
`chat_config_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '聊天配置json',
|
||||
`chat_roles_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '聊天角色 json',
|
||||
`chat_models_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'AI模型 json',
|
||||
`last_login_at` int NOT NULL COMMENT '最后登录时间',
|
||||
`vip` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否会员',
|
||||
`last_login_ip` char(16) NOT NULL COMMENT '最后登录 IP',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 转存表中的数据 `chatgpt_users`
|
||||
--
|
||||
|
||||
INSERT INTO `chatgpt_users` (`id`, `username`, `nickname`, `password`, `avatar`, `salt`, `power`, `expired_time`, `status`, `chat_config_json`, `chat_roles_json`, `chat_models_json`, `last_login_at`, `vip`, `last_login_ip`, `created_at`, `updated_at`) VALUES
|
||||
(4, '18575670125', '极客学长@830270', 'ccc3fb7ab61b8b5d096a4a166ae21d121fc38c71bbd1be6173d9ab973214a63b', 'http://localhost:5678/static/upload/2024/2/1708682650912429.png', 'ueedue5l', 9384, 1717292086, 1, '{\"api_keys\":{\"Azure\":\"\",\"ChatGLM\":\"\",\"OpenAI\":\"\"}}', '[\"red_book\",\"gpt\",\"programmer\",\"seller\"]', '[1,11]', 1711698298, 1, '::1', '2023-06-12 16:47:17', '2024-03-29 15:44:58');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 表的结构 `chatgpt_user_login_logs`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `chatgpt_user_login_logs`;
|
||||
CREATE TABLE `chatgpt_user_login_logs` (
|
||||
`id` int NOT NULL,
|
||||
`user_id` int NOT NULL COMMENT '用户ID',
|
||||
`username` varchar(30) NOT NULL COMMENT '用户名',
|
||||
`login_ip` char(16) NOT NULL COMMENT '登录IP',
|
||||
`login_address` varchar(30) NOT NULL COMMENT '登录地址',
|
||||
`created_at` datetime NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户登录日志';
|
||||
|
||||
--
|
||||
-- 转储表的索引
|
||||
--
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_admin_users`
|
||||
--
|
||||
ALTER TABLE `chatgpt_admin_users`
|
||||
ADD PRIMARY KEY (`id`) USING BTREE,
|
||||
ADD UNIQUE KEY `username` (`username`) USING BTREE;
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_api_keys`
|
||||
--
|
||||
ALTER TABLE `chatgpt_api_keys`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_chat_history`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_history`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `chat_id` (`chat_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_chat_items`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_items`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `chat_id` (`chat_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_chat_models`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_models`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_chat_roles`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_roles`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `marker` (`marker`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_configs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_configs`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `marker` (`marker`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_files`
|
||||
--
|
||||
ALTER TABLE `chatgpt_files`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_functions`
|
||||
--
|
||||
ALTER TABLE `chatgpt_functions`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `name` (`name`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_invite_codes`
|
||||
--
|
||||
ALTER TABLE `chatgpt_invite_codes`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `code` (`code`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_invite_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_invite_logs`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_menus`
|
||||
--
|
||||
ALTER TABLE `chatgpt_menus`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_mj_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_mj_jobs`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `task_id` (`task_id`),
|
||||
ADD KEY `message_id` (`message_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_orders`
|
||||
--
|
||||
ALTER TABLE `chatgpt_orders`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `order_no` (`order_no`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_power_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_power_logs`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_products`
|
||||
--
|
||||
ALTER TABLE `chatgpt_products`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_rewards`
|
||||
--
|
||||
ALTER TABLE `chatgpt_rewards`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `tx_id` (`tx_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_sd_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_sd_jobs`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `task_id` (`task_id`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_users`
|
||||
--
|
||||
ALTER TABLE `chatgpt_users`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `username` (`username`),
|
||||
ADD UNIQUE KEY `username_2` (`username`);
|
||||
|
||||
--
|
||||
-- 表的索引 `chatgpt_user_login_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_user_login_logs`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- 在导出的表使用AUTO_INCREMENT
|
||||
--
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_admin_users`
|
||||
--
|
||||
ALTER TABLE `chatgpt_admin_users`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=113;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_api_keys`
|
||||
--
|
||||
ALTER TABLE `chatgpt_api_keys`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_history`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_history`
|
||||
MODIFY `id` bigint NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_items`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_items`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_models`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_models`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=25;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_roles`
|
||||
--
|
||||
ALTER TABLE `chatgpt_chat_roles`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=130;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_configs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_configs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_files`
|
||||
--
|
||||
ALTER TABLE `chatgpt_files`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_functions`
|
||||
--
|
||||
ALTER TABLE `chatgpt_functions`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_invite_codes`
|
||||
--
|
||||
ALTER TABLE `chatgpt_invite_codes`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_invite_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_invite_logs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_menus`
|
||||
--
|
||||
ALTER TABLE `chatgpt_menus`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_mj_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_mj_jobs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_orders`
|
||||
--
|
||||
ALTER TABLE `chatgpt_orders`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_power_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_power_logs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_products`
|
||||
--
|
||||
ALTER TABLE `chatgpt_products`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_rewards`
|
||||
--
|
||||
ALTER TABLE `chatgpt_rewards`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_sd_jobs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_sd_jobs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_users`
|
||||
--
|
||||
ALTER TABLE `chatgpt_users`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- 使用表AUTO_INCREMENT `chatgpt_user_login_logs`
|
||||
--
|
||||
ALTER TABLE `chatgpt_user_login_logs`
|
||||
MODIFY `id` int NOT NULL AUTO_INCREMENT;
|
||||
COMMIT;
|
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
@ -51,7 +51,7 @@ services:
|
||||
|
||||
# 后端 API 程序
|
||||
geekai-api:
|
||||
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-api:v4.0.7-amd64
|
||||
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-api:v4.0.8-amd64
|
||||
container_name: geekai-api
|
||||
restart: always
|
||||
depends_on:
|
||||
@ -73,7 +73,7 @@ services:
|
||||
|
||||
# 前端应用
|
||||
geekai-web:
|
||||
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-web:v4.0.7-amd64
|
||||
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-web:v4.0.8-amd64
|
||||
container_name: geekai-web
|
||||
restart: always
|
||||
depends_on:
|
||||
|
@ -6,4 +6,4 @@ VUE_APP_ADMIN_USER=admin
|
||||
VUE_APP_ADMIN_PASS=admin123
|
||||
VUE_APP_KEY_PREFIX=ChatPLUS_DEV_
|
||||
VUE_APP_TITLE="Geek-AI 创作系统"
|
||||
VUE_APP_VERSION=v4.0.7
|
||||
VUE_APP_VERSION=v4.0.8
|
||||
|
@ -2,4 +2,4 @@ VUE_APP_API_HOST=
|
||||
VUE_APP_WS_HOST=
|
||||
VUE_APP_KEY_PREFIX=ChatPLUS_
|
||||
VUE_APP_TITLE="Geek-AI 创作系统"
|
||||
VUE_APP_VERSION=v4.0.7
|
||||
VUE_APP_VERSION=v4.0.8
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "chatgpt-plus-web",
|
||||
"name": "geekai-web",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@ -20,8 +20,7 @@
|
||||
"json-bigint": "^1.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"markdown-it": "^13.0.1",
|
||||
"markdown-it-latex2img": "^0.0.6",
|
||||
"markdown-it-mathjax": "^2.0.0",
|
||||
"markdown-it-mathjax3": "^4.3.2",
|
||||
"markmap-common": "^0.16.0",
|
||||
"markmap-lib": "^0.16.1",
|
||||
"markmap-toolbar": "^0.17.0",
|
||||
|
@ -13,8 +13,9 @@
|
||||
.item {
|
||||
display flex
|
||||
flex-flow row
|
||||
border 1px solid #3c3c3c
|
||||
border 1px solid rgb(80,80,80)
|
||||
padding 10px
|
||||
background rgba(60,60,60 0.5)
|
||||
|
||||
.image {
|
||||
width 80px
|
||||
|
@ -129,15 +129,44 @@ $borderColor = #4676d0;
|
||||
--el-main-padding: 0;
|
||||
margin: 0;
|
||||
|
||||
.chat-box {
|
||||
.chat-container {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
background-color: var(--el-bg-color)
|
||||
color var(--el-text-color-primary)
|
||||
|
||||
.chat-config {
|
||||
height 30px
|
||||
padding 10px 30px
|
||||
display flex
|
||||
justify-content center
|
||||
justify-items center
|
||||
border-bottom 1px solid #d9d9e3
|
||||
|
||||
.role-select-label {
|
||||
color #ffffff
|
||||
}
|
||||
|
||||
.el-select {
|
||||
max-width 150px;
|
||||
margin-right 10px;
|
||||
}
|
||||
|
||||
.role-select {
|
||||
max-width 130px;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
.el-icon {
|
||||
margin-right 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#container {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
position relative
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 0;
|
||||
@ -165,68 +194,97 @@ $borderColor = #4676d0;
|
||||
}
|
||||
|
||||
.input-box {
|
||||
background-color: #ffffff
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1);
|
||||
padding 0 15px;
|
||||
position absolute
|
||||
bottom 0
|
||||
width 100%
|
||||
|
||||
.tool-item {
|
||||
margin-right 15px
|
||||
border-radius: 6px;
|
||||
color: #19c37d;
|
||||
.input-box-inner {
|
||||
display flex
|
||||
justify-content center
|
||||
justify-items center
|
||||
padding 6px
|
||||
cursor pointer
|
||||
background #F2F2F2
|
||||
background-color: #ffffff
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1);
|
||||
padding 0 15px;
|
||||
|
||||
&:hover {
|
||||
background #D5FAD3
|
||||
}
|
||||
.tool-item {
|
||||
margin-right 15px
|
||||
border-radius: 6px;
|
||||
color: #19c37d;
|
||||
display flex
|
||||
justify-content center
|
||||
justify-items center
|
||||
padding 6px
|
||||
cursor pointer
|
||||
background #F2F2F2
|
||||
|
||||
.iconfont {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background #D5FAD3
|
||||
}
|
||||
|
||||
.input-container {
|
||||
width 100%
|
||||
margin: 0;
|
||||
border: none;
|
||||
padding: 10px 0;
|
||||
display flex
|
||||
justify-content center
|
||||
position relative
|
||||
|
||||
.el-textarea {
|
||||
.el-textarea__inner::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
.iconfont {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.select-file {
|
||||
position absolute;
|
||||
right 48px;
|
||||
top 20px;
|
||||
}
|
||||
.input-body {
|
||||
width 100%
|
||||
margin: 0;
|
||||
border: none;
|
||||
padding: 10px 0;
|
||||
display flex
|
||||
justify-content center
|
||||
position relative
|
||||
|
||||
.send-btn {
|
||||
position absolute;
|
||||
right 12px;
|
||||
top 20px;
|
||||
.hide-div {
|
||||
white-space: pre-wrap; /* 保持文本换行 */
|
||||
visibility: hidden; /* 隐藏 div */
|
||||
position: absolute; /* 脱离文档流 */
|
||||
line-height: 24px
|
||||
font-size 14px
|
||||
word-wrap: break-word; /* 允许单词换行 */
|
||||
overflow-wrap: break-word; /* 允许长单词换行,适用于现代浏览器 */
|
||||
}
|
||||
|
||||
.input-border {
|
||||
display flex
|
||||
width 100%
|
||||
overflow hidden
|
||||
border: 2px solid #21AA93
|
||||
border-radius 10px
|
||||
padding 10px
|
||||
|
||||
|
||||
.prompt-input::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.prompt-input {
|
||||
width 100%
|
||||
line-height: 24px
|
||||
border none
|
||||
font-size 14px
|
||||
background none
|
||||
resize: none
|
||||
white-space: pre-wrap; /* 保持文本换行 */
|
||||
word-wrap: break-word; /* 允许单词换行 */
|
||||
overflow-wrap: break-word; /* 允许长单词换行,适用于现代浏览器 */
|
||||
}
|
||||
|
||||
.send-btn {
|
||||
width 32px
|
||||
margin-left 10px
|
||||
.el-button {
|
||||
padding 8px 5px;
|
||||
border-radius 6px;
|
||||
font-size 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-button {
|
||||
padding 8px 5px;
|
||||
border-radius 6px;
|
||||
font-size 20px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,8 @@
|
||||
cursor pointer
|
||||
|
||||
.el-image {
|
||||
width 40px
|
||||
height 40px
|
||||
width 48px
|
||||
height 48px
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@
|
||||
.navigator {
|
||||
display flex
|
||||
flex-flow column
|
||||
width 50px
|
||||
width 60px
|
||||
padding 10px 1px
|
||||
border-right: 1px solid #3c3c3c
|
||||
background-color: #1E1F22
|
||||
@ -97,12 +97,14 @@
|
||||
|
||||
li {
|
||||
margin-bottom 15px
|
||||
display flex
|
||||
flex-flow column
|
||||
|
||||
a {
|
||||
color #DADBDC
|
||||
border-radius 10px
|
||||
width 40px
|
||||
height 40px
|
||||
width 48px
|
||||
height 48px
|
||||
display flex
|
||||
justify-content center
|
||||
align-items center
|
||||
@ -125,9 +127,12 @@
|
||||
|
||||
.title {
|
||||
font-size: 12px
|
||||
padding-top: 5px
|
||||
padding-top: 6px
|
||||
color: #e5e7eb;
|
||||
text-align: center;
|
||||
white-space: nowrap; /* 防止文本换行 */
|
||||
overflow: hidden; /* 隐藏溢出内容 */
|
||||
text-overflow: unset; /* 使用省略号表示溢出内容 */
|
||||
}
|
||||
|
||||
.active {
|
||||
|
@ -50,6 +50,7 @@
|
||||
display flex
|
||||
cursor pointer
|
||||
margin-bottom: 10px;
|
||||
border 1px solid #383838
|
||||
|
||||
&:hover {
|
||||
background-color #585858
|
||||
@ -61,60 +62,9 @@
|
||||
margin-bottom 5px
|
||||
}
|
||||
|
||||
.shape {
|
||||
width 16px
|
||||
height 16px
|
||||
margin-bottom 5px
|
||||
border 1px solid #C4C4C4
|
||||
border-radius 3px
|
||||
}
|
||||
|
||||
.shape.size9-16 {
|
||||
width 9px
|
||||
height 16px
|
||||
}
|
||||
|
||||
.shape.size16-9 {
|
||||
height 9px
|
||||
width 16px
|
||||
position relative
|
||||
margin 4px 0 7px
|
||||
}
|
||||
|
||||
.shape.size3-4 {
|
||||
width 12px
|
||||
height 16px
|
||||
}
|
||||
|
||||
.shape.size4-3 {
|
||||
height 12px
|
||||
width 16px
|
||||
position relative
|
||||
margin 4px 0 4px
|
||||
}
|
||||
|
||||
.shape.size2-3 {
|
||||
width 11px
|
||||
height 16px
|
||||
}
|
||||
|
||||
.shape.size3-2 {
|
||||
height 11px
|
||||
width 16px
|
||||
position relative
|
||||
margin 4px 0 5px
|
||||
}
|
||||
|
||||
.shape.size1-2 {
|
||||
width 8px
|
||||
height 16px
|
||||
}
|
||||
|
||||
.shape.size2-1 {
|
||||
height 8px
|
||||
width 16px
|
||||
position relative
|
||||
margin 4px 0 8px
|
||||
.text {
|
||||
margin-left 5px
|
||||
margin-top 2px
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,10 +72,7 @@
|
||||
.grid-content.active {
|
||||
color #47fff1
|
||||
background-color #585858
|
||||
|
||||
.shape {
|
||||
border 1px solid #47fff1
|
||||
}
|
||||
border 1px solid #47fff1
|
||||
}
|
||||
|
||||
.model {
|
||||
|
@ -92,9 +92,9 @@ const items = [
|
||||
},
|
||||
|
||||
{
|
||||
icon: 'role',
|
||||
index: '/admin/role',
|
||||
title: '角色管理',
|
||||
icon: 'menu',
|
||||
index: '/admin/app',
|
||||
title: '应用管理',
|
||||
},
|
||||
{
|
||||
icon: 'api-key',
|
||||
|
@ -46,7 +46,7 @@ const routes = [
|
||||
component: () => import('@/views/Member.vue'),
|
||||
},
|
||||
{
|
||||
name: 'chat-role',
|
||||
name: 'chat-app',
|
||||
path: '/apps',
|
||||
meta: {title: '应用中心'},
|
||||
component: () => import('@/views/ChatApps.vue'),
|
||||
@ -139,10 +139,10 @@ const routes = [
|
||||
component: () => import('@/views/admin/Users.vue'),
|
||||
},
|
||||
{
|
||||
path: '/admin/role',
|
||||
name: 'admin-role',
|
||||
meta: {title: '角色管理'},
|
||||
component: () => import('@/views/admin/Roles.vue'),
|
||||
path: '/admin/app',
|
||||
name: 'admin-app',
|
||||
meta: {title: '应用管理'},
|
||||
component: () => import('@/views/admin/Apps.vue'),
|
||||
},
|
||||
{
|
||||
path: '/admin/apikey',
|
||||
|
@ -65,9 +65,44 @@
|
||||
</div>
|
||||
</el-aside>
|
||||
<el-main v-loading="loading" element-loading-background="rgba(122, 122, 122, 0.3)">
|
||||
<div class="chat-box" :style="{height: mainWinHeight+'px'}">
|
||||
<div class="chat-container">
|
||||
<div class="chat-config">
|
||||
<el-select v-model="roleId" filterable placeholder="角色" @change="_newChat"
|
||||
class="role-select"
|
||||
style="width:150px">
|
||||
<el-option
|
||||
v-for="item in roles"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
>
|
||||
<div class="role-option">
|
||||
<el-image :src="item.icon"></el-image>
|
||||
<span>{{ item.name }}</span>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
||||
<el-select v-model="modelID" filterable placeholder="模型" @change="_newChat"
|
||||
:disabled="disableModel"
|
||||
style="width:150px">
|
||||
<el-option
|
||||
v-for="item in models"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
>
|
||||
<span>{{ item.name }}</span>
|
||||
<el-tag style="margin-left: 5px; position: relative; top:-2px" type="info" size="small">{{
|
||||
item.power
|
||||
}}算力
|
||||
</el-tag>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div id="container">
|
||||
<div id="container" :style="{height: mainWinHeight+'px'}">
|
||||
<div class="chat-box" id="chat-box" :style="{height: chatBoxHeight+'px'}">
|
||||
<div v-if="showHello">
|
||||
<welcome @send="autofillPrompt"/>
|
||||
@ -84,61 +119,8 @@
|
||||
</div>
|
||||
</div><!-- end chat box -->
|
||||
|
||||
<el-affix position="bottom" :offset="0">
|
||||
<div class="input-box">
|
||||
<span class="tool-item">
|
||||
<el-popover
|
||||
:width="300"
|
||||
trigger="click"
|
||||
placement="top-start"
|
||||
>
|
||||
<template #reference>
|
||||
<div>
|
||||
<el-tooltip effect="dark" content="模型选择">
|
||||
<i class="iconfont icon-model"></i>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #default>
|
||||
<div class="chat-config">
|
||||
<el-select v-model="roleId" filterable placeholder="角色" @change="_newChat"
|
||||
class="role-select"
|
||||
style="width:150px">
|
||||
<el-option
|
||||
v-for="item in roles"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
>
|
||||
<div class="role-option">
|
||||
<el-image :src="item.icon"></el-image>
|
||||
<span>{{ item.name }}</span>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
||||
<el-select v-model="modelID" filterable placeholder="模型" @change="_newChat"
|
||||
:disabled="disableModel"
|
||||
style="width:150px">
|
||||
<el-option
|
||||
v-for="item in models"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
>
|
||||
<span>{{ item.name }}</span>
|
||||
<el-tag style="margin-left: 5px; position: relative; top:-2px" type="info" size="small">{{
|
||||
item.power
|
||||
}}算力
|
||||
</el-tag>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
</el-popover>
|
||||
</span>
|
||||
|
||||
<div class="input-box">
|
||||
<div class="input-box-inner">
|
||||
<span class="tool-item" @click="ElMessage.info('暂时不支持语音输入')">
|
||||
<el-tooltip class="box-item" effect="dark" content="语音输入">
|
||||
<i class="iconfont icon-mic-bold"></i>
|
||||
@ -151,32 +133,34 @@
|
||||
</el-tooltip>
|
||||
</span>
|
||||
|
||||
<div class="input-container">
|
||||
<el-input
|
||||
ref="textInput"
|
||||
v-model="prompt"
|
||||
v-on:keydown="inputKeyDown"
|
||||
autofocus
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
style="--el-input-focus-border-color:#21AA93;
|
||||
border: 1px solid #21AA93;--el-input-border-color:#21AA93;
|
||||
border-radius: 5px; --el-input-hover-border-color:#21AA93;"
|
||||
placeholder="按 Enter 键发送消息,使用 Ctrl + Enter 换行"
|
||||
/>
|
||||
<span class="send-btn">
|
||||
<el-button type="info" v-if="showStopGenerate" @click="stopGenerate" plain>
|
||||
<el-icon>
|
||||
<VideoPause/>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<el-button @click="sendMessage" color="#19c37d" style="color:#ffffff" v-else>
|
||||
<el-icon><Promotion/></el-icon>
|
||||
</el-button>
|
||||
</span>
|
||||
<div class="input-body">
|
||||
<div ref="textHeightRef" class="hide-div">{{prompt}}</div>
|
||||
<div class="input-border">
|
||||
<textarea
|
||||
ref="inputRef"
|
||||
class="prompt-input"
|
||||
:rows="row"
|
||||
v-model="prompt"
|
||||
@keydown="onInput"
|
||||
@input="onInput"
|
||||
placeholder="按 Enter 键发送消息,使用 Ctrl + Enter 换行"
|
||||
autofocus>
|
||||
</textarea>
|
||||
<span class="send-btn">
|
||||
<el-button type="info" v-if="showStopGenerate" @click="stopGenerate" plain>
|
||||
<el-icon>
|
||||
<VideoPause/>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<el-button @click="sendMessage" color="#19c37d" style="color:#ffffff" v-else>
|
||||
<el-icon><Promotion/></el-icon>
|
||||
</el-button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div><!-- end input box -->
|
||||
</el-affix>
|
||||
</div>
|
||||
</div><!-- end container -->
|
||||
</div><!-- end loading -->
|
||||
</div>
|
||||
@ -237,11 +221,13 @@ const roleId = ref(0)
|
||||
const newChatItem = ref(null);
|
||||
const isLogin = ref(false)
|
||||
const showHello = ref(true)
|
||||
const textInput = ref(null)
|
||||
const inputRef = ref(null)
|
||||
const textHeightRef = ref(null)
|
||||
const showNotice = ref(false)
|
||||
const notice = ref("")
|
||||
const noticeKey = ref("SYSTEM_NOTICE")
|
||||
const store = useSharedStore();
|
||||
const row = ref(1)
|
||||
|
||||
if (isMobile()) {
|
||||
router.replace("/mobile/chat")
|
||||
@ -372,8 +358,8 @@ const getRoleById = function (rid) {
|
||||
}
|
||||
|
||||
const resizeElement = function () {
|
||||
chatBoxHeight.value = window.innerHeight - 50 - 82 - 38;
|
||||
mainWinHeight.value = window.innerHeight - 50;
|
||||
chatBoxHeight.value = window.innerHeight - 101 - 82 - 38;
|
||||
mainWinHeight.value = window.innerHeight - 101;
|
||||
leftBoxHeight.value = window.innerHeight - 90 - 45 - 82;
|
||||
};
|
||||
|
||||
@ -517,8 +503,7 @@ const removeChat = function (chat) {
|
||||
|
||||
}
|
||||
|
||||
const latexPlugin = require('markdown-it-latex2img')
|
||||
const mathjaxPlugin = require('markdown-it-mathjax')
|
||||
const mathjaxPlugin = require('markdown-it-mathjax3')
|
||||
const md = require('markdown-it')({
|
||||
breaks: true,
|
||||
html: true,
|
||||
@ -543,7 +528,6 @@ const md = require('markdown-it')({
|
||||
return `<pre class="code-container"><code class="language-${lang} hljs">${preCode}</code>${copyBtn}</pre>`
|
||||
}
|
||||
});
|
||||
md.use(latexPlugin)
|
||||
md.use(mathjaxPlugin)
|
||||
|
||||
// 创建 socket 连接
|
||||
@ -705,8 +689,19 @@ const enableInput = () => {
|
||||
showStopGenerate.value = false;
|
||||
}
|
||||
|
||||
// 登录输入框输入事件处理
|
||||
const inputKeyDown = function (e) {
|
||||
const onInput = (e) => {
|
||||
// 根据输入的内容自动计算输入框的行数
|
||||
const lineHeight = parseFloat(window.getComputedStyle(inputRef.value).lineHeight)
|
||||
textHeightRef.value.style.width = inputRef.value.clientWidth + 'px'; // 设定宽度和 textarea 相同
|
||||
const lines = Math.floor(textHeightRef.value.clientHeight / lineHeight);
|
||||
inputRef.value.scrollTo(0, inputRef.value.scrollHeight)
|
||||
if (prompt.value.length < 10) {
|
||||
row.value = 1
|
||||
} else if (row.value <= 7) {
|
||||
row.value = lines
|
||||
}
|
||||
|
||||
// 输入回车自动提交
|
||||
if (e.keyCode === 13) {
|
||||
if (e.ctrlKey) { // Ctrl + Enter 换行
|
||||
prompt.value += "\n";
|
||||
@ -720,7 +715,7 @@ const inputKeyDown = function (e) {
|
||||
// 自动填充 prompt
|
||||
const autofillPrompt = (text) => {
|
||||
prompt.value = text
|
||||
textInput.value.focus()
|
||||
inputRef.value.focus()
|
||||
// sendMessage()
|
||||
}
|
||||
// 发送消息
|
||||
@ -929,29 +924,4 @@ const insertURL = (url) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chat-config {
|
||||
display flex
|
||||
flex-direction row
|
||||
padding-top 10px;
|
||||
|
||||
.role-select-label {
|
||||
color #ffffff
|
||||
}
|
||||
|
||||
.el-select {
|
||||
max-width 150px;
|
||||
margin-right 10px;
|
||||
}
|
||||
|
||||
.role-select {
|
||||
max-width 130px;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
.el-icon {
|
||||
margin-right 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -11,8 +11,8 @@
|
||||
</div>
|
||||
|
||||
<div class="navbar">
|
||||
|
||||
<el-tooltip
|
||||
v-if="!licenseConfig.de_copy"
|
||||
class="box-item"
|
||||
effect="light"
|
||||
content="部署文档"
|
||||
@ -23,6 +23,7 @@
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip
|
||||
v-if="!licenseConfig.de_copy"
|
||||
class="box-item"
|
||||
effect="light"
|
||||
content="项目源码"
|
||||
@ -85,6 +86,7 @@
|
||||
<el-image :src="item.icon" style="width: 30px;height: 30px"/>
|
||||
</a>
|
||||
</el-tooltip>
|
||||
<span :class="item.url === curPath ? 'title active' : 'title'">{{ item.name }}</span>
|
||||
</li>
|
||||
|
||||
<el-popover
|
||||
@ -139,6 +141,7 @@ import {removeUserToken} from "@/store/session";
|
||||
import LoginDialog from "@/components/LoginDialog.vue";
|
||||
import {useSharedStore} from "@/store/sharedata";
|
||||
import ConfigDialog from "@/components/ConfigDialog.vue";
|
||||
import {showMessageError} from "@/utils/dialog";
|
||||
|
||||
const router = useRouter();
|
||||
const logo = ref('/images/logo.png');
|
||||
@ -151,6 +154,7 @@ const loginUser = ref({})
|
||||
const version = ref(process.env.VUE_APP_VERSION)
|
||||
const routerViewKey = ref(0)
|
||||
const showConfigDialog = ref(false)
|
||||
const licenseConfig = ref({})
|
||||
|
||||
const store = useSharedStore();
|
||||
const show = ref(false)
|
||||
@ -190,6 +194,12 @@ onMounted(() => {
|
||||
ElMessage.error("获取系统菜单失败:" + e.message)
|
||||
})
|
||||
|
||||
httpGet("/api/config/license").then(res => {
|
||||
licenseConfig.value = res.data
|
||||
}).catch(e => {
|
||||
showMessageError("获取 License 配置:" + e.message)
|
||||
})
|
||||
|
||||
init()
|
||||
})
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="index-page" :style="{height: winHeight+'px'}">
|
||||
<div class="bg"></div>
|
||||
<div :class="bgClass"></div>
|
||||
<div class="menu-box">
|
||||
<el-menu
|
||||
mode="horizontal"
|
||||
@ -11,7 +11,8 @@
|
||||
<div class="title">{{ title }}</div>
|
||||
</div>
|
||||
<div class="menu-item">
|
||||
<a href="https://ai.r9it.com/docs/install/" target="_blank">
|
||||
<span v-if="!licenseConfig.de_copy">
|
||||
<a href="https://ai.r9it.com/docs/install/" target="_blank">
|
||||
<el-button type="primary" round>
|
||||
<i class="iconfont icon-book"></i>
|
||||
<span>部署文档</span>
|
||||
@ -24,6 +25,7 @@
|
||||
<span>项目源码</span>
|
||||
</el-button>
|
||||
</a>
|
||||
</span>
|
||||
<el-button @click="router.push('/login')" round>登录</el-button>
|
||||
<el-button @click="router.push('/register')" round>注册</el-button>
|
||||
</div>
|
||||
@ -52,7 +54,7 @@
|
||||
<!-- <div id="animation-container"></div>-->
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<div class="footer" v-if="!licenseConfig.de_copy">
|
||||
<footer-bar />
|
||||
</div>
|
||||
</div>
|
||||
@ -77,73 +79,31 @@ if (isMobile()) {
|
||||
const title = ref("Geek-AI 创作系统")
|
||||
const logo = ref("/images/logo.png")
|
||||
const slogan = ref("我辈之人,先干为敬,陪您先把 AI 用起来")
|
||||
const licenseConfig = ref({})
|
||||
// const size = Math.max(window.innerWidth * 0.5, window.innerHeight * 0.8)
|
||||
const winHeight = window.innerHeight - 150
|
||||
const bgClass = ref('fixed-bg')
|
||||
|
||||
onMounted(() => {
|
||||
httpGet("/api/config/get?key=system").then(res => {
|
||||
title.value = res.data.title
|
||||
logo.value = res.data.logo
|
||||
if (res.data.rand_bg) {
|
||||
bgClass.value = "rand-bg"
|
||||
}
|
||||
}).catch(e => {
|
||||
ElMessage.error("获取系统配置失败:" + e.message)
|
||||
})
|
||||
|
||||
httpGet("/api/config/license").then(res => {
|
||||
licenseConfig.value = res.data
|
||||
}).catch(e => {
|
||||
ElMessage.error("获取 License 配置:" + e.message)
|
||||
})
|
||||
init()
|
||||
})
|
||||
|
||||
const init = () => {
|
||||
// // 创建场景
|
||||
// // 创建场景
|
||||
// const scene = new THREE.Scene();
|
||||
//
|
||||
// // 创建相机
|
||||
// const camera = new THREE.PerspectiveCamera(30, 1, 0.1, 1000);
|
||||
// camera.position.z = 3.88;
|
||||
//
|
||||
// // 创建渲染器
|
||||
// const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
|
||||
// renderer.setSize(size, size);
|
||||
// renderer.setClearColor(0x000000, 0);
|
||||
// const container = document.getElementById('animation-container');
|
||||
// container.appendChild(renderer.domElement);
|
||||
//
|
||||
// // 加载地球纹理
|
||||
// const loader = new THREE.TextureLoader();
|
||||
// loader.load(
|
||||
// '/images/land_ocean_ice_cloud_2048.jpg',
|
||||
// function (texture) {
|
||||
// // 创建地球球体
|
||||
// const geometry = new THREE.SphereGeometry(1, 32, 32);
|
||||
// const material = new THREE.MeshPhongMaterial({
|
||||
// map: texture,
|
||||
// bumpMap: texture, // 使用同一张纹理作为凹凸贴图
|
||||
// bumpScale: 0.05, // 调整凹凸贴图的影响程度
|
||||
// specularMap: texture, // 高光贴图
|
||||
// specular: new THREE.Color('#01193B'), // 高光颜色
|
||||
// });
|
||||
// const earth = new THREE.Mesh(geometry, material);
|
||||
// scene.add(earth);
|
||||
//
|
||||
// // 添加环境光和点光源
|
||||
// const ambientLight = new THREE.AmbientLight(0xffffff, 0.3);
|
||||
// scene.add(ambientLight);
|
||||
// const pointLight = new THREE.PointLight(0xffffff, 0.8);
|
||||
// pointLight.position.set(5, 5, 5);
|
||||
// scene.add(pointLight);
|
||||
//
|
||||
// // 创建动画
|
||||
// const animate = function () {
|
||||
// requestAnimationFrame(animate);
|
||||
//
|
||||
// // 使地球自转和公转
|
||||
// earth.rotation.y += 0.0006;
|
||||
//
|
||||
// renderer.render(scene, camera);
|
||||
// };
|
||||
//
|
||||
// // 执行动画
|
||||
// animate();
|
||||
// }
|
||||
// );
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -158,14 +118,25 @@ const init = () => {
|
||||
align-items baseline
|
||||
padding-top 150px
|
||||
|
||||
.bg {
|
||||
.fixed-bg {
|
||||
position absolute
|
||||
top 0
|
||||
left 0
|
||||
width 100vw
|
||||
height 100vh
|
||||
background-image url("~@/assets/img/ai-bg.jpg")
|
||||
//filter: blur(8px);
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.rand-bg {
|
||||
position absolute
|
||||
top 0
|
||||
left 0
|
||||
width 100vw
|
||||
height 100vh
|
||||
background-image url("https://api.dujin.org/bing/1920.php")
|
||||
filter: blur(8px);
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@
|
||||
|
||||
<reset-pass @hide="showResetPass = false" :show="showResetPass"/>
|
||||
|
||||
<footer class="footer">
|
||||
<footer class="footer" v-if="!licenseConfig.de_copy">
|
||||
<footer-bar/>
|
||||
</footer>
|
||||
</div>
|
||||
@ -74,6 +74,7 @@ const username = ref(process.env.VUE_APP_USER);
|
||||
const password = ref(process.env.VUE_APP_PASS);
|
||||
const showResetPass = ref(false)
|
||||
const logo = ref("/images/logo.png")
|
||||
const licenseConfig = ref({})
|
||||
|
||||
// 获取系统配置
|
||||
httpGet("/api/config/get?key=system").then(res => {
|
||||
@ -83,6 +84,11 @@ httpGet("/api/config/get?key=system").then(res => {
|
||||
showMessageError("获取系统配置失败:" + e.message)
|
||||
})
|
||||
|
||||
httpGet("/api/config/license").then(res => {
|
||||
licenseConfig.value = res.data
|
||||
}).catch(e => {
|
||||
showMessageError("获取 License 配置:" + e.message)
|
||||
})
|
||||
|
||||
checkSession().then(() => {
|
||||
if (isMobile()) {
|
||||
|
@ -160,7 +160,7 @@
|
||||
</el-result>
|
||||
</div>
|
||||
|
||||
<footer class="footer">
|
||||
<footer class="footer" v-if="!licenseConfig.de_copy">
|
||||
<footer-bar/>
|
||||
</footer>
|
||||
</div>
|
||||
@ -199,6 +199,7 @@ const enableUser = ref(false)
|
||||
const enableRegister = ref(false)
|
||||
const activeName = ref("mobile")
|
||||
const wxImg = ref("/images/wx.png")
|
||||
const licenseConfig = ref({})
|
||||
|
||||
httpGet("/api/config/get?key=system").then(res => {
|
||||
if (res.data) {
|
||||
@ -225,6 +226,12 @@ httpGet("/api/config/get?key=system").then(res => {
|
||||
ElMessage.error("获取系统配置失败:" + e.message)
|
||||
})
|
||||
|
||||
httpGet("/api/config/license").then(res => {
|
||||
licenseConfig.value = res.data
|
||||
}).catch(e => {
|
||||
showMessageError("获取 License 配置:" + e.message)
|
||||
})
|
||||
|
||||
// 注册操作
|
||||
const submitRegister = () => {
|
||||
if (data.value.username === '') {
|
||||
|
@ -119,12 +119,12 @@ const mjModels = ref([
|
||||
{name: "急速(Turbo)", value: "turbo"},
|
||||
])
|
||||
|
||||
httpGet("/api/admin/config/get/draw").then(res => {
|
||||
httpGet("/api/admin/config/get/app").then(res => {
|
||||
sdConfigs.value = res.data.sd
|
||||
mjPlusConfigs.value = res.data.mj_plus
|
||||
mjProxyConfigs.value = res.data.mj_proxy
|
||||
}).catch(e =>{
|
||||
ElMessage.error("获取AI绘画配置失败:"+e.message)
|
||||
ElMessage.error("获取配置失败:"+e.message)
|
||||
})
|
||||
|
||||
const addConfig = (configs) => {
|
||||
|
@ -2,6 +2,24 @@
|
||||
<div class="container list" v-loading="loading">
|
||||
|
||||
<div class="handle-box">
|
||||
<el-select v-model="query.platform" placeholder="平台" class="handle-input">
|
||||
<el-option
|
||||
v-for="item in platforms"
|
||||
:key="item.value"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-select v-model="query.type" placeholder="类型" class="handle-input">
|
||||
<el-option
|
||||
v-for="item in types"
|
||||
:key="item.value"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<el-button :icon="Search" @click="fetchData">搜索</el-button>
|
||||
<el-button type="primary" :icon="Plus" @click="add">新增</el-button>
|
||||
<a href="https://api.chat-plus.net" target="_blank" style="margin-left: 10px">
|
||||
<el-button type="success" :icon="ShoppingCart" @click="add" plain>购买API-KEY</el-button>
|
||||
@ -87,7 +105,7 @@
|
||||
<el-input v-model="item.name" autocomplete="off"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="用途:" prop="type">
|
||||
<el-select v-model="item.type" placeholder="请选择用途" @change="changePlatform">
|
||||
<el-select v-model="item.type" placeholder="请选择用途" @change="changeType">
|
||||
<el-option v-for="item in types" :value="item.value" :label="item.name" :key="item.value">{{
|
||||
item.name
|
||||
}}
|
||||
@ -99,7 +117,8 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="API URL:" prop="api_url">
|
||||
<el-input v-model="item.api_url" autocomplete="off"
|
||||
placeholder="如果你用了第三方的 API 中转,这里填写中转地址"/>
|
||||
placeholder="必须填土完整的 Chat API URL,如:https://api.openai.com/v1/chat/completions"/>
|
||||
<div class="info">如果你使用了第三方中转,这里就填写中转地址</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="代理地址:" prop="proxy_url">
|
||||
@ -126,11 +145,12 @@ import {onMounted, onUnmounted, reactive, ref} from "vue";
|
||||
import {httpGet, httpPost} from "@/utils/http";
|
||||
import {ElMessage} from "element-plus";
|
||||
import {dateFormat, removeArrayItem, substr} from "@/utils/libs";
|
||||
import {DocumentCopy, Plus, ShoppingCart} from "@element-plus/icons-vue";
|
||||
import {DocumentCopy, Plus, ShoppingCart, Search} from "@element-plus/icons-vue";
|
||||
import ClipboardJS from "clipboard";
|
||||
|
||||
// 变量定义
|
||||
const items = ref([])
|
||||
const query = ref({type: '',platform:''})
|
||||
const item = ref({})
|
||||
const showDialog = ref(false)
|
||||
const rules = reactive({
|
||||
@ -142,39 +162,7 @@ const rules = reactive({
|
||||
const loading = ref(true)
|
||||
const formRef = ref(null)
|
||||
const title = ref("")
|
||||
const platforms = ref([
|
||||
{
|
||||
name: "【OpenAI/中转】ChatGPT",
|
||||
value: "OpenAI",
|
||||
api_url: "https://api.chat-plus.net/v1/chat/completions",
|
||||
img_url: "https://api.chat-plus.net/v1/images/generations"
|
||||
},
|
||||
{
|
||||
name: "【讯飞】星火大模型",
|
||||
value: "XunFei",
|
||||
api_url: "wss://spark-api.xf-yun.com/{version}/chat"
|
||||
},
|
||||
{
|
||||
name: "【清华智普】ChatGLM",
|
||||
value: "ChatGLM",
|
||||
api_url: "https://open.bigmodel.cn/api/paas/v3/model-api/{model}/sse-invoke"
|
||||
},
|
||||
{
|
||||
name: "【百度】文心一言",
|
||||
value: "Baidu",
|
||||
api_url: "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/{model}"
|
||||
},
|
||||
{
|
||||
name: "【微软】Azure",
|
||||
value: "Azure",
|
||||
api_url: "https://chat-bot-api.openai.azure.com/openai/deployments/{model}/chat/completions?api-version=2023-05-15"
|
||||
},
|
||||
{
|
||||
name: "【阿里】千义通问",
|
||||
value: "QWen",
|
||||
api_url: "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation"
|
||||
},
|
||||
])
|
||||
const platforms = ref([])
|
||||
const types = ref([
|
||||
{name: "聊天", value: "chat"},
|
||||
{name: "绘画", value: "img"},
|
||||
@ -191,6 +179,14 @@ onMounted(() => {
|
||||
clipboard.value.on('error', () => {
|
||||
ElMessage.error('复制失败!');
|
||||
})
|
||||
|
||||
httpGet("/api/admin/config/get/app").then(res => {
|
||||
platforms.value = res.data.platforms
|
||||
}).catch(e =>{
|
||||
ElMessage.error("获取配置失败:"+e.message)
|
||||
})
|
||||
|
||||
fetchData()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
@ -198,19 +194,22 @@ onUnmounted(() => {
|
||||
})
|
||||
|
||||
// 获取数据
|
||||
httpGet('/api/admin/apikey/list').then((res) => {
|
||||
if (res.data) {
|
||||
// 初始化数据
|
||||
const arr = res.data;
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
arr[i].last_used_at = dateFormat(arr[i].last_used_at)
|
||||
|
||||
const fetchData = () => {
|
||||
httpGet('/api/admin/apikey/list', query.value).then((res) => {
|
||||
if (res.data) {
|
||||
// 初始化数据
|
||||
const arr = res.data;
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
arr[i].last_used_at = dateFormat(arr[i].last_used_at)
|
||||
}
|
||||
items.value = arr
|
||||
}
|
||||
items.value = arr
|
||||
}
|
||||
loading.value = false
|
||||
}).catch(() => {
|
||||
ElMessage.error("获取数据失败");
|
||||
})
|
||||
loading.value = false
|
||||
}).catch(() => {
|
||||
ElMessage.error("获取数据失败");
|
||||
})
|
||||
}
|
||||
|
||||
const add = function () {
|
||||
showDialog.value = true
|
||||
@ -263,21 +262,24 @@ const set = (filed, row) => {
|
||||
})
|
||||
}
|
||||
|
||||
const changePlatform = () => {
|
||||
let platform = null
|
||||
const selectedPlatform = ref(null)
|
||||
const changePlatform = (value) => {
|
||||
console.log(value)
|
||||
for (let v of platforms.value) {
|
||||
if (v.value === item.value.platform) {
|
||||
platform = v
|
||||
break
|
||||
if (v.value === value) {
|
||||
selectedPlatform.value = v
|
||||
item.value.api_url = v.chat_url
|
||||
}
|
||||
}
|
||||
if (platform !== null) {
|
||||
if (item.value.type === "img" && platform.img_url) {
|
||||
item.value.api_url = platform.img_url
|
||||
} else {
|
||||
item.value.api_url = platform.api_url
|
||||
}
|
||||
}
|
||||
|
||||
const changeType = (value) => {
|
||||
if (selectedPlatform.value) {
|
||||
if(value === 'img') {
|
||||
item.value.api_url = selectedPlatform.value.img_url
|
||||
} else {
|
||||
item.value.api_url = selectedPlatform.value.chat_url
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -286,6 +288,10 @@ const changePlatform = () => {
|
||||
.list {
|
||||
.handle-box {
|
||||
margin-bottom 20px
|
||||
.handle-input {
|
||||
max-width 150px;
|
||||
margin-right 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.copy-key {
|
||||
@ -306,7 +312,9 @@ const changePlatform = () => {
|
||||
|
||||
.el-form {
|
||||
.el-form-item__content {
|
||||
|
||||
.info {
|
||||
color #999999
|
||||
}
|
||||
.el-icon {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
@ -9,25 +9,25 @@
|
||||
<template #default="props">
|
||||
<div>
|
||||
<el-table :data="props.row.context" :border="childBorder">
|
||||
<el-table-column label="对话角色" prop="role" width="120"/>
|
||||
<el-table-column label="对话应用" prop="role" width="120"/>
|
||||
<el-table-column label="对话内容" prop="content"/>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="角色名称" prop="name">
|
||||
<el-table-column label="应用名称" prop="name">
|
||||
<template #default="scope">
|
||||
<span class="sort" :data-id="scope.row.id">{{ scope.row.name }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="角色标识" prop="key"/>
|
||||
<el-table-column label="应用标识" prop="key"/>
|
||||
<el-table-column label="绑定模型" prop="model_name"/>
|
||||
<el-table-column label="启用状态">
|
||||
<template #default="scope">
|
||||
<el-switch v-model="scope.row['enable']" @change="roleSet('enable',scope.row)"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="角色图标" prop="icon">
|
||||
<el-table-column label="应用图标" prop="icon">
|
||||
<template #default="scope">
|
||||
<el-image :src="scope.row.icon" style="width: 45px; height: 45px; border-radius: 50%"/>
|
||||
</template>
|
||||
@ -36,7 +36,7 @@
|
||||
<el-table-column label="操作" width="150" align="right">
|
||||
<template #default="scope">
|
||||
<el-button size="small" type="primary" @click="rowEdit(scope.$index, scope.row)">编辑</el-button>
|
||||
<el-popconfirm title="确定要删除当前角色吗?" @confirm="removeRole(scope.row)" :width="200">
|
||||
<el-popconfirm title="确定要删除当前应用吗?" @confirm="removeRole(scope.row)" :width="200">
|
||||
<template #reference>
|
||||
<el-button size="small" type="danger">删除</el-button>
|
||||
</template>
|
||||
@ -53,21 +53,21 @@
|
||||
width="50%"
|
||||
>
|
||||
<el-form :model="role" label-width="120px" ref="formRef" label-position="left" :rules="rules">
|
||||
<el-form-item label="角色名称:" prop="name">
|
||||
<el-form-item label="应用名称:" prop="name">
|
||||
<el-input
|
||||
v-model="role.name"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="角色标志:" prop="key">
|
||||
<el-form-item label="应用标志:" prop="key">
|
||||
<el-input
|
||||
v-model="role.key"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="角色图标:" prop="icon">
|
||||
<el-form-item label="应用图标:" prop="icon">
|
||||
<el-input v-model="role.icon">
|
||||
<template #append>
|
||||
<el-upload
|
||||
@ -107,7 +107,7 @@
|
||||
<el-form-item label="上下文信息:" prop="context">
|
||||
<template #default>
|
||||
<el-table :data="role.context" :border="childBorder" size="small">
|
||||
<el-table-column label="对话角色" width="120">
|
||||
<el-table-column label="对话应用" width="120">
|
||||
<template #default="scope">
|
||||
<el-input
|
||||
v-model="scope.row.role"
|
||||
@ -133,6 +133,8 @@
|
||||
<template #default="scope">
|
||||
<div class="context-msg-content">
|
||||
<el-input
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
v-model="scope.row.content"
|
||||
autocomplete="off"
|
||||
/>
|
||||
@ -181,8 +183,8 @@ const loading = ref(true)
|
||||
|
||||
const rules = reactive({
|
||||
name: [{required: true, message: '请输入用户名', trigger: 'blur',}],
|
||||
key: [{required: true, message: '请输入角色标识', trigger: 'blur',}],
|
||||
icon: [{required: true, message: '请输入角色图标', trigger: 'blur',}],
|
||||
key: [{required: true, message: '请输入应用标识', trigger: 'blur',}],
|
||||
icon: [{required: true, message: '请输入应用图标', trigger: 'blur',}],
|
||||
sort: [
|
||||
{required: true, message: '请输入排序数字', trigger: 'blur'},
|
||||
{type: 'number', message: '请输入有效数字'},
|
||||
@ -204,13 +206,13 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
const fetchData = () => {
|
||||
// 获取角色列表
|
||||
// 获取应用列表
|
||||
httpGet('/api/admin/role/list').then((res) => {
|
||||
tableData.value = res.data
|
||||
sortedTableData.value = copyObj(tableData.value)
|
||||
loading.value = false
|
||||
}).catch(() => {
|
||||
ElMessage.error("获取聊天角色失败");
|
||||
ElMessage.error("获取聊天应用失败");
|
||||
})
|
||||
|
||||
const drawBodyWrapper = document.querySelector('.el-table__body tbody')
|
||||
@ -250,14 +252,14 @@ const roleSet = (filed, row) => {
|
||||
// 编辑
|
||||
const curIndex = ref(0)
|
||||
const rowEdit = function (index, row) {
|
||||
optTitle.value = "修改角色"
|
||||
optTitle.value = "修改应用"
|
||||
curIndex.value = index
|
||||
role.value = copyObj(row)
|
||||
showDialog.value = true
|
||||
}
|
||||
|
||||
const addRole = function () {
|
||||
optTitle.value = "添加新角色"
|
||||
optTitle.value = "添加新应用"
|
||||
role.value = {context: []}
|
||||
showDialog.value = true
|
||||
}
|
@ -163,11 +163,8 @@
|
||||
:model="item.model"
|
||||
:content="item.content"/>
|
||||
<chat-reply v-else-if="item.type==='reply'"
|
||||
:icon="item.icon"
|
||||
:org-content="item.orgContent"
|
||||
:created-at="dateFormat(item['created_at'])"
|
||||
:tokens="item['tokens']"
|
||||
:content="item.content"/>
|
||||
:read-only="true"
|
||||
:data="item"/>
|
||||
</div>
|
||||
</div><!-- end chat box -->
|
||||
</el-dialog>
|
||||
@ -291,8 +288,7 @@ const removeMessage = function (row) {
|
||||
})
|
||||
}
|
||||
|
||||
const latexPlugin = require('markdown-it-latex2img')
|
||||
const mathjaxPlugin = require('markdown-it-mathjax')
|
||||
const mathjaxPlugin = require('markdown-it-mathjax3')
|
||||
const md = require('markdown-it')({
|
||||
breaks: true,
|
||||
html: true,
|
||||
@ -312,7 +308,6 @@ const md = require('markdown-it')({
|
||||
return `<pre class="code-container"><code class="language-${lang} hljs">${preCode}</code></pre>`
|
||||
}
|
||||
});
|
||||
md.use(latexPlugin)
|
||||
md.use(mathjaxPlugin)
|
||||
|
||||
const showContentDialog = ref(false)
|
||||
|
@ -2,6 +2,16 @@
|
||||
<div class="container model-list" v-loading="loading">
|
||||
|
||||
<div class="handle-box">
|
||||
<el-select v-model="query.platform" placeholder="平台" class="handle-input">
|
||||
<el-option
|
||||
v-for="item in platforms"
|
||||
:key="item.value"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<el-button :icon="Search" @click="fetchData">搜索</el-button>
|
||||
<el-button type="primary" :icon="Plus" @click="add">新增</el-button>
|
||||
</div>
|
||||
|
||||
@ -198,12 +208,13 @@ import {onMounted, onUnmounted, reactive, ref} from "vue";
|
||||
import {httpGet, httpPost} from "@/utils/http";
|
||||
import {ElMessage} from "element-plus";
|
||||
import {dateFormat, removeArrayItem, substr} from "@/utils/libs";
|
||||
import {DocumentCopy, InfoFilled, Plus} from "@element-plus/icons-vue";
|
||||
import {DocumentCopy, InfoFilled, Plus,Search} from "@element-plus/icons-vue";
|
||||
import {Sortable} from "sortablejs";
|
||||
import ClipboardJS from "clipboard";
|
||||
|
||||
// 变量定义
|
||||
const items = ref([])
|
||||
const query = ref({platform:''})
|
||||
const item = ref({})
|
||||
const showDialog = ref(false)
|
||||
const title = ref("")
|
||||
@ -214,15 +225,7 @@ const rules = reactive({
|
||||
})
|
||||
const loading = ref(true)
|
||||
const formRef = ref(null)
|
||||
const platforms = ref([
|
||||
{name: "【OpenAI】ChatGPT", value: "OpenAI"},
|
||||
{name: "【讯飞】星火大模型", value: "XunFei"},
|
||||
{name: "【清华智普】ChatGLM", value: "ChatGLM"},
|
||||
{name: "【百度】文心一言", value: "Baidu"},
|
||||
{name: "【微软】Azure", value: "Azure"},
|
||||
{name: "【阿里】通义千问", value: "QWen"},
|
||||
|
||||
])
|
||||
const platforms = ref([])
|
||||
|
||||
// 获取 API KEY
|
||||
const apiKeys = ref([])
|
||||
@ -234,7 +237,7 @@ httpGet('/api/admin/apikey/list?status=true&type=chat').then(res => {
|
||||
|
||||
// 获取数据
|
||||
const fetchData = () => {
|
||||
httpGet('/api/admin/model/list').then((res) => {
|
||||
httpGet('/api/admin/model/list', query.value).then((res) => {
|
||||
if (res.data) {
|
||||
// 初始化数据
|
||||
const arr = res.data;
|
||||
@ -287,6 +290,12 @@ onMounted(() => {
|
||||
clipboard.value.on('error', () => {
|
||||
ElMessage.error('复制失败!');
|
||||
})
|
||||
|
||||
httpGet("/api/admin/config/get/app").then(res => {
|
||||
platforms.value = res.data.platforms
|
||||
}).catch(e =>{
|
||||
ElMessage.error("获取配置失败:"+e.message)
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
@ -352,6 +361,10 @@ const remove = function (row) {
|
||||
|
||||
.handle-box {
|
||||
margin-bottom 20px
|
||||
.handle-input {
|
||||
max-width 150px;
|
||||
margin-right 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.cell {
|
||||
|
@ -44,6 +44,20 @@
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="随机背景">
|
||||
<el-switch v-model="system['rand_bg']"/>
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
content="打开之后前端首页将使用随机壁纸作为背景图"
|
||||
raw-content
|
||||
placement="right"
|
||||
>
|
||||
<el-icon>
|
||||
<InfoFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="注册方式" prop="register_ways">
|
||||
<el-checkbox-group v-model="system['register_ways']">
|
||||
<el-checkbox value="mobile">手机注册</el-checkbox>
|
||||
@ -298,16 +312,22 @@
|
||||
<el-descriptions
|
||||
v-if="license.is_active"
|
||||
class="margin-top"
|
||||
title="授权信息"
|
||||
:column="3"
|
||||
title="已授权信息"
|
||||
:column="1"
|
||||
border
|
||||
>
|
||||
<el-descriptions-item :span="3" :width="150">
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<div class="cell-item">License Key</div>
|
||||
</template>
|
||||
{{ license.key }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<div class="cell-item">机器码</div>
|
||||
</template>
|
||||
{{ license.machine_id }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<div class="cell-item">到期时间</div>
|
||||
@ -318,13 +338,15 @@
|
||||
<template #label>
|
||||
<div class="cell-item">用户人数</div>
|
||||
</template>
|
||||
{{ license.user_num }}
|
||||
{{ license.configs?.user_num }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item>
|
||||
<template #label>
|
||||
<div class="cell-item">机器码</div>
|
||||
<div class="cell-item">去版权</div>
|
||||
</template>
|
||||
{{ license.machine_id }}
|
||||
<el-icon class="selected" v-if="license.configs?.de_copy"><Select /></el-icon>
|
||||
<el-icon class="closed" v-else><CloseBold /></el-icon>
|
||||
<span class="text">去版权之后前端页面将不会显示版权信息和源码地址</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
@ -348,7 +370,7 @@ import {onMounted, reactive, ref} from "vue";
|
||||
import {httpGet, httpPost} from "@/utils/http";
|
||||
import Compressor from "compressorjs";
|
||||
import {ElMessage} from "element-plus";
|
||||
import {InfoFilled, UploadFilled} from "@element-plus/icons-vue";
|
||||
import {InfoFilled, UploadFilled,Select,CloseBold} from "@element-plus/icons-vue";
|
||||
import MdEditor from "md-editor-v3";
|
||||
import 'md-editor-v3/lib/style.css';
|
||||
import Menu from "@/views/admin/Menu.vue";
|
||||
@ -536,6 +558,23 @@ const onUploadImg = (files, callback) => {
|
||||
|
||||
.el-descriptions {
|
||||
margin-bottom 20px
|
||||
.el-icon {
|
||||
font-size 18px
|
||||
}
|
||||
.selected {
|
||||
color #0bc15f
|
||||
}
|
||||
|
||||
.closed {
|
||||
color #da0d54
|
||||
}
|
||||
.text {
|
||||
margin-left 10px
|
||||
font-size 12px
|
||||
color #999999
|
||||
position: relative;
|
||||
top -5px
|
||||
}
|
||||
}
|
||||
|
||||
.el-alert {
|
||||
|
@ -354,6 +354,8 @@ const doResetPass = () => {
|
||||
.pagination {
|
||||
padding 20px 0
|
||||
display flex
|
||||
justify-content right
|
||||
width 100%
|
||||
}
|
||||
|
||||
.el-select {
|
||||
|
@ -62,6 +62,7 @@ const model = ref('')
|
||||
const finished = ref(false)
|
||||
const error = ref(false)
|
||||
|
||||
const mathjaxPlugin = require('markdown-it-mathjax3')
|
||||
const md = require('markdown-it')({
|
||||
breaks: true,
|
||||
html: true,
|
||||
@ -86,6 +87,7 @@ const md = require('markdown-it')({
|
||||
return `<pre class="code-container"><code class="language-${lang} hljs">${preCode}</code>${copyBtn}</pre>`
|
||||
}
|
||||
});
|
||||
md.use(mathjaxPlugin)
|
||||
|
||||
const onLoad = () => {
|
||||
httpGet('/api/chat/history?chat_id=' + chatId).then(res => {
|
||||
@ -127,7 +129,7 @@ const onLoad = () => {
|
||||
};
|
||||
|
||||
</script>
|
||||
<style lang="stylus">
|
||||
<style scoped lang="stylus">
|
||||
.chat-export-mobile {
|
||||
height 100vh
|
||||
|
||||
@ -144,7 +146,7 @@ const onLoad = () => {
|
||||
|
||||
.message-list-box {
|
||||
background #F5F5F5;
|
||||
padding-bottom: 10px
|
||||
padding-bottom: 50px
|
||||
|
||||
.van-cell {
|
||||
background none
|
||||
|
@ -225,18 +225,6 @@ const newChat = (item) => {
|
||||
}
|
||||
showPicker.value = false
|
||||
const options = item.selectedOptions
|
||||
// setChatConfig({
|
||||
// role: {
|
||||
// id: options[0].value,
|
||||
// name: options[0].text,
|
||||
// icon: options[0].icon,
|
||||
// helloMsg: options[0].helloMsg
|
||||
// },
|
||||
// model: options[1].value,
|
||||
// modelValue: getModelValue(options[1].value),
|
||||
// title: '新建会话',
|
||||
// chatId: 0
|
||||
// })
|
||||
router.push({
|
||||
name: "mobile-chat-session",
|
||||
params: {role_id: options[0].value, model_id: options[1].value, title: '新建会话', chat_id: 0}
|
||||
@ -244,25 +232,6 @@ const newChat = (item) => {
|
||||
}
|
||||
|
||||
const changeChat = (chat) => {
|
||||
// let role = {}
|
||||
// for (let i = 0; i < roles.value.length; i++) {
|
||||
// if (roles.value[i].value === chat.role_id) {
|
||||
// role = roles.value[i]
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// setChatConfig({
|
||||
// role: {
|
||||
// id: chat.role_id,
|
||||
// name: role.text,
|
||||
// icon: role.icon
|
||||
// },
|
||||
// model: chat.model_id,
|
||||
// modelValue: getModelValue(chat.model_id),
|
||||
// title: chat.title,
|
||||
// chatId: chat.chat_id,
|
||||
// helloMsg: chat.hello_msg,
|
||||
// })
|
||||
router.push(`/mobile/chat/session?chat_id=${chat.chat_id}`)
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ httpGet('/api/model/list').then(res => {
|
||||
models.value[i].mValue = models.value[i].value
|
||||
models.value[i].value = models.value[i].id
|
||||
}
|
||||
modelValue.value = getModelValue(modelId.value)
|
||||
modelValue.value = getModelName(modelId.value)
|
||||
// 加载角色列表
|
||||
httpGet(`/api/role/list`).then((res) => {
|
||||
roles.value = res.data;
|
||||
@ -236,6 +236,7 @@ const newChat = (item) => {
|
||||
const options = item.selectedOptions
|
||||
roleId.value = options[0].value
|
||||
modelId.value = options[1].value
|
||||
modelValue.value = getModelName(modelId.value)
|
||||
chatId.value = ""
|
||||
chatData.value = []
|
||||
role.value = getRoleById(roleId.value)
|
||||
@ -248,8 +249,7 @@ const loading = ref(false)
|
||||
const finished = ref(false)
|
||||
const error = ref(false)
|
||||
|
||||
const latexPlugin = require('markdown-it-latex2img')
|
||||
const mathjaxPlugin = require('markdown-it-mathjax')
|
||||
const mathjaxPlugin = require('markdown-it-mathjax3')
|
||||
const md = require('markdown-it')({
|
||||
breaks: true,
|
||||
html: true,
|
||||
@ -274,7 +274,6 @@ const md = require('markdown-it')({
|
||||
return `<pre class="code-container"><code class="language-${lang} hljs">${preCode}</code>${copyBtn}</pre>`
|
||||
}
|
||||
});
|
||||
md.use(latexPlugin)
|
||||
md.use(mathjaxPlugin)
|
||||
|
||||
|
||||
@ -537,7 +536,7 @@ const shareChat = (option) => {
|
||||
showToast({message: "当前会话已经导出,请通过浏览器或者微信的自带分享功能分享给好友", duration: 5000})
|
||||
router.push({
|
||||
path: "/mobile/chat/export",
|
||||
query: {title: title, chat_id: chatId, role: role.value.name, model: modelValue}
|
||||
query: {title: title.value, chat_id: chatId.value, role: role.value.name, model: modelValue.value}
|
||||
})
|
||||
} else if (option.icon === "link") {
|
||||
document.getElementById('copy-link-btn').click();
|
||||
@ -553,10 +552,10 @@ const getRoleById = function (rid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const getModelValue = (model_id) => {
|
||||
const getModelName = (model_id) => {
|
||||
for (let i = 0; i < models.value.length; i++) {
|
||||
if (models.value[i].id === model_id) {
|
||||
return models.value[i].mValue
|
||||
return models.value[i].text
|
||||
}
|
||||
}
|
||||
return ""
|
||||
|
@ -8,7 +8,7 @@
|
||||
<image-sd/>
|
||||
</van-tab>
|
||||
<van-tab title="DALL" name="dall">
|
||||
<van-empty description="功能正在开发中"/>
|
||||
<image-dall />
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
@ -18,6 +18,7 @@
|
||||
import {ref} from "vue";
|
||||
import ImageMj from "@/views/mobile/pages/ImageMj.vue";
|
||||
import ImageSd from "@/views/mobile/pages/ImageSd.vue";
|
||||
import ImageDall from "@/views/mobile/pages/ImageDall.vue";
|
||||
|
||||
const activeName = ref("mj")
|
||||
</script>
|
||||
@ -30,4 +31,4 @@ const activeName = ref("mj")
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
473
web/src/views/mobile/pages/ImageDall.vue
Normal file
473
web/src/views/mobile/pages/ImageDall.vue
Normal file
@ -0,0 +1,473 @@
|
||||
<template>
|
||||
<div class="mobile-sd">
|
||||
<van-form @submit="generate">
|
||||
<van-cell-group inset>
|
||||
<div>
|
||||
<van-field
|
||||
v-model="quality"
|
||||
is-link
|
||||
label="图片质量"
|
||||
placeholder="选择图片质量"
|
||||
@click="showQualityPicker = true"
|
||||
/>
|
||||
<van-popup v-model:show="showQualityPicker" position="bottom" teleport="#app">
|
||||
<van-picker
|
||||
:columns="qualities"
|
||||
@cancel="showQualityPicker = false"
|
||||
@confirm="qualityConfirm"
|
||||
/>
|
||||
</van-popup>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<van-field
|
||||
v-model="size"
|
||||
is-link
|
||||
label="图片尺寸"
|
||||
placeholder="选择图片尺寸"
|
||||
@click="showSizePicker = true"
|
||||
/>
|
||||
<van-popup v-model:show="showSizePicker" position="bottom" teleport="#app">
|
||||
<van-picker
|
||||
:columns="sizes"
|
||||
@cancel="showSizePicker = false"
|
||||
@confirm="sizeConfirm"
|
||||
/>
|
||||
</van-popup>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<van-field
|
||||
v-model="style"
|
||||
is-link
|
||||
label="图片样式"
|
||||
placeholder="选择图片样式"
|
||||
@click="showStylePicker = true"
|
||||
/>
|
||||
<van-popup v-model:show="showStylePicker" position="bottom" teleport="#app">
|
||||
<van-picker
|
||||
:columns="styles"
|
||||
@cancel="showStylePicker = false"
|
||||
@confirm="styleConfirm"
|
||||
/>
|
||||
</van-popup>
|
||||
</div>
|
||||
|
||||
<van-field
|
||||
v-model="params.prompt"
|
||||
rows="3"
|
||||
autosize
|
||||
type="textarea"
|
||||
placeholder="请在此输入绘画提示词,系统会自动翻译中文提示词,高手请直接输入英文提示词"
|
||||
/>
|
||||
|
||||
<div class="text-line pt-6">
|
||||
<el-tag>绘图消耗{{ dallPower }}算力,当前算力:{{ power }}</el-tag>
|
||||
</div>
|
||||
|
||||
<div class="text-line">
|
||||
<van-button round block type="primary" native-type="submit">
|
||||
立即生成
|
||||
</van-button>
|
||||
</div>
|
||||
</van-cell-group>
|
||||
</van-form>
|
||||
|
||||
<h3>任务列表</h3>
|
||||
<div class="running-job-list">
|
||||
<van-empty v-if="runningJobs.length ===0"
|
||||
image="https://fastly.jsdelivr.net/npm/@vant/assets/custom-empty-image.png"
|
||||
image-size="80"
|
||||
description="暂无记录"
|
||||
/>
|
||||
<van-grid :gutter="10" :column-num="3" v-else>
|
||||
<van-grid-item v-for="item in runningJobs">
|
||||
<div v-if="item.progress > 0">
|
||||
<van-image :src="item['img_url']">
|
||||
<template v-slot:error>加载失败</template>
|
||||
</van-image>
|
||||
<div class="progress">
|
||||
<van-circle
|
||||
v-model:current-rate="item.progress"
|
||||
:rate="item.progress"
|
||||
:speed="100"
|
||||
:text="item.progress+'%'"
|
||||
:stroke-width="60"
|
||||
size="90px"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="task-in-queue">
|
||||
<span class="icon"><i class="iconfont icon-quick-start"></i></span>
|
||||
<span class="text">排队中</span>
|
||||
</div>
|
||||
|
||||
</van-grid-item>
|
||||
</van-grid>
|
||||
</div>
|
||||
|
||||
<h3>创作记录</h3>
|
||||
<div class="finish-job-list">
|
||||
<van-empty v-if="finishedJobs.length ===0"
|
||||
image="https://fastly.jsdelivr.net/npm/@vant/assets/custom-empty-image.png"
|
||||
image-size="80"
|
||||
description="暂无记录"
|
||||
/>
|
||||
|
||||
<van-list v-else
|
||||
v-model:error="error"
|
||||
v-model:loading="loading"
|
||||
:finished="finished"
|
||||
error-text="请求失败,点击重新加载"
|
||||
finished-text="没有更多了"
|
||||
@load="onLoad"
|
||||
>
|
||||
<van-grid :gutter="10" :column-num="2">
|
||||
<van-grid-item v-for="item in finishedJobs">
|
||||
<div class="job-item">
|
||||
<van-image
|
||||
:src="item['img_url']"
|
||||
:class="item['can_opt'] ? '' : 'upscale'"
|
||||
lazy-load
|
||||
@click="imageView(item)"
|
||||
fit="cover">
|
||||
<template v-slot:loading>
|
||||
<van-loading type="spinner" size="20"/>
|
||||
</template>
|
||||
</van-image>
|
||||
|
||||
<div class="remove">
|
||||
<el-button type="danger" :icon="Delete" @click="removeImage($event, item)" circle/>
|
||||
<el-button type="warning" v-if="item.publish" @click="publishImage($event,item, false)"
|
||||
circle>
|
||||
<i class="iconfont icon-cancel-share"></i>
|
||||
</el-button>
|
||||
<el-button type="success" v-else @click="publishImage($event, item, true)" circle>
|
||||
<i class="iconfont icon-share-bold"></i>
|
||||
</el-button>
|
||||
<el-button type="primary" @click="showPrompt(item)" circle>
|
||||
<i class="iconfont icon-prompt"></i>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</van-grid-item>
|
||||
</van-grid>
|
||||
</van-list>
|
||||
|
||||
</div>
|
||||
<button style="display: none" class="copy-prompt-dall" :data-clipboard-text="prompt" id="copy-btn-dall">复制</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {onMounted, onUnmounted, ref} from "vue"
|
||||
import {Delete} from "@element-plus/icons-vue";
|
||||
import {httpGet, httpPost} from "@/utils/http";
|
||||
import Clipboard from "clipboard";
|
||||
import {checkSession} from "@/action/session";
|
||||
import {useRouter} from "vue-router";
|
||||
import {getSessionId} from "@/store/session";
|
||||
import {
|
||||
showConfirmDialog,
|
||||
showDialog,
|
||||
showFailToast,
|
||||
showImagePreview,
|
||||
showNotify,
|
||||
showSuccessToast,
|
||||
showToast
|
||||
} from "vant";
|
||||
import {showLoginDialog} from "@/utils/libs";
|
||||
|
||||
const listBoxHeight = ref(window.innerHeight - 40)
|
||||
const mjBoxHeight = ref(window.innerHeight - 150)
|
||||
const item = ref({})
|
||||
const isLogin = ref(false)
|
||||
const activeColspan = ref([""])
|
||||
|
||||
window.onresize = () => {
|
||||
listBoxHeight.value = window.innerHeight - 40
|
||||
mjBoxHeight.value = window.innerHeight - 150
|
||||
}
|
||||
|
||||
const qualities = [
|
||||
{text: "标准", value: "standard"},
|
||||
{text: "高清", value: "hd"},
|
||||
]
|
||||
const sizes = [
|
||||
{text:"1024x1024",value:"1024x1024"},
|
||||
{text:"1792x1024",value:"1792x1024"},
|
||||
{text: "1024x1792",value:"1024x1792"},
|
||||
]
|
||||
const styles = [
|
||||
{text: "生动", value: "vivid"},
|
||||
{text: "自然", value: "natural"}
|
||||
]
|
||||
const params = ref({
|
||||
quality: qualities[0].value,
|
||||
size: sizes[0].value,
|
||||
style: styles[0].value,
|
||||
prompt: ""
|
||||
})
|
||||
const quality = ref(qualities[0].text)
|
||||
const size = ref(sizes[0].text)
|
||||
const style = ref(styles[0].text)
|
||||
|
||||
const showQualityPicker = ref(false)
|
||||
const showStylePicker = ref(false)
|
||||
const showSizePicker = ref(false)
|
||||
|
||||
|
||||
const runningJobs = ref([])
|
||||
const finishedJobs = ref([])
|
||||
const router = useRouter()
|
||||
const power = ref(0)
|
||||
const dallPower = ref(0) // 画一张 DALL 图片消耗算力
|
||||
|
||||
const socket = ref(null)
|
||||
const userId = ref(0)
|
||||
const heartbeatHandle = ref(null)
|
||||
const connect = () => {
|
||||
let host = process.env.VUE_APP_WS_HOST
|
||||
if (host === '') {
|
||||
if (location.protocol === 'https:') {
|
||||
host = 'wss://' + location.host;
|
||||
} else {
|
||||
host = 'ws://' + location.host;
|
||||
}
|
||||
}
|
||||
|
||||
// 心跳函数
|
||||
const sendHeartbeat = () => {
|
||||
clearTimeout(heartbeatHandle.value)
|
||||
new Promise((resolve, reject) => {
|
||||
if (socket.value !== null) {
|
||||
socket.value.send(JSON.stringify({type: "heartbeat", content: "ping"}))
|
||||
}
|
||||
resolve("success")
|
||||
}).then(() => {
|
||||
heartbeatHandle.value = setTimeout(() => sendHeartbeat(), 5000)
|
||||
});
|
||||
}
|
||||
|
||||
const _socket = new WebSocket(host + `/api/dall/client?user_id=${userId.value}`);
|
||||
_socket.addEventListener('open', () => {
|
||||
socket.value = _socket;
|
||||
|
||||
// 发送心跳消息
|
||||
sendHeartbeat()
|
||||
});
|
||||
|
||||
_socket.addEventListener('message', event => {
|
||||
if (event.data instanceof Blob) {
|
||||
fetchRunningJobs()
|
||||
finished.value = false
|
||||
page.value = 1
|
||||
fetchFinishJobs(page.value)
|
||||
}
|
||||
});
|
||||
|
||||
_socket.addEventListener('close', () => {
|
||||
if (socket.value !== null) {
|
||||
connect()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const clipboard = ref(null)
|
||||
const prompt = ref('')
|
||||
onMounted(() => {
|
||||
initData()
|
||||
clipboard.value = new Clipboard(".copy-prompt-dall");
|
||||
clipboard.value.on('success', () => {
|
||||
showNotify({type: 'success', message: '复制成功', duration: 1000})
|
||||
})
|
||||
clipboard.value.on('error', () => {
|
||||
showNotify({type: 'danger', message: '复制失败', duration: 2000})
|
||||
})
|
||||
|
||||
httpGet("/api/config/get?key=system").then(res => {
|
||||
dallPower.value = res.data.dall_power
|
||||
}).catch(e => {
|
||||
showNotify({type: "danger", message: "获取系统配置失败:" + e.message})
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
clipboard.value.destroy()
|
||||
if (socket.value !== null) {
|
||||
socket.value.close()
|
||||
socket.value = null
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const initData = () => {
|
||||
checkSession().then(user => {
|
||||
power.value = user['power']
|
||||
userId.value = user.id
|
||||
isLogin.value = true
|
||||
fetchRunningJobs()
|
||||
fetchFinishJobs(1)
|
||||
connect()
|
||||
}).catch(() => {
|
||||
loading.value = false
|
||||
});
|
||||
}
|
||||
|
||||
const fetchRunningJobs = () => {
|
||||
// 获取运行中的任务
|
||||
httpGet(`/api/dall/jobs?status=0`).then(res => {
|
||||
const jobs = res.data
|
||||
const _jobs = []
|
||||
for (let i = 0; i < jobs.length; i++) {
|
||||
if (jobs[i].progress === -1) {
|
||||
showNotify({
|
||||
message: `任务ID:${jobs[i]['task_id']} 原因:${jobs[i]['err_msg']}`,
|
||||
type: 'danger',
|
||||
})
|
||||
power.value += dallPower.value
|
||||
continue
|
||||
}
|
||||
_jobs.push(jobs[i])
|
||||
}
|
||||
runningJobs.value = _jobs
|
||||
}).catch(e => {
|
||||
showNotify({type: "danger", message: "获取任务失败:" + e.message})
|
||||
})
|
||||
}
|
||||
|
||||
const loading = ref(false)
|
||||
const finished = ref(false)
|
||||
const error = ref(false)
|
||||
const page = ref(0)
|
||||
const pageSize = ref(10)
|
||||
// 获取已完成的任务
|
||||
const fetchFinishJobs = (page) => {
|
||||
loading.value = true
|
||||
httpGet(`/api/dall/jobs?status=1&page=${page}&page_size=${pageSize.value}`).then(res => {
|
||||
if (res.data.length < pageSize.value) {
|
||||
finished.value = true
|
||||
}
|
||||
if (page === 1) {
|
||||
finishedJobs.value = res.data
|
||||
} else {
|
||||
finishedJobs.value = finishedJobs.value.concat(res.data)
|
||||
}
|
||||
loading.value = false
|
||||
}).catch(e => {
|
||||
loading.value = false
|
||||
showNotify({type: "danger", message: "获取任务失败:" + e.message})
|
||||
})
|
||||
}
|
||||
|
||||
const onLoad = () => {
|
||||
page.value += 1
|
||||
fetchFinishJobs(page.value)
|
||||
}
|
||||
|
||||
// 创建绘图任务
|
||||
const promptRef = ref(null)
|
||||
const generate = () => {
|
||||
if (!isLogin.value) {
|
||||
return showLoginDialog(router)
|
||||
}
|
||||
|
||||
if (params.value.prompt === '') {
|
||||
promptRef.value.focus()
|
||||
return showToast("请输入绘画提示词!")
|
||||
}
|
||||
|
||||
if (!params.value.seed) {
|
||||
params.value.seed = -1
|
||||
}
|
||||
params.value.session_id = getSessionId()
|
||||
httpPost("/api/dall/image", params.value).then(() => {
|
||||
showSuccessToast("绘画任务推送成功,请耐心等待任务执行...")
|
||||
power.value -= dallPower.value
|
||||
}).catch(e => {
|
||||
showFailToast("任务推送失败:" + e.message)
|
||||
})
|
||||
}
|
||||
|
||||
const showPrompt = (item) => {
|
||||
prompt.value = item.prompt
|
||||
showConfirmDialog({
|
||||
title: "绘画提示词",
|
||||
message: item.prompt,
|
||||
confirmButtonText: "复制",
|
||||
cancelButtonText: "关闭",
|
||||
}).then(() => {
|
||||
document.querySelector('#copy-btn-dall').click()
|
||||
}).catch(() => {
|
||||
});
|
||||
}
|
||||
|
||||
const removeImage = (event, item) => {
|
||||
event.stopPropagation()
|
||||
showConfirmDialog({
|
||||
title: '标题',
|
||||
message:
|
||||
'此操作将会删除任务和图片,继续操作码?',
|
||||
}).then(() => {
|
||||
httpPost("/api/dall/remove", {id: item.id, img_url: item.img_url, user_id: userId.value}).then(() => {
|
||||
showSuccessToast("任务删除成功")
|
||||
}).catch(e => {
|
||||
showFailToast("任务删除失败:" + e.message)
|
||||
})
|
||||
}).catch(() => {
|
||||
showToast("您取消了操作")
|
||||
});
|
||||
}
|
||||
|
||||
// 发布图片到作品墙
|
||||
const publishImage = (event, item, action) => {
|
||||
event.stopPropagation()
|
||||
let text = "图片发布"
|
||||
if (action === false) {
|
||||
text = "取消发布"
|
||||
}
|
||||
httpPost("/api/dall/publish", {id: item.id, action: action}).then(() => {
|
||||
showSuccessToast(text + "成功")
|
||||
item.publish = action
|
||||
}).catch(e => {
|
||||
showFailToast(text + "失败:" + e.message)
|
||||
})
|
||||
}
|
||||
|
||||
const imageView = (item) => {
|
||||
showImagePreview([item['img_url']]);
|
||||
}
|
||||
|
||||
|
||||
const qualityConfirm = (item) => {
|
||||
params.value.quality = item.selectedOptions[0].value;
|
||||
quality.value = item.selectedOptions[0].text
|
||||
showQualityPicker.value = false
|
||||
}
|
||||
|
||||
const styleConfirm = (item) => {
|
||||
params.value.style = item.selectedOptions[0].value;
|
||||
style.value = item.selectedOptions[0].text
|
||||
showStylePicker.value = false
|
||||
}
|
||||
|
||||
const sizeConfirm =(item) => {
|
||||
params.value.size = item.selectedOptions[0].value
|
||||
size.value=item.selectedOptions[0].text
|
||||
showSizePicker.value =false
|
||||
}
|
||||
|
||||
const showInfo = (message) => {
|
||||
showDialog({
|
||||
title: "参数说明",
|
||||
message: message,
|
||||
}).then(() => {
|
||||
// on close
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
@import "@/assets/css/mobile/image-sd.styl"
|
||||
</style>
|
@ -43,8 +43,25 @@
|
||||
</van-cell>
|
||||
</van-list>
|
||||
</van-tab>
|
||||
<van-tab title="DALL" name="dalle3">
|
||||
<van-empty description="功能正在开发中"/>
|
||||
<van-tab title="DALL" name="dall">
|
||||
<van-list
|
||||
v-model:error="data['dall'].error"
|
||||
v-model:loading="data['dall'].loading"
|
||||
:finished="data['dall'].finished"
|
||||
error-text="请求失败,点击重新加载"
|
||||
finished-text="没有更多了"
|
||||
@load="onLoad"
|
||||
>
|
||||
<van-cell v-for="item in data['dall'].data" :key="item.id">
|
||||
<van-image :src="item['img_thumb']" @click="imageView(item)" fit="cover"/>
|
||||
|
||||
<div class="opt-box">
|
||||
<el-button type="primary" @click="showPrompt(item)" circle>
|
||||
<i class="iconfont icon-prompt"></i>
|
||||
</el-button>
|
||||
</div>
|
||||
</van-cell>
|
||||
</van-list>
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
@ -81,13 +98,13 @@ const data = ref({
|
||||
url: "/api/sd/imgWall",
|
||||
data: []
|
||||
},
|
||||
"dalle3": {
|
||||
"dall": {
|
||||
loading: false,
|
||||
finished: false,
|
||||
error: false,
|
||||
page: 1,
|
||||
pageSize: 12,
|
||||
url: "/api/dalle3/imgWall",
|
||||
url: "/api/dall/imgWall",
|
||||
data: []
|
||||
}
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user