Browse Source

资产入库

main
kkerwin 12 months ago
parent
commit
472495efa6
  1. 6
      web-admin-app/README.md
  2. 2
      web-admin-app/src/app/app.config.ts
  3. 7
      web-admin-app/src/app/components/asset-category-select/asset-category-select.component.html
  4. 0
      web-admin-app/src/app/components/asset-category-select/asset-category-select.component.less
  5. 77
      web-admin-app/src/app/components/asset-category-select/asset-category-select.component.ts
  6. 263
      web-admin-app/src/app/components/asset-form/asset-form.component.html
  7. 4
      web-admin-app/src/app/components/asset-form/asset-form.component.less
  8. 122
      web-admin-app/src/app/components/asset-form/asset-form.component.ts
  9. 4
      web-admin-app/src/app/components/component-basic-category-tree/component-basic-category-tree.component.ts
  10. 6
      web-admin-app/src/app/components/index.ts
  11. 5
      web-admin-app/src/app/components/maintenance-select/maintenance-select.component.html
  12. 0
      web-admin-app/src/app/components/maintenance-select/maintenance-select.component.less
  13. 87
      web-admin-app/src/app/components/maintenance-select/maintenance-select.component.ts
  14. 10
      web-admin-app/src/app/components/manufacturer-select/manufacturer-select.component.html
  15. 0
      web-admin-app/src/app/components/manufacturer-select/manufacturer-select.component.less
  16. 78
      web-admin-app/src/app/components/manufacturer-select/manufacturer-select.component.ts
  17. 7
      web-admin-app/src/app/components/org-select/org-select.component.html
  18. 0
      web-admin-app/src/app/components/org-select/org-select.component.less
  19. 89
      web-admin-app/src/app/components/org-select/org-select.component.ts
  20. 8
      web-admin-app/src/app/components/position-select/position-select.component.html
  21. 0
      web-admin-app/src/app/components/position-select/position-select.component.less
  22. 77
      web-admin-app/src/app/components/position-select/position-select.component.ts
  23. 55
      web-admin-app/src/app/components/select-user-by-org/select-user-by-org.component.html
  24. 2
      web-admin-app/src/app/components/select-user-by-org/select-user-by-org.component.less
  25. 74
      web-admin-app/src/app/components/select-user-by-org/select-user-by-org.component.ts
  26. 44
      web-admin-app/src/app/constants/index.ts
  27. 4
      web-admin-app/src/app/pages/fixed-asset/fixed-asset.component.html
  28. 163
      web-admin-app/src/app/pages/fixed-asset/manage/fixed-asset-manage/fixed-asset-manage.component.html
  29. 204
      web-admin-app/src/app/pages/fixed-asset/manage/fixed-asset-manage/fixed-asset-manage.component.ts
  30. 80
      web-admin-app/src/app/pages/fixed-asset/stocktaking/stockaking-job/stockaking-job.component.html
  31. 110
      web-admin-app/src/app/pages/fixed-asset/stocktaking/stockaking-job/stockaking-job.component.ts
  32. 61
      web-admin-app/src/app/services/api.service.ts
  33. 11
      web-admin-app/src/app/shared/components/server-paginated-table/query-item/query-item.component.less
  34. 8
      web-admin-app/src/app/shared/components/server-paginated-table/server-paginated-table.component.ts
  35. 55
      web-admin-app/src/app/utils/index.ts
  36. 10
      web-admin-app/src/styles.less

6
web-admin-app/README.md

@ -29,3 +29,9 @@
-【基础数据】【物品档案】的接口是那个? -【基础数据】【物品档案】的接口是那个?
## 05-03
- 所有列表页分页total 最多10 条, pageSize & pageNum
- 【盘点计划】内容和盘点任务一样 ?
- 【资产】 财务分类 id 从哪里选择?

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

@ -15,8 +15,6 @@ import { ServerPaginatedTableService } from './shared/components/server-paginate
registerLocaleData(zh) registerLocaleData(zh)
export const MaxPageSize = 10000000
export function initializeApp(configService: ServerPaginatedTableService) { export function initializeApp(configService: ServerPaginatedTableService) {
return () => { return () => {
configService.initial() configService.initial()

7
web-admin-app/src/app/components/asset-category-select/asset-category-select.component.html

@ -0,0 +1,7 @@
<nz-tree-select
[nzNodes]="assetCategoryTree"
[nzPlaceHolder]="placeholder"
[(ngModel)]="value"
(ngModelChange)="onChange($event)"
>
</nz-tree-select>

0
web-admin-app/src/app/components/asset-category-select/asset-category-select.component.less

77
web-admin-app/src/app/components/asset-category-select/asset-category-select.component.ts

@ -0,0 +1,77 @@
import { ChangeDetectorRef, Component, Input, OnInit, TemplateRef, ViewChild, forwardRef } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NzModalService } from 'ng-zorro-antd/modal'
import { ApiService } from 'app/services'
import { NzMessageService } from 'ng-zorro-antd/message'
import { SharedModule } from 'app/shared/shared.module'
import { Utils } from 'app/utils'
import { NzFormatEmitEvent, NzTreeNode } from 'ng-zorro-antd/tree'
import { NzTreeSelectComponent } from 'ng-zorro-antd/tree-select'
@Component({
selector: 'app-asset-category-select',
standalone: true,
imports: [SharedModule],
templateUrl: './asset-category-select.component.html',
styleUrl: './asset-category-select.component.less',
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => AssetCategorySelectComponent),
},
],
})
export class AssetCategorySelectComponent implements ControlValueAccessor, OnInit {
constructor(
private modal: NzModalService,
private api: ApiService,
private msg: NzMessageService,
private cdr: ChangeDetectorRef,
) {}
@Input() placeholder: string = '请选择'
@Input() modalTitle: string = '选择'
@Input() radio: boolean = false
@ViewChild('el') el!: NzTreeSelectComponent
assetCategoryTree: NzSafeAny[] = []
originTreeData: NzSafeAny[] = []
value?: string
ngOnInit(): void {
this.api.getBasicCategoryTree().subscribe((res) => {
this.originTreeData = res.body
this.assetCategoryTree = Utils.buildTree(this.originTreeData, 'categoryId', 'categoryName')
console.log('this.assetCategoryTree', this.originTreeData, this.assetCategoryTree)
})
}
onTouched = () => {}
onChange(v: NzSafeAny[]) {}
writeValue(v: NzSafeAny): void {
this.value = v
}
registerOnChange(fn: any): void {
this.onChange = fn
}
registerOnTouched(fn: any): void {
this.onTouched = fn
}
setDisabledState?(isDisabled: boolean): void {}
}

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

@ -0,0 +1,263 @@
<form nz-form [formGroup]="formGroup" nzLayout="vertical">
<div class="asset-form">
<nz-card [nzBordered]="false">
<nz-card-tab>
<nz-tabset [(nzSelectedIndex)]="groupIndex">
<nz-tab nzTitle="基本信息"></nz-tab>
<nz-tab nzTitle="维保信息"></nz-tab>
<nz-tab nzTitle="财务信息"></nz-tab>
</nz-tabset>
</nz-card-tab>
@switch (groupIndex) {
@case (0) {
<ng-container [ngTemplateOutlet]="basicTpl"> </ng-container>
}
@case (1) {
<ng-container [ngTemplateOutlet]="maintainTpl"> </ng-container>
}
@case (2) {
<ng-container [ngTemplateOutlet]="financeTpl"> </ng-container>
}
}
</nz-card>
</div>
<ng-template #basicTpl>
<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">
<app-asset-category-select formControlName="categoryId"></app-asset-category-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">
<input nz-input placeholder="请输入名称" formControlName="name" />
</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="status">
@for (item of ASSET_STATUS; track $index) {
<nz-option [nzLabel]="item.label" [nzValue]="item.value"></nz-option>
}
</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-org-select formControlName="ownCompanyId" [company]="true" />
</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-org-select formControlName="useOrganizationId" />
</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">
<!-- manager -->
<app-select-user-by-org formControlName="manager" />
</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-select-user-by-org formControlName="useUserId" />
</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-select nzPlaceHolder="请选择" formControlName="sourceId">
@for (item of ASSET_SOURCE_MAP | keyvalue; track $index) {
<nz-option [nzLabel]="item.value" [nzValue]="item.key"></nz-option>
}
</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">
<!-- manufacturersVendorId -->
<app-manufacturer-select formControlName="manufacturersVendorId" />
</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 placeholder="请输入序列号" formControlName="serialNumber" />
</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 placeholder="请输入规格型号" formControlName="model" />
</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 placeholder="请输入用途" formControlName="purpose" />
</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">
<!-- positionId -->
<app-position-select formControlName="positionId" />
</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 placeholder="请输入详细位置" formControlName="positionDetail" />
</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 placeholder="请输入计量单位" formControlName="unit" />
</nz-form-control>
</nz-form-item>
</div>
</div>
</ng-template>
<ng-template #maintainTpl>
<div nz-row [nzGutter]="24">
<div nz-col [nzSpan]="8">
<nz-form-item>
<nz-form-label>维保厂商</nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl">
<app-maintenance-select formControlName="maintenanceVendor" />
</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 placeholder="请输入联系人" formControlName="contactor" />
</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 placeholder="请输入联系方式" formControlName="contact" />
</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-select-user-by-org formControlName="responsiblePerson" />
</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-date-picker class="w-full" formControlName="maintenanceStartDate" />
</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-date-picker class="w-full" formControlName="maintenanceEndDate" />
</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-select nzPlaceHolder="请选择" formControlName="maintenanceStatus">
@for (item of MAINTENANCE_STATUS | keyvalue; track $index) {
<nz-option [nzLabel]="item.value" [nzValue]="item.key"></nz-option>
}
</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-select nzPlaceHolder="请选择" formControlName="maintenanceType">
@for (item of MAINTENANCE_TYPE | keyvalue; track $index) {
<nz-option [nzLabel]="item.value" [nzValue]="item.key"></nz-option>
}
</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-select nzPlaceHolder="请选择" formControlName="suggestMaintenanceType">
@for (item of MAINTENANCE_TYPE | keyvalue; track $index) {
<nz-option [nzLabel]="item.value" [nzValue]="item.key"></nz-option>
}
</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">
<textarea nz-input placeholder="请输入" formControlName="maintenanceNotes"></textarea>
</nz-form-control>
</nz-form-item>
</div>
</div>
</ng-template>
<ng-template #financeTpl>3</ng-template>
</form>
<ng-template #errorTpl let-control>
<form-error-tips [control]="control"></form-error-tips>
</ng-template>

