refactor(chart): enforce 400-line source limit
Some checks failed
Package component / package (push) Failing after 4m19s

This commit is contained in:
liqiyuan
2026-07-27 15:05:13 +08:00
parent dcc27a88be
commit 082462cf67
61 changed files with 9682 additions and 8407 deletions

View File

@@ -0,0 +1,55 @@
<script setup lang="ts">
import { ref } from 'vue'
import { WaveformChart } from '../components'
import type { DemoChartModel } from './types'
const model = defineModel<DemoChartModel>('model', { required: true })
const waveformChartRef = ref<{ resetViewport: (trackIndex?: number) => void }>()
function resetViewport() {
waveformChartRef.value?.resetViewport()
}
defineExpose({ resetViewport })
</script>
<template>
<section class="chart-panel">
<WaveformChart
ref="waveformChartRef"
v-model:annotations="model.annotations"
v-model:hidden-series-ids="model.hiddenSeriesIds"
:data="model.data"
:min-zoom-span="model.minZoomSpan"
:min-visible-points="5"
:initial-x-domain="model.initialXDomain"
:display-mode="model.displayMode"
:overlay-mode="model.overlayMode"
:grid="{
rowCount: model.rowCount,
columnCount: model.columnCount,
showPagination: true,
trackLines: model.gridTrackLines,
}"
:title="model.title"
:legend="{
position: model.legendPosition,
orientation: model.legendOrientation,
backgroundColor: model.legendBackgroundColor,
interactive: true,
}"
:frame-style="model.frameStyle"
:axes="model.axes"
:clean-view="model.cleanView"
:show-tooltip="model.showTooltip"
:zero-line="model.zeroLine"
:frame-number="model.frameWatermarkVisible ? 1 : undefined"
:annotations-visible="model.annotationsVisible"
:interaction-mode="model.interactionMode"
@zoom-end="model.handleZoomEnd"
@zoom-reset="model.resetWaveformViewport"
/>
</section>
</template>

View File

@@ -0,0 +1,44 @@
<script setup lang="ts">
import { Button } from 'ant-design-vue'
import DemoGridFrameControls from './DemoGridFrameControls.vue'
import DemoTitleLegendControls from './DemoTitleLegendControls.vue'
import DemoViewControls from './DemoViewControls.vue'
import type { DemoControlPanelModel } from './types'
const model = defineModel<DemoControlPanelModel>('model', { required: true })
</script>
<template>
<Button
class="mobile-control-toggle"
size="small"
:aria-expanded="model.controlsOpen"
aria-controls="waveform-control-panel"
@click="model.controlsOpen = true"
>
控制面板
</Button>
<button
v-if="model.controlsOpen"
type="button"
class="control-backdrop"
aria-label="关闭控制面板"
@click="model.closeControls"
/>
<aside
id="waveform-control-panel"
class="control-panel"
:class="{ 'is-open': model.controlsOpen }"
aria-label="波形图控制"
>
<div class="control-panel__scroll">
<Button class="control-panel__close" type="text" size="small" @click="model.closeControls">
关闭
</Button>
<DemoViewControls :model="model" />
<DemoGridFrameControls :model="model" />
<DemoTitleLegendControls :model="model" />
</div>
</aside>
</template>

View File

@@ -0,0 +1,157 @@
<script setup lang="ts">
import { InputNumber, Select, Switch } from 'ant-design-vue'
import { ColorPicker } from 'vue3-colorpicker'
import type { DemoControlPanelModel } from './types'
const model = defineModel<DemoControlPanelModel>('model', { required: true })
</script>
<template>
<section class="control-section">
<div class="control-section__header">
<h2>零值参考线</h2>
<Switch v-model:checked="model.zeroLineVisible" size="small" aria-label="显示零值参考线" />
</div>
<div class="auxiliary-style-controls zero-line-controls" style="margin-top: 10px">
<label class="frame-style-control">
<span>颜色</span>
<ColorPicker
v-model:pure-color="model.zeroLineColor"
aria-label="零值参考线颜色"
use-type="pure"
picker-type="chrome"
format="hex"
:disable-alpha="true"
:blur-close="true"
/>
</label>
<label class="frame-style-control">
<span>线宽</span>
<InputNumber
v-model:value="model.zeroLineWidth"
:min="0.5"
:max="10"
:step="0.5"
size="small"
aria-label="零值参考线线宽"
/>
</label>
<label class="frame-style-control">
<span>线型</span>
<Select
v-model:value="model.zeroLineDash"
:options="model.zeroLineDashOptions"
size="small"
aria-label="零值参考线线型"
/>
</label>
</div>
</section>
<section class="control-section">
<h2>网格与轴线</h2>
<div class="grid-line-controls">
<div class="grid-line-control">
<span>水平网格</span>
<Switch
v-model:checked="model.horizontalGridVisible"
size="small"
aria-label="显示水平网格线"
/>
<span class="grid-line-color-picker" role="group" aria-label="水平网格线颜色">
<ColorPicker
v-model:pure-color="model.horizontalGridColor"
use-type="pure"
picker-type="chrome"
format="hex"
:disable-alpha="true"
:blur-close="true"
/>
</span>
</div>
<div class="grid-line-control">
<span>垂直网格</span>
<Switch
v-model:checked="model.verticalGridVisible"
size="small"
aria-label="显示垂直网格线"
/>
<span class="grid-line-color-picker" role="group" aria-label="垂直网格线颜色">
<ColorPicker
v-model:pure-color="model.verticalGridColor"
use-type="pure"
picker-type="chrome"
format="hex"
:disable-alpha="true"
:blur-close="true"
/>
</span>
</div>
<div class="grid-line-control grid-line-control--switch-only">
<span>横轴线</span>
<Switch v-model:checked="model.xAxisLineVisible" size="small" aria-label="显示横轴线" />
</div>
<div class="grid-line-control grid-line-control--switch-only">
<span>纵轴线</span>
<Switch v-model:checked="model.yAxisLineVisible" size="small" aria-label="显示纵轴线" />
</div>
</div>
</section>
<section class="control-section">
<h2>图框样式</h2>
<div class="frame-style-controls">
<label class="frame-style-control">
<span>边框颜色</span>
<ColorPicker
v-model:pure-color="model.frameBorderColor"
aria-label="图框边框颜色"
use-type="pure"
picker-type="chrome"
format="rgb"
:disable-alpha="false"
:blur-close="true"
/>
</label>
<label class="frame-style-control">
<span>背景颜色</span>
<ColorPicker
v-model:pure-color="model.frameBackgroundColor"
aria-label="图框背景颜色"
use-type="pure"
picker-type="chrome"
format="rgb"
:disable-alpha="false"
:blur-close="true"
/>
</label>
<label class="frame-style-control">
<span>线宽</span>
<InputNumber
v-model:value="model.frameBorderWidth"
:min="0"
:max="10"
:step="0.5"
size="small"
aria-label="图框线宽"
/>
</label>
<label class="frame-style-control">
<span>线型</span>
<Select
v-model:value="model.frameBorderStyle"
:options="model.frameBorderStyleOptions"
size="small"
aria-label="图框线型"
/>
</label>
<label class="frame-style-control frame-style-control--switch">
<span>水印</span>
<Switch
v-model:checked="model.frameWatermarkVisible"
size="small"
aria-label="显示图框水印"
/>
</label>
</div>
</section>
</template>

View File

@@ -0,0 +1,152 @@
<script setup lang="ts">
import { Input, InputNumber, Select, Switch } from 'ant-design-vue'
import { ColorPicker } from 'vue3-colorpicker'
import type { DemoControlPanelModel } from './types'
const model = defineModel<DemoControlPanelModel>('model', { required: true })
</script>
<template>
<section class="control-section title-control-section">
<div class="control-section__header">
<h2>标题</h2>
<Switch v-model:checked="model.titleVisible" size="small" aria-label="显示标题" />
</div>
<div class="title-controls">
<label class="title-control title-control--wide">
<span>标题名称</span>
<Input v-model:value="model.titleText" size="small" aria-label="标题名称" />
</label>
<label class="title-control title-control--wide">
<span>对齐方式</span>
<Select
v-model:value="model.titleAlign"
:options="model.titleAlignOptions"
size="small"
aria-label="标题对齐方式"
/>
</label>
<label class="title-control">
<span>字体</span>
<Select
v-model:value="model.titleFontFamily"
:options="model.titleFontFamilyOptions"
size="small"
aria-label="标题字体"
/>
</label>
<label class="title-control">
<span>字号</span>
<InputNumber
v-model:value="model.titleFontSize"
:min="8"
:max="72"
:step="1"
size="small"
aria-label="标题字号"
/>
</label>
<div class="title-control">
<span>字体样式</span>
<div class="title-style-controls" role="group" aria-label="标题字体样式">
<button
type="button"
aria-label="恢复标题常规样式"
title="恢复常规样式"
@click="model.resetTitleTextStyle"
>
A
</button>
<button
type="button"
:class="{ 'is-active': model.titleBold }"
:aria-pressed="model.titleBold"
aria-label="标题粗体"
title="粗体"
@click="model.titleBold = !model.titleBold"
>
<b>B</b>
</button>
<button
type="button"
:class="{ 'is-active': model.titleItalic }"
:aria-pressed="model.titleItalic"
aria-label="标题斜体"
title="斜体"
@click="model.titleItalic = !model.titleItalic"
>
<i>I</i>
</button>
<button
type="button"
:class="{ 'is-active': model.titleUnderline }"
:aria-pressed="model.titleUnderline"
aria-label="标题下划线"
title="下划线"
@click="model.titleUnderline = !model.titleUnderline"
>
<u>U</u>
</button>
</div>
</div>
<label class="title-control">
<span>旋转</span>
<InputNumber
v-model:value="model.titleRotation"
:min="-180"
:max="180"
:step="1"
addon-after="°"
size="small"
aria-label="标题旋转角度"
/>
</label>
<div class="title-control title-control--color">
<span>颜色</span>
<ColorPicker
v-model:pure-color="model.titleColor"
aria-label="标题颜色"
use-type="pure"
picker-type="chrome"
format="hex"
:disable-alpha="true"
:blur-close="true"
/>
</div>
</div>
</section>
<section class="control-section">
<h2>图例</h2>
<label class="select-control">
<span>位置</span>
<Select
v-model:value="model.legendPosition"
:options="model.legendPositionOptions"
size="small"
aria-label="图例位置"
/>
</label>
<label class="select-control">
<span>排列</span>
<Select
v-model:value="model.legendOrientation"
:options="model.legendOrientationOptions"
size="small"
aria-label="图例排列"
/>
</label>
<label class="legend-color-control">
<span>背景</span>
<ColorPicker
v-model:pure-color="model.legendBackgroundColor"
aria-label="图例背景颜色"
use-type="pure"
picker-type="chrome"
format="rgb"
:disable-alpha="false"
:blur-close="true"
/>
</label>
</section>
</template>

View File

@@ -0,0 +1,82 @@
<script setup lang="ts">
import { Button, InputNumber, Radio, Select, Switch } from 'ant-design-vue'
import type { DemoControlPanelModel } from './types'
const model = defineModel<DemoControlPanelModel>('model', { required: true })
</script>
<template>
<section class="control-section">
<h2>显示方式</h2>
<Radio.Group
v-model:value="model.displayMode"
class="display-mode-control"
button-style="solid"
size="small"
aria-label="波形展示方式"
>
<Radio.Button value="independent">单独坐标</Radio.Button>
<Radio.Button value="separated">多道分离</Radio.Button>
<Radio.Button value="compact">多道紧凑</Radio.Button>
</Radio.Group>
</section>
<section class="control-section">
<h2>叠加方式</h2>
<Radio.Group
v-model:value="model.overlayMode"
class="display-mode-control"
button-style="solid"
size="small"
aria-label="波形叠加方式"
>
<Radio.Button value="single-axis">单值轴</Radio.Button>
<Radio.Button value="multi-axis">多值轴</Radio.Button>
</Radio.Group>
</section>
<section class="control-section">
<h2>视图</h2>
<Button block aria-label="重置波形视图" @click="model.resetWaveformViewport"> 重置视图 </Button>
<div class="auxiliary-style-controls" style="margin-top: 10px">
<label class="frame-style-control frame-style-control--switch">
<span>数值 Tooltip</span>
<Switch v-model:checked="model.showTooltip" size="small" aria-label="显示数值 Tooltip" />
</label>
<label class="frame-style-control frame-style-control--switch">
<span>净图</span>
<Switch v-model:checked="model.cleanView" size="small" aria-label="净图模式" />
</label>
</div>
</section>
<section class="control-section">
<h2>波形线型</h2>
<label class="select-control">
<span>波形</span>
<Select
v-model:value="model.selectedSeriesId"
:options="model.seriesStyleOptions"
size="small"
aria-label="选择波形线型"
/>
</label>
<label class="select-control">
<span>线型</span>
<Select
v-model:value="model.selectedLineStyle"
:options="model.lineStyleOptions"
size="small"
aria-label="设置波形线型"
/>
</label>
</section>
<section class="control-section">
<h2>图框布局</h2>
<div class="grid-size-control" aria-label="波形网格尺寸">
<InputNumber v-model:value="model.rowCount" :min="1" :max="10" size="small" />
<span></span>
<span class="control-separator">×</span>
<InputNumber v-model:value="model.columnCount" :min="1" :max="10" size="small" />
<span></span>
</div>
</section>
</template>

