Commit 92c63c3c authored by 郝聪敏's avatar 郝聪敏

feature: 基础组件库迁入;自由容器内组件支持拖拽;组件添加基础样式

parent 86be0fcf
...@@ -70,7 +70,6 @@ export class PageInfo extends Model<PageInfo> { ...@@ -70,7 +70,6 @@ export class PageInfo extends Model<PageInfo> {
get() { get() {
const moment = require('moment'); const moment = require('moment');
const updatedAt = this.getDataValue('updatedAt'); const updatedAt = this.getDataValue('updatedAt');
console.log('updatedAt', moment(updatedAt).format('YYYY-MM-DD HH:mm:ss'));
return moment(updatedAt).format('YYYY-MM-DD HH:mm:ss'); return moment(updatedAt).format('YYYY-MM-DD HH:mm:ss');
}, },
}) })
......
export const basicComponents = [ const mdData = require('@qg/cherry-ui/md/index.json');
{ // mdData.forEach(com => com.value = com.config.reduce((pre, cur) => {
eleName: 'freedom-container', // pre[cur.key] = cur.val;
title: '自由容器', // return pre;
h: 300, // }, {}));
config: [ // console.log('basicComponents', mdData);
{ export const basicComponents = mdData;
key: 'backgroundImage', // export const basicComponents = [
name: '背景图片', // {
type: 'Upload' // eleName: 'freedom-container',
}, // title: '自由容器',
], // h: 300,
value: { // config: [
backgroundImage: 'http://activitystatic.q-gp.com/landing-bg.png'; // {
}, // key: 'backgroundImage',
commonStyle: {} // name: '背景图片',
}, // type: 'Upload'
{ // },
eleName: 'cr-button', // ],
title: '按钮', // value: {
h: 42, // backgroundImage: 'http://activitystatic.q-gp.com/landing-bg.png';
config: [ // },
{ // commonStyle: {}
key: 'color', // },
name: '按钮颜色', // {
type: 'ColorPicker' // h: 44,
}, // eleName: 'cr-button',
{ // title: 'Button 按钮',
key: 'text', // config: [
name: '按钮文案', // {
type: 'Input' // key: 'type',
} // name: '类型',
], // desc: '类型,可选值为',
value: { // options: [
color: '#07c160', // 'default',
text: '按钮1' // 'primary',
}, // 'info',
commonStyle: {} // 'danger',
}, // 'waring',
{ // 'success'
eleName: 'cr-field', // ],
title: '输入框', // type: 'select'
h: 48, // },
config: [ // {
{ // key: 'size',
key: 'placeholder', // name: '尺寸',
name: '提示信息', // desc: '尺寸,可选值为',
type: 'Input' // options: [
}, // 'normal',
{ // 'large',
key: 'label', // 'small',
name: 'label', // 'mini'
type: 'Input' // ],
} // type: 'select'
], // },
value: { // {
placeholder: '请输入', // key: 'color',
label: 'label' // name: '颜色',
}, // desc: '按钮颜色,支持传入',
commonStyle: {} // type: 'ColorSelector'
}, // },
{ // {
eleName: 'cr-image', // key: 'icon',
title: '图片', // name: '图标',
h: 140, // desc: '左侧',
config: [ // type: 'text'
{ // },
key: 'width', // {
name: '宽度', // key: 'block',
type: 'Input' // name: '块级元素',
}, // desc: '是否为块级元素',
{ // type: 'checkbox'
key: 'height', // },
name: '高度', // {
type: 'Input' // key: 'shape',
}, // name: '形状',
{ // desc: '按钮形状,可选值为',
key: 'src', // options: [
name: '图片', // 'square',
type: 'Upload' // 'circle'
}, // ],
], // type: 'select'
value: { // },
width: '5.067rem', // {
height: '3.733rem', // key: 'disabled',
src: 'https://appsync.lkbang.net/Fs0qmUsMry39AjHDf_W-qgn8XEy6', // name: '禁用',
fit: 'contain', // desc: '是否禁用按钮',
}, // type: 'checkbox'
commonStyle: {} // },
} // {
]; // key: 'plain',
// name: '朴素按钮',
// desc: '朴素按钮',
// type: 'checkbox'
// },
// {
// key: 'hairline',
// name: '细边框',
// desc: '细边框',
// type: 'checkbox'
// },
// {
// key: 'loading',
// name: '加载中',
// desc: '是否显示为加载状态',
// type: 'checkbox'
// },
// {
// key: 'loadingText',
// name: '加载文字',
// desc: '加载状态提示文字',
// type: 'text'
// },
// {
// key: 'loadingType',
// name: '加载图标类型',
// desc: '',
// options: [
// 'circular',
// 'spinner'
// ],
// type: 'select'
// },
// {
// key: 'loadingSize',
// name: '加载图标大小',
// desc: '加载图标大小',
// type: 'text'
// }
// ],
// value: {
// type: 'default',
// size: 'normal',
// color: '',
// icon: '',
// block: false,
// shape: 'square',
// disabled: false,
// plain: false,
// hairline: false,
// loading: false,
// loadingText: '',
// loadingType: 'circular',
// loadingSize: '20px'
// },
// commonStyle: {}
// },
// {
// eleName: 'cr-image',
// title: '图片',
// h: 140,
// config: [
// {
// key: 'width',
// name: '宽度',
// type: 'text'
// },
// {
// key: 'height',
// name: '高度',
// type: 'text'
// },
// {
// key: 'src',
// name: '图片',
// type: 'Upload'
// },
// ],
// value: {
// width: '5.067rem',
// height: '3.733rem',
// src: 'https://appsync.lkbang.net/Fs0qmUsMry39AjHDf_W-qgn8XEy6',
// fit: 'contain',
// },
// commonStyle: {}
// },
// {
// eleName: 'cr-nav-bar',
// title: 'NavBar 导航栏',
// h: 48,
// config: [
// {
// key: 'title',
// name: '标题',
// desc: '标题',
// propType: 'string',
// options: [],
// type: 'text'
// },
// {
// key: 'leftText',
// name: '左侧文案',
// desc: '左侧文案',
// propType: 'string',
// options: [],
// type: 'text'
// },
// {
// key: 'rightText',
// name: '右侧文案',
// desc: '右侧文案',
// default: '',
// options: [
// 'info',
// 'danger',
// 'primary',
// 'warning'
// ],
// type: 'text'
// },
// {
// key: 'leftArrow',
// name: '左侧箭头',
// desc: '是否显示左侧箭头',
// propType: 'boolean',
// options: [],
// type: 'checkbox'
// },
// {
// key: 'border',
// name: '边框',
// desc: '是否显示下边框',
// propType: 'boolean',
// options: [],
// type: 'checkbox'
// },
// {
// key: 'fixed',
// name: '固定导航栏',
// desc: '是否固定导航栏',
// propType: 'boolean',
// options: [],
// type: 'checkbox'
// },
// {
// key: 'zIndex',
// name: 'z-index',
// desc: '元素z-index',
// propType: [
// 'number',
// 'string'
// ],
// options: [],
// type: 'text'
// }
// ],
// value: {
// title: '',
// leftText: '返回',
// rightText: '',
// leftArrow: true,
// border: true,
// fixed: true,
// zIndex: '9999'
// },
// commonStyle: {}
// }
// ];
export const businessComponents = [ export const businessComponents = [
{ {
...@@ -99,7 +266,7 @@ export const businessComponents = [ ...@@ -99,7 +266,7 @@ export const businessComponents = [
{ {
key: 'btnTxt', key: 'btnTxt',
name: '按钮文案', name: '按钮文案',
type: 'Input' type: 'text'
}, },
{ {
key: 'btnColor', key: 'btnColor',
...@@ -113,13 +280,13 @@ export const businessComponents = [ ...@@ -113,13 +280,13 @@ export const businessComponents = [
}, },
{ {
key: 'vcBgColor', key: 'vcBgColor',
name: '验证码背景色', name: '验证码背景色(可点击态)',
type: 'ColorSelector' type: 'ColorSelector'
}, },
{ {
key: 'registerFrom', key: 'registerFrom',
name: '渠道号', name: '渠道号',
type: 'Input' type: 'text'
}, },
], ],
value: { value: {
...@@ -139,7 +306,7 @@ export const businessComponents = [ ...@@ -139,7 +306,7 @@ export const businessComponents = [
{ {
key: 'href', key: 'href',
name: '跳转链接', name: '跳转链接',
type: 'Input' type: 'text'
}, },
{ {
key: 'leftImg', key: 'leftImg',
...@@ -148,7 +315,7 @@ export const businessComponents = [ ...@@ -148,7 +315,7 @@ export const businessComponents = [
} }
], ],
value: { value: {
href: 'https://s.xyqb.com/m', href: 'https://s.xyqb.com/4',
leftImg: 'http://activitystatic.q-gp.com/xyqb%402x.png' leftImg: 'http://activitystatic.q-gp.com/xyqb%402x.png'
}, },
commonStyle: {} commonStyle: {}
......
...@@ -21,7 +21,7 @@ export default class Activity extends Vue { ...@@ -21,7 +21,7 @@ export default class Activity extends Vue {
return this.pageData && this.pageData.elements.map(v => v.point) || []; return this.pageData && this.pageData.elements.map(v => v.point) || [];
} }
@Watch('pageName') @Watch('pageName', { immediate: true })
onPageNameChange(newVal) { onPageNameChange(newVal) {
if (newVal) { if (newVal) {
document.title = newVal; document.title = newVal;
......
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'; import { Component, Vue, Prop, Watch } from 'vue-property-decorator';
import components from '@qg/cherry-ui/src/index.js'; import components from '@qg/cherry-ui/src/index.js';
import FreedomContainer from '../../component/FreedomContainer/index.vue'; import FreedomContainer from '../../component/FreedomContainer/index.vue';
import { kebabCase } from 'lodash'; import { kebabCase, chunk, flatten } from 'lodash';
import { chunk, flatten } from 'lodash'; import { State } from 'vuex-class';
@Component({ name: 'DynamicComponent' }) @Component({ name: 'DynamicComponent' })
export default class DynamicComponent extends Vue { export default class DynamicComponent extends Vue {
@State(state => state.editor.gridLayout.colNum) colNum;
@Prop({ default: () => ([]), type: Array }) data; @Prop({ default: () => ([]), type: Array }) data;
eleConfig: array = []; eleConfig: array = [];
...@@ -18,7 +19,7 @@ export default class DynamicComponent extends Vue { ...@@ -18,7 +19,7 @@ export default class DynamicComponent extends Vue {
dragstart(event, eleName) { dragstart(event, eleName) {
this.$emit('dragstart'); this.$emit('dragstart');
const eleConfig = flatten(this.eleConfig).find(config => config.eleName === eleName); const eleConfig = flatten(this.eleConfig).find(config => config.eleName === eleName);
const props = this.getProps(eleName); // const props = this.getProps(eleName);
if (eleName.includes('template')) { if (eleName.includes('template')) {
event.dataTransfer.setData('text', JSON.stringify({ event.dataTransfer.setData('text', JSON.stringify({
template: eleConfig.page template: eleConfig.page
...@@ -26,18 +27,20 @@ export default class DynamicComponent extends Vue { ...@@ -26,18 +27,20 @@ export default class DynamicComponent extends Vue {
} else if (eleName === 'freedom-container') { } else if (eleName === 'freedom-container') {
event.dataTransfer.setData('text', JSON.stringify({ event.dataTransfer.setData('text', JSON.stringify({
name: eleName, name: eleName,
point: {x: 0, y: 2, w: 12, h: eleConfig.h || 1, i: '0'}, title: eleConfig.title,
point: {x: 0, y: 2, w: this.colNum, h: eleConfig.h || 1, i: '0'},
child: [], child: [],
schame: eleConfig.config, schame: eleConfig.config,
props: {...props, ...eleConfig.value}, props: {...eleConfig.value},
commonStyle: eleConfig.commonStyle commonStyle: eleConfig.commonStyle
})); }));
} else { } else {
event.dataTransfer.setData('text', JSON.stringify({ event.dataTransfer.setData('text', JSON.stringify({
name: eleName, name: eleName,
point: {x: 0, y: 0, w: 12, h: eleConfig.h || 1, i: '0'}, title: eleConfig.title,
point: {x: 0, y: 0, w: this.colNum, h: eleConfig.h || 1, i: '0'},
schame: eleConfig.config, schame: eleConfig.config,
props: {...props, ...eleConfig.value}, props: {...eleConfig.value},
commonStyle: eleConfig.commonStyle commonStyle: eleConfig.commonStyle
})); }));
} }
......
<template>
<div class="select">
<Select v-model="selected">
<Option v-for="item in options" :value="item" :key="item">{{ item }}</Option>
</Select>
</div>
</template>
<script>
export default {
props: {
value: String,
options: Array,
},
data() {
return {
selected: this.value,
}
},
watch: {
selected(val) {
this.$emit('input', val);
}
}
}
</script>
<style lang="less">
.color-selector {
display: flex;
align-items: center;
justify-content: space-between;
&-input {
flex-basis: 150px;
}
}
</style>
\ No newline at end of file
<template>
<Input v-model="text" :number="true"></Input>
</template>
<script>
export default {
props: {
value: Number,
},
data() {
return {
text: this.value,
}
},
watch: {
text(val) {
this.$emit('input', val);
}
}
}
</script>
\ No newline at end of file
<template>
<Input v-model="text" type="textarea"></Input>
</template>
<script>
export default {
props: {
value: Object | Array,
},
data() {
return {
text: JSON.stringify(this.value),
}
},
watch: {
text(val) {
try {
const jsonData = JSON.parse(val);
this.$emit('input', jsonData);
} catch(e) {
console.log(e);
}
}
}
}
</script>
\ No newline at end of file
...@@ -4,18 +4,39 @@ import { reduce, ceil, subtract, divide } from 'lodash'; ...@@ -4,18 +4,39 @@ import { reduce, ceil, subtract, divide } from 'lodash';
import { ContextMenu } from '@editor/mixins/contextMenu.mixin'; import { ContextMenu } from '@editor/mixins/contextMenu.mixin';
import Upload from './component/Upload/index.vue'; import Upload from './component/Upload/index.vue';
import ColorSelector from './component/ColorSelector/index.vue'; import ColorSelector from './component/ColorSelector/index.vue';
import { resizeDiv } from '@/service/utils.service'; import BaseSelect from './component/BaseSelect/index.vue';
import Textarea from './component/Textarea/index.vue';
import Number from './component/Number/index.vue';
import { resizeDiv, getStyle } from '@/service/utils.service';
@Component({ components: { Upload, ColorSelector }, name: 'DynamicForm' }) @Component({ components: { Upload, ColorSelector, BaseSelect, Textarea, Number }, name: 'DynamicForm' })
export default class DynamicForm extends Mixins(ContextMenu) { export default class DynamicForm extends Mixins(ContextMenu) {
@State(state => state.editor.curEleIndex) curEleIndex; @State(state => state.editor.curEleIndex) curEleIndex;
@State(state => state.editor.curChildIndex) curChildIndex; @State(state => state.editor.curChildIndex) curChildIndex;
@Getter('pageData') pageData; @Getter('pageData') pageData;
@Prop({type: Object, default: () => ({ schame: [], props: {} })}) curElement;
form: object = {}; form: object = {};
get curElement() {
let element = {};
if (this.curEleIndex !== null) {
if (this.curChildIndex !== null && this.pageData.elements[this.curEleIndex]) {
element = this.pageData.elements[this.curEleIndex].child[this.curChildIndex];
} else {
element = this.pageData.elements[this.curEleIndex];
}
}
return element;
}
get point() {
return this.curEleIndex || this.curEleIndex === 0 ? this.pageData.elements[this.curEleIndex]?.point : { h: 0, w: 0 };
}
get commonStyle() {
return (this.curEleIndex || this.curEleIndex === 0) && (this.curChildIndex || this.curChildIndex === 0) ? this.pageData.elements[this.curEleIndex].child[this.curChildIndex].commonStyle : { h: 0, w: 0 };
}
@Watch('curElement', { immediate: true, deep: true }) @Watch('curElement', { immediate: true, deep: true })
onElementChange(newVal) { onElementChange(newVal) {
newVal?.schame?.forEach(schame => { newVal?.schame?.forEach(schame => {
...@@ -47,16 +68,16 @@ export default class DynamicForm extends Mixins(ContextMenu) { ...@@ -47,16 +68,16 @@ export default class DynamicForm extends Mixins(ContextMenu) {
} }
} }
getStyle(oElement, sName) { resizedChildEvent(type) {
const result = oElement.currentStyle ? oElement.currentStyle[sName] : getComputedStyle(oElement, null)[sName]; this.$emit('resizedChildEvent', type);
return result.includes('px') ? result.slice(0, -2) : result; // const containerEle = this.$refs.freedomContainer[this.curEleIndex];
} }
changeAlignType(type) { changeAlignType(type) {
const freedomBody = document.querySelector('.freedom-body'); const freedomBody = document.querySelector('.freedom-body');
const curElement = (freedomBody as Element).children[this.curChildIndex]; const curElement = (freedomBody as Element).children[this.curChildIndex];
const [ containerW, containerH ] = [this.getStyle(freedomBody, 'width'), this.getStyle(freedomBody, 'height')]; const [ containerW, containerH ] = [getStyle(freedomBody, 'width'), getStyle(freedomBody, 'height')];
const [ eleW, eleH ] = [this.getStyle(curElement, 'width'), this.getStyle(curElement, 'height')]; const [ eleW, eleH ] = [getStyle(curElement, 'width'), getStyle(curElement, 'height')];
const elements = this.pageData.elements[this.curEleIndex].child[this.curChildIndex]; const elements = this.pageData.elements[this.curEleIndex].child[this.curChildIndex];
let { left, top } = elements.commonStyle; let { left, top } = elements.commonStyle;
switch (type) { switch (type) {
...@@ -76,4 +97,29 @@ export default class DynamicForm extends Mixins(ContextMenu) { ...@@ -76,4 +97,29 @@ export default class DynamicForm extends Mixins(ContextMenu) {
} }
this.updatePageInfo({ containerIndex: this.curEleIndex, childIndex: this.curChildIndex, data: { ...elements, commonStyle: { ...elements.commonStyle, left, top } } }); this.updatePageInfo({ containerIndex: this.curEleIndex, childIndex: this.curChildIndex, data: { ...elements, commonStyle: { ...elements.commonStyle, left, top } } });
} }
getComponent(type) {
let result = 'Input';
switch (type) {
case 'text':
result = 'Input';
break;
case 'select':
result = 'BaseSelect';
break;
case 'checkbox' :
result = 'Checkbox';
break;
case 'ColorSelector' :
result = 'ColorSelector';
break;
case 'textarea' :
result = 'Textarea';
break;
case 'number' :
result = 'Number';
break;
}
return result;
}
} }
\ No newline at end of file
<template> <template>
<div class="dynamic-form"> <div class="dynamic-form">
<h2>{{curElement.title}}</h2>
<template> <template>
<h4>组件属性</h4> <h4>组件属性</h4>
<Form ref="formCustom" :label-width="70" :model="form"> <Form class="dynamic-form-component" :label-width="80" :model="form">
<FormItem :label="item.name" :key="index" v-for="(item, index) in curElement.schame"> <FormItem :label="item.name" :key="index" v-for="(item, index) in curElement.schame">
<component :is="item.type" v-model="form[item.key]" /> <component :is="getComponent(item.type)" :options="item.options" v-model="form[item.key]" />
</FormItem> </FormItem>
</Form> </Form>
</template> </template>
<template v-if="eleName === 'freedom-container' || curChildIndex || curChildIndex === 0"> <template>
<h4>基础样式</h4> <h4>基础样式</h4>
<Form ref="formCustom" :label-width="70"> <Form class="dynamic-form-basic" :label-width="80">
<FormItem label="尺寸" v-if="eleName === 'freedom-container'"> <template v-if="curChildIndex || curChildIndex === 0">
<Tooltip placement="top" content="全屏"> <FormItem label="定位">
<Button type="ghost" icon="arrow-resize" @click="resizedEvent(667, 12)"></Button>
</Tooltip>
<Tooltip placement="top" content="根据背景图片自动调整宽高">
<Button type="ghost" icon="image" @click="resizedEvent(667, 12, true)" ></Button>
</Tooltip>
<Tooltip placement="top" content="宽100%">
<Button type="ghost" icon="arrow-swap" @click="resizedEvent(null, 12)"></Button>
</Tooltip>
<Tooltip placement="top" content="高100%">
<Button type="ghost" icon="arrow-swap" @click="resizedEvent(667, null)" ></Button>
</Tooltip>
</FormItem>
<FormItem label="定位" v-if="curChildIndex || curChildIndex === 0">
<Tooltip placement="top" content="上对齐"> <Tooltip placement="top" content="上对齐">
<Button type="ghost" icon="arrow-up-c" @click="changeAlignType('top')"></Button> <Button type="ghost" icon="arrow-up-c" @click="changeAlignType('top')"></Button>
<!-- <Button @click="changeAlignType('top')">上对齐</Button> -->
</Tooltip> </Tooltip>
<Tooltip placement="top" content="右对齐"> <Tooltip placement="top" content="右对齐">
<Button type="ghost" icon="arrow-right-c" @click="changeAlignType('right')"></Button> <Button type="ghost" icon="arrow-right-c" @click="changeAlignType('right')"></Button>
<!-- <Button @click="changeAlignType('right')">右对齐</Button> -->
</Tooltip> </Tooltip>
<Tooltip placement="top" content="下对齐"> <Tooltip placement="top" content="下对齐">
<Button type="ghost" icon="arrow-down-c" @click="changeAlignType('bottom')"></Button> <Button type="ghost" icon="arrow-down-c" @click="changeAlignType('bottom')"></Button>
<!-- <Button @click="changeAlignType('bottom')">下对齐</Button> -->
</Tooltip> </Tooltip>
<Tooltip placement="top" content="左对齐"> <Tooltip placement="top" content="左对齐">
<Button type="ghost" icon="arrow-left-c" @click="changeAlignType('left')"></Button> <Button type="ghost" icon="arrow-left-c" @click="changeAlignType('left')"></Button>
<!-- <Button @click="changeAlignType('left')">左对齐</Button> -->
</Tooltip> </Tooltip>
<Tooltip placement="top" content="垂直居中"> <Tooltip placement="top" content="垂直居中">
<Button type="ghost" icon="android-film" @click="changeAlignType('vertical')"></Button> <Button type="ghost" icon="android-film" @click="changeAlignType('vertical')"></Button>
<!-- <Button @click="changeAlignType('vertical')">垂直居中</Button> -->
</Tooltip> </Tooltip>
<Tooltip placement="top" content="水平居中"> <Tooltip placement="top" content="水平居中">
<Button type="ghost" icon="android-film" @click="changeAlignType('horizontal')"></Button> <Button type="ghost" icon="android-film" @click="changeAlignType('horizontal')"></Button>
<!-- <Button @click="changeAlignType('horizontal')">水平居中</Button> -->
</Tooltip> </Tooltip>
</FormItem> </FormItem>
<FormItem label="位置">
<InputNumber class="Df-basic-inputnumber" v-model="commonStyle.left"></InputNumber>
<InputNumber v-model="commonStyle.top"></InputNumber>
</FormItem>
<FormItem label="尺寸">
<Tooltip placement="top" content="全屏">
<Button type="ghost" icon="arrow-resize" @click="resizedChildEvent('full')"></Button>
</Tooltip>
<Tooltip placement="top" content="宽100%">
<Button type="ghost" icon="arrow-swap" @click="resizedChildEvent('width')"></Button>
</Tooltip>
<Tooltip placement="top" content="高100%">
<Button type="ghost" icon="arrow-swap" @click="resizedChildEvent('height')" ></Button>
</Tooltip>
</FormItem>
<FormItem label="宽高">
<InputNumber class="Df-basic-inputnumber" :max="375" :min="0" v-model="commonStyle.width"></InputNumber>
<InputNumber :max="667" :min="0" v-model="commonStyle.height"></InputNumber>
</FormItem>
</template>
<template v-if="(curEleIndex || curEleIndex === 0) && !curChildIndex && curChildIndex !== 0">
<FormItem label="尺寸">
<Tooltip placement="top" content="全屏">
<Button type="ghost" icon="arrow-resize" @click="resizedEvent(667, 375)"></Button>
</Tooltip>
<Tooltip placement="top" content="根据背景图片自动调整宽高">
<Button type="ghost" icon="image" @click="resizedEvent(667, 375, true)" ></Button>
</Tooltip>
<Tooltip placement="top" content="宽100%">
<Button type="ghost" icon="arrow-swap" @click="resizedEvent(null, 375)"></Button>
</Tooltip>
<Tooltip placement="top" content="高100%">
<Button type="ghost" icon="arrow-swap" @click="resizedEvent(667, null)" ></Button>
</Tooltip>
</FormItem>
<FormItem label="宽高">
<InputNumber class="Df-basic-inputnumber" :max="375" :min="0" v-model="point.w"></InputNumber>
<InputNumber :max="667" :min="0" v-model="point.h"></InputNumber>
</FormItem>
</template>
</Form> </Form>
</template> </template>
</div> </div>
</template> </template>
<script lang="ts" src="./index.ts"></script> <script lang="ts" src="./index.ts"></script>
<style lang="less"> <style lang="less" scoped>
.dynamic-form { .dynamic-form {
padding: 0 15px; padding: 0 15px 16px;
h2 {
text-align: center;
}
h4 { h4 {
padding: 10px 0; padding: 10px 0;
margin-bottom: 10px; margin-bottom: 10px;
border-bottom: 1px solid #ebeef5; border-bottom: 1px solid #ebeef5;
} }
&-component {
padding: 0 20px;
}
&-basic {
padding: 0 20px;
.Df-basic-inputnumber {
margin-right: 10px;
}
}
/deep/ .ivu-form-item-label { /deep/ .ivu-form-item-label {
font-size: 14px; font-size: 14px;
} }
/deep/ .ivu-input-number {
width: 60px;
}
/deep/ .ivu-form-item-content { /deep/ .ivu-form-item-content {
.ivu-tooltip { .ivu-tooltip {
margin-right: 6px; margin-right: 6px;
......
import { Component, Prop, Mixins } from 'vue-property-decorator'; import { Component, Prop, Mixins, Watch } from 'vue-property-decorator';
import LoginForm from '@/lib/Form/index.vue'; import LoginForm from '@/lib/Form/index.vue';
import DownloadGuide from '@/lib/DownloadGuide/index.vue';
import { ContextMenu } from '@editor/mixins/contextMenu.mixin'; import { ContextMenu } from '@editor/mixins/contextMenu.mixin';
import { cloneDeep } from 'lodash'; import { cloneDeep, pick, omit, throttle } from 'lodash';
import { Action, Mutation, State } from 'vuex-class'; import { Action, Mutation, State } from 'vuex-class';
import { convertPointStyle, getStyle } from '@/service/utils.service';
@Component({ components: { LoginForm }, name: 'FreedomContainer' }) @Component({ components: { LoginForm, DownloadGuide }, name: 'FreedomContainer' })
export default class FreedomContainer extends Mixins(ContextMenu) { export default class FreedomContainer extends Mixins(ContextMenu) {
@Action('setDragable') setDragable; @Action('setDragable') setDragable;
@State(state => state.editor.curChildIndex) curChildIndex; @State(state => state.editor.curChildIndex) curChildIndex;
...@@ -20,7 +22,7 @@ export default class FreedomContainer extends Mixins(ContextMenu) { ...@@ -20,7 +22,7 @@ export default class FreedomContainer extends Mixins(ContextMenu) {
const { top: startTop, left: startLeft } = childItem.child[childIndex].commonStyle; const { top: startTop, left: startLeft } = childItem.child[childIndex].commonStyle;
const { clientY, clientX } = event; const { clientY, clientX } = event;
const move = moveEvent => { const move = throttle(moveEvent => {
moveEvent.stopPropagation(); moveEvent.stopPropagation();
moveEvent.preventDefault(); moveEvent.preventDefault();
...@@ -28,7 +30,7 @@ export default class FreedomContainer extends Mixins(ContextMenu) { ...@@ -28,7 +30,7 @@ export default class FreedomContainer extends Mixins(ContextMenu) {
const left = moveEvent.clientX - clientX + startLeft; const left = moveEvent.clientX - clientX + startLeft;
this.updatePageInfo({ containerIndex: this.containerIndex, childIndex, data: { ...childItem.child[childIndex], commonStyle: {...childItem.child[childIndex].commonStyle, top, left} } }); this.updatePageInfo({ containerIndex: this.containerIndex, childIndex, data: { ...childItem.child[childIndex], commonStyle: {...childItem.child[childIndex].commonStyle, top, left} } });
}; }, 50);
const up = () => { const up = () => {
this.setDragable(true); this.setDragable(true);
document.removeEventListener('mousemove', move, true); document.removeEventListener('mousemove', move, true);
...@@ -38,23 +40,123 @@ export default class FreedomContainer extends Mixins(ContextMenu) { ...@@ -38,23 +40,123 @@ export default class FreedomContainer extends Mixins(ContextMenu) {
document.addEventListener('mouseup', up, true); document.addEventListener('mouseup', up, true);
} }
transformStyle(styleObj) { transformStyle(styleObj, element) {
const style = {}; let style = {};
for (const key of Object.keys(styleObj)) { for (const key of Object.keys(styleObj)) {
if ( typeof styleObj[key] === 'number') { if ( typeof styleObj[key] === 'number') {
style[key] = `${(styleObj[key] / 37.5).toFixed(2)}rem`; style[key] = `${(styleObj[key] / 37.5).toFixed(2)}rem`;
} else { } else {
style[key] = styleObj[key].includes('px') ? `${(+(styleObj[key].slice(0, -2)) / 37.5).toFixed(2)}rem` : styleObj[key]; style[key] = styleObj[key]?.includes('px') ? `${(+(styleObj[key].slice(0, -2)) / 37.5).toFixed(2)}rem` : styleObj[key];
} }
if (key === 'backgroundImage') { if (key === 'backgroundImage') {
style.backgroundImage = `url(${style.backgroundImage})`; style.backgroundImage = `url(${style.backgroundImage})`;
} }
} }
const transformFun = element === 'container' ? pick : omit;
style = transformFun(style, ['position', 'top', 'left']);
return style; return style;
} }
handleElementClick(curEleIndex, curChildIndex) { handleElementClick(curEleIndex, curChildIndex) {
console.log('handleElementClick', curEleIndex, curChildIndex, this.childItem);
this.$emit('handleElementClick', curEleIndex, curChildIndex); this.$emit('handleElementClick', curEleIndex, curChildIndex);
} }
@Watch('curChildIndex')
onIndexChange(newVal) {
this.childItem.child.forEach(item => delete item.dots);
if (newVal || newVal === 0) {
this.setPointStyle();
}
}
// 获取point计算后样式
setPointStyle() {
this.$nextTick(() => {
const points = ['lt', 'rt', 'lb', 'rb', 'l', 'r', 't', 'b'];
const [height, width] = this.getHW(this.curChildIndex);
const dots = points.reduce((pre, cur) => {
pre[cur] = convertPointStyle(cur, {height, width});
return pre;
}, {});
const childEle = this.childItem.child[this.curChildIndex];
// this.updatePageInfo({ containerIndex: this.containerIndex, childIndex: this.curChildIndex, data: { ...childEle, commonStyle: { ...childEle.commonStyle, height: +height, width: +width } } });
this.updateCommonStyle({ containerIndex: this.containerIndex, childIndex: this.curChildIndex, data: { ...childEle.commonStyle, height: +height, width: +width }});
this.$set(this.childItem.child[this.curChildIndex], 'dots', dots);
});
}
getHW(index) {
const childComponent = this.$refs.childComponent[index];
return [getStyle(childComponent.$el, 'height'), getStyle(childComponent.$el, 'width')];
}
setChildSize(type) {
const childEle = this.childItem.child[this.curChildIndex];
const [height, width] = [getStyle(this.$el, 'height'), getStyle(this.$el, 'width')];
console.log('setChildSize', this, height, width);
switch (type) {
case 'width':
this.updateCommonStyle({ containerIndex: this.containerIndex, childIndex: this.curChildIndex, data: { ...childEle.commonStyle, width: +width }});
break;
case 'height':
this.updateCommonStyle({ containerIndex: this.containerIndex, childIndex: this.curChildIndex, data: { ...childEle.commonStyle, height: +height }});
break;
case 'full':
this.updateCommonStyle({ containerIndex: this.containerIndex, childIndex: this.curChildIndex, data: { ...childEle.commonStyle, height: +height, width: +width }});
break;
}
}
handleMouseDownOnPoint(point, event) {
const downEvent = event;
// 抛出事件让父组件设置当前元素选中状态
downEvent.stopPropagation();
downEvent.preventDefault();
const [height, width] = this.getHW(this.curChildIndex);
const pos = {...this.childItem.child[this.curChildIndex].commonStyle, height, width };
const top = pos.top;
const left = pos.left;
const startX = downEvent.clientX;
const startY = downEvent.clientY;
// 当前模块的最小宽度值
let minWidth = 0;
if (pos.minWidth) {
minWidth = pos.minWidth;
}
// 当前模块的最小高度值
let minHeight = 0;
if (pos.minHeight) {
minHeight = pos.minHeight;
}
const move = throttle(moveEvent => {
this.setDragable(false);
moveEvent.stopPropagation();
moveEvent.preventDefault();
const currX = moveEvent.clientX;
const currY = moveEvent.clientY;
const disY = currY - startY;
const disX = currX - startX;
const hasT = /t/.test(point);
const hasB = /b/.test(point);
const hasL = /l/.test(point);
const hasR = /r/.test(point);
const newHeight = +height + (hasT ? -disY : hasB ? disY : 0);
const newWidth = +width + (hasL ? -disX : hasR ? disX : 0);
pos.width = newWidth > 0 ? newWidth : 0;
pos.height = newHeight > 0 ? newHeight : 0;
pos.left = +left + (hasL ? disX : 0);
pos.top = +top + (hasT ? disY : 0);
this.updateCommonStyle({ containerIndex: this.containerIndex, childIndex: this.curChildIndex, data: pos });
this.setPointStyle();
}, 100);
const up = () => {
this.setDragable(true);
this.$emit('resize');
document.removeEventListener('mousemove', move);
document.removeEventListener('mouseup', up);
};
document.addEventListener('mousemove', move);
document.addEventListener('mouseup', up);
}
} }
\ No newline at end of file
<template> <template>
<div class="freedom" @click.stop="handleElementClick(containerIndex)"> <div class="freedom" :ref="`freedomContainer${containerIndex}`" @click.stop="handleElementClick(containerIndex)">
<div class="freedom-body" :style="{background: `url(${backgroundImage}) no-repeat 0 0 / cover`}"> <div class="freedom-body" :style="{background: `url(${backgroundImage}) no-repeat 0 0 / cover`}">
<component :class="['freedom-body-item', { 'Fb-item_selected': curChildIndex === index }]" v-for="(item, index) in childItem.child" :style="transformStyle(item.commonStyle)" :is="item.name" :key="index" @click.stop.native="handleElementClick(containerIndex, index)" @mousedown.native.stop="mousedown(index, $event)" v-bind="item.props" @contextmenu.native.prevent.stop="show($event, containerIndex, index)"></component> <div v-for="(item, index) in childItem.child" :style="transformStyle(item.commonStyle, 'container')" :class="['freedom-body-item', { 'Fb-item_selected': curChildIndex === index }]" :key="index" @click.stop="handleElementClick(containerIndex, index)" @mousedown.stop="mousedown(index, $event)" @contextmenu.prevent.stop="show($event, containerIndex, index)">
<component ref="childComponent" :style="transformStyle(item.commonStyle, 'component')" :is="item.name" v-bind="item.props"></component>
<div class="freedom-body-dot"
v-for="(style, key) in item.dots"
:key="key"
:style="style"
@mousedown.stop.prevent="handleMouseDownOnPoint(key, $event)"/>
</div>
</div>
</div> </div>
</div> </div>
</template> </template>
...@@ -22,13 +30,23 @@ ...@@ -22,13 +30,23 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
.freedom-body-item { &-item {
font-size: 0;
&:hover { &:hover {
border: 2px dashed #0c0c0c !important; border: 1px dashed #0c0c0c !important;
}
} }
&-dot {
width: 8px;
height: 8px;
background-color: #fff;
border: 1px solid #59c7f9;
border-radius: 8px;
position: absolute;
z-index: 1001;
} }
.Fb-item_selected { .Fb-item_selected {
border: 2px dashed #0c0c0c !important; border: 1px dashed #0c0c0c !important;
} }
} }
.activity { .activity {
......
...@@ -5,6 +5,7 @@ import { Mutation } from 'vuex-class'; ...@@ -5,6 +5,7 @@ import { Mutation } from 'vuex-class';
export class ContextMenu extends Vue { export class ContextMenu extends Vue {
@Mutation('COPY_OR_DELETE_PAGE_INFO') updatePageData; @Mutation('COPY_OR_DELETE_PAGE_INFO') updatePageData;
@Mutation('UPDATE_PAGE_INFO') updatePageInfo; @Mutation('UPDATE_PAGE_INFO') updatePageInfo;
@Mutation('UPDATE_COMMON_STYLE') updateCommonStyle;
show(event, containerIndex, childIndex) { show(event, containerIndex, childIndex) {
console.log('删除', event, containerIndex, childIndex); console.log('删除', event, containerIndex, childIndex);
......
...@@ -31,6 +31,7 @@ export default class DashBoard extends Mixins(ContextMenu) { ...@@ -31,6 +31,7 @@ export default class DashBoard extends Mixins(ContextMenu) {
@Getter('pageData') pageData; @Getter('pageData') pageData;
@State(state => state.editor.gridLayout.draggable) draggable; @State(state => state.editor.gridLayout.draggable) draggable;
@State(state => state.editor.gridLayout.rowHeight) rowHeight; @State(state => state.editor.gridLayout.rowHeight) rowHeight;
@State(state => state.editor.gridLayout.colNum) colNum;
@State(state => state.editor.curEleIndex) curEleIndex; @State(state => state.editor.curEleIndex) curEleIndex;
@State(state => state.editor.curChildIndex) curChildIndex; @State(state => state.editor.curChildIndex) curChildIndex;
@State(state => state.editor.templateList) templateList; @State(state => state.editor.templateList) templateList;
...@@ -59,18 +60,6 @@ export default class DashBoard extends Mixins(ContextMenu) { ...@@ -59,18 +60,6 @@ export default class DashBoard extends Mixins(ContextMenu) {
return this.pageData.elements.map(v => v.point); return this.pageData.elements.map(v => v.point);
} }
get curElement() {
let element = {};
if (this.curEleIndex !== null) {
if (this.curChildIndex !== null && this.pageData.elements[this.curEleIndex]) {
element = this.pageData.elements[this.curEleIndex].child[this.curChildIndex];
} else {
element = this.pageData.elements[this.curEleIndex];
}
}
return element;
}
// 选择组件库 // 选择组件库
selectMaterial(val: string) { selectMaterial(val: string) {
this.activeName = val; this.activeName = val;
...@@ -98,6 +87,7 @@ export default class DashBoard extends Mixins(ContextMenu) { ...@@ -98,6 +87,7 @@ export default class DashBoard extends Mixins(ContextMenu) {
} }
handleElementClick(curEleIndex = null, curChildIndex = null) { handleElementClick(curEleIndex = null, curChildIndex = null) {
console.log('handleElementClick - DashBoard', curEleIndex, curChildIndex);
this.toggle(false); this.toggle(false);
this.setCurEleIndex(curEleIndex); this.setCurEleIndex(curEleIndex);
this.setCurChildIndex(curChildIndex); this.setCurChildIndex(curChildIndex);
...@@ -185,4 +175,13 @@ export default class DashBoard extends Mixins(ContextMenu) { ...@@ -185,4 +175,13 @@ export default class DashBoard extends Mixins(ContextMenu) {
const index = this.pageData.elements.findIndex(ele => ele.point.i === i); const index = this.pageData.elements.findIndex(ele => ele.point.i === i);
this.updatePageInfo({ containerIndex: index, data: { ...this.pageData.elements[index], point: { ...this.pageData.elements[index].point, w, h } } }); this.updatePageInfo({ containerIndex: index, data: { ...this.pageData.elements[index], point: { ...this.pageData.elements[index].point, w, h } } });
} }
/**
* 调整自由容器子元素宽高及边框原点位置
* @param {[type]} type 尺寸类型
*/
resizedChildEvent(type) {
const containerEle = this.$refs.container[this.curEleIndex];
containerEle.setChildSize(type);
containerEle.setPointStyle();
}
} }
\ No newline at end of file
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
@dragleave="dragleave" @drop="drops"> @dragleave="dragleave" @drop="drops">
<grid-layout <grid-layout
:layout.sync="layout" :layout.sync="layout"
:col-num="12" :col-num="colNum"
:row-height="rowHeight" :row-height="rowHeight"
:margin="[0, 0]" :margin="[0, 0]"
:is-draggable="draggable" :is-draggable="draggable"
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
@contextmenu.native.prevent="show($event, index)" @contextmenu.native.prevent="show($event, index)"
@resized="resizedEvent" @resized="resizedEvent"
:class="{'Dcmcp-item_selected': curEleIndex === index && curChildIndex === null}"> :class="{'Dcmcp-item_selected': curEleIndex === index && curChildIndex === null}">
<component class="Dcmcp-item-com" @handleElementClick="handleElementClick" :data-index="index" :containerIndex="index" :childItem="item" :is="item.name" :key="index" v-bind="item.props"></component> <component ref="container" class="Dcmcp-item-com" @handleElementClick="handleElementClick" :data-index="index" :containerIndex="index" :childItem="item" :is="item.name" :key="index" v-bind="item.props"></component>
</grid-item> </grid-item>
</grid-layout> </grid-layout>
</div> </div>
...@@ -79,7 +79,7 @@ ...@@ -79,7 +79,7 @@
<Col span="8" :class="[{'Dcm-sider_none': isCollapsed}, 'Dc-middle-sider']"> <Col span="8" :class="[{'Dcm-sider_none': isCollapsed}, 'Dc-middle-sider']">
<Tabs class="Dc-middle-editing" type="card"> <Tabs class="Dc-middle-editing" type="card">
<TabPane label="属性"> <TabPane label="属性">
<dynamic-form :curElement="curElement" @modProps="modProps"></dynamic-form> <dynamic-form @modProps="modProps" @resizedChildEvent="resizedChildEvent"></dynamic-form>
</TabPane> </TabPane>
<TabPane label="事件">事件</TabPane> <TabPane label="事件">事件</TabPane>
<TabPane label="页面设置">页面设置</TabPane> <TabPane label="页面设置">页面设置</TabPane>
...@@ -129,6 +129,7 @@ ...@@ -129,6 +129,7 @@
flex: 1; flex: 1;
padding: 10px; padding: 10px;
background: #fff; background: #fff;
overflow-y: scroll;
} }
.tabs-position(); .tabs-position();
} }
...@@ -152,9 +153,7 @@ ...@@ -152,9 +153,7 @@
box-shadow: 2px 0px 10px rgba(0, 0, 0, 0.2); box-shadow: 2px 0px 10px rgba(0, 0, 0, 0.2);
/deep/ .vue-grid-layout { /deep/ .vue-grid-layout {
.vue-grid-item { .vue-grid-item {
display: flex; text-align: center;
justify-content: center;
align-items: center;
background: #fff; background: #fff;
overflow: hidden; overflow: hidden;
&:hover { &:hover {
...@@ -163,6 +162,9 @@ ...@@ -163,6 +162,9 @@
&>*:first-child { &>*:first-child {
height: 100%; height: 100%;
} }
.vue-resizable-handle {
z-index: 10000;
}
} }
.Dcmcp-item_selected { .Dcmcp-item_selected {
border: 1px dashed #0c0c0c !important; border: 1px dashed #0c0c0c !important;
...@@ -187,6 +189,11 @@ ...@@ -187,6 +189,11 @@
height: 100%; height: 100%;
min-width: 320px; min-width: 320px;
.tabs-position(); .tabs-position();
/deep/ .ivu-tabs-content {
height: calc(100% - 48px);
overflow-y: scroll;
overflow-x: hidden;
}
} }
} }
.Dcm-sider_none { .Dcm-sider_none {
......
...@@ -13,6 +13,7 @@ import { ...@@ -13,6 +13,7 @@ import {
RESET_PAGE_DATA, RESET_PAGE_DATA,
SET_TEMPLATE_LIST, SET_TEMPLATE_LIST,
SET_PAGE_DATA, SET_PAGE_DATA,
UPDATE_COMMON_STYLE,
} from './type'; } from './type';
import RootState from '../../state'; import RootState from '../../state';
...@@ -99,6 +100,8 @@ export default class EditorModule implements Module<EditorState, RootState> { ...@@ -99,6 +100,8 @@ export default class EditorModule implements Module<EditorState, RootState> {
} else { } else {
page.splice(containerIndex, 1); page.splice(containerIndex, 1);
} }
state.curEleIndex = null;
state.curChildIndex = null;
} else if (type === 'copy') { } else if (type === 'copy') {
let eleCopyed = {} as PageElement; let eleCopyed = {} as PageElement;
if (childIndex || childIndex === 0) { if (childIndex || childIndex === 0) {
...@@ -119,6 +122,14 @@ export default class EditorModule implements Module<EditorState, RootState> { ...@@ -119,6 +122,14 @@ export default class EditorModule implements Module<EditorState, RootState> {
page.splice(containerIndex, 1, data); page.splice(containerIndex, 1, data);
} }
}, },
[UPDATE_COMMON_STYLE](state, {containerIndex, childIndex, data}) {
const page = (state.pageInfo.page as Page).elements;
if (childIndex || childIndex === 0) {
page[containerIndex].child[childIndex].commonStyle = data;
} else {
page[containerIndex].commonStyle = data;
}
},
[ADD_ELEMENTS](state, { containerIndex, data }) { [ADD_ELEMENTS](state, { containerIndex, data }) {
const page = (state.pageInfo.page as Page).elements; const page = (state.pageInfo.page as Page).elements;
if (containerIndex || containerIndex === 0) { if (containerIndex || containerIndex === 0) {
......
...@@ -25,6 +25,7 @@ interface GridLayout { ...@@ -25,6 +25,7 @@ interface GridLayout {
export interface PageElement { export interface PageElement {
name: string; name: string;
title: string;
schame: Schame[]; schame: Schame[];
props: object; props: object;
point: Point; point: Point;
...@@ -62,7 +63,8 @@ export const defaultState = { ...@@ -62,7 +63,8 @@ export const defaultState = {
templateList: [], templateList: [],
gridLayout: { gridLayout: {
draggable: true, draggable: true,
rowHeight: 1 rowHeight: 1,
colNum: 375
}, },
}; };
......
...@@ -10,3 +10,4 @@ export const SET_CUR_CHILD_INDEX = 'SET_CUR_CHILD_INDEX'; ...@@ -10,3 +10,4 @@ export const SET_CUR_CHILD_INDEX = 'SET_CUR_CHILD_INDEX';
export const RESET_PAGE_DATA = 'RESET_PAGE_DATA'; export const RESET_PAGE_DATA = 'RESET_PAGE_DATA';
export const SET_TEMPLATE_LIST = 'SET_TEMPLATE_LIST'; export const SET_TEMPLATE_LIST = 'SET_TEMPLATE_LIST';
export const SET_PAGE_DATA = 'SET_PAGE_DATA'; export const SET_PAGE_DATA = 'SET_PAGE_DATA';
export const UPDATE_COMMON_STYLE = 'UPDATE_COMMON_STYLE';
\ No newline at end of file
...@@ -52,3 +52,44 @@ export function resizeDiv(imgUrl, clientHeight = 0, clientWidth = 0, callback) { ...@@ -52,3 +52,44 @@ export function resizeDiv(imgUrl, clientHeight = 0, clientWidth = 0, callback) {
}; };
img.src = imgUrl; img.src = imgUrl;
} }
const DK = {t: 'n', b: 's', l: 'w', r: 'e'}; // 上下左右 对应的 东南西北
export const convertPointStyle = (point, defaultStyle, directionKey = DK) => {
const pos = defaultStyle;
const height = pos.height;
const width = pos.width;
const hasT = /t/.test(point);
const hasB = /b/.test(point);
const hasL = /l/.test(point);
const hasR = /r/.test(point);
let newLeft = 0;
let newTop = 0;
if (point.length === 2) {
newLeft = hasL ? 0 : width;
newTop = hasT ? 0 : height;
} else {
// !#zh 上下点,宽度固定在中间
if (hasT || hasB) {
newLeft = width / 2 - 4;
newTop = hasT ? 0 : height;
}
// !#zh 左右点,高度固定在中间
if (hasL || hasR) {
newLeft = hasL ? 0 : width;
newTop = height / 2 - 4;
}
}
const style = {
marginLeft: (hasL || hasR) ? '-4px' : 0,
marginTop: (hasT || hasB) ? '-4px' : 0,
left: `${newLeft}px`,
top: `${newTop}px`,
cursor: point.split('').reverse().map(m => directionKey[m]).join('') + '-resize'
};
return style;
};
export const getStyle = function(oElement, sName) {
const result = oElement.currentStyle ? oElement.currentStyle[sName] : getComputedStyle(oElement, null)[sName];
return result.includes('px') ? result.slice(0, -2) : result;
};
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" style="font-size: 37.5px;"> <html lang="en" style="font-size: 37.5px;">
<head> <head>
<title>低代码平台</title> <title>低代码平台1</title>
<meta name="keywords"> <meta name="keywords">
<meta name="description"> <meta name="description">
<meta http-equiv="content-type" content="text/html;charset=utf-8"> <meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui"> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /> <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="/public/asset/css/reset.css"> <link rel="stylesheet" href="/public/asset/css/reset.css">
</head> <style>
<body> html, body {
line-height: 1.15 !important;
}
</style>
</head>
<body>
<div id="app"><!--vue-ssr-outlet--></div> <div id="app"><!--vue-ssr-outlet--></div>
<script src="https://cdn.staticfile.org/plupload/2.1.2/plupload.full.min.js"></script> <script src="https://cdn.staticfile.org/plupload/2.1.2/plupload.full.min.js"></script>
</body> </body>
</html> </html>
\ No newline at end of file
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
"dependencies": { "dependencies": {
"@better-scroll/core": "^2.0.5", "@better-scroll/core": "^2.0.5",
"@hubcarl/json-typescript-mapper": "^2.0.0", "@hubcarl/json-typescript-mapper": "^2.0.0",
"@qg/cherry-ui": "^2.17.66", "@qg/cherry-ui": "^2.18.66",
"axios": "^0.18.1", "axios": "^0.18.1",
"egg": "^2.3.0", "egg": "^2.3.0",
"egg-cors": "^2.1.1", "egg-cors": "^2.1.1",
...@@ -29,15 +29,11 @@ ...@@ -29,15 +29,11 @@
"egg-view-vue-ssr": "^3.0.5", "egg-view-vue-ssr": "^3.0.5",
"egg-webpack": "^4.4.7", "egg-webpack": "^4.4.7",
"egg-webpack-vue": "^2.0.0", "egg-webpack-vue": "^2.0.0",
"element-ui": "^2.0.8",
"extend": "~3.0.0", "extend": "~3.0.0",
"font-awesome": "^4.7.0",
"html2canvas": "^1.0.0-rc.7", "html2canvas": "^1.0.0-rc.7",
"iview": "^2.9.0", "iview": "^2.9.0",
"js-cookie": "^2.2.1", "js-cookie": "^2.2.1",
"lodash": "^4.17.4", "lodash": "^4.17.4",
"lodash-id": "^0.14.0",
"lowdb": "^1.0.0",
"mockjs": "^1.0.1-beta3", "mockjs": "^1.0.1-beta3",
"moment": "^2.17.1", "moment": "^2.17.1",
"mysql2": "^2.2.5", "mysql2": "^2.2.5",
...@@ -48,9 +44,6 @@ ...@@ -48,9 +44,6 @@
"sa-sdk-javascript": "^1.15.27", "sa-sdk-javascript": "^1.15.27",
"sequelize": "^4.38.0", "sequelize": "^4.38.0",
"sequelize-typescript": "^0.6.6", "sequelize-typescript": "^0.6.6",
"shortid": "^2.2.8",
"showdown": "^1.8.6",
"simplemde": "^1.11.2",
"vue": "^2.6.12", "vue": "^2.6.12",
"vue-grid-layout": "^2.3.11", "vue-grid-layout": "^2.3.11",
"vue-property-decorator": "^7.2.0", "vue-property-decorator": "^7.2.0",
......
...@@ -17,7 +17,8 @@ ...@@ -17,7 +17,8 @@
"max-line-length": false, "max-line-length": false,
"only-arrow-functions": false, "only-arrow-functions": false,
"interface-over-type-literal": false, "interface-over-type-literal": false,
"ter-indent": [ true, 2] "ter-indent": [ true, 2],
"no-var-requires": false
}, },
"rulesDirectory": ["app"] "rulesDirectory": ["app"]
} }
\ No newline at end of file
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