diff --git a/api/handler/user_handler.go b/api/handler/user_handler.go index 2a7ba461..f93fec05 100644 --- a/api/handler/user_handler.go +++ b/api/handler/user_handler.go @@ -80,7 +80,7 @@ func (h *UserHandler) Register(c *gin.Context) { // check if the username is exists var item model.User res := h.db.Where("username = ?", data.Username).First(&item) - if res.RowsAffected > 0 { + if item.Id > 0 { resp.ERROR(c, "该用户名已经被注册") return } @@ -257,7 +257,7 @@ type userProfile struct { Calls int `json:"calls"` ImgCalls int `json:"img_calls"` TotalTokens int64 `json:"total_tokens"` - Tokens int64 `json:"tokens"` + Tokens int `json:"tokens"` ExpiredTime int64 `json:"expired_time"` Vip bool `json:"vip"` } diff --git a/database/update-v3.2.8.sql b/database/update-v3.2.8.sql new file mode 100644 index 00000000..bd031e71 --- /dev/null +++ b/database/update-v3.2.8.sql @@ -0,0 +1,23 @@ +-- 删除用户名重复的用户,只保留一条 +DELETE FROM chatgpt_users +WHERE username IN ( + SELECT username + FROM ( + SELECT username + FROM chatgpt_users + GROUP BY username + HAVING COUNT(*) > 1 + ) AS temp +) AND id NOT IN ( + SELECT MIN(id) + FROM ( + SELECT id, username + FROM chatgpt_users + GROUP BY id, username + HAVING COUNT(*) > 1 + ) AS temp + GROUP BY username +); + +-- 给 username 字段建立唯一索引 +ALTER TABLE `chatgpt_users` ADD UNIQUE(`username`) \ No newline at end of file diff --git a/web/src/assets/css/member.css b/web/src/assets/css/member.css new file mode 100644 index 00000000..2cf320ff --- /dev/null +++ b/web/src/assets/css/member.css @@ -0,0 +1,147 @@ +.member { + background-color: #282c34; + height: 100vh; +} +.member .el-dialog .el-dialog__body { + padding-top: 10px; +} +.member .el-dialog .el-dialog__body .pay-container .count-down { + display: flex; + justify-content: center; +} +.member .el-dialog .el-dialog__body .pay-container .pay-qrcode { + display: flex; + justify-content: center; +} +.member .el-dialog .el-dialog__body .pay-container .pay-qrcode .el-image { + width: 360px; + height: 360px; +} +.member .el-dialog .el-dialog__body .pay-container .tip { + display: flex; + justify-content: center; +} +.member .el-dialog .el-dialog__body .pay-container .tip .el-icon { + font-size: 24px; +} +.member .el-dialog .el-dialog__body .pay-container .tip .text { + font-size: 16px; + margin-left: 10px; +} +.member .el-dialog .el-dialog__body .pay-container .tip.success { + color: #07c160; +} +.member .title { + text-align: center; + background-color: #25272d; + font-size: 24px; + color: #fff; + padding: 10px; + border-bottom: 1px solid #3c3c3c; +} +.member .inner { + color: #fff; + padding: 15px 0 15px 15px; + overflow-x: hidden; + overflow-y: visible; +} +.member .inner .user-profile { + padding: 10px 20px 20px 20px; + background-color: #393f4a; + color: #fff; + border-radius: 10px; + height: 100vh; +} +.member .inner .user-profile .el-form-item__label { + color: #fff; + justify-content: start; +} +.member .inner .user-profile .user-opt .el-col { + padding: 10px; +} +.member .inner .user-profile .user-opt .el-col .el-button { + width: 100%; +} +.member .inner .product-box .info { + padding: 10px 20px 20px 0; +} +.member .inner .product-box .info .el-alert__description { + font-size: 14px !important; + margin: 0; +} +.member .inner .product-box .list-box .product-item { + border: 1px solid #666; + border-radius: 6px; + overflow: hidden; + cursor: pointer; + transition: all 0.3s ease; /* 添加过渡效果 */ +} +.member .inner .product-box .list-box .product-item .image-container { + display: flex; + justify-content: center; +} +.member .inner .product-box .list-box .product-item .image-container .el-image { + padding: 6px; +} +.member .inner .product-box .list-box .product-item .image-container .el-image .el-image__inner { + border-radius: 10px; +} +.member .inner .product-box .list-box .product-item .product-title { + display: flex; + padding: 10px; +} +.member .inner .product-box .list-box .product-item .product-title .name { + width: 100%; + text-align: center; + font-size: 16px; + font-weight: bold; + color: #47fff1; +} +.member .inner .product-box .list-box .product-item .product-info { + padding: 10px 20px; + font-size: 14px; + color: #999; +} +.member .inner .product-box .list-box .product-item .product-info .info-line { + display: flex; + width: 100%; + padding: 5px 0; +} +.member .inner .product-box .list-box .product-item .product-info .info-line .label { + display: flex; + width: 100%; +} +.member .inner .product-box .list-box .product-item .product-info .info-line .price, +.member .inner .product-box .list-box .product-item .product-info .info-line .expire, +.member .inner .product-box .list-box .product-item .product-info .info-line calls { + display: flex; + width: 90px; + justify-content: right; +} +.member .inner .product-box .list-box .product-item .product-info .info-line .price { + color: #f56c6c; +} +.member .inner .product-box .list-box .product-item .product-info .info-line .expire { + color: #409eff; +} +.member .inner .product-box .list-box .product-item .product-info .info-line .calls { + color: #f2cb51; +} +.member .inner .product-box .list-box .product-item .product-info .pay-way { + padding: 10px 0; + display: flex; + justify-content: space-between; +} +.member .inner .product-box .list-box .product-item .product-info .pay-way .iconfont { + margin-right: 5px; +} +.member .inner .product-box .list-box .product-item:hover { + box-shadow: 0 0 10px rgba(71,255,241,0.6); /* 添加阴影效果 */ + transform: translateY(-10px); /* 向上移动10像素 */ +} +.member .inner .product-box .headline { + padding: 0 20px 20px 0; +} +.member .inner .product-box .user-order { + padding: 0 20px 20px 0; +} diff --git a/web/src/assets/css/member.styl b/web/src/assets/css/member.styl new file mode 100644 index 00000000..65dcfcc2 --- /dev/null +++ b/web/src/assets/css/member.styl @@ -0,0 +1,191 @@ +.member { + background-color: #282c34; + height 100vh + + .el-dialog { + .el-dialog__body { + padding-top 10px + + .pay-container { + .count-down { + display flex + justify-content center + } + + .pay-qrcode { + display flex + justify-content center + + .el-image { + width 360px; + height 360px; + } + } + + .tip { + display flex + justify-content center + + .el-icon { + font-size 24px + } + + .text { + font-size: 16px + margin-left 10px + } + } + + .tip.success { + color #07c160 + } + } + } + } + + .title { + text-align center + background-color #25272d + font-size 24px + color #ffffff + padding 10px + border-bottom 1px solid #3c3c3c + } + + .inner { + color #ffffff + padding 15px 0 15px 15px; + overflow-x hidden + overflow-y visible + + .user-profile { + padding 10px 20px 20px 20px + background-color #393F4A + color #ffffff + border-radius 10px + height 100vh + + .el-form-item__label { + color #ffffff + justify-content start + } + + .user-opt { + .el-col { + padding 10px + + .el-button { + width 100% + } + } + } + } + + + .product-box { + .info { + .el-alert__description { + font-size 14px !important + margin 0 + } + padding 10px 20px 20px 0 + } + + .list-box { + .product-item { + border 1px solid #666666 + border-radius 6px + overflow hidden + cursor pointer + transition: all 0.3s ease; /* 添加过渡效果 */ + + .image-container { + display flex + justify-content center + + .el-image { + padding 6px + + .el-image__inner { + border-radius 10px + } + } + } + + .product-title { + display flex + padding 10px + + .name { + width 100% + text-align center + font-size 16px + font-weight bold + color #47fff1 + } + } + + .product-info { + padding 10px 20px + font-size 14px + color #999999 + + .info-line { + display flex + width 100% + padding 5px 0 + + .label { + display flex + width 100% + } + + .price, .expire, calls { + display flex + width 90px + justify-content right + } + + .price { + color #f56c6c + } + + .expire { + color #409eff + } + + .calls { + color #F2CB51 + } + } + + + .pay-way { + padding 10px 0 + display flex + justify-content: space-between + + .iconfont { + margin-right 5px + } + } + } + + &:hover { + box-shadow: 0 0 10px rgba(71, 255, 241, 0.6); /* 添加阴影效果 */ + transform: translateY(-10px); /* 向上移动10像素 */ + } + } + } + + .headline { + padding 0 20px 20px 0 + } + + .user-order { + padding 0 20px 20px 0 + } + } + } + +} \ No newline at end of file diff --git a/web/src/components/ChatPrompt.vue b/web/src/components/ChatPrompt.vue index a1669c25..9bf53c43 100644 --- a/web/src/components/ChatPrompt.vue +++ b/web/src/components/ChatPrompt.vue @@ -9,7 +9,7 @@
diff --git a/web/src/components/ChatReply.vue b/web/src/components/ChatReply.vue index 2aed7e5b..752282dc 100644 --- a/web/src/components/ChatReply.vue +++ b/web/src/components/ChatReply.vue @@ -9,7 +9,7 @@ +