Commit 66e9527edc841c11e54fb0a3509a7b3d4d5e6788

Authored by ww
1 parent 19f98345

wip: implement TextComponent && DigitalDashboardComponent font size scale zoom on drag

1 1 <script lang="ts" setup>
2 2 import type { ECharts, EChartsOption } from 'echarts';
3   - import type { PropType } from 'vue';
4   - import { nextTick, onMounted, onUnmounted, ref, unref } from 'vue';
  3 + import { PropType } from 'vue';
  4 + import { nextTick, onMounted, onUnmounted, ref, unref, computed } from 'vue';
5 5 import { init } from 'echarts';
6   - import { instrumentComponent1 } from './dashBoardComponent.config';
  6 + import {
  7 + DashboardComponentLayout,
  8 + DashBoardValue,
  9 + instrumentComponent1,
  10 + InstrumentComponentType,
  11 + update_instrument_1_font,
  12 + update_instrument_2_font,
  13 + } from './dashBoardComponent.config';
7 14 import { dateUtil } from '/@/utils/dateUtil';
  15 + import {
  16 + DEFAULT_RADIO_RECORD,
  17 + RadioRecord,
  18 + DEFAULT_DATE_FORMAT,
  19 + fontSize,
  20 + } from '../../detail/config/util';
8 21
9 22 const props = defineProps({
10 23 add: {
11 24 type: Function,
12 25 },
13 26 layout: {
14   - type: Object as PropType<Recordable>,
  27 + type: Object as PropType<DashboardComponentLayout>,
15 28 default: () => ({}),
16 29 },
17 30 value: {
18   - type: Object as PropType<Recordable>,
  31 + type: Object as PropType<DashBoardValue>,
19 32 default: () => ({}),
20 33 },
  34 + radio: {
  35 + type: Object as PropType<RadioRecord>,
  36 + default: () => DEFAULT_RADIO_RECORD,
  37 + },
21 38 });
22 39
23 40 const getControlsWidgetId = () => `widget-chart-${props.value.id}`;
... ... @@ -33,8 +50,21 @@
33 50 option && unref(chartRef)?.setOption(option);
34 51 });
35 52 }
  53 + const getRadio = computed(() => {
  54 + const { radio } = props.radio;
  55 + return radio;
  56 + });
  57 +
  58 + const beforeUpdateFn = (componentType: InstrumentComponentType) => {
  59 + if (componentType === 'instrument-component-1') return update_instrument_1_font;
  60 + if (componentType === 'instrument-component-2') return update_instrument_2_font;
  61 + return (_radio: number) => {};
  62 + };
36 63
37 64 function update() {
  65 + const option = beforeUpdateFn(props.layout.componentType);
  66 + console.log(unref(chartRef));
  67 + unref(chartRef)?.setOption(option(unref(getRadio)) as unknown as EChartsOption);
38 68 unref(chartRef)?.resize();
39 69 }
40 70
... ... @@ -54,12 +84,15 @@
54 84 <div class="flex flex-col w-full h-full min-w-3 min-h-3">
55 85 <div :id="getControlsWidgetId()" class="widget-charts flex-auto"></div>
56 86 <div>
57   - <div class="text-center">{{ props.value.name }}</div>
58   - <div class="text-xs text-center text-gray-400">
59   - <span>更新时间:</span>
60   - <span>
61   - {{ props.value.updateTime || dateUtil().format('YYYY-MM-DD HH:mm:ss') }}
62   - </span>
  87 + <div class="text-center" :style="{ fontSize: fontSize({ radio: getRadio, basic: 16 }) }">{{
  88 + props.value.name
  89 + }}</div>
  90 + <div
  91 + class="text-xs text-center text-gray-400 truncate"
  92 + :style="{ fontSize: fontSize({ radio: getRadio, basic: 12, max: 16 }) }"
  93 + >
  94 + <span class="mr-2">更新时间:</span>
  95 + <span> {{ props.value.updateTime || dateUtil().format(DEFAULT_DATE_FORMAT) }}</span>
63 96 </div>
64 97 </div>
65 98 </div>
... ...
... ... @@ -3,10 +3,17 @@
3 3 import { Space } from 'ant-design-vue';
4 4 import type { DigitalDashBoardLayout, DigitalDashBoardValue } from './digitalDashBoard.config';
5 5 import { dateUtil } from '/@/utils/dateUtil';
  6 + import {
  7 + fontSize,
  8 + RadioRecord,
  9 + DEFAULT_DATE_FORMAT,
  10 + DEFAULT_RADIO_RECORD,
  11 + } from '../../detail/config/util';
