|
|
|
|
@ -67,12 +67,17 @@
|
|
|
|
|
return timestamp + randomNum;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 判断是画布还是组件
|
|
|
|
|
var isScreen = function (type) {
|
|
|
|
|
return type === 'screen';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** 初始化 */
|
|
|
|
|
var init = function (type, self) {
|
|
|
|
|
// debugger;
|
|
|
|
|
const initDataStorage = localStorage.getItem(`${type}Data`);
|
|
|
|
|
if (!initDataStorage) {
|
|
|
|
|
self['initData'] = {
|
|
|
|
|
type: 'screen',
|
|
|
|
|
id: `grid_${generateUniqueId()}`,
|
|
|
|
|
children: [],
|
|
|
|
|
version: '1.0.0',
|
|
|
|
|
@ -85,6 +90,8 @@
|
|
|
|
|
self['initData'] = JSON.parse(initDataStorage);
|
|
|
|
|
conputedInitData('init', self);
|
|
|
|
|
}
|
|
|
|
|
self['initData'].el = document.getElementById(`${type}-screen`);
|
|
|
|
|
|
|
|
|
|
console.log(self['initData'], `${type}Data`);
|
|
|
|
|
|
|
|
|
|
// 初始化时应用画布背景
|
|
|
|
|
@ -114,7 +121,7 @@
|
|
|
|
|
},
|
|
|
|
|
`#${type}-screen`
|
|
|
|
|
);
|
|
|
|
|
console.log(self['grid'], `${type}.grid实例`);
|
|
|
|
|
// console.log(self['grid'], `${type}.grid实例`);
|
|
|
|
|
|
|
|
|
|
// grid.load(initData.children);
|
|
|
|
|
|
|
|
|
|
@ -143,25 +150,17 @@
|
|
|
|
|
component.id = `${component.type}_${generateUniqueId()}`;
|
|
|
|
|
}
|
|
|
|
|
setComponentView(component);
|
|
|
|
|
component.el.addEventListener('click', () => {
|
|
|
|
|
console.log('点击组件', component);
|
|
|
|
|
component.el.addEventListener('click', (e) => {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
console.log(isScreen(component.type) ? `点击画布` : `点击组件`, component);
|
|
|
|
|
|
|
|
|
|
if (currentComponent && currentComponent.id === component.id) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 1. 解绑可能存在的画布属性事件处理器
|
|
|
|
|
$('#props-panel form').find('#image, #background').off();
|
|
|
|
|
// 2. 重新绑定通用的组件事件处理器
|
|
|
|
|
bindComponentEvents();
|
|
|
|
|
// 3. 重置属性面板标题并显示所有表单项,为显示组件属性做准备
|
|
|
|
|
$('#props-panel .panel-title span').text('组件属性');
|
|
|
|
|
$('#props-panel form .form-item').show();
|
|
|
|
|
|
|
|
|
|
// 清除之前选中组件的获取焦点后的样式
|
|
|
|
|
clearOldFocusStyle();
|
|
|
|
|
currentComponent = component;
|
|
|
|
|
// 设置当前选中组件的获取焦点后的样式
|
|
|
|
|
setCurrentFocusStyle();
|
|
|
|
|
// 右侧显示组件属性列表
|
|
|
|
|
if (!$('#props-panel').find('form').is(':visible')) {
|
|
|
|
|
$('#props-panel').find('.wait-box').hide();
|
|
|
|
|
@ -169,13 +168,19 @@
|
|
|
|
|
}
|
|
|
|
|
// 将当前选中组件的属性显示在右侧列表中
|
|
|
|
|
setCurrentComponentProps(currentComponent);
|
|
|
|
|
|
|
|
|
|
// 非画布时设置
|
|
|
|
|
if (!isScreen(component.type)) {
|
|
|
|
|
// 设置当前选中组件的获取焦点后的样式
|
|
|
|
|
setCurrentFocusStyle();
|
|
|
|
|
// 设置上下左右移动组件ID
|
|
|
|
|
setMoveComponentId(currentComponent, self);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var clearOldFocusStyle = function () {
|
|
|
|
|
if (currentComponent) {
|
|
|
|
|
if (currentComponent && !isScreen(currentComponent.type)) {
|
|
|
|
|
let el = $(currentComponent.el).find('.grid-stack-item-content');
|
|
|
|
|
el.css('background', '');
|
|
|
|
|
if (currentComponent.image) {
|
|
|
|
|
@ -191,7 +196,7 @@
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var setCurrentFocusStyle = function () {
|
|
|
|
|
if (currentComponent) {
|
|
|
|
|
if (currentComponent && !isScreen(currentComponent.type)) {
|
|
|
|
|
let el = $(currentComponent.el).find('.grid-stack-item-content');
|
|
|
|
|
if (currentComponent.focusedStyle_background) {
|
|
|
|
|
el.css('background', currentComponent.focusedStyle_background);
|
|
|
|
|
@ -238,16 +243,23 @@
|
|
|
|
|
var handleRemoveComponent = (component) => {
|
|
|
|
|
if (currentComponent && currentComponent.id === component.id) {
|
|
|
|
|
currentComponent = null;
|
|
|
|
|
hidePropsPanel();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var hidePropsPanel = () => {
|
|
|
|
|
// 右侧显示请选择组件
|
|
|
|
|
if (!$('#props-panel').find('wait-box').is(':visible')) {
|
|
|
|
|
$('#props-panel').find('.wait-box').show();
|
|
|
|
|
$('#props-panel').find('form').hide();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//将当前选中组件的属性显示在右侧列表中
|
|
|
|
|
var setCurrentComponentProps = function (component) {
|
|
|
|
|
// 设置标题
|
|
|
|
|
$('#props-panel .panel-title span').text(isScreen(component.type) ? '画布属性' : '组件属性');
|
|
|
|
|
|
|
|
|
|
const form = $('#props-panel').find('form');
|
|
|
|
|
if (component.hasOwnProperty('childrenType')) {
|
|
|
|
|
form.find('#childrenType').val(component.childrenType);
|
|
|
|
|
@ -256,7 +268,11 @@
|
|
|
|
|
form.find('#childrenType').parent().hide();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isScreen(component.type)) {
|
|
|
|
|
form.find('#name').val(component.name);
|
|
|
|
|
} else {
|
|
|
|
|
form.find('#name').parent().hide();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (component.hasOwnProperty('image')) {
|
|
|
|
|
form.find('#image').val(component.image);
|
|
|
|
|
@ -266,7 +282,36 @@
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (component.hasOwnProperty('background')) {
|
|
|
|
|
form.find('#background').val(component.background);
|
|
|
|
|
let options = {
|
|
|
|
|
elem: '#background',
|
|
|
|
|
alpha: true,
|
|
|
|
|
format: 'rgb',
|
|
|
|
|
done: function (color) {
|
|
|
|
|
const el = $(component.el);
|
|
|
|
|
let cptColor = rgbaToHex(color);
|
|
|
|
|
component.background = cptColor;
|
|
|
|
|
if (isScreen(component.type)) {
|
|
|
|
|
component.image = '';
|
|
|
|
|
}
|
|
|
|
|
if (!cptColor) {
|
|
|
|
|
if (isScreen(component.type)) {
|
|
|
|
|
el.css('background', 'none');
|
|
|
|
|
} else {
|
|
|
|
|
el.find('.grid-stack-item-content').css('background', 'none');
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (isScreen(component.type)) {
|
|
|
|
|
el.css('background', color);
|
|
|
|
|
} else {
|
|
|
|
|
el.find('.grid-stack-item-content').css('background', color);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
if (component.background) {
|
|
|
|
|
options.color = component.background;
|
|
|
|
|
}
|
|
|
|
|
layui.colorpicker.render(options);
|
|
|
|
|
form.find('#background').parent().show();
|
|
|
|
|
} else {
|
|
|
|
|
form.find('#background').parent().hide();
|
|
|
|
|
@ -288,6 +333,7 @@
|
|
|
|
|
form.find('#fontWeight').parent().hide();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isScreen(component.type)) {
|
|
|
|
|
form.find('#eventsType').val(component.eventsType);
|
|
|
|
|
form.find('#eventsAction').val(component.eventsAction);
|
|
|
|
|
form.find('#defaultFocus').val(component.defaultFocus);
|
|
|
|
|
@ -300,21 +346,83 @@
|
|
|
|
|
form.find('#focusedStyle_border_width').val(component.focusedStyle_border_width);
|
|
|
|
|
form.find('#focusedStyle_border_color').val(component.focusedStyle_border_color);
|
|
|
|
|
form.find('#focusedStyle_scale').val(component.focusedStyle_scale);
|
|
|
|
|
|
|
|
|
|
form.find('#eventsType').parent().show();
|
|
|
|
|
form.find('#eventsAction').parent().show();
|
|
|
|
|
form.find('#defaultFocus').parent().show();
|
|
|
|
|
form.find('#leftId').parent().show();
|
|
|
|
|
form.find('#rightId').parent().show();
|
|
|
|
|
form.find('#upId').parent().show();
|
|
|
|
|
form.find('#downId').parent().show();
|
|
|
|
|
form.find('#focusedStyle_background').parent().show();
|
|
|
|
|
form.find('#focusedStyle_border_width').parent().show();
|
|
|
|
|
form.find('#focusedStyle_border_color').parent().show();
|
|
|
|
|
form.find('#focusedStyle_scale').parent().show();
|
|
|
|
|
} else {
|
|
|
|
|
form.find('#eventsType').parent().hide();
|
|
|
|
|
form.find('#eventsAction').parent().hide();
|
|
|
|
|
form.find('#defaultFocus').parent().hide();
|
|
|
|
|
form.find('#leftId').parent().hide();
|
|
|
|
|
form.find('#rightId').parent().hide();
|
|
|
|
|
form.find('#upId').parent().hide();
|
|
|
|
|
form.find('#downId').parent().hide();
|
|
|
|
|
form.find('#focusedStyle_background').parent().hide();
|
|
|
|
|
form.find('#focusedStyle_border_width').parent().hide();
|
|
|
|
|
form.find('#focusedStyle_border_color').parent().hide();
|
|
|
|
|
form.find('#focusedStyle_scale').parent().hide();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 定义组件设置配置策略
|
|
|
|
|
const componentStrategies = {
|
|
|
|
|
background: function (el, value) {
|
|
|
|
|
background: function (el, value, component) {
|
|
|
|
|
let options = {
|
|
|
|
|
elem: '#background',
|
|
|
|
|
alpha: true,
|
|
|
|
|
format: 'rgb',
|
|
|
|
|
done: function (color) {
|
|
|
|
|
const el = $(component.el);
|
|
|
|
|
let cptColor = rgbaToHex(color);
|
|
|
|
|
component.background = cptColor;
|
|
|
|
|
if (isScreen(component.type)) {
|
|
|
|
|
component.image = '';
|
|
|
|
|
}
|
|
|
|
|
if (!cptColor) {
|
|
|
|
|
if (isScreen(component.type)) {
|
|
|
|
|
el.css('background', 'none');
|
|
|
|
|
} else {
|
|
|
|
|
el.find('.grid-stack-item-content').css('background', 'none');
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (isScreen(component.type)) {
|
|
|
|
|
el.css('background', color);
|
|
|
|
|
} else {
|
|
|
|
|
el.find('.grid-stack-item-content').css('background', color);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
if (component.background) {
|
|
|
|
|
options.color = component.background;
|
|
|
|
|
}
|
|
|
|
|
layui.colorpicker.render(options);
|
|
|
|
|
|
|
|
|
|
if (!isScreen(component.type)) {
|
|
|
|
|
if (!value) {
|
|
|
|
|
el.find('.grid-stack-item-content').css('background', 'none');
|
|
|
|
|
} else {
|
|
|
|
|
el.find('.grid-stack-item-content').css('background', value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
image: function (el, value, component) {
|
|
|
|
|
if (!value) return;
|
|
|
|
|
// el.find('.grid-stack-item-content').css('background', `url(${value}) no-repeat center center`).css('background-size', 'cover');
|
|
|
|
|
if (isScreen(component.type)) {
|
|
|
|
|
el.css('background', `url(${value}) no-repeat center center`).css('background-size', 'cover');
|
|
|
|
|
component.background = '';
|
|
|
|
|
} else {
|
|
|
|
|
el.find('img').attr('src', value);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
fontSize: function (el, value) {
|
|
|
|
|
if (!value) return;
|
|
|
|
|
@ -338,19 +446,19 @@
|
|
|
|
|
el.find('.grid-stack-item-content').css('background', value);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
focusedStyle_border_width: function (el, value) {
|
|
|
|
|
focusedStyle_border_width: function (el, value, component) {
|
|
|
|
|
if (!value) return;
|
|
|
|
|
if (currentComponent && currentComponent.id === component.id) {
|
|
|
|
|
el.find('.grid-stack-item-content').css('border-width', value + 'px');
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
focusedStyle_border_color: function (el, value) {
|
|
|
|
|
focusedStyle_border_color: function (el, value, component) {
|
|
|
|
|
if (!value) return;
|
|
|
|
|
if (currentComponent && currentComponent.id === component.id) {
|
|
|
|
|
el.find('.grid-stack-item-content').css('border-color', value);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
focusedStyle_scale: function (el, value) {
|
|
|
|
|
focusedStyle_scale: function (el, value, component) {
|
|
|
|
|
if (!value) return;
|
|
|
|
|
if (currentComponent && currentComponent.id === component.id) {
|
|
|
|
|
el.find('.grid-stack-item-content').css('transform', `scale(${value})`);
|
|
|
|
|
@ -432,13 +540,35 @@
|
|
|
|
|
$('.grid-stack')
|
|
|
|
|
.not('#' + tabId)
|
|
|
|
|
.hide();
|
|
|
|
|
|
|
|
|
|
// 处理右侧面板的显示/隐藏
|
|
|
|
|
hidePropsPanel();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 点击保存按钮处理
|
|
|
|
|
var handleSaveClick = function () {
|
|
|
|
|
$('.save-container').click(function () {
|
|
|
|
|
main.initData.children = main.grid.save();
|
|
|
|
|
welcome.initData.children = welcome.grid.save();
|
|
|
|
|
console.log(main.initData);
|
|
|
|
|
console.log(welcome.initData);
|
|
|
|
|
localStorage.setItem('mainData', JSON.stringify(conputedInitData('save', main)));
|
|
|
|
|
localStorage.setItem('welcomeData', JSON.stringify(conputedInitData('save', welcome)));
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 点击画布处理
|
|
|
|
|
var handleCanvasClick = function () {
|
|
|
|
|
handleAddComponent(welcome.initData, welcome);
|
|
|
|
|
handleAddComponent(main.initData, main);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 保存的时候计算x,y,w,h
|
|
|
|
|
var conputedInitData = function (type, self) {
|
|
|
|
|
if (type === 'save') {
|
|
|
|
|
let initDataCopy = JSON.parse(JSON.stringify(self['initData']));
|
|
|
|
|
const { el, ...otherInfo } = self['initData'];
|
|
|
|
|
let initDataCopy = JSON.parse(JSON.stringify(otherInfo));
|
|
|
|
|
initDataCopy.children.forEach((item) => {
|
|
|
|
|
item.xCopy = item.x;
|
|
|
|
|
item.x = item.x * (1920 / 12);
|
|
|
|
|
@ -469,88 +599,15 @@
|
|
|
|
|
|
|
|
|
|
/** 执行方法 */
|
|
|
|
|
$(function () {
|
|
|
|
|
init('main', main);
|
|
|
|
|
init('welcome', welcome);
|
|
|
|
|
init('main', main);
|
|
|
|
|
// 调用绑定
|
|
|
|
|
bindComponentEvents();
|
|
|
|
|
// 处理Tab切换
|
|
|
|
|
handleTabSwitch();
|
|
|
|
|
|
|
|
|
|
$('.save-container').click(function () {
|
|
|
|
|
main.initData.children = main.grid.save();
|
|
|
|
|
welcome.initData.children = welcome.grid.save();
|
|
|
|
|
console.log(main.initData);
|
|
|
|
|
console.log(welcome.initData);
|
|
|
|
|
localStorage.setItem('mainData', JSON.stringify(conputedInitData('save', main)));
|
|
|
|
|
localStorage.setItem('welcomeData', JSON.stringify(conputedInitData('save', welcome)));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 给画布添加点击事件,用于编辑画布属性
|
|
|
|
|
$('#main-screen, #welcome-screen').on('click', function (e) {
|
|
|
|
|
// 确保点击的是画布背景,而不是某个组件
|
|
|
|
|
if (e.target !== this) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('点击了画布背景,编辑画布属性');
|
|
|
|
|
|
|
|
|
|
// 1. 如果有,则取消当前选中的组件
|
|
|
|
|
if (currentComponent) {
|
|
|
|
|
clearOldFocusStyle();
|
|
|
|
|
currentComponent = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. 更新右侧面板以显示画布属性
|
|
|
|
|
$('#props-panel .panel-title span').text('画布属性');
|
|
|
|
|
$('#props-panel .wait-box').hide();
|
|
|
|
|
const $form = $('#props-panel form');
|
|
|
|
|
$form.show();
|
|
|
|
|
|
|
|
|
|
// 3. 只显示画布相关的表单项
|
|
|
|
|
$form.find('.form-item').hide(); // 首先隐藏所有
|
|
|
|
|
$form.find('#image').parent().show(); // 显示背景图片
|
|
|
|
|
$form.find('#background').parent().show(); // 显示背景颜色
|
|
|
|
|
|
|
|
|
|
// 4. 获取当前点击的画布及其数据对象
|
|
|
|
|
const canvasId = this.id; // "main-screen" 或 "welcome-screen"
|
|
|
|
|
const type = canvasId.split('-')[0]; // "main" 或 "welcome"
|
|
|
|
|
const canvasData = type === 'main' ? main : welcome;
|
|
|
|
|
|
|
|
|
|
// 5. 将当前画布的属性值填充到表单中
|
|
|
|
|
$form.find('#image').val(canvasData.initData.image || '');
|
|
|
|
|
$form.find('#background').val(canvasData.initData.background || '');
|
|
|
|
|
|
|
|
|
|
// 6. 为画布属性输入框绑定新的事件
|
|
|
|
|
$form.find('#image, #background').off(); // 先解绑旧事件,防止重复绑定
|
|
|
|
|
|
|
|
|
|
$form.find('#image').on('change', function () {
|
|
|
|
|
const imageUrl = $(this).val();
|
|
|
|
|
canvasData.initData.image = imageUrl;
|
|
|
|
|
if (imageUrl) {
|
|
|
|
|
$('#' + canvasId)
|
|
|
|
|
.css('background-image', `url(${imageUrl})`)
|
|
|
|
|
.css('background-size', 'cover');
|
|
|
|
|
// 当设置图片时,清空背景色
|
|
|
|
|
$('#' + canvasId).css('background-color', '');
|
|
|
|
|
canvasData.initData.background = '';
|
|
|
|
|
$form.find('#background').val('');
|
|
|
|
|
} else {
|
|
|
|
|
// 如果选择的是“请选择”,则只移除背景图片
|
|
|
|
|
$('#' + canvasId).css('background-image', 'none');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$form.find('#background').on('blur', function () {
|
|
|
|
|
const color = $(this).val();
|
|
|
|
|
canvasData.initData.background = color;
|
|
|
|
|
if (color) {
|
|
|
|
|
// 当设置颜色时,清空背景图片
|
|
|
|
|
$('#' + canvasId).css('background-color', color);
|
|
|
|
|
$('#' + canvasId).css('background-image', 'none');
|
|
|
|
|
canvasData.initData.image = '';
|
|
|
|
|
$form.find('#image').val('');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
// 处理保存按钮
|
|
|
|
|
handleSaveClick();
|
|
|
|
|
// 处理画布点击事件
|
|
|
|
|
handleCanvasClick();
|
|
|
|
|
});
|
|
|
|
|
})();
|
|
|
|
|
|