feat(仪表盘): 增加文字组件 矩形组件等,统一归类为样式组件 增加仪表盘侧边 '其他' 按钮 用来存放其他类型的组件

This commit is contained in:
wangjiahao 2021-06-01 22:46:08 +08:00
parent e05dd9f681
commit 039f3832a8
12 changed files with 427 additions and 60 deletions

View File

@ -1,24 +1,42 @@
<!-- TODO: 这个页面后续将用 JSX 重构 -->
<template>
<div class="attr-list">
<el-form>
<el-form-item v-for="(key, index) in styleKeys.filter(item => (item != 'rotate' && item != 'borderWidth'))" :key="index" :label="map[key]">
<el-form-item v-for="(key, index) in styleKeys.filter(item => item != 'rotate')" :key="index" :label="map[key]">
<el-color-picker v-if="key == 'borderColor'" v-model="curComponent.style[key]" />
<el-color-picker v-else-if="key == 'color'" v-model="curComponent.style[key]" />
<el-color-picker v-else-if="key == 'backgroundColor'" v-model="curComponent.style[key]" />
<el-select v-else-if="key == 'textAlign'" v-model="curComponent.style[key]">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
<el-select v-else-if="selectKey.includes(key)" v-model="curComponent.style[key]">
<template v-if="key == 'textAlign'">
<el-option
v-for="item in textAlignOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</template>
<template v-else-if="key == 'borderStyle'">
<el-option
v-for="item in borderStyleOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</template>
<template v-else>
<el-option
v-for="item in verticalAlignOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</template>
</el-select>
<el-input v-if="key ==='opacity'" v-model="curComponent.style[key]" type="number" :min="0" :step="0.1" :max="1" />
<el-input v-else v-model="curComponent.style[key]" type="number" />
</el-form-item>
<!-- <el-form-item v-if="curComponent && !excludes.includes(curComponent.component)" label="内容">-->
<!-- <el-input v-model="curComponent.propValue" type="textarea" />-->
<!-- </el-form-item>-->
<el-form-item v-if="curComponent && !excludes.includes(curComponent.component)" :label="$t('panel.content')">
<el-input v-model="curComponent.propValue" type="textarea" />
</el-form-item>
</el-form>
</div>
</template>
@ -27,21 +45,46 @@
export default {
data() {
return {
excludes: ['Picture', 'Group'], //
options: [
excludes: ['Picture', 'Group', 'user-view'], //
textAlignOptions: [
{
label: this.$t('panel.aline_left'),
label: this.$t('panel.text_align_left'),
value: 'left'
},
{
label: this.$t('panel.aline_center'),
label: this.$t('panel.text_align_center'),
value: 'center'
},
{
label: this.$t('panel.aline_right'),
label: this.$t('panel.text_align_right'),
value: 'right'
}
],
borderStyleOptions: [
{
label: this.$t('panel.border_style_solid'),
value: 'solid'
},
{
label: this.$t('panel.border_style_dashed'),
value: 'dashed'
}
],
verticalAlignOptions: [
{
label: this.$t('panel.vertical_align_top'),
value: 'top'
},
{
label: this.$t('panel.vertical_align_middle'),
value: 'middle'
},
{
label: this.$t('panel.vertical_align_bottom'),
value: 'bottom'
}
],
selectKey: ['textAlign', 'borderStyle', 'verticalAlign'],
map: {
left: this.$t('panel.left'),
top: this.$t('panel.top'),
@ -49,6 +92,7 @@ export default {
width: this.$t('panel.width'),
color: this.$t('panel.color'),
backgroundColor: this.$t('panel.backgroundColor'),
borderStyle: this.$t('panel.borderStyle'),
borderWidth: this.$t('panel.borderWidth'),
borderColor: this.$t('panel.borderColor'),
borderRadius: this.$t('panel.borderRadius'),
@ -57,12 +101,14 @@ export default {
lineHeight: this.$t('panel.lineHeight'),
letterSpacing: this.$t('panel.letterSpacing'),
textAlign: this.$t('panel.textAlign'),
opacity: this.$t('panel.opacity')
opacity: this.$t('panel.opacity'),
verticalAlign: this.$t('panel.verticalAlign')
}
}
},
computed: {
styleKeys() {
console.log(this.$store.state.curComponent.style)
return this.$store.state.curComponent ? Object.keys(this.$store.state.curComponent.style) : []
},
curComponent() {
@ -73,10 +119,10 @@ export default {
</script>
<style lang="scss" scoped>
.attr-list {
.attr-list {
overflow: auto;
padding: 0px;
padding: 20px;
padding-top: 0;
height: 100%;
}
}
</style>

View File

@ -334,7 +334,6 @@ export default {
curPoint,
symmetricPoint
})
// console.log('this is test:' + JSON.stringify(this.element.propValue.viewId))
this.$store.commit('setShapeStyle', style)
this.element.propValue && this.element.propValue.viewId && eventBus.$emit('resizing', this.element.propValue.viewId)

View File

@ -21,22 +21,20 @@
:index="index"
:class="{ lock: item.isLock }"
>
<!-- item.style-&#45;&#45;{{ item.style }}-->
<!-- item.style-&#45;&#45;{{ getShapeStyleInt(item.style) }}-->
<component
:is="item.component"
v-if="item.type==='custom'"
v-if="item.type==='v-text'"
:id="'component' + item.id"
class="component"
:style="item.style"
:out-style="getShapeStyleInt(item.style)"
:style="getComponentStyleDefault(item.style)"
:prop-value="item.propValue"
:element="item"
:out-style="getShapeStyleInt(item.style)"
@input="handleInput"
/>
<component
:is="item.component"
v-else
v-else-if="item.type==='other'"
:id="'component' + item.id"
class="component"
:style="getComponentStyle(item.style)"
@ -45,6 +43,16 @@
:filter="filter"
:out-style="getShapeStyleInt(item.style)"
/>
<component
:is="item.component"
v-else
:id="'component' + item.id"
class="component"
:style="getComponentStyleDefault(item.style)"
:prop-value="item.propValue"
:element="item"
:out-style="getShapeStyleInt(item.style)"
/>
<!-- <component
:is="item.component"
v-else
@ -365,17 +373,26 @@ export default {
return result
},
getComponentStyleDefault(style) {
debugger
return getStyle(style, ['top', 'left', 'width', 'height', 'rotate'])
// return style
},
getComponentStyle(style) {
debugger
// return getStyle(style, ['top', 'left', 'width', 'height', 'rotate'])
return style
},
handleInput(element, value) {
// shape
this.$store.commit('setShapeStyle', { height: this.getTextareaHeight(element, value) })
// remain -
// this.$store.commit('setShapeStyle', { height: this.getTextareaHeight(element, value) })
},
getTextareaHeight(element, text) {
debugger
// eslint-disable-next-line prefer-const
let { lineHeight, fontSize, height } = element.style
if (lineHeight === '') {

View File

@ -11,6 +11,25 @@ export const commonAttr = {
isLock: false // 是否锁定组件
}
export const assistList = [
{
id: '10001',
component: 'v-text',
type: 'v-text',
label: '文字',
icon: 'iconfont icon-shuru',
defaultClass: 'text-filter'
},
{
id: '10004',
component: 'rect-shape',
type: 'rect-shape',
label: '矩形',
icon: 'iconfont icon-xialakuang',
defaultClass: 'text-filter'
}
]
// 编辑器左侧组件列表
const list = [
{
@ -19,7 +38,7 @@ const list = [
label: '文字',
propValue: '双击编辑文字',
icon: 'wenben',
type: 'other',
type: 'v-text',
style: {
width: 200,
height: 22,
@ -37,7 +56,7 @@ const list = [
label: '按钮',
propValue: '按钮',
icon: 'button',
type: 'other',
type: 'v-button',
style: {
width: 100,
height: 34,
@ -58,7 +77,7 @@ const list = [
component: 'Picture',
label: '图片',
icon: 'tupian',
type: 'other',
type: 'Picture',
propValue: require('@/components/canvas/assets/title.jpg'),
style: {
width: 300,
@ -71,7 +90,7 @@ const list = [
component: 'Picture',
label: '背景-科技1',
icon: 'tupian',
type: 'other',
type: 'Picture',
propValue: require('@/components/canvas/assets/bg-kj-1.jpg'),
style: {
width: 600,
@ -83,9 +102,9 @@ const list = [
id: '10004',
component: 'rect-shape',
label: '矩形',
propValue: '&nbsp;',
propValue: '',
icon: 'juxing',
type: 'other',
type: 'rect-shape',
style: {
width: 200,
height: 200,
@ -112,7 +131,7 @@ const list = [
style: {
width: 200,
height: 300,
borderWidth: 1
borderRadius: ''
}
}
]

View File

@ -27,6 +27,7 @@ export function getStyle(style, filter = []) {
}
})
debugger
return result
}

View File

@ -932,6 +932,7 @@ export default {
width: 'Width',
color: 'Color',
backgroundColor: 'BackgroundColor',
borderStyle: 'Border Style',
borderWidth: 'BorderWidth',
borderColor: 'BorderColor',
borderRadius: 'BorderRadius',
@ -941,10 +942,18 @@ export default {
letterSpacing: 'LetterSpacing',
textAlign: 'TextAlign',
opacity: 'Opacity',
aline_left: 'Aline Left',
aline_center: 'Aline Center',
aline_right: 'Aline Right',
select_component: 'Check Component'
verticalAlign: 'Vertical Align',
text_align_left: 'Aline Left',
text_align_center: 'Aline Center',
text_align_right: 'Aline Right',
vertical_align_top: 'Align Align',
vertical_align_middle: 'Align Middle',
vertical_align_bottom: 'Align Bottom',
border_style_solid: 'Solid',
border_style_dashed: 'Dashed',
select_component: 'Check Component',
other_module: 'Other',
content: 'Content'
},
plugin: {
local_install: 'Local installation',

View File

@ -932,6 +932,7 @@ export default {
width: '宽',
color: '颜色',
backgroundColor: '背景色',
borderStyle: '边框风格',
borderWidth: '边框宽度',
borderColor: '边框颜色',
borderRadius: '边框半径',
@ -939,12 +940,20 @@ export default {
fontWeight: '字体粗细',
lineHeight: '行高',
letterSpacing: '字间距',
textAlign: '对齐方式',
textAlign: '左右对齐',
opacity: '透明度',
aline_left: '左对齐',
aline_center: '居中',
aline_right: '右对齐',
select_component: '请选择组件'
verticalAlign: '上下对齐',
text_align_left: '左对齐',
text_align_center: '左右居中',
text_align_right: '右对齐',
vertical_align_top: '上对齐',
vertical_align_middle: '居中对齐',
vertical_align_bottom: '下对齐',
border_style_solid: '实线',
border_style_dashed: '虚线',
select_component: '请选择组件',
other_module: '其他',
content: '内容'
},
plugin: {
local_install: '本地安裝',

View File

@ -932,6 +932,7 @@ export default {
width: '宽',
color: '颜色',
backgroundColor: '背景色',
borderStyle: '边框风格',
borderWidth: '边框宽度',
borderColor: '边框颜色',
borderRadius: '边框半径',
@ -939,12 +940,20 @@ export default {
fontWeight: '字体粗细',
lineHeight: '行高',
letterSpacing: '字间距',
textAlign: '对齐方式',
textAlign: '左右对齐',
opacity: '透明度',
aline_left: '左对齐',
aline_center: '居中',
aline_right: '右对齐',
select_component: '请选择组件'
verticalAlign: '上下对齐',
text_align_left: '左对齐',
text_align_center: '左右居中',
text_align_right: '右对齐',
vertical_align_top: '上对齐',
vertical_align_middle: '居中对齐',
vertical_align_bottom: '下对齐',
border_style_solid: '实线',
border_style_dashed: '虚线',
select_component: '请选择组件',
other_module: '其他',
content: '内容'
},
plugin: {
local_install: '本地安装',

View File

@ -72,6 +72,7 @@ const data = {
},
setCurComponent(state, { component, index }) {
console.log('curComponent' + JSON.stringify(component))
state.curComponent = component
state.curComponentIndex = index
},
@ -87,6 +88,7 @@ const data = {
if (width) curComponent.style.width = parseInt(canvasStyleData.selfAdaption ? (width * 100 / curCanvasScale.scaleWidth) : width)
if (height) curComponent.style.height = parseInt(canvasStyleData.selfAdaption ? (height * 100 / curCanvasScale.scaleHeight) : height)
if (rotate) curComponent.style.rotate = rotate
console.log('setShapeStyle' + JSON.stringify(curComponent))
},
setShapeSingleStyle({ curComponent }, { key, value }) {

View File

@ -0,0 +1,225 @@
<template>
<div class="filter-container" @dragstart="handleDragStart">
<div class="widget-subject">
<div class="filter-header">
<div class="filter-header-text"> 样式组件 </div>
</div>
<div class="filter-widget-content">
<div
v-for="(item, index) in assistList"
:key="index"
:data-id="item.id"
draggable
:data-index="index"
:class="'filter-widget '+ (item.defaultClass || '')"
>
<div class="filter-widget-icon">
<i :class="(item.icon || 'el-icon-setting') + ' widget-icon-i'" />
</div>
<div class="filter-widget-text">{{ item.label }}</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { assistList } from '@/components/canvas/custom-component/component-list'
export default {
name: 'FilterGroup',
data() {
return {
assistList
}
},
methods: {
handleDragStart(ev) {
ev.dataTransfer.effectAllowed = 'copy'
const dataTrans = {
type: 'assist',
id: ev.target.dataset.id
}
ev.dataTransfer.setData('componentInfo', JSON.stringify(dataTrans))
}
}
}
</script>
<style lang="scss" scoped>
.filter-container {
width: 240px;
overflow: hidden auto;
min-height: 24px;
padding-top: 0px;
padding-bottom: 0px;
position: relative;
height: 940px;
max-height: 976px;
}
.filter-header {
overflow: hidden;
position: relative;
margin-top: 24px;
margin-left: 15px;
align-items: center;
word-break: break-all;
display: flex;
flex-direction: row;
justify-content: flex-start;
flex-wrap: nowrap;
}
.filter-header-text {
font-size: 14px;
max-width: 100%;
color: gray;
text-align: left;
white-space: pre;
text-overflow: ellipsis;
position: relative;
flex-shrink: 0;
box-sizing: border-box;
overflow: hidden;
overflow-x: hidden;
overflow-y: hidden;
word-break: break-all;
}
.filter-widget-content {
position: relative;
margin-left: 5px;
}
.filter-widget {
width: 100px;
height: 36px;
position: relative;
float: left;
margin-top: 10px;
margin-left: 10px;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#1a3685f2,endColorstr=#1a3685f2);
font-size: 12px;
border-radius: 10px;
cursor: pointer;
overflow: hidden;
}
.time-filter {
background-color: rgba(54,133,242,.1);
.filter-widget-icon {
color: #3685f2;
}
.filter-widget-text {
color: #3d4d66;
}
}
.time-filter:hover {
background-color: #3685f2;
color: #fff;
.filter-widget-icon {
background-color: #3685f2;
color: #fff;
}
.filter-widget-text {
color: #fff;
}
}
.text-filter {
background-color: rgba(35,190,239,.1);
.filter-widget-icon {
color: #23beef;
}
.filter-widget-text {
color: #3d4d66;
}
}
.text-filter:hover {
background-color: #23beef;
color: #fff;
.filter-widget-icon {
background-color: #23beef;
color: #fff;
}
.filter-widget-text {
color: #fff;
}
}
.tree-filter {
background-color: rgba(22,160,132,.1);
.filter-widget-icon {
color: #37b4aa;
}
.filter-widget-text {
color: #3d4d66;
}
}
.tree-filter:hover {
background-color: #37b4aa;
.filter-widget-icon {
color: #37b4aa;
}
.filter-widget-text {
color: #fff;
}
}
.filter-widget-icon {
width: 40px;
height: 36px;
text-align: center;
line-height: 1;
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
justify-content: center;
align-items: center;
flex-direction: row;
flex-wrap: nowrap;
display: flex;
.widget-icon-i {
width: 24px;
height: 24px;
position: relative;
flex-shrink: 0;
font-size: 24px;
margin: auto;
font-family: fineui;
font-style: normal;
-webkit-font-smoothing: antialiased;
text-align: center;
}
}
.filter-widget-text {
font-size: 14px;
height: 36px;
line-height: 36px;
text-align: left;
white-space: pre;
text-overflow: ellipsis;
position: absolute;
inset: 0px 0px 0px 40px;
box-sizing: border-box;
overflow: hidden;
overflow-x: hidden;
overflow-y: hidden;
word-break: break-all;
cursor: pointer;
}
.widget-subject {
display: flow-root;
}
</style>

View File

@ -52,6 +52,23 @@
<div style="width: 60px;height: 1px;line-height: 1px;text-align: center;white-space: pre;text-overflow: ellipsis;position: relative;flex-shrink: 0;" />
</div>
<!-- 过滤组件 end -->
<!-- 其他组件 start -->
<div tabindex="-1" style="position: relative; margin: 16px auto">
<div style="height: 60px; position: relative">
<div class="button-div-class" style=" text-align: center;line-height: 1;position: absolute;inset: 0px 0px 45px; ">
<el-button circle :class="show&&showIndex===3? 'button-show':'button-closed'" class="el-icon-brush" size="mini" @click="showPanel(3)" />
</div>
<div style=" position: absolute;left: 0px;right: 0px;bottom: 10px; height: 16px;">
<div style=" max-width: 100%;text-align: center;white-space: nowrap;text-overflow: ellipsis;position: relative;flex-shrink: 0;">
{{ $t('panel.other_module') }}
</div>
</div>
</div>
</div>
<div style="height: 1px; position: relative; margin: 0px auto;background-color:#E6E6E6;">
<div style="width: 60px;height: 1px;line-height: 1px;text-align: center;white-space: pre;text-overflow: ellipsis;position: relative;flex-shrink: 0;" />
</div>
<!-- 其他组件 end -->
</div>
</div>
</de-aside-container>
@ -73,6 +90,7 @@
<view-select v-show=" show && showIndex===0" />
<filter-group v-show=" show &&showIndex===1" />
<subject-setting v-show=" show &&showIndex===2" />
<assist-component v-show=" show &&showIndex===3" />
</el-drawer>
<div
@ -147,8 +165,9 @@ import Toolbar from '@/components/canvas/components/Toolbar'
import { findOne } from '@/api/panel/panel'
import PreviewFullScreen from '@/components/canvas/components/Editor/PreviewFullScreen'
import Preview from '@/components/canvas/components/Editor/Preview'
import AttrList from '@/components/canvas/components/AttrList.vue'
import AttrList from '@/components/canvas/components/AttrList'
import elementResizeDetectorMaker from 'element-resize-detector'
import AssistComponent from '@/views/panel/AssistComponent'
//
import '@/components/canvas/assets/iconfont/iconfont.css'
@ -171,7 +190,8 @@ export default {
SubjectSetting,
PreviewFullScreen,
Preview,
AttrList
AttrList,
AssistComponent
},
data() {
return {
@ -334,6 +354,7 @@ export default {
return data
},
handleDrop(e) {
debugger
e.preventDefault()
e.stopPropagation()
let component
@ -341,8 +362,15 @@ export default {
const componentInfo = JSON.parse(e.dataTransfer.getData('componentInfo'))
//
if (componentInfo.type === 'view') {
if (componentInfo.type === 'assist') {
//
componentList.forEach(componentTemp => {
if (componentInfo.id === componentTemp.id) {
component = deepCopy(componentTemp)
}
})
} else if (componentInfo.type === 'view') {
//
componentList.forEach(componentTemp => {
if (componentTemp.type === 'view') {
component = deepCopy(componentTemp)
@ -368,6 +396,7 @@ export default {
component = deepCopy(this.currentFilterCom)
}
// position = absolution
component.style.top = e.offsetY
component.style.left = e.offsetX
component.id = newComponentId
@ -546,10 +575,10 @@ export default {
background-color: #ffffff!important;
}
.style-aside{
width: 85px;
max-width:85px!important;
width: 200px;
max-width:200px!important;
border: 1px solid #E6E6E6;
padding: 3px;
padding: 10px;
transition: all 0.3s;
}

View File

@ -28,7 +28,8 @@
</template>
<script>import componentList from '@/components/canvas/custom-component/component-list'
<script>
import componentList from '@/components/canvas/custom-component/component-list'
import { ApplicationContext } from '@/utils/ApplicationContext'
export default {
name: 'FilterGroup',
@ -73,6 +74,7 @@ export default {
return result
})
}
console.log('this.widgetSubjects=>' + JSON.stringify(this.widgetSubjects))
},
methods: {