6 12
7 13 const props = defineProps<{
8 14 layout: DigitalDashBoardLayout;
9 15 value: DigitalDashBoardValue;
  16 + radio: RadioRecord;
10 17 }>();
11 18
12 19 const integerPart = computed(() => {
... ... @@ -30,6 +37,11 @@
30 37
31 38 return _value;
32 39 });
  40 +
  41 + const getRadio = computed(() => {
  42 + const { radio } = props.radio || DEFAULT_RADIO_RECORD;
  43 + return radio;
  44 + });
33 45 </script>
34 46
35 47 <template>
... ... @@ -37,22 +49,28 @@
37 49 <div class="flex flex-col w-full h-full">
38 50 <div class="flex-1 flex justify-center items-center">
39 51 <div class="flex flex-col">
40   - <Space justify="end" class="justify-end">
  52 + <Space justify="end" class="justify-end" :size="getRadio * 15">
41 53 <div
42 54 v-for="number in integerPart"
43 55 :key="number"
44 56 class="border border-gray-400 p-2"
45   - :style="{ color: props.value.valueColor }"
  57 + :style="{
  58 + color: props.value.valueColor,
  59 + fontSize: fontSize({ radio: getRadio, basic: 20 }),
  60 + }"
46 61 >
47 62 {{ number }}
48 63 </div>
49 64 </Space>
50   - <Space justify="end" class="justify-end mt-2">
  65 + <Space justify="end" class="justify-end mt-2" :size="getRadio * 15">
51 66 <div
52 67 v-for="number in decimalPart"
53 68 :key="number"
54 69 class="border border-gray-400 p-1"
55   - :style="{ color: props.value.valueColor }"
  70 + :style="{
  71 + color: props.value.valueColor,
  72 + fontSize: fontSize({ radio: getRadio, basic: 18 }),
  73 + }"
56 74 >
57 75 {{ number }}
58 76 </div>
... ... @@ -60,13 +78,19 @@
60 78 </div>
61 79 </div>
62 80
63   - <div class="text-center">
  81 + <div
  82 + class="text-center truncate"
  83 + :style="{ fontSize: fontSize({ radio: getRadio, basic: 18 }) }"
  84 + >
64 85 <span>{{ props.value.name || '电表' }}</span>
65 86 <span class="px-1">({{ props.value.unit || 'kw/h' }})</span>
66 87 </div>
67   - <div class="text-center mt-1 text-gray-400 text-xs">
  88 + <div
  89 + class="text-center mt-1 text-gray-400 text-xs truncate"
  90 + :style="{ fontSize: fontSize({ radio: getRadio, basic: 12 }) }"
  91 + >
68 92 <span class="mr-1">更新时间:</span>
69   - <span>{{ props.value.updateTime || dateUtil().format('YYYY-MM-DD HH:mm:ss') }}</span>
  93 + <span>{{ props.value.updateTime || dateUtil().format(DEFAULT_DATE_FORMAT) }}</span>
70 94 </div>
71 95 </div>
72 96 <div></div>
... ...
1 1 import { EChartsOption } from 'echarts';
  2 +import { fontSize } from '../../detail/config/util';
2 3 import { visualOptionField } from '../../detail/config/visualOptions';
3 4 import { DataComponentRecord, DataSource } from '/@/api/dataBoard/model';
4 5 import { buildUUID } from '/@/utils/uuid';
... ... @@ -19,6 +20,7 @@ export interface GradientInfoRecord {
19 20 }
20 21
21 22 export interface DashBoardValue {
  23 + id: string;
22 24 unit?: string;
23 25 name?: string;
24 26 updateTime?: string;
... ... @@ -29,6 +31,7 @@ export interface DashBoardValue {
29 31
30 32 export interface DashboardComponentLayout {
31 33 chartOption: EChartsOption;
  34 + componentType: InstrumentComponentType;
32 35 }
33 36
34 37 export const instrumentComponent1 = (params?: { value: number; unit: string }): EChartsOption => {
... ... @@ -199,14 +202,14 @@ export const instrumentComponent2 = (params?: {
199 202 },
200 203 axisLabel: {
201 204 color: 'auto',
202   - distance: 40,
203   - fontSize: 14,
  205 + distance: 35,
  206 + fontSize: 6,
204 207 },
205 208 detail: {
206 209 valueAnimation: true,
207 210 formatter: `{value} ${unit}`,
208 211 color: 'auto',
209   - fontSize: '16',
  212 + fontSize: 14,
210 213 },
211 214 data: [
212 215 {
... ... @@ -222,6 +225,38 @@ export const getGradientValue = (key: GradientKey, record: GradientInfoRecord[])
222 225 return record.find((item) => item.key === key)?.value;
223 226 };
224 227
  228 +export const update_instrument_1_font = (radio: number) => {
  229 + console.log(fontSize({ radio, basic: 14 }));
  230 + return {
  231 + series: [
  232 + {
  233 + axisLabel: {
  234 + fontSize: fontSize({ radio, basic: 14 }),
  235 + },
  236 + detail: {
  237 + fontSize: fontSize({ radio, basic: 14 }),
  238 + },
  239 + },
  240 + ],
  241 + } as EChartsOption;
  242 +};
  243 +
  244 +export const update_instrument_2_font = (radio: number) => {
  245 + const axisLabelFontSize = fontSize({ radio, basic: 10, max: 25 });
  246 + return {
  247 + series: [
  248 + {
  249 + axisLabel: {
  250 + fontSize: axisLabelFontSize,
  251 + },
  252 + detail: {
  253 + fontSize: axisLabelFontSize,
  254 + },
  255 + },
  256 + ],
  257 + } as EChartsOption;
  258 +};
  259 +
225 260 export const transformDashboardComponentConfig = (
226 261 config: DashboardComponentLayout,
227 262 record: DataComponentRecord,
... ... @@ -229,7 +264,8 @@ export const transformDashboardComponentConfig = (
229 264 ) => {
230 265 return {
231 266 layout: {
232   - chartOption: config,
  267 + chartOption: config.chartOption,
  268 + componentType: config.componentType,
233 269 } as DashboardComponentLayout,
234 270 value: {
235 271 id: buildUUID(),
... ...
1 1 <script lang="ts" setup>
2 2 import { computed } from '@vue/reactivity';
3 3 import { Statistic } from 'ant-design-vue';
  4 + import { fontSize, RadioRecord, DEFAULT_RADIO_RECORD } from '../../detail/config/util';
4 5 import type { TextComponentLayout, TextComponentValue } from './config';
5 6 import { SvgIcon } from '/@/components/Icon';
6 7 const props = defineProps({
... ... @@ -12,6 +13,10 @@
12 13 type: Object as PropType<TextComponentValue>,
13 14 default: () => ({ name: '温度', value: 123 } as TextComponentValue),
14 15 },
  16 + radio: {
  17 + type: Object as PropType<RadioRecord>,
  18 + default: () => DEFAULT_RADIO_RECORD as RadioRecord,
  19 + },
15 20 });
16 21
17 22 const getIsColumnLayout = computed(() => {
... ... @@ -33,6 +38,11 @@
33 38 const { showUnit, base } = props.layout;
34 39 return base ? false : showUnit;
35 40 });
  41 +
  42 + const getRadio = computed(() => {
  43 + const { radio } = props.radio;
  44 + return radio;
  45 + });
36 46 </script>
37 47
38 48 <template>
... ... @@ -47,23 +57,34 @@
47 57 <SvgIcon
48 58 :name="props.value.icon || 'CO2'"
49 59 prefix="iconfont"
50   - class="!w-1/2 !h-[2em]"
51   - :style="{ color: props.value.iconColor }"
  60 + :style="{
  61 + color: props.value.iconColor,
  62 + width: fontSize({ radio: getRadio, basic: 40 }),
  63 + height: fontSize({ radio: getRadio, basic: 40 }),
  64 + }"
52 65 />
53 66 </div>
54   - <div>{{ props.value.name }}</div>
  67 + <div class="truncate" :style="{ fontSize: fontSize({ radio: getRadio, basic: 16 }) }">{{
  68 + props.value.name
  69 + }}</div>
55 70 </div>
56 71 </div>
57 72 <div class="w-1/2 flex justify-center">
58 73 <Statistic
59 74 :value="props.value.value || '123'"
60 75 :suffix="getShowUnit ? props.value.unit : ''"
61   - :value-style="{ fontSize: '1.3em', color: props.value.fontColor }"
  76 + class="truncate"
  77 + :value-style="{
  78 + fontSize: fontSize({ radio: getRadio, basic: 16 }),
  79 + color: props.value.fontColor,
  80 + }"
62 81 />
63 82 </div>
64 83 </div>
65   - <div v-if="getShowUpdate" class="text-center text-xs text-gray-400">
66   - <span> 更新时间: {{ props.value.updateTime }}</span>
  84 + <div v-if="getShowUpdate" class="text-center text-xs text-gray-400 truncate">
  85 + <span :style="{ fontSize: fontSize({ radio: getRadio, basic: 12 }) }" class="truncate">
  86 + 更新时间: {{ props.value.updateTime }}</span
  87 + >
67 88 </div>
68 89 </div>
69 90 </template>
... ...
1 1 <script lang="ts" setup>
2 2 import { onMounted, useSlots } from 'vue';
3 3 import { useUpdateCenter } from '../../hook/useUpdateCenter';
4   - import type { DataSource, WidgetWrapperRegister } from './type';
  4 + import { DataBoardLayoutInfo } from '../../types/type';
  5 + import type { WidgetWrapperRegister } from './type';
  6 + import { DataSource } from '/@/api/dataBoard/model';
5 7
6 8 const props = defineProps<{
7   - dataSource: DataSource[];
  9 + dataSource: DataBoardLayoutInfo['record'][];
8 10 register?: WidgetWrapperRegister;
9 11 }>();
10 12
... ...
1   -import { DataComponentRecord } from '/@/api/dataBoard/model';
  1 +import { DataBoardLayoutInfo } from '../../types/type';
  2 +import { DataSource } from '/@/api/dataBoard/model';
2 3
3   -export interface DataSource {
4   - id: number | string;
5   - width: number;
6   - height: number;
  4 +// export interface DataSource {
  5 +// id: number | string;
  6 +// width: number;
  7 +// height: number;
7 8
8   - [key: string]: any;
9   -}
  9 +// [key: string]: any;
  10 +// }
10 11
11   -export type WidgetWrapperRegister = (dataSource: DataComponentRecord[]) => any;
  12 +export type WidgetWrapperRegister = (dataSource: DataBoardLayoutInfo['record'][]) => any;
... ...
... ... @@ -12,6 +12,7 @@ import { DataComponentRecord, DataSource } from '/@/api/dataBoard/model';
12 12 import DashBoardComponent from '../../components/InstrumentComponent/DashBoardComponent.vue';
13 13 import { WidgetComponentType } from './visualOptions';
14 14 import {
  15 + DashboardComponentLayout,
15 16 instrumentComponent1,
16 17 instrumentComponent2,
17 18 transformDashboardComponentConfig,
... ... @@ -72,13 +73,19 @@ frontComponentMap.set(FrontComponent.TEXT_COMPONENT_5, {
72 73
73 74 frontComponentMap.set(FrontComponent.INSTRUMENT_COMPONENT_1, {
74 75 Component: DashBoardComponent,
75   - ComponentConfig: instrumentComponent1(),
  76 + ComponentConfig: {
  77 + chartOption: instrumentComponent1(),
  78 + componentType: FrontComponent.INSTRUMENT_COMPONENT_1,
  79 + } as DashboardComponentLayout,
76 80 transformConfig: transformDashboardComponentConfig,
77 81 });
78 82
79 83 frontComponentMap.set(FrontComponent.INSTRUMENT_COMPONENT_2, {
80 84 Component: DashBoardComponent,
81   - ComponentConfig: instrumentComponent2(),
  85 + ComponentConfig: {
  86 + chartOption: instrumentComponent2(),
  87 + componentType: FrontComponent.INSTRUMENT_COMPONENT_2,
  88 + } as DashboardComponentLayout,
82 89 transformConfig: transformDashboardComponentConfig,
83 90 });
84 91
... ...
  1 +export interface RadioRecord {
  2 + width: number;
  3 + height: number;
  4 + isLess: boolean;
  5 + radio: number;
  6 +}
  7 +
  8 +export const DEFAULT_RADIO_RECORD: RadioRecord = {
  9 + width: 300,
  10 + height: 300,
  11 + isLess: false,
  12 + radio: 1,
  13 +};
  14 +
  15 +export const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss';
  16 +
  17 +export const calcScale = (
  18 + width: number,
  19 + height: number,
  20 + widthRadio: number,
  21 + heightRadio: number
  22 +): RadioRecord => {
  23 + width = width * (widthRadio / 100);
  24 + height = height * (heightRadio / 100);
  25 +
  26 + const temp = width * height;
  27 +
  28 + const isLess = temp < 300 * 300;
  29 +
  30 + const radio = temp / (300 * 300);
  31 +
  32 + return {
  33 + width,
  34 + height,
  35 + isLess,
  36 + radio,
  37 + };
  38 +};
  39 +
  40 +export const fontSize = ({ radio, basic, max }: { radio: number; basic: number; max?: number }) => {
  41 + let res = basic * radio;
  42 + if (max && res > max) res = max;
  43 + return res + 'px';
  44 +};
... ...
... ... @@ -17,9 +17,11 @@
17 17 import { useRoute } from 'vue-router';
18 18 import { computed, unref } from '@vue/reactivity';
19 19 import { DataComponentRecord, DataSource, Layout } from '/@/api/dataBoard/model';
20   - import { frontComponentMap, FrontComponentType } from './config/help';
  20 + import { frontComponentMap } from './config/help';
  21 + import { calcScale } from './config/util';
21 22 import { useMessage } from '/@/hooks/web/useMessage';
22 23 import { DataBoardLayoutInfo } from '../types/type';
  24 + import { WidgetComponentType } from './config/visualOptions';
23 25
24 26 const ROUTE = useRoute();
25 27
... ... @@ -41,7 +43,7 @@
41 43 const defaultWidth = 6;
42 44 const defaultHeight = 6;
43 45
44   - function updateSize(i: string, newH: number, newW: number, newHPx: number, newWPx: number) {
  46 + function updateSize(i: string, _newH: number, _newW: number, newHPx: number, newWPx: number) {
45 47 newWPx = Number(newWPx);
46 48 newHPx = Number(newHPx);
47 49
... ... @@ -71,6 +73,7 @@
71 73 ...item,
72 74 width,
73 75 height,
  76 + radio: calcScale(newWPx, newHPx, width, height),
74 77 };
75 78 });
76 79
... ... @@ -82,7 +85,6 @@
82 85
83 86 const itemResize = (i: string, newH: number, newW: number, newHPx: number, newWPx: number) => {
84 87 updateSize(i, newH, newW, newHPx, newWPx);
85   - console.log({ i, newH, newW, newHPx, newWPx });
86 88 };
87 89
88 90 const itemResized = (i: string, newH: number, newW: number, newHPx: number, newWPx: number) => {
... ... @@ -157,6 +159,7 @@
157 159
158 160 const getDataBoardComponent = async () => {
159 161 try {
  162 + // dataBoardList.value = [];
160 163 const data = await getDataComponent(unref(getBoardId));
161 164 dataBoardList.value = data.data.componentData.map((item) => {
162 165 const index = data.data.componentLayout.findIndex((each) => item.id === each.id);
... ... @@ -184,13 +187,16 @@
184 187
185 188 const getComponent = (record: DataComponentRecord) => {
186 189 const frontComponent = record.frontId;
187   - const component = frontComponentMap.get(frontComponent as FrontComponentType);
  190 + const component = frontComponentMap.get(frontComponent as WidgetComponentType);
188 191 return component?.Component;
189 192 };
190 193
191   - const getComponentConfig = (record: DataComponentRecord, dataSourceRecord: DataSource) => {
  194 + const getComponentConfig = (
  195 + record: DataBoardLayoutInfo['record'],
  196 + dataSourceRecord: DataSource
  197 + ) => {
192 198 const frontComponent = record.frontId;
193   - const component = frontComponentMap.get(frontComponent as FrontComponentType);
  199 + const component = frontComponentMap.get(frontComponent as WidgetComponentType);
194 200 return component?.transformConfig(component.ComponentConfig, record, dataSourceRecord);
195 201 };
196 202
... ... @@ -289,6 +295,7 @@
289 295 :add="add"
290 296 :remove="remove"
291 297 :update="update"
  298 + :radio="record.radio"
292 299 v-bind="getComponentConfig(item.record, record)"
293 300 />
294 301 </template>
... ...
... ... @@ -2,5 +2,5 @@ import { Layout } from 'vue3-grid-layout';
2 2 import { DataComponentRecord } from '/@/api/dataBoard/model';
3 3
4 4 export type DataBoardLayoutInfo = Layout & {
5   - record: DataComponentRecord & { width: number; height: number };
  5 + record: DataComponentRecord & { width: number; height: number; radio?: number };
6 6 };
... ...