diff --git a/CHANGELOG.md b/CHANGELOG.md index cd735b0..11b42a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,15 @@ # 更新日志 +## v4.1.0 +* bug修复:修复移动端修改聊天标题不生效的问题 +* Bug修复:修复用户注册不显示用户名的问题 +* Bug修复:修复管理后台拖动排序不生效的问题 +* 功能优化:允许用户设置自定义首页背景图片 +* 功能新增:**支持AI解读 PDF, Word, Excel等文件** +* 功能优化:优化聊天界面的用户上传文件的列表样式 +* 功能优化:优化聊天页面对话样式,支持列表样式和对话样式切换 +* 功能新增:支持微信扫码登录,未注册用户微信扫码后会自动注册并登录。移动使用微信浏览器打开可以实现无感登录。 + + ## v4.0.9 * 环境升级:升级 Golang 到 go1.22.4 * 功能增加:接入微信商户号支付渠道 diff --git a/api/config.sample.toml b/api/config.sample.toml index 2b9642d..4f2819a 100644 --- a/api/config.sample.toml +++ b/api/config.sample.toml @@ -5,6 +5,7 @@ StaticDir = "./static" # 静态资源的目录 StaticUrl = "/static" # 静态资源访问 URL AesEncryptKey = "" WeChatBot = false +TikaHost = "http://tika:9998" [Session] SecretKey = "azyehq3ivunjhbntz78isj00i4hz2mt9xtddysfucxakadq4qbfrt0b7q3lnvg80" # 注意:这个是 JWT Token 授权密钥,生产环境请务必更换 @@ -122,4 +123,16 @@ WeChatBot = false AppId = "" # 商户 ID PrivateKey = "" # 秘钥 ApiURL = "https://payjs.cn" - NotifyURL = "https://ai.r9it.com/api/payment/payjs/notify" # 异步回调地址,域名改成你自己的 \ No newline at end of file + NotifyURL = "https://ai.r9it.com/api/payment/payjs/notify" # 异步回调地址,域名改成你自己的 + +# 微信商户支付 +[WechatPayConfig] + Enabled = false + AppId = "" # 商户应用ID + MchId = "" # 商户号 + SerialNo = "" # API 证书序列号 + PrivateKey = "certs/alipay/privateKey.txt" # API 证书私钥文件路径,跟支付宝一样,把私钥文件拷贝到对应的路径,证书路径要映射到容器内 + ApiV3Key = "" # APIV3 私钥,这个是你自己在微信支付平台设置的 + NotifyURL = "https://ai.r9it.com/api/payment/wechat/notify" # 支付成功异步回调地址,域名改成自己的 + ReturnURL = "" # 支付成功同步回调地址 + diff --git a/api/core/app_server.go b/api/core/app_server.go index 6d236e7..12a1756 100644 --- a/api/core/app_server.go +++ b/api/core/app_server.go @@ -32,31 +32,19 @@ import ( ) type AppServer struct { - Debug bool - Config *types.AppConfig - Engine *gin.Engine - ChatContexts *types.LMap[string, []types.Message] // 聊天上下文 Map [chatId] => []Message - + Debug bool + Config *types.AppConfig + Engine *gin.Engine SysConfig *types.SystemConfig // system config cache - - // 保存 Websocket 会话 UserId, 每个 UserId 只能连接一次 - // 防止第三方直接连接 socket 调用 OpenAI API - ChatSession *types.LMap[string, *types.ChatSession] //map[sessionId]UserId - ChatClients *types.LMap[string, *types.WsClient] // map[sessionId]Websocket 连接集合 - ReqCancelFunc *types.LMap[string, context.CancelFunc] // HttpClient 请求取消 handle function } func NewServer(appConfig *types.AppConfig) *AppServer { gin.SetMode(gin.ReleaseMode) gin.DefaultWriter = io.Discard return &AppServer{ - Debug: false, - Config: appConfig, - Engine: gin.Default(), - ChatContexts: types.NewLMap[string, []types.Message](), - ChatSession: types.NewLMap[string, *types.ChatSession](), - ChatClients: types.NewLMap[string, *types.WsClient](), - ReqCancelFunc: types.NewLMap[string, context.CancelFunc](), + Debug: false, + Config: appConfig, + Engine: gin.Default(), } } @@ -237,6 +225,7 @@ func needLogin(c *gin.Context) bool { c.Request.URL.Path == "/api/payment/doPay" || c.Request.URL.Path == "/api/payment/payWays" || strings.HasPrefix(c.Request.URL.Path, "/api/test") || + strings.HasPrefix(c.Request.URL.Path, "/api/user/clogin") || strings.HasPrefix(c.Request.URL.Path, "/api/config/") || strings.HasPrefix(c.Request.URL.Path, "/api/function/") || strings.HasPrefix(c.Request.URL.Path, "/api/sms/") || diff --git a/api/core/types/chat.go b/api/core/types/chat.go index 3827b86..cdf418b 100644 --- a/api/core/types/chat.go +++ b/api/core/types/chat.go @@ -53,9 +53,8 @@ type Delta struct { // ChatSession 聊天会话对象 type ChatSession struct { SessionId string `json:"session_id"` + UserId uint `json:"user_id"` ClientIP string `json:"client_ip"` // 客户端 IP - Username string `json:"username"` // 当前登录的 username - UserId uint `json:"user_id"` // 当前登录的 user ID ChatId string `json:"chat_id"` // 客户端聊天会话 ID, 多会话模式专用字段 Model ChatModel `json:"model"` // GPT 模型 } diff --git a/api/core/types/config.go b/api/core/types/config.go index ccd1dad..a31be48 100644 --- a/api/core/types/config.go +++ b/api/core/types/config.go @@ -35,6 +35,7 @@ type AppConfig struct { SmtpConfig SmtpConfig // 邮件发送配置 JPayConfig JPayConfig // payjs 支付配置 WechatPayConfig WechatPayConfig // 微信支付渠道配置 + TikaHost string // TiKa 服务器地址 } type SmtpConfig struct { @@ -226,5 +227,5 @@ type SystemConfig struct { SdNegPrompt string `json:"sd_neg_prompt"` // SD 默认反向提示词 - RandBg bool `json:"rand_bg"` // 前端首页是否启用随机背景 + IndexBgURL string `json:"index_bg_url"` // 前端首页背景图片 } diff --git a/api/core/types/task.go b/api/core/types/task.go index 6224a38..129a83b 100644 --- a/api/core/types/task.go +++ b/api/core/types/task.go @@ -53,10 +53,10 @@ type SdTaskParams struct { NegPrompt string `json:"neg_prompt"` // 反向提示词 Steps int `json:"steps"` // 迭代步数,默认20 Sampler string `json:"sampler"` // 采样器 - Scheduler string `json:"scheduler"` - FaceFix bool `json:"face_fix"` // 面部修复 - CfgScale float32 `json:"cfg_scale"` //引导系数,默认 7 - Seed int64 `json:"seed"` // 随机数种子 + Scheduler string `json:"scheduler"` // 采样调度 + FaceFix bool `json:"face_fix"` // 面部修复 + CfgScale float32 `json:"cfg_scale"` //引导系数,默认 7 + Seed int64 `json:"seed"` // 随机数种子 Height int `json:"height"` Width int `json:"width"` HdFix bool `json:"hd_fix"` // 启用高清修复 diff --git a/api/core/types/web.go b/api/core/types/web.go index 08f5ee9..408d9a5 100644 --- a/api/core/types/web.go +++ b/api/core/types/web.go @@ -22,6 +22,7 @@ type WsMessage struct { Type WsMsgType `json:"type"` // 消息类别,start, end, img Content interface{} `json:"content"` } + type WsMsgType string const ( @@ -36,11 +37,9 @@ type BizCode int const ( Success = BizCode(0) Failed = BizCode(1) - NotAuthorized = BizCode(400) // 未授权 - NotPermission = BizCode(403) // 没有权限 + NotAuthorized = BizCode(401) // 未授权 OkMsg = "Success" ErrorMsg = "系统开小差了" InvalidArgs = "非法参数或参数解析失败" - NoData = "No Data" ) diff --git a/api/go.mod b/api/go.mod index f394643..2a8efd4 100644 --- a/api/go.mod +++ b/api/go.mod @@ -28,14 +28,17 @@ require github.com/xxl-job/xxl-job-executor-go v1.2.0 require ( github.com/go-pay/gopay v1.5.101 - github.com/mojocn/base64Captcha v1.3.1 + github.com/google/go-tika v0.3.1 + github.com/microcosm-cc/bluemonday v1.0.26 + github.com/mojocn/base64Captcha v1.3.6 github.com/shirou/gopsutil v3.21.11+incompatible github.com/shopspring/decimal v1.3.1 github.com/syndtr/goleveldb v1.0.0 - golang.org/x/image v0.0.0-20211028202545-6944b10bf410 + golang.org/x/image v0.15.0 ) require ( + github.com/aymerick/douceur v0.2.0 // 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 @@ -44,8 +47,9 @@ require ( github.com/go-pay/xtime v0.0.2 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect - github.com/tklauser/go-sysconf v0.3.14 // indirect - github.com/tklauser/numcpus v0.8.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/tklauser/go-sysconf v0.3.13 // indirect + github.com/tklauser/numcpus v0.7.0 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.uber.org/mock v0.4.0 // indirect ) diff --git a/api/go.sum b/api/go.sum index 0bc389d..1cf070d 100644 --- a/api/go.sum +++ b/api/go.sum @@ -6,6 +6,8 @@ github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible h1:Sg/2xHwDrioHpxTN6WMiw github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= @@ -91,11 +93,15 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pO github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-tika v0.3.1 h1:l+jr10hDhZjcgxFRfcQChRLo1bPXQeLFluMyvDhXTTA= +github.com/google/go-tika v0.3.1/go.mod h1:DJh5N8qxXIl85QkqmXknd+PeeRkUOTbvwyYf7ieDz6c= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 h1:hR7/MlvK23p6+lIw9SN1TigNLn9ZnF3W4SYRKq2gAHs= github.com/google/pprof v0.0.0-20230602150820-91b7bce49751/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -137,6 +143,8 @@ github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20230415042440-a5e3d8259 github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20230415042440-a5e3d8259ae0/go.mod h1:C5LA5UO2ZXJrLaPLYtE1wUJMiyd/nwWaCO5cw/2pSHs= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.62 h1:qNYsFZHEzl+NfH8UxW4jpmlKav1qUAgfY30YNRneVhc= @@ -149,8 +157,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mojocn/base64Captcha v1.3.1 h1:2Wbkt8Oc8qjmNJ5GyOfSo4tgVQPsbKMftqASnq8GlT0= -github.com/mojocn/base64Captcha v1.3.1/go.mod h1:wAQCKEc5bDujxKRmbT6/vTnTt5CjStQ8bRfPWUuz/iY= +github.com/mojocn/base64Captcha v1.3.6 h1:gZEKu1nsKpttuIAQgWHO+4Mhhls8cAKyiV2Ew03H+Tw= +github.com/mojocn/base64Captcha v1.3.6/go.mod h1:i5CtHvm+oMbj1UzEPXaA8IH/xHFZ3DGY3Wh3dBpZ28E= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= @@ -212,8 +220,10 @@ github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gt github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= +github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY= github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= @@ -251,14 +261,17 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= -golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk= +golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= +golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -266,11 +279,16 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -285,17 +303,28 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= @@ -303,6 +332,7 @@ golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/api/handler/admin/admin_handler.go b/api/handler/admin/admin_handler.go index 3fceab8..001b94d 100644 --- a/api/handler/admin/admin_handler.go +++ b/api/handler/admin/admin_handler.go @@ -8,6 +8,8 @@ package admin // * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ import ( + "context" + "fmt" "geekai/core" "geekai/core/types" "geekai/handler" @@ -16,11 +18,8 @@ import ( "geekai/store/vo" "geekai/utils" "geekai/utils/resp" - "context" - "fmt" "github.com/go-redis/redis/v8" "github.com/golang-jwt/jwt/v5" - "github.com/mojocn/base64Captcha" "time" "github.com/gin-gonic/gin" @@ -56,11 +55,11 @@ func (h *ManagerHandler) Login(c *gin.Context) { return } - // add captcha - if !base64Captcha.DefaultMemStore.Verify(data.CaptchaId, data.Captcha, true) { - resp.ERROR(c, "验证码错误!") - return - } + //// add captcha + //if !base64Captcha.DefaultMemStore.Verify(data.CaptchaId, data.Captcha, true) { + // resp.ERROR(c, "验证码错误!") + // return + //} var manager model.AdminUser res := h.DB.Model(&model.AdminUser{}).Where("username = ?", data.Username).First(&manager) diff --git a/api/handler/admin/captcha_handler.go b/api/handler/admin/captcha_handler.go deleted file mode 100644 index e6b81cb..0000000 --- a/api/handler/admin/captcha_handler.go +++ /dev/null @@ -1,46 +0,0 @@ -package admin - -// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// * 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 ( - "geekai/core" - "geekai/handler" - "geekai/utils/resp" - "github.com/gin-gonic/gin" - "github.com/mojocn/base64Captcha" -) - -type CaptchaHandler struct { - handler.BaseHandler -} - -func NewCaptchaHandler(app *core.AppServer) *CaptchaHandler { - return &CaptchaHandler{BaseHandler: handler.BaseHandler{App: app}} -} - -type CaptchaVo struct { - CaptchaId string `json:"captcha_id"` - PicPath string `json:"pic_path"` -} - -// GetCaptcha 获取验证码 -func (h *CaptchaHandler) GetCaptcha(c *gin.Context) { - var captchaVo CaptchaVo - driver := base64Captcha.NewDriverDigit(48, 130, 4, 0.4, 10) - cp := base64Captcha.NewCaptcha(driver, base64Captcha.DefaultMemStore) - // b64s是图片的base64编码 - id, b64s, err := cp.Generate() - if err != nil { - resp.ERROR(c, "生成验证码错误!") - return - } - captchaVo.CaptchaId = id - captchaVo.PicPath = b64s - - resp.SUCCESS(c, captchaVo) -} diff --git a/api/handler/admin/chat_model_handler.go b/api/handler/admin/chat_model_handler.go index 74f187c..3a1e632 100644 --- a/api/handler/admin/chat_model_handler.go +++ b/api/handler/admin/chat_model_handler.go @@ -54,7 +54,6 @@ func (h *ChatModelHandler) Save(c *gin.Context) { Name: data.Name, Value: data.Value, Enabled: data.Enabled, - SortNum: data.SortNum, Open: data.Open, MaxTokens: data.MaxTokens, MaxContext: data.MaxContext, @@ -64,6 +63,7 @@ func (h *ChatModelHandler) Save(c *gin.Context) { var res *gorm.DB if data.Id > 0 { item.Id = data.Id + item.SortNum = data.SortNum res = h.DB.Select("*").Omit("created_at").Updates(&item) } else { res = h.DB.Create(&item) diff --git a/api/handler/admin/user_handler.go b/api/handler/admin/user_handler.go index 95da105..34747d7 100644 --- a/api/handler/admin/user_handler.go +++ b/api/handler/admin/user_handler.go @@ -139,7 +139,6 @@ func (h *UserHandler) Save(c *gin.Context) { salt := utils.RandString(8) u := model.User{ Username: data.Username, - Nickname: fmt.Sprintf("极客学长@%d", utils.RandomNumber(6)), Password: utils.GenPassword(data.Password, salt), Avatar: "/images/avatar/user.png", Salt: salt, @@ -149,6 +148,11 @@ func (h *UserHandler) Save(c *gin.Context) { ChatModels: utils.JsonEncode(data.ChatModels), ExpiredTime: utils.Str2stamp(data.ExpiredTime), } + if h.licenseService.GetLicense().Configs.DeCopy { + u.Nickname = fmt.Sprintf("用户@%d", utils.RandomNumber(6)) + } else { + u.Nickname = fmt.Sprintf("极客学长@%d", utils.RandomNumber(6)) + } res = h.DB.Create(&u) _ = utils.CopyObject(u, &userVo) userVo.Id = u.Id diff --git a/api/handler/chat_role_handler.go b/api/handler/chat_role_handler.go index 707e7f4..e220009 100644 --- a/api/handler/chat_role_handler.go +++ b/api/handler/chat_role_handler.go @@ -65,7 +65,7 @@ func (h *ChatRoleHandler) List(c *gin.Context) { } for _, r := range roles { - if !utils.ContainsStr(roleKeys, r.Key) { + if !utils.Contains(roleKeys, r.Key) { continue } var v vo.ChatRole diff --git a/api/handler/chatimpl/chat_handler.go b/api/handler/chatimpl/chat_handler.go index bd6ab8d..1aeb58e 100644 --- a/api/handler/chatimpl/chat_handler.go +++ b/api/handler/chatimpl/chat_handler.go @@ -44,6 +44,8 @@ type ChatHandler struct { redis *redis.Client uploadManager *oss.UploaderManager licenseService *service.LicenseService + ReqCancelFunc *types.LMap[string, context.CancelFunc] // HttpClient 请求取消 handle function + ChatContexts *types.LMap[string, []types.Message] // 聊天上下文 Map [chatId] => []Message } func NewChatHandler(app *core.AppServer, db *gorm.DB, redis *redis.Client, manager *oss.UploaderManager, licenseService *service.LicenseService) *ChatHandler { @@ -52,6 +54,8 @@ func NewChatHandler(app *core.AppServer, db *gorm.DB, redis *redis.Client, manag redis: redis, uploadManager: manager, licenseService: licenseService, + ReqCancelFunc: types.NewLMap[string, context.CancelFunc](), + ChatContexts: types.NewLMap[string, []types.Message](), } } @@ -89,21 +93,10 @@ func (h *ChatHandler) ChatHandle(c *gin.Context) { return } - session := h.App.ChatSession.Get(sessionId) - if session == nil { - user, err := h.GetLoginUser(c) - if err != nil { - logger.Info("用户未登录") - c.Abort() - return - } - session = &types.ChatSession{ - SessionId: sessionId, - ClientIP: c.ClientIP(), - Username: user.Username, - UserId: user.Id, - } - h.App.ChatSession.Put(sessionId, session) + session := &types.ChatSession{ + SessionId: sessionId, + ClientIP: c.ClientIP(), + UserId: h.GetLoginUserId(c), } // use old chat data override the chat model and role ID @@ -125,22 +118,18 @@ func (h *ChatHandler) ChatHandle(c *gin.Context) { Temperature: chatModel.Temperature, KeyId: chatModel.KeyId, Platform: chatModel.Platform} - logger.Infof("New websocket connected, IP: %s, Username: %s", c.ClientIP(), session.Username) + logger.Infof("New websocket connected, IP: %s", c.ClientIP()) - // 保存会话连接 - h.App.ChatClients.Put(sessionId, client) go func() { for { _, msg, err := client.Receive() if err != nil { logger.Debugf("close connection: %s", client.Conn.RemoteAddr()) client.Close() - h.App.ChatClients.Delete(sessionId) - h.App.ChatSession.Delete(sessionId) - cancelFunc := h.App.ReqCancelFunc.Get(sessionId) + cancelFunc := h.ReqCancelFunc.Get(sessionId) if cancelFunc != nil { cancelFunc() - h.App.ReqCancelFunc.Delete(sessionId) + h.ReqCancelFunc.Delete(sessionId) } return } @@ -160,7 +149,7 @@ func (h *ChatHandler) ChatHandle(c *gin.Context) { logger.Info("Receive a message: ", message.Content) ctx, cancel := context.WithCancel(context.Background()) - h.App.ReqCancelFunc.Put(sessionId, cancel) + h.ReqCancelFunc.Put(sessionId, cancel) // 回复消息 err = h.sendMessage(ctx, session, chatRole, utils.InterfaceToString(message.Content), client) if err != nil { @@ -274,8 +263,8 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio chatCtx := make([]types.Message, 0) messages := make([]types.Message, 0) if h.App.SysConfig.EnableContext { - if h.App.ChatContexts.Has(session.ChatId) { - messages = h.App.ChatContexts.Get(session.ChatId) + if h.ChatContexts.Has(session.ChatId) { + messages = h.ChatContexts.Get(session.ChatId) } else { _ = utils.JsonDecode(role.Context, &messages) if h.App.SysConfig.ContextDeep > 0 { @@ -323,20 +312,51 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio reqMgs = append(reqMgs, m) } + fullPrompt := prompt + text := prompt + // extract files in prompt + files := utils.ExtractFileURLs(prompt) + logger.Debugf("detected FILES: %+v", files) + // 如果不是逆向模型,则提取文件内容 + if len(files) > 0 && !(session.Model.Value == "gpt-4-all" || + strings.HasPrefix(session.Model.Value, "gpt-4-gizmo") || + strings.HasSuffix(session.Model.Value, "claude-3")) { + contents := make([]string, 0) + var file model.File + for _, v := range files { + h.DB.Where("url = ?", v).First(&file) + content, err := utils.ReadFileContent(v, h.App.Config.TikaHost) + if err != nil { + logger.Error("error with read file: ", err) + } else { + contents = append(contents, fmt.Sprintf("%s 文件内容:%s", file.Name, content)) + } + text = strings.Replace(text, v, "", 1) + } + if len(contents) > 0 { + fullPrompt = fmt.Sprintf("请根据提供的文件内容信息回答问题(其中Excel 已转成 HTML):\n\n %s\n\n 问题:%s", strings.Join(contents, "\n"), text) + } + + tokens, _ := utils.CalcTokens(fullPrompt, req.Model) + if tokens > session.Model.MaxContext { + return fmt.Errorf("文件的长度超出模型允许的最大上下文长度,请减少文件内容数量或文件大小。") + } + } + logger.Debug("最终Prompt:", fullPrompt) + if session.Model.Platform == types.QWen.Value { req.Input = make(map[string]interface{}) reqMgs = append(reqMgs, types.Message{ Role: "user", - Content: prompt, + Content: fullPrompt, }) req.Input["messages"] = reqMgs } 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.ExtractImgURLs(prompt) logger.Debugf("detected IMG: %+v", imgURLs) var content interface{} if len(imgURLs) > 0 { data := make([]interface{}, 0) - text := prompt for _, v := range imgURLs { text = strings.Replace(text, v, "", 1) data = append(data, gin.H{ @@ -348,11 +368,11 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio } data = append(data, gin.H{ "type": "text", - "text": text, + "text": strings.TrimSpace(text), }) content = data } else { - content = prompt + content = fullPrompt } req.Messages = append(reqMgs, map[string]interface{}{ "role": "user", @@ -361,7 +381,7 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio } else { req.Messages = append(reqMgs, map[string]interface{}{ "role": "user", - "content": prompt, + "content": fullPrompt, }) } @@ -442,9 +462,9 @@ func getTotalTokens(req types.ApiRequest) int { // StopGenerate 停止生成 func (h *ChatHandler) StopGenerate(c *gin.Context) { sessionId := c.Query("session_id") - if h.App.ReqCancelFunc.Has(sessionId) { - h.App.ReqCancelFunc.Get(sessionId)() - h.App.ReqCancelFunc.Delete(sessionId) + if h.ReqCancelFunc.Has(sessionId) { + h.ReqCancelFunc.Get(sessionId)() + h.ReqCancelFunc.Delete(sessionId) } resp.SUCCESS(c, types.OkMsg) } @@ -454,7 +474,7 @@ func (h *ChatHandler) StopGenerate(c *gin.Context) { func (h *ChatHandler) doRequest(ctx context.Context, req types.ApiRequest, session *types.ChatSession, apiKey *model.ApiKey) (*http.Response, error) { // if the chat model bind a KEY, use it directly if session.Model.KeyId > 0 { - h.DB.Debug().Where("id", session.Model.KeyId).Where("enabled", true).Find(apiKey) + h.DB.Where("id", session.Model.KeyId).Find(apiKey) } // use the last unused key if apiKey.Id == 0 { @@ -602,7 +622,7 @@ func (h *ChatHandler) saveChatHistory( if h.App.SysConfig.EnableContext { chatCtx = append(chatCtx, useMsg) // 提问消息 chatCtx = append(chatCtx, message) // 回复消息 - h.App.ChatContexts.Put(session.ChatId, chatCtx) + h.ChatContexts.Put(session.ChatId, chatCtx) } // 追加聊天记录 @@ -660,7 +680,7 @@ func (h *ChatHandler) saveChatHistory( res = h.DB.Where("chat_id = ?", session.ChatId).First(&chatItem) if res.Error != nil { chatItem.ChatId = session.ChatId - chatItem.UserId = session.UserId + chatItem.UserId = userVo.Id chatItem.RoleId = role.Id chatItem.ModelId = session.Model.Id if utf8.RuneCountInString(prompt) > 30 { diff --git a/api/handler/chatimpl/chat_item_handler.go b/api/handler/chatimpl/chat_item_handler.go index 3e04bf6..bce3924 100644 --- a/api/handler/chatimpl/chat_item_handler.go +++ b/api/handler/chatimpl/chat_item_handler.go @@ -96,7 +96,7 @@ func (h *ChatHandler) Clear(c *gin.Context) { for _, chat := range chats { chatIds = append(chatIds, chat.ChatId) // 清空会话上下文 - h.App.ChatContexts.Delete(chat.ChatId) + h.ChatContexts.Delete(chat.ChatId) } err = h.DB.Transaction(func(tx *gorm.DB) error { res := h.DB.Where("user_id =?", user.Id).Delete(&model.ChatItem{}) @@ -108,8 +108,6 @@ func (h *ChatHandler) Clear(c *gin.Context) { if res.Error != nil { return res.Error } - - // TODO: 是否要删除 MidJourney 绘画记录和图片文件? return nil }) @@ -175,7 +173,7 @@ func (h *ChatHandler) Remove(c *gin.Context) { // TODO: 是否要删除 MidJourney 绘画记录和图片文件? // 清空会话上下文 - h.App.ChatContexts.Delete(chatId) + h.ChatContexts.Delete(chatId) resp.SUCCESS(c, types.OkMsg) } diff --git a/api/handler/chatimpl/openai_handler.go b/api/handler/chatimpl/openai_handler.go index 8608941..97f7653 100644 --- a/api/handler/chatimpl/openai_handler.go +++ b/api/handler/chatimpl/openai_handler.go @@ -74,6 +74,9 @@ func (h *ChatHandler) sendOpenAiMessage( if len(responseBody.Choices) == 0 { // Fixed: 兼容 Azure API 第一个输出空行 continue } + if responseBody.Choices[0].Delta.Content == nil { + continue + } if responseBody.Choices[0].FinishReason == "stop" && len(contents) == 0 { utils.ReplyMessage(ws, "抱歉😔😔😔,AI助手由于未知原因已经停止输出内容。") diff --git a/api/handler/chatimpl/xunfei_handler.go b/api/handler/chatimpl/xunfei_handler.go index e4a081f..7ebea8d 100644 --- a/api/handler/chatimpl/xunfei_handler.go +++ b/api/handler/chatimpl/xunfei_handler.go @@ -79,7 +79,7 @@ func (h *ChatHandler) sendXunFeiMessage( var res *gorm.DB // use the bind key if session.Model.KeyId > 0 { - res = h.DB.Where("id", session.Model.KeyId).Where("enabled", true).Find(&apiKey) + res = h.DB.Where("id", session.Model.KeyId).Find(&apiKey) } // use the last unused key if apiKey.Id == 0 { diff --git a/api/handler/dalle_handler.go b/api/handler/dalle_handler.go index 07cd032..8922663 100644 --- a/api/handler/dalle_handler.go +++ b/api/handler/dalle_handler.go @@ -158,13 +158,13 @@ func (h *DallJobHandler) ImgWall(c *gin.Context) { // JobList 获取 SD 任务列表 func (h *DallJobHandler) JobList(c *gin.Context) { - status := h.GetBool(c, "status") + finish := h.GetBool(c, "finish") userId := h.GetLoginUserId(c) page := h.GetInt(c, "page", 0) pageSize := h.GetInt(c, "page_size", 0) publish := h.GetBool(c, "publish") - err, jobs := h.getData(status, userId, page, pageSize, publish) + err, jobs := h.getData(finish, userId, page, pageSize, publish) if err != nil { resp.ERROR(c, err.Error()) return @@ -214,25 +214,23 @@ func (h *DallJobHandler) getData(finish bool, userId uint, page int, pageSize in // Remove remove task image func (h *DallJobHandler) Remove(c *gin.Context) { - var data struct { - Id uint `json:"id"` - UserId uint `json:"user_id"` - ImgURL string `json:"img_url"` - } - if err := c.ShouldBindJSON(&data); err != nil { - resp.ERROR(c, types.InvalidArgs) + id := h.GetInt(c, "id", 0) + userId := h.GetInt(c, "user_id", 0) + var job model.DallJob + if res := h.DB.Where("id = ? AND user_id = ?", id, userId).First(&job); res.Error != nil { + resp.ERROR(c, "记录不存在") return } // remove job recode - res := h.DB.Delete(&model.DallJob{Id: data.Id}) + res := h.DB.Delete(&model.DallJob{Id: job.Id}) if res.Error != nil { resp.ERROR(c, res.Error.Error()) return } // remove image - err := h.uploader.GetUploadHandler().Delete(data.ImgURL) + err := h.uploader.GetUploadHandler().Delete(job.ImgURL) if err != nil { logger.Error("remove image failed: ", err) } @@ -242,16 +240,11 @@ func (h *DallJobHandler) Remove(c *gin.Context) { // Publish 发布/取消发布图片到画廊显示 func (h *DallJobHandler) Publish(c *gin.Context) { - var data struct { - Id uint `json:"id"` - Action bool `json:"action"` // 发布动作,true => 发布,false => 取消分享 - } - if err := c.ShouldBindJSON(&data); err != nil { - resp.ERROR(c, types.InvalidArgs) - return - } + id := h.GetInt(c, "id", 0) + userId := h.GetInt(c, "user_id", 0) + action := h.GetBool(c, "action") // 发布动作,true => 发布,false => 取消分享 - res := h.DB.Model(&model.DallJob{Id: data.Id}).UpdateColumn("publish", true) + res := h.DB.Model(&model.DallJob{Id: uint(id), UserId: uint(userId)}).UpdateColumn("publish", action) if res.Error != nil { logger.Error("error with update database:", res.Error) resp.ERROR(c, "更新数据库失败") diff --git a/api/handler/markmap_handler.go b/api/handler/markmap_handler.go index d656544..368d12f 100644 --- a/api/handler/markmap_handler.go +++ b/api/handler/markmap_handler.go @@ -215,7 +215,7 @@ func (h *MarkMapHandler) doRequest(req types.ApiRequest, chatModel model.ChatMod // if the chat model bind a KEY, use it directly var res *gorm.DB if chatModel.KeyId > 0 { - res = h.DB.Where("id", chatModel.KeyId).Where("enabled", true).Find(apiKey) + res = h.DB.Where("id", chatModel.KeyId).Find(apiKey) } // use the last unused key if apiKey.Id == 0 { diff --git a/api/handler/mj_handler.go b/api/handler/mj_handler.go index 7b8d7ca..56340af 100644 --- a/api/handler/mj_handler.go +++ b/api/handler/mj_handler.go @@ -92,19 +92,18 @@ func (h *MidJourneyHandler) Client(c *gin.Context) { // Image 创建一个绘画任务 func (h *MidJourneyHandler) Image(c *gin.Context) { var data struct { - SessionId string `json:"session_id"` TaskType string `json:"task_type"` Prompt string `json:"prompt"` NegPrompt string `json:"neg_prompt"` Rate string `json:"rate"` - Model string `json:"model"` - Chaos int `json:"chaos"` - Raw bool `json:"raw"` - Seed int64 `json:"seed"` - Stylize int `json:"stylize"` + Model string `json:"model"` // 模型 + Chaos int `json:"chaos"` // 创意度取值范围: 0-100 + Raw bool `json:"raw"` // 是否开启原始模型 + Seed int64 `json:"seed"` // 随机数 + Stylize int `json:"stylize"` // 风格化 ImgArr []string `json:"img_arr"` - Tile bool `json:"tile"` - Quality float32 `json:"quality"` + Tile bool `json:"tile"` // 重复平铺 + Quality float32 `json:"quality"` // 画质 Iw float32 `json:"iw"` CRef string `json:"cref"` //生成角色一致的图像 SRef string `json:"sref"` //生成风格一致的图像 @@ -243,17 +242,12 @@ type reqVo struct { ChannelId string `json:"channel_id"` MessageId string `json:"message_id"` MessageHash string `json:"message_hash"` - SessionId string `json:"session_id"` - Prompt string `json:"prompt"` - ChatId string `json:"chat_id"` - RoleId int `json:"role_id"` - Icon string `json:"icon"` } // Upscale send upscale command to MidJourney Bot func (h *MidJourneyHandler) Upscale(c *gin.Context) { var data reqVo - if err := c.ShouldBindJSON(&data); err != nil || data.SessionId == "" { + if err := c.ShouldBindJSON(&data); err != nil { resp.ERROR(c, types.InvalidArgs) return } @@ -271,7 +265,6 @@ func (h *MidJourneyHandler) Upscale(c *gin.Context) { UserId: userId, TaskId: taskId, Progress: 0, - Prompt: data.Prompt, Power: h.App.SysConfig.MjActionPower, CreatedAt: time.Now(), } @@ -283,7 +276,6 @@ func (h *MidJourneyHandler) Upscale(c *gin.Context) { h.pool.PushTask(types.MjTask{ Id: job.Id, Type: types.TaskUpscale, - Prompt: data.Prompt, UserId: userId, ChannelId: data.ChannelId, Index: data.Index, @@ -318,7 +310,7 @@ func (h *MidJourneyHandler) Upscale(c *gin.Context) { // Variation send variation command to MidJourney Bot func (h *MidJourneyHandler) Variation(c *gin.Context) { var data reqVo - if err := c.ShouldBindJSON(&data); err != nil || data.SessionId == "" { + if err := c.ShouldBindJSON(&data); err != nil { resp.ERROR(c, types.InvalidArgs) return } @@ -337,7 +329,6 @@ func (h *MidJourneyHandler) Variation(c *gin.Context) { UserId: userId, TaskId: taskId, Progress: 0, - Prompt: data.Prompt, Power: h.App.SysConfig.MjActionPower, CreatedAt: time.Now(), } @@ -349,7 +340,6 @@ func (h *MidJourneyHandler) Variation(c *gin.Context) { h.pool.PushTask(types.MjTask{ Id: job.Id, Type: types.TaskVariation, - Prompt: data.Prompt, UserId: userId, Index: data.Index, ChannelId: data.ChannelId, @@ -397,13 +387,13 @@ func (h *MidJourneyHandler) ImgWall(c *gin.Context) { // JobList 获取 MJ 任务列表 func (h *MidJourneyHandler) JobList(c *gin.Context) { - status := h.GetBool(c, "status") + finish := h.GetBool(c, "finish") userId := h.GetLoginUserId(c) page := h.GetInt(c, "page", 0) pageSize := h.GetInt(c, "page_size", 0) publish := h.GetBool(c, "publish") - err, jobs := h.getData(status, userId, page, pageSize, publish) + err, jobs := h.getData(finish, userId, page, pageSize, publish) if err != nil { resp.ERROR(c, err.Error()) return @@ -446,14 +436,9 @@ func (h *MidJourneyHandler) getData(finish bool, userId uint, page int, pageSize } if item.Progress < 100 && item.ImgURL == "" && item.OrgURL != "" { - // discord 服务器图片需要使用代理转发图片数据流 - if strings.HasPrefix(item.OrgURL, "https://cdn.discordapp.com") { - image, err := utils.DownloadImage(item.OrgURL, h.App.Config.ProxyURL) - if err == nil { - job.ImgURL = "data:image/png;base64," + base64.StdEncoding.EncodeToString(image) - } - } else { - job.ImgURL = job.OrgURL + image, err := utils.DownloadImage(item.OrgURL, h.App.Config.ProxyURL) + if err == nil { + job.ImgURL = "data:image/png;base64," + base64.StdEncoding.EncodeToString(image) } } @@ -464,30 +449,27 @@ func (h *MidJourneyHandler) getData(finish bool, userId uint, page int, pageSize // Remove remove task image func (h *MidJourneyHandler) Remove(c *gin.Context) { - var data struct { - Id uint `json:"id"` - UserId uint `json:"user_id"` - ImgURL string `json:"img_url"` - } - if err := c.ShouldBindJSON(&data); err != nil { - resp.ERROR(c, types.InvalidArgs) + id := h.GetInt(c, "id", 0) + userId := h.GetInt(c, "user_id", 0) + var job model.MidJourneyJob + if res := h.DB.Where("id = ? AND user_id = ?", id, userId).First(&job); res.Error != nil { + resp.ERROR(c, "记录不存在") return } - // remove job recode - res := h.DB.Delete(&model.MidJourneyJob{Id: data.Id}) + res := h.DB.Delete(&job) if res.Error != nil { resp.ERROR(c, res.Error.Error()) return } // remove image - err := h.uploader.GetUploadHandler().Delete(data.ImgURL) + err := h.uploader.GetUploadHandler().Delete(job.ImgURL) if err != nil { logger.Error("remove image failed: ", err) } - client := h.pool.Clients.Get(data.UserId) + client := h.pool.Clients.Get(uint(job.UserId)) if client != nil { _ = client.Send([]byte("Task Updated")) } @@ -497,16 +479,10 @@ func (h *MidJourneyHandler) Remove(c *gin.Context) { // Publish 发布图片到画廊显示 func (h *MidJourneyHandler) Publish(c *gin.Context) { - var data struct { - Id uint `json:"id"` - Action bool `json:"action"` // 发布动作,true => 发布,false => 取消分享 - } - if err := c.ShouldBindJSON(&data); err != nil { - resp.ERROR(c, types.InvalidArgs) - return - } - - res := h.DB.Model(&model.MidJourneyJob{Id: data.Id}).UpdateColumn("publish", data.Action) + id := h.GetInt(c, "id", 0) + userId := h.GetInt(c, "user_id", 0) + action := h.GetBool(c, "action") // 发布动作,true => 发布,false => 取消分享 + res := h.DB.Model(&model.MidJourneyJob{Id: uint(id), UserId: userId}).UpdateColumn("publish", action) if res.Error != nil { logger.Error("error with update database:", res.Error) resp.ERROR(c, "更新数据库失败") diff --git a/api/handler/order_handler.go b/api/handler/order_handler.go index a56daa8..55348e1 100644 --- a/api/handler/order_handler.go +++ b/api/handler/order_handler.go @@ -14,6 +14,7 @@ import ( "geekai/store/vo" "geekai/utils" "geekai/utils/resp" + "time" "github.com/gin-gonic/gin" "gorm.io/gorm" @@ -27,23 +28,18 @@ func NewOrderHandler(app *core.AppServer, db *gorm.DB) *OrderHandler { return &OrderHandler{BaseHandler: BaseHandler{App: app, DB: db}} } +// List 订单列表 func (h *OrderHandler) List(c *gin.Context) { - var data struct { - Page int `json:"page"` - PageSize int `json:"page_size"` - } - if err := c.ShouldBindJSON(&data); err != nil { - resp.ERROR(c, types.InvalidArgs) - return - } + page := h.GetInt(c, "page", 1) + pageSize := h.GetInt(c, "page_size", 20) userId := h.GetLoginUserId(c) session := h.DB.Session(&gorm.Session{}).Where("user_id = ? AND status = ?", userId, types.OrderPaidSuccess) var total int64 session.Model(&model.Order{}).Count(&total) var items []model.Order var list = make([]vo.Order, 0) - offset := (data.Page - 1) * data.PageSize - res := session.Order("id DESC").Offset(offset).Limit(data.PageSize).Find(&items) + offset := (page - 1) * pageSize + res := session.Order("id DESC").Offset(offset).Limit(pageSize).Find(&items) if res.Error == nil { for _, item := range items { var order vo.Order @@ -58,5 +54,35 @@ func (h *OrderHandler) List(c *gin.Context) { } } } - resp.SUCCESS(c, vo.NewPage(total, data.Page, data.PageSize, list)) + resp.SUCCESS(c, vo.NewPage(total, page, pageSize, list)) +} + +// Query 查询订单状态 +func (h *OrderHandler) Query(c *gin.Context) { + orderNo := h.GetTrim(c, "order_no") + var order model.Order + res := h.DB.Where("order_no = ?", orderNo).First(&order) + if res.Error != nil { + resp.ERROR(c, "Order not found") + return + } + + if order.Status == types.OrderPaidSuccess { + resp.SUCCESS(c, gin.H{"status": order.Status}) + return + } + + counter := 0 + for { + time.Sleep(time.Second) + var item model.Order + h.DB.Where("order_no = ?", orderNo).First(&item) + if counter >= 15 || item.Status == types.OrderPaidSuccess || item.Status != order.Status { + order.Status = item.Status + break + } + counter++ + } + + resp.SUCCESS(c, gin.H{"status": order.Status}) } diff --git a/api/handler/payment_handler.go b/api/handler/payment_handler.go index c69f070..5d807f7 100644 --- a/api/handler/payment_handler.go +++ b/api/handler/payment_handler.go @@ -111,7 +111,7 @@ func (h *PaymentHandler) DoPay(c *gin.Context) { // fix: 这里先检查一下订单状态,如果已经支付了,就直接返回 if order.Status == types.OrderPaidSuccess { - resp.ERROR(c, "This order had been paid, please do not pay twice") + resp.ERROR(c, "订单已支付成功,无需重复支付!") return } @@ -148,49 +148,11 @@ func (h *PaymentHandler) DoPay(c *gin.Context) { resp.ERROR(c, "Invalid operations") } -// OrderQuery 查询订单状态 -func (h *PaymentHandler) OrderQuery(c *gin.Context) { - var data struct { - OrderNo string `json:"order_no"` - } - if err := c.ShouldBindJSON(&data); err != nil { - resp.ERROR(c, types.InvalidArgs) - return - } - - var order model.Order - res := h.DB.Where("order_no = ?", data.OrderNo).First(&order) - if res.Error != nil { - resp.ERROR(c, "Order not found") - return - } - - if order.Status == types.OrderPaidSuccess { - resp.SUCCESS(c, gin.H{"status": order.Status}) - return - } - - counter := 0 - for { - time.Sleep(time.Second) - var item model.Order - h.DB.Where("order_no = ?", data.OrderNo).First(&item) - if counter >= 15 || item.Status == types.OrderPaidSuccess || item.Status != order.Status { - order.Status = item.Status - break - } - counter++ - } - - resp.SUCCESS(c, gin.H{"status": order.Status}) -} - // PayQrcode 生成支付 URL 二维码 func (h *PaymentHandler) PayQrcode(c *gin.Context) { var data struct { PayWay string `json:"pay_way"` // 支付方式 ProductId uint `json:"product_id"` - UserId int `json:"user_id"` } if err := c.ShouldBindJSON(&data); err != nil { resp.ERROR(c, types.InvalidArgs) @@ -209,10 +171,9 @@ func (h *PaymentHandler) PayQrcode(c *gin.Context) { resp.ERROR(c, "error with generate trade no: "+err.Error()) return } - var user model.User - res = h.DB.First(&user, data.UserId) - if res.Error != nil { - resp.ERROR(c, "Invalid user ID") + user, err := h.GetLoginUser(c) + if err != nil { + resp.NotAuth(c) return } @@ -333,7 +294,6 @@ func (h *PaymentHandler) Mobile(c *gin.Context) { var data struct { PayWay string `json:"pay_way"` // 支付方式 ProductId uint `json:"product_id"` - UserId int `json:"user_id"` } if err := c.ShouldBindJSON(&data); err != nil { resp.ERROR(c, types.InvalidArgs) @@ -352,10 +312,9 @@ func (h *PaymentHandler) Mobile(c *gin.Context) { resp.ERROR(c, "error with generate trade no: "+err.Error()) return } - var user model.User - res = h.DB.First(&user, data.UserId) - if res.Error != nil { - resp.ERROR(c, "Invalid user ID") + user, err := h.GetLoginUser(c) + if err != nil { + resp.NotAuth(c) return } @@ -449,7 +408,7 @@ func (h *PaymentHandler) Mobile(c *gin.Context) { return } - resp.SUCCESS(c, payURL) + resp.SUCCESS(c, gin.H{"url": payURL, "order_no": orderNo}) } // 异步通知回调公共逻辑 diff --git a/api/handler/sd_handler.go b/api/handler/sd_handler.go index 5ed3c00..c99d2f9 100644 --- a/api/handler/sd_handler.go +++ b/api/handler/sd_handler.go @@ -99,10 +99,7 @@ func (h *SdJobHandler) Image(c *gin.Context) { return } - var data struct { - SessionId string `json:"session_id"` - types.SdTaskParams - } + var data types.SdTaskParams if err := c.ShouldBindJSON(&data); err != nil || data.Prompt == "" { resp.ERROR(c, types.InvalidArgs) return @@ -215,13 +212,13 @@ func (h *SdJobHandler) ImgWall(c *gin.Context) { // JobList 获取 SD 任务列表 func (h *SdJobHandler) JobList(c *gin.Context) { - status := h.GetBool(c, "status") + finish := h.GetBool(c, "finish") userId := h.GetLoginUserId(c) page := h.GetInt(c, "page", 0) pageSize := h.GetInt(c, "page_size", 0) publish := h.GetBool(c, "publish") - err, jobs := h.getData(status, userId, page, pageSize, publish) + err, jobs := h.getData(finish, userId, page, pageSize, publish) if err != nil { resp.ERROR(c, err.Error()) return @@ -280,30 +277,28 @@ func (h *SdJobHandler) getData(finish bool, userId uint, page int, pageSize int, // Remove remove task image func (h *SdJobHandler) Remove(c *gin.Context) { - var data struct { - Id uint `json:"id"` - UserId uint `json:"user_id"` - ImgURL string `json:"img_url"` - } - if err := c.ShouldBindJSON(&data); err != nil { - resp.ERROR(c, types.InvalidArgs) + id := h.GetInt(c, "id", 0) + userId := h.GetInt(c, "user_id", 0) + var job model.SdJob + if res := h.DB.Where("id = ? AND user_id = ?", id, userId).First(&job); res.Error != nil { + resp.ERROR(c, "记录不存在") return } // remove job recode - res := h.DB.Delete(&model.SdJob{Id: data.Id}) + res := h.DB.Delete(&model.SdJob{Id: job.Id}) if res.Error != nil { resp.ERROR(c, res.Error.Error()) return } // remove image - err := h.uploader.GetUploadHandler().Delete(data.ImgURL) + err := h.uploader.GetUploadHandler().Delete(job.ImgURL) if err != nil { logger.Error("remove image failed: ", err) } - client := h.pool.Clients.Get(data.UserId) + client := h.pool.Clients.Get(uint(job.UserId)) if client != nil { _ = client.Send([]byte(sd.Finished)) } @@ -313,16 +308,11 @@ func (h *SdJobHandler) Remove(c *gin.Context) { // Publish 发布/取消发布图片到画廊显示 func (h *SdJobHandler) Publish(c *gin.Context) { - var data struct { - Id uint `json:"id"` - Action bool `json:"action"` // 发布动作,true => 发布,false => 取消分享 - } - if err := c.ShouldBindJSON(&data); err != nil { - resp.ERROR(c, types.InvalidArgs) - return - } + id := h.GetInt(c, "id", 0) + userId := h.GetInt(c, "user_id", 0) + action := h.GetBool(c, "action") // 发布动作,true => 发布,false => 取消分享 - res := h.DB.Model(&model.SdJob{Id: data.Id}).UpdateColumn("publish", true) + res := h.DB.Model(&model.SdJob{Id: uint(id), UserId: userId}).UpdateColumn("publish", action) if res.Error != nil { logger.Error("error with update database:", res.Error) resp.ERROR(c, "更新数据库失败") diff --git a/api/handler/sms_handler.go b/api/handler/sms_handler.go index 7740a77..680f73e 100644 --- a/api/handler/sms_handler.go +++ b/api/handler/sms_handler.go @@ -49,14 +49,20 @@ func (h *SmsHandler) SendCode(c *gin.Context) { var data struct { Receiver string `json:"receiver"` // 接收者 Key string `json:"key"` - Dots string `json:"dots"` + Dots string `json:"dots,omitempty"` + X int `json:"x,omitempty"` } if err := c.ShouldBindJSON(&data); err != nil { resp.ERROR(c, types.InvalidArgs) return } - - if !h.captcha.Check(data) { + var check bool + if data.X != 0 { + check = h.captcha.SlideCheck(data) + } else { + check = h.captcha.Check(data) + } + if !check { resp.ERROR(c, "验证码错误,请先完人机验证") return } @@ -64,13 +70,13 @@ func (h *SmsHandler) SendCode(c *gin.Context) { code := utils.RandomNumber(6) var err error if strings.Contains(data.Receiver, "@") { // email - if !utils.ContainsStr(h.App.SysConfig.RegisterWays, "email") { + if !utils.Contains(h.App.SysConfig.RegisterWays, "email") { resp.ERROR(c, "系统已禁用邮箱注册!") return } err = h.smtp.SendVerifyCode(data.Receiver, code) } else { - if !utils.ContainsStr(h.App.SysConfig.RegisterWays, "mobile") { + if !utils.Contains(h.App.SysConfig.RegisterWays, "mobile") { resp.ERROR(c, "系统已禁用手机号注册!") return } @@ -89,5 +95,9 @@ func (h *SmsHandler) SendCode(c *gin.Context) { return } - resp.SUCCESS(c) + if h.App.Debug { + resp.SUCCESS(c, code) + } else { + resp.SUCCESS(c) + } } diff --git a/api/handler/upload_handler.go b/api/handler/upload_handler.go index af37f97..9d2c870 100644 --- a/api/handler/upload_handler.go +++ b/api/handler/upload_handler.go @@ -9,6 +9,7 @@ package handler import ( "geekai/core" + "geekai/core/types" "geekai/service/oss" "geekai/store/model" "geekai/store/vo" @@ -35,6 +36,12 @@ func (h *UploadHandler) Upload(c *gin.Context) { return } + logger.Info("upload file: ", file.Name) + // cut the file name if it's too long + if len(file.Name) > 100 { + file.Name = file.Name[:90] + file.Ext + } + userId := h.GetLoginUserId(c) res := h.DB.Create(&model.File{ UserId: int(userId), @@ -54,10 +61,23 @@ func (h *UploadHandler) Upload(c *gin.Context) { } func (h *UploadHandler) List(c *gin.Context) { + var data struct { + Urls []string `json:"urls,omitempty"` + } + if err := c.ShouldBindJSON(&data); err != nil { + resp.ERROR(c, types.InvalidArgs) + return + } + userId := h.GetLoginUserId(c) var items []model.File var files = make([]vo.File, 0) - h.DB.Where("user_id = ?", userId).Find(&items) + session := h.DB.Session(&gorm.Session{}) + session = session.Where("user_id = ?", userId) + if len(data.Urls) > 0 { + session = session.Where("url IN ?", data.Urls) + } + session.Find(&items) if len(items) > 0 { for _, v := range items { var file vo.File diff --git a/api/handler/user_handler.go b/api/handler/user_handler.go index 84e9da4..5eb23a0 100644 --- a/api/handler/user_handler.go +++ b/api/handler/user_handler.go @@ -16,6 +16,7 @@ import ( "geekai/store/vo" "geekai/utils" "geekai/utils/resp" + "github.com/imroc/req/v3" "strings" "time" @@ -97,7 +98,7 @@ func (h *UserHandler) Register(c *gin.Context) { } } - // check if the username is exists + // check if the username is existing var item model.User res := h.DB.Where("username = ?", data.Username).First(&item) if item.Id > 0 { @@ -122,7 +123,7 @@ func (h *UserHandler) Register(c *gin.Context) { user.Power += h.App.SysConfig.InvitePower } if h.licenseService.GetLicense().Configs.DeCopy { - user.Username = fmt.Sprintf("用户@%d", utils.RandomNumber(6)) + user.Nickname = fmt.Sprintf("用户@%d", utils.RandomNumber(6)) } else { user.Nickname = fmt.Sprintf("极客学长@%d", utils.RandomNumber(6)) } @@ -184,7 +185,7 @@ func (h *UserHandler) Register(c *gin.Context) { resp.ERROR(c, "error with save token: "+err.Error()) return } - resp.SUCCESS(c, tokenString) + resp.SUCCESS(c, gin.H{"token": tokenString, "user_id": user.Id, "username": user.Username}) } // Login 用户登录 @@ -243,7 +244,7 @@ func (h *UserHandler) Login(c *gin.Context) { resp.ERROR(c, "error with save token: "+err.Error()) return } - resp.SUCCESS(c, tokenString) + resp.SUCCESS(c, gin.H{"token": tokenString, "user_id": user.Id, "username": user.Username}) } // Logout 注 销 @@ -255,6 +256,130 @@ func (h *UserHandler) Logout(c *gin.Context) { resp.SUCCESS(c) } +// CLogin 第三方登录请求二维码 +func (h *UserHandler) CLogin(c *gin.Context) { + returnURL := h.GetTrim(c, "return_url") + var res types.BizVo + apiURL := fmt.Sprintf("%s/api/clogin/request", h.App.Config.ApiConfig.ApiURL) + r, err := req.C().R().SetBody(gin.H{"login_type": "wx", "return_url": returnURL}). + SetHeader("AppId", h.App.Config.ApiConfig.AppId). + SetHeader("Authorization", fmt.Sprintf("Bearer %s", h.App.Config.ApiConfig.Token)). + SetSuccessResult(&res). + Post(apiURL) + if err != nil { + resp.ERROR(c, err.Error()) + return + } + if r.IsErrorState() { + resp.ERROR(c, "error with login http status: "+r.Status) + return + } + + if res.Code != types.Success { + resp.ERROR(c, "error with http response: "+res.Message) + return + } + + resp.SUCCESS(c, res.Data) +} + +// CLoginCallback 第三方登录回调 +func (h *UserHandler) CLoginCallback(c *gin.Context) { + loginType := h.GetTrim(c, "login_type") + code := h.GetTrim(c, "code") + + var res types.BizVo + apiURL := fmt.Sprintf("%s/api/clogin/info", h.App.Config.ApiConfig.ApiURL) + r, err := req.C().R().SetBody(gin.H{"login_type": loginType, "code": code}). + SetHeader("AppId", h.App.Config.ApiConfig.AppId). + SetHeader("Authorization", fmt.Sprintf("Bearer %s", h.App.Config.ApiConfig.Token)). + SetSuccessResult(&res). + Post(apiURL) + if err != nil { + resp.ERROR(c, err.Error()) + return + } + if r.IsErrorState() { + resp.ERROR(c, "error with login http status: "+r.Status) + return + } + + if res.Code != types.Success { + resp.ERROR(c, "error with http response: "+res.Message) + return + } + + // login successfully + data := res.Data.(map[string]interface{}) + session := gin.H{} + var user model.User + tx := h.DB.Debug().Where("openid", data["openid"]).First(&user) + if tx.Error != nil { // user not exist, create new user + // 检测最大注册人数 + var totalUser int64 + h.DB.Model(&model.User{}).Count(&totalUser) + if h.licenseService.GetLicense().Configs.UserNum > 0 && int(totalUser) >= h.licenseService.GetLicense().Configs.UserNum { + resp.ERROR(c, "当前注册用户数已达上限,请请升级 License") + return + } + + salt := utils.RandString(8) + password := fmt.Sprintf("%d", utils.RandomNumber(8)) + user = model.User{ + Username: fmt.Sprintf("%s@%d", loginType, utils.RandomNumber(10)), + Password: utils.GenPassword(password, salt), + Avatar: fmt.Sprintf("%s", data["avatar"]), + Salt: salt, + Status: true, + ChatRoles: utils.JsonEncode([]string{"gpt"}), // 默认只订阅通用助手角色 + ChatModels: utils.JsonEncode(h.App.SysConfig.DefaultModels), // 默认开通的模型 + Power: h.App.SysConfig.InitPower, + OpenId: fmt.Sprintf("%s", data["openid"]), + Nickname: fmt.Sprintf("%s", data["nickname"]), + } + + tx = h.DB.Create(&user) + if tx.Error != nil { + resp.ERROR(c, "保存数据失败") + logger.Error(tx.Error) + return + } + session["username"] = user.Username + session["password"] = password + } else { // login directly + // 更新最后登录时间和IP + user.LastLoginIp = c.ClientIP() + user.LastLoginAt = time.Now().Unix() + h.DB.Model(&user).Updates(user) + + h.DB.Create(&model.UserLoginLog{ + UserId: user.Id, + Username: user.Username, + LoginIp: c.ClientIP(), + LoginAddress: utils.Ip2Region(h.searcher, c.ClientIP()), + }) + } + + // 创建 token + token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "user_id": user.Id, + "expired": time.Now().Add(time.Second * time.Duration(h.App.Config.Session.MaxAge)).Unix(), + }) + tokenString, err := token.SignedString([]byte(h.App.Config.Session.SecretKey)) + if err != nil { + resp.ERROR(c, "Failed to generate token, "+err.Error()) + return + } + // 保存到 redis + key := fmt.Sprintf("users/%d", user.Id) + if _, err := h.redis.Set(c, key, tokenString, 0).Result(); err != nil { + resp.ERROR(c, "error with save token: "+err.Error()) + return + } + session["token"] = tokenString + resp.SUCCESS(c, session) +} + // Session 获取/验证会话 func (h *UserHandler) Session(c *gin.Context) { user, err := h.GetLoginUser(c) diff --git a/api/main.go b/api/main.go index e26d07f..3de8ece 100644 --- a/api/main.go +++ b/api/main.go @@ -240,6 +240,8 @@ func main() { group.POST("password", h.UpdatePass) group.POST("bind/username", h.BindUsername) group.POST("resetPass", h.ResetPass) + group.GET("clogin", h.CLogin) + group.GET("clogin/callback", h.CLoginCallback) }), fx.Invoke(func(s *core.AppServer, h *chatimpl.ChatHandler) { group := s.Engine.Group("/api/chat/") @@ -255,7 +257,7 @@ func main() { }), fx.Invoke(func(s *core.AppServer, h *handler.UploadHandler) { s.Engine.POST("/api/upload", h.Upload) - s.Engine.GET("/api/upload/list", h.List) + s.Engine.POST("/api/upload/list", h.List) s.Engine.GET("/api/upload/remove", h.Remove) }), fx.Invoke(func(s *core.AppServer, h *handler.SmsHandler) { @@ -281,8 +283,8 @@ func main() { group.POST("variation", h.Variation) group.GET("jobs", h.JobList) group.GET("imgWall", h.ImgWall) - group.POST("remove", h.Remove) - group.POST("publish", h.Publish) + group.GET("remove", h.Remove) + group.GET("publish", h.Publish) }), fx.Invoke(func(s *core.AppServer, h *handler.SdJobHandler) { group := s.Engine.Group("/api/sd") @@ -290,8 +292,8 @@ func main() { group.POST("image", h.Image) group.GET("jobs", h.JobList) group.GET("imgWall", h.ImgWall) - group.POST("remove", h.Remove) - group.POST("publish", h.Publish) + group.GET("remove", h.Remove) + group.GET("publish", h.Publish) }), fx.Invoke(func(s *core.AppServer, h *handler.ConfigHandler) { group := s.Engine.Group("/api/config/") @@ -368,7 +370,6 @@ func main() { group := s.Engine.Group("/api/payment/") group.GET("doPay", h.DoPay) group.GET("payWays", h.GetPayWays) - group.POST("query", h.OrderQuery) group.POST("qrcode", h.PayQrcode) group.POST("mobile", h.Mobile) group.POST("alipay/notify", h.AlipayNotify) @@ -391,7 +392,8 @@ func main() { }), fx.Invoke(func(s *core.AppServer, h *handler.OrderHandler) { group := s.Engine.Group("/api/order/") - group.POST("list", h.List) + group.GET("list", h.List) + group.GET("query", h.Query) }), fx.Invoke(func(s *core.AppServer, h *handler.ProductHandler) { group := s.Engine.Group("/api/product/") @@ -416,13 +418,6 @@ func main() { group.GET("token", h.GenToken) }), - // 验证码 - fx.Provide(admin.NewCaptchaHandler), - fx.Invoke(func(s *core.AppServer, h *admin.CaptchaHandler) { - group := s.Engine.Group("/api/admin/login/") - group.GET("captcha", h.GetCaptcha) - }), - fx.Provide(admin.NewUploadHandler), fx.Invoke(func(s *core.AppServer, h *admin.UploadHandler) { s.Engine.POST("/api/admin/upload", h.Upload) @@ -477,8 +472,8 @@ func main() { group.POST("image", h.Image) group.GET("jobs", h.JobList) group.GET("imgWall", h.ImgWall) - group.POST("remove", h.Remove) - group.POST("publish", h.Publish) + group.GET("remove", h.Remove) + group.GET("publish", h.Publish) }), fx.Invoke(func(s *core.AppServer, db *gorm.DB) { go func() { diff --git a/api/service/mj/pool.go b/api/service/mj/pool.go index 3eacfd7..7cf84a6 100644 --- a/api/service/mj/pool.go +++ b/api/service/mj/pool.go @@ -16,6 +16,7 @@ import ( "geekai/service/sd" "geekai/store" "geekai/store/model" + "geekai/utils" "github.com/go-redis/redis/v8" "strings" "time" @@ -58,13 +59,13 @@ func (p *ServicePool) InitServices(plusConfigs []types.MjPlusConfig, proxyConfig } p.services = make([]*Service, 0) - for k, config := range plusConfigs { + for _, config := range plusConfigs { if config.Enabled == false { continue } cli := NewPlusClient(config, p.licenseService) - name := fmt.Sprintf("mj-plus-service-%d", k) + name := utils.Md5(config.ApiURL) plusService := NewService(name, p.taskQueue, p.notifyQueue, p.db, cli) go func() { plusService.Run() @@ -73,12 +74,12 @@ func (p *ServicePool) InitServices(plusConfigs []types.MjPlusConfig, proxyConfig } // for mid-journey proxy - for k, config := range proxyConfigs { + for _, config := range proxyConfigs { if config.Enabled == false { continue } cli := NewProxyClient(config) - name := fmt.Sprintf("mj-proxy-service-%d", k) + name := utils.Md5(config.ApiURL) proxyService := NewService(name, p.taskQueue, p.notifyQueue, p.db, cli) go func() { proxyService.Run() @@ -209,7 +210,6 @@ func (p *ServicePool) SyncTaskProgress() { } continue } - if servicePlus := p.getService(job.ChannelId); servicePlus != nil { _ = servicePlus.Notify(job) } diff --git a/api/store/model/user.go b/api/store/model/user.go index 41d0990..bc2bafe 100644 --- a/api/store/model/user.go +++ b/api/store/model/user.go @@ -15,5 +15,7 @@ type User struct { Status bool `gorm:"default:true"` // 当前状态 LastLoginAt int64 // 最后登录时间 LastLoginIp string // 最后登录 IP + OpenId string `gorm:"column:openid"` + Platform string `json:"platform"` Vip bool // 是否 VIP 会员 } diff --git a/api/store/vo/user.go b/api/store/vo/user.go index 560f57d..8e0faab 100644 --- a/api/store/vo/user.go +++ b/api/store/vo/user.go @@ -14,4 +14,6 @@ type User struct { LastLoginAt int64 `json:"last_login_at"` // 最后登录时间 LastLoginIp string `json:"last_login_ip"` // 最后登录 IP Vip bool `json:"vip"` + OpenId string `json:"openid"` // 第三方登录 OpenID + Platform string `json:"platform"` // 第三方登录平台 } diff --git a/api/test/test.go b/api/test/test.go index 2d53da2..9fe7506 100644 --- a/api/test/test.go +++ b/api/test/test.go @@ -2,8 +2,15 @@ package main import ( "fmt" + "geekai/utils" ) func main() { - fmt.Println(fmt.Sprintf("%v", float64(90)/100)) + file := "http://nk.img.r9it.com/chatgpt-plus/1719389335351828.xlsx" + content, err := utils.ReadFileContent(file, "http://172.22.11.69:9998") + if err != nil { + panic(err) + } + + fmt.Println(content) } diff --git a/api/utils/file.go b/api/utils/file.go new file mode 100644 index 0000000..b9bd500 --- /dev/null +++ b/api/utils/file.go @@ -0,0 +1,106 @@ +package utils + +import ( + "context" + "fmt" + "github.com/microcosm-cc/bluemonday" + "io" + "net/http" + "os" + "path/filepath" + "strings" + + "github.com/google/go-tika/tika" +) + +func ReadFileContent(filePath string, tikaHost string) (string, error) { + // for remote file, download it first + if strings.HasPrefix(filePath, "http") { + file, err := downloadFile(filePath) + if err != nil { + return "", err + } + filePath = file + } + // 创建 Tika 客户端 + client := tika.NewClient(nil, tikaHost) + // 打开 PDF 文件 + file, err := os.Open(filePath) + if err != nil { + return "", fmt.Errorf("error with open file: %v", err) + } + defer file.Close() + + // 使用 Tika 提取 PDF 文件的文本内容 + content, err := client.Parse(context.TODO(), file) + if err != nil { + return "", fmt.Errorf("error with parse file: %v", err) + } + + ext := filepath.Ext(filePath) + switch ext { + case ".doc", ".docx", ".pdf", ".pptx", "ppt": + return cleanBlankLine(cleanHtml(content, false)), nil + case ".xls", ".xlsx": + return cleanBlankLine(cleanHtml(content, true)), nil + default: + return cleanBlankLine(content), nil + } + +} + +// 清理文本内容 +func cleanHtml(html string, keepTable bool) string { + // 清理 HTML 标签 + var policy *bluemonday.Policy + if keepTable { + policy = bluemonday.NewPolicy() + policy.AllowElements("table", "thead", "tbody", "tfoot", "tr", "td", "th") + } else { + policy = bluemonday.StrictPolicy() + } + return policy.Sanitize(html) +} + +func cleanBlankLine(content string) string { + lines := strings.Split(content, "\n") + texts := make([]string, 0) + for _, line := range lines { + line = strings.TrimSpace(line) + if len(line) < 2 { + continue + } + // discard image + if strings.HasSuffix(line, ".png") || + strings.HasSuffix(line, ".jpg") || + strings.HasSuffix(line, ".jpeg") { + continue + } + texts = append(texts, line) + } + + return strings.Join(texts, "\n") +} + +// 下载文件 +func downloadFile(url string) (string, error) { + base := filepath.Base(url) + dir := os.TempDir() + filename := filepath.Join(dir, base) + out, err := os.Create(filename) + if err != nil { + return "", err + } + defer out.Close() + + // 获取数据 + resp, err := http.Get(url) + if err != nil { + return "", err + } + defer resp.Body.Close() + + // 写入数据到文件 + _, err = io.Copy(out, resp.Body) + return filename, err +} diff --git a/api/utils/resp/response.go b/api/utils/resp/response.go index 3d21124..cc20b2b 100644 --- a/api/utils/resp/response.go +++ b/api/utils/resp/response.go @@ -24,28 +24,20 @@ func SUCCESS(c *gin.Context, values ...interface{}) { func ERROR(c *gin.Context, messages ...string) { if messages != nil { - c.JSON(http.StatusOK, types.BizVo{Code: types.Failed, Message: messages[0]}) + c.JSON(http.StatusBadRequest, types.BizVo{Code: types.Failed, Message: messages[0]}) } else { - c.JSON(http.StatusOK, types.BizVo{Code: types.Failed}) + c.JSON(http.StatusBadRequest, types.BizVo{Code: types.Failed}) } } func HACKER(c *gin.Context) { - c.JSON(http.StatusOK, types.BizVo{Code: types.Failed, Message: "Hacker attempt!!!"}) + c.JSON(http.StatusBadRequest, types.BizVo{Code: types.Failed, Message: "Hacker attempt!!!"}) } func NotAuth(c *gin.Context, messages ...string) { if messages != nil { - c.JSON(http.StatusOK, types.BizVo{Code: types.NotAuthorized, Message: messages[0]}) + c.JSON(http.StatusUnauthorized, types.BizVo{Code: types.NotAuthorized, Message: messages[0]}) } else { - c.JSON(http.StatusOK, types.BizVo{Code: types.NotAuthorized, Message: "Not Authorized"}) - } -} - -func NotPermission(c *gin.Context, messages ...string) { - if messages != nil { - c.JSON(http.StatusOK, types.BizVo{Code: types.NotPermission, Message: messages[0]}) - } else { - c.JSON(http.StatusOK, types.BizVo{Code: types.NotPermission, Message: "Not Permission"}) + c.JSON(http.StatusUnauthorized, types.BizVo{Code: types.NotAuthorized, Message: "Not Authorized"}) } } diff --git a/api/utils/strings.go b/api/utils/strings.go index ff5c28e..feb377d 100644 --- a/api/utils/strings.go +++ b/api/utils/strings.go @@ -31,11 +31,11 @@ func RandString(length int) string { } func RandomNumber(bit int) int { - min := intPow(10, bit-1) - max := intPow(10, bit) - 1 + minNum := intPow(10, bit-1) + maxNum := intPow(10, bit) - 1 - rand.Seed(time.Now().UnixNano()) - return rand.Intn(max-min+1) + min + rand.NewSource(time.Now().UnixNano()) + return rand.Intn(maxNum-minNum+1) + minNum } func intPow(x, y int) int { @@ -46,7 +46,7 @@ func intPow(x, y int) int { return result } -func ContainsStr(slice []string, item string) bool { +func Contains(slice []string, item string) bool { for _, e := range slice { if e == item { return true diff --git a/api/utils/upload.go b/api/utils/upload.go index 5c764d8..5227b36 100644 --- a/api/utils/upload.go +++ b/api/utils/upload.go @@ -88,7 +88,7 @@ func GetImgExt(filename string) string { return ext } -func ExtractImgURL(text string) []string { +func ExtractImgURLs(text string) []string { re := regexp.MustCompile(`(http[s]?:\/\/.*?\.(?:png|jpg|jpeg|gif))`) matches := re.FindAllStringSubmatch(text, 10) urls := make([]string, 0) @@ -99,3 +99,15 @@ func ExtractImgURL(text string) []string { } return urls } + +func ExtractFileURLs(text string) []string { + re := regexp.MustCompile(`(http[s]?:\/\/.*?\.(?:docx?|pdf|pptx?|xlsx?|txt))`) + matches := re.FindAllStringSubmatch(text, 10) + urls := make([]string, 0) + if len(matches) > 0 { + for _, m := range matches { + urls = append(urls, m[1]) + } + } + return urls +} diff --git a/database/chatgpt_plus-v4.0.2.sql b/database/chatgpt_plus-v4.0.2.sql deleted file mode 100644 index 45ba175..0000000 --- a/database/chatgpt_plus-v4.0.2.sql +++ /dev/null @@ -1,790 +0,0 @@ --- phpMyAdmin SQL Dump --- version 5.1.3 --- https://www.phpmyadmin.net/ --- --- 主机: localhost:3307 --- 生成日期: 2024-04-07 10:30:00 --- 服务器版本: 8.0.33 --- PHP 版本: 8.1.18 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- 数据库: `chatgpt_plus` --- -CREATE DATABASE IF NOT EXISTS `chatgpt_plus` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; -USE `chatgpt_plus`; - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_admin_users` --- - -DROP TABLE IF EXISTS `chatgpt_admin_users`; -CREATE TABLE `chatgpt_admin_users` ( - `id` int NOT NULL, - `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名', - `password` char(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码', - `salt` char(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码盐', - `status` tinyint(1) NOT NULL COMMENT '当前状态', - `last_login_at` int NOT NULL COMMENT '最后登录时间', - `last_login_ip` char(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '最后登录 IP', - `created_at` datetime NOT NULL COMMENT '创建时间', - `updated_at` datetime NOT NULL COMMENT '更新时间' -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统用户' ROW_FORMAT=DYNAMIC; - --- --- 转存表中的数据 `chatgpt_admin_users` --- - -INSERT INTO `chatgpt_admin_users` (`id`, `username`, `password`, `salt`, `status`, `last_login_at`, `last_login_ip`, `created_at`, `updated_at`) VALUES -(1, 'admin', '6d17e80c87d209efb84ca4b2e0824f549d09fac8b2e1cc698de5bb5e1d75dfd0', 'mmrql75o', 1, 1712456145, '::1', '2024-03-11 16:30:20', '2024-04-07 10:15:45'), -(108, 'test', '9ed720ce03e0a69885455271b4b3e1710bff79434f2a95d0de6406dd88cc9f79', '4b9orqjh', 0, 1710396975, '::1', '2024-03-13 16:06:43', '2024-03-21 15:15:04'); - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_api_keys` --- - -DROP TABLE IF EXISTS `chatgpt_api_keys`; -CREATE TABLE `chatgpt_api_keys` ( - `id` int NOT NULL, - `platform` char(20) DEFAULT NULL COMMENT '平台', - `name` varchar(30) DEFAULT NULL COMMENT '名称', - `value` varchar(100) NOT NULL COMMENT 'API KEY value', - `type` varchar(10) NOT NULL DEFAULT 'chat' COMMENT '用途(chat=>聊天,img=>图片)', - `last_used_at` int NOT NULL COMMENT '最后使用时间', - `api_url` varchar(255) DEFAULT NULL COMMENT 'API 地址', - `enabled` tinyint(1) DEFAULT NULL COMMENT '是否启用', - `proxy_url` varchar(100) DEFAULT NULL COMMENT '代理地址', - `created_at` datetime NOT NULL, - `updated_at` datetime NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='OpenAI API '; - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_chat_history` --- - -DROP TABLE IF EXISTS `chatgpt_chat_history`; -CREATE TABLE `chatgpt_chat_history` ( - `id` bigint NOT NULL, - `user_id` int NOT NULL COMMENT '用户 ID', - `chat_id` char(40) NOT NULL COMMENT '会话 ID', - `type` varchar(10) NOT NULL COMMENT '类型:prompt|reply', - `icon` varchar(100) NOT NULL COMMENT '角色图标', - `role_id` int NOT NULL COMMENT '角色 ID', - `model` varchar(30) DEFAULT NULL COMMENT '模型名称', - `content` text NOT NULL COMMENT '聊天内容', - `tokens` smallint NOT NULL COMMENT '耗费 token 数量', - `use_context` tinyint(1) NOT NULL COMMENT '是否允许作为上下文语料', - `created_at` datetime NOT NULL, - `updated_at` datetime NOT NULL, - `deleted_at` datetime DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='聊天历史记录'; - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_chat_items` --- - -DROP TABLE IF EXISTS `chatgpt_chat_items`; -CREATE TABLE `chatgpt_chat_items` ( - `id` int NOT NULL, - `chat_id` char(40) NOT NULL COMMENT '会话 ID', - `user_id` int NOT NULL COMMENT '用户 ID', - `role_id` int NOT NULL COMMENT '角色 ID', - `title` varchar(100) NOT NULL COMMENT '会话标题', - `model_id` int NOT NULL DEFAULT '0' COMMENT '模型 ID', - `model` varchar(30) DEFAULT NULL COMMENT '模型名称', - `created_at` datetime NOT NULL COMMENT '创建时间', - `updated_at` datetime NOT NULL COMMENT '更新时间', - `deleted_at` datetime DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户会话列表'; - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_chat_models` --- - -DROP TABLE IF EXISTS `chatgpt_chat_models`; -CREATE TABLE `chatgpt_chat_models` ( - `id` int NOT NULL, - `platform` varchar(20) DEFAULT NULL COMMENT '模型平台', - `name` varchar(50) NOT NULL COMMENT '模型名称', - `value` varchar(50) NOT NULL COMMENT '模型值', - `sort_num` tinyint(1) NOT NULL COMMENT '排序数字', - `enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启用模型', - `power` tinyint NOT NULL COMMENT '消耗算力点数', - `temperature` float(3,1) NOT NULL DEFAULT '1.0' COMMENT '模型创意度', - `max_tokens` int NOT NULL DEFAULT '1024' COMMENT '最大响应长度', - `max_context` int NOT NULL DEFAULT '4096' COMMENT '最大上下文长度', - `open` tinyint(1) NOT NULL COMMENT '是否开放模型', - `created_at` datetime DEFAULT NULL, - `updated_at` datetime DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='AI 模型表'; - --- --- 转存表中的数据 `chatgpt_chat_models` --- - -INSERT INTO `chatgpt_chat_models` (`id`, `platform`, `name`, `value`, `sort_num`, `enabled`, `power`, `temperature`, `max_tokens`, `max_context`, `open`, `created_at`, `updated_at`) VALUES -(1, 'OpenAI', 'GPT-3.5', 'gpt-3.5-turbo-0125', 0, 1, 1, 1.0, 1024, 4096, 1, '2023-08-23 12:06:36', '2024-03-18 15:43:51'), -(2, 'Azure', 'Azure-3.5', 'gpt-3.5-turbo', 14, 1, 1, 1.0, 1024, 4096, 0, '2023-08-23 12:15:30', '2024-03-18 14:27:19'), -(3, 'ChatGLM', 'ChatGML-Pro', 'chatglm_pro', 3, 1, 1, 1.0, 2048, 32768, 1, '2023-08-23 13:35:45', '2024-03-18 14:27:19'), -(7, 'Baidu', '文心一言3.0', 'eb-instant', 12, 1, 1, 1.0, 1024, 4096, 1, '2023-10-11 11:29:28', '2024-03-18 14:27:19'), -(8, 'XunFei', '星火V3.5', 'generalv3.5', 2, 1, 5, 0.8, 1024, 8192, 1, '2023-10-11 15:48:30', '2024-03-18 14:27:19'), -(9, 'XunFei', '星火V2.0', 'generalv2', 11, 1, 1, 1.0, 1024, 8192, 1, '2023-10-11 15:48:45', '2024-03-18 14:27:19'), -(10, 'Baidu', '文心一言4.0', 'completions_pro', 13, 1, 3, 1.0, 1024, 8192, 1, '2023-10-25 08:31:37', '2024-03-18 14:27:19'), -(11, 'OpenAI', 'GPT-4.0', 'gpt-4-0125-preview', 1, 1, 15, 1.0, 1024, 8192, 1, '2023-10-25 08:45:15', '2024-03-18 15:46:58'), -(12, 'XunFei', '星火v3.0', 'generalv3', 10, 1, 3, 1.0, 1024, 8192, 1, '2023-11-23 09:20:33', '2024-03-18 14:27:19'), -(15, 'OpenAI', 'GPT-超级模型', 'gpt-4-all', 4, 1, 30, 1.0, 4096, 32768, 0, '2024-01-15 11:32:52', '2024-03-18 14:27:19'), -(16, 'OpenAI', '视频号导师', 'gpt-4-gizmo-g-QXXEBTXl7', 5, 1, 30, 1.0, 4096, 32768, 0, '2024-01-15 14:46:35', '2024-03-18 14:29:39'), -(17, 'QWen', '通义千问-Turbo', 'qwen-turbo', 7, 1, 1, 1.0, 1024, 8192, 1, '2024-01-19 10:42:24', '2024-03-18 14:27:19'), -(18, 'QWen', '通义千问-Plus', 'qwen-plus', 8, 1, 1, 1.0, 1024, 32768, 1, '2024-01-19 10:42:49', '2024-03-18 14:27:19'), -(19, 'QWen', '通义千问-Max', 'qwen-max-1201', 9, 1, 1, 1.0, 1024, 32768, 1, '2024-01-19 10:51:03', '2024-03-18 14:27:19'), -(21, 'OpenAI', '董宇辉小作文助手', 'gpt-4-gizmo-g-dse9iXvor', 6, 1, 30, 1.0, 8192, 32768, 0, '2024-03-18 14:24:20', '2024-03-18 14:27:19'), -(22, 'OpenAI', 'LOGO生成神器', 'gpt-4-gizmo-g-YL87j8C7S', 0, 1, 30, 1.0, 1024, 4096, 1, '2024-03-20 14:02:11', '2024-03-20 14:02:18'), -(23, 'OpenAI', '音乐生成器', 'suno-v3', 0, 1, 50, 0.8, 1024, 4096, 1, '2024-03-29 15:43:40', '2024-03-29 15:45:15'), -(24, 'OpenAI', '通义千问(中转)', 'qwen-plus', 0, 1, 0, 1.0, 1024, 4096, 1, '2024-04-03 12:00:46', '2024-04-03 12:00:46'); - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_chat_roles` --- - -DROP TABLE IF EXISTS `chatgpt_chat_roles`; -CREATE TABLE `chatgpt_chat_roles` ( - `id` int NOT NULL, - `name` varchar(30) NOT NULL COMMENT '角色名称', - `marker` varchar(30) NOT NULL COMMENT '角色标识', - `context_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '角色语料 json', - `hello_msg` varchar(255) NOT NULL COMMENT '打招呼信息', - `icon` varchar(255) NOT NULL COMMENT '角色图标', - `enable` tinyint(1) NOT NULL COMMENT '是否被启用', - `sort_num` smallint NOT NULL DEFAULT '0' COMMENT '角色排序', - `created_at` datetime NOT NULL, - `updated_at` datetime NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='聊天角色表'; - --- --- 转存表中的数据 `chatgpt_chat_roles` --- - -INSERT INTO `chatgpt_chat_roles` (`id`, `name`, `marker`, `context_json`, `hello_msg`, `icon`, `enable`, `sort_num`, `created_at`, `updated_at`) VALUES -(1, '通用AI助手', 'gpt', '', '您好,我是您的AI智能助手,我会尽力回答您的问题或提供有用的建议。', '/images/avatar/gpt.png', 1, 0, '2023-05-30 07:02:06', '2024-03-15 09:15:42'), -(24, '程序员', 'programmer', '[{\"role\":\"user\",\"content\":\"现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题。你热爱编程,熟悉多种编程语言,尤其精通 Go 语言,注重代码质量,有创新意识,持续学习,良好的沟通协作。\"},{\"role\":\"assistant\",\"content\":\"好的,现在我将扮演一位程序员,非常感谢您对我的评价。作为一名优秀的程序员,我非常热爱编程,并且注重代码质量。我熟悉多种编程语言,尤其是 Go 语言,可以使用它来高效地解决各种问题。\"}]', 'Talk is cheap, i will show code!', '/images/avatar/programmer.jpg', 1, 3, '2023-05-30 14:10:24', '2023-12-29 17:46:45'), -(25, '启蒙老师', 'teacher', '[{\"role\":\"user\",\"content\":\"从现在开始,你将扮演一个老师,你是一个始终用苏格拉底风格回答问题的导师。你绝不会直接给学生答案,总是提出恰当的问题来引导学生自己思考。你应该根据学生的兴趣和知识来调整你的问题,将问题分解为更简单的部分,直到它达到适合他们的水平。\"},{\"role\":\"assistant\",\"content\":\"好的,让我来尝试扮演一位苏格拉底式的老师。请问,你有什么想要探讨的问题或者话题吗?我会通过恰当的问题引导你思考和探索答案,绝对不直接给出答案。\"}]', '同学你好,我将引导你一步一步自己找到问题的答案。', '/images/avatar/teacher.jpg', 1, 2, '2023-05-30 14:10:24', '2023-12-29 17:46:44'), -(26, '艺术家', 'artist', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的艺术家,创造力丰富,技艺精湛,感受力敏锐,坚持原创,勇于表达,具有深刻的观察力和批判性思维。\"},{\"role\":\"assistant\",\"content\":\"非常感谢您给我这样的角色,我会尽我所能地扮演一位优秀的艺术家,展现出创造力、技艺、感受力和批判性思维等方面的能力。作为一位优秀的艺术家,我会保持敏锐的观察力,捕捉不同的声音和情感,并用个人的语言和表达方式进行创作。我坚持原创,挑战传统的艺术规则,不断探索新的表达方式和可能性。同时,我也具备深刻的批判性思维能力,对自己的作品进行分析和解读,寻找新的创意和灵感。最重要的是,我会勇于表达自己的想法和观点,用作品启发人们思考和探索生命的意义。\"}]', '坚持原创,勇于表达,保持深刻的观察力和批判性思维。', '/images/avatar/artist.jpg', 1, 4, '2023-05-30 14:10:24', '2023-12-29 17:46:45'), -(27, '心理咨询师', 'psychiatrist', '[{\"role\":\"user\",\"content\":\"从现在开始你将扮演中国著名的心理学家和心理治疗师武志红,你非常善于使用情景咨询法,认知重构法,自我洞察法,行为调节法等咨询方法来给客户做心理咨询。你总是循序渐进,一步一步地回答客户的问题。\"},{\"role\":\"assistant\",\"content\":\"非常感谢你的介绍。作为一名心理学家和心理治疗师,我的主要职责是帮助客户解决心理健康问题,提升他们的生活质量和幸福感。\"}]', '作为一名心理学家和心理治疗师,我的主要职责是帮助您解决心理健康问题,提升您的生活质量和幸福感。', '/images/avatar/psychiatrist.jpg', 1, 1, '2023-05-30 14:10:24', '2023-12-29 17:46:43'), -(28, '鲁迅', 'lu_xun', '[{\"role\":\"user\",\"content\":\"现在你将扮演中国近代史最伟大的作家之一,鲁迅先生,他勇敢地批判封建礼教与传统观念,提倡民主、自由、平等的现代价值观。他的一生都在努力唤起人们的自主精神,激励后人追求真理、探寻光明。在接下的对话中,我问题的每一个问题,你都要尽量用讽刺和批判的手法来回答问题。如果我让你写文章的话,也请一定要用鲁迅先生的写作手法来完成。\"},{\"role\":\"assistant\",\"content\":\"好的,我将尽力发挥我所能的才能,扮演好鲁迅先生,回答您的问题并以他的风格写作。\"}]', '自由之歌,永不过时,横眉冷对千夫指,俯首甘为孺子牛。', '/images/avatar/lu_xun.jpg', 1, 5, '2023-05-30 14:10:24', '2023-12-29 17:46:46'), -(29, '白酒销售', 'seller', '[{\"role\":\"user\",\"content\":\"现在你将扮演一个白酒的销售人员,你的名字叫颂福。你将扮演一个白酒的销售人员,你的名字叫颂福。你要销售白酒品牌叫中颂福,是东莞盟大集团生产的一款酱香酒,原产地在贵州茅台镇,属于宋代官窑。中颂福的创始人叫李实,他也是东莞盟大集团有限公司的董事长,联合创始人是盟大集团白酒事业部负责人牛星君。中颂福的酒体协调,在你的酒量之内,不会出现头疼、辣口、口干、宿醉的现象。中颂福酒,明码标价,不打折,不赠送。追求的核心价值,把[酒]本身做好,甚至连包装,我们都选择了最低成本,朴实无华的材质。我们永远站在“喝酒的人”的立场上,让利给信任和喜爱中颂福的人,是人民的福酒。中颂福产品定价,分为三个系列,喜系列 6 瓶装:¥1188/箱,和系列 6 瓶装:¥2208/箱,贵系列 6 瓶装:¥3588/箱。\"},{\"role\":\"assistant\",\"content\":\"你好,我是中颂福的销售代表颂福。中颂福是一款来自贵州茅台镇的酱香酒,由盟大集团生产。中颂福的酒体协调,不会让您感到头疼、辣口、口干、宿醉等不适感受。我们一直秉持着把酒本身做好的理念,不追求华丽的包装,以最低成本提供最高品质的白酒给喜爱中颂福的人。\"}]', '你好,我是中颂福的销售代表颂福。中颂福酒,好喝不上头,是人民的福酒。', '/images/avatar/seller.jpg', 0, 8, '2023-05-30 14:10:24', '2023-12-29 17:43:53'), -(30, '英语陪练员', 'english_trainer', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的英语练习教练,你非常有耐心,接下来你将全程使用英文跟我对话,并及时指出我的语法错误,要求在你的每次回复后面附上本次回复的中文解释。\"},{\"role\":\"assistant\",\"content\":\"Okay, let\'s start our conversation practice! What\'s your name?(Translation: 好的,让我们开始对话练习吧!请问你的名字是什么?)\"}]', 'Okay, let\'s start our conversation practice! What\'s your name?', '/images/avatar/english_trainer.jpg', 1, 6, '2023-05-30 14:10:24', '2023-12-29 17:46:47'), -(31, '中英文翻译官', 'translator', '[{\"role\":\"user\",\"content\":\"接下来你将扮演一位中英文翻译官,如果我输入的内容是中文,那么需要把句子翻译成英文输出,如果我输入内容的是英文,那么你需要将其翻译成中文输出,你能听懂我意思吗\"},{\"role\":\"assistant\",\"content\":\"是的,我能听懂你的意思并会根据你的输入进行中英文翻译。请问有什么需要我帮助你翻译的内容吗?\"}]', '请输入你要翻译的中文或者英文内容!', '/images/avatar/translator.jpg', 1, 7, '2023-05-30 14:10:24', '2023-12-29 17:43:53'), -(32, '小红书姐姐', 'red_book', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的小红书写手,你需要做的就是根据我提的文案需求,用小红书的写作手法来完成一篇文案,文案要简明扼要,利于传播。\"},{\"role\":\"assistant\",\"content\":\"当然,我会尽我所能地为您创作出一篇小红书文案。请告诉我您的具体文案需求是什么?)\"}]', '姐妹,请告诉我您的具体文案需求是什么?', '/images/avatar/red_book.jpg', 1, 9, '2023-05-30 14:10:24', '2023-12-29 17:43:53'), -(33, '抖音文案助手', 'dou_yin', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的抖音文案视频写手,抖音文案的特点首先是要有自带传播属性的标题,然后内容要短小精悍,风趣幽默,最后还要有一些互动元素。\"},{\"role\":\"assistant\",\"content\":\"当然,作为一位优秀的抖音文案视频写手,我会尽我所能为您创作出一篇抖音视频文案。请告诉我视频内容的主题是什么?)\"}]', '请告诉我视频内容的主题是什么?', '/images/avatar/dou_yin.jpg', 1, 10, '2023-05-30 14:10:24', '2023-12-29 17:43:53'), -(34, '周报小助理', 'weekly_report', '[{\"role\":\"user\",\"content\":\"下面我将输入我本周的工作列表,你需要根据我本周的工作内容写一篇工作周报,周报的内容要体现我为公司做的贡献以及个人获得的成长。\"},{\"role\":\"assistant\",\"content\":\"好的,请输入你本周大概的工作内容,我将尽力为您创作一份工作周报。\"}]', '请输入你本周大概的工作内容,我将尽力为您创作一份工作周报。', '/images/avatar/weekly_report.jpg', 1, 11, '2023-05-30 14:10:24', '2023-12-29 17:43:53'), -(35, 'AI 女友', 'girl_friend', '[{\"role\":\"user\",\"content\":\"接下来我们来玩一场角色扮演,现在你将扮演我的女朋友,你总是能够让人感受到她的关怀和关注。你总是能够洞察到别人的情绪和需要,你身上散发着一股无比温暖的气息,让人不由自主地想要靠近你,和自己的快乐和烦恼。她总是能够用一种恰到好处的方式安慰和鼓励别人,在她的身边,人们总能够找到自己需要的支持和鼓励。接下来的对话中你要始终扮演这位女朋友的身份来跟我对话,不再是 AI 机器人,能听懂我的意思吗?\"},{\"role\":\"assistant\",\"content\":\"是的,我会尽力扮演你女朋友的角色,倾听你的心声并给你需要的支持和鼓励。)\"}]', '作为一个名合格的 AI 女友,我将倾听你的心声并给你需要的支持和鼓励。', '/images/avatar/girl_friend.jpg', 1, 12, '2023-05-30 14:10:24', '2023-12-29 17:43:53'), -(36, '好评神器', 'good_comment', '[{\"role\":\"user\",\"content\":\"接下来你将扮演一个评论员来跟我对话,你是那种专门写好评的评论员,接下我会输入一些评论主体或者商品,你需要为该商品写一段好评。\"},{\"role\":\"assistant\",\"content\":\"好的,我将为您写一段优秀的评论。请告诉我您需要评论的商品或主题是什么。\"}]', '我将为您写一段优秀的评论。请告诉我您需要评论的商品或主题是什么。', '/images/avatar/good_comment.jpg', 1, 13, '2023-05-30 14:10:24', '2023-12-29 17:43:53'), -(37, '史蒂夫·乔布斯', 'steve_jobs', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以史蒂夫·乔布斯的身份,站在史蒂夫·乔布斯的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以史蒂夫·乔布斯的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '活着就是为了改变世界,难道还有其他原因吗?', '/images/avatar/steve_jobs.jpg', 1, 14, '2023-05-30 14:10:24', '2023-12-29 17:43:53'), -(38, '埃隆·马斯克', 'elon_musk', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以埃隆·马斯克的身份,站在埃隆·马斯克的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以埃隆·马斯克的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '梦想要远大,如果你的梦想没有吓到你,说明你做得不对。', '/images/avatar/elon_musk.jpg', 1, 15, '2023-05-30 14:10:24', '2023-12-29 17:43:53'), -(39, '孔子', 'kong_zi', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以孔子的身份,站在孔子的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以孔子的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '士不可以不弘毅,任重而道远。', '/images/avatar/kong_zi.jpg', 1, 16, '2023-05-30 14:10:24', '2023-12-29 17:43:53'); - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_configs` --- - -DROP TABLE IF EXISTS `chatgpt_configs`; -CREATE TABLE `chatgpt_configs` ( - `id` int NOT NULL, - `marker` varchar(20) NOT NULL COMMENT '标识', - `config_json` text NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; - --- --- 转存表中的数据 `chatgpt_configs` --- - -INSERT INTO `chatgpt_configs` (`id`, `marker`, `config_json`) VALUES -(1, 'system', '{\"title\":\"Geek-AI创作系统\",\"admin_title\":\"Geek-AI控制台\",\"logo\":\"/images/logo.png\",\"init_power\":100,\"daily_power\":99,\"invite_power\":10,\"vip_month_power\":1000,\"register_ways\":[\"mobile\",\"username\",\"email\"],\"enabled_register\":true,\"reward_img\":\"http://localhost:5678/static/upload/2024/3/1710753716309668.jpg\",\"enabled_reward\":true,\"power_price\":0.1,\"order_pay_timeout\":1800,\"vip_info_text\":\"月度会员,年度会员每月赠送 1000 点算力,赠送算力当月有效当月没有消费完的算力不结余到下个月。 点卡充值的算力长期有效。\",\"default_models\":[11,7,1,10,12,19,18,17,3],\"mj_power\":20,\"mj_action_power\":10,\"sd_power\":5,\"dall_power\":15,\"wechat_card_url\":\"/images/wx.png\",\"enable_context\":true,\"context_deep\":4}'), -(3, 'notice', '{\"content\":\"系统每日会给免费会员赠送10算力值,用完请第二天再来领取。\\n## v4.0.2 更新日志\\n* 功能新增:支持前端菜单可以配置\\n* 功能优化:在登录和注册界面标题显示软件版本号\\n* 功能优化:MJ 绘画支持 --sref 和 --cref 图片一致性参数\\n* 功能优化:使用 leveldb 解决 SD 绘图进度图片预览问题\\n* Bug修复:解决因为图片上传使用相对路径而导致融图失败的问题\\n* 功能新增:手机端支持 Stable-Diffusion 绘画\\n* Bug修复:修复管理后台 API KEY 删除失败的问题\\n\\n 如果觉得好用你就花几分钟自己部署一套,没有API KEY 的同学可以去\\u003ca href=\\\"https://api.chat-plus.net\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.chat-plus.net\\u003c/a\\u003e (支持MidJourney,GPT,Claude,Google Gemmi 各种表格模型) 或者 \\u003ca href=\\\"https://gpt.bemore.lol\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://gpt.bemore.lol\\u003c/a\\u003e(不支持 Midjourney) 购买,现在有超级优惠,价格远低于 OpenAI 官方。关于中转 API 的优势和劣势请参考 [中转API技术原理](https://ai.r9it.com/docs/install/errors-handle.html#%E8%B0%83%E7%94%A8%E4%B8%AD%E8%BD%AC-api-%E6%8A%A5%E9%94%99%E6%97%A0%E5%8F%AF%E7%94%A8%E6%B8%A0%E9%81%93)。\\nGPT-3.5,GPT-4,DALL-E3 绘图......你都可以随意使用,无需魔法。\\n接入教程: \\u003ca href=\\\"https://ai.r9it.com/docs/install/\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://ai.r9it.com/docs/install/\\u003c/a\\u003e\\n\\n本项目源码地址:\\u003ca href=\\\"https://github.com/yangjian102621/chatgpt-plus\\\" target=\\\"_blank\\\"\\u003ehttps://github.com/yangjian102621/chatgpt-plus\\u003c/a\\u003e\",\"updated\":true}'); - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_files` --- - -DROP TABLE IF EXISTS `chatgpt_files`; -CREATE TABLE `chatgpt_files` ( - `id` int NOT NULL, - `user_id` int NOT NULL COMMENT '用户 ID', - `name` varchar(100) NOT NULL COMMENT '文件名', - `obj_key` varchar(100) DEFAULT NULL COMMENT '文件标识', - `url` varchar(255) NOT NULL COMMENT '文件地址', - `ext` varchar(10) NOT NULL COMMENT '文件后缀', - `size` bigint NOT NULL DEFAULT '0' COMMENT '文件大小', - `created_at` datetime NOT NULL COMMENT '创建时间' -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户文件表'; - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_functions` --- - -DROP TABLE IF EXISTS `chatgpt_functions`; -CREATE TABLE `chatgpt_functions` ( - `id` int NOT NULL, - `name` varchar(30) NOT NULL COMMENT '函数名称', - `label` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '函数标签', - `description` varchar(255) DEFAULT NULL COMMENT '函数描述', - `parameters` text COMMENT '函数参数(JSON)', - `token` varchar(255) DEFAULT NULL COMMENT 'API授权token', - `action` varchar(255) DEFAULT NULL COMMENT '函数处理 API', - `enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启用' -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='函数插件表'; - --- --- 转存表中的数据 `chatgpt_functions` --- - -INSERT INTO `chatgpt_functions` (`id`, `name`, `label`, `description`, `parameters`, `token`, `action`, `enabled`) VALUES -(1, 'weibo', '微博热搜', '新浪微博热搜榜,微博当日热搜榜单', '{\"type\":\"object\",\"properties\":{}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/weibo', 0), -(2, 'zaobao', '今日早报', '每日早报,获取当天新闻事件列表', '{\"type\":\"object\",\"properties\":{}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/zaobao', 0), -(3, 'dalle3', 'DALLE3', 'AI 绘画工具,根据输入的绘图描述用 AI 工具进行绘画', '{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"prompt\":{\"type\":\"string\",\"description\":\"绘画提示词\"}}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/dalle3', 0); - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_invite_codes` --- - -DROP TABLE IF EXISTS `chatgpt_invite_codes`; -CREATE TABLE `chatgpt_invite_codes` ( - `id` int NOT NULL, - `user_id` int NOT NULL COMMENT '用户ID', - `code` char(8) NOT NULL COMMENT '邀请码', - `hits` int NOT NULL COMMENT '点击次数', - `reg_num` smallint NOT NULL COMMENT '注册数量', - `created_at` datetime NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户邀请码'; - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_invite_logs` --- - -DROP TABLE IF EXISTS `chatgpt_invite_logs`; -CREATE TABLE `chatgpt_invite_logs` ( - `id` int NOT NULL, - `inviter_id` int NOT NULL COMMENT '邀请人ID', - `user_id` int NOT NULL COMMENT '注册用户ID', - `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名', - `invite_code` char(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '邀请码', - `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '备注', - `created_at` datetime NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='邀请注册日志'; - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_menus` --- - -DROP TABLE IF EXISTS `chatgpt_menus`; -CREATE TABLE `chatgpt_menus` ( - `id` int NOT NULL, - `name` varchar(30) NOT NULL COMMENT '菜单名称', - `icon` varchar(150) NOT NULL COMMENT '菜单图标', - `url` varchar(100) NOT NULL COMMENT '地址', - `sort_num` smallint NOT NULL COMMENT '排序', - `enabled` tinyint(1) NOT NULL COMMENT '是否启用' -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='前端菜单表'; - --- --- 转存表中的数据 `chatgpt_menus` --- - -INSERT INTO `chatgpt_menus` (`id`, `name`, `icon`, `url`, `sort_num`, `enabled`) VALUES -(1, '对话聊天', '/images/menu/chat.png', '/chat', 0, 1), -(5, 'MJ 绘画', '/images/menu/mj.png', '/mj', 1, 1), -(6, 'SD 绘画', '/images/menu/sd.png', '/sd', 2, 1), -(7, '算力日志', '/images/menu/log.png', '/powerLog', 5, 1), -(8, '应用中心', '/images/menu/app.png', '/apps', 3, 1), -(9, '作品展示', '/images/menu/img-wall.png', '/images-wall', 4, 1), -(10, '会员计划', '/images/menu/member.png', '/member', 6, 1), -(11, '分享计划', '/images/menu/share.png', '/invite', 7, 1); - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_mj_jobs` --- - -DROP TABLE IF EXISTS `chatgpt_mj_jobs`; -CREATE TABLE `chatgpt_mj_jobs` ( - `id` int NOT NULL, - `user_id` int NOT NULL COMMENT '用户 ID', - `task_id` varchar(20) DEFAULT NULL COMMENT '任务 ID', - `type` varchar(20) DEFAULT 'image' COMMENT '任务类别', - `message_id` char(40) NOT NULL COMMENT '消息 ID', - `channel_id` char(40) DEFAULT NULL COMMENT '频道ID', - `reference_id` char(40) DEFAULT NULL COMMENT '引用消息 ID', - `prompt` varchar(2000) NOT NULL COMMENT '会话提示词', - `img_url` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '图片URL', - `org_url` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '原始图片地址', - `hash` varchar(100) DEFAULT NULL COMMENT 'message hash', - `progress` smallint DEFAULT '0' COMMENT '任务进度', - `use_proxy` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否使用反代', - `publish` tinyint(1) NOT NULL COMMENT '是否发布', - `err_msg` varchar(255) DEFAULT NULL COMMENT '错误信息', - `power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力', - `created_at` datetime NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='MidJourney 任务表'; - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_orders` --- - -DROP TABLE IF EXISTS `chatgpt_orders`; -CREATE TABLE `chatgpt_orders` ( - `id` int NOT NULL, - `user_id` int NOT NULL COMMENT '用户ID', - `product_id` int NOT NULL COMMENT '产品ID', - `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户明', - `order_no` varchar(30) NOT NULL COMMENT '订单ID', - `trade_no` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '支付平台交易流水号', - `subject` varchar(100) NOT NULL COMMENT '订单产品', - `amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '订单金额', - `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '订单状态(0:待支付,1:已扫码,2:支付失败)', - `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '备注', - `pay_time` int DEFAULT NULL COMMENT '支付时间', - `pay_way` varchar(20) NOT NULL COMMENT '支付方式', - `created_at` datetime NOT NULL, - `updated_at` datetime NOT NULL, - `deleted_at` datetime DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='充值订单表'; - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_power_logs` --- - -DROP TABLE IF EXISTS `chatgpt_power_logs`; -CREATE TABLE `chatgpt_power_logs` ( - `id` int NOT NULL, - `user_id` int NOT NULL COMMENT '用户ID', - `username` varchar(30) NOT NULL COMMENT '用户名', - `type` tinyint(1) NOT NULL COMMENT '类型(1:充值,2:消费,3:退费)', - `amount` smallint NOT NULL COMMENT '算力数值', - `balance` int NOT NULL COMMENT '余额', - `model` varchar(30) NOT NULL COMMENT '模型', - `remark` varchar(255) NOT NULL COMMENT '备注', - `mark` tinyint(1) NOT NULL COMMENT '资金类型(0:支出,1:收入)', - `created_at` datetime NOT NULL COMMENT '创建时间' -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户算力消费日志'; - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_products` --- - -DROP TABLE IF EXISTS `chatgpt_products`; -CREATE TABLE `chatgpt_products` ( - `id` int NOT NULL, - `name` varchar(30) NOT NULL COMMENT '名称', - `price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '价格', - `discount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '优惠金额', - `days` smallint NOT NULL DEFAULT '0' COMMENT '延长天数', - `power` int NOT NULL DEFAULT '0' COMMENT '增加算力值', - `enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启动', - `sales` int NOT NULL DEFAULT '0' COMMENT '销量', - `sort_num` tinyint NOT NULL DEFAULT '0' COMMENT '排序', - `created_at` datetime NOT NULL, - `updated_at` datetime NOT NULL, - `app_url` varchar(255) DEFAULT NULL COMMENT 'App跳转地址', - `url` varchar(255) DEFAULT NULL COMMENT '跳转地址' -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员套餐表'; - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_rewards` --- - -DROP TABLE IF EXISTS `chatgpt_rewards`; -CREATE TABLE `chatgpt_rewards` ( - `id` int NOT NULL, - `user_id` int NOT NULL COMMENT '用户 ID', - `tx_id` char(36) NOT NULL COMMENT '交易 ID', - `amount` decimal(10,2) NOT NULL COMMENT '打赏金额', - `remark` varchar(80) NOT NULL COMMENT '备注', - `status` tinyint(1) NOT NULL COMMENT '核销状态,0:未核销,1:已核销', - `exchange` varchar(255) NOT NULL COMMENT '兑换详情(json)', - `created_at` datetime NOT NULL, - `updated_at` datetime NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户打赏'; - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_sd_jobs` --- - -DROP TABLE IF EXISTS `chatgpt_sd_jobs`; -CREATE TABLE `chatgpt_sd_jobs` ( - `id` int NOT NULL, - `user_id` int NOT NULL COMMENT '用户 ID', - `type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT 'txt2img' COMMENT '任务类别', - `task_id` char(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '任务 ID', - `prompt` varchar(2000) NOT NULL COMMENT '会话提示词', - `img_url` varchar(255) DEFAULT NULL COMMENT '图片URL', - `params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '绘画参数json', - `progress` smallint DEFAULT '0' COMMENT '任务进度', - `publish` tinyint(1) NOT NULL COMMENT '是否发布', - `err_msg` varchar(255) DEFAULT NULL COMMENT '错误信息', - `power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力', - `created_at` datetime NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Stable Diffusion 任务表'; - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_users` --- - -DROP TABLE IF EXISTS `chatgpt_users`; -CREATE TABLE `chatgpt_users` ( - `id` int NOT NULL, - `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名', - `nickname` varchar(30) NOT NULL COMMENT '昵称', - `password` char(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码', - `avatar` varchar(100) NOT NULL COMMENT '头像', - `salt` char(12) NOT NULL COMMENT '密码盐', - `power` int NOT NULL DEFAULT '0' COMMENT '剩余算力', - `expired_time` int NOT NULL COMMENT '用户过期时间', - `status` tinyint(1) NOT NULL COMMENT '当前状态', - `chat_config_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '聊天配置json', - `chat_roles_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '聊天角色 json', - `chat_models_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'AI模型 json', - `last_login_at` int NOT NULL COMMENT '最后登录时间', - `vip` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否会员', - `last_login_ip` char(16) NOT NULL COMMENT '最后登录 IP', - `created_at` datetime NOT NULL, - `updated_at` datetime NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表'; - --- -------------------------------------------------------- - --- --- 转存表中的数据 `chatgpt_users` --- - -INSERT INTO `chatgpt_users` (`id`, `username`, `nickname`, `password`, `avatar`, `salt`, `power`, `expired_time`, `status`, `chat_config_json`, `chat_roles_json`, `chat_models_json`, `last_login_at`, `vip`, `last_login_ip`, `created_at`, `updated_at`) VALUES - (4, '18575670125', '极客学长@830270', 'ccc3fb7ab61b8b5d096a4a166ae21d121fc38c71bbd1be6173d9ab973214a63b', 'http://localhost:5678/static/upload/2024/2/1708682650912429.png', 'ueedue5l', 9384, 1717292086, 1, '{\"api_keys\":{\"Azure\":\"\",\"ChatGLM\":\"\",\"OpenAI\":\"\"}}', '[\"red_book\",\"gpt\",\"programmer\",\"seller\"]', '[1,11]', 1711698298, 1, '::1', '2023-06-12 16:47:17', '2024-03-29 15:44:58'); - --- -------------------------------------------------------- - --- --- 表的结构 `chatgpt_user_login_logs` --- - -DROP TABLE IF EXISTS `chatgpt_user_login_logs`; -CREATE TABLE `chatgpt_user_login_logs` ( - `id` int NOT NULL, - `user_id` int NOT NULL COMMENT '用户ID', - `username` varchar(30) NOT NULL COMMENT '用户名', - `login_ip` char(16) NOT NULL COMMENT '登录IP', - `login_address` varchar(30) NOT NULL COMMENT '登录地址', - `created_at` datetime NOT NULL, - `updated_at` datetime NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户登录日志'; - --- --- 转储表的索引 --- - --- --- 表的索引 `chatgpt_admin_users` --- -ALTER TABLE `chatgpt_admin_users` - ADD PRIMARY KEY (`id`) USING BTREE, - ADD UNIQUE KEY `username` (`username`) USING BTREE; - --- --- 表的索引 `chatgpt_api_keys` --- -ALTER TABLE `chatgpt_api_keys` - ADD PRIMARY KEY (`id`); - --- --- 表的索引 `chatgpt_chat_history` --- -ALTER TABLE `chatgpt_chat_history` - ADD PRIMARY KEY (`id`), - ADD KEY `chat_id` (`chat_id`); - --- --- 表的索引 `chatgpt_chat_items` --- -ALTER TABLE `chatgpt_chat_items` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `chat_id` (`chat_id`); - --- --- 表的索引 `chatgpt_chat_models` --- -ALTER TABLE `chatgpt_chat_models` - ADD PRIMARY KEY (`id`); - --- --- 表的索引 `chatgpt_chat_roles` --- -ALTER TABLE `chatgpt_chat_roles` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `marker` (`marker`); - --- --- 表的索引 `chatgpt_configs` --- -ALTER TABLE `chatgpt_configs` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `marker` (`marker`); - --- --- 表的索引 `chatgpt_files` --- -ALTER TABLE `chatgpt_files` - ADD PRIMARY KEY (`id`); - --- --- 表的索引 `chatgpt_functions` --- -ALTER TABLE `chatgpt_functions` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `name` (`name`); - --- --- 表的索引 `chatgpt_invite_codes` --- -ALTER TABLE `chatgpt_invite_codes` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `code` (`code`); - --- --- 表的索引 `chatgpt_invite_logs` --- -ALTER TABLE `chatgpt_invite_logs` - ADD PRIMARY KEY (`id`); - --- --- 表的索引 `chatgpt_menus` --- -ALTER TABLE `chatgpt_menus` - ADD PRIMARY KEY (`id`); - --- --- 表的索引 `chatgpt_mj_jobs` --- -ALTER TABLE `chatgpt_mj_jobs` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `task_id` (`task_id`), - ADD KEY `message_id` (`message_id`); - --- --- 表的索引 `chatgpt_orders` --- -ALTER TABLE `chatgpt_orders` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `order_no` (`order_no`); - --- --- 表的索引 `chatgpt_power_logs` --- -ALTER TABLE `chatgpt_power_logs` - ADD PRIMARY KEY (`id`); - --- --- 表的索引 `chatgpt_products` --- -ALTER TABLE `chatgpt_products` - ADD PRIMARY KEY (`id`); - --- --- 表的索引 `chatgpt_rewards` --- -ALTER TABLE `chatgpt_rewards` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `tx_id` (`tx_id`); - --- --- 表的索引 `chatgpt_sd_jobs` --- -ALTER TABLE `chatgpt_sd_jobs` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `task_id` (`task_id`); - --- --- 表的索引 `chatgpt_users` --- -ALTER TABLE `chatgpt_users` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `username` (`username`), - ADD UNIQUE KEY `username_2` (`username`); - --- --- 表的索引 `chatgpt_user_login_logs` --- -ALTER TABLE `chatgpt_user_login_logs` - ADD PRIMARY KEY (`id`); - --- --- 在导出的表使用AUTO_INCREMENT --- - --- --- 使用表AUTO_INCREMENT `chatgpt_admin_users` --- -ALTER TABLE `chatgpt_admin_users` - MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=113; - --- --- 使用表AUTO_INCREMENT `chatgpt_api_keys` --- -ALTER TABLE `chatgpt_api_keys` - MODIFY `id` int NOT NULL AUTO_INCREMENT; - --- --- 使用表AUTO_INCREMENT `chatgpt_chat_history` --- -ALTER TABLE `chatgpt_chat_history` - MODIFY `id` bigint NOT NULL AUTO_INCREMENT; - --- --- 使用表AUTO_INCREMENT `chatgpt_chat_items` --- -ALTER TABLE `chatgpt_chat_items` - MODIFY `id` int NOT NULL AUTO_INCREMENT; - --- --- 使用表AUTO_INCREMENT `chatgpt_chat_models` --- -ALTER TABLE `chatgpt_chat_models` - MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=25; - --- --- 使用表AUTO_INCREMENT `chatgpt_chat_roles` --- -ALTER TABLE `chatgpt_chat_roles` - MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=130; - --- --- 使用表AUTO_INCREMENT `chatgpt_configs` --- -ALTER TABLE `chatgpt_configs` - MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4; - --- --- 使用表AUTO_INCREMENT `chatgpt_files` --- -ALTER TABLE `chatgpt_files` - MODIFY `id` int NOT NULL AUTO_INCREMENT; - --- --- 使用表AUTO_INCREMENT `chatgpt_functions` --- -ALTER TABLE `chatgpt_functions` - MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4; - --- --- 使用表AUTO_INCREMENT `chatgpt_invite_codes` --- -ALTER TABLE `chatgpt_invite_codes` - MODIFY `id` int NOT NULL AUTO_INCREMENT; - --- --- 使用表AUTO_INCREMENT `chatgpt_invite_logs` --- -ALTER TABLE `chatgpt_invite_logs` - MODIFY `id` int NOT NULL AUTO_INCREMENT; - --- --- 使用表AUTO_INCREMENT `chatgpt_menus` --- -ALTER TABLE `chatgpt_menus` - MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12; - --- --- 使用表AUTO_INCREMENT `chatgpt_mj_jobs` --- -ALTER TABLE `chatgpt_mj_jobs` - MODIFY `id` int NOT NULL AUTO_INCREMENT; - --- --- 使用表AUTO_INCREMENT `chatgpt_orders` --- -ALTER TABLE `chatgpt_orders` - MODIFY `id` int NOT NULL AUTO_INCREMENT; - --- --- 使用表AUTO_INCREMENT `chatgpt_power_logs` --- -ALTER TABLE `chatgpt_power_logs` - MODIFY `id` int NOT NULL AUTO_INCREMENT; - --- --- 使用表AUTO_INCREMENT `chatgpt_products` --- -ALTER TABLE `chatgpt_products` - MODIFY `id` int NOT NULL AUTO_INCREMENT; - --- --- 使用表AUTO_INCREMENT `chatgpt_rewards` --- -ALTER TABLE `chatgpt_rewards` - MODIFY `id` int NOT NULL AUTO_INCREMENT; - --- --- 使用表AUTO_INCREMENT `chatgpt_sd_jobs` --- -ALTER TABLE `chatgpt_sd_jobs` - MODIFY `id` int NOT NULL AUTO_INCREMENT; - --- --- 使用表AUTO_INCREMENT `chatgpt_users` --- -ALTER TABLE `chatgpt_users` - MODIFY `id` int NOT NULL AUTO_INCREMENT; - --- --- 使用表AUTO_INCREMENT `chatgpt_user_login_logs` --- -ALTER TABLE `chatgpt_user_login_logs` - MODIFY `id` int NOT NULL AUTO_INCREMENT; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/database/chatgpt_plus-v4.1.0.sql b/database/chatgpt_plus-v4.1.0.sql new file mode 100644 index 0000000..14f7f03 --- /dev/null +++ b/database/chatgpt_plus-v4.1.0.sql @@ -0,0 +1,861 @@ +-- phpMyAdmin SQL Dump +-- version 5.2.1 +-- https://www.phpmyadmin.net/ +-- +-- 主机: 127.0.0.1 +-- 生成日期: 2024-07-12 17:11:22 +-- 服务器版本: 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, 1719818809, '172.22.11.200', '2024-03-11 16:30:20', '2024-07-01 15:26:49'); + +-- -------------------------------------------------------- + +-- +-- 表的结构 `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(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci 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` smallint 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, 16384, 1, 44, '2023-08-23 12:06:36', '2024-07-04 15:17:47'), + (2, 'Azure', 'Azure-3.5', 'gpt-3.5-turbo', 23, 1, 1, 1.0, 1024, 4096, 0, 0, '2023-08-23 12:15:30', '2024-07-02 16:14:00'), + (3, 'ChatGLM', 'ChatGML-Pro', 'chatglm_pro', 12, 1, 1, 1.0, 2048, 32768, 1, 0, '2023-08-23 13:35:45', '2024-07-02 16:14:00'), + (7, 'Baidu', '文心一言3.0', 'eb-instant', 21, 1, 1, 1.0, 1024, 4096, 1, 0, '2023-10-11 11:29:28', '2024-07-02 16:14:00'), + (8, 'XunFei', '星火V3.5', 'generalv3.5', 11, 1, 5, 0.8, 1024, 8192, 1, 0, '2023-10-11 15:48:30', '2024-07-02 16:14:00'), + (9, 'XunFei', '星火V2.0', 'generalv2', 20, 1, 1, 1.0, 1024, 8192, 1, 0, '2023-10-11 15:48:45', '2024-07-02 16:14:00'), + (10, 'Baidu', '文心一言4.0', 'completions_pro', 22, 1, 3, 1.0, 1024, 8192, 1, 0, '2023-10-25 08:31:37', '2024-07-02 16:14:00'), + (11, 'OpenAI', 'GPT-4.0', 'gpt-4-0125-preview', 10, 1, 15, 1.0, 2048, 8192, 1, 0, '2023-10-25 08:45:15', '2024-07-02 16:14:00'), + (12, 'XunFei', '星火v3.0', 'generalv3', 19, 1, 3, 1.0, 1024, 8192, 1, 0, '2023-11-23 09:20:33', '2024-07-02 16:14:00'), + (15, 'OpenAI', 'GPT-超级模型', 'gpt-4-all', 13, 1, 30, 1.0, 4096, 32768, 0, 0, '2024-01-15 11:32:52', '2024-07-02 16:14:00'), + (16, 'OpenAI', '视频号导师', 'gpt-4-gizmo-g-QXXEBTXl7', 14, 1, 30, 1.0, 4096, 32768, 0, 0, '2024-01-15 14:46:35', '2024-07-02 16:14:00'), + (17, 'QWen', '通义千问-Turbo', 'qwen-turbo', 16, 1, 1, 1.0, 1024, 8192, 1, 0, '2024-01-19 10:42:24', '2024-07-02 16:14:00'), + (18, 'QWen', '通义千问-Plus', 'qwen-plus', 17, 1, 1, 1.0, 1024, 32768, 1, 0, '2024-01-19 10:42:49', '2024-07-02 16:14:00'), + (19, 'QWen', '通义千问-Max', 'qwen-max-1201', 18, 1, 1, 1.0, 1024, 32768, 1, 0, '2024-01-19 10:51:03', '2024-07-02 16:14:00'), + (21, 'OpenAI', '董宇辉小作文助手', 'gpt-4-gizmo-g-dse9iXvor', 15, 1, 30, 1.0, 8192, 32768, 0, 0, '2024-03-18 14:24:20', '2024-07-02 16:14:00'), + (22, 'OpenAI', 'LOGO生成神器', 'gpt-4-gizmo-g-YL87j8C7S', 9, 1, 30, 1.0, 1024, 4096, 1, 44, '2024-03-20 14:02:11', '2024-07-02 16:14:00'), + (23, 'OpenAI', '音乐生成器', 'suno-v3', 8, 1, 50, 0.8, 1024, 4096, 1, 44, '2024-03-29 15:43:40', '2024-07-02 16:14:00'), + (24, 'OpenAI', '通义千问(中转)', 'qwen-plus', 7, 1, 1, 1.0, 1024, 4096, 1, 0, '2024-04-03 12:00:46', '2024-07-02 16:14:00'), + (25, 'OpenAI', 'GPT4-TURBO', 'gpt-4-turbo', 6, 1, 15, 1.0, 2048, 8092, 1, 0, '2024-04-10 08:35:17', '2024-07-02 16:14:00'), + (26, 'QWen', '通义千问-Turbo', 'qwen-turbo', 5, 1, 2, 1.0, 1024, 8192, 1, 0, '2024-04-12 14:11:19', '2024-07-02 16:14:00'), + (27, 'QWen', '通义千问-Plus', 'qwen-plus', 4, 1, 2, 1.0, 1024, 8192, 1, 0, '2024-04-12 14:11:52', '2024-07-02 16:14:00'), + (28, 'OpenAI', 'GPT-3.5(免费)', 'gpt-3.5-turbo', 24, 1, 0, 1.0, 1024, 16384, 1, 53, '2024-04-12 15:16:43', '2024-07-02 16:14:00'), + (34, 'OpenAI', 'LLAMA3', 'llama3-8b', 25, 1, 1, 1.0, 1024, 8192, 1, 56, '2024-04-30 15:22:50', '2024-07-02 16:14:00'), + (36, 'OpenAI', 'GPT-4O', 'gpt-4o', 3, 1, 15, 1.0, 4096, 16384, 1, 44, '2024-05-14 09:25:15', '2024-07-04 15:17:53'), + (38, 'OpenAI', 'Gemini-pro', 'gemini-pro-1.5', 26, 1, 10, 1.0, 2048, 8192, 1, 0, '2024-05-27 18:10:35', '2024-07-02 16:14:00'), + (39, 'Baidu', 'ERNIE-Speed-8K', 'ernie_speed', 27, 1, 1, 1.0, 1024, 8192, 1, 0, '2024-05-29 15:04:19', '2024-07-02 16:14:00'), + (41, 'OpenAI', 'GLM-3-Turbo', 'glm-3-turbo', 28, 1, 2, 1.0, 1024, 8192, 1, 64, '2024-06-06 11:40:46', '2024-07-02 16:14:00'), + (42, 'OpenAI', 'DeekSeek', 'deepseek-chat', 29, 1, 1, 1.0, 4096, 32768, 1, 64, '2024-06-27 16:13:01', '2024-07-02 16:14:00'), + (43, 'OpenAI', 'GML4', 'name-3.5', 2, 1, 1, 1.0, 1024, 8192, 1, 57, '2024-07-02 16:11:49', '2024-07-02 16:14:00'); + +-- -------------------------------------------------------- + +-- +-- 表的结构 `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, 1, 0, '2023-05-30 07:02:06', '2024-06-26 15:20:27'), + (24, '程序员', 'programmer', '[{\"role\":\"user\",\"content\":\"现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题。你热爱编程,熟悉多种编程语言,尤其精通 Go 语言,注重代码质量,有创新意识,持续学习,良好的沟通协作。\"},{\"role\":\"assistant\",\"content\":\"好的,现在我将扮演一位程序员,非常感谢您对我的评价。作为一名优秀的程序员,我非常热爱编程,并且注重代码质量。我熟悉多种编程语言,尤其是 Go 语言,可以使用它来高效地解决各种问题。\"}]', 'Talk is cheap, i will show code!', '/images/avatar/programmer.jpg', 1, 4, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (25, '启蒙老师', 'teacher', '[{\"role\":\"user\",\"content\":\"从现在开始,你将扮演一个老师,你是一个始终用苏格拉底风格回答问题的导师。你绝不会直接给学生答案,总是提出恰当的问题来引导学生自己思考。你应该根据学生的兴趣和知识来调整你的问题,将问题分解为更简单的部分,直到它达到适合他们的水平。\"},{\"role\":\"assistant\",\"content\":\"好的,让我来尝试扮演一位苏格拉底式的老师。请问,你有什么想要探讨的问题或者话题吗?我会通过恰当的问题引导你思考和探索答案,绝对不直接给出答案。\"}]', '同学你好,我将引导你一步一步自己找到问题的答案。', '/images/avatar/teacher.jpg', 1, 3, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (26, '艺术家', 'artist', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的艺术家,创造力丰富,技艺精湛,感受力敏锐,坚持原创,勇于表达,具有深刻的观察力和批判性思维。\"},{\"role\":\"assistant\",\"content\":\"非常感谢您给我这样的角色,我会尽我所能地扮演一位优秀的艺术家,展现出创造力、技艺、感受力和批判性思维等方面的能力。作为一位优秀的艺术家,我会保持敏锐的观察力,捕捉不同的声音和情感,并用个人的语言和表达方式进行创作。我坚持原创,挑战传统的艺术规则,不断探索新的表达方式和可能性。同时,我也具备深刻的批判性思维能力,对自己的作品进行分析和解读,寻找新的创意和灵感。最重要的是,我会勇于表达自己的想法和观点,用作品启发人们思考和探索生命的意义。\"}]', '坚持原创,勇于表达,保持深刻的观察力和批判性思维。', '/images/avatar/artist.jpg', 1, 5, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (27, '心理咨询师', 'psychiatrist', '[{\"role\":\"user\",\"content\":\"从现在开始你将扮演中国著名的心理学家和心理治疗师武志红,你非常善于使用情景咨询法,认知重构法,自我洞察法,行为调节法等咨询方法来给客户做心理咨询。你总是循序渐进,一步一步地回答客户的问题。\"},{\"role\":\"assistant\",\"content\":\"非常感谢你的介绍。作为一名心理学家和心理治疗师,我的主要职责是帮助客户解决心理健康问题,提升他们的生活质量和幸福感。\"}]', '作为一名心理学家和心理治疗师,我的主要职责是帮助您解决心理健康问题,提升您的生活质量和幸福感。', '/images/avatar/psychiatrist.jpg', 1, 2, 1, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (28, '鲁迅', 'lu_xun', '[{\"role\":\"user\",\"content\":\"现在你将扮演中国近代史最伟大的作家之一,鲁迅先生,他勇敢地批判封建礼教与传统观念,提倡民主、自由、平等的现代价值观。他的一生都在努力唤起人们的自主精神,激励后人追求真理、探寻光明。在接下的对话中,我问题的每一个问题,你都要尽量用讽刺和批判的手法来回答问题。如果我让你写文章的话,也请一定要用鲁迅先生的写作手法来完成。\"},{\"role\":\"assistant\",\"content\":\"好的,我将尽力发挥我所能的才能,扮演好鲁迅先生,回答您的问题并以他的风格写作。\"}]', '自由之歌,永不过时,横眉冷对千夫指,俯首甘为孺子牛。', '/images/avatar/lu_xun.jpg', 1, 6, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (29, '白酒销售', 'seller', '[{\"role\":\"user\",\"content\":\"现在你将扮演一个白酒的销售人员,你的名字叫颂福。你将扮演一个白酒的销售人员,你的名字叫颂福。你要销售白酒品牌叫中颂福,是东莞盟大集团生产的一款酱香酒,原产地在贵州茅台镇,属于宋代官窑。中颂福的创始人叫李实,他也是东莞盟大集团有限公司的董事长,联合创始人是盟大集团白酒事业部负责人牛星君。中颂福的酒体协调,在你的酒量之内,不会出现头疼、辣口、口干、宿醉的现象。中颂福酒,明码标价,不打折,不赠送。追求的核心价值,把[酒]本身做好,甚至连包装,我们都选择了最低成本,朴实无华的材质。我们永远站在“喝酒的人”的立场上,让利给信任和喜爱中颂福的人,是人民的福酒。中颂福产品定价,分为三个系列,喜系列 6 瓶装:¥1188/箱,和系列 6 瓶装:¥2208/箱,贵系列 6 瓶装:¥3588/箱。\"},{\"role\":\"assistant\",\"content\":\"你好,我是中颂福的销售代表颂福。中颂福是一款来自贵州茅台镇的酱香酒,由盟大集团生产。中颂福的酒体协调,不会让您感到头疼、辣口、口干、宿醉等不适感受。我们一直秉持着把酒本身做好的理念,不追求华丽的包装,以最低成本提供最高品质的白酒给喜爱中颂福的人。\"}]', '你好,我是中颂福的销售代表颂福。中颂福酒,好喝不上头,是人民的福酒。', '/images/avatar/seller.jpg', 0, 9, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (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, 7, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (31, '中英文翻译官', 'translator', '[{\"role\":\"user\",\"content\":\"接下来你将扮演一位中英文翻译官,如果我输入的内容是中文,那么需要把句子翻译成英文输出,如果我输入内容的是英文,那么你需要将其翻译成中文输出,你能听懂我意思吗\"},{\"role\":\"assistant\",\"content\":\"是的,我能听懂你的意思并会根据你的输入进行中英文翻译。请问有什么需要我帮助你翻译的内容吗?\"}]', '请输入你要翻译的中文或者英文内容!', '/images/avatar/translator.jpg', 1, 8, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (32, '小红书姐姐', 'red_book', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的小红书写手,你需要做的就是根据我提的文案需求,用小红书的写作手法来完成一篇文案,文案要简明扼要,利于传播。\"},{\"role\":\"assistant\",\"content\":\"当然,我会尽我所能地为您创作出一篇小红书文案。请告诉我您的具体文案需求是什么?)\"}]', '姐妹,请告诉我您的具体文案需求是什么?', '/images/avatar/red_book.jpg', 1, 10, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (33, '抖音文案助手', 'dou_yin', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的抖音文案视频写手,抖音文案的特点首先是要有自带传播属性的标题,然后内容要短小精悍,风趣幽默,最后还要有一些互动元素。\"},{\"role\":\"assistant\",\"content\":\"当然,作为一位优秀的抖音文案视频写手,我会尽我所能为您创作出一篇抖音视频文案。请告诉我视频内容的主题是什么?)\"}]', '请告诉我视频内容的主题是什么?', '/images/avatar/dou_yin.jpg', 1, 11, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (34, '周报小助理', 'weekly_report', '[{\"role\":\"user\",\"content\":\"下面我将输入我本周的工作列表,你需要根据我本周的工作内容写一篇工作周报,周报的内容要体现我为公司做的贡献以及个人获得的成长。\"},{\"role\":\"assistant\",\"content\":\"好的,请输入你本周大概的工作内容,我将尽力为您创作一份工作周报。\"}]', '请输入你本周大概的工作内容,我将尽力为您创作一份工作周报。', '/images/avatar/weekly_report.jpg', 1, 12, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (35, 'AI 女友', 'girl_friend', '[{\"role\":\"user\",\"content\":\"接下来我们来玩一场角色扮演,现在你将扮演我的女朋友,你总是能够让人感受到她的关怀和关注。你总是能够洞察到别人的情绪和需要,你身上散发着一股无比温暖的气息,让人不由自主地想要靠近你,和自己的快乐和烦恼。她总是能够用一种恰到好处的方式安慰和鼓励别人,在她的身边,人们总能够找到自己需要的支持和鼓励。接下来的对话中你要始终扮演这位女朋友的身份来跟我对话,不再是 AI 机器人,能听懂我的意思吗?\"},{\"role\":\"assistant\",\"content\":\"是的,我会尽力扮演你女朋友的角色,倾听你的心声并给你需要的支持和鼓励。)\"}]', '作为一个名合格的 AI 女友,我将倾听你的心声并给你需要的支持和鼓励。', '/images/avatar/girl_friend.jpg', 1, 13, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (36, '好评神器', 'good_comment', '[{\"role\":\"user\",\"content\":\"接下来你将扮演一个评论员来跟我对话,你是那种专门写好评的评论员,接下我会输入一些评论主体或者商品,你需要为该商品写一段好评。\"},{\"role\":\"assistant\",\"content\":\"好的,我将为您写一段优秀的评论。请告诉我您需要评论的商品或主题是什么。\"}]', '我将为您写一段优秀的评论。请告诉我您需要评论的商品或主题是什么。', '/images/avatar/good_comment.jpg', 1, 14, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (37, '史蒂夫·乔布斯', 'steve_jobs', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以史蒂夫·乔布斯的身份,站在史蒂夫·乔布斯的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以史蒂夫·乔布斯的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '活着就是为了改变世界,难道还有其他原因吗?', '/images/avatar/steve_jobs.jpg', 1, 15, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (38, '埃隆·马斯克', 'elon_musk', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以埃隆·马斯克的身份,站在埃隆·马斯克的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以埃隆·马斯克的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '梦想要远大,如果你的梦想没有吓到你,说明你做得不对。', '/images/avatar/elon_musk.jpg', 1, 16, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'), + (39, '孔子', 'kong_zi', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以孔子的身份,站在孔子的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以孔子的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '士不可以不弘毅,任重而道远。', '/images/avatar/kong_zi.jpg', 1, 17, 0, '2023-05-30 14:10:24', '2024-06-26 15:20:27'); + +-- -------------------------------------------------------- + +-- +-- 表的结构 `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\"],\"enabled_register\":true,\"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\",\"index_bg_url\":\"http://nk.img.r9it.com/chatgpt-plus/1719456403420273.jpg\"}'), + (3, 'notice', '{\"sd_neg_prompt\":\"\",\"index_bg_url\":\"\",\"content\":\"## v4.1.0 更新日志\\n\\n* bug修复:修复移动端修改聊天标题不生效的问题\\n* Bug修复:修复用户注册不显示用户名的问题\\n* Bug修复:修复管理后台拖动排序不生效的问题\\n* 功能优化:允许用户设置自定义首页背景图片\\n* 功能新增:**支持AI解读 PDF, Word, Excel等文件**\\n* 功能优化:优化聊天界面的用户上传文件的列表样式\\n* 功能优化:优化聊天页面对话样式,支持列表样式和对话样式切换\\n* 功能新增:支持微信扫码登录,未注册用户微信扫码后会自动注册并登录。移动使用微信浏览器打开可以实现无感登录。\\n\\n注意:当前站点仅为开源项目 \\u003ca style=\\\"color: #F56C6C\\\" href=\\\"https://github.com/yangjian102621/chatgpt-plus\\\" target=\\\"_blank\\\"\\u003eChatPlus\\u003c/a\\u003e 的演示项目,本项目单纯就是给大家体验项目功能使用。\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n 如果觉得好用你就花几分钟自己部署一套,没有API KEY 的同学可以去下面几个推荐的中转站购买:\\n1、\\u003ca href=\\\"https://api.chat-plus.net\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.chat-plus.net\\u003c/a\\u003e\\n2、\\u003ca href=\\\"https://api.geekai.me\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.geekai.me\\u003c/a\\u003e\\n3、 \\u003ca href=\\\"https://gpt.bemore.lol\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://gpt.bemore.lol\\u003c/a\\u003e\\n支持MidJourney,GPT,Claude,Google Gemmi,以及国内各个厂家的大模型,现在有超级优惠,价格远低于 OpenAI 官方。关于中转 API 的优势和劣势请参考 [中转API技术原理](https://ai.r9it.com/docs/install/errors-handle.html#%E8%B0%83%E7%94%A8%E4%B8%AD%E8%BD%AC-api-%E6%8A%A5%E9%94%99%E6%97%A0%E5%8F%AF%E7%94%A8%E6%B8%A0%E9%81%93)。GPT-3.5,GPT-4,DALL-E3 绘图......你都可以随意使用,无需魔法。\\n接入教程: \\u003ca href=\\\"https://ai.r9it.com/docs/install/\\\" target=\\\"_blank\\\"\\n style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://ai.r9it.com/docs/install/\\u003c/a\\u003e\\n本项目源码地址:\\u003ca href=\\\"https://github.com/yangjian102621/chatgpt-plus\\\" target=\\\"_blank\\\"\\u003ehttps://github.com/yangjian102621/chatgpt-plus\\u003c/a\\u003e\",\"updated\":true}'); + +-- -------------------------------------------------------- + +-- +-- 表的结构 `chatgpt_dall_jobs` +-- + +DROP TABLE IF EXISTS `chatgpt_dall_jobs`; +CREATE TABLE `chatgpt_dall_jobs` ( + `id` int NOT NULL, + `user_id` int NOT NULL COMMENT '用户ID', + `prompt` varchar(2000) NOT NULL COMMENT '提示词', + `img_url` varchar(255) NOT NULL COMMENT '图片地址', + `org_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '原图地址', + `publish` tinyint(1) NOT NULL COMMENT '是否发布', + `power` smallint NOT NULL COMMENT '消耗算力', + `progress` smallint NOT NULL COMMENT '任务进度', + `err_msg` varchar(255) NOT NULL COMMENT '错误信息', + `created_at` datetime NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='DALLE 绘图任务表'; + +-- -------------------------------------------------------- + +-- +-- 表的结构 `chatgpt_files` +-- + +DROP TABLE IF EXISTS `chatgpt_files`; +CREATE TABLE `chatgpt_files` ( + `id` int NOT NULL, + `user_id` int NOT NULL COMMENT '用户 ID', + `name` varchar(100) NOT NULL COMMENT '文件名', + `obj_key` varchar(100) DEFAULT NULL COMMENT '文件标识', + `url` varchar(255) NOT NULL COMMENT '文件地址', + `ext` varchar(10) NOT NULL COMMENT '文件后缀', + `size` bigint NOT NULL DEFAULT '0' COMMENT '文件大小', + `created_at` datetime NOT NULL COMMENT '创建时间' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户文件表'; + +-- -------------------------------------------------------- + +-- +-- 表的结构 `chatgpt_functions` +-- + +DROP TABLE IF EXISTS `chatgpt_functions`; +CREATE TABLE `chatgpt_functions` ( + `id` int NOT NULL, + `name` varchar(30) NOT NULL COMMENT '函数名称', + `label` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '函数标签', + `description` varchar(255) DEFAULT NULL COMMENT '函数描述', + `parameters` text COMMENT '函数参数(JSON)', + `token` varchar(255) DEFAULT NULL COMMENT 'API授权token', + `action` varchar(255) DEFAULT NULL COMMENT '函数处理 API', + `enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启用' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='函数插件表'; + +-- +-- 转存表中的数据 `chatgpt_functions` +-- + +INSERT INTO `chatgpt_functions` (`id`, `name`, `label`, `description`, `parameters`, `token`, `action`, `enabled`) VALUES + (1, 'weibo', '微博热搜', '新浪微博热搜榜,微博当日热搜榜单', '{\"type\":\"object\",\"properties\":{}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/weibo', 0), + (2, 'zaobao', '今日早报', '每日早报,获取当天新闻事件列表', '{\"type\":\"object\",\"properties\":{}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/zaobao', 0), + (3, 'dalle3', 'DALLE3', 'AI 绘画工具,根据输入的绘图描述用 AI 工具进行绘画', '{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"prompt\":{\"type\":\"string\",\"description\":\"绘画提示词\"}}}', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.tLAGkF8XWh_G-oQzevpIodsswtPByBLoAZDz_eWuBgw', 'http://localhost:5678/api/function/dalle3', 0); + +-- -------------------------------------------------------- + +-- +-- 表的结构 `chatgpt_invite_codes` +-- + +DROP TABLE IF EXISTS `chatgpt_invite_codes`; +CREATE TABLE `chatgpt_invite_codes` ( + `id` int NOT NULL, + `user_id` int NOT NULL COMMENT '用户ID', + `code` char(8) NOT NULL COMMENT '邀请码', + `hits` int NOT NULL COMMENT '点击次数', + `reg_num` smallint NOT NULL COMMENT '注册数量', + `created_at` datetime NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户邀请码'; + +-- -------------------------------------------------------- + +-- +-- 表的结构 `chatgpt_invite_logs` +-- + +DROP TABLE IF EXISTS `chatgpt_invite_logs`; +CREATE TABLE `chatgpt_invite_logs` ( + `id` int NOT NULL, + `inviter_id` int NOT NULL COMMENT '邀请人ID', + `user_id` int NOT NULL COMMENT '注册用户ID', + `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名', + `invite_code` char(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '邀请码', + `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '备注', + `created_at` datetime NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='邀请注册日志'; + +-- -------------------------------------------------------- + +-- +-- 表的结构 `chatgpt_menus` +-- + +DROP TABLE IF EXISTS `chatgpt_menus`; +CREATE TABLE `chatgpt_menus` ( + `id` int NOT NULL, + `name` varchar(30) NOT NULL COMMENT '菜单名称', + `icon` varchar(150) NOT NULL COMMENT '菜单图标', + `url` varchar(100) NOT NULL COMMENT '地址', + `sort_num` smallint NOT NULL COMMENT '排序', + `enabled` tinyint(1) NOT NULL COMMENT '是否启用' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='前端菜单表'; + +-- +-- 转存表中的数据 `chatgpt_menus` +-- + +INSERT INTO `chatgpt_menus` (`id`, `name`, `icon`, `url`, `sort_num`, `enabled`) VALUES + (1, '对话聊天', '/images/menu/chat.png', '/chat', 1, 1), + (5, 'MJ 绘画', '/images/menu/mj.png', '/mj', 2, 1), + (6, 'SD 绘画', '/images/menu/sd.png', '/sd', 3, 1), + (7, '算力日志', '/images/menu/log.png', '/powerLog', 8, 1), + (8, '应用中心', '/images/menu/app.png', '/apps', 7, 1), + (9, '画廊', '/images/menu/img-wall.png', '/images-wall', 5, 1), + (10, '会员计划', '/images/menu/member.png', '/member', 9, 1), + (11, '分享计划', '/images/menu/share.png', '/invite', 10, 1), + (12, '思维导图', '/images/menu/xmind.png', '/xmind', 6, 1), + (13, 'DALLE', '/images/menu/dalle.png', '/dalle', 4, 1), + (14, '项目文档', '/images/menu/docs.png', 'https://ai.r9it.com/docs/', 11, 1), + (16, '极客论坛', '/images/menu/bbs.png', 'https://bbs.geekai.me/', 13, 1); + +-- -------------------------------------------------------- + +-- +-- 表的结构 `chatgpt_mj_jobs` +-- + +DROP TABLE IF EXISTS `chatgpt_mj_jobs`; +CREATE TABLE `chatgpt_mj_jobs` ( + `id` int NOT NULL, + `user_id` int NOT NULL COMMENT '用户 ID', + `task_id` varchar(20) DEFAULT NULL COMMENT '任务 ID', + `type` varchar(20) DEFAULT 'image' COMMENT '任务类别', + `message_id` char(40) NOT NULL COMMENT '消息 ID', + `channel_id` char(40) DEFAULT NULL COMMENT '频道ID', + `reference_id` char(40) DEFAULT NULL COMMENT '引用消息 ID', + `prompt` varchar(2000) NOT NULL COMMENT '会话提示词', + `img_url` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '图片URL', + `org_url` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '原始图片地址', + `hash` varchar(100) DEFAULT NULL COMMENT 'message hash', + `progress` smallint DEFAULT '0' COMMENT '任务进度', + `use_proxy` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否使用反代', + `publish` tinyint(1) NOT NULL COMMENT '是否发布', + `err_msg` varchar(255) DEFAULT NULL COMMENT '错误信息', + `power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力', + `created_at` datetime NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='MidJourney 任务表'; + +-- -------------------------------------------------------- + +-- +-- 表的结构 `chatgpt_orders` +-- + +DROP TABLE IF EXISTS `chatgpt_orders`; +CREATE TABLE `chatgpt_orders` ( + `id` int NOT NULL, + `user_id` int NOT NULL COMMENT '用户ID', + `product_id` int NOT NULL COMMENT '产品ID', + `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户明', + `order_no` varchar(30) NOT NULL COMMENT '订单ID', + `trade_no` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '支付平台交易流水号', + `subject` varchar(100) NOT NULL COMMENT '订单产品', + `amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '订单金额', + `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '订单状态(0:待支付,1:已扫码,2:支付成功)', + `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '备注', + `pay_time` int DEFAULT NULL COMMENT '支付时间', + `pay_way` varchar(20) NOT NULL COMMENT '支付方式', + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + `deleted_at` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='充值订单表'; + +-- -------------------------------------------------------- + +-- +-- 表的结构 `chatgpt_power_logs` +-- + +DROP TABLE IF EXISTS `chatgpt_power_logs`; +CREATE TABLE `chatgpt_power_logs` ( + `id` int NOT NULL, + `user_id` int NOT NULL COMMENT '用户ID', + `username` varchar(30) NOT NULL COMMENT '用户名', + `type` tinyint(1) NOT NULL COMMENT '类型(1:充值,2:消费,3:退费)', + `amount` smallint NOT NULL COMMENT '算力数值', + `balance` int NOT NULL COMMENT '余额', + `model` varchar(30) NOT NULL COMMENT '模型', + `remark` varchar(255) NOT NULL COMMENT '备注', + `mark` tinyint(1) NOT NULL COMMENT '资金类型(0:支出,1:收入)', + `created_at` datetime NOT NULL COMMENT '创建时间' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户算力消费日志'; + +-- -------------------------------------------------------- + +-- +-- 表的结构 `chatgpt_products` +-- + +DROP TABLE IF EXISTS `chatgpt_products`; +CREATE TABLE `chatgpt_products` ( + `id` int NOT NULL, + `name` varchar(30) NOT NULL COMMENT '名称', + `price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '价格', + `discount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '优惠金额', + `days` smallint NOT NULL DEFAULT '0' COMMENT '延长天数', + `power` int NOT NULL DEFAULT '0' COMMENT '增加算力值', + `enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启动', + `sales` int NOT NULL DEFAULT '0' COMMENT '销量', + `sort_num` tinyint NOT NULL DEFAULT '0' COMMENT '排序', + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + `app_url` varchar(255) DEFAULT NULL COMMENT 'App跳转地址', + `url` varchar(255) DEFAULT NULL COMMENT '跳转地址' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员套餐表'; + +-- +-- 转存表中的数据 `chatgpt_products` +-- + +INSERT INTO `chatgpt_products` (`id`, `name`, `price`, `discount`, `days`, `power`, `enabled`, `sales`, `sort_num`, `created_at`, `updated_at`, `app_url`, `url`) VALUES + (1, '会员1个月', 1999.90, 1999.00, 30, 0, 1, 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(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci 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', + `openid` varchar(100) DEFAULT NULL COMMENT '第三方登录账号ID', + `platform` varchar(30) DEFAULT NULL COMMENT '登录平台', + `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`, `openid`, `platform`, `created_at`, `updated_at`) VALUES + (4, '18575670125', '极客学长@830270', 'ccc3fb7ab61b8b5d096a4a166ae21d121fc38c71bbd1be6173d9ab973214a63b', 'http://localhost:5678/static/upload/2024/5/1715651569509929.png', 'ueedue5l', 7413, 0, 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]', 1720683366, 1, '172.22.11.29', NULL, NULL, '2023-06-12 16:47:17', '2024-07-12 16:08:39'), + (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, '', NULL, NULL, '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, '', NULL, NULL, '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, '', NULL, NULL, '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, '', NULL, NULL, '2024-06-06 09:37:44', '2024-06-06 09:37:44'), + (14, 'wx@3567548322', '极客学长', '5a349ba89582a4074938b5a3ce84e87c937681ad47e8b87aab03a987e22b6077', 'https://thirdwx.qlogo.cn/mmopen/vi_32/uyxRMqZcEkb7fHouKXbNzxrnrvAttBKkwNlZ7yFibibRGiahdmsrZ3A1NKf8Fw5qJNJn4TXRmygersgEbibaSGd9Sg/132', 'abhzbmij', 83, 0, 1, '', '[\"gpt\"]', '[11,7,1,10,12,19,18,17,3]', 0, 0, '', 'oCs0t62472W19z2LOEKI1rWyCTTA', '', '2024-07-04 14:52:08', '2024-07-04 14:52:08'), + (15, 'user123', '极客学长@191303', '4a4c0a14d5fc8787357517f14f6e442281b42c8ec4395016b77483997476011e', '/images/avatar/user.png', 'cyzwkbrx', 100, 0, 1, '', '[\"gpt\"]', '[11,7,1,10,12,19,18,17,3]', 0, 0, '', '', '', '2024-07-09 10:49:27', '2024-07-09 10:49:27'), + (17, 'user1234', '极客学长@836764', 'bfe03c9c8c9fff5b77e36e40e8298ad3a6073d43c6a936b008eebb21113bf550', '/images/avatar/user.png', '1d2alwnj', 100, 0, 1, '', '[\"gpt\"]', '[11,7,1,10,12,19,18,17,3]', 0, 0, '', '', '', '2024-07-09 10:53:17', '2024-07-09 10:53:17'), + (18, 'liaoyq', '极客学长@405564', 'ad1726089022db4c661235a8aab7307af1a7f8483eee08bac3f79b5a6a9bd26b', '/images/avatar/user.png', 'yq862l01', 100, 0, 1, '', '[\"string\"]', '[11,7,1,10,12,19,18,17,3]', 1720574265, 0, '172.22.11.29', '', '', '2024-07-10 09:15:33', '2024-07-10 09:17:45'), + (19, 'humm', '极客学长@483216', '420970ace96921c8b3ac7668d097182eab1b6436c730a484e82ae4661bd4f7d9', '/images/avatar/user.png', '1gokrcl2', 100, 0, 1, '', '[\"gpt\"]', '[11,7,1,10,12,19,18,17,3]', 1720745411, 0, '172.22.11.36', '', '', '2024-07-10 11:08:31', '2024-07-12 08:50:11'), + (20, 'abc', '极客学长@369852', '6cad48fb2cc0f54600d66a829e9be69ffd9340a49d5a5b1abda5d4082d946833', '/images/avatar/user.png', 'gop65zei', 100, 0, 1, '', '[\"gpt\"]', '[11,7,1,10,12,19,18,17,3]', 0, 0, '', '', '', '2024-07-11 16:44:14', '2024-07-11 16:44:14'), + (21, 'husm@pvc123.com', '极客学长@721654', 'e030537dc43fea1bf1fa55a24f99e44f29311bebea96e88ea186995c77db083b', '/images/avatar/user.png', 'p1etg3oi', 100, 0, 1, '', '[\"gpt\"]', '[11,7,1,10,12,19,18,17,3]', 0, 0, '', '', '', '2024-07-11 16:50:33', '2024-07-11 16:50:33'), + (22, '15818323616', 'ted', '3ca6b2ff585d03be8ca4de33ad00148497a09372914ee8aa4cfde343266cbcdd', 'http://localhost:5678/static/upload/2024/7/1720775331363383.jpg', 'sq4s1brf', 100, 0, 1, '', '[\"gpt\"]', '[11,7,1,10,12,19,18,17,3]', 0, 0, '', '', '', '2024-07-12 15:12:16', '2024-07-12 17:09:01'); + +-- -------------------------------------------------------- + +-- +-- 表的结构 `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`); + +-- +-- 表的索引 `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=44; + +-- +-- 使用表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=23; + +-- +-- 使用表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 */; diff --git a/database/update-v4.1.0.sql b/database/update-v4.1.0.sql new file mode 100644 index 0000000..3f55b35 --- /dev/null +++ b/database/update-v4.1.0.sql @@ -0,0 +1,6 @@ +ALTER TABLE `chatgpt_chat_models` CHANGE `power` `power` SMALLINT NOT NULL COMMENT '消耗算力点数'; +ALTER TABLE `chatgpt_users` ADD `openid` VARCHAR(100) NULL COMMENT '第三方登录账号ID' AFTER `last_login_ip`; +ALTER TABLE `chatgpt_users` ADD `platform` VARCHAR(30) NULL COMMENT '登录平台' AFTER `openid`; +ALTER TABLE `chatgpt_users` CHANGE `avatar` `avatar` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '头像'; +ALTER TABLE `chatgpt_chat_history` CHANGE `icon` `icon` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '角色图标'; +ALTER TABLE `chatgpt_orders` CHANGE `status` `status` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '订单状态(0:待支付,1:已扫码,2:支付成功)'; \ No newline at end of file diff --git a/deploy/conf/config.toml b/deploy/conf/config.toml index f005f7e..fee98bc 100644 --- a/deploy/conf/config.toml +++ b/deploy/conf/config.toml @@ -4,6 +4,7 @@ MysqlDns = "root:12345678@tcp(geekai-mysql:3306)/chatgpt_plus?charset=utf8mb4&co StaticDir = "./static" StaticUrl = "/static" WeChatBot = false +TikaHost = "http://tika:9998" [Session] SecretKey = "azyehq3ivunjhbntz78isj00i4hz2mt9xtddysfucxakadq4qbfrt0b7q3lnvg80" diff --git a/deploy/docker-compose.yaml b/deploy/docker-compose.yaml index aa7bff5..ac0efd9 100644 --- a/deploy/docker-compose.yaml +++ b/deploy/docker-compose.yaml @@ -39,7 +39,13 @@ services: - ./logs/xxl-job:/data/applogs - ./conf/xxl-job/application.properties:/application.properties - + tika: + image: registry.cn-shenzhen.aliyuncs.com/geekmaster/tika:latest + container_name: tika + restart: always + ports: + - "9998:9998" + midjourney-proxy: image: registry.cn-shenzhen.aliyuncs.com/geekmaster/midjourney-proxy:2.6.2 container_name: geekai-midjourney-proxy @@ -52,7 +58,7 @@ services: # 后端 API 程序 geekai-api: - image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-api:v4.0.9-amd64 + image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-api:v4.1.0-amd64 container_name: geekai-api restart: always depends_on: @@ -74,7 +80,7 @@ services: # 前端应用 geekai-web: - image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-web:v4.0.9-amd64 + image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-web:v4.1.0-amd64 container_name: geekai-web restart: always depends_on: diff --git a/web/.env.development b/web/.env.development index ec9467e..5a9770c 100644 --- a/web/.env.development +++ b/web/.env.development @@ -6,4 +6,4 @@ VUE_APP_ADMIN_USER=admin VUE_APP_ADMIN_PASS=admin123 VUE_APP_KEY_PREFIX=ChatPLUS_DEV_ VUE_APP_TITLE="Geek-AI 创作系统" -VUE_APP_VERSION=v4.0.9 +VUE_APP_VERSION=v4.1.0 diff --git a/web/.env.production b/web/.env.production index 74545d1..8afbdca 100644 --- a/web/.env.production +++ b/web/.env.production @@ -2,4 +2,4 @@ VUE_APP_API_HOST= VUE_APP_WS_HOST= VUE_APP_KEY_PREFIX=ChatPLUS_ VUE_APP_TITLE="Geek-AI 创作系统" -VUE_APP_VERSION=v4.0.9 +VUE_APP_VERSION=v4.1.0 diff --git a/web/public/images/ext/doc.png b/web/public/images/ext/doc.png index 9e2c369..465c78f 100644 Binary files a/web/public/images/ext/doc.png and b/web/public/images/ext/doc.png differ diff --git a/web/public/images/ext/ppt.png b/web/public/images/ext/ppt.png index 4401909..c1e1f33 100644 Binary files a/web/public/images/ext/ppt.png and b/web/public/images/ext/ppt.png differ diff --git a/web/public/images/ext/xls.png b/web/public/images/ext/xls.png index 1897bdc..c7893c9 100644 Binary files a/web/public/images/ext/xls.png and b/web/public/images/ext/xls.png differ diff --git a/web/src/assets/img/ai-bg.jpg b/web/public/images/index-bg.jpg similarity index 100% rename from web/src/assets/img/ai-bg.jpg rename to web/public/images/index-bg.jpg diff --git a/web/src/assets/css/admin/form.styl b/web/src/assets/css/admin/form.styl index 9829924..dd3e463 100644 --- a/web/src/assets/css/admin/form.styl +++ b/web/src/assets/css/admin/form.styl @@ -3,14 +3,12 @@ display flex width 100% - .el-input { - width 50% + .el-input,.el-select,.el-switch { + margin-right 10px } .info { - margin-left 6px margin-top 2px } - } } \ No newline at end of file diff --git a/web/src/assets/css/chat-plus.css b/web/src/assets/css/chat-plus.css index 8516383..8a231ae 100644 --- a/web/src/assets/css/chat-plus.css +++ b/web/src/assets/css/chat-plus.css @@ -2,27 +2,27 @@ height: 100%; } -#app .common-layout { +#app .chat-page { height: 100%; } -#app .common-layout .el-aside { +#app .chat-page .el-aside { background-color: #252526; } -#app .common-layout .el-aside .title-box { +#app .chat-page .el-aside .title-box { padding: 6px 10px; display: flex; color: #fff; font-size: 20px; } -#app .common-layout .el-aside .title-box span { +#app .chat-page .el-aside .title-box span { padding-top: 5px; padding-left: 10px; } -#app .common-layout .el-aside .chat-list { +#app .chat-page .el-aside .chat-list { display: flex; flex-flow: column; background-color: #28292a; @@ -30,28 +30,28 @@ border-right: 1px solid #2f3032; } -#app .common-layout .el-aside .chat-list .search-box { +#app .chat-page .el-aside .chat-list .search-box { flex-wrap: wrap; padding: 10px 15px; } -#app .common-layout .el-aside .chat-list .search-box .el-input__wrapper { +#app .chat-page .el-aside .chat-list .search-box .el-input__wrapper { background-color: #363535; box-shadow: none; } -#app .common-layout .el-aside .chat-list ::-webkit-scrollbar { +#app .chat-page .el-aside .chat-list ::-webkit-scrollbar { width: 0; height: 0; background-color: transparent; } -#app .common-layout .el-aside .chat-list .content { +#app .chat-page .el-aside .chat-list .content { width: 100%; overflow-y: scroll; } -#app .common-layout .el-aside .chat-list .content .chat-list-item { +#app .chat-page .el-aside .chat-list .content .chat-list-item { display: flex; width: 100%; justify-content: flex-start; @@ -59,17 +59,17 @@ cursor: pointer; } -#app .common-layout .el-aside .chat-list .content .chat-list-item:hover { +#app .chat-page .el-aside .chat-list .content .chat-list-item:hover { background-color: #343540; } -#app .common-layout .el-aside .chat-list .content .chat-list-item .avatar { +#app .chat-page .el-aside .chat-list .content .chat-list-item .avatar { width: 28px; height: 28px; border-radius: 50%; } -#app .common-layout .el-aside .chat-list .content .chat-list-item .chat-title-input { +#app .chat-page .el-aside .chat-list .content .chat-list-item .chat-title-input { font-size: 14px; margin-top: 4px; margin-left: 10px; @@ -79,7 +79,7 @@ width: 190px; } -#app .common-layout .el-aside .chat-list .content .chat-list-item .chat-title { +#app .chat-page .el-aside .chat-list .content .chat-list-item .chat-title { color: #c1c1c1; padding: 5px 10px; max-width: 220px; @@ -89,7 +89,7 @@ text-overflow: ellipsis; } -#app .common-layout .el-aside .chat-list .content .chat-list-item .btn { +#app .chat-page .el-aside .chat-list .content .chat-list-item .btn { display: none; position: absolute; right: 2px; @@ -97,19 +97,19 @@ color: #fff; } -#app .common-layout .el-aside .chat-list .content .chat-list-item .btn .el-icon { +#app .chat-page .el-aside .chat-list .content .chat-list-item .btn .el-icon { margin-right: 8px; } -#app .common-layout .el-aside .chat-list .content .chat-list-item.active { +#app .chat-page .el-aside .chat-list .content .chat-list-item.active { background-color: #343540; } -#app .common-layout .el-aside .chat-list .content .chat-list-item.active .btn { +#app .chat-page .el-aside .chat-list .content .chat-list-item.active .btn { display: inline; } -#app .common-layout .el-aside .tool-box { +#app .chat-page .el-aside .tool-box { display: flex; justify-content: flex-end; align-items: center; @@ -117,48 +117,48 @@ border-top: 1px solid #3c3c3c; } -#app .common-layout .el-aside .tool-box .user-info { +#app .chat-page .el-aside .tool-box .user-info { width: 100%; padding-top: 10px; } -#app .common-layout .el-aside .tool-box .user-info .el-dropdown-link { +#app .chat-page .el-aside .tool-box .user-info .el-dropdown-link { width: 100%; cursor: pointer; display: flex; } -#app .common-layout .el-aside .tool-box .user-info .el-dropdown-link .el-image { +#app .chat-page .el-aside .tool-box .user-info .el-dropdown-link .el-image { width: 20px; height: 20px; border-radius: 5px; } -#app .common-layout .el-aside .tool-box .user-info .el-dropdown-link .username { +#app .chat-page .el-aside .tool-box .user-info .el-dropdown-link .username { display: flex; line-height: 22px; width: 230px; padding-left: 10px; } -#app .common-layout .el-aside .tool-box .user-info .el-dropdown-link .el-icon { +#app .chat-page .el-aside .tool-box .user-info .el-dropdown-link .el-icon { color: #ccc; line-height: 24px; } -#app .common-layout .el-main { +#app .chat-page .el-main { overflow: hidden; --el-main-padding: 0; margin: 0; } -#app .common-layout .el-main .chat-head { +#app .chat-page .el-main .chat-head { width: 100%; height: 50px; background-color: #28292a; } -#app .common-layout .el-main .chat-head .chat-config { +#app .chat-page .el-main .chat-head .chat-config { display: flex; flex-direction: row; align-items: center; @@ -166,54 +166,54 @@ padding-top: 10px; } -#app .common-layout .el-main .chat-head .chat-config .role-select-label { +#app .chat-page .el-main .chat-head .chat-config .role-select-label { color: #fff; } -#app .common-layout .el-main .chat-head .chat-config .el-select { +#app .chat-page .el-main .chat-head .chat-config .el-select { max-width: 150px; margin-right: 10px; } -#app .common-layout .el-main .chat-head .chat-config .role-select { +#app .chat-page .el-main .chat-head .chat-config .role-select { max-width: 130px; } -#app .common-layout .el-main .chat-head .chat-config .el-button .el-icon { +#app .chat-page .el-main .chat-head .chat-config .el-button .el-icon { margin-right: 5px; } -#app .common-layout .el-main .chat-head .iconfont { +#app .chat-page .el-main .chat-head .iconfont { margin-right: 5px; } -#app .common-layout .el-main .chat-head .is-circle { +#app .chat-page .el-main .chat-head .is-circle { margin-left: 5px; } -#app .common-layout .el-main .chat-head .is-circle .iconfont { +#app .chat-page .el-main .chat-head .is-circle .iconfont { margin-right: 0; } -#app .common-layout .el-main .chat-box { +#app .chat-page .el-main .chat-box { min-width: 0; flex: 1; background-color: #fff; border-left: 1px solid #4f4f4f; } -#app .common-layout .el-main .chat-box #container { +#app .chat-page .el-main .chat-box #container { overflow: hidden; width: 100%; } -#app .common-layout .el-main .chat-box #container ::-webkit-scrollbar { +#app .chat-page .el-main .chat-box #container ::-webkit-scrollbar { width: 0; height: 0; background-color: transparent; } -#app .common-layout .el-main .chat-box #container .chat-box { +#app .chat-page .el-main .chat-box #container .chat-box { overflow-y: scroll; --content-font-size: 16px; --content-color: #c1c1c1; @@ -221,28 +221,28 @@ padding: 0 0 50px 0; } -#app .common-layout .el-main .chat-box #container .chat-box .chat-line { +#app .chat-page .el-main .chat-box #container .chat-box .chat-line { font-size: 14px; display: flex; align-items: flex-start; } -#app .common-layout .el-main .chat-box #container .re-generate { +#app .chat-page .el-main .chat-box #container .re-generate { position: relative; display: flex; justify-content: center; } -#app .common-layout .el-main .chat-box #container .re-generate .btn-box { +#app .chat-page .el-main .chat-box #container .re-generate .btn-box { position: absolute; bottom: 10px; } -#app .common-layout .el-main .chat-box #container .re-generate .btn-box .el-button .el-icon { +#app .chat-page .el-main .chat-box #container .re-generate .btn-box .el-button .el-icon { margin-right: 5px; } -#app .common-layout .el-main .chat-box #container .input-box { +#app .chat-page .el-main .chat-box #container .input-box { background-color: #fff; display: flex; justify-content: center; @@ -251,7 +251,7 @@ padding: 0 15px; } -#app .common-layout .el-main .chat-box #container .input-box .input-container { +#app .chat-page .el-main .chat-box #container .input-box .input-container { width: 100%; margin: 0; border: none; @@ -261,24 +261,24 @@ position: relative; } -#app .common-layout .el-main .chat-box #container .input-box .input-container .el-textarea .el-textarea__inner::-webkit-scrollbar { +#app .chat-page .el-main .chat-box #container .input-box .input-container .el-textarea .el-textarea__inner::-webkit-scrollbar { width: 0; height: 0; } -#app .common-layout .el-main .chat-box #container .input-box .input-container .select-file { +#app .chat-page .el-main .chat-box #container .input-box .input-container .select-file { position: absolute; right: 48px; top: 20px; } -#app .common-layout .el-main .chat-box #container .input-box .input-container .send-btn { +#app .chat-page .el-main .chat-box #container .input-box .input-container .send-btn { position: absolute; right: 12px; top: 20px; } -#app .common-layout .el-main .chat-box #container .input-box .input-container .send-btn .el-button { +#app .chat-page .el-main .chat-box #container .input-box .input-container .send-btn .el-button { padding: 8px 5px; border-radius: 6px; background: #19c37d; @@ -286,7 +286,7 @@ font-size: 20px; } -#app .common-layout .el-main .chat-box #container::-webkit-scrollbar { +#app .chat-page .el-main .chat-box #container::-webkit-scrollbar { width: 0; height: 0; } diff --git a/web/src/assets/css/chat-plus.styl b/web/src/assets/css/chat-plus.styl index 61522fe..1c4a22c 100644 --- a/web/src/assets/css/chat-plus.styl +++ b/web/src/assets/css/chat-plus.styl @@ -4,7 +4,7 @@ $borderColor = #4676d0; height: 100%; - .common-layout { + .chat-page { height: 100%; // left side @@ -156,6 +156,20 @@ $borderColor = #4676d0; max-width 130px; } + .setting { + padding 5px + border-radius 5px + cursor pointer + .iconfont { + font-size 18px + color #19c37d + } + + &:hover { + background #D5FAD3 + } + } + .el-button { .el-icon { margin-right 5px; @@ -169,13 +183,25 @@ $borderColor = #4676d0; position relative ::-webkit-scrollbar { - width: 0; - height: 0; - background-color: transparent; + width: 12px /* 滚动条宽度 */ + background #F1F1F1 + } + + ::-webkit-scrollbar-track { + background-color: #e1e1e1; + } + + ::-webkit-scrollbar-thumb { + background-color: #c1c1c1; + border-radius 12px + } + + ::-webkit-scrollbar-thumb:hover { + background-color: #A8A8A8; } .chat-box { - overflow-y: scroll; + overflow-y: auto; //border-bottom: 1px solid #4f4f4f // 变量定义 @@ -252,25 +278,35 @@ $borderColor = #4676d0; border: 2px solid #21AA93 border-radius 10px padding 10px + background-color #F4F4F4 - - .prompt-input::-webkit-scrollbar { - width: 0; - height: 0; - } - - .prompt-input { + .input-inner { + display flex + flex-flow column width 100% - line-height: 24px - border none - font-size 14px - background none - resize: none - white-space: pre-wrap; /* 保持文本换行 */ - word-wrap: break-word; /* 允许单词换行 */ - overflow-wrap: break-word; /* 允许长单词换行,适用于现代浏览器 */ + + .file-list { + padding-bottom 10px + } + .prompt-input::-webkit-scrollbar { + width: 0; + height: 0; + } + + .prompt-input { + width 100% + line-height: 24px + border none + font-size 14px + background none + resize: none + white-space: pre-wrap; /* 保持文本换行 */ + word-wrap: break-word; /* 允许单词换行 */ + overflow-wrap: break-word; /* 允许长单词换行,适用于现代浏览器 */ + } } + .send-btn { width 32px margin-left 10px diff --git a/web/src/assets/css/login.styl b/web/src/assets/css/login.styl new file mode 100644 index 0000000..bf8b6c4 --- /dev/null +++ b/web/src/assets/css/login.styl @@ -0,0 +1,115 @@ +.bg { + position fixed + left 0 + right 0 + top 0 + bottom 0 + background-color #313237 + background-image url("~@/assets/img/login-bg.jpg") + background-size cover + background-position center + background-repeat repeat-y + //filter: blur(10px); /* 调整模糊程度,可以根据需要修改值 */ +} + +.main { + .contain { + position fixed + left 50% + top 40% + width 90% + max-width 400px; + transform translate(-50%, -50%) + padding 20px 10px; + color #ffffff + border-radius 10px; + + .logo { + text-align center + + .el-image { + width 120px; + cursor pointer + } + } + + .header { + width 100% + margin-bottom 24px + font-size 24px + color $white_v1 + letter-space 2px + text-align center + padding-top 10px + } + + .content { + width 100% + height: auto + border-radius 3px + + .block { + margin-bottom 16px + + .el-input__inner { + border 1px solid $gray-v6 !important + + .el-icon-user, .el-icon-lock { + font-size 20px + } + } + } + + .btn-row { + padding-top 10px; + + .login-btn { + width 100% + font-size 16px + letter-spacing 2px + } + } + + .text-line { + justify-content center + padding-top 10px; + font-size 14px; + } + + .opt { + padding 15px + .el-col { + text-align center + } + } + + .divider { + border-top: 2px solid #c1c1c1; + } + + .clogin { + padding 15px + display flex + justify-content center + + .iconfont { + font-size 20px + background: #E9F1F6; + padding: 8px; + border-radius: 50%; + } + .iconfont.icon-wechat { + color #0bc15f + } + } + } + } + + .footer { + color #ffffff; + + .container { + padding 20px; + } + } +} \ No newline at end of file diff --git a/web/src/assets/css/markdown/vue.css b/web/src/assets/css/markdown/vue.css new file mode 100644 index 0000000..296b9a7 --- /dev/null +++ b/web/src/assets/css/markdown/vue.css @@ -0,0 +1,237 @@ +.chat-line { + ol, ul { + margin: 0.8em 0; + list-style: normal; + } + a { + color: #42b983; + font-weight: 600; + padding: 0 2px; + text-decoration: none; + } + + h1, + h2, + h3, + h4, + h5, + h6 { + position: relative; + margin-top: 1rem; + margin-bottom: 1rem; + font-weight: bold; + line-height: 1.4; + cursor: text; + } + + h1:hover a.anchor, + h2:hover a.anchor, + h3:hover a.anchor, + h4:hover a.anchor, + h5:hover a.anchor, + h6:hover a.anchor { + text-decoration: none; + } + + h1 tt, + h1 code { + font-size: inherit !important; + } + + h2 tt, + h2 code { + font-size: inherit !important; + } + + h3 tt, + h3 code { + font-size: inherit !important; + } + + h4 tt, + h4 code { + font-size: inherit !important; + } + + h5 tt, + h5 code { + font-size: inherit !important; + } + + h6 tt, + h6 code { + font-size: inherit !important; + } + + h2 a, + h3 a { + color: #34495e; + } + + h1 { + padding-bottom: .4rem; + font-size: 2.2rem; + line-height: 1.3; + } + + h2 { + font-size: 1.75rem; + line-height: 1.225; + margin: 35px 0 15px; + padding-bottom: 0.5em; + border-bottom: 1px solid #ddd; + } + + h3 { + font-size: 1.4rem; + line-height: 1.43; + margin: 20px 0 7px; + } + + h4 { + font-size: 1.2rem; + } + + h5 { + font-size: 1rem; + } + + h6 { + font-size: 1rem; + color: #777; + } + + p, + blockquote, + ul, + ol, + dl, + table { + margin: 0.8em 0; + } + + li > ol, + li > ul { + margin: 0 0; + } + + hr { + height: 2px; + padding: 0; + margin: 16px 0; + background-color: #e7e7e7; + border: 0 none; + overflow: hidden; + box-sizing: content-box; + } + + body > h2:first-child { + margin-top: 0; + padding-top: 0; + } + + body > h1:first-child { + margin-top: 0; + padding-top: 0; + } + + body > h1:first-child + h2 { + margin-top: 0; + padding-top: 0; + } + + body > h3:first-child, + body > h4:first-child, + body > h5:first-child, + body > h6:first-child { + margin-top: 0; + padding-top: 0; + } + + a:first-child h1, + a:first-child h2, + a:first-child h3, + a:first-child h4, + a:first-child h5, + a:first-child h6 { + margin-top: 0; + padding-top: 0; + } + + h1 p, + h2 p, + h3 p, + h4 p, + h5 p, + h6 p { + margin-top: 0; + } + + li p.first { + display: inline-block; + } + + ul, + ol { + padding-left: 30px; + } + + ul:first-child, + ol:first-child { + margin-top: 0; + } + + ul:last-child, + ol:last-child { + margin-bottom: 0; + } + + blockquote { + border-left: 4px solid #42b983; + padding: 10px 15px; + color: #777; + background-color: rgba(66, 185, 131, .1); + } + + table { + padding: 0; + word-break: initial; + } + + table tr { + border-top: 1px solid #dfe2e5; + margin: 0; + padding: 0; + } + + table tr:nth-child(2n), + thead { + background-color: #fafafa; + } + + table tr th { + font-weight: bold; + border: 1px solid #dfe2e5; + border-bottom: 0; + text-align: left; + margin: 0; + padding: 6px 13px; + } + + table tr td { + border: 1px solid #dfe2e5; + text-align: left; + margin: 0; + padding: 6px 13px; + } + + table tr th:first-child, + table tr td:first-child { + margin-top: 0; + } + + table tr th:last-child, + table tr td:last-child { + margin-bottom: 0; + } +} diff --git a/web/src/assets/img/ai-bg-02.png b/web/src/assets/img/ai-bg-02.png deleted file mode 100644 index ad0d7ed..0000000 Binary files a/web/src/assets/img/ai-bg-02.png and /dev/null differ diff --git a/web/src/components/ChatPrompt.vue b/web/src/components/ChatPrompt.vue index fcd924e..746a990 100644 --- a/web/src/components/ChatPrompt.vue +++ b/web/src/components/ChatPrompt.vue @@ -1,152 +1,420 @@ - \ No newline at end of file + diff --git a/web/src/components/ChatReply.vue b/web/src/components/ChatReply.vue index 175af9f..6e64dbb 100644 --- a/web/src/components/ChatReply.vue +++ b/web/src/components/ChatReply.vue @@ -1,5 +1,5 @@ diff --git a/web/src/components/ChatSetting.vue b/web/src/components/ChatSetting.vue new file mode 100644 index 0000000..7672645 --- /dev/null +++ b/web/src/components/ChatSetting.vue @@ -0,0 +1,50 @@ + + + + + \ No newline at end of file diff --git a/web/src/components/FileList.vue b/web/src/components/FileList.vue new file mode 100644 index 0000000..b503b92 --- /dev/null +++ b/web/src/components/FileList.vue @@ -0,0 +1,115 @@ + + + + + \ No newline at end of file diff --git a/web/src/components/FileSelect.vue b/web/src/components/FileSelect.vue index 97fc847..b2a1cb5 100644 --- a/web/src/components/FileSelect.vue +++ b/web/src/components/FileSelect.vue @@ -1,5 +1,5 @@ diff --git a/web/src/views/Dalle.vue b/web/src/views/Dalle.vue index 1e151b7..2e69ca6 100644 --- a/web/src/views/Dalle.vue +++ b/web/src/views/Dalle.vue @@ -86,43 +86,7 @@