4
web-admin-app/src/app/components/asset-form/asset-form.component.less

@ -0,0 +1,4 @@
.asset-form {
height: 80vh;
overflow: auto;
}

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

@ -0,0 +1,122 @@
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 } 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'
@Component({
selector: 'app-asset-form',
standalone: true,
imports: [
SharedModule,
AssetCategorySelectComponent,
OrgSelectComponent,
SelectUserByOrgComponent,
ManufacturerSelectComponent,
PositionSelectComponent,
MaintenanceSelectComponent,
],
templateUrl: './asset-form.component.html',
styleUrl: './asset-form.component.less',
})
export class AssetFormComponent implements OnInit {
constructor(
private fb: FormBuilder,
private api: ApiService,
private msg: NzMessageService,
) {}
readonly data: NzSafeAny = inject(NZ_MODAL_DATA)
formGroup!: FormGroup
groupIndex = 0
ASSET_STATUS = ASSET_STATUS
ASSET_SOURCE_MAP = ASSET_SOURCE_MAP
MAINTENANCE_STATUS = MAINTENANCE_STATUS
MAINTENANCE_TYPE = MAINTENANCE_TYPE
ngOnInit(): void {
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('请选择')]),
sourceId: this.fb.control(null, []),
unit: this.fb.control(null, []),
positionId: this.fb.control(null, []),
positionDetail: this.fb.control(null, []),
serialNumber: this.fb.control(null, []),
manufacturersVendorId: this.fb.control(null, []),
useUserId: this.fb.control(null, []),
useOrganizationId: this.fb.control(null, []),
manager: this.fb.control(null, []),
purpose: this.fb.control(null, []),
model: this.fb.control(null, []),
maintenanceVendor: this.fb.control(null, []),
contactor: this.fb.control(null, []),
contact: this.fb.control(null, []),
responsiblePerson: this.fb.control(null, []),
maintenanceStartDate: this.fb.control(null, []),
maintenanceEndDate: this.fb.control(null, []),
maintenanceStatus: this.fb.control(null, []),
maintenanceType: this.fb.control(null, []),
suggestMaintenanceType: this.fb.control(null, []),
maintenanceNotes: this.fb.control(null, []),
})
this.patchValues()
}
patchValues() {
if (this.data) {
const data = this.data
this.formGroup.patchValue({
...data,
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,
})
}
}
public getValues() {
let values = null
if (FormValidators.validateFormGroup(this.formGroup)) {
const v = this.formGroup.getRawValue()
values = {
...v,
useUserId: v.useUserId?.[0],
manager: v.manager?.[0],
categoryId: v.categoryId?.[0],
ownCompanyId: v.ownCompanyId?.[0],
positionId: v.positionId?.[0],
useOrganizationId: v.useOrganizationId?.[0],
responsiblePerson: v.responsiblePerson?.[0],
}
}
return values
}
}

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

