Эх сурвалжийг харах

feat: risk categroy relate to department

Signed-off-by: carlos <568187512@qq.com>
carlos 2 сар өмнө
parent
commit
77f3e2cdc0
29 өөрчлөгдсөн 343 нэмэгдсэн , 176 устгасан
  1. 1 1
      src/app/pages/login/login.component.html
  2. 1 11
      src/app/pages/manager/basic/basic.component.ts
  3. 9 57
      src/app/pages/manager/basic/basic.route.ts
  4. 3 3
      src/app/pages/manager/basic/dj/dj.component.html
  5. 31 0
      src/app/pages/manager/basic/dr-relationship/dr-relationship.component.html
  6. 52 0
      src/app/pages/manager/basic/dr-relationship/dr-relationship.component.less
  7. 23 0
      src/app/pages/manager/basic/dr-relationship/dr-relationship.component.spec.ts
  8. 123 0
      src/app/pages/manager/basic/dr-relationship/dr-relationship.component.ts
  9. 3 0
      src/app/pages/manager/basic/poe/poe.component.ts
  10. 4 1
      src/app/pages/manager/manager.component.ts
  11. 0 4
      src/app/pages/manager/risk/risk-bank/risk-bank.component.ts
  12. 0 4
      src/app/pages/manager/risk/risk-bank/risk-item-detail/risk-item-detail.component.ts
  13. 21 2
      src/app/pages/manager/risk/risk-bank/risk-item-form/risk-item-form.component.html
  14. 56 56
      src/app/pages/manager/risk/risk-bank/risk-item-form/risk-item-form.component.ts
  15. 1 0
      src/app/pages/manager/risk/risk-knowledge/knowledge-risk-type/knowledge-type-form/knowledge-type-form.component.ts
  16. 0 4
      src/app/pages/manager/risk/risk-knowledge/risk-knowledge.component.ts
  17. 3 1
      src/app/pages/manager/risk/risk-list/risk-list.component.html
  18. 1 1
      src/app/pages/manager/risk/risk-list/risk-list.component.ts
  19. 1 6
      src/app/pages/manager/risk/risk.component.ts
  20. 1 6
      src/app/pages/manager/workbench/workbench.component.ts
  21. 3 16
      src/app/services/knowledge.service.ts
  22. 0 0
      src/app/shared/filter-button-group-with-count/filter-button-group-with-count.component.html
  23. 0 0
      src/app/shared/filter-button-group-with-count/filter-button-group-with-count.component.less
  24. 0 0
      src/app/shared/filter-button-group-with-count/filter-button-group-with-count.component.ts
  25. 0 0
      src/app/shared/filter-button-group-with-count/filter-button-group.component.spec.ts
  26. 3 1
      src/app/shared/risk-type-category-nav/risk-type-category-nav.component.html
  27. 1 2
      src/app/shared/risk-type-category-nav/risk-type-category-nav.component.ts
  28. 1 0
      src/assets/icons/link.svg
  29. 1 0
      src/types/knowledge.d.ts

+ 1 - 1
src/app/pages/login/login.component.html

@@ -92,5 +92,5 @@
 <div class="fixed bottom-[4.5%] left-[7%] font-fangzheng text-white text-[50px]">
   <span>双重预防</span>
   <span class="mx-12">安全先行</span>
-  <span>守护轨道每一程</span>
+  <span>守护市域每一程</span>
 </div>

+ 1 - 11
src/app/pages/manager/basic/basic.component.ts

@@ -1,7 +1,5 @@
 import { Component } from '@angular/core';
 import { RouterOutlet } from '@angular/router';
-import { BasicDataService } from '../../../services/basic.service';
-import { KnowledgeService } from '../../../services/knowledge.service';
 
 @Component({
   selector: 'app-basic',
@@ -10,12 +8,4 @@ import { KnowledgeService } from '../../../services/knowledge.service';
   template: `<router-outlet></router-outlet>`,
   styleUrl: './basic.component.less',
 })
-export class BasicComponent {
-  constructor(
-    private basic: BasicDataService,
-    private knowledge: KnowledgeService
-  ) {
-    this.basic.init();
-    this.knowledge.init();
-  }
-}
+export class BasicComponent {}

