颜色配置表单

main
一杯沧海 1 year ago
parent b7d451b5fb
commit 32a7696b66
  1. 16
      src/App.vue
  2. 3
      src/engineer/components/Canvas.vue
  3. 124
      src/engineer/components/switch.vue
  4. 110
      src/engineer/configs/BackgroundConfig.vue
  5. 19
      src/engineer/configs/BaseConfig.vue
  6. 18
      src/engineer/configs/BooleanConfig.vue
  7. 21
      src/engineer/configs/ColorConfig.vue
  8. 69
      src/engineer/configs/ImageConfig.vue
  9. 23
      src/engineer/configs/ListConfig.vue
  10. 47
      src/engineer/configs/MarkConfig.vue
  11. 9
      src/engineer/configs/ObjectConfig.vue
  12. 6
      src/engineer/configs/render.ts
  13. 27
      src/engineer/utils/clone.ts
  14. 1
      src/engineer/utils/index.ts

@ -143,12 +143,14 @@ categories.value.unshift({
{
type: 'list',
field: 'items',
label: '',
label: '轮播图设置',
help: '最多可添加10张图片,建议宽度750px;鼠标拖拽左侧圆点可调整图片顺序',
addable: true,
configs: [{
type: 'image',
field: 'image',
label: '图片',
required: true,
//
inlines: [{
type: 'text',
@ -159,10 +161,8 @@ categories.value.unshift({
type: 'text',
field: 'link',
label: '链接',
// help: '', // "${label}"
help: '请输入链接', // "${label}"
}],
label: '图片',
required: true,
}],
},
{
@ -207,14 +207,18 @@ categories.value.unshift({
items: [
{
image: '',
// title: '',
// link: '',
title: '123',
link: '123',
}
],
indicator: {
style: 'circle',
color: '#000000',
position: 'left',
},
background: {
enabled: true,
value: "#ffffff",
}
},
theme: {

@ -2,6 +2,7 @@
import { computed, ref } from 'vue'
import Draggable from 'vuedraggable'
import { useContext, getModule } from '../context'
import { clone } from '../utils'
import { RenderBlock } from '../render'
import { DddView } from '../views'
@ -73,7 +74,7 @@ function handleDragAdd(e: DraggableEvent): void {
ctx.activeBlockId = block.vid
ctx.hoverViewId = '#canvas'
ctx.configurator = 'block'
ctx.sources[block.vid] = module.init ?? {}
ctx.sources[block.vid] = module?.init ? clone(module.init) : {}
key.value++
}

@ -0,0 +1,124 @@
<script lang="ts" setup>
import { computed, ref } from 'vue'
defineOptions({
name: 'Switch'
})
const props = withDefaults(
defineProps<{
size?: 'small' | 'medium' | 'large'
value?: boolean
loading?: boolean
defaultValue?: boolean
disabled?: boolean
bgActiveColor?: string
}>(),
{
size: 'medium',
defaultValue: false,
disabled: false,
bgActiveColor: '#0256FF'
}
)
const { _width } = formartSize(props.size)
const _bgActiveColor = computed(() => props.bgActiveColor)
const status = ref<boolean>()
status.value = props.value || props.defaultValue
const emits = defineEmits<{
(event: 'change', status: boolean): void
}>()
type tempObj = {
_width: string
_height: string
}
function formartSize(str: string): tempObj {
let _width = "", _height = ""
if (str === 'small') {
_width = "40px"
_height = "20px"
}
if (str === 'medium') {
_width = "40px"
_height = "20px"
}
if (str === 'large') {
_width = "40px"
_height = "20px"
}
return { _width, _height }
}
const handleClick = () => {
if (!props.disabled) {
status.value = !status.value
emits('change', status.value)
}
}
</script>
<template>
<div class="d-switch" :class="{ 'is-checked': status }">
<input
class="d-switch__input"
ref="input"
type="checkbox"
:checked="status"
@change="handleClick"
/>
<span class="d-switch_action"></span>
</div>
</template>
<style lang="less" scoped>
.d-switch {
position: relative;
height: 18px;
transition: #0256FF 0.2s;
width: v-bind(_width);
background: rgb(117, 117, 117);
border-radius: 10px;
display: inline-flex;
align-items: center;
vertical-align: middle;
.d-switch__input {
position: relative;
z-index: 1;
margin: 0;
width: 100%;
height: 100%;
opacity: 0;
}
.d-switch_action {
position: absolute;
transition: 0.2s;
left: 2px;
top: 2px;
z-index: 0;
height: 14px;
width: 14px;
background: #fff;
border-radius: 50%;
}
&.is-checked {
background: v-bind(_bgActiveColor);
.d-switch_action {
left: 100%;
background: #fff;
margin-left: -18px;
}
}
}
</style>

@ -1,62 +1,86 @@
<script lang="ts" setup>
import { computed } from "vue";
import { computed, ref } from "vue";
import { useSource } from "../context"
defineOptions({
name: "DddBackgroundConfig"
})
const props = defineProps<{
field: string
help?: string
features: string[]
label?: string
}>()
const tempString = useSource(props.field)
const typeList = computed(() => {
return props.features.map((item: any)=> {
return {
value: item,
label: formart(item)
}
})
})
defineOptions({
name: "DddBackgroundConfig"
})
const props = defineProps<{
field: string
help?: string
features: string[]
label?: string
}>()
const tempString = useSource<string>(props.field)
const chooseType = ref<string>()
if(typeof tempString.value === 'string'){
chooseType.value = 'color'
}
function formart(str: string) {
const temp: Record<string, any> = {
color: '纯色',
gradient: '渐变',
const typeList = computed(() => {
return props.features.map((item: any) => {
return {
value: item,
label: formart(item)
}
return temp[str]
})
})
function formart(str: string) {
const temp: Record<string, any> = {
color: '纯色',
gradient: '渐变',
}
return temp[str]
}
</script>
<template>
<div class="box">
<label>{{ label }}</label>
<div class="box-typeList">
<div v-for="(item,index) in typeList" :key="index" class="box-typeList-box">
<span>{{ item.label }}</span>
<div>
<div class="box">
<label>{{ label }}</label>
<div class="box-typeList">
<div v-for="(item, index) in typeList" :key="index" :class="{ 'is-active': chooseType === item.value }"
class="box-typeList-box" @click="chooseType = item.value">
<span>{{ item.label }}</span>
</div>
</div>
</div>
<template v-if="chooseType === 'color'">
<label style="display: flex;justify-content: space-between;">
<span>颜色</span>
<input v-model="tempString" type="color">
</label>
</template>
</div>
</template>
<style lang="less" scoped>
.box{
.box {
display: flex;
justify-content: space-between;
align-items: center;
&-typeList {
display: flex;
justify-content: space-between;
align-items: center;
&-typeList{
&-box {
display: flex;
&-box{
display: flex;
color:#fff;
background-color: aqua;
width:50px;
height:20px;
font-size: 12px;
justify-content: center;
align-items: center;
color: #0256ff;
border: 1px solid #0256ff;
width: 50px;
height: 20px;
font-size: 12px;
justify-content: center;
align-items: center;
&.is-active {
background-color: #0256ff;
color: #fff;
}
}
}
}
</style>

@ -0,0 +1,19 @@
<script lang="ts" setup>
import { ref } from 'vue'
import { useSource } from "../context"
defineOptions({
name: 'DddBaseConfig'
})
const props = defineProps<{
field: string
label?: string
help?:string
}>()
const tempStr = useSource<string>(props.field)
</script>
<template>
<div>
</div>
</template>

@ -1,5 +1,7 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { useSource } from '../context'
import Switch from '../components/switch.vue'
defineOptions({
name: "DddBooleanConfig"
@ -13,20 +15,18 @@ const props = defineProps<{
const tempString = useSource<boolean>(props.field)
const defaultValue = computed(() => {
return tempString.value ? true: false
})
</script>
<template>
<div>
<label>
{{ label }}
<label style="display: flex;justify-content: space-between;align-items: center;">
<span>{{ label }}</span>
<Switch :default-value="defaultValue" @change="(e) => tempString=e"></Switch>
</label>
<div>
<label></label>
<input type="radio" :value="true" v-model="tempString"><br>
<label></label>
<input type="radio" :value="false" v-model="tempString"><br>
</div>
</div>
</template>

@ -0,0 +1,21 @@
<script lang="ts" setup>
import { useSource} from "../context"
defineOptions({
name: "DddColorConfig"
})
const props = defineProps<{
field: string
label?: string
help?: string
}>()
const tempStr = useSource<string>(props.field)
</script>
<template>
<label style="display: flex;justify-content: space-between;align-items: center;">
<span>{{ label }}</span>
<input v-model="tempStr" type="color">
</label>
</template>

@ -0,0 +1,69 @@
<script lang="ts" setup>
import { computed } from 'vue';
import { RenderConfig } from './render';
import { useSource } from '../context'
defineOptions({
name: "DddImageConfig"
})
const props = defineProps<{
field: string
label?: string
help?: string
required?: boolean
inlines?: any
}>()
const inlineFieldPrefix = computed(() => {
const i = props.field.lastIndexOf('.')
return i > -1 ? `${props.field.slice(0, i)}.` : ''
})
const img = useSource<string>(props.field)
</script>
<template>
<div class="container">
<div class="container-imgbox">
<span>{{ label }}<span v-if="required" style="color: brown;">*</span></span>
<!-- <input type="text" v-model="img"> -->
</div>
<div class="container-rightbox">
<div v-for="(line, index) in props.inlines" :key="index">
<!-- {{inlineFieldPrefix}}{{ line.field }} -->
<RenderConfig :type="line.type" :props="{
...line,
field: `${inlineFieldPrefix}${line.field}`,
}" />
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.container {
box-sizing: border-box;
border-radius: 2px;
padding: 2px;
display:flex;
gap:10px;
align-items:center;
background-color: #f5f5f5;
margin-bottom: 5px;
&-imgbox {
width: 55px;
height: 55px;
border-radius:5px;
border : 1px solid #ccc;
display:flex;
justify-content: center;
align-items: center;
}
&-rightbox{
display: flex;
flex:1;
overflow: hidden;
flex-direction: column;
}
}
</style>

@ -35,18 +35,19 @@ const add = () => {
</script>
<template>
<div v-for="(_, line) in list" :key="line">
<div v-for="(cfg, idx) in configs" :key="idx">
<RenderConfig
:type="cfg.type"
:props="{
<fieldset>
<legend>{{ label }}设置</legend>
<div v-for="(_, line) in list" :key="line">
<div v-for="(cfg, idx) in configs" :key="idx">
<RenderConfig :type="cfg.type" :props="{
...cfg,
field: `${field}.${line}.${cfg.field}`,
}"
/>
}" />
</div>
</div>
</div>
<div>
<button @click="add">+</button>
</div>
<div>
<button @click="add">+增加</button>
</div>
</fieldset>
</template>

@ -14,21 +14,44 @@ const props = defineProps<{
const tempString = useSource<string>(props.field)
function selectChange(e: any){
console.log(e.target.value)
}
</script>
<template>
<div>
<label>
{{ label }}
</label>
<div>
<select v-model="tempString" @change="selectChange">
<option value="none">不设置</option>
<option v-for="(opt,idx) in values" :key="idx" :value="opt.value">{{ opt.label }}</option>
</select>
<div class="box">
<label>{{ label }}</label>
<div class="box-list">
<div v-for="(opt,idx) in values" :key="idx" class="box-list-item" :class="[tempString === opt.value && 'is-active']" @click="tempString = opt.value">
<span>{{ opt.label }}</span>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.box {
display: flex;
justify-content: space-between;
align-items: center;
&-list {
display: flex;
&-item {
display: flex;
color: #0256ff;
border: 1px solid #0256ff;
width: 50px;
height: 20px;
font-size: 12px;
justify-content: center;
align-items: center;
&.is-active {
background-color: #0256ff;
color: #fff;
}
}
}
}
</style>

@ -1,6 +1,5 @@
<script lang="ts" setup>
import { ModuleConfig } from "..";
import { useSource } from "../context"
import { RenderConfig } from './render';
defineOptions({
@ -18,10 +17,8 @@ defineProps<{
</script>
<template>
<div>
<label>
<span>{{ label }}设置</span>
</label>
<fieldset>
<legend>{{ label }}设置</legend>
<div v-for="(cfg, idx) in configs" :key="idx">
<RenderConfig
:type="cfg.type"
@ -31,5 +28,5 @@ defineProps<{
}"
/>
</div>
</div>
</fieldset>
</template>

@ -6,6 +6,8 @@ import ObjectConfig from './ObjectConfig.vue'
import MarkConfig from "./MarkConfig.vue";
import BooleanConfig from "./BooleanConfig.vue"
import BackgroundConfig from "./BackgroundConfig.vue";
import ImageConfig from "./ImageConfig.vue";
import ColorConfig from './ColorConfig.vue'
const configs: Record<string, Component> = {
text: TextConfig,
@ -13,7 +15,9 @@ const configs: Record<string, Component> = {
object: ObjectConfig,
mark: MarkConfig,
boolean: BooleanConfig,
background:BackgroundConfig,
background: BackgroundConfig,
image: ImageConfig,
color: ColorConfig,
}
function render(type: string, props: Record<string, any>) {

@ -0,0 +1,27 @@
import { error } from "console"
export function clone<T>(v: T): T {
switch (typeof v) {
case "string":
case "boolean":
case "number":
case "undefined":
return v
case "symbol":
case "function":
case "bigint":
throw new Error("invalid type")
case "object":
if (v == null) {
return v
}
if (Array.isArray(v)) {
return v.map(clone) as T
}
const obj = Object.create(null)
for (const [key, value] of Object.entries(v)) {
obj[key] = clone(value)
}
return obj
}
}

@ -1,6 +1,7 @@
export * from './align'
export * from './background'
export * from './border'
export * from './clone'
export * from './clip'
export * from './gap'
export * from './hash'

Loading…
Cancel
Save