@ -19,7 +19,7 @@ interface CateGoryInterface {
safetyLimit: number | null safetyLimit: number | null
upperLimit: number | null upperLimit: number | null
} }
function buildTree(organizations: CateGoryInterface[]): NzTreeNodeOptions[] { export function buildCateTree(organizations: CateGoryInterface[]): NzTreeNodeOptions[] {
const map: { [parentId: number]: NzTreeNodeOptions[] } = {} const map: { [parentId: number]: NzTreeNodeOptions[] } = {}
organizations.forEach((org) => { organizations.forEach((org) => {
@ -85,7 +85,7 @@ export class ComponentBasicCategoryTreeComponent {
initTree() { initTree() {
this.api.getBasicCategoryTree().subscribe((res) => { this.api.getBasicCategoryTree().subscribe((res) => {
this.nodes = buildTree(res.body) this.nodes = buildCateTree(res.body)
this.expandedKeys = [...this.expandedKeys] this.expandedKeys = [...this.expandedKeys]
console.log('this.selectedKeys', this.selectedKeys) console.log('this.selectedKeys', this.selectedKeys)
if (this.selectedKeys.length === 0) { if (this.selectedKeys.length === 0) {

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

@ -1,3 +1,9 @@
export * from './component-org-tree/component-org-tree.component' export * from './component-org-tree/component-org-tree.component'
export * from './component-basic-category-tree/component-basic-category-tree.component' export * from './component-basic-category-tree/component-basic-category-tree.component'
export * from './select-user-by-org/select-user-by-org.component' export * from './select-user-by-org/select-user-by-org.component'
export * from './asset-form/asset-form.component'
export * from './asset-category-select/asset-category-select.component'
export * from './org-select/org-select.component'
export * from './manufacturer-select/manufacturer-select.component'
export * from './position-select/position-select.component'
export * from './maintenance-select/maintenance-select.component'

5
web-admin-app/src/app/components/maintenance-select/maintenance-select.component.html

@ -0,0 +1,5 @@
<nz-select [nzPlaceHolder]="placeholder" [(ngModel)]="value" (ngModelChange)="onModelChange($event)">
@for (item of originData; track $index) {
<nz-option [nzLabel]="item.name" [nzValue]="item.maintenanceVendorId"></nz-option>
}
</nz-select>

0
web-admin-app/src/app/components/maintenance-select/maintenance-select.component.less

87
web-admin-app/src/app/components/maintenance-select/maintenance-select.component.ts

@ -0,0 +1,87 @@
import {
ChangeDetectorRef,
Component,
EventEmitter,
Input,
OnInit,
Output,
TemplateRef,
ViewChild,
forwardRef,
} from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NzModalService } from 'ng-zorro-antd/modal'
import { ApiService } from 'app/services'
import { NzMessageService } from 'ng-zorro-antd/message'
import { SharedModule } from 'app/shared/shared.module'
import { Utils } from 'app/utils'
import { NzFormatEmitEvent, NzTreeNode } from 'ng-zorro-antd/tree'
import { NzTreeSelectComponent } from 'ng-zorro-antd/tree-select'
import { MAX_PAGE_SIZE } from 'app/constants'
@Component({
selector: 'app-maintenance-select',
standalone: true,
imports: [SharedModule],
templateUrl: './maintenance-select.component.html',
styleUrl: './maintenance-select.component.less',
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => MaintenanceSelectComponent),
},
],
})
export class MaintenanceSelectComponent {
constructor(private api: ApiService) {}
@Input() placeholder: string = '请选择'
@Input() modalTitle: string = '选择'
@Input() radio: boolean = false
@Output() onSelected = new EventEmitter<NzSafeAny>()
@ViewChild('el') el!: NzTreeSelectComponent
originData: NzSafeAny[] = []
value?: string
ngOnInit(): void {
this.api.getBasicMaintenanceVendorPage({ pageSize: MAX_PAGE_SIZE, pageNum: 1 }).subscribe((res) => {
this.originData = res.body.rows
})
}
onModelChange(v: NzSafeAny) {
const item = this.originData.find((f) => f.maintenanceVendorId === v)
this.onSelected.emit(item)
this.onChange(v)
}
onTouched = () => {}
onChange(v: NzSafeAny[]) {}
writeValue(v: NzSafeAny): void {
this.value = v
}
registerOnChange(fn: any): void {
this.onChange = fn
}
registerOnTouched(fn: any): void {
this.onTouched = fn
}
setDisabledState?(isDisabled: boolean): void {}
}

10
web-admin-app/src/app/components/manufacturer-select/manufacturer-select.component.html

@ -0,0 +1,10 @@
<nz-select
[nzPlaceHolder]="placeholder"
[(ngModel)]="value"
(ngModelChange)="onModelChange($event)"
[nzDropdownMatchSelectWidth]="false"
>
@for (item of originData; track $index) {
<nz-option [nzLabel]="item.name" [nzValue]="item.manufacturersVendorId"></nz-option>
}
</nz-select>

0
web-admin-app/src/app/components/manufacturer-select/manufacturer-select.component.less

78
web-admin-app/src/app/components/manufacturer-select/manufacturer-select.component.ts

@ -0,0 +1,78 @@
import { ChangeDetectorRef, Component, Input, OnInit, TemplateRef, ViewChild, forwardRef } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NzModalService } from 'ng-zorro-antd/modal'
import { ApiService } from 'app/services'
import { NzMessageService } from 'ng-zorro-antd/message'
import { SharedModule } from 'app/shared/shared.module'
import { Utils } from 'app/utils'
import { NzFormatEmitEvent, NzTreeNode } from 'ng-zorro-antd/tree'
import { NzTreeSelectComponent } from 'ng-zorro-antd/tree-select'
import { MAX_PAGE_SIZE } from 'app/constants'
@Component({
selector: 'app-manufacturer-select',
standalone: true,
imports: [SharedModule],
templateUrl: './manufacturer-select.component.html',
styleUrl: './manufacturer-select.component.less',
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => ManufacturerSelectComponent),
},
],
})
export class ManufacturerSelectComponent {
constructor(
private modal: NzModalService,
private api: ApiService,
private msg: NzMessageService,
private cdr: ChangeDetectorRef,
) {}
@Input() placeholder: string = '请选择'
@Input() modalTitle: string = '选择'
@Input() radio: boolean = false
@ViewChild('el') el!: NzTreeSelectComponent
originData: NzSafeAny[] = []
value?: string
ngOnInit(): void {
this.api.getBasicManufacturersVendorPage({ pageSize: MAX_PAGE_SIZE, pageNum: 1 }).subscribe((res) => {
this.originData = res.body.rows
})
}
onModelChange(v: NzSafeAny) {
this.onChange(v)
}
onTouched = () => {}
onChange(v: NzSafeAny[]) {}
writeValue(v: NzSafeAny): void {
this.value = v
}
registerOnChange(fn: any): void {
this.onChange = fn
}
registerOnTouched(fn: any): void {
this.onTouched = fn
}
setDisabledState?(isDisabled: boolean): void {}
}

7
web-admin-app/src/app/components/org-select/org-select.component.html

@ -0,0 +1,7 @@
<nz-tree-select
[nzNodes]="orgTree"
[nzPlaceHolder]="placeholder"
[(ngModel)]="value"
(ngModelChange)="onChange($event)"
>
</nz-tree-select>

0
web-admin-app/src/app/components/org-select/org-select.component.less

89
web-admin-app/src/app/components/org-select/org-select.component.ts

@ -0,0 +1,89 @@
import { ChangeDetectorRef, Component, Input, OnInit, TemplateRef, ViewChild, forwardRef } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NzModalService } from 'ng-zorro-antd/modal'
import { ApiService } from 'app/services'
import { NzMessageService } from 'ng-zorro-antd/message'
import { SharedModule } from 'app/shared/shared.module'
import { Utils } from 'app/utils'
import { NzFormatEmitEvent, NzTreeNode } from 'ng-zorro-antd/tree'
import { NzTreeSelectComponent } from 'ng-zorro-antd/tree-select'
@Component({
selector: 'app-org-select',
standalone: true,
imports: [SharedModule],
templateUrl: './org-select.component.html',
styleUrl: './org-select.component.less',
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => OrgSelectComponent),
},
],
})
export class OrgSelectComponent implements ControlValueAccessor, OnInit {
constructor(
private modal: NzModalService,
private api: ApiService,
private msg: NzMessageService,
private cdr: ChangeDetectorRef,
) {}
@Input() placeholder: string = '请选择'
@Input() company: boolean = false
originTreeData: NzSafeAny[] = []
orgTree: NzSafeAny[] = []
value?: string
ngOnInit(): void {
this.api.getOrgTree().subscribe((res) => {
this.originTreeData = res.body
const c: NzSafeAny[] = []
res.body.forEach((i: NzSafeAny) => {
if (this.company) {
if (i.organizationType === '0') {
c.push(i)
}
} else {
if (['1', '0'].includes(i.organizationType)) {
c.push(i)
}
}
})
this.orgTree = Utils.buildTree(c, 'organizationId', 'organizationName')
})
}
onSelect(e: NzFormatEmitEvent) {
// this.onChange(e.keys ?? [])
}
onTouched = () => {}
onChange(v: NzSafeAny[]) {}
writeValue(v: NzSafeAny): void {
this.value = v
}
registerOnChange(fn: any): void {
this.onChange = fn
}
registerOnTouched(fn: any): void {
this.onTouched = fn
}
setDisabledState?(isDisabled: boolean): void {}
}

8
web-admin-app/src/app/components/position-select/position-select.component.html

@ -0,0 +1,8 @@
<nz-tree-select
[nzNodes]="positionTree"
[nzPlaceHolder]="placeholder"
[(ngModel)]="value"
(ngModelChange)="onChange($event)"
[nzDropdownMatchSelectWidth]="false"
>
</nz-tree-select>

0
web-admin-app/src/app/components/position-select/position-select.component.less

77
web-admin-app/src/app/components/position-select/position-select.component.ts

@ -0,0 +1,77 @@
import { ChangeDetectorRef, Component, Input, OnInit, TemplateRef, ViewChild, forwardRef } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
import { NzSafeAny } from 'ng-zorro-antd/core/types'
import { NzModalService } from 'ng-zorro-antd/modal'
import { ApiService } from 'app/services'
import { NzMessageService } from 'ng-zorro-antd/message'
import { SharedModule } from 'app/shared/shared.module'
import { Utils } from 'app/utils'
import { NzFormatEmitEvent, NzTreeNode } from 'ng-zorro-antd/tree'
import { NzTreeSelectComponent } from 'ng-zorro-antd/tree-select'
import { MAX_PAGE_SIZE } from 'app/constants'
@Component({
selector: 'app-position-select',
standalone: true,
imports: [SharedModule],
templateUrl: './position-select.component.html',
styleUrl: './position-select.component.less',
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => PositionSelectComponent),
},
],
})
export class PositionSelectComponent {
constructor(
private modal: NzModalService,
private api: ApiService,
private msg: NzMessageService,
private cdr: ChangeDetectorRef,
) {}
@Input() placeholder: string = '请选择'
@Input() modalTitle: string = '选择'
@Input() radio: boolean = false
@ViewChild('el') el!: NzTreeSelectComponent
originData: NzSafeAny[] = []
positionTree: NzSafeAny[] = []
value?: string
ngOnInit(): void {
this.api.getBasicPositionTree().subscribe((res) => {
this.originData = res.body
this.positionTree = Utils.buildTree(res.body, 'positionId', 'name')
})
}
onTouched = () => {}
onChange(v: NzSafeAny[]) {}
writeValue(v: NzSafeAny): void {
this.value = v
}
registerOnChange(fn: any): void {
this.onChange = fn
}
registerOnTouched(fn: any): void {
this.onTouched = fn
}
setDisabledState?(isDisabled: boolean): void {}
}

55
web-admin-app/src/app/components/select-user-by-org/select-user-by-org.component.html

@ -1,30 +1,29 @@
<div <button nz-button nzBlock (click)="onTriggerClick(selectUserModalTpl)">
class="cursor-pointer trigger min-h-[100px] max-h-[200px] overflow-auto p-3"
(click)="onTriggerClick(selectUserModalTpl)"
>
@if (selectedKeys.size > 0) { @if (selectedKeys.size > 0) {
<ng-container [ngTemplateOutlet]="selectedUserTpl"></ng-container> <div class="text-left">
@for (uid of selectedKeys; track $index) {
<span class="mr-1 mb-1 inline-block">
<nz-tag>{{ allGetedDataMap.get(uid)?.userName ?? '-' }}</nz-tag>
</span>
}
</div>
} @else { } @else {
<div class="p-3 h-full flex min-h-[100px] items-center justify-center w-full text-black opacity-50"> <div class="flex items-center justify-center w-full text-black opacity-50">
<i nz-icon nzType="plus" class="text-large"></i> <i nz-icon nzType="plus" class="text-large"></i>
<span class="ml-2"> <span class="ml-2">
{{ placeholder }} {{ placeholder }}
</span> </span>
</div> </div>
} }
</div> </button>
<ng-template #selectedUserTpl>
@for (uid of selectedKeys; track $index) {
<span class="mr-2 mb-2">
<nz-tag>{{ allGetedDataMap.get(uid).userName }}</nz-tag>
</span>
}
</ng-template>
<ng-template #selectUserModalTpl> <ng-template #selectUserModalTpl>
<div class="cursor-pointer trigger min-h-[100px] max-h-[200px] overflow-auto p-3"> <div class="temp cursor-pointer min-h-[90px] max-h-[200px] overflow-auto p-3">
<ng-container [ngTemplateOutlet]="selectedUserTpl"></ng-container> @for (uid of tempSelectedKeys; track $index) {
<span class="mr-1 mb-1 inline-block">
<nz-tag>{{ allGetedDataMap.get(uid)?.userName ?? '-' }}</nz-tag>
</span>
}
</div> </div>
<div class="mt-3"> <div class="mt-3">
@ -42,14 +41,18 @@
<div class="flex-1 flex flex-col overflow-hidden relative user-list"> <div class="flex-1 flex flex-col overflow-hidden relative user-list">
<div class="hd flex items-center justify-between py-2 px-3"> <div class="hd flex items-center justify-between py-2 px-3">
<!-- <a nz-button nzType="link" class="flex"> 已选 1/{{ currentUsers.length }} </a> --> <!-- <a nz-button nzType="link" class="flex"> 已选 1/{{ currentUsers.length }} </a> -->
<span class="flex"> 全选 </span> @if (radio) {
<label <span class="flex"> 选择 </span>
nz-checkbox } @else {
[nzIndeterminate]="indeterminate" <span class="flex"> 全选 </span>
[nzChecked]="allChecked" <label
(nzCheckedChange)="onAllCheckedChange($event)" nz-checkbox
> [nzIndeterminate]="indeterminate"
</label> [nzChecked]="allChecked"
(nzCheckedChange)="onAllCheckedChange($event)"
>
</label>
}
</div> </div>
<div class="bd flex-1 overflow-auto"> <div class="bd flex-1 overflow-auto">
<ul> <ul>
@ -60,7 +63,7 @@
nz-checkbox nz-checkbox
(nzCheckedChange)="onUserCheckedChange($event, item.userId)" (nzCheckedChange)="onUserCheckedChange($event, item.userId)"
[nzValue]="item.userId" [nzValue]="item.userId"
[nzChecked]="selectedKeys.has(item.userId)" [nzChecked]="tempSelectedKeys.has(item.userId)"
> >
</label> </label>
</li> </li>

2
web-admin-app/src/app/components/select-user-by-org/select-user-by-org.component.less

@ -1,4 +1,4 @@
.trigger { .temp {
border: 1px dashed #e0e0e0; border: 1px dashed #e0e0e0;
} }

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

