Selaa lähdekoodia

feat: 添加表单组件

liaojiaxing 10 kuukautta sitten
vanhempi
commit
24293928ff

+ 0 - 0
src/components/CusForm/BackgroundSelect.vue


+ 5 - 0
src/components/CusForm/index.ts

@@ -0,0 +1,5 @@
+import CusForm from './src/index.vue';
+
+export default {
+  CusForm
+}

+ 48 - 0
src/components/CusForm/src/BackgroundSelect.vue

@@ -0,0 +1,48 @@
+<template>
+  <div>
+    <Select v-model="background.type" :options="options" style="width: 100%" />
+    <template v-if="background.type === 'color'">
+      <ColorPicker v-model="background.color" />
+    </template>
+    <template v-else-if="background.type === 'image'">
+      <div class="img-preview">
+        <Image :src="background.image" />
+        <div class="img-tip">选择图片</div>
+      </div>
+      <RadioGroup v-model="background.fillType">
+        <RadioButton value="cover">填充</RadioButton>
+        <RadioButton value="contain">适应</RadioButton>
+        <RadioButton value="stretch">拉伸</RadioButton>
+      </RadioGroup>
+    </template>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { defineEmits, defineProps, computed } from "vue";
+import { Select, Image, RadioGroup, RadioButton } from "ant-design-vue";
+
+const props = defineProps<{
+  background: {
+    type: "none" | "color" | "image";
+    color?: string;
+    image?: string;
+    fillType?: "cover" | "contain" | "stretch";
+  };
+}>();
+
+const emit = defineEmits(["update:background"]);
+
+const background = computed({
+  get: () => props.background,
+  set: (val) => emit("update:background", val),
+});
+
+const options = [
+  { label: "无", value: "none" },
+  { label: "颜色", value: "color" },
+  { label: "图片", value: "image" },
+];
+</script>
+
+<style scoped></style>

+ 120 - 0
src/components/CusForm/src/index.vue

@@ -0,0 +1,120 @@
+<template>
+  <Form :model="formModel" ref="formRef" layout="horizontal">
+    <FormItem
+      v-for="item in formItems"
+      :key="item.key"
+      :label="item.label"
+      :name="item.key"
+      :rules="item.rules"
+    >
+      <template v-if="item.type === 'input'">
+        <Input v-model="formModel[item.key]" />
+      </template>
+      <template v-else-if="item.type === 'select'">
+        <Select v-model="formModel[item.key]" :options="item.options" />
+      </template>
+      <template v-else-if="item.type === 'inputnumber'">
+        <InputNumber v-model="formModel[item.key]" />
+      </template>
+      <template v-else-if="item.type === 'image'">
+        <Image v-model="formModel[item.key]" />
+      </template>
+      <template v-else-if="item.type === 'checkbox'">
+        <Checkbox v-model="formModel[item.key]" />
+      </template>
+      <template v-else-if="item.type === 'backgroundSelect'">
+        <BackgroundSelect v-model:background="formModel[item.key]" />
+      </template>
+      <!-- <template v-else-if="item.type === 'boderSelect'">
+        <BoderSelect v-model="formModel[item.key]" />
+      </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>
+  </Form>
+</template>
+
+<script setup lang="ts">
+import type { FormInstance } from "ant-design-vue";
+import { ref, defineProps, defineExpose, computed, watch } from "vue";
+import {
+  Form,
+  FormItem,
+  Input,
+  Select,
+  InputNumber,
+  Checkbox,
+  Image,
+} from "ant-design-vue";
+import BackgroundSelect from "./BackgroundSelect.vue";
+
+interface FormItem {
+  label: string;
+  key: string;
+  type:
+    | "input"
+    | "select"
+    | "inputnumber"
+    | "image"
+    | "checkbox"
+    | "backgroundSelect" // 背景选择
+    | "boderSelect" // 边框选择
+    | "boderRadiusSelect" // 边框圆角选择
+    | "shodowSelect" // 阴影选择
+    | "paddingSelect" // 内边距选择
+    | "rotateSelect" // 旋转选择
+    | "opacitySelect"; // 透明度选择
+  options?: any[];
+  prefix?: string;
+  suffix?: string;
+  rules?: any[];
+  defaultValue?: any;
+}
+
+const props = defineProps<{
+  columns: FormItem[];
+  formModel: Record<string, any>;
+}>();
+
+const formModel = ref<Record<string, any>>({});
+const formRef = ref<FormInstance>();
+
+const formItems = computed(() => {
+  return props.columns.map((item) => {
+    return {
+      ...item,
+      rules: item.rules || [],
+    };
+  });
+});
+
+watch(
+  () => props.columns,
+  () => {
+    props.columns.forEach((item) => {
+      formModel.value[item.key] = item?.defaultValue;
+      if (props.formModel[item.key] !== undefined) {
+        formModel.value[item.key] = props.formModel[item.key];
+      }
+    });
+  },
+  { immediate: true }
+)
+
+defineExpose(formRef.value);
+</script>
+
+<style scoped></style>

