diff --git a/api/app/init.go b/api/app/init.go index 67a2f48..30ba67c 100644 --- a/api/app/init.go +++ b/api/app/init.go @@ -21,5 +21,5 @@ func init() { crud.All(appRouter.SubRouter("resource"), cfg.DB, models.Resource{}) crud.All(appRouter.SubRouter("user"), cfg.DB, models.AppUser{}) crud.All(appRouter.SubRouter("role"), cfg.DB, models.Role{}) - crud.All(Router.SubRouter("access"), cfg.DB, models.Access{}) + crud.All(appRouter.SubRouter("access"), cfg.DB, models.Access{}) } diff --git a/api/init.go b/api/init.go index 1832fce..c8f5ff7 100644 --- a/api/init.go +++ b/api/init.go @@ -8,8 +8,6 @@ package api import ( - "fmt" - "github.com/veypi/OneAuth/api/app" "github.com/veypi/OneAuth/api/token" "github.com/veypi/OneAuth/api/user" @@ -26,5 +24,5 @@ var ( ) var _ = Router.Any("*", func(x *vigo.X) error { - return fmt.Errorf("404") + return vigo.ErrNotFound }) diff --git a/api/user/init.go b/api/user/init.go index 3703e35..6b3414c 100644 --- a/api/user/init.go +++ b/api/user/init.go @@ -8,12 +8,15 @@ package user import ( - "github.com/veypi/OneAuth/api/user/role" + "github.com/veypi/OneAuth/cfg" + "github.com/veypi/OneAuth/models" "github.com/vyes/vigo" + "github.com/vyes/vigo/contrib/crud" ) var Router = vigo.NewRouter() -var ( - _ = Router.Extend("/:user_id/user_role", role.Router) -) +func init() { + crud.All(Router.SubRouter("/:user_id/user_role"), cfg.DB, models.UserRole{}) + +} diff --git a/api/user/user.go b/api/user/user.go index 268f962..6992b62 100644 --- a/api/user/user.go +++ b/api/user/user.go @@ -5,6 +5,7 @@ import ( "github.com/veypi/OneAuth/libs/auth" "github.com/veypi/OneAuth/models" "github.com/vyes/vigo" + "github.com/vyes/vigo/contrib/crud" ) var _ = Router.Delete("/:user_id", auth.Check("user", "user_id", auth.DoDelete), userDelete) @@ -34,7 +35,7 @@ func userGet(x *vigo.X) (any, error) { return data, err } -var _ = Router.Get("/", "list user", listOpts{}, auth.Check("user", "", auth.DoRead), userList) +var _ = Router.Get("/", "list user", listOpts{}, auth.Check("user", "", auth.DoUpdate), crud.List(cfg.DB, &models.User{})) type listOpts struct { Username *string `json:"username" parse:"query"` diff --git a/models/app.go b/models/app.go index bb05694..cdd00cc 100644 --- a/models/app.go +++ b/models/app.go @@ -69,10 +69,10 @@ func (m *AppUser) AfterUpdate(tx *gorm.DB) error { type Resource struct { BaseModel - AppID string `json:"app_id" methods:"*list,post" parse:"path"` + AppID string `json:"app_id" parse:"path@app_id"` App *App `json:"-" gorm:"foreignKey:AppID;references:ID"` - Name string `json:"name" methods:"post" parse:"json"` - Des string `json:"des" methods:"post,*patch" parse:"json"` + Name string `json:"name" parse:"json"` + Des string `json:"des" parse:"json"` } type Role struct { @@ -87,20 +87,19 @@ type Role struct { type Access struct { BaseModel - AppID string `json:"app_id" gorm:"index;type:varchar(32)" methods:"post,list" parse:"json"` + AppID string `json:"app_id" gorm:"index;type:varchar(32)" parse:"path@app_id"` App *App `json:"-" gorm:"foreignKey:AppID;references:ID"` - UserID *string `json:"user_id" gorm:"index;type:varchar(32);default: null" methods:"post,list" parse:"json"` + UserID *string `json:"user_id" gorm:"index;type:varchar(32);default: null" parse:"json"` User *User `json:"-" gorm:"foreignKey:UserID;references:ID"` - RoleID *string `json:"role_id" gorm:"index;type:varchar(32);default: null" methods:"post,list" parse:"json"` + RoleID *string `json:"role_id" gorm:"index;type:varchar(32);default: null" parse:"json"` Role *Role `json:"-" gorm:"foreignKey:RoleID;references:ID"` - ResourceID *string `json:"resource_id" gorm:"index;type:varchar(32);default: null" methods:"post,list" parse:"json"` + ResourceID *string `json:"resource_id" gorm:"index;type:varchar(32);default: null" parse:"json"` Resource *Resource `json:"-" gorm:"foreignKey:ResourceID;references:ID"` - Name string `json:"name" methods:"post,*list" parse:"json"` - - TID string `json:"tid" methods:"post,*patch" parse:"json"` - Level uint `json:"level" methods:"post,*patch" parse:"json"` + Name string `json:"name" parse:"json"` + TID string `json:"tid" parse:"json"` + Level uint `json:"level" parse:"json"` } diff --git a/models/user.go b/models/user.go index 81271d9..a29281f 100644 --- a/models/user.go +++ b/models/user.go @@ -24,16 +24,16 @@ type User struct { type UserRole struct { BaseModel - UserID string `json:"user_id" methods:"*list,post" parse:"path"` + UserID string `json:"user_id" parse:"path@user_id"` User *User `json:"-" gorm:"foreignKey:UserID;references:ID"` - RoleID string `json:"role_id" methods:"*list,post" parse:"json"` + RoleID string `json:"role_id" parse:"json"` Role *Role `json:"-" gorm:"foreignKey:RoleID;references:ID"` - AppID string `json:"app_id" methods:"*list,post" parse:"json"` + AppID string `json:"app_id" parse:"json"` App *App `json:"-" gorm:"foreignKey:AppID;references:ID"` - Status string `json:"status" methods:"post,*patch,*list, *go@get@/go" parse:"json@ssss"` + Status string `json:"status"` } func (m *UserRole) AfterCreate(tx *gorm.DB) error { diff --git a/ui/assets/common.css b/ui/assets/common.css index b01dcfa..b86d577 100644 --- a/ui/assets/common.css +++ b/ui/assets/common.css @@ -167,16 +167,6 @@ line-height: 1.6; } - a { - color: var(--color-link); - text-decoration: none; - transition: var(--transition); - } - - a:hover { - color: var(--color-link-hover); - text-decoration: underline; - } hr { border: 0; @@ -278,9 +268,7 @@ input[type="number"], textarea { border: 1px solid var(--color-border); - padding: 8px 12px; border-radius: 4px; - background-color: white; color: var(--text-color); transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out; } diff --git a/ui/c/app/menu.html b/ui/c/app/menu.html index a5799d9..cb354b9 100644 --- a/ui/c/app/menu.html +++ b/ui/c/app/menu.html @@ -1,33 +1,10 @@ - - - - - - diff --git a/ui/c/table.html b/ui/c/table.html index 29046f9..04a2e94 100644 --- a/ui/c/table.html +++ b/ui/c/table.html @@ -1,630 +1,260 @@ - + - - - - 多字段表格管理界面 - - - - -
-

客户信息管理

+ - const backdrop = modal.querySelector('.modal-backdrop') || modal; - const content = modal.querySelector('.modal-content'); - backdrop.style.opacity = '0'; - if (content) content.style.transform = 'scale(0.95)'; - - setTimeout(() => { - modal.classList.add('hidden'); - modal.classList.remove('flex'); - - if (!document.querySelector('.modal-backdrop:not(.hidden)')) { - document.body.style.overflow = 'auto'; - } - }, 300); - }; - - saveRecord = () => { - if (isEditMode) { - const index = records.findIndex((record) => record.id === currentRecord.id); - records[index] = { ...currentRecord }; + +
+
+
{{key.label||key.name}}
+
+ +
+
+
+ {{ (key.field?key.field(row):row[key.name]) || ' '}} +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+ +
+
+
+
+
+
+
+
+
+ +
+
{{listOpts.page}}
+
+
总计{{total}}条数据
+
+
+
+ + + + + +
+ +
智能识别
+
+
+
+ + - + let data = await $data.next(listOpts) + if (Array.isArray(data)) { + $data.data = data + } else { + $data.data = data.items + $data.total = data.total + } + } else if (mode === 1) { + await update(props) + props._enable = false + } else if (mode === 2) { + let res = await create(props) + showFlag = false + $data.data.push(res) + } else if (mode == 3) { + await del(props) + $data.data = $data.data.filter((d) => d.id !== data.id) + } + showFlag = false + } catch (e) { + $data.onerr(e) + } + console.log('done') + } + onerr = (e) => { + console.error(e) + } + + + diff --git a/ui/env.js b/ui/env.js new file mode 100644 index 0000000..d094067 --- /dev/null +++ b/ui/env.js @@ -0,0 +1,34 @@ +import routes from './routes.js' +import token from './token.js' + +export default ($env) => { + console.log($env, $vyes.root) + token.setBaseUrl($env.root) + token.wrapAxios($env.$axios) + $env.$global.token = token + $env.$global.user = token.body() + + + $env.$router.addRoutes(routes) + $env.$router.beforeEnter = async (to, from, next) => { + if (to.meta && to.meta.auth) { + if (token.isExpired()) { + await token.refresh() + } + if (token.isExpired()) { + token.logout(to.path) + } + } else { + next(); + } + }; + $env.$axios.interceptors.response.use(function(response) { + if (response?.data) { + return response.data + } + return response; + }, function(error) { + let data = error.response ? error.response.data : error.response + return Promise.reject(data.message || data); + }); +} diff --git a/ui/layout/app.html b/ui/layout/app.html new file mode 100644 index 0000000..60498d9 --- /dev/null +++ b/ui/layout/app.html @@ -0,0 +1,120 @@ + + + + + Auth Layout + + + + +
+
+
+ 首页 +
+ 应用权限管理 + +
+ +
+ + + +
+ Copyright © 2025 veypi. All Rights Reserved.. +
+
+ + + + diff --git a/ui/layout/default.html b/ui/layout/default.html index 5506a62..d6adab4 100644 --- a/ui/layout/default.html +++ b/ui/layout/default.html @@ -35,25 +35,26 @@ .menu { width: 200px; - background: #f5f5f5; border-right: 1px solid #ddd; padding: 20px 0; } - .menu-item { + .menu a { padding: 10px 20px; cursor: pointer; transition: background 0.3s; + display: block; + color: inherit; + text-decoration: none; } - .menu-item:hover { + .menu a:hover { background: #e0e0e0; } - .menu-item a { - display: block; - color: inherit; - text-decoration: none; + + .menu a[active] { + background: #409EFF; } .content { @@ -90,15 +91,9 @@
- - - + 应用管理 + 个人中心 + 系统设置 diff --git a/ui/page/app.html b/ui/page/app.html index 05635b5..28046b9 100644 --- a/ui/page/app.html +++ b/ui/page/app.html @@ -256,68 +256,66 @@ -
-
-

权限应用管理

-
- - - - -
-
- -
- -
-
-
-

加载中...

-
-
- 没有找到任何应用 -
-
-
-
- -
-
-

{{ app.name }}{{app.cid}}

- - {{ app.status }} - -
+
+
+
+
-
-

{{ app.des || '暂无描述信息' }}

-
- 类型: {{ app.typ || 'N/A' }} - 用户数量: {{ app.user_count }} -
+
+

{{ app.name }}{{app.cid}}

+ + {{ app.status }} +
- +
+

{{ app.des || '暂无描述信息' }}

+
+ 类型: {{ app.typ || 'N/A' }} + 用户数量: {{ app.user_count }} +
+
+
-
-
+
+ diff --git a/ui/page/app/index.html b/ui/page/app/index.html index d8279df..ff2619e 100644 --- a/ui/page/app/index.html +++ b/ui/page/app/index.html @@ -161,7 +161,6 @@ -
@@ -223,11 +222,11 @@
创建于
-
{{formatDate(app.created_at) || 'N/A'}}
+
最后更新
-
{{formatDate(app.updated_at) || 'N/A'}}
+
@@ -252,7 +251,7 @@ } id = $router.params.id if (!id) { - $router.back() + $router.push('/app') return } @@ -281,7 +280,7 @@ }) .catch((e) => { console.log(e) - history.back() + $router.push('/app') }) } sync() diff --git a/ui/page/app/user.html b/ui/page/app/user.html index f1c1103..c3b9d3a 100644 --- a/ui/page/app/user.html +++ b/ui/page/app/user.html @@ -28,29 +28,26 @@ -
应用用户管理
- - 权限表 + + 权限表
{{selected.username}} 角色表
- +
diff --git a/ui/page/login.html b/ui/page/login.html index 853096b..cf35da1 100644 --- a/ui/page/login.html +++ b/ui/page/login.html @@ -327,7 +327,8 @@ +
+ + + +
+ +
+ + +
+ +
+ + +
+ + - +
{{ errorMessage }}
+
{{ successMessage }}
+ + + + diff --git a/ui/root.html b/ui/root.html index 23f3bc9..ff98786 100644 --- a/ui/root.html +++ b/ui/root.html @@ -5,53 +5,16 @@ oa + - - + + - diff --git a/ui/routes.js b/ui/routes.js index b94f4ff..c456114 100644 --- a/ui/routes.js +++ b/ui/routes.js @@ -10,9 +10,14 @@ const routes = [ { path: '/login', component: '/page/login.html', name: 'login', meta: { auth: false } }, { path: '/profile', component: '/page/profile.html', name: 'profile', meta: { auth: true } }, { path: '/app', component: '/page/app.html', name: 'app', meta: { auth: true } }, + { path: '/settings', component: '/page/settings.html', name: 'settings', meta: { auth: true } }, { - path: '/app/:app_id', children: [ - { path: '/', component: '/page/app/index.html', name: 'app_index', meta: { auth: true } }, + path: '/app/:id', layout: 'app', meta: { auth: true }, + children: [ + { path: '/', component: '/page/app/index.html' }, + { path: '/user', component: '/page/app/user.html' }, + { path: '/auth', component: '/page/app/auth.html' }, + { path: '/settings', component: '/page/app/settings.html' }, ] }, { path: '*', component: '/page/404.html', name: '404' }, diff --git a/ui/token.js b/ui/token.js index 4fbeb42..914a61e 100644 --- a/ui/token.js +++ b/ui/token.js @@ -6,13 +6,13 @@ */ class TokenService { - __root = '' + #url = '/' constructor() { this.tokenKey = 'access'; this.refreshTokenKey = 'refresh'; } - setRoot(root) { - this.__root = root; + setBaseUrl(url) { + this.#url = url; } setToken(token) { @@ -71,7 +71,9 @@ class TokenService { } logout(to) { this.clearToken(); - location.href = this.__root + '/login?redirect=' + (to || window.location.pathname); + let url = this.#url + '/login'; + url += '?redirect=' + location.href = url + (to || window.location.pathname); } async refresh() { @@ -81,17 +83,13 @@ class TokenService { return; } try { - let data = await fetch(this.__root + '/api/token', { + let data = await fetch(this.#url + '/api/token', { method: 'post', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ refresh: refreshToken }) }).then(res => res.json()) this.__cache = null; // 清除缓存 - if (data.code === 0) { - this.setToken(data.data); - } else { - this.clearToken() - } + this.setToken(data); } catch (e) { console.error('Token刷新失败:', e); this.clearToken()