@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common' import { CommonModule } from '@angular/common'
import { Component, Input, OnInit, TemplateRef, forwardRef } from '@angular/core' import { ChangeDetectorRef, Component, Input, OnInit, TemplateRef, forwardRef } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
import { NzCardModule } from 'ng-zorro-antd/card' import { NzCardModule } from 'ng-zorro-antd/card'
import { NzSafeAny } from 'ng-zorro-antd/core/types' import { NzSafeAny } from 'ng-zorro-antd/core/types'
@ -11,7 +11,7 @@ import { NzButtonModule } from 'ng-zorro-antd/button'
import { NzCheckboxModule } from 'ng-zorro-antd/checkbox' import { NzCheckboxModule } from 'ng-zorro-antd/checkbox'
import { ApiService } from 'app/services' import { ApiService } from 'app/services'
import { NzMessageModule, NzMessageService } from 'ng-zorro-antd/message' import { NzMessageModule, NzMessageService } from 'ng-zorro-antd/message'
import { MaxPageSize } from 'app/app.config' import { MAX_PAGE_SIZE } from 'app/constants'
import { NzTagModule } from 'ng-zorro-antd/tag' import { NzTagModule } from 'ng-zorro-antd/tag'
@Component({ @Component({
@ -44,16 +44,23 @@ export class SelectUserByOrgComponent implements ControlValueAccessor, OnInit {
private modal: NzModalService, private modal: NzModalService,
private api: ApiService, private api: ApiService,
private msg: NzMessageService, private msg: NzMessageService,
private cdr: ChangeDetectorRef,
) {} ) {}
@Input() placeholder: string = '请选择' @Input() placeholder: string = '请选择'
@Input() modalTitle: string = '选择' @Input() modalTitle: string = '选择'
@Input() radio: boolean = true
@Input() size: 'small' | 'default' = 'default'
allGetedDataMap = new Map<number, NzSafeAny>() allGetedDataMap = new Map<number, NzSafeAny>()
currentUsers: NzSafeAny[] = [] currentUsers: NzSafeAny[] = []
tempSelectedKeys = new Set<number>()
selectedKeys = new Set<number>() selectedKeys = new Set<number>()
indeterminate = false indeterminate = false
@ -63,58 +70,95 @@ export class SelectUserByOrgComponent implements ControlValueAccessor, OnInit {
ngOnInit(): void {} ngOnInit(): void {}
onTriggerClick(nzContent: TemplateRef<NzSafeAny>) { onTriggerClick(nzContent: TemplateRef<NzSafeAny>) {
this.tempSelectedKeys = new Set([...this.selectedKeys])
this.modal.create({ this.modal.create({
nzTitle: this.modalTitle, nzTitle: this.modalTitle,
nzContent, nzContent,
nzWidth: '660px', nzWidth: '660px',
nzOnOk: () => {
this.selectedKeys = new Set([...this.tempSelectedKeys])
this.onChange(Array.from(this.selectedKeys))
},
nzOnCancel: () => {
this.tempSelectedKeys.clear()
},
}) })
} }
onOrgSelectedChange(v: NzSafeAny) { onOrgSelectedChange(v?: NzSafeAny, uid?: number) {
this.api this.api
.getUserPage({ pageSize: MaxPageSize, pageNum: 1, organizationId: v.organizationId }) .getUserPage({ pageSize: MAX_PAGE_SIZE, pageNum: 1, userId: uid, organizationId: v?.organizationId })
.subscribe((res) => { .subscribe((res) => {
if (Array.isArray(res.body?.rows) && res.body.rows.length > 0) { if (Array.isArray(res.body?.rows) && res.body.rows.length > 0) {
res.body.rows.forEach((element: NzSafeAny) => { res.body.rows.forEach((element: NzSafeAny) => {
this.currentUsers = res.body.rows this.currentUsers = res.body.rows
this.allGetedDataMap.set(element.userId, element) this.allGetedDataMap.set(element.userId, element)
this.statusChange()
console.log('this.allGetedDataMap', this.allGetedDataMap)
}) })
} }
}) })
} }
onUserCheckedChange(e: boolean, v: number) { onUserCheckedChange(e: boolean, v: number) {
if (e) { if (this.radio) {
this.selectedKeys.add(v) this.tempSelectedKeys.clear()
if (e) {
this.tempSelectedKeys.add(v)
}
} else { } else {
this.selectedKeys.delete(v) if (e) {
this.tempSelectedKeys.add(v)
} else {
this.tempSelectedKeys.delete(v)
}
} }
this.statusChange() this.statusChange()
} }
statusChange() { statusChange() {
this.allChecked = this.selectedKeys.size === this.currentUsers.length const currentSelected = this.currentUsers.filter((f) => this.tempSelectedKeys.has(f.userId))
this.indeterminate = this.selectedKeys.size > 0 && this.selectedKeys.size < this.currentUsers.length this.allChecked = currentSelected.length === this.currentUsers.length
this.indeterminate =
this.currentUsers.length !== 0 &&
currentSelected.length > 0 &&
currentSelected.length < this.currentUsers.length
} }
onAllCheckedChange(e: boolean) { onAllCheckedChange(e: boolean) {
if (e) { if (e) {
this.currentUsers.forEach((element) => { this.currentUsers.forEach((element) => {
this.selectedKeys.add(element.userId) this.tempSelectedKeys.add(element.userId)
}) })
} else { } else {
this.selectedKeys.clear() this.tempSelectedKeys.clear()
} }
this.statusChange() this.statusChange()
} }
getUserById(id: number) {
this.api.getUserDetail(id).subscribe((res) => {
this.allGetedDataMap.set(id, res.body)
})
}
onTouched = () => {} onTouched = () => {}
onChange(v: string[]) { onChange(v: NzSafeAny[]) {}
console.log('v', v)
}
writeValue(v: any): void {} writeValue(v: NzSafeAny[]): void {
// console.log('this.selectedKeys writeValue', v)
if (Array.isArray(v) && v.length > 0) {
this.tempSelectedKeys.clear()
this.selectedKeys.clear()
v.forEach((element) => {
this.getUserById(element)
this.selectedKeys.add(element)
this.tempSelectedKeys.add(element)
})
}
}
registerOnChange(fn: any): void { registerOnChange(fn: any): void {
this.onChange = fn this.onChange = fn

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

@ -0,0 +1,44 @@
export const MAX_PAGE_SIZE = 10000000
export const ASSET_STATUS = [
{ label: '闲置', value: 0 },
{ label: '在用', value: 1 },
{ label: '借用中', value: 2 },
{ label: '维修中', value: 3 },
{ label: '调拨中', value: 4 },
{ label: '待报废', value: 5 },
{ label: '已处置', value: 6 },
{ label: '库存', value: 7 },
{ label: '已报废', value: 8 },
]
export const ASSET_STATUS_MAP = () => {
return ASSET_STATUS.reduce(
(map, item) => {
map[item.value] = item.label
return map
},
{} as Record<number, string>,
)
}
export const ASSET_SOURCE_MAP = new Map([
[0, '捐赠'],
[1, '赠送'],
[2, '其他'],
[3, '采购'],
[4, '自建'],
[4, '自购'],
])
export const MAINTENANCE_STATUS = new Map([
[0, '不需要'],
[1, '脱保'],
[2, '在保'],
[3, '未知'],
])
export const MAINTENANCE_TYPE = new Map([
[0, '原厂'],
[1, '第三方'],
])

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

@ -101,10 +101,10 @@
<li nzMatchRouter [nzPaddingLeft]="12" nz-submenu nzTitle="盘点管理"> <li nzMatchRouter [nzPaddingLeft]="12" nz-submenu nzTitle="盘点管理">
<ul> <ul>
<li nz-menu-item [nzPaddingLeft]="24" [routerLink]="['/fixed-asset/stocktaking/job']" nzMatchRouter> <li nz-menu-item [nzPaddingLeft]="24" [routerLink]="['/fixed-asset/stocktaking/job']" nzMatchRouter>
盘点计划 盘点任务
</li> </li>
<li nz-menu-item [nzPaddingLeft]="24" [routerLink]="['/fixed-asset/stocktaking/plan']" nzMatchRouter> <li nz-menu-item [nzPaddingLeft]="24" [routerLink]="['/fixed-asset/stocktaking/plan']" nzMatchRouter>
盘点任务 盘点计划
</li> </li>
</ul> </ul>
</li> </li>

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

@ -1,78 +1,124 @@
<app-page [actions]="actionTpl"> <app-page>
<ng-template #actionTpl> <ng-template #actionTpl>
<nz-space> <nz-space>
<button *nzSpaceItem nz-button nzType="primary"> <button *nzSpaceItem nz-button nzType="primary" (click)="onCreate()">
<span>登记</span> <span>登记</span>
</button> </button>
<button *nzSpaceItem nz-button> <button *nzSpaceItem nz-button>
<span>删除</span>
</button>
<button *nzSpaceItem nz-button [disabled]="table.ref.selected.size === 0" (click)="confirmAsset()">
<span>资产确认</span>
</button>
<button *nzSpaceItem nz-button nz-dropdown [nzDropdownMenu]="export">
<span>导入/导出</span> <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> </button>
<button *nzSpaceItem nz-button> <!-- <button *nzSpaceItem nz-button>
<span>打印</span> <span>打印</span>
</button> </button> -->
</nz-space> </nz-space>
</ng-template> </ng-template>
<div class="flex flex-1"> <div class="flex-1 overflow-hidden">
<app-server-paginated-table [options]="table" [formGroup]="queryForm"> <app-server-paginated-table
<ng-container *appTableAction> [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> <nz-space>
<button *nzSpaceItem nz-button nzType="link">资产确认</button> <button *nzSpaceItem nz-button nzType="link">资产确认</button>
<button *nzSpaceItem nz-button nzType="link" nzDanger="">删除</button> <button *nzSpaceItem nz-button nzType="link" nzDanger="">删除</button>
</nz-space> </nz-space>
</ng-container> </ng-container> -->
<ng-container *appTableForm> <ng-container *appTableForm>
<app-query-item label="办理状态"> <app-query-item label="资产名称">
<nz-select <input nz-input placeholder="请输入" formControlName="name" />
nzPlacement="bottomRight"
nzBorderless
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="2231" nzLabel="取消"></nz-option>
</nz-select>
</app-query-item> </app-query-item>
<app-query-item label="资产编号"> <app-query-item label="资产编号">
<input nz-input placeholder="请输入" formControlName="name" /> <input nz-input placeholder="请输入" formControlName="assetCode" />
</app-query-item> </app-query-item>
<app-query-item label="规格型号"> <app-query-item label="规格型号">
<input nz-input placeholder="请输入" formControlName="name" /> <input nz-input placeholder="请输入" formControlName="model" />
</app-query-item> </app-query-item>
<app-query-item label="资产名称"> <app-query-item label="序列号">
<input nz-input placeholder="请输入" formControlName="name" /> <input nz-input placeholder="请输入" formControlName="serialNumber" />
</app-query-item> </app-query-item>
<app-query-item label="资产状态"> <app-query-item label="资产状态">
<nz-select <nz-select
nzPlacement="bottomRight" nzPlacement="bottomRight"
nzBorderless nzBorderless
class="!w-auto" class="!w-auto"
[nzDropdownMatchSelectWidth]="false" [nzDropdownMatchSelectWidth]="false"
formControlName="status"
> >
<nz-option nzValue="123" nzLabel="闲置"></nz-option> @for (item of ASSET_STATUS_MAP | keyvalue; track $index) {
<nz-option nzValue="22" nzLabel="在用"></nz-option> <nz-option [nzLabel]="item.value" [nzValue]="item.key"></nz-option>
<nz-option nzValue="2211" nzLabel="借用中"></nz-option> }
<nz-option nzValue="2221" nzLabel="维修中"></nz-option>
<nz-option nzValue="2231" nzLabel="调拨中"></nz-option>
<nz-option nzValue="2241" nzLabel="待作废"></nz-option>
</nz-select> </nz-select>
</app-query-item> </app-query-item>
<app-query-item label="资产来源">
<app-query-item label="位置">
<nz-select <nz-select
nzPlacement="bottomRight" nzPlacement="bottomRight"
nzBorderless nzBorderless
class="!w-auto" class="!w-auto"
[nzDropdownMatchSelectWidth]="false" [nzDropdownMatchSelectWidth]="false"
formControlName="sourceId"
> >
<nz-option nzValue="123" nzLabel="位置1"></nz-option> @for (item of ASSET_SOURCE_MAP | keyvalue; track $index) {
<nz-option [nzLabel]="item.value" [nzValue]="item.key"></nz-option>
}
</nz-select> </nz-select>
</app-query-item> </app-query-item>
<app-query-item label="序列号"> <app-query-item label="位置">
<input nz-input placeholder="请输入" formControlName="name" /> <app-position-select formControlName="positionId" />
</app-query-item>
<app-query-item label="生产厂商">
<app-manufacturer-select formControlName="manufacturersVendorId" />
</app-query-item> </app-query-item>
<app-query-item label="设备标签"> <app-query-item label="设备标签">
@ -185,3 +231,48 @@
</app-server-paginated-table> </app-server-paginated-table>
</div> </div>
</app-page> </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>
<nz-alert [nzMessage]="copyTextTpl">
<ng-template #copyTextTpl> 按照要求填写Excel数据,系统会对部分字段做验证! </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">
<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>
</div>
</ng-template>

204
web-admin-app/src/app/pages/fixed-asset/manage/fixed-asset-manage/fixed-asset-manage.component.ts

@ -1,85 +1,197 @@
import { Component } from '@angular/core' import { Component, TemplateRef, ViewChild } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms' import { FormControl, FormGroup } from '@angular/forms'
import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table' import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table'
import { ApiService } from 'app/services' import { ApiService } from 'app/services'
import { SharedModule } from 'app/shared/shared.module' import { SharedModule } from 'app/shared/shared.module'
import { format } from 'date-fns' import { format } from 'date-fns'
import { of } from 'rxjs' 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({ @Component({
selector: 'app-fixed-asset-manage', selector: 'app-fixed-asset-manage',
standalone: true, standalone: true,
imports: [SharedModule], imports: [SharedModule, AssetFormComponent, PositionSelectComponent, ManufacturerSelectComponent],
templateUrl: './fixed-asset-manage.component.html', templateUrl: './fixed-asset-manage.component.html',
styleUrl: './fixed-asset-manage.component.less', styleUrl: './fixed-asset-manage.component.less',
}) })
export class FixedAssetManageComponent { export class FixedAssetManageComponent {
constructor(private api: ApiService) {} constructor(
private api: ApiService,
private modal: NzModalService,
private msg: NzMessageService,
) {}
queryForm = new FormGroup({ queryForm = new FormGroup({
name: new FormControl(''), name: new FormControl(),
type: new FormControl(''), model: new FormControl(),
status: new FormControl(''), status: new FormControl(),
date: 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)) table = new TableOption(this.fetchData.bind(this))
copyNum = 1
ngOnInit(): void { ngOnInit(): void {
this.table this.table
.setConfig({ .setConfig({
selectable: true, selectable: true,
rowKey: 'assetId',
}) })
.setColumn([ .setColumn([
{ key: '办理状态', title: '办理状态', visible: true }, { key: 'assetCode', title: '资产编号', visible: true },
{ key: '资产编号', title: '资产编号', visible: true }, { key: 'name', title: '资产名称', visible: true },
{ key: '资产状态', title: '资产状态', visible: true }, { key: '_category', title: '资产分类', visible: true },
{ key: '资产分类', title: '资产分类', visible: true }, { key: 'status', title: '资产状态', visible: true },
{ key: '资产名称', title: '资产名称', visible: true }, { key: '_ownCompany', title: '所属公司', visible: true },
{ key: '规格型号', title: '规格型号', visible: true }, { key: '_useOrganization', title: '使用组织', visible: true },
{ key: '所属公司', title: '所属公司', visible: true }, { key: '_position', title: '存放位置', visible: true },
{ key: '使用组织', title: '使用组织', visible: true },
{ key: '存放位置', title: '存放位置', visible: true },
]) ])
.setRowOperate([ .setRowOperate([
{ title: '查看', premissions: [] }, { title: '查看' },
{ title: '修改' }, { title: '修改', onClick: this.onCreate.bind(this) },
{ title: '复制' }, { title: '复制', onClick: this.onCopy.bind(this) },
{ title: '密文箱' },
{ title: '折旧记录' }, { title: '折旧记录' },
{ title: '二维码' }, { title: '二维码', onClick: this.qrcode.bind(this) },
{ title: '操作明细' }, { title: '操作明细' },
{ title: '删除' }, { title: '删除', onClick: this.deleteItem.bind(this) },
]) ])
} }
fetchData(p: {}, q: AnyObject) { fetchData(p: {}, q: AnyObject) {
if (Array.isArray(q['createTime'])) { return this.api.getAssetPage({ ...p, ...q })
const createTimeStart = q['createTime']?.[0] }
const createTimeEnd = q['createTime']?.[1]
q['createTimeStart'] = createTimeStart ? format(new Date(createTimeStart), 'yyyy-MM-dd HH:mm:ss') : '' onCopy(data: NzSafeAny) {
q['createTimeEnd'] = createTimeEnd ? format(new Date(createTimeEnd), 'yyyy-MM-dd HH:mm:ss') : '' this.modal.create({
} nzTitle: '复制资产',
return of({ nzWidth: 600,
data: { nzContent: this.copyTpl,
total: 5, nzOnOk: async () => {
records: [ if (!this.copyNum) {
{ this.msg.error('请输入复制数量')
id: 1, return false
name: '沙滩', }
price: 590, const res = await lastValueFrom(this.api.copyAsset(this.copyNum, data.assetId))
type: 0, this.msg.success(res.desc)
lifespan: 6, this.table.ref.reload()
number: 20, return true
max: 20, },
status: 1, })
createTime: '2024-05-01', }
},
], onCreate(data?: NzSafeAny) {
this.modal.create({
nzTitle: data ? '编辑资产' : '添加资产',
nzContent: AssetFormComponent,
nzWidth: '80vw',
nzWrapClassName: 'modal-lg',
nzData: data,
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()
}, },
}) })
return this.api.getEntityPage(p, q) }
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,
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生成成功')
})
} }
} }

80
web-admin-app/src/app/pages/fixed-asset/stocktaking/stockaking-job/stockaking-job.component.html

@ -40,7 +40,30 @@
} }
} }
} }
@case ('_stocktakingUser') {
{{ data?.userName ?? '-' }}
}
@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 { @default {
{{ data }} {{ data }}
} }
@ -63,11 +86,23 @@
<app-query-item label="名称" class="w-60"> <app-query-item label="名称" class="w-60">
<input nz-input placeholder="请输入" formControlName="name" /> <input nz-input placeholder="请输入" formControlName="name" />
</app-query-item> </app-query-item>
<app-query-item label="编码" class="w-60"> <app-query-item label="备注" class="w-60">
<input nz-input placeholder="请输入" formControlName="code" /> <input nz-input placeholder="请输入" formControlName="notes" />
</app-query-item> </app-query-item>
<app-query-item label="统一社会信用代码"> <app-query-item label="盘点状态">
<input nz-input placeholder="请输入" formControlName="uscc" /> <nz-select
nzPlacement="bottomRight"
nzBorderless
class="!w-auto"
[nzDropdownMatchSelectWidth]="false"
formControlName="status"
nzAllowClear
>
<nz-option [nzValue]="0" 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>
</ng-container> </ng-container>
</app-server-paginated-table> </app-server-paginated-table>
@ -101,12 +136,14 @@
<nz-form-item> <nz-form-item>
<nz-form-label> 负责人 </nz-form-label> <nz-form-label> 负责人 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl"> <nz-form-control [nzErrorTip]="errorTpl">
<app-select-user-by-org /> <app-select-user-by-org [radio]="true" formControlName="head" />
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item>
<nz-form-label> 盘点人 </nz-form-label> <nz-form-label> 盘点人 </nz-form-label>
<nz-form-control [nzErrorTip]="errorTpl"> </nz-form-control> <nz-form-control [nzErrorTip]="errorTpl">
<app-select-user-by-org [radio]="true" formControlName="stocktakingUserId" />
</nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item>
@ -120,55 +157,66 @@
<nz-form-item> <nz-form-item>
<nz-form-label> 购置开始日期 </nz-form-label> <nz-form-label> 购置开始日期 </nz-form-label>
<nz-form-control> <nz-form-control>
<nz-date-picker nzShowTime formControlName="stocktakingStartDate" /> <nz-date-picker nzShowTime class="w-full" formControlName="stocktakingStartDate" />
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item>
<nz-form-label> 购置结束日期 </nz-form-label> <nz-form-label> 购置结束日期 </nz-form-label>
<nz-form-control> <nz-form-control>
<nz-date-picker nzShowTime formControlName="stocktakingStartDate" /> <nz-date-picker nzShowTime class="w-full" formControlName="stocktakingEndDate" />
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item>
<nz-form-label> 资产分类 </nz-form-label> <nz-form-label> 资产分类 </nz-form-label>
<nz-form-control> <nz-form-control>
<nz-select> </nz-select> <nz-tree-select [nzNodes]="assetCategoryTree" formControlName="categoryId"></nz-tree-select>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item>
<nz-form-label> 资产状态 </nz-form-label> <nz-form-label> 资产状态 </nz-form-label>
<nz-form-control> <nz-form-control>
<nz-select> </nz-select> <nz-select nzPlaceHolder="请选择" formControlName="assetStatus">
@for (item of ASSET_STATUS; track $index) {
<nz-option [nzLabel]="item.label" [nzValue]="item.value"></nz-option>
}
</nz-select>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item>
<nz-form-label> 位置 </nz-form-label> <nz-form-label> 位置 </nz-form-label>
<nz-form-control> <nz-form-control>
<nz-select> </nz-select> <nz-tree-select nzPlaceHolder="请选择" [nzNodes]="positionTree" formControlName="positionId">
</nz-tree-select>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item>
<nz-form-label> 仓库 </nz-form-label> <nz-form-label> 仓库 </nz-form-label>
<nz-form-control> <nz-form-control>
<nz-select> </nz-select> <nz-select nzPlaceHolder="请选择" formControlName="warehouseId">
@for (item of warehouse; track $index) {
<nz-option [nzLabel]="item.label" [nzValue]="item.value"></nz-option>
}
</nz-select>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item>
<nz-form-label> 所属公司 </nz-form-label> <nz-form-label> 所属公司 </nz-form-label>
<nz-form-control> <nz-form-control>
<nz-select> </nz-select> <nz-tree-select nzPlaceHolder="请选择" [nzNodes]="companyTree" formControlName="ownCompanyId">
</nz-tree-select>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item>
<nz-form-label> 使用公司/部门 </nz-form-label> <nz-form-label> 使用公司/部门 </nz-form-label>
<nz-form-control> <nz-form-control>
<nz-select> </nz-select> <nz-tree-select nzPlaceHolder="请选择" [nzNodes]="orgTree" formControlName="useOrganizationId">
</nz-tree-select>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item>
<nz-form-label> 保管人 </nz-form-label> <nz-form-label> 保管人 </nz-form-label>
<nz-form-control> <nz-form-control>
<nz-select> </nz-select> <app-select-user-by-org [radio]="true" formControlName="useUserId" />
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
</form> </form>

