Selaa lähdekoodia

pref: 优化配置项

liaojiaxing 10 kuukautta sitten
vanhempi
commit
c4a75ab262

+ 10 - 3
README.md

@@ -14,7 +14,7 @@
 -- 组件内容为每个组件单独提供的配置组件,通常为数据源,数据样式等
 
 
-### echarts文件夹结构目录如下:
+### 图表文件夹结构目录如下:
 ```
 components/Charts/
 ├── BarChart/ // 柱状图
@@ -27,6 +27,13 @@ components/Charts/
 ...其他图表组件
 ├── hooks
 │   └── useChartOptions.ts // 用于获取组件配置项options数据
-|—— Echarts.vue // 封装echarts组件
+|—— Charts.vue // 封装Charts组件
 |—— DataConfig.vue // 数据配置组件
-```
+```
+
+图表分为3层设计
+1、实现层:通过useEchars封装,实现echarts的初始化加载,渲染,设置配置项目。
+2、渲染层:提供图表统一的渲染,通过给实现层提供配置项,实现图表的渲染。
+3、应用层:提供具体的业务组件。
+图表封装采用echarts  后期可替换为其他图表库
+图表配置项采用Echarts为通用配置项,可以通过切换“实现层”,满足不同图表库的适配器进行转换,满足不同图表库的配置项差异

+ 2 - 2
src/components/Charts/Bar/BasicBar/src/BasicBar.vue

@@ -1,10 +1,10 @@
 <template>
-  <Echarts :width="width" :height="height" :echarts-options="options" :loading="loading"></Echarts>
+  <Charts :width="width" :height="height" :echarts-options="options" :loading="loading"></Charts>
 </template>
 
 <script setup lang="ts">
 import { defineProps } from "vue";
-import Echarts from '@/components/Charts/Echarts.vue';
+import Charts from '@/components/Charts/Charts.vue';
 import { basicBarProps } from "./props";
 import { useChartOptions } from "@/components/Charts/hooks/useChartOptions";
 

+ 39 - 7
src/components/Charts/Bar/BasicBar/src/Config.vue

@@ -1,28 +1,60 @@
 <template>
   <div class="chart-config">
     <div class="config-tab">
-      <ElRadioGroup v-model="activeTab" size="small">
-        <ElRadioButton value="1">数据</ElRadioButton>
-        <ElRadioButton value="2">样式</ElRadioButton>
-      </ElRadioGroup>
+      <Tabs v-model:activeKey="activeTab" size="small" centered>
+        <TabPane key="1">
+          <template #tab>
+            <DatabaseOutlined />
+            <span>数据设置</span>
+          </template>
+        </TabPane>
+        <TabPane key="2">
+          <template #tab>
+            <SkinOutlined />
+            <span>样式设置</span>
+          </template>
+        </TabPane>
+      </Tabs>
     </div>
 
     <DataConfig v-if="activeTab === '1'" :dataSource="dataSource" @change="handleChange"/>
-    <StyleConfig v-if="activeTab === '2'" @change="handleChange"/>
+    <CusForm v-if="activeTab === '2'" :columns=""/>
   </div>
 </template>
 
 <script setup lang="ts">
 import { ref, defineProps, defineEmits } from 'vue';
-import { ElRadioGroup, ElRadioButton } from 'element-plus';
+import { Tabs, TabPane } from 'ant-design-vue';
+import { DatabaseOutlined, SkinOutlined } from '@ant-design/icons-vue';
 import DataConfig from '@/components/Charts/DataConfig.vue';
-import StyleConfig from '@/components/Charts/StyleConfig.vue';
+import { CusForm, IFormItem } from '@/components/CusForm';
 import { basicBarProps } from './props';
 
 const props = defineProps(basicBarProps);
 const activeTab = ref('1');
 const emit = defineEmits(['change']);
 
+const formItems: IFormItem[] = [
+  {
+    label: '标题',
+    prop: 'title',
+    type: 'group',
+    children: [
+      {
+        label: '标题可见',
+        prop: 'showTitle',
+        type: 'checkbox',
+      },
+      {
+        label: '文本',
+        prop: 'titleText',
+        type: 'input',
+      },
+      
+    ]
+  }
+]
+
 const handleChange = (data: any) => {
   emit('change', {
     ...props,

+ 1 - 1
src/components/Charts/Echarts.vue

@@ -1,4 +1,4 @@
-<!-- echarts基础组件 -->
+<!-- charts基础组件 -->
 <template>
   <Spin :spinning="loading" :indicator="indicator">
     <div ref="chartRef" :style="{width: width + 'px', height: height + 'px'}"></div>

+ 1 - 1
src/components/Charts/DataConfig.vue

@@ -95,7 +95,7 @@ import {
  * {
  *  xData: ['x轴标签A', 'x轴标签B', 'x轴标签C', 'x轴标签D'],
  *  yData: ['y轴数据A', 'y轴数据B', 'y轴数据C', 'y轴数据D'],
- * // 根据不同类型的图表配置不同的series
+ *  // 根据不同类型的图表配置不同的series
  *  series: [
  *    {
  *      name: '系列A',

+ 2 - 2
src/components/Charts/Line/BasicLine/src/BasicLine.vue

@@ -1,10 +1,10 @@
 <template>
-  <Echarts :width="width" :height="height" :echarts-options="options" :loading="loading"></Echarts>
+  <Charts :width="width" :height="height" :echarts-options="options" :loading="loading"></Charts>
 </template>
 
 <script setup lang="ts">
 import { defineProps } from "vue";
-import Echarts from '@/components/Charts/Echarts.vue';
+import Charts from '@/components/Charts/Charts.vue';
 import { basicLineProps } from "./props";
 import { useChartOptions } from "@/components/Charts/hooks/useChartOptions";
 

+ 77 - 0
src/components/CusForm/src/CusFormItem.vue

@@ -0,0 +1,77 @@
+<template>
+  <FormItem :label="item.label" :name="item.prop" :rules="item.rules">
+    <template v-if="item.type === 'input'">
+      <Input v-model:value="model" />
+    </template>
+    <template v-else-if="item.type === 'select'">
+      <Select v-model:value="model" :options="item.options"></Select>
+    </template>
+    <template v-else-if="item.type === 'inputnumber'">
+      <InputNumber v-model:value="model" />
+    </template>
+    <template v-else-if="item.type === 'image'">
+      <Image v-model:value="model" />
+    </template>
+    <template v-else-if="item.type === 'checkbox'">
+      <Checkbox v-model:value="model" />
+    </template>
+    <template v-else-if="item.type === 'backgroundSelect'">
+      <BackgroundSelect v-model:background="model" />
+    </template>
+    <template v-else-if="item.type === 'colorSelect'">
+      <ColorSelect v-model:value="model" />
+    </template>
+    <template v-else-if="item.type === 'radioGroup'">
+      <ElRadioGroup v-model="model" size="small">
+        <ElRadioButton
+          v-for="option in item.options"
+          :key="option.value"
+          :value="option.value"
+        >
+          {{ option.label }}
+        </ElRadioButton>
+      </ElRadioGroup>
+    </template>
+    <!--<template v-else-if="item.type === 'boderRadiusSelect'">
+          <BoderRadiusSelect v-model="formModel[item.key]" />
+        </template>
+        <template v-else-if="item.type === 'shodowSelect'">
+          <ShodowSelect v-model="formModel[item.key]" />
+        </template>
+        <template v-else-if="item.type === 'paddingSelect'">
+          <PaddingSelect v-model="formModel[item.key]" />
+        </template>
+        <template v-else-if="item.type === 'rotateSelect'">
+          <RotateSelect v-model="formModel[item.key]" />
+        </template>
+        <template v-else-if="item.type === 'opacitySelect'">
+          <OpacitySelect v-model="formModel[item.key]" />
+        </template> -->
+  </FormItem>
+</template>
+
+<script setup lang="ts">
+import { IFormItem } from "./type";
+import { defineProps, defineModel } from "vue";
+import {
+  FormItem,
+  Input,
+  Select,
+  InputNumber,
+  Checkbox,
+  Image,
+} from "ant-design-vue";
+import {
+  ElRadioGroup,
+  ElRadioButton,
+} from "element-plus";
+
+import BackgroundSelect from "./BackgroundSelect.vue";
+import ColorSelect from "./ColorSelect.vue";
+
+defineProps<{item: IFormItem}>();
+const model = defineModel<any>();
+
+</script>
+
+<style scoped></style>

+ 4 - 4
src/components/CusForm/src/FontStyle.vue

@@ -31,7 +31,7 @@ import {
 import { InputNumber } from "ant-design-vue";
 
 const props = defineProps<{
-  value: number;
+  size: number;
   bold: boolean;
   italic: boolean;
   underline: boolean;
@@ -47,7 +47,7 @@ const emit = defineEmits([
 const bold = ref(props.bold);
 const italic = ref(props.italic);
 const underline = ref(props.underline);
-const value = ref(props.value);
+const size = ref(props.size);
 
 const handleBold = () => {
   bold.value = !bold.value;
@@ -62,8 +62,8 @@ const handleUnderline = () => {
   emit("update:underline", underline.value);
 };
 const handleChange = (e: any) => {
-  value.value = e.target.value;
-  emit("update:value", value.value);
+  size.value = e.target.value;
+  emit("update:value", size.value);
 };
 </script>
 

+ 18 - 0
src/components/CusForm/src/Position.vue

@@ -0,0 +1,18 @@
+<template>
+  <div>
+    <RadioGroup v-model:value="formModel.title.position">
+      <RadioButton value="left"><AlignLeftOutlined/></RadioButton>
+      <RadioButton value="center"><AlignCenterOutlined/></RadioButton>
+      <RadioButton value="right"><AlignRightOutlined/></RadioButton>
+    </RadioGroup>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { RadioGroup, RadioButton } from 'ant-design-vue';
+import { AlignCenterOutlined, AlignRightOutlined, AlignLeftOutlined } from '@ant-design/icons-vue';
+</script>
+
+<style scoped>
+
+</style>

+ 22 - 65
src/components/CusForm/src/index.vue

@@ -7,57 +7,16 @@
     layout="horizontal"
     size="small"
   >
-    <FormItem
-      v-for="item in formItems"
-      :key="item.prop"
-      :label="item.label"
-      :name="item.prop"
-      :rules="item.rules"
-    >
-      <template v-if="item.type === 'input'">
-        <Input v-model:value="formModel[item.prop]" />
-      </template>
-      <template v-else-if="item.type === 'select'">
-        <Select v-model:value="formModel[item.prop]" :options="item.options" />
-      </template>
-      <template v-else-if="item.type === 'inputnumber'">
-        <InputNumber v-model:value="formModel[item.prop]" />
-      </template>
-      <template v-else-if="item.type === 'image'">
-        <Image v-model:value="formModel[item.prop]" />
-      </template>
-      <template v-else-if="item.type === 'checkbox'">
-        <Checkbox v-model:value="formModel[item.prop]" />
-      </template>
-      <template v-else-if="item.type === 'backgroundSelect'">
-        <BackgroundSelect v-model:background="formModel[item.prop]" />
-      </template>
-      <template v-else-if="item.type === 'colorSelect'">
-        <ColorSelect v-model:value="formModel[item.prop]" />
-      </template>
-      <template v-else-if="item.type === 'radioGroup'">
-        <ElRadioGroup v-model="formModel[item.prop]" size="small">
-          <ElRadioButton v-for="option in item.options" :key="option.value" :value="option.value">
-            {{ option.label }}
-          </ElRadioButton>
-        </ElRadioGroup>
-      </template>
-      <!--<template v-else-if="item.type === 'boderRadiusSelect'">
-        <BoderRadiusSelect v-model="formModel[item.key]" />
-      </template>
-      <template v-else-if="item.type === 'shodowSelect'">
-        <ShodowSelect v-model="formModel[item.key]" />
-      </template>
-      <template v-else-if="item.type === 'paddingSelect'">
-        <PaddingSelect v-model="formModel[item.key]" />
-      </template>
-      <template v-else-if="item.type === 'rotateSelect'">
-        <RotateSelect v-model="formModel[item.key]" />
-      </template>
-      <template v-else-if="item.type === 'opacitySelect'">
-        <OpacitySelect v-model="formModel[item.key]" />
-      </template> -->
-    </FormItem>
+    <template v-for="item in formItems" :key="item.prop">
+      <!-- 分组 -->
+      <Collapse v-if="item.type === 'group'">
+        <CollapsePanel :name="item.prop" :label="item.label">
+          <CusFormItem :item="item" v-model="formModel[item.prop]" />
+        </CollapsePanel>
+      </Collapse>
+      <!-- 单个表单项 -->
+      <CusFormItem v-else :item="item" v-model="formModel[item.prop]" />
+    </template>
   </Form>
 </template>
 
@@ -74,20 +33,10 @@ import {
 } from "vue";
 import {
   Form,
-  FormItem,
-  Input,
-  Select,
-  InputNumber,
-  Checkbox,
-  Image,
+  Collapse,
+  CollapsePanel
 } from "ant-design-vue";
-import {
-  ElRadioGroup,
-  ElRadioButton,
-} from "element-plus";
-
-import BackgroundSelect from "./BackgroundSelect.vue";
-import ColorSelect from "./ColorSelect.vue";
+import CusFormItem from "./CusFormItem.vue";
 
 const props = defineProps<{
   columns: IFormItem[];
@@ -113,7 +62,15 @@ watch(
   (val) => {
     val &&
       props.columns?.forEach((item) => {
-        formModel.value[item.prop] = item?.defaultValue;
+        // 设置表单初始值
+        if (item.type === "group") {
+          const children = item.children || [];
+          children.forEach((child) => {
+            formModel.value[child.prop] = child?.defaultValue;
+          });
+        } else {
+          formModel.value[item.prop] = item?.defaultValue;
+        }
       });
   },
   { immediate: true }

+ 26 - 8
src/components/CusForm/src/type.ts

@@ -3,23 +3,41 @@ export interface IFormItem {
   icon?: string;
   prop: string;
   type:
+    // 内置类型--分组
+    | "group"
     | "input"
     | "select"
     | "inputnumber"
     | "image"
     | "checkbox"
     | "radioGroup"
-    | "backgroundSelect" // 背景选择
-    | "boderSelect" // 边框选择
-    | "boderRadiusSelect" // 边框圆角选择
-    | "shodowSelect" // 阴影选择
-    | "paddingSelect" // 内边距选择
-    | "rotateSelect" // 旋转选择
-    | "opacitySelect" // 透明度选择
-    | "colorSelect" // 颜色选择
+    // 背景选择
+    | "backgroundSelect"
+    // 边框选择
+    | "boderSelect"
+    // 边框圆角选择
+    | "boderRadiusSelect"
+    // 阴影选择
+    | "shodowSelect"
+    // 内边距选择
+    | "paddingSelect"
+    // 旋转选择
+    | "rotateSelect"
+    // 透明度选择
+    | "opacitySelect"
+    // 颜色选择
+    | "colorSelect"
+    // 配色方案
+    | "colorScheme"
+    // 字体样式
+    | "fontStyle"
+    // 位置
+    | "position"
   options?: any[];
   prefix?: string;
   suffix?: string;
   rules?: any[];
   defaultValue?: any;
+  // 分组表单项
+  children?: IFormItem[];
 }

+ 2 - 2
src/store/modules/stage.ts

@@ -30,7 +30,7 @@ interface StageState {
   wrapperWidth: number;
   // 容器高度
   wrapperHeight: number;
-  // 显示图层
+  // 显示图层面板
   showLayer: boolean;
 }
 
@@ -50,7 +50,7 @@ export const useStageStore = defineStore({
     scrollY: 0,
     wrapperWidth: 0,
     wrapperHeight: 0,
-    showLayer: true
+    showLayer: false
   }),
   getters: {
     // 根据滚动和缩放,重新计算辅助线位置

+ 7 - 1
src/views/designer/component/Configurator.vue

@@ -70,7 +70,6 @@ const handleConfigChange = (config: any) => {
 <style lang="less" scoped>
 .configurator {
   width: 300px;
-  padding: 0 12px;
   height: 100%;
   display: flex;
   flex-direction: column;
@@ -78,6 +77,13 @@ const handleConfigChange = (config: any) => {
     flex: 1;
     overflow-y: scroll;
   }
+  :deep(.ant-tabs-nav) {
+    margin-bottom: 0;
+  }
+  :deep(.ant-tabs-content-holder) {
+    background-color: @bg-color;
+    padding-top: 12px;
+  }
   .config-content {
     padding: 12px;
     padding-top: 0;