Merge branch 'main' into husm_2024-09-02

This commit is contained in:
胡双明 2024-09-13 10:25:15 +08:00
commit db90131bd6
26 changed files with 361 additions and 40 deletions

View File

@ -1,6 +1,7 @@
# 更新日志 # 更新日志
## v4.1.4 ## v4.1.4
* 功能优化:用户文件列表组件增加分页功能支持 * 功能优化:用户文件列表组件增加分页功能支持
* Bug修复修复用户注册失败Bug注册操作只弹出一次行为验证码
## v4.1.3 ## v4.1.3
* 功能优化:重构用户登录模块,给所有的登录组件增加行为验证码功能,支持用户绑定手机,邮箱和微信 * 功能优化:重构用户登录模块,给所有的登录组件增加行为验证码功能,支持用户绑定手机,邮箱和微信

View File

@ -204,7 +204,8 @@ func needLogin(c *gin.Context) bool {
c.Request.URL.Path == "/api/chat/history" || c.Request.URL.Path == "/api/chat/history" ||
c.Request.URL.Path == "/api/chat/detail" || c.Request.URL.Path == "/api/chat/detail" ||
c.Request.URL.Path == "/api/chat/list" || c.Request.URL.Path == "/api/chat/list" ||
c.Request.URL.Path == "/api/role/list" || c.Request.URL.Path == "/api/app/list" ||
c.Request.URL.Path == "/api/app/list/user" ||
c.Request.URL.Path == "/api/model/list" || c.Request.URL.Path == "/api/model/list" ||
c.Request.URL.Path == "/api/mj/imgWall" || c.Request.URL.Path == "/api/mj/imgWall" ||
c.Request.URL.Path == "/api/mj/client" || c.Request.URL.Path == "/api/mj/client" ||

View File

@ -74,7 +74,6 @@ func (h *ApiKeyHandler) Save(c *gin.Context) {
func (h *ApiKeyHandler) List(c *gin.Context) { func (h *ApiKeyHandler) List(c *gin.Context) {
status := h.GetBool(c, "status") status := h.GetBool(c, "status")
t := h.GetTrim(c, "type") t := h.GetTrim(c, "type")
platform := h.GetTrim(c, "platform")
session := h.DB.Session(&gorm.Session{}) session := h.DB.Session(&gorm.Session{})
if status { if status {
@ -83,9 +82,6 @@ func (h *ApiKeyHandler) List(c *gin.Context) {
if t != "" { if t != "" {
session = session.Where("type", t) session = session.Where("type", t)
} }
if platform != "" {
session = session.Where("platform", platform)
}
var items []model.ApiKey var items []model.ApiKey
var keys = make([]vo.ApiKey, 0) var keys = make([]vo.ApiKey, 0)

View File

@ -22,16 +22,16 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
) )
type ChatRoleHandler struct { type ChatAppHandler struct {
handler.BaseHandler handler.BaseHandler
} }
func NewChatRoleHandler(app *core.AppServer, db *gorm.DB) *ChatRoleHandler { func NewChatAppHandler(app *core.AppServer, db *gorm.DB) *ChatAppHandler {
return &ChatRoleHandler{BaseHandler: handler.BaseHandler{App: app, DB: db}} return &ChatAppHandler{BaseHandler: handler.BaseHandler{App: app, DB: db}}
} }
// Save 创建或者更新某个角色 // Save 创建或者更新某个角色
func (h *ChatRoleHandler) Save(c *gin.Context) { func (h *ChatAppHandler) Save(c *gin.Context) {
var data vo.ChatRole var data vo.ChatRole
if err := c.ShouldBindJSON(&data); err != nil { if err := c.ShouldBindJSON(&data); err != nil {
resp.ERROR(c, types.InvalidArgs) resp.ERROR(c, types.InvalidArgs)
@ -64,7 +64,7 @@ func (h *ChatRoleHandler) Save(c *gin.Context) {
resp.SUCCESS(c, data) resp.SUCCESS(c, data)
} }
func (h *ChatRoleHandler) List(c *gin.Context) { func (h *ChatAppHandler) List(c *gin.Context) {
var items []model.ChatRole var items []model.ChatRole
var roles = make([]vo.ChatRole, 0) var roles = make([]vo.ChatRole, 0)
res := h.DB.Order("sort_num ASC").Find(&items) res := h.DB.Order("sort_num ASC").Find(&items)
@ -108,7 +108,7 @@ func (h *ChatRoleHandler) List(c *gin.Context) {
} }
// Sort 更新角色排序 // Sort 更新角色排序
func (h *ChatRoleHandler) Sort(c *gin.Context) { func (h *ChatAppHandler) Sort(c *gin.Context) {
var data struct { var data struct {
Ids []uint `json:"ids"` Ids []uint `json:"ids"`
Sorts []int `json:"sorts"` Sorts []int `json:"sorts"`
@ -130,7 +130,7 @@ func (h *ChatRoleHandler) Sort(c *gin.Context) {
resp.SUCCESS(c) resp.SUCCESS(c)
} }
func (h *ChatRoleHandler) Set(c *gin.Context) { func (h *ChatAppHandler) Set(c *gin.Context) {
var data struct { var data struct {
Id uint `json:"id"` Id uint `json:"id"`
Filed string `json:"filed"` Filed string `json:"filed"`
@ -150,7 +150,7 @@ func (h *ChatRoleHandler) Set(c *gin.Context) {
resp.SUCCESS(c) resp.SUCCESS(c)
} }
func (h *ChatRoleHandler) Remove(c *gin.Context) { func (h *ChatAppHandler) Remove(c *gin.Context) {
id := h.GetInt(c, "id", 0) id := h.GetInt(c, "id", 0)
if id <= 0 { if id <= 0 {

View File

@ -0,0 +1,148 @@
package admin
import (
"geekai/core"
"geekai/core/types"
"geekai/handler"
"geekai/store/model"
"geekai/store/vo"
"geekai/utils"
"geekai/utils/resp"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type ChatAppTypeHandler struct {
handler.BaseHandler
}
func NewChatAppTypeHandler(app *core.AppServer, db *gorm.DB) *ChatAppTypeHandler {
return &ChatAppTypeHandler{BaseHandler: handler.BaseHandler{App: app, DB: db}}
}
// Save 创建或更新App类型
func (h *ChatAppTypeHandler) Save(c *gin.Context) {
var data struct {
Id uint `json:"id"`
Name string `json:"name"`
Enable bool `json:"enable"`
Icon string `json:"icon"`
SortNum int `json:"sort_num"`
}
if err := c.ShouldBindJSON(&data); err != nil {
resp.ERROR(c, types.InvalidArgs)
return
}
if data.Id == 0 { // for add
err := h.DB.Where("name", data.Name).First(&model.AppType{}).Error
if err == nil {
resp.ERROR(c, "当前分类已经存在")
return
}
err = h.DB.Create(&model.AppType{
Name: data.Name,
Icon: data.Icon,
Enabled: data.Enable,
SortNum: data.SortNum,
}).Error
if err != nil {
resp.ERROR(c, err.Error())
return
}
} else { // for update
err := h.DB.Model(&model.AppType{}).Where("id", data.Id).Updates(map[string]interface{}{
"name": data.Name,
"icon": data.Icon,
"enabled": data.Enable,
}).Error
if err != nil {
resp.ERROR(c, err.Error())
return
}
}
resp.SUCCESS(c)
}
// List 获取App类型列表
func (h *ChatAppTypeHandler) List(c *gin.Context) {
var items []model.AppType
var appTypes = make([]vo.AppType, 0)
err := h.DB.Order("sort_num ASC").Find(&items).Error
if err != nil {
resp.ERROR(c, err.Error())
return
}
for _, v := range items {
var appType vo.AppType
err = utils.CopyObject(v, &appType)
if err != nil {
continue
}
appType.Id = v.Id
appType.CreatedAt = v.CreatedAt.Unix()
appTypes = append(appTypes, appType)
}
resp.SUCCESS(c, appTypes)
}
// Remove 删除App类型
func (h *ChatAppTypeHandler) Remove(c *gin.Context) {
id := h.GetInt(c, "id", 0)
if id <= 0 {
resp.ERROR(c, types.InvalidArgs)
return
}
err := h.DB.Where("id", id).Delete(&model.AppType{}).Error
if err != nil {
resp.ERROR(c, err.Error())
return
}
resp.SUCCESS(c)
}
// Enable 启用|禁用
func (h *ChatAppTypeHandler) Enable(c *gin.Context) {
var data struct {
Id uint `json:"id"`
Enabled bool `json:"enabled"`
}
if err := c.ShouldBindJSON(&data); err != nil {
resp.ERROR(c, types.InvalidArgs)
return
}
err := h.DB.Model(&model.AppType{}).Where("id", data.Id).UpdateColumn("enabled", data.Enabled).Error
if err != nil {
resp.ERROR(c, err.Error())
return
}
resp.SUCCESS(c)
}
// Sort 更新排序
func (h *ChatAppTypeHandler) Sort(c *gin.Context) {
var data struct {
Ids []uint `json:"ids"`
Sorts []int `json:"sorts"`
}
if err := c.ShouldBindJSON(&data); err != nil {
resp.ERROR(c, types.InvalidArgs)
return
}
for index, id := range data.Ids {
err := h.DB.Model(&model.AppType{}).Where("id", id).Update("sort_num", data.Sorts[index]).Error
if err != nil {
resp.ERROR(c, err.Error())
return
}
}
resp.SUCCESS(c)
}

View File

@ -73,6 +73,8 @@ func (h *UserHandler) Save(c *gin.Context) {
Id uint `json:"id"` Id uint `json:"id"`
Password string `json:"password"` Password string `json:"password"`
Username string `json:"username"` Username string `json:"username"`
Mobile string `json:"mobile"`
Email string `json:"email"`
ChatRoles []string `json:"chat_roles"` ChatRoles []string `json:"chat_roles"`
ChatModels []int `json:"chat_models"` ChatModels []int `json:"chat_models"`
ExpiredTime string `json:"expired_time"` ExpiredTime string `json:"expired_time"`
@ -102,6 +104,8 @@ func (h *UserHandler) Save(c *gin.Context) {
} }
var oldPower = user.Power var oldPower = user.Power
user.Username = data.Username user.Username = data.Username
user.Email = data.Email
user.Mobile = data.Mobile
user.Status = data.Status user.Status = data.Status
user.Vip = data.Vip user.Vip = data.Vip
user.Power = data.Power user.Power = data.Power
@ -109,7 +113,8 @@ func (h *UserHandler) Save(c *gin.Context) {
user.ChatModels = utils.JsonEncode(data.ChatModels) user.ChatModels = utils.JsonEncode(data.ChatModels)
user.ExpiredTime = utils.Str2stamp(data.ExpiredTime) user.ExpiredTime = utils.Str2stamp(data.ExpiredTime)
res = h.DB.Select("username", "status", "vip", "power", "chat_roles_json", "chat_models_json", "expired_time").Updates(&user) res = h.DB.Select("username", "mobile", "email", "status", "vip", "power", "chat_roles_json", "chat_models_json", "expired_time").Updates(&user)
if res.Error != nil { if res.Error != nil {
logger.Error("error with update database", res.Error) logger.Error("error with update database", res.Error)
resp.ERROR(c, res.Error.Error()) resp.ERROR(c, res.Error.Error())
@ -147,6 +152,8 @@ func (h *UserHandler) Save(c *gin.Context) {
u := model.User{ u := model.User{
Username: data.Username, Username: data.Username,
Password: utils.GenPassword(data.Password, salt), Password: utils.GenPassword(data.Password, salt),
Mobile: data.Mobile,
Email: data.Email,
Avatar: "/images/avatar/user.png", Avatar: "/images/avatar/user.png",
Salt: salt, Salt: salt,
Power: data.Power, Power: data.Power,

View File

@ -0,0 +1,43 @@
package handler
import (
"geekai/core"
"geekai/store/model"
"geekai/store/vo"
"geekai/utils"
"geekai/utils/resp"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type ChatAppTypeHandler struct {
BaseHandler
}
func NewChatAppTypeHandler(app *core.AppServer, db *gorm.DB) *ChatAppTypeHandler {
return &ChatAppTypeHandler{BaseHandler: BaseHandler{App: app, DB: db}}
}
// List 获取App类型列表
func (h *ChatAppTypeHandler) List(c *gin.Context) {
var items []model.AppType
var appTypes = make([]vo.AppType, 0)
err := h.DB.Order("sort_num ASC").Find(&items).Error
if err != nil {
resp.ERROR(c, err.Error())
return
}
for _, v := range items {
var appType vo.AppType
err = utils.CopyObject(v, &appType)
if err != nil {
continue
}
appType.Id = v.Id
appType.CreatedAt = v.CreatedAt.Unix()
appTypes = append(appTypes, appType)
}
resp.SUCCESS(c, appTypes)
}

View File

@ -29,10 +29,37 @@ func NewChatRoleHandler(app *core.AppServer, db *gorm.DB) *ChatRoleHandler {
// List 获取用户聊天应用列表 // List 获取用户聊天应用列表
func (h *ChatRoleHandler) List(c *gin.Context) { func (h *ChatRoleHandler) List(c *gin.Context) {
tid := h.GetInt(c, "tid", 0)
var roles []model.ChatRole
session := h.DB.Where("enable", true)
if tid > 0 {
session = session.Where("tid", tid)
}
err := session.Order("sort_num ASC").Find(&roles).Error
if err != nil {
resp.ERROR(c, err.Error())
return
}
var roleVos = make([]vo.ChatRole, 0)
for _, r := range roles {
var v vo.ChatRole
err := utils.CopyObject(r, &v)
if err == nil {
v.Id = r.Id
roleVos = append(roleVos, v)
}
}
resp.SUCCESS(c, roleVos)
}
// ListByUser 获取用户添加的角色列表
func (h *ChatRoleHandler) ListByUser(c *gin.Context) {
id := h.GetInt(c, "id", 0) id := h.GetInt(c, "id", 0)
userId := h.GetLoginUserId(c) userId := h.GetLoginUserId(c)
var roles []model.ChatRole var roles []model.ChatRole
query := h.DB.Where("enable", true) session := h.DB.Where("enable", true)
// 如果用户没登录,则获取所有角色
if userId > 0 { if userId > 0 {
var user model.User var user model.User
h.DB.First(&user, userId) h.DB.First(&user, userId)
@ -42,12 +69,13 @@ func (h *ChatRoleHandler) List(c *gin.Context) {
resp.ERROR(c, "角色解析失败!") resp.ERROR(c, "角色解析失败!")
return return
} }
query = query.Where("marker IN ?", roleKeys) session = session.Where("marker IN ?", roleKeys)
} }
if id > 0 { if id > 0 {
query = query.Or("id", id) session = session.Or("id", id)
} }
res := h.DB.Where("enable", true).Order("sort_num ASC").Find(&roles) res := session.Order("sort_num ASC").Find(&roles)
if res.Error != nil { if res.Error != nil {
resp.ERROR(c, res.Error.Error()) resp.ERROR(c, res.Error.Error())
return return

View File

@ -74,6 +74,20 @@ func (h *UserHandler) Register(c *gin.Context) {
resp.ERROR(c, types.InvalidArgs) resp.ERROR(c, types.InvalidArgs)
return return
} }
if h.App.SysConfig.EnabledVerify && data.RegWay == "username" {
var check bool
if data.X != 0 {
check = h.captcha.SlideCheck(data)
} else {
check = h.captcha.Check(data)
}
if !check {
resp.ERROR(c, "请先完人机验证")
return
}
}
data.Password = strings.TrimSpace(data.Password) data.Password = strings.TrimSpace(data.Password)
if len(data.Password) < 8 { if len(data.Password) < 8 {
resp.ERROR(c, "密码长度不能少于8个字符") resp.ERROR(c, "密码长度不能少于8个字符")
@ -587,7 +601,7 @@ func (h *UserHandler) ResetPass(c *gin.Context) {
session = session.Where("email", data.Email) session = session.Where("email", data.Email)
key = CodeStorePrefix + data.Email key = CodeStorePrefix + data.Email
} else if data.Type == "mobile" { } else if data.Type == "mobile" {
session = session.Where("mobile", data.Email) session = session.Where("mobile", data.Mobile)
key = CodeStorePrefix + data.Mobile key = CodeStorePrefix + data.Mobile
} else { } else {
resp.ERROR(c, "验证类别错误") resp.ERROR(c, "验证类别错误")

View File

@ -146,7 +146,7 @@ func main() {
fx.Provide(admin.NewAdminHandler), fx.Provide(admin.NewAdminHandler),
fx.Provide(admin.NewApiKeyHandler), fx.Provide(admin.NewApiKeyHandler),
fx.Provide(admin.NewUserHandler), fx.Provide(admin.NewUserHandler),
fx.Provide(admin.NewChatRoleHandler), fx.Provide(admin.NewChatAppHandler),
fx.Provide(admin.NewRedeemHandler), fx.Provide(admin.NewRedeemHandler),
fx.Provide(admin.NewDashboardHandler), fx.Provide(admin.NewDashboardHandler),
fx.Provide(admin.NewChatModelHandler), fx.Provide(admin.NewChatModelHandler),
@ -226,8 +226,9 @@ func main() {
// 注册路由 // 注册路由
fx.Invoke(func(s *core.AppServer, h *handler.ChatRoleHandler) { fx.Invoke(func(s *core.AppServer, h *handler.ChatRoleHandler) {
group := s.Engine.Group("/api/role/") group := s.Engine.Group("/api/app/")
group.GET("list", h.List) group.GET("list", h.List)
group.GET("list/user", h.ListByUser)
group.POST("update", h.UpdateRole) group.POST("update", h.UpdateRole)
}), }),
fx.Invoke(func(s *core.AppServer, h *handler.UserHandler) { fx.Invoke(func(s *core.AppServer, h *handler.UserHandler) {
@ -338,7 +339,7 @@ func main() {
group.GET("loginLog", h.LoginLog) group.GET("loginLog", h.LoginLog)
group.POST("resetPass", h.ResetPass) group.POST("resetPass", h.ResetPass)
}), }),
fx.Invoke(func(s *core.AppServer, h *admin.ChatRoleHandler) { fx.Invoke(func(s *core.AppServer, h *admin.ChatAppHandler) {
group := s.Engine.Group("/api/admin/role/") group := s.Engine.Group("/api/admin/role/")
group.GET("list", h.List) group.GET("list", h.List)
group.POST("save", h.Save) group.POST("save", h.Save)
@ -502,6 +503,15 @@ func main() {
group.GET("remove", h.Remove) group.GET("remove", h.Remove)
group.GET("publish", h.Publish) group.GET("publish", h.Publish)
}), }),
fx.Provide(admin.NewChatAppTypeHandler),
fx.Invoke(func(s *core.AppServer, h *admin.ChatAppTypeHandler) {
group := s.Engine.Group("/api/admin/app/type")
group.POST("save", h.Save)
group.GET("list", h.List)
group.GET("remove", h.Remove)
group.POST("enable", h.Enable)
group.POST("sort", h.Sort)
}),
fx.Provide(handler.NewTestHandler), fx.Provide(handler.NewTestHandler),
fx.Invoke(func(s *core.AppServer, h *handler.TestHandler) { fx.Invoke(func(s *core.AppServer, h *handler.TestHandler) {
group := s.Engine.Group("/api/test") group := s.Engine.Group("/api/test")

View File

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

View File

@ -0,0 +1,12 @@
package model
import "time"
type AppType struct {
Id uint `gorm:"primarykey"`
Name string
Icon string
Enabled bool
SortNum int
CreatedAt time.Time
}

10
api/store/vo/app_type.go Normal file
View File

@ -0,0 +1,10 @@
package vo
type AppType struct {
Id uint `json:"id"`
Name string `json:"name"`
Icon string `json:"icon"`
SortNum int `json:"sort_num"`
Enabled bool `json:"enabled"`
CreatedAt int64 `json:"created_at"`
}

View File

@ -0,0 +1,12 @@
CREATE TABLE `chatgpt_app_types` (
`id` int NOT NULL,
`name` varchar(50) NOT NULL COMMENT '名称',
`icon` varchar(255) NOT NULL COMMENT '图标URL',
`sort_num` tinyint(3) NOT NULL COMMENT '排序',
`enabled` tinyint(1) NOT NULL COMMENT '是否启用',
`created_at` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='应用分类表';
ALTER TABLE `chatgpt_app_types`ADD PRIMARY KEY (`id`);
ALTER TABLE `chatgpt_app_types` MODIFY `id` int NOT NULL AUTO_INCREMENT;
ALTER TABLE `chatgpt_chat_roles` ADD `tid` INT NOT NULL COMMENT '分类ID' AFTER `name`;

View File

@ -384,7 +384,7 @@ const submitRegister = () => {
if ((activeName.value === 'mobile' || activeName.value === 'email') && data.value.code === '') { if ((activeName.value === 'mobile' || activeName.value === 'email') && data.value.code === '') {
return ElMessage.error('请输入验证码'); return ElMessage.error('请输入验证码');
} }
if (enableVerify.value) { if (enableVerify.value && activeName.value === 'username') {
captchaRef.value.loadCaptcha() captchaRef.value.loadCaptcha()
action.value = "register" action.value = "register"
} else { } else {

View File

@ -90,12 +90,22 @@ const items = [
index: '/admin/user', index: '/admin/user',
title: '用户管理', title: '用户管理',
}, },
{ {
icon: 'menu', icon: 'menu',
index: '/admin/app', index: '1',
title: '应用管理', title: '应用管理',
subs: [
{
index: '/admin/app',
title: '应用列表',
},
{
index: '/admin/app/type',
title: '应用分类',
},
],
}, },
{ {
icon: 'api-key', icon: 'api-key',
index: '/admin/apikey', index: '/admin/apikey',

View File

@ -173,6 +173,12 @@ const routes = [
meta: {title: '应用管理'}, meta: {title: '应用管理'},
component: () => import('@/views/admin/Apps.vue'), component: () => import('@/views/admin/Apps.vue'),
}, },
{
path: '/admin/app/type',
name: 'admin-app-type',
meta: {title: '应用管理'},
component: () => import('@/views/admin/AppType.vue'),
},
{ {
path: '/admin/apikey', path: '/admin/apikey',
name: 'admin-apikey', name: 'admin-apikey',

View File

@ -64,7 +64,6 @@ import {arrayContains, removeArrayItem, substr} from "@/utils/libs";
import {useRouter} from "vue-router"; import {useRouter} from "vue-router";
import {useSharedStore} from "@/store/sharedata"; import {useSharedStore} from "@/store/sharedata";
import ItemList from "@/components/ItemList.vue"; import ItemList from "@/components/ItemList.vue";
import {Plus} from "@element-plus/icons-vue";
const listBoxHeight = window.innerHeight - 87 const listBoxHeight = window.innerHeight - 87
const list = ref([]) const list = ref([])
@ -72,7 +71,7 @@ const roles = ref([])
const store = useSharedStore(); const store = useSharedStore();
onMounted(() => { onMounted(() => {
httpGet("/api/role/list").then((res) => { httpGet("/api/app/list").then((res) => {
const items = res.data const items = res.data
// hello message // hello message
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
@ -112,7 +111,7 @@ const updateRole = (row, opt) => {
} }
roles.value = removeArrayItem(roles.value, row.key) roles.value = removeArrayItem(roles.value, row.key)
} }
httpPost("/api/role/update", {keys: roles.value}).then(() => { httpPost("/api/app/update", {keys: roles.value}).then(() => {
ElMessage.success({message: title.value + "成功!", duration: 1000}) ElMessage.success({message: title.value + "成功!", duration: 1000})
}).catch(e => { }).catch(e => {
ElMessage.error(title.value + "失败:" + e.message) ElMessage.error(title.value + "失败:" + e.message)

View File

@ -364,7 +364,7 @@ const initData = () => {
modelID.value = models.value[0].id modelID.value = models.value[0].id
} }
// //
httpGet(`/api/role/list`,{id:roleId.value}).then((res) => { httpGet(`/api/app/list/user`,{id:roleId.value}).then((res) => {
roles.value = res.data; roles.value = res.data;
if (!roleId.value) { if (!roleId.value) {
roleId.value = roles.value[0]['id'] roleId.value = roles.value[0]['id']

View File

@ -16,7 +16,7 @@
<div class="block"> <div class="block">
<el-input placeholder="手机号码" <el-input placeholder="手机号码"
size="large" size="large"
v-model="data.username" v-model="data.mobile"
maxlength="11" maxlength="11"
autocomplete="off"> autocomplete="off">
<template #prefix> <template #prefix>
@ -41,7 +41,7 @@
</el-input> </el-input>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<send-msg size="large" :receiver="data.username" type="mobile"/> <send-msg size="large" :receiver="data.mobile" type="mobile"/>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
@ -195,6 +195,8 @@ const title = ref('');
const logo = ref("") const logo = ref("")
const data = ref({ const data = ref({
username: '', username: '',
mobile: '',
email: '',
password: '', password: '',
code: '', code: '',
repass: '', repass: '',
@ -250,15 +252,15 @@ getLicenseInfo().then(res => {
// //
const submitRegister = () => { const submitRegister = () => {
if (data.value.username === '') { if (activeName.value === 'username' && data.value.username === '') {
return showMessageError('请输入用户名'); return showMessageError('请输入用户名');
} }
if (activeName.value === 'mobile' && !validateMobile(data.value.username)) { if (activeName.value === 'mobile' && !validateMobile(data.value.mobile)) {
return showMessageError('请输入合法的手机号'); return showMessageError('请输入合法的手机号');
} }
if (activeName.value === 'email' && !validateEmail(data.value.username)) { if (activeName.value === 'email' && !validateEmail(data.value.email)) {
return showMessageError('请输入合法的邮箱地址'); return showMessageError('请输入合法的邮箱地址');
} }
@ -273,7 +275,8 @@ const submitRegister = () => {
return showMessageError('请输入验证码'); return showMessageError('请输入验证码');
} }
if (enableVerify.value) { //
if (enableVerify.value && activeName.value === 'username') {
captchaRef.value.loadCaptcha() captchaRef.value.loadCaptcha()
} else { } else {
doSubmitRegister({}) doSubmitRegister({})

View File

@ -0,0 +1,13 @@
<template>
<div class="container app-type" >
</div>
</template>
<script setup>
</script>
<style lang="stylus" scoped>
</style>

View File

@ -18,6 +18,8 @@
<el-image v-if="scope.row.vip" :src="vipImg" style="height: 20px;position: relative; top:5px; left: 5px"/> <el-image v-if="scope.row.vip" :src="vipImg" style="height: 20px;position: relative; top:5px; left: 5px"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="mobile" label="手机"/>
<el-table-column prop="email" label="邮箱"/>
<el-table-column prop="nickname" label="昵称"/> <el-table-column prop="nickname" label="昵称"/>
<el-table-column prop="power" label="剩余算力"/> <el-table-column prop="power" label="剩余算力"/>
<el-table-column label="状态" width="80"> <el-table-column label="状态" width="80">
@ -73,6 +75,12 @@
<el-form-item label="账号:" prop="username"> <el-form-item label="账号:" prop="username">
<el-input v-model="user.username" autocomplete="off"/> <el-input v-model="user.username" autocomplete="off"/>
</el-form-item> </el-form-item>
<el-form-item label="手机:" prop="mobile">
<el-input v-model="user.mobile" autocomplete="off"/>
</el-form-item>
<el-form-item label="邮箱:" prop="email">
<el-input v-model="user.email" autocomplete="off"/>
</el-form-item>
<el-form-item v-if="add" label="密码:" prop="password"> <el-form-item v-if="add" label="密码:" prop="password">
<el-input v-model="user.password" autocomplete="off" placeholder="8-16位"/> <el-input v-model="user.password" autocomplete="off" placeholder="8-16位"/>
</el-form-item> </el-form-item>

View File

@ -105,7 +105,7 @@ checkSession().then((user) => {
loginUser.value = user loginUser.value = user
isLogin.value = true isLogin.value = true
// //
httpGet(`/api/role/list`).then((res) => { httpGet(`/api/app/list/user`).then((res) => {
if (res.data) { if (res.data) {
const items = res.data const items = res.data
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
@ -139,7 +139,7 @@ checkSession().then((user) => {
finished.value = true finished.value = true
// //
httpGet('/api/role/list').then((res) => { httpGet('/api/app/list/user').then((res) => {
if (res.data) { if (res.data) {
const items = res.data const items = res.data
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {

View File

@ -186,7 +186,7 @@ httpGet('/api/model/list').then(res => {
} }
modelValue.value = getModelName(modelId.value) modelValue.value = getModelName(modelId.value)
// //
httpGet(`/api/role/list`).then((res) => { httpGet(`/api/app/list/user`).then((res) => {
roles.value = res.data; roles.value = res.data;
if (!roleId.value) { if (!roleId.value) {
roleId.value = roles.value[0]['id'] roleId.value = roles.value[0]['id']

View File

@ -109,7 +109,7 @@ onMounted(() => {
}) })
const fetchApps = () => { const fetchApps = () => {
httpGet("/api/role/list").then((res) => { httpGet("/api/app/list/user").then((res) => {
const items = res.data const items = res.data
// hello message // hello message
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {