mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-09-17 17:26:38 +08:00
feat(projects): add visactor plugin demos (#658)
* feat: add vtable plugin * feat: add vchart hook * feat: add dark mode support in vtable * feat: add visactor icon * feat: add vtable-gantt plugin * fix: fix theme update in vtable-gantt * feat: update visactor version
This commit is contained in:
parent
aabe7fe592
commit
b9e873e53c
@ -58,6 +58,11 @@
|
||||
"@sa/hooks": "workspace:*",
|
||||
"@sa/materials": "workspace:*",
|
||||
"@sa/utils": "workspace:*",
|
||||
"@visactor/vchart": "1.12.10",
|
||||
"@visactor/vchart-theme": "1.12.2",
|
||||
"@visactor/vtable-editors": "1.10.2",
|
||||
"@visactor/vtable-gantt": "1.10.2",
|
||||
"@visactor/vue-vtable": "1.10.2",
|
||||
"@vueuse/components": "11.1.0",
|
||||
"@vueuse/core": "11.1.0",
|
||||
"clipboard": "2.0.11",
|
||||
|
12336
pnpm-lock.yaml
12336
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
3
src/assets/svg-icon/visactor.svg
Normal file
3
src/assets/svg-icon/visactor.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M100 10C149.706 10 190 50.2944 190 100C190 108.029 188.949 115.812 186.976 123.219L136.254 39.4666H136.195C131.638 32.531 123.789 27.9518 114.87 27.9518C105.952 27.9518 98.1024 32.531 93.5456 39.4666H93.4853L92.8532 40.5821C92.731 40.7907 92.6117 41.0012 92.4953 41.2136L36.9057 139.312C34.7053 143.082 33.4445 147.467 33.4445 152.147C33.4445 156.134 34.3599 159.908 35.9919 163.269C19.9218 147.012 10 124.665 10 100C10 50.2944 50.2944 10 100 10ZM53.4722 177.056C55.2341 177.441 57.0641 177.644 58.9415 177.644C73.0231 177.644 84.4384 166.228 84.4384 152.147C84.4384 147.63 83.2642 143.388 81.2043 139.709L81.2172 139.704L68.7932 118.202C62.0989 106.608 66.0716 91.7816 77.6663 85.0874C89.261 78.3932 104.087 82.3658 110.781 93.9605L154.607 168.236L154.625 168.229C155.082 168.971 155.575 169.689 156.103 170.378C140.717 182.659 121.216 190 100 190C82.9725 190 67.0494 185.271 53.4722 177.056Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
157
src/hooks/common/vchart.ts
Normal file
157
src/hooks/common/vchart.ts
Normal file
@ -0,0 +1,157 @@
|
||||
import { computed, effectScope, onScopeDispose, ref, watch } from 'vue';
|
||||
import VChart, { registerLiquidChart } from '@visactor/vchart';
|
||||
import type { ISpec, ITheme } from '@visactor/vchart';
|
||||
import light from '@visactor/vchart-theme/public/light.json';
|
||||
import dark from '@visactor/vchart-theme/public/dark.json';
|
||||
import { useElementSize } from '@vueuse/core';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
registerLiquidChart();
|
||||
|
||||
// register the theme
|
||||
VChart.ThemeManager.registerTheme('light', light as ITheme);
|
||||
VChart.ThemeManager.registerTheme('dark', dark as ITheme);
|
||||
|
||||
interface ChartHooks {
|
||||
onRender?: (chart: VChart) => void | Promise<void>;
|
||||
onUpdated?: (chart: VChart) => void | Promise<void>;
|
||||
onDestroy?: (chart: VChart) => void | Promise<void>;
|
||||
}
|
||||
|
||||
export function useVChart<T extends ISpec>(specFactory: () => T, hooks: ChartHooks = {}) {
|
||||
const scope = effectScope();
|
||||
const themeStore = useThemeStore();
|
||||
const darkMode = computed(() => themeStore.darkMode);
|
||||
|
||||
const domRef = ref<HTMLElement | null>(null);
|
||||
const initialSize = { width: 0, height: 0 };
|
||||
const { width, height } = useElementSize(domRef, initialSize);
|
||||
|
||||
let chart: VChart | null = null;
|
||||
const spec: T = specFactory();
|
||||
|
||||
const { onRender, onUpdated, onDestroy } = hooks;
|
||||
|
||||
/**
|
||||
* whether can render chart
|
||||
*
|
||||
* when domRef is ready and initialSize is valid
|
||||
*/
|
||||
function canRender() {
|
||||
return domRef.value && initialSize.width > 0 && initialSize.height > 0;
|
||||
}
|
||||
|
||||
/** is chart rendered */
|
||||
function isRendered() {
|
||||
return Boolean(domRef.value && chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* update chart spec
|
||||
*
|
||||
* @param callback callback function
|
||||
*/
|
||||
async function updateSpec(callback: (opts: T, optsFactory: () => T) => ISpec = () => spec) {
|
||||
if (!isRendered()) return;
|
||||
|
||||
const updatedOpts = callback(spec, specFactory);
|
||||
|
||||
Object.assign(spec, updatedOpts);
|
||||
|
||||
if (isRendered()) {
|
||||
chart?.release();
|
||||
}
|
||||
|
||||
chart?.updateSpec({ ...updatedOpts }, true);
|
||||
|
||||
await onUpdated?.(chart!);
|
||||
}
|
||||
|
||||
function setSpec(newSpec: T) {
|
||||
chart?.updateSpec(newSpec);
|
||||
}
|
||||
|
||||
/** render chart */
|
||||
async function render() {
|
||||
if (!isRendered()) {
|
||||
// apply the theme
|
||||
if (darkMode.value) {
|
||||
VChart.ThemeManager.setCurrentTheme('dark');
|
||||
} else {
|
||||
VChart.ThemeManager.setCurrentTheme('light');
|
||||
}
|
||||
|
||||
chart = new VChart(spec, { dom: domRef.value as HTMLElement });
|
||||
chart.renderSync();
|
||||
|
||||
await onRender?.(chart);
|
||||
}
|
||||
}
|
||||
|
||||
/** resize chart */
|
||||
function resize() {
|
||||
// chart?.resize();
|
||||
}
|
||||
|
||||
/** destroy chart */
|
||||
async function destroy() {
|
||||
if (!chart) return;
|
||||
|
||||
await onDestroy?.(chart);
|
||||
chart?.release();
|
||||
chart = null;
|
||||
}
|
||||
|
||||
/** change chart theme */
|
||||
async function changeTheme() {
|
||||
await destroy();
|
||||
await render();
|
||||
await onUpdated?.(chart!);
|
||||
}
|
||||
|
||||
/**
|
||||
* render chart by size
|
||||
*
|
||||
* @param w width
|
||||
* @param h height
|
||||
*/
|
||||
async function renderChartBySize(w: number, h: number) {
|
||||
initialSize.width = w;
|
||||
initialSize.height = h;
|
||||
|
||||
// size is abnormal, destroy chart
|
||||
if (!canRender()) {
|
||||
await destroy();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// resize chart
|
||||
if (isRendered()) {
|
||||
resize();
|
||||
}
|
||||
|
||||
// render chart
|
||||
await render();
|
||||
}
|
||||
|
||||
scope.run(() => {
|
||||
watch([width, height], ([newWidth, newHeight]) => {
|
||||
renderChartBySize(newWidth, newHeight);
|
||||
});
|
||||
|
||||
watch(darkMode, () => {
|
||||
changeTheme();
|
||||
});
|
||||
});
|
||||
|
||||
onScopeDispose(() => {
|
||||
destroy();
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
return {
|
||||
domRef,
|
||||
updateSpec,
|
||||
setSpec
|
||||
};
|
||||
}
|
0
src/hooks/common/vtable.ts
Normal file
0
src/hooks/common/vtable.ts
Normal file
@ -205,6 +205,7 @@ const local: App.I18n.Schema = {
|
||||
plugin_charts: 'Charts',
|
||||
plugin_charts_echarts: 'ECharts',
|
||||
plugin_charts_antv: 'AntV',
|
||||
plugin_charts_vchart: 'VChart',
|
||||
plugin_editor: 'Editor',
|
||||
plugin_editor_quill: 'Quill',
|
||||
plugin_editor_markdown: 'Markdown',
|
||||
@ -218,7 +219,11 @@ const local: App.I18n.Schema = {
|
||||
plugin_excel: 'Excel',
|
||||
plugin_pdf: 'PDF preview',
|
||||
plugin_gantt: 'Gantt Chart',
|
||||
plugin_typeit: 'Typeit'
|
||||
plugin_gantt_dhtmlx: 'dhtmlxGantt',
|
||||
plugin_gantt_vtable: 'VTableGantt',
|
||||
plugin_typeit: 'Typeit',
|
||||
plugin_tables: 'Tables',
|
||||
plugin_tables_vtable: 'VTable'
|
||||
},
|
||||
page: {
|
||||
login: {
|
||||
|
@ -205,6 +205,7 @@ const local: App.I18n.Schema = {
|
||||
plugin_charts: '图表',
|
||||
plugin_charts_echarts: 'ECharts',
|
||||
plugin_charts_antv: 'AntV',
|
||||
plugin_charts_vchart: 'VChart',
|
||||
plugin_editor: '编辑器',
|
||||
plugin_editor_quill: '富文本编辑器',
|
||||
plugin_editor_markdown: 'MD 编辑器',
|
||||
@ -218,7 +219,11 @@ const local: App.I18n.Schema = {
|
||||
plugin_excel: 'Excel',
|
||||
plugin_pdf: 'PDF 预览',
|
||||
plugin_gantt: '甘特图',
|
||||
plugin_typeit: '打字机'
|
||||
plugin_gantt_dhtmlx: 'dhtmlxGantt',
|
||||
plugin_gantt_vtable: 'VTableGantt',
|
||||
plugin_typeit: '打字机',
|
||||
plugin_tables: '表格',
|
||||
plugin_tables_vtable: 'VTable'
|
||||
},
|
||||
page: {
|
||||
login: {
|
||||
|
@ -42,17 +42,20 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
||||
plugin_barcode: () => import("@/views/plugin/barcode/index.vue"),
|
||||
plugin_charts_antv: () => import("@/views/plugin/charts/antv/index.vue"),
|
||||
plugin_charts_echarts: () => import("@/views/plugin/charts/echarts/index.vue"),
|
||||
plugin_charts_vchart: () => import("@/views/plugin/charts/vchart/index.vue"),
|
||||
plugin_copy: () => import("@/views/plugin/copy/index.vue"),
|
||||
plugin_editor_markdown: () => import("@/views/plugin/editor/markdown/index.vue"),
|
||||
plugin_editor_quill: () => import("@/views/plugin/editor/quill/index.vue"),
|
||||
plugin_excel: () => import("@/views/plugin/excel/index.vue"),
|
||||
plugin_gantt: () => import("@/views/plugin/gantt/index.vue"),
|
||||
plugin_gantt_dhtmlx: () => import("@/views/plugin/gantt/dhtmlx/index.vue"),
|
||||
plugin_gantt_vtable: () => import("@/views/plugin/gantt/vtable/index.vue"),
|
||||
plugin_icon: () => import("@/views/plugin/icon/index.vue"),
|
||||
plugin_map: () => import("@/views/plugin/map/index.vue"),
|
||||
plugin_pdf: () => import("@/views/plugin/pdf/index.vue"),
|
||||
plugin_pinyin: () => import("@/views/plugin/pinyin/index.vue"),
|
||||
plugin_print: () => import("@/views/plugin/print/index.vue"),
|
||||
plugin_swiper: () => import("@/views/plugin/swiper/index.vue"),
|
||||
plugin_tables_vtable: () => import("@/views/plugin/tables/vtable/index.vue"),
|
||||
plugin_typeit: () => import("@/views/plugin/typeit/index.vue"),
|
||||
plugin_video: () => import("@/views/plugin/video/index.vue"),
|
||||
"user-center": () => import("@/views/user-center/index.vue"),
|
||||
|
@ -424,6 +424,16 @@ export const generatedRoutes: GeneratedRoute[] = [
|
||||
i18nKey: 'route.plugin_charts_echarts',
|
||||
icon: 'simple-icons:apacheecharts'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'plugin_charts_vchart',
|
||||
path: '/plugin/charts/vchart',
|
||||
component: 'view.plugin_charts_vchart',
|
||||
meta: {
|
||||
title: 'plugin_charts_vchart',
|
||||
i18nKey: 'route.plugin_charts_vchart',
|
||||
localIcon: 'visactor'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -482,12 +492,32 @@ export const generatedRoutes: GeneratedRoute[] = [
|
||||
{
|
||||
name: 'plugin_gantt',
|
||||
path: '/plugin/gantt',
|
||||
component: 'view.plugin_gantt',
|
||||
meta: {
|
||||
title: 'plugin_gantt',
|
||||
i18nKey: 'route.plugin_gantt',
|
||||
icon: 'ant-design:bar-chart-outlined'
|
||||
}
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'plugin_gantt_dhtmlx',
|
||||
path: '/plugin/gantt/dhtmlx',
|
||||
component: 'view.plugin_gantt_dhtmlx',
|
||||
meta: {
|
||||
title: 'plugin_gantt_dhtmlx',
|
||||
i18nKey: 'route.plugin_gantt_dhtmlx'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'plugin_gantt_vtable',
|
||||
path: '/plugin/gantt/vtable',
|
||||
component: 'view.plugin_gantt_vtable',
|
||||
meta: {
|
||||
title: 'plugin_gantt_vtable',
|
||||
i18nKey: 'route.plugin_gantt_vtable',
|
||||
localIcon: 'visactor'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'plugin_icon',
|
||||
@ -549,6 +579,27 @@ export const generatedRoutes: GeneratedRoute[] = [
|
||||
icon: 'simple-icons:swiper'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'plugin_tables',
|
||||
path: '/plugin/tables',
|
||||
meta: {
|
||||
title: 'plugin_tables',
|
||||
i18nKey: 'route.plugin_tables',
|
||||
icon: 'icon-park-outline:table'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'plugin_tables_vtable',
|
||||
path: '/plugin/tables/vtable',
|
||||
component: 'view.plugin_tables_vtable',
|
||||
meta: {
|
||||
title: 'plugin_tables_vtable',
|
||||
i18nKey: 'route.plugin_tables_vtable',
|
||||
localIcon: 'visactor'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'plugin_typeit',
|
||||
path: '/plugin/typeit',
|
||||
|
@ -213,18 +213,23 @@ const routeMap: RouteMap = {
|
||||
"plugin_charts": "/plugin/charts",
|
||||
"plugin_charts_antv": "/plugin/charts/antv",
|
||||
"plugin_charts_echarts": "/plugin/charts/echarts",
|
||||
"plugin_charts_vchart": "/plugin/charts/vchart",
|
||||
"plugin_copy": "/plugin/copy",
|
||||
"plugin_editor": "/plugin/editor",
|
||||
"plugin_editor_markdown": "/plugin/editor/markdown",
|
||||
"plugin_editor_quill": "/plugin/editor/quill",
|
||||
"plugin_excel": "/plugin/excel",
|
||||
"plugin_gantt": "/plugin/gantt",
|
||||
"plugin_gantt_dhtmlx": "/plugin/gantt/dhtmlx",
|
||||
"plugin_gantt_vtable": "/plugin/gantt/vtable",
|
||||
"plugin_icon": "/plugin/icon",
|
||||
"plugin_map": "/plugin/map",
|
||||
"plugin_pdf": "/plugin/pdf",
|
||||
"plugin_pinyin": "/plugin/pinyin",
|
||||
"plugin_print": "/plugin/print",
|
||||
"plugin_swiper": "/plugin/swiper",
|
||||
"plugin_tables": "/plugin/tables",
|
||||
"plugin_tables_vtable": "/plugin/tables/vtable",
|
||||
"plugin_typeit": "/plugin/typeit",
|
||||
"plugin_video": "/plugin/video",
|
||||
"user-center": "/user-center"
|
||||
|
10
src/typings/elegant-router.d.ts
vendored
10
src/typings/elegant-router.d.ts
vendored
@ -67,18 +67,23 @@ declare module "@elegant-router/types" {
|
||||
"plugin_charts": "/plugin/charts";
|
||||
"plugin_charts_antv": "/plugin/charts/antv";
|
||||
"plugin_charts_echarts": "/plugin/charts/echarts";
|
||||
"plugin_charts_vchart": "/plugin/charts/vchart";
|
||||
"plugin_copy": "/plugin/copy";
|
||||
"plugin_editor": "/plugin/editor";
|
||||
"plugin_editor_markdown": "/plugin/editor/markdown";
|
||||
"plugin_editor_quill": "/plugin/editor/quill";
|
||||
"plugin_excel": "/plugin/excel";
|
||||
"plugin_gantt": "/plugin/gantt";
|
||||
"plugin_gantt_dhtmlx": "/plugin/gantt/dhtmlx";
|
||||
"plugin_gantt_vtable": "/plugin/gantt/vtable";
|
||||
"plugin_icon": "/plugin/icon";
|
||||
"plugin_map": "/plugin/map";
|
||||
"plugin_pdf": "/plugin/pdf";
|
||||
"plugin_pinyin": "/plugin/pinyin";
|
||||
"plugin_print": "/plugin/print";
|
||||
"plugin_swiper": "/plugin/swiper";
|
||||
"plugin_tables": "/plugin/tables";
|
||||
"plugin_tables_vtable": "/plugin/tables/vtable";
|
||||
"plugin_typeit": "/plugin/typeit";
|
||||
"plugin_video": "/plugin/video";
|
||||
"user-center": "/user-center";
|
||||
@ -184,17 +189,20 @@ declare module "@elegant-router/types" {
|
||||
| "plugin_barcode"
|
||||
| "plugin_charts_antv"
|
||||
| "plugin_charts_echarts"
|
||||
| "plugin_charts_vchart"
|
||||
| "plugin_copy"
|
||||
| "plugin_editor_markdown"
|
||||
| "plugin_editor_quill"
|
||||
| "plugin_excel"
|
||||
| "plugin_gantt"
|
||||
| "plugin_gantt_dhtmlx"
|
||||
| "plugin_gantt_vtable"
|
||||
| "plugin_icon"
|
||||
| "plugin_map"
|
||||
| "plugin_pdf"
|
||||
| "plugin_pinyin"
|
||||
| "plugin_print"
|
||||
| "plugin_swiper"
|
||||
| "plugin_tables_vtable"
|
||||
| "plugin_typeit"
|
||||
| "plugin_video"
|
||||
| "user-center"
|
||||
|
861
src/views/plugin/charts/vchart/data.ts
Normal file
861
src/views/plugin/charts/vchart/data.ts
Normal file
@ -0,0 +1,861 @@
|
||||
export const shapeWordCloudSpec = {
|
||||
type: 'wordCloud',
|
||||
maskShape: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/log.jpeg',
|
||||
nameField: 'challenge_name',
|
||||
valueField: 'sum_count',
|
||||
seriesField: 'challenge_name',
|
||||
data: [
|
||||
{
|
||||
name: 'data',
|
||||
values: [
|
||||
{
|
||||
challenge_name: '刘浩存',
|
||||
sum_count: 957
|
||||
},
|
||||
{
|
||||
challenge_name: '刘昊然',
|
||||
sum_count: 942
|
||||
},
|
||||
{
|
||||
challenge_name: '喜欢',
|
||||
sum_count: 842
|
||||
},
|
||||
{
|
||||
challenge_name: '真的',
|
||||
sum_count: 828
|
||||
},
|
||||
{
|
||||
challenge_name: '四海',
|
||||
sum_count: 665
|
||||
},
|
||||
{
|
||||
challenge_name: '好看',
|
||||
sum_count: 627
|
||||
},
|
||||
{
|
||||
challenge_name: '评论',
|
||||
sum_count: 574
|
||||
},
|
||||
{
|
||||
challenge_name: '好像',
|
||||
sum_count: 564
|
||||
},
|
||||
{
|
||||
challenge_name: '沈腾',
|
||||
sum_count: 554
|
||||
},
|
||||
{
|
||||
challenge_name: '不像',
|
||||
sum_count: 540
|
||||
},
|
||||
{
|
||||
challenge_name: '多少钱',
|
||||
sum_count: 513
|
||||
},
|
||||
{
|
||||
challenge_name: '韩寒',
|
||||
sum_count: 513
|
||||
},
|
||||
{
|
||||
challenge_name: '不知道',
|
||||
sum_count: 499
|
||||
},
|
||||
{
|
||||
challenge_name: '感觉',
|
||||
sum_count: 499
|
||||
},
|
||||
{
|
||||
challenge_name: '尹正',
|
||||
sum_count: 495
|
||||
},
|
||||
{
|
||||
challenge_name: '不看',
|
||||
sum_count: 487
|
||||
},
|
||||
{
|
||||
challenge_name: '奥特之父',
|
||||
sum_count: 484
|
||||
},
|
||||
{
|
||||
challenge_name: '阿姨',
|
||||
sum_count: 482
|
||||
},
|
||||
{
|
||||
challenge_name: '支持',
|
||||
sum_count: 482
|
||||
},
|
||||
{
|
||||
challenge_name: '父母',
|
||||
sum_count: 479
|
||||
},
|
||||
{
|
||||
challenge_name: '一条',
|
||||
sum_count: 462
|
||||
},
|
||||
{
|
||||
challenge_name: '女主',
|
||||
sum_count: 456
|
||||
},
|
||||
{
|
||||
challenge_name: '确实',
|
||||
sum_count: 456
|
||||
},
|
||||
{
|
||||
challenge_name: '票房',
|
||||
sum_count: 456
|
||||
},
|
||||
{
|
||||
challenge_name: '无语',
|
||||
sum_count: 443
|
||||
},
|
||||
{
|
||||
challenge_name: '干干净净',
|
||||
sum_count: 443
|
||||
},
|
||||
{
|
||||
challenge_name: '为啥',
|
||||
sum_count: 426
|
||||
},
|
||||
{
|
||||
challenge_name: '爱情',
|
||||
sum_count: 425
|
||||
},
|
||||
{
|
||||
challenge_name: '喜剧',
|
||||
sum_count: 422
|
||||
},
|
||||
{
|
||||
challenge_name: '春节',
|
||||
sum_count: 414
|
||||
},
|
||||
{
|
||||
challenge_name: '剧情',
|
||||
sum_count: 414
|
||||
},
|
||||
{
|
||||
challenge_name: '人生',
|
||||
sum_count: 409
|
||||
},
|
||||
{
|
||||
challenge_name: '风格',
|
||||
sum_count: 408
|
||||
},
|
||||
{
|
||||
challenge_name: '演员',
|
||||
sum_count: 403
|
||||
},
|
||||
{
|
||||
challenge_name: '成长',
|
||||
sum_count: 403
|
||||
},
|
||||
{
|
||||
challenge_name: '玩意',
|
||||
sum_count: 402
|
||||
},
|
||||
{
|
||||
challenge_name: '文学',
|
||||
sum_count: 397
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export const circularProgressTickSpec = {
|
||||
type: 'circularProgress',
|
||||
data: [
|
||||
{
|
||||
id: 'id0',
|
||||
values: [
|
||||
{
|
||||
type: 'Tradition Industries',
|
||||
value: 0.795,
|
||||
text: '79.5%'
|
||||
},
|
||||
{
|
||||
type: 'Business Companies',
|
||||
value: 0.5,
|
||||
text: '50%'
|
||||
},
|
||||
{
|
||||
type: 'Customer-facing Companies',
|
||||
value: 0.25,
|
||||
text: '25%'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
color: ['rgb(255, 222, 0)', 'rgb(171, 205, 5)', 'rgb(0, 154, 68)'],
|
||||
valueField: 'value',
|
||||
categoryField: 'type',
|
||||
seriesField: 'type',
|
||||
radius: 0.8,
|
||||
innerRadius: 0.4,
|
||||
tickMask: {
|
||||
visible: true,
|
||||
angle: 10,
|
||||
offsetAngle: 0,
|
||||
forceAlign: true,
|
||||
style: {
|
||||
cornerRadius: 15
|
||||
}
|
||||
},
|
||||
axes: [
|
||||
{
|
||||
visible: false,
|
||||
type: 'linear',
|
||||
orient: 'angle'
|
||||
},
|
||||
{
|
||||
visible: false,
|
||||
type: 'band',
|
||||
orient: 'radius'
|
||||
}
|
||||
],
|
||||
indicator: {
|
||||
visible: true,
|
||||
trigger: 'hover',
|
||||
title: {
|
||||
visible: true,
|
||||
field: 'type',
|
||||
autoLimit: true,
|
||||
style: {
|
||||
fontSize: 20,
|
||||
fill: 'black'
|
||||
}
|
||||
},
|
||||
content: [
|
||||
{
|
||||
visible: true,
|
||||
field: 'text',
|
||||
style: {
|
||||
fontSize: 16,
|
||||
fill: 'gray'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
legends: {
|
||||
visible: true,
|
||||
orient: 'bottom',
|
||||
title: {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const liquidChartSmartInvertSpec = {
|
||||
type: 'liquid',
|
||||
valueField: 'value',
|
||||
data: {
|
||||
id: 'data',
|
||||
values: [
|
||||
{
|
||||
value: 0.8
|
||||
}
|
||||
]
|
||||
},
|
||||
maskShape: 'drop', // 水滴
|
||||
// maskShape: 'circle',
|
||||
// maskShape: 'star',
|
||||
indicatorSmartInvert: true,
|
||||
indicator: {
|
||||
visible: true,
|
||||
title: {
|
||||
visible: true,
|
||||
style: {
|
||||
text: '进度'
|
||||
}
|
||||
},
|
||||
content: [
|
||||
{
|
||||
visible: true,
|
||||
style: {
|
||||
fill: 'black',
|
||||
text: '80%'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
liquidBackground: {
|
||||
style: {
|
||||
fill: 'blue'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const goldenMedals: Record<number, any[]> = {
|
||||
2000: [
|
||||
{ country: 'USA', value: 37 },
|
||||
{ country: 'Russia', value: 32 },
|
||||
{ country: 'China', value: 28 },
|
||||
{ country: 'Australia', value: 16 },
|
||||
{ country: 'Germany', value: 13 },
|
||||
{ country: 'France', value: 13 },
|
||||
{ country: 'Italy', value: 13 },
|
||||
{ country: 'Netherlands', value: 12 },
|
||||
{ country: 'Cuba', value: 11 },
|
||||
{ country: 'U.K.', value: 11 }
|
||||
],
|
||||
2004: [
|
||||
{ country: 'USA', value: 36 },
|
||||
{ country: 'China', value: 32 },
|
||||
{ country: 'Russia', value: 28 },
|
||||
{ country: 'Australia', value: 17 },
|
||||
{ country: 'Japan', value: 16 },
|
||||
{ country: 'Germany', value: 13 },
|
||||
{ country: 'France', value: 11 },
|
||||
{ country: 'Italy', value: 10 },
|
||||
{ country: 'South Korea', value: 9 },
|
||||
{ country: 'U.K.', value: 9 }
|
||||
],
|
||||
2008: [
|
||||
{ country: 'China', value: 48 },
|
||||
{ country: 'USA', value: 36 },
|
||||
{ country: 'Russia', value: 24 },
|
||||
{ country: 'U.K.', value: 19 },
|
||||
{ country: 'Germany', value: 16 },
|
||||
{ country: 'Australia', value: 14 },
|
||||
{ country: 'South Korea', value: 13 },
|
||||
{ country: 'Japan', value: 9 },
|
||||
{ country: 'Italy', value: 8 },
|
||||
{ country: 'France', value: 7 }
|
||||
],
|
||||
2012: [
|
||||
{ country: 'USA', value: 46 },
|
||||
{ country: 'China', value: 39 },
|
||||
{ country: 'U.K.', value: 29 },
|
||||
{ country: 'Russia', value: 19 },
|
||||
{ country: 'South Korea', value: 13 },
|
||||
{ country: 'Germany', value: 11 },
|
||||
{ country: 'France', value: 11 },
|
||||
{ country: 'Australia', value: 8 },
|
||||
{ country: 'Italy', value: 8 },
|
||||
{ country: 'Hungary', value: 8 }
|
||||
],
|
||||
2016: [
|
||||
{ country: 'USA', value: 46 },
|
||||
{ country: 'U.K.', value: 27 },
|
||||
{ country: 'China', value: 26 },
|
||||
{ country: 'Russia', value: 19 },
|
||||
{ country: 'Germany', value: 17 },
|
||||
{ country: 'Japan', value: 12 },
|
||||
{ country: 'France', value: 10 },
|
||||
{ country: 'South Korea', value: 9 },
|
||||
{ country: 'Italy', value: 8 },
|
||||
{ country: 'Australia', value: 8 }
|
||||
],
|
||||
2020: [
|
||||
{ country: 'USA', value: 39 },
|
||||
{ country: 'China', value: 38 },
|
||||
{ country: 'Japan', value: 27 },
|
||||
{ country: 'U.K.', value: 22 },
|
||||
{ country: 'Russian Olympic Committee', value: 20 },
|
||||
{ country: 'Australia', value: 17 },
|
||||
{ country: 'Netherlands', value: 10 },
|
||||
{ country: 'France', value: 10 },
|
||||
{ country: 'Germany', value: 10 },
|
||||
{ country: 'Italy', value: 10 }
|
||||
]
|
||||
};
|
||||
|
||||
const colors = {
|
||||
China: '#d62728',
|
||||
USA: '#1664FF',
|
||||
Russia: '#B2CFFF',
|
||||
'U.K.': '#1AC6FF',
|
||||
Australia: '#94EFFF',
|
||||
Japan: '#FF8A00',
|
||||
Cuba: '#FFCE7A',
|
||||
Germany: '#3CC780',
|
||||
France: '#B9EDCD',
|
||||
Italy: '#7442D4',
|
||||
'South Korea': '#DDC5FA',
|
||||
'Russian Olympic Committee': '#B2CFFF',
|
||||
Netherlands: '#FFC400',
|
||||
Hungary: '#FAE878'
|
||||
};
|
||||
|
||||
const dataSpecs = Object.keys(goldenMedals).map(year => {
|
||||
return {
|
||||
data: [
|
||||
{
|
||||
id: 'id',
|
||||
values: (goldenMedals[year as unknown as number] as any)
|
||||
.sort((a: any, b: any) => b.value - a.value)
|
||||
.map((v: any) => {
|
||||
return { ...v, fill: (colors as any)[v.country] };
|
||||
})
|
||||
},
|
||||
{
|
||||
id: 'year',
|
||||
values: [{ year }]
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
const duration = 1000;
|
||||
const exchangeDuration = 600;
|
||||
|
||||
export const rankingBarSpec = {
|
||||
type: 'bar',
|
||||
padding: {
|
||||
top: 12,
|
||||
right: 100,
|
||||
bottom: 12
|
||||
},
|
||||
data: dataSpecs[0].data,
|
||||
direction: 'horizontal',
|
||||
yField: 'country',
|
||||
xField: 'value',
|
||||
seriesField: 'country',
|
||||
bar: {
|
||||
style: {
|
||||
fill: (datum: any) => datum.fill
|
||||
}
|
||||
},
|
||||
axes: [
|
||||
{
|
||||
animation: true,
|
||||
orient: 'bottom',
|
||||
type: 'linear',
|
||||
visible: true,
|
||||
max: 50,
|
||||
grid: {
|
||||
visible: true
|
||||
}
|
||||
},
|
||||
{
|
||||
animation: true,
|
||||
id: 'axis-left',
|
||||
orient: 'left',
|
||||
width: 130,
|
||||
tick: { visible: false },
|
||||
label: { visible: true },
|
||||
type: 'band'
|
||||
}
|
||||
],
|
||||
title: {
|
||||
visible: true,
|
||||
text: 'Top 10 Olympic Gold Medals by Country Since 2000'
|
||||
},
|
||||
animationUpdate: {
|
||||
bar: [
|
||||
{
|
||||
type: 'update',
|
||||
options: { excludeChannels: ['y'] },
|
||||
easing: 'linear',
|
||||
duration
|
||||
},
|
||||
{
|
||||
channel: ['y'],
|
||||
easing: 'circInOut',
|
||||
duration: exchangeDuration
|
||||
}
|
||||
],
|
||||
axis: {
|
||||
duration: exchangeDuration,
|
||||
easing: 'circInOut'
|
||||
}
|
||||
},
|
||||
animationEnter: {
|
||||
bar: [
|
||||
{
|
||||
type: 'moveIn',
|
||||
duration: exchangeDuration,
|
||||
easing: 'circInOut',
|
||||
options: {
|
||||
direction: 'y',
|
||||
orient: 'negative'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
animationExit: {
|
||||
bar: [
|
||||
{
|
||||
type: 'fadeOut',
|
||||
duration: exchangeDuration
|
||||
}
|
||||
]
|
||||
},
|
||||
customMark: [
|
||||
{
|
||||
type: 'text',
|
||||
dataId: 'year',
|
||||
style: {
|
||||
textBaseline: 'bottom',
|
||||
fontSize: 200,
|
||||
textAlign: 'right',
|
||||
fontFamily: 'PingFang SC',
|
||||
fontWeight: 600,
|
||||
text: (datum: any) => datum.year,
|
||||
x: (_datum: any, ctx: any) => {
|
||||
return ctx.vchart.getChart().getCanvasRect()?.width - 50;
|
||||
},
|
||||
y: (_datum: any, ctx: any) => {
|
||||
return ctx.vchart.getChart().getCanvasRect()?.height - 50;
|
||||
},
|
||||
fill: 'grey',
|
||||
fillOpacity: 0.5
|
||||
}
|
||||
}
|
||||
],
|
||||
player: {
|
||||
type: 'continuous',
|
||||
orient: 'bottom',
|
||||
auto: true,
|
||||
loop: true,
|
||||
dx: 80,
|
||||
position: 'middle',
|
||||
interval: duration,
|
||||
specs: dataSpecs,
|
||||
slider: {
|
||||
railStyle: {
|
||||
height: 6
|
||||
}
|
||||
},
|
||||
controller: {
|
||||
backward: {
|
||||
style: {
|
||||
size: 12
|
||||
}
|
||||
},
|
||||
forward: {
|
||||
style: {
|
||||
size: 12
|
||||
}
|
||||
},
|
||||
start: {
|
||||
order: 1,
|
||||
position: 'end'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const stackedDashAreaSpec = {
|
||||
type: 'area',
|
||||
data: {
|
||||
values: [
|
||||
{ month: 'Jan', country: 'Africa', value: 4229 },
|
||||
{ month: 'Jan', country: 'EU', value: 4376 },
|
||||
{ month: 'Jan', country: 'China', value: 3054 },
|
||||
{ month: 'Jan', country: 'USA', value: 12814 },
|
||||
{ month: 'Feb', country: 'Africa', value: 3932 },
|
||||
{ month: 'Feb', country: 'EU', value: 3987 },
|
||||
{ month: 'Feb', country: 'China', value: 5067 },
|
||||
{ month: 'Feb', country: 'USA', value: 13012 },
|
||||
{ month: 'Mar', country: 'Africa', value: 5221 },
|
||||
{ month: 'Mar', country: 'EU', value: 3574 },
|
||||
{ month: 'Mar', country: 'China', value: 7004 },
|
||||
{ month: 'Mar', country: 'USA', value: 11624 },
|
||||
{ month: 'Apr', country: 'Africa', value: 9256 },
|
||||
{ month: 'Apr', country: 'EU', value: 4376 },
|
||||
{ month: 'Apr', country: 'China', value: 9054 },
|
||||
{ month: 'Apr', country: 'USA', value: 8814 },
|
||||
{ month: 'May', country: 'Africa', value: 3308 },
|
||||
{ month: 'May', country: 'EU', value: 4572 },
|
||||
{ month: 'May', country: 'China', value: 12043 },
|
||||
{ month: 'May', country: 'USA', value: 12998 },
|
||||
{ month: 'Jun', country: 'Africa', value: 5432 },
|
||||
{ month: 'Jun', country: 'EU', value: 3417 },
|
||||
{ month: 'Jun', country: 'China', value: 15067 },
|
||||
{ month: 'Jun', country: 'USA', value: 12321 },
|
||||
{ month: 'Jul', country: 'Africa', value: 13701 },
|
||||
{ month: 'Jul', country: 'EU', value: 5231 },
|
||||
{ month: 'Jul', country: 'China', value: 10119 },
|
||||
{ month: 'Jul', country: 'USA', value: 10342 },
|
||||
{ month: 'Aug', country: 'Africa', value: 4008, forecast: true },
|
||||
{ month: 'Aug', country: 'EU', value: 4572, forecast: true },
|
||||
{ month: 'Aug', country: 'China', value: 12043, forecast: true },
|
||||
{ month: 'Aug', country: 'USA', value: 22998, forecast: true },
|
||||
{ month: 'Sept', country: 'Africa', value: 18712, forecast: true },
|
||||
{ month: 'Sept', country: 'EU', value: 6134, forecast: true },
|
||||
{ month: 'Sept', country: 'China', value: 10419, forecast: true },
|
||||
{ month: 'Sept', country: 'USA', value: 11261, forecast: true }
|
||||
]
|
||||
},
|
||||
stack: true,
|
||||
xField: 'month',
|
||||
yField: 'value',
|
||||
seriesField: 'country',
|
||||
point: {
|
||||
style: {
|
||||
size: 0
|
||||
},
|
||||
state: {
|
||||
dimension_hover: {
|
||||
size: 10,
|
||||
outerBorder: {
|
||||
distance: 0,
|
||||
lineWidth: 6,
|
||||
strokeOpacity: 0.2
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
line: {
|
||||
style: {
|
||||
// Configure the lineDash attribute based on the forecast field value of the data
|
||||
lineDash: (data: any) => {
|
||||
if (data.forecast) {
|
||||
return [5, 5];
|
||||
}
|
||||
return [0];
|
||||
}
|
||||
}
|
||||
},
|
||||
area: {
|
||||
style: {
|
||||
fillOpacity: 0.5,
|
||||
textureColor: '#fff',
|
||||
textureSize: 14,
|
||||
// Configure the texture attribute based on the forecast field value of the data
|
||||
texture: (data: any) => {
|
||||
if (data.forecast) {
|
||||
return 'bias-rl';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
legends: [{ visible: true, position: 'middle', orient: 'bottom' }],
|
||||
crosshair: {
|
||||
xField: {
|
||||
visible: true,
|
||||
line: {
|
||||
type: 'line'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const barMarkPointSpec = {
|
||||
type: 'bar',
|
||||
height: 300,
|
||||
data: [
|
||||
{
|
||||
id: 'barData',
|
||||
values: [
|
||||
{ time: '10:20', cost: 2 },
|
||||
{ time: '10:30', cost: 1 },
|
||||
{ time: '10:40', cost: 1 },
|
||||
{ time: '10:50', cost: 2 },
|
||||
{ time: '11:00', cost: 2 },
|
||||
{ time: '11:10', cost: 2 },
|
||||
{ time: '11:20', cost: 1 },
|
||||
{ time: '11:30', cost: 1 },
|
||||
{ time: '11:40', cost: 2 },
|
||||
{ time: '11:50', cost: 1 }
|
||||
]
|
||||
}
|
||||
],
|
||||
xField: 'time',
|
||||
yField: 'cost',
|
||||
crosshair: {
|
||||
xField: {
|
||||
visible: true,
|
||||
line: {
|
||||
type: 'rect',
|
||||
style: {
|
||||
fill: 'rgb(85,208,93)',
|
||||
fillOpacity: 0.1
|
||||
}
|
||||
},
|
||||
bindingAxesIndex: [1],
|
||||
defaultSelect: {
|
||||
axisIndex: 1,
|
||||
datum: '10:20'
|
||||
}
|
||||
}
|
||||
},
|
||||
label: {
|
||||
visible: true,
|
||||
animation: false,
|
||||
formatMethod: (datum: any) => `${datum}分钟`,
|
||||
style: {
|
||||
fill: 'rgb(155,155,155)'
|
||||
}
|
||||
},
|
||||
bar: {
|
||||
style: {
|
||||
fill: 'rgb(85,208,93)',
|
||||
cornerRadius: [4, 4, 0, 0],
|
||||
width: 30
|
||||
}
|
||||
},
|
||||
markPoint: [
|
||||
{
|
||||
coordinate: {
|
||||
time: '10:20',
|
||||
cost: 2
|
||||
},
|
||||
itemContent: {
|
||||
type: 'text',
|
||||
autoRotate: false,
|
||||
offsetY: -10,
|
||||
text: {
|
||||
dy: 14,
|
||||
text: '2分钟',
|
||||
style: {
|
||||
fill: 'white',
|
||||
fontSize: 14
|
||||
},
|
||||
labelBackground: {
|
||||
padding: [5, 10, 5, 10],
|
||||
style: {
|
||||
fill: '#000',
|
||||
cornerRadius: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
itemLine: {
|
||||
endSymbol: {
|
||||
visible: true,
|
||||
style: {
|
||||
angle: Math.PI,
|
||||
scaleY: 0.4,
|
||||
fill: '#000',
|
||||
dy: 4,
|
||||
stroke: '#000'
|
||||
}
|
||||
},
|
||||
startSymbol: { visible: false },
|
||||
line: {
|
||||
style: {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
animationUpdate: false,
|
||||
axes: [
|
||||
{
|
||||
orient: 'left',
|
||||
max: 10,
|
||||
label: { visible: false },
|
||||
grid: {
|
||||
style: { lineDash: [4, 4] }
|
||||
}
|
||||
},
|
||||
{
|
||||
orient: 'bottom',
|
||||
label: {
|
||||
formatMethod: (datum: any) => {
|
||||
return datum === '10:20' ? '当前' : datum;
|
||||
},
|
||||
style: (datum: any) => {
|
||||
return {
|
||||
fontSize: datum === '10:20' ? 14 : 12,
|
||||
fill: datum === '10:20' ? 'black' : 'grey'
|
||||
};
|
||||
}
|
||||
},
|
||||
paddingOuter: 0.5,
|
||||
paddingInner: 0,
|
||||
grid: {
|
||||
visible: true,
|
||||
alignWithLabel: false,
|
||||
style: { lineDash: [4, 4] }
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export const histogramDifferentBinSpec = {
|
||||
type: 'histogram',
|
||||
xField: 'from',
|
||||
x2Field: 'to',
|
||||
yField: 'profit',
|
||||
seriesField: 'type',
|
||||
bar: {
|
||||
style: {
|
||||
stroke: 'white',
|
||||
lineWidth: 1
|
||||
}
|
||||
},
|
||||
title: {
|
||||
text: 'Profit',
|
||||
textStyle: {
|
||||
align: 'center',
|
||||
height: 50,
|
||||
lineWidth: 3,
|
||||
fill: '#333',
|
||||
fontSize: 25,
|
||||
fontFamily: 'Times New Roman'
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
visible: true,
|
||||
mark: {
|
||||
title: {
|
||||
key: 'title',
|
||||
value: 'profit'
|
||||
},
|
||||
content: [
|
||||
{
|
||||
key: (datum: any) => `${datum.from}~${datum.to}`,
|
||||
value: (datum: any) => datum.profit
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
axes: [
|
||||
{
|
||||
orient: 'bottom',
|
||||
nice: false
|
||||
}
|
||||
],
|
||||
data: [
|
||||
{
|
||||
name: 'data1',
|
||||
values: [
|
||||
{
|
||||
from: 0,
|
||||
to: 10,
|
||||
profit: 2,
|
||||
type: 'A'
|
||||
},
|
||||
{
|
||||
from: 10,
|
||||
to: 16,
|
||||
profit: 3,
|
||||
type: 'B'
|
||||
},
|
||||
{
|
||||
from: 16,
|
||||
to: 18,
|
||||
profit: 15,
|
||||
type: 'C'
|
||||
},
|
||||
{
|
||||
from: 18,
|
||||
to: 26,
|
||||
profit: 12,
|
||||
type: 'D'
|
||||
},
|
||||
{
|
||||
from: 26,
|
||||
to: 32,
|
||||
profit: 22,
|
||||
type: 'E'
|
||||
},
|
||||
{
|
||||
from: 32,
|
||||
to: 56,
|
||||
profit: 7,
|
||||
type: 'F'
|
||||
},
|
||||
{
|
||||
from: 56,
|
||||
to: 62,
|
||||
profit: 17,
|
||||
type: 'G'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
69
src/views/plugin/charts/vchart/index.vue
Normal file
69
src/views/plugin/charts/vchart/index.vue
Normal file
@ -0,0 +1,69 @@
|
||||
<script setup lang="ts">
|
||||
import { onUnmounted } from 'vue';
|
||||
import type {
|
||||
IAreaChartSpec,
|
||||
IBarChartSpec,
|
||||
ICircularProgressChartSpec,
|
||||
IHistogramChartSpec,
|
||||
ILiquidChartSpec
|
||||
} from '@visactor/vchart';
|
||||
import { useVChart } from '@/hooks/common/vchart';
|
||||
import {
|
||||
barMarkPointSpec,
|
||||
circularProgressTickSpec,
|
||||
histogramDifferentBinSpec,
|
||||
liquidChartSmartInvertSpec,
|
||||
rankingBarSpec,
|
||||
shapeWordCloudSpec,
|
||||
stackedDashAreaSpec
|
||||
} from './data';
|
||||
|
||||
const { domRef: stackedDashAreaRef } = useVChart(() => stackedDashAreaSpec as IAreaChartSpec, { onRender() {} });
|
||||
const { domRef: barMarkPointRef } = useVChart(() => barMarkPointSpec as IBarChartSpec, { onRender() {} });
|
||||
const { domRef: histogramDifferentBinRef } = useVChart(() => histogramDifferentBinSpec as IHistogramChartSpec, {
|
||||
onRender() {}
|
||||
});
|
||||
const { domRef: rankingBarRef } = useVChart(() => rankingBarSpec as IBarChartSpec, { onRender() {} });
|
||||
const { domRef: shapeWordCloudRef } = useVChart(() => shapeWordCloudSpec, { onRender() {} });
|
||||
const { domRef: circularProgressTickRef } = useVChart(() => circularProgressTickSpec as ICircularProgressChartSpec, {
|
||||
onRender() {}
|
||||
});
|
||||
const { domRef: liquidChartSmartInvertRef } = useVChart(() => liquidChartSmartInvertSpec as ILiquidChartSpec, {
|
||||
onRender() {}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
// clearGaugeChart();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NSpace vertical :size="16">
|
||||
<NCard title="Stacked Dash Area Chart" :bordered="false" class="h-full card-wrapper">
|
||||
<div ref="stackedDashAreaRef" class="h-400px" />
|
||||
</NCard>
|
||||
<NCard title="Bar Mark Point Chart" :bordered="false" class="h-full card-wrapper">
|
||||
<div ref="barMarkPointRef" class="h-400px" />
|
||||
</NCard>
|
||||
<NCard title="Histogram Different Bin Chart" :bordered="false" class="h-full card-wrapper">
|
||||
<div ref="histogramDifferentBinRef" class="h-400px" />
|
||||
</NCard>
|
||||
<NCard title="Ranking Bar Chart" :bordered="false" class="h-full card-wrapper">
|
||||
<div ref="rankingBarRef" class="h-400px" />
|
||||
</NCard>
|
||||
<NCard title="Circular Progress Tick Chart" :bordered="false" class="h-full card-wrapper">
|
||||
<div ref="circularProgressTickRef" class="h-400px" />
|
||||
</NCard>
|
||||
<NCard title="Liquid Chart Smart Invert Chart" :bordered="false" class="h-full card-wrapper">
|
||||
<div ref="liquidChartSmartInvertRef" class="h-400px" />
|
||||
</NCard>
|
||||
<NCard title="Shape Word Cloud Chart" :bordered="false" class="h-full card-wrapper">
|
||||
<div ref="shapeWordCloudRef" class="h-400px" />
|
||||
</NCard>
|
||||
<NCard :bordered="false" class="h-full w-2/3 card-wrapper">
|
||||
<WebSiteLink label="More VChart Demos: " link="https://www.visactor.com/vchart/example" />
|
||||
</NCard>
|
||||
</NSpace>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
721
src/views/plugin/gantt/vtable/data.ts
Normal file
721
src/views/plugin/gantt/vtable/data.ts
Normal file
@ -0,0 +1,721 @@
|
||||
export const basicGanttRecords = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-15',
|
||||
progress: 31,
|
||||
priority: 'P0',
|
||||
children: [
|
||||
{
|
||||
id: 2,
|
||||
title: 'Project Feature Review',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-07-24',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-25',
|
||||
end: '2024-07-26',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Project Create',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-27',
|
||||
end: '2024-07-26',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Develop feature 1',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-08-01',
|
||||
end: '2024-08-15',
|
||||
progress: 0,
|
||||
priority: 'P1'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-01',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 100,
|
||||
priority: 'P1',
|
||||
children: [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-08-01',
|
||||
end: '2024-08-01',
|
||||
progress: 90,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-30',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024.07.26',
|
||||
end: '2024.07.08',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-29',
|
||||
end: '2024-07-31',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '07.24.2024',
|
||||
end: '08.04.2024',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-16',
|
||||
end: '2024-07-18',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-08-09',
|
||||
end: '2024-09-11',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-26',
|
||||
end: '2024-07-28',
|
||||
progress: 60,
|
||||
priority: 'P0',
|
||||
children: [
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-29',
|
||||
end: '2024-07-31',
|
||||
progress: 100,
|
||||
priority: 'P1',
|
||||
children: [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-26',
|
||||
end: '2024-07-28',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-29',
|
||||
end: '2024-07-31',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0',
|
||||
children: [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-06',
|
||||
end: '2024-07-08',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-29',
|
||||
end: '2024-07-31',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-26',
|
||||
end: '2024-07-28',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-29',
|
||||
end: '2024-07-31',
|
||||
progress: 100,
|
||||
priority: 'P1',
|
||||
children: [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-06',
|
||||
end: '2024-07-08',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-26',
|
||||
end: '2024-07-28',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-29',
|
||||
end: '2024-07-31',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-29',
|
||||
end: '2024-07-31',
|
||||
progress: 100,
|
||||
priority: 'P1',
|
||||
children: [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-23',
|
||||
end: '2024-07-28',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-29',
|
||||
end: '2024-07-31',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-30',
|
||||
end: '2024-08-14',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0',
|
||||
children: [
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-08-04',
|
||||
end: '2024-08-04',
|
||||
progress: 90,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '07/24/2024',
|
||||
end: '08/04/2024',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-27',
|
||||
end: '2024-07-28',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-29',
|
||||
end: '2024-07-31',
|
||||
progress: 100,
|
||||
priority: 'P1',
|
||||
children: [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '07.24.2024',
|
||||
end: '08.04.2024',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-26',
|
||||
end: '2024-07-28',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-08-09',
|
||||
end: '2024-09-11',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-26',
|
||||
end: '2024-07-28',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-29',
|
||||
end: '2024-07-31',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-26',
|
||||
end: '2024-07-28',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-29',
|
||||
end: '2024-07-31',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0',
|
||||
children: [
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024.07.06',
|
||||
end: '2024.07.08',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-29',
|
||||
end: '2024-07-31',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
export const linkGanttRecords = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-15',
|
||||
end: '2024-07-16',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-16',
|
||||
end: '2024-07-17',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-18',
|
||||
end: '2024-07-19',
|
||||
progress: 90,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024/07/17',
|
||||
end: '2024/07/18',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '07/19/2024',
|
||||
end: '07/20/2024',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024.07.06',
|
||||
end: '2024.07.08',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024/07/09',
|
||||
end: '2024/07/11',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '07.24.2024',
|
||||
end: '08.04.2024',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
|
||||
{
|
||||
id: 11,
|
||||
title: 'Software Development',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-24',
|
||||
end: '2024-08-04',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
title: 'Scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-06',
|
||||
end: '2024-07-08',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
title: 'Determine project scope',
|
||||
developer: 'liufangfang.jane@bytedance.com',
|
||||
start: '2024-07-09',
|
||||
end: '2024-07-11',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
}
|
||||
];
|
||||
|
||||
export const customGanttRecords = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Project Task 1',
|
||||
developer: 'bear.xiong',
|
||||
avatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
|
||||
start: '2024-07-24',
|
||||
end: '2024-07-26',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Project Task 2',
|
||||
developer: 'wolf.lang',
|
||||
avatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
|
||||
start: '07/25/2024',
|
||||
end: '07/28/2024',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Project Task 3',
|
||||
developer: 'rabbit.tu',
|
||||
avatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg',
|
||||
start: '2024-07-28',
|
||||
end: '2024-08-01',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'Project Task 4',
|
||||
developer: 'cat.mao',
|
||||
avatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg',
|
||||
start: '2024-07-31',
|
||||
end: '2024-08-03',
|
||||
progress: 31,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Project Task 5',
|
||||
developer: 'bird.niao',
|
||||
avatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bird.jpeg',
|
||||
start: '2024-08-02',
|
||||
end: '2024-08-04',
|
||||
progress: 60,
|
||||
priority: 'P0'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Project Task 6',
|
||||
developer: 'flower.hua',
|
||||
avatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg',
|
||||
start: '2024-08-03',
|
||||
end: '2024-08-10',
|
||||
progress: 100,
|
||||
priority: 'P1'
|
||||
}
|
||||
];
|
794
src/views/plugin/gantt/vtable/index.vue
Normal file
794
src/views/plugin/gantt/vtable/index.vue
Normal file
@ -0,0 +1,794 @@
|
||||
<script setup lang="tsx">
|
||||
import { onMounted, onUnmounted, shallowRef, watch } from 'vue';
|
||||
import * as VTableGantt from '@visactor/vtable-gantt';
|
||||
import * as VTable_editors from '@visactor/vtable-editors';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { basicGanttRecords, customGanttRecords, linkGanttRecords } from './data';
|
||||
|
||||
const theme = useThemeStore();
|
||||
|
||||
const input_editor = new VTable_editors.InputEditor();
|
||||
const date_input_editor = new VTable_editors.DateInputEditor();
|
||||
VTableGantt.VTable.register.editor('input', input_editor);
|
||||
VTableGantt.VTable.register.editor('date-input', date_input_editor);
|
||||
|
||||
const basicGanttDomRef = shallowRef<HTMLElement>();
|
||||
const linkGanttDomRef = shallowRef<HTMLElement>();
|
||||
const customGanttDomRef = shallowRef<HTMLElement>();
|
||||
|
||||
const basicGanttInstance = shallowRef<VTableGantt.Gantt>();
|
||||
const linkGanttInstance = shallowRef<VTableGantt.Gantt>();
|
||||
const customGanttInstance = shallowRef<VTableGantt.Gantt>();
|
||||
|
||||
const basicGanttColumns = [
|
||||
{
|
||||
field: 'title',
|
||||
title: 'title',
|
||||
width: 'auto',
|
||||
sort: true,
|
||||
tree: true,
|
||||
editor: 'input'
|
||||
},
|
||||
{
|
||||
field: 'start',
|
||||
title: 'start',
|
||||
width: 'auto',
|
||||
sort: true,
|
||||
editor: 'date-input'
|
||||
},
|
||||
{
|
||||
field: 'end',
|
||||
title: 'end',
|
||||
width: 'auto',
|
||||
sort: true,
|
||||
editor: 'date-input'
|
||||
},
|
||||
{
|
||||
field: 'priority',
|
||||
title: 'priority',
|
||||
width: 'auto',
|
||||
sort: true,
|
||||
editor: 'input'
|
||||
},
|
||||
{
|
||||
field: 'progress',
|
||||
title: 'progress',
|
||||
width: 'auto',
|
||||
sort: true,
|
||||
headerStyle: {
|
||||
borderColor: '#e1e4e8'
|
||||
},
|
||||
style: {
|
||||
borderColor: '#e1e4e8',
|
||||
color: 'green'
|
||||
},
|
||||
editor: 'input'
|
||||
}
|
||||
];
|
||||
const basicGanttOption: VTableGantt.GanttConstructorOptions = {
|
||||
overscrollBehavior: 'none',
|
||||
records: basicGanttRecords,
|
||||
taskListTable: {
|
||||
columns: basicGanttColumns,
|
||||
tableWidth: 250,
|
||||
minTableWidth: 100,
|
||||
maxTableWidth: 600
|
||||
// rightFrozenColCount: 1
|
||||
},
|
||||
frame: {
|
||||
outerFrameStyle: {
|
||||
borderLineWidth: 2,
|
||||
borderColor: '#e1e4e8',
|
||||
cornerRadius: 8
|
||||
},
|
||||
verticalSplitLine: {
|
||||
lineColor: '#e1e4e8',
|
||||
lineWidth: 3
|
||||
},
|
||||
horizontalSplitLine: {
|
||||
lineColor: '#e1e4e8',
|
||||
lineWidth: 3
|
||||
},
|
||||
verticalSplitLineMoveable: true,
|
||||
verticalSplitLineHighlight: {
|
||||
lineColor: 'green',
|
||||
lineWidth: 3
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
// backgroundColor: 'gray',
|
||||
verticalLine: {
|
||||
lineWidth: 1,
|
||||
lineColor: '#e1e4e8'
|
||||
},
|
||||
horizontalLine: {
|
||||
lineWidth: 1,
|
||||
lineColor: '#e1e4e8'
|
||||
}
|
||||
},
|
||||
headerRowHeight: 40,
|
||||
rowHeight: 40,
|
||||
taskBar: {
|
||||
startDateField: 'start',
|
||||
endDateField: 'end',
|
||||
progressField: 'progress',
|
||||
// resizable: false,
|
||||
moveable: true,
|
||||
hoverBarStyle: {
|
||||
barOverlayColor: 'rgba(99, 144, 0, 0.4)'
|
||||
},
|
||||
labelText: '{title} {progress}%',
|
||||
labelTextStyle: {
|
||||
// padding: 2,
|
||||
fontFamily: 'Arial',
|
||||
fontSize: 16,
|
||||
textAlign: 'left',
|
||||
textOverflow: 'ellipsis'
|
||||
},
|
||||
barStyle: {
|
||||
width: 20,
|
||||
/** 任务条的颜色 */
|
||||
barColor: '#ee8800',
|
||||
/** 已完成部分任务条的颜色 */
|
||||
completedBarColor: '#91e8e0',
|
||||
/** 任务条的圆角 */
|
||||
cornerRadius: 8
|
||||
}
|
||||
},
|
||||
timelineHeader: {
|
||||
colWidth: 100,
|
||||
backgroundColor: '#EEF1F5',
|
||||
horizontalLine: {
|
||||
lineWidth: 1,
|
||||
lineColor: '#e1e4e8'
|
||||
},
|
||||
verticalLine: {
|
||||
lineWidth: 1,
|
||||
lineColor: '#e1e4e8'
|
||||
},
|
||||
scales: [
|
||||
{
|
||||
unit: 'week',
|
||||
step: 1,
|
||||
startOfWeek: 'sunday',
|
||||
format(date: any) {
|
||||
return `Week ${date.dateIndex}`;
|
||||
},
|
||||
style: {
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
color: 'white',
|
||||
strokeColor: 'black',
|
||||
textAlign: 'right',
|
||||
textBaseline: 'bottom',
|
||||
textStick: true
|
||||
// padding: [0, 30, 0, 20]
|
||||
}
|
||||
},
|
||||
{
|
||||
unit: 'day',
|
||||
step: 1,
|
||||
format(date: any) {
|
||||
return date.dateIndex.toString();
|
||||
},
|
||||
style: {
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
color: 'white',
|
||||
strokeColor: 'black',
|
||||
textAlign: 'right',
|
||||
textBaseline: 'bottom'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
markLine: [
|
||||
{
|
||||
date: '2024-07-28',
|
||||
style: {
|
||||
lineWidth: 1,
|
||||
lineColor: 'blue',
|
||||
lineDash: [8, 4]
|
||||
}
|
||||
},
|
||||
{
|
||||
date: '2024-08-17',
|
||||
style: {
|
||||
lineWidth: 2,
|
||||
lineColor: 'red',
|
||||
lineDash: [8, 4]
|
||||
}
|
||||
}
|
||||
],
|
||||
rowSeriesNumber: {
|
||||
title: '行号',
|
||||
dragOrder: true
|
||||
},
|
||||
scrollStyle: {
|
||||
scrollRailColor: 'RGBA(246,246,246,0.5)',
|
||||
visible: 'scrolling',
|
||||
width: 6,
|
||||
scrollSliderCornerRadius: 2,
|
||||
scrollSliderColor: '#5cb85c'
|
||||
}
|
||||
};
|
||||
|
||||
const linkGanttColumns = [
|
||||
{
|
||||
field: 'title',
|
||||
title: 'title',
|
||||
width: 'auto',
|
||||
tree: true
|
||||
},
|
||||
{
|
||||
field: 'start',
|
||||
title: 'start',
|
||||
width: 'auto',
|
||||
editor: 'date-input'
|
||||
},
|
||||
{
|
||||
field: 'end',
|
||||
title: 'end',
|
||||
width: 'auto',
|
||||
editor: 'date-input'
|
||||
},
|
||||
{
|
||||
field: 'priority',
|
||||
title: 'priority',
|
||||
width: 'auto',
|
||||
editor: 'input'
|
||||
},
|
||||
{
|
||||
field: 'progress',
|
||||
title: 'progress',
|
||||
width: 'auto',
|
||||
headerStyle: {
|
||||
borderColor: '#e1e4e8'
|
||||
},
|
||||
style: {
|
||||
borderColor: '#e1e4e8',
|
||||
color: 'green'
|
||||
},
|
||||
editor: 'input'
|
||||
}
|
||||
];
|
||||
const linkGanttOption: VTableGantt.GanttConstructorOptions = {
|
||||
records: linkGanttRecords,
|
||||
taskListTable: {
|
||||
columns: linkGanttColumns,
|
||||
tableWidth: 400,
|
||||
minTableWidth: 100,
|
||||
maxTableWidth: 600
|
||||
},
|
||||
dependency: {
|
||||
links: [
|
||||
{
|
||||
type: VTableGantt.TYPES.DependencyType.FinishToStart,
|
||||
linkedFromTaskKey: 1,
|
||||
linkedToTaskKey: 2
|
||||
},
|
||||
{
|
||||
type: VTableGantt.TYPES.DependencyType.StartToFinish,
|
||||
linkedFromTaskKey: 2,
|
||||
linkedToTaskKey: 3
|
||||
},
|
||||
{
|
||||
type: VTableGantt.TYPES.DependencyType.StartToStart,
|
||||
linkedFromTaskKey: 3,
|
||||
linkedToTaskKey: 4
|
||||
},
|
||||
{
|
||||
type: VTableGantt.TYPES.DependencyType.FinishToFinish,
|
||||
linkedFromTaskKey: 4,
|
||||
linkedToTaskKey: 5
|
||||
}
|
||||
],
|
||||
// linkSelectable: false,
|
||||
linkSelectedLineStyle: {
|
||||
shadowBlur: 5, // 阴影宽度
|
||||
shadowColor: 'red',
|
||||
lineColor: 'red',
|
||||
lineWidth: 1
|
||||
}
|
||||
},
|
||||
frame: {
|
||||
verticalSplitLineMoveable: true,
|
||||
outerFrameStyle: {
|
||||
borderLineWidth: 2,
|
||||
// borderColor: 'red',
|
||||
cornerRadius: 8
|
||||
},
|
||||
verticalSplitLine: {
|
||||
lineWidth: 3,
|
||||
lineColor: '#e1e4e8'
|
||||
},
|
||||
verticalSplitLineHighlight: {
|
||||
lineColor: 'green',
|
||||
lineWidth: 3
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
// backgroundColor: 'gray',
|
||||
verticalLine: {
|
||||
lineWidth: 1,
|
||||
lineColor: '#e1e4e8'
|
||||
},
|
||||
horizontalLine: {
|
||||
lineWidth: 1,
|
||||
lineColor: '#e1e4e8'
|
||||
}
|
||||
},
|
||||
headerRowHeight: 60,
|
||||
rowHeight: 40,
|
||||
|
||||
taskBar: {
|
||||
startDateField: 'start',
|
||||
endDateField: 'end',
|
||||
progressField: 'progress',
|
||||
labelText: '{title} {progress}%',
|
||||
labelTextStyle: {
|
||||
fontFamily: 'Arial',
|
||||
fontSize: 16,
|
||||
textAlign: 'left'
|
||||
},
|
||||
barStyle: {
|
||||
width: 20,
|
||||
/** 任务条的颜色 */
|
||||
barColor: '#ee8800',
|
||||
/** 已完成部分任务条的颜色 */
|
||||
completedBarColor: '#91e8e0',
|
||||
/** 任务条的圆角 */
|
||||
cornerRadius: 10
|
||||
},
|
||||
selectedBarStyle: {
|
||||
shadowBlur: 5, // 阴影宽度
|
||||
shadowOffsetX: 0, // x方向偏移
|
||||
shadowOffsetY: 0, // Y方向偏移
|
||||
shadowColor: 'black', // 阴影颜色
|
||||
borderColor: 'red', // 边框颜色
|
||||
borderLineWidth: 1 // 边框宽度
|
||||
}
|
||||
},
|
||||
timelineHeader: {
|
||||
verticalLine: {
|
||||
lineWidth: 1,
|
||||
lineColor: '#e1e4e8'
|
||||
},
|
||||
horizontalLine: {
|
||||
lineWidth: 1,
|
||||
lineColor: '#e1e4e8'
|
||||
},
|
||||
backgroundColor: '#EEF1F5',
|
||||
colWidth: 60,
|
||||
scales: [
|
||||
{
|
||||
unit: 'week',
|
||||
step: 1,
|
||||
startOfWeek: 'sunday',
|
||||
format(date: any) {
|
||||
return `Week ${date.dateIndex}`;
|
||||
},
|
||||
style: {
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
color: 'red'
|
||||
}
|
||||
},
|
||||
{
|
||||
unit: 'day',
|
||||
step: 1,
|
||||
format(date: any) {
|
||||
return date.dateIndex.toString();
|
||||
},
|
||||
style: {
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
color: 'red'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
minDate: '2024-07-14',
|
||||
maxDate: '2024-10-15',
|
||||
|
||||
rowSeriesNumber: {
|
||||
title: '行号',
|
||||
dragOrder: true
|
||||
},
|
||||
scrollStyle: {
|
||||
visible: 'scrolling'
|
||||
},
|
||||
overscrollBehavior: 'none'
|
||||
};
|
||||
|
||||
const barColors0 = ['#aecde6', '#c6a49a', '#ffb582', '#eec1de', '#b3d9b3', '#cccccc', '#e59a9c', '#d9d1a5', '#c9bede'];
|
||||
const barColors = ['#1f77b4', '#8c564b', '#ff7f0e', '#e377c2', '#2ca02c', '#7f7f7f', '#d62728', '#bcbd22', '#9467bd'];
|
||||
const customGanttColumns: VTableGantt.ColumnsDefine = [
|
||||
{
|
||||
field: 'title',
|
||||
title: 'TASK',
|
||||
width: '200',
|
||||
headerStyle: {
|
||||
textAlign: 'center',
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold'
|
||||
// color: 'black',
|
||||
// bgColor: '#f0f0fb'
|
||||
},
|
||||
style: {
|
||||
// bgColor: '#f0f0fb'
|
||||
},
|
||||
customLayout: (args: any) => {
|
||||
const { table, row, col, rect } = args;
|
||||
const taskRecord = table.getCellOriginRecord(col, row);
|
||||
const { height, width } = rect ?? table.getCellRect(col, row);
|
||||
const container = new VTableGantt.VRender.Group({
|
||||
y: 10,
|
||||
x: 20,
|
||||
height: height - 20,
|
||||
width: width - 40,
|
||||
fill: '#ddd',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
cornerRadius: 30
|
||||
});
|
||||
|
||||
const developer = new VTableGantt.VRender.Text({
|
||||
text: taskRecord.developer,
|
||||
fontSize: 16,
|
||||
fontFamily: 'sans-serif',
|
||||
fill: barColors[args.row],
|
||||
fontWeight: 'bold',
|
||||
maxLineWidth: width - 120,
|
||||
boundsPadding: [10, 0, 0, 0],
|
||||
alignSelf: 'center'
|
||||
});
|
||||
container.add(developer);
|
||||
|
||||
const days = new VTableGantt.VRender.Text({
|
||||
text: `${VTableGantt.tools.formatDate(new Date(taskRecord.start), 'mm/dd')}-${VTableGantt.tools.formatDate(
|
||||
new Date(taskRecord.end),
|
||||
'mm/dd'
|
||||
)}`,
|
||||
fontSize: 12,
|
||||
fontFamily: 'sans-serif',
|
||||
fontWeight: 'bold',
|
||||
fill: 'black',
|
||||
boundsPadding: [10, 0, 0, 0],
|
||||
alignSelf: 'center'
|
||||
});
|
||||
container.add(days);
|
||||
|
||||
return {
|
||||
rootContainer: container,
|
||||
expectedWidth: 160
|
||||
};
|
||||
}
|
||||
}
|
||||
];
|
||||
const customGanttOption: VTableGantt.GanttConstructorOptions = {
|
||||
records: customGanttRecords,
|
||||
taskListTable: {
|
||||
columns: customGanttColumns,
|
||||
tableWidth: 'auto'
|
||||
},
|
||||
frame: {
|
||||
outerFrameStyle: {
|
||||
borderLineWidth: 2,
|
||||
borderColor: '#E1E4E8',
|
||||
cornerRadius: 8
|
||||
}
|
||||
// verticalSplitLineHighlight: {
|
||||
// lineColor: 'green',
|
||||
// lineWidth: 3
|
||||
// }
|
||||
},
|
||||
grid: {
|
||||
// backgroundColor: '#f0f0fb',
|
||||
// vertical: {
|
||||
// lineWidth: 1,
|
||||
// lineColor: '#e1e4e8'
|
||||
// },
|
||||
horizontalLine: {
|
||||
lineWidth: 2,
|
||||
lineColor: '#d5d9ee'
|
||||
}
|
||||
},
|
||||
headerRowHeight: 60,
|
||||
rowHeight: 80,
|
||||
taskBar: {
|
||||
startDateField: 'start',
|
||||
endDateField: 'end',
|
||||
progressField: 'progress',
|
||||
barStyle: { width: 60 },
|
||||
customLayout: (args: any) => {
|
||||
const colorLength = barColors.length;
|
||||
const { width, height, index, taskDays, progress, taskRecord } = args;
|
||||
const container = new VTableGantt.VRender.Group({
|
||||
width,
|
||||
height,
|
||||
cornerRadius: 30,
|
||||
fill: {
|
||||
gradient: 'linear',
|
||||
x0: 0,
|
||||
y0: 0,
|
||||
x1: 1,
|
||||
y1: 0,
|
||||
stops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: barColors0[index % colorLength]
|
||||
},
|
||||
{
|
||||
offset: 0.5,
|
||||
color: barColors[index % colorLength]
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: barColors0[index % colorLength]
|
||||
}
|
||||
]
|
||||
},
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'nowrap'
|
||||
});
|
||||
const containerLeft = new VTableGantt.VRender.Group({
|
||||
height,
|
||||
width: 60,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-around'
|
||||
// fill: 'red'
|
||||
});
|
||||
container.add(containerLeft as any);
|
||||
|
||||
const avatar = new VTableGantt.VRender.Image({
|
||||
width: 50,
|
||||
height: 50,
|
||||
image: taskRecord.avatar,
|
||||
cornerRadius: 25
|
||||
});
|
||||
containerLeft.add(avatar);
|
||||
const containerCenter = new VTableGantt.VRender.Group({
|
||||
height,
|
||||
width: width - 120,
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
// alignItems: 'left'
|
||||
});
|
||||
container.add(containerCenter as any);
|
||||
|
||||
const developer = new VTableGantt.VRender.Text({
|
||||
text: taskRecord.developer,
|
||||
fontSize: 16,
|
||||
fontFamily: 'sans-serif',
|
||||
fill: 'white',
|
||||
fontWeight: 'bold',
|
||||
maxLineWidth: width - 120,
|
||||
boundsPadding: [10, 0, 0, 0]
|
||||
});
|
||||
containerCenter.add(developer);
|
||||
|
||||
const days = new VTableGantt.VRender.Text({
|
||||
text: `${taskDays}天`,
|
||||
fontSize: 13,
|
||||
fontFamily: 'sans-serif',
|
||||
fill: 'white',
|
||||
boundsPadding: [10, 0, 0, 0]
|
||||
});
|
||||
containerCenter.add(days);
|
||||
|
||||
if (width >= 120) {
|
||||
const containerRight = new VTableGantt.VRender.Group({
|
||||
cornerRadius: 20,
|
||||
fill: 'white',
|
||||
height: 40,
|
||||
width: 40,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center', // 垂直方向居中对齐
|
||||
boundsPadding: [10, 0, 0, 0]
|
||||
});
|
||||
container.add(containerRight as any);
|
||||
|
||||
const progressText = new VTableGantt.VRender.Text({
|
||||
text: `${progress}%`,
|
||||
fontSize: 12,
|
||||
fontFamily: 'sans-serif',
|
||||
fill: 'black',
|
||||
alignSelf: 'center',
|
||||
fontWeight: 'bold',
|
||||
maxLineWidth: (width - 60) / 2,
|
||||
boundsPadding: [0, 0, 0, 0]
|
||||
});
|
||||
containerRight.add(progressText);
|
||||
}
|
||||
return {
|
||||
rootContainer: container
|
||||
// renderDefaultBar: true
|
||||
// renderDefaultText: true
|
||||
};
|
||||
},
|
||||
hoverBarStyle: {
|
||||
cornerRadius: 30
|
||||
}
|
||||
},
|
||||
timelineHeader: {
|
||||
backgroundColor: '#f0f0fb',
|
||||
colWidth: 80,
|
||||
// verticalLine: {
|
||||
// lineColor: 'red',
|
||||
// lineWidth: 1,
|
||||
// lineDash: [4, 2]
|
||||
// },
|
||||
// horizontalLine: {
|
||||
// lineColor: 'green',
|
||||
// lineWidth: 1,
|
||||
// lineDash: [4, 2]
|
||||
// },
|
||||
scales: [
|
||||
{
|
||||
unit: 'day',
|
||||
step: 1,
|
||||
format(date: any) {
|
||||
return date.dateIndex.toString();
|
||||
},
|
||||
customLayout: (args: any) => {
|
||||
const { width, height, startDate, dateIndex } = args;
|
||||
const container = new VTableGantt.VRender.Group({
|
||||
width,
|
||||
height,
|
||||
// fill: '#f0f0fb',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'nowrap'
|
||||
});
|
||||
const containerLeft = new VTableGantt.VRender.Group({
|
||||
height,
|
||||
width: 30,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-around'
|
||||
// fill: 'red'
|
||||
});
|
||||
container.add(containerLeft as any);
|
||||
|
||||
const avatar = new VTableGantt.VRender.Image({
|
||||
width: 20,
|
||||
height: 30,
|
||||
image:
|
||||
'<svg t="1724675965803" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4299" width="200" height="200"><path d="M53.085678 141.319468C23.790257 141.319468 0 165.035326 0 194.34775L0 918.084273C0 947.295126 23.796789 971.112572 53.085678 971.112572L970.914322 971.112572C1000.209743 971.112572 1024 947.396696 1024 918.084273L1024 194.34775C1024 165.136896 1000.203211 141.319468 970.914322 141.319468L776.827586 141.319468 812.137931 176.629813 812.137931 88.275862C812.137931 68.774506 796.328942 52.965517 776.827586 52.965517 757.32623 52.965517 741.517241 68.774506 741.517241 88.275862L741.517241 176.629813 741.517241 211.940158 776.827586 211.940158 970.914322 211.940158C961.186763 211.940158 953.37931 204.125926 953.37931 194.34775L953.37931 918.084273C953.37931 908.344373 961.25643 900.491882 970.914322 900.491882L53.085678 900.491882C62.813237 900.491882 70.62069 908.306097 70.62069 918.084273L70.62069 194.34775C70.62069 204.087649 62.74357 211.940158 53.085678 211.940158L247.172414 211.940158C266.67377 211.940158 282.482759 196.131169 282.482759 176.629813 282.482759 157.128439 266.67377 141.319468 247.172414 141.319468L53.085678 141.319468ZM211.862069 176.629813C211.862069 196.131169 227.671058 211.940158 247.172414 211.940158 266.67377 211.940158 282.482759 196.131169 282.482759 176.629813L282.482759 88.275862C282.482759 68.774506 266.67377 52.965517 247.172414 52.965517 227.671058 52.965517 211.862069 68.774506 211.862069 88.275862L211.862069 176.629813ZM1024 353.181537 1024 317.871192 988.689655 317.871192 35.310345 317.871192 0 317.871192 0 353.181537 0 441.457399C0 460.958755 15.808989 476.767744 35.310345 476.767744 54.811701 476.767744 70.62069 460.958755 70.62069 441.457399L70.62069 353.181537 35.310345 388.491882 988.689655 388.491882 953.37931 353.181537 953.37931 441.457399C953.37931 460.958755 969.188299 476.767744 988.689655 476.767744 1008.191011 476.767744 1024 460.958755 1024 441.457399L1024 353.181537ZM776.937913 582.62069C796.439287 582.62069 812.248258 566.811701 812.248258 547.310345 812.248258 527.808989 796.439287 512 776.937913 512L247.172414 512C227.671058 512 211.862069 527.808989 211.862069 547.310345 211.862069 566.811701 227.671058 582.62069 247.172414 582.62069L776.937913 582.62069ZM247.172414 688.551724C227.671058 688.551724 211.862069 704.360713 211.862069 723.862069 211.862069 743.363425 227.671058 759.172414 247.172414 759.172414L600.386189 759.172414C619.887563 759.172414 635.696534 743.363425 635.696534 723.862069 635.696534 704.360713 619.887563 688.551724 600.386189 688.551724L247.172414 688.551724ZM776.827586 211.940158 741.517241 176.629813 741.517241 247.328574C741.517241 266.829948 757.32623 282.638919 776.827586 282.638919 796.328942 282.638919 812.137931 266.829948 812.137931 247.328574L812.137931 176.629813 812.137931 141.319468 776.827586 141.319468 247.172414 141.319468C227.671058 141.319468 211.862069 157.128439 211.862069 176.629813 211.862069 196.131169 227.671058 211.940158 247.172414 211.940158L776.827586 211.940158ZM282.482759 176.629813C282.482759 157.128439 266.67377 141.319468 247.172414 141.319468 227.671058 141.319468 211.862069 157.128439 211.862069 176.629813L211.862069 247.328574C211.862069 266.829948 227.671058 282.638919 247.172414 282.638919 266.67377 282.638919 282.482759 266.829948 282.482759 247.328574L282.482759 176.629813Z" fill="#389BFF" p-id="4300"></path></svg>'
|
||||
});
|
||||
containerLeft.add(avatar);
|
||||
|
||||
const containerCenter = new VTableGantt.VRender.Group({
|
||||
height,
|
||||
width: width - 30,
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
// alignItems: 'left'
|
||||
});
|
||||
container.add(containerCenter as any);
|
||||
const dayNumber = new VTableGantt.VRender.Text({
|
||||
text: String(dateIndex).padStart(2, '0'),
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
fontFamily: 'sans-serif',
|
||||
fill: '#777',
|
||||
textAlign: 'right',
|
||||
maxLineWidth: width - 30,
|
||||
boundsPadding: [15, 0, 0, 0]
|
||||
});
|
||||
containerCenter.add(dayNumber);
|
||||
|
||||
const weekDay = new VTableGantt.VRender.Text({
|
||||
text: VTableGantt.tools.getWeekday(startDate, 'short').toLocaleUpperCase(),
|
||||
fontSize: 12,
|
||||
fontFamily: 'sans-serif',
|
||||
fill: '#777',
|
||||
boundsPadding: [0, 0, 0, 0]
|
||||
});
|
||||
containerCenter.add(weekDay);
|
||||
return {
|
||||
rootContainer: container
|
||||
// renderDefaultText: true
|
||||
};
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
minDate: '2024-07-20',
|
||||
maxDate: '2024-08-15',
|
||||
markLine: [
|
||||
{
|
||||
date: '2024-07-29',
|
||||
style: {
|
||||
lineWidth: 1,
|
||||
lineColor: 'blue',
|
||||
lineDash: [8, 4]
|
||||
}
|
||||
},
|
||||
{
|
||||
date: '2024-08-17',
|
||||
style: {
|
||||
lineWidth: 2,
|
||||
lineColor: 'red',
|
||||
lineDash: [8, 4]
|
||||
}
|
||||
}
|
||||
],
|
||||
scrollStyle: {
|
||||
scrollRailColor: 'RGBA(246,246,246,0.5)',
|
||||
visible: 'focus',
|
||||
width: 6,
|
||||
scrollSliderCornerRadius: 2,
|
||||
scrollSliderColor: '#5cb85c'
|
||||
}
|
||||
};
|
||||
|
||||
function initVTableGantt() {
|
||||
basicGanttInstance.value = new VTableGantt.Gantt(basicGanttDomRef.value as HTMLElement, getOption(basicGanttOption));
|
||||
linkGanttInstance.value = new VTableGantt.Gantt(linkGanttDomRef.value as HTMLElement, getOption(linkGanttOption));
|
||||
customGanttInstance.value = new VTableGantt.Gantt(
|
||||
customGanttDomRef.value as HTMLElement,
|
||||
getOption(customGanttOption)
|
||||
);
|
||||
}
|
||||
|
||||
function getOption(option: VTableGantt.GanttConstructorOptions) {
|
||||
const isDark = theme.darkMode;
|
||||
if (isDark) {
|
||||
option.taskListTable!.theme = VTableGantt.VTable.themes.DARK;
|
||||
option.timelineHeader.backgroundColor = '#212121';
|
||||
option.underlayBackgroundColor = '#000';
|
||||
} else {
|
||||
option.taskListTable!.theme = VTableGantt.VTable.themes.DEFAULT;
|
||||
option.timelineHeader.backgroundColor = '#f0f0fb';
|
||||
option.underlayBackgroundColor = '#fff';
|
||||
}
|
||||
|
||||
return option;
|
||||
}
|
||||
|
||||
const stopHandle = watch(
|
||||
() => theme.darkMode,
|
||||
_newValue => {
|
||||
basicGanttInstance.value?.release();
|
||||
linkGanttInstance.value?.release();
|
||||
customGanttInstance.value?.release();
|
||||
|
||||
initVTableGantt();
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
initVTableGantt();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
stopHandle();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-full">
|
||||
<NSpace vertical :size="16">
|
||||
<NCard :bordered="false" class="h-full w-2/3 card-wrapper">
|
||||
<div ref="basicGanttDomRef" class="relative h-400px"></div>
|
||||
</NCard>
|
||||
<NCard :bordered="false" class="h-full w-2/3 card-wrapper">
|
||||
<div ref="linkGanttDomRef" class="relative h-400px"></div>
|
||||
</NCard>
|
||||
<NCard :bordered="false" class="h-full w-2/3 card-wrapper">
|
||||
<div ref="customGanttDomRef" class="relative h-400px"></div>
|
||||
</NCard>
|
||||
<NCard :bordered="false" class="h-full w-2/3 card-wrapper">
|
||||
<WebSiteLink label="More VTableGantt Demos: " link="https://www.visactor.com/vtable/example" />
|
||||
</NCard>
|
||||
</NSpace>
|
||||
</div>
|
||||
</template>
|
1044
src/views/plugin/tables/vtable/data.ts
Normal file
1044
src/views/plugin/tables/vtable/data.ts
Normal file
File diff suppressed because it is too large
Load Diff
408
src/views/plugin/tables/vtable/index.vue
Normal file
408
src/views/plugin/tables/vtable/index.vue
Normal file
@ -0,0 +1,408 @@
|
||||
<script setup lang="tsx">
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import {
|
||||
Group,
|
||||
Image,
|
||||
ListColumn,
|
||||
ListTable,
|
||||
Menu,
|
||||
PivotChart,
|
||||
PivotColumnDimension,
|
||||
PivotCorner,
|
||||
PivotIndicator,
|
||||
PivotRowDimension,
|
||||
PivotTable,
|
||||
Tag,
|
||||
Text,
|
||||
VTable,
|
||||
registerChartModule
|
||||
} from '@visactor/vue-vtable';
|
||||
import VChart from '@visactor/vchart';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { customListRecords, listTableRecords, pivotChartColumns, pivotChartIndicators, pivotChartRows } from './data';
|
||||
|
||||
registerChartModule('vchart', VChart);
|
||||
const titleColorPool = ['#3370ff', '#34c724', '#ff9f1a', '#ff4050', '#1f2329'];
|
||||
|
||||
const themeStore = useThemeStore();
|
||||
|
||||
// list table
|
||||
const listTableRef = ref(null);
|
||||
const listOptions = computed(() => {
|
||||
const options = {
|
||||
theme: themeStore.darkMode ? VTable.themes.DARK : VTable.themes.DEFAULT
|
||||
};
|
||||
return options;
|
||||
});
|
||||
const listRecords = ref<Record<string, string | number>[]>(listTableRecords);
|
||||
|
||||
// group table
|
||||
const groupTableRef = ref(null);
|
||||
const groupOptions = computed(() => {
|
||||
const options = {
|
||||
groupBy: ['Category', 'Sub-Category'],
|
||||
theme: (themeStore.darkMode ? VTable.themes.DARK : VTable.themes.DEFAULT).extends({
|
||||
groupTitleStyle: {
|
||||
fontWeight: 'bold',
|
||||
bgColor: (args: any) => {
|
||||
const { col, row, table } = args;
|
||||
const index = table.getGroupTitleLevel(col, row);
|
||||
if (index !== undefined) {
|
||||
return titleColorPool[index % titleColorPool.length] as string;
|
||||
}
|
||||
return 'white';
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
return options;
|
||||
});
|
||||
const groupRecords = ref<Record<string, string | number>[]>(listTableRecords);
|
||||
|
||||
// pivot table
|
||||
const pivotTableRef = ref(null);
|
||||
const pivotTableOptions = computed(() => {
|
||||
return {
|
||||
tooltip: {
|
||||
isShowOverflowTextTooltip: true
|
||||
},
|
||||
dataConfig: {
|
||||
sortRules: [
|
||||
{
|
||||
sortField: 'Category',
|
||||
sortBy: ['Office Supplies', 'Technology', 'Furniture']
|
||||
}
|
||||
]
|
||||
},
|
||||
widthMode: 'standard',
|
||||
theme: themeStore.darkMode ? VTable.themes.DARK : VTable.themes.DEFAULT,
|
||||
emptyTip: {
|
||||
text: 'no data records'
|
||||
}
|
||||
};
|
||||
});
|
||||
const pivotTableIndicators = ref([
|
||||
{
|
||||
indicatorKey: 'Quantity',
|
||||
title: 'Quantity',
|
||||
width: 'auto',
|
||||
showSort: false,
|
||||
headerStyle: { fontWeight: 'normal' },
|
||||
style: {
|
||||
padding: [16, 28, 16, 28],
|
||||
color(args: any) {
|
||||
return args.dataValue >= 0 ? 'black' : 'red';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
indicatorKey: 'Sales',
|
||||
title: 'Sales',
|
||||
width: 'auto',
|
||||
showSort: false,
|
||||
headerStyle: { fontWeight: 'normal' },
|
||||
format: (rec: string) => `$${Number(rec).toFixed(2)}`,
|
||||
style: {
|
||||
padding: [16, 28, 16, 28],
|
||||
color(args: any) {
|
||||
return args.dataValue >= 0 ? 'black' : 'red';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
indicatorKey: 'Profit',
|
||||
title: 'Profit',
|
||||
width: 'auto',
|
||||
showSort: false,
|
||||
headerStyle: { fontWeight: 'normal' },
|
||||
format: (rec: string) => `$${Number(rec).toFixed(2)}`,
|
||||
style: {
|
||||
padding: [16, 28, 16, 28],
|
||||
color(args: any) {
|
||||
return args.dataValue >= 0 ? 'black' : 'red';
|
||||
}
|
||||
}
|
||||
}
|
||||
]);
|
||||
const pivotTableRows = ref([
|
||||
{
|
||||
dimensionKey: 'City',
|
||||
title: 'City',
|
||||
headerStyle: { textStick: true },
|
||||
width: 'auto'
|
||||
}
|
||||
]);
|
||||
const pivotTableRecords = ref([]);
|
||||
|
||||
// pivot chart
|
||||
const pivotChartRef = ref(null);
|
||||
const pivotChartOptions = computed(() => {
|
||||
return {
|
||||
rows: pivotChartRows,
|
||||
columns: pivotChartColumns,
|
||||
indicators: pivotChartIndicators,
|
||||
indicatorsAsCol: false,
|
||||
defaultRowHeight: 200,
|
||||
defaultHeaderRowHeight: 50,
|
||||
defaultColWidth: 280,
|
||||
defaultHeaderColWidth: 100,
|
||||
indicatorTitle: '指标',
|
||||
autoWrapText: true,
|
||||
corner: {
|
||||
titleOnDimension: 'row',
|
||||
headerStyle: { autoWrapText: true }
|
||||
},
|
||||
legends: {
|
||||
orient: 'bottom',
|
||||
type: 'discrete',
|
||||
data: [
|
||||
{ label: 'Consumer-Quantity', shape: { fill: '#2E62F1', symbolType: 'circle' } },
|
||||
{ label: 'Consumer-Quantity', shape: { fill: '#4DC36A', symbolType: 'square' } },
|
||||
{ label: 'Home Office-Quantity', shape: { fill: '#FF8406', symbolType: 'square' } },
|
||||
{ label: 'Consumer-Sales', shape: { fill: '#FFCC00', symbolType: 'square' } },
|
||||
{ label: 'Consumer-Sales', shape: { fill: '#4F44CF', symbolType: 'square' } },
|
||||
{ label: 'Home Office-Sales', shape: { fill: '#5AC8FA', symbolType: 'square' } },
|
||||
{ label: 'Consumer-Profit', shape: { fill: '#003A8C', symbolType: 'square' } },
|
||||
{ label: 'Consumer-Profit', shape: { fill: '#B08AE2', symbolType: 'square' } },
|
||||
{ label: 'Home Office-Profit', shape: { fill: '#FF6341', symbolType: 'square' } }
|
||||
]
|
||||
},
|
||||
theme: (themeStore.darkMode ? VTable.themes.DARK : VTable.themes.DEFAULT).extends({
|
||||
bodyStyle: { borderColor: 'gray', borderLineWidth: [1, 0, 0, 1] },
|
||||
headerStyle: { borderColor: 'gray', borderLineWidth: [0, 0, 1, 1], hover: { cellBgColor: '#CCE0FF' } },
|
||||
rowHeaderStyle: { borderColor: 'gray', borderLineWidth: [1, 1, 0, 0], hover: { cellBgColor: '#CCE0FF' } },
|
||||
cornerHeaderStyle: { borderColor: 'gray', borderLineWidth: [0, 1, 1, 0], hover: { cellBgColor: '' } },
|
||||
cornerRightTopCellStyle: { borderColor: 'gray', borderLineWidth: [0, 0, 1, 1], hover: { cellBgColor: '' } },
|
||||
cornerLeftBottomCellStyle: { borderColor: 'gray', borderLineWidth: [1, 1, 0, 0], hover: { cellBgColor: '' } },
|
||||
cornerRightBottomCellStyle: { borderColor: 'gray', borderLineWidth: [1, 0, 0, 1], hover: { cellBgColor: '' } },
|
||||
rightFrozenStyle: { borderColor: 'gray', borderLineWidth: [1, 0, 1, 1], hover: { cellBgColor: '' } },
|
||||
bottomFrozenStyle: { borderColor: 'gray', borderLineWidth: [1, 1, 0, 1], hover: { cellBgColor: '' } },
|
||||
selectionStyle: { cellBgColor: '', cellBorderColor: '' },
|
||||
frameStyle: { borderLineWidth: 0 }
|
||||
}),
|
||||
emptyTip: {
|
||||
text: 'no data records'
|
||||
}
|
||||
};
|
||||
});
|
||||
const pivotChartRecords = ref({} as any);
|
||||
const handleLegendItemClick = (args: { value: any }) => {
|
||||
(pivotChartRef?.value as any)?.vTableInstance.updateFilterRules([
|
||||
{
|
||||
filterKey: 'Segment-Indicator',
|
||||
filteredValues: args.value
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
// custom layout list table
|
||||
const customLayoutListTableRef = ref(null);
|
||||
const customLayoutListTableOptions = computed(() => {
|
||||
return {
|
||||
defaultRowHeight: 80,
|
||||
theme: themeStore.darkMode ? VTable.themes.DARK : VTable.themes.DEFAULT
|
||||
};
|
||||
});
|
||||
const customLayoutListTableRecords = ref(customListRecords);
|
||||
const customLayoutListTableColumnStyle = ref({ fontFamily: 'Arial', fontSize: 12, fontWeight: 'bold' });
|
||||
|
||||
onMounted(() => {
|
||||
// pivot tablt records
|
||||
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_data.json')
|
||||
.then(res => res.json())
|
||||
.then(jsonData => {
|
||||
// update record
|
||||
pivotTableRecords.value = jsonData;
|
||||
});
|
||||
|
||||
// pivot chart records
|
||||
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
// update record
|
||||
pivotChartRecords.value = data;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-full">
|
||||
<NSpace vertical :size="16">
|
||||
<NCard title="List Table" :bordered="false" class="h-full w-2/3 card-wrapper">
|
||||
<ListTable ref="listTableRef" :options="listOptions" :records="listRecords" height="400px">
|
||||
<ListColumn field="Order ID" title="Order ID" width="auto" />
|
||||
<ListColumn field="Customer ID" title="Customer ID" width="auto" />
|
||||
<ListColumn field="Product Name" title="Product Name" width="auto" />
|
||||
<ListColumn field="Category" title="Category" width="auto" />
|
||||
<ListColumn field="Sub-Category" title="Sub-Category" width="auto" />
|
||||
<ListColumn field="Region" title="Region" width="auto" />
|
||||
<ListColumn field="City" title="City" width="auto" />
|
||||
<ListColumn field="Order Date" title="Order Date" width="auto" />
|
||||
<ListColumn field="Quantity" title="Quantity" width="auto" />
|
||||
<ListColumn field="Sales" title="Sales" width="auto" />
|
||||
<ListColumn field="Profit" title="Profit" width="auto" />
|
||||
</ListTable>
|
||||
</NCard>
|
||||
|
||||
<NCard title="Group Table" :bordered="false" class="h-full w-2/3 card-wrapper">
|
||||
<ListTable ref="groupTableRef" :options="groupOptions" :records="groupRecords" height="400px">
|
||||
<ListColumn field="Order ID" title="Order ID" width="auto" />
|
||||
<ListColumn field="Customer ID" title="Customer ID" width="auto" />
|
||||
<ListColumn field="Product Name" title="Product Name" width="auto" />
|
||||
<ListColumn field="Category" title="Category" width="auto" />
|
||||
<ListColumn field="Sub-Category" title="Sub-Category" width="auto" />
|
||||
<ListColumn field="Region" title="Region" width="auto" />
|
||||
<ListColumn field="City" title="City" width="auto" />
|
||||
<ListColumn field="Order Date" title="Order Date" width="auto" />
|
||||
<ListColumn field="Quantity" title="Quantity" width="auto" />
|
||||
<ListColumn field="Sales" title="Sales" width="auto" />
|
||||
<ListColumn field="Profit" title="Profit" width="auto" />
|
||||
</ListTable>
|
||||
</NCard>
|
||||
|
||||
<NCard title="Pivot Table" :bordered="false" class="h-full w-2/3 card-wrapper">
|
||||
<PivotTable ref="pivotTableRef" :options="pivotTableOptions" :records="pivotTableRecords" height="400px">
|
||||
<PivotColumnDimension
|
||||
title="Category"
|
||||
dimension-key="Category"
|
||||
:header-style="{ textStick: true }"
|
||||
width="auto"
|
||||
/>
|
||||
<PivotRowDimension
|
||||
v-for="(row, index) in pivotTableRows"
|
||||
:key="index"
|
||||
:dimension-key="row.dimensionKey"
|
||||
:title="row.title"
|
||||
:header-style="row.headerStyle"
|
||||
:width="row.width"
|
||||
/>
|
||||
<PivotIndicator
|
||||
v-for="(indicator, index) in pivotTableIndicators"
|
||||
:key="index"
|
||||
:indicator-key="indicator.indicatorKey"
|
||||
:title="indicator.title"
|
||||
:width="indicator.width"
|
||||
:show-sort="indicator.showSort"
|
||||
:header-style="indicator.headerStyle"
|
||||
:format="indicator.format"
|
||||
:style="indicator.style"
|
||||
/>
|
||||
<PivotCorner title-on-dimension="row" />
|
||||
<Menu menu-type="html" :context-menu-items="['copy', 'paste', 'delete', '...']" />
|
||||
</PivotTable>
|
||||
</NCard>
|
||||
|
||||
<NCard title="Pivot Chart" :bordered="false" class="h-full w-2/3 card-wrapper">
|
||||
<PivotChart
|
||||
ref="pivotChartRef"
|
||||
:options="pivotChartOptions"
|
||||
:records="pivotChartRecords"
|
||||
height="800px"
|
||||
@on-legend-item-click="handleLegendItemClick"
|
||||
/>
|
||||
</NCard>
|
||||
|
||||
<NCard title="Custom Component" :bordered="false" class="h-full w-2/3 card-wrapper">
|
||||
<ListTable
|
||||
ref="customLayoutListTableRef"
|
||||
:options="customLayoutListTableOptions"
|
||||
:records="customLayoutListTableRecords"
|
||||
height="400px"
|
||||
>
|
||||
<!-- Order Number Column -->
|
||||
<ListColumn field="bloggerId" title="Order Number" width="100" />
|
||||
|
||||
<!-- Anchor Nickname Column with Custom Layout -->
|
||||
<ListColumn field="bloggerName" title="Anchor Nickname" :width="330">
|
||||
<template #customLayout="{ record, height, width }">
|
||||
<Group :height="height" :width="width" display="flex" flex-direction="row" flex-wrap="nowrap">
|
||||
<!-- Avatar Group -->
|
||||
<Group
|
||||
:height="height"
|
||||
:width="60"
|
||||
display="flex"
|
||||
flex-direction="column"
|
||||
align-items="center"
|
||||
justify-content="space-around"
|
||||
fill="red"
|
||||
:opacity="0.1"
|
||||
>
|
||||
<Image id="icon0" :width="50" :height="50" :image="record.bloggerAvatar" :corner-radius="25" />
|
||||
</Group>
|
||||
<!-- Blogger Info Group -->
|
||||
<Group :height="height" :width="width - 60" display="flex" flex-direction="column" flex-wrap="nowrap">
|
||||
<Group
|
||||
:height="height / 2"
|
||||
:width="width - 60"
|
||||
display="flex"
|
||||
flex-wrap="wrap"
|
||||
align-items="center"
|
||||
fill="orange"
|
||||
:opacity="0.1"
|
||||
>
|
||||
<Text
|
||||
:text="record.bloggerName"
|
||||
:font-size="13"
|
||||
font-family="sans-serif"
|
||||
fill="black"
|
||||
:bounds-padding="[0, 0, 0, 10]"
|
||||
/>
|
||||
<Image
|
||||
id="location"
|
||||
image="https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/location.svg"
|
||||
:width="15"
|
||||
:height="15"
|
||||
:bounds-padding="[0, 0, 0, 10]"
|
||||
cursor="pointer"
|
||||
/>
|
||||
<Text :text="record.city" :font-size="11" font-family="sans-serif" fill="#6f7070" />
|
||||
</Group>
|
||||
<!-- Tags Group -->
|
||||
<Group
|
||||
:height="height / 2"
|
||||
:width="width - 60"
|
||||
display="flex"
|
||||
align-items="center"
|
||||
fill="yellow"
|
||||
:opacity="0.1"
|
||||
>
|
||||
<Tag
|
||||
v-for="tag in record?.tags"
|
||||
:key="tag"
|
||||
:text="tag"
|
||||
:text-style="{ fontSize: 10, fontFamily: 'sans-serif', fill: 'rgb(51, 101, 238)' }"
|
||||
:panel="{ visible: true, fill: '#f4f4f2', cornerRadius: 5 }"
|
||||
:space="5"
|
||||
:bounds-padding="[0, 0, 0, 5]"
|
||||
/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</template>
|
||||
</ListColumn>
|
||||
|
||||
<!-- Other Columns -->
|
||||
<ListColumn
|
||||
field="fansCount"
|
||||
title="Fans Count"
|
||||
width="120"
|
||||
:field-format="rec => rec.fansCount + 'w'"
|
||||
:style="customLayoutListTableColumnStyle"
|
||||
/>
|
||||
<ListColumn field="worksCount" title="Works Count" :style="customLayoutListTableColumnStyle" width="135" />
|
||||
<ListColumn
|
||||
field="viewCount"
|
||||
title="View Count"
|
||||
width="120"
|
||||
:field-format="rec => rec.viewCount + 'w'"
|
||||
:style="customLayoutListTableColumnStyle"
|
||||
/>
|
||||
</ListTable>
|
||||
</NCard>
|
||||
|
||||
<NCard :bordered="false" class="h-full w-2/3 card-wrapper">
|
||||
<WebSiteLink label="More VTable Demos: " link="https://www.visactor.com/vtable/example" />
|
||||
</NCard>
|
||||
</NSpace>
|
||||
</div>
|
||||
</template>
|
Loading…
Reference in New Issue
Block a user