Forráskód Böngészése

feat: new page role with list

ryanemax 8 hónapja
szülő
commit
43ec4531ea

+ 19 - 0
projects/textbook/src/app/comp-table/comp-edit-object/comp-edit-object.component.html

@@ -0,0 +1,19 @@
+<h1 mat-dialog-title *ngIf="data?.cluster?.id">{{"编辑" | translate}}-{{data?.cluster?.get("name") | translate}}</h1>
+<h1 mat-dialog-title *ngIf="!data?.cluster?.id">{{"创建新" | translate}}{{data?.title}}</h1>
+<div mat-dialog-content>
+    <form>
+        <ng-container *ngFor="let field of data?.fieldsArray">
+            <mat-form-field>
+                <mat-label translate>{{field?.name}}</mat-label>
+                <input matInput [(ngModel)]="jsonData[field?.key]" [formControl]="formControlMap[field?.key]" [errorState]="requiredErrorMap[field?.key]">
+                <mat-error *ngIf="requiredErrorMap[field?.key]">
+                    {{field?.name | translate}}<strong translate>必填</strong>
+                </mat-error>
+            </mat-form-field>
+        </ng-container>
+    </form>
+</div>
+<div mat-dialog-actions>
+  <button mat-button [disabled]="isSaving" (click)="close()" >{{"取消" | translate}}</button>
+  <button mat-button [disabled]="isSaving" (click)="save()" >{{"保存" | translate}}</button>
+</div>

+ 0 - 0
projects/textbook/src/app/comp-table/comp-edit-object/comp-edit-object.component.scss


+ 23 - 0
projects/textbook/src/app/comp-table/comp-edit-object/comp-edit-object.component.spec.ts

