From 36d55d1f1f2900bcb650bdc195fad50504ace235 Mon Sep 17 00:00:00 2001 From: veypi Date: Fri, 6 Oct 2023 22:53:57 +0800 Subject: [PATCH] update app home --- oab/Cargo.toml | 9 +++++ oab/proc/src/curd.rs | 0 oab/src/api/app.rs | 46 ++++++++++++++++----- oab/src/api/appuser.rs | 18 ++++++++- oab/src/api/mod.rs | 2 +- oab/src/libs/app.rs | 6 +++ oab/src/libs/mod.rs | 1 + oab/src/libs/user.rs | 13 +++++- oab/src/result.rs | 3 +- oab/src/test.rs | 8 ++++ oaweb/package.json | 5 ++- oaweb/quasar.config.js | 1 + oaweb/src/boot/api/app.ts | 2 +- oaweb/src/boot/pack.ts | 6 ++- oaweb/src/components/app.vue | 69 +++++++++++++++----------------- oaweb/src/layouts/AppLayout.vue | 55 +++++++++++++++++++++---- oaweb/src/layouts/MainLayout.vue | 28 ++++++++----- oaweb/src/pages/AppHome.vue | 44 +++++++++++++++++++- oaweb/src/pages/AppUser.vue | 17 ++++++++ oaweb/src/pages/IndexPage.vue | 11 +++-- oaweb/src/router/index.ts | 8 ++-- oaweb/src/router/routes.ts | 6 ++- oaweb/src/stores/menu.ts | 2 +- oaweb/src/stores/user.ts | 9 ++--- oaweb/yarn.lock | 17 ++++++++ 25 files changed, 295 insertions(+), 91 deletions(-) create mode 100644 oab/proc/src/curd.rs create mode 100644 oab/src/libs/app.rs create mode 100644 oab/src/test.rs create mode 100644 oaweb/src/pages/AppUser.vue diff --git a/oab/Cargo.toml b/oab/Cargo.toml index 0ad50e7..6bacd82 100644 --- a/oab/Cargo.toml +++ b/oab/Cargo.toml @@ -2,6 +2,15 @@ name = "oab" version = "0.1.0" edition = "2021" +default-run = "web" + +[[bin]] +name = "web" +path = "src/main.rs" + +[[bin]] +name = "test" +path = "src/test.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/oab/proc/src/curd.rs b/oab/proc/src/curd.rs new file mode 100644 index 0000000..e69de29 diff --git a/oab/src/api/app.rs b/oab/src/api/app.rs index 9b4923e..58f297a 100644 --- a/oab/src/api/app.rs +++ b/oab/src/api/app.rs @@ -5,8 +5,8 @@ // Distributed under terms of the Apache license. // // -use actix_web::{delete, get, post, web, Responder}; -use proc::{access_create, access_read}; +use actix_web::{delete, get, patch, post, put, web, Responder}; +use proc::{access_create, access_delete, access_read, access_update}; use sea_orm::{ActiveModelTrait, EntityTrait, TransactionTrait}; use serde::{Deserialize, Serialize}; use tracing::info; @@ -54,12 +54,6 @@ pub struct App { #[access_read("app")] pub async fn list(stat: web::Data) -> Result { let res = app::Entity::find().all(stat.db()).await?; - // let result = sqlx::query_as::<_,app::Model>( - // "select app.*,app_userstatus as status from app left join app_user on app_user.user_id = ? && app_user.app_id = app.id", - // ).bind(_auth_token.id) - // .fetch_all(stat.sqlx()) - // .await?; - Ok(web::Json(res)) } @@ -101,12 +95,46 @@ pub async fn create( level: sea_orm::ActiveValue::Set(AccessLevel::ALL as i32), ..Default::default() }; - let ac: access::Model = ac.insert(&db).await?; + ac.insert(&db).await?; libs::user::connect_to_app(t.id.clone(), obj.id.clone(), &db, Some(obj.clone())).await?; db.commit().await?; Ok(web::Json(obj)) } + +#[derive(Debug, Deserialize, Serialize)] +pub struct UpdateOpt { + name: Option, + icon: Option, + enable_register: Option, + des: Option, + host: Option, + redirect: Option, +} + +#[patch("/app/{id}")] +#[access_update("app")] +pub async fn update( + id: web::Path, + stat: web::Data, + data: web::Json, +) -> Result { + let data = data.into_inner(); + let id = id.into_inner(); + let obj = app::Entity::find_by_id(&id).one(stat.db()).await?; + let mut obj: app::ActiveModel = match obj { + Some(o) => o.into(), + None => return Err(Error::NotFound(id)), + }; + if let Some(name) = data.name { + obj.name = sea_orm::Set(name) + }; + + let obj = obj.update(stat.db()).await?; + Ok(web::Json(obj)) +} + #[delete("/app/{id}")] +#[access_delete("app")] pub async fn del(_id: web::Path) -> Result { Ok("") } diff --git a/oab/src/api/appuser.rs b/oab/src/api/appuser.rs index 46bd778..3a60ec9 100644 --- a/oab/src/api/appuser.rs +++ b/oab/src/api/appuser.rs @@ -5,11 +5,12 @@ // Distributed under terms of the MIT license. // -use actix_web::{get, web, Responder}; +use actix_web::{get, post, web, Responder}; use proc::access_read; -use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; +use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, TransactionTrait}; use crate::{ + libs, models::{app, app_user}, AppState, Error, Result, }; @@ -51,3 +52,16 @@ pub async fn get( Ok(web::Json(res)) } } + +#[post("/app/{aid}/user/{uid}")] +#[access_read("app")] +pub async fn add( + params: web::Path<(String, String)>, + stat: web::Data, +) -> Result { + let (aid, uid) = params.into_inner(); + let db = stat.db().begin().await?; + let res = libs::user::connect_to_app(uid, aid, &db, None).await?; + db.commit().await?; + Ok(web::Json(res)) +} diff --git a/oab/src/api/mod.rs b/oab/src/api/mod.rs index 49f3289..4e4b9c0 100644 --- a/oab/src/api/mod.rs +++ b/oab/src/api/mod.rs @@ -27,5 +27,5 @@ pub fn routes(cfg: &mut web::ServiceConfig) { .service(app::create) .service(app::del); - cfg.service(appuser::get); + cfg.service(appuser::get).service(appuser::add); } diff --git a/oab/src/libs/app.rs b/oab/src/libs/app.rs new file mode 100644 index 0000000..49d8a46 --- /dev/null +++ b/oab/src/libs/app.rs @@ -0,0 +1,6 @@ +// +// app.rs +// Copyright (C) 2023 veypi +// 2023-10-06 19:39 +// Distributed under terms of the MIT license. +// diff --git a/oab/src/libs/mod.rs b/oab/src/libs/mod.rs index f448e04..610e15e 100644 --- a/oab/src/libs/mod.rs +++ b/oab/src/libs/mod.rs @@ -9,3 +9,4 @@ pub mod auth; pub mod cors; pub mod fs; pub mod user; +pub mod app; diff --git a/oab/src/libs/user.rs b/oab/src/libs/user.rs index 509268c..33898e5 100644 --- a/oab/src/libs/user.rs +++ b/oab/src/libs/user.rs @@ -9,7 +9,9 @@ use crate::{ models::{self, app, app_user, user_role}, Error, Result, }; -use sea_orm::{ActiveModelTrait, ConnectionTrait, DatabaseTransaction, EntityTrait}; +use sea_orm::{ + ActiveModelTrait, ColumnTrait, ConnectionTrait, DatabaseTransaction, EntityTrait, QueryFilter, +}; // 尝试绑定应用 pub async fn connect_to_app( @@ -18,6 +20,15 @@ pub async fn connect_to_app( db: &DatabaseTransaction, app_obj: Option, ) -> Result { + match app_user::Entity::find() + .filter(app_user::Column::AppId.eq(&aid)) + .filter(app_user::Column::UserId.eq(&uid)) + .one(db) + .await? + { + Some(au) => return Ok(au), + None => {} + }; let app_obj = match app_obj { Some(o) => o, None => match app::Entity::find_by_id(&aid).one(db).await? { diff --git a/oab/src/result.rs b/oab/src/result.rs index 7e1f8e7..5a36e18 100644 --- a/oab/src/result.rs +++ b/oab/src/result.rs @@ -168,7 +168,6 @@ impl From> for Error { } } - impl actix_web::Responder for Error { type Body = actix_web::body::BoxBody; fn respond_to(self, _req: &actix_web::HttpRequest) -> HttpResponse { @@ -182,7 +181,7 @@ impl error::ResponseError for Error { HttpResponse::build(self.status_code()) .insert_header(ContentType::html()) .insert_header(("error", self.to_string())) - .body("".to_string()) + .body(self.to_string()) } fn status_code(&self) -> StatusCode { diff --git a/oab/src/test.rs b/oab/src/test.rs new file mode 100644 index 0000000..32f1613 --- /dev/null +++ b/oab/src/test.rs @@ -0,0 +1,8 @@ +// +// test.rs +// Copyright (C) 2023 veypi +// 2023-10-06 22:45 +// Distributed under terms of the MIT license. +// + +fn main() {} diff --git a/oaweb/package.json b/oaweb/package.json index 92c7259..4e811ac 100644 --- a/oaweb/package.json +++ b/oaweb/package.json @@ -14,15 +14,16 @@ }, "dependencies": { "@quasar/extras": "^1.16.4", - "@veypi/msg": "^0.1.0", - "@veypi/one-icon": "2", + "@veypi/msg": "^0.1.1", "@veypi/oaer": "^0.0.1", + "@veypi/one-icon": "2", "animate.css": "^4.1.1", "axios": "^1.2.1", "js-base64": "^3.7.5", "mitt": "^3.0.1", "pinia": "^2.0.11", "quasar": "^2.6.0", + "vditor": "^3.9.6", "vue": "^3.0.0", "vue-i18n": "^9.2.2", "vue-router": "^4.0.0", diff --git a/oaweb/quasar.config.js b/oaweb/quasar.config.js index 5362074..b8fbf5f 100644 --- a/oaweb/quasar.config.js +++ b/oaweb/quasar.config.js @@ -155,6 +155,7 @@ module.exports = configure(function(/* ctx */) { plugins: [ 'LoadingBar', 'AppFullscreen', + 'Dialog' ] }, diff --git a/oaweb/src/boot/api/app.ts b/oaweb/src/boot/api/app.ts index 191f994..68a7941 100644 --- a/oaweb/src/boot/api/app.ts +++ b/oaweb/src/boot/api/app.ts @@ -37,7 +37,7 @@ export default { list(id: string) { return ajax.get(this.local + id) }, - add(uid: number) { + add(uid: string) { return ajax.post(this.local + uid) }, update(uid: number, status: string) { diff --git a/oaweb/src/boot/pack.ts b/oaweb/src/boot/pack.ts index ca81d57..b0746e2 100644 --- a/oaweb/src/boot/pack.ts +++ b/oaweb/src/boot/pack.ts @@ -9,11 +9,15 @@ import { boot } from 'quasar/wrappers' import '@veypi/msg/index.css' +import { conf } from '@veypi/msg' import '../assets/icon.js' - import '@veypi/oaer/dist/index.css' import { Cfg } from '@veypi/oaer' +import 'vditor/dist/index.css'; + +conf.timeout = 5000 + Cfg.host.value = 'http://' + window.location.host Cfg.token.value = localStorage.getItem('auth_token') || '' Cfg.uuid.value = 'FR9P5t8debxc11aFF' diff --git a/oaweb/src/components/app.vue b/oaweb/src/components/app.vue index 35e00ed..988d3cc 100644 --- a/oaweb/src/components/app.vue +++ b/oaweb/src/components/app.vue @@ -17,6 +17,7 @@ diff --git a/oaweb/src/pages/AppHome.vue b/oaweb/src/pages/AppHome.vue index 50ad2ce..239c559 100644 --- a/oaweb/src/pages/AppHome.vue +++ b/oaweb/src/pages/AppHome.vue @@ -6,17 +6,57 @@ --> diff --git a/oaweb/src/pages/AppUser.vue b/oaweb/src/pages/AppUser.vue new file mode 100644 index 0000000..3168bac --- /dev/null +++ b/oaweb/src/pages/AppUser.vue @@ -0,0 +1,17 @@ + + + + + + + diff --git a/oaweb/src/pages/IndexPage.vue b/oaweb/src/pages/IndexPage.vue index 2409f25..6696e96 100644 --- a/oaweb/src/pages/IndexPage.vue +++ b/oaweb/src/pages/IndexPage.vue @@ -8,9 +8,9 @@ -
+
- +
@@ -18,7 +18,7 @@

