Browse Source

二期

main
kely 1 year ago
parent
commit
1a74c3044b
  1. 1
      .gitignore
  2. 7
      web-admin-app/README.md
  3. 4
      web-admin-app/proxy/devserver.js
  4. 2
      web-admin-app/src/app/app.config.ts
  5. 226
      web-admin-app/src/app/app.routes.ts
  6. 44
      web-admin-app/src/app/components/asset-basic-team-form/asset-basic-team-form.component.html
  7. 0
      web-admin-app/src/app/components/asset-basic-team-form/asset-basic-team-form.component.less
  8. 92
      web-admin-app/src/app/components/asset-basic-team-form/asset-basic-team-form.component.ts
  9. 80
      web-admin-app/src/app/components/asset-form/asset-form.component.html
  10. 76
      web-admin-app/src/app/components/asset-form/asset-form.component.ts
  11. 19
      web-admin-app/src/app/components/component-basic-category-tree/component-basic-category-tree.component.ts
  12. 1
      web-admin-app/src/app/components/flow-form-create/flow-form-create.component.html
  13. 0
      web-admin-app/src/app/components/flow-form-create/flow-form-create.component.less
  14. 12
      web-admin-app/src/app/components/flow-form-create/flow-form-create.component.ts
  15. 3
      web-admin-app/src/app/components/index.ts
  16. 84
      web-admin-app/src/app/components/maintain-record-form/maintain-record-form.component.html
  17. 0
      web-admin-app/src/app/components/maintain-record-form/maintain-record-form.component.less
  18. 117
      web-admin-app/src/app/components/maintain-record-form/maintain-record-form.component.ts
  19. 37
      web-admin-app/src/app/components/plan-task/calendar-list/calendar-list.component.html
  20. 22
      web-admin-app/src/app/components/plan-task/calendar-list/calendar-list.component.less
  21. 54
      web-admin-app/src/app/components/plan-task/calendar-list/calendar-list.component.ts
  22. 152
      web-admin-app/src/app/components/plan-task/plan-form/plan-form.component.html
  23. 5
      web-admin-app/src/app/components/plan-task/plan-form/plan-form.component.less
  24. 160
      web-admin-app/src/app/components/plan-task/plan-form/plan-form.component.ts
  25. 38
      web-admin-app/src/app/components/plan-task/plan-list/plan-list.component.html
  26. 0
      web-admin-app/src/app/components/plan-task/plan-list/plan-list.component.less
  27. 128
      web-admin-app/src/app/components/plan-task/plan-list/plan-list.component.ts
  28. 73
      web-admin-app/src/app/components/plan-task/repair-task-form/repair-task-form.component.html
  29. 0
      web-admin-app/src/app/components/plan-task/repair-task-form/repair-task-form.component.less
  30. 151
      web-admin-app/src/app/components/plan-task/repair-task-form/repair-task-form.component.ts
  31. 95
      web-admin-app/src/app/components/plan-task/task-form/task-form.component.html
  32. 0
      web-admin-app/src/app/components/plan-task/task-form/task-form.component.less
  33. 152
      web-admin-app/src/app/components/plan-task/task-form/task-form.component.ts
  34. 32
      web-admin-app/src/app/components/plan-task/task-list/task-list.component.html
  35. 0
      web-admin-app/src/app/components/plan-task/task-list/task-list.component.less
  36. 153
      web-admin-app/src/app/components/plan-task/task-list/task-list.component.ts
  37. 25
      web-admin-app/src/app/components/select-user-by-org/select-user-by-org.component.ts
  38. 11
      web-admin-app/src/app/components/status-tag/status-tag.component.html
  39. 0
      web-admin-app/src/app/components/status-tag/status-tag.component.less
  40. 17
      web-admin-app/src/app/components/status-tag/status-tag.component.ts
  41. 46
      web-admin-app/src/app/constants/index.ts
  42. 73
      web-admin-app/src/app/pages/fixed-asset/asset-management/asset-management.component.html
  43. 0
      web-admin-app/src/app/pages/fixed-asset/asset-management/asset-management.component.less
  44. 194
      web-admin-app/src/app/pages/fixed-asset/asset-management/asset-management.component.ts
  45. 59
      web-admin-app/src/app/pages/fixed-asset/basic/asset-user-group/asset-user-group.component.html
  46. 0
      web-admin-app/src/app/pages/fixed-asset/basic/asset-user-group/asset-user-group.component.less
  47. 125
      web-admin-app/src/app/pages/fixed-asset/basic/asset-user-group/asset-user-group.component.ts
  48. 324
      web-admin-app/src/app/pages/fixed-asset/basic/basic-category/basic-category.component.html
  49. 133
      web-admin-app/src/app/pages/fixed-asset/basic/basic-category/basic-category.component.ts
  50. 219
      web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form-manage/basic-flow-form-manage.component.html
  51. 8
      web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form-manage/basic-flow-form-manage.component.less
  52. 198
      web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form-manage/basic-flow-form-manage.component.ts
  53. 71
      web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form/basic-flow-form.component.html
  54. 0
      web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form/basic-flow-form.component.less
  55. 117
      web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form/basic-flow-form.component.ts
  56. 209
      web-admin-app/src/app/pages/fixed-asset/fixed-asset.component.html
  57. 106
      web-admin-app/src/app/pages/fixed-asset/maintain/maintain-on-off/maintain-on-off.component.html
  58. 0
      web-admin-app/src/app/pages/fixed-asset/maintain/maintain-on-off/maintain-on-off.component.less
  59. 105
      web-admin-app/src/app/pages/fixed-asset/maintain/maintain-on-off/maintain-on-off.component.ts
  60. 38
      web-admin-app/src/app/pages/fixed-asset/maintain/maintain-record/maintain-record.component.html
  61. 0
      web-admin-app/src/app/pages/fixed-asset/maintain/maintain-record/maintain-record.component.less
  62. 97
      web-admin-app/src/app/pages/fixed-asset/maintain/maintain-record/maintain-record.component.ts
  63. 1
      web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-calendar/inspection-calendar.component.html
  64. 0
      web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-calendar/inspection-calendar.component.less
  65. 12
      web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-calendar/inspection-calendar.component.ts
  66. 1
      web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-plan/inspection-plan.component.html
  67. 0
      web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-plan/inspection-plan.component.less
  68. 13
      web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-plan/inspection-plan.component.ts
  69. 1
      web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-task/inspection-task.component.html
  70. 0
      web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-task/inspection-task.component.less
  71. 12
      web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-task/inspection-task.component.ts
  72. 1
      web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-calendar/maintenance-calendar.component.html
  73. 0
      web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-calendar/maintenance-calendar.component.less
  74. 12
      web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-calendar/maintenance-calendar.component.ts
  75. 1
      web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-plan/maintenance-plan.component.html
  76. 0
      web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-plan/maintenance-plan.component.less
  77. 12
      web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-plan/maintenance-plan.component.ts
  78. 1
      web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-task/maintenance-task.component.html
  79. 0
      web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-task/maintenance-task.component.less
  80. 12
      web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-task/maintenance-task.component.ts
  81. 1
      web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-calendar/stocktaking-calendar.component.html
  82. 0
      web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-calendar/stocktaking-calendar.component.less
  83. 12
      web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-calendar/stocktaking-calendar.component.ts
  84. 1
      web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-plan/stocktaking-plan.component.html
  85. 0
      web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-plan/stocktaking-plan.component.less
  86. 12
      web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-plan/stocktaking-plan.component.ts
  87. 1
      web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-task/stocktaking-task.component.html
  88. 0
      web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-task/stocktaking-task.component.less
  89. 12
      web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-task/stocktaking-task.component.ts
  90. 283
      web-admin-app/src/app/pages/fixed-asset/registration/registration.component.html
  91. 0
      web-admin-app/src/app/pages/fixed-asset/registration/registration.component.less
  92. 208
      web-admin-app/src/app/pages/fixed-asset/registration/registration.component.ts
  93. 145
      web-admin-app/src/app/pages/flow/flow-main/flow-main.component.html
  94. 6
      web-admin-app/src/app/pages/flow/flow-main/flow-main.component.less
  95. 35
      web-admin-app/src/app/pages/flow/flow-main/flow-main.component.ts
  96. 16
      web-admin-app/src/app/pages/system/index/system.component.html
  97. 63
      web-admin-app/src/app/pages/system/system-address/system-address.component.html
  98. 0
      web-admin-app/src/app/pages/system/system-address/system-address.component.less
  99. 80
      web-admin-app/src/app/pages/system/system-address/system-address.component.ts
  100. 81
      web-admin-app/src/app/pages/system/system-warehouse/system-warehouse.component.html

1
.gitignore

@ -0,0 +1 @@
version 2

7
web-admin-app/README.md

@ -86,3 +86,10 @@
- ~~归还 #~~
- ~~库存 列表字段 / 仓库、分类字段~~
- ~~ 我处理 不要作废 ~~
# v2
## 10-10
-

4
web-admin-app/proxy/devserver.js

