diff --git a/web-admin-app/README.md b/web-admin-app/README.md index 2758755..0d4a2f8 100644 --- a/web-admin-app/README.md +++ b/web-admin-app/README.md @@ -125,3 +125,46 @@ 执行接口 /api/v2/flowable/device/update/{id} +# 10.30 +1、资产查看-维修、巡检、保养、盘点记录 procInsId +/api/eamAssetLog/list/device +operationType:可选项:[设备报修维修, 设备巡检任务, 设备保养任务, 设备盘点任务] +详情:/api/flowable/task/flowRecord 参数只用填procInsId + +2、运行统计 /api/eamAsset/operationalStatistics + +6、开关机记录 + /api/v2/device/record + +7、计划- cron表达式有误(TODO) + +8、任务 +处置信息已经更新 但是页面需要刷新 + +~~9、任务报表 /api/v2/flowable/device/export/{jobId} 直接下载文档~~ + +10、流程表单 +Excel导入 /api/v2/sysFormTemp/exportExcel +Excel导出 /api/v2/sysFormTemp/importByExcel + +11、流程表单新建 +步骤一、导入模板 +选择模板 上传字段模板 接口不变 +点击下载字段模板 + +步骤二、检查明细 +检查步骤一返回的字段内容 + +步骤三、模板确认 +上传模板接口返回word和excel模板的zip /api/v2/sysFormTemp/formTemplate +上传表单(接口/api/v2/sysFormTemp/upload),暂存templatePath,调用模板确认预览 /api/v2/sysFormTemp/confirm + formKey(必填项), formName,formValue,templatePath; + +确认上传添加保存数据 + +12、维修 详情 + +13、工作报表 api/flFormItem/workReport + 富文本 + html转word api/flFormItem/h52word 或者api/flFormItem/h5str2word + + diff --git a/web-admin-app/proxy/devserver.js b/web-admin-app/proxy/devserver.js index cabcc03..9718e09 100644 --- a/web-admin-app/proxy/devserver.js +++ b/web-admin-app/proxy/devserver.js @@ -11,6 +11,10 @@ const devProxy = (remote) => { target, secure: false, }, + '/file/upload': { + target, + secure: false, + }, } } diff --git a/web-admin-app/src/app/app.routes.ts b/web-admin-app/src/app/app.routes.ts index 3e16584..d5ed155 100644 --- a/web-admin-app/src/app/app.routes.ts +++ b/web-admin-app/src/app/app.routes.ts @@ -85,6 +85,7 @@ import { SystemLogComponent } from './pages/msg/system-log/system-log.component' import { MsgLayoutComponent } from './pages/msg/msg-layout/msg-layout.component' import { FlowManagementComponent } from './pages/flow/flow-management/flow-management.component' import { FlowReportComponent } from './pages/flow/flow-report/flow-report.component' +import { DataVisComponent } from './pages/data-vis/data-vis.component' export const routes: Routes = [ { @@ -96,6 +97,12 @@ export const routes: Routes = [ component: LicensePageComponent, }, + { + path: 'data-vis', + canActivate: [authGuard], + component: DataVisComponent, + }, + { path: '', component: LayoutComponent, diff --git a/web-admin-app/src/app/components/asset-form/asset-form.component.html b/web-admin-app/src/app/components/asset-form/asset-form.component.html index 9bd710a..78f6abd 100644 --- a/web-admin-app/src/app/components/asset-form/asset-form.component.html +++ b/web-admin-app/src/app/components/asset-form/asset-form.component.html @@ -502,16 +502,16 @@ } @case (5) { - 5 + } @case (6) { - 6 + } @case (7) { - + } @case (8) { - + } } } diff --git a/web-admin-app/src/app/components/asset-form/asset-form.component.ts b/web-admin-app/src/app/components/asset-form/asset-form.component.ts index 3bc842e..7b86fa8 100644 --- a/web-admin-app/src/app/components/asset-form/asset-form.component.ts +++ b/web-admin-app/src/app/components/asset-form/asset-form.component.ts @@ -15,7 +15,11 @@ import { NzSafeAny } from 'ng-zorro-antd/core/types' import { NZ_MODAL_DATA } from 'ng-zorro-antd/modal' import { AssetOperationRecordsComponent } from '../asset-operation-records/asset-operation-records.component' import { AssetRepairRecordsComponent } from '../asset-repair-records/asset-repair-records.component' +import { AssetInspectionRecordComponent } from '../asset-inspection-record/asset-inspection-record.component' +import { AssetMaintenanceRecordComponent } from '../asset-maintenance-record/asset-maintenance-record.component' +import { AssetStocktakingRecordComponent } from '../asset-stocktaking-record/asset-stocktaking-record.component' import { UploadComponent } from '../../shared/components/upload/upload.component' +import { AssetOperationalStatisticsComponent } from '../asset-operational-statistics/asset-operational-statistics.component' @Component({ selector: 'app-asset-form', @@ -30,6 +34,10 @@ import { UploadComponent } from '../../shared/components/upload/upload.component MaintenanceSelectComponent, AssetOperationRecordsComponent, AssetRepairRecordsComponent, + AssetInspectionRecordComponent, + AssetStocktakingRecordComponent, + AssetMaintenanceRecordComponent, + AssetOperationalStatisticsComponent, UploadComponent, ], templateUrl: './asset-form.component.html', diff --git a/web-admin-app/src/app/components/asset-inspection-record/asset-inspection-record.component.html b/web-admin-app/src/app/components/asset-inspection-record/asset-inspection-record.component.html new file mode 100644 index 0000000..77fbfe6 --- /dev/null +++ b/web-admin-app/src/app/components/asset-inspection-record/asset-inspection-record.component.html @@ -0,0 +1,52 @@ +
+ + + @switch (key) { + @case ('status') { + + } + @case ('_repairType') { + {{ data.name }} + } + + @default { + {{ data }} + } + } + + + + +
diff --git a/web-admin-app/src/app/components/asset-inspection-record/asset-inspection-record.component.less b/web-admin-app/src/app/components/asset-inspection-record/asset-inspection-record.component.less new file mode 100644 index 0000000..e69de29 diff --git a/web-admin-app/src/app/components/asset-inspection-record/asset-inspection-record.component.ts b/web-admin-app/src/app/components/asset-inspection-record/asset-inspection-record.component.ts new file mode 100644 index 0000000..8dce3f4 --- /dev/null +++ b/web-admin-app/src/app/components/asset-inspection-record/asset-inspection-record.component.ts @@ -0,0 +1,63 @@ +import { Component, Input, 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 { 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' +@Component({ + selector: 'app-asset-inspection-records', + standalone: true, + imports: [SharedModule], + templateUrl: './asset-inspection-record.component.html', + styleUrl: './asset-inspection-record.component.less', +}) +export class AssetInspectionRecordComponent { + constructor( + private modal: NzModalService, + private msg: NzMessageService, + private drawer: NzDrawerService, + private api: ApiService, + private fb: FormBuilder, + ) {} + + @Input() assetId!: number + + table = new TableOption(this.fetchData.bind(this)) + + queryForm!: FormGroup + + initQueryForm() { + this.queryForm = this.fb.group({ + businessId: [], + operationNotes: [], + operationType: [], + }) + } + + ngOnInit(): void { + this.table + .setConfig({ + cacheKey: 'asset-repair-records.component', + }) + .setColumn([ + { key: 'id', title: '主键', width: '100px' }, + { key: 'businessId', title: '业务编号', width: '170px' }, + { key: 'name', title: '名称' }, + { key: '_repairType', title: '维修类型' }, + { key: 'plannedDate', title: '计划完成时间' }, + + // { key: 'createTime', title: '创建时间' }, + ]) + this.initQueryForm() + } + + fetchData(p: {}, q: AnyObject) { + return this.api.deviceLog({ ...p, ...q, assetId: this.assetId, operationType: '设备巡检任务' }) + } +} diff --git a/web-admin-app/src/app/components/asset-maintenance-record/asset-maintenance-record.component.html b/web-admin-app/src/app/components/asset-maintenance-record/asset-maintenance-record.component.html new file mode 100644 index 0000000..77fbfe6 --- /dev/null +++ b/web-admin-app/src/app/components/asset-maintenance-record/asset-maintenance-record.component.html @@ -0,0 +1,52 @@ +
+ + + @switch (key) { + @case ('status') { + + } + @case ('_repairType') { + {{ data.name }} + } + + @default { + {{ data }} + } + } + + + + +
diff --git a/web-admin-app/src/app/components/asset-maintenance-record/asset-maintenance-record.component.less b/web-admin-app/src/app/components/asset-maintenance-record/asset-maintenance-record.component.less new file mode 100644 index 0000000..e69de29 diff --git a/web-admin-app/src/app/components/asset-maintenance-record/asset-maintenance-record.component.ts b/web-admin-app/src/app/components/asset-maintenance-record/asset-maintenance-record.component.ts new file mode 100644 index 0000000..ba3f53c --- /dev/null +++ b/web-admin-app/src/app/components/asset-maintenance-record/asset-maintenance-record.component.ts @@ -0,0 +1,63 @@ +import { Component, Input, 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 { 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' +@Component({ + selector: 'app-asset-maintenance-records', + standalone: true, + imports: [SharedModule], + templateUrl: './asset-maintenance-record.component.html', + styleUrl: './asset-maintenance-record.component.less', +}) +export class AssetMaintenanceRecordComponent { + constructor( + private modal: NzModalService, + private msg: NzMessageService, + private drawer: NzDrawerService, + private api: ApiService, + private fb: FormBuilder, + ) {} + + @Input() assetId!: number + + table = new TableOption(this.fetchData.bind(this)) + + queryForm!: FormGroup + + initQueryForm() { + this.queryForm = this.fb.group({ + businessId: [], + operationNotes: [], + operationType: [], + }) + } + + ngOnInit(): void { + this.table + .setConfig({ + cacheKey: 'asset-repair-records.component', + }) + .setColumn([ + { key: 'id', title: '主键', width: '100px' }, + { key: 'businessId', title: '业务编号', width: '170px' }, + { key: 'name', title: '名称' }, + { key: '_repairType', title: '维修类型' }, + { key: 'plannedDate', title: '计划完成时间' }, + + // { key: 'createTime', title: '创建时间' }, + ]) + this.initQueryForm() + } + + fetchData(p: {}, q: AnyObject) { + return this.api.deviceLog({ ...p, ...q, assetId: this.assetId, operationType: '设备保养任务' }) + } +} diff --git a/web-admin-app/src/app/components/asset-operational-statistics/asset-operational-statistics.component.html b/web-admin-app/src/app/components/asset-operational-statistics/asset-operational-statistics.component.html new file mode 100644 index 0000000..5976657 --- /dev/null +++ b/web-admin-app/src/app/components/asset-operational-statistics/asset-operational-statistics.component.html @@ -0,0 +1,83 @@ + +
+
+

+
+ @if (data?.deviceStatus === 'ON') { + + } @else { + + } +
+
+ + + + + + + +
+

+
+
+ + @if (data?.img) { + + } @else { + + } + +
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ +
+ + {{ data?.depreciation ?? '-' }}% +
+
+ + {{ data?.maintenanceDays ?? '-' }}天 +
+
+
+
+
diff --git a/web-admin-app/src/app/components/asset-operational-statistics/asset-operational-statistics.component.less b/web-admin-app/src/app/components/asset-operational-statistics/asset-operational-statistics.component.less new file mode 100644 index 0000000..e69de29 diff --git a/web-admin-app/src/app/components/asset-operational-statistics/asset-operational-statistics.component.ts b/web-admin-app/src/app/components/asset-operational-statistics/asset-operational-statistics.component.ts new file mode 100644 index 0000000..e5c8818 --- /dev/null +++ b/web-admin-app/src/app/components/asset-operational-statistics/asset-operational-statistics.component.ts @@ -0,0 +1,153 @@ +import { Component, ElementRef, Input, ViewChild } from '@angular/core' +import { ApiService } from 'app/services' +import { SharedModule } from 'app/shared/shared.module' +import { NzSafeAny } from 'ng-zorro-antd/core/types' +import { finalize } from 'rxjs' +import { init, EChartsType } from 'echarts' + +@Component({ + selector: 'app-asset-operational-statistics', + standalone: true, + imports: [SharedModule], + templateUrl: './asset-operational-statistics.component.html', + styleUrl: './asset-operational-statistics.component.less', +}) +export class AssetOperationalStatisticsComponent { + constructor(private api: ApiService) {} + + @ViewChild('openTimeChart') openTimeChart?: ElementRef + + @ViewChild('runningStatusChart') runningStatusChart?: ElementRef + + @Input() assetId!: number + + data: NzSafeAny + + type = 1 + + loading = false + ngOnInit() { + this.onChange() + } + + onChange() { + this.loading = true + this.api + .operationalStatistics({ id: this.assetId, type: this.type }) + .pipe( + finalize(() => { + this.loading = false + }), + ) + .subscribe((res) => { + // console.log('res', res) + this.data = res.body + if (this.data) { + setTimeout(() => { + this.renderBar() + this.renderPie() + }) + } + }) + } + + barRef?: EChartsType + renderBar() { + if (this.openTimeChart?.nativeElement) { + if (!this.barRef) { + this.barRef = init(this.openTimeChart?.nativeElement) + } + const name: string[] = [] + const value: number[] = [] + this.data?.openLogs.forEach((i: NzSafeAny) => { + name.push(i.name) + value.push(i.value) + }) + this.barRef.setOption({ + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow', + }, + }, + xAxis: { + type: 'category', + data: name, + }, + yAxis: { + type: 'value', + }, + series: [ + { + data: value, + type: 'bar', + }, + ], + }) + } + } + pieRef?: EChartsType + renderPie() { + if (this.runningStatusChart?.nativeElement) { + if (!this.pieRef) { + this.pieRef = init(this.runningStatusChart?.nativeElement) + let data: NzSafeAny[] = [] + const odata: NzSafeAny[] = this.data?.runLogs ?? [] + const total = odata.reduce((a: number, b: any) => a + Math.abs(b.value), 0) + + data = odata.map((i: NzSafeAny) => { + const value = Math.abs(i.value) + const percent = ((value / total) * 100).toFixed(2) + + return { + ...i, + percent, + value, + } + }) + this.pieRef.setOption({ + tooltip: { + trigger: 'item', + }, + legend: { + orient: 'scroll', + + formatter: function (name: string, d: any) { + const item = data.find((i: NzSafeAny) => i.name === name) + return name + ' | ' + item?.percent + '%' + ' ' + item?.value + '天' + }, + }, + series: [ + { + name: '运行状态', + type: 'pie', + radius: ['40%', '70%'], + // center: ['40%', '50%'], + avoidLabelOverlap: false, + itemStyle: { + borderRadius: 10, + borderColor: '#fff', + borderWidth: 2, + }, + label: { + show: false, + position: 'center', + }, + emphasis: { + label: { + show: true, + fontSize: 30, + fontWeight: 'bold', + }, + }, + labelLine: { + show: false, + }, + data: data, + }, + ], + }) + } + } + } +} diff --git a/web-admin-app/src/app/components/asset-repair-records/asset-repair-records.component.ts b/web-admin-app/src/app/components/asset-repair-records/asset-repair-records.component.ts index 68bdbae..e309ccf 100644 --- a/web-admin-app/src/app/components/asset-repair-records/asset-repair-records.component.ts +++ b/web-admin-app/src/app/components/asset-repair-records/asset-repair-records.component.ts @@ -58,6 +58,6 @@ export class AssetRepairRecordsComponent { } fetchData(p: {}, q: AnyObject) { - return this.api.getAssetRepairLog({ ...p, ...q }, this.assetId) + return this.api.deviceLog({ ...p, ...q, assetId: this.assetId, operationType: '设备报修维修' }) } } diff --git a/web-admin-app/src/app/components/asset-select-beijian/asset-select-beijian.component.html b/web-admin-app/src/app/components/asset-select-beijian/asset-select-beijian.component.html new file mode 100644 index 0000000..6e90ece --- /dev/null +++ b/web-admin-app/src/app/components/asset-select-beijian/asset-select-beijian.component.html @@ -0,0 +1,157 @@ + + + + + + + + + + + + @switch (key) { + @case ('status') { + + {{ ASSET_STATUS_MAP[data] }} + + } + @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 }} + } + } + + + + + + + + + + + + + + + + + + + @for (item of ASSET_STATUS_MAP | keyvalue; track $index) { + + } + + + + + @for (item of ASSET_SOURCE_MAP | keyvalue; track $index) { + + } + + + + + + + + + + + + + + + + + + 资产编号 + 资产状态 + 资产名称 + 数量 + 规格型号 + 资产序列号 + + + + + + {{ data.assetCode }} + + + + {{ ASSET_STATUS_MAP[data.status] }} + + + {{ data.name }} + + + + {{ data.model }} + {{ data.serialNumber }} + + + + diff --git a/web-admin-app/src/app/components/asset-select-beijian/asset-select-beijian.component.less b/web-admin-app/src/app/components/asset-select-beijian/asset-select-beijian.component.less new file mode 100644 index 0000000..e69de29 diff --git a/web-admin-app/src/app/components/asset-select-beijian/asset-select-beijian.component.ts b/web-admin-app/src/app/components/asset-select-beijian/asset-select-beijian.component.ts new file mode 100644 index 0000000..1fa8502 --- /dev/null +++ b/web-admin-app/src/app/components/asset-select-beijian/asset-select-beijian.component.ts @@ -0,0 +1,222 @@ +import { + ChangeDetectorRef, + Component, + EventEmitter, + Input, + OnInit, + Output, + TemplateRef, + ViewChild, + forwardRef, +} from '@angular/core' +import { ControlValueAccessor, FormControl, FormGroup, 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 { ASSET_SOURCE_MAP, ASSET_STATUS_MAP, MAX_PAGE_SIZE } from 'app/constants' +import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table' +import { PositionSelectComponent } from '../position-select/position-select.component' +import { ManufacturerSelectComponent } from '../manufacturer-select/manufacturer-select.component' +import { map, tap } from 'rxjs' + +@Component({ + selector: 'asset-select-beijian', + standalone: true, + imports: [SharedModule, PositionSelectComponent, ManufacturerSelectComponent], + templateUrl: './asset-select-beijian.component.html', + styleUrl: './asset-select-beijian.component.less', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + multi: true, + useExisting: forwardRef(() => AssetSelectBeijianComponent), + }, + ], +}) +export class AssetSelectBeijianComponent { + constructor( + private api: ApiService, + private modal: NzModalService, + private msg: NzMessageService, + ) {} + + @Input() radio: boolean = false + + @Input() storage: boolean = false + + @Input() buy: boolean = false + + @Output() onSelected = new EventEmitter() + + allGetedDataMap = new Map() + + originData: NzSafeAny[] = [] + + value?: string + + disabled = false + + selectedDataList: NzSafeAny[] = [] + + checkedAll = false + + loading = false + + indeterminate = false + + setOfCheckedId = new Set() + + ASSET_SOURCE_MAP = ASSET_SOURCE_MAP + + ASSET_STATUS_MAP = ASSET_STATUS_MAP() + + table = new TableOption(this.fetchData.bind(this)) + + 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(), + }) + + ngOnInit(): void { + this.api.getBasicSupplierVendorPage({ pageSize: MAX_PAGE_SIZE, pageNum: 1 }).subscribe((res) => { + this.originData = res.body.rows + }) + this.table + .setConfig({ + selectable: true, + rowKey: 'key', + radio: this.radio, + noneCache: true, + }) + .setColumn([ + { key: 'assetCode', title: '资产编号', visible: true }, + { key: 'name', title: '资产名称', visible: true }, + + { key: 'status', title: '资产状态', visible: true }, + { key: 'count', title: '库存数量', visible: true }, + ]) + } + + fetchData(p: {}, q: AnyObject) { + const fn = this.storage ? 'getAeamBusinessStorageList' : 'getAssetStroagePage' + return this.api[fn]({ ...p, ...q }).pipe( + map((res) => { + res.body.rows.forEach((item: NzSafeAny) => { + item['key'] = item.assetId + '_' + item.warehouseId + this.allGetedDataMap.set(item.key, item) + }) + return res + }), + ) + } + + onTrigger(nzContent: TemplateRef<{}>) { + this.modal.create({ + nzTitle: '选择资产', + nzContent, + nzWidth: '80vw', + nzWrapClassName: 'modal-lg', + nzOnOk: () => { + if (this.radio) { + this.selectedDataList = [] + } + this.allGetedDataMap.forEach((i: NzSafeAny) => { + if (this.table.ref.selected.has(String(i.key))) { + if (!this.selectedDataList.some((s) => s.key === i.key)) { + this.selectedDataList.push({ ...i, count: i.count === 0 ? 0 : 1, max: i.count }) + } + } + }) + this.selectedDataList = this.selectedDataList.slice() + this.refreshCheckedStatus() + this.onChange(this.selectedDataList) + }, + }) + } + + onRemove() { + this.selectedDataList = this.selectedDataList.filter((i) => !this.setOfCheckedId.has(i.key)) + this.refreshCheckedStatus() + this.onChange(this.selectedDataList) + } + + onCountChange() { + this.onChange(this.selectedDataList) + } + + updateCheckedSet(id: number, checked: boolean): void { + if (checked) { + this.setOfCheckedId.add(id) + } else { + this.setOfCheckedId.delete(id) + } + } + + refreshCheckedStatus(): void { + const listOfEnabledData = this.selectedDataList.filter(({ disabled }) => !disabled) + this.checkedAll = listOfEnabledData.every(({ key }) => this.setOfCheckedId.has(key)) + this.indeterminate = listOfEnabledData.some(({ key }) => this.setOfCheckedId.has(key)) && !this.checkedAll + } + + onItemChecked(id: number, checked: boolean): void { + this.updateCheckedSet(id, checked) + this.refreshCheckedStatus() + } + + onAllChecked(checked: boolean): void { + this.selectedDataList + .filter(({ disabled }) => !disabled) + .forEach(({ key }) => this.updateCheckedSet(key, checked)) + this.refreshCheckedStatus() + } + + onTouched = () => {} + + onChange(v: NzSafeAny[]) {} + + writeValue(v: NzSafeAny): void { + let vals = v + if (typeof v === 'string') { + try { + vals = JSON.parse(v) ?? [] + } catch (error) {} + } + if (Array.isArray(vals) && vals.length > 0) { + // const ids = vals.map((i: NzSafeAny) => i.assetId) + this.api.getAssetStorageListByIds(vals).subscribe((res) => { + this.selectedDataList = res.body.rows.map((item: NzSafeAny) => { + item['key'] = item.assetId + '_' + item.warehouseId + this.allGetedDataMap.set(item.assetId, item) + return item + }) + }) + } + } + + registerOnChange(fn: any): void { + this.onChange = fn + } + + registerOnTouched(fn: any): void { + this.onTouched = fn + } + + setDisabledState?(isDisabled: boolean): void { + this.disabled = isDisabled + } +} diff --git a/web-admin-app/src/app/components/asset-stocktaking-record/asset-stocktaking-record.component.html b/web-admin-app/src/app/components/asset-stocktaking-record/asset-stocktaking-record.component.html new file mode 100644 index 0000000..77fbfe6 --- /dev/null +++ b/web-admin-app/src/app/components/asset-stocktaking-record/asset-stocktaking-record.component.html @@ -0,0 +1,52 @@ +
+ + + @switch (key) { + @case ('status') { + + } + @case ('_repairType') { + {{ data.name }} + } + + @default { + {{ data }} + } + } + + + + +
diff --git a/web-admin-app/src/app/components/asset-stocktaking-record/asset-stocktaking-record.component.less b/web-admin-app/src/app/components/asset-stocktaking-record/asset-stocktaking-record.component.less new file mode 100644 index 0000000..e69de29 diff --git a/web-admin-app/src/app/components/asset-stocktaking-record/asset-stocktaking-record.component.ts b/web-admin-app/src/app/components/asset-stocktaking-record/asset-stocktaking-record.component.ts new file mode 100644 index 0000000..83363ea --- /dev/null +++ b/web-admin-app/src/app/components/asset-stocktaking-record/asset-stocktaking-record.component.ts @@ -0,0 +1,63 @@ +import { Component, Input, 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 { 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' +@Component({ + selector: 'app-asset-stocktaking-records', + standalone: true, + imports: [SharedModule], + templateUrl: './asset-stocktaking-record.component.html', + styleUrl: './asset-stocktaking-record.component.less', +}) +export class AssetStocktakingRecordComponent { + constructor( + private modal: NzModalService, + private msg: NzMessageService, + private drawer: NzDrawerService, + private api: ApiService, + private fb: FormBuilder, + ) {} + + @Input() assetId!: number + + table = new TableOption(this.fetchData.bind(this)) + + queryForm!: FormGroup + + initQueryForm() { + this.queryForm = this.fb.group({ + businessId: [], + operationNotes: [], + operationType: [], + }) + } + + ngOnInit(): void { + this.table + .setConfig({ + cacheKey: 'asset-repair-records.component', + }) + .setColumn([ + { key: 'id', title: '主键', width: '100px' }, + { key: 'businessId', title: '业务编号', width: '170px' }, + { key: 'name', title: '名称' }, + { key: '_repairType', title: '维修类型' }, + { key: 'plannedDate', title: '计划完成时间' }, + + // { key: 'createTime', title: '创建时间' }, + ]) + this.initQueryForm() + } + + fetchData(p: {}, q: AnyObject) { + return this.api.deviceLog({ ...p, ...q, assetId: this.assetId, operationType: '设备盘点任务' }) + } +} diff --git a/web-admin-app/src/app/components/flow-list-by-type/flow-list-by-type.component.html b/web-admin-app/src/app/components/flow-list-by-type/flow-list-by-type.component.html new file mode 100644 index 0000000..4321ccf --- /dev/null +++ b/web-admin-app/src/app/components/flow-list-by-type/flow-list-by-type.component.html @@ -0,0 +1,32 @@ +
+ + + + + + + + @switch (key) { + @case ('_assignee') { + {{ data.userName }} + } + @case ('procVars') { + {{ data?.title ?? data?.name ?? '-' }} + } + @case ('status') { + + {{ FLOW_STATUS.get(data) }} + + } + @case ('urgency') { + + {{ row.procVars.urgency === 2 ? '紧急' : '普通' }} + + } + @default { + {{ data }} + } + } + + +
diff --git a/web-admin-app/src/app/components/flow-list-by-type/flow-list-by-type.component.less b/web-admin-app/src/app/components/flow-list-by-type/flow-list-by-type.component.less new file mode 100644 index 0000000..e69de29 diff --git a/web-admin-app/src/app/components/flow-list-by-type/flow-list-by-type.component.ts b/web-admin-app/src/app/components/flow-list-by-type/flow-list-by-type.component.ts new file mode 100644 index 0000000..3b5d9ad --- /dev/null +++ b/web-admin-app/src/app/components/flow-list-by-type/flow-list-by-type.component.ts @@ -0,0 +1,135 @@ +import { Component, EventEmitter, Input, Output, 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 { last, lastValueFrom, map, of, tap } 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 { FormValidators } from 'app/utils' +import { AssetEmployeeApplyComponent } from 'app/components' +import { FLOW_STATUS, flowIntStatus } from 'app/constants' +import { comsMap } from 'app/pages/flow/flow-main/flow-main.component' + +@Component({ + selector: 'app-flow-list-by-type', + standalone: true, + imports: [SharedModule], + templateUrl: './flow-list-by-type.component.html', + styleUrl: './flow-list-by-type.component.less', +}) +export class FlowListByTypeComponent { + constructor( + private api: ApiService, + private modal: NzModalService, + private msg: NzMessageService, + ) {} + + @ViewChild('createFormTpl') createFormTpl!: TemplateRef<{}> + + @Input() type: 'asset' | 'device' = 'asset' + + @Input() page: string = 'apply' + + @Output() onLoad = new EventEmitter() + + createForm = new FormGroup({ + formId: new FormControl(''), + userId: new FormControl([], [FormValidators.required('请选择')]), + }) + + table = new TableOption(this.fetchData.bind(this)) + + assetTotal = 0 + + deviceTotal = 0 + + queryForm = new FormGroup({ + name: new FormControl(''), + }) + + FLOW_STATUS = flowIntStatus + ngOnInit(): void { + this.table + .setConfig({ + cacheKey: this.page + '_' + this.type, + }) + .setColumn([ + { key: 'procVars', title: '名称', visible: true }, + { key: 'status', title: '流程状态', visible: true }, + { key: 'urgency', title: '紧急程度', visible: true }, + { key: 'procDefName', title: '流程类型', visible: true }, + { key: 'assigneeName', title: '审批人', visible: true }, + { key: 'createTime', title: '提交时间', visible: true }, + // { key: 'createTime', title: '作废时间', visible: true }, + // { key: 'createTime', title: '完成时间', visible: true }, + ]) + .setRowOperate([ + { title: '查看', onClick: this.onDetail.bind(this) }, + { + title: '作废', + onClick: this.cancleFlow.bind(this), + visible: (v) => { + return this.page === 'apply' + }, + }, + ]) + } + + fetchData(p: {}, q: AnyObject) { + if (this.page === 'apply') { + return this.api.getMyApplyAssetFlow({ ...p, ...q, type: this.type }).pipe( + tap((res) => { + this.onLoad.emit(res.body.total) + }), + ) + } else if (this.page === 'finished') { + return this.api.getMyFinishedAssetFlow({ ...p, ...q, type: this.type }).pipe( + tap((res) => { + this.onLoad.emit(res.body.total) + }), + ) + } else { + return this.api.getMyTodoAssetFlow({ ...p, ...q, type: this.type }).pipe( + tap((res) => { + this.onLoad.emit(res.body.total) + }), + ) + } + } + + onDetail(model: NzSafeAny) { + console.log('model', model, comsMap[model.category]) + this.modal.create({ + nzTitle: '查看', + nzContent: comsMap[model.category], + nzWrapClassName: 'modal-lg', + nzWidth: '80vw', + nzFooter: null, + nzData: { + value: model, + preview: true, + }, + }) + } + + cancleFlow(d: NzSafeAny) { + this.modal.confirm({ + nzTitle: '作废', + nzContent: '是否要作废该申请?', + nzOnOk: async () => { + const res = await lastValueFrom( + this.api.cancelFlow({ + instanceId: d.procInsId, + taskId: d.taskId, + }), + ) + this.msg.success('作废成功') + this.table.ref.reload() + }, + }) + } +} diff --git a/web-admin-app/src/app/components/plan-task/handle-task-asset-item/handle-task-asset-item.component.html b/web-admin-app/src/app/components/plan-task/handle-task-asset-item/handle-task-asset-item.component.html index 487f443..c453511 100644 --- a/web-admin-app/src/app/components/plan-task/handle-task-asset-item/handle-task-asset-item.component.html +++ b/web-admin-app/src/app/components/plan-task/handle-task-asset-item/handle-task-asset-item.component.html @@ -38,15 +38,28 @@ - -
- - 自动发起报修流程 - - - - -
+ @if (type != 'stocktaking' && formGroup.get('defectStatus')?.value === 2) { +
+ + 自动发起报修流程 + + + + +
+ } + @if (type === 'maintenance') { +
+ + 保养成本 + + + + + + +
+ }
{{ data.title }}总结 @@ -128,6 +141,64 @@ }
+ @if (type === 'maintenance') { +
备件损耗
+ + + } + diff --git a/web-admin-app/src/app/components/plan-task/handle-task-asset-item/handle-task-asset-item.component.ts b/web-admin-app/src/app/components/plan-task/handle-task-asset-item/handle-task-asset-item.component.ts index d2b15b1..9539a81 100644 --- a/web-admin-app/src/app/components/plan-task/handle-task-asset-item/handle-task-asset-item.component.ts +++ b/web-admin-app/src/app/components/plan-task/handle-task-asset-item/handle-task-asset-item.component.ts @@ -12,10 +12,11 @@ import { ASSET_SOURCE_MAP, ASSET_STATUS, MAINTENANCE_STATUS, MAINTENANCE_TYPE, M // 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 { NZ_MODAL_DATA, NzModalService } from 'ng-zorro-antd/modal' import { UploadComponent } from 'app/shared/components/upload/upload.component' import { AssetCategorySelectComponent } from 'app/components/asset-category-select/asset-category-select.component' import { PlanTaskType } from 'app/types' +import { AssetSelectBeijianComponent } from 'app/components/asset-select-beijian/asset-select-beijian.component' // import { AssetOperationRecordsComponent } from '../asset-operation-records/asset-operation-records.component' // import { AssetRepairRecordsComponent } from '../asset-repair-records/asset-repair-records.component' // import { UploadComponent } from '../../shared/components/upload/upload.component' @@ -39,6 +40,7 @@ export const defectStatusText: Record = { // MaintenanceSelectComponent, // AssetOperationRecordsComponent, // AssetRepairRecordsComponent, + AssetSelectBeijianComponent, UploadComponent, ], templateUrl: './handle-task-asset-item.component.html', @@ -86,8 +88,10 @@ export class HandleTaskAssetItemComponent { img: this.fb.control(null, []), attachment: this.fb.control(null, []), notes: this.fb.control(null, []), - + autoRepair: this.fb.control(false, []), + cost: this.fb.control(0, []), _extInfo: this.fb.array([]), + sparePartsList: this.fb.control([], []), }) this.patchValues() @@ -100,6 +104,9 @@ export class HandleTaskAssetItemComponent { get extInfo(): FormArray { return this.formGroup.get('_extInfo') as FormArray } + // get sparePartsList(): FormArray { + // return this.formGroup.get('sparePartsList') as FormArray + // } onExtraChange(v: any) { let extraFields: NzSafeAny[] = [] @@ -110,9 +117,36 @@ export class HandleTaskAssetItemComponent { } catch (error) {} this.setExtraFields(extraFields) + // this.setBeijian(extraFields) } ext = null + setBeijian(beijian: NzSafeAny[]) { + // this.sparePartsList.clear() + // beijian.forEach((i) => { + // this.sparePartsList.push( + // this.fb.group({ + // assetId: this.fb.control(i.assetId), + // categoryId: this.fb.control(i.categoryId), + // categoryName: this.fb.control(i.categoryName), + // count: this.fb.control(i.count), + // model: this.fb.control(i.model), + // name: this.fb.control(i.name), + // remark: this.fb.control(i.remark), + // }), + // ) + // }) + } + + modal = inject(NzModalService) + addSpareParts() { + this.modal.create({ + nzTitle: '选择备件', + }) + } + removeSpareParts(idx: number) { + // this.sparePartsList.removeAt(idx) + } setExtraFields(fields: NzSafeAny[]) { this.extInfo.clear() this.extraFields = fields @@ -136,6 +170,7 @@ export class HandleTaskAssetItemComponent { fields: this.fb.control(i.type === 'RADIO' ? i.value?.fields : []), }), ) + return i }) } diff --git a/web-admin-app/src/app/components/plan-task/handle-task/handle-task.component.html b/web-admin-app/src/app/components/plan-task/handle-task/handle-task.component.html index 27f2388..96eff2c 100644 --- a/web-admin-app/src/app/components/plan-task/handle-task/handle-task.component.html +++ b/web-admin-app/src/app/components/plan-task/handle-task/handle-task.component.html @@ -172,7 +172,7 @@ - @if (item.defectStatus == 0) { + @if (item.defectStatus == 0 && !data.preview) { { const vals = e.getValues() if (vals) { - const res = await lastValueFrom( - this.api.handleTaskAssetItem( - { - ...this.data.value, - defects: this.data.value.defects.map((i: NzSafeAny) => { - if (i.assetId === asset.assetId) { - return { - ...asset, - _formValue: vals._extInfo, - ...vals, - } - } - return i - }), - }, - this.data.value.id, - ), - ) + const val = { + ...this.data.value, + defects: this.data.value.defects.map((i: NzSafeAny) => { + if (i.assetId === asset.assetId) { + return { + ...asset, + _formValue: vals._extInfo, + ...vals, + } + } + return i + }), + } + console.log('val', val) + + const res = await lastValueFrom(this.api.handleTaskAssetItem(val, this.data.value.id)) + this.data.value = JSON.parse(JSON.stringify(val)) this.msg.success(res.desc) // this.table.ref.reload() return true diff --git a/web-admin-app/src/app/components/plan-task/task-form/task-form.component.html b/web-admin-app/src/app/components/plan-task/task-form/task-form.component.html index 4702cfd..b7984c8 100644 --- a/web-admin-app/src/app/components/plan-task/task-form/task-form.component.html +++ b/web-admin-app/src/app/components/plan-task/task-form/task-form.component.html @@ -45,7 +45,12 @@ 任务时长 - + diff --git a/web-admin-app/src/app/components/plan-task/task-form/task-form.component.ts b/web-admin-app/src/app/components/plan-task/task-form/task-form.component.ts index 09a92b4..92aaa4f 100644 --- a/web-admin-app/src/app/components/plan-task/task-form/task-form.component.ts +++ b/web-admin-app/src/app/components/plan-task/task-form/task-form.component.ts @@ -81,7 +81,7 @@ export class TaskFormComponent { businessId: this.fb.control(null, []), attachment: this.fb.control(null, []), - duration: this.fb.control(null, []), + duration: this.fb.control(null, [FormValidators.required('请输入')]), order: this.fb.control(false, []), limit: this.fb.control(false, []), img: this.fb.control(null, []), diff --git a/web-admin-app/src/app/components/plan-task/task-list/task-list.component.ts b/web-admin-app/src/app/components/plan-task/task-list/task-list.component.ts index 40572cb..e87839e 100644 --- a/web-admin-app/src/app/components/plan-task/task-list/task-list.component.ts +++ b/web-admin-app/src/app/components/plan-task/task-list/task-list.component.ts @@ -17,6 +17,7 @@ import { StatusTagComponent } from 'app/components/status-tag/status-tag.compone import { PlanFormComponent } from '../plan-form/plan-form.component' import { TaskFormComponent } from '../task-form/task-form.component' import { HandleTaskComponent } from '../handle-task/handle-task.component' +import { Utils } from 'app/utils' @Component({ selector: 'app-task-list', @@ -99,13 +100,12 @@ export class TaskListComponent { title: '审批', onClick: this.onHandle.bind(this, false), visible(v) { - return true return v.status === 'APPROVAL' }, }, { title: '报表', - onClick: this.deleteItem.bind(this), + onClick: this.onReport.bind(this), visible(v) { return v.status === 'COMPLETED' }, @@ -171,6 +171,7 @@ export class TaskListComponent { } this.table.ref.reload() + this.modalRef?.close() return true }, }) @@ -245,8 +246,22 @@ export class TaskListComponent { // }, }) } + + modalRef?: NzModalRef + + onReport(i: NzSafeAny) { + this.msg.loading('下载中...') + this.api.downloadTaskReport(i.id).subscribe((res) => { + Utils.downLoadFile( + res, + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=utf-8', + ) + this.msg.remove() + this.msg.success('下载成功') + }) + } onHandle(chuzhi: boolean, data: NzSafeAny) { - console.log('chuzhi', chuzhi, data) + // console.log('chuzhi', chuzhi, data) let nzTitle = chuzhi ? '处置任务' : '任务审批' const footer: NzSafeAny[] = chuzhi ? [ @@ -268,7 +283,7 @@ export class TaskListComponent { ) this.msg.success(res.desc) this.table.ref.reload() - ref.close() + this.modalRef?.close() } }, }, @@ -293,7 +308,7 @@ export class TaskListComponent { ) this.msg.success(res.desc) this.table.ref.reload() - ref.close() + this.modalRef?.close() } }, }, @@ -317,7 +332,7 @@ export class TaskListComponent { }, }, ] - const ref = this.modal.create({ + this.modalRef = this.modal.create({ nzTitle, nzContent: HandleTaskComponent, nzWidth: '80vw', @@ -326,11 +341,12 @@ export class TaskListComponent { value: data, chuzhi, type: this.type, + preview: !chuzhi, }, nzFooter: footer.concat({ label: '取消', onClick: () => { - ref.close() + this.modalRef?.close() }, }), }) diff --git a/web-admin-app/src/app/pages/data-vis/data-vis.component.html b/web-admin-app/src/app/pages/data-vis/data-vis.component.html new file mode 100644 index 0000000..5913909 --- /dev/null +++ b/web-admin-app/src/app/pages/data-vis/data-vis.component.html @@ -0,0 +1,113 @@ +
+
+
+ {{ time | date: 'yyyy-MM-dd HH:mm:ss' }} +
+
EAM数据可视化
+
+ {{ data?.slogan }} +
+
+
+
+
+
+ @for (item of data.assetCostStatistics; track $index) { +
+

{{ item.content }}

+ + + {{ item.name }} + +
+ } +
+
+ +
+
+

资产分类排名

+
+
+
+
+
+

设备状态分析

+
+
+
+ +
+
+ +
+

+ + 资产变动分析 +

+
+
+ +
+
+

资产存放分布

+
+
+
+
+
+
+
+ + +
+ @for (item of data.flowCountStatistics; track $index) { +
+

{{ item.content }}

+ + + {{ item.name }} + +
+ } +
+
+
+ +
+
+
+

流程类型统计

+
+
+
+
+ +
+
+ +
+
+ 消息名称 + 消息内容 +
+
+
+ @for (item of data.messages; track $index) { +
+ {{ item.name }} + {{ item.content }} +
+ } +
+
+
+
+
+
+
+
diff --git a/web-admin-app/src/app/pages/data-vis/data-vis.component.less b/web-admin-app/src/app/pages/data-vis/data-vis.component.less new file mode 100644 index 0000000..5621eeb --- /dev/null +++ b/web-admin-app/src/app/pages/data-vis/data-vis.component.less @@ -0,0 +1,761 @@ +::ng-deep { + body { + line-height: 1.15; + font-size: 0.5rem; + margin: 0; + padding: 0; + background-repeat: no-repeat; + background-position: 0 0 / cover; + background-color: #101129; + } + + html { + font-size: 21.1375px !important; + } + + * { + margin: 0; + padding: 0; + font-weight: normal; + } + + ul { + list-style: none; + } + + a { + text-decoration: none; + } +} + +.vis-hd-left { + position: absolute; + left: 40px; + top: 40px; + color: #fff; + font-size: 20px; +} + +.vis-hd-right { + position: absolute; + right: 40px; + top: 40px; + color: #fff; + font-size: 20px; +} + +.vis-title { + font-size: 28px; + position: absolute; + top: 40px; + left: 50%; + transform: translateX(-50%); + color: #fff; +} + +.viewport { + /* 限定大小 */ + min-width: 1024px; + max-width: 1920px; + min-height: 780px; + margin: 0 auto; + background: url(/assets/data-vis/images/logo.png) no-repeat 0 0 / contain; + display: flex; + padding: 3.667rem 0.833rem 0; + position: relative; +} + +.column { + flex: 3; + position: relative; +} + +.column:nth-child(2) { + flex: 4; + margin: 1.333rem 0.833rem 0; +} + +.panel { + /* 边框 */ + box-sizing: border-box; + border: 2px solid red; + border-image: url(/assets/data-vis/images/border.png) 51 38 21 132; + border-width: 2.125rem 1.583rem 0.875rem 5.5rem; + position: relative; + + &:not(:first-child) { + margin-top: 0.833rem; + } +} + +.panel .inner { + /* 装内容 */ + /* height: 60px; */ + position: absolute; + top: -2.125rem; + right: -1.583rem; + bottom: -0.875rem; + left: -5.5rem; + padding: 1rem 1.5rem; + +} + +.panel h3 { + font-size: 0.833rem; + color: #fff; +} + +/* 概览区域 */ +.overview { + height: 4.583rem; +} + +.overview .inner { + display: flex; + justify-content: space-between; +} + +.overview h4 { + font-size: 1.167rem; + padding-left: 0.2rem; + color: #fff; + margin-bottom: 0.333rem +} + +.overview span { + font-size: 0.667rem; + color: #4c9bfd; +} + +/* 监控 */ +.monitor { + height: 14rem; +} + +.monitor .inner { + padding: 1rem 0; + display: flex; + flex-direction: column; +} + +.monitor .tabs { + padding: 0 1.5rem; + margin-bottom: 0.75rem; +} + +.monitor .tabs a { + color: #1950c4; + font-size: 0.75rem; + padding: 0 1.125rem; +} + +// .monitor .tabs a:first-child { +// border-right: 0.083rem solid #00f2f1; +// padding-left: 0; +// } + +.monitor .tabs a.active { + color: #fff; +} + +.monitor .content { + flex: 1; + display: none; + position: relative; +} + +.monitor .head { + background: rgba(255, 255, 255, 0.1); + font-size: 0.583rem; + padding: 0.5rem 1.5rem; + color: #68d8fe; + display: flex; + justify-content: space-between; + line-height: 1.05; +} + +.monitor .col:nth-child(1) { + width: 3.2rem; +} + +.monitor .col:nth-child(2) { + width: 8.4rem; + /* 不换行 一行省略*/ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.monitor .col:nth-child(3) { + width: 3.2rem; +} + +.monitor .marquee-view { + position: absolute; + top: 1.6rem; + bottom: 0; + width: 100%; + overflow: hidden; +} + +.monitor .row { + line-height: 1.05; + padding: 0.5rem 1.5rem; + color: #61a8ff; + font-size: 0.5rem; + position: relative; + display: flex; + justify-content: space-between; +} + +.monitor .row:hover { + color: #68d8ff; + background: rgba(255, 255, 255, 0.1); +} + +.monitor .row:hover .icon-dot { + opacity: 1; +} + +.monitor .icon-dot { + position: absolute; + left: 0.64rem; + opacity: 0; +} + +.monitor .marquee-view { + position: absolute; + top: 1.6rem; + bottom: 0; + width: 100%; + overflow: hidden; +} + +.monitor .row { + line-height: 1.05; + padding: 0.5rem 1.5rem; + color: #61a8ff; + font-size: 0.5rem; + position: relative; + display: flex; + justify-content: space-between; +} + +.monitor .row:hover { + color: #68d8ff; + background: rgba(255, 255, 255, 0.1); +} + +.monitor .row:hover .icon-dot { + opacity: 1; +} + +.monitor .icon-dot { + position: absolute; + left: 0.64rem; + opacity: 0; +} + +/* ------------------------------------------------------------动画 */ +@keyframes row { + 0% {} + + 100% { + transform: translateY(-50%); + } +} + +/* 调用动画 */ +.monitor .marquee { + /* //infinite永久调用动画 */ + animation: row 10s linear infinite; +} + +/*鼠标划入 停止动画 */ +.monitor .marquee:hover { + animation-play-state: paused; +} + +/* 点位 */ +.point { + height: 20rem; +} + +.point .chart { + display: flex; + margin-top: 1rem; + justify-content: space-between; +} + +.point .pie { + width: 13rem; + height: 10rem; + margin-left: -0.4rem; +} + +.point .data { + display: flex; + flex-direction: column; + justify-content: space-between; + width: 7rem; + padding: 1.5rem 1.25rem; + box-sizing: border-box; + background-image: url(/assets/data-vis/images/rect.png); + background-size: cover; +} + +.point h4 { + margin-bottom: 0.5rem; + font-size: 1.167rem; + color: #fff; +} + +.point span { + display: block; + color: #4c9bfd; + font-size: 0.667rem; +} + +/* 地图 */ +.map { + height: 24.1rem; + margin-bottom: 0.833rem; + display: flex; + flex-direction: column; +} + +.map h3 { + line-height: 1; + padding: 0.667rem 0; + margin: 0; + font-size: 0.833rem; + color: #fff; +} + +.map .icon-cube { + color: #68d8fe; +} + +.map .chart { + flex: 1; + background-color: rgba(255, 255, 255, 0.05); +} + +.map .geo { + width: 100%; + height: 100%; +} + +/* 用户模块 */ +.users { + height: 14.167rem; + display: flex; +} + +.users .inner { + display: flex; + flex-direction: column; +} + +.users .chart { + flex: 1; + display: flex; + margin-top: 1rem; +} + +.users .bar { + width: 24.5rem; + height: 10rem; +} + +.users .data { + display: flex; + flex-direction: column; + justify-content: space-between; + width: 7rem; + padding: 1.5rem 1.25rem; + box-sizing: border-box; + background-image: url(/assets/data-vis/images/rect.png); + background-size: cover; +} + +.users h4 { + margin-bottom: 0.5rem; + font-size: 1.167rem; + color: #fff; +} + +.users span { + display: block; + color: #4c9bfd; + font-size: 0.667rem; +} + +/* 订单 */ +.order { + height: 6.167rem; +} + +.order .filter { + display: flex; +} + +.order .filter a { + display: block; + height: 0.75rem; + line-height: 1; + padding: 0 0.75rem; + color: #1950c4; + font-size: 0.75rem; + border-right: 0.083rem solid #00f2f1; +} + +.order .filter a:first-child { + padding-left: 0; +} + +.order .filter a:last-child { + border-right: none; +} + +.order .filter a.active { + color: #fff; + font-size: 0.833rem; +} + +.order .data { + display: flex; + margin-top: 0.833rem; +} + +.order .item { + width: 50%; +} + +.order h4 { + font-size: 1.167rem; + color: #fff; + margin-bottom: 0.417rem; +} + +.order span { + display: block; + color: #4c9bfd; + font-size: 0.667rem; +} + +/* 销售区域 */ +.sales { + height: 18.333rem; +} + +.sales .caption { + display: flex; + line-height: 1; +} + +.sales h3 { + height: 0.75rem; + padding-right: 0.75rem; + +} + +.sales a { + padding: 0.167rem; + font-size: 0.667rem; + margin: -0.125rem 0 0 0.875rem; + border-radius: 0.125rem; + color: #0bace6; +} + +.sales a.active { + background-color: #4c9bfd; + color: #fff; +} + +.sales .inner { + display: flex; + flex-direction: column; +} + +.sales .chart { + flex: 1; + padding-top: 0.6rem; + position: relative; +} + +.sales .label { + position: absolute; + left: 1.75rem; + top: 0.75rem; + color: #4996f5; + font-size: 0.583rem; +} + +.sales .line { + width: 100%; + height: 100%; +} + +/* 渠道区块 */ +.wrap { + display: flex; +} + +.channel, +.quarter { + flex: 1; + height: 13.5rem; +} + +.channel { + margin-right: 0.833rem; +} + +.channel .data { + overflow: hidden; +} + +.channel .item { + margin-top: 0.85rem; +} + +.channel .item:first-child { + float: left; +} + +.channel .item:last-child { + float: right; +} + +.channel h4 { + color: #fff; + font-size: 1.333rem; + margin-bottom: 0.2rem; +} + +.channel small { + font-size: 50%; +} + +.channel span { + display: block; + color: #4c9bfd; + font-size: 0.583rem; +} + +/* 季度区块 */ +.quarter .inner { + display: flex; + flex-direction: column; + margin: 0 -0.25rem; +} + +.quarter .chart { + flex: 1; + padding-top: 0.75rem; +} + +.quarter .box { + position: relative; +} + +.quarter .label { + transform: translate(-50%, -30%); + color: #fff; + font-size: 1.25rem; + position: absolute; + left: 50%; + top: 50%; +} + +.quarter .label small { + font-size: 50%; +} + +.quarter .gauge { + height: 3.5rem; +} + +.quarter .data { + display: flex; + justify-content: space-between; +} + +.quarter .item { + width: 50%; +} + +.quarter h4 { + color: #fff; + font-size: 1rem; + margin-bottom: 0.4rem; +} + +.quarter span { + display: block; + width: 100%; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + color: #4c9bfd; + font-size: 0.583rem; +} + +.point .inner { + display: flex; + flex-direction: column; + + .chart { + flex: 1; + } +} + +/* 排行榜 */ +.top { + height: 11.8rem; +} + +.top .inner { + display: flex; +} + +.top .all { + display: flex; + flex-direction: column; + width: 7rem; + color: #4c9bfd; + font-size: 0.6rem; + vertical-align: middle; +} + +.top .all ul { + padding-left: 0.5rem; + margin-top: 0.5rem; + flex: 1; + display: flex; + flex-direction: column; + justify-content: space-around; +} + +.top .all li { + overflow: hidden; +} + +.top .all [class^="icon-"] { + font-size: 1.5rem; + vertical-align: middle; + margin-right: 0.5rem; +} + +.top .province { + flex: 1; + display: flex; + flex-direction: column; + color: #fff; +} + +.top .province i { + padding: 0 0.5rem; + margin-top: 0.208rem; + float: right; + font-style: normal; + font-size: 0.583rem; + color: #0bace6; +} + +.top .province s { + display: inline-block; + transform: scale(0.8); + text-decoration: none; +} + +.top .province .icon-up { + color: #dc3c33; +} + +.top .province .icon-down { + color: #36be90; +} + +.top .province .data { + flex: 1; + display: flex; + margin-top: 0.6rem; +} + +.top .province ul { + flex: 1; + line-height: 1; + margin-bottom: 0.25rem; +} + +.top .province ul li { + display: flex; + justify-content: space-between; +} + +.top .province ul span { + display: block; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.top .province ul.sup { + font-size: 0.583rem; +} + +.top .province ul.sup li { + color: #4995f4; + padding: 0.5rem; +} + +.top .province ul.sup li.active { + color: #a3c6f2; + background-color: rgba(10, 67, 188, 0.2); +} + +.top .province ul.sub { + display: flex; + flex-direction: column; + justify-content: space-around; + font-size: 0.5rem; + background-color: rgba(10, 67, 188, 0.2); +} + +.top .province ul.sub li { + color: #52ffff; + padding: 0.417rem 0.6rem; +} + +.clock { + position: absolute; + top: -1.5rem; + right: 1.667rem; + font-size: 0.833rem; + color: #0bace6; +} + +.clock i { + margin-right: 5px; + font-size: 0.833rem; +} + +@media screen and (max-width: 1600px) { + .top span { + transform: scale(0.9); + } + + .top .province ul.sup li { + padding: 0.4rem 0.5rem; + } + + .top .province ul.sub li { + padding: 0.23rem 0.5rem; + } + + .quarter span { + transform: scale(0.9); + } +} \ No newline at end of file diff --git a/web-admin-app/src/app/pages/data-vis/data-vis.component.ts b/web-admin-app/src/app/pages/data-vis/data-vis.component.ts new file mode 100644 index 0000000..52cb682 --- /dev/null +++ b/web-admin-app/src/app/pages/data-vis/data-vis.component.ts @@ -0,0 +1,271 @@ +import { Component, ElementRef, ViewChild } from '@angular/core' +import { ApiService } from 'app/services' +import { SharedModule } from 'app/shared/shared.module' +import { NzSafeAny } from 'ng-zorro-antd/core/types' +import { interval } from 'rxjs' +import { init, EChartsType } from 'echarts' + +@Component({ + selector: 'app-data-vis', + standalone: true, + imports: [SharedModule], + templateUrl: './data-vis.component.html', + styleUrl: './data-vis.component.less', +}) +export class DataVisComponent { + constructor(private api: ApiService) {} + + @ViewChild('cateTpl') cateTpl?: ElementRef + @ViewChild('statusTpl') statusTpl?: ElementRef + @ViewChild('changeTpl') changeTpl?: ElementRef + @ViewChild('posTpl') posTpl?: ElementRef + @ViewChild('flowTpl') flowTpl?: ElementRef + + cateRef?: EChartsType + statusRef?: EChartsType + changeRef?: EChartsType + posRef?: EChartsType + flowRef?: EChartsType + + data: NzSafeAny + + time = new Date() + ngOnInit(): void { + this.api.bigScreen().subscribe((res) => { + this.data = res.body + setTimeout(() => { + this.renderCate() + this.renderStatus() + this.renderChange() + this.renderPos() + this.renderFlow() + }, 10) + }) + + interval(1000).subscribe(() => { + this.time = new Date() + }) + } + + renderFlow() { + if (!this.flowTpl?.nativeElement) { + return + } + if (!this.flowRef) { + this.flowRef = init(this.flowTpl.nativeElement) + } + const name: string[] = [] + const val: number[] = [] + this.data.assetPositionChart.forEach((i: any) => { + name.push(i.name) + val.push(i.total) + }) + this.flowRef.setOption({ + legend: { + bottom: 'bottom', + left: 'center', + type: 'scroll', + textStyle: { + color: '#ffffff', + }, + }, + + series: [ + { + type: 'pie', + radius: [10, 100], + label: { + formatter: '{b}-{c}', + // position: 'inside', + }, + itemStyle: { + borderRadius: 8, + }, + data: this.data.flowTypeChart.map((i: any) => { + return { + value: i.total, + name: i.name, + } + }), + }, + ], + }) + } + renderPos() { + if (!this.posTpl?.nativeElement) { + return + } + if (!this.posRef) { + this.posRef = init(this.posTpl.nativeElement) + } + const name: string[] = [] + const val: number[] = [] + this.data.assetPositionChart.forEach((i: any) => { + name.push(i.name) + val.push(i.total) + }) + this.posRef.setOption({ + grid: { + top: '5%', + left: '10%', + right: '5%', + bottom: '10%', + }, + xAxis: { + type: 'category', + boundaryGap: false, + data: name, + splitLine: { + show: false, + }, + axisLabel: { + show: true, + color: '#ffffff', + }, + }, + yAxis: { + type: 'value', + axisLabel: { + show: true, + color: '#ffffff', + }, + }, + series: [ + { + data: val, + type: 'bar', + areaStyle: {}, + smooth: true, + }, + ], + }) + } + renderChange() { + if (!this.changeTpl?.nativeElement) { + return + } + if (!this.changeRef) { + this.changeRef = init(this.changeTpl.nativeElement) + } + const name: string[] = [] + const val: number[] = [] + this.data.assetChangeChart.forEach((i: any) => { + name.push(i.name) + val.push(i.total) + }) + this.changeRef.setOption({ + grid: { + top: '5%', + left: '10%', + right: '5%', + bottom: '6%', + }, + xAxis: { + type: 'category', + boundaryGap: false, + data: name, + splitLine: { + show: false, + }, + axisLabel: { + show: true, + color: '#ffffff', + }, + }, + yAxis: { + type: 'value', + axisLabel: { + show: true, + color: '#ffffff', + }, + }, + series: [ + { + data: val, + type: 'line', + areaStyle: {}, + smooth: true, + }, + ], + }) + } + renderStatus() { + if (!this.statusTpl?.nativeElement) { + return + } + if (!this.statusRef) { + this.statusRef = init(this.statusTpl.nativeElement) + } + + this.statusRef.setOption({ + legend: { + bottom: 'bottom', + left: 'center', + type: 'scroll', + textStyle: { + color: '#ffffff', + }, + }, + + series: [ + { + type: 'pie', + radius: [10, 100], + + roseType: 'area', + itemStyle: { + borderRadius: 8, + }, + data: this.data.assetStatusChart.map((i: any) => { + return { + value: i.total, + name: i.name, + } + }), + }, + ], + }) + } + renderCate() { + if (!this.cateTpl?.nativeElement) { + return + } + if (!this.cateRef) { + this.cateRef = init(this.cateTpl.nativeElement) + } + const name: string[] = [] + const val: number[] = [] + this.data.assetCategoryChart.forEach((i: any) => { + name.push(i.name) + val.push(i.total) + }) + this.cateRef.setOption({ + grid: { + top: 0, + left: '10%', + right: '0%', + bottom: '0%', + }, + xAxis: { + type: 'value', + splitLine: { + show: false, + }, + }, + yAxis: { + type: 'category', + data: name, + axisLabel: { + show: true, + color: '#ffffff', + }, + }, + series: [ + { + type: 'bar', + data: val, + }, + ], + }) + } +} diff --git a/web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form-manage/basic-flow-form-manage.component.html b/web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form-manage/basic-flow-form-manage.component.html index fcc0186..7d14eb4 100644 --- a/web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form-manage/basic-flow-form-manage.component.html +++ b/web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form-manage/basic-flow-form-manage.component.html @@ -23,7 +23,11 @@ - @@ -69,3 +70,13 @@ + +
+ + 文件 + + + + +
+
diff --git a/web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form/basic-flow-form.component.ts b/web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form/basic-flow-form.component.ts index c2ddccd..eed7db8 100644 --- a/web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form/basic-flow-form.component.ts +++ b/web-admin-app/src/app/pages/fixed-asset/basic/basic-flow-form/basic-flow-form.component.ts @@ -1,11 +1,12 @@ -import { Component, inject, TemplateRef, ViewChild } from '@angular/core' +import { Component, ElementRef, 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 { UploadComponent } from 'app/shared/components/upload/upload.component' import { SharedModule } from 'app/shared/shared.module' -import { FormValidators } from 'app/utils' +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' @@ -14,13 +15,13 @@ import { lastValueFrom, map } from 'rxjs' @Component({ selector: 'app-basic-flow-form', standalone: true, - imports: [SharedModule, StatusTagComponent], + imports: [SharedModule, StatusTagComponent, UploadComponent], templateUrl: './basic-flow-form.component.html', styleUrl: './basic-flow-form.component.less', }) export class BasicFlowFormComponent { constructor( - private api: ApiService, + public api: ApiService, private modal: NzModalService, private msg: NzMessageService, ) {} @@ -38,12 +39,28 @@ export class BasicFlowFormComponent { table = new TableOption(this.fetchData.bind(this)) + importData(nzContent: TemplateRef<{}>) { + this.modal.create({ + nzTitle: '导入', + nzContent, + nzFooter: null, + }) + } + exportData() { + this.msg.loading('正在下载...', { nzDuration: 0 }) + this.api.exportFlowForm(Array.from(this.table.ref.selected)).subscribe((res) => { + Utils.downLoadFile(res, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8') + this.msg.remove() + this.msg.success('下载成功') + }) + } + ngOnInit(): void { this.table - // .setConfig({ - // selectable: true, - // rowKey: 'id', - // }) + .setConfig({ + selectable: true, + rowKey: 'formTempId', + }) .setColumn([ { key: 'formKey', title: '表单编号', visible: true }, { key: 'formName', title: '表单名称', visible: true }, @@ -64,7 +81,7 @@ export class BasicFlowFormComponent { router = inject(Router) onEdit(v: NzSafeAny) { - this.router.navigate(['/fixed-asset/basic/flow-form/manage/', v.formKey]) + this.router.navigate(['/fixed-asset/basic/flow-form/manage/', v.formTempId]) } onDelete(data: NzSafeAny) { diff --git a/web-admin-app/src/app/pages/fixed-asset/fixed-asset.component.html b/web-admin-app/src/app/pages/fixed-asset/fixed-asset.component.html index 2be54b3..da65d47 100644 --- a/web-admin-app/src/app/pages/fixed-asset/fixed-asset.component.html +++ b/web-admin-app/src/app/pages/fixed-asset/fixed-asset.component.html @@ -307,7 +307,7 @@ > 供应商 -
  • 维保商 -
  • -
  • --> + +
  • - 维修类型 + 维保类型
  • { + this.onRecords(v) + }, + }, ]) } @@ -102,4 +111,14 @@ export class MaintainOnOffComponent { batchOnOff(type: number) { this.onOff(Array.from(this.table.ref.selected), type) } + + onRecords(v: NzSafeAny) { + this.modal.create({ + nzTitle: '开关机记录', + nzContent: OnOffRecordsComponent, + nzData: v, + + nzFooter: null, + }) + } } diff --git a/web-admin-app/src/app/pages/fixed-asset/maintain/on-off-records/on-off-records.component.html b/web-admin-app/src/app/pages/fixed-asset/maintain/on-off-records/on-off-records.component.html new file mode 100644 index 0000000..46dbdb8 --- /dev/null +++ b/web-admin-app/src/app/pages/fixed-asset/maintain/on-off-records/on-off-records.component.html @@ -0,0 +1,12 @@ +
    + + @for (item of records; track $index) { + + {{ item.operationType }} + + } + +
    diff --git a/web-admin-app/src/app/pages/fixed-asset/maintain/on-off-records/on-off-records.component.less b/web-admin-app/src/app/pages/fixed-asset/maintain/on-off-records/on-off-records.component.less new file mode 100644 index 0000000..e69de29 diff --git a/web-admin-app/src/app/pages/fixed-asset/maintain/on-off-records/on-off-records.component.ts b/web-admin-app/src/app/pages/fixed-asset/maintain/on-off-records/on-off-records.component.ts new file mode 100644 index 0000000..96464d8 --- /dev/null +++ b/web-admin-app/src/app/pages/fixed-asset/maintain/on-off-records/on-off-records.component.ts @@ -0,0 +1,27 @@ +import { Component, inject, OnInit } from '@angular/core' +import { ApiService } from 'app/services' +import { SharedModule } from 'app/shared/shared.module' +import { NzSafeAny } from 'ng-zorro-antd/core/types' +import { NZ_MODAL_DATA } from 'ng-zorro-antd/modal' + +@Component({ + selector: 'app-on-off-records', + standalone: true, + imports: [SharedModule], + templateUrl: './on-off-records.component.html', + styleUrl: './on-off-records.component.less', +}) +export class OnOffRecordsComponent implements OnInit { + constructor(private api: ApiService) {} + + data = inject(NZ_MODAL_DATA) + + records: NzSafeAny[] = [] + ngOnInit(): void { + if (this.data) { + this.api.onOffRecord(this.data.assetId).subscribe((res) => { + this.records = res.body + }) + } + } +} diff --git a/web-admin-app/src/app/pages/fixed-asset/registration/registration.component.html b/web-admin-app/src/app/pages/fixed-asset/registration/registration.component.html index e24357a..7f7ef0d 100644 --- a/web-admin-app/src/app/pages/fixed-asset/registration/registration.component.html +++ b/web-admin-app/src/app/pages/fixed-asset/registration/registration.component.html @@ -244,6 +244,27 @@
    + + 模版文件类型 + + + + + + + + @if (templateType === '2') { + + 扩展资产表单 + + + @for (item of flowForms; track $index) { + + } + + + + } 模版文件 diff --git a/web-admin-app/src/app/pages/fixed-asset/registration/registration.component.ts b/web-admin-app/src/app/pages/fixed-asset/registration/registration.component.ts index bcde03d..9b17cb3 100644 --- a/web-admin-app/src/app/pages/fixed-asset/registration/registration.component.ts +++ b/web-admin-app/src/app/pages/fixed-asset/registration/registration.component.ts @@ -48,6 +48,12 @@ export class RegistrationComponent { copyNum = 1 + templateType = '1' + + extendFormId?: string + + flowForms: NzSafeAny[] = [] + ngOnInit(): void { this.table .setConfig({ @@ -75,6 +81,10 @@ export class RegistrationComponent { { title: '二维码', onClick: this.qrcode.bind(this) }, { title: '删除', onClick: this.deleteItem.bind(this) }, ]) + + this.api.getFlowFormList().subscribe((res) => { + this.flowForms = res.body + }) } fetchData(p: {}, q: AnyObject) { @@ -163,8 +173,12 @@ export class RegistrationComponent { } downloadTemplate() { + if (this.templateType === '2' && !this.extendFormId) { + this.msg.error('请选择表单') + return + } this.msg.loading('模板下载中...') - this.api.downloadAssetTemplate().subscribe((res) => { + this.api.downloadAssetTemplate(this.extendFormId).subscribe((res) => { Utils.downLoadFile(res, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8') this.msg.remove() this.msg.success('模板下载成功') diff --git a/web-admin-app/src/app/pages/flow/flow-my-apply/flow-my-apply.component.html b/web-admin-app/src/app/pages/flow/flow-my-apply/flow-my-apply.component.html index c2380bf..3f47fd0 100644 --- a/web-admin-app/src/app/pages/flow/flow-my-apply/flow-my-apply.component.html +++ b/web-admin-app/src/app/pages/flow/flow-my-apply/flow-my-apply.component.html @@ -1,34 +1,12 @@ -
    - - - - - - - - @switch (key) { - @case ('_assignee') { - {{ data.userName }} - } - @case ('procVars') { - {{ data?.title ?? data?.name ?? '-' }} - } - @case ('status') { - - {{ FLOW_STATUS.get(data) }} - - } - @case ('urgency') { - - {{ row.procVars.urgency === 2 ? '紧急' : '普通' }} - - } - @default { - {{ data }} - } - } - - +
    + + + + + + + +
    diff --git a/web-admin-app/src/app/pages/flow/flow-my-apply/flow-my-apply.component.ts b/web-admin-app/src/app/pages/flow/flow-my-apply/flow-my-apply.component.ts index 262d00c..133b08b 100644 --- a/web-admin-app/src/app/pages/flow/flow-my-apply/flow-my-apply.component.ts +++ b/web-admin-app/src/app/pages/flow/flow-my-apply/flow-my-apply.component.ts @@ -13,11 +13,12 @@ import { FormValidators } from 'app/utils' import { AssetEmployeeApplyComponent } from 'app/components' import { comsMap } from '../flow-main/flow-main.component' import { FLOW_STATUS, flowIntStatus } from 'app/constants' +import { FlowListByTypeComponent } from 'app/components/flow-list-by-type/flow-list-by-type.component' @Component({ selector: 'app-flow-my-apply', standalone: true, - imports: [SharedModule], + imports: [SharedModule, FlowListByTypeComponent], templateUrl: './flow-my-apply.component.html', styleUrl: './flow-my-apply.component.less', }) @@ -35,67 +36,13 @@ export class FlowMyApplyComponent { userId: new FormControl([], [FormValidators.required('请选择')]), }) - table = new TableOption(this.fetchData.bind(this)) + assetTotal = 0 - queryForm = new FormGroup({ - name: new FormControl(''), - }) - - FLOW_STATUS = flowIntStatus - ngOnInit(): void { - this.table - // .setConfig({ - // selectable: true, - // rowKey: 'id', - // }) - .setColumn([ - { key: 'procVars', title: '名称', visible: true }, - { key: 'status', title: '流程状态', visible: true }, - { key: 'urgency', title: '紧急程度', visible: true }, - { key: 'procDefName', title: '流程类型', visible: true }, - { key: 'assigneeName', title: '审批人', visible: true }, - { key: 'createTime', title: '提交时间', visible: true }, - // { key: 'createTime', title: '作废时间', visible: true }, - // { key: 'createTime', title: '完成时间', visible: true }, - ]) - .setRowOperate([ - { title: '查看', onClick: this.onDetail.bind(this) }, - { title: '作废', onClick: this.cancleFlow.bind(this) }, - ]) - } + deviceTotal = 0 - fetchData(p: {}, q: AnyObject) { - return this.api.getMyApplyAssetFlow({ ...p, ...q }) + onLoad(total: number, type: 'assetTotal' | 'deviceTotal') { + this[type] = total } - onDetail(model: NzSafeAny) { - this.modal.create({ - nzTitle: '查看任务', - nzContent: comsMap[model.category], - nzWrapClassName: 'modal-lg', - nzWidth: '80vw', - nzFooter: null, - nzData: { - value: model, - preview: true, - }, - }) - } - - cancleFlow(d: NzSafeAny) { - this.modal.confirm({ - nzTitle: '作废', - nzContent: '是否要作废该申请?', - nzOnOk: async () => { - const res = await lastValueFrom( - this.api.cancelFlow({ - instanceId: d.procInsId, - taskId: d.taskId, - }), - ) - this.msg.success('作废成功') - this.table.ref.reload() - }, - }) - } + ngOnInit(): void {} } diff --git a/web-admin-app/src/app/pages/flow/flow-my-finished/flow-my-finished.component.html b/web-admin-app/src/app/pages/flow/flow-my-finished/flow-my-finished.component.html index c2380bf..85aa338 100644 --- a/web-admin-app/src/app/pages/flow/flow-my-finished/flow-my-finished.component.html +++ b/web-admin-app/src/app/pages/flow/flow-my-finished/flow-my-finished.component.html @@ -1,34 +1,12 @@ -
    - - - - - - - - @switch (key) { - @case ('_assignee') { - {{ data.userName }} - } - @case ('procVars') { - {{ data?.title ?? data?.name ?? '-' }} - } - @case ('status') { - - {{ FLOW_STATUS.get(data) }} - - } - @case ('urgency') { - - {{ row.procVars.urgency === 2 ? '紧急' : '普通' }} - - } - @default { - {{ data }} - } - } - - +
    + + + + + + + +
    diff --git a/web-admin-app/src/app/pages/flow/flow-my-finished/flow-my-finished.component.ts b/web-admin-app/src/app/pages/flow/flow-my-finished/flow-my-finished.component.ts index 6be7ba3..b4ec651 100644 --- a/web-admin-app/src/app/pages/flow/flow-my-finished/flow-my-finished.component.ts +++ b/web-admin-app/src/app/pages/flow/flow-my-finished/flow-my-finished.component.ts @@ -12,11 +12,12 @@ import { NzMessageService } from 'ng-zorro-antd/message' import { FormValidators } from 'app/utils' import { comsMap } from '../flow-main/flow-main.component' import { FLOW_STATUS, flowIntStatus } from 'app/constants' +import { FlowListByTypeComponent } from 'app/components/flow-list-by-type/flow-list-by-type.component' @Component({ selector: 'app-flow-my-finished', standalone: true, - imports: [SharedModule], + imports: [SharedModule, FlowListByTypeComponent], templateUrl: './flow-my-finished.component.html', styleUrl: './flow-my-finished.component.less', }) @@ -34,6 +35,14 @@ export class FlowMyFinishedComponent { userId: new FormControl([], [FormValidators.required('请选择')]), }) + assetTotal = 0 + + deviceTotal = 0 + + onLoad(total: number, type: 'assetTotal' | 'deviceTotal') { + this[type] = total + } + table = new TableOption(this.fetchData.bind(this)) queryForm = new FormGroup({ @@ -43,23 +52,23 @@ export class FlowMyFinishedComponent { FLOW_STATUS = flowIntStatus ngOnInit(): void { - this.table - // .setConfig({ - // selectable: true, - // rowKey: 'id', - // }) - .setColumn([ - { key: 'procVars', title: '名称', visible: true }, - // { key: 'status', title: '审批状态', visible: true }, - { key: 'status', title: '流程状态', visible: true }, - { key: 'urgency', title: '紧急程度', visible: true }, - { key: 'procDefName', title: '流程类型', visible: true }, - { key: 'assigneeName', title: '审批人', visible: true }, - { key: 'createTime', title: '提交时间', visible: true }, - // { key: 'createTime', title: '作废时间', visible: true }, - // { key: 'createTime', title: '完成时间', visible: true }, - ]) - .setRowOperate([{ title: '查看', onClick: this.onDetail.bind(this) }]) + // this.table + // // .setConfig({ + // // selectable: true, + // // rowKey: 'id', + // // }) + // .setColumn([ + // { key: 'procVars', title: '名称', visible: true }, + // // { key: 'status', title: '审批状态', visible: true }, + // { key: 'status', title: '流程状态', visible: true }, + // { key: 'urgency', title: '紧急程度', visible: true }, + // { key: 'procDefName', title: '流程类型', visible: true }, + // { key: 'assigneeName', title: '审批人', visible: true }, + // { key: 'createTime', title: '提交时间', visible: true }, + // // { key: 'createTime', title: '作废时间', visible: true }, + // // { key: 'createTime', title: '完成时间', visible: true }, + // ]) + // .setRowOperate([{ title: '查看', onClick: this.onDetail.bind(this) }]) } fetchData(p: {}, q: AnyObject) { diff --git a/web-admin-app/src/app/pages/flow/flow-my-todo/flow-my-todo.component.html b/web-admin-app/src/app/pages/flow/flow-my-todo/flow-my-todo.component.html index 69a4e8b..bb64685 100644 --- a/web-admin-app/src/app/pages/flow/flow-my-todo/flow-my-todo.component.html +++ b/web-admin-app/src/app/pages/flow/flow-my-todo/flow-my-todo.component.html @@ -1,4 +1,4 @@ - + + + +
    + + + + + + + + +
    +
    diff --git a/web-admin-app/src/app/pages/flow/flow-my-todo/flow-my-todo.component.ts b/web-admin-app/src/app/pages/flow/flow-my-todo/flow-my-todo.component.ts index a51af71..9ff6f76 100644 --- a/web-admin-app/src/app/pages/flow/flow-my-todo/flow-my-todo.component.ts +++ b/web-admin-app/src/app/pages/flow/flow-my-todo/flow-my-todo.component.ts @@ -12,11 +12,12 @@ import { NzMessageService } from 'ng-zorro-antd/message' import { FormValidators } from 'app/utils' import { comsMap } from '../flow-main/flow-main.component' import { FLOW_STATUS, flowIntStatus } from 'app/constants' +import { FlowListByTypeComponent } from 'app/components/flow-list-by-type/flow-list-by-type.component' @Component({ selector: 'app-flow-my-todo', standalone: true, - imports: [SharedModule], + imports: [SharedModule, FlowListByTypeComponent], templateUrl: './flow-my-todo.component.html', styleUrl: './flow-my-todo.component.less', }) @@ -38,6 +39,14 @@ export class FlowMyTodoComponent { comment = '' + assetTotal = 0 + + deviceTotal = 0 + + onLoad(total: number, type: 'assetTotal' | 'deviceTotal') { + this[type] = total + } + table = new TableOption(this.fetchData.bind(this)) queryForm = new FormGroup({ diff --git a/web-admin-app/src/app/pages/flow/flow-report/flow-report.component.html b/web-admin-app/src/app/pages/flow/flow-report/flow-report.component.html index c178d98..49c2fdf 100644 --- a/web-admin-app/src/app/pages/flow/flow-report/flow-report.component.html +++ b/web-admin-app/src/app/pages/flow/flow-report/flow-report.component.html @@ -1 +1,135 @@ -

    flow-report works!

    + +
    +
    + + 任务类型 + + + + + + + + + +
    +
    + + 类型 + + + + + + + + + +
    +
    + + 自定义时段 + + + + +
    +
    +
    + + + + + + +
    +
    +
    +
    + +
    +
    +
    + 工作报表 +
    +
    + 日期:{{ data.startDate | date: 'yyyy-MM-dd' }} ~ {{ data.endDate | date: 'yyyy-MM-dd' }} +
    +
    +
    +
    +

    {{ reportTypeText.get(reportType) }}工作概述

    +
    +
    + +
    +
    +
      +
    • +

      {{ data.taskCount ?? 0 }}

      +

      累计处理任务数

      +
    • +
    • +

      {{ data.taskCount ?? 0 }}

      +

      已完成任务数

      +
    • +
    • +

      {{ data.taskCount ?? 0 }}

      +

      未完成任务数

      +
    • +
    +
    +
    +
    + @for (item of data.taskList; track $index) { +
    +

    任务执行情况

    +
    +
    +

    任务执行数据分析

    +
    +
    +
    +
    + +
    +
    +
    + } + +
    +

    工作计划

    +
    +
    + +
    +
    +
    +
    +

    总结

    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +
    diff --git a/web-admin-app/src/app/pages/flow/flow-report/flow-report.component.less b/web-admin-app/src/app/pages/flow/flow-report/flow-report.component.less index e69de29..c7fc982 100644 --- a/web-admin-app/src/app/pages/flow/flow-report/flow-report.component.less +++ b/web-admin-app/src/app/pages/flow/flow-report/flow-report.component.less @@ -0,0 +1,127 @@ +.report { + + + padding: 24px; + background-color: #fff; + + h1 { + font-size: 22px; + } + + h2 { + font-size: 18x; + } + + .report-title { + position: relative; + + } + + .echart { + height: 205px; + + } + + .pie { + width: 200px; + } + + .line { + flex: 1; + } + + .report-title-left { + font-size: 24px; + text-align: center; + } + + .report-title-right { + position: absolute; + bottom: 5px; + right: 0; + } + + .report-footer { + text-align: right; + + &>div { + margin-top: 12px; + } + } + + .report-content-row { + min-height: 220px; + + textarea { + width: 100%; + min-height: 150px; + border: 1px solid #ccc; + + &:focus, + &:active, + &:hover { + outline: none; + border: 1px solid #ccc; + } + } + } + + .report-content-row-content { + display: flex; + + .report-content-row-left { + display: flex; + flex-basis: 60%; + flex-shrink: 0; + } + + .report-content-row-right { + padding-left: 24px; + flex: 1; + } + } + + .counter { + display: flex; + justify-content: center; + + + + + li { + margin: 0 12px; + padding: 24px 0; + flex: 1; + text-align: center; + border: 1px dashed #027db4; + + &.error { + border-color: #d9001b; + + p { + color: #d9001b; + } + } + + &.success { + border-color: #70b603; + + p { + color: #70b603; + } + } + + p { + margin-bottom: 6px; + color: #027db4; + + &:first-child { + + font-size: 20px; + font-weight: bold; + } + } + } + } + +} \ No newline at end of file diff --git a/web-admin-app/src/app/pages/flow/flow-report/flow-report.component.ts b/web-admin-app/src/app/pages/flow/flow-report/flow-report.component.ts index 3ab3eec..96fa60f 100644 --- a/web-admin-app/src/app/pages/flow/flow-report/flow-report.component.ts +++ b/web-admin-app/src/app/pages/flow/flow-report/flow-report.component.ts @@ -1,12 +1,217 @@ -import { Component } from '@angular/core'; +import { Component, ElementRef, QueryList, ViewChildren } from '@angular/core' +import { FormControl, FormGroup } from '@angular/forms' +import { ApiService } from 'app/services' +import { SharedModule } from 'app/shared/shared.module' +import { NzSafeAny } from 'ng-zorro-antd/core/types' +import { + startOfDay, + endOfDay, + startOfWeek, + endOfWeek, + startOfMonth, + endOfMonth, + startOfYear, + endOfYear, + format, +} from 'date-fns' +import { finalize } from 'rxjs' + +import { init, EChartsType } from 'echarts' + +function getDateRange(n: number): { startDate: string; endDate: string } { + const today = new Date() + + let startDate: Date + let endDate: Date + + switch (n) { + case 0: // Today + startDate = startOfDay(today) + endDate = endOfDay(today) + break + case 1: // This Week + startDate = startOfWeek(today, { weekStartsOn: 1 }) + endDate = endOfWeek(today, { weekStartsOn: 1 }) + break + case 2: // This Month + startDate = startOfMonth(today) + endDate = endOfMonth(today) + break + case 3: // This Year + startDate = startOfYear(today) + endDate = endOfYear(today) + break + default: + throw new Error('Invalid parameter. Please provide a number between 0 and 3.') + } + + return { + startDate: format(startDate, 'yyyy-MM-dd'), + endDate: format(endDate, 'yyyy-MM-dd'), + } +} @Component({ - selector: 'app-flow-report', - standalone: true, - imports: [], - templateUrl: './flow-report.component.html', - styleUrl: './flow-report.component.less' + selector: 'app-flow-report', + standalone: true, + imports: [SharedModule], + templateUrl: './flow-report.component.html', + styleUrl: './flow-report.component.less', }) export class FlowReportComponent { + constructor(private api: ApiService) {} + + formKeys: NzSafeAny[] = [] + + reportType: number = 0 + + range: Date[] = [] + + data: NzSafeAny + + loading = false + + today = format(new Date(), 'yyyy年MM月dd日') + + reportTypeText = new Map([ + [0, '今日'], + [1, '本周'], + [2, '本月'], + [3, '本年'], + ]) + + gaishu = ` + 1、本周 + 2、继续对所有锅炉和电梯设备进行定期巡检,确保设备安全稳定运行。 + 3、根据本周巡检结果,对设备维护计划进行必要的调整,以提高设备运行效率和安全性。` + + plan = ` + 1、安排专业人员对{锅炉001}进行返修,确保设备尽快恢复正常运行。 + 2、继续对所有锅炉和电梯设备进行定期巡检,确保设备安全稳定运行。 + 3、根据本周巡检结果,对设备维护计划进行必要的调整,以提高设备运行效率和安全性。 + ` + + zongjie = ` + 本周的巡检和检修工作总体顺利,除了锅炉001需要返修外,其他设备均运行正常。 + 我们将继续密切关注设备状态,并及时处理任何潜在问题,以确保公司运营的顺畅和安全。 + 请各部门继续配合我们的工作,如有任何问题或建议,请及时与我们联系。 + + ` + + @ViewChildren('itemElement') itemElements!: QueryList + + ngOnInit() { + this.onTypeChange(this.reportType) + } + + ngAfterViewInit() {} + + onTypeChange(n: number) { + const { startDate, endDate } = getDateRange(n) + this.range = [new Date(startDate), new Date(endDate)] + this.onChange() + } + onChange() { + let startDate = '' + let endDate = '' + this.loading = true + if (this.range.length === 2) { + startDate = format(this.range[0], 'yyyy-MM-dd') + endDate = format(this.range[1], 'yyyy-MM-dd') + } + this.api + .getReportData({ + formKeys: this.formKeys, + reportType: this.reportType, + startDate, + endDate, + }) + .pipe( + finalize(() => { + this.loading = false + }), + ) + .subscribe((res) => { + this.data = res.body + setTimeout(() => { + console.log('this.data', this.itemElements) + this.itemElements.forEach((itemElement, index) => { + console.log(`Element ${index}: `, itemElement.nativeElement) + this.renderPie(itemElement.nativeElement, []) + this.renderLine(itemElement.nativeElement, []) + }) + }, 0) + }) + } + + renderLine(el: HTMLElement, data: NzSafeAny[]) { + el = el.querySelector('.line') as HTMLDivElement + if (el) { + const lineRef = init(el) + const name: string[] = [] + const value: number[] = [] + data?.forEach((i: NzSafeAny) => { + name.push(i.name) + value.push(i.value) + }) + lineRef.setOption({ + xAxis: { + type: 'category', + data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], + }, + yAxis: { + type: 'value', + }, + series: [ + { + data: [820, 932, 901, 934, 1290, 1330, 1320], + type: 'line', + smooth: true, + }, + ], + }) + } + } + renderPie(el: HTMLElement, data: NzSafeAny[]) { + el = el.querySelector('.pie') as HTMLDivElement + if (el) { + const pieRef = init(el) + let data: NzSafeAny[] = [] + const odata: NzSafeAny[] = data ?? [] + const total = odata.reduce((a: number, b: any) => a + Math.abs(b.value), 0) + + data = odata.map((i: NzSafeAny) => { + const value = Math.abs(i.value) + const percent = ((value / total) * 100).toFixed(2) + + return { + ...i, + percent, + value, + } + }) + pieRef.setOption({ + title: { + text: '', + }, + series: [ + { + name: 'Access From', + type: 'pie', + radius: ['40%', '70%'], + avoidLabelOverlap: false, + label: { + show: false, + position: 'center', + }, + data: [ + { value: 1048, name: 'Search Engine' }, + { value: 735, name: 'Direct' }, + ], + }, + ], + }) + } + } } diff --git a/web-admin-app/src/app/pages/msg/flow-msg/flow-msg.component.ts b/web-admin-app/src/app/pages/msg/flow-msg/flow-msg.component.ts index d2d9c12..17ec2da 100644 --- a/web-admin-app/src/app/pages/msg/flow-msg/flow-msg.component.ts +++ b/web-admin-app/src/app/pages/msg/flow-msg/flow-msg.component.ts @@ -43,11 +43,11 @@ export class FlowMsgComponent { // rowKey: 'id', // }) .setColumn([ - { key: 'logId', title: '序号', visible: true }, + // { key: 'logId', title: '序号', visible: true }, { key: 'createTime', title: '时间', visible: true }, - { key: 'logType', title: '类型', visible: true }, - { key: 'logContent', title: '内容', visible: true }, - { key: 'logContent', title: '待我处理', visible: true }, + // { key: 'logType', title: '类型', visible: true }, + { key: 'content', title: '内容', visible: true }, + // { key: 'logContent', title: '待我处理', visible: true }, ]) } diff --git a/web-admin-app/src/app/services/api.service.ts b/web-admin-app/src/app/services/api.service.ts index 05fee66..485a47c 100644 --- a/web-admin-app/src/app/services/api.service.ts +++ b/web-admin-app/src/app/services/api.service.ts @@ -55,6 +55,13 @@ export class ApiService { uploadLicenseInfo(formData: FormData) { return this.http.post('/api/license/update', formData) } + importFlowFormByExcel(formData: FormData) { + return this.http.post('/api/v2/sysFormTemp/importByExcel', formData) + } + + uploadFormTpl(formData: FormData) { + return this.http.post(`/api/v2/sysFormTemp/upload`, formData) + } login(data: {}) { return this.http.post('/api/oauth/login', data).pipe( @@ -194,8 +201,9 @@ export class ApiService { responseType: 'blob' as 'json', }) } - downloadAssetTemplate() { + downloadAssetTemplate(categoryId?: string) { return this.http.post(`/api/eamAsset/importTemplate`, null, { + params: categoryId ? { categoryId } : {}, observe: 'response', responseType: 'blob' as 'json', }) @@ -617,6 +625,12 @@ export class ApiService { responseType: 'blob' as 'json', }) } + downloadTpl() { + return this.http.post(`/api/v2/sysFormTemp/formTemplate`, null, { + observe: 'response', + responseType: 'blob' as 'json', + }) + } addFlowForm(data: NzSafeAny) { return this.http.post(`/api/v2/sysFormTemp/add`, data) @@ -624,6 +638,9 @@ export class ApiService { updateFlowForm(data: NzSafeAny) { return this.http.post(`/api/v2/sysFormTemp/update`, data) } + confirmFlowForm(data: NzSafeAny) { + return this.http.post(` /api/v2/sysFormTemp/confirm`, data) + } deleteFlowForm(idList: NzSafeAny) { return this.http.post(`/api/v2/sysFormTemp/delete`, idList) @@ -698,7 +715,7 @@ export class ApiService { return this.http.post('/api/v2/alarm/list', data) } getFlowMsg(data: {}) { - return this.http.post('/api/flowable/task/todoListMSG ', data) + return this.http.post('/api/flowable/task/todoListMSG', data) } getCalendarData(data: {}) { return this.http.post('/api/flFormItem/calendar', data) @@ -709,4 +726,41 @@ export class ApiService { flowFormUpdate(d: {}) { return this.http.post('/api/flForm/update', d) } + deviceLog(d: {}) { + return this.http.post('/api/eamAssetLog/list/device', d) + } + assetFlowRecord(d: {}) { + return this.http.post('/api/flowable/task/flowRecord', d) + } + operationalStatistics(d: {}) { + return this.http.get('/api/eamAsset/operationalStatistics', { + params: d, + }) + } + downloadTaskReport(id: string) { + return this.http.post(`/api/v2/flowable/device/export/${id}`, null, { + observe: 'response', + responseType: 'blob' as 'json', + }) + } + exportFlowForm(idList: string[]) { + return this.http.post(`/api/v2/sysFormTemp/exportExcel`, idList, { + observe: 'response', + responseType: 'blob' as 'json', + }) + } + onOffRecord(id: string) { + return this.http.post(`/api/v2/device/record`, null, { + params: { id }, + }) + } + getReportData(data: {}) { + return this.http.post(`/api/flFormItem/workReport`, data) + } + saveReport(content: string) { + return this.http.post(`api/flFormItem/h5str2word`, null, { params: { content } }) + } + bigScreen() { + return this.http.post(`/api/home/bigScreen`, null) + } } diff --git a/web-admin-app/src/app/shared/components/header/header.component.html b/web-admin-app/src/app/shared/components/header/header.component.html index 6840138..0a4526d 100644 --- a/web-admin-app/src/app/shared/components/header/header.component.html +++ b/web-admin-app/src/app/shared/components/header/header.component.html @@ -94,7 +94,7 @@ - + diff --git a/web-admin-app/src/app/shared/components/server-paginated-table/server-paginated-table.component.html b/web-admin-app/src/app/shared/components/server-paginated-table/server-paginated-table.component.html index 24379a0..b10f935 100644 --- a/web-admin-app/src/app/shared/components/server-paginated-table/server-paginated-table.component.html +++ b/web-admin-app/src/app/shared/components/server-paginated-table/server-paginated-table.component.html @@ -90,7 +90,7 @@ } } @if (options.operate.length > 0) { - 操作 + 操作 } @if (options.columns.length > 3) { @@ -142,26 +142,24 @@ @if (options.operate.length > 0) { - - -
      - @for (operate of options.operate; track operate.title) { - @if (operate?.visible(data)) { -
    • - {{ operate.title }} -
    • - } + + + + + + @for (operate of options.operate; track operate.title) { + @if (operate?.visible(data)) { + + {{ operate.title }} + } -
    -
    + } + } @if (options.columns.length > 3) { diff --git a/web-admin-app/src/app/utils/index.ts b/web-admin-app/src/app/utils/index.ts index 156beb2..ce4acc7 100644 --- a/web-admin-app/src/app/utils/index.ts +++ b/web-admin-app/src/app/utils/index.ts @@ -98,6 +98,7 @@ export class Utils { } static downLoadFile(response: HttpResponse, type: string, ext: string = 'pdf') { const fileNameFromHeader = response.headers.get('Content-Disposition') + console.log('fileNameFromHeader', fileNameFromHeader) let fileName = '' if (fileNameFromHeader) { fileName = fileNameFromHeader.trim().split('=')[1].replace(/"/g, '') diff --git a/web-admin-app/src/assets/data-vis/fonts/icomoon.css b/web-admin-app/src/assets/data-vis/fonts/icomoon.css new file mode 100644 index 0000000..4fd4f97 --- /dev/null +++ b/web-admin-app/src/assets/data-vis/fonts/icomoon.css @@ -0,0 +1,62 @@ +@font-face { + font-family: 'icomoon'; + src: url('icomoon.eot'); + src: url('icomoon.eot#iefix') format('embedded-opentype'), + url('icomoon.ttf') format('truetype'), + url('icomoon.woff') format('woff'), + url('icomoon.svg#icomoon') format('svg'); + font-weight: normal; + font-style: normal; +} + +[class^="icon-"], [class*=" icon-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'icomoon' !important; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-dot:before { + content: "\e900"; +} +.icon-cup1:before { + content: "\e901"; +} +.icon-cup2:before { + content: "\e902"; +} +.icon-cup3:before { + content: "\e903"; +} +.icon-clock:before { + content: "\e904"; +} +.icon-down:before { + content: "\e905"; +} +.icon-cube:before { + content: "\e906"; +} +.icon-plane:before { + content: "\e907"; +} +.icon-train:before { + content: "\e908"; +} +.icon-bus:before { + content: "\e909"; +} +.icon-bag:before { + content: "\e90a"; +} +.icon-up:before { + content: "\e90b"; +} diff --git a/web-admin-app/src/assets/data-vis/fonts/icomoon.eot b/web-admin-app/src/assets/data-vis/fonts/icomoon.eot new file mode 100644 index 0000000..80633f0 Binary files /dev/null and b/web-admin-app/src/assets/data-vis/fonts/icomoon.eot differ diff --git a/web-admin-app/src/assets/data-vis/fonts/icomoon.svg b/web-admin-app/src/assets/data-vis/fonts/icomoon.svg new file mode 100644 index 0000000..65855b0 --- /dev/null +++ b/web-admin-app/src/assets/data-vis/fonts/icomoon.svg @@ -0,0 +1,22 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web-admin-app/src/assets/data-vis/fonts/icomoon.ttf b/web-admin-app/src/assets/data-vis/fonts/icomoon.ttf new file mode 100644 index 0000000..68a6c8d Binary files /dev/null and b/web-admin-app/src/assets/data-vis/fonts/icomoon.ttf differ diff --git a/web-admin-app/src/assets/data-vis/fonts/icomoon.woff b/web-admin-app/src/assets/data-vis/fonts/icomoon.woff new file mode 100644 index 0000000..eb9298a Binary files /dev/null and b/web-admin-app/src/assets/data-vis/fonts/icomoon.woff differ diff --git a/web-admin-app/src/assets/data-vis/images/border.png b/web-admin-app/src/assets/data-vis/images/border.png new file mode 100644 index 0000000..b854cea Binary files /dev/null and b/web-admin-app/src/assets/data-vis/images/border.png differ diff --git a/web-admin-app/src/assets/data-vis/images/line.png b/web-admin-app/src/assets/data-vis/images/line.png new file mode 100644 index 0000000..34e99ac Binary files /dev/null and b/web-admin-app/src/assets/data-vis/images/line.png differ diff --git a/web-admin-app/src/assets/data-vis/images/logo.png b/web-admin-app/src/assets/data-vis/images/logo.png new file mode 100644 index 0000000..eeab725 Binary files /dev/null and b/web-admin-app/src/assets/data-vis/images/logo.png differ diff --git a/web-admin-app/src/assets/data-vis/images/rect.png b/web-admin-app/src/assets/data-vis/images/rect.png new file mode 100644 index 0000000..6c0ebf0 Binary files /dev/null and b/web-admin-app/src/assets/data-vis/images/rect.png differ diff --git a/web-admin-app/src/assets/data-vis/images/更多内容关注公众号.gif b/web-admin-app/src/assets/data-vis/images/更多内容关注公众号.gif new file mode 100644 index 0000000..f2951f1 Binary files /dev/null and b/web-admin-app/src/assets/data-vis/images/更多内容关注公众号.gif differ diff --git a/web-admin-app/src/assets/images/data-vis/fonts/icomoon.css b/web-admin-app/src/assets/images/data-vis/fonts/icomoon.css new file mode 100644 index 0000000..4fd4f97 --- /dev/null +++ b/web-admin-app/src/assets/images/data-vis/fonts/icomoon.css @@ -0,0 +1,62 @@ +@font-face { + font-family: 'icomoon'; + src: url('icomoon.eot'); + src: url('icomoon.eot#iefix') format('embedded-opentype'), + url('icomoon.ttf') format('truetype'), + url('icomoon.woff') format('woff'), + url('icomoon.svg#icomoon') format('svg'); + font-weight: normal; + font-style: normal; +} + +[class^="icon-"], [class*=" icon-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'icomoon' !important; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-dot:before { + content: "\e900"; +} +.icon-cup1:before { + content: "\e901"; +} +.icon-cup2:before { + content: "\e902"; +} +.icon-cup3:before { + content: "\e903"; +} +.icon-clock:before { + content: "\e904"; +} +.icon-down:before { + content: "\e905"; +} +.icon-cube:before { + content: "\e906"; +} +.icon-plane:before { + content: "\e907"; +} +.icon-train:before { + content: "\e908"; +} +.icon-bus:before { + content: "\e909"; +} +.icon-bag:before { + content: "\e90a"; +} +.icon-up:before { + content: "\e90b"; +} diff --git a/web-admin-app/src/assets/images/data-vis/fonts/icomoon.eot b/web-admin-app/src/assets/images/data-vis/fonts/icomoon.eot new file mode 100644 index 0000000..80633f0 Binary files /dev/null and b/web-admin-app/src/assets/images/data-vis/fonts/icomoon.eot differ diff --git a/web-admin-app/src/assets/images/data-vis/fonts/icomoon.svg b/web-admin-app/src/assets/images/data-vis/fonts/icomoon.svg new file mode 100644 index 0000000..65855b0 --- /dev/null +++ b/web-admin-app/src/assets/images/data-vis/fonts/icomoon.svg @@ -0,0 +1,22 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web-admin-app/src/assets/images/data-vis/fonts/icomoon.ttf b/web-admin-app/src/assets/images/data-vis/fonts/icomoon.ttf new file mode 100644 index 0000000..68a6c8d Binary files /dev/null and b/web-admin-app/src/assets/images/data-vis/fonts/icomoon.ttf differ diff --git a/web-admin-app/src/assets/images/data-vis/fonts/icomoon.woff b/web-admin-app/src/assets/images/data-vis/fonts/icomoon.woff new file mode 100644 index 0000000..eb9298a Binary files /dev/null and b/web-admin-app/src/assets/images/data-vis/fonts/icomoon.woff differ diff --git a/web-admin-app/src/assets/images/data-vis/images/border.png b/web-admin-app/src/assets/images/data-vis/images/border.png new file mode 100644 index 0000000..b854cea Binary files /dev/null and b/web-admin-app/src/assets/images/data-vis/images/border.png differ diff --git a/web-admin-app/src/assets/images/data-vis/images/line.png b/web-admin-app/src/assets/images/data-vis/images/line.png new file mode 100644 index 0000000..34e99ac Binary files /dev/null and b/web-admin-app/src/assets/images/data-vis/images/line.png differ diff --git a/web-admin-app/src/assets/images/data-vis/images/logo.png b/web-admin-app/src/assets/images/data-vis/images/logo.png new file mode 100644 index 0000000..18fcfaa Binary files /dev/null and b/web-admin-app/src/assets/images/data-vis/images/logo.png differ diff --git a/web-admin-app/src/assets/images/data-vis/images/rect.png b/web-admin-app/src/assets/images/data-vis/images/rect.png new file mode 100644 index 0000000..6c0ebf0 Binary files /dev/null and b/web-admin-app/src/assets/images/data-vis/images/rect.png differ diff --git a/web-admin-app/src/assets/images/data-vis/images/更多内容关注公众号.gif b/web-admin-app/src/assets/images/data-vis/images/更多内容关注公众号.gif new file mode 100644 index 0000000..f2951f1 Binary files /dev/null and b/web-admin-app/src/assets/images/data-vis/images/更多内容关注公众号.gif differ