99
src/demo/types.ts Normal file
View File

@@ -0,0 +1,99 @@
import type {
WaveformAnnotation,
WaveformAxesOptions,
WaveformData,
WaveformDisplayMode,
WaveformFrameStyle,
WaveformGridTrackLines,
WaveformInteractionMode,
WaveformLegendOrientation,
WaveformLegendPosition,
WaveformLineStyle,
WaveformOverlayMode,
WaveformTitleOptions,
WaveformZeroLineOptions,
WaveformZoomEndPayload,
} from '../components'
interface SelectOption<T> {
label: string
value: T
}
export interface DemoControlPanelModel {
controlsOpen: boolean
displayMode: WaveformDisplayMode
overlayMode: WaveformOverlayMode
showTooltip: boolean
cleanView: boolean
selectedSeriesId: string
selectedLineStyle: WaveformLineStyle
lineStyleOptions: Array<SelectOption<WaveformLineStyle>>
seriesStyleOptions: Array<SelectOption<string>>
zeroLineVisible: boolean
zeroLineColor: string
zeroLineWidth: number
zeroLineDash: string
zeroLineDashOptions: Array<SelectOption<string>>
rowCount: number
columnCount: number
horizontalGridVisible: boolean
horizontalGridColor: string
verticalGridVisible: boolean
verticalGridColor: string
xAxisLineVisible: boolean
yAxisLineVisible: boolean
frameBorderColor: string
frameBackgroundColor: string
frameBorderWidth: number
frameBorderStyle: NonNullable<WaveformFrameStyle['borderStyle']>
frameBorderStyleOptions: Array<SelectOption<string>>
frameWatermarkVisible: boolean
titleVisible: boolean
titleText: string
titleAlign: NonNullable<WaveformTitleOptions['align']>
titleAlignOptions: Array<SelectOption<NonNullable<WaveformTitleOptions['align']>>>
titleFontFamily: string
titleFontFamilyOptions: Array<SelectOption<string>>
titleFontSize: number
titleBold: boolean
titleItalic: boolean
titleUnderline: boolean
titleRotation: number
titleColor: string
legendPosition: WaveformLegendPosition
legendPositionOptions: Array<SelectOption<WaveformLegendPosition>>
legendOrientation: WaveformLegendOrientation
legendOrientationOptions: Array<SelectOption<WaveformLegendOrientation>>
legendBackgroundColor: string
closeControls: () => void
resetTitleTextStyle: () => void
resetWaveformViewport: () => void
}
export interface DemoChartModel {
data: WaveformData
minZoomSpan?: number
initialXDomain?: [number, number]
displayMode: WaveformDisplayMode
overlayMode: WaveformOverlayMode
rowCount: number
columnCount: number
gridTrackLines: WaveformGridTrackLines
title: WaveformTitleOptions
legendPosition: WaveformLegendPosition
legendOrientation: WaveformLegendOrientation
legendBackgroundColor: string
frameStyle: WaveformFrameStyle
axes: WaveformAxesOptions
cleanView: boolean
showTooltip: boolean
zeroLine: WaveformZeroLineOptions
frameWatermarkVisible: boolean
annotations: WaveformAnnotation[]
annotationsVisible: boolean
interactionMode: WaveformInteractionMode
hiddenSeriesIds: string[]
handleZoomEnd: (payload: WaveformZoomEndPayload) => void | Promise<void>
resetWaveformViewport: () => void
}