@ -1,6 +1,6 @@
// const remoteTarget = "http://10.168.1.60:8300";
const remoteTarget = 'http://47.109.27.8:8280/'
const localTarget = 'http://47.109.27.8:8280/'
const remoteTarget = 'http://47.109.27.8:8282/'
const localTarget = 'http://47.109.27.8:8282/'
const devProxy = (remote) => {
let config = {}

2
web-admin-app/src/app/app.config.ts

@ -26,7 +26,7 @@ const disabledLog = () => {
}
}
disabledLog()
// disabledLog()
export function initializeApp(configService: ServerPaginatedTableService) {
return () => {

226
web-admin-app/src/app/app.routes.ts

@ -62,6 +62,24 @@ import { FixedAssetStorageComponent } from './pages/fixed-asset/ledger/fixed-ass
import { HomeComponent } from './pages/home/home.component'
import { LicensePageComponent } from './pages/license/license.component'
import { SystemLicenseComponent } from './pages/system/license/license.component'
import { RegistrationComponent } from './pages/fixed-asset/registration/registration.component'
import { SystemWarehouseComponent } from './pages/system/system-warehouse/system-warehouse.component'
import { SystemAddressComponent } from './pages/system/system-address/system-address.component'
import { BasicFlowFormComponent } from './pages/fixed-asset/basic/basic-flow-form/basic-flow-form.component'
import { BasicFlowFormManageComponent } from './pages/fixed-asset/basic/basic-flow-form-manage/basic-flow-form-manage.component'
import { MaintainRecordComponent } from './pages/fixed-asset/maintain/maintain-record/maintain-record.component'
import { MaintainOnOffComponent } from './pages/fixed-asset/maintain/maintain-on-off/maintain-on-off.component'
import { AssetManagementComponent } from './pages/fixed-asset/asset-management/asset-management.component'
import { AssetUserGroupComponent } from './pages/fixed-asset/basic/asset-user-group/asset-user-group.component'
import { InspectionPlanComponent } from './pages/fixed-asset/plan-task/inspection-plan/inspection-plan.component'
import { InspectionTaskComponent } from './pages/fixed-asset/plan-task/inspection-task/inspection-task.component'
import { InspectionCalendarComponent } from './pages/fixed-asset/plan-task/inspection-calendar/inspection-calendar.component'
import { MaintenanceTaskComponent } from './pages/fixed-asset/plan-task/maintenance-task/maintenance-task.component'
import { MaintenanceCalendarComponent } from './pages/fixed-asset/plan-task/maintenance-calendar/maintenance-calendar.component'
import { MaintenancePlanComponent } from './pages/fixed-asset/plan-task/maintenance-plan/maintenance-plan.component'
import { StocktakingPlanComponent } from './pages/fixed-asset/plan-task/stocktaking-plan/stocktaking-plan.component'
import { StocktakingTaskComponent } from './pages/fixed-asset/plan-task/stocktaking-task/stocktaking-task.component'
import { StocktakingCalendarComponent } from './pages/fixed-asset/plan-task/stocktaking-calendar/stocktaking-calendar.component'
export const routes: Routes = [
{
@ -172,6 +190,27 @@ export const routes: Routes = [
},
},
},
{
path: 'place',
title: '场所地址',
children: [
{
path: '',
redirectTo: 'warehouse',
pathMatch: 'full',
},
{
path: 'warehouse',
title: '仓库管理',
component: SystemWarehouseComponent,
},
{
path: 'address',
title: '地址管理',
component: SystemAddressComponent,
},
],
},
{
path: 'flow',
canActivate: [permissionGuard],
@ -311,6 +350,16 @@ export const routes: Routes = [
},
],
},
{
path: 'registration',
component: RegistrationComponent,
title: '资产登记',
},
{
path: 'management',
component: AssetManagementComponent,
title: '资产管理',
},
{
path: 'repair',
title: '维护维保',
@ -389,6 +438,27 @@ export const routes: Routes = [
},
],
},
{
path: 'maintain',
title: '运维管理',
children: [
{
path: '',
pathMatch: 'full',
redirectTo: 'record',
},
{
path: 'record',
component: MaintainRecordComponent,
title: '维修登记',
},
{
path: 'on-off',
title: '开关机',
component: MaintainOnOffComponent,
},
],
},
{
path: 'basic',
title: '基础数据',
@ -396,7 +466,26 @@ export const routes: Routes = [
{
path: '',
pathMatch: 'full',
redirectTo: 'goods-stock',
redirectTo: 'category',
},
{
path: 'flow-form',
title: '流程表单',
children: [
{
path: '',
pathMatch: 'full',
redirectTo: 'list',
},
{
path: 'list',
component: BasicFlowFormComponent,
},
{
path: 'manage/:id',
component: BasicFlowFormManageComponent,
},
],
},
{
path: 'repair-type',
@ -411,7 +500,7 @@ export const routes: Routes = [
{
path: 'category',
component: BasicCategoryComponent,
title: '物品分类',
title: '资产分类',
},
{
path: 'save-position',
@ -438,6 +527,63 @@ export const routes: Routes = [
component: BasicWarehouseComponent,
title: '存放仓库',
},
{
path: 'team',
component: AssetUserGroupComponent,
title: '班组管理',
},
],
},
{
path: 'inspection',
title: '巡检管理',
children: [
{
path: '',
pathMatch: 'full',
redirectTo: 'plan',
},
{
title: '巡检计划',
path: 'plan',
component: InspectionPlanComponent,
},
{
title: '巡检任务',
path: 'task',
component: InspectionTaskComponent,
},
{
title: '巡检日历',
path: 'calendar',
component: InspectionCalendarComponent,
},
],
},
{
path: 'maintenance',
title: '保养管理',
children: [
{
path: '',
pathMatch: 'full',
redirectTo: 'plan',
},
{
title: '保养计划',
path: 'plan',
component: MaintenancePlanComponent,
},
{
title: '保养任务',
path: 'task',
component: MaintenanceTaskComponent,
},
{
title: '保养日历',
path: 'calendar',
component: MaintenanceCalendarComponent,
},
],
},
{
@ -447,41 +593,67 @@ export const routes: Routes = [
{
path: '',
pathMatch: 'full',
redirectTo: 'job',
redirectTo: 'plan',
},
{
path: 'job',
title: '盘点任务',
children: [
{
path: '',
pathMatch: 'full',
redirectTo: 'list',
},
{
path: 'list',
component: StockakingJobComponent,
},
{
path: 'detail/:id',
title: '盘点明细',
component: StocktakingDetailComponent,
},
],
title: '盘点计划',
path: 'plan',
component: StocktakingPlanComponent,
},
{
path: 'job',
component: StockakingJobComponent,
title: '盘点任务',
path: 'task',
component: StocktakingTaskComponent,
},
{
path: 'plan',
component: StockakingPlanComponent,
title: '盘点计划',
title: '盘点日历',
path: 'calendar',
component: StocktakingCalendarComponent,
},
],
},
// {
// path: 'stocktaking',
// title: '盘点管理',
// children: [
// {
// path: '',
// pathMatch: 'full',
// redirectTo: 'job',
// },
// {
// path: 'job',
// title: '盘点任务',
// children: [
// {
// path: '',
// pathMatch: 'full',
// redirectTo: 'list',
// },
// {
// path: 'list',
// component: StockakingJobComponent,
// },
// {
// path: 'detail/:id',
// title: '盘点明细',
// component: StocktakingDetailComponent,
// },
// ],
// },
// {
// path: 'job',
// component: StockakingJobComponent,
// title: '盘点任务',
// },
// {
// path: 'plan',
// component: StockakingPlanComponent,
// title: '盘点计划',
// },
// ],
// },
{
path: 'alert',
title: '预警中心',

44
web-admin-app/src/app/components/asset-basic-team-form/asset-basic-team-form.component.html

@ -0,0 +1,44 @@
<div class="modal">
<form nz-form [formGroup]="formGroup" nzLayout="vertical">
<div class="overflow-hidden">
<nz-form-item>
<nz-form-label nzRequired>班组名称</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input nz-input placeholder="请输入班组名称" formControlName="teamName" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzRequired>班组编号</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input nz-input placeholder="请输入班组编号" formControlName="teamKey" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzRequired>班组状态</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-radio-group formControlName="status">
<label nz-radio [nzValue]="0">停用</label>
<label nz-radio [nzValue]="1">启用</label>
</nz-radio-group>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzRequired>添加成员</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<app-select-user-by-org [radio]="false" (onSelect)="onUerChange($event)" formControlName="_value" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label>备注</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input nz-input placeholder="请输入班组名称" formControlName="remark" />
</nz-form-control>
</nz-form-item>
</div>
</form>
<ng-template #errorTpl let-control>
<form-error-tips [control]="control"></form-error-tips>
</ng-template>
</div>

0
web-admin-app/src/app/components/asset-basic-team-form/asset-basic-team-form.component.less

92
web-admin-app/src/app/components/asset-basic-team-form/asset-basic-team-form.component.ts

@ -0,0 +1,92 @@
import { Component, Input, OnInit, inject } from '@angular/core'
import { FormBuilder, FormGroup } from '@angular/forms'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { FormValidators, Utils } from 'app/utils'
import { NzMessageService } from 'ng-zorro-antd/message'
import { OrgSelectComponent } from '../org-select/org-select.component'
import { SelectUserByOrgComponent } from '../select-user-by-org/select-user-by-org.component'
import { PositionSelectComponent } from '../position-select/position-select.component'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NZ_MODAL_DATA } from 'ng-zorro-antd/modal'
import { SupplierSelectComponent } from '../supplier-select/supplier-select.component'
import { AssetSelectComponent } from '../asset-select/asset-select.component'
import { WarehouseSelectComponent } from '../warehouse-select/warehouse-select.component'
@Component({
selector: 'app-asset-basic-team-form',
standalone: true,
imports: [
SharedModule,
SelectUserByOrgComponent,
SupplierSelectComponent,
AssetSelectComponent,
OrgSelectComponent,
PositionSelectComponent,
WarehouseSelectComponent,
],
templateUrl: './asset-basic-team-form.component.html',
styleUrl: './asset-basic-team-form.component.less',
})
export class AssetBasicTeamFormComponent {
constructor(
private fb: FormBuilder,
private api: ApiService,
private msg: NzMessageService,
) {}
readonly data: NzSafeAny = inject(NZ_MODAL_DATA)
formGroup!: FormGroup
groupIndex = 0
uploadLoading = false
ngOnInit(): void {
this.formGroup = this.fb.group({
teamId: this.fb.control(null, []),
teamName: this.fb.control('', [FormValidators.required('请输入')]),
teamKey: this.fb.control('', [FormValidators.required('请输入')]),
// useUserId: this.fb.control(null, [FormValidators.required('请选择')]),
// useOrganizationId: this.fb.control(null, [FormValidators.required('请选择')]),
status: this.fb.control(1, [FormValidators.required('请选择')]),
_value: this.fb.control([], [FormValidators.required('请选择')]),
remark: this.fb.control(null, []),
})
this.patchValues()
}
patchValues() {
const { value: data, preview } = this.data
if (data) {
this.formGroup.patchValue({
...data,
_value: data?._value?.map((i: NzSafeAny) => i.userId),
})
}
if (preview) {
this.formGroup.disable()
}
}
public getValues() {
let values = null
if (FormValidators.validateFormGroup(this.formGroup)) {
const v = this.formGroup.value
values = {
...v,
_value: this.selectedUser,
}
}
return values
}
selectedUser = []
onUerChange(e: any) {
this.selectedUser = e
}
}

80
web-admin-app/src/app/components/asset-form/asset-form.component.html

@ -30,11 +30,35 @@
}
<ng-template #basicTpl>
<div nz-row [nzGutter]="24">
<!-- @if (!data) {
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label>扩展属性</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-select
nzPlaceHolder="请选择"
[(ngModel)]="ext"
(ngModelChange)="onExtraChange($event)"
[ngModelOptions]="{ standalone: true }"
>
@for (item of flowForms; track $index) {
<nz-option [nzLabel]="item.formName" [nzValue]="item.formTempId" />
}
</nz-select>
</nz-form-control>
</nz-form-item>
</div>
} -->
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>资产分类</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<app-asset-category-select formControlName="categoryId"></app-asset-category-select>
<app-asset-category-select
#assetCategorySelect
formControlName="categoryId"
(ngModelChange)="onExtraChange($event)"
/>
</nz-form-control>
</nz-form-item>
</div>
@ -163,6 +187,60 @@
</nz-form-item>
</div>
</div>
<div formArrayName="_extInfo">
@if (extraFields.length > 0) {
<div class="text-lg mb-6">扩展信息</div>
<div nz-row [nzGutter]="24">
@for (item of extraFields; track item.key) {
<div nz-col nzSpan="8" [formGroupName]="$index">
<nz-form-item>
<nz-form-label>{{ item.name }}</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
@switch (item.type) {
@case ('DATE') {
<nz-date-picker
class="!w-full"
placeholder="请输入"
[formControlName]="'value'"
/>
}
@case ('RADIO') {
<ng-container *ngIf="item?.value?.fields as fields">
<nz-radio-group [formControlName]="'value'" class="radio">
<label
*ngFor="let f of fields; let i = index"
nz-radio
[nzValue]="f"
>
{{ f }}
</label>
</nz-radio-group>
</ng-container>
}
@case ('NUMBER') {
<nz-input-number
class="!w-full"
nz-input
placeholder="请输入"
[formControlName]="'value'"
/>
}
@default {
<input
class="w-full"
nz-input
placeholder="请输入"
[formControlName]="'value'"
/>
}
}
</nz-form-control>
</nz-form-item>
</div>
}
</div>
}
</div>
</ng-template>
<ng-template #maintainTpl>
<div nz-row [nzGutter]="24">

76
web-admin-app/src/app/components/asset-form/asset-form.component.ts

@ -1,5 +1,5 @@
import { Component, Input, OnInit, inject } from '@angular/core'
import { FormBuilder, FormGroup } from '@angular/forms'
import { Component, Input, OnInit, ViewChild, inject } from '@angular/core'
import { FormArray, FormBuilder, FormGroup } from '@angular/forms'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { FormValidators, Utils } from 'app/utils'
@ -40,6 +40,8 @@ export class AssetFormComponent implements OnInit {
private msg: NzMessageService,
) {}
@ViewChild('assetCategorySelect') assetCategorySelect!: AssetCategorySelectComponent
readonly data: NzSafeAny = inject(NZ_MODAL_DATA)
formGroup!: FormGroup
@ -56,13 +58,22 @@ export class AssetFormComponent implements OnInit {
financialCategory: NzSafeAny[] = []
flowForms: NzSafeAny[] = []
extraFields: NzSafeAny[] = []
ngOnInit(): void {
// this.api.getFlowFormList().subscribe((res) => {
// this.flowForms = res.body
// })
this.formGroup = this.fb.group({
assetId: this.fb.control(null, []),
name: this.fb.control('', [FormValidators.required('请输入')]),
categoryId: this.fb.control(null, [FormValidators.required('请选择')]),
ownCompanyId: this.fb.control(null, [FormValidators.required('请选择')]),
status: this.fb.control(null, [FormValidators.required('请选择')]),
// flowForm: this.fb.control(null, [FormValidators.required('请选择')]),
sourceId: this.fb.control(null, []),
unit: this.fb.control(null, []),
positionId: this.fb.control(null, []),
@ -96,6 +107,8 @@ export class AssetFormComponent implements OnInit {
taxAmountRate: this.fb.control(null, []),
totalAmountPrice: this.fb.control(null, []),
registerDate: this.fb.control(null, []),
_extInfo: this.fb.array([]),
})
this.patchValues()
@ -105,10 +118,52 @@ export class AssetFormComponent implements OnInit {
})
}
get extInfo(): FormArray {
return this.formGroup.get('_extInfo') as FormArray
}
onExtraChange(v: any) {
let extraFields: NzSafeAny[] = []
try {
const formValue = this.assetCategorySelect.originTreeData.find((f) => f.categoryId === Number(v))
?._assetExtTemp
extraFields = formValue ?? []
} catch (error) {}
this.setExtraFields(extraFields)
}
ext = null
setExtraFields(fields: NzSafeAny[]) {
this.extInfo.clear()
this.extraFields = fields
.sort((a, b) => a.sort - b.sort)
.map((i) => {
let val = i.value
if (i.type === 'RADIO') {
val = i.value?.value
} else if (i.type === 'DATE') {
val = new Date(i.value)
}
this.extInfo.push(
this.fb.group({
key: this.fb.control(i.key),
name: this.fb.control(i.name),
remark: this.fb.control(i.remark),
sort: this.fb.control(i.sort),
type: this.fb.control(i.type),
value: this.fb.control(val),
fields: this.fb.control(i.type === 'RADIO' ? i.value?.fields : []),
}),
)
return i
})
}
patchValues() {
const { value: data, preview } = this.data
if (data) {
console.log('data', data)
this.formGroup.patchValue({
...data,
useUserId: data._useUser?.userId ? [data._useUser?.userId] : [],
@ -123,6 +178,7 @@ export class AssetFormComponent implements OnInit {
maintenanceVendor: data._maintenanceVendor?.maintenanceVendorId,
manufacturersVendorId: data._manufacturersVendor?.manufacturersVendorId,
})
this.setExtraFields(data._extInfo)
}
if (preview) {
this.formGroup.disable()
@ -133,7 +189,7 @@ export class AssetFormComponent implements OnInit {
let values = null
if (FormValidators.validateFormGroup(this.formGroup)) {
const v = this.formGroup.getRawValue()
console.log('v', v)
values = {
...v,
useUserId: v.useUserId?.[0],
@ -143,6 +199,18 @@ export class AssetFormComponent implements OnInit {
positionId: v.positionId,
useOrganizationId: v.useOrganizationId,
responsiblePerson: v.responsiblePerson?.[0],
_extInfo: this.extInfo.value.map((v: any) => {
if (v.type === 'RADIO') {
return {
...v,
value: {
value: v.value,
fields: v.fields.map((i: string) => i),
},
}
}
return v
}),
}
}
return values

19
web-admin-app/src/app/components/component-basic-category-tree/component-basic-category-tree.component.ts

@ -1,13 +1,17 @@
import { CommonModule } from '@angular/common'
import { Component, EventEmitter, Input, OnInit, Output, TemplateRef } from '@angular/core'
import { FormBuilder, FormGroup } from '@angular/forms'
import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { FormValidators } from 'app/utils'
import { NzButtonModule } from 'ng-zorro-antd/button'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NzDrawerRef, NzDrawerService } from 'ng-zorro-antd/drawer'
import { NzDropDownModule } from 'ng-zorro-antd/dropdown'
import { NzInputModule } from 'ng-zorro-antd/input'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzModalService } from 'ng-zorro-antd/modal'
import { NzFormatEmitEvent, NzTreeNodeOptions } from 'ng-zorro-antd/tree'
import { NzFormatEmitEvent, NzTreeModule, NzTreeNodeOptions } from 'ng-zorro-antd/tree'
interface CateGoryInterface {
categoryId: number
@ -54,7 +58,15 @@ export function buildCateTree(organizations: CateGoryInterface[]): NzTreeNodeOpt
@Component({
selector: 'app-component-basic-category-tree',
standalone: true,
imports: [SharedModule],
imports: [
NzDropDownModule,
NzTreeModule,
NzInputModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
NzButtonModule,
],
templateUrl: './component-basic-category-tree.component.html',
styleUrl: './component-basic-category-tree.component.less',
})
@ -131,7 +143,6 @@ export class ComponentBasicCategoryTreeComponent {
.subscribe((res) => {
this.expandedKeys.push(String(parentId))
this.initTree()
this.msg.success(res.desc)
})
}

1
web-admin-app/src/app/components/flow-form-create/flow-form-create.component.html

@ -0,0 +1 @@
<p>flow-form-create works!</p>

0
web-admin-app/src/app/components/flow-form-create/flow-form-create.component.less

12
web-admin-app/src/app/components/flow-form-create/flow-form-create.component.ts

@ -0,0 +1,12 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-flow-form-create',
standalone: true,
imports: [],
templateUrl: './flow-form-create.component.html',
styleUrl: './flow-form-create.component.less'
})
export class FlowFormCreateComponent {
}

3
web-admin-app/src/app/components/index.ts

@ -38,3 +38,6 @@ export * from './apply-asset-flow/eam-asset-purchase-apply/eam-asset-purchase-ap
export * from './apply-asset-flow/eam-asset-employee-handover/eam-asset-employee-handover.component'
export * from './apply-asset-flow/eam-asset-equipment-repair/eam-asset-equipment-repair.component'
export * from './apply-asset-flow/eam-asset-stock-goods-use/eam-asset-stock-goods-use.component'
export * from './status-tag/status-tag.component'
export * from './flow-form-create/flow-form-create.component'

84
web-admin-app/src/app/components/maintain-record-form/maintain-record-form.component.html

@ -0,0 +1,84 @@
<div class="modal">
<form nz-form [formGroup]="formGroup" nzLayout="vertical">
<div class="overflow-hidden">
<div nz-row [nzGutter]="24">
<div nz-col [nzSpan]="6">
<nz-form-item>
<nz-form-label nzRequired>业务名称</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input nz-input placeholder="请输入业务名称" formControlName="name" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="6">
<nz-form-item>
<nz-form-label>业务编号</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input nz-input placeholder="请输入业务编号" formControlName="businessId" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="6">
<nz-form-item>
<nz-form-label nzRequired>维修类型</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-select nzPlaceHolder="请选择维修类型" formControlName="repairTypeId">
@for (item of types; track $index) {
<nz-option [nzLabel]="item.name" [nzValue]="item.repairTypeId"></nz-option>
}
</nz-select>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="6">
<nz-form-item>
<nz-form-label nzRequired>计划完成时间</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-date-picker class="w-full" formControlName="plannedDate" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="6">
<nz-form-item>
<nz-form-label>附件</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<button class="upload-btn" nz-button [nzLoading]="uploadLoading">
<i nz-icon nzType="upload"></i>
选择文件
<input type="file" (change)="onFileChange($event)" />
</button>
@if (formGroup.get('attach')?.value) {
<div class="mt-1">
<nz-tag class="break-words w-full !whitespace-pre-wrap">
{{ formGroup.get('attach')?.value }}
</nz-tag>
</div>
}
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="18">
<nz-form-item>
<nz-form-label>维修说明</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<textarea nz-input placeholder="请输入维修说明" formControlName="notes"></textarea>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="24">
<nz-form-item>
<nz-form-label>资产列表</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<app-asset-select formControlName="assetIdList" />
</nz-form-control>
</nz-form-item>
</div>
</div>
</div>
</form>
<ng-template #errorTpl let-control>
<form-error-tips [control]="control"></form-error-tips>
</ng-template>
</div>

0
web-admin-app/src/app/components/maintain-record-form/maintain-record-form.component.less

117
web-admin-app/src/app/components/maintain-record-form/maintain-record-form.component.ts

@ -0,0 +1,117 @@
import { Component, Input, OnInit, inject } from '@angular/core'
import { FormBuilder, FormGroup } from '@angular/forms'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { FormValidators, Utils } from 'app/utils'
import { NzMessageService } from 'ng-zorro-antd/message'
import { AssetCategorySelectComponent } from '../asset-category-select/asset-category-select.component'
import { OrgSelectComponent } from '../org-select/org-select.component'
import { ASSET_SOURCE_MAP, ASSET_STATUS, MAINTENANCE_STATUS, MAINTENANCE_TYPE, MAX_PAGE_SIZE } from 'app/constants'
import { SelectUserByOrgComponent } from '../select-user-by-org/select-user-by-org.component'
import { ManufacturerSelectComponent } from '../manufacturer-select/manufacturer-select.component'
import { PositionSelectComponent } from '../position-select/position-select.component'
import { MaintenanceSelectComponent } from '../maintenance-select/maintenance-select.component'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NZ_MODAL_DATA } from 'ng-zorro-antd/modal'
import { SupplierSelectComponent } from '../supplier-select/supplier-select.component'
import { AssetSelectComponent } from '../asset-select/asset-select.component'
@Component({
selector: 'app-maintain-record-form',
standalone: true,
imports: [SharedModule, SelectUserByOrgComponent, SupplierSelectComponent, AssetSelectComponent],
templateUrl: './maintain-record-form.component.html',
styleUrl: './maintain-record-form.component.less',
})
export class MaintainRecordFormComponent {
constructor(
private fb: FormBuilder,
private api: ApiService,
private msg: NzMessageService,
) {}
readonly data: NzSafeAny = inject(NZ_MODAL_DATA)
formGroup!: FormGroup
groupIndex = 0
uploadLoading = false
types: NzSafeAny[] = []
ngOnInit(): void {
this.formGroup = this.fb.group({
id: this.fb.control(null, []),
name: this.fb.control('', [FormValidators.required('请输入')]),
repairTypeId: this.fb.control(null, [FormValidators.required('请输入')]),
businessId: this.fb.control(null, []),
plannedDate: this.fb.control(null, [FormValidators.required('请输入')]),
notes: this.fb.control(null, []),
attach: this.fb.control('', []),
assetIdList: this.fb.control([], []),
})
this.api.getRepairTypePage({ pageSize: MAX_PAGE_SIZE }).subscribe((res) => {
this.types = res.body.rows
})
this.patchValues()
}
patchValues() {
const { value: v, preview } = this.data
if (v) {
this.api.getRepairDetail(v.id).subscribe((res) => {
const data = res.body
this.formGroup.patchValue({
...data,
repairTypeId: data._repairType?.repairTypeId,
useUserId: data._useUser?.userId ? [data._useUser?.userId] : [],
manager: data._manager?.userId ? [data._manager?.userId] : [],
responsiblePerson: data._responsiblePerson?.userId ? [data._responsiblePerson?.userId] : [],
categoryId: data._category?.categoryId + '',
positionId: data._position?.positionId + '',
ownCompanyId: data._ownCompany?.organizationId + '',
useOrganizationId: data._useOrganization?.organizationId + '',
maintenanceVendor: data._maintenanceVendor?.maintenanceVendorId,
manufacturersVendorId: data._manufacturersVendor?.manufacturersVendorId,
})
})
}
if (preview) {
this.formGroup.disable()
}
}
public getValues() {
let values = null
if (FormValidators.validateFormGroup(this.formGroup)) {
const v = this.formGroup.value
values = {
...v,
useUserId: v.useUserId?.[0],
manager: v.manager?.[0],
categoryId: v.categoryId?.[0],
ownCompanyId: v.ownCompanyId?.[0],
positionId: v.positionId,
useOrganizationId: v.useOrganizationId?.[0],
responsiblePerson: v.responsiblePerson?.[0],
assetIdList: v.assetIdList,
}
}
return values
}
onFileChange(e: Event) {
const target = e.target as HTMLInputElement
const file = target.files![0]
target.value = ''
const formdata = new FormData()
formdata.append('file', file)
this.api.upload(formdata).subscribe((res) => {
this.formGroup.get('attach')?.setValue(res.body.fileName)
})
}
}

37
web-admin-app/src/app/components/plan-task/calendar-list/calendar-list.component.html

@ -0,0 +1,37 @@
<app-page>
<nz-calendar [(ngModel)]="date" [(nzMode)]="mode" (nzPanelChange)="panelChange($event)">
<ul *nzDateCell="let date" class="events">
@switch (date.getDate()) {
@case (8) {
@for (item of listDataMap.eight; track $index) {
<li>
<nz-badge [nzStatus]="item.type" [nzText]="item.content"></nz-badge>
</li>
}
}
@case (10) {
@for (item of listDataMap.ten; track $index) {
<li>
<nz-badge [nzStatus]="item.type" [nzText]="item.content"></nz-badge>
</li>
}
}
@case (11) {
@for (item of listDataMap.eleven; track $index) {
<li>
<nz-badge [nzStatus]="item.type" [nzText]="item.content"></nz-badge>
</li>
}
}
}
</ul>
<ng-container *nzMonthCell="let month">
@if (getMonthData(month); as monthData) {
<div class="notes-month">
<section>{{ monthData }}</section>
<span>Backlog number</span>
</div>
}
</ng-container>
</nz-calendar>
</app-page>

22
web-admin-app/src/app/components/plan-task/calendar-list/calendar-list.component.less

@ -0,0 +1,22 @@
.events {
list-style: none;
margin: 0;
padding: 0;
}
.events .ant-badge-status {
overflow: hidden;
white-space: nowrap;
width: 100%;
text-overflow: ellipsis;
font-size: 12px;
}
.notes-month {
text-align: center;
font-size: 28px;
}
.notes-month section {
font-size: 28px;
}

54
web-admin-app/src/app/components/plan-task/calendar-list/calendar-list.component.ts

@ -0,0 +1,54 @@
import { Component, Input } from '@angular/core'
import { SharedModule } from 'app/shared/shared.module'
import { PlanTaskType } from 'app/types'
import { NzCalendarMode } from 'ng-zorro-antd/calendar'
@Component({
selector: 'app-calendar-list',
standalone: true,
imports: [SharedModule],
templateUrl: './calendar-list.component.html',
styleUrl: './calendar-list.component.less',
})
export class CalendarListComponent {
constructor() {}
@Input() type: PlanTaskType = 'inspection'
date = new Date(2012, 11, 21)
mode: NzCalendarMode = 'month'
OnInit() {}
panelChange(change: { date: Date; mode: string }): void {
console.log(change.date, change.mode)
}
listDataMap = {
eight: [
{ type: 'warning', content: 'This is warning event.' },
{ type: 'success', content: 'This is usual event.' },
],
ten: [
{ type: 'warning', content: 'This is warning event.' },
{ type: 'success', content: 'This is usual event.' },
{ type: 'error', content: 'This is error event.' },
],
eleven: [
{ type: 'warning', content: 'This is warning event' },
{ type: 'success', content: 'This is very long usual event........' },
{ type: 'error', content: 'This is error event 1.' },
{ type: 'error', content: 'This is error event 2.' },
{ type: 'error', content: 'This is error event 3.' },
{ type: 'error', content: 'This is error event 4.' },
],
}
getMonthData(date: Date): number | null {
if (date.getMonth() === 8) {
return 1394
}
return null
}
}

152
web-admin-app/src/app/components/plan-task/plan-form/plan-form.component.html

@ -0,0 +1,152 @@
<div class="modal-container">
<form nz-form [formGroup]="formGroup" nzLayout="vertical">
<div class="overflow-hidden">
<div class="text-lg mb-2">基本信息</div>
<div nz-row [nzGutter]="24">
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>计划名称</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input nz-input formControlName="name" placeholder="请输入" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label>计划编号</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input nz-input formControlName="businessId" placeholder="请输入" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>执行班组</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-select nzPlaceHolder="请选择" formControlName="teamId" nzAllowClear nzShowSearch>
@for (item of teamList; track $index) {
<nz-option [nzLabel]="item.teamName" [nzValue]="item.teamId" />
}
</nz-select>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>计划类型</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-radio-group formControlName="cycleType">
<label nz-radio nzValue="day">日循环计划 </label>
<label nz-radio nzValue="week">周循环计划 </label>
<label nz-radio nzValue="month">月循环计划</label>
<label nz-radio nzValue="once">单任务计划</label>
</nz-radio-group>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>计划开始</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-date-picker class="!w-full" formControlName="expectedStartTime" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>计划结束</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-date-picker class="!w-full" formControlName="expectedFinishTime" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>任务开始</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-date-picker class="!w-full" nzShowTime formControlName="actualStartTime" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>任务时长</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-input-group nzAddOnAfter="天">
<nz-input-number class="!w-full" [nzMin]="0" formControlName="duration" />
</nz-input-group>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>顺序巡检</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-switch formControlName="order" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>超期限制</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-switch formControlName="limit" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>跳过周末</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-switch formControlName="skipWeekend" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="24">
<nz-form-item>
<nz-form-label>计划备注</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input nz-input placeholder="请输入" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col nzSpan="24">
<div class="text-lg mb-2">任务单据</div>
</div>
<div nz-col nzSpan="16">
<nz-form-item>
<nz-form-label nzRequired>表单</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-select nzPlaceHolder="请选择" formControlName="formTempId" nzAllowClear nzShowSearch>
@for (item of flowForms; track $index) {
<nz-option [nzLabel]="item.formName" [nzValue]="item.formTempId" />
}
</nz-select>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col nzSpan="8">
<nz-form-item>
<nz-form-label>开启拍照</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-switch formControlName="photo" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="24">
<nz-form-item>
<nz-form-label>资产列表</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<app-asset-select [storage]="true" formControlName="assetIdList" />
</nz-form-control>
</nz-form-item>
</div>
</div>
</div>
</form>
<ng-template #errorTpl let-control>
<form-error-tips [control]="control"></form-error-tips>
</ng-template>
</div>

5
web-admin-app/src/app/components/plan-task/plan-form/plan-form.component.less

@ -0,0 +1,5 @@
.modal-container {
height: 70vh;
overflow: auto;
}

160
web-admin-app/src/app/components/plan-task/plan-form/plan-form.component.ts

@ -0,0 +1,160 @@
import { Component, Input, OnInit, inject } from '@angular/core'
import { FormBuilder, FormGroup } from '@angular/forms'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { FormValidators, Utils } from 'app/utils'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NZ_MODAL_DATA } from 'ng-zorro-antd/modal'
import { ActivatedRoute } from '@angular/router'
import { STOCKTAKING_JOB_STATUS_MAP } from 'app/constants'
import {
AssetSelectComponent,
OrgSelectComponent,
PositionSelectComponent,
SelectUserByOrgComponent,
SupplierSelectComponent,
} from 'app/components'
@Component({
selector: 'app-stocktaking-detail-form',
standalone: true,
imports: [
SharedModule,
SelectUserByOrgComponent,
SupplierSelectComponent,
AssetSelectComponent,
OrgSelectComponent,
PositionSelectComponent,
],
templateUrl: './plan-form.component.html',
styleUrl: './plan-form.component.less',
})
export class PlanFormComponent {
constructor(
private fb: FormBuilder,
private api: ApiService,
private msg: NzMessageService,
private route: ActivatedRoute,
) {}
readonly data: NzSafeAny = inject(NZ_MODAL_DATA)
STOCKTAKING_JOB_STATUS_MAP = STOCKTAKING_JOB_STATUS_MAP
jobName = ''
formGroup!: FormGroup
groupIndex = 0
uploadLoading = false
uploadImgLoading = false
iconPreview = ''
flowForms: NzSafeAny[] = []
teamList: NzSafeAny[] = []
ngOnInit(): void {
this.api.getAssetTeamAll().subscribe((res) => {
this.teamList = res.body
})
this.api.getFlowFormList().subscribe((res) => {
this.flowForms = res.body
})
this.formGroup = this.fb.group({
jobId: this.fb.control(null, []),
status: this.fb.control(null, []),
name: this.fb.control(null, [FormValidators.required('请输入')]),
teamId: this.fb.control(null, [FormValidators.required('请选择')]),
cycleType: this.fb.control('once', [FormValidators.required('请选择')]),
duration: this.fb.control(0, [FormValidators.required('请选择')]),
actualStartTime: this.fb.control(null, [FormValidators.required('请选择')]),
expectedFinishTime: this.fb.control(null, [FormValidators.required('请选择')]),
expectedStartTime: this.fb.control(null, [FormValidators.required('请选择')]),
limit: this.fb.control(false, [FormValidators.required('请选择')]),
order: this.fb.control(false, [FormValidators.required('请选择')]),
skipWeekend: this.fb.control(false, [FormValidators.required('请选择')]),
photo: this.fb.control(false, []),
businessId: this.fb.control(null, []),
remark: this.fb.control(null, []),
formTempId: this.fb.control(null, [FormValidators.required('请选择')]),
assetIdList: this.fb.control([], []),
})
this.patchValues()
}
patchValues() {
const { value: data, preview } = this.data
if (data) {
this.formGroup.patchValue({
...data,
})
}
if (preview) {
this.formGroup.disable()
}
}
public getValues() {
let values = null
console.log('this.formGroup', this.formGroup)
if (FormValidators.validateFormGroup(this.formGroup)) {
const v = this.formGroup.value
values = {
...v,
assetIdList: v.assetIdList.map((i: NzSafeAny) => {
return {
...i,
// assetId: i,
}
}),
// assetId
}
}
return values
}
onFileChange(e: Event) {
const target = e.target as HTMLInputElement
const file = target.files![0]
target.value = ''
const formdata = new FormData()
formdata.append('file', file)
this.api.upload(formdata).subscribe((res) => {
this.formGroup.get('attachment')?.setValue(res.body.fileName)
})
}
onImgChange(e: Event) {
const target = e.target as HTMLInputElement
const file = target.files![0]
target.value = ''
if (file.size / 1024 / 1024 >= 2) {
this.msg.error('图片大小不能超过2M')
return
}
const fileReader = new FileReader()
fileReader.onload = () => {
const base64 = fileReader.result as string
this.iconPreview = base64
}
fileReader.readAsDataURL(file)
const formdata = new FormData()
formdata.append('file', file)
this.api.upload(formdata).subscribe((res) => {
this.formGroup.get('img')?.setValue(res.body.fileName)
})
}
}

38
web-admin-app/src/app/components/plan-task/plan-list/plan-list.component.html

@ -0,0 +1,38 @@
<app-page>
<ng-template #actionTpl>
<nz-space>
<button *nzSpaceItem nz-button nzType="primary" (click)="onCreate()">
<span>新建计划</span>
</button>
</nz-space>
</ng-template>
<div class="flex-1 overflow-hidden">
<app-server-paginated-table
[options]="table"
[formGroup]="queryForm"
[tableAction]="actionTpl"
[renderColumn]="renderColumnTpl"
>
<ng-template #renderColumnTpl let-data let-key="key" let-row="row">
@switch (key) {
@case ('status') {
<app-status-tag [status]="data" />
}
@case ('_value') {
{{ data?.length ?? 0 }}
}
@default {
{{ data }}
}
}
</ng-template>
<ng-container *appTableForm>
<app-query-item label="计划名称">
<input nz-input placeholder="请输入" formControlName="name" />
</app-query-item>
</ng-container>
</app-server-paginated-table>
</div>
</app-page>

0
web-admin-app/src/app/components/plan-task/plan-list/plan-list.component.less

128
web-admin-app/src/app/components/plan-task/plan-list/plan-list.component.ts

@ -0,0 +1,128 @@
import { PlanTaskType } from 'app/types'
import { Component, Input, TemplateRef, ViewChild } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { lastValueFrom, of } from 'rxjs'
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { ASSET_TYPE } from 'app/constants'
import { AssetBasicTeamFormComponent } from 'app/components/asset-basic-team-form/asset-basic-team-form.component'
import { StatusTagComponent } from 'app/components/status-tag/status-tag.component'
import { PlanFormComponent } from '../plan-form/plan-form.component'
@Component({
selector: 'app-plan-list',
standalone: true,
imports: [SharedModule, StatusTagComponent],
templateUrl: './plan-list.component.html',
styleUrl: './plan-list.component.less',
})
export class PlanListComponent {
constructor(
private api: ApiService,
private modal: NzModalService,
private msg: NzMessageService,
) {}
@Input() type: PlanTaskType = 'inspection'
queryForm = new FormGroup({
name: new FormControl(),
// status: new FormControl(),
})
table = new TableOption(this.fetchData.bind(this))
copyNum = 1
ASSET_TYPE = ASSET_TYPE
ngOnInit(): void {
this.table
.setColumn([
{ key: 'teamKey', title: '计划编号', visible: true },
{ key: 'teamName', title: '计划名称', visible: true },
{ key: 'status', title: '计划状态', visible: true },
{ key: 'createUser', title: '执行计划', visible: true },
{ key: 'createTime', title: '开始时间', visible: true },
{ key: 'createTime', title: '截止时间', visible: true },
{ key: 'createTime', title: '执行周期', visible: true },
{ key: '_value', title: '下次执行', visible: true },
{ key: 'remark', title: '巡检设备数', visible: true },
])
.setRowOperate([
{
title: '查看',
onClick: (v) => {
this.onCreate(v, true)
},
},
{ title: '修改', onClick: this.onCreate.bind(this) },
{ title: '删除', onClick: this.deleteItem.bind(this) },
{ title: '停用', onClick: this.deleteItem.bind(this) },
{ title: '启用', onClick: this.deleteItem.bind(this) },
{ title: '报表', onClick: this.deleteItem.bind(this) },
])
}
fetchData(p: {}, q: AnyObject) {
return this.api.getPlanPage({ ...p, ...q, platType: this.type })
}
onCopy(data: NzSafeAny) {}
onCreate(data?: NzSafeAny, preview?: boolean) {
let nzTitle = data ? '编辑计划' : '添加计划'
if (preview) {
nzTitle = '预览计划'
}
this.modal.create({
nzTitle,
nzContent: PlanFormComponent,
nzWidth: '80vw',
nzWrapClassName: 'modal-lg',
nzData: {
value: data,
preview,
},
nzOnOk: async (e) => {
const vals = e.getValues()
if (vals) {
const res = await lastValueFrom(
this.api.savePlan({
...vals,
planType: this.type,
}),
)
this.msg.success(res.desc)
this.table.ref.reload()
return true
}
return false
},
})
}
deleteItem(item?: NzSafeAny) {
const ids = item ? [item.teamId] : Array.from(this.table.ref.selected)
this.modal.confirm({
nzTitle: '警告',
nzContent: `是否要删除${ids.length}个计划?`,
nzOnOk: async () => {
const res = await lastValueFrom(this.api.deleteUserTeam(ids))
this.msg.success(res.desc)
this.table.ref.reload()
},
})
}
}

73
web-admin-app/src/app/components/plan-task/repair-task-form/repair-task-form.component.html

@ -0,0 +1,73 @@
<div class="modal-lg-container">
<form nz-form [formGroup]="formGroup" nzLayout="vertical">
<div class="overflow-hidden">
<div class="text-lg mb-2">基本信息</div>
<div nz-row [nzGutter]="24">
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>任务名称</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input nz-input formControlName="name" placeholder="请输入" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label>任务编号</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input nz-input formControlName="businessId" placeholder="请输入" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>故障时间</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-date-picker class="!w-full" nzShowTime formControlName="plannedDate" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="24">
<nz-form-item>
<nz-form-label>故障说明</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<textarea nz-input placeholder="请输入" formControlName="remark"></textarea>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label>图片信息</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<app-upload [drag]="true" placeholder="拖动或点击上传图片" formControlName="img" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label>附件信息</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<app-upload [drag]="true" placeholder="拖动或点击上传附件" formControlName="attachment" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col nzSpan="24">
<div class="text-lg mb-2">选择设备</div>
</div>
<div nz-col [nzSpan]="24">
<nz-form-item>
<!-- <nz-form-label>资产列表</nz-form-label> -->
<nz-form-control [nzErrorTip]="errorTpl">
<app-asset-select [storage]="true" formControlName="assetIdList" />
</nz-form-control>
</nz-form-item>
</div>
</div>
</div>
</form>
<ng-template #errorTpl let-control>
<form-error-tips [control]="control"></form-error-tips>
</ng-template>
</div>

0
web-admin-app/src/app/components/plan-task/repair-task-form/repair-task-form.component.less

151
web-admin-app/src/app/components/plan-task/repair-task-form/repair-task-form.component.ts

@ -0,0 +1,151 @@
import { Component, Input, OnInit, inject } from '@angular/core'
import { FormBuilder, FormGroup } from '@angular/forms'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { FormValidators, Utils } from 'app/utils'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NZ_MODAL_DATA } from 'ng-zorro-antd/modal'
import { ActivatedRoute } from '@angular/router'
import { STOCKTAKING_JOB_STATUS_MAP } from 'app/constants'
import {
AssetSelectComponent,
OrgSelectComponent,
PositionSelectComponent,
SelectUserByOrgComponent,
SupplierSelectComponent,
} from 'app/components'
import { UploadComponent } from '../../../shared/components/upload/upload.component'
@Component({
selector: 'app-stocktaking-detail-form',
standalone: true,
imports: [
SharedModule,
SelectUserByOrgComponent,
SupplierSelectComponent,
AssetSelectComponent,
OrgSelectComponent,
PositionSelectComponent,
UploadComponent,
],
templateUrl: './repair-task-form.component.html',
styleUrl: './repair-task-form.component.less',
})
export class RepairTaskFormComponent {
constructor(
private fb: FormBuilder,
private api: ApiService,
private msg: NzMessageService,
private route: ActivatedRoute,
) {}
readonly data: NzSafeAny = inject(NZ_MODAL_DATA)
STOCKTAKING_JOB_STATUS_MAP = STOCKTAKING_JOB_STATUS_MAP
jobName = ''
formGroup!: FormGroup
groupIndex = 0
uploadLoading = false
uploadImgLoading = false
iconPreview = ''
flowForms: NzSafeAny[] = []
teamList: NzSafeAny[] = []
ngOnInit(): void {
this.api.getAssetTeamAll().subscribe((res) => {
this.teamList = res.body
})
this.api.getFlowFormList().subscribe((res) => {
this.flowForms = res.body
})
this.formGroup = this.fb.group({
name: this.fb.control(null, [FormValidators.required('请输入')]),
remark: this.fb.control(null, []),
plannedDate: this.fb.control(null, [FormValidators.required('请选择')]),
businessId: this.fb.control(null, []),
attachment: this.fb.control(null, []),
img: this.fb.control(null, []),
assetIdList: this.fb.control([], []),
})
this.patchValues()
}
patchValues() {
const { value: data, preview } = this.data
if (data) {
this.formGroup.patchValue({
...data,
})
}
if (preview) {
this.formGroup.disable()
}
}
public getValues() {
let values = null
console.log('this.formGroup', this.formGroup)
if (FormValidators.validateFormGroup(this.formGroup)) {
const v = this.formGroup.value
values = {
...v,
assetIdList: v.assetIdList.map((i: NzSafeAny) => {
return {
...i,
// assetId: i,
}
}),
// assetId
}
}
return values
}
onFileChange(e: Event) {
const target = e.target as HTMLInputElement
const file = target.files![0]
target.value = ''
const formdata = new FormData()
formdata.append('file', file)
this.api.upload(formdata).subscribe((res) => {
this.formGroup.get('attachment')?.setValue(res.body.fileName)
})
}
onImgChange(e: Event) {
const target = e.target as HTMLInputElement
const file = target.files![0]
target.value = ''
if (file.size / 1024 / 1024 >= 2) {
this.msg.error('图片大小不能超过2M')
return
}
const fileReader = new FileReader()
fileReader.onload = () => {
const base64 = fileReader.result as string
this.iconPreview = base64
}
fileReader.readAsDataURL(file)
const formdata = new FormData()
formdata.append('file', file)
this.api.upload(formdata).subscribe((res) => {
this.formGroup.get('img')?.setValue(res.body.fileName)
})
}
}

95
web-admin-app/src/app/components/plan-task/task-form/task-form.component.html

@ -0,0 +1,95 @@
<div class="modal-lg-container">
<form nz-form [formGroup]="formGroup" nzLayout="vertical">
<div class="overflow-hidden">
<div class="text-lg mb-2">基本信息</div>
<div nz-row [nzGutter]="24">
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>任务名称</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input nz-input formControlName="name" placeholder="请输入" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label>任务编号</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input nz-input formControlName="businessId" placeholder="请输入" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>执行班组</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-select nzPlaceHolder="请选择" formControlName="teamId" nzAllowClear nzShowSearch>
@for (item of teamList; track $index) {
<nz-option [nzLabel]="item.teamName" [nzValue]="item.teamId" />
}
</nz-select>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>任务开始</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-date-picker class="!w-full" nzShowTime formControlName="actualStartTime" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>任务时长</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-input-group nzAddOnAfter="天">
<nz-input-number class="!w-full" [nzMin]="0" formControlName="duration" />
</nz-input-group>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>顺序巡检</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-switch formControlName="order" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label nzRequired>超期限制</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-switch formControlName="limit" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="24">
<nz-form-item>
<nz-form-label>任务备注</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input nz-input placeholder="请输入" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col nzSpan="24">
<div class="text-lg mb-2">选择设备</div>
</div>
<div nz-col [nzSpan]="24">
<nz-form-item>
<!-- <nz-form-label>资产列表</nz-form-label> -->
<nz-form-control [nzErrorTip]="errorTpl">
<app-asset-select [storage]="true" formControlName="assetIdList" />
</nz-form-control>
</nz-form-item>
</div>
</div>
</div>
</form>
<ng-template #errorTpl let-control>
<form-error-tips [control]="control"></form-error-tips>
</ng-template>
</div>

0
web-admin-app/src/app/components/plan-task/task-form/task-form.component.less

152
web-admin-app/src/app/components/plan-task/task-form/task-form.component.ts

@ -0,0 +1,152 @@
import { Component, Input, OnInit, inject } from '@angular/core'
import { FormBuilder, FormGroup } from '@angular/forms'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { FormValidators, Utils } from 'app/utils'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NZ_MODAL_DATA } from 'ng-zorro-antd/modal'
import { ActivatedRoute } from '@angular/router'
import { STOCKTAKING_JOB_STATUS_MAP, taskTypeTitle } from 'app/constants'
import {
AssetSelectComponent,
OrgSelectComponent,
PositionSelectComponent,
SelectUserByOrgComponent,
SupplierSelectComponent,
} from 'app/components'
import { UploadComponent } from '../../../shared/components/upload/upload.component'
@Component({
selector: 'app-stocktaking-detail-form',
standalone: true,
imports: [
SharedModule,
SelectUserByOrgComponent,
SupplierSelectComponent,
AssetSelectComponent,
OrgSelectComponent,
PositionSelectComponent,
UploadComponent,
],
templateUrl: './task-form.component.html',
styleUrl: './task-form.component.less',
})
export class TaskFormComponent {
constructor(
private fb: FormBuilder,
private api: ApiService,
private msg: NzMessageService,
private route: ActivatedRoute,
) {}
readonly data: NzSafeAny = inject(NZ_MODAL_DATA)
STOCKTAKING_JOB_STATUS_MAP = STOCKTAKING_JOB_STATUS_MAP
formGroup!: FormGroup
groupIndex = 0
uploadLoading = false
uploadImgLoading = false
iconPreview = ''
flowForms: NzSafeAny[] = []
teamList: NzSafeAny[] = []
ngOnInit(): void {
this.api.getAssetTeamAll().subscribe((res) => {
this.teamList = res.body
})
this.api.getFlowFormList().subscribe((res) => {
this.flowForms = res.body
})
this.formGroup = this.fb.group({
name: this.fb.control(null, [FormValidators.required('请输入')]),
remark: this.fb.control(null, []),
plannedDate: this.fb.control(null, [FormValidators.required('请选择')]),
businessId: this.fb.control(null, []),
attachment: this.fb.control(null, []),
img: this.fb.control(null, []),
assetIdList: this.fb.control([], []),
})
this.patchValues()
}
title?: string
patchValues() {
const { value: data, preview, type } = this.data
this.title = taskTypeTitle.get(type)
if (data) {
this.formGroup.patchValue({
...data,
})
}
if (preview) {
this.formGroup.disable()
}
}
public getValues() {
let values = null
console.log('this.formGroup', this.formGroup)
if (FormValidators.validateFormGroup(this.formGroup)) {
const v = this.formGroup.value
values = {
...v,
assetIdList: v.assetIdList.map((i: NzSafeAny) => {
return {
...i,
// assetId: i,
}
}),
// assetId
}
}
return values
}
onFileChange(e: Event) {
const target = e.target as HTMLInputElement
const file = target.files![0]
target.value = ''
const formdata = new FormData()
formdata.append('file', file)
this.api.upload(formdata).subscribe((res) => {
this.formGroup.get('attachment')?.setValue(res.body.fileName)
})
}
onImgChange(e: Event) {
const target = e.target as HTMLInputElement
const file = target.files![0]
target.value = ''
if (file.size / 1024 / 1024 >= 2) {
this.msg.error('图片大小不能超过2M')
return
}
const fileReader = new FileReader()
fileReader.onload = () => {
const base64 = fileReader.result as string
this.iconPreview = base64
}
fileReader.readAsDataURL(file)
const formdata = new FormData()
formdata.append('file', file)
this.api.upload(formdata).subscribe((res) => {
this.formGroup.get('img')?.setValue(res.body.fileName)
})
}
}

32
web-admin-app/src/app/components/plan-task/task-list/task-list.component.html

@ -0,0 +1,32 @@
<app-page>
<ng-template #actionTpl> </ng-template>
<div class="flex-1 overflow-hidden">
<app-server-paginated-table
[options]="table"
[formGroup]="queryForm"
[tableAction]="actionTpl"
[renderColumn]="renderColumnTpl"
>
<ng-template #renderColumnTpl let-data let-key="key" let-row="row">
@switch (key) {
@case ('status') {
<app-status-tag [status]="data" />
}
@case ('_value') {
{{ data?.length ?? 0 }}
}
@default {
{{ data }}
}
}
</ng-template>
<ng-container *appTableForm>
<app-query-item label="任务名称">
<input nz-input placeholder="请输入" formControlName="name" />
</app-query-item>
</ng-container>
</app-server-paginated-table>
</div>
</app-page>

0
web-admin-app/src/app/components/plan-task/task-list/task-list.component.less

153
web-admin-app/src/app/components/plan-task/task-list/task-list.component.ts

@ -0,0 +1,153 @@
import { PlanTaskType } from 'app/types'
import { Component, Input, TemplateRef, ViewChild } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { lastValueFrom, of } from 'rxjs'
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { ASSET_TYPE } from 'app/constants'
import { AssetBasicTeamFormComponent } from 'app/components/asset-basic-team-form/asset-basic-team-form.component'
import { StatusTagComponent } from 'app/components/status-tag/status-tag.component'
import { PlanFormComponent } from '../plan-form/plan-form.component'
@Component({
selector: 'app-task-list',
standalone: true,
imports: [SharedModule, StatusTagComponent],
templateUrl: './task-list.component.html',
styleUrl: './task-list.component.less',
})
export class TaskListComponent {
constructor(
private api: ApiService,
private modal: NzModalService,
private msg: NzMessageService,
) {}
@Input() type: PlanTaskType = 'inspection'
queryForm = new FormGroup({
name: new FormControl(),
// status: new FormControl(),
})
table = new TableOption(this.fetchData.bind(this))
copyNum = 1
ASSET_TYPE = ASSET_TYPE
ngOnInit(): void {
this.table
.setColumn([
{ key: 'teamKey', title: '任务名称', visible: true },
{ key: 'teamName', title: '任务状态', visible: true },
{ key: 'status', title: '任务来源', visible: true },
{ key: 'createUser', title: '开始时间', visible: true },
{ key: 'createTime', title: '任务时长', visible: true },
{ key: 'createTime', title: '完成时间', visible: true },
{ key: 'createTime', title: '设备总数', visible: true },
{ key: '_value', title: '待处理设备数', visible: true },
{ key: 'remark', title: '已处理设备数', visible: true },
{ key: 'remark', title: '执行班组', visible: true },
])
.setRowOperate([
{
title: '查看',
onClick: (v) => {
this.onCreate(v, true)
},
},
{ title: '受理', onClick: this.shouli.bind(this) },
{ title: '指派', onClick: this.zhipai.bind(this) },
{ title: '处置', onClick: this.chuzhi.bind(this) },
{ title: '报表', onClick: this.deleteItem.bind(this) },
])
}
fetchData(p: {}, q: AnyObject) {
return this.api.getTaskPage({ ...p, ...q, jobType: this.type })
}
shouli(item?: NzSafeAny) {
const ids = item ? [item.teamId] : Array.from(this.table.ref.selected)
this.modal.confirm({
nzTitle: '是否确定受理当前设备流程?',
nzContent: `受理后你将作为该任务的责任人,其他人员无法受理!`,
nzOnOk: async () => {
const res = await lastValueFrom(this.api.deleteUserTeam(ids))
this.msg.success(res.desc)
this.table.ref.reload()
},
})
}
zhipai(item?: NzSafeAny) {
const ids = item ? [item.teamId] : Array.from(this.table.ref.selected)
this.modal.confirm({
nzTitle: '请选择设备任务处置人员',
nzContent: ``,
nzOnOk: async () => {
const res = await lastValueFrom(this.api.deleteUserTeam(ids))
this.msg.success(res.desc)
this.table.ref.reload()
},
})
}
chuzhi(data: NzSafeAny) {}
onCreate(data?: NzSafeAny, preview?: boolean) {
let nzTitle = data ? '编辑任务' : '添加任务'
if (preview) {
nzTitle = '预览任务'
}
this.modal.create({
nzTitle,
nzContent: PlanFormComponent,
nzWidth: '80vw',
nzWrapClassName: 'modal-lg',
nzData: {
value: data,
preview,
},
nzOnOk: async (e) => {
const vals = e.getValues()
if (vals) {
const res = await lastValueFrom(
this.api.savePlan({
...vals,
planType: this.type,
}),
)
this.msg.success(res.desc)
this.table.ref.reload()
return true
}
return false
},
})
}
deleteItem(item?: NzSafeAny) {
const ids = item ? [item.teamId] : Array.from(this.table.ref.selected)
this.modal.confirm({
nzTitle: '警告',
nzContent: `是否要删除${ids.length}个任务?`,
nzOnOk: async () => {
const res = await lastValueFrom(this.api.deleteUserTeam(ids))
this.msg.success(res.desc)
this.table.ref.reload()
},
})
}
}

25
web-admin-app/src/app/components/select-user-by-org/select-user-by-org.component.ts

@ -1,5 +1,14 @@
import { CommonModule } from '@angular/common'
import { ChangeDetectorRef, Component, Input, OnInit, TemplateRef, forwardRef } from '@angular/core'
import {
ChangeDetectorRef,
Component,
EventEmitter,
Input,
OnInit,
Output,
TemplateRef,
forwardRef,
} from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
import { NzCardModule } from 'ng-zorro-antd/card'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
@ -55,6 +64,8 @@ export class SelectUserByOrgComponent implements ControlValueAccessor, OnInit {
@Input() size: 'small' | 'default' = 'default'
@Output() onSelect = new EventEmitter()
allGetedDataMap = new Map<number, NzSafeAny>()
currentUsers: NzSafeAny[] = []
@ -80,6 +91,7 @@ export class SelectUserByOrgComponent implements ControlValueAccessor, OnInit {
nzOnOk: () => {
this.selectedKeys = new Set([...this.tempSelectedKeys])
this.onChange(Array.from(this.selectedKeys))
this.handleSelect()
},
nzOnCancel: () => {
this.tempSelectedKeys.clear()
@ -87,6 +99,16 @@ export class SelectUserByOrgComponent implements ControlValueAccessor, OnInit {
})
}
handleSelect() {
const selected: NzSafeAny[] = []
this.allGetedDataMap.forEach((i) => {
if (this.selectedKeys.has(i.userId)) {
selected.push(i)
}
})
this.onSelect.emit(selected)
}
onOrgSelectedChange(v?: NzSafeAny, uid?: number) {
this.api
.getUserPage({
@ -148,6 +170,7 @@ export class SelectUserByOrgComponent implements ControlValueAccessor, OnInit {
getUserById(id: number) {
this.api.getUserDetail(id).subscribe((res) => {
this.allGetedDataMap.set(id, res.body)
this.handleSelect()
})
}

11
web-admin-app/src/app/components/status-tag/status-tag.component.html

@ -0,0 +1,11 @@
@switch (status) {
@case (0) {
<nz-badge nzText="停用" nzStatus="default"></nz-badge>
}
@case (1) {
<nz-badge nzText="启用" nzStatus="success"></nz-badge>
}
@default {
{{ status }}
}
}

0
web-admin-app/src/app/components/status-tag/status-tag.component.less

17
web-admin-app/src/app/components/status-tag/status-tag.component.ts

@ -0,0 +1,17 @@
import { Component, Input } from '@angular/core'
import { NzBadgeModule } from 'ng-zorro-antd/badge'
@Component({
selector: 'app-status-tag',
standalone: true,
imports: [NzBadgeModule],
templateUrl: './status-tag.component.html',
styleUrl: './status-tag.component.less',
})
export class StatusTagComponent {
constructor() {}
@Input() status: number = 0
ngOnInit() {}
}

46
web-admin-app/src/app/constants/index.ts

@ -1,3 +1,5 @@
import { PlanTaskType } from 'app/types'
export const MAX_PAGE_SIZE = 10000000
export const LOCALSTORAGKEY = {
@ -16,6 +18,12 @@ export const ASSET_STATUS = [
{ label: '已报废', value: 8 },
]
export const FLOW_FORM_TYPES = [
{ value: 'DATE', label: '日期' },
{ value: 'NUMBER', label: '数字' },
{ value: 'RADIO', label: '单选' },
{ value: 'STRING', label: '文本' },
]
export const ASSET_STATUS_MAP = () => {
return ASSET_STATUS.reduce(
(map, item) => {
@ -26,6 +34,37 @@ export const ASSET_STATUS_MAP = () => {
)
}
// 业务类型:
// ALLOCATE-资产调拨,
// BORROW-资产借用,
// COLLECTION-资产领用,
// OUTBOUND-资产出库,
// RETURN-资产归还,
// RETURN_INVENTORY-资产退库,
// STORAGE-资产入库"),
// TRANSFER("transfer", "资产转移"),\n
// REPAIR_FAULT("repair_fault", "故障登记"),
// REPAIR("repair", "设备报修"),
// RETIREMENT("retirement", "资产报废"),
// CLEAN("clean", "资产清理"),
// UNKNOWN("null", "未知操作");
export const ASSET_TYPE = [
{ label: '资产入库', value: 'STORAGE' },
{ label: '资产领用', value: 'COLLECTION' },
{ label: '资产退库', value: 'RETURN_INVENTORY' },
{ label: '资产借用', value: 'BORROW' },
{ label: '资产归还', value: 'RETURN' },
{ label: '资产调拨', value: 'ALLOCATE' },
{ label: '资产转移', value: 'TRANSFER' },
{ label: '资产报废', value: 'RETIREMENT' },
// { label: '资产出库', value: 'OUTBOUND' },
// { label: '故障登记', value: 'REPAIR_FAULT' },
// { label: '设备报修', value: 'REPAIR' },
// { label: '资产清理', value: 'CLEAN' },
// { label: '未知操作', value: 'UNKNOWN' },
]
export const ASSET_SOURCE_MAP = new Map([
[0, '捐赠'],
[1, '赠送'],
@ -81,3 +120,10 @@ export const FLOW_STATUS = new Map([
[5, '已废弃'],
[6, '流程异常'],
])
export const taskTypeTitle = new Map<PlanTaskType, string>([
['inspection', '巡检'],
['maintenance', '保养'],
['repair', '报修'],
['stocktaking', '盘点'],
])

73
web-admin-app/src/app/pages/fixed-asset/asset-management/asset-management.component.html

@ -0,0 +1,73 @@
<app-page>
<ng-template #actionTpl>
<nz-space>
<button *nzSpaceItem nz-button nzType="primary" (click)="onCreate()">
<span>新建流程</span>
</button>
</nz-space>
</ng-template>
<div class="flex-1 overflow-hidden">
<app-server-paginated-table
[options]="table"
[formGroup]="queryForm"
[tableAction]="actionTpl"
[renderColumn]="renderColumnTpl"
>
<ng-template #renderColumnTpl let-data let-key="key" let-row="row">
@switch (key) {
@case ('status') {
<nz-tag>
{{ ASSET_STATUS_MAP[data] }}
</nz-tag>
}
@case ('_useUser') {
{{ data?.userName ?? '-' }}
}
@case ('_warehouse') {
{{ data?.name ?? '-' }}
}
@case ('_position') {
{{ data?.name ?? '-' }}
}
@case ('_head') {
{{ data?.userName ?? '-' }}
}
@case ('_ownCompany') {
{{ data?.organizationName ?? '-' }}
}
@case ('_useOrganization') {
{{ data?.organizationName ?? '-' }}
}
@case ('_category') {
{{ data?.categoryName ?? '-' }}
}
@default {
{{ data }}
}
}
</ng-template>
<ng-container *appTableForm>
<app-query-item label="流程类型">
<nz-select
nzPlaceHolder="请选择"
nzPlacement="bottomRight"
class="!w-24"
[nzDropdownMatchSelectWidth]="false"
formControlName="model"
nzAllowClear
>
<nz-option nzLabel="所有分类" nzValue=""></nz-option>
<nz-option *ngFor="let item of ASSET_TYPE" [nzLabel]="item.label" [nzValue]="item.value" />
</nz-select>
</app-query-item>
<app-query-item label="流程状态">
<input nz-input placeholder="请输入" formControlName="assetCode" />
</app-query-item>
<app-query-item label="流程名称">
<input nz-input placeholder="请输入" formControlName="model" />
</app-query-item>
</ng-container>
</app-server-paginated-table>
</div>
</app-page>

0
web-admin-app/src/app/pages/fixed-asset/asset-management/asset-management.component.less

194
web-admin-app/src/app/pages/fixed-asset/asset-management/asset-management.component.ts

@ -0,0 +1,194 @@
import { Component, TemplateRef, ViewChild } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { format } from 'date-fns'
import { lastValueFrom, of } from 'rxjs'
import { AssetFormComponent, ManufacturerSelectComponent, PositionSelectComponent } from 'app/components'
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { ASSET_SOURCE_MAP, ASSET_STATUS, ASSET_STATUS_MAP, ASSET_TYPE } from 'app/constants'
import { Utils } from 'app/utils'
@Component({
selector: 'app-asset-management',
standalone: true,
imports: [SharedModule, AssetFormComponent, PositionSelectComponent, ManufacturerSelectComponent],
templateUrl: './asset-management.component.html',
styleUrl: './asset-management.component.less',
})
export class AssetManagementComponent {
constructor(
private api: ApiService,
private modal: NzModalService,
private msg: NzMessageService,
) {}
queryForm = new FormGroup({
name: new FormControl(),
model: new FormControl(),
status: new FormControl(),
assetCode: new FormControl(),
serialNumber: new FormControl(),
sourceId: new FormControl(),
positionId: new FormControl(),
manufacturersVendorId: new FormControl(),
})
ASSET_STATUS_MAP = ASSET_STATUS_MAP()
ASSET_SOURCE_MAP = ASSET_SOURCE_MAP
table = new TableOption(this.fetchData.bind(this))
copyNum = 1
ASSET_TYPE = ASSET_TYPE
ngOnInit(): void {
this.table
.setConfig({
selectable: true,
rowKey: 'assetId',
})
.setColumn([
{ key: 'assetCode', title: '业务编号', visible: true },
{ key: 'name', title: '流程名称', visible: true },
{ key: '_category', title: '流程类型', visible: true },
{ key: 'status', title: '流程状态', visible: true },
{ key: '_ownCompany', title: '紧急程度', visible: true },
{ key: '_useOrganization', title: '发起人', visible: true },
{ key: '_position', title: '创建时间', visible: true },
{ key: '_position', title: '当前节点', visible: true },
{ key: '_position', title: '备注', visible: true },
])
.setRowOperate([
{
title: '查看',
onClick: (v) => {
this.onCreate(v, true)
},
},
{ title: '修改', onClick: this.onCreate.bind(this) },
{ title: '复制', onClick: this.onCopy.bind(this) },
{ title: '二维码', onClick: this.qrcode.bind(this) },
{ title: '删除', onClick: this.deleteItem.bind(this) },
])
}
fetchData(p: {}, q: AnyObject) {
return this.api.getAssetManagerPage({ ...p, ...q })
}
onCopy(data: NzSafeAny) {}
onCreate(data?: NzSafeAny, preview?: boolean) {
let nzTitle = data ? '编辑资产' : '添加资产'
if (preview) {
nzTitle = '预览资产'
}
this.modal.create({
nzTitle,
nzContent: AssetFormComponent,
nzWidth: '80vw',
nzWrapClassName: 'modal-lg',
nzData: {
value: data,
preview,
},
nzOnOk: async (e) => {
const vals = e.getValues()
if (vals) {
const res = await lastValueFrom(this.api.saveAsset(vals))
this.msg.success(res.desc)
this.table.ref.reload()
return true
}
return false
},
})
}
deleteItem(item?: NzSafeAny) {
const ids = item ? [item.assetId] : Array.from(this.table.ref.selected)
this.modal.confirm({
nzTitle: '警告',
nzContent: `是否要删除${ids.length}个资产?`,
nzOnOk: async () => {
const res = await lastValueFrom(this.api.deleteAsset(ids))
this.msg.success(res.desc)
this.table.ref.reload()
},
})
}
confirmAsset() {
const ids = Array.from(this.table.ref.selected).map((i) => Number(i))
this.modal.confirm({
nzTitle: '警告',
nzContent: `是否对选择的${ids.length}个资产进行确认?`,
nzOnOk: async () => {
const res = await lastValueFrom(this.api.confirmAsset(ids))
this.msg.success(res.desc)
this.table.ref.reload()
},
})
}
qrcode(d: NzSafeAny) {
this.msg.loading('二维码生成中...')
this.api.assetQrcode(d.assetId).subscribe((res) => {
Utils.downLoadFile(res, 'application/pdf')
this.msg.remove()
this.msg.success('二维码生成成功')
})
}
downloadTemplate() {
this.msg.loading('模板下载中...')
this.api.downloadAssetTemplate().subscribe((res) => {
Utils.downLoadFile(res, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8')
this.msg.remove()
this.msg.success('模板下载成功')
})
}
importModalRef?: NzModalRef
importExcel(nzContent: TemplateRef<{}>) {
this.importModalRef = this.modal.create({
nzTitle: '资产数据导入',
nzContent,
nzWidth: 800,
nzFooter: null,
})
}
onFileChange(e: Event) {
const target = e.target as HTMLInputElement
const file = target.files![0]
target.value = ''
const formdata = new FormData()
formdata.append('file', file)
this.api.uploadAsset(formdata).subscribe((res) => {
this.importModalRef?.close()
this.msg.success(res.desc)
this.table.ref.reload()
})
}
exportExcel() {
const ids = Array.from(this.table.ref.selected).map((i) => Number(i))
if (ids.length === 0) {
return
}
this.msg.loading('Excel生成中...')
this.api.exportAsset(ids).subscribe((res) => {
Utils.downLoadFile(res, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8')
this.msg.remove()
this.msg.success('Excel生成成功')
})
}
}

59
web-admin-app/src/app/pages/fixed-asset/basic/asset-user-group/asset-user-group.component.html

@ -0,0 +1,59 @@
<app-page>
<ng-template #actionTpl>
<nz-space>
<button *nzSpaceItem nz-button nzType="primary" (click)="onCreate()">
<span>创建班组</span>
</button>
</nz-space>
</ng-template>
<div class="flex-1 overflow-hidden">
<app-server-paginated-table
[options]="table"
[formGroup]="queryForm"
[tableAction]="actionTpl"
[renderColumn]="renderColumnTpl"
>
<ng-template #renderColumnTpl let-data let-key="key" let-row="row">
@switch (key) {
@case ('status') {
<app-status-tag [status]="data" />
}
@case ('_value') {
{{ data?.length ?? 0 }}
}
@default {
{{ data }}
}
}
</ng-template>
<ng-container *appTableForm>
<!-- <app-query-item label="班组类型">
<nz-select nzShowSearch nzPlaceHolder="请选择">
<nz-option nzValue="" nzLabel="所有表单"></nz-option>
<nz-option nzValue="1" nzLabel="默认巡检表单"></nz-option>
<nz-option nzValue="2" nzLabel="默认保养表单"></nz-option>
<nz-option nzValue="3" nzLabel="默认盘点表单"></nz-option>
</nz-select>
</app-query-item> -->
<app-query-item label="班组名称">
<input nz-input placeholder="请输入" formControlName="teamName" />
</app-query-item>
<!-- <app-query-item label="状态">
<nz-select nzShowSearch nzPlaceHolder="请选择" formControlName="status">
<nz-option [nzValue]="0" nzLabel="停用"></nz-option>
<nz-option [nzValue]="1" nzLabel="启用"></nz-option>
</nz-select>
</app-query-item> -->
<!-- <app-query-item label="巡检班组">
<nz-select nzShowSearch nzPlaceHolder="请选择">
<nz-option nzValue="">所有类型</nz-option>
<nz-option nzValue="1">物品领用</nz-option>
<nz-option nzValue="2">设备保修</nz-option>
</nz-select>
</app-query-item> -->
</ng-container>
</app-server-paginated-table>
</div>
</app-page>

0
web-admin-app/src/app/pages/fixed-asset/basic/asset-user-group/asset-user-group.component.less

125
web-admin-app/src/app/pages/fixed-asset/basic/asset-user-group/asset-user-group.component.ts

@ -0,0 +1,125 @@
import { Component, TemplateRef, ViewChild } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { format } from 'date-fns'
import { lastValueFrom, of } from 'rxjs'
import {
AssetFormComponent,
ManufacturerSelectComponent,
PositionSelectComponent,
StatusTagComponent,
} from 'app/components'
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { ASSET_SOURCE_MAP, ASSET_STATUS, ASSET_STATUS_MAP, ASSET_TYPE } from 'app/constants'
import { Utils } from 'app/utils'
import { AssetBasicTeamFormComponent } from 'app/components/asset-basic-team-form/asset-basic-team-form.component'
@Component({
selector: 'app-asset-management',
standalone: true,
imports: [
SharedModule,
AssetFormComponent,
PositionSelectComponent,
ManufacturerSelectComponent,
StatusTagComponent,
],
templateUrl: './asset-user-group.component.html',
styleUrl: './asset-user-group.component.less',
})
export class AssetUserGroupComponent {
constructor(
private api: ApiService,
private modal: NzModalService,
private msg: NzMessageService,
) {}
queryForm = new FormGroup({
teamName: new FormControl(),
// status: new FormControl(),
})
table = new TableOption(this.fetchData.bind(this))
copyNum = 1
ASSET_TYPE = ASSET_TYPE
ngOnInit(): void {
this.table
.setColumn([
{ key: 'teamKey', title: '班组编号', visible: true },
{ key: 'teamName', title: '班组名称', visible: true },
{ key: 'status', title: '班组状态', visible: true },
{ key: 'createUser', title: '创建人', visible: true },
{ key: 'createTime', title: '创建时间', visible: true },
{ key: '_value', title: '成员数', visible: true },
{ key: 'remark', title: '备注', visible: true },
])
.setRowOperate([
{
title: '查看',
onClick: (v) => {
this.onCreate(v, true)
},
},
{ title: '修改', onClick: this.onCreate.bind(this) },
{ title: '删除', onClick: this.deleteItem.bind(this) },
])
}
fetchData(p: {}, q: AnyObject) {
return this.api.getAssetTeamPage({ ...p, ...q })
}
onCopy(data: NzSafeAny) {}
onCreate(data?: NzSafeAny, preview?: boolean) {
let nzTitle = data ? '编辑班组' : '添加班组'
if (preview) {
nzTitle = '预览班组'
}
this.modal.create({
nzTitle,
nzContent: AssetBasicTeamFormComponent,
nzWidth: '800px',
nzData: {
value: data,
preview,
},
nzOnOk: async (e) => {
const vals = e.getValues()
if (vals) {
const res = await lastValueFrom(this.api.saveUserTeam(vals))
this.msg.success(res.desc)
this.table.ref.reload()
return true
}
return false
},
})
}
deleteItem(item?: NzSafeAny) {
const ids = item ? [item.teamId] : Array.from(this.table.ref.selected)
this.modal.confirm({
nzTitle: '警告',
nzContent: `是否要删除${ids.length}个班组?`,
nzOnOk: async () => {
const res = await lastValueFrom(this.api.deleteUserTeam(ids))
this.msg.success(res.desc)
this.table.ref.reload()
},
})
}
}

324
web-admin-app/src/app/pages/fixed-asset/basic/basic-category/basic-category.component.html

@ -4,54 +4,278 @@
<app-component-basic-category-tree #treeEl (onSelectedChange)="onSelectedChange($event)" />
</nz-card>
<div class="flex-1 pl-3">
<nz-card [nzBordered]="false" nzTitle="分类信息">
<form nz-form nzLayout="vertical" [formGroup]="createForm" class="w-72">
<nz-form-item>
<nz-form-label [nzRequired]="true"> 名称 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input type="text" nz-input formControlName="categoryName" placeholder="请输入名称" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label> 安全库存 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-input-number
nzPlaceHolder="请输入"
[nzMin]="0"
class="!w-full"
formControlName="safetyLimit"
/>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label> 安全库存上限 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-input-number
nzPlaceHolder="请输入"
[nzMin]="0"
class="!w-full"
formControlName="upperLimit"
/>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label> 安全库存下限 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-input-number
nzPlaceHolder="请输入"
[nzMin]="0"
class="!w-full"
formControlName="lowerLimit"
/>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control>
<nz-space>
<button *nzSpaceItem nz-button nzType="primary" (click)="onConfirm()">确定</button>
</nz-space>
</nz-form-control>
</nz-form-item>
<nz-card [nzBordered]="false" nzTitle="分类信息" [nzExtra]="extraTpl">
<ng-template #extraTpl>
<nz-space>
<button *nzSpaceItem nz-button nzType="primary" (click)="onConfirm()">保存</button>
</nz-space>
</ng-template>
<form nz-form nzLayout="vertical" [formGroup]="createForm">
<div class="flex">
<div class="w-72 pr-8">
<nz-form-item>
<nz-form-label [nzRequired]="true"> 名称 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input
type="text"
nz-input
formControlName="categoryName"
placeholder="请输入名称"
/>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label> 安全库存 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-input-number
nzPlaceHolder="请输入"
[nzMin]="0"
class="!w-full"
formControlName="safetyLimit"
/>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label> 安全库存上限 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-input-number
nzPlaceHolder="请输入"
[nzMin]="0"
class="!w-full"
formControlName="upperLimit"
/>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label> 安全库存下限 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-input-number
nzPlaceHolder="请输入"
[nzMin]="0"
class="!w-full"
formControlName="lowerLimit"
/>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control> </nz-form-control>
</nz-form-item>
</div>
<div class="flex-1">
<nz-form-item>
<nz-form-label nzSpan="5" [nzRequired]="true">扩展属性表单模板</nz-form-label>
<nz-form-control [nzExtra]="tempalteTpl" [nzErrorTip]="formErrorTpl">
<app-upload
[drag]="true"
[uploadFn]="api.uploadFlowFormTpl"
(onUpload)="onTplupload($event)"
/>
</nz-form-control>
<ng-template #tempalteTpl>
<div class="mt-4">
<a (click)="downloadTemplate()">
<i nz-icon nzType="cloud-download" class="mb-2"></i>
点击下载模板示例
</a>
</div>
</ng-template>
</nz-form-item>
<nz-form-item>
<nz-form-label> 扩展属性 </nz-form-label>
<nz-form-control>
<div formArrayName="_assetExtTemp">
<div>
<nz-table nzTemplateMode nzSize="small" [nzBordered]="true">
<thead>
<tr>
<th>序号</th>
<th>标识符</th>
<th>检查内容</th>
<th>类型</th>
<th>结果</th>
<th>备注</th>
<th>操作</th>
</tr>
</thead>
<tbody>
@for (item of formValue.controls; track $index) {
<tr [formGroupName]="$index">
<td>
<nz-input-number
[nzStep]="1"
placeholder="请输入"
formControlName="sort"
/>
</td>
<td>
<input
nz-input
placeholder="请输入"
formControlName="key"
/>
</td>
<td>
<input
nz-input
placeholder="请输入"
formControlName="name"
/>
</td>
<td>
<nz-select
nzPlaceHolder="请选择"
formControlName="type"
>
@for (item of FLOW_FORM_TYPES; track $index) {
<nz-option
[nzLabel]="item.label"
[nzValue]="item.value"
/>
}
</nz-select>
</td>
<td>
@switch (
formValue.controls.at($index)?.get('type')?.value
) {
@case ('DATE') {
<nz-date-picker
class="!w-full"
placeholder="请输入"
formControlName="value"
/>
}
@case ('RADIO') {
<ng-container
*ngIf="getRadioFields($index) as fields"
>
<nz-radio-group
formControlName="value"
class="radio"
>
<div formArrayName="fields">
<div
class="flex items-center mb-2"
*ngFor="
let f of fields;
let i = index
"
>
<!-- <label
class="!flex"
nz-radio
[nzValue]="f.value"
>
</label> -->
<input
class="flex-1"
nz-input
nzSize="small"
[formControlName]="i"
/>
<button
nz-button
nzType="text"
nzSize="small"
class="ml-2"
nzDanger
(click)="
removeRadioItem(
$index,
i
)
"
>
<i
nz-icon
nzType="delete"
></i>
</button>
</div>
</div>
</nz-radio-group>
</ng-container>
<div class="mt-2">
<button
nz-button
nzSize="small"
(click)="addRadioItem($index)"
>
<span
nz-icon
nzType="plus"
nzTheme="outline"
></span>
新增选项
</button>
</div>
}
@case ('NUMBER') {
<nz-input-number
class="!w-full"
nz-input
placeholder="请输入"
formControlName="value"
/>
}
@default {
<input
class="w-full"
nz-input
placeholder="请输入"
formControlName="value"
/>
}
}
</td>
<td>
<input
nz-input
placeholder="请输入"
formControlName="remark"
/>
</td>
<td>
<button
nz-button
nzShape="circle"
nzType="primary"
nzDanger=""
(click)="removeFormItem($index)"
>
<span
nz-icon
nzType="delete"
nzTheme="outline"
></span>
</button>
</td>
</tr>
}
<tr>
<td colspan="6" class="text-right"></td>
<td>
<button
nz-button
nzType="primary"
nzShape="circle"
(click)="addFormItem()"
>
<span nz-icon nzType="plus" nzTheme="outline"></span>
</button>
</td>
</tr>
</tbody>
</nz-table>
</div>
</div>
</nz-form-control>
</nz-form-item>
</div>
</div>
</form>
</nz-card>
</div>
@ -61,3 +285,7 @@
<ng-template #errorTpl let-control>
<form-error-tips [control]="control"></form-error-tips>
</ng-template>
<ng-template #formErrorTpl let-control>
<form-error-tips [control]="control"></form-error-tips>
</ng-template>

133
web-admin-app/src/app/pages/fixed-asset/basic/basic-category/basic-category.component.ts

@ -1,21 +1,24 @@
import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'
import { Component, inject, OnInit, TemplateRef, ViewChild } from '@angular/core'
import { SharedModule } from 'app/shared/shared.module'
import { ApiService } from 'app/services'
import { FormBuilder, FormGroup } from '@angular/forms'
import { FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms'
import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NzModalService } from 'ng-zorro-antd/modal'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzDrawerRef, NzDrawerService } from 'ng-zorro-antd/drawer'
import { lastValueFrom } from 'rxjs'
import { FormValidators } from 'app/utils'
import { FormValidators, Utils } from 'app/utils'
import { ComponentBasicCategoryTreeComponent } from 'app/components'
import { ActivatedRoute, Router } from '@angular/router'
import { FLOW_FORM_TYPES } from 'app/constants'
import { UploadComponent } from 'app/shared/components/upload/upload.component'
@Component({
selector: 'app-basic-category',
standalone: true,
imports: [SharedModule, ComponentBasicCategoryTreeComponent],
imports: [SharedModule, ComponentBasicCategoryTreeComponent, UploadComponent],
templateUrl: './basic-category.component.html',
styleUrl: './basic-category.component.less',
})
@ -24,12 +27,13 @@ export class BasicCategoryComponent {
private modal: NzModalService,
private msg: NzMessageService,
private drawer: NzDrawerService,
private api: ApiService,
private fb: FormBuilder,
public api: ApiService,
) {}
@ViewChild('treeEl') treeEl!: ComponentBasicCategoryTreeComponent
step = 0
queryForm!: FormGroup
createForm!: FormGroup
@ -48,6 +52,7 @@ export class BasicCategoryComponent {
safetyLimit: [0, []],
lowerLimit: [0, []],
upperLimit: [0, []],
_assetExtTemp: new FormArray([]),
})
}
initQueryForm() {
@ -62,7 +67,14 @@ export class BasicCategoryComponent {
}
onSelectedChange(v: NzSafeAny) {
this.createForm.patchValue(v)
this.createForm.patchValue({
...v,
})
this.patchFormValue(v._assetExtTemp ?? [])
}
get formValue(): FormArray {
return this.createForm.get('_assetExtTemp') as FormArray
}
onConfirm() {
@ -72,6 +84,18 @@ export class BasicCategoryComponent {
this.api
.updateBasicCategoryTree({
...value,
_assetExtTemp: this.formValue.value.map((v: any) => {
if (v.type === 'RADIO') {
return {
...v,
value: {
value: v.value,
fields: v.fields.map((i: string) => i),
},
}
}
return v
}),
})
.subscribe((res) => {
this.msg.success(res.desc)
@ -80,4 +104,99 @@ export class BasicCategoryComponent {
})
}
}
downloadTemplate() {
this.msg.loading('模板下载中...')
this.api.getFlowFormsTpl().subscribe((res) => {
Utils.downLoadFile(res, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8')
this.msg.remove()
this.msg.success('模板下载成功')
})
}
fb = inject(FormBuilder)
onTplupload(e: NzSafeAny[]) {
this.patchFormValue(e)
}
patchFormValue(e: NzSafeAny[]) {
this.formValue.clear()
e.forEach((v) => {
let value = v.value
const fieldsArrays = this.fb.array([])
if (v.type === 'RADIO') {
let val = Object.create(null)
try {
val = typeof v.value === 'string' ? JSON.parse(v.value) : v.value
} catch (error) {}
val?.fields?.forEach((i: string) => {
fieldsArrays.push(this.fb.control(i))
})
value = val?.value
}
this.formValue.push(
new FormGroup({
key: new FormControl(v.key, []),
value: new FormControl(value, []),
name: new FormControl(v.name, []),
type: new FormControl(v.type, []),
remark: new FormControl(v.remark, []),
sort: new FormControl(v.sort ?? 0, []),
fields: fieldsArrays,
}),
)
})
}
formatRadioValue(fields: string[], value: string) {}
router = inject(Router)
FLOW_FORM_TYPES = FLOW_FORM_TYPES
route = inject(ActivatedRoute)
getRadioFieldsFormArray(index: number): FormArray {
return this.formValue.at(index).get('fields') as FormArray
}
getRadioFields(index: number): any[] {
return this.getRadioFieldsFormArray(index).controls
}
addRadioItem(idx: number) {
this.getRadioFieldsFormArray(idx).push(new FormControl())
}
addFormItem() {
this.formValue.push(
new FormGroup({
key: new FormControl(null, []),
value: new FormControl(null, []),
name: new FormControl(null, []),
type: new FormControl(null, []),
remark: new FormControl(null, []),
sort: new FormControl(null, []),
fields: this.fb.array([]),
}),
)
}
addFormValue() {
this.formValue.push(
new FormGroup({
key: new FormControl(),
value: new FormControl(),
name: new FormControl(),
type: new FormControl(),
remark: new FormControl(),
sort: new FormControl(0),
}),
)
}
removeFormItem(idx: number) {
this.formValue.removeAt(idx)
}
removeRadioItem(idx: number, idx2: number) {
this.getRadioFieldsFormArray(idx).removeAt(idx2)
}
}

219
web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form-manage/basic-flow-form-manage.component.html

@ -0,0 +1,219 @@
<app-page>
<nz-card>
<nz-steps [nzCurrent]="step">
<nz-step nzTitle="导入模板"></nz-step>
<nz-step nzTitle="检项明细"></nz-step>
<nz-step nzTitle="模板确认"></nz-step>
</nz-steps>
<div class="mt-6 p-4">
<form [formGroup]="formGroup">
@switch (step) {
@case (0) {
<ng-container *ngTemplateOutlet="step1"></ng-container>
}
@case (1) {
<ng-container *ngTemplateOutlet="step2"></ng-container>
}
@case (2) {
<ng-container *ngTemplateOutlet="step3"></ng-container>
}
}
<nz-form-item class="mt-4">
<nz-form-control nzSpan="14" nzOffset="5">
<nz-space>
<button *nzSpaceItem nz-button nzType="primary" (click)="nextStep(this.step)">
下一步
</button>
<button *nzSpaceItem nz-button nzType="primary" nzDanger (click)="cancel(this.step)">
取消
</button>
</nz-space>
</nz-form-control>
</nz-form-item>
<ng-template #step1>
<nz-form-item>
<nz-form-label nzSpan="5" nzRequired>表单名称</nz-form-label>
<nz-form-control nzSpan="14" [nzErrorTip]="formErrorTpl">
<input nz-input placeholder="请输入表单名称" formControlName="formName" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="5" [nzRequired]="true">表单编号</nz-form-label>
<nz-form-control nzSpan="14" [nzErrorTip]="formErrorTpl">
<input nz-input placeholder="请输入表单编号" formControlName="formKey" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="5" [nzRequired]="true">选择模板</nz-form-label>
<nz-form-control nzSpan="14" [nzExtra]="tempalteTpl" [nzErrorTip]="formErrorTpl">
<app-upload
[drag]="true"
formControlName="templatePath"
[uploadFn]="api.uploadFlowFormTpl"
(onUpload)="onTplupload($event)"
/>
</nz-form-control>
<ng-template #tempalteTpl>
<div class="mt-4">
<a (click)="downloadTemplate()">
<i nz-icon nzType="cloud-download" class="mb-2"></i>
点击下载模板示例
</a>
</div>
</ng-template>
</nz-form-item>
</ng-template>
<ng-template #step2>
<div formArrayName="_formValue">
<div>
<nz-table nzTemplateMode nzSize="small" [nzBordered]="true">
<thead>
<tr>
<th>序号</th>
<th>标识符</th>
<th>检查内容</th>
<th>类型</th>
<th>结果</th>
<th>备注</th>
<th>操作</th>
</tr>
</thead>
<tbody>
@for (item of formValue.controls; track $index) {
<tr [formGroupName]="$index">
<td>
<nz-input-number
[nzStep]="1"
placeholder="请输入"
formControlName="sort"
/>
</td>
<td>
<input nz-input placeholder="请输入" formControlName="key" />
</td>
<td>
<input nz-input placeholder="请输入" formControlName="name" />
</td>
<td>
<nz-select nzPlaceHolder="请选择" formControlName="type">
@for (item of FLOW_FORM_TYPES; track $index) {
<nz-option [nzLabel]="item.label" [nzValue]="item.value" />
}
</nz-select>
</td>
<td>
@switch (formValue.controls.at($index)?.get('type')?.value) {
@case ('DATE') {
<nz-date-picker
class="!w-full"
placeholder="请输入"
formControlName="value"
/>
}
@case ('RADIO') {
<ng-container *ngIf="getRadioFields($index) as fields">
<nz-radio-group formControlName="value" class="radio">
<div formArrayName="fields">
<div
class="flex items-center"
*ngFor="let f of fields; let i = index"
>
<label
class="!flex"
nz-radio
[nzValue]="f.value"
>
</label>
<input
class="flex-1"
nz-input
nzSize="small"
[formControlName]="i"
/>
<button
nz-button
nzType="text"
nzSize="small"
class="ml-2"
nzDanger
(click)="removeRadioItem($index, i)"
>
<i nz-icon nzType="delete"></i>
</button>
</div>
</div>
</nz-radio-group>
</ng-container>
<div class="mt-2">
<button
nz-button
nzSize="small"
(click)="addRadioItem($index)"
>
<span nz-icon nzType="plus" nzTheme="outline"></span>
新增选项
</button>
</div>
}
@case ('NUMBER') {
<nz-input-number
class="!w-full"
nz-input
placeholder="请输入"
formControlName="value"
/>
}
@default {
<input
class="w-full"
nz-input
placeholder="请输入"
formControlName="value"
/>
}
}
</td>
<td>
<input nz-input placeholder="请输入" formControlName="remark" />
</td>
<td>
<button
nz-button
nzShape="circle"
nzType="primary"
nzDanger=""
(click)="removeFormItem($index)"
>
<span nz-icon nzType="delete" nzTheme="outline"></span>
</button>
</td>
</tr>
}
<tr>
<td colspan="6" class="text-right"></td>
<td>
<button nz-button nzType="primary" nzShape="circle" (click)="addFormItem()">
<span nz-icon nzType="plus" nzTheme="outline"></span>
</button>
</td>
</tr>
</tbody>
</nz-table>
</div>
</div>
</ng-template>
<ng-template #step3> 33 </ng-template>
<ng-template #radioTpl let-fields> </ng-template>
</form>
</div>
</nz-card>
</app-page>
<ng-template #formErrorTpl let-control>
<form-error-tips [control]="control"></form-error-tips>
</ng-template>

8
web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form-manage/basic-flow-form-manage.component.less

@ -0,0 +1,8 @@
.radio {
[nz-radio] {
display: block;
height: 32px;
line-height: 32px;
}
}

198
web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form-manage/basic-flow-form-manage.component.ts

@ -0,0 +1,198 @@
import { Component, inject } from '@angular/core'
import { FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms'
import { ActivatedRoute, Router } from '@angular/router'
import { FLOW_FORM_TYPES } from 'app/constants'
import { ApiService } from 'app/services'
import { UploadComponent } from 'app/shared/components/upload/upload.component'
import { SharedModule } from 'app/shared/shared.module'
import { FormValidators, Utils } from 'app/utils'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzModalService } from 'ng-zorro-antd/modal'
import { lastValueFrom } from 'rxjs'
@Component({
selector: 'app-basic-flow-form-manage',
standalone: true,
imports: [SharedModule, UploadComponent],
templateUrl: './basic-flow-form-manage.component.html',
styleUrl: './basic-flow-form-manage.component.less',
})
export class BasicFlowFormManageComponent {
constructor(public api: ApiService) {}
step = 0
formJsonData = []
FLOW_FORM_TYPES = FLOW_FORM_TYPES
formGroup = new FormGroup({
formKey: new FormControl('', [FormValidators.required()]),
formName: new FormControl('', [FormValidators.required()]),
templatePath: new FormControl('', []),
_formValue: new FormArray([]),
})
msg = inject(NzMessageService)
router = inject(Router)
modal = inject(NzModalService)
route = inject(ActivatedRoute)
get formValue(): FormArray {
return this.formGroup.get('_formValue') as FormArray
}
id: string | null = null
ngOnInit() {
const id = this.route.snapshot.paramMap.get('id')
if (id && id !== 'create') {
this.id = id
this.api.getFlowFormDetail(id).subscribe((res) => {
Object.entries(res.body).forEach(([k, v]) => {
if (k === '_formValue') {
this.patchFormValue(res.body[k] ?? [])
} else {
this.formGroup.get(k)?.setValue(v)
}
})
console.log('this.formGroup', this.formGroup)
})
}
}
downloadTemplate() {
this.msg.loading('模板下载中...')
this.api.getFlowFormsTpl().subscribe((res) => {
Utils.downLoadFile(res, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8')
this.msg.remove()
this.msg.success('模板下载成功')
})
}
fb = inject(FormBuilder)
onTplupload(e: NzSafeAny[]) {
this.patchFormValue(e)
}
patchFormValue(e: NzSafeAny[]) {
this.formValue.clear()
e.forEach((v) => {
let value = v.value
const fieldsArrays = this.fb.array([])
if (v.type === 'RADIO') {
let val = Object.create(null)
try {
val = typeof v.value === 'string' ? JSON.parse(v.value) : v.value
} catch (error) {}
val?.fields?.forEach((i: string) => {
fieldsArrays.push(this.fb.control(i))
})
value = val?.value
}
this.formValue.push(
new FormGroup({
key: new FormControl(v.key, []),
value: new FormControl(value, []),
name: new FormControl(v.name, []),
type: new FormControl(v.type, []),
remark: new FormControl(v.remark, []),
sort: new FormControl(v.sort ?? 0, []),
fields: fieldsArrays,
}),
)
})
}
nextStep(currentStep: number) {
if (currentStep === 0) {
if (!FormValidators.validateFormGroup(this.formGroup) || this.formValue.value.length === 0) {
this.msg.error('请完善表单信息')
return
}
}
if (currentStep === 2) {
this.handleSubmit()
}
this.step = currentStep + 1
}
handleSubmit() {
if (FormValidators.validateFormGroup(this.formGroup)) {
// if(this.formValue.value)
this.modal.confirm({
nzTitle: '提交表单',
nzContent: '确定提交表单?',
nzOnOk: async () => {
const vals = this.formGroup.value
const res = await lastValueFrom(
this.id
? this.api.updateFlowForm({
...vals,
id: this.id,
formTempId: this.id,
})
: this.api.addFlowForm(vals),
)
this.msg.success(res.desc)
this.router.navigate(['/fixed-asset/basic/flow-form/list'])
},
})
}
}
getRadioFieldsFormArray(index: number): FormArray {
return this.formValue.at(index).get('fields') as FormArray
}
getRadioFields(index: number): any[] {
return this.getRadioFieldsFormArray(index).controls
}
cancel(currentStep: number) {
if (currentStep === 0) {
this.router.navigate(['/fixed-asset/basic/flow-form/list'])
return
}
this.step = currentStep - 1
}
addRadioItem(idx: number) {
this.getRadioFieldsFormArray(idx).push(new FormControl())
}
addFormItem() {
this.formValue.push(
new FormGroup({
key: new FormControl(null, []),
value: new FormControl(null, []),
name: new FormControl(null, []),
type: new FormControl(null, []),
remark: new FormControl(null, []),
sort: new FormControl(null, []),
fields: this.fb.array([]),
}),
)
}
addFormValue() {
this.formValue.push(
new FormGroup({
key: new FormControl(),
value: new FormControl(),
name: new FormControl(),
type: new FormControl(),
remark: new FormControl(),
sort: new FormControl(0),
}),
)
}
removeFormItem(idx: number) {
this.formValue.removeAt(idx)
}
removeRadioItem(idx: number, idx2: number) {
this.getRadioFieldsFormArray(idx).removeAt(idx2)
}
}

71
web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form/basic-flow-form.component.html

@ -0,0 +1,71 @@
<app-page>
<ng-template #actionsTpl>
<nz-space>
<button
*nzSpaceItem
nzType="primary"
nz-button
[routerLink]="['/fixed-asset/basic/flow-form/manage/create']"
>
新建
</button>
<button *nzSpaceItem nzType="primary" nz-button [routerLink]="['/fixed-asset/basic/flow-form/import']">
导入
</button>
</nz-space>
</ng-template>
<div class="flex-1 overflow-hidden">
<app-server-paginated-table
[options]="table"
[tableAction]="actionsTpl"
[renderColumn]="renderColumnTpl"
[formGroup]="queryForm"
>
<ng-container *appTableForm>
<app-query-item label="表单状态">
<nz-select nzPlaceHolder="请选择" class="w-40">
<nz-option nzValue="1" nzLabel="所有表单"></nz-option>
<nz-option nzValue="2" nzLabel="默认巡检表单"></nz-option>
<nz-option nzValue="3" nzLabel="默认保养表单"></nz-option>
<nz-option nzValue="4" nzLabel="默认盘点表单"></nz-option>
</nz-select>
</app-query-item>
<app-query-item label="表单名称">
<input nz-input placeholder="请输入" class="w-60" formControlName="name" />
</app-query-item>
<app-query-item label="巡检班组">
<nz-select nzPlaceHolder="请选择" class="w-40">
<nz-option nzValue="1" nzLabel="所有类型"></nz-option>
<nz-option nzValue="2" nzLabel="物品领用"></nz-option>
<nz-option nzValue="3" nzLabel="设备报修"></nz-option>
</nz-select>
</app-query-item>
</ng-container>
<ng-template #renderColumnTpl let-data let-key="key" let-row="row">
@switch (key) {
@case ('formStatus') {
<app-status-tag [status]="data" />
}
@default {
{{ data }}
}
}
</ng-template>
</app-server-paginated-table>
</div>
</app-page>
<ng-template #createFormTpl>
<form nz-form [formGroup]="createForm">
<nz-form-item>
<nz-form-label [nzSpan]="6" [nzRequired]="true">审批人</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="errorTpl">
<app-select-user-by-org formControlName="userId" />
</nz-form-control>
</nz-form-item>
</form>
</ng-template>
<ng-template #errorTpl let-control>
<form-error-tips [control]="control"></form-error-tips>
</ng-template>

0
web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form/basic-flow-form.component.less

117
web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form/basic-flow-form.component.ts

@ -0,0 +1,117 @@
import { Component, inject, TemplateRef, ViewChild } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { Router } from '@angular/router'
import { StatusTagComponent } from 'app/components'
import { ApiService } from 'app/services'
import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table'
import { SharedModule } from 'app/shared/shared.module'
import { FormValidators } from 'app/utils'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzModalService } from 'ng-zorro-antd/modal'
import { lastValueFrom, map } from 'rxjs'
@Component({
selector: 'app-basic-flow-form',
standalone: true,
imports: [SharedModule, StatusTagComponent],
templateUrl: './basic-flow-form.component.html',
styleUrl: './basic-flow-form.component.less',
})
export class BasicFlowFormComponent {
constructor(
private api: ApiService,
private modal: NzModalService,
private msg: NzMessageService,
) {}
@ViewChild('createFormTpl') createFormTpl!: TemplateRef<{}>
queryForm = new FormGroup({
name: new FormControl(null),
})
createForm = new FormGroup({
formId: new FormControl(''),
userId: new FormControl<NzSafeAny[]>([], [FormValidators.required('请选择')]),
})
table = new TableOption(this.fetchData.bind(this))
ngOnInit(): void {
this.table
// .setConfig({
// selectable: true,
// rowKey: 'id',
// })
.setColumn([
{ key: 'formKey', title: '表单编号', visible: true },
{ key: 'formName', title: '表单名称', visible: true },
{ key: 'formStatus', title: '表单状态', visible: true },
{ key: 'createUserName', title: '创建人', visible: true },
{ key: 'createTime', title: '创建时间', visible: true },
{ key: 'updateTime', title: '最后修改时间', visible: true },
{ key: 'count', title: '项目数量', visible: true },
])
.setRowOperate([
{ title: '编辑', onClick: this.onEdit.bind(this) },
{ title: '删除', onClick: this.onDelete.bind(this) },
{ title: '停用', onClick: this.onSetApprover.bind(this) },
{ title: '预览', onClick: this.onSetApprover.bind(this) },
])
}
router = inject(Router)
onEdit(v: NzSafeAny) {
this.router.navigate(['/fixed-asset/basic/flow-form/manage/', v.formKey])
}
onDelete(data: NzSafeAny) {
this.modal.confirm({
nzTitle: '警告',
nzContent: '是否要删除该流程表单?',
nzOnOk: async () => {
const res = await lastValueFrom(this.api.deleteFlowForm([data.formTempId]))
this.table.ref.reload()
this.msg.success(res.desc)
},
})
}
fetchData(p: {}, q: AnyObject) {
return this.api.getFlowFormsList({ ...p, ...q }).pipe()
}
onSetApprover(data?: NzSafeAny) {
if (data) {
this.createForm.patchValue({
formId: data.formId,
userId: data._assignee.userId ? [data._assignee.userId] : [],
})
}
this.modal.create({
nzTitle: '设置审批人',
nzContent: this.createFormTpl,
nzOnOk: async () => {
if (FormValidators.validateFormGroup(this.createForm)) {
const vals = this.createForm.value
const res = await lastValueFrom(
this.api.setFlowFormsAssignee({
...vals,
userId: vals.userId?.[0],
}),
)
this.msg.success(res.desc)
this.table.ref.reload()
this.createForm.reset()
return true
}
return false
},
nzOnCancel: () => {
this.createForm.reset()
},
})
}
}

209
web-admin-app/src/app/pages/fixed-asset/fixed-asset.component.html

@ -17,13 +17,16 @@
[routerLink]="['/fixed-asset/ledger']"
nzMatchRouter
>
资台账
台账
</li>
<li nz-menu-item [nzPaddingLeft]="12" [routerLink]="['/fixed-asset/registration']" nzMatchRouter>资产登记</li>
<!-- nz-submenu
[nzOpen]="openedSubmenu.startsWith('/fixed-asset/manage/')" -->
<li
nz-submenu
[nzOpen]="openedSubmenu.startsWith('/fixed-asset/manage/')"
nz-menu-item
[nzPaddingLeft]="12"
nzTitle="固资管理"
[routerLink]="['/fixed-asset/management']"
nzMatchRouter
*appPermission="[
'fixed-asset-manage:view',
'fixed-asset-manage-entry:view',
@ -36,151 +39,101 @@
'fixed-asset-manage-scrap:view'
]"
>
资产管理
</li>
<li
nzMatchRouter
[nzPaddingLeft]="12"
nz-submenu
nzTitle="运维管理"
[nzOpen]="openedSubmenu.startsWith('/fixed-asset/maintain/')"
>
<!-- *appPermission="['maintain-record:view', 'maintain-on-off:view']" -->
<ul>
<li
*appPermission="['fixed-asset-manage:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/manage/list']"
nzMatchRouter
>
资产管理
</li>
<li
*appPermission="['fixed-asset-manage-entry:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/manage/entry']"
nzMatchRouter
>
资产入库
</li>
<li
*appPermission="['fixed-asset-manage-distribution:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/manage/distribution']"
nzMatchRouter
>
资产领用
</li>
<li
*appPermission="['fixed-asset-manage-return:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/manage/return']"
nzMatchRouter
>
资产退库
<li nz-menu-item [nzPaddingLeft]="24" [routerLink]="['/fixed-asset/maintain/record']" nzMatchRouter>
维修登记
</li>
<li
*appPermission="['fixed-asset-manage-borrow:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/manage/borrow']"
nzMatchRouter
>
资产借用
</li>
<li
*appPermission="['fixed-asset-manage-revert:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/manage/revert']"
nzMatchRouter
>
资产归还
<li nz-menu-item [nzPaddingLeft]="24" [routerLink]="['/fixed-asset/maintain/on-off']" nzMatchRouter>
开关机
</li>
</ul>
</li>
<li
nzMatchRouter
[nzPaddingLeft]="12"
nz-submenu
nzTitle="巡检管理"
[nzOpen]="openedSubmenu.startsWith('/fixed-asset/stocktaking/')"
*appPermission="['stocktaking-plan:view', 'stocktaking-job:view']"
>
<ul>
<li
*appPermission="['fixed-asset-manage-allot:view']"
*appPermission="['stocktaking-plan:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/manage/allot']"
[routerLink]="['/fixed-asset/inspection/plan']"
nzMatchRouter
>
资产调拨
巡检计划
</li>
<li
*appPermission="['fixed-asset-manage-transfer:view']"
*appPermission="['stocktaking-job:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/manage/transfer']"
[routerLink]="['/fixed-asset/inspection/task']"
nzMatchRouter
>
资产转移
巡检任务
</li>
<li
*appPermission="['fixed-asset-manage-scrap:view']"
*appPermission="['stocktaking-job:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/manage/scrap']"
[routerLink]="['/fixed-asset/inspection/calendar']"
nzMatchRouter
>
资产报废
巡检日历
</li>
<!-- <li nzMatchRouter [nzPaddingLeft]="24" nz-submenu nzTitle="资产变更">
<ul>
<li
nz-menu-item
[nzPaddingLeft]="36"
[routerLink]="['/fixed-asset/manage/entry']"
nzMatchRouter
>
资产基础变更
</li>
<li
nz-menu-item
[nzPaddingLeft]="36"
[routerLink]="['/fixed-asset/manage/entry']"
nzMatchRouter
>
资产维保变更
</li>
<li
nz-menu-item
[nzPaddingLeft]="12"
[routerLink]="['/fixed-asset/manage/entry']"
nzMatchRouter
>
资产财务变更
</li>
</ul>
</li> -->
</ul>
</li>
<li
nzMatchRouter
[nzPaddingLeft]="12"
nz-submenu
nzTitle="维护维保"
*appPermission="['fixed-asset-repair-list:view', 'fixed-asset-repair-fault:view']"
[nzOpen]="openedSubmenu.startsWith('/fixed-asset/repair/')"
nzTitle="保养管理"
[nzOpen]="openedSubmenu.startsWith('/fixed-asset/stocktaking/')"
*appPermission="['stocktaking-plan:view', 'stocktaking-job:view']"
>
<!-- 'fixed-asset-repair-type:view', -->
<ul>
<li
*appPermission="['fixed-asset-repair-list:view']"
*appPermission="['stocktaking-plan:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/repair/list']"
[routerLink]="['/fixed-asset/maintenance/plan']"
nzMatchRouter
>
维修登记
保养计划
</li>
<li
*appPermission="['fixed-asset-repair-fault:view']"
*appPermission="['stocktaking-job:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/repair/fault']"
[routerLink]="['/fixed-asset/maintenance/task']"
nzMatchRouter
>
故障登记
保养任务
</li>
<li
*appPermission="['stocktaking-job:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/maintenance/calendar']"
nzMatchRouter
>
保养日历
</li>
</ul>
</li>
<!-- <li nz-menu-item [nzPaddingLeft]="12" [routerLink]="['/fixed-asset/flow']" nzMatchRouter>固资流程</li>
<li nz-menu-item [nzPaddingLeft]="12" [routerLink]="['/fixed-asset/kucun']" nzMatchRouter>库存物品</li> -->
<li
nzMatchRouter
[nzPaddingLeft]="12"
@ -203,15 +156,24 @@
*appPermission="['stocktaking-job:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/stocktaking/job']"
[routerLink]="['/fixed-asset/stocktaking/task']"
nzMatchRouter
>
盘点任务
</li>
<li
*appPermission="['stocktaking-job:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/stocktaking/calendar']"
nzMatchRouter
>
盘点日历
</li>
</ul>
</li>
<li
<!-- <li
nzMatchRouter
[nzPaddingLeft]="12"
nz-submenu
@ -287,7 +249,7 @@
</ul>
</li>
</ul>
</li>
</li> -->
<li
nzMatchRouter
@ -316,7 +278,16 @@
[routerLink]="['/fixed-asset/basic/category']"
nzMatchRouter
>
物品分类
资产分类
</li>
<li
*appPermission="['basic-category:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/basic/flow-form']"
nzMatchRouter
>
流程表单
</li>
<li
*appPermission="['basic-manufacturer:view']"
@ -372,6 +343,24 @@
>
维修类型
</li>
<li
*appPermission="['fixed-asset-repair-type:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/basic/repair-type']"
nzMatchRouter
>
维修类型
</li>
<li
*appPermission="['fixed-asset-repair-type:view']"
nz-menu-item
[nzPaddingLeft]="24"
[routerLink]="['/fixed-asset/basic/team']"
nzMatchRouter
>
班组管理
</li>
</ul>
</li>

106
web-admin-app/src/app/pages/fixed-asset/maintain/maintain-on-off/maintain-on-off.component.html

@ -0,0 +1,106 @@
<app-page>
<ng-template #actionTpl>
<nz-space>
<button
*nzSpaceItem
nz-button
nzType="primary"
[disabled]="table.ref.selected.size === 0"
(click)="batchOnOff(1)"
>
批量开机
</button>
<button
*nzSpaceItem
nz-button
nzType="primary"
[disabled]="table.ref.selected.size === 0"
(click)="batchOnOff(0)"
nzDanger
>
批量关机
</button>
</nz-space>
</ng-template>
<div class="flex-1 overflow-hidden">
<app-server-paginated-table
[options]="table"
[tableAction]="actionTpl"
[formGroup]="queryForm"
[renderColumn]="renderColumnTpl"
>
<ng-template #renderColumnTpl let-data let-key="key" let-row="row">
@switch (key) {
@case ('_category') {
{{ data?.categoryName }}
}
@case ('_ownCompany') {
{{ data?.organizationName }}
}
@case ('status') {
<nz-tag>
{{ ASSET_STATUS_MAP[data] }}
</nz-tag>
}
@case ('_useOrganization') {
{{ data?.organizationName }}
}
@case ('_position') {
{{ data?.name }}
}
@case ('deviceStatus') {
<ng-container *ngIf="data === 'ON'">
<nz-tag nzColor="green">运行中</nz-tag>
</ng-container>
<ng-container *ngIf="data === 'OFF'">
<nz-tag nzColor="red">已关机</nz-tag>
</ng-container>
}
@default {
{{ data }}
}
}
</ng-template>
<ng-container *appTableForm>
<app-query-item label="业务分类">
<nz-select
nzPlaceHolder="请选择"
nzPlacement="bottomRight"
class="!w-24"
[nzDropdownMatchSelectWidth]="false"
formControlName="model"
nzAllowClear
>
<nz-option nzLabel="所有分类" nzValue=""></nz-option>
<nz-option *ngFor="let item of ASSET_TYPE" [nzLabel]="item.label" [nzValue]="item.value" />
</nz-select>
</app-query-item>
<app-query-item label="资产状态">
<nz-select
nzPlacement="bottomRight"
class="!w-24"
[nzDropdownMatchSelectWidth]="false"
formControlName="status"
nzPlaceHolder="请选择"
nzAllowClear
>
@for (item of ASSET_STATUS_MAP | keyvalue; track $index) {
<nz-option [nzLabel]="item.value" [nzValue]="item.key"></nz-option>
}
</nz-select>
</app-query-item>
<app-query-item label="设备名称">
<input nz-input placeholder="请输入" formControlName="name" />
</app-query-item>
<app-query-item label="设备编号">
<input nz-input placeholder="请输入" formControlName="assetCode" />
</app-query-item>
<app-query-item label="位置信息">
<app-position-select formControlName="positionId" />
</app-query-item>
</ng-container>
</app-server-paginated-table>
</div>
</app-page>

0
web-admin-app/src/app/pages/fixed-asset/maintain/maintain-on-off/maintain-on-off.component.less

105
web-admin-app/src/app/pages/fixed-asset/maintain/maintain-on-off/maintain-on-off.component.ts

@ -0,0 +1,105 @@
import { Component, TemplateRef, ViewChild } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { format } from 'date-fns'
import { lastValueFrom, of } from 'rxjs'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NzModalService } from 'ng-zorro-antd/modal'
import { NzMessageService } from 'ng-zorro-antd/message'
import { ASSET_STATUS_MAP, ASSET_TYPE } from 'app/constants'
import { PositionSelectComponent } from 'app/components'
@Component({
selector: 'app-maintain-on-off',
standalone: true,
imports: [SharedModule, PositionSelectComponent],
templateUrl: './maintain-on-off.component.html',
styleUrl: './maintain-on-off.component.less',
})
export class MaintainOnOffComponent {
constructor(
private api: ApiService,
private modal: NzModalService,
private msg: NzMessageService,
) {}
queryForm = new FormGroup({
model: new FormControl(),
name: new FormControl(),
status: new FormControl(),
assetCode: new FormControl(),
positionId: new FormControl(),
})
table = new TableOption(this.fetchData.bind(this))
ASSET_STATUS_MAP = ASSET_STATUS_MAP()
ASSET_TYPE = ASSET_TYPE
ngOnInit(): void {
this.table
.setConfig({
selectable: true,
rowKey: 'assetId',
})
.setColumn([
{ key: 'serialNumber', title: '序号', visible: true },
{ key: 'assetCode', title: '资产编号', visible: true },
{ key: 'name', title: '资产名称', visible: true },
{ key: '_category', title: '资产分类', visible: true },
{ key: 'status', title: '资产状态', visible: true },
{ key: '_ownCompany', title: '所属公司', visible: true },
{ key: '_useOrganization', title: '使用组织', visible: true },
{ key: '_position', title: '位置信息', visible: true },
{ key: 'deviceStatus', title: '当前状态', visible: true },
])
.setRowOperate([
// { title: '修改', onClick: this.onCreate.bind(this) },
{
title: '开机',
visible(v) {
return v.deviceStatus === 'OFF'
},
onClick: (v) => {
this.onOff([v.assetId], 1)
},
},
{
title: '关机',
visible(v) {
return v.deviceStatus === 'ON'
},
onClick: (v) => {
this.onOff([v.assetId], 0)
},
},
{ title: '记录', onClick: this.onOff.bind(this, [0]) },
])
}
fetchData(p: {}, q: AnyObject) {
return this.api.getDeviceOnOffPage({ ...p, ...q })
}
onOff(ids: any[], type: number) {
console.log('type', ids, type)
const typeText = type === 1 ? '开机' : '关机'
this.modal.confirm({
nzTitle: '警告',
nzContent: `是否要${typeText}${ids.length}个设备?`,
nzOnOk: async () => {
const res = await lastValueFrom(this.api.onOffDevice(ids, type))
this.msg.success(res.desc)
this.table.ref.reload()
},
})
}
batchOnOff(type: number) {
this.onOff(Array.from(this.table.ref.selected), type)
}
}

38
web-admin-app/src/app/pages/fixed-asset/maintain/maintain-record/maintain-record.component.html

@ -0,0 +1,38 @@
<app-page>
<ng-template #actionTpl>
<nz-space>
<button *nzSpaceItem nz-button nzType="primary" (click)="onCreate()">
<span>新建</span>
</button>
</nz-space>
</ng-template>
<div class="flex-1 overflow-hidden">
<app-server-paginated-table
[options]="table"
[tableAction]="actionTpl"
[formGroup]="queryForm"
[renderColumn]="renderColumnTpl"
>
<ng-template #renderColumnTpl let-data let-key="key" let-row="row">
@switch (key) {
@default {
{{ data }}
}
}
</ng-template>
<ng-container *appTableAction>
<nz-space>
<button *nzSpaceItem nz-button nzType="link" nzDanger="">删除</button>
</nz-space>
</ng-container>
<ng-container *appTableForm>
<app-query-item label="业务名称">
<input nz-input placeholder="请输入" formControlName="name" />
</app-query-item>
<app-query-item label="业务编号">
<input nz-input placeholder="请输入" formControlName="businessId" />
</app-query-item>
</ng-container>
</app-server-paginated-table>
</div>
</app-page>

0
web-admin-app/src/app/pages/fixed-asset/maintain/maintain-record/maintain-record.component.less

97
web-admin-app/src/app/pages/fixed-asset/maintain/maintain-record/maintain-record.component.ts

@ -0,0 +1,97 @@
import { Component, TemplateRef, ViewChild } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { format } from 'date-fns'
import { lastValueFrom, of } from 'rxjs'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NzModalService } from 'ng-zorro-antd/modal'
import { NzMessageService } from 'ng-zorro-antd/message'
import { RepairFormComponent } from 'app/components'
import { MaintainRecordFormComponent } from 'app/components/maintain-record-form/maintain-record-form.component'
@Component({
selector: 'app-maintain-record',
standalone: true,
imports: [SharedModule],
templateUrl: './maintain-record.component.html',
styleUrl: './maintain-record.component.less',
})
export class MaintainRecordComponent {
constructor(
private api: ApiService,
private modal: NzModalService,
private msg: NzMessageService,
) {}
queryForm = new FormGroup({
name: new FormControl(''),
businessId: new FormControl(''),
})
table = new TableOption(this.fetchData.bind(this))
ngOnInit(): void {
this.table
// .setConfig({
// selectable: true,
// rowKey: 'id',
// })
.setColumn([
{ key: 'name', title: '业务名称', visible: true },
{ key: 'businessId', title: '业务编号', visible: true },
{ key: 'plannedDate', title: '计划完成时间', visible: true },
{ key: 'notes', title: '备注', visible: true },
{ key: 'createTime', title: '创建时间', visible: true },
])
.setRowOperate([
{ title: '修改', onClick: this.onCreate.bind(this) },
{ title: '删除', onClick: this.deleteItem.bind(this) },
])
}
fetchData(p: {}, q: AnyObject) {
return this.api.getRepairPage({ ...p, ...q })
}
onCreate(data?: NzSafeAny, preview?: boolean) {
this.modal.create({
nzTitle: data ? '编辑维修登记' : '添加维修登记',
nzContent: MaintainRecordFormComponent,
nzWidth: '80vw',
nzWrapClassName: 'modal-lg',
nzData: {
value: data,
preview,
},
nzOnOk: async (e) => {
const vals = e.getValues()
if (vals) {
const res = await lastValueFrom(this.api.saveRepair(vals))
this.msg.success(res.desc)
this.table.ref.reload()
return true
}
return false
},
})
}
deleteItem(item?: NzSafeAny) {
const ids = [item.id]
this.modal.confirm({
nzTitle: '警告',
nzContent: `是否要删除${ids.length}个维修登记?`,
nzOnOk: async () => {
const res = await lastValueFrom(this.api.deleteRepair(ids))
this.msg.success(res.desc)
this.table.ref.reload()
},
})
}
}

1
web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-calendar/inspection-calendar.component.html

@ -0,0 +1 @@
<app-calendar-list type="inspection" />

0
web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-calendar/inspection-calendar.component.less

12
web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-calendar/inspection-calendar.component.ts

@ -0,0 +1,12 @@
import { Component } from '@angular/core'
import { CalendarListComponent } from 'app/components/plan-task/calendar-list/calendar-list.component'
import { SharedModule } from 'app/shared/shared.module'
@Component({
selector: 'app-inspection-calendar',
standalone: true,
imports: [SharedModule, CalendarListComponent],
templateUrl: './inspection-calendar.component.html',
styleUrl: './inspection-calendar.component.less',
})
export class InspectionCalendarComponent {}

1
web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-plan/inspection-plan.component.html

@ -0,0 +1 @@
<app-plan-list />

0
web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-plan/inspection-plan.component.less

13
web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-plan/inspection-plan.component.ts

@ -0,0 +1,13 @@
import { Component } from '@angular/core'
import { PlanListComponent } from 'app/components/plan-task/plan-list/plan-list.component'
import { TaskListComponent } from 'app/components/plan-task/task-list/task-list.component'
import { SharedModule } from 'app/shared/shared.module'
@Component({
selector: 'app-inspection-plan',
standalone: true,
imports: [SharedModule, PlanListComponent],
templateUrl: './inspection-plan.component.html',
styleUrl: './inspection-plan.component.less',
})
export class InspectionPlanComponent {}

1
web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-task/inspection-task.component.html

@ -0,0 +1 @@
<app-task-list type="inspection" />

0
web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-task/inspection-task.component.less

12
web-admin-app/src/app/pages/fixed-asset/plan-task/inspection-task/inspection-task.component.ts

@ -0,0 +1,12 @@
import { Component } from '@angular/core'
import { TaskListComponent } from 'app/components/plan-task/task-list/task-list.component'
import { SharedModule } from 'app/shared/shared.module'
@Component({
selector: 'app-inspection-task',
standalone: true,
imports: [SharedModule, TaskListComponent],
templateUrl: './inspection-task.component.html',
styleUrl: './inspection-task.component.less',
})
export class InspectionTaskComponent {}

1
web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-calendar/maintenance-calendar.component.html

@ -0,0 +1 @@
<p>maintenance-calendar works!</p>

0
web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-calendar/maintenance-calendar.component.less

12
web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-calendar/maintenance-calendar.component.ts

@ -0,0 +1,12 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-maintenance-calendar',
standalone: true,
imports: [],
templateUrl: './maintenance-calendar.component.html',
styleUrl: './maintenance-calendar.component.less'
})
export class MaintenanceCalendarComponent {
}

1
web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-plan/maintenance-plan.component.html

@ -0,0 +1 @@
<p>maintenance-plan works!</p>

0
web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-plan/maintenance-plan.component.less

12
web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-plan/maintenance-plan.component.ts

@ -0,0 +1,12 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-maintenance-plan',
standalone: true,
imports: [],
templateUrl: './maintenance-plan.component.html',
styleUrl: './maintenance-plan.component.less'
})
export class MaintenancePlanComponent {
}

1
web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-task/maintenance-task.component.html

@ -0,0 +1 @@
<p>maintenance-task works!</p>

0
web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-task/maintenance-task.component.less

12
web-admin-app/src/app/pages/fixed-asset/plan-task/maintenance-task/maintenance-task.component.ts

@ -0,0 +1,12 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-maintenance-task',
standalone: true,
imports: [],
templateUrl: './maintenance-task.component.html',
styleUrl: './maintenance-task.component.less'
})
export class MaintenanceTaskComponent {
}

1
web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-calendar/stocktaking-calendar.component.html

@ -0,0 +1 @@
<p>stocktaking-calendar works!</p>

0
web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-calendar/stocktaking-calendar.component.less

12
web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-calendar/stocktaking-calendar.component.ts

@ -0,0 +1,12 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-stocktaking-calendar',
standalone: true,
imports: [],
templateUrl: './stocktaking-calendar.component.html',
styleUrl: './stocktaking-calendar.component.less'
})
export class StocktakingCalendarComponent {
}

1
web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-plan/stocktaking-plan.component.html

@ -0,0 +1 @@
<p>stocktaking-plan works!</p>

0
web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-plan/stocktaking-plan.component.less

12
web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-plan/stocktaking-plan.component.ts

@ -0,0 +1,12 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-stocktaking-plan',
standalone: true,
imports: [],
templateUrl: './stocktaking-plan.component.html',
styleUrl: './stocktaking-plan.component.less'
})
export class StocktakingPlanComponent {
}

