Commit e0535b05124400b672355f4c9ab5a856d9a5143c

Authored by ww
1 parent 0814f5f9

feat: implement picture component

1 -<script lang="ts" setup>  
2 - import type { ECharts, EChartsOption } from 'echarts';  
3 - import type { PropType } from 'vue';  
4 - import { nextTick, onMounted, onUnmounted, ref, unref } from 'vue';  
5 - import { init } from 'echarts';  
6 -  
7 - interface DataSource {  
8 - id: string | number;  
9 - }  
10 -  
11 - const props = defineProps({  
12 - dataSource: {  
13 - type: Object as PropType<DataSource>,  
14 - required: true,  
15 - },  
16 - chartOption: {  
17 - type: Object as PropType<EChartsOption>,  
18 - // required: true,  
19 - },  
20 - add: {  
21 - type: Function,  
22 - required: true,  
23 - },  
24 - });  
25 -  
26 - const getControlsWidgetId = () => `widget-chart-${props.dataSource.id}`;  
27 -  
28 - const chartRef = ref<Nullable<ECharts>>(null);  
29 -  
30 - function initChart() {  
31 - const chartDom = document.getElementById(getControlsWidgetId())!;  
32 - chartRef.value = init(chartDom);  
33 - const option: EChartsOption = props.chartOption || {  
34 - tooltip: {  
35 - trigger: 'item',  
36 - // confine: true,  
37 - extraCssText: 'position: fixed;',  
38 - position: (point, params, dom, rect, size) => {  
39 - const parentEl = (dom as HTMLDivElement).parentElement!;  
40 -  
41 - const { top = 0, left = 0 } = parentEl.getBoundingClientRect()!;  
42 - return [left, top];  
43 - },  
44 - },  
45 - series: [  
46 - {  
47 - name: 'Access From',  
48 - type: 'pie',  
49 - radius: '50%',  
50 - data: [  
51 - { value: 1048, name: 'Search Engine' },  
52 - { value: 735, name: 'Direct' },  
53 - { value: 580, name: 'Email' },  
54 - { value: 484, name: 'Union Ads' },  
55 - { value: 300, name: 'Video Ads' },  
56 - ],  
57 - emphasis: {  
58 - itemStyle: {  
59 - shadowBlur: 10,  
60 - shadowOffsetX: 0,  
61 - shadowColor: 'rgba(0, 0, 0, 0.5)',  
62 - },  
63 - },  
64 - },  
65 - ],  
66 - };  
67 -  
68 - nextTick(() => {  
69 - option && unref(chartRef)?.setOption(option);  
70 - });  
71 - }  
72 -  
73 - function update() {  
74 - unref(chartRef)?.resize();  
75 - }  
76 -  
77 - onMounted(() => {  
78 - initChart();  
79 - props.add(props.dataSource.id, update);  
80 - });  
81 -  
82 - onUnmounted(() => {  
83 - unref(chartRef)?.clear();  
84 - });  
85 -  
86 - defineExpose({ update });  
87 -</script>  
88 -  
89 -<template>  
90 - <div :id="getControlsWidgetId()" class="widget-charts"></div>  
91 -</template>  
92 -  
93 -<style scoped>  
94 - .widget-charts {  
95 - min-width: 10px;  
96 - min-height: 10px;  
97 - width: 100%;  
98 - height: 100%;  
99 - }  
100 -  
101 - .widget-charts > div {  
102 - width: 100%;  
103 - height: 100%;  
104 - }  
105 -</style>  
  1 +<script lang="ts" setup>
  2 + import { computed } from 'vue';
  3 + import { Tooltip, Image } from 'ant-design-vue';
  4 + import {
  5 + DEFAULT_DATE_FORMAT,
  6 + DEFAULT_RADIO_RECORD,
  7 + fontSize,
  8 + RadioRecord,
  9 + } from '../../detail/config/util';
  10 + import { PictureComponentLayout, PictureComponentValue } from './pictureComponent.config';
  11 + import { dateUtil } from '/@/utils/dateUtil';
  12 +
  13 + const props = defineProps<{
  14 + layout: PictureComponentLayout;
  15 + value: PictureComponentValue;
  16 + radio: RadioRecord;
  17 + }>();
  18 +
  19 + const fallback =
  20 + 'data:image/png;base64,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';
  21 +
  22 + const getRadio = computed(() => {
  23 + const { radio } = props.radio || DEFAULT_RADIO_RECORD;
  24 + console.log(props.radio);
  25 + return radio;
  26 + });
  27 +
  28 + const getWidth = computed(() => {
  29 + const marign = 5;
  30 + const { width = 180 } = props.radio || {};
  31 + return width - 5;
  32 + });
  33 +</script>
  34 +
  35 +<template>
  36 + <section class="w-full h-full flex flex-col justify-center items-center">
  37 + <Image :width="getWidth" :src="props?.value?.value || ''" :fallback="fallback" />
  38 + <div
  39 + class="w-full text-center text-gray-400 truncate"
  40 + :style="{ fontSize: fontSize({ radio: getRadio, basic: 12, max: 16 }) }"
  41 + >
  42 + <Tooltip
  43 + placement="topLeft"
  44 + :title="props?.value?.updateTime || dateUtil().format(DEFAULT_DATE_FORMAT)"
  45 + >
  46 + <span>更新时间:</span>
  47 + <span class="truncate">
  48 + {{ props?.value?.updateTime || dateUtil().format(DEFAULT_DATE_FORMAT) }}
  49 + </span>
  50 + </Tooltip>
  51 + </div>
  52 + </section>
  53 +</template>
  54 +
  55 +<style scoped></style>
  1 +import PictureComponent from './PictureComponent.vue';
  2 +
  3 +import { PictureComponentType } from './pictureComponent.config';
  4 +import { Component } from 'vue';
  5 +
  6 +interface PictureComponentList {
  7 + id: PictureComponentType;
  8 + component: Component;
  9 +}
  10 +// {
  11 +// id: 'instrument-component-1',
  12 +// layout: { chartOption: instrumentComponent1() },
  13 +// component: DashBoardComponent,
  14 +// value: { id: buildUUID() },
  15 +// }
  16 +const pictureComponentList: PictureComponentList[] = [
  17 + {
  18 + id: 'picture-component-1',
  19 + component: PictureComponent,
  20 + },
  21 +];
  22 +
  23 +export { PictureComponent, pictureComponentList };
  1 +import { DataComponentRecord, DataSource } from '/@/api/dataBoard/model';
  2 +
  3 +export type PictureComponentType = 'picture-component-1';
  4 +
  5 +export interface PictureComponentLayout {}
  6 +
  7 +export interface PictureComponentValue {
  8 + value?: string;
  9 + updateTime?: string;
  10 +}
  11 +
  12 +export const transformPictureConfig = (
  13 + config: PictureComponentLayout,
  14 + record: DataComponentRecord,
  15 + dataSourceRecord: DataSource
  16 +) => {
  17 + return {};
  18 +};
@@ -4,13 +4,15 @@ @@ -4,13 +4,15 @@
4 import { FormActionType, useForm } from '/@/components/Form'; 4 import { FormActionType, useForm } from '/@/components/Form';
5 import { basicSchema, dataSourceSchema } from '../config/basicConfiguration'; 5 import { basicSchema, dataSourceSchema } from '../config/basicConfiguration';
6 import BasicForm from '/@/components/Form/src/BasicForm.vue'; 6 import BasicForm from '/@/components/Form/src/BasicForm.vue';
7 - import { reactive, ref, shallowReactive, unref, nextTick, watch } from 'vue'; 7 + import { ref, shallowReactive, unref, nextTick, watch } from 'vue';
8 import VisualOptionsModal from './VisualOptionsModal.vue'; 8 import VisualOptionsModal from './VisualOptionsModal.vue';
9 import { useModal } from '/@/components/Modal'; 9 import { useModal } from '/@/components/Modal';
10 import { buildUUID } from '/@/utils/uuid'; 10 import { buildUUID } from '/@/utils/uuid';
11 import type { ComponentInfo, DataSource } from '/@/api/dataBoard/model'; 11 import type { ComponentInfo, DataSource } from '/@/api/dataBoard/model';
12 import { useMessage } from '/@/hooks/web/useMessage'; 12 import { useMessage } from '/@/hooks/web/useMessage';
13 import { DataBoardLayoutInfo } from '../../types/type'; 13 import { DataBoardLayoutInfo } from '../../types/type';
  14 + import { FrontComponent } from '../config/help';
  15 + import { computed } from '@vue/reactivity';