应用中心

- +
@@ -74,11 +74,10 @@ function getApps() { api.app.list().then( (e: modelsApp[]) => { apps.value = e; - api.app.user('-').list(user.id).then((aus: modelsAppUser[]) => { + api.app.user('-').list(user.id).then((aus: modelsApp[]) => { for (let i in aus) { - let ai = apps.value.findIndex(a => a.id === aus[i].app_id) + let ai = apps.value.findIndex(a => a.id === aus[i].id) if (ai >= 0) { - apps.value[ai].au = aus[i] if (aus[i].status === AUStatus.OK) { ofApps.value.push(apps.value[ai]) apps.value.splice(ai, 1) diff --git a/oaweb/src/router/index.ts b/oaweb/src/router/index.ts index 443b311..863e46c 100644 --- a/oaweb/src/router/index.ts +++ b/oaweb/src/router/index.ts @@ -19,7 +19,7 @@ import routes from './routes'; * with the Router instance. */ -export default route(function(/* { store, ssrContext } */) { +function newRouter(/* { store, ssrContext } */) { const createHistory = process.env.SERVER ? createMemoryHistory : (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory); @@ -33,7 +33,6 @@ export default route(function(/* { store, ssrContext } */) { // quasar.conf.js -> build -> publicPath history: createHistory(process.env.VUE_ROUTER_BASE), }); - const u = useUserStore() Router.beforeEach((to, from) => { if (to.meta.requiresAuth && !util.checkLogin()) { @@ -46,6 +45,7 @@ export default route(function(/* { store, ssrContext } */) { } } if (to.meta.checkAuth) { + const u = useUserStore() if (!to.meta.checkAuth(u.auth, to)) { // if (window.$msg) { @@ -56,4 +56,6 @@ export default route(function(/* { store, ssrContext } */) { } }) return Router; -}); +}; + +export default newRouter(); diff --git a/oaweb/src/router/routes.ts b/oaweb/src/router/routes.ts index 5ecfd8a..2922130 100644 --- a/oaweb/src/router/routes.ts +++ b/oaweb/src/router/routes.ts @@ -34,14 +34,16 @@ const routes: RouteRecordRaw[] = [ children: [ loadcomponents('home', 'home', 'IndexPage'), loadcomponents('user', 'user', '404'), + loadcomponents('file', 'file', '404'), loadcomponents('settings', 'settings', '404'), { path: 'app/:id?', component: () => import("../layouts/AppLayout.vue"), redirect: { name: 'app.home' }, children: [ - loadcomponents('home', 'app.home', 'IndexPage'), - loadcomponents('user', 'app.user', 'AppHome'), + loadcomponents('home', 'app.home', 'AppHome'), + loadcomponents('user', 'app.user', 'AppUser'), + loadcomponents('settings', 'app.settings', 'IndexPage'), ] } ], diff --git a/oaweb/src/stores/menu.ts b/oaweb/src/stores/menu.ts index 28d5e4e..b60a130 100644 --- a/oaweb/src/stores/menu.ts +++ b/oaweb/src/stores/menu.ts @@ -17,7 +17,7 @@ const defaultLinks: MenuLink[] = [ to: { name: 'home' } }, { - title: '用户管理', + title: '账号设置', caption: 'oa.veypi.com', icon: 'person', to: { name: 'user' } diff --git a/oaweb/src/stores/user.ts b/oaweb/src/stores/user.ts index e3466ac..b4adfa7 100644 --- a/oaweb/src/stores/user.ts +++ b/oaweb/src/stores/user.ts @@ -8,8 +8,8 @@ import { defineStore } from 'pinia'; import { Auths, modelsUser, NewAuths } from 'src/models'; -import { useRouter } from 'vue-router'; import { Base64 } from 'js-base64' +import router from 'src/router'; import api from 'src/boot/api'; export const useUserStore = defineStore('user', { @@ -23,10 +23,9 @@ export const useUserStore = defineStore('user', { }, actions: { logout() { - // this.ready = false - // localStorage.removeItem('auth_token') - // const r = useRouter() - // r.push({ name: 'login' }) + this.ready = false + localStorage.removeItem('auth_token') + router.push({ name: 'login' }) }, fetchUserData() { let token = localStorage.getItem('auth_token')?.split('.'); diff --git a/oaweb/yarn.lock b/oaweb/yarn.lock index 54d073c..b7af311 100644 --- a/oaweb/yarn.lock +++ b/oaweb/yarn.lock @@ -465,6 +465,11 @@ resolved "https://registry.yarnpkg.com/@veypi/msg/-/msg-0.1.0.tgz#2ebe899527a11ed11f68c2c96f468cfcc66ad3d4" integrity sha512-58dj5nnpHsxaiK5sbPiDK5t8OF4uvN+kAmWhU0BRAgXHpkxkZNZ8rn7hXvSVybG1BbM8EuMNkq0lIxGYNKl8aw== +"@veypi/msg@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@veypi/msg/-/msg-0.1.1.tgz#94864ae2c0a81991b8a30d87f12d2245fdebbead" + integrity sha512-UiAF/Y0EGT/37tGApptzHBNUpo78LbnrEkCqGAGMkJp86wrUyOgTAvuvQ197Ifqw9PIbjZM9dAgMv4DfMJQEYA== + "@veypi/oaer@^0.0.1": version "0.0.1" resolved "https://registry.yarnpkg.com/@veypi/oaer/-/oaer-0.0.1.tgz#b22ebaf72a7bfd5abf62f099b72b533a8cf27abd" @@ -1207,6 +1212,11 @@ didyoumean@^1.2.2: resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== +diff-match-patch@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37" + integrity sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -3469,6 +3479,13 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +vditor@^3.9.6: + version "3.9.6" + resolved "https://registry.yarnpkg.com/vditor/-/vditor-3.9.6.tgz#c6a9e460984992d00b7d4b1f9f79bc75cbba4e34" + integrity sha512-97sPNHnBpfEFnk5WARCpmdKxgUiPtp0/fPLAUmzZ+axFFf7kExWHRNIUO7OTQzEUMJP/rcXESQTlYGhgKYrsOQ== + dependencies: + diff-match-patch "^1.0.5" + vite@^2.9.13: version "2.9.16" resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.16.tgz#daf7ba50f5cc37a7bf51b118ba06bc36e97898e9"