diff --git a/src/app/routes/datatable/components/customtable/customindex/customindex.component.html b/src/app/routes/datatable/components/customtable/customindex/customindex.component.html
new file mode 100644
index 00000000..56092666
--- /dev/null
+++ b/src/app/routes/datatable/components/customtable/customindex/customindex.component.html
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/app/routes/datatable/components/customtable/customindex/customindex.component.spec.ts b/src/app/routes/datatable/components/customtable/customindex/customindex.component.spec.ts
new file mode 100644
index 00000000..09bf44a2
--- /dev/null
+++ b/src/app/routes/datatable/components/customtable/customindex/customindex.component.spec.ts
@@ -0,0 +1,24 @@
+import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
+import { DatatableCustomindexComponent } from './customindex.component';
+
+describe('DatatableCustomindexComponent', () => {
+ let component: DatatableCustomindexComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [ DatatableCustomindexComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DatatableCustomindexComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/routes/datatable/components/customtable/customindex/customindex.component.ts b/src/app/routes/datatable/components/customtable/customindex/customindex.component.ts
new file mode 100644
index 00000000..7e720e39
--- /dev/null
+++ b/src/app/routes/datatable/components/customtable/customindex/customindex.component.ts
@@ -0,0 +1,45 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { STColumn, STComponent } from '@delon/abc/st';
+import { SFSchema } from '@delon/form';
+import { ModalHelper, _HttpClient } from '@delon/theme';
+
+@Component({
+ selector: 'app-datatable-customindex',
+ templateUrl: './customindex.component.html',
+})
+export class DatatableCustomindexComponent implements OnInit {
+ url = `/user`;
+ searchSchema: SFSchema = {
+ properties: {
+ no: {
+ type: 'string',
+ title: '编号'
+ }
+ }
+ };
+ @ViewChild('st') private readonly st!: STComponent;
+ columns: STColumn[] = [
+ { title: '编号', index: 'no' },
+ { title: '调用次数', type: 'number', index: 'callNo' },
+ { title: '头像', type: 'img', width: '50px', index: 'avatar' },
+ { title: '时间', type: 'date', index: 'updatedAt' },
+ {
+ title: '',
+ buttons: [
+ // { text: '查看', click: (item: any) => `/form/${item.id}` },
+ // { text: '编辑', type: 'static', component: FormEditComponent, click: 'reload' },
+ ]
+ }
+ ];
+
+ constructor(private http: _HttpClient, private modal: ModalHelper) { }
+
+ ngOnInit(): void { }
+
+ add(): void {
+ // this.modal
+ // .createStatic(FormEditComponent, { i: { id: 0 } })
+ // .subscribe(() => this.st.reload());
+ }
+
+}
diff --git a/src/app/routes/datatable/components/customtable/customtable.component.html b/src/app/routes/datatable/components/customtable/customtable.component.html
new file mode 100644
index 00000000..56092666
--- /dev/null
+++ b/src/app/routes/datatable/components/customtable/customtable.component.html
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/app/routes/datatable/components/customtable/customtable.component.spec.ts b/src/app/routes/datatable/components/customtable/customtable.component.spec.ts
new file mode 100644
index 00000000..980fc9d9
--- /dev/null
+++ b/src/app/routes/datatable/components/customtable/customtable.component.spec.ts
@@ -0,0 +1,24 @@
+import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
+import { DatatableCustomtableComponent } from './customtable.component';
+
+describe('DatatableCustomtableComponent', () => {
+ let component: DatatableCustomtableComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [ DatatableCustomtableComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DatatableCustomtableComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/routes/datatable/components/customtable/customtable.component.ts b/src/app/routes/datatable/components/customtable/customtable.component.ts
new file mode 100644
index 00000000..292a9c25
--- /dev/null
+++ b/src/app/routes/datatable/components/customtable/customtable.component.ts
@@ -0,0 +1,45 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { STColumn, STComponent } from '@delon/abc/st';
+import { SFSchema } from '@delon/form';
+import { ModalHelper, _HttpClient } from '@delon/theme';
+
+@Component({
+ selector: 'app-datatable-customtable',
+ templateUrl: './customtable.component.html',
+})
+export class DatatableCustomtableComponent implements OnInit {
+ url = `/user`;
+ searchSchema: SFSchema = {
+ properties: {
+ no: {
+ type: 'string',
+ title: '编号'
+ }
+ }
+ };
+ @ViewChild('st') private readonly st!: STComponent;
+ columns: STColumn[] = [
+ { title: '编号', index: 'no' },
+ { title: '调用次数', type: 'number', index: 'callNo' },
+ { title: '头像', type: 'img', width: '50px', index: 'avatar' },
+ { title: '时间', type: 'date', index: 'updatedAt' },
+ {
+ title: '',
+ buttons: [
+ // { text: '查看', click: (item: any) => `/form/${item.id}` },
+ // { text: '编辑', type: 'static', component: FormEditComponent, click: 'reload' },
+ ]
+ }
+ ];
+
+ constructor(private http: _HttpClient, private modal: ModalHelper) { }
+
+ ngOnInit(): void { }
+
+ add(): void {
+ // this.modal
+ // .createStatic(FormEditComponent, { i: { id: 0 } })
+ // .subscribe(() => this.st.reload());
+ }
+
+}
diff --git a/src/app/routes/datatable/components/customtable/driver/driver.component.html b/src/app/routes/datatable/components/customtable/driver/driver.component.html
new file mode 100644
index 00000000..56092666
--- /dev/null
+++ b/src/app/routes/datatable/components/customtable/driver/driver.component.html
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/app/routes/datatable/components/customtable/driver/driver.component.spec.ts b/src/app/routes/datatable/components/customtable/driver/driver.component.spec.ts
new file mode 100644
index 00000000..6a2084a2
--- /dev/null
+++ b/src/app/routes/datatable/components/customtable/driver/driver.component.spec.ts
@@ -0,0 +1,24 @@
+import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
+import { DatatableDriverComponent } from './driver.component';
+
+describe('DatatableDriverComponent', () => {
+ let component: DatatableDriverComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [ DatatableDriverComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DatatableDriverComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/routes/datatable/components/customtable/driver/driver.component.ts b/src/app/routes/datatable/components/customtable/driver/driver.component.ts
new file mode 100644
index 00000000..f27f6788
--- /dev/null
+++ b/src/app/routes/datatable/components/customtable/driver/driver.component.ts
@@ -0,0 +1,45 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { STColumn, STComponent } from '@delon/abc/st';
+import { SFSchema } from '@delon/form';
+import { ModalHelper, _HttpClient } from '@delon/theme';
+
+@Component({
+ selector: 'app-datatable-driver',
+ templateUrl: './driver.component.html',
+})
+export class DatatableDriverComponent implements OnInit {
+ url = `/user`;
+ searchSchema: SFSchema = {
+ properties: {
+ no: {
+ type: 'string',
+ title: '编号'
+ }
+ }
+ };
+ @ViewChild('st') private readonly st!: STComponent;
+ columns: STColumn[] = [
+ { title: '编号', index: 'no' },
+ { title: '调用次数', type: 'number', index: 'callNo' },
+ { title: '头像', type: 'img', width: '50px', index: 'avatar' },
+ { title: '时间', type: 'date', index: 'updatedAt' },
+ {
+ title: '',
+ buttons: [
+ // { text: '查看', click: (item: any) => `/form/${item.id}` },
+ // { text: '编辑', type: 'static', component: FormEditComponent, click: 'reload' },
+ ]
+ }
+ ];
+
+ constructor(private http: _HttpClient, private modal: ModalHelper) { }
+
+ ngOnInit(): void { }
+
+ add(): void {
+ // this.modal
+ // .createStatic(FormEditComponent, { i: { id: 0 } })
+ // .subscribe(() => this.st.reload());
+ }
+
+}
diff --git a/src/app/routes/datatable/components/customtable/owner/owner.component.html b/src/app/routes/datatable/components/customtable/owner/owner.component.html
new file mode 100644
index 00000000..3a90b91b
--- /dev/null
+++ b/src/app/routes/datatable/components/customtable/owner/owner.component.html
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/src/app/routes/datatable/components/customtable/owner/owner.component.spec.ts b/src/app/routes/datatable/components/customtable/owner/owner.component.spec.ts
new file mode 100644
index 00000000..8c518688
--- /dev/null
+++ b/src/app/routes/datatable/components/customtable/owner/owner.component.spec.ts
@@ -0,0 +1,24 @@
+import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
+import { DatatableOwnerComponent } from './owner.component';
+
+describe('DatatableOwnerComponent', () => {
+ let component: DatatableOwnerComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [ DatatableOwnerComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DatatableOwnerComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/routes/datatable/components/customtable/owner/owner.component.ts b/src/app/routes/datatable/components/customtable/owner/owner.component.ts
new file mode 100644
index 00000000..af6bf032
--- /dev/null
+++ b/src/app/routes/datatable/components/customtable/owner/owner.component.ts
@@ -0,0 +1,45 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { STColumn, STComponent } from '@delon/abc/st';
+import { SFSchema } from '@delon/form';
+import { ModalHelper, _HttpClient } from '@delon/theme';
+
+@Component({
+ selector: 'app-datatable-owner',
+ templateUrl: './owner.component.html',
+})
+export class DatatableOwnerComponent implements OnInit {
+ url = `/user`;
+ searchSchema: SFSchema = {
+ properties: {
+ no: {
+ type: 'string',
+ title: '编号'
+ }
+ }
+ };
+ @ViewChild('st') private readonly st!: STComponent;
+ columns: STColumn[] = [
+ { title: '编号', index: 'no' },
+ { title: '调用次数', type: 'number', index: 'callNo' },
+ { title: '头像', type: 'img', width: '50px', index: 'avatar' },
+ { title: '时间', type: 'date', index: 'updatedAt' },
+ {
+ title: '',
+ buttons: [
+ // { text: '查看', click: (item: any) => `/form/${item.id}` },
+ // { text: '编辑', type: 'static', component: FormEditComponent, click: 'reload' },
+ ]
+ }
+ ];
+
+ constructor(private http: _HttpClient, private modal: ModalHelper) { }
+
+ ngOnInit(): void { }
+
+ add(): void {
+ // this.modal
+ // .createStatic(FormEditComponent, { i: { id: 0 } })
+ // .subscribe(() => this.st.reload());
+ }
+
+}
diff --git a/src/app/routes/datatable/components/dataindex/dataindex.component.html b/src/app/routes/datatable/components/dataindex/dataindex.component.html
new file mode 100644
index 00000000..3f148bfd
--- /dev/null
+++ b/src/app/routes/datatable/components/dataindex/dataindex.component.html
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/routes/datatable/dataindex/dataindex.component.less b/src/app/routes/datatable/components/dataindex/dataindex.component.less
similarity index 100%
rename from src/app/routes/datatable/dataindex/dataindex.component.less
rename to src/app/routes/datatable/components/dataindex/dataindex.component.less
diff --git a/src/app/routes/datatable/dataindex/dataindex.component.spec.ts b/src/app/routes/datatable/components/dataindex/dataindex.component.spec.ts
similarity index 100%
rename from src/app/routes/datatable/dataindex/dataindex.component.spec.ts
rename to src/app/routes/datatable/components/dataindex/dataindex.component.spec.ts
diff --git a/src/app/routes/datatable/components/dataindex/dataindex.component.ts b/src/app/routes/datatable/components/dataindex/dataindex.component.ts
new file mode 100644
index 00000000..0881c73c
--- /dev/null
+++ b/src/app/routes/datatable/components/dataindex/dataindex.component.ts
@@ -0,0 +1,249 @@
+import { Component, ElementRef, NgZone, OnInit, ViewChild } from '@angular/core';
+import { ModalHelper, _HttpClient } from '@delon/theme';
+import { G2MiniAreaClickItem, G2MiniAreaData } from '@delon/chart/mini-area';
+import { G2PieClickItem, G2PieComponent, G2PieData } from '@delon/chart/pie';
+import { format } from 'date-fns';
+import { DataService } from '../../services/data.service';
+import { Chart, registerShape, Util } from '@antv/g2';
+import { G2TimelineClickItem, G2TimelineData } from '@delon/chart/timeline';
+
+@Component({
+ selector: 'app-datatable-dataindex',
+ templateUrl: './dataindex.component.html',
+ styleUrls: ['./dataindex.component.less']
+})
+export class DatatableDataindexComponent implements OnInit {
+ @ViewChild('pie', { static: false }) pie!: G2PieComponent;
+ chartData: G2TimelineData[] = [];
+ visitData = this.genData();
+ salesData = this.genData();
+ salesPieData: G2PieData[] = [];
+ total = '';
+
+ constructor(private service: DataService, private ngZone: NgZone) {
+
+ }
+
+ ngOnInit(): void {
+ this.refreshPie();
+ this.initLineData()
+ }
+ initLineData(){
+ for (let i = 0; i < 20; i += 1) {
+ this.chartData.push({
+ time: new Date().getTime() + 1000 * 60 * 60 * 24 * i,
+ y1: Math.floor(Math.random() * 100) + 1000,
+ y2: Math.floor(Math.random() * 100) + 10,
+ });
+ }
+ }
+ private genData(): G2MiniAreaData[] {
+ const beginDay = new Date().getTime();
+ const res: G2MiniAreaData[] = [];
+ for (let i = 0; i < 20; i += 1) {
+ res.push({
+ x: format(new Date(beginDay + 1000 * 60 * 60 * 24 * i), 'yyyy-MM-dd'),
+ y: Math.floor(Math.random() * 100) + 10,
+ });
+ }
+ return res;
+ }
+
+ refresh(): void {
+ this.visitData = this.genData();
+ }
+ refreshPie(): void {
+ const rv = (min: number = 0, max: number = 5000) => Math.floor(Math.random() * (max - min + 1) + min);
+ this.salesPieData = [
+ {
+ x: '家用电器',
+ y: rv(),
+ },
+ {
+ x: '食用酒水',
+ y: rv(),
+ },
+ {
+ x: '个护健康',
+ y: rv(),
+ },
+ {
+ x: '服饰箱包',
+ y: rv(),
+ },
+ {
+ x: '母婴产品',
+ y: rv(),
+ },
+ ];
+ if (Math.random() > 0.5) {
+ this.salesPieData.push({
+ x: '其他',
+ y: rv(),
+ });
+ }
+ this.total = `¥ ${this.salesPieData.reduce((pre, now) => now.y + pre, 0).toFixed(2)}`;
+ if (this.pie) {
+ // 等待组件渲染
+ setTimeout(() => {
+ console.log('a')
+ this.pie.changeData()
+ });
+ }
+ }
+
+ handleClick(data: G2MiniAreaClickItem): void {
+ this.service.msgSrv.info(`${data.item.x} - ${data.item.y}`);
+ }
+ format(val: number): string {
+ return `¥ ${val.toFixed(2)}`;
+ }
+ render(el: ElementRef): void {
+ this.ngZone.runOutsideAngular(() => this.init(el.nativeElement));
+ }
+ private init(el: HTMLElement): void {
+ const data = [
+ { item: '货源单', count: 40, percent: 0.4 },
+ { item: '合同单', count: 21, percent: 0.21 },
+ { item: '事例三', count: 17, percent: 0.17 },
+ { item: '事例四', count: 13, percent: 0.13 },
+ { item: '事例五', count: 9, percent: 0.09 },
+ ];
+ const chart = new Chart({
+ container: el,
+ autoFit: true,
+ height: 400,
+ });
+ // 新建一个 view 用来单独渲染Annotation
+ const innerView = chart.createView();
+ chart.coordinate('theta', {
+ radius: 0.6,
+ innerRadius: 0.7,
+ });
+
+ chart.data(data);
+
+ chart.scale('percent', {
+ formatter: val => {
+ val = val * 100 + '%';
+ return val;
+ },
+ });
+
+ chart.tooltip(false);
+
+ // 声明需要进行自定义图例字段: 'item'
+ chart.legend('item', {
+ position: 'right', // 配置图例显示位置
+ custom: true, // 关键字段,告诉 G2,要使用自定义的图例
+ items: data.map((obj, index) => {
+ return {
+ name: obj.item, // 对应 itemName
+ value: obj.percent, // 对应 itemValue
+ marker: {
+ symbol: 'square', // marker 的形状
+ style: {
+ r: 5, // marker 图形半径
+ fill: chart.getTheme().colors10[index], // marker 颜色,使用默认颜色,同图形对应
+ },
+ }, // marker 配置
+ };
+ }),
+ itemValue: {
+ style: {
+ fill: '#999',
+ }, // 配置 itemValue 样式
+ formatter: (val: any) => `${val * 100}%` // 格式化 itemValue 内容
+ },
+ });
+
+ chart
+ .interval()
+ .adjust('stack')
+ .position('percent')
+ .color('item')
+ .style({
+ fillOpacity: 1,
+ stroke: 'white',
+ lineWidth: 8,
+ })
+ .state({
+ active: {
+ style: element => {
+ const shape = element.shape;
+ return {
+ lineWidth: 1,
+ stroke: 'white',
+ strokeOpacity: shape.attr('fillOpacity'),
+ };
+ },
+ },
+ });
+
+ // 移除图例点击过滤交互
+ chart.removeInteraction('legend-filter');
+ chart.interaction('element-active');
+
+ chart.render();
+
+ // 监听 element 上状态的变化来动态更新 Annotation 信息
+ chart.on('element:statechange', (ev: any) => {
+ const { state, stateStatus, element } = ev.gEvent.originalEvent;
+
+ // 本示例只需要监听 active 的状态变化
+ if (state === 'active') {
+ const data = element.getData();
+ if (stateStatus) {
+ // 更新 Annotation
+ updateAnnotation(data);
+ } else {
+ // 隐藏 Annotation
+ clearAnnotation();
+ }
+ }
+ });
+
+ // 绘制 annotation
+ let lastItem: any;
+ function updateAnnotation(data: any) {
+ if (data.item !== lastItem) {
+ innerView.annotation().clear(true);
+ innerView
+ .annotation()
+ .text({
+ position: ['50%', '50%'],
+ content: data.item,
+ style: {
+ fontSize: 20,
+ fill: '#8c8c8c',
+ textAlign: 'center',
+ },
+ offsetY: -20,
+ })
+ .text({
+ position: ['50%', '50%'],
+ content: data.count,
+ style: {
+ fontSize: 28,
+ fill: '#8c8c8c',
+ textAlign: 'center',
+ },
+ offsetX: -10,
+ offsetY: 20,
+ })
+ innerView.render(true);
+ lastItem = data.item;
+ }
+ }
+
+ // 清空 annotation
+ function clearAnnotation() {
+ innerView.annotation().clear(true);
+ innerView.render(true);
+ lastItem = null;
+ }
+
+ }
+}
+
+
diff --git a/src/app/routes/datatable/components/dataindex/dataindex_line/dataindex_line.component.html b/src/app/routes/datatable/components/dataindex/dataindex_line/dataindex_line.component.html
new file mode 100644
index 00000000..3f148bfd
--- /dev/null
+++ b/src/app/routes/datatable/components/dataindex/dataindex_line/dataindex_line.component.html
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/routes/datatable/components/dataindex/dataindex_line/dataindex_line.component.less b/src/app/routes/datatable/components/dataindex/dataindex_line/dataindex_line.component.less
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/routes/datatable/components/dataindex/dataindex_line/dataindex_line.component.spec.ts b/src/app/routes/datatable/components/dataindex/dataindex_line/dataindex_line.component.spec.ts
new file mode 100644
index 00000000..cd009e56
--- /dev/null
+++ b/src/app/routes/datatable/components/dataindex/dataindex_line/dataindex_line.component.spec.ts
@@ -0,0 +1,24 @@
+import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
+import { DatatableDataindexComponent } from './dataindex.component';
+
+describe('DatatableDataindexComponent', () => {
+ let component: DatatableDataindexComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [ DatatableDataindexComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DatatableDataindexComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/routes/datatable/components/dataindex/dataindex_line/dataindex_line.component.ts b/src/app/routes/datatable/components/dataindex/dataindex_line/dataindex_line.component.ts
new file mode 100644
index 00000000..eb15c985
--- /dev/null
+++ b/src/app/routes/datatable/components/dataindex/dataindex_line/dataindex_line.component.ts
@@ -0,0 +1,249 @@
+import { Component, ElementRef, NgZone, OnInit, ViewChild } from '@angular/core';
+import { ModalHelper, _HttpClient } from '@delon/theme';
+import { G2MiniAreaClickItem, G2MiniAreaData } from '@delon/chart/mini-area';
+import { G2PieClickItem, G2PieComponent, G2PieData } from '@delon/chart/pie';
+import { format } from 'date-fns';
+import { DataindexService } from '../services/dataindex.service';
+import { Chart, registerShape, Util } from '@antv/g2';
+import { G2TimelineClickItem, G2TimelineData } from '@delon/chart/timeline';
+
+@Component({
+ selector: 'app-datatable-dataindex',
+ templateUrl: './dataindex.component.html',
+ styleUrls: ['./dataindex.component.less']
+})
+export class DatatableDataindexComponent implements OnInit {
+ @ViewChild('pie', { static: false }) pie!: G2PieComponent;
+ chartData: G2TimelineData[] = [];
+ visitData = this.genData();
+ salesData = this.genData();
+ salesPieData: G2PieData[] = [];
+ total = '';
+
+ constructor(private service: DataindexService, private ngZone: NgZone) {
+
+ }
+
+ ngOnInit(): void {
+ this.refreshPie();
+ this.initLineData()
+ }
+ initLineData(){
+ for (let i = 0; i < 20; i += 1) {
+ this.chartData.push({
+ time: new Date().getTime() + 1000 * 60 * 60 * 24 * i,
+ y1: Math.floor(Math.random() * 100) + 1000,
+ y2: Math.floor(Math.random() * 100) + 10,
+ });
+ }
+ }
+ private genData(): G2MiniAreaData[] {
+ const beginDay = new Date().getTime();
+ const res: G2MiniAreaData[] = [];
+ for (let i = 0; i < 20; i += 1) {
+ res.push({
+ x: format(new Date(beginDay + 1000 * 60 * 60 * 24 * i), 'yyyy-MM-dd'),
+ y: Math.floor(Math.random() * 100) + 10,
+ });
+ }
+ return res;
+ }
+
+ refresh(): void {
+ this.visitData = this.genData();
+ }
+ refreshPie(): void {
+ const rv = (min: number = 0, max: number = 5000) => Math.floor(Math.random() * (max - min + 1) + min);
+ this.salesPieData = [
+ {
+ x: '家用电器',
+ y: rv(),
+ },
+ {
+ x: '食用酒水',
+ y: rv(),
+ },
+ {
+ x: '个护健康',
+ y: rv(),
+ },
+ {
+ x: '服饰箱包',
+ y: rv(),
+ },
+ {
+ x: '母婴产品',
+ y: rv(),
+ },
+ ];
+ if (Math.random() > 0.5) {
+ this.salesPieData.push({
+ x: '其他',
+ y: rv(),
+ });
+ }
+ this.total = `¥ ${this.salesPieData.reduce((pre, now) => now.y + pre, 0).toFixed(2)}`;
+ if (this.pie) {
+ // 等待组件渲染
+ setTimeout(() => {
+ console.log('a')
+ this.pie.changeData()
+ });
+ }
+ }
+
+ handleClick(data: G2MiniAreaClickItem): void {
+ this.service.msgSrv.info(`${data.item.x} - ${data.item.y}`);
+ }
+ format(val: number): string {
+ return `¥ ${val.toFixed(2)}`;
+ }
+ render(el: ElementRef): void {
+ this.ngZone.runOutsideAngular(() => this.init(el.nativeElement));
+ }
+ private init(el: HTMLElement): void {
+ const data = [
+ { item: '货源单', count: 40, percent: 0.4 },
+ { item: '合同单', count: 21, percent: 0.21 },
+ { item: '事例三', count: 17, percent: 0.17 },
+ { item: '事例四', count: 13, percent: 0.13 },
+ { item: '事例五', count: 9, percent: 0.09 },
+ ];
+ const chart = new Chart({
+ container: el,
+ autoFit: true,
+ height: 400,
+ });
+ // 新建一个 view 用来单独渲染Annotation
+ const innerView = chart.createView();
+ chart.coordinate('theta', {
+ radius: 0.6,
+ innerRadius: 0.7,
+ });
+
+ chart.data(data);
+
+ chart.scale('percent', {
+ formatter: val => {
+ val = val * 100 + '%';
+ return val;
+ },
+ });
+
+ chart.tooltip(false);
+
+ // 声明需要进行自定义图例字段: 'item'
+ chart.legend('item', {
+ position: 'right', // 配置图例显示位置
+ custom: true, // 关键字段,告诉 G2,要使用自定义的图例
+ items: data.map((obj, index) => {
+ return {
+ name: obj.item, // 对应 itemName
+ value: obj.percent, // 对应 itemValue
+ marker: {
+ symbol: 'square', // marker 的形状
+ style: {
+ r: 5, // marker 图形半径
+ fill: chart.getTheme().colors10[index], // marker 颜色,使用默认颜色,同图形对应
+ },
+ }, // marker 配置
+ };
+ }),
+ itemValue: {
+ style: {
+ fill: '#999',
+ }, // 配置 itemValue 样式
+ formatter: (val: any) => `${val * 100}%` // 格式化 itemValue 内容
+ },
+ });
+
+ chart
+ .interval()
+ .adjust('stack')
+ .position('percent')
+ .color('item')
+ .style({
+ fillOpacity: 1,
+ stroke: 'white',
+ lineWidth: 8,
+ })
+ .state({
+ active: {
+ style: element => {
+ const shape = element.shape;
+ return {
+ lineWidth: 1,
+ stroke: 'white',
+ strokeOpacity: shape.attr('fillOpacity'),
+ };
+ },
+ },
+ });
+
+ // 移除图例点击过滤交互
+ chart.removeInteraction('legend-filter');
+ chart.interaction('element-active');
+
+ chart.render();
+
+ // 监听 element 上状态的变化来动态更新 Annotation 信息
+ chart.on('element:statechange', (ev: any) => {
+ const { state, stateStatus, element } = ev.gEvent.originalEvent;
+
+ // 本示例只需要监听 active 的状态变化
+ if (state === 'active') {
+ const data = element.getData();
+ if (stateStatus) {
+ // 更新 Annotation
+ updateAnnotation(data);
+ } else {
+ // 隐藏 Annotation
+ clearAnnotation();
+ }
+ }
+ });
+
+ // 绘制 annotation
+ let lastItem: any;
+ function updateAnnotation(data: any) {
+ if (data.item !== lastItem) {
+ innerView.annotation().clear(true);
+ innerView
+ .annotation()
+ .text({
+ position: ['50%', '50%'],
+ content: data.item,
+ style: {
+ fontSize: 20,
+ fill: '#8c8c8c',
+ textAlign: 'center',
+ },
+ offsetY: -20,
+ })
+ .text({
+ position: ['50%', '50%'],
+ content: data.count,
+ style: {
+ fontSize: 28,
+ fill: '#8c8c8c',
+ textAlign: 'center',
+ },
+ offsetX: -10,
+ offsetY: 20,
+ })
+ innerView.render(true);
+ lastItem = data.item;
+ }
+ }
+
+ // 清空 annotation
+ function clearAnnotation() {
+ innerView.annotation().clear(true);
+ innerView.render(true);
+ lastItem = null;
+ }
+
+ }
+}
+
+
diff --git a/src/app/routes/datatable/components/operationtable/curve/curve.component.html b/src/app/routes/datatable/components/operationtable/curve/curve.component.html
new file mode 100644
index 00000000..3f148bfd
--- /dev/null
+++ b/src/app/routes/datatable/components/operationtable/curve/curve.component.html
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/routes/datatable/components/operationtable/curve/curve.component.less b/src/app/routes/datatable/components/operationtable/curve/curve.component.less
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/routes/datatable/components/operationtable/curve/curve.component.spec.ts b/src/app/routes/datatable/components/operationtable/curve/curve.component.spec.ts
new file mode 100644
index 00000000..cd009e56
--- /dev/null
+++ b/src/app/routes/datatable/components/operationtable/curve/curve.component.spec.ts
@@ -0,0 +1,24 @@
+import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
+import { DatatableDataindexComponent } from './dataindex.component';
+
+describe('DatatableDataindexComponent', () => {
+ let component: DatatableDataindexComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [ DatatableDataindexComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DatatableDataindexComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/routes/datatable/components/operationtable/curve/curve.component.ts b/src/app/routes/datatable/components/operationtable/curve/curve.component.ts
new file mode 100644
index 00000000..aedbf57a
--- /dev/null
+++ b/src/app/routes/datatable/components/operationtable/curve/curve.component.ts
@@ -0,0 +1,249 @@
+import { Component, ElementRef, NgZone, OnInit, ViewChild } from '@angular/core';
+import { ModalHelper, _HttpClient } from '@delon/theme';
+import { G2MiniAreaClickItem, G2MiniAreaData } from '@delon/chart/mini-area';
+import { G2PieClickItem, G2PieComponent, G2PieData } from '@delon/chart/pie';
+import { format } from 'date-fns';
+import { Chart, registerShape, Util } from '@antv/g2';
+import { G2TimelineClickItem, G2TimelineData } from '@delon/chart/timeline';
+import { DataService } from '../../../services/data.service';
+
+@Component({
+ selector: 'app-datatable-curve',
+ templateUrl: './curve.component.html',
+ styleUrls: ['./curve.component.less']
+})
+export class DatatableDataindexComponent implements OnInit {
+ @ViewChild('pie', { static: false }) pie!: G2PieComponent;
+ chartData: G2TimelineData[] = [];
+ visitData = this.genData();
+ salesData = this.genData();
+ salesPieData: G2PieData[] = [];
+ total = '';
+
+ constructor(private service: DataService, private ngZone: NgZone) {
+
+ }
+
+ ngOnInit(): void {
+ this.refreshPie();
+ this.initLineData()
+ }
+ initLineData(){
+ for (let i = 0; i < 20; i += 1) {
+ this.chartData.push({
+ time: new Date().getTime() + 1000 * 60 * 60 * 24 * i,
+ y1: Math.floor(Math.random() * 100) + 1000,
+ y2: Math.floor(Math.random() * 100) + 10,
+ });
+ }
+ }
+ private genData(): G2MiniAreaData[] {
+ const beginDay = new Date().getTime();
+ const res: G2MiniAreaData[] = [];
+ for (let i = 0; i < 20; i += 1) {
+ res.push({
+ x: format(new Date(beginDay + 1000 * 60 * 60 * 24 * i), 'yyyy-MM-dd'),
+ y: Math.floor(Math.random() * 100) + 10,
+ });
+ }
+ return res;
+ }
+
+ refresh(): void {
+ this.visitData = this.genData();
+ }
+ refreshPie(): void {
+ const rv = (min: number = 0, max: number = 5000) => Math.floor(Math.random() * (max - min + 1) + min);
+ this.salesPieData = [
+ {
+ x: '家用电器',
+ y: rv(),
+ },
+ {
+ x: '食用酒水',
+ y: rv(),
+ },
+ {
+ x: '个护健康',
+ y: rv(),
+ },
+ {
+ x: '服饰箱包',
+ y: rv(),
+ },
+ {
+ x: '母婴产品',
+ y: rv(),
+ },
+ ];
+ if (Math.random() > 0.5) {
+ this.salesPieData.push({
+ x: '其他',
+ y: rv(),
+ });
+ }
+ this.total = `¥ ${this.salesPieData.reduce((pre, now) => now.y + pre, 0).toFixed(2)}`;
+ if (this.pie) {
+ // 等待组件渲染
+ setTimeout(() => {
+ console.log('a')
+ this.pie.changeData()
+ });
+ }
+ }
+
+ handleClick(data: G2MiniAreaClickItem): void {
+ this.service.msgSrv.info(`${data.item.x} - ${data.item.y}`);
+ }
+ format(val: number): string {
+ return `¥ ${val.toFixed(2)}`;
+ }
+ render(el: ElementRef): void {
+ this.ngZone.runOutsideAngular(() => this.init(el.nativeElement));
+ }
+ private init(el: HTMLElement): void {
+ const data = [
+ { item: '货源单', count: 40, percent: 0.4 },
+ { item: '合同单', count: 21, percent: 0.21 },
+ { item: '事例三', count: 17, percent: 0.17 },
+ { item: '事例四', count: 13, percent: 0.13 },
+ { item: '事例五', count: 9, percent: 0.09 },
+ ];
+ const chart = new Chart({
+ container: el,
+ autoFit: true,
+ height: 400,
+ });
+ // 新建一个 view 用来单独渲染Annotation
+ const innerView = chart.createView();
+ chart.coordinate('theta', {
+ radius: 0.6,
+ innerRadius: 0.7,
+ });
+
+ chart.data(data);
+
+ chart.scale('percent', {
+ formatter: val => {
+ val = val * 100 + '%';
+ return val;
+ },
+ });
+
+ chart.tooltip(false);
+
+ // 声明需要进行自定义图例字段: 'item'
+ chart.legend('item', {
+ position: 'right', // 配置图例显示位置
+ custom: true, // 关键字段,告诉 G2,要使用自定义的图例
+ items: data.map((obj, index) => {
+ return {
+ name: obj.item, // 对应 itemName
+ value: obj.percent, // 对应 itemValue
+ marker: {
+ symbol: 'square', // marker 的形状
+ style: {
+ r: 5, // marker 图形半径
+ fill: chart.getTheme().colors10[index], // marker 颜色,使用默认颜色,同图形对应
+ },
+ }, // marker 配置
+ };
+ }),
+ itemValue: {
+ style: {
+ fill: '#999',
+ }, // 配置 itemValue 样式
+ formatter: (val: any) => `${val * 100}%` // 格式化 itemValue 内容
+ },
+ });
+
+ chart
+ .interval()
+ .adjust('stack')
+ .position('percent')
+ .color('item')
+ .style({
+ fillOpacity: 1,
+ stroke: 'white',
+ lineWidth: 8,
+ })
+ .state({
+ active: {
+ style: element => {
+ const shape = element.shape;
+ return {
+ lineWidth: 1,
+ stroke: 'white',
+ strokeOpacity: shape.attr('fillOpacity'),
+ };
+ },
+ },
+ });
+
+ // 移除图例点击过滤交互
+ chart.removeInteraction('legend-filter');
+ chart.interaction('element-active');
+
+ chart.render();
+
+ // 监听 element 上状态的变化来动态更新 Annotation 信息
+ chart.on('element:statechange', (ev: any) => {
+ const { state, stateStatus, element } = ev.gEvent.originalEvent;
+
+ // 本示例只需要监听 active 的状态变化
+ if (state === 'active') {
+ const data = element.getData();
+ if (stateStatus) {
+ // 更新 Annotation
+ updateAnnotation(data);
+ } else {
+ // 隐藏 Annotation
+ clearAnnotation();
+ }
+ }
+ });
+
+ // 绘制 annotation
+ let lastItem: any;
+ function updateAnnotation(data: any) {
+ if (data.item !== lastItem) {
+ innerView.annotation().clear(true);
+ innerView
+ .annotation()
+ .text({
+ position: ['50%', '50%'],
+ content: data.item,
+ style: {
+ fontSize: 20,
+ fill: '#8c8c8c',
+ textAlign: 'center',
+ },
+ offsetY: -20,
+ })
+ .text({
+ position: ['50%', '50%'],
+ content: data.count,
+ style: {
+ fontSize: 28,
+ fill: '#8c8c8c',
+ textAlign: 'center',
+ },
+ offsetX: -10,
+ offsetY: 20,
+ })
+ innerView.render(true);
+ lastItem = data.item;
+ }
+ }
+
+ // 清空 annotation
+ function clearAnnotation() {
+ innerView.annotation().clear(true);
+ innerView.render(true);
+ lastItem = null;
+ }
+
+ }
+}
+
+
diff --git a/src/app/routes/datatable/components/operationtable/operationtable.component.html b/src/app/routes/datatable/components/operationtable/operationtable.component.html
new file mode 100644
index 00000000..d50b08b2
--- /dev/null
+++ b/src/app/routes/datatable/components/operationtable/operationtable.component.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/routes/datatable/components/operationtable/operationtable.component.less b/src/app/routes/datatable/components/operationtable/operationtable.component.less
new file mode 100644
index 00000000..6b4b1cba
--- /dev/null
+++ b/src/app/routes/datatable/components/operationtable/operationtable.component.less
@@ -0,0 +1,11 @@
+.chooseBox{
+ display: flex;
+}
+.timeBox{
+ display: flex;
+ margin: 0 0 0 10px;
+}
+.dateBox{
+ display: inline-block;
+ margin: 0 0 0 10px;
+}
\ No newline at end of file
diff --git a/src/app/routes/datatable/components/operationtable/operationtable.component.spec.ts b/src/app/routes/datatable/components/operationtable/operationtable.component.spec.ts
new file mode 100644
index 00000000..3b100f2c
--- /dev/null
+++ b/src/app/routes/datatable/components/operationtable/operationtable.component.spec.ts
@@ -0,0 +1,24 @@
+import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
+import { DatatableOperationtableComponent } from './operationtable.component';
+
+describe('DatatableOperationtableComponent', () => {
+ let component: DatatableOperationtableComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [ DatatableOperationtableComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DatatableOperationtableComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/routes/datatable/components/operationtable/operationtable.component.ts b/src/app/routes/datatable/components/operationtable/operationtable.component.ts
new file mode 100644
index 00000000..bfa13aea
--- /dev/null
+++ b/src/app/routes/datatable/components/operationtable/operationtable.component.ts
@@ -0,0 +1,89 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { STColumn, STComponent } from '@delon/abc/st';
+import { DatePipe, _HttpClient } from '@delon/theme';
+import { DataService } from '../../services/data.service';
+import { differenceInCalendarDays } from 'date-fns';
+
+@Component({
+ selector: 'app-datatable-operationtable',
+ templateUrl: './operationtable.component.html',
+ styleUrls: ['./operationtable.component.less'],
+ providers: [DatePipe]
+
+})
+export class DatatableOperationtableComponent implements OnInit {;
+ type = 1;
+ mode = 'year';
+ date: any = null;
+ defineDate = [];
+ time: any = []
+ dateFormat = 'yyyy-MM-dd';
+ today = new Date();
+ @ViewChild('st') private readonly st!: STComponent;
+ columns: STColumn[] = [
+ { title: '运营主体', index: 'networkTransporterName', className: 'text-center' },
+ { title: '订单数', index: 'zsl', className: 'text-center' },
+ { title: '应收金额', index: 'yingsje', className: 'text-center' },
+ { title: '承运数', index: 'cys', className: 'text-center' },
+ { title: '应付运费', index: 'yingfyf', className: 'text-center' },
+ { title: '运量(吨)', index: 'yl', className: 'text-center' },
+ { title: '待接单数', index: 'djd', className: 'text-center' },
+ { title: '在途数', index: 'ysz', className: 'text-center' },
+ { title: '运输完成', index: 'yswc', className: 'text-center' },
+ { title: '已收金额', index: 'yisje', className: 'text-center' },
+ { title: '已付运费', index: 'yifyf', className: 'text-center' }
+ ];
+ /**
+ * 查询参数
+ */
+ get reqParams() {
+ if(this.mode === 'year') {
+ this.type = 1
+ } else if(this.mode === 'month') {
+ this.type = 2
+ } else if(this.mode === 'date') {
+ this.type = 3
+ } else {
+ this.type = 4
+ }
+ let params: any = {
+ time: this.time,
+ type: this.type
+ };
+
+ delete params._$expand;
+ return { ...params };
+ }
+
+ constructor(public service: DataService, private datePipe: DatePipe) { }
+ ngOnInit(): void { }
+
+ changeData(){
+ if(this.mode === 'year') {
+ this.dateFormat = 'yyyy'
+ } else if(this.mode === 'month') {
+ this.dateFormat = 'yyyy-MM'
+ } else {
+ this.dateFormat = 'yyyy-MM-dd'
+ }
+ }
+ onChange(result: any) {
+ if(this.mode === 'year') {
+ this.time = [this.datePipe.transform(this.date, 'yyyy') + '-01-01 00:00:00']
+ } else if(this.mode === 'month') {
+ this.time = [this.datePipe.transform(this.date, 'yyyy-MM') + '-01 00:00:00']
+ } else if(this.mode === 'date') {
+ this.time = [this.datePipe.transform(this.date, 'yyyy-MM-dd') + ' 00:00:00']
+ } else{
+ this.time = [this.datePipe.transform(this.defineDate[0], 'yyyy-MM-dd') + '00:00:00', this.datePipe.transform(this.defineDate[1], 'yyyy-MM-dd') + ' 00:00:00']
+ }
+ this.st.reload({ ...this.reqParams });
+ }
+ disabledDate = (current: Date): boolean =>
+ // Can not select days before today and today
+ differenceInCalendarDays(current, this.today) > 0;
+ exportFun(){
+
+ }
+
+}
diff --git a/src/app/routes/datatable/components/operationtable/pie/pie.component.html b/src/app/routes/datatable/components/operationtable/pie/pie.component.html
new file mode 100644
index 00000000..0640a4d4
--- /dev/null
+++ b/src/app/routes/datatable/components/operationtable/pie/pie.component.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/app/routes/datatable/components/operationtable/pie/pie.component.less b/src/app/routes/datatable/components/operationtable/pie/pie.component.less
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/routes/datatable/components/operationtable/pie/pie.component.spec.ts b/src/app/routes/datatable/components/operationtable/pie/pie.component.spec.ts
new file mode 100644
index 00000000..cd009e56
--- /dev/null
+++ b/src/app/routes/datatable/components/operationtable/pie/pie.component.spec.ts
@@ -0,0 +1,24 @@
+import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
+import { DatatableDataindexComponent } from './dataindex.component';
+
+describe('DatatableDataindexComponent', () => {
+ let component: DatatableDataindexComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [ DatatableDataindexComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DatatableDataindexComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/routes/datatable/components/operationtable/pie/pie.component.ts b/src/app/routes/datatable/components/operationtable/pie/pie.component.ts
new file mode 100644
index 00000000..1e69183a
--- /dev/null
+++ b/src/app/routes/datatable/components/operationtable/pie/pie.component.ts
@@ -0,0 +1,252 @@
+import { Component, ElementRef, NgZone, OnInit, ViewChild } from '@angular/core';
+import { ModalHelper, _HttpClient } from '@delon/theme';
+import { G2MiniAreaClickItem, G2MiniAreaData } from '@delon/chart/mini-area';
+import { G2PieClickItem, G2PieComponent, G2PieData } from '@delon/chart/pie';
+import { format } from 'date-fns';
+import { Chart, registerShape, Util } from '@antv/g2';
+import { G2TimelineClickItem, G2TimelineData } from '@delon/chart/timeline';
+import { DataService } from '../../../services/data.service';
+
+@Component({
+ selector: 'app-opeationtable-pie',
+ templateUrl: './pie.component.html',
+ styleUrls: ['./pie.component.less']
+})
+export class OperationtablePieComponent implements OnInit {
+ @ViewChild('pie', { static: false }) pie!: G2PieComponent;
+ chartData: G2TimelineData[] = [];
+ visitData = this.genData();
+ salesData = this.genData();
+ salesPieData: G2PieData[] = [];
+ total = '';
+
+ constructor(private service: DataService, private ngZone: NgZone) {
+
+ }
+
+ ngOnInit(): void {
+ this.refreshPie();
+ this.initLineData()
+ }
+ initLineData() {
+ for (let i = 0; i < 20; i += 1) {
+ this.chartData.push({
+ time: new Date().getTime() + 1000 * 60 * 60 * 24 * i,
+ y1: Math.floor(Math.random() * 100) + 1000,
+ y2: Math.floor(Math.random() * 100) + 10,
+ });
+ }
+ }
+ private genData(): G2MiniAreaData[] {
+ const beginDay = new Date().getTime();
+ const res: G2MiniAreaData[] = [];
+ for (let i = 0; i < 20; i += 1) {
+ res.push({
+ x: format(new Date(beginDay + 1000 * 60 * 60 * 24 * i), 'yyyy-MM-dd'),
+ y: Math.floor(Math.random() * 100) + 10,
+ });
+ }
+ return res;
+ }
+
+ refresh(): void {
+ this.visitData = this.genData();
+ }
+ refreshPie(): void {
+ const rv = (min: number = 0, max: number = 5000) => Math.floor(Math.random() * (max - min + 1) + min);
+ this.salesPieData = [
+ {
+ x: '家用电器',
+ y: rv(),
+ },
+ {
+ x: '食用酒水',
+ y: rv(),
+ },
+ {
+ x: '个护健康',
+ y: rv(),
+ },
+ {
+ x: '服饰箱包',
+ y: rv(),
+ },
+ {
+ x: '母婴产品',
+ y: rv(),
+ },
+ ];
+ if (Math.random() > 0.5) {
+ this.salesPieData.push({
+ x: '其他',
+ y: rv(),
+ });
+ }
+ this.total = `¥ ${this.salesPieData.reduce((pre, now) => now.y + pre, 0).toFixed(2)}`;
+ if (this.pie) {
+ // 等待组件渲染
+ setTimeout(() => {
+ console.log('a')
+ this.pie.changeData()
+ });
+ }
+ }
+
+ handleClick(data: G2MiniAreaClickItem): void {
+ this.service.msgSrv.info(`${data.item.x} - ${data.item.y}`);
+ }
+ format(val: number): string {
+ return `¥ ${val.toFixed(2)}`;
+ }
+ render(el: ElementRef): void {
+ this.ngZone.runOutsideAngular(() => this.init(el.nativeElement));
+ }
+ private init(el: HTMLElement): void {
+ const data = [
+ { item: '货源单', count: 40, percent: 0.4 },
+ { item: '合同单', count: 21, percent: 0.21 },
+ { item: '事例三', count: 17, percent: 0.17 },
+ { item: '事例四', count: 13, percent: 0.13 },
+ { item: '事例五', count: 9, percent: 0.09 },
+ ];
+ const chart = new Chart({
+ container: el,
+ autoFit: true,
+ height: 400,
+ });
+ // 新建一个 view 用来单独渲染Annotation
+ const innerView = chart.createView();
+ chart.coordinate('theta', {
+ radius: 0.6,
+ innerRadius: 0.7,
+ });
+
+ chart.data(data);
+
+ chart.scale('percent', {
+ formatter: val => {
+ val = val * 100 + '%';
+ return val;
+ },
+ });
+
+ chart.tooltip(false);
+
+ // 声明需要进行自定义图例字段: 'item'
+ chart.legend('item', {
+ position: 'right', // 配置图例显示位置
+ custom: true, // 关键字段,告诉 G2,要使用自定义的图例
+ items: data.map((obj, index) => {
+ return {
+ name: obj.item, // 对应 itemName
+ value: obj.percent, // 对应 itemValue
+ marker: {
+ symbol: 'square', // marker 的形状
+ style: {
+ r: 5, // marker 图形半径
+ fill: chart.getTheme().colors10[index], // marker 颜色,使用默认颜色,同图形对应
+ },
+ }, // marker 配置
+ };
+ }),
+ itemValue: {
+ style: {
+ fill: '#999',
+ }, // 配置 itemValue 样式
+ formatter: (val: any) => `${val * 100}%` // 格式化 itemValue 内容
+ },
+ });
+
+ const interval = chart
+ .interval()
+ .adjust('stack')
+ .position('percent')
+ .color('item')
+ .style({
+ fillOpacity: 1,
+ stroke: 'white',
+ lineWidth: 8,
+ })
+ .state({
+ active: {
+ style: element => {
+ const shape = element.shape;
+ return {
+ lineWidth: 1,
+ stroke: 'white',
+ strokeOpacity: shape.attr('fillOpacity'),
+ };
+ },
+ },
+ });
+
+ // 移除图例点击过滤交互
+ chart.removeInteraction('legend-filter');
+ chart.interaction('element-active');
+
+ chart.render();
+ // 默认选择
+ interval.elements[0].setState('selected', true);
+ // 监听 element 上状态的变化来动态更新 Annotation 信息
+ chart.on('element:statechange', (ev: any) => {
+ const { state, stateStatus, element } = ev.gEvent.originalEvent;
+
+ // 本示例只需要监听 active 的状态变化
+ if (state === 'active') {
+ const data = element.getData();
+ if (stateStatus) {
+ // 更新 Annotation
+ updateAnnotation(data);
+ } else {
+ // 隐藏 Annotation
+ clearAnnotation();
+ }
+ }
+ });
+
+ // 绘制 annotation
+ let lastItem: any;
+ function updateAnnotation(data: any) {
+ if (data.item !== lastItem) {
+ innerView.annotation().clear(true);
+ innerView
+ .annotation()
+ .text({
+ position: ['50%', '50%'],
+ content: data.item,
+ style: {
+ fontSize: 20,
+ fill: '#8c8c8c',
+ textAlign: 'center',
+ },
+ offsetY: -20,
+ })
+ .text({
+ position: ['50%', '50%'],
+ content: data.count,
+ style: {
+ fontSize: 28,
+ fill: '#8c8c8c',
+ textAlign: 'center',
+ },
+ offsetX: -10,
+ offsetY: 20,
+ })
+ innerView.render(true);
+
+
+ lastItem = data.item;
+ }
+ }
+
+ // 清空 annotation
+ function clearAnnotation() {
+ innerView.annotation().clear(true);
+ innerView.render(true);
+ lastItem = null;
+ }
+
+ }
+}
+
+
diff --git a/src/app/routes/datatable/dataindex/dataindex.component.html b/src/app/routes/datatable/dataindex/dataindex.component.html
deleted file mode 100644
index ffa275ac..00000000
--- a/src/app/routes/datatable/dataindex/dataindex.component.html
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/app/routes/datatable/dataindex/dataindex.component.ts b/src/app/routes/datatable/dataindex/dataindex.component.ts
deleted file mode 100644
index b180b8a5..00000000
--- a/src/app/routes/datatable/dataindex/dataindex.component.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { Component, OnInit, ViewChild } from '@angular/core';
-import { ModalHelper, _HttpClient } from '@delon/theme';
-import { G2MiniAreaClickItem, G2MiniAreaData } from '@delon/chart/mini-area';
-import { format } from 'date-fns';
-
-@Component({
- selector: 'app-datatable-dataindex',
- templateUrl: './dataindex.component.html',
- styleUrls: ['./dataindex.component.less']
-})
-export class DatatableDataindexComponent implements OnInit {
- visitData = this.genData();
-
- constructor(private http: _HttpClient, private modal: ModalHelper) { }
-
- ngOnInit(): void { }
- private genData(): G2MiniAreaData[] {
- const beginDay = new Date().getTime();
- const res: G2MiniAreaData[] = [];
- for (let i = 0; i < 20; i += 1) {
- res.push({
- x: format(new Date(beginDay + 1000 * 60 * 60 * 24 * i), 'yyyy-MM-dd'),
- y: Math.floor(Math.random() * 100) + 10,
- });
- }
- return res;
- }
-
- refresh(): void {
- this.visitData = this.genData();
- }
-
- handleClick(data: G2MiniAreaClickItem): void {
- //this.msg.info(`${data.item.x} - ${data.item.y}`);
- }
-
-}
diff --git a/src/app/routes/datatable/datatable-routing.module.ts b/src/app/routes/datatable/datatable-routing.module.ts
index 76a62af8..3f26a99f 100644
--- a/src/app/routes/datatable/datatable-routing.module.ts
+++ b/src/app/routes/datatable/datatable-routing.module.ts
@@ -1,10 +1,19 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
-import { DatatableDataindexComponent } from './dataindex/dataindex.component';
+import { DatatableCustomtableComponent } from './components/customtable/customtable.component';
+import { DatatableCustomindexComponent } from './components/customtable/customindex/customindex.component';
+import { DatatableOwnerComponent } from './components/customtable/owner/owner.component';
+import { DatatableDriverComponent } from './components/customtable/driver/driver.component';
+import { DatatableOperationtableComponent } from './components/operationtable/operationtable.component';
+import { DatatableDataindexComponent } from './components/dataindex/dataindex.component';
const routes: Routes = [
-
- { path: 'dataindex', component: DatatableDataindexComponent }];
+ { path: 'dataindex', component: DatatableDataindexComponent },
+ { path: 'customtable', component: DatatableCustomtableComponent },
+ { path: 'customindex', component: DatatableCustomindexComponent },
+ { path: 'owner', component: DatatableOwnerComponent },
+ { path: 'driver', component: DatatableDriverComponent },
+ { path: 'operationtable', component: DatatableOperationtableComponent }];
@NgModule({
imports: [RouterModule.forChild(routes)],
diff --git a/src/app/routes/datatable/datatable.module.ts b/src/app/routes/datatable/datatable.module.ts
index f996d3b5..10668149 100644
--- a/src/app/routes/datatable/datatable.module.ts
+++ b/src/app/routes/datatable/datatable.module.ts
@@ -1,10 +1,23 @@
import { NgModule, Type } from '@angular/core';
import { SharedModule, SHARED_G2_MODULES } from '@shared';
import { DatatableRoutingModule } from './datatable-routing.module';
-import { DatatableDataindexComponent } from './dataindex/dataindex.component';
+import { DatatableCustomtableComponent } from './components/customtable/customtable.component';
+import { DatatableCustomindexComponent } from './components/customtable/customindex/customindex.component';
+import { DatatableOwnerComponent } from './components/customtable/owner/owner.component';
+import { DatatableDriverComponent } from './components/customtable/driver/driver.component';
+import { DatatableOperationtableComponent } from './components/operationtable/operationtable.component';
+import { DatatableDataindexComponent } from './components/dataindex/dataindex.component';
+import { OperationtablePieComponent } from './components/operationtable/pie/pie.component';
const COMPONENTS: Type[] = [
- DatatableDataindexComponent];
+ DatatableDataindexComponent,
+ DatatableCustomtableComponent,
+ DatatableCustomindexComponent,
+ DatatableOwnerComponent,
+ DatatableDriverComponent,
+ DatatableOperationtableComponent,
+ OperationtablePieComponent
+];
@NgModule({
imports: [
diff --git a/src/app/routes/datatable/services/data.service.ts b/src/app/routes/datatable/services/data.service.ts
new file mode 100644
index 00000000..be36c9cf
--- /dev/null
+++ b/src/app/routes/datatable/services/data.service.ts
@@ -0,0 +1,30 @@
+/*
+ * @Description :
+ * @Version : 1.0
+ * @Author : Shiming
+ * @Date : 2021-12-27 10:30:56
+ * @LastEditors : Shiming
+ * @LastEditTime : 2022-01-18 17:14:59
+ * @FilePath : \\tms-obc-web\\src\\app\\routes\\account\\services\\account.service.ts
+ * Copyright (C) 2022 huzhenhong. All rights reserved.
+ */
+
+import { Injectable, Injector } from '@angular/core';
+import { _HttpClient } from '@delon/theme';
+import { NzMessageService } from 'ng-zorro-antd/message';
+import { map } from 'rxjs/operators';
+import { BaseService } from 'src/app/shared/services/core/base.service';
+import { EAFileUtil } from 'src/app/shared/utils/file.util';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class DataService extends BaseService {
+
+ // 查询运营报表
+ $api_listOperationalReportPage = `/api/sdc/report/listOperationalReportPage`;
+
+ constructor(public injector: Injector) {
+ super(injector);
+ }
+}
diff --git a/src/app/shared/shared-g2.module.ts b/src/app/shared/shared-g2.module.ts
index 93863e08..10ea8fcc 100644
--- a/src/app/shared/shared-g2.module.ts
+++ b/src/app/shared/shared-g2.module.ts
@@ -3,6 +3,7 @@ import { G2MiniAreaModule } from '@delon/chart/mini-area';
import { G2PieModule } from '@delon/chart/pie';
import { G2TimelineModule } from '@delon/chart/timeline';
import { G2CardModule } from '@delon/chart/card';
+import { G2CustomModule } from '@delon/chart/custom';
-export const SHARED_G2_MODULES = [G2BarModule, G2PieModule, G2TimelineModule, G2MiniAreaModule, G2CardModule];
+export const SHARED_G2_MODULES = [G2BarModule, G2PieModule, G2TimelineModule, G2MiniAreaModule, G2CardModule, G2CustomModule];