Commit 7521b52f authored by 郭志伟's avatar 郭志伟

Merge branch 'feat/share' into 'feat/v1.3'

Feat/share

See merge request !33
parents 2b137439 c28d4c19
<template>
<div class="form-list">
<Card class="form-list-card" :key="index" v-for="(item, index) in list">
<div slot='title' class="Fl-card-title">
<h4>项目{{index + 1}}</h4>
<a @click="del(index)">删除</a>
</div>
<Form @submit.native.prevent :model="item" :label-width="50">
<FormItem :prop="`${keywords.key}`" :label="keywords.name" :key="idx" v-for="(keywords, idx) in formControl">
<component :is="getComponent(keywords.type)" v-bind="keywords.props" :options="keywords.options" :disabled="shareDisableUrl(item, keywords)" v-model="item[keywords.key]" @input="handleModelChange($event, keywords.key, index)" />
</FormItem>
</Form>
</Card>
<div class="form-list-button">
<Button type="dashed" icon="plus-round" @click="add">添加项目</Button>
</div>
</div>
</template>
<script>
import FormList from '../mixins/formList.mixin.ts';
import { SHOP_CART_CONFIG, SHARE_CONFIG, DEFAULT_CONFIG } from '@service/staticData.service';
const CONFIG_MAP = {
['购物车']: SHOP_CART_CONFIG,
['分享']: SHARE_CONFIG,
['自定义']: DEFAULT_CONFIG
};
export default {
mixins: [FormList],
data() {
return {
oldPersets: []
};
},
methods: {
shareDisableUrl(item, keywords) {
return item.persets === '分享' && keywords.key === 'url';
},
handleModelChange(e, key, index) {
if (key !== 'persets') return;
if (e !== this.oldPersets[index]) {
this.$set(this.list, index, JSON.parse(JSON.stringify(CONFIG_MAP[e])));
this.oldPersets[index] = e;
}
}
}
}
</script>
<style lang="less" scoped>
.form-list {
/deep/ .ivu-card {
margin-bottom: 16px;
.ivu-form {
.ivu-form-item {
display: flex;
margin-bottom: 12px;
}
.ivu-form-item-label {
text-align: left;
width: 60px !important;
font-size: 12px;
}
.ivu-form-item-content {
flex: 1 !important;
}
}
&:hover {
box-shadow: 0 0 14px 0 rgba(46,140,240,0.20);
border: 1px solid #2E8CF0 !important;
}
}
h3 {
padding-bottom: 10px;
text-align: center;
}
&-card {
/deep/ .ivu-card-head{
background: #f0f2f5;
}
/deep/ .ivu-card-body {
padding: 10px !important;
}
.Fl-card-title {
display: flex;
justify-content: space-between;
}
}
&-button {
// margin-top: 20px;
// text-align: center;
}
}
</style>
\ No newline at end of file
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<Icon type="ios-arrow-forward" /> <Icon type="ios-arrow-forward" />
</div> </div>
<div class="color-selector" v-if="showToColor"> <div class="color-selector" v-if="showToColor">
<Input class="color-selector-input" v-model="toColor" placeholder="请输入" @input="change"></Input> <Input class="color-selector-input" v-model="toColor" placeholder="请输入" @input="change($event, 'to')"></Input>
<ColorPicker placement="bottom-end" v-model="toColor" :alpha="alpha" @on-active-change="change($event, 'to')" @on-change="change($event, 'to')" /> <ColorPicker placement="bottom-end" v-model="toColor" :alpha="alpha" @on-active-change="change($event, 'to')" @on-change="change($event, 'to')" />
</div> </div>
</div> </div>
...@@ -53,13 +53,14 @@ ...@@ -53,13 +53,14 @@
if (val && this.toColor) { if (val && this.toColor) {
this.$emit('input', [this.color, this.toColor]); this.$emit('input', [this.color, this.toColor]);
} else { } else {
this.toColor = '';
this.$emit('input', this.color); this.$emit('input', this.color);
} }
} }
}, },
methods: { methods: {
change(val, type) { change(val, type) {
if (type === 'to') { if (type === 'to' || this.toColor) {
this.$emit('input', [this.color, this.toColor]); this.$emit('input', [this.color, this.toColor]);
} else { } else {
this.$emit('input', val); this.$emit('input', val);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
</div> </div>
<Form @submit.native.prevent :model="item" :label-width="50"> <Form @submit.native.prevent :model="item" :label-width="50">
<FormItem :prop="`${keywords.key}`" :label="keywords.name" :key="idx" v-for="(keywords, idx) in formControl"> <FormItem :prop="`${keywords.key}`" :label="keywords.name" :key="idx" v-for="(keywords, idx) in formControl">
<component :is="getComponent(keywords.type)" :options="item.options" v-model="item[keywords.key]" /> <component :is="getComponent(keywords.type)" v-bind="keywords.props" :options="keywords.options" v-model="item[keywords.key]" />
</FormItem> </FormItem>
</Form> </Form>
</Card> </Card>
...@@ -17,72 +17,9 @@ ...@@ -17,72 +17,9 @@
</div> </div>
</template> </template>
<script> <script>
import ComponentSelect from '../ComponentSelect/index.vue'; import FormList from '../mixins/formList.mixin.ts';
import Upload from '../Upload/index.vue';
import ColorSelector from '../ColorSelector/index.vue';
export default { export default {
components: { mixins: [FormList]
ComponentSelect,
Upload,
ColorSelector
},
props: {
value: {
type: Array,
default: () => []
},
formControl: {
type: Array,
default: () => []
},
name: String
},
data() {
return {
list: this.value,
}
},
watch: {
list(val) {
this.$emit('input', val);
},
value(val) {
this.list = val;
}
},
methods: {
getComponent(type) {
let result = type;
switch (type) {
case 'text':
result = 'Input';
break;
case 'select':
result = 'BaseSelect';
break;
case 'checkbox' :
result = 'Checkbox';
break;
case 'textarea' :
result = 'Textarea';
break;
case 'number' :
result = 'Number';
break;
}
return result;
},
add() {
const object = this.formControl.reduce((pre, cur) => {
pre[cur.key] = '';
return pre;
}, {})
this.list.push(object);
},
del(index) {
this.list.splice(index, 1);
}
}
} }
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
......
<template>
<iSwitch v-model="switchVal" size="large" class="switch-btn">
<span slot="open">开启</span>
<span slot="close">关闭</span>
</iSwitch>
</template>
<script>
export default {
props: {
value: Boolean,
},
data() {
return {
switchVal: this.value,
}
},
watch: {
switchVal(val) {
this.$emit('input', val);
}
}
}
</script>
<style scoped>
.switch-btn {
transform: scale(0.8);
margin-left: -7px;
}
</style>
\ No newline at end of file
import {Component, Prop, Watch, Vue } from 'vue-property-decorator';
import ComponentSelect from '../ComponentSelect/index.vue';
import Upload from '../Upload/index.vue';
import ColorSelector from '../ColorSelector/index.vue';
import SwitchBtn from '../SwitchBtn/index.vue';
import BaseSelect from '../BaseSelect/index.vue';
@Component({ name: 'formListMixin', components: { ComponentSelect, Upload, ColorSelector, SwitchBtn, BaseSelect } })
export default class DynamicFormMixin extends Vue {
@Prop({ type: Array, default: () => [] }) value;
@Prop({ type: Array, default: () => [] }) formControl;
@Prop({ type: Object, default: () => [] }) formDefault;
@Prop(String) name;
list: object[] = [];
@Watch('list')
onListChange(val) {
this.$emit('input', val);
}
@Watch('value', { immediate: true })
onValueChange(val) {
this.list = val;
}
getComponent(type) {
let result = type;
switch (type) {
case 'text':
result = 'Input';
break;
case 'select':
result = 'BaseSelect';
break;
case 'checkbox':
result = 'Checkbox';
break;
case 'textarea':
result = 'Textarea';
break;
case 'number' :
result = 'Number';
break;
case 'switch':
result = 'SwitchBtn';
break;
}
return result;
}
add() {
const object = this.formControl.reduce((pre, cur) => {
pre[cur.key] = this.formDefault[cur.key] || '';
return pre;
}, {});
this.list.push(object);
}
del(index) {
this.list.splice(index, 1);
}
}
\ No newline at end of file
...@@ -8,9 +8,11 @@ import BaseSelect from '../DynamicForm/component/BaseSelect/index.vue'; ...@@ -8,9 +8,11 @@ import BaseSelect from '../DynamicForm/component/BaseSelect/index.vue';
import Textarea from '../DynamicForm/component/Textarea/index.vue'; import Textarea from '../DynamicForm/component/Textarea/index.vue';
import Number from '../DynamicForm/component/Number/index.vue'; import Number from '../DynamicForm/component/Number/index.vue';
import FormList from '../DynamicForm/component/FormList/index.vue'; import FormList from '../DynamicForm/component/FormList/index.vue';
import { resizeDiv, getStyle } from '@/service/utils.service'; import BackTopPicker from '../DynamicForm/component/BackTopPicker/index.vue';
import SwitchBtn from '../DynamicForm/component/SwitchBtn/index.vue';
import { SHOP_CART_CONFIG } from '@service/staticData.service';
@Component({ components: { Upload, ColorSelector, BaseSelect, Textarea, Number, FormList }, name: 'DynamicPageForm' }) @Component({ components: { Upload, ColorSelector, BaseSelect, Textarea, Number, FormList, BackTopPicker, SwitchBtn }, name: 'DynamicPageForm' })
export default class DynamicPageForm extends Mixins(ContextMenuMixin) { export default class DynamicPageForm extends Mixins(ContextMenuMixin) {
@Getter('pageData') pageData; @Getter('pageData') pageData;
...@@ -29,21 +31,22 @@ export default class DynamicPageForm extends Mixins(ContextMenuMixin) { ...@@ -29,21 +31,22 @@ export default class DynamicPageForm extends Mixins(ContextMenuMixin) {
type: 'ColorSelector' type: 'ColorSelector'
} }
]; ];
titleSchema: object[] = [
propsSchame: object[] = [
{ {
key: 'titleBgColor', key: 'titleBgColor',
name: '标题栏 背景色', name: '背景色',
type: 'ColorSelector', type: 'ColorSelector',
props: { props: {
gradient: true, gradient: true,
alpha: false alpha: false
} }
}, },
];
bottomSchema: object[] = [
{ {
key: 'showPageBottomTip', key: 'showPageBottomTip',
name: '底部提示', name: '状态',
type: 'checkbox' type: 'SwitchBtn'
}, },
{ {
key: 'pageBottomTxt', key: 'pageBottomTxt',
...@@ -55,21 +58,32 @@ export default class DynamicPageForm extends Mixins(ContextMenuMixin) { ...@@ -55,21 +58,32 @@ export default class DynamicPageForm extends Mixins(ContextMenuMixin) {
name: '提示颜色', name: '提示颜色',
type: 'ColorSelector' type: 'ColorSelector'
}, },
];
floatSchema: object[] = [
{ {
key: 'showBackTop', key: 'showBackTop',
name: '返回顶部', name: '返回顶部',
type: 'checkbox' type: 'SwitchBtn'
}, },
{ {
key: 'btAttachVal', key: 'btAttachVal',
name: '添加按钮', name: '添加按钮',
desc: '添加按钮', desc: '添加按钮',
type: 'FormList', type: 'BackTopPicker',
formControl: [ formControl: [
{ {
key: 'name', key: 'persets',
name: '名称', name: '预设属性',
type: 'text' type: 'select',
options: ['购物车', '分享', '自定义']
},
{
key: 'txt',
name: '文字',
type: 'text',
props: {
placeholder: '(选填) 图标下方文字',
}
}, },
{ {
key: 'url', key: 'url',
...@@ -86,21 +100,57 @@ export default class DynamicPageForm extends Mixins(ContextMenuMixin) { ...@@ -86,21 +100,57 @@ export default class DynamicPageForm extends Mixins(ContextMenuMixin) {
name: '文字颜色', name: '文字颜色',
type: 'ColorSelector' type: 'ColorSelector'
}, },
{
key: 'iconColor',
name: '图标颜色',
type: 'ColorSelector'
},
{ {
key: 'background', key: 'background',
name: '背景颜色', name: '背景颜色',
type: 'ColorSelector' type: 'ColorSelector'
},
{
key: 'size',
name: '尺寸',
type: 'Slider',
props: {
min: 14,
max: 68
}
},
{
key: 'iconSize',
name: '图标尺寸',
type: 'Slider',
props: {
min: 14,
max: 68
}
},
{
key: 'radius',
name: '圆角',
type: 'checkbox'
},
{
key: 'shadow',
name: '阴影',
type: 'checkbox'
} }
] ],
}, formDefault: SHOP_CART_CONFIG
}
]; ];
get propsSchema() {
return [...this.titleSchema, ...this.bottomSchema, ...this.floatSchema];
}
@Watch('pageData', { immediate: true, deep: true }) @Watch('pageData', { immediate: true, deep: true })
onElementChange(newVal) { onElementChange() {
this.commonStyleSchame.forEach(schame => { this.commonStyleSchame.forEach(schame => {
this.$set(this.commonStyleForm, schame.key, this.pageData?.commonStyle[schame.key]); this.$set(this.commonStyleForm, schame.key, this.pageData?.commonStyle[schame.key]);
}); });
this.propsSchame.forEach(schame => { this.propsSchema.forEach(schame => {
this.$set(this.propsForm, schame.key, this.pageData?.props?.[schame.key]); this.$set(this.propsForm, schame.key, this.pageData?.props?.[schame.key]);
}); });
} }
......
<template> <template>
<div class="dynamic-form"> <div class="dynamic-form">
<h2>{{title}}</h2> <h2>{{title}}</h2>
<Form class="dynamic-form-component" :label-width="80" :model="propsForm" @submit.native.prevent> <Form class="dynamic-form-component" :label-width="80" :model="propsForm" @submit.native.prevent>
<h3>基础属性</h3> <h3>基础属性</h3>
<template v-for="(item, index) in propsSchame"> <h4>标题栏</h4>
<FormItem class="Df-component-formitem" :label="item.name" > <template v-for="(item, index) in titleSchema">
<FormItem class="Df-component-formitem" :label="item.name" :key="'titleSchema_' + index">
<component :is="item.type" :options="item.options" v-bind="item.props" v-model="propsForm[item.key]" :formControl="item.formControl" />
</FormItem>
</template>
<h4>底部提示</h4>
<template v-for="(item, index) in bottomSchema">
<FormItem class="Df-component-formitem" :label="item.name" :key="'bottomSchema_' + index">
<component :is="item.type" :options="item.options" v-bind="item.props" v-model="propsForm[item.key]" :formControl="item.formControl" /> <component :is="item.type" :options="item.options" v-bind="item.props" v-model="propsForm[item.key]" :formControl="item.formControl" />
</FormItem> </FormItem>
</template> </template>
</Form> <h4>悬浮窗</h4>
<Form class="dynamic-form-component" :label-width="80" :model="commonStyleForm" @submit.native.prevent> <template v-for="(item, index) in floatSchema">
<h3>基础样式</h3> <FormItem class="Df-component-formitem" :label="item.name" :key="'floatSchema_' + index">
<template v-for="(item, index) in commonStyleSchame"> <component :is="item.type" :options="item.options" v-bind="item.props" v-model="propsForm[item.key]" :formDefault="item.formDefault" :formControl="item.formControl" />
<FormItem class="Df-component-formitem" :label="item.name" >
<component :is="item.type" :options="item.options" v-bind="item.props" v-model="commonStyleForm[item.key]" />
</FormItem> </FormItem>
</template> </template>
</Form>
<Form class="dynamic-form-component" :label-width="80" :model="commonStyleForm" @submit.native.prevent>
<h3>基础样式</h3>
<template v-for="(item, index) in commonStyleSchame">
<FormItem class="Df-component-formitem" :label="item.name" :key="index">
<component :is="item.type" :options="item.options" v-bind="item.props" v-model="commonStyleForm[item.key]" />
</FormItem>
</template>
</Form> </Form>
</div> </div>
</template> </template>
...@@ -28,7 +41,7 @@ ...@@ -28,7 +41,7 @@
border-bottom: 8px solid #F5F6FA; border-bottom: 8px solid #F5F6FA;
text-align: center; text-align: center;
} }
h3 { h3, h4 {
padding: 10px 0; padding: 10px 0;
margin-bottom: 10px; margin-bottom: 10px;
border-bottom: 1px solid #ebeef5; border-bottom: 1px solid #ebeef5;
......
<template>
<cr-back-top :show-back-top="false" :list="list" class="back-top-preview" />
</template>
<script>
import { BACK_TOP_CONFIG } from '@service/staticData.service';
import { mapGetters } from 'vuex';
export default {
name: 'BackTopPreview',
data() {
return {
oldPersets: []
};
},
computed: {
...mapGetters(['pageData']),
list() {
const { btAttachVal, showBackTop } = this.pageData.props;
const btnGroup = btAttachVal.map(item => {
let it = JSON.parse(JSON.stringify(item));
delete it.url;
return it;
});
if (showBackTop) {
btnGroup.splice(0, 0, BACK_TOP_CONFIG);
}
return btnGroup;
}
},
}
</script>
<style lang="less" scoped>
.back-top-preview {
position: absolute;
}
</style>
\ No newline at end of file
<template>
<cr-nav-bar
class="nav-bar"
:title="tille"
:left-arrow="false"
left-text=""
:fixed="false"
:style="titleStyle"
/>
</template>
<script>
import { hexToRgb } from '@service/color.service';
import { mapGetters } from 'vuex';
export default {
name: 'TitlePreview',
computed: {
...mapGetters(['pageData']),
tille() {
return '标题';
},
titleStyle() {
const { titleBgColor } = this.pageData.props;
return this.getTitleStyle(titleBgColor);
}
},
methods: {
getTitleStyle(bgcolor = "#fff") {
if (!EASY_ENV_IS_BROWSER) return;
const DARK_COLOR = "#000";
const LIGHT_COLOR = "#fff";
const isGradient = Array.isArray(bgcolor);
let rgbColor = isGradient ? bgcolor[0] : bgcolor;
if (rgbColor.toLocaleLowerCase().indexOf("rgb") === -1) rgbColor = hexToRgb(rgbColor);
const isDarkContent = 0.213 * rgbColor[0] + 0.715 * rgbColor[1] + 0.072 * rgbColor[2] <= 255 / 2;
const color = isDarkContent ? LIGHT_COLOR : DARK_COLOR;
const background = isGradient ? `linear-gradient(90deg, ${bgcolor[0]}, ${bgcolor[1]})` : bgcolor;
return {
color,
background
};
}
}
}
</script>
<style lang="less" scoped>
@deep: ~'>>>';
.nav-bar {
@{deep} .cr-nav-bar {
z-index: inherit !important;
background-color: transparent;
&__title {
color: inherit;
}
}
}
</style>
...@@ -4,8 +4,9 @@ import type { PageInfo, Page, GridLayout } from '@store/modules/editor/state'; ...@@ -4,8 +4,9 @@ import type { PageInfo, Page, GridLayout } from '@store/modules/editor/state';
import TransformStyleMixin from '@page/mixins/transformStyle.mixin'; import TransformStyleMixin from '@page/mixins/transformStyle.mixin';
import FreedomContainer from '@editor/component/FreedomContainer/index.vue'; import FreedomContainer from '@editor/component/FreedomContainer/index.vue';
import PageBottomTip from './component/PageBottomTip/index.vue'; import PageBottomTip from './component/PageBottomTip/index.vue';
import BackTopPreview from './component/BackTopPreview/index.vue';
@Component({ components: { FreedomContainer, PageBottomTip }, name: 'OperationPanel' }) import TitlePreview from './component/TitlePreview/index.vue';
@Component({ components: { FreedomContainer, PageBottomTip, BackTopPreview, TitlePreview }, name: 'OperationPanel' })
export default class OperationPanel extends Mixins(TransformStyleMixin) { export default class OperationPanel extends Mixins(TransformStyleMixin) {
@Getter('pageData') pageData; @Getter('pageData') pageData;
@State(state => state.editor.gridLayout) gridLayout?: GridLayout; @State(state => state.editor.gridLayout) gridLayout?: GridLayout;
......
<template> <template>
<div :class="[{'Dcm-container-panel_in': isDragIn, 'Dcm-container-panel_draging': isDraging}, 'Dcm-container-panel']" @dragover.prevent @dragenter="dragenter" @dragover="dragover" <div class="Dcm-container-panel_container">
@dragleave="dragleave" @drop="drops"> <title-preview />
<grid-layout <div :class="[{'Dcm-container-panel_in': isDragIn, 'Dcm-container-panel_draging': isDraging}, 'Dcm-container-panel']" @dragover.prevent @dragenter="dragenter" @dragover="dragover"
:layout.sync="layout" @dragleave="dragleave" @drop="drops">
:col-num="gridLayout.colNum" <grid-layout
:row-height="gridLayout.rowHeight" :layout.sync="layout"
:margin="[0, 0]" :col-num="gridLayout.colNum"
:is-draggable="gridLayout.draggable" :row-height="gridLayout.rowHeight"
:is-resizable="true" :margin="[0, 0]"
:is-mirrored="false" :is-draggable="gridLayout.draggable"
:vertical-compact="true" :is-resizable="true"
:use-css-transforms="true" :is-mirrored="false"
:style="transformStyle(pageData.commonStyle)" :vertical-compact="true"
@click.native.stop="toggle(false)" :use-css-transforms="true"
@layout-updated="layoutUpdatedEvent" :style="transformStyle(pageData.commonStyle)"
> @click.native.stop="toggle(false)"
<grid-item @click.native.stop="handleElementClick(index, null)" v-for="(item, index) in pageData.elements" @layout-updated="layoutUpdatedEvent"
:x="item.point.x"
:y="item.point.y"
:w="item.point.w"
:h="item.point.h"
:i="item.point.i"
:key="item.point.i + index"
@contextmenu.native.prevent="show($event, index)"
@resized="resizedEvent"
@moved="movedEvent"
:style="transformStyle(item.commonStyle, item.name)"
:class="{'Dcmcp-item_selected': curEleIndex === index && curChildIndex === null}">
<component ref="container" :id="item.id" class="Dcmcp-item-com" @handleElementClick="handleElementClick" :containerIndex="index" :childItem="item" :is="item.name" :key="index" v-bind="item.props"></component>
</grid-item>
<grid-item
v-if="pageData.props.showPageBottomTip"
:x="bottomInfo.x"
:y="bottomInfo.y"
:w="bottomInfo.w"
:h="bottomInfo.h"
:i="bottomInfo.i"
:static="true"
:key="bottomInfo.i + pageData.elements.length"
> >
<page-bottom-tip /> <grid-item @click.native.stop="handleElementClick(index, null)" v-for="(item, index) in pageData.elements"
</grid-item> :x="item.point.x"
</grid-layout> :y="item.point.y"
:w="item.point.w"
:h="item.point.h"
:i="item.point.i"
:key="item.point.i + index"
@contextmenu.native.prevent="show($event, index)"
@resized="resizedEvent"
@moved="movedEvent"
:style="transformStyle(item.commonStyle, item.name)"
:class="{'Dcmcp-item_selected': curEleIndex === index && curChildIndex === null}">
<component ref="container" :id="item.id" class="Dcmcp-item-com" @handleElementClick="handleElementClick" :containerIndex="index" :childItem="item" :is="item.name" :key="index" v-bind="item.props"></component>
</grid-item>
<grid-item
v-if="pageData.props.showPageBottomTip"
:x="bottomInfo.x"
:y="bottomInfo.y"
:w="bottomInfo.w"
:h="bottomInfo.h"
:i="bottomInfo.i"
:static="true"
:key="bottomInfo.i + pageData.elements.length"
>
<page-bottom-tip />
</grid-item>
</grid-layout>
</div>
<back-top-preview />
</div> </div>
</template> </template>
<script lang="ts" src="./index.ts"></script> <script lang="ts" src="./index.ts"></script>
...@@ -60,16 +64,21 @@ ...@@ -60,16 +64,21 @@
} }
.Dcm-container-panel { .Dcm-container-panel {
margin: 30px auto; &_container {
position: relative;
width: 375px;
height: 667px;
margin: 30px auto;
box-shadow: 2px 3px 10px rgba(0, 0, 0, 0.2);
}
width: 375px; width: 375px;
height: 667px; height: 619px;
min-height: 667px; min-height: 619px;
overflow-y: scroll; overflow-y: scroll;
background-color: rgb(244, 244, 244); background-color: rgb(244, 244, 244);
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.2);
/deep/ .vue-grid-layout { /deep/ .vue-grid-layout {
min-height: 667px; min-height: 619px;
.vue-grid-item { .vue-grid-item {
display: flex; display: flex;
......
...@@ -15,7 +15,6 @@ import localStorage from '@service/localStorage.service'; ...@@ -15,7 +15,6 @@ import localStorage from '@service/localStorage.service';
import EventBus from '@service/eventBus.service'; import EventBus from '@service/eventBus.service';
import { getStyle } from '@service/utils.service'; import { getStyle } from '@service/utils.service';
import OperationPanel from '@editor/component/OperationPanel/index.vue'; import OperationPanel from '@editor/component/OperationPanel/index.vue';
import type { PageInfo, Page, GridLayout } from '../../../store/modules/editor/state'; import type { PageInfo, Page, GridLayout } from '../../../store/modules/editor/state';
@Component({components: { GridLayout: VueGridLayout.GridLayout, @Component({components: { GridLayout: VueGridLayout.GridLayout,
......
...@@ -89,11 +89,16 @@ export const defaultState = { ...@@ -89,11 +89,16 @@ export const defaultState = {
showBackTop: true, showBackTop: true,
btAttachVal: [ btAttachVal: [
{ {
name: '购物车', persets: '购物车',
icon: 'shopping-cart-o', icon: 'shopping-cart-o',
url: 'xyqb://shoppingCartTab', url: 'xyqb://shoppingCart?needLogin=1',
color: '#333', color: '#333',
background: '#fff' iconColor: '#333',
background: '#fff',
shadow: true,
radius: true,
size: 46,
iconSize: 20
} }
], ],
}, },
......
// tslint:disable
import { isApp } from './utils.service';
// RGB转HEX
export function rgbToHex(r, g, b) {
const hex = ((r << 16) | (g << 8) | b).toString(16);
return "#" + new Array(Math.abs(hex.length - 7)).join("0") + hex;
}
// HEX转RGB
export function hexToRgb(hex) {
var rgb = [];
for (let i = 1; i < 7; i += 2) {
rgb.push(parseInt("0x" + hex.slice(i, i + 2)));
}
return rgb;
}
// 计算RGB渐变色色值
export function gradient(startColor, endColor, step) {
// 将 hex 转换为rgb
let sColor = hexToRgb(startColor);
let eColor = hexToRgb(endColor);
// 计算R\G\B每一步的差值
let rStep = (eColor[0] - sColor[0]) / step;
let gStep = (eColor[1] - sColor[1]) / step;
let bStep = (eColor[2] - sColor[2]) / step;
let gradientColorArr = [];
for (let i = 0; i < step; i++) {
// 计算每一步的hex值
gradientColorArr.push(
rgbToHex(
parseInt(rStep * i + sColor[0]),
parseInt(gStep * i + sColor[1]),
parseInt(bStep * i + sColor[2])
)
);
}
return gradientColorArr;
}
export function colorToRgb(color) {
// 16进制颜色值的正则
let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
// 把颜色值变成小写
color = color.toLowerCase();
if (reg.test(color)) {
// 如果只有三位的值,需变成六位,如:#fff => #ffffff
if (color.length === 4) {
let colorNew = "#";
for (let i = 1; i < 4; i += 1) {
colorNew += color.slice(i, i + 1).concat(color.slice(i, i + 1));
}
color = colorNew;
}
// 处理六位的颜色值,转为RGB
let colorChange = [];
for (let i = 1; i < 7; i += 2) {
colorChange.push(parseInt("0x" + color.slice(i, i + 2)));
}
return "RGB(" + colorChange.join(",") + ")";
} else {
return color;
}
}
// RGB TO RGBA
export function rgbToRgba(rgb, opacity) {
return rgb.replace(")", `, ${opacity})`);
}
// 判断色值
export function isColor(color) {
var re1 = /^#([0-9a-f]{6}|[0-9a-f]{3})$/i;
var re2 = /^rgb\(([0-9]|[0-9][0-9]|25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9])\\,([0-9]|[0-9][0-9]|25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9])\\,([0-9]|[0-9][0-9]|25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9])\)$/i;
var re3 = /^rgba\(([0-9]|[0-9][0-9]|25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9])\\,([0-9]|[0-9][0-9]|25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9])\\,([0-9]|[0-9][0-9]|25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9])\\,(1|1.0|0.[0-9])\)$/i;
return re2.test(color) || re1.test(color) || re3.test(color);
}
'use strict';
export const SHOP_CART_CONFIG = {
persets: '购物车',
txt: '',
icon: 'shopping-cart-o',
url: 'xyqb://shoppingCart?needLogin=1',
color: '#333',
iconColor: '#333',
background: '#fff',
shadow: true,
radius: true,
size: 46,
iconSize: 20
};
export const BACK_TOP_CONFIG = {
persets: '自定义',
icon: 'back-top-o',
background: '#fff',
color: '#333',
size: 46,
iconSize: 20,
txt: '顶部'
};
export const SHARE_CONFIG = {
persets: '分享',
txt: '',
icon: 'share',
url: '',
color: '#333',
iconColor: '#333',
background: '#fff',
shadow: true,
radius: true,
size: 46,
iconSize: 20
};
export const DEFAULT_CONFIG = {
persets: '自定义',
txt: '',
icon: '',
url: '',
color: '#333',
iconColor: '#333',
background: '#fff',
shadow: true,
radius: true,
size: 46,
iconSize: 20
};
\ No newline at end of file
...@@ -1481,9 +1481,9 @@ ...@@ -1481,9 +1481,9 @@
"integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==" "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw=="
}, },
"@popperjs/core": { "@popperjs/core": {
"version": "2.9.2", "version": "2.9.3",
"resolved": "http://npmprivate.quantgroups.com/@popperjs%2fcore/-/core-2.9.2.tgz", "resolved": "http://npmprivate.quantgroups.com/@popperjs%2fcore/-/core-2.9.3.tgz",
"integrity": "sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==" "integrity": "sha512-xDu17cEfh7Kid/d95kB6tZsLOmSWKCZKtprnhVepjsSaCij+lM3mItSJDuuHDMbCWTh8Ejmebwb+KONcCJ0eXQ=="
}, },
"@qg/apollo-nodejs": { "@qg/apollo-nodejs": {
"version": "2.1.2", "version": "2.1.2",
...@@ -1491,9 +1491,9 @@ ...@@ -1491,9 +1491,9 @@
"integrity": "sha512-uOCUKu5mvX3PWee+7ZFXQSNIR1V5SN2JVE2yANmW9/wQOgpEct291gXGok8VMw0009HlTWB4JATURPwyOP2DFg==" "integrity": "sha512-uOCUKu5mvX3PWee+7ZFXQSNIR1V5SN2JVE2yANmW9/wQOgpEct291gXGok8VMw0009HlTWB4JATURPwyOP2DFg=="
}, },
"@qg/cherry-ui": { "@qg/cherry-ui": {
"version": "2.21.1", "version": "2.22.3",
"resolved": "http://npmprivate.quantgroups.com/@qg%2fcherry-ui/-/cherry-ui-2.21.1.tgz", "resolved": "http://npmprivate.quantgroups.com/@qg%2fcherry-ui/-/cherry-ui-2.22.3.tgz",
"integrity": "sha512-OQ9njfH6cs6FaNqPb7W+hEe/yftpdLXyjGXo2g4IwY7o/9Z5EH6Bn6B5X6dFGOka7LSyXyWRSfZzX0upIIpDFw==", "integrity": "sha512-8BIV5E1oc3Rr/ofvuCK7qNqcg340CKmI6n5GU0hKtPsxmly7pNcQWsu6k0AHI/cpPHdPkvEbtjpLVWGac+zBWg==",
"requires": { "requires": {
"@popperjs/core": "^2.5.4", "@popperjs/core": "^2.5.4",
"vue-lazyload": "^1.3.3", "vue-lazyload": "^1.3.3",
...@@ -1501,9 +1501,9 @@ ...@@ -1501,9 +1501,9 @@
} }
}, },
"@qg/citrus-ui": { "@qg/citrus-ui": {
"version": "0.2.18", "version": "0.2.20",
"resolved": "http://npmprivate.quantgroups.com/@qg%2fcitrus-ui/-/citrus-ui-0.2.18.tgz", "resolved": "http://npmprivate.quantgroups.com/@qg%2fcitrus-ui/-/citrus-ui-0.2.20.tgz",
"integrity": "sha512-GMcMbG8SBR6ZFOOeP7Zp9nPbs4j2cN1YrtZgE/yFxeoaCVKA4Sm+llRRVD3ZpYp5J4nmMztOvHlu+upy24yF4A==", "integrity": "sha512-eKyAqqsUgk34ztLfnL7XyCbariEtkVv30FltCfxm/zx9QhqzFLmB54VR6/F3lOeGQveQcT/NE9hXHsC9K+QjaQ==",
"requires": { "requires": {
"@better-scroll/core": "^2.1.1", "@better-scroll/core": "^2.1.1",
"@qg/cherry-ui": "^2.21.1", "@qg/cherry-ui": "^2.21.1",
...@@ -18187,9 +18187,9 @@ ...@@ -18187,9 +18187,9 @@
} }
}, },
"parse-headers": { "parse-headers": {
"version": "2.0.3", "version": "2.0.4",
"resolved": "http://npmprivate.quantgroups.com/parse-headers/-/parse-headers-2.0.3.tgz", "resolved": "http://npmprivate.quantgroups.com/parse-headers/-/parse-headers-2.0.4.tgz",
"integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==" "integrity": "sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw=="
}, },
"parse-json": { "parse-json": {
"version": "2.2.0", "version": "2.2.0",
...@@ -22491,9 +22491,9 @@ ...@@ -22491,9 +22491,9 @@
} }
}, },
"url-toolkit": { "url-toolkit": {
"version": "2.2.2", "version": "2.2.3",
"resolved": "http://npmprivate.quantgroups.com/url-toolkit/-/url-toolkit-2.2.2.tgz", "resolved": "http://npmprivate.quantgroups.com/url-toolkit/-/url-toolkit-2.2.3.tgz",
"integrity": "sha512-l25w6Sy+Iy3/IbogunxhWwljPaDnqpiKvrQRoLBm6DfISco7NyRIS7Zf6+Oxhy1T8kHxWdwLND7ZZba6NjXMug==" "integrity": "sha512-Da75SQoxsZ+2wXS56CZBrj2nukQ4nlGUZUP/dqUBG5E1su5GKThgT94Q00x81eVII7AyS1Pn+CtTTZ4Z0pLUtQ=="
}, },
"urllib": { "urllib": {
"version": "2.37.1", "version": "2.37.1",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment