merged v4.0.9 and fixed conflicts

This commit is contained in:
RockYang 2024-09-05 11:02:32 +08:00
commit 08319391ea
47 changed files with 1927 additions and 427 deletions

View File

@ -1,4 +1,15 @@
# 更新日志 # 更新日志
## v4.0.9
* 环境升级:升级 Golang 到 go1.22.4
* 功能增加:接入微信商户号支付渠道
* Bug修复修复前端页面菜单把页面撑开底部留白问题
* 功能优化:聊天页面自动根据内容调整输入框的高度
* Bug修复修复Dalle绘图失败退回算力的问题
* 功能优化:邀请码注册时被邀请人也可以获得赠送的算力
* 功能优化:允许设置邮件验证码的抬头
* Bug修复修复免费模型不会记录聊天记录的bug
* Bug修复修复聊天输入公式显示异常的Bug
## v4.0.8 ## v4.0.8
* 功能优化:升级 mathjax 公式解析插件,修复公式因为图片访问限制而无法显示的问题 * 功能优化:升级 mathjax 公式解析插件,修复公式因为图片访问限制而无法显示的问题
* 功能优化:当数据库更新失败的时候记录错误日志 * 功能优化:当数据库更新失败的时候记录错误日志

1
api/.gitignore vendored
View File

@ -18,3 +18,4 @@ data
config.toml config.toml
static/upload static/upload
storage.json storage.json
res/certs/wechat/apiclient_key.pem

View File

@ -233,6 +233,7 @@ func needLogin(c *gin.Context) bool {
c.Request.URL.Path == "/api/payment/alipay/notify" || c.Request.URL.Path == "/api/payment/alipay/notify" ||
c.Request.URL.Path == "/api/payment/hupipay/notify" || c.Request.URL.Path == "/api/payment/hupipay/notify" ||
c.Request.URL.Path == "/api/payment/payjs/notify" || c.Request.URL.Path == "/api/payment/payjs/notify" ||
c.Request.URL.Path == "/api/payment/wechat/notify" ||
c.Request.URL.Path == "/api/payment/doPay" || c.Request.URL.Path == "/api/payment/doPay" ||
c.Request.URL.Path == "/api/payment/payWays" || c.Request.URL.Path == "/api/payment/payWays" ||
strings.HasPrefix(c.Request.URL.Path, "/api/test") || strings.HasPrefix(c.Request.URL.Path, "/api/test") ||

View File

@ -30,10 +30,11 @@ type AppConfig struct {
SdConfigs []StableDiffusionConfig // sd AI draw service pool SdConfigs []StableDiffusionConfig // sd AI draw service pool
XXLConfig XXLConfig XXLConfig XXLConfig
AlipayConfig AlipayConfig AlipayConfig AlipayConfig // 支付宝支付渠道配置
HuPiPayConfig HuPiPayConfig HuPiPayConfig HuPiPayConfig // 虎皮椒支付配置
SmtpConfig SmtpConfig // 邮件发送配置 SmtpConfig SmtpConfig // 邮件发送配置
JPayConfig JPayConfig // payjs 支付配置 JPayConfig JPayConfig // payjs 支付配置
WechatPayConfig WechatPayConfig // 微信支付渠道配置
} }
type SmtpConfig struct { type SmtpConfig struct {
@ -85,6 +86,17 @@ type AlipayConfig struct {
ReturnURL string // 支付成功返回地址 ReturnURL string // 支付成功返回地址
} }
type WechatPayConfig struct {
Enabled bool // 是否启用该支付通道
AppId string // 公众号的APPID,如wxd678efh567hg6787
MchId string // 直连商户的商户号,由微信支付生成并下发
SerialNo string // 商户证书的证书序列号
PrivateKey string // 用户私钥文件路径
ApiV3Key string // API V3 秘钥
NotifyURL string // 异步通知回调
ReturnURL string // 支付成功返回地址
}
type HuPiPayConfig struct { //虎皮椒第四方支付配置 type HuPiPayConfig struct { //虎皮椒第四方支付配置
Enabled bool // 是否启用该支付通道 Enabled bool // 是否启用该支付通道
Name string // 支付名称wechat/alipay Name string // 支付名称wechat/alipay
@ -182,8 +194,9 @@ var QWen = Platform{
} }
type SystemConfig struct { type SystemConfig struct {
Title string `json:"title,omitempty"` Title string `json:"title,omitempty"` // 网站标题
AdminTitle string `json:"admin_title,omitempty"` Slogan string `json:"slogan,omitempty"` // 网站 slogan
AdminTitle string `json:"admin_title,omitempty"` // 管理后台标题
Logo string `json:"logo,omitempty"` Logo string `json:"logo,omitempty"`
InitPower int `json:"init_power,omitempty"` // 新用户注册赠送算力值 InitPower int `json:"init_power,omitempty"` // 新用户注册赠送算力值
DailyPower int `json:"daily_power,omitempty"` // 每日赠送算力 DailyPower int `json:"daily_power,omitempty"` // 每日赠送算力

View File

@ -28,7 +28,6 @@ type MjTask struct {
TaskId string `json:"task_id"` TaskId string `json:"task_id"`
ImgArr []string `json:"img_arr"` ImgArr []string `json:"img_arr"`
ChannelId string `json:"channel_id"` ChannelId string `json:"channel_id"`
SessionId string `json:"session_id"`
Type TaskType `json:"type"` Type TaskType `json:"type"`
UserId int `json:"user_id"` UserId int `json:"user_id"`
Prompt string `json:"prompt,omitempty"` Prompt string `json:"prompt,omitempty"`
@ -42,7 +41,6 @@ type MjTask struct {
type SdTask struct { type SdTask struct {
Id int `json:"id"` // job 数据库ID Id int `json:"id"` // job 数据库ID
SessionId string `json:"session_id"`
Type TaskType `json:"type"` Type TaskType `json:"type"`
UserId int `json:"user_id"` UserId int `json:"user_id"`
Params SdTaskParams `json:"params"` Params SdTaskParams `json:"params"`

View File

@ -19,7 +19,6 @@ require (
github.com/pkoukk/tiktoken-go v0.1.1-0.20230418101013-cae809389480 github.com/pkoukk/tiktoken-go v0.1.1-0.20230418101013-cae809389480
github.com/qiniu/go-sdk/v7 v7.17.1 github.com/qiniu/go-sdk/v7 v7.17.1
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/smartwalle/alipay/v3 v3.2.15
go.uber.org/zap v1.23.0 go.uber.org/zap v1.23.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/natefinch/lumberjack.v2 v2.2.1
gorm.io/driver/mysql v1.4.7 gorm.io/driver/mysql v1.4.7
@ -28,6 +27,7 @@ require (
require github.com/xxl-job/xxl-job-executor-go v1.2.0 require github.com/xxl-job/xxl-job-executor-go v1.2.0
require ( require (
github.com/go-pay/gopay v1.5.101
github.com/mojocn/base64Captcha v1.3.1 github.com/mojocn/base64Captcha v1.3.1
github.com/shirou/gopsutil v3.21.11+incompatible github.com/shirou/gopsutil v3.21.11+incompatible
github.com/shopspring/decimal v1.3.1 github.com/shopspring/decimal v1.3.1
@ -37,6 +37,11 @@ require (
require ( require (
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-pay/crypto v0.0.1 // indirect
github.com/go-pay/errgroup v0.0.2 // indirect
github.com/go-pay/util v0.0.2 // indirect
github.com/go-pay/xlog v0.0.2 // indirect
github.com/go-pay/xtime v0.0.2 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect github.com/tklauser/go-sysconf v0.3.14 // indirect
@ -79,9 +84,6 @@ require (
github.com/refraction-networking/utls v1.3.2 // indirect github.com/refraction-networking/utls v1.3.2 // indirect
github.com/rs/xid v1.5.0 // indirect github.com/rs/xid v1.5.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartwalle/ncrypto v1.0.2 // indirect
github.com/smartwalle/ngx v1.0.6 // indirect
github.com/smartwalle/nsign v1.0.8 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
go.uber.org/dig v1.16.1 // indirect go.uber.org/dig v1.16.1 // indirect
golang.org/x/arch v0.3.0 // indirect golang.org/x/arch v0.3.0 // indirect

View File

@ -45,6 +45,18 @@ 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-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 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-pay/crypto v0.0.1 h1:B6InT8CLfSLc6nGRVx9VMJRBBazFMjr293+jl0lLXUY=
github.com/go-pay/crypto v0.0.1/go.mod h1:41oEIvHMKbNcYlWUlRWtsnC6+ASgh7u29z0gJXe5bes=
github.com/go-pay/errgroup v0.0.2 h1:5mZMdm0TDClDm2S3G0/sm0f8AuQRtz0dOrTHDR9R8Cc=
github.com/go-pay/errgroup v0.0.2/go.mod h1:0+4b8mvFMS71MIzsaC+gVvB4x37I93lRb2dqrwuU8x8=
github.com/go-pay/gopay v1.5.101 h1:rVb+sfv6hiQtknAlZnTTLvU27NvFJ4p0yglN/vPpGXI=
github.com/go-pay/gopay v1.5.101/go.mod h1:AW4Yj8jDZX9BM1/GTLTY1Gy5SHjiq8kQvG5sBTN2sxI=
github.com/go-pay/util v0.0.2 h1:goJ4f6kNY5zzdtg1Cj8oWC+Cw7bfg/qq2rJangMAb9U=
github.com/go-pay/util v0.0.2/go.mod h1:qM8VbyF1n7YAPZBSJONSPMPsPedhUTktewUAdf1AjPg=
github.com/go-pay/xlog v0.0.2 h1:kUg5X8/5VZAPDg1J5eGjA3MG0/H5kK6Ew0dW/Bycsws=
github.com/go-pay/xlog v0.0.2/go.mod h1:DbjMADPK4+Sjxj28ekK9goqn4zmyY4hql/zRiab+S9E=
github.com/go-pay/xtime v0.0.2 h1:7YR4/iuELsEHpJ6LUO0SVK80hQxDO9MLCfuVYIiTCRM=
github.com/go-pay/xtime v0.0.2/go.mod h1:W1yRbJaSt4CSBcdAtLBQ8xajiN/Pl5hquGczUcUE9xE=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 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 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
@ -186,14 +198,6 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/smartwalle/alipay/v3 v3.2.15 h1:3fvFJnINKKAOXHR/Iv20k1Z7KJ+nOh3oK214lELPqG8=
github.com/smartwalle/alipay/v3 v3.2.15/go.mod h1:niTNB609KyUYuAx9Bex/MawEjv2yPx4XOjxSAkqmGjE=
github.com/smartwalle/ncrypto v1.0.2 h1:pTAhCqtPCMhpOwFXX+EcMdR6PNzruBNoGQrN2S1GbGI=
github.com/smartwalle/ncrypto v1.0.2/go.mod h1:Dwlp6sfeNaPMnOxMNayMTacvC5JGEVln3CVdiVDgbBk=
github.com/smartwalle/ngx v1.0.6 h1:JPNqNOIj+2nxxFtrSkJO+vKJfeNUSEQueck/Wworjps=
github.com/smartwalle/ngx v1.0.6/go.mod h1:mx/nz2Pk5j+RBs7t6u6k22MPiBG/8CtOMpCnALIG8Y0=
github.com/smartwalle/nsign v1.0.8 h1:78KWtwKPrdt4Xsn+tNEBVxaTLIJBX9YRX0ZSrMUeuHo=
github.com/smartwalle/nsign v1.0.8/go.mod h1:eY6I4CJlyNdVMP+t6z1H6Jpd4m5/V+8xi44ufSTxXgc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=

View File

@ -330,7 +330,7 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio
Content: prompt, Content: prompt,
}) })
req.Input["messages"] = reqMgs req.Input["messages"] = reqMgs
} else if session.Model.Platform == types.OpenAI.Value { // extract image for gpt-vision model } else if session.Model.Platform == types.OpenAI.Value || session.Model.Platform == types.Azure.Value { // extract image for gpt-vision model
imgURLs := utils.ExtractImgURL(prompt) imgURLs := utils.ExtractImgURL(prompt)
logger.Debugf("detected IMG: %+v", imgURLs) logger.Debugf("detected IMG: %+v", imgURLs)
var content interface{} var content interface{}
@ -651,10 +651,10 @@ func (h *ChatHandler) saveChatHistory(
logger.Error("failed to save reply history message: ", res.Error) logger.Error("failed to save reply history message: ", res.Error)
} }
if session.Model.Power > 0 {
// 更新用户算力 // 更新用户算力
if session.Model.Power > 0 {
h.subUserPower(userVo, session, promptToken, replyTokens) h.subUserPower(userVo, session, promptToken, replyTokens)
}
// 保存当前会话 // 保存当前会话
var chatItem model.ChatItem var chatItem model.ChatItem
res = h.DB.Where("chat_id = ?", session.ChatId).First(&chatItem) res = h.DB.Where("chat_id = ?", session.ChatId).First(&chatItem)
@ -671,7 +671,6 @@ func (h *ChatHandler) saveChatHistory(
chatItem.Model = req.Model chatItem.Model = req.Model
h.DB.Create(&chatItem) h.DB.Create(&chatItem)
} }
}
} }
// 将AI回复消息中生成的图片链接下载到本地 // 将AI回复消息中生成的图片链接下载到本地

View File

@ -142,7 +142,7 @@ func (h *ChatHandler) sendOpenAiMessage(
} }
if toolCall { // 调用函数完成任务 if toolCall { // 调用函数完成任务
var params map[string]interface{} params := make(map[string]interface{})
_ = utils.JsonDecode(strings.Join(arguments, ""), &params) _ = utils.JsonDecode(strings.Join(arguments, ""), &params)
logger.Debugf("函数名称: %s, 函数参数:%s", function.Name, params) logger.Debugf("函数名称: %s, 函数参数:%s", function.Name, params)
params["user_id"] = userVo.Id params["user_id"] = userVo.Id

View File

@ -183,29 +183,12 @@ func (h *MarkMapHandler) sendMessage(client *types.WsClient, prompt string, mode
utils.ReplyChunkMessage(client, types.WsMessage{Type: types.WsEnd}) utils.ReplyChunkMessage(client, types.WsMessage{Type: types.WsEnd})
} else { } else {
body, err := io.ReadAll(response.Body) body, _ := io.ReadAll(response.Body)
if err != nil { return fmt.Errorf("请求 OpenAI API 失败:%s", string(body))
return fmt.Errorf("读取响应失败: %v", err)
}
var res types.ApiError
err = json.Unmarshal(body, &res)
if err != nil {
return fmt.Errorf("解析响应失败: %v", err)
}
// OpenAI API 调用异常处理
if strings.Contains(res.Error.Message, "This key is associated with a deactivated account") {
// remove key
h.DB.Where("value = ?", apiKey).Delete(&model.ApiKey{})
return errors.New("请求 OpenAI API 失败API KEY 所关联的账户被禁用。")
} else if strings.Contains(res.Error.Message, "You exceeded your current quota") {
return errors.New("请求 OpenAI API 失败API KEY 触发并发限制,请稍后再试。")
} else {
return fmt.Errorf("请求 OpenAI API 失败:%v", res.Error.Message)
}
} }
// 扣减算力 // 扣减算力
if chatModel.Power > 0 {
res = h.DB.Model(&model.User{}).Where("id", userId).UpdateColumn("power", gorm.Expr("power - ?", chatModel.Power)) res = h.DB.Model(&model.User{}).Where("id", userId).UpdateColumn("power", gorm.Expr("power - ?", chatModel.Power))
if res.Error == nil { if res.Error == nil {
// 记录算力消费日志 // 记录算力消费日志
@ -223,6 +206,7 @@ func (h *MarkMapHandler) sendMessage(client *types.WsClient, prompt string, mode
CreatedAt: time.Now(), CreatedAt: time.Now(),
}) })
} }
}
return nil return nil
} }
@ -235,7 +219,7 @@ func (h *MarkMapHandler) doRequest(req types.ApiRequest, chatModel model.ChatMod
} }
// use the last unused key // use the last unused key
if apiKey.Id == 0 { if apiKey.Id == 0 {
res = h.DB.Where("platform", types.OpenAI). res = h.DB.Where("platform", types.OpenAI.Value).
Where("type", "chat"). Where("type", "chat").
Where("enabled", true).Order("last_used_at ASC").First(apiKey) Where("enabled", true).Order("last_used_at ASC").First(apiKey)
} }

View File

@ -205,7 +205,6 @@ func (h *MidJourneyHandler) Image(c *gin.Context) {
h.pool.PushTask(types.MjTask{ h.pool.PushTask(types.MjTask{
Id: job.Id, Id: job.Id,
TaskId: taskId, TaskId: taskId,
SessionId: data.SessionId,
Type: types.TaskType(data.TaskType), Type: types.TaskType(data.TaskType),
Prompt: data.Prompt, Prompt: data.Prompt,
NegPrompt: data.NegPrompt, NegPrompt: data.NegPrompt,
@ -283,7 +282,6 @@ func (h *MidJourneyHandler) Upscale(c *gin.Context) {
h.pool.PushTask(types.MjTask{ h.pool.PushTask(types.MjTask{
Id: job.Id, Id: job.Id,
SessionId: data.SessionId,
Type: types.TaskUpscale, Type: types.TaskUpscale,
Prompt: data.Prompt, Prompt: data.Prompt,
UserId: userId, UserId: userId,
@ -350,7 +348,6 @@ func (h *MidJourneyHandler) Variation(c *gin.Context) {
h.pool.PushTask(types.MjTask{ h.pool.PushTask(types.MjTask{
Id: job.Id, Id: job.Id,
SessionId: data.SessionId,
Type: types.TaskVariation, Type: types.TaskVariation,
Prompt: data.Prompt, Prompt: data.Prompt,
UserId: userId, UserId: userId,

View File

@ -29,10 +29,16 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
) )
const ( type PayWay struct {
PayWayAlipay = "支付宝" Name string `json:"name"`
PayWayXunHu = "虎皮椒" Value string `json:"value"`
PayWayJs = "PayJS" }
var (
PayWayAlipay = PayWay{Name: "支付宝", Value: "alipay"}
PayWayXunHu = PayWay{Name: "虎皮椒", Value: "hupi"}
PayWayJs = PayWay{Name: "PayJS", Value: "payjs"}
PayWayWechat = PayWay{Name: "微信支付", Value: "wechat"}
) )
// PaymentHandler 支付服务回调 handler // PaymentHandler 支付服务回调 handler
@ -40,7 +46,8 @@ type PaymentHandler struct {
BaseHandler BaseHandler
alipayService *payment.AlipayService alipayService *payment.AlipayService
huPiPayService *payment.HuPiPayService huPiPayService *payment.HuPiPayService
js *payment.PayJS jsPayService *payment.JPayService
wechatPayService *payment.WechatPayService
snowflake *service.Snowflake snowflake *service.Snowflake
fs embed.FS fs embed.FS
lock sync.Mutex lock sync.Mutex
@ -51,14 +58,16 @@ func NewPaymentHandler(
server *core.AppServer, server *core.AppServer,
alipayService *payment.AlipayService, alipayService *payment.AlipayService,
huPiPayService *payment.HuPiPayService, huPiPayService *payment.HuPiPayService,
js *payment.PayJS, jsPayService *payment.JPayService,
wechatPayService *payment.WechatPayService,
db *gorm.DB, db *gorm.DB,
snowflake *service.Snowflake, snowflake *service.Snowflake,
fs embed.FS) *PaymentHandler { fs embed.FS) *PaymentHandler {
return &PaymentHandler{ return &PaymentHandler{
alipayService: alipayService, alipayService: alipayService,
huPiPayService: huPiPayService, huPiPayService: huPiPayService,
js: js, jsPayService: jsPayService,
wechatPayService: wechatPayService,
snowflake: snowflake, snowflake: snowflake,
fs: fs, fs: fs,
lock: sync.Mutex{}, lock: sync.Mutex{},
@ -108,13 +117,10 @@ func (h *PaymentHandler) DoPay(c *gin.Context) {
// 更新扫码状态 // 更新扫码状态
h.DB.Model(&order).UpdateColumn("status", types.OrderScanned) h.DB.Model(&order).UpdateColumn("status", types.OrderScanned)
if payWay == "alipay" { // 支付宝
// 生成支付链接
notifyURL := h.App.Config.AlipayConfig.NotifyURL
returnURL := "" // 关闭同步回跳
amount := fmt.Sprintf("%.2f", order.Amount)
uri, err := h.alipayService.PayUrlMobile(order.OrderNo, notifyURL, returnURL, amount, order.Subject) if payWay == "alipay" { // 支付宝
amount := fmt.Sprintf("%.2f", order.Amount)
uri, err := h.alipayService.PayUrlMobile(order.OrderNo, amount, order.Subject)
if err != nil { if err != nil {
resp.ERROR(c, "error with generate pay url: "+err.Error()) resp.ERROR(c, "error with generate pay url: "+err.Error())
return return
@ -214,14 +220,21 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
var notifyURL string var notifyURL string
switch data.PayWay { switch data.PayWay {
case "hupi": case "hupi":
payWay = PayWayXunHu payWay = PayWayXunHu.Value
notifyURL = h.App.Config.HuPiPayConfig.NotifyURL notifyURL = h.App.Config.HuPiPayConfig.NotifyURL
break
case "payjs": case "payjs":
payWay = PayWayJs payWay = PayWayJs.Value
notifyURL = h.App.Config.JPayConfig.NotifyURL notifyURL = h.App.Config.JPayConfig.NotifyURL
default: break
payWay = PayWayAlipay case "alipay":
payWay = PayWayAlipay.Value
notifyURL = h.App.Config.AlipayConfig.NotifyURL notifyURL = h.App.Config.AlipayConfig.NotifyURL
break
default:
payWay = PayWayWechat.Value
notifyURL = h.App.Config.WechatPayConfig.NotifyURL
} }
// 创建订单 // 创建订单
remark := types.OrderRemark{ remark := types.OrderRemark{
@ -257,7 +270,7 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
OutTradeNo: order.OrderNo, OutTradeNo: order.OrderNo,
Subject: product.Name, Subject: product.Name,
} }
r := h.js.Pay(params) r := h.jsPayService.Pay(params)
if r.IsOK() { if r.IsOK() {
resp.SUCCESS(c, gin.H{"order_no": order.OrderNo, "image": r.Qrcode}) resp.SUCCESS(c, gin.H{"order_no": order.OrderNo, "image": r.Qrcode})
return return
@ -276,6 +289,8 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
} else { } else {
logo = "res/img/alipay.jpg" logo = "res/img/alipay.jpg"
} }
} else if data.PayWay == "wechat" {
logo = "res/img/wechat-pay.jpg"
} }
file, err := h.fs.Open(logo) file, err := h.fs.Open(logo)
@ -292,7 +307,18 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) {
timestamp := time.Now().Unix() timestamp := time.Now().Unix()
signStr := fmt.Sprintf("%s-%s-%d-%s", orderNo, data.PayWay, timestamp, h.signKey) signStr := fmt.Sprintf("%s-%s-%d-%s", orderNo, data.PayWay, timestamp, h.signKey)
sign := utils.Sha256(signStr) 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) var imageURL string
if data.PayWay == "wechat" {
payUrl, err := h.wechatPayService.PayUrlNative(order.OrderNo, int(math.Floor(order.Amount*100)), product.Name)
if err != nil {
resp.ERROR(c, "error with generating wechat payment qrcode: "+err.Error())
return
} else {
imageURL = payUrl
}
} else {
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) imgData, err := utils.GenQrcode(imageURL, 400, file)
if err != nil { if err != nil {
resp.ERROR(c, err.Error()) resp.ERROR(c, err.Error())
@ -339,7 +365,7 @@ func (h *PaymentHandler) Mobile(c *gin.Context) {
var payURL string var payURL string
switch data.PayWay { switch data.PayWay {
case "hupi": case "hupi":
payWay = PayWayXunHu payWay = PayWayXunHu.Name
notifyURL = h.App.Config.HuPiPayConfig.NotifyURL notifyURL = h.App.Config.HuPiPayConfig.NotifyURL
returnURL = h.App.Config.HuPiPayConfig.ReturnURL returnURL = h.App.Config.HuPiPayConfig.ReturnURL
parse, _ := url.Parse(h.App.Config.HuPiPayConfig.ReturnURL) parse, _ := url.Parse(h.App.Config.HuPiPayConfig.ReturnURL)
@ -358,13 +384,14 @@ func (h *PaymentHandler) Mobile(c *gin.Context) {
} }
r, err := h.huPiPayService.Pay(params) r, err := h.huPiPayService.Pay(params)
if err != nil { if err != nil {
logger.Error("error with generating Pay URL: ", err.Error()) errMsg := "error with generating Pay Hupi URL: " + err.Error()
resp.ERROR(c, "error with generating Pay URL: "+err.Error()) logger.Error(errMsg)
resp.ERROR(c, errMsg)
return return
} }
payURL = r.URL payURL = r.URL
case "payjs": case "payjs":
payWay = PayWayJs payWay = PayWayJs.Name
notifyURL = h.App.Config.JPayConfig.NotifyURL notifyURL = h.App.Config.JPayConfig.NotifyURL
returnURL = h.App.Config.JPayConfig.ReturnURL returnURL = h.App.Config.JPayConfig.ReturnURL
totalFee := decimal.NewFromFloat(product.Price).Sub(decimal.NewFromFloat(product.Discount)).Mul(decimal.NewFromInt(100)).IntPart() totalFee := decimal.NewFromFloat(product.Price).Sub(decimal.NewFromFloat(product.Discount)).Mul(decimal.NewFromInt(100)).IntPart()
@ -374,14 +401,22 @@ func (h *PaymentHandler) Mobile(c *gin.Context) {
params.Add("body", product.Name) params.Add("body", product.Name)
params.Add("notify_url", notifyURL) params.Add("notify_url", notifyURL)
params.Add("auto", "0") params.Add("auto", "0")
payURL = h.js.PayH5(params) payURL = h.jsPayService.PayH5(params)
case "alipay": case "alipay":
payWay = PayWayAlipay payWay = PayWayAlipay.Name
notifyURL = h.App.Config.AlipayConfig.NotifyURL payURL, err = h.alipayService.PayUrlMobile(orderNo, fmt.Sprintf("%.2f", amount), product.Name)
returnURL = h.App.Config.AlipayConfig.ReturnURL
payURL, err = h.alipayService.PayUrlMobile(orderNo, notifyURL, returnURL, fmt.Sprintf("%.2f", amount), product.Name)
if err != nil { if err != nil {
resp.ERROR(c, "error with generating Pay URL: "+err.Error()) errMsg := "error with generating Alipay URL: " + err.Error()
resp.ERROR(c, errMsg)
return
}
case "wechat":
payWay = PayWayWechat.Name
payURL, err = h.wechatPayService.PayUrlH5(orderNo, int(amount*100), product.Name, c.ClientIP())
if err != nil {
errMsg := "error with generating Wechat URL: " + err.Error()
logger.Error(errMsg)
resp.ERROR(c, errMsg)
return return
} }
default: default:
@ -493,7 +528,7 @@ func (h *PaymentHandler) notify(orderNo string, tradeNo string) error {
h.DB.Model(&model.Product{}).Where("id = ?", order.ProductId).UpdateColumn("sales", gorm.Expr("sales + ?", 1)) h.DB.Model(&model.Product{}).Where("id = ?", order.ProductId).UpdateColumn("sales", gorm.Expr("sales + ?", 1))
// 记录算力充值日志 // 记录算力充值日志
if opt != "" { if power > 0 {
h.DB.Create(&model.PowerLog{ h.DB.Create(&model.PowerLog{
UserId: user.Id, UserId: user.Id,
Username: user.Username, Username: user.Username,
@ -522,6 +557,9 @@ func (h *PaymentHandler) GetPayWays(c *gin.Context) {
if h.App.Config.JPayConfig.Enabled { if h.App.Config.JPayConfig.Enabled {
data["payjs"] = gin.H{"name": h.App.Config.JPayConfig.Name} data["payjs"] = gin.H{"name": h.App.Config.JPayConfig.Name}
} }
if h.App.Config.WechatPayConfig.Enabled {
data["wechat"] = gin.H{"name": "wechat"}
}
resp.SUCCESS(c, data) resp.SUCCESS(c, data)
} }
@ -560,7 +598,7 @@ func (h *PaymentHandler) AlipayNotify(c *gin.Context) {
} }
// TODO验证交易签名 // TODO验证交易签名
res := h.alipayService.TradeVerify(c.Request.Form) res := h.alipayService.TradeVerify(c.Request)
logger.Infof("验证支付结果:%+v", res) logger.Infof("验证支付结果:%+v", res)
if !res.Success() { if !res.Success() {
logger.Error("订单校验失败:", res.Message) logger.Error("订单校验失败:", res.Message)
@ -588,7 +626,7 @@ func (h *PaymentHandler) PayJsNotify(c *gin.Context) {
orderNo := c.Request.Form.Get("out_trade_no") orderNo := c.Request.Form.Get("out_trade_no")
returnCode := c.Request.Form.Get("return_code") returnCode := c.Request.Form.Get("return_code")
logger.Infof("收到订单支付回调,订单 NO%s支付结果代码%v", orderNo, returnCode) logger.Infof("收到PayJs订单支付回调,订单 NO%s支付结果代码%v", orderNo, returnCode)
// 支付失败 // 支付失败
if returnCode != "1" { if returnCode != "1" {
return return
@ -596,7 +634,7 @@ func (h *PaymentHandler) PayJsNotify(c *gin.Context) {
// 校验订单支付状态 // 校验订单支付状态
tradeNo := c.Request.Form.Get("payjs_order_id") tradeNo := c.Request.Form.Get("payjs_order_id")
err = h.js.Check(tradeNo) err = h.jsPayService.TradeVerify(tradeNo)
if err != nil { if err != nil {
logger.Error("订单校验失败:", err) logger.Error("订单校验失败:", err)
c.String(http.StatusOK, "fail") c.String(http.StatusOK, "fail")
@ -611,3 +649,30 @@ func (h *PaymentHandler) PayJsNotify(c *gin.Context) {
c.String(http.StatusOK, "success") c.String(http.StatusOK, "success")
} }
// WechatPayNotify 微信商户支付异步回调
func (h *PaymentHandler) WechatPayNotify(c *gin.Context) {
err := c.Request.ParseForm()
if err != nil {
c.String(http.StatusOK, "fail")
return
}
result := h.wechatPayService.TradeVerify(c.Request)
if !result.Success() {
logger.Error("订单校验失败:", err)
c.JSON(http.StatusBadRequest, gin.H{
"code": "FAIL",
"message": err.Error(),
})
return
}
err = h.notify(result.OutTradeNo, result.TradeId)
if err != nil {
c.String(http.StatusOK, "fail")
return
}
c.String(http.StatusOK, "success")
}

View File

@ -169,7 +169,6 @@ func (h *SdJobHandler) Image(c *gin.Context) {
h.pool.PushTask(types.SdTask{ h.pool.PushTask(types.SdTask{
Id: int(job.Id), Id: int(job.Id),
SessionId: data.SessionId,
Type: types.TaskImage, Type: types.TaskImage,
Params: params, Params: params,
UserId: userId, UserId: userId,

View File

@ -9,9 +9,9 @@ import (
type TestHandler struct { type TestHandler struct {
db *gorm.DB db *gorm.DB
snowflake *service.Snowflake snowflake *service.Snowflake
js *payment.PayJS js *payment.JPayService
} }
func NewTestHandler(db *gorm.DB, snowflake *service.Snowflake, js *payment.PayJS) *TestHandler { func NewTestHandler(db *gorm.DB, snowflake *service.Snowflake, js *payment.JPayService) *TestHandler {
return &TestHandler{db: db, snowflake: snowflake, js: js} return &TestHandler{db: db, snowflake: snowflake, js: js}
} }

View File

@ -109,7 +109,6 @@ func (h *UserHandler) Register(c *gin.Context) {
user := model.User{ user := model.User{
Username: data.Username, Username: data.Username,
Password: utils.GenPassword(data.Password, salt), Password: utils.GenPassword(data.Password, salt),
Nickname: fmt.Sprintf("极客学长@%d", utils.RandomNumber(6)),
Avatar: "/images/avatar/user.png", Avatar: "/images/avatar/user.png",
Salt: salt, Salt: salt,
Status: true, Status: true,
@ -118,6 +117,16 @@ func (h *UserHandler) Register(c *gin.Context) {
Power: h.App.SysConfig.InitPower, Power: h.App.SysConfig.InitPower,
} }
// 被邀请人也获得赠送算力
if data.InviteCode != "" {
user.Power += h.App.SysConfig.InvitePower
}
if h.licenseService.GetLicense().Configs.DeCopy {
user.Username = fmt.Sprintf("用户@%d", utils.RandomNumber(6))
} else {
user.Nickname = fmt.Sprintf("极客学长@%d", utils.RandomNumber(6))
}
res = h.DB.Create(&user) res = h.DB.Create(&user)
if res.Error != nil { if res.Error != nil {
resp.ERROR(c, "保存数据失败") resp.ERROR(c, "保存数据失败")

View File

@ -211,7 +211,8 @@ func main() {
fx.Provide(payment.NewAlipayService), fx.Provide(payment.NewAlipayService),
fx.Provide(payment.NewHuPiPay), fx.Provide(payment.NewHuPiPay),
fx.Provide(payment.NewPayJS), fx.Provide(payment.NewJPayService),
fx.Provide(payment.NewWechatService),
fx.Provide(service.NewSnowflake), fx.Provide(service.NewSnowflake),
fx.Provide(service.NewXXLJobExecutor), fx.Provide(service.NewXXLJobExecutor),
fx.Invoke(func(exec *service.XXLJobExecutor, config *types.AppConfig) { fx.Invoke(func(exec *service.XXLJobExecutor, config *types.AppConfig) {
@ -373,6 +374,7 @@ func main() {
group.POST("alipay/notify", h.AlipayNotify) group.POST("alipay/notify", h.AlipayNotify)
group.POST("hupipay/notify", h.HuPiPayNotify) group.POST("hupipay/notify", h.HuPiPayNotify)
group.POST("payjs/notify", h.PayJsNotify) group.POST("payjs/notify", h.PayJsNotify)
group.POST("wechat/notify", h.WechatPayNotify)
}), }),
fx.Invoke(func(s *core.AppServer, h *admin.ProductHandler) { fx.Invoke(func(s *core.AppServer, h *admin.ProductHandler) {
group := s.Engine.Group("/api/admin/product/") group := s.Engine.Group("/api/admin/product/")

View File

@ -109,25 +109,43 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) {
logger.Debugf("绘画参数:%+v", task) logger.Debugf("绘画参数:%+v", task)
prompt := task.Prompt prompt := task.Prompt
// translate prompt // translate prompt
if utils.HasChinese(task.Prompt) { if utils.HasChinese(prompt) {
content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.RewritePromptTemplate, task.Prompt)) content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.RewritePromptTemplate, prompt))
if err != nil { if err == nil {
return "", fmt.Errorf("error with translate prompt: %v", err)
}
prompt = content prompt = content
logger.Debugf("重写后提示词:%s", prompt) logger.Debugf("重写后提示词:%s", prompt)
} }
}
var user model.User var user model.User
s.db.Where("id", task.UserId).First(&user) s.db.Where("id", task.UserId).First(&user)
if user.Power < task.Power { if user.Power < task.Power {
return "", errors.New("insufficient of power") return "", errors.New("insufficient of power")
} }
// 更新用户算力
tx := s.db.Model(&model.User{}).Where("id", user.Id).UpdateColumn("power", gorm.Expr("power - ?", task.Power))
// 记录算力变化日志
if tx.Error == nil && tx.RowsAffected > 0 {
var u model.User
s.db.Where("id", user.Id).First(&u)
s.db.Create(&model.PowerLog{
UserId: user.Id,
Username: user.Username,
Type: types.PowerConsume,
Amount: task.Power,
Balance: u.Power,
Mark: types.PowerSub,
Model: "dall-e-3",
Remark: fmt.Sprintf("绘画提示词:%s", utils.CutWords(task.Prompt, 10)),
CreatedAt: time.Now(),
})
}
// get image generation API KEY // get image generation API KEY
var apiKey model.ApiKey var apiKey model.ApiKey
tx := s.db.Where("platform", types.OpenAI.Value). tx = s.db.Where("type", "img").
Where("type", "img").
Where("enabled", true). Where("enabled", true).
Order("last_used_at ASC").First(&apiKey) Order("last_used_at ASC").First(&apiKey)
if tx.Error != nil { if tx.Error != nil {
@ -139,25 +157,28 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) {
if len(apiKey.ProxyURL) > 5 { if len(apiKey.ProxyURL) > 5 {
s.httpClient.SetProxyURL(apiKey.ProxyURL).R() s.httpClient.SetProxyURL(apiKey.ProxyURL).R()
} }
logger.Infof("Sending %s request, ApiURL:%s, API KEY:%s, PROXY: %s", apiKey.Platform, apiKey.ApiURL, apiKey.Value, apiKey.ProxyURL) reqBody := imgReq{
r, err := s.httpClient.R().SetHeader("Content-Type", "application/json").
SetHeader("Authorization", "Bearer "+apiKey.Value).
SetBody(imgReq{
Model: "dall-e-3", Model: "dall-e-3",
Prompt: prompt, Prompt: prompt,
N: 1, N: 1,
Size: task.Size, Size: task.Size,
Style: task.Style, Style: task.Style,
Quality: task.Quality, Quality: task.Quality,
}). }
SetErrorResult(&errRes). logger.Infof("Sending %s request, ApiURL:%s, API KEY:%s, BODY: %+v", apiKey.Platform, apiKey.ApiURL, apiKey.Value, reqBody)
SetSuccessResult(&res).Post(apiKey.ApiURL) request := s.httpClient.R().SetHeader("Content-Type", "application/json")
if apiKey.Platform == types.Azure.Value {
request = request.SetHeader("api-key", apiKey.Value)
} else {
request = request.SetHeader("Authorization", "Bearer "+apiKey.Value)
}
r, err := request.SetBody(reqBody).SetErrorResult(&errRes).SetSuccessResult(&res).Post(apiKey.ApiURL)
if err != nil { if err != nil {
return "", fmt.Errorf("error with send request: %v", err) return "", fmt.Errorf("error with send request: %v", err)
} }
if r.IsErrorState() { if r.IsErrorState() {
return "", fmt.Errorf("error with send request: %v", errRes.Error) return "", fmt.Errorf("error with send request, status: %s, %+v", r.Status, errRes.Error)
} }
// update the api key last use time // update the api key last use time
s.db.Model(&apiKey).UpdateColumn("last_used_at", time.Now().Unix()) s.db.Model(&apiKey).UpdateColumn("last_used_at", time.Now().Unix())
@ -181,25 +202,6 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) {
content = fmt.Sprintf("```\n%s\n```\n下面是我为你创作的图片\n\n![](%s)\n", prompt, imgURL) content = fmt.Sprintf("```\n%s\n```\n下面是我为你创作的图片\n\n![](%s)\n", prompt, imgURL)
} }
// 更新用户算力
tx = s.db.Model(&model.User{}).Where("id", user.Id).UpdateColumn("power", gorm.Expr("power - ?", task.Power))
// 记录算力变化日志
if tx.Error == nil && tx.RowsAffected > 0 {
var u model.User
s.db.Where("id", user.Id).First(&u)
s.db.Create(&model.PowerLog{
UserId: user.Id,
Username: user.Username,
Type: types.PowerConsume,
Amount: task.Power,
Balance: u.Power,
Mark: types.PowerSub,
Model: "dall-e-3",
Remark: fmt.Sprintf("绘画提示词:%s", utils.CutWords(task.Prompt, 10)),
CreatedAt: time.Now(),
})
}
return content, nil return content, nil
} }

View File

@ -91,7 +91,7 @@ func (s *LicenseService) SyncLicense() {
if err != nil { if err != nil {
retryCounter++ retryCounter++
if retryCounter < 5 { if retryCounter < 5 {
logger.Error(err) logger.Warn(err)
} }
s.license.IsActive = false s.license.IsActive = false
} else { } else {

View File

@ -179,14 +179,14 @@ func (p *ServicePool) HasAvailableService() bool {
// SyncTaskProgress 异步拉取任务 // SyncTaskProgress 异步拉取任务
func (p *ServicePool) SyncTaskProgress() { func (p *ServicePool) SyncTaskProgress() {
go func() { go func() {
var items []model.MidJourneyJob var jobs []model.MidJourneyJob
for { for {
res := p.db.Where("progress < ?", 100).Find(&items) res := p.db.Where("progress < ?", 100).Find(&jobs)
if res.Error != nil { if res.Error != nil {
continue continue
} }
for _, job := range items { for _, job := range jobs {
// 失败或者 30 分钟还没完成的任务删除并退回算力 // 失败或者 30 分钟还没完成的任务删除并退回算力
if time.Now().Sub(job.CreatedAt) > time.Minute*30 || job.Progress == -1 { if time.Now().Sub(job.CreatedAt) > time.Minute*30 || job.Progress == -1 {
p.db.Delete(&job) p.db.Delete(&job)

View File

@ -8,12 +8,13 @@ package payment
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
import ( import (
"context"
"fmt" "fmt"
"geekai/core/types" "geekai/core/types"
logger2 "geekai/logger" logger2 "geekai/logger"
"github.com/smartwalle/alipay/v3" "github.com/go-pay/gopay"
"log" "github.com/go-pay/gopay/alipay"
"net/url" "net/http"
"os" "os"
) )
@ -35,93 +36,90 @@ func NewAlipayService(appConfig *types.AppConfig) (*AlipayService, error) {
return nil, fmt.Errorf("error with read App Private key: %v", err) return nil, fmt.Errorf("error with read App Private key: %v", err)
} }
xClient, err := alipay.New(config.AppId, priKey, !config.SandBox) client, err := alipay.NewClient(config.AppId, priKey, !config.SandBox)
if err != nil { if err != nil {
return nil, fmt.Errorf("error with initialize alipay service: %v", err) return nil, fmt.Errorf("error with initialize alipay service: %v", err)
} }
if err = xClient.LoadAppCertPublicKeyFromFile(config.PublicKey); err != nil { //client.DebugSwitch = gopay.DebugOn // 开启调试模式
return nil, fmt.Errorf("error with loading App PublicKey: %v", err) client.SetLocation(alipay.LocationShanghai). // 设置时区,不设置或出错均为默认服务器时间
} SetCharset(alipay.UTF8). // 设置字符编码,不设置默认 utf-8
if err = xClient.LoadAliPayRootCertFromFile(config.RootCert); err != nil { SetSignType(alipay.RSA2). // 设置签名类型,不设置默认 RSA2
return nil, fmt.Errorf("error with loading alipay RootCert: %v", err) SetReturnUrl(config.ReturnURL). // 设置返回URL
} SetNotifyUrl(config.NotifyURL)
if err = xClient.LoadAlipayCertPublicKeyFromFile(config.AlipayPublicKey); err != nil {
return nil, fmt.Errorf("error with loading Alipay PublicKey: %v", err) if err = client.SetCertSnByPath(config.PublicKey, config.RootCert, config.AlipayPublicKey); err != nil {
return nil, fmt.Errorf("error with load payment public key: %v", err)
} }
return &AlipayService{config: &config, client: xClient}, nil return &AlipayService{config: &config, client: client}, nil
} }
func (s *AlipayService) PayUrlMobile(outTradeNo string, notifyURL string, returnURL string, Amount string, subject string) (string, error) { func (s *AlipayService) PayUrlMobile(outTradeNo string, amount string, subject string) (string, error) {
var p = alipay.TradeWapPay{} bm := make(gopay.BodyMap)
p.NotifyURL = notifyURL bm.Set("subject", subject)
p.ReturnURL = returnURL bm.Set("out_trade_no", outTradeNo)
p.Subject = subject bm.Set("quit_url", s.config.ReturnURL)
p.OutTradeNo = outTradeNo bm.Set("total_amount", amount)
p.TotalAmount = Amount bm.Set("product_code", "QUICK_WAP_WAY")
p.ProductCode = "QUICK_WAP_WAY" return s.client.TradeWapPay(context.Background(), bm)
res, err := s.client.TradeWapPay(p)
if err != nil {
return "", err
}
return res.String(), err
} }
func (s *AlipayService) PayUrlPc(outTradeNo string, notifyURL string, returnURL string, amount string, subject string) (string, error) { func (s *AlipayService) PayUrlPc(outTradeNo string, amount string, subject string) (string, error) {
var p = alipay.TradePagePay{} bm := make(gopay.BodyMap)
p.NotifyURL = notifyURL bm.Set("subject", subject)
p.ReturnURL = returnURL bm.Set("out_trade_no", outTradeNo)
p.Subject = subject bm.Set("total_amount", amount)
p.OutTradeNo = outTradeNo bm.Set("product_code", "FAST_INSTANT_TRADE_PAY")
p.TotalAmount = amount return s.client.TradePagePay(context.Background(), bm)
p.ProductCode = "FAST_INSTANT_TRADE_PAY"
res, err := s.client.TradePagePay(p)
if err != nil {
return "", nil
}
return res.String(), err
} }
// TradeVerify 交易验证 // TradeVerify 交易验证
func (s *AlipayService) TradeVerify(reqForm url.Values) NotifyVo { func (s *AlipayService) TradeVerify(request *http.Request) NotifyVo {
err := s.client.VerifySign(reqForm) notifyReq, err := alipay.ParseNotifyToBodyMap(request) // c.Request 是 gin 框架的写法
if err != nil { if err != nil {
log.Println("异步通知验证签名发生错误", err)
return NotifyVo{ return NotifyVo{
Status: 0, Status: Failure,
Message: "异步通知验证签名发生错误", Message: "error with parse notify request: " + err.Error(),
} }
} }
return s.TradeQuery(reqForm.Get("out_trade_no")) _, err = alipay.VerifySignWithCert(s.config.AlipayPublicKey, notifyReq)
if err != nil {
return NotifyVo{
Status: Failure,
Message: "error with verify sign: " + err.Error(),
}
}
return s.TradeQuery(request.Form.Get("out_trade_no"))
} }
func (s *AlipayService) TradeQuery(outTradeNo string) NotifyVo { func (s *AlipayService) TradeQuery(outTradeNo string) NotifyVo {
var p = alipay.TradeQuery{} bm := make(gopay.BodyMap)
p.OutTradeNo = outTradeNo bm.Set("out_trade_no", outTradeNo)
rsp, err := s.client.TradeQuery(p)
//查询订单
rsp, err := s.client.TradeQuery(context.Background(), bm)
if err != nil { if err != nil {
return NotifyVo{ return NotifyVo{
Status: 0, Status: Failure,
Message: "异步查询验证订单信息发生错误" + outTradeNo + err.Error(), Message: "异步查询验证订单信息发生错误" + outTradeNo + err.Error(),
} }
} }
if rsp.IsSuccess() == true && rsp.TradeStatus == "TRADE_SUCCESS" { if rsp.Response.TradeStatus == "TRADE_SUCCESS" {
return NotifyVo{ return NotifyVo{
Status: 1, Status: Success,
OutTradeNo: rsp.OutTradeNo, OutTradeNo: rsp.Response.OutTradeNo,
TradeNo: rsp.TradeNo, TradeId: rsp.Response.TradeNo,
Amount: rsp.TotalAmount, Amount: rsp.Response.TotalAmount,
Subject: rsp.Subject, Subject: rsp.Response.Subject,
Message: "OK", Message: "OK",
} }
} else { } else {
return NotifyVo{ return NotifyVo{
Status: 0, Status: Failure,
Message: "异步查询验证订单信息发生错误" + outTradeNo, Message: "异步查询验证订单信息发生错误" + outTradeNo,
} }
} }
@ -134,16 +132,3 @@ func readKey(filename string) (string, error) {
} }
return string(data), nil return string(data), nil
} }
type NotifyVo struct {
Status int
OutTradeNo string
TradeNo string
Amount string
Message string
Subject string
}
func (v NotifyVo) Success() bool {
return v.Status == 1
}

View File

@ -21,12 +21,12 @@ import (
"strings" "strings"
) )
type PayJS struct { type JPayService struct {
config *types.JPayConfig config *types.JPayConfig
} }
func NewPayJS(appConfig *types.AppConfig) *PayJS { func NewJPayService(appConfig *types.AppConfig) *JPayService {
return &PayJS{ return &JPayService{
config: &appConfig.JPayConfig, config: &appConfig.JPayConfig,
} }
} }
@ -53,7 +53,7 @@ func (r JPayReps) IsOK() bool {
return r.ReturnMsg == "SUCCESS" return r.ReturnMsg == "SUCCESS"
} }
func (js *PayJS) Pay(param JPayReq) JPayReps { func (js *JPayService) Pay(param JPayReq) JPayReps {
param.NotifyURL = js.config.NotifyURL param.NotifyURL = js.config.NotifyURL
var p = url.Values{} var p = url.Values{}
encode := utils.JsonEncode(param) encode := utils.JsonEncode(param)
@ -86,13 +86,13 @@ func (js *PayJS) Pay(param JPayReq) JPayReps {
return data return data
} }
func (js *PayJS) PayH5(p url.Values) string { func (js *JPayService) PayH5(p url.Values) string {
p.Add("mchid", js.config.AppId) p.Add("mchid", js.config.AppId)
p.Add("sign", js.sign(p)) p.Add("sign", js.sign(p))
return fmt.Sprintf("%s/api/cashier?%s", js.config.ApiURL, p.Encode()) return fmt.Sprintf("%s/api/cashier?%s", js.config.ApiURL, p.Encode())
} }
func (js *PayJS) sign(params url.Values) string { func (js *JPayService) sign(params url.Values) string {
params.Del(`sign`) params.Del(`sign`)
var keys = make([]string, 0, 0) var keys = make([]string, 0, 0)
for key := range params { for key := range params {
@ -117,20 +117,18 @@ func (js *PayJS) sign(params url.Values) string {
return strings.ToUpper(md5res) return strings.ToUpper(md5res)
} }
// Check 查询订单支付状态 // TradeVerify 查询订单支付状态
// @param tradeNo 支付平台交易 ID // @param tradeNo 支付平台交易 ID
func (js *PayJS) Check(tradeNo string) error { func (js *JPayService) TradeVerify(tradeNo string) error {
apiURL := fmt.Sprintf("%s/api/check", js.config.ApiURL) apiURL := fmt.Sprintf("%s/api/check", js.config.ApiURL)
params := url.Values{} params := url.Values{}
params.Add("payjs_order_id", tradeNo) params.Add("payjs_order_id", tradeNo)
params.Add("sign", js.sign(params)) params.Add("sign", js.sign(params))
data := strings.NewReader(params.Encode()) data := strings.NewReader(params.Encode())
resp, err := http.Post(apiURL, "application/x-www-form-urlencoded", data) resp, err := http.Post(apiURL, "application/x-www-form-urlencoded", data)
defer resp.Body.Close()
if err != nil { if err != nil {
return fmt.Errorf("error with http reqeust: %v", err) return fmt.Errorf("error with http reqeust: %v", err)
} }
defer resp.Body.Close() defer resp.Body.Close()
body, err := io.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {

View File

@ -0,0 +1,19 @@
package payment
type NotifyVo struct {
Status int
OutTradeNo string // 商户订单号
TradeId string // 交易ID
Amount string // 交易金额
Message string
Subject string
}
func (v NotifyVo) Success() bool {
return v.Status == Success
}
const (
Success = 0
Failure = 1
)

View File

@ -0,0 +1,135 @@
package payment
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// * 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 (
"context"
"fmt"
"geekai/core/types"
"github.com/go-pay/gopay"
"github.com/go-pay/gopay/wechat/v3"
"net/http"
"time"
)
type WechatPayService struct {
config *types.WechatPayConfig
client *wechat.ClientV3
}
func NewWechatService(appConfig *types.AppConfig) (*WechatPayService, error) {
config := appConfig.WechatPayConfig
if !config.Enabled {
logger.Info("Disabled WechatPay service")
return nil, nil
}
priKey, err := readKey(config.PrivateKey)
if err != nil {
return nil, fmt.Errorf("error with read App Private key: %v", err)
}
client, err := wechat.NewClientV3(config.MchId, config.SerialNo, config.ApiV3Key, priKey)
if err != nil {
return nil, fmt.Errorf("error with initialize WechatPay service: %v", err)
}
err = client.AutoVerifySign()
if err != nil {
return nil, fmt.Errorf("error with autoVerifySign: %v", err)
}
//client.DebugSwitch = gopay.DebugOn
return &WechatPayService{config: &config, client: client}, nil
}
func (s *WechatPayService) PayUrlNative(outTradeNo string, amount int, subject string) (string, error) {
expire := time.Now().Add(10 * time.Minute).Format(time.RFC3339)
// 初始化 BodyMap
bm := make(gopay.BodyMap)
bm.Set("appid", s.config.AppId).
Set("mchid", s.config.MchId).
Set("description", subject).
Set("out_trade_no", outTradeNo).
Set("time_expire", expire).
Set("notify_url", s.config.NotifyURL).
SetBodyMap("amount", func(bm gopay.BodyMap) {
bm.Set("total", amount).
Set("currency", "CNY")
})
wxRsp, err := s.client.V3TransactionNative(context.Background(), bm)
if err != nil {
return "", fmt.Errorf("error with client v3 transaction Native: %v", err)
}
if wxRsp.Code != wechat.Success {
return "", fmt.Errorf("error status with generating pay url: %v", wxRsp.Error)
}
return wxRsp.Response.CodeUrl, nil
}
func (s *WechatPayService) PayUrlH5(outTradeNo string, amount int, subject string, ip string) (string, error) {
expire := time.Now().Add(10 * time.Minute).Format(time.RFC3339)
// 初始化 BodyMap
bm := make(gopay.BodyMap)
bm.Set("appid", s.config.AppId).
Set("mchid", s.config.MchId).
Set("description", subject).
Set("out_trade_no", outTradeNo).
Set("time_expire", expire).
Set("notify_url", s.config.NotifyURL).
SetBodyMap("amount", func(bm gopay.BodyMap) {
bm.Set("total", amount).
Set("currency", "CNY")
}).
SetBodyMap("scene_info", func(bm gopay.BodyMap) {
bm.Set("payer_client_ip", ip).
SetBodyMap("h5_info", func(bm gopay.BodyMap) {
bm.Set("type", "Wap")
})
})
wxRsp, err := s.client.V3TransactionH5(context.Background(), bm)
if err != nil {
return "", fmt.Errorf("error with client v3 transaction H5: %v", err)
}
if wxRsp.Code != wechat.Success {
return "", fmt.Errorf("error with generating pay url: %v", wxRsp.Error)
}
return wxRsp.Response.H5Url, nil
}
type NotifyResponse struct {
Code string `json:"code"`
Message string `xml:"message"`
}
// TradeVerify 交易验证
func (s *WechatPayService) TradeVerify(request *http.Request) NotifyVo {
notifyReq, err := wechat.V3ParseNotify(request)
if err != nil {
return NotifyVo{Status: 1, Message: fmt.Sprintf("error with client v3 parse notify: %v", err)}
}
// TODO: 这里验签程序有 Bug一直报错crypto/rsa: verification error先暂时取消验签
//err = notifyReq.VerifySignByPK(s.client.WxPublicKey())
//if err != nil {
// return fmt.Errorf("error with client v3 verify sign: %v", err)
//}
// 解密支付密文,验证订单信息
result, err := notifyReq.DecryptPayCipherText(s.config.ApiV3Key)
if err != nil {
return NotifyVo{Status: Failure, Message: fmt.Sprintf("error with client v3 decrypt: %v", err)}
}
return NotifyVo{
Status: Success,
OutTradeNo: result.OutTradeNo,
TradeId: result.TransactionId,
Amount: fmt.Sprintf("%.2f", float64(result.Amount.Total)/100),
}
}

View File

@ -132,7 +132,7 @@ func (p *ServicePool) CheckTaskStatus() {
continue continue
} }
} }
time.Sleep(time.Second * 10) time.Sleep(time.Second * 5)
} }
}() }()
} }

View File

@ -192,7 +192,7 @@ func (s *Service) Txt2Img(task types.SdTask) error {
return return
} }
task.Params.Seed = int64(utils.IntValue(utils.InterfaceToString(info["seed"]), -1)) task.Params.Seed = int64(utils.IntValue(utils.InterfaceToString(info["seed"]), -1))
s.db.Model(&model.SdJob{Id: uint(task.Id)}).UpdateColumns(model.SdJob{ImgURL: imgURL, Params: utils.JsonEncode(task.Params)}) s.db.Model(&model.SdJob{Id: uint(task.Id)}).UpdateColumns(model.SdJob{ImgURL: imgURL, Params: utils.JsonEncode(task.Params), Prompt: task.Params.Prompt})
errChan <- nil errChan <- nil
}() }()

View File

@ -28,8 +28,8 @@ func NewSmtpService(appConfig *types.AppConfig) *SmtpService {
} }
func (s *SmtpService) SendVerifyCode(to string, code int) error { func (s *SmtpService) SendVerifyCode(to string, code int) error {
subject := "Geek-AI 注册验证码" subject := fmt.Sprintf("%s 注册验证码", s.config.AppName)
body := fmt.Sprintf("您正在注册 Geek-AI 助手账户,注册验证码为 %d请不要告诉他人。如非本人操作请忽略此邮件。", code) body := fmt.Sprintf("您正在注册 %s 账户,注册验证码为 %d请不要告诉他人。如非本人操作请忽略此邮件。", s.config.AppName, code)
auth := smtp.PlainAuth("", s.config.From, s.config.Password, s.config.Host) auth := smtp.PlainAuth("", s.config.From, s.config.Password, s.config.Host)
if s.config.UseTls { if s.config.UseTls {

View File

@ -106,8 +106,10 @@ func (e *XXLJobExecutor) ResetVipPower(cxt context.Context, param *xxl.RunReq) (
e.db.Model(&model.User{}).Where("id", u.Id).UpdateColumn("vip", false) e.db.Model(&model.User{}).Where("id", u.Id).UpdateColumn("vip", false)
continue continue
} }
if u.Power < config.VipMonthPower {
power := config.VipMonthPower - u.Power
// update user // update user
tx := e.db.Model(&model.User{}).Where("id", u.Id).UpdateColumn("power", gorm.Expr("power + ?", config.VipMonthPower)) tx := e.db.Model(&model.User{}).Where("id", u.Id).UpdateColumn("power", gorm.Expr("power + ?", power))
// 记录算力变动日志 // 记录算力变动日志
if tx.Error == nil { if tx.Error == nil {
var user model.User var user model.User
@ -116,7 +118,7 @@ func (e *XXLJobExecutor) ResetVipPower(cxt context.Context, param *xxl.RunReq) (
UserId: u.Id, UserId: u.Id,
Username: u.Username, Username: u.Username,
Type: types.PowerRecharge, Type: types.PowerRecharge,
Amount: config.VipMonthPower, Amount: power,
Mark: types.PowerAdd, Mark: types.PowerAdd,
Balance: user.Power, Balance: user.Power,
Model: "系统盘点", Model: "系统盘点",
@ -125,6 +127,7 @@ func (e *XXLJobExecutor) ResetVipPower(cxt context.Context, param *xxl.RunReq) (
}) })
} }
} }
}
logger.Info("月底盘点完成!") logger.Info("月底盘点完成!")
return "success" return "success"
} }

View File

@ -2,11 +2,8 @@ package main
import ( import (
"fmt" "fmt"
"net/url"
) )
func main() { func main() {
text := "https://nk.img.r9it.com/chatgpt-plus/1712709360012445.png" fmt.Println(fmt.Sprintf("%v", float64(90)/100))
parse, _ := url.Parse(text)
fmt.Println(fmt.Sprintf("%s://%s", parse.Scheme, parse.Host))
} }

View File

@ -54,7 +54,7 @@ type apiErrRes struct {
func OpenAIRequest(db *gorm.DB, prompt string) (string, error) { func OpenAIRequest(db *gorm.DB, prompt string) (string, error) {
var apiKey model.ApiKey var apiKey model.ApiKey
res := db.Where("platform = ?", types.OpenAI.Value).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 { if res.Error != nil {
return "", fmt.Errorf("error with fetch OpenAI API KEY%v", res.Error) return "", fmt.Errorf("error with fetch OpenAI API KEY%v", res.Error)
} }
@ -74,7 +74,7 @@ func OpenAIRequest(db *gorm.DB, prompt string) (string, error) {
r, err := client.R().SetHeader("Content-Type", "application/json"). r, err := client.R().SetHeader("Content-Type", "application/json").
SetHeader("Authorization", "Bearer "+apiKey.Value). SetHeader("Authorization", "Bearer "+apiKey.Value).
SetBody(types.ApiRequest{ SetBody(types.ApiRequest{
Model: "gpt-3.5-turbo-0125", Model: "gpt-3.5-turbo",
Temperature: 0.9, Temperature: 0.9,
MaxTokens: 1024, MaxTokens: 1024,
Stream: false, Stream: false,

View File

@ -0,0 +1,852 @@
-- phpMyAdmin SQL Dump
-- version 5.2.1
-- https://www.phpmyadmin.net/
--
-- 主机: 127.0.0.1
-- 生成日期: 2024-06-22 12:15:45
-- 服务器版本: 8.0.33
-- PHP 版本: 8.1.2-1ubuntu2.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, 1718094709, '172.22.11.200', '2024-03-11 16:30:20', '2024-06-11 16:31:50');
-- --------------------------------------------------------
--
-- 表的结构 `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'),
(40, 'Azure', 'Azure-GPT-4O', 'xygpt4o', 27, 1, 20, 1.0, 4096, 8192, 1, 62, '2024-06-03 17:22:37', '2024-06-03 17:47:46'),
(41, 'OpenAI', 'GLM-3-Turbo', 'glm-3-turbo', 28, 1, 2, 1.0, 1024, 8192, 1, 64, '2024-06-06 11:40:46', '2024-06-06 11:40: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 '角色排序',
`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\":\"GeekAI 创作系统\",\"slogan\":\"你有多少想象力AI 就有多大创造力。我辈之人,先干为敬,陪您先把 AI 用起来。\",\"admin_title\":\"GeekAI 控制台\",\"logo\":\"http://localhost:5678/static/upload/2024/4/1714382860986912.png\",\"init_power\":100,\"daily_power\":99,\"invite_power\":1024,\"vip_month_power\":1000,\"register_ways\":[\"mobile\",\"username\",\"email\"],\"reward_img\":\"http://localhost:5678/static/upload/2024/3/1710753716309668.jpg\",\"enabled_reward\":true,\"power_price\":0.1,\"order_pay_timeout\":600,\"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.9 更新日志\\n\\n* 环境升级:升级 Golang 到 go1.22.4\\n* 功能增加:接入微信商户号支付渠道\\n* Bug修复修复前端页面菜单把页面撑开底部留白问题\\n* 功能优化:聊天页面自动根据内容调整输入框的高度\\n* Bug修复修复Dalle绘图失败退回算力的问题\\n* 功能优化:邀请码注册时被邀请人也可以获得赠送的算力\\n* 功能优化:允许设置邮件验证码的抬头\\n* Bug修复修复免费模型不会记录聊天记录的bug\\n* Bug修复修复聊天输入公式显示异常的Bug\\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支持MidJourneyGPTClaudeGoogle 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.5GPT-4DALL-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', 1),
(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', 1);
-- --------------------------------------------------------
--
-- 表的结构 `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, 1, 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次点卡', 9.99, 9.98, 0, 100, 1, 7, 0, '2023-08-28 10:55:08', '2024-06-11 16:48:44', NULL, NULL),
(6, '200次点卡', 19.90, 15.00, 0, 200, 1, 1, 0, '1970-01-01 08:00:00', '2024-06-11 11:41:52', 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', 7723, 1720669190, 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]', 1719026861, 1, '172.22.19.12', '2023-06-12 16:47:17', '2024-06-22 11:27:42'),
(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'),
(11, 'abc123', '极客学长@965562', '7a15c53afdb1da7093d80f9940e716eb396e682cfb1f2d107d0b81b183a3ba13', '/images/avatar/user.png', '6433mfbk', 1124, 0, 1, '', '[\"gpt\"]', '[11,7,1,10,12,19,18,17,3]', 0, 0, '', '2024-06-06 09:37:44', '2024-06-06 09:37:44');
-- --------------------------------------------------------
--
-- 表的结构 `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=42;
--
-- 使用表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=12;
--
-- 使用表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 */;

View File

@ -49,9 +49,10 @@ services:
volumes: volumes:
- ./conf/mj-proxy:/home/spring/config - ./conf/mj-proxy:/home/spring/config
# 后端 API 程序 # 后端 API 程序
geekai-api: geekai-api:
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-api:v4.0.8-amd64 image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-api:v4.0.9-amd64
container_name: geekai-api container_name: geekai-api
restart: always restart: always
depends_on: depends_on:
@ -73,7 +74,7 @@ services:
# 前端应用 # 前端应用
geekai-web: geekai-web:
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-web:v4.0.8-amd64 image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-web:v4.0.9-amd64
container_name: geekai-web container_name: geekai-web
restart: always restart: always
depends_on: depends_on:

View File

@ -1,5 +1,5 @@
VUE_APP_API_HOST=http://localhost:5678 VUE_APP_API_HOST=http://172.22.11.69:5678
VUE_APP_WS_HOST=ws://localhost:5678 VUE_APP_WS_HOST=ws://172.22.11.69:5678
VUE_APP_USER=18575670125 VUE_APP_USER=18575670125
VUE_APP_PASS=12345678 VUE_APP_PASS=12345678
VUE_APP_ADMIN_USER=admin VUE_APP_ADMIN_USER=admin

493
web/package-lock.json generated
View File

@ -1,11 +1,11 @@
{ {
"name": "chatgpt-plus-web", "name": "geekai-web",
"version": "0.1.0", "version": "0.1.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "chatgpt-plus-web", "name": "geekai-web",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^2.1.0", "@element-plus/icons-vue": "^2.1.0",
@ -14,14 +14,13 @@
"compressorjs": "^1.2.1", "compressorjs": "^1.2.1",
"core-js": "^3.8.3", "core-js": "^3.8.3",
"echarts": "^5.5.0", "echarts": "^5.5.0",
"element-plus": "^2.3.0", "element-plus": "^2.4.0",
"good-storage": "^1.1.1", "good-storage": "^1.1.1",
"highlight.js": "^11.7.0", "highlight.js": "^11.7.0",
"json-bigint": "^1.0.0", "json-bigint": "^1.0.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"markdown-it": "^13.0.1", "markdown-it": "^13.0.1",
"markdown-it-latex2img": "^0.0.6", "markdown-it-mathjax3": "^4.3.2",
"markdown-it-mathjax": "^2.0.0",
"markmap-common": "^0.16.0", "markmap-common": "^0.16.0",
"markmap-lib": "^0.16.1", "markmap-lib": "^0.16.1",
"markmap-toolbar": "^0.17.0", "markmap-toolbar": "^0.17.0",
@ -1739,9 +1738,9 @@
} }
}, },
"node_modules/@element-plus/icons-vue": { "node_modules/@element-plus/icons-vue": {
"version": "2.1.0", "version": "2.3.1",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.1.0.tgz", "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz",
"integrity": "sha512-PSBn3elNoanENc1vnCfh+3WA9fimRC7n+fWkf3rE5jvv+aBohNHABC/KAR5KWPecxWxDTVT1ERpRbOMRcOV/vA==", "integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==",
"peerDependencies": { "peerDependencies": {
"vue": "^3.2.0" "vue": "^3.2.0"
} }
@ -3586,7 +3585,6 @@
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmmirror.com/ansi-colors/-/ansi-colors-4.1.1.tgz", "resolved": "https://registry.npmmirror.com/ansi-colors/-/ansi-colors-4.1.1.tgz",
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
"dev": true,
"engines": { "engines": {
"node": ">=6" "node": ">=6"
} }
@ -4974,7 +4972,6 @@
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmmirror.com/css-select/-/css-select-4.3.0.tgz", "resolved": "https://registry.npmmirror.com/css-select/-/css-select-4.3.0.tgz",
"integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
"dev": true,
"dependencies": { "dependencies": {
"boolbase": "^1.0.0", "boolbase": "^1.0.0",
"css-what": "^6.0.1", "css-what": "^6.0.1",
@ -5833,7 +5830,6 @@
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz", "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz",
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
"dev": true,
"dependencies": { "dependencies": {
"domelementtype": "^2.0.1", "domelementtype": "^2.0.1",
"domhandler": "^4.2.0", "domhandler": "^4.2.0",
@ -5849,7 +5845,6 @@
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-4.3.1.tgz", "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-4.3.1.tgz",
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
"dev": true,
"dependencies": { "dependencies": {
"domelementtype": "^2.2.0" "domelementtype": "^2.2.0"
}, },
@ -5861,7 +5856,6 @@
"version": "2.8.0", "version": "2.8.0",
"resolved": "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz", "resolved": "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz",
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
"dev": true,
"dependencies": { "dependencies": {
"dom-serializer": "^1.0.1", "dom-serializer": "^1.0.1",
"domelementtype": "^2.2.0", "domelementtype": "^2.2.0",
@ -5935,12 +5929,12 @@
"dev": true "dev": true
}, },
"node_modules/element-plus": { "node_modules/element-plus": {
"version": "2.3.9", "version": "2.7.6",
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.3.9.tgz", "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.7.6.tgz",
"integrity": "sha512-TIOLnPl4cnoCPXqK3QYh+jpkthUBQnAM21O7o3Lhbse8v9pfrRXRTaBJtoEKnYNa8GZ4lZptUfH0PeZgDCNLUg==", "integrity": "sha512-36sw1K23hYjgeooR10U6CiCaCp2wvOqwoFurADZVlekeQ9v5U1FhJCFGEXO6i/kZBBMwsE1c9fxjLs9LENw2Rg==",
"dependencies": { "dependencies": {
"@ctrl/tinycolor": "^3.4.1", "@ctrl/tinycolor": "^3.4.1",
"@element-plus/icons-vue": "^2.0.6", "@element-plus/icons-vue": "^2.3.1",
"@floating-ui/dom": "^1.0.1", "@floating-ui/dom": "^1.0.1",
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
"@types/lodash": "^4.14.182", "@types/lodash": "^4.14.182",
@ -6030,8 +6024,7 @@
"node_modules/entities": { "node_modules/entities": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz", "resolved": "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz",
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
"dev": true
}, },
"node_modules/error-ex": { "node_modules/error-ex": {
"version": "1.3.2", "version": "1.3.2",
@ -6066,6 +6059,17 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/escape-goat": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/escape-goat/-/escape-goat-3.0.0.tgz",
"integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/escape-html": { "node_modules/escape-html": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
@ -6459,6 +6463,14 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/esm": {
"version": "3.2.25",
"resolved": "https://registry.npmmirror.com/esm/-/esm-3.2.25.tgz",
"integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==",
"engines": {
"node": ">=6"
}
},
"node_modules/espree": { "node_modules/espree": {
"version": "7.3.1", "version": "7.3.1",
"resolved": "https://registry.npmmirror.com/espree/-/espree-7.3.1.tgz", "resolved": "https://registry.npmmirror.com/espree/-/espree-7.3.1.tgz",
@ -7287,7 +7299,6 @@
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-6.1.0.tgz", "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-6.1.0.tgz",
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
"dev": true,
"dependencies": { "dependencies": {
"domelementtype": "^2.0.1", "domelementtype": "^2.0.1",
"domhandler": "^4.0.0", "domhandler": "^4.0.0",
@ -7804,6 +7815,72 @@
"graceful-fs": "^4.1.6" "graceful-fs": "^4.1.6"
} }
}, },
"node_modules/juice": {
"version": "8.1.0",
"resolved": "https://registry.npmmirror.com/juice/-/juice-8.1.0.tgz",
"integrity": "sha512-FLzurJrx5Iv1e7CfBSZH68dC04EEvXvvVvPYB7Vx1WAuhCp1ZPIMtqxc+WTWxVkpTIC2Ach/GAv0rQbtGf6YMA==",
"dependencies": {
"cheerio": "1.0.0-rc.10",
"commander": "^6.1.0",
"mensch": "^0.3.4",
"slick": "^1.12.2",
"web-resource-inliner": "^6.0.1"
},
"bin": {
"juice": "bin/juice"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/juice/node_modules/cheerio": {
"version": "1.0.0-rc.10",
"resolved": "https://registry.npmmirror.com/cheerio/-/cheerio-1.0.0-rc.10.tgz",
"integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==",
"dependencies": {
"cheerio-select": "^1.5.0",
"dom-serializer": "^1.3.2",
"domhandler": "^4.2.0",
"htmlparser2": "^6.1.0",
"parse5": "^6.0.1",
"parse5-htmlparser2-tree-adapter": "^6.0.1",
"tslib": "^2.2.0"
},
"engines": {
"node": ">= 6"
},
"funding": {
"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
}
},
"node_modules/juice/node_modules/cheerio-select": {
"version": "1.6.0",
"resolved": "https://registry.npmmirror.com/cheerio-select/-/cheerio-select-1.6.0.tgz",
"integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==",
"dependencies": {
"css-select": "^4.3.0",
"css-what": "^6.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.3.1",
"domutils": "^2.8.0"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/juice/node_modules/commander": {
"version": "6.2.1",
"resolved": "https://registry.npmmirror.com/commander/-/commander-6.2.1.tgz",
"integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
"engines": {
"node": ">= 6"
}
},
"node_modules/juice/node_modules/parse5": {
"version": "6.0.1",
"resolved": "https://registry.npmmirror.com/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
},
"node_modules/katex": { "node_modules/katex": {
"version": "0.16.10", "version": "0.16.10",
"resolved": "https://registry.npmmirror.com/katex/-/katex-0.16.10.tgz", "resolved": "https://registry.npmmirror.com/katex/-/katex-0.16.10.tgz",
@ -8254,15 +8331,14 @@
"markdown-it": "bin/markdown-it.js" "markdown-it": "bin/markdown-it.js"
} }
}, },
"node_modules/markdown-it-latex2img": { "node_modules/markdown-it-mathjax3": {
"version": "0.0.6", "version": "4.3.2",
"resolved": "https://registry.npmmirror.com/markdown-it-latex2img/-/markdown-it-latex2img-0.0.6.tgz", "resolved": "https://registry.npmmirror.com/markdown-it-mathjax3/-/markdown-it-mathjax3-4.3.2.tgz",
"integrity": "sha512-plzX+YmYv28UnM172ZDKexyquec/GMit2K84g4x60u0YRFybhDQl8W0aTCHD8gJbhYVJRTWIDaL9YB0cvTijYQ==" "integrity": "sha512-TX3GW5NjmupgFtMJGRauioMbbkGsOXAAt1DZ/rzzYmTHqzkO1rNAdiMD4NiruurToPApn2kYy76x02QN26qr2w==",
}, "dependencies": {
"node_modules/markdown-it-mathjax": { "juice": "^8.0.0",
"version": "2.0.0", "mathjax-full": "^3.2.0"
"resolved": "https://registry.npmmirror.com/markdown-it-mathjax/-/markdown-it-mathjax-2.0.0.tgz", }
"integrity": "sha512-Fafv7TnMENccWYTNjMZzV4BzONPxpK9Mknr1iMEK6m7PI5a5UTCOFctPzx7Nhv81fFzYEY8WHDkSu9n43fTV9g=="
}, },
"node_modules/markdown-it/node_modules/argparse": { "node_modules/markdown-it/node_modules/argparse": {
"version": "2.0.1", "version": "2.0.1",
@ -8364,6 +8440,17 @@
"markmap-common": "*" "markmap-common": "*"
} }
}, },
"node_modules/mathjax-full": {
"version": "3.2.2",
"resolved": "https://registry.npmmirror.com/mathjax-full/-/mathjax-full-3.2.2.tgz",
"integrity": "sha512-+LfG9Fik+OuI8SLwsiR02IVdjcnRCy5MufYLi0C3TdMT56L/pjB0alMVGgoWJF8pN9Rc7FESycZB9BMNWIid5w==",
"dependencies": {
"esm": "^3.2.25",
"mhchemparser": "^4.1.0",
"mj-context-menu": "^0.6.1",
"speech-rule-engine": "^4.0.6"
}
},
"node_modules/md-editor-v3": { "node_modules/md-editor-v3": {
"version": "2.11.3", "version": "2.11.3",
"resolved": "https://registry.npmjs.org/md-editor-v3/-/md-editor-v3-2.11.3.tgz", "resolved": "https://registry.npmjs.org/md-editor-v3/-/md-editor-v3-2.11.3.tgz",
@ -8409,6 +8496,11 @@
"resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz", "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
}, },
"node_modules/mensch": {
"version": "0.3.4",
"resolved": "https://registry.npmmirror.com/mensch/-/mensch-0.3.4.tgz",
"integrity": "sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g=="
},
"node_modules/merge-descriptors": { "node_modules/merge-descriptors": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@ -8457,6 +8549,11 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/mhchemparser": {
"version": "4.2.1",
"resolved": "https://registry.npmmirror.com/mhchemparser/-/mhchemparser-4.2.1.tgz",
"integrity": "sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ=="
},
"node_modules/micromatch": { "node_modules/micromatch": {
"version": "4.0.5", "version": "4.0.5",
"resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz", "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz",
@ -8611,6 +8708,11 @@
"resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz", "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==" "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
}, },
"node_modules/mj-context-menu": {
"version": "0.6.1",
"resolved": "https://registry.npmmirror.com/mj-context-menu/-/mj-context-menu-0.6.1.tgz",
"integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA=="
},
"node_modules/mkdirp": { "node_modules/mkdirp": {
"version": "0.5.6", "version": "0.5.6",
"resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz",
@ -8720,7 +8822,6 @@
"version": "2.6.7", "version": "2.6.7",
"resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.7.tgz", "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"dev": true,
"dependencies": { "dependencies": {
"whatwg-url": "^5.0.0" "whatwg-url": "^5.0.0"
}, },
@ -9141,7 +9242,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", "resolved": "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
"integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
"dev": true,
"dependencies": { "dependencies": {
"parse5": "^6.0.1" "parse5": "^6.0.1"
} }
@ -9149,8 +9249,7 @@
"node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmmirror.com/parse5/-/parse5-6.0.1.tgz", "resolved": "https://registry.npmmirror.com/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
"dev": true
}, },
"node_modules/parseurl": { "node_modules/parseurl": {
"version": "1.3.3", "version": "1.3.3",
@ -10780,6 +10879,14 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true "dev": true
}, },
"node_modules/slick": {
"version": "1.12.2",
"resolved": "https://registry.npmmirror.com/slick/-/slick-1.12.2.tgz",
"integrity": "sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A==",
"engines": {
"node": "*"
}
},
"node_modules/sockjs": { "node_modules/sockjs": {
"version": "0.3.24", "version": "0.3.24",
"resolved": "https://registry.npmmirror.com/sockjs/-/sockjs-0.3.24.tgz", "resolved": "https://registry.npmmirror.com/sockjs/-/sockjs-0.3.24.tgz",
@ -10896,6 +11003,27 @@
"wbuf": "^1.7.3" "wbuf": "^1.7.3"
} }
}, },
"node_modules/speech-rule-engine": {
"version": "4.0.7",
"resolved": "https://registry.npmmirror.com/speech-rule-engine/-/speech-rule-engine-4.0.7.tgz",
"integrity": "sha512-sJrL3/wHzNwJRLBdf6CjJWIlxC04iYKkyXvYSVsWVOiC2DSkHmxsqOhEeMsBA9XK+CHuNcsdkbFDnoUfAsmp9g==",
"dependencies": {
"commander": "9.2.0",
"wicked-good-xpath": "1.3.0",
"xmldom-sre": "0.1.31"
},
"bin": {
"sre": "bin/sre"
}
},
"node_modules/speech-rule-engine/node_modules/commander": {
"version": "9.2.0",
"resolved": "https://registry.npmmirror.com/commander/-/commander-9.2.0.tgz",
"integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==",
"engines": {
"node": "^12.20.0 || >=14"
}
},
"node_modules/sprintf-js": { "node_modules/sprintf-js": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz", "resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz",
@ -11371,8 +11499,7 @@
"node_modules/tr46": { "node_modules/tr46": {
"version": "0.0.3", "version": "0.0.3",
"resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
"dev": true
}, },
"node_modules/tslib": { "node_modules/tslib": {
"version": "2.4.0", "version": "2.4.0",
@ -11542,6 +11669,14 @@
"integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
"dev": true "dev": true
}, },
"node_modules/valid-data-url": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/valid-data-url/-/valid-data-url-3.0.1.tgz",
"integrity": "sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA==",
"engines": {
"node": ">=10"
}
},
"node_modules/validate-npm-package-license": { "node_modules/validate-npm-package-license": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@ -11829,11 +11964,65 @@
"defaults": "^1.0.3" "defaults": "^1.0.3"
} }
}, },
"node_modules/web-resource-inliner": {
"version": "6.0.1",
"resolved": "https://registry.npmmirror.com/web-resource-inliner/-/web-resource-inliner-6.0.1.tgz",
"integrity": "sha512-kfqDxt5dTB1JhqsCUQVFDj0rmY+4HLwGQIsLPbyrsN9y9WV/1oFDSx3BQ4GfCv9X+jVeQ7rouTqwK53rA/7t8A==",
"dependencies": {
"ansi-colors": "^4.1.1",
"escape-goat": "^3.0.0",
"htmlparser2": "^5.0.0",
"mime": "^2.4.6",
"node-fetch": "^2.6.0",
"valid-data-url": "^3.0.0"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/web-resource-inliner/node_modules/domhandler": {
"version": "3.3.0",
"resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-3.3.0.tgz",
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
"dependencies": {
"domelementtype": "^2.0.1"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/web-resource-inliner/node_modules/htmlparser2": {
"version": "5.0.1",
"resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-5.0.1.tgz",
"integrity": "sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==",
"dependencies": {
"domelementtype": "^2.0.1",
"domhandler": "^3.3.0",
"domutils": "^2.4.2",
"entities": "^2.0.0"
},
"funding": {
"url": "https://github.com/fb55/htmlparser2?sponsor=1"
}
},
"node_modules/web-resource-inliner/node_modules/mime": {
"version": "2.6.0",
"resolved": "https://registry.npmmirror.com/mime/-/mime-2.6.0.tgz",
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
"bin": {
"mime": "cli.js"
},
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/webidl-conversions": { "node_modules/webidl-conversions": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
"dev": true
}, },
"node_modules/webpack": { "node_modules/webpack": {
"version": "5.90.3", "version": "5.90.3",
@ -12243,7 +12432,6 @@
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dev": true,
"dependencies": { "dependencies": {
"tr46": "~0.0.3", "tr46": "~0.0.3",
"webidl-conversions": "^3.0.0" "webidl-conversions": "^3.0.0"
@ -12266,6 +12454,11 @@
"resolved": "https://registry.npmmirror.com/which-module/-/which-module-2.0.1.tgz", "resolved": "https://registry.npmmirror.com/which-module/-/which-module-2.0.1.tgz",
"integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="
}, },
"node_modules/wicked-good-xpath": {
"version": "1.3.0",
"resolved": "https://registry.npmmirror.com/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz",
"integrity": "sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw=="
},
"node_modules/wildcard": { "node_modules/wildcard": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.0.tgz", "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.0.tgz",
@ -12352,6 +12545,14 @@
} }
} }
}, },
"node_modules/xmldom-sre": {
"version": "0.1.31",
"resolved": "https://registry.npmmirror.com/xmldom-sre/-/xmldom-sre-0.1.31.tgz",
"integrity": "sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw==",
"engines": {
"node": ">=0.1"
}
},
"node_modules/y18n": { "node_modules/y18n": {
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz",
@ -13672,9 +13873,9 @@
"integrity": "sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==" "integrity": "sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw=="
}, },
"@element-plus/icons-vue": { "@element-plus/icons-vue": {
"version": "2.1.0", "version": "2.3.1",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.1.0.tgz", "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz",
"integrity": "sha512-PSBn3elNoanENc1vnCfh+3WA9fimRC7n+fWkf3rE5jvv+aBohNHABC/KAR5KWPecxWxDTVT1ERpRbOMRcOV/vA==", "integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==",
"requires": {} "requires": {}
}, },
"@eslint/eslintrc": { "@eslint/eslintrc": {
@ -15283,8 +15484,7 @@
"ansi-colors": { "ansi-colors": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmmirror.com/ansi-colors/-/ansi-colors-4.1.1.tgz", "resolved": "https://registry.npmmirror.com/ansi-colors/-/ansi-colors-4.1.1.tgz",
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA=="
"dev": true
}, },
"ansi-escapes": { "ansi-escapes": {
"version": "3.2.0", "version": "3.2.0",
@ -16429,7 +16629,6 @@
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmmirror.com/css-select/-/css-select-4.3.0.tgz", "resolved": "https://registry.npmmirror.com/css-select/-/css-select-4.3.0.tgz",
"integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
"dev": true,
"requires": { "requires": {
"boolbase": "^1.0.0", "boolbase": "^1.0.0",
"css-what": "^6.0.1", "css-what": "^6.0.1",
@ -17068,7 +17267,6 @@
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz", "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz",
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
"dev": true,
"requires": { "requires": {
"domelementtype": "^2.0.1", "domelementtype": "^2.0.1",
"domhandler": "^4.2.0", "domhandler": "^4.2.0",
@ -17084,7 +17282,6 @@
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-4.3.1.tgz", "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-4.3.1.tgz",
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
"dev": true,
"requires": { "requires": {
"domelementtype": "^2.2.0" "domelementtype": "^2.2.0"
} }
@ -17093,7 +17290,6 @@
"version": "2.8.0", "version": "2.8.0",
"resolved": "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz", "resolved": "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz",
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
"dev": true,
"requires": { "requires": {
"dom-serializer": "^1.0.1", "dom-serializer": "^1.0.1",
"domelementtype": "^2.2.0", "domelementtype": "^2.2.0",
@ -17163,12 +17359,12 @@
"dev": true "dev": true
}, },
"element-plus": { "element-plus": {
"version": "2.3.9", "version": "2.7.6",
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.3.9.tgz", "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.7.6.tgz",
"integrity": "sha512-TIOLnPl4cnoCPXqK3QYh+jpkthUBQnAM21O7o3Lhbse8v9pfrRXRTaBJtoEKnYNa8GZ4lZptUfH0PeZgDCNLUg==", "integrity": "sha512-36sw1K23hYjgeooR10U6CiCaCp2wvOqwoFurADZVlekeQ9v5U1FhJCFGEXO6i/kZBBMwsE1c9fxjLs9LENw2Rg==",
"requires": { "requires": {
"@ctrl/tinycolor": "^3.4.1", "@ctrl/tinycolor": "^3.4.1",
"@element-plus/icons-vue": "^2.0.6", "@element-plus/icons-vue": "^2.3.1",
"@floating-ui/dom": "^1.0.1", "@floating-ui/dom": "^1.0.1",
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
"@types/lodash": "^4.14.182", "@types/lodash": "^4.14.182",
@ -17244,8 +17440,7 @@
"entities": { "entities": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz", "resolved": "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz",
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
"dev": true
}, },
"error-ex": { "error-ex": {
"version": "1.3.2", "version": "1.3.2",
@ -17277,6 +17472,11 @@
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true "dev": true
}, },
"escape-goat": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/escape-goat/-/escape-goat-3.0.0.tgz",
"integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw=="
},
"escape-html": { "escape-html": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
@ -17575,6 +17775,11 @@
} }
} }
}, },
"esm": {
"version": "3.2.25",
"resolved": "https://registry.npmmirror.com/esm/-/esm-3.2.25.tgz",
"integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA=="
},
"espree": { "espree": {
"version": "7.3.1", "version": "7.3.1",
"resolved": "https://registry.npmmirror.com/espree/-/espree-7.3.1.tgz", "resolved": "https://registry.npmmirror.com/espree/-/espree-7.3.1.tgz",
@ -18245,7 +18450,6 @@
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-6.1.0.tgz", "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-6.1.0.tgz",
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
"dev": true,
"requires": { "requires": {
"domelementtype": "^2.0.1", "domelementtype": "^2.0.1",
"domhandler": "^4.0.0", "domhandler": "^4.0.0",
@ -18641,6 +18845,56 @@
"universalify": "^2.0.0" "universalify": "^2.0.0"
} }
}, },
"juice": {
"version": "8.1.0",
"resolved": "https://registry.npmmirror.com/juice/-/juice-8.1.0.tgz",
"integrity": "sha512-FLzurJrx5Iv1e7CfBSZH68dC04EEvXvvVvPYB7Vx1WAuhCp1ZPIMtqxc+WTWxVkpTIC2Ach/GAv0rQbtGf6YMA==",
"requires": {
"cheerio": "1.0.0-rc.10",
"commander": "^6.1.0",
"mensch": "^0.3.4",
"slick": "^1.12.2",
"web-resource-inliner": "^6.0.1"
},
"dependencies": {
"cheerio": {
"version": "1.0.0-rc.10",
"resolved": "https://registry.npmmirror.com/cheerio/-/cheerio-1.0.0-rc.10.tgz",
"integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==",
"requires": {
"cheerio-select": "^1.5.0",
"dom-serializer": "^1.3.2",
"domhandler": "^4.2.0",
"htmlparser2": "^6.1.0",
"parse5": "^6.0.1",
"parse5-htmlparser2-tree-adapter": "^6.0.1",
"tslib": "^2.2.0"
}
},
"cheerio-select": {
"version": "1.6.0",
"resolved": "https://registry.npmmirror.com/cheerio-select/-/cheerio-select-1.6.0.tgz",
"integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==",
"requires": {
"css-select": "^4.3.0",
"css-what": "^6.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.3.1",
"domutils": "^2.8.0"
}
},
"commander": {
"version": "6.2.1",
"resolved": "https://registry.npmmirror.com/commander/-/commander-6.2.1.tgz",
"integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="
},
"parse5": {
"version": "6.0.1",
"resolved": "https://registry.npmmirror.com/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
}
}
},
"katex": { "katex": {
"version": "0.16.10", "version": "0.16.10",
"resolved": "https://registry.npmmirror.com/katex/-/katex-0.16.10.tgz", "resolved": "https://registry.npmmirror.com/katex/-/katex-0.16.10.tgz",
@ -19018,15 +19272,14 @@
} }
} }
}, },
"markdown-it-latex2img": { "markdown-it-mathjax3": {
"version": "0.0.6", "version": "4.3.2",
"resolved": "https://registry.npmmirror.com/markdown-it-latex2img/-/markdown-it-latex2img-0.0.6.tgz", "resolved": "https://registry.npmmirror.com/markdown-it-mathjax3/-/markdown-it-mathjax3-4.3.2.tgz",
"integrity": "sha512-plzX+YmYv28UnM172ZDKexyquec/GMit2K84g4x60u0YRFybhDQl8W0aTCHD8gJbhYVJRTWIDaL9YB0cvTijYQ==" "integrity": "sha512-TX3GW5NjmupgFtMJGRauioMbbkGsOXAAt1DZ/rzzYmTHqzkO1rNAdiMD4NiruurToPApn2kYy76x02QN26qr2w==",
}, "requires": {
"markdown-it-mathjax": { "juice": "^8.0.0",
"version": "2.0.0", "mathjax-full": "^3.2.0"
"resolved": "https://registry.npmmirror.com/markdown-it-mathjax/-/markdown-it-mathjax-2.0.0.tgz", }
"integrity": "sha512-Fafv7TnMENccWYTNjMZzV4BzONPxpK9Mknr1iMEK6m7PI5a5UTCOFctPzx7Nhv81fFzYEY8WHDkSu9n43fTV9g=="
}, },
"markmap-common": { "markmap-common": {
"version": "0.16.0", "version": "0.16.0",
@ -19099,6 +19352,17 @@
"d3-flextree": "^2.1.2" "d3-flextree": "^2.1.2"
} }
}, },
"mathjax-full": {
"version": "3.2.2",
"resolved": "https://registry.npmmirror.com/mathjax-full/-/mathjax-full-3.2.2.tgz",
"integrity": "sha512-+LfG9Fik+OuI8SLwsiR02IVdjcnRCy5MufYLi0C3TdMT56L/pjB0alMVGgoWJF8pN9Rc7FESycZB9BMNWIid5w==",
"requires": {
"esm": "^3.2.25",
"mhchemparser": "^4.1.0",
"mj-context-menu": "^0.6.1",
"speech-rule-engine": "^4.0.6"
}
},
"md-editor-v3": { "md-editor-v3": {
"version": "2.11.3", "version": "2.11.3",
"resolved": "https://registry.npmjs.org/md-editor-v3/-/md-editor-v3-2.11.3.tgz", "resolved": "https://registry.npmjs.org/md-editor-v3/-/md-editor-v3-2.11.3.tgz",
@ -19136,6 +19400,11 @@
"resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz", "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
}, },
"mensch": {
"version": "0.3.4",
"resolved": "https://registry.npmmirror.com/mensch/-/mensch-0.3.4.tgz",
"integrity": "sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g=="
},
"merge-descriptors": { "merge-descriptors": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@ -19177,6 +19446,11 @@
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
"dev": true "dev": true
}, },
"mhchemparser": {
"version": "4.2.1",
"resolved": "https://registry.npmmirror.com/mhchemparser/-/mhchemparser-4.2.1.tgz",
"integrity": "sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ=="
},
"micromatch": { "micromatch": {
"version": "4.0.5", "version": "4.0.5",
"resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz", "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz",
@ -19297,6 +19571,11 @@
"resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz", "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==" "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
}, },
"mj-context-menu": {
"version": "0.6.1",
"resolved": "https://registry.npmmirror.com/mj-context-menu/-/mj-context-menu-0.6.1.tgz",
"integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA=="
},
"mkdirp": { "mkdirp": {
"version": "0.5.6", "version": "0.5.6",
"resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz",
@ -19388,7 +19667,6 @@
"version": "2.6.7", "version": "2.6.7",
"resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.7.tgz", "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"dev": true,
"requires": { "requires": {
"whatwg-url": "^5.0.0" "whatwg-url": "^5.0.0"
} }
@ -19715,7 +19993,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", "resolved": "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
"integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
"dev": true,
"requires": { "requires": {
"parse5": "^6.0.1" "parse5": "^6.0.1"
}, },
@ -19723,8 +20000,7 @@
"parse5": { "parse5": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmmirror.com/parse5/-/parse5-6.0.1.tgz", "resolved": "https://registry.npmmirror.com/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
"dev": true
} }
} }
}, },
@ -20941,6 +21217,11 @@
} }
} }
}, },
"slick": {
"version": "1.12.2",
"resolved": "https://registry.npmmirror.com/slick/-/slick-1.12.2.tgz",
"integrity": "sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A=="
},
"sockjs": { "sockjs": {
"version": "0.3.24", "version": "0.3.24",
"resolved": "https://registry.npmmirror.com/sockjs/-/sockjs-0.3.24.tgz", "resolved": "https://registry.npmmirror.com/sockjs/-/sockjs-0.3.24.tgz",
@ -21049,6 +21330,23 @@
"wbuf": "^1.7.3" "wbuf": "^1.7.3"
} }
}, },
"speech-rule-engine": {
"version": "4.0.7",
"resolved": "https://registry.npmmirror.com/speech-rule-engine/-/speech-rule-engine-4.0.7.tgz",
"integrity": "sha512-sJrL3/wHzNwJRLBdf6CjJWIlxC04iYKkyXvYSVsWVOiC2DSkHmxsqOhEeMsBA9XK+CHuNcsdkbFDnoUfAsmp9g==",
"requires": {
"commander": "9.2.0",
"wicked-good-xpath": "1.3.0",
"xmldom-sre": "0.1.31"
},
"dependencies": {
"commander": {
"version": "9.2.0",
"resolved": "https://registry.npmmirror.com/commander/-/commander-9.2.0.tgz",
"integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w=="
}
}
},
"sprintf-js": { "sprintf-js": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz", "resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz",
@ -21418,8 +21716,7 @@
"tr46": { "tr46": {
"version": "0.0.3", "version": "0.0.3",
"resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
"dev": true
}, },
"tslib": { "tslib": {
"version": "2.4.0", "version": "2.4.0",
@ -21550,6 +21847,11 @@
"integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
"dev": true "dev": true
}, },
"valid-data-url": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/valid-data-url/-/valid-data-url-3.0.1.tgz",
"integrity": "sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA=="
},
"validate-npm-package-license": { "validate-npm-package-license": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@ -21786,11 +22088,49 @@
"defaults": "^1.0.3" "defaults": "^1.0.3"
} }
}, },
"web-resource-inliner": {
"version": "6.0.1",
"resolved": "https://registry.npmmirror.com/web-resource-inliner/-/web-resource-inliner-6.0.1.tgz",
"integrity": "sha512-kfqDxt5dTB1JhqsCUQVFDj0rmY+4HLwGQIsLPbyrsN9y9WV/1oFDSx3BQ4GfCv9X+jVeQ7rouTqwK53rA/7t8A==",
"requires": {
"ansi-colors": "^4.1.1",
"escape-goat": "^3.0.0",
"htmlparser2": "^5.0.0",
"mime": "^2.4.6",
"node-fetch": "^2.6.0",
"valid-data-url": "^3.0.0"
},
"dependencies": {
"domhandler": {
"version": "3.3.0",
"resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-3.3.0.tgz",
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
"requires": {
"domelementtype": "^2.0.1"
}
},
"htmlparser2": {
"version": "5.0.1",
"resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-5.0.1.tgz",
"integrity": "sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^3.3.0",
"domutils": "^2.4.2",
"entities": "^2.0.0"
}
},
"mime": {
"version": "2.6.0",
"resolved": "https://registry.npmmirror.com/mime/-/mime-2.6.0.tgz",
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="
}
}
},
"webidl-conversions": { "webidl-conversions": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
"dev": true
}, },
"webpack": { "webpack": {
"version": "5.90.3", "version": "5.90.3",
@ -22109,7 +22449,6 @@
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dev": true,
"requires": { "requires": {
"tr46": "~0.0.3", "tr46": "~0.0.3",
"webidl-conversions": "^3.0.0" "webidl-conversions": "^3.0.0"
@ -22129,6 +22468,11 @@
"resolved": "https://registry.npmmirror.com/which-module/-/which-module-2.0.1.tgz", "resolved": "https://registry.npmmirror.com/which-module/-/which-module-2.0.1.tgz",
"integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="
}, },
"wicked-good-xpath": {
"version": "1.3.0",
"resolved": "https://registry.npmmirror.com/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz",
"integrity": "sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw=="
},
"wildcard": { "wildcard": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.0.tgz", "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.0.tgz",
@ -22191,6 +22535,11 @@
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },
"xmldom-sre": {
"version": "0.1.31",
"resolved": "https://registry.npmmirror.com/xmldom-sre/-/xmldom-sre-0.1.31.tgz",
"integrity": "sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw=="
},
"y18n": { "y18n": {
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz",

View File

@ -221,7 +221,7 @@
</template> </template>
<script setup> <script setup>
import {ref, watch} from "vue" import {nextTick, onUnmounted, ref, watch} from "vue"
import {httpGet, httpPost} from "@/utils/http"; import {httpGet, httpPost} from "@/utils/http";
import {ElMessage} from "element-plus"; import {ElMessage} from "element-plus";
import {setUserToken} from "@/store/session"; import {setUserToken} from "@/store/session";
@ -339,7 +339,8 @@ const submitRegister = () => {
} }
const close = function () { const close = function () {
emits('hide', false); emits('hide', false)
login.value = true
} }
</script> </script>

View File

@ -6,19 +6,20 @@
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
import {createRouter, createWebHistory} from "vue-router"; import {createRouter, createWebHistory} from "vue-router";
import {ref} from "vue";
import {httpGet} from "@/utils/http";
const routes = [ const routes = [
{ {
name: 'Index', name: 'Index',
path: '/', path: '/',
meta: {title: process.env.VUE_APP_TITLE}, meta: {title: "首页"},
component: () => import('@/views/Index.vue'), component: () => import('@/views/Index.vue'),
}, },
{ {
name: 'home', name: 'home',
path: '/home', path: '/home',
redirect: '/chat', redirect: '/chat',
meta: {title: '首页'},
component: () => import('@/views/Home.vue'), component: () => import('@/views/Home.vue'),
children: [ children: [
{ {
@ -273,11 +274,22 @@ const router = createRouter({
routes: routes, routes: routes,
}) })
const active = ref(false)
const title = ref('')
httpGet("/api/config/license").then(res => {
active.value = res.data.de_copy
}).catch(() => {})
httpGet("/api/config/get?key=system").then(res => {
title.value = res.data.title
}).catch(()=>{})
let prevRoute = null let prevRoute = null
// dynamic change the title when router change // dynamic change the title when router change
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
if (to.meta.title) { if (!active.value) {
document.title = `${to.meta.title} | ${process.env.VUE_APP_TITLE}` document.title = `${to.meta.title} | ${process.env.VUE_APP_TITLE}`
} else {
document.title = `${to.meta.title} | ${title.value}`
} }
prevRoute = from prevRoute = from
next() next()

View File

@ -222,15 +222,29 @@ export function processContent(content) {
return texts.join("\n") return texts.join("\n")
} }
export function escapeHTML(html) { export function processPrompt(prompt) {
return html.replace(/&/g, "&amp;") prompt = prompt.replace(/&/g, "&amp;")
.replace(/</g, "&lt;") .replace(/</g, "&lt;")
.replace(/>/g, "&gt;"); .replace(/>/g, "&gt;");
const linkRegex = /(https?:\/\/\S+)/g;
const links = prompt.match(linkRegex);
if (links) {
for (let link of links) {
if (isImage(link)) {
const index = prompt.indexOf(link)
if (prompt.substring(index - 1, 2) !== "]") {
prompt = prompt.replace(link, "\n![](" + link + ")\n")
}
}
}
}
return prompt
} }
// 判断是否为 iphone 设备 // 判断是否为微信浏览器
export function isIphone() { export function isWeChatBrowser() {
return /iPhone/i.test(navigator.userAgent) && !/iPad/i.test(navigator.userAgent); return /MicroMessenger/i.test( navigator.userAgent);
} }
export function showLoginDialog(router) { export function showLoginDialog(router) {

View File

@ -191,7 +191,15 @@ import ChatPrompt from "@/components/ChatPrompt.vue";
import ChatReply from "@/components/ChatReply.vue"; import ChatReply from "@/components/ChatReply.vue";
import {Delete, Edit, More, Plus, Promotion, Search, Share, VideoPause} from '@element-plus/icons-vue' import {Delete, Edit, More, Plus, Promotion, Search, Share, VideoPause} from '@element-plus/icons-vue'
import 'highlight.js/styles/a11y-dark.css' import 'highlight.js/styles/a11y-dark.css'
import {dateFormat, escapeHTML, isMobile, processContent, randString, removeArrayItem, UUID} from "@/utils/libs"; import {
dateFormat,
isMobile,
processContent,
processPrompt,
randString,
removeArrayItem,
UUID
} from "@/utils/libs";
import {ElMessage, ElMessageBox} from "element-plus"; import {ElMessage, ElMessageBox} from "element-plus";
import hl from "highlight.js"; import hl from "highlight.js";
import {getSessionId, getUserToken, removeUserToken} from "@/store/session"; import {getSessionId, getUserToken, removeUserToken} from "@/store/session";
@ -697,8 +705,10 @@ const onInput = (e) => {
inputRef.value.scrollTo(0, inputRef.value.scrollHeight) inputRef.value.scrollTo(0, inputRef.value.scrollHeight)
if (prompt.value.length < 10) { if (prompt.value.length < 10) {
row.value = 1 row.value = 1
} else if (row.value <= 7) { } else if (lines <= 7){
row.value = lines row.value = lines
} else {
row.value = 7
} }
// //
@ -738,7 +748,7 @@ const sendMessage = function () {
type: "prompt", type: "prompt",
id: randString(32), id: randString(32),
icon: loginUser.value.avatar, icon: loginUser.value.avatar,
content: md.render(escapeHTML(processContent(prompt.value))), content: md.render(processPrompt(prompt.value)),
created_at: new Date().getTime() / 1000, created_at: new Date().getTime() / 1000,
}); });

View File

@ -167,11 +167,6 @@
<i class="iconfont icon-loading"></i> <i class="iconfont icon-loading"></i>
<span>正在下载图片</span> <span>正在下载图片</span>
</div> </div>
<div class="image-slot">
<el-icon>
<Picture/>
</el-icon>
</div>
</template> </template>
</el-image> </el-image>

View File

@ -46,6 +46,7 @@
<span class="username">{{ loginUser.nickname }}</span> <span class="username">{{ loginUser.nickname }}</span>
</el-dropdown-item> </el-dropdown-item>
<div v-if="!licenseConfig.de_copy">
<el-dropdown-item> <el-dropdown-item>
<i class="iconfont icon-book"></i> <i class="iconfont icon-book"></i>
<a href="https://github.com/yangjian102621/chatgpt-plus" target="_blank"> <a href="https://github.com/yangjian102621/chatgpt-plus" target="_blank">
@ -59,6 +60,7 @@
Geek-AI {{ version }} Geek-AI {{ version }}
</a> </a>
</el-dropdown-item> </el-dropdown-item>
</div>
<el-divider style="margin: 2px 0"/> <el-divider style="margin: 2px 0"/>
<el-dropdown-item @click="logout"> <el-dropdown-item @click="logout">
<i class="iconfont icon-logout"></i> <i class="iconfont icon-logout"></i>
@ -185,7 +187,7 @@ onMounted(() => {
httpGet("/api/menu/list").then(res => { httpGet("/api/menu/list").then(res => {
mainNavs.value = res.data mainNavs.value = res.data
// //
const rows = Math.floor((window.innerHeight - 90) / 60) const rows = Math.floor((window.innerHeight - 100) / 90)
if (res.data.length > rows) { if (res.data.length > rows) {
mainNavs.value = res.data.slice(0, rows) mainNavs.value = res.data.slice(0, rows)
moreNavs.value = res.data.slice(rows) moreNavs.value = res.data.slice(rows)

View File

@ -515,6 +515,13 @@
正在加载图片 正在加载图片
</div> </div>
</template> </template>
<template #error>
<div class="image-slot">
<el-icon>
<Picture/>
</el-icon>
</div>
</template>
</el-image> </el-image>
<el-image v-else> <el-image v-else>
<template #error> <template #error>
@ -522,11 +529,6 @@
<i class="iconfont icon-loading"></i> <i class="iconfont icon-loading"></i>
<span>正在下载图片</span> <span>正在下载图片</span>
</div> </div>
<div class="image-slot">
<el-icon>
<Picture/>
</el-icon>
</div>
</template> </template>
</el-image> </el-image>

View File

@ -308,11 +308,7 @@
</template> </template>
<template #error> <template #error>
<div class="image-slot"> <div class="image-slot"></div>
<el-icon>
<Picture/>
</el-icon>
</div>
</template> </template>
</el-image> </el-image>

View File

@ -26,8 +26,11 @@
</el-button> </el-button>
</a> </a>
</span> </span>
<span v-if="!isLogin">
<el-button @click="router.push('/login')" round>登录</el-button> <el-button @click="router.push('/login')" round>登录</el-button>
<el-button @click="router.push('/register')" round>注册</el-button> <el-button @click="router.push('/register')" round>注册</el-button>
</span>
</div> </div>
</el-menu> </el-menu>
</div> </div>
@ -69,6 +72,7 @@ import FooterBar from "@/components/FooterBar.vue";
import {httpGet} from "@/utils/http"; import {httpGet} from "@/utils/http";
import {ElMessage} from "element-plus"; import {ElMessage} from "element-plus";
import {isMobile} from "@/utils/libs"; import {isMobile} from "@/utils/libs";
import {checkSession} from "@/action/session";
const router = useRouter() const router = useRouter()
@ -83,6 +87,7 @@ const licenseConfig = ref({})
// const size = Math.max(window.innerWidth * 0.5, window.innerHeight * 0.8) // const size = Math.max(window.innerWidth * 0.5, window.innerHeight * 0.8)
const winHeight = window.innerHeight - 150 const winHeight = window.innerHeight - 150
const bgClass = ref('fixed-bg') const bgClass = ref('fixed-bg')
const isLogin = ref(false)
onMounted(() => { onMounted(() => {
httpGet("/api/config/get?key=system").then(res => { httpGet("/api/config/get?key=system").then(res => {
@ -91,6 +96,9 @@ onMounted(() => {
if (res.data.rand_bg) { if (res.data.rand_bg) {
bgClass.value = "rand-bg" bgClass.value = "rand-bg"
} }
if (res.data.slogan) {
slogan.value = res.data.slogan
}
}).catch(e => { }).catch(e => {
ElMessage.error("获取系统配置失败:" + e.message) ElMessage.error("获取系统配置失败:" + e.message)
}) })
@ -100,11 +108,11 @@ onMounted(() => {
}).catch(e => { }).catch(e => {
ElMessage.error("获取 License 配置:" + e.message) ElMessage.error("获取 License 配置:" + e.message)
}) })
init()
})
const init = () => { checkSession().then(() => {
} isLogin.value = true
}).catch(()=>{})
})
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>

View File

@ -5,9 +5,8 @@
<h2>会员推广计划</h2> <h2>会员推广计划</h2>
<div class="share-box"> <div class="share-box">
<div class="info"> <div class="info">
我们非常欢迎您把此应用分享给您身边的朋友分享成功注册后您将获得 <strong>{{ inviteChatCalls }}</strong> 我们非常欢迎您把此应用分享给您身边的朋友分享成功注册后您和被邀请人都将获得 <strong>{{ invitePower }}</strong>
次对话额度以及 算力额度作为奖励
<strong>{{ inviteImgCalls }}</strong> 次AI绘画额度作为奖励
你可以保存下面的二维码或者直接复制分享您的专属推广链接发送给微信好友 你可以保存下面的二维码或者直接复制分享您的专属推广链接发送给微信好友
</div> </div>
@ -99,8 +98,7 @@ import {useSharedStore} from "@/store/sharedata";
const inviteURL = ref("") const inviteURL = ref("")
const qrImg = ref("/images/wx.png") const qrImg = ref("/images/wx.png")
const inviteChatCalls = ref(0) const invitePower = ref(0)
const inviteImgCalls = ref(0)
const hits = ref(0) const hits = ref(0)
const regNum = ref(0) const regNum = ref(0)
const rate = ref(0) const rate = ref(0)
@ -144,8 +142,7 @@ const initData = () => {
}) })
httpGet("/api/config/get?key=system").then(res => { httpGet("/api/config/get?key=system").then(res => {
inviteChatCalls.value = res.data["invite_chat_calls"] invitePower.value = res.data["invite_power"]
inviteImgCalls.value = res.data["invite_img_calls"]
}).catch(e => { }).catch(e => {
ElMessage.error("获取系统配置失败:" + e.message) ElMessage.error("获取系统配置失败:" + e.message)
}) })

View File

@ -76,6 +76,9 @@
<el-button type="success" @click="PayJs(scope.item)" size="small" v-if="payWays['payjs']"> <el-button type="success" @click="PayJs(scope.item)" size="small" v-if="payWays['payjs']">
<span><i class="iconfont icon-wechat-pay"></i> 微信</span> <span><i class="iconfont icon-wechat-pay"></i> 微信</span>
</el-button> </el-button>
<el-button type="success" @click="wechatPay(scope.item)" size="small" v-if="payWays['wechat']">
<i class="iconfont icon-wechat-pay"></i> 微信
</el-button>
</div> </div>
</div> </div>
</div> </div>
@ -237,9 +240,11 @@ onMounted(() => {
// refresh payment qrcode // refresh payment qrcode
const refreshPayCode = () => { const refreshPayCode = () => {
if (curPay.value === 'alipay') { if (curPay.value === 'alipay') {
alipay() alipay(curPayProduct.value)
} else if (curPay.value === 'hupi') { } else if (curPay.value === 'hupi') {
huPiPay() huPiPay(curPayProduct.value)
} else if (curPay.value === 'payjs') {
PayJs(curPayProduct.value)
} }
} }
@ -312,6 +317,21 @@ const PayJs = (row) => {
genPayQrcode() genPayQrcode()
} }
const wechatPay = (row) => {
payName.value = '微信'
curPay.value = "wechat"
amount.value = (row.price - row.discount).toFixed(2)
if (!isLogin.value) {
store.setShowLoginDialog(true)
return
}
if (row) {
curPayProduct.value = row
}
genPayQrcode()
}
const queryOrder = (orderNo) => { const queryOrder = (orderNo) => {
httpPost("/api/payment/query", {order_no: orderNo}).then(res => { httpPost("/api/payment/query", {order_no: orderNo}).then(res => {
if (res.data.status === 1) { if (res.data.status === 1) {

View File

@ -13,6 +13,9 @@
<el-form-item label="控制台标题" prop="admin_title"> <el-form-item label="控制台标题" prop="admin_title">
<el-input v-model="system['admin_title']"/> <el-input v-model="system['admin_title']"/>
</el-form-item> </el-form-item>
<el-form-item label="网站Slogan" prop="slogan">
<el-input v-model="system['slogan']"/>
</el-form-item>
<el-form-item label="网站 LOGO" prop="logo"> <el-form-item label="网站 LOGO" prop="logo">
<el-input v-model="system['logo']" placeholder="网站LOGO图片"> <el-input v-model="system['logo']" placeholder="网站LOGO图片">
<template #append> <template #append>
@ -44,7 +47,7 @@
</el-tooltip> </el-tooltip>
</el-form-item> </el-form-item>
<el-form-item label="随机背景"> <el-form-item label="动态背景">
<el-switch v-model="system['rand_bg']"/> <el-switch v-model="system['rand_bg']"/>
<el-tooltip <el-tooltip
effect="dark" effect="dark"

View File

@ -1,9 +1,7 @@
<template> <template>
<div class="index container"> <div class="index container">
<h2 class="title">{{title}}</h2> <h2 class="title">{{title}}</h2>
<van-notice-bar left-icon="info-o" :scrollable="true"> <van-notice-bar left-icon="info-o" :scrollable="true">{{slogan}}}</van-notice-bar>
你有多少想象力AI就有多大创造力我辈之人先干为敬陪您先把 AI 用起来
</van-notice-bar>
<div class="content"> <div class="content">
<van-grid :column-num="3" :gutter="10" border> <van-grid :column-num="3" :gutter="10" border>
@ -90,8 +88,18 @@ const isLogin = ref(false)
const apps = ref([]) const apps = ref([])
const loading = ref(false) const loading = ref(false)
const roles = ref([]) const roles = ref([])
const slogan = ref('你有多大想象力AI就有多大创造力')
onMounted(() => { onMounted(() => {
httpGet("/api/config/get?key=system").then(res => {
title.value = res.data.title
if (res.data.slogan) {
slogan.value = res.data.slogan
}
}).catch(e => {
ElMessage.error("获取系统配置失败:" + e.message)
})
checkSession().then((user) => { checkSession().then((user) => {
isLogin.value = true isLogin.value = true
roles.value = user.chat_roles roles.value = user.chat_roles

View File

@ -69,6 +69,9 @@
<van-button type="success" @click="pay('payjs',item)" size="small" v-if="payWays['payjs']"> <van-button type="success" @click="pay('payjs',item)" size="small" v-if="payWays['payjs']">
<span><i class="iconfont icon-wechat-pay"></i> 微信</span> <span><i class="iconfont icon-wechat-pay"></i> 微信</span>
</van-button> </van-button>
<van-button type="primary" @click="pay('wechat',item)" size="small" v-if="payWays['wechat']">
<i class="iconfont icon-wechat-pay"></i> 微信
</van-button>
</div> </div>
</h4> </h4>
@ -151,10 +154,10 @@
<script setup> <script setup>
import {onMounted, ref} from "vue"; import {onMounted, ref} from "vue";
import {showFailToast, showNotify, showSuccessToast} from "vant"; import {showFailToast, showNotify, showSuccessToast, showToast} from "vant";
import {httpGet, httpPost} from "@/utils/http"; import {httpGet, httpPost} from "@/utils/http";
import Compressor from 'compressorjs'; import Compressor from 'compressorjs';
import {dateFormat, showLoginDialog} from "@/utils/libs"; import {dateFormat, isWeChatBrowser, showLoginDialog} from "@/utils/libs";
import {ElMessage} from "element-plus"; import {ElMessage} from "element-plus";
import {checkSession} from "@/action/session"; import {checkSession} from "@/action/session";
import {useRouter} from "vue-router"; import {useRouter} from "vue-router";
@ -296,8 +299,11 @@ const pay = (payWay, item) => {
product_id: item.id, product_id: item.id,
user_id: userId.value user_id: userId.value
}).then(res => { }).then(res => {
// console.log(res.data) if (isWeChatBrowser() && payWay === 'wechat') {
showFailToast("请在系统自带浏览器打开支付页面,或者在 PC 端进行扫码支付")
} else {
location.href = res.data location.href = res.data
}
}).catch(e => { }).catch(e => {
showFailToast("生成支付订单失败:" + e.message) showFailToast("生成支付订单失败:" + e.message)
}) })