14 16
15 type DataSourceFormEL = { [key: string]: Nullable<FormActionType> }; 17 type DataSourceFormEL = { [key: string]: Nullable<FormActionType> };
16 18
@@ -133,6 +135,10 @@ @@ -133,6 +135,10 @@
133 }); 135 });
134 }; 136 };
135 137
  138 + const showSettingButton = computed(() => {
  139 + return props.frontId !== FrontComponent.PICTURE_COMPONENT_1;
  140 + });
  141 +
136 watch( 142 watch(
137 () => props.record, 143 () => props.record,
138 () => { 144 () => {
@@ -183,6 +189,7 @@ @@ -183,6 +189,7 @@
183 </Tooltip> 189 </Tooltip>
184 <Tooltip title="设置"> 190 <Tooltip title="设置">
185 <SettingOutlined 191 <SettingOutlined
  192 + v-show="showSettingButton"
186 @click="handleSetting(item)" 193 @click="handleSetting(item)"
187 class="cursor-pointer text-lg !leading-30px" 194 class="cursor-pointer text-lg !leading-30px"
188 /> 195 />
@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 import TextComponent from '../../components/TextComponent/TextComponent.vue'; 4 import TextComponent from '../../components/TextComponent/TextComponent.vue';
5 import { textComponentConfig } from '../../components/TextComponent/config'; 5 import { textComponentConfig } from '../../components/TextComponent/config';
6 import { instrumentComponentConfig } from '../../components/InstrumentComponent'; 6 import { instrumentComponentConfig } from '../../components/InstrumentComponent';
  7 + import { pictureComponentList } from '../../components/PictureComponent';
7 const props = defineProps<{ 8 const props = defineProps<{
8 value: string; 9 value: string;
9 }>(); 10 }>();
@@ -35,7 +36,25 @@ @@ -35,7 +36,25 @@
35 </template> 36 </template>
36 </List> 37 </List>
37 </Tabs.TabPane> 38 </Tabs.TabPane>
38 - <Tabs.TabPane key="2" tab="仪表组件"> 39 + <Tabs.TabPane key="2" tab="图片组件">
  40 + <List
  41 + :grid="{ gutter: 10, column: 3, xs: 3, sm: 3, md: 3, lg: 3, xl: 3, xxl: 3 }"
  42 + :data-source="pictureComponentList"
  43 + >
  44 + <template #renderItem="{ item }">
  45 + <List.Item class="!flex !justify-center">
  46 + <VisualWidgetSelect
  47 + :checked-id="props.value"
  48 + :control-id="item.id"
  49 + @change="handleCheck"
  50 + >
  51 + <component :is="item.component" />
  52 + </VisualWidgetSelect>
  53 + </List.Item>
  54 + </template>
  55 + </List>
  56 + </Tabs.TabPane>
  57 + <Tabs.TabPane key="3" tab="仪表组件">
39 <List 58 <List
40 :grid="{ gutter: 10, column: 3, xs: 3, sm: 3, md: 3, lg: 3, xl: 3, xxl: 3 }" 59 :grid="{ gutter: 10, column: 3, xs: 3, sm: 3, md: 3, lg: 3, xl: 3, xxl: 3 }"
41 :data-source="instrumentComponentConfig" 60 :data-source="instrumentComponentConfig"
@@ -18,7 +18,7 @@ export const basicSchema: FormSchema[] = [ @@ -18,7 +18,7 @@ export const basicSchema: FormSchema[] = [
18 }, 18 },
19 }, 19 },
20 { 20 {
21 - field: 'remake', 21 + field: 'remark',
22 label: '组件备注', 22 label: '组件备注',
23 component: 'InputTextArea', 23 component: 'InputTextArea',
24 componentProps: { 24 componentProps: {
@@ -10,6 +10,8 @@ import { @@ -10,6 +10,8 @@ import {
10 } from '../../components/TextComponent/config'; 10 } from '../../components/TextComponent/config';
11 import { DataComponentRecord, DataSource } from '/@/api/dataBoard/model'; 11 import { DataComponentRecord, DataSource } from '/@/api/dataBoard/model';
12 import DashBoardComponent from '../../components/InstrumentComponent/DashBoardComponent.vue'; 12 import DashBoardComponent from '../../components/InstrumentComponent/DashBoardComponent.vue';
  13 +import PictureComponent from '../../components/PictureComponent/PictureComponent.vue';
  14 +import { transformPictureConfig } from '../../components/PictureComponent/pictureComponent.config';
13 import { WidgetComponentType } from './visualOptions'; 15 import { WidgetComponentType } from './visualOptions';
14 import { 16 import {
15 DashboardComponentLayout, 17 DashboardComponentLayout,
@@ -27,6 +29,7 @@ export enum FrontComponent { @@ -27,6 +29,7 @@ export enum FrontComponent {
27 INSTRUMENT_COMPONENT_1 = 'instrument-component-1', 29 INSTRUMENT_COMPONENT_1 = 'instrument-component-1',
28 INSTRUMENT_COMPONENT_2 = 'instrument-component-2', 30 INSTRUMENT_COMPONENT_2 = 'instrument-component-2',
29 DIGITAL_DASHBOARD_COMPONENT = 'digital-dashboard-component', 31 DIGITAL_DASHBOARD_COMPONENT = 'digital-dashboard-component',
  32 + PICTURE_COMPONENT_1 = 'picture-component-1',
30 } 33 }
31 34
32 export interface ComponentConfig { 35 export interface ComponentConfig {
@@ -94,3 +97,9 @@ frontComponentMap.set(FrontComponent.DIGITAL_DASHBOARD_COMPONENT, { @@ -94,3 +97,9 @@ frontComponentMap.set(FrontComponent.DIGITAL_DASHBOARD_COMPONENT, {
94 ComponentConfig: {}, 97 ComponentConfig: {},
95 transformConfig: transformDashboardComponentConfig, 98 transformConfig: transformDashboardComponentConfig,
96 }); 99 });
  100 +
  101 +frontComponentMap.set(FrontComponent.PICTURE_COMPONENT_1, {
  102 + Component: PictureComponent,
  103 + ComponentConfig: {},
  104 + transformConfig: transformPictureConfig,
  105 +});
1 import { InstrumentComponentType } from '../../components/InstrumentComponent/dashBoardComponent.config'; 1 import { InstrumentComponentType } from '../../components/InstrumentComponent/dashBoardComponent.config';
2 import { DigitalDashBoardComponentType } from '../../components/InstrumentComponent/digitalDashBoard.config'; 2 import { DigitalDashBoardComponentType } from '../../components/InstrumentComponent/digitalDashBoard.config';
  3 +import { PictureComponentType } from '../../components/PictureComponent/pictureComponent.config';
3 import { TextComponentType } from '../../components/TextComponent/config'; 4 import { TextComponentType } from '../../components/TextComponent/config';
4 import { FormSchema } from '/@/components/Form'; 5 import { FormSchema } from '/@/components/Form';
5 6
6 export type WidgetComponentType = 7 export type WidgetComponentType =
7 | TextComponentType 8 | TextComponentType
8 | InstrumentComponentType 9 | InstrumentComponentType
9 - | DigitalDashBoardComponentType; 10 + | DigitalDashBoardComponentType
  11 + | PictureComponentType;
10 12
11 export interface VisualOptionParams { 13 export interface VisualOptionParams {
12 [visualOptionField.FONT_COLOR]: string; 14 [visualOptionField.FONT_COLOR]: string;