+ 9 - 57
src/app/pages/manager/basic/basic.route.ts

@@ -20,36 +20,6 @@ export const basicRoutes: Routes = [
       weight: 2,
     },
   },
-  // {
-  //   path: 'unit',
-  //   loadComponent: () => import('./unit/unit.component').then(m => m.UnitComponent),
-  //   data: {
-  //     animation: 'UnitPage',
-  //     title: '生产单元',
-  //     icon: 'icons:unit',
-  //     weight: 3,
-  //   },
-  // },
-  // {
-  //   path: 'position',
-  //   loadComponent: () => import('./position/position.component').then(m => m.PositionComponent),
-  //   data: {
-  //     animation: 'PositionPage',
-  //     title: '场所',
-  //     icon: 'icons:unit',
-  //     weight: 4,
-  //   },
-  // },
-  // {
-  //   path: 'post',
-  //   loadComponent: () => import('./post/post.component').then(m => m.PostComponent),
-  //   data: {
-  //     animation: 'PostPage',
-  //     title: '岗位',
-  //     icon: 'icons:user-fill',
-  //     weight: 4,
-  //   },
-  // },
   {
     path: 'post-group',
     loadComponent: () => import('./post-group/post-group.component').then(m => m.PostGroupComponent),
@@ -60,24 +30,6 @@ export const basicRoutes: Routes = [
       weight: 5,
     },
   },
-  // {
-  //   path: 'operation',
-  //   loadComponent: () => import('./operation/operation.component').then(m => m.OperationComponent),
-  //   data: {
-  //     title: '作业',
-  //     icon: 'icons:transit',
-  //     weight: 6,
-  //   },
-  // },
-  // {
-  //   path: 'equipment',
-  //   loadComponent: () => import('./equipment/equipment.component').then(m => m.EquipmentComponent),
-  //   data: {
-  //     title: '设备',
-  //     icon: 'icons:equipment',
-  //     weight: 7,
-  //   },
-  // },
   {
     path: 'poe',
     loadComponent: () => import('./poe/poe.component').then(m => m.PoeComponent),
@@ -96,15 +48,15 @@ export const basicRoutes: Routes = [
       weight: 8,
     },
   },
-  // {
-  //   path: 'department',
-  //   loadComponent: () => import('./department/department.component').then(m => m.DepartmentComponent),
-  //   data: {
-  //     title: '部门',
-  //     icon: 'icons:post-group',
-  //     weight: 8,
-  //   },
-  // },
+  {
+    path: 'relationship',
+    loadComponent: () => import('./dr-relationship/dr-relationship.component').then(m => m.DrRelationshipComponent),
+    data: {
+      title: '部门风险项关联',
+      icon: 'icons:link',
+      weight: 8,
+    },
+  },
   {
     path: 'consequence',
     loadComponent: () => import('./consequence/consequence.component').then(m => m.ConsequenceComponent),

+ 3 - 3
src/app/pages/manager/basic/dj/dj.component.html

@@ -20,12 +20,12 @@
     <tbody>
       <tr *ngFor="let data of table.data">
         <td>{{ data.name }}</td>
-        <td>
+        <td class="pb-2">
           @for (item of data.jobs; track $index) {
-            <nz-tag class="rounded" nzColor="blue">{{ item.name }}</nz-tag>
+            <nz-tag class="rounded mb-2" nzColor="blue">{{ item.name }}</nz-tag>
           }
         </td>
-        <td>
+        <td class="text-nowrap">
           <button class="precaution-button px-4" nz-button nzSize="small" nzType="primary" (click)="handleEdit(data)">
             编辑
           </button>

+ 31 - 0
src/app/pages/manager/basic/dr-relationship/dr-relationship.component.html

@@ -0,0 +1,31 @@
+<div class="shared-panel">
+  <div class="shared-panel-header">
+    <div class="title">部门风险项关联</div>
+  </div>
+  <div class="dr-content">
+    <div class="type-nav-container">
+      <div class="type-nav-box">
+        <risk-type-category-nav
+          [emptyAbleToSelect]="true"
+          [showCount]="false"
+          [types]="types"
+          [categories]="categories"
+          [selectedType]="selectedType"
+          [selectedCategory]="selectedCategory"
+          (selectedTypeChange)="selectedTypeChange($event)"
+          (selectedCategoryChange)="selectedCategoryChange($event)"
+        ></risk-type-category-nav>
+      </div>
+    </div>
+    <div class="dr-content flex-1 py-4">
+      <div class="h-full p-4 overflow-y-auto custom-scroll-bar">
+        <div class="p-4 border border-primary border-solid rounded-xl">
+          <nz-checkbox-group
+            [(ngModel)]="departmentOptions"
+            (ngModelChange)="onDepartmentChange($event)"
+          ></nz-checkbox-group>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 52 - 0
src/app/pages/manager/basic/dr-relationship/dr-relationship.component.less

@@ -0,0 +1,52 @@
+.type-nav-container {
+  width: 310px;
+  padding: 8px 0 8px 8px;
+  .type-nav-box {
+    height: 100%;
+    border-radius: 10px 0px 0px 15px;
+    border: 1px solid #e5e5e5;
+    overflow: hidden;
+  }
+}
+.dr-content {
+  height: calc(100vh - var(--header-height) - 97px - 48px);
+  display: flex;
+}
+
+.list-item-card {
+  box-shadow: 0px 2px 4px 2px rgba(53, 53, 53, 0.1);
+  border-radius: 8px;
+  border: 1px solid transparent;
+  padding: 16px 0 32px 16px;
+  transition: border 0.3s;
+  cursor: pointer;
+  margin-bottom: 12px;
+  &:hover {
+    border: 1px solid #2953e830;
+  }
+  &.active {
+    border: 1px solid var(--deep-blue);
+  }
+  .card-header {
+    @apply flex justify-between items-center;
+    line-height: 31px;
+    .title {
+      @apply text-base font-medium line-clamp-1;
+      font-size: 16px;
+    }
+    .level {
+      box-shadow: 0px 1px 4px 0px rgba(187, 187, 187, 0.5);
+      border-radius: 16px 0px 0px 16px;
+      backdrop-filter: blur(1.838235294117647px);
+      height: 31px;
+      width: 80px;
+      font-weight: 500;
+      font-size: 14px;
+      text-align: center;
+    }
+  }
+  .description {
+    @apply text-sm text-gray-500 line-clamp-2 pt-3 pr-4;
+    color: #666666;
+  }
+}

+ 23 - 0
src/app/pages/manager/basic/dr-relationship/dr-relationship.component.spec.ts

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

+ 123 - 0
src/app/pages/manager/basic/dr-relationship/dr-relationship.component.ts

@@ -0,0 +1,123 @@
+import { Component } from '@angular/core';
+import { NzMessageService } from 'ng-zorro-antd/message';
+import { Subscription } from 'rxjs';
+import { CommonNzModule } from '../../../../common.nz.module';
+import { ApiService } from '../../../../services/api.service';
+import { BasicDataService } from '../../../../services/basic.service';
+import { KnowledgeService } from '../../../../services/knowledge.service';
+import { RiskTypeCategoryNavComponent } from '../../../../shared/risk-type-category-nav/risk-type-category-nav.component';
+import { StarIconComponent } from '../../../../shared/star/star.icon';
+
+interface CheckOption {
+  label: string;
+  value: number;
+  checked: boolean;
+}
+
+const colorMap: Record<string, string> = {
+  'R1': '#FF0000',
+  'R2': '#EB5D00',
+  'R2*': '#EB5D00',
+  'R3': '#fcd34d',
+  'R4': '#4677F2',
+};
+
+@Component({
+  selector: 'app-dr-relationship',
+  standalone: true,
+  imports: [CommonNzModule, RiskTypeCategoryNavComponent, StarIconComponent],
+  templateUrl: './dr-relationship.component.html',
+  styleUrl: './dr-relationship.component.less',
+})
+export class DrRelationshipComponent {
+  subs = new Subscription();
+  types: OptionWithCount<number>[] = [];
+  categories: OptionWithCount<number>[] = [];
+  selectedType = -1;
+  selectedCategory = -1;
+  departmentOptions: CheckOption[] = [];
+  colorMap = colorMap;
+  constructor(
+    private message: NzMessageService,
+    private knowledge: KnowledgeService,
+    private basic: BasicDataService,
+    private api: ApiService
+  ) {
+    const sub = this.knowledge.onTypesChange.subscribe(() => {
+      this.resetSelected();
+    });
+    this.subs.add(sub);
+  }
+  ngOnInit() {
+    this.resetSelected();
+  }
+  ngOnDestroy() {
+    this.subs.unsubscribe();
+  }
+  resetSelected() {
+    this.types = this.getTypes();
+    if (!this.currentCategory) {
+      this.selectedTypeChange(this.types[0]?.value || -1);
+    }
+  }
+  selectedTypeChange(value: number) {
+    this.selectedType = value;
+    this.categories = this.getCategories(value);
+
+    this.selectedCategoryChange(this.categories[0]?.value || -1);
+  }
+  selectedCategoryChange(value: number) {
+    this.selectedCategory = value;
+    this.departmentOptions = this.getCurrentDepartmentIds();
+  }
+  getTypes(): OptionWithCount<number>[] {
+    return this.allTypes.map(type => ({
+      label: type.value,
+      value: type.id,
+      count: 0,
+    }));
+  }
+  getCategories(typeId: number): OptionWithCount<number>[] {
+    const options = this.knowledge.getCategoryOptionsByType(typeId);
+    return options.map(option => ({
+      ...option,
+      count: 0,
+    }));
+  }
+  getCurrentDepartmentIds() {
+    const empty = this.allDepartments.map(d => ({ label: d.name, value: d.id, checked: false }));
+    const currentCategory = this.currentCategory;
+    if (!currentCategory) return empty;
+    return empty.map(d => ({
+      ...d,
+      checked: currentCategory.departments.includes(d.value),
+    }));
+  }
+
+  onDepartmentChange(ops: CheckOption[]) {
+    const dIds = ops.filter(d => d.checked).map(d => d.value);
+    if (!this.currentCategory) {
+      this.message.error('操作失败');
+      return;
+    }
+    this.setDepartmentsOfRiskCategory(dIds);
+  }
+  async setDepartmentsOfRiskCategory(dIds: number[]) {
+    await this.api.knowledge.updateRiskCategory({
+      ...this.currentCategory,
+      departments: dIds,
+    });
+    this.knowledge.fetchRiskTypes();
+  }
+  get allDepartments() {
+    return this.basic.departments;
+  }
+  get allTypes() {
+    return this.knowledge.types();
+  }
+  get currentCategory() {
+    const currentType = this.allTypes.find(t => t.id === this.selectedType);
+    if (!currentType) return undefined;
+    return currentType.categories.find(c => c.id === this.selectedCategory);
+  }
+}

+ 3 - 0
src/app/pages/manager/basic/poe/poe.component.ts

@@ -77,6 +77,9 @@ export class PoeComponent {
   ngOnInit() {
     this.resetSelected();
   }
+  ngOnDestroy() {
+    this.subs.unsubscribe();
+  }
   resetSelected() {
     this.types = this.getTypes();
     if (this.selectedType === -1) {

+ 4 - 1
src/app/pages/manager/manager.component.ts

@@ -3,6 +3,7 @@ import { ChildrenOutletContexts, RouterModule } from '@angular/router';
 import { slideInAnimation } from '../../animations';
 import { CommonNzModule } from '../../common.nz.module';
 import { BasicDataService } from '../../services/basic.service';
+import { KnowledgeService } from '../../services/knowledge.service';
 import { SettingService } from '../../services/setting.service';
 import { LayoutComponent } from './layout/layout.component';
 
@@ -19,9 +20,11 @@ export class ManagerComponent {
   constructor(
     public readonly settings: SettingService,
     private readonly basic: BasicDataService,
+    private readonly knowledge: KnowledgeService,
     private contexts: ChildrenOutletContexts
   ) {
-    this.basic.init();
+    basic.init();
+    knowledge.init();
   }
 
   getRouteAnimationData() {

+ 0 - 4
src/app/pages/manager/risk/risk-bank/risk-bank.component.ts

@@ -1,6 +1,5 @@
 import { Component } from '@angular/core';
 import { CommonNzModule } from '../../../../common.nz.module';
-import { KnowledgeService } from '../../../../services/knowledge.service';
 import { EnterpriseInputComponent } from './enterprise-input/enterprise-input.component';
 import { RiskItemListComponent } from './risk-item-list/risk-item-list.component';
 import { UpdateRecordComponent } from './update-record/update-record.component';
@@ -13,9 +12,6 @@ import { UpdateRecordComponent } from './update-record/update-record.component';
   styleUrl: './risk-bank.component.less',
 })
 export class RiskBankComponent {
-  constructor(private readonly knowledge: KnowledgeService) {
-    knowledge.init();
-  }
   tabs = [
     {
       label: '风险知识',

+ 0 - 4
src/app/pages/manager/risk/risk-bank/risk-item-detail/risk-item-detail.component.ts

@@ -22,10 +22,6 @@ export class RiskItemDetailComponent extends RiskItemModel {
     this.selectChange.emit(id);
   }
 
-  ngOnInit() {
-    this.knowledge.init();
-    this.basic.init();
-  }
   levelText(level: string) {
     return getLevelText(level);
   }

+ 21 - 2
src/app/pages/manager/risk/risk-bank/risk-item-form/risk-item-form.component.html

@@ -13,7 +13,7 @@
     style="--icon-cell-width: 40px"
   >
     <nz-form-item>
-      <nz-form-label nzRequired nzSpan="3">风险描述</nz-form-label>
+      <nz-form-label nzRequired style="width: 95px">风险描述</nz-form-label>
       <nz-form-control nzSpan="21" nzErrorTip="请输入风险描述">
         <textarea
           nz-input
@@ -105,7 +105,7 @@
           <nz-form-control nzSpan="16" nzErrorTip="请选择涉及场所">
             <nz-select
               class="precaution-select"
-              [nzOptions]="options.unit"
+              [nzOptions]="options.position"
               formControlName="involvedPositions"
               nzPlaceHolder="请选择涉及场所"
               nzAllowClear
@@ -116,6 +116,25 @@
         </nz-form-item>
       </div>
     </div>
+
+    <nz-form-item class="mb-3 -mt-2">
+      <nz-form-label style="width: 95px; color: var(--ant-primary-color) !important">关联部门</nz-form-label>
+      <nz-form-control>
+        @if (currentDepartments.length > 0) {
+          <div>
+            @for (d of currentDepartments; track d; let i = $index) {
+              <nz-tag class="rounded my-1" [nzColor]="'blue'">{{ d.name }}</nz-tag>
+            }
+          </div>
+        } @else {
+          @if (currentCategory) {
+            <div class="text-sm text-red-400">无关联部门</div>
+          }
+        }
+        <textarea class="hidden" formControlName="title"></textarea>
+      </nz-form-control>
+    </nz-form-item>
+
     <div nz-row>
       <div nz-col nzSpan="10">
         <nz-form-item>

+ 56 - 56
src/app/pages/manager/risk/risk-bank/risk-item-form/risk-item-form.component.ts

@@ -45,7 +45,7 @@ export class RiskItemFormComponent {
     category: [] as Option[],
     type: [] as Option[],
     job: [] as Option[],
-    unit: [] as Option[],
+    position: [] as Option[],
     operation: [] as Option[],
     equipment: [] as Option[],
   };
@@ -110,21 +110,31 @@ export class RiskItemFormComponent {
       label: item.value,
       value: item.id,
     }));
-
-    this.options.job = this.basic.jobs.map(item => ({
-      label: this.basic.getJobName(item.id),
-      value: item.id,
-    }));
-    this.options.unit = this.getPositionOptions();
-    this.options.operation = this.getOperationOptions();
-    this.options.equipment = this.getEquipmentOptions();
+    this.options.operation = this.getTargetOptions('operation');
+    this.options.position = this.getTargetOptions('position');
+    this.options.equipment = this.getTargetOptions('equipment');
+    this.setJobOptions();
+  }
+  setJobOptions() {
+    this.currentCategory = this.getCurrentCategory();
+    if (!this.currentCategory) {
+      this.options.job = [];
+      this.currentDepartments = [];
+      return;
+    }
+    this.currentDepartments = this.getSelectedDepartments();
+    this.options.job = this.basic.jobs
+      .filter(j => this.currentCategory!.departments.includes(j.department))
+      .map(item => ({
+        label: this.basic.getJobName(item.id),
+        value: item.id,
+      }));
   }
 
-  getOperationOptions() {
+  getOptions(rawList: (BasicData.Operation | BasicData.Operation | BasicData.Equipment)[]) {
     const { type, category } = this.validateForm.value;
     if (!type || !category) return [];
-    const all = this.basic.operations;
-    const filtered = all.filter(item => {
+    const filtered = rawList.filter(item => {
       let isMatch = true;
 
       if (isMatch && type) {
@@ -140,46 +150,17 @@ export class RiskItemFormComponent {
       value: item.id,
     }));
   }
-  getPositionOptions() {
-    const { type, category } = this.validateForm.value;
-    if (!type || !category) return [];
-    const all = this.basic.positions;
-    const filtered = all.filter(item => {
-      let isMatch = true;
-
-      if (isMatch && type) {
-        isMatch = item.type === type;
-      }
-      if (isMatch && category) {
-        isMatch = item.category === category;
-      }
-      return isMatch;
-    });
-    return filtered.map(item => ({
-      label: item.name,
-      value: item.id,
-    }));
+  getTargetOptions(key: 'operation' | 'position' | 'equipment') {
+    switch (key) {
+      case 'position':
+        return this.getOptions(this.basic.positions);
+      case 'operation':
+        return this.getOptions(this.basic.operations);
+      case 'equipment':
+        return this.getOptions(this.basic.equipments);
+    }
   }
-  getEquipmentOptions() {
-    const { type, category } = this.validateForm.value;
-    if (!type || !category) return [];
-    const all = this.basic.equipments;
-    const filtered = all.filter(item => {
-      let isMatch = true;
 
-      if (isMatch && type) {
-        isMatch = item.type === type;
-      }
-      if (isMatch && category) {
-        isMatch = item.category === category;
-      }
-      return isMatch;
-    });
-    return filtered.map(item => ({
-      label: item.name,
-      value: item.id,
-    }));
-  }
   changeType(value: number) {
     this.options.category = this.knowledge.getCategoryOptionsByType(value);
     this.validateForm.patchValue({
@@ -187,20 +168,25 @@ export class RiskItemFormComponent {
       involvedOperations: [],
       involvedEquipments: [],
       involvedPositions: [],
+      responsiblePositions: [],
     });
-    this.options.operation = this.getOperationOptions();
-    this.options.unit = this.getPositionOptions();
-    this.options.equipment = this.getEquipmentOptions();
+    this.options.operation = this.getTargetOptions('operation');
+    this.options.position = this.getTargetOptions('position');
+    this.options.equipment = this.getTargetOptions('equipment');
   }
   changeCategory() {
     this.validateForm.patchValue({
       involvedOperations: [],
       involvedEquipments: [],
       involvedPositions: [],
+      responsiblePositions: [],
+    });
+    setTimeout(() => {
+      this.options.operation = this.getTargetOptions('operation');
+      this.options.position = this.getTargetOptions('position');
+      this.options.equipment = this.getTargetOptions('equipment');
+      this.setJobOptions();
     });
-    this.options.operation = this.getOperationOptions();
-    this.options.unit = this.getPositionOptions();
-    this.options.equipment = this.getEquipmentOptions();
   }
   closeInsideDrawer() {
     this.insideDrawerVisible = false;
@@ -425,4 +411,18 @@ export class RiskItemFormComponent {
       nzOnOk: () => this.onUpdate({ ...v, updateReason: this.updateReason }),
     });
   }
+  currentCategory?: Knowledge.RiskCategoryDto;
+  getCurrentCategory() {
+    const { category, type } = this.validateForm.value;
+    const currentType = this.knowledge.types().find(t => t.id === type);
+    if (!currentType) return undefined;
+    return currentType.categories.find(c => c.id === category);
+  }
+  currentDepartments: BasicData.Department[] = [];
+  getSelectedDepartments() {
+    if (!this.currentCategory) return [];
+    return (this.currentDepartments = this.basic.departments.filter(d =>
+      this.currentCategory!.departments.includes(d.id)
+    ));
+  }
 }

+ 1 - 0
src/app/pages/manager/risk/risk-knowledge/knowledge-risk-type/knowledge-type-form/knowledge-type-form.component.ts

@@ -192,6 +192,7 @@ export class KnowledgeTypeFormComponent {
       id,
       value: '',
       company: this.setting.userCompany,
+      departments: [],
       status: 0,
       isDelete: 0,
     };

+ 0 - 4
src/app/pages/manager/risk/risk-knowledge/risk-knowledge.component.ts

@@ -1,5 +1,4 @@
 import { Component } from '@angular/core';
-import { KnowledgeService } from '../../../../services/knowledge.service';
 import { KnowledgeRiskLevelComponent } from './knowledge-risk-level/knowledge-risk-level.component';
 import { KnowledgeRiskTypeComponent } from './knowledge-risk-type/knowledge-risk-type.component';
 
@@ -26,9 +25,6 @@ export class RiskKnowledgeComponent {
     // },
   ];
   activeTab = this.tabs[0].value;
-  constructor(private readonly knowledge: KnowledgeService) {
-    knowledge.init();
-  }
 
   changeTab(tab: string) {
     this.activeTab = tab;

+ 3 - 1
src/app/pages/manager/risk/risk-list/risk-list.component.html

@@ -35,7 +35,9 @@
             (change)="changeLevel($event!)"
           ></filter-button-group-with-count>
         </div>
-        <div class="flex-center pt-4"><data-empty [isEmpty]="filteredList.length === 0"></data-empty></div>
+        <div class="flex-center pt-4">
+          <data-empty [isEmpty]="filteredList.length === 0"></data-empty>
+        </div>
         <div class="list-container custom-scroll-bar" [class.half]="showDetail">
           <div class="card-list">
             @for (item of filteredList; track $index) {

+ 1 - 1
src/app/pages/manager/risk/risk-list/risk-list.component.ts

@@ -4,7 +4,7 @@ import { CommonNzModule } from '../../../../common.nz.module';
 import { ApiService } from '../../../../services/api.service';
 import { KnowledgeService } from '../../../../services/knowledge.service';
 import { DataEmptyComponent } from '../../../../shared/data-empty/data-empty.component';
-import { FilterButtonGroupWithCountComponent } from '../../../../shared/filter-button-group-with-conunt/filter-button-group-with-count.component';
+import { FilterButtonGroupWithCountComponent } from '../../../../shared/filter-button-group-with-count/filter-button-group-with-count.component';
 import { RiskTypeCategoryNavComponent } from '../../../../shared/risk-type-category-nav/risk-type-category-nav.component';
 import { StarIconComponent } from '../../../../shared/star/star.icon';
 import { ControlInfoComponent } from './control-info/control-info.component';

+ 1 - 6
src/app/pages/manager/risk/risk.component.ts

@@ -1,6 +1,5 @@
 import { Component } from '@angular/core';
 import { RouterOutlet } from '@angular/router';
-import { KnowledgeService } from '../../../services/knowledge.service';
 
 @Component({
   selector: 'app-risk-control',
@@ -9,8 +8,4 @@ import { KnowledgeService } from '../../../services/knowledge.service';
   template: `<router-outlet></router-outlet>`,
   styleUrl: './risk.component.less',
 })
-export class RiskControlComponent {
-  constructor(private knowledge: KnowledgeService) {
-    knowledge.init();
-  }
-}
+export class RiskControlComponent {}

+ 1 - 6
src/app/pages/manager/workbench/workbench.component.ts

@@ -1,6 +1,5 @@
 import { Component } from '@angular/core';
 import { RouterOutlet } from '@angular/router';
-import { KnowledgeService } from '../../../services/knowledge.service';
 
 @Component({
   selector: 'app-workbench',
@@ -9,8 +8,4 @@ import { KnowledgeService } from '../../../services/knowledge.service';
   templateUrl: './workbench.component.html',
   styleUrl: './workbench.component.less',
 })
-export class WorkbenchComponent {
-  constructor(private readonly knowledge: KnowledgeService) {
-    knowledge.init();
-  }
-}
+export class WorkbenchComponent {}

+ 3 - 16
src/app/services/knowledge.service.ts

@@ -4,16 +4,6 @@ import { getLevelColor } from '../app.util';
 import { ApiService } from './api.service';
 import { SettingService } from './setting.service';
 
-const mapStringToCategory = (cStrings: string[]): Knowledge.RiskCategoryDto[] => {
-  return cStrings.map(c => ({
-    id: 0,
-    company: '',
-    value: c,
-    status: 0,
-    isDelete: 0,
-  }));
-};
-
 const mockLevels: Knowledge.RiskLevelDtoWithColor[] = [
   {
     id: 1,
@@ -246,8 +236,9 @@ export class KnowledgeService {
 
   async fetchRiskTypes() {
     this.api.knowledge.getRiskTypes().then(res => {
-      this.updateTypes(res.list);
+      this._types.set(res.list);
       this._typeUpdateDate.set(res.updateDate);
+      this.onTypesChange.next();
     });
   }
 
@@ -260,14 +251,10 @@ export class KnowledgeService {
   async fetchRiskItems() {
     this.api.knowledge.getAllItems().then(res => {
       this._riskItems.set(res);
+      this.onRiskItemsChange.next();
     });
   }
 
-  updateTypes(types: Knowledge.RiskTypeDto[]) {
-    this._types.set(types);
-    this.onTypesChange.next();
-  }
-
   updateLevels(levels: Knowledge.RiskLevelDto[]) {
     this._levels.set(
       levels.map(l => {

+ 0 - 0
src/app/shared/filter-button-group-with-conunt/filter-button-group-with-count.component.html → src/app/shared/filter-button-group-with-count/filter-button-group-with-count.component.html


+ 0 - 0
src/app/shared/filter-button-group-with-conunt/filter-button-group-with-count.component.less → src/app/shared/filter-button-group-with-count/filter-button-group-with-count.component.less


+ 0 - 0
src/app/shared/filter-button-group-with-conunt/filter-button-group-with-count.component.ts → src/app/shared/filter-button-group-with-count/filter-button-group-with-count.component.ts


+ 0 - 0
src/app/shared/filter-button-group-with-conunt/filter-button-group.component.spec.ts → src/app/shared/filter-button-group-with-count/filter-button-group.component.spec.ts


+ 3 - 1
src/app/shared/risk-type-category-nav/risk-type-category-nav.component.html

@@ -25,7 +25,9 @@
           [class.is-empty]="!emptyAbleToSelect && category.count === 0"
           (click)="changeCategory(category)"
         >
-          <span class="text-block">{{ category.label }} {{ category.count ? '(' + category.count + ')' : '' }}</span>
+          <span class="text-block"
+            >{{ category.label }} {{ showCount && category.count ? '(' + category.count + ')' : '' }}</span
+          >
         </div>
       }
     </div>

+ 1 - 2
src/app/shared/risk-type-category-nav/risk-type-category-nav.component.ts

@@ -9,6 +9,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
 })
 export class RiskTypeCategoryNavComponent {
   @Input() emptyAbleToSelect = false;
+  @Input() showCount = true;
   @Input() types: OptionWithCount<number>[] = [];
   @Input() categories: OptionWithCount<number>[] = [];
   @Input() selectedType = -1;
@@ -21,12 +22,10 @@ export class RiskTypeCategoryNavComponent {
 
   changeType(op: OptionWithCount<number>) {
     if (!op.count && !this.emptyAbleToSelect) return;
-    // this.selectedType = op.value;
     this.selectedTypeChange.emit(op.value);
   }
   changeCategory(op: OptionWithCount<number>) {
     if (!op.count && !this.emptyAbleToSelect) return;
-    // this.selectedCategory = op.value;
     this.selectedCategoryChange.emit(op.value);
   }
 }

+ 1 - 0
src/assets/icons/link.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 14a3.5 3.5 0 0 0 5 0l4-4a3.5 3.5 0 0 0-5-5l-.5.5"></path><path d="M14 10a3.5 3.5 0 0 0-5 0l-4 4a3.5 3.5 0 0 0 5 5l.5-.5"></path></g></svg>

+ 1 - 0
src/types/knowledge.d.ts

@@ -19,6 +19,7 @@ declare namespace Knowledge {
   interface RiskCategoryDto {
     id: number;
     company: string;
+    departments: number[];
     value: string;
     status: number;
     isDelete: number;