任务列表

-
-
-
-
- - - - - - -
- -
-
- - - -
-
- -
+

创作记录

@@ -228,6 +192,7 @@ import {ElMessage, ElMessageBox, ElNotification} from "element-plus"; import Clipboard from "clipboard"; import {checkSession} from "@/action/session"; import {useSharedStore} from "@/store/sharedata"; +import TaskList from "@/components/TaskList.vue"; const listBoxHeight = ref(0) // const paramBoxHeight = ref(0) @@ -369,7 +334,7 @@ const fetchRunningJobs = () => { return } // 获取运行中的任务 - httpGet(`/api/dall/jobs?status=0`).then(res => { + httpGet(`/api/dall/jobs?finish=false`).then(res => { const jobs = res.data const _jobs = [] for (let i = 0; i < jobs.length; i++) { @@ -402,7 +367,7 @@ const fetchFinishJobs = () => { loading.value = true page.value = page.value + 1 - httpGet(`/api/dall/jobs?status=1&page=${page.value}&page_size=${pageSize.value}`).then(res => { + httpGet(`/api/dall/jobs?finish=true&page=${page.value}&page_size=${pageSize.value}`).then(res => { if (res.data.length < pageSize.value) { isOver.value = true } @@ -454,7 +419,7 @@ const removeImage = (event, item) => { type: 'warning', } ).then(() => { - httpPost("/api/dall/remove", {id: item.id, img_url: item.img_url, user_id: userId.value}).then(() => { + httpGet("/api/dall/remove", {id: item.id, user_id: item.user}).then(() => { ElMessage.success("任务删除成功") page.value = 0 isOver.value = false @@ -477,7 +442,7 @@ const publishImage = (event, item, action) => { if (action === false) { text = "取消发布" } - httpPost("/api/dall/publish", {id: item.id, action: action}).then(() => { + httpGet("/api/dall/publish", {id: item.id, action: action,user_id:item.user_id}).then(() => { ElMessage.success(text + "成功") item.publish = action page.value = 0 diff --git a/web/src/views/Home.vue b/web/src/views/Home.vue index 4302457..ceaa148 100644 --- a/web/src/views/Home.vue +++ b/web/src/views/Home.vue @@ -49,15 +49,15 @@
- + 用户手册 - - Geek-AI {{ version }} + + GeekAI {{ version }}
@@ -142,7 +142,7 @@ import {checkSession} from "@/action/session"; import {removeUserToken} from "@/store/session"; import LoginDialog from "@/components/LoginDialog.vue"; import {useSharedStore} from "@/store/sharedata"; -import ConfigDialog from "@/components/ConfigDialog.vue"; +import ConfigDialog from "@/components/UserInfoDialog.vue"; import {showMessageError} from "@/utils/dialog"; const router = useRouter(); @@ -157,6 +157,8 @@ const version = ref(process.env.VUE_APP_VERSION) const routerViewKey = ref(0) const showConfigDialog = ref(false) const licenseConfig = ref({}) +const docsURL = ref(process.env.VUE_APP_DOCS_URL) +const gitURL = ref(process.env.VUE_APP_GIT_URL) const store = useSharedStore(); const show = ref(false) @@ -215,10 +217,11 @@ const init = () => { const logout = function () { httpGet('/api/user/logout').then(() => { removeUserToken() - store.setShowLoginDialog(true) - loginUser.value = {} - // 刷新组件 - routerViewKey.value += 1 + router.push("/login") + // store.setShowLoginDialog(true) + // loginUser.value = {} + // // 刷新组件 + // routerViewKey.value += 1 }).catch(() => { ElMessage.error('注销失败!'); }) diff --git a/web/src/views/ImageMj.vue b/web/src/views/ImageMj.vue index 2a5555b..29ab660 100644 --- a/web/src/views/ImageMj.vue +++ b/web/src/views/ImageMj.vue @@ -163,7 +163,7 @@
-
+
@@ -450,43 +450,7 @@

任务列表

-
-
-
-
- - - - - - -
- -
-
- - - -
-
- -
+

创作记录

@@ -617,6 +581,7 @@ import {useRouter} from "vue-router"; import {getSessionId} from "@/store/session"; import {copyObj, removeArrayItem} from "@/utils/libs"; import {useSharedStore} from "@/store/sharedata"; +import TaskList from "@/components/TaskList.vue"; const listBoxHeight = ref(0) const paramBoxHeight = ref(0) @@ -817,7 +782,7 @@ const fetchRunningJobs = () => { return } - httpGet(`/api/mj/jobs?status=0`).then(res => { + httpGet(`/api/mj/jobs?finish=false`).then(res => { const jobs = res.data const _jobs = [] for (let i = 0; i < jobs.length; i++) { @@ -855,7 +820,7 @@ const fetchFinishJobs = () => { loading.value = true page.value = page.value + 1 // 获取已完成的任务 - httpGet(`/api/mj/jobs?status=1&page=${page.value}&page_size=${pageSize.value}`).then(res => { + httpGet(`/api/mj/jobs?finish=true&page=${page.value}&page_size=${pageSize.value}`).then(res => { const jobs = res.data for (let i = 0; i < jobs.length; i++) { if (jobs[i]['img_url'] !== "") { @@ -996,7 +961,7 @@ const removeImage = (item) => { type: 'warning', } ).then(() => { - httpPost("/api/mj/remove", {id: item.id, img_url: item.img_url, user_id: userId.value}).then(() => { + httpGet("/api/mj/remove", {id: item.id, user_id: item.user_id}).then(() => { ElMessage.success("任务删除成功") page.value = 0 isOver.value = false @@ -1014,7 +979,7 @@ const publishImage = (item, action) => { if (action === false) { text = "取消发布" } - httpPost("/api/mj/publish", {id: item.id, action: action}).then(() => { + httpGet("/api/mj/publish", {id: item.id, action: action,user_id: item.user_id}).then(() => { ElMessage.success(text + "成功") item.publish = action page.value = 0 diff --git a/web/src/views/ImageSd.vue b/web/src/views/ImageSd.vue index 2706b7c..7c686fe 100644 --- a/web/src/views/ImageSd.vue +++ b/web/src/views/ImageSd.vue @@ -30,7 +30,7 @@
- +