+ 33 - 18
src/views/designer/component/Configurator.vue

@@ -1,21 +1,28 @@
 <template>
-  <div>
-    <Tabs type="card">
-      <!-- 页面设置 -->
-       <template v-if="projectStore.selectedElementKeys.length === 0">
-        <TabPane key="0" tab="页面">
-          <div>页面设置</div>
-        </TabPane>
-       </template>
-      <!-- 组件设置 -->
-      <template v-else>
-        <TabPane key="1" tab="组件">
-          <div>基本配置</div>
-        </TabPane>
-        <TabPane key="2" tab="样式">
-          <div>样式配置</div>
-        </TabPane>
-      </template>
+  <div class="configurator">
+    <!-- 页面设置 -->
+    <Tabs v-if="projectStore.selectedElementKeys.length === 0" centered>
+      <TabPane key="1" tab="页面">
+        <div class="config-content">
+          <PageConfig/>
+        </div>
+      </TabPane>
+    </Tabs>
+
+    <!-- 组件设置 -->
+    <Tabs  centered v-else>
+      <TabPane key="1" tab="内容">
+        <div class="config-content">内容配置</div>
+      </TabPane>
+      <TabPane key="2" tab="事件">
+        <div class="config-content">事件处理</div>
+      </TabPane>
+      <TabPane key="3" tab="动画">
+        <div class="config-content">动画处理</div>
+      </TabPane>
+      <TabPane key="4" tab="组件">
+        <div class="config-content">样式属性</div>
+      </TabPane>
     </Tabs>
   </div>
 </template>
@@ -23,11 +30,19 @@
 <script setup lang="ts">
 import { Tabs, TabPane } from 'ant-design-vue';
 import { useProjectStore } from '@/store/modules/project';
+import PageConfig from './PageConfig.vue';
 
 const projectStore = useProjectStore();
 
 </script>
 
-<style scoped>
+<style lang="less" scoped>
+.configurator {
+  width: 300px;
 
+  .config-content {
+    padding: 12px;
+    padding-top: 0;
+  }
+}
 </style>

+ 21 - 0
src/views/designer/component/PageConfig.vue

@@ -0,0 +1,21 @@
+<template>
+  <div>
+    <CusForm :columns="formItems" />
+  </div>
+</template>
+
+<script setup lang="ts">
+// import { CusForm } from '@/components/CusForm';
+
+const formItems = [
+  {
+    label: '页面背景',
+    key: 'background',
+    type: 'backgroundSelect',
+  }
+]
+</script>
+
+<style scoped>
+
+</style>

+ 0 - 1
src/views/designer/index.vue

@@ -101,7 +101,6 @@ const projectStore = useProjectStore();
 }
 .config-wrapper {
   position: relative;
-  width: 200px;
   background: #fff;
   border-left: solid 1px #eee;
 }