110
web-admin-app/src/app/pages/fixed-asset/stocktaking/stockaking-job/stockaking-job.component.ts

@ -8,8 +8,9 @@ import { NzModalService } from 'ng-zorro-antd/modal'
import { NzMessageService } from 'ng-zorro-antd/message' import { NzMessageService } from 'ng-zorro-antd/message'
import { NzDrawerRef, NzDrawerService } from 'ng-zorro-antd/drawer' import { NzDrawerRef, NzDrawerService } from 'ng-zorro-antd/drawer'
import { lastValueFrom } from 'rxjs' import { lastValueFrom } from 'rxjs'
import { FormValidators } from 'app/utils' import { FormValidators, Utils } from 'app/utils'
import { SelectUserByOrgComponent } from 'app/components' import { SelectUserByOrgComponent, buildCateTree } from 'app/components'
import { ASSET_STATUS, MAX_PAGE_SIZE } from 'app/constants'
@Component({ @Component({
selector: 'app-stockaking-job', selector: 'app-stockaking-job',
@ -39,21 +40,42 @@ export class StockakingJobComponent {
@ViewChild('formContentTpl') formContentTpl!: TemplateRef<NzSafeAny> @ViewChild('formContentTpl') formContentTpl!: TemplateRef<NzSafeAny>
ASSET_STATUS = ASSET_STATUS
assetCategoryTree: NzSafeAny[] = []
positionTree: NzSafeAny[] = []
warehouse: NzSafeAny[] = []
companyTree: NzSafeAny[] = []
orgTree: NzSafeAny[] = []
initCreateForm() { initCreateForm() {
this.createForm = this.fb.group({ this.createForm = this.fb.group({
stocktakingJobId: [], stocktakingJobId: [],
name: ['', [FormValidators.required('请输入')]], name: ['', [FormValidators.required('请输入')]],
notes: ['', []], notes: ['', []],
stocktakingUserId: [[], []],
head: [[], []],
fullStocktaking: [1, []], fullStocktaking: [1, []],
stocktakingStartDate: [null, []], stocktakingStartDate: [null, []],
stocktakingEndDate: [null, []], stocktakingEndDate: [null, []],
categoryId: [null, []],
warehouseId: [null, []],
positionId: [null, []],
ownCompanyId: [null, []],
useOrganizationId: [null, []],
useUserId: [null, []],
assetStatus: [0, []],
}) })
} }
initQueryForm() { initQueryForm() {
this.queryForm = this.fb.group({ this.queryForm = this.fb.group({
name: [''], name: [],
uscc: [''], status: [],
code: [''], notes: [],
}) })
} }
@ -67,21 +89,61 @@ export class StockakingJobComponent {
{ key: 'name', title: '名称' }, { key: 'name', title: '名称' },
{ key: 'fullStocktaking', title: '全员盘点' }, { key: 'fullStocktaking', title: '全员盘点' },
{ key: 'status', title: '盘点状态' }, { key: 'status', title: '盘点状态' },
{ key: 'head', title: '负责人' }, { key: '_head', title: '负责人', width: '150px' },
{ key: 'stocktakingUserId', title: '盘点人' }, { key: '_stocktakingUser', title: '盘点人', width: '150px' },
{ key: 'countPending', title: '待盘点', width: '100px' },
{ key: 'countCompleted', title: '已盘点', width: '100px' },
{ key: 'countLoss', title: '盘亏', width: '100px' },
{ key: 'countSurplus', title: '盘盈', width: '100px' },
{ key: 'countException', title: '异常数据', width: '100px' },
{ key: '_category', title: '资产分类' },
{ key: '_ownCompany', title: '所属公司' },
{ key: '_useOrganization', title: '使用公司/部门' },
{ key: '_useUser', title: '保管人', width: '150px' },
{ key: '_warehouse', title: '仓库' },
{ key: '_position', title: '存放位置' },
{ key: 'stocktakingStartDate', title: '购置开始日期', width: '180px' }, { key: 'stocktakingStartDate', title: '购置开始日期', width: '180px' },
{ key: 'stocktakingEndDate', title: '购置结束日期', width: '180px' }, { key: 'stocktakingEndDate', title: '购置结束日期', width: '180px' },
{ key: 'createTime', title: '创建时间', width: '180px' }, { key: 'createTime', title: '创建时间', width: '180px' },
{ key: 'createUser', title: '创建人' }, { key: 'createUser', title: '创建人', width: '150px' },
{ key: 'notes', title: '备注' }, { key: 'notes', title: '备注' },
]) ])
.setRowOperate([ .setRowOperate([
{ title: '编辑', onClick: this.onCreate.bind(this) }, { title: '明细', onClick: this.onCreate.bind(this) },
// { title: '详情', onClick: this.onDetail.bind(this) },
{ title: '编辑', onClick: this.onCreate.bind(this) }, { title: '编辑', onClick: this.onCreate.bind(this) },
{ title: '删除', onClick: this.deleteItem.bind(this) }, { title: '删除', onClick: this.deleteItem.bind(this) },
]) ])
this.initQueryForm() this.initQueryForm()
this.initCreateForm() this.initCreateForm()
this.api.getBasicCategoryTree().subscribe((res) => {
this.assetCategoryTree = Utils.buildTree(res.body, 'categoryId', 'categoryName')
})
this.api.getBasicPositionTree().subscribe((res) => {
this.positionTree = Utils.buildTree(res.body, 'positionId', 'name')
})
this.api.getBasicWarehousePage({ pageSize: MAX_PAGE_SIZE, pageNum: 1 }).subscribe((r) => {
this.warehouse = r.body.rows.map((i: NzSafeAny) => {
return {
label: i.name,
value: i.warehouseId,
}
})
})
this.api.getOrgTree().subscribe((res) => {
const c: NzSafeAny[] = []
const o: NzSafeAny[] = []
res.body.forEach((i: NzSafeAny) => {
if (i.organizationType === '0') {
c.push(i)
}
if (['1', '0'].includes(i.organizationType)) {
o.push(i)
}
})
this.orgTree = Utils.buildTree(o, 'organizationId', 'organizationName')
this.companyTree = Utils.buildTree(c, 'organizationId', 'organizationName')
})
} }
fetchData(p: {}, q: AnyObject) { fetchData(p: {}, q: AnyObject) {
@ -90,7 +152,17 @@ export class StockakingJobComponent {
onCreate(data?: NzSafeAny) { onCreate(data?: NzSafeAny) {
if (data) { if (data) {
this.createForm.patchValue(data) this.createForm.patchValue({
...data,
stocktakingUserId: data._stocktakingUser?.userId ? [data._stocktakingUser?.userId] : [],
head: data._head?.userId ? [data._head?.userId] : [],
useUserId: data._useUser?.userId ? [data._useUser?.userId] : [],
categoryId: data._category?.categoryId + '',
positionId: data._position?.positionId + '',
ownCompanyId: data._ownCompany?.organizationId + '',
useOrganizationId: data._useOrganization?.organizationId + '',
warehouseId: data._warehouse?.warehouseId,
})
} }
this.drawerRef = this.drawer.create({ this.drawerRef = this.drawer.create({
nzTitle: data ? '编辑盘点任务' : '新增盘点任务', nzTitle: data ? '编辑盘点任务' : '新增盘点任务',
@ -100,6 +172,15 @@ export class StockakingJobComponent {
nzOnCancel: this.onCancel.bind(this), nzOnCancel: this.onCancel.bind(this),
}) })
} }
onDetail(data: NzSafeAny) {
this.drawerRef = this.drawer.create({
nzTitle: data ? '编辑盘点任务' : '新增盘点任务',
nzContent: this.formContentTpl,
nzFooter: this.drawerFooterTpl,
nzWidth: 600,
nzOnCancel: this.onCancel.bind(this),
})
}
onConfirm() { onConfirm() {
if (FormValidators.validateFormGroup(this.createForm)) { if (FormValidators.validateFormGroup(this.createForm)) {
@ -108,8 +189,9 @@ export class StockakingJobComponent {
this.api this.api
.saveStocktakingJob({ .saveStocktakingJob({
...value, ...value,
stocktakingUserId: value.stocktakingUserId?.[0],
// stocktakingJobId: value.stocktakingJobId ?? 0, head: value.head?.[0],
useUserId: value.useUserId?.[0],
}) })
.subscribe((res) => { .subscribe((res) => {
this.msg.success(res.desc) this.msg.success(res.desc)
@ -121,7 +203,9 @@ export class StockakingJobComponent {
async onCancel() { async onCancel() {
this.drawerRef?.close() this.drawerRef?.close()
this.createForm.reset({}) this.createForm.reset({
fullStocktaking: 1,
})
} }
deleteItem(item: NzSafeAny) { deleteItem(item: NzSafeAny) {

61
web-admin-app/src/app/services/api.service.ts

@ -89,6 +89,9 @@ export class ApiService {
getUserPage(data: {}) { getUserPage(data: {}) {
return this.http.post<JwResponse>('/api/umsUser/list', data) return this.http.post<JwResponse>('/api/umsUser/list', data)
} }
getUserDetail(id: number) {
return this.http.post<JwResponse>(`/api/umsUser/query?userId=${id}`, null)
}
deleteUser(ids: number[]) { deleteUser(ids: number[]) {
return this.http.post<JwResponse>(`/api/umsUser/delete`, ids) return this.http.post<JwResponse>(`/api/umsUser/delete`, ids)
@ -101,9 +104,52 @@ export class ApiService {
return this.http.post<JwResponse>('/api/umsUser/update', data) return this.http.post<JwResponse>('/api/umsUser/update', data)
} }
getAssetPage(data: {}) {
return this.http.post<JwResponse>('/api/eamAsset/list', data)
}
copyAsset(num: number, id: number) {
return this.http.post<JwResponse>(`/api/eamAsset/copyByNum?num=${num}&id=${id}`, null)
}
deleteAsset(ids: number[]) {
return this.http.post<JwResponse>('/api/eamAsset/delete', ids)
}
uploadAsset(data: FormData) {
return this.http.post<JwResponse>('/api/eamAsset/importData', data)
}
confirmAsset(ids: number[]) {
return this.http.post<JwResponse>('/api/eamAsset/confirm', ids)
}
assetQrcode(id: number) {
return this.http.post<JwResponse>(`/api/qr/generate?id=${id}`, null, {
observe: 'response',
responseType: 'blob' as 'json',
})
}
downloadAssetTemplate() {
return this.http.post<JwResponse>(`/api/eamAsset/importTemplate`, null, {
observe: 'response',
responseType: 'blob' as 'json',
})
}
exportAsset(ids: number[]) {
return this.http.post<JwResponse>(`/api/eamAsset/export`, ids, {
observe: 'response',
responseType: 'blob' as 'json',
})
}
saveAsset(data: NzSafeAny) {
if (Utils.isEmpty(data.assetId)) {
return this.http.post<JwResponse>('/api/eamAsset/add', data)
}
return this.http.post<JwResponse>('/api/eamAsset/update', data)
}
getBasicPositionPage(data: {}) { getBasicPositionPage(data: {}) {
return this.http.post<JwResponse>('/api/eamBasicPosition/list', data) return this.http.post<JwResponse>('/api/eamBasicPosition/list', data)
} }
getBasicPositionTree() {
return this.http.post<JwResponse>('/api/eamBasicPosition/tree', null)
}
saveBasicPosition(data: NzSafeAny) { saveBasicPosition(data: NzSafeAny) {
if (Utils.isEmpty(data.positionId)) { if (Utils.isEmpty(data.positionId)) {
return this.http.post<JwResponse>('/api/eamBasicPosition/add', data) return this.http.post<JwResponse>('/api/eamBasicPosition/add', data)
@ -166,8 +212,19 @@ export class ApiService {
return this.http.post<JwResponse>(`/api/eamBasicWarehouse/delete`, ids) return this.http.post<JwResponse>(`/api/eamBasicWarehouse/delete`, ids)
} }
getBasicCategoryTree() { categoryTree: NzSafeAny[] = []
return this.http.post<JwResponse>('/api/eamBasicCategory/tree', null)
getBasicCategoryTree(force?: boolean) {
if (this.categoryTree.length > 0 && !force) {
return of({
body: this.categoryTree,
} as JwResponse)
}
return this.http.post<JwResponse>('/api/eamBasicCategory/tree', null).pipe(
tap((res) => {
this.categoryTree = res.body
}),
)
} }
addBasicCategoryTree(data: {}) { addBasicCategoryTree(data: {}) {
return this.http.post<JwResponse>('/api/eamBasicCategory/add', data) return this.http.post<JwResponse>('/api/eamBasicCategory/add', data)

11
web-admin-app/src/app/shared/components/server-paginated-table/query-item/query-item.component.less

@ -4,5 +4,16 @@
min-width: 100px; min-width: 100px;
width: 100%; width: 100%;
} }
nz-tree-select,
nz-select {
width: auto !important;
}
.ant-select:not(.ant-select-customize-input) .ant-select-selector {
border: none;
}
} }
} }

8
web-admin-app/src/app/shared/components/server-paginated-table/server-paginated-table.component.ts

@ -347,17 +347,21 @@ export class ServerPaginatedTableComponent implements OnInit, OnChanges {
} else { } else {
this.selected.clear() this.selected.clear()
} }
this.onSelectChange()
} }
onRowSelected(selected: boolean, row: any) { onRowSelected(selected: boolean, row: any) {
const id = String(row[this.options.config.rowKey!]) const id = String(row[this.options.config.rowKey!])
console.log('selected', selected, id)
if (selected) { if (selected) {
this.selected.add(id) this.selected.add(id)
} else { } else {
this.selected.delete(id) this.selected.delete(id)
} }
console.log('this.selected', this.selected) this.onSelectChange()
}
onSelectChange() {
console.log('this.pagination.data', this.pagination.data)
this.indeterminate = this.selected.size > 0 && this.selected.size < this.pagination.data.length this.indeterminate = this.selected.size > 0 && this.selected.size < this.pagination.data.length
} }
} }

55
web-admin-app/src/app/utils/index.ts

@ -1,3 +1,7 @@
import { HttpResponse } from '@angular/common/http'
import { AnyObject } from 'app/shared/components/server-paginated-table'
import { NzTreeNodeOptions } from 'ng-zorro-antd/tree'
export * from './form' export * from './form'
export * from './storage' export * from './storage'
@ -56,4 +60,55 @@ export class Utils {
}) })
return params return params
} }
static buildTree<T extends { parentId: number } & AnyObject>(
organizations: T[],
keyName: string = 'key',
titleName: string = 'title',
): NzTreeNodeOptions[] {
const map: { [parentId: number]: NzTreeNodeOptions[] } = {}
organizations.forEach((org) => {
if (!map[org.parentId]) {
map[org.parentId] = []
}
const treeNode: NzTreeNodeOptions = {
...org,
title: org[titleName],
key: org[keyName].toString(),
}
map[org.parentId].push(treeNode)
})
const build = (parentId: number): NzTreeNodeOptions[] => {
if (!map[parentId]) {
return []
}
return map[parentId].map((node) => {
const children = build(parseInt(node.key))
return {
...node,
isLeaf: children.length === 0,
children,
}
})
}
return build(0)
}
static downLoadFile(response: HttpResponse<Object>, type: string, ext: string = 'pdf') {
const fileNameFromHeader = response.headers.get('Content-Disposition')
let fileName = ''
if (fileNameFromHeader) {
fileName = fileNameFromHeader.trim().split('=')[1].replace(/"/g, '')
}
console.log('fileName', fileName)
const blob = new Blob([response.body as any], { type })
const downloadLink = document.createElement('a')
downloadLink.href = URL.createObjectURL(blob)
downloadLink.download = decodeURIComponent(fileName)
document.body.appendChild(downloadLink)
downloadLink.click()
document.body.removeChild(downloadLink)
}
} }

10
web-admin-app/src/styles.less

@ -63,6 +63,16 @@ body {
background-color: rgba(0, 0, 0, .171) background-color: rgba(0, 0, 0, .171)
} }
.modal-lg {
.ant-modal {
top: 5vh !important;
&-body {
padding: 0;
}
}
}
.upload-btn { .upload-btn {
position: relative; position: relative;

Loading…
Cancel
Save