1
web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-task/stocktaking-task.component.html

@ -0,0 +1 @@
<p>stocktaking-task works!</p>

0
web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-task/stocktaking-task.component.less

12
web-admin-app/src/app/pages/fixed-asset/plan-task/stocktaking-task/stocktaking-task.component.ts

@ -0,0 +1,12 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-stocktaking-task',
standalone: true,
imports: [],
templateUrl: './stocktaking-task.component.html',
styleUrl: './stocktaking-task.component.less'
})
export class StocktakingTaskComponent {
}

283
web-admin-app/src/app/pages/fixed-asset/registration/registration.component.html

@ -0,0 +1,283 @@
<app-page>
<ng-template #actionTpl>
<nz-space>
<button *nzSpaceItem nz-button nzType="primary" (click)="onCreate()">
<span>登记资产</span>
</button>
<button *nzSpaceItem nzDanger nz-button [disabled]="table.ref.selected.size === 0" (click)="deleteItem()">
<span>批量删除</span>
</button>
<!-- <button *nzSpaceItem nz-button [disabled]="table.ref.selected.size === 0" (click)="confirmAsset()">
<span>资产确认</span>
</button> -->
<button *nzSpaceItem nz-button (click)="importExcel(importExcelTpl)">
<span>批量导入</span>
</button>
<!-- <button *nzSpaceItem nz-button nz-dropdown [nzDropdownMenu]="export">
<span>导入/导出</span>
<i nz-icon nzType="down"></i>
<nz-dropdown-menu #export="nzDropdownMenu">
<ul nz-menu>
<li nz-menu-item (click)="importExcel(importExcelTpl)">导入Excel</li>
<li nz-menu-item [nzDisabled]="table.ref.selected.size === 0" (click)="exportExcel()">
导出Excel
</li>
</ul>
</nz-dropdown-menu>
</button> -->
</nz-space>
</ng-template>
<div class="flex-1 overflow-hidden">
<app-server-paginated-table
[options]="table"
[formGroup]="queryForm"
[tableAction]="actionTpl"
[renderColumn]="renderColumnTpl"
>
<ng-template #renderColumnTpl let-data let-key="key" let-row="row">
@switch (key) {
@case ('status') {
<nz-tag>
{{ ASSET_STATUS_MAP[data] }}
</nz-tag>
}
@case ('_useUser') {
{{ data?.userName ?? '-' }}
}
@case ('_warehouse') {
{{ data?.name ?? '-' }}
}
@case ('_position') {
{{ data?.name ?? '-' }}
}
@case ('_head') {
{{ data?.userName ?? '-' }}
}
@case ('_ownCompany') {
{{ data?.organizationName ?? '-' }}
}
@case ('_useOrganization') {
{{ data?.organizationName ?? '-' }}
}
@case ('_category') {
{{ data?.categoryName ?? '-' }}
}
@default {
{{ data }}
}
}
</ng-template>
<!-- <ng-container *appTableAction>
<nz-space>
<button *nzSpaceItem nz-button nzType="link">资产确认</button>
<button *nzSpaceItem nz-button nzType="link" nzDanger="">删除</button>
</nz-space>
</ng-container> -->
<ng-container *appTableForm>
<app-query-item label="资产名称">
<input nz-input placeholder="请输入" formControlName="name" />
</app-query-item>
<app-query-item label="资产编号">
<input nz-input placeholder="请输入" formControlName="assetCode" />
</app-query-item>
<app-query-item label="规格型号">
<input nz-input placeholder="请输入" formControlName="model" />
</app-query-item>
<app-query-item label="序列号">
<input nz-input placeholder="请输入" formControlName="serialNumber" />
</app-query-item>
<app-query-item label="资产状态">
<nz-select
nzPlacement="bottomRight"
class="!w-24"
[nzDropdownMatchSelectWidth]="false"
formControlName="status"
>
@for (item of ASSET_STATUS_MAP | keyvalue; track $index) {
<nz-option [nzLabel]="item.value" [nzValue]="item.key"></nz-option>
}
</nz-select>
</app-query-item>
<app-query-item label="资产来源">
<nz-select
nzPlacement="bottomRight"
class="!w-24"
[nzDropdownMatchSelectWidth]="false"
formControlName="sourceId"
>
@for (item of ASSET_SOURCE_MAP | keyvalue; track $index) {
<nz-option [nzLabel]="item.value" [nzValue]="item.key"></nz-option>
}
</nz-select>
</app-query-item>
<app-query-item label="位置">
<app-position-select formControlName="positionId" />
</app-query-item>
<app-query-item label="生产厂商">
<app-manufacturer-select class="block w-36" formControlName="manufacturersVendorId" />
</app-query-item>
<!-- <app-query-item label="设备标签">
<input nz-input placeholder="请输入" formControlName="name" />
</app-query-item>
<app-query-item label="设备IP">
<input nz-input placeholder="请输入" formControlName="name" />
</app-query-item>
<app-query-item label="管理IP">
<input nz-input placeholder="请输入" formControlName="name" />
</app-query-item>
<app-query-item label="设备IP">
<input nz-input placeholder="请输入" formControlName="name" />
</app-query-item>
<app-query-item label="运行环境">
<nz-select
nzPlacement="bottomRight"
class="!w-auto"
[nzDropdownMatchSelectWidth]="false"
>
<nz-option nzValue="123" nzLabel="营业"></nz-option>
<nz-option nzValue="22" nzLabel="办公"></nz-option>
<nz-option nzValue="2211" nzLabel="生产"></nz-option>
<nz-option nzValue="2221" nzLabel="测试"></nz-option>
</nz-select>
</app-query-item>
<app-query-item label="来源">
<nz-select
nzPlacement="bottomRight"
class="!w-auto"
[nzDropdownMatchSelectWidth]="false"
>
<nz-option nzValue="123" nzLabel="捐赠"></nz-option>
<nz-option nzValue="22" nzLabel="赠送"></nz-option>
<nz-option nzValue="2211" nzLabel="采购"></nz-option>
<nz-option nzValue="2221" nzLabel="自建"></nz-option>
<nz-option nzValue="2221" nzLabel="自购"></nz-option>
<nz-option nzValue="2221" nzLabel="其他"></nz-option>
</nz-select>
</app-query-item>
<app-query-item label="厂商">
<nz-select
nzPlacement="bottomRight"
class="!w-auto"
[nzDropdownMatchSelectWidth]="false"
>
<nz-option nzValue="123" nzLabel="11"></nz-option>
</nz-select>
</app-query-item>
<app-query-item label="维保商">
<nz-select
nzPlacement="bottomRight"
class="!w-auto"
[nzDropdownMatchSelectWidth]="false"
>
<nz-option nzValue="123" nzLabel="11"></nz-option>
</nz-select>
</app-query-item>
<app-query-item label="采购日期">
<app-date-query></app-date-query>
</app-query-item>
<app-query-item label="所属公司">
<nz-select
nzPlacement="bottomRight"
class="!w-auto"
[nzDropdownMatchSelectWidth]="false"
>
<nz-option nzValue="123" nzLabel="11"></nz-option>
</nz-select>
</app-query-item>
<app-query-item label="使用组织">
<nz-select
nzPlacement="bottomRight"
class="!w-auto"
[nzDropdownMatchSelectWidth]="false"
>
<nz-option nzValue="123" nzLabel="11"></nz-option>
</nz-select>
</app-query-item>
<app-query-item label="管理人员">
<nz-select
nzPlacement="bottomRight"
class="!w-auto"
[nzDropdownMatchSelectWidth]="false"
>
<nz-option nzValue="123" nzLabel="11"></nz-option>
</nz-select>
</app-query-item>
<app-query-item label="使用人员">
<nz-select
nzPlacement="bottomRight"
class="!w-auto"
[nzDropdownMatchSelectWidth]="false"
>
<nz-option nzValue="123" nzLabel="11"></nz-option>
</nz-select>
</app-query-item> -->
</ng-container>
</app-server-paginated-table>
</div>
</app-page>
<ng-template #copyTpl>
<div nz-form>
<nz-alert [nzMessage]="copyTextTpl">
<ng-template #copyTextTpl>
1、为了保证复制速度,一次最多可复制200个资产<br />
2、以下资产信息不可被复制:资产编码、资产编码(旧)、序列号、使用人、管理人、入库时间、累计折旧、残值、净值<br />
3、复制后的资产状态为空闲
</ng-template>
</nz-alert>
<div class="mt-3">
<nz-form-item>
<nz-form-label [nzSpan]="6" nzRequired> 复制数量 </nz-form-label>
<nz-form-control [nzSpan]="12">
<nz-input-number [nzMin]="1" class="!w-full" [(ngModel)]="copyNum" nzPlaceHolder="请输入" />
</nz-form-control>
</nz-form-item>
</div>
</div>
</ng-template>
<ng-template #importExcelTpl>
<div nz-form>
<div class="mb-3">
<nz-form-item>
<nz-form-label [nzSpan]="6" nzRequired> 模版文件 </nz-form-label>
<nz-form-control [nzSpan]="12">
<button nz-button nzType="link" (click)="downloadTemplate()">模板文件下载</button>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="6" nzRequired> 文件 </nz-form-label>
<nz-form-control [nzSpan]="12">
<button nz-button class="upload-btn">
<i nz-icon nzType="upload"></i>
选择文件
<input type="file" (change)="onFileChange($event)" />
</button>
</nz-form-control>
</nz-form-item>
</div>
<nz-alert [nzMessage]="copyTextTpl">
<ng-template #copyTextTpl>
按照要求填写Excel数据,系统会对部分字段做验证! <br />
资产导入规则 字段填写要求:<br />
1、资产编码:资产编号由后台自动生成,导入数据时不填写<br />
2、资产分类:填写系统中存在的资产分类名称,若资产分类存在重名时,请同时填写上资产分类的id<br />
3、所属公司:填写系统中存在的公司名称,若公司存在重名时,请同时填写上公司的id<br />
4、使用组织:填写系统中存在的组织名称,若组织存在重名时,请同时填写上组织的id<br />
5、管理人员:填写系统中存在的管理员姓名,若管理员姓名存在重名时,请同时填写上管理员id<br />
6、供应商:填写系统中存在的供应商名称,若供应商存在重名时,请同时填写上供应商的id<br />
7、资产厂商:填写系统中存在的资产厂商名称,若资产厂商存在重名时,请同时填写上资产厂商的id<br />
8、使用人员:填写系统中存在的账户姓名,若账户姓名存在重名时,请同时填写上使用人员id<br />
9、存放位置:填写系统中存在的存放位置名称,若存放位置名称存在重名时,请同时填写上存放位置id<br />
10、维保信息_维保厂商:填写系统中存在的维保厂商名称,若维保厂商名称存在重名时,请同时填写上维保厂商id<br />
11、日期格式:yyyy-MM-dd HH:mm:ss<br />
12、财务信息:保留2位小数,若您填写超过2位小数后,系统会自动做四舍五入处理<br />
</ng-template>
</nz-alert>
</div>
</ng-template>