@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CompEditObjectComponent } from './comp-edit-object.component';
+
+describe('CompEditObjectComponent', () => {
+  let component: CompEditObjectComponent;
+  let fixture: ComponentFixture<CompEditObjectComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ CompEditObjectComponent ]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(CompEditObjectComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 100 - 0
projects/textbook/src/app/comp-table/comp-edit-object/comp-edit-object.component.ts

@@ -0,0 +1,100 @@
+import { CommonModule } from '@angular/common';
+import { Component, Inject } from '@angular/core';
+import { FormControl, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { TranslateModule } from '@ngx-translate/core';
+import Parse from "parse";
+
+@Component({
+  selector: 'app-comp-edit-object',
+  standalone:true,
+  imports:[ 
+    CommonModule,
+    FormsModule,
+    MatFormFieldModule,
+    ReactiveFormsModule,
+    MatInputModule,
+    MatButtonModule,
+    MatDialogModule,
+    TranslateModule,
+  ],
+  templateUrl: './comp-edit-object.component.html',
+  styleUrls: ['./comp-edit-object.component.scss']
+})
+export class CompEditObjectComponent {
+  jsonData:any = {}
+  MinerCluster = Parse.Object.extend("MinerCluster")
+
+  formControlMap:any = {}
+  constructor(
+    public dialogRef: MatDialogRef<CompEditObjectComponent>,
+    @Inject(MAT_DIALOG_DATA) public data: {
+      cluster:Parse.Object|null|undefined,
+      center:Parse.Object|null|undefined,
+      fieldsArray:Array<any>|null,
+      title:string|null,
+      default?:any
+    },
+  ){
+    // 设置数据校验
+    this.data?.fieldsArray?.forEach(field=>{
+      if(field?.require){
+        this.formControlMap[field?.key] = new FormControl(field?.key, [Validators.required]);
+      }
+    })
+    if(this.data.cluster?.toJSON()){
+      this.jsonData = this.data?.cluster?.toJSON();
+    }
+    if(!this.data?.cluster?.id){
+      this.data.cluster = new this.MinerCluster()
+    }
+  }
+  ngOnInit(){
+
+  }
+  /**
+   * 保存与取消
+   */
+  close(){
+    this.dialogRef.close();
+  }
+  isSaving:boolean = false;
+  requiredErrorMap:any = {}
+  async save() {
+    if(this.isSaving) return;
+    this.isSaving = true
+    // 检查必填项
+    this.requiredErrorMap = {}
+    this.data?.fieldsArray?.forEach(field=>{
+      if(field?.require && typeof this.jsonData[field?.key] == "undefined"){
+        this.requiredErrorMap[field?.key] = true
+      }
+    })
+    if(Object.keys(this.requiredErrorMap)?.length>=1){
+      this.isSaving = false
+      return
+    }
+
+    // 设置编辑结果
+    delete this.jsonData.objectId
+    delete this.jsonData.updatedAt
+    delete this.jsonData.createdAt
+    delete this.jsonData.ACL
+    this.data?.cluster?.set(this.jsonData);
+
+    // 设置默认值
+    if(this.data?.default){
+      this.data?.cluster?.set(this.data?.default)
+    }
+
+    // 保存并返回
+    this.data.cluster = await this.data?.cluster?.save();
+    this.dialogRef.close(this.data?.cluster);
+    this.isSaving = false
+
+  }
+
+}

+ 1 - 1
projects/textbook/src/app/comp-table/comp-table-list/comp-table-list.component.html

@@ -16,7 +16,7 @@
         <ng-container *ngFor="let field of headerArray">
             <th >{{field?.name}}</th>
         </ng-container>
-            <th >状态</th>
+            <th >时间</th>
             <th >操作</th>
     </tr>
     </thead>

+ 3 - 1
projects/textbook/src/app/comp-table/comp-table-list/comp-table-list.component.ts

@@ -83,7 +83,9 @@ export class CompTableListComponent {
   onButtonHandleCallBack:Function|undefined
   buttonHandle(button:any,object:any){
     let that = this
-    button?.handle({object:object,dialog:this.dialog,callback:this.onButtonHandleCallBack},that.currentLang)
+    if(button?.handle){
+      button?.handle({object:object,dialog:this.dialog,callback:this.onButtonHandleCallBack},that.currentLang)
+    }
   }
   refresh(page?:number){
     if(page){this.pageIndex=page}

+ 11 - 0
projects/textbook/src/modules/nav-admin/modules.routes.ts

@@ -1,6 +1,7 @@
 import { NgModule } from "@angular/core";
 import { RouterModule, Routes } from "@angular/router";
 import { PageHomeComponent } from './page-home/page-home.component';
+import { PageRoleComponent } from "./page-role/page-role.component";
 const routes: Routes = [
   {
     path: 'home',
@@ -12,6 +13,16 @@ const routes: Routes = [
       //   pathMatch: "full",
       // },
     ]
+  },
+  {
+    path: 'manage',
+    component: PageHomeComponent,
+    children:[
+      {
+        path: 'role',//列表
+        component: PageRoleComponent,
+      },
+    ]
   }
 ];
 @NgModule({

+ 3 - 3
projects/textbook/src/modules/nav-admin/page-home/page-home.component.html

@@ -10,7 +10,7 @@
           <li
             nz-menu-item
             [nzSelected]="active == child.id"
-            (click)="toUrl('/nav-admin', child.id, { category: child.id })"
+            (click)="toUrl(child)"
           >
             {{ child.name }}
           </li>
@@ -20,7 +20,7 @@
       } @else {
       <li
         nz-menu-item
-        (click)="toUrl('/nav-admin', 'list')"
+        (click)="toUrl(item)"
         [nzSelected]="active == item.id"
       >
         <span nz-icon nzType="home" nzTheme="outline"></span>
@@ -29,7 +29,7 @@
       } }
     </ul>
   </div>
-  <div class="proview">
+  <div class="preview">
     <router-outlet></router-outlet>
   </div>
 </div>

+ 1 - 1
projects/textbook/src/modules/nav-admin/page-home/page-home.component.scss

@@ -6,7 +6,7 @@
   .content-left{
     background-color:#fff;
   }
-  .content-rifht{
+  .preview{
     height: 100%;
     overflow-y: scroll;
     padding: 20px 0 40px 0;

+ 11 - 4
projects/textbook/src/modules/nav-admin/page-home/page-home.component.ts

@@ -37,6 +37,7 @@ export class PageHomeComponent  implements OnInit {
         },
         {
           name:'用户组管理',
+          path:"/nav-admin/manage/role",
           id:'2-2',
         },
       ]
@@ -66,9 +67,15 @@ export class PageHomeComponent  implements OnInit {
   ) { }
 
   ngOnInit() {}
-  toUrl(url:string, cateid:string, params?:any){
-    this.active = cateid
-    localStorage.setItem('active', cateid)
-    // this.router.navigate([url, params ? params : {}])
+  toUrl(child: any) {
+    let cateid = child.id;
+    this.active = cateid;
+    localStorage.setItem('active', cateid);
+    console.log(child);
+    if (child.params) {
+      this.router.navigate([child.path, child?.params]);
+    } else {
+      this.router.navigate([child.path]);
+    }
   }
 }

+ 8 - 0
projects/textbook/src/modules/nav-admin/page-role/page-role.component.html

@@ -0,0 +1,8 @@
+<comp-table-list
+  #list
+  [schema]="_Role"
+  *ngIf="className && fieldsArray"
+  [className]="className"
+  [fieldsArray]="fieldsArray"
+  [queryParams]="queryParams"
+></comp-table-list>

+ 0 - 0
projects/textbook/src/modules/nav-admin/page-role/page-role.component.scss


+ 22 - 0
projects/textbook/src/modules/nav-admin/page-role/page-role.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { PageRoleComponent } from './page-role.component';
+
+describe('PageRoleComponent', () => {
+  let component: PageRoleComponent;
+  let fixture: ComponentFixture<PageRoleComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [PageRoleComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(PageRoleComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 52 - 0
projects/textbook/src/modules/nav-admin/page-role/page-role.component.ts

@@ -0,0 +1,52 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { ActivatedRoute, RouterOutlet } from '@angular/router';
+import { CompTableListComponent } from '../../../app/comp-table/comp-table-list/comp-table-list.component';
+import _Role from '../../../schemas/_Role';
+// import { TranslateService } from '@ngx-translate/core';
+import * as Parse from "parse";
+import { CommonModule } from '@angular/common';
+
+
+@Component({
+  selector: 'app-page-role',
+  templateUrl: './page-role.component.html',
+  styleUrls: ['./page-role.component.scss'],
+  imports: [CommonModule,RouterOutlet,CompTableListComponent],
+  standalone: true,
+})
+export class PageRoleComponent  implements OnInit {
+  @ViewChild(CompTableListComponent) list:CompTableListComponent|undefined
+
+  _Role = _Role
+  user:Parse.User|undefined
+  className:string|undefined
+  queryParams:any|undefined
+  fieldsArray:Array<any>|undefined
+
+  constructor(
+    private route: ActivatedRoute,
+    private activeRoute: ActivatedRoute,
+    // private translate:TranslateService,
+  ) {
+    this.user = Parse.User.current();
+    this.className = this._Role.className
+    this.fieldsArray = this._Role.fieldsArray
+    this.queryParams = {where:{
+      // user:this.user?.toPointer(),
+      isDeleted:{$ne:true},
+    }}
+  }
+
+  ngOnInit(): void {
+    this.activeRoute.paramMap.subscribe(async (params) => {
+      let isDeleted = params.get('isDeleted')
+      if(isDeleted){
+        this.queryParams.where['isDeleted'] = {$eq:true}
+      }else{
+        this.queryParams.where['isDeleted'] = {$ne:true}
+      }
+      this.list?.ngOnInit()
+    });
+  }
+
+}

+ 1 - 3
projects/textbook/src/modules/nav-author/page-home/page-home.component.scss

@@ -12,7 +12,5 @@
     padding: 20px 0 40px 0;
     flex: 1;
   }
-  .proview{
-    flex: 1;
-  }
+
 }

+ 44 - 0
projects/textbook/src/schemas/_Role.ts

@@ -0,0 +1,44 @@
+
+
+    const _Role = {
+        "className": "_Role",
+        "fieldsArray": [
+            {
+                "key":"title",
+                "name":"用户组名称",
+                "type": "String",
+                isHeader:true
+            },
+            {
+                "key":"name",
+                "name":"用户组标识",
+                "type": "String",
+                isHeader:true
+            },
+            {
+                "key":"desc",
+                "name":"描述",
+                "type": "String"
+            },
+            // {
+            //     "key":"user",
+            //     "type": "Pointer",
+            //     "targetClass":"_User",
+            //     "required": false
+            // }
+        ],
+        buttons:[
+            {
+                name:"编辑",
+                place:"item",
+                show:(options:{object:Parse.Object})=>{
+                    return true
+                },
+                // handle:(options:{clusterServ:ClusterService,dialog:MatDialog,object:Parse.Object})=>{
+                //     options?.clusterServ?.openMinerDialog(options?.dialog,options?.object)
+                // }
+            },
+        ]
+      };
+      
+      export default _Role;

+ 19 - 0
server/db/data/init-data.sql

@@ -16,3 +16,22 @@ SET
 "company" = excluded."company",
 "createdAt"=excluded."createdAt",
 "updatedAt"=excluded."updatedAt";
+
+-- 初始化超级管理员角色
+INSERT INTO "_Role" ("objectId", "name", "_rperm", "_wperm", "company", "createdAt", "updatedAt")
+VALUES
+('ZQOwyoDteL', 'superadmin','{*,BOOKADMINI}','{BOOKADMINI}','RbIKpmuaMC','2024-06-16 12:00:00','2024-06-16 12:00:00')
+ON conflict("objectId") DO UPDATE
+SET 
+"name" = excluded."name",
+"company" = excluded."company",
+"createdAt"=excluded."createdAt";
+
+-- 超级管理员帐号,添加至超管用户组
+INSERT INTO "_Join:users:_Role" ("relatedId", "owningId")
+VALUES
+('BOOKADMINI', 'ZQOwyoDteL')
+ON conflict("relatedId","owningId") DO UPDATE
+SET 
+"relatedId" = excluded."relatedId",
+"owningId" = excluded."owningId";