Angular BaseView抽离页面公用属性

前言

如果有一系列的页面布局很类似,为了节省时间,我们可以把这些类似的页面所通用的属性和方法抽离成一个BaseView,让其它页面继承该基础页面,同时将一些经常改变的属性和差异的属性写到配置文件里。例如树容器初始时是否展开、某些图表是否显示等都可以写到配置文件里面。本文将带你实现该功能,抽离出BaseView页面组件,鉴于json文件无法写注释的情况,配置文件采取yml的格式

页面设计

在这里插入图片描述

组件抽离

BaseViewComponent

import { Injectable, OnDestroy, OnInit } from "@angular/core";import { ConfigService } from "@app/core/config/config.service";
import { Subject } from "rxjs";
import { takeUntil } from "rxjs/operators";
import { deepMergeKey } from "../utils";
import { HandlebarCalendarModelType } from "./baseView.type";
import { TimeRange } from "topdsm-lib/core/util"import dayjs from 'dayjs';
var customParseFormat = require('dayjs/plugin/advancedFormat')@Injectable()
export class BaseViewComponent implements OnInit, OnDestroy {/** 页面通用属性 */pageNum = 1pageSize = 10tableData = []tableTotal = 0public unsubscribe$ = new Subject<void>();/** 原始config */public originalConfig: Record<string, any> = null/** 页面config */public config: Record<string, any> = {leftPanelExpand: true,handlebarCalendarModel: [],query: {}}constructor(public viewKey: string, // 页面唯一keypublic configService: ConfigService // 用来读取json配置文件) {console.log("BaseViewComponent constructor");}ngOnInit(): void {console.log();this.configService.change.pipe(takeUntil(this.unsubscribe$)).subscribe(async (config) => {console.log(config);if (config) {this.originalConfig = configif (this['configServiceReaderBefore']) {await this['configServiceReaderBefore'](config)}this.handleConfig()if (this['configServiceReaderAfter']) {await this['configServiceReaderAfter'](config)}}});}ngOnDestroy(): void {const { unsubscribe$ } = this;unsubscribe$.next();unsubscribe$.complete();}handleConfig() {deepMergeKey(this.config, true, this.originalConfig.global, this.originalConfig?.modules?.[this.viewKey])this.handleCalendarTime()this.handleBarBtn()console.log(this.config);}/*** handlebar 日历组件初始值处理,* 获取开始时间和结束时间,该逻辑可以根据自己的业务场景自定义*/handleCalendarTime() {let tg = {start: "",end: ""}switch (this.config.handlebarCalendarModelType) {case HandlebarCalendarModelType.CUSTOM:if (this.config.handlebarCalendarModel.length === 1) {tg.start = this.config.handlebarCalendarModel[0]tg.end = dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss").substring(0, 10) + " 23:59:59"} else if (this.config.handlebarCalendarModel.length === 2) {tg.start = this.config.handlebarCalendarModel[0]tg.end = this.config.handlebarCalendarModel[1]}break;case HandlebarCalendarModelType.LASTYEAY: // 上一年tg = TimeRange.getLastYearRange()break;case HandlebarCalendarModelType.LASTQUATER: // 上一季度tg = TimeRange.getLastQuarterRange()break;case HandlebarCalendarModelType.LASTMONTH: // 上一月tg = TimeRange.getLastMonthRange()break;case HandlebarCalendarModelType.LAST7DAY: // 近7天tg = {start: TimeRange.getLast7dayRange().start,end: dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss").substring(0, 10) + " 23:59:59"}break;case HandlebarCalendarModelType.MONTH: // 本月tg = TimeRange.getMonthRange()break;case HandlebarCalendarModelType.QUATER: // 本年度tg = TimeRange.getQuarterRange()break;case HandlebarCalendarModelType.YEAR: // 本年度tg = TimeRange.getYearRange()break;default:break;}if (tg.start !== "" && tg.end !== "") {tg.start = tg.start.substring(0, 10) + " 00:00:00"tg.end = tg.end.substring(0, 10) + " 23:59:59"}this.config.query.startTimeStr = tg.startthis.config.query.endTimeStr = tg.endif (tg.start !== "" && tg.end !== "") {this.config.handlebarCalendarModel = [dayjs(this.config.query.startTimeStr, "YYYY-MM-DD HH:mm:ss").toDate(),dayjs(this.config.query.endTimeStr, "YYYY-MM-DD HH:mm:ss").toDate(),]} else {this.config.handlebarCalendarModel = []}}handleBarBtn() {let btnSelected = {}this.config.handlebarRightBtn = this.config.handlebarRightBtn.filter(item => item.show)this.config.handlebarRightBtn.forEach(item => {btnSelected[item.key] = item.selected})this.config.handlebarRightBtnSelected = btnSelected}
}

时间段枚举

export enum HandlebarCalendarModelType {/** 自定义 */CUSTOM = "0",/** 上一年 */LASTYEAY = "1",/** 上一季度 */LASTQUATER = "2",/** 上一月 */LASTMONTH = "3",/** 上一周 */LASTWEEK = "4",/** 本周 */WEEK = "5",/** 本月 */MONTH = "6",/** 本季度 */QUATER = "7",/** 本年度 */YEAR = "8",/** 近7天 */LAST7DAY = "9"
}

属性合并的函数


/*** Deep merge object.** 深度合并对象** @param original 原始对象* @param arrayProcessMethod 数组处理方式*  - `true` 表示替换新值,不管新值为哪种类型*  - `false` 表示会合并整个数组(将旧数据与新数据合并成新数组)* @param objects 要合并的对象*/export function deepMergeKey(original: unknown, arrayProcessMethod: boolean, ...objects: NzSafeAny[]): NzSafeAny {if (Array.isArray(original) || typeof original !== 'object') return original;const isObject = (v: unknown): boolean => typeof v === 'object';const merge = (target: NzSafeAny, obj: NzSafeAny): NzSafeAny => {Object.keys(obj).filter(key => key !== '__proto__' && Object.prototype.hasOwnProperty.call(obj, key)).forEach(key => {const fromValue = obj[key];const toValue = target[key];if (Array.isArray(toValue)) {target[key] = arrayProcessMethod ? fromValue : [...toValue, ...fromValue];} else if (typeof fromValue === 'function') {target[key] = fromValue;} else if (fromValue != null && isObject(fromValue) && toValue != null && isObject(toValue)) {target[key] = merge(toValue, fromValue);} else {target[key] = deepCopy(fromValue);}});return target;};objects.filter(v => v != null && isObject(v)).forEach(v => merge(original, v));return original;
}

ConfigService

读取yml配置文件

import { Injectable } from "@angular/core";
import { environment } from "@env/environment";
import { BehaviorSubject, Observable } from "rxjs";
import yaml from "js-yaml"
import axios from "axios"
@Injectable({providedIn: 'root'
})
export class ConfigService {private change$ = new BehaviorSubject(null);constructor() {this.getGlobalConfig()}get change(): Observable<any> {return this.change$.asObservable();}getGlobalConfig() {return new Promise((resolve, reject) => {let url = "/assets/config.yml"if(environment.production){url = environment.assetBaseUrl + "/assets/config.yml"}axios.get(url).then(res => {const config = yaml.load(res.data)this.change$.next(config);             }).catch(err => {reject(err)})})}
}

config.yml

global: handlebarCalendarModelType: "0"handlebarCalendarModel: - "2023-01-01 00:00:00"leftPanelWidth: "200px" # 左侧树容器宽度leftPanelExpand: true   # 左侧容器初始是否展开 true: 展开  false: 收起handlebarRight: true # 是否展示 handlebar右侧的操作按钮handlebarRightBtn: # hanlebar右侧操作按钮 控制图标统计区域的显示与否- selected: true      # 是否选中show: true          # 是否显示label: "总量统计"icon: "icon-proxy"key: "cardNumStatis" # 每个按钮都应该有唯一的key- selected: trueshow: truelabel: "对比统计"icon: "icon-pie1"key: "pieAndBar"- selected: trueshow: falselabel: "趋势统计"icon: "icon-pie1"key: "lineTrend"barStyleConfig:grid: bottom: 30xAxis:axisLabel: width: 80modules: demoPage: leftPanelExpand: truebarStyleConfig:grid: bottom: 45xAxis:axisLabel:overflow: "truncate" # 截断rotate: 330  # 旋转度数

demo

demo-component.ts

import { Component, OnDestroy, OnInit, ViewChild } from "@angular/core";
import { ActivatedRoute, NavigationEnd, Router, RouterEvent } from "@angular/router";
import { BaseViewComponent } from "@app/core/config/base-view.component";
import { ConfigService } from "@app/core/config/config.service";
import { DEMOPAGE } from "@app/core/config/view-key";
import { removeNullProperty } from "@app/core/utils";
import { AccountAssetService } from "@app/services/data-asset-management/account-asset/account-asset.service";
import { format } from "date-fns";@Component({selector: 'app-demo',templateUrl: './demo.component.html',styleUrls: ['./demo.component.less']
})
export class DemoComponent extends BaseViewComponent {q = {}constructor(private router: Router,public activatedRoute: ActivatedRoute,public configService: ConfigService,private apiService: AccountAssetService,) {super(DEMOPAGE, configService)console.log("DemoComponent constructor");}ngOnInit(): void {console.log("DemoComponent ngOnInit");super.ngOnInit()}ngOnDestroy(): void {console.log("DemoComponent ngOnDestroy");super.ngOnDestroy()}configServiceReaderAfter(config) {console.log("configServiceReaderAfter...");return new Promise(async (resolve, reject) => {this.refsh()resolve(null)})}async refsh() {//await this.getAccountTypeTreeL1()if (this.config.handlebarRight) {this.getPieChart1Data()this.getPieChart2Data()this.getBarChartData()this.getAccountCard()}this.getData()}getAccountCard() {}getPieChart1Data() {}getPieChart2Data() {}getBarChartData() {}getData() {let params: { [key: string]: any } = {...this.q,pageNum: this.pageNum,pageSize: this.pageSize,}if (this.config.handlebarRight) {params.startTimeStr = this.config.query.startTimeStrparams.endTimeStr = this.config.query.endTimeStr}this.apiService.getAccountListByPageApi(removeNullProperty(params)).then((res: resType) => {if (res.resultStat == "0") {this.tableData = res.data.listthis.tableTotal = res.data.total}})}/** handlebar 操作栏 */handleChange(e: any) {console.log(e);if(e.type === "button"){this.config.handlebarRightBtnSelected[e.data.key] = e.data.selected}else if(e.type === "calendar"){if(e.data.length === 2){this.config.query = {startTimeStr: format(e.data[0], 'yyyy-MM-dd HH:mm:ss').substring(0,10)+ " 00:00:00",endTimeStr: format(e.data[1], 'yyyy-MM-dd HH:mm:ss').substring(0,10)+ " 23:59:59",}}else{this.config.query = {startTimeStr: "",endTimeStr: ""}}this.refsh()}}}

合并后的配置对象config

{"leftPanelExpand": true,"handlebarCalendarModel": ["2022-12-31T16:00:00.000Z","2024-02-04T15:59:59.000Z"],"query": {"startTimeStr": "2023-01-01 00:00:00","endTimeStr": "2024-02-04 23:59:59"},"handlebarCalendarModelType": "0","leftPanelWidth": "200px","handlebarRight": true,"handlebarRightBtn": [{"selected": true,"show": true,"label": "总量统计","icon": "icon-proxy","key": "cardNumStatis"},{"selected": true,"show": true,"label": "对比统计","icon": "icon-pie1","key": "pieAndBar"}],"barStyleConfig": {"grid": {"bottom": 45},"xAxis": {"axisLabel": {"width": 80,"overflow": "truncate","rotate": 330}}},"handlebarRightBtnSelected": {"cardNumStatis": true,"pieAndBar": true}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/253685.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习 Redis 基础数据结构,不讲虚的。

学习 Redis 基础数据结构&#xff0c;不讲虚的。 一个群友给我发消息&#xff0c;“该学的都学了&#xff0c;怎么就找不到心意的工作&#xff0c;太难了”。 很多在近期找过工作的同学一定都知道了&#xff0c;背诵八股文已经不是找工作的绝对王牌。企业最终要的是可以创造价…

免费生成ios证书的方法(无需mac电脑)

使用hbuilderx的uniapp框架开发移动端程序很方便&#xff0c;可以很方便地开发出移动端的小程序和app。但是打包ios版本的app的时候却很麻烦&#xff0c;官方提供的教程需要使用mac电脑来生成证书&#xff0c;但是mac电脑却不便宜&#xff0c;一般的型号都差不多上万。 因此&a…

Quicker读取浏览器的书签(包括firefox火狐)

从edge换了火狐&#xff0c;但是quicker不能读取本地的bookmarks文件了&#xff0c;就研究了一下。 方法1&#xff1a;读取本地Bookmarks文件&#xff08;仅谷歌内核浏览器&#xff09; 谷歌内核的浏览器本地会有Bookmarks文件&#xff0c;放了所有的书签数据&#xff0c;直接…

泰克示波器(TBS2000系列)数学运算功能使用

目录 1 数学运算菜单1.1 运算符选择1.2 信源选择1.3 数学运算结果 1 数学运算菜单 Math运算按钮&#xff0c;用于实现对两个通道的信号进行实时的“加、减、乘”运算&#xff0c;计算时信源1在前面&#xff0c;信源2在运算符的右边&#xff0c;设置时设置信源与运算符就行了。…

HCIA-HarmonyOS设备开发认证V2.0-3.轻量系统内核基础

目录 一、前言二、LiteOS-M系统概述三、内核框架3.1、CMSIS 和 POSIX 整体架构3.2、LiteOS-M内核启动流程 四、内核基础4.1、任务管理4.2、时间管理(待续)4.3、中断管理(待续)4.4、软件定时器(待续) 五、内存管理5.1、静态内存(待续)5.2、动态内存(待续) 六、内核通信机制6.1、…

CentOS镜像如何下载?在VMware中如何安装?

一、问题 CentOS镜像如何下载&#xff1f;在VMware中如何安装&#xff1f; 二、解决 1、CentOS镜像的下载 &#xff08;1&#xff09;官方网站 The CentOS Project &#xff08;2&#xff09;官方中文官网 CentOS 中文 官网 &#xff08;3&#xff09;选择CentOS Linux…

16.docker删除redis缓存数据、redis常用基本命令

1.进入redis容器内部 &#xff08;1&#xff09;筛选过滤出redis容器 docker ps | grep "redis"&#xff08;2&#xff09;进入redis容器 #说明&#xff1a;d24为redis容器iddocker exec -it d24 /bin/bash2.登陆redis (1) 进入redis命令行界面 redis-cli说明&a…

备战蓝桥杯---搜索(进阶1)

话不多说&#xff0c;直接看题&#xff1a; 没有传送带时&#xff0c;我们可以直接BFS&#xff0c;但因为传送带的出现&#xff0c;可能在队列里的元素到起点时间不单调的问题&#xff0c;而BFS本来就是可以看成随着时间推移而产生的情况&#xff0c;于是我们把队列看成优先队列…

黑马程序员——html css基础——day09——CSS高级

目录&#xff1a; 定位 相对定位&#xff1a;绝对定位定位居中固定定位堆叠层级z-index高级技巧 CSS精灵案例-写出自己的名字字体图标下载字体使用字体CSS修饰属性 垂直对齐方式过渡表单获得焦点选择器focus透明度opacity光标类型cursor禁用鼠标样式表格样式-合并相邻两个边框…

Redis篇之分布式锁

一、为什么要使用分布式锁 1.抢劵场景 &#xff08;1&#xff09;代码及流程图 &#xff08;2&#xff09;抢劵执行的正常流程 就是正好线程1执行完整个操作&#xff0c;线程2再执行。 &#xff08;3&#xff09;抢劵执行的非正常流程 因为线程是交替进行的&#xff0c;所以有…

Vagrant 虚拟机工具基本操作指南

Vagrant 虚拟机工具基本操作指南 ​#虚拟机 #​ ​#vargant#​ ​#ubuntu#​ ‍ 虚拟机virtualbox ,VMWare及WSL等大家都很了解了&#xff0c;那Vagrant是什么东西&#xff1f; 它是一组命令行工具&#xff0c;可以象Docker管理容器一样管理虚拟机&#xff0c;这样快速创…

Java代码实现基数排序算法(附带源码)

基数排序是一种非比较型整数排序算法&#xff0c;其原理是将整数按位数切割成不同的数字&#xff0c;然后按每个位数分别比较。由于整数也可以表达字符串&#xff08;比如名字或日期&#xff09;和特定格式的浮点数&#xff0c;所以基数排序也不是只能使用于整数。 1. 基数排序…

缓存组件Caffeine的使用

caffeine是一个高性能的缓存组件&#xff0c;在需要缓存数据&#xff0c;但数据量不算太大&#xff0c;不想引入redis的时候&#xff0c;caffeine就是一个不错的选择。可以把caffeine理解为一个简单的redis。 1、导入依赖 <!-- https://mvnrepository.com/artifact/com.git…

Sublime Text 3配置 Node.js 开发环境

《开发工具系列》 Sublime Text 3配置 Node.js 开发环境 一、引言二、主要内容2.1 初识 Sublime Text 32.2 初识 Node.js2.3 接入 Node.js2.3.1 下载并安装 Node.js2.3.2 环境变量配置 2.4 配置 Node.js 开发环境2.5 编写 Node.js 代码2.6 运行 Node.js 代码 三、总结 一、引言…

网站服务器中毒或是被入侵该怎么办?

随着互联网的普及和发展&#xff0c;网站服务器已经成为企业和个人不可或缺的资源。然而&#xff0c;网络安全问题也日益突出&#xff0c;其中服务器中毒或被入侵是常见的问题之一。一旦服务器中毒或被入侵&#xff0c;不仅会导致数据泄露、网站瘫痪等严重后果&#xff0c;还可…

Ubuntu22.04切换系统cuda版本

由于最近项目要求的cuda版本有差异&#xff0c;而在Ubuntu中可以通过切换cuda来满足需求&#xff0c;现记录如下。 1、按照 Ubuntu22.04与深度学习配置 中的cuda安装章节&#xff0c;将需要的cuda版本下载到本地并进行安装。 2、cuda安装完成后修改bashrc文件内容 sudo gedit …

2024 Google Chrome 浏览器回退安装旧版本

2024 Google Chrome 浏览器回退安装旧版本 查看当前谷歌版本备份浏览器数据卸载浏览器双击重新安装旧版本浏览器 查看当前谷歌版本 详细参考&#xff1a;参考 笔记&#xff1a;最近谷歌浏览器更新后&#xff0c;用着总感觉别扭&#xff1a;不习惯 备份浏览器数据 &#xff…

MySQL ——group by子句使用with rollup

group by 子句使用with rollup关键字之后&#xff0c;具有分组加和的功能。即&#xff1a;在所有的分组记录之后&#xff0c;自动新增一条记录&#xff0c;从全局计算所有记录的数据。 0 问题描述 求出每年的学生平均成绩&#xff0c;及历史至今的平均成绩&#xff0c;结果保留…

高可用 k8s 1.29 一键安装脚本, 丝滑至极

博客原文 文章目录 集群配置配置清单集群规划集群网络规划 环境初始化主机配置 配置高可用ApiServer安装 nginx安装 Keepalived 安装脚本需要魔法的脚本不需要魔法的脚本配置自动补全加入其余节点 验证集群 集群配置 配置清单 OS&#xff1a; ubuntu 20.04kubernetes&#xf…

C++三剑客之std::any(一) : 使用

相关系列文章 C三剑客之std::any(一) : 使用 C之std::tuple(一) : 使用精讲(全) C三剑客之std::variant(一) : 使用 C三剑客之std::variant(二)&#xff1a;深入剖析​​​​​​​ 目录 1.概述 2.构建方式 2.1.构造函数 2.2.std::make_any 2.3.operator分配新值 3.访问值…