0
web-admin-app/src/app/pages/fixed-asset/registration/registration.component.less

208
web-admin-app/src/app/pages/fixed-asset/registration/registration.component.ts

@ -0,0 +1,208 @@
import { Component, TemplateRef, ViewChild } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { format } from 'date-fns'
import { lastValueFrom, of } from 'rxjs'
import { AssetFormComponent, ManufacturerSelectComponent, PositionSelectComponent } from 'app/components'
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { ASSET_SOURCE_MAP, ASSET_STATUS, ASSET_STATUS_MAP } from 'app/constants'
import { Utils } from 'app/utils'
@Component({
selector: 'app-fixed-asset-registration',
standalone: true,
imports: [SharedModule, AssetFormComponent, PositionSelectComponent, ManufacturerSelectComponent],
templateUrl: './registration.component.html',
styleUrl: './registration.component.less',
})
export class RegistrationComponent {
constructor(
private api: ApiService,
private modal: NzModalService,
private msg: NzMessageService,
) {}
queryForm = new FormGroup({
name: new FormControl(),
model: new FormControl(),
status: new FormControl(),
assetCode: new FormControl(),
serialNumber: new FormControl(),
sourceId: new FormControl(),
positionId: new FormControl(),
manufacturersVendorId: new FormControl(),
})
@ViewChild('copyTpl') copyTpl!: TemplateRef<NzSafeAny>
ASSET_STATUS_MAP = ASSET_STATUS_MAP()
ASSET_SOURCE_MAP = ASSET_SOURCE_MAP
table = new TableOption(this.fetchData.bind(this))
copyNum = 1
ngOnInit(): void {
this.table
.setConfig({
selectable: true,
rowKey: 'assetId',
})
.setColumn([
{ key: 'assetCode', title: '资产编号', visible: true },
{ key: 'name', title: '资产名称', visible: true },
{ key: '_category', title: '资产分类', visible: true },
{ key: 'status', title: '资产状态', visible: true },
{ key: '_ownCompany', title: '所属公司', visible: true },
{ key: '_useOrganization', title: '使用组织', visible: true },
{ key: '_position', title: '存放位置', visible: true },
])
.setRowOperate([
{
title: '查看',
onClick: (v) => {
this.onCreate(v, true)
},
},
{ title: '修改', onClick: this.onCreate.bind(this) },
{ title: '复制', onClick: this.onCopy.bind(this) },
{ title: '二维码', onClick: this.qrcode.bind(this) },
{ title: '删除', onClick: this.deleteItem.bind(this) },
])
}
fetchData(p: {}, q: AnyObject) {
return this.api.getAssetPage({ ...p, ...q })
}
onCopy(data: NzSafeAny) {
this.modal.create({
nzTitle: '复制资产',
nzWidth: 600,
nzContent: this.copyTpl,
nzOnOk: async () => {
if (!this.copyNum) {
this.msg.error('请输入复制数量')
return false
}
const res = await lastValueFrom(this.api.copyAsset(this.copyNum, data.assetId))
this.msg.success(res.desc)
this.table.ref.reload()
return true
},
})
}
onCreate(data?: NzSafeAny, preview?: boolean) {
let nzTitle = data ? '编辑资产' : '添加资产'
if (preview) {
nzTitle = '预览资产'
}
this.modal.create({
nzTitle,
nzContent: AssetFormComponent,
nzWidth: '80vw',
nzWrapClassName: 'modal-lg',
nzData: {
value: data,
preview,
},
nzOnOk: async (e) => {
const vals = e.getValues()
if (vals) {
const res = await lastValueFrom(this.api.saveAsset(vals))
this.msg.success(res.desc)
this.table.ref.reload()
return true
}
return false
},
})
}
deleteItem(item?: NzSafeAny) {
const ids = item ? [item.assetId] : Array.from(this.table.ref.selected)
this.modal.confirm({
nzTitle: '警告',
nzContent: `是否要删除${ids.length}个资产?`,
nzOnOk: async () => {
const res = await lastValueFrom(this.api.deleteAsset(ids))
this.msg.success(res.desc)
this.table.ref.reload()
},
})
}
confirmAsset() {
const ids = Array.from(this.table.ref.selected).map((i) => Number(i))
this.modal.confirm({
nzTitle: '警告',
nzContent: `是否对选择的${ids.length}个资产进行确认?`,
nzOnOk: async () => {
const res = await lastValueFrom(this.api.confirmAsset(ids))
this.msg.success(res.desc)
this.table.ref.reload()
},
})
}
qrcode(d: NzSafeAny) {
this.msg.loading('二维码生成中...')
this.api.assetQrcode(d.assetId).subscribe((res) => {
Utils.downLoadFile(res, 'application/pdf')
this.msg.remove()
this.msg.success('二维码生成成功')
})
}
downloadTemplate() {
this.msg.loading('模板下载中...')
this.api.downloadAssetTemplate().subscribe((res) => {
Utils.downLoadFile(res, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8')
this.msg.remove()
this.msg.success('模板下载成功')
})
}
importModalRef?: NzModalRef
importExcel(nzContent: TemplateRef<{}>) {
this.importModalRef = this.modal.create({
nzTitle: '资产数据导入',
nzContent,
nzWidth: 800,
nzFooter: null,
})
}
onFileChange(e: Event) {
const target = e.target as HTMLInputElement
const file = target.files![0]
target.value = ''
const formdata = new FormData()
formdata.append('file', file)
this.api.uploadAsset(formdata).subscribe((res) => {
this.importModalRef?.close()
this.msg.success(res.desc)
this.table.ref.reload()
})
}
exportExcel() {
const ids = Array.from(this.table.ref.selected).map((i) => Number(i))
if (ids.length === 0) {
return
}
this.msg.loading('Excel生成中...')
this.api.exportAsset(ids).subscribe((res) => {
Utils.downLoadFile(res, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8')
this.msg.remove()
this.msg.success('Excel生成成功')
})
}
}

145
web-admin-app/src/app/pages/flow/flow-main/flow-main.component.html

@ -1,37 +1,124 @@
<app-page>
<nz-spin [nzSpinning]="loading">
<div nz-row [nzGutter]="[24, 24]">
@for (item of assetFlows; track $index) {
<div nz-col nzSpan="8" [nzXl]="6">
<nz-card [nzBordered]="false" [nzActions]="[actionSetting]">
<div class="h-22 flex overflow-hidden">
<div class="flex-shrink-0">
<div class="icon flex items-center justify-center">
<span nz-icon nzType="node-index" nzTheme="outline"></span>
<div nz-row [nzGutter]="[24, 24]">
<div nz-col nzSpan="12">
<nz-card [nzBordered]="false" nzTitle="资管流程分析">
<div nz-row nzGutter="12">
<div nz-col nzSpan="8">
<nz-statistic nzTitle="累计流程总数" nzValue="15666" />
</div>
<div nz-col nzSpan="8">
<nz-statistic nzTitle="当日新增流程" nzValue="11" />
</div>
<div nz-col nzSpan="8">
<nz-statistic nzTitle="待我处理流程" nzValue="2" />
</div>
</div>
</nz-card>
</div>
<div nz-col nzSpan="12">
<nz-card [nzBordered]="false" nzTitle="设备流程统计">
<div nz-row nzGutter="12">
<div nz-col nzSpan="8">
<nz-statistic nzTitle="累计流程总数" nzValue="15666" />
</div>
<div nz-col nzSpan="8">
<nz-statistic nzTitle="当日新增流程" nzValue="11" />
</div>
<div nz-col nzSpan="8">
<nz-statistic nzTitle="待我处理流程" nzValue="2" />
</div>
</div>
</nz-card>
</div>
</div>
<div class="mt-4">
<nz-card [nzBordered]="false" nzTitle="资管流程">
<nz-spin [nzSpinning]="loading">
<div nz-row [nzGutter]="[24, 24]">
@for (item of assetFlows; track $index) {
<div nz-col nzSpan="8" [nzXl]="4" (click)="onStart(item)" class="cursor-pointer">
<div>
<div class="h-22 flex flex-col items-center justify-center text-center overflow-hidden">
<div class="flex-shrink-0">
<div class="icon flex items-center justify-center rounded">
<span nz-icon nzType="node-index" nzTheme="outline"></span>
</div>
</div>
<div class="flex-1 pt-3 text-base overflow-hidden">
<div>
{{ item.name }}
</div>
</div>
</div>
</div>
</div>
}
</div>
</nz-spin>
</nz-card>
</div>
<div class="mt-4">
<nz-card [nzBordered]="false" nzTitle="设备流程">
<nz-spin [nzSpinning]="loading">
<div nz-row [nzGutter]="[24, 24]">
<div nz-col nzSpan="8" [nzXl]="4" class="cursor-pointer" (click)="createTask('repair')">
<div>
<div class="h-22 flex flex-col items-center justify-center text-center overflow-hidden">
<div class="flex-shrink-0">
<div class="icon flex items-center justify-center rounded">
<span nz-icon nzType="node-index" nzTheme="outline"></span>
</div>
</div>
<div class="flex-1 pt-3 text-base overflow-hidden">
<div>报修维修</div>
</div>
</div>
</div>
</div>
<div nz-col nzSpan="8" [nzXl]="4" class="cursor-pointer" (click)="createTask('inspection')">
<div>
<div class="h-22 flex flex-col items-center justify-center text-center overflow-hidden">
<div class="flex-shrink-0">
<div class="icon flex items-center justify-center rounded">
<span nz-icon nzType="node-index" nzTheme="outline"></span>
</div>
</div>
<div class="flex-1 pt-3 text-base overflow-hidden">
<div>巡检任务</div>
</div>
</div>
<div class="flex-1 pl-3 text-base overflow-hidden">
<div>
{{ item.name }}
</div>
<div class="mt-2 break-words whitespace-pre-wrap">{{ item.formKey }}</div>
@if (item._assignee) {
<div class="mt-2">
<nz-tag> 审批人:{{ item._assignee.userName }} </nz-tag>
</div>
</div>
<div nz-col nzSpan="8" [nzXl]="4" class="cursor-pointer" (click)="createTask('maintenance')">
<div>
<div class="h-22 flex flex-col items-center justify-center text-center overflow-hidden">
<div class="flex-shrink-0">
<div class="icon flex items-center justify-center rounded">
<span nz-icon nzType="node-index" nzTheme="outline"></span>
</div>
}
</div>
<div class="flex-1 pt-3 text-base overflow-hidden">
<div>保养任务</div>
</div>
</div>
</div>
<ng-template #actionSetting>
@if (item.enabled) {
<div (click)="onStart(item)">发起流程</div>
} @else {
<div>没有表单</div>
}
</ng-template>
</nz-card>
</div>
<div nz-col nzSpan="8" [nzXl]="4" class="cursor-pointer" (click)="createTask('stocktaking')">
<div>
<div class="h-22 flex flex-col items-center justify-center text-center overflow-hidden">
<div class="flex-shrink-0">
<div class="icon flex items-center justify-center rounded">
<span nz-icon nzType="node-index" nzTheme="outline"></span>
</div>
</div>
<div class="flex-1 pt-3 text-base overflow-hidden">
<div>盘点任务</div>
</div>
</div>
</div>
</div>
</div>
}
</div>
</nz-spin>
</nz-spin>
</nz-card>
</div>
</app-page>

6
web-admin-app/src/app/pages/flow/flow-main/flow-main.component.less

@ -1,7 +1,7 @@
.icon {
width: 48px;
height: 48px;
border-radius: 8px;
width: 60px;
height: 60px;
border-radius: 50%;
overflow: hidden;
background-image: linear-gradient(135deg, #77abf4, #2f7deb);
font-size: 32px;

35
web-admin-app/src/app/pages/flow/flow-main/flow-main.component.ts

@ -9,8 +9,12 @@ import {
EamAssetPurchaseApplyComponent,
EamAssetStockGoodsUseComponent,
} from 'app/components'
import { RepairTaskFormComponent } from 'app/components/plan-task/repair-task-form/repair-task-form.component'
import { TaskFormComponent } from 'app/components/plan-task/task-form/task-form.component'
import { taskTypeTitle } from 'app/constants'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { PlanTaskType } from 'app/types'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzModalService } from 'ng-zorro-antd/modal'
@ -88,4 +92,35 @@ export class FlowMainComponent implements OnInit {
},
})
}
createTask(type: PlanTaskType) {
const nzTitle = '创建' + taskTypeTitle.get(type) + '任务'
this.modal.create({
nzTitle,
nzContent: type === 'repair' ? RepairTaskFormComponent : TaskFormComponent,
nzWrapClassName: 'modal-lg',
nzWidth: '80vw',
nzData: {
value: null,
preview: false,
},
nzOnOk: async (e: NzSafeAny) => {
const vals = e.getValues()
console.log('vals', vals)
if (vals) {
if (type === 'repair') {
const res = await lastValueFrom(this.api.createRapairTask(vals))
this.msg.success(res.desc)
}
return true
}
return false
},
nzOnCancel: () => {
console.log('Cancel')
},
})
}
}

