diff --git a/front-end/h5/package.json b/front-end/h5/package.json index 34be1404..be3dee79 100644 --- a/front-end/h5/package.json +++ b/front-end/h5/package.json @@ -6,7 +6,7 @@ "dev": "vue-cli-service serve", "serve": "vue-cli-service serve", "build": "npm run build:editor && npm run build:engine", - "lint": "vue-cli-service lint --fix", + "lint": "vue-cli-service lint --fix src", "deploy": "rm -rf dist && npm run build:editor && npm run build:engine && ./deploy.sh", "test:e2e": "vue-cli-service test:e2e", "test:unit": "vue-cli-service test:unit", @@ -44,11 +44,12 @@ "vue-matomo": "^3.13.0-2", "vue-quill-editor": "^3.0.6", "vue-router": "^3.0.3", + "vuedraggable": "^2.24.3", "vuex": "^3.0.1", "x-data-spreadsheet": "^1.1.4" }, "devDependencies": { - "@babel/plugin-proposal-optional-chaining": "^7.12.16", + "@babel/plugin-proposal-optional-chaining": "^7.14.5", "@vue/cli-plugin-babel": "^3.8.0", "@vue/cli-plugin-eslint": "^3.8.0", "@vue/cli-plugin-pwa": "^3.8.0", diff --git a/front-end/h5/src/components/core/editor/canvas/KFormItem/README.md b/front-end/h5/src/components/core/editor/canvas/KFormItem/README.md new file mode 100644 index 00000000..6c6f7642 --- /dev/null +++ b/front-end/h5/src/components/core/editor/canvas/KFormItem/README.md @@ -0,0 +1,35 @@ +KFormItem +==== +构建表单控件 +根据参数不同的type,生成对应的控件 + + +### 使用方式 + +``` +# 参数record: +{ + type: "input", // 表单类型 + name: "输入框", // 标题文字 + options: { + type: "text", // input的type类型 + width: "100%", // 宽度 + defaultValue: "", // 默认值 + placeholder: "请输入", // 占位内容 + disabled: false // 是否禁用 + }, + model: "", // 数据字段 + key: "", + rules: [ //验证规则 + { + required: false, // 是否必填 + message: "必填项" + } + ] + } + +``` + + + + diff --git a/front-end/h5/src/components/core/editor/canvas/KFormItem/customComponent.vue b/front-end/h5/src/components/core/editor/canvas/KFormItem/customComponent.vue new file mode 100644 index 00000000..344a8955 --- /dev/null +++ b/front-end/h5/src/components/core/editor/canvas/KFormItem/customComponent.vue @@ -0,0 +1,76 @@ + + + diff --git a/front-end/h5/src/components/core/editor/canvas/KFormItem/index.js b/front-end/h5/src/components/core/editor/canvas/KFormItem/index.js new file mode 100644 index 00000000..36a0e169 --- /dev/null +++ b/front-end/h5/src/components/core/editor/canvas/KFormItem/index.js @@ -0,0 +1,11 @@ +/* + * author kcz + * date 2019-11-20 + */ +import KFormItem from './index.vue' + +KFormItem.install = function (Vue) { + Vue.component(KFormItem.name, KFormItem) +} + +export default KFormItem diff --git a/front-end/h5/src/components/core/editor/canvas/KFormItem/index.vue b/front-end/h5/src/components/core/editor/canvas/KFormItem/index.vue new file mode 100644 index 00000000..47286da9 --- /dev/null +++ b/front-end/h5/src/components/core/editor/canvas/KFormItem/index.vue @@ -0,0 +1,468 @@ + + + + diff --git a/front-end/h5/src/components/core/editor/canvas/core/components_use copy 2.js b/front-end/h5/src/components/core/editor/canvas/core/components_use copy 2.js new file mode 100644 index 00000000..aa69dc77 --- /dev/null +++ b/front-end/h5/src/components/core/editor/canvas/core/components_use copy 2.js @@ -0,0 +1,106 @@ +/** + * 该文件是为了按需加载,剔除掉了一些不需要的框架组件。 + * 减少了编译支持库包大小 + * + * 当需要更多组件依赖时,在该文件加入即可 + */ +import Vue from "vue"; +import { + ConfigProvider, + Layout, + Input, + Rate, + Slider, + InputNumber, + Button, + Switch, + Radio, + Checkbox, + Select, + Card, + Empty, + Form, + Row, + Col, + Modal, + Table, + Tabs, + Icon, + Steps, + Alert, + Tag, + Divider, + DatePicker, + TimePicker, + message, + Upload, + Tooltip, + FormModel, + Collapse, + Cascader, + TreeSelect +} from "ant-design-vue"; +import vcolorpicker from "vcolorpicker"; + +import KBatch from "../KBatch"; +import KSelectInputList from "../KSelectInputList"; +import KEditor from "../KEditor"; +import UploadFile from "../UploadFile"; +import UploadImg from "../UploadImg"; +import KDatePicker from "../KDatePicker"; +import KTimePicker from "../KTimePicker"; + +export default { + input: Input, + number: InputNumber, + select: Select, + checkbox: Checkbox, + radio: Radio, + date: KDatePicker, + time: KTimePicker, + rate: Rate, + slider: Slider, + switch: Switch, + uploadFile: UploadFile, + uploadImg: UploadImg, + treeSelect: TreeSelect, + cascader: Cascader, + batch: KBatch, + selectInputList: KSelectInputList, + editor: KEditor +}; + +Vue.use(ConfigProvider); +Vue.use(Tooltip); +Vue.use(Empty); +Vue.use(FormModel); +Vue.use(Collapse); +Vue.use(Layout); +Vue.use(Input); +Vue.use(Rate); +Vue.use(Slider); +Vue.use(InputNumber); +Vue.use(Button); +Vue.use(Switch); +Vue.use(Radio); +Vue.use(Checkbox); +Vue.use(Select); +Vue.use(Card); +Vue.use(Form); +Vue.use(Row); +Vue.use(Col); +Vue.use(Modal); +Vue.use(Table); +Vue.use(Tabs); +Vue.use(Icon); +Vue.use(Steps); +Vue.use(Alert); +Vue.use(Tag); +Vue.use(Divider); +Vue.use(DatePicker); +Vue.use(TimePicker); +Vue.use(Upload); +Vue.use(vcolorpicker); + +Vue.prototype.$confirm = Modal.confirm; +Vue.prototype.$message = message; diff --git a/front-end/h5/src/components/core/editor/canvas/core/components_use.js b/front-end/h5/src/components/core/editor/canvas/core/components_use.js new file mode 100644 index 00000000..ca383bee --- /dev/null +++ b/front-end/h5/src/components/core/editor/canvas/core/components_use.js @@ -0,0 +1,106 @@ +/** + * 该文件是为了按需加载,剔除掉了一些不需要的框架组件。 + * 减少了编译支持库包大小 + * + * 当需要更多组件依赖时,在该文件加入即可 + */ +import Vue from 'vue' +import { + ConfigProvider, + Layout, + Input, + Rate, + Slider, + InputNumber, + Button, + Switch, + Radio, + Checkbox, + Select, + Card, + Empty, + Form, + Row, + Col, + Modal, + Table, + Tabs, + Icon, + Steps, + Alert, + Tag, + Divider, + DatePicker, + TimePicker, + message, + Upload, + Tooltip, + FormModel, + Collapse, + Cascader, + TreeSelect +} from 'ant-design-vue' +// import vcolorpicker from 'vcolorpicker' + +// import KBatch from '../KBatch' +// import KSelectInputList from '../KSelectInputList' +// import KEditor from '../KEditor' +// import UploadFile from '../UploadFile' +// import UploadImg from '../UploadImg' +// import KDatePicker from '../KDatePicker' +// import KTimePicker from '../KTimePicker' + +export default { + input: Input, + number: InputNumber, + select: Select, + checkbox: Checkbox, + radio: Radio, + // date: KDatePicker, + // time: KTimePicker, + rate: Rate, + slider: Slider, + switch: Switch, + // uploadFile: UploadFile, + // uploadImg: UploadImg, + treeSelect: TreeSelect, + cascader: Cascader + // batch: KBatch, + // selectInputList: KSelectInputList, + // editor: KEditor +} + +Vue.use(ConfigProvider) +Vue.use(Tooltip) +Vue.use(Empty) +Vue.use(FormModel) +Vue.use(Collapse) +Vue.use(Layout) +Vue.use(Input) +Vue.use(Rate) +Vue.use(Slider) +Vue.use(InputNumber) +Vue.use(Button) +Vue.use(Switch) +Vue.use(Radio) +Vue.use(Checkbox) +Vue.use(Select) +Vue.use(Card) +Vue.use(Form) +Vue.use(Row) +Vue.use(Col) +Vue.use(Modal) +Vue.use(Table) +Vue.use(Tabs) +Vue.use(Icon) +Vue.use(Steps) +Vue.use(Alert) +Vue.use(Tag) +Vue.use(Divider) +Vue.use(DatePicker) +Vue.use(TimePicker) +Vue.use(Upload) +// Vue.use(vcolorpicker) + +Vue.prototype.$confirm = Modal.confirm +Vue.prototype.$message = message diff --git a/front-end/h5/src/components/core/editor/canvas/core/revoke.js b/front-end/h5/src/components/core/editor/canvas/core/revoke.js new file mode 100644 index 00000000..c13e2675 --- /dev/null +++ b/front-end/h5/src/components/core/editor/canvas/core/revoke.js @@ -0,0 +1,93 @@ +/** + 撤销重做功能 + */ +export class Revoke { + // 历史记录 + recordList = []; + + // 撤销记录,用于重做 + redoList = []; + + // 当前记录用currentRecord变量暂时存储,当用户修改时,再存放到recordList + currentRecord = null; + + // 上次插入数据时间 + time = 0; + + /** + * @description: 插入历史记录 + * @param {object}record + * @return {boolean} + */ + push(record) { + const nowTime = Date.now(); + // 防止添加重复的时间,当添加间隔小于100ms时,则替换当前记录并取消执行添加 + if (this.time + 100 > nowTime) { + this.currentRecord = JSON.stringify(record); + return false; + } + + this.time = nowTime; + + // 判断之前是否已经存在currentRecord记录,有则存储到recordList + if (this.currentRecord) { + this.recordList.push(this.currentRecord); + // 增加记录后则应该清空重做记录 + this.redoList.splice(0, this.redoList.length); + } + + // 将json转成字符串存储 + this.currentRecord = JSON.stringify(record); + + // 最多存储20条记录,超过20天记录则删除之前的记录 + if (this.length > 20) { + this.recordList.unshift(); + } + + return true; + } + + /** + * @description: 撤销操作 + * @param {*} + * @return {object} + */ + undo() { + // 没有记录时,返回false + if (this.recordList.length === 0) { + return false; + } + const record = this.recordList.pop(); + + // 将当前记录添加到重做记录里面 + if (this.currentRecord) { + this.redoList.push(this.currentRecord); + } + // 丢弃当前记录,防止重复添加 + this.currentRecord = null; + + return JSON.parse(record); + } + + /** + * @description: 重做操作 + * @param {*} + * @return {*} + */ + redo() { + // 没有重做记录时,返回false + if (this.redoList.length === 0) { + return false; + } + + const record = this.redoList.pop(); + // 添加到重做记录里面 + if (this.currentRecord) { + this.recordList.push(this.currentRecord); + } + // 丢弃当前记录,防止重复添加 + this.currentRecord = null; + + return JSON.parse(record); + } +} diff --git a/front-end/h5/src/components/core/editor/canvas/formComponentPanel.vue b/front-end/h5/src/components/core/editor/canvas/formComponentPanel.vue new file mode 100644 index 00000000..9760b488 --- /dev/null +++ b/front-end/h5/src/components/core/editor/canvas/formComponentPanel.vue @@ -0,0 +1,504 @@ + + + + + diff --git a/front-end/h5/src/components/core/editor/canvas/formNode.vue b/front-end/h5/src/components/core/editor/canvas/formNode.vue new file mode 100644 index 00000000..1bf0d147 --- /dev/null +++ b/front-end/h5/src/components/core/editor/canvas/formNode.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/front-end/h5/src/components/core/editor/canvas/index.js b/front-end/h5/src/components/core/editor/canvas/index.js index 68dfa801..cdafb89a 100644 --- a/front-end/h5/src/components/core/editor/canvas/index.js +++ b/front-end/h5/src/components/core/editor/canvas/index.js @@ -2,11 +2,39 @@ import { mapState, mapActions } from 'vuex' import RenderEditCanvas from './edit' import RenderPreviewCanvas from './preview' +import formComponentPanel from './formComponentPanel.vue' +import './styles/form-design.less' export default { name: 'EditorCanvas', data: () => ({ - isPreviewMode: false + isPreviewMode: false, + selectItem: { + key: '' + }, + noModel: [ + 'button', + 'divider', + 'card', + 'grid', + 'tabs', + 'table', + 'alert', + 'text', + 'html' + ], + data: { + list: [], + config: { + layout: 'horizontal', + labelCol: { xs: 4, sm: 4, md: 4, lg: 4, xl: 4, xxl: 4 }, + labelWidth: 100, + labelLayout: 'flex', + wrapperCol: { xs: 18, sm: 18, md: 18, lg: 18, xl: 18, xxl: 18 }, + hideRequiredMark: false, + customStyle: '' + } + } }), computed: { ...mapState('editor', { @@ -15,7 +43,8 @@ export default { elements: state => state.editingPage.elements, pages: state => state.work.pages, work: state => state.work, - scaleRate: state => state.scaleRate + scaleRate: state => state.scaleRate, + startType: state => state.startType }), ...mapState('loading', [ 'saveWork_loading', @@ -54,24 +83,41 @@ export default { onInput={this.handleToggleMode} > {/* 编辑模式、预览模式 */} - {this.$t('editor.centerPanel.mode.edit')} - {this.$t('editor.centerPanel.mode.preview')} + + {this.$t('editor.centerPanel.mode.edit')} + + + {this.$t('editor.centerPanel.mode.preview')} + - +
- { this.isPreviewMode - ? - : - } + {}} + /> + {/* {this.isPreviewMode ? ( + + ) : ( + + )} */}
diff --git a/front-end/h5/src/components/core/editor/canvas/layoutItem.vue b/front-end/h5/src/components/core/editor/canvas/layoutItem.vue new file mode 100644 index 00000000..814c5fa2 --- /dev/null +++ b/front-end/h5/src/components/core/editor/canvas/layoutItem.vue @@ -0,0 +1,556 @@ + + + diff --git a/front-end/h5/src/components/core/editor/canvas/styles/form-design.less b/front-end/h5/src/components/core/editor/canvas/styles/form-design.less new file mode 100644 index 00000000..18811bfd --- /dev/null +++ b/front-end/h5/src/components/core/editor/canvas/styles/form-design.less @@ -0,0 +1,1204 @@ +// 表单设计器样式 +@primary-color: #13c2c2; +@layout-color : #ccc; + +@primary-background-color: fade(@primary-color, 6%); +@primary-hover-bg-color : fade(@primary-color, 20%); +@layout-background-color : fade(@layout-color, 12%); +@layout-hover-bg-color : fade(@layout-color, 24%); + +@title-text-color: #fff; +@border-color : #ccc; + +@left-right-width : 270px; +@header-height : 56px; +@operating-area-height : 45px; +@import "./k-table.less"; +@import "./k-editor.less"; + +// 表单设计器样式 +.form-designer-container-9136076486841527 { + height : 100vh; + width : 100%; + overflow: hidden; + + // header样式 + .header { + width : 100%; + height : @header-height; + text-align : center; + background : @primary-color; + color : @title-text-color; + // margin-bottom: 6px; + // border-bottom: 1px solid @border-color; + line-height : @header-height; + font-size : 18px; + font-weight : bold; + } + + // 头部操作按钮区域 + .operating-area { + border-bottom : 2px solid @border-color; + font-size : 16px; + text-align : left; + height : @operating-area-height; + line-height : @operating-area-height; + padding : 0px 12px; + display : flex; + justify-content: space-between; + align-content : center; + + a { + color : #666; + margin: 0 5px; + &.disabled, &.disabled:hover { + color : #ccc; + } + &:hover { + color: @primary-color; + } + + >span { + font-size : 14px; + padding-left: 2px; + } + } + } + + // iconfont 样式 + .icon { + width : 1em; + height : 1em; + vertical-align: -0.15em; + fill : currentColor; + overflow : hidden; + } + + // 设计器内容样式 + .content { + display: flex; + height : 100%; + flex : 1; + + &.show-head { + margin-top: 6px; + height : calc(100% - @header-height - 6px); + } + + &.toolbars-top { + margin-top: 6px; + height : calc(100% - @operating-area-height - 6px); + } + + &.show-head-and-toolbars-top { + margin-top: 6px; + height : calc(100% - @header-height - @operating-area-height - 6px); + } + + // 左右栏 + aside { + box-shadow : 0px 0px 1px 1px @border-color; + width : @left-right-width; + height : 100%; + // >.left-title { + // padding : 12px 10px 8px; + // user-select: none; + // } + + &.left { + // border-right: 1px solid @aside-border-color; + height : 100%; + overflow : auto; + user-select: none; + + .ant-collapse-content-box { + padding: 0; + } + + .ant-collapse { + border: 0; + + >.ant-collapse-item { + border-color: @border-color; + + >.ant-collapse-header { + padding: 7px 0 7px 40px; + } + + >.ant-collapse-content { + border-color: @border-color; + } + } + } + + + ul { + padding : 5px; + list-style : none; + display : flex; + margin-bottom: 0; + flex-wrap : wrap; + // background: #efefef; + + li { + border-radius: 0; + border : 0; + box-shadow : 1px 0 0 0 @border-color, 0 1px 0 0 @border-color, 1px 1px 0 0 @border-color, 1px 0 0 0 @border-color inset, 0 1px 0 0 @border-color inset; + padding : 8px 12px; + transition : all 0.3s; + width : calc(50% - 6px); + margin : 2.7px; + height : 36px; + line-height : 20px; + cursor : move; + border : 1px solid transparent; + border-radius: 3px; + transition : all .3s; + + &:hover { + color : @primary-color; + border : 1px solid @primary-color; + position : relative; + z-index : 1; + box-shadow: 0 2px 6px @primary-color; + } + } + } + } + + // 右侧区域 + &.right { + height : 100%; + // border-left: 1px solid @aside-border-color; + // border-top : 1px solid @aside-border-color; + color : #fff; + overflow : hidden; + position : relative; + + + // 控件属性设置 + .form-item-properties { + width : 100%; + height: 100%; + } + + .ant-tabs { + height: 100%; + + .ant-tabs-content { + height: 100%; + + .ant-tabs-tabpane { + + height : calc(100% - 45px); + overflow: auto; + } + } + } + + .properties-centent { + height : 100%; + overflow : hidden; + background: #fff; + + .properties-body { + overflow: auto; + height : 100%; + padding : 8px 16px; + } + + + .ant-form-item { + margin-bottom: 0; + padding : 6px 0; + border-bottom: 1px solid @border-color; + + .ant-form-item-label { + line-height: 2; + } + } + } + + .hint-box { + margin-top: 120px; + } + } + } + + // 中间内容区域 + section { + flex : 1; + max-width : calc(100% - @left-right-width - @left-right-width); + user-select: none; + margin : 0 8px 0; + box-shadow : 0px 0px 1px 1px @border-color; + + + + // 内容操作区域 + .form-panel { + // height : calc(100% - 50px); + height : 100%; + background : #eee; + // border : 1px solid #ccc; + position : relative; + + &.no-toolbars-top { + height: calc(100% - 50px); + } + + >.hint-text { + position : absolute; + left : 0; + top : 50%; + width : 100%; + transform: translateY(-50%); + font-size : 20px; + color : #aaa; + z-index : 16; + } + + .a-form-box { + height : 100%; + // box-shadow: 0px 1px 5px 1px #ccc; + } + + .draggable-box { + height : 100%; + overflow: auto; + + .list-main { + min-height : 100%; + padding : 5px; + position : relative; + background : #fafafa; + // border : 1px #ccc dashed; + + .moving { + // 拖放移动中 + // outline-width: 0; + min-height : 35px; + box-sizing : border-box; + overflow : hidden; + padding : 0 !important; + // margin : 3px 0; + position : relative; + + &::before { + content : ''; + height : 5px; + width : 100%; + background: @primary-color; + position : absolute; + top : 0; + right : 0; + } + } + + .drag-move-box { + position : relative; + box-sizing: border-box; + padding : 8px; + overflow : hidden; + transition: all .3s; + min-height: 36px; + + &:hover { + background: @primary-hover-bg-color; + } + + // 选择时 start + &::before { + content : ''; + height : 5px; + width : 100%; + background: @primary-color; + position : absolute; + top : 0; + right : -100%; + transition: all .3s; + } + + &.active { + &::before { + right: 0; + } + + background : @primary-hover-bg-color; + outline-offset: 0; + } + + // 选择时 end + .form-item-box { + position : relative; + box-sizing: border-box; + word-wrap : break-word; + + &::before { + content : ""; + position: absolute; + width : 100%; + height : 100%; + top : 0; + left : 0; + z-index : 888; + } + + .ant-form-item { + // 修改ant form-item的margin为padding + margin : 0; + padding-bottom: 6px; + } + } + + .show-key-box { + // 显示key + position : absolute; + bottom : 2px; + right : 5px; + font-size: 14px; + z-index : 999; + color : @primary-color; + } + + >.copy, + >.delete { + position : absolute; + top : 0; + width : 30px; + height : 30px; + line-height: 30px; + text-align : center; + color : #fff; + z-index : 989; + transition : all .3s; + + &.unactivated { + opacity : 0 !important; + pointer-events: none; + } + + &.active { + opacity: 1 !important; + } + } + + >.copy { + border-radius: 0 0 0 8px; + right : 30px; + background : @primary-color; + } + + >.delete { + right : 0px; + background: @primary-color; + } + + } + + // 动态表格设计面板样式 + .batch-box, + .select-input-list-box { + >.batch-label { + font-size : 16px; + font-weight: 500; + padding : 10px 10px; + + } + + + .draggable-box { + min-height: 60px; + width : 100%; + border : 1px #ccc dashed; + background: #fff; + + .list-main { + min-height : 60px; + position : relative; + border : 1px #ccc dashed; + overflow-x : auto; + overflow-y : auto; + white-space: nowrap; + + .moving { + // 拖放移动中 + width : 175px; + min-height: 94px; + display : inline-block; + } + + >div { + min-width : 185px; + display : inline-block; + vertical-align: top; + + .ant-form-item>.ant-form-item-label, + .ant-form-item>.ant-form-item-control-wrapper { + text-align: left; + display : block; + } + + .ant-col { + width: 100%; + } + + } + } + } + + } + + .select-input-list-box { + .column-box { + display: flex; + width : 100%; + + .check-box { + width: 80px; + } + + .draggable-box { + flex: 1; + } + } + + // 隐藏选择输入列的所有组件的label + .draggable-box { + .ant-form-item-label { + display: none !important; + } + } + } + + .batch-box, + .select-input-list-box, + .grid-box, + .table-box { + position : relative; + box-sizing: border-box; + padding : 5px; + background: @layout-background-color; + width : 100%; + transition: all .3s; + overflow : hidden; + + .form-item-box { + position : relative; + box-sizing: border-box; + + .ant-form-item { + // 修改ant form-item的margin为padding + margin : 0; + padding-bottom: 15px; + } + } + + .grid-row, + .table-layout { + background: @layout-background-color; + + + .grid-col, + .table-td { + .draggable-box { + min-height: 60px; + min-width : 50px; + border : 1px #ccc dashed; + background: #fff; + + .list-main { + min-height: 60px; + position : relative; + border : 1px #ccc dashed; + } + } + } + } + + // 选择时 start + &::before { + content : ''; + height : 5px; + width : 100%; + background: transparent; + position : absolute; + top : 0; + right : -100%; + transition: all .3s; + } + + &.active { + &::before { + background: @layout-color; + right : 0; + } + + background : @layout-hover-bg-color; + outline-offset: 0; + } + + >.copy, + >.delete { + position : absolute; + top : 0px; + width : 30px; + height : 30px; + line-height: 30px; + text-align : center; + color : #fff; + z-index : 989; + transition : all .3s; + + &.unactivated { + opacity : 0 !important; + pointer-events: none; + } + + &.active { + opacity: 1 !important; + } + } + + >.copy { + border-radius: 0 0 0 8px; + right : 30px; + background : @layout-color; + } + + >.delete { + right : 0px; + background: @layout-color; + } + } + } + } + } + } + } + + // 表格右键菜单样式 + .right-menu { + width : 160px; + background: #fff; + border : 1px solid #ccc; + position : fixed; + transition: all 0s; + box-shadow: 3px 3px 8px #999; + border-radius: 3px; + padding : 8px 0; + z-index : 2199; + + ul { + padding : 0; + margin : 0; + list-style: none; + + li { + cursor : pointer; + user-select: none; + padding : 0 15px; + height : 30px; + line-height: 30px; + font-size : 14px; + i{ + margin-right: 4px; + } + &:hover { + background: #eee; + } + } + } + } + + // 控件属性复选组件样式 + .kk-checkbox { + .ant-checkbox-wrapper { + margin-left : 0 !important; + margin-right: 8px; + } + } + + // 列表动画 + .list-enter-active { + transition: all .5s; + } + + .list-leave-active { + transition: all .3s; + } + + .list-enter, + .list-leave-to + + /* .list-leave-active for below version 2.1.8 */ + { + opacity : 0; + transform: translateX(-100px); + } + + .list-enter { + height: 30px; + } + + ::-webkit-scrollbar { + /*滚动条整体样式*/ + width : 6px; + /*高宽分别对应横竖滚动条的尺寸*/ + height : 6px; + scrollbar-arrow-color: red; + + } + + ::-webkit-scrollbar-thumb { + /*滚动条里面小方块*/ + border-radius : 5px; + box-shadow : inset 0 0 5px rgba(0, 0, 0, 0.2); + background : rgba(0, 0, 0, 0.2); + scrollbar-arrow-color: red; + } + + ::-webkit-scrollbar-track { + /*滚动条里面轨道*/ + box-shadow : inset 0 0 5px rgba(0, 0, 0, 0.2); + border-radius: 0; + background : rgba(0, 0, 0, 0.1); + } + + // 行内组件宽度默认175px + .ant-form-inline { + .list-main { + display : flex; + flex-wrap : wrap; + justify-content: flex-start; + align-content : flex-start; + + .layout-width { + width: 100%; + } + } + + .ant-form-item-control-wrapper { + width: 175px !important; + } + } +} + + + +// code盒子样式 +.json-box-9136076486841527 { + height : 570px; + overflow: auto; + + .vue-codemirror-wrap { + height: 100%; + + .CodeMirror-wrap { + height : 100%; + background: #f6f6f6; + + .CodeMirror-scroll { + height: 100%; + width : 100%; + } + + pre.CodeMirror-line, + .CodeMirror-linenumber { + min-height : 21px; + line-height: 21px; + } + } + } +} + +// code-modal盒子样式 +.code-modal-9136076486841527 { + .ant-modal-body { + padding: 12px; + } +} + +// modal复制按钮样式 +.copy-btn-box-9136076486841527 { + padding-top: 8px; + text-align : center; + + .copy-btn { + margin-right: 8px; + } +} + +// k-form-build +.k-form-build-9136076486841527 { + + .select-input-list-box { + color : rgba(0, 0, 0, 0.65); + font-size: 14px; + + .ant-form-item { + margin-bottom: 2px; + margin-right : 8px + } + + &.ant-form-horizontal { + .ant-col.ant-form-item-control-wrapper { + height : 30px; + display : flex; + align-items: center; + } + + .text-box { + height : 30px; + line-height: 30px; + } + } + + } + + .ant-form-item { + margin-bottom: 16px; + } + + // 防止报错信息占位 + .ant-form-item-control { + position: relative; + + .ant-form-explain { + bottom : -16px; + position: absolute; + z-index : 10; + } + } + + &.ant-form-inline { + .ant-form-item-control-wrapper { + width: 175px !important; + } + } + + // 动态表格样式 + .batch-table { + .ant-form-item { + margin: 0; + } + + .ant-form-item-control-wrapper { + width: 170px !important; + } + + .ant-table-thead>tr>th { + + padding: 12px; + } + + .ant-table-tbody>tr>td { + padding: 8px; + } + + .ant-form-inline .ant-form-item-with-help { + margin: 0; + } + + .ant-table-placeholder { + padding: 0; + } + } + + // 拖拽上传控件隐藏 + .hide-upload-drag { + .ant-upload.ant-upload-drag { + display: none; + } + } + +} + +//颜色选择器覆盖 +.m-colorPicker { + width:25%; + vertical-align:bottom; + padding: 5px; + border: 1px solid #e6e6e6; + border-radius: 4px; + font-size: 0; + .colorBtn { + height: 22px !important; + width: 100% !important; + } +} + +// .k-form-build-9136076486841527 { + +// } + + +// footer样式 +// .footer-9136076486841527 { +// width : 100%; +// height : 30px; +// line-height: 30px; +// padding : 0 15px; +// text-align : right; +// background : #fafafa; +// color : @primary-color; +// font-size : 14px; +// font-weight: bold; +// border-top : 1px solid #e0e0e0; + +// >a { +// color : @primary-color; +// text-decoration: none; +// } +// } + + // 中间内容区域 + section { + // flex : 1; + // max-width : calc(100% - @left-right-width - @left-right-width); + // user-select: none; + // margin : 0 8px 0; + // box-shadow : 0px 0px 1px 1px @border-color; + + + + // 内容操作区域 + .form-panel { + // height : calc(100% - 50px); + height : 100%; + background : #eee; + // border : 1px solid #ccc; + position : relative; + + &.no-toolbars-top { + height: calc(100% - 50px); + } + + >.hint-text { + position : absolute; + left : 0; + top : 50%; + width : 100%; + transform: translateY(-50%); + font-size : 20px; + color : #aaa; + z-index : 16; + } + + .a-form-box { + height : 100%; + // box-shadow: 0px 1px 5px 1px #ccc; + } + + .draggable-box { + height : 100%; + overflow: auto; + + .list-main { + min-height : 100%; + padding : 5px; + position : relative; + background : #fafafa; + // border : 1px #ccc dashed; + + .moving { + // 拖放移动中 + // outline-width: 0; + min-height : 35px; + box-sizing : border-box; + overflow : hidden; + padding : 0 !important; + // margin : 3px 0; + position : relative; + + &::before { + content : ''; + height : 5px; + width : 100%; + background: @primary-color; + position : absolute; + top : 0; + right : 0; + } + } + + .drag-move-box { + position : relative; + box-sizing: border-box; + padding : 8px; + overflow : hidden; + transition: all .3s; + min-height: 36px; + + &:hover { + background: @primary-hover-bg-color; + } + + // 选择时 start + &::before { + content : ''; + height : 5px; + width : 100%; + background: @primary-color; + position : absolute; + top : 0; + right : -100%; + transition: all .3s; + } + + &.active { + &::before { + right: 0; + } + + background : @primary-hover-bg-color; + outline-offset: 0; + } + + // 选择时 end + .form-item-box { + position : relative; + box-sizing: border-box; + word-wrap : break-word; + + &::before { + content : ""; + position: absolute; + width : 100%; + height : 100%; + top : 0; + left : 0; + z-index : 888; + } + + .ant-form-item { + // 修改ant form-item的margin为padding + margin : 0; + padding-bottom: 6px; + } + } + + .show-key-box { + // 显示key + position : absolute; + bottom : 2px; + right : 5px; + font-size: 14px; + z-index : 999; + color : @primary-color; + } + + >.copy, + >.delete { + position : absolute; + top : 0; + width : 30px; + height : 30px; + line-height: 30px; + text-align : center; + color : #fff; + z-index : 989; + transition : all .3s; + + &.unactivated { + opacity : 0 !important; + pointer-events: none; + } + + &.active { + opacity: 1 !important; + } + } + + >.copy { + border-radius: 0 0 0 8px; + right : 30px; + background : @primary-color; + } + + >.delete { + right : 0px; + background: @primary-color; + } + + } + + // 动态表格设计面板样式 + .batch-box, + .select-input-list-box { + >.batch-label { + font-size : 16px; + font-weight: 500; + padding : 10px 10px; + + } + + + .draggable-box { + min-height: 60px; + width : 100%; + border : 1px #ccc dashed; + background: #fff; + + .list-main { + min-height : 60px; + position : relative; + border : 1px #ccc dashed; + overflow-x : auto; + overflow-y : auto; + white-space: nowrap; + + .moving { + // 拖放移动中 + width : 175px; + min-height: 94px; + display : inline-block; + } + + >div { + min-width : 185px; + display : inline-block; + vertical-align: top; + + .ant-form-item>.ant-form-item-label, + .ant-form-item>.ant-form-item-control-wrapper { + text-align: left; + display : block; + } + + .ant-col { + width: 100%; + } + + } + } + } + + } + + .select-input-list-box { + .column-box { + display: flex; + width : 100%; + + .check-box { + width: 80px; + } + + .draggable-box { + flex: 1; + } + } + + // 隐藏选择输入列的所有组件的label + .draggable-box { + .ant-form-item-label { + display: none !important; + } + } + } + + .batch-box, + .select-input-list-box, + .grid-box, + .table-box { + position : relative; + box-sizing: border-box; + padding : 5px; + background: @layout-background-color; + width : 100%; + transition: all .3s; + overflow : hidden; + + .form-item-box { + position : relative; + box-sizing: border-box; + + .ant-form-item { + // 修改ant form-item的margin为padding + margin : 0; + padding-bottom: 15px; + } + } + + .grid-row, + .table-layout { + background: @layout-background-color; + + + .grid-col, + .table-td { + .draggable-box { + min-height: 60px; + min-width : 50px; + border : 1px #ccc dashed; + background: #fff; + + .list-main { + min-height: 60px; + position : relative; + border : 1px #ccc dashed; + } + } + } + } + + // 选择时 start + &::before { + content : ''; + height : 5px; + width : 100%; + background: transparent; + position : absolute; + top : 0; + right : -100%; + transition: all .3s; + } + + &.active { + &::before { + background: @layout-color; + right : 0; + } + + background : @layout-hover-bg-color; + outline-offset: 0; + } + + >.copy, + >.delete { + position : absolute; + top : 0px; + width : 30px; + height : 30px; + line-height: 30px; + text-align : center; + color : #fff; + z-index : 989; + transition : all .3s; + + &.unactivated { + opacity : 0 !important; + pointer-events: none; + } + + &.active { + opacity: 1 !important; + } + } + + >.copy { + border-radius: 0 0 0 8px; + right : 30px; + background : @layout-color; + } + + >.delete { + right : 0px; + background: @layout-color; + } + } + } + } + } + } \ No newline at end of file diff --git a/front-end/h5/src/components/core/editor/canvas/styles/k-editor.less b/front-end/h5/src/components/core/editor/canvas/styles/k-editor.less new file mode 100644 index 00000000..4fc92cfa --- /dev/null +++ b/front-end/h5/src/components/core/editor/canvas/styles/k-editor.less @@ -0,0 +1,83 @@ +/* + * @Description: 用于汉化编辑器 + * @Author: kcz + * @Date: 2020-03-30 14:00:29 + * @LastEditors: kcz + * @LastEditTime: 2020-03-30 14:04:41 + */ + + .form-designer-container-9136076486841527,.k-form-build-9136076486841527{ + .chinesization{ + .ql-snow .ql-tooltip[data-mode="link"]::before { + content: "请输入链接地址:"; + } + .ql-snow .ql-tooltip.ql-editing a.ql-action::after { + border-right: 0px; + content: "保存"; + padding-right: 0px; + } + + .ql-snow .ql-tooltip[data-mode="video"]::before { + content: "请输入视频地址:"; + } + + .ql-snow .ql-picker.ql-size .ql-picker-label::before, + .ql-snow .ql-picker.ql-size .ql-picker-item::before { + content: "14px"; + } + .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before, + .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before { + content: "10px"; + } + .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before, + .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before { + content: "18px"; + } + .ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before, + .ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before { + content: "32px"; + } + + .ql-snow .ql-picker.ql-header .ql-picker-label::before, + .ql-snow .ql-picker.ql-header .ql-picker-item::before { + content: "文本"; + } + .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, + .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { + content: "标题1"; + } + .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, + .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { + content: "标题2"; + } + .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, + .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { + content: "标题3"; + } + .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, + .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { + content: "标题4"; + } + .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, + .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { + content: "标题5"; + } + .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, + .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { + content: "标题6"; + } + + .ql-snow .ql-picker.ql-font .ql-picker-label::before, + .ql-snow .ql-picker.ql-font .ql-picker-item::before { + content: "标准字体"; + } + .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before, + .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before { + content: "衬线字体"; + } + .ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before, + .ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before { + content: "等宽字体"; + } + } + } \ No newline at end of file diff --git a/front-end/h5/src/components/core/editor/canvas/styles/k-form-design.less b/front-end/h5/src/components/core/editor/canvas/styles/k-form-design.less new file mode 100644 index 00000000..5ed7711e --- /dev/null +++ b/front-end/h5/src/components/core/editor/canvas/styles/k-form-design.less @@ -0,0 +1,4 @@ +// 允许用户引入less,定义主题 +// @import "../lib/k-form-design.css"; +@import "./k-table.less"; +@import "./form-design.less"; diff --git a/front-end/h5/src/components/core/editor/canvas/styles/k-table.less b/front-end/h5/src/components/core/editor/canvas/styles/k-table.less new file mode 100644 index 00000000..3d8e7ddb --- /dev/null +++ b/front-end/h5/src/components/core/editor/canvas/styles/k-table.less @@ -0,0 +1,46 @@ +// 表单设计器-表格样式 +.kk-table-9136076486841527 { + width: 100%; + box-sizing: border-box; + transition: all 0.3s; + border-collapse: collapse; + + tr { + transition: all 0.3s; + border-collapse: collapse; + td { + box-sizing: border-box; + transition: all 0.3s; + padding: 12px 12px; + border-collapse: collapse; + vertical-align:top; + } + } + &.bordered { + // 添加边框 + tr { + td { + border: 1px solid #e8e8e8 !important; + } + } + } + &.bright { + // 点亮行 + tr { + &:hover > td { + background: #e6f7ff; + } + } + } + &.small { + // 紧凑型 + tr { + td { + padding: 8px 8px; + } + } + } + .ant-row.ant-form-item{ + margin: 0 !important; + } +} diff --git a/front-end/h5/src/components/core/editor/data-source/data-source.js b/front-end/h5/src/components/core/editor/data-source/data-source.js index 95d3cf8d..f3205a78 100644 --- a/front-end/h5/src/components/core/editor/data-source/data-source.js +++ b/front-end/h5/src/components/core/editor/data-source/data-source.js @@ -109,7 +109,7 @@ export default { description="使用 {{DC.[keyPath]}} 消费数据。比如输入框内容为 下载了{{DC.count}}次 => 下载了count次" type="info" /> - + @@ -131,17 +131,17 @@ export default { this.toggleAddDialog() switch (actionType) { case 'edit': - this.activeDataSource = {...ds} + this.activeDataSource = { ...ds } this.dataSourceManager({ type: actionType, - value: {...ds } + value: { ...ds } }) break case 'delete': case 'add': this.dataSourceManager({ type: actionType, - value: {...ds } + value: { ...ds } }) break } diff --git a/front-end/h5/src/components/core/editor/data-source/variable-pool.vue b/front-end/h5/src/components/core/editor/data-source/variable-pool.vue index 4f13a8ba..7fb8713f 100644 --- a/front-end/h5/src/components/core/editor/data-source/variable-pool.vue +++ b/front-end/h5/src/components/core/editor/data-source/variable-pool.vue @@ -9,7 +9,7 @@ -