16
web-admin-app/src/app/pages/system/index/system.component.html

@ -20,6 +20,22 @@
>
角色管理
</li>
<li
nzMatchRouter
[nzPaddingLeft]="12"
nz-submenu
nzTitle="场所地址"
[nzOpen]="openedSubmenu.startsWith('/system/place/')"
>
<ul>
<li nz-menu-item [nzPaddingLeft]="24" [routerLink]="['/system/place/warehouse']" nzMatchRouter>
仓库管理
</li>
<li nz-menu-item [nzPaddingLeft]="24" [routerLink]="['/system/place/address']" nzMatchRouter>
地址管理
</li>
</ul>
</li>
<li
*appPermission="['system-license:view']"
nz-menu-item

63
web-admin-app/src/app/pages/system/system-address/system-address.component.html

@ -0,0 +1,63 @@
<app-page class="p-3">
<div class="flex flex-1">
<nz-card [nzBordered]="false" class="org shadow" nzSize="small">
<app-component-basic-category-tree #treeEl (onSelectedChange)="onSelectedChange($event)" />
</nz-card>
<div class="flex-1 pl-3">
<nz-card [nzBordered]="false" nzTitle="地址信息">
<form nz-form nzLayout="vertical" [formGroup]="createForm" class="w-72">
<nz-form-item>
<nz-form-label [nzRequired]="true"> 名称 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input type="text" nz-input formControlName="categoryName" placeholder="请输入名称" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label> 安全库存 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-input-number
nzPlaceHolder="请输入"
[nzMin]="0"
class="!w-full"
formControlName="safetyLimit"
/>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label> 安全库存上限 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-input-number
nzPlaceHolder="请输入"
[nzMin]="0"
class="!w-full"
formControlName="upperLimit"
/>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label> 安全库存下限 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-input-number
nzPlaceHolder="请输入"
[nzMin]="0"
class="!w-full"
formControlName="lowerLimit"
/>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control>
<nz-space>
<button *nzSpaceItem nz-button nzType="primary" (click)="onConfirm()">确定</button>
</nz-space>
</nz-form-control>
</nz-form-item>
</form>
</nz-card>
</div>
</div>
</app-page>
<ng-template #errorTpl let-control>
<form-error-tips [control]="control"></form-error-tips>
</ng-template>

0
web-admin-app/src/app/pages/system/system-address/system-address.component.less

80
web-admin-app/src/app/pages/system/system-address/system-address.component.ts

@ -0,0 +1,80 @@
import { Component, TemplateRef, ViewChild } from '@angular/core'
import { FormBuilder, FormGroup } from '@angular/forms'
import { ComponentBasicCategoryTreeComponent } from 'app/components'
import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module'
import { FormValidators } from 'app/utils'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NzDrawerRef, NzDrawerService } from 'ng-zorro-antd/drawer'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzModalService } from 'ng-zorro-antd/modal'
@Component({
selector: 'app-system-address',
standalone: true,
imports: [SharedModule, ComponentBasicCategoryTreeComponent],
templateUrl: './system-address.component.html',
styleUrl: './system-address.component.less',
})
export class SystemAddressComponent {
constructor(
private modal: NzModalService,
private msg: NzMessageService,
private drawer: NzDrawerService,
private api: ApiService,
private fb: FormBuilder,
) {}
@ViewChild('treeEl') treeEl!: ComponentBasicCategoryTreeComponent
queryForm!: FormGroup
createForm!: FormGroup
drawerRef?: NzDrawerRef
@ViewChild('drawerFooterTpl') drawerFooterTpl!: TemplateRef<NzSafeAny>
@ViewChild('formContentTpl') formContentTpl!: TemplateRef<NzSafeAny>
initCreateForm() {
this.createForm = this.fb.group({
categoryId: [],
parentId: ['', [FormValidators.required('请输入')]],
categoryName: ['', [FormValidators.required('请输入')]],
safetyLimit: [0, []],
lowerLimit: [0, []],
upperLimit: [0, []],
})
}
initQueryForm() {
this.queryForm = this.fb.group({
name: [''],
})
}
ngOnInit(): void {
this.initQueryForm()
this.initCreateForm()
}
onSelectedChange(v: NzSafeAny) {
this.createForm.patchValue(v)
}
onConfirm() {
if (FormValidators.validateFormGroup(this.createForm)) {
const { value } = this.createForm
this.api
.updateBasicCategoryTree({
...value,
})
.subscribe((res) => {
this.msg.success(res.desc)
this.treeEl.initTree()
})
}
}
}

81
web-admin-app/src/app/pages/system/system-warehouse/system-warehouse.component.html

@ -0,0 +1,81 @@
<app-page class="p-3">
<ng-template #actionsTpl>
<nz-space>
<button *nzSpaceItem nz-button nzType="primary" (click)="onCreate()">新建</button>
</nz-space>
</ng-template>
<div class="flex flex-1">
<div class="flex-1">
<app-server-paginated-table
[tableAction]="actionsTpl"
[options]="table"
[renderColumn]="renderColumnTpl"
[formGroup]="queryForm"
>
<ng-template #renderColumnTpl let-data let-key="key" let-row="row">
@switch (key) {
@case ('status') {
<nz-badge
[nzText]="data === 0 ? '启用' : '禁用'"
[nzStatus]="data === 0 ? 'processing' : 'error'"
/>
}
@default {
{{ data }}
}
}
</ng-template>
<ng-container *appTableForm>
<app-query-item label="名称" class="w-60">
<input nz-input placeholder="请输入" formControlName="name" />
</app-query-item>
<app-query-item label="状态">
<nz-select
nzPlacement="bottomRight"
class="!w-20"
[nzDropdownMatchSelectWidth]="false"
formControlName="status"
nzAllowClear
>
<nz-option [nzValue]="0" nzLabel="启用"></nz-option>
<nz-option [nzValue]="1" nzLabel="禁用"></nz-option>
</nz-select>
</app-query-item>
</ng-container>
</app-server-paginated-table>
</div>
</div>
</app-page>
<ng-template #drawerFooterTpl>
<nz-space>
<button *nzSpaceItem nz-button nzType="primary" (click)="onConfirm()">确定</button>
<button *nzSpaceItem nz-button nzType="default" (click)="onCancel()">取消</button>
</nz-space>
</ng-template>
<ng-template #formContentTpl>
<form nz-form nzLayout="vertical" [formGroup]="createForm">
<nz-form-item>
<nz-form-label nzRequired> 名称 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<input type="text" nz-input formControlName="name" placeholder="请输入名称" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzRequired> 状态 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<nz-radio-group formControlName="status">
<label nz-radio [nzValue]="0"> 启用 </label>
<label nz-radio [nzValue]="1"> 禁用 </label>
</nz-radio-group>
</nz-form-control>
</nz-form-item>
</form>
</ng-template>
<ng-template #errorTpl let-control>
<form-error-tips [control]="control"></form-error-tips>
</ng-template>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save