2.1.9推送:主要修复一些bug,表单设计器支持传入预定义CSS代码。

master
vdpAdmin 2021-12-09 14:58:57 +08:00
parent f7535ddf64
commit 5497382aea
24 changed files with 274 additions and 144 deletions

View File

@ -17,14 +17,19 @@
### 功能一览 ### 功能一览
``` ```
> 拖拽式表单设计; > 拖拽式可视化表单设计;
> 支持PC、H5两种布局; > 支持PC、Pad、H5三种布局;
> 支持运行时动态加载表单; > 支持运行时动态加载表单;
> 支持表单复杂交互控制; > 支持表单复杂交互控制;
> 支持自定义CSS样式 > 支持自定义CSS样式
> 支持历史撤销、重做功能; > 支持自定义校验逻辑;
> 支持国际化多语言;
> 兼容IE 11浏览器
> 可导出Vue组件、HTML源码 > 可导出Vue组件、HTML源码
> 可导出Vue的SFC单文件组件 > 可导出Vue的SFC单文件组件
> 支持开发自定义组件;
> 支持响应式自适应布局;
> 支持VS Code插件
> 更多功能等你探究... > 更多功能等你探究...
``` ```
@ -158,17 +163,17 @@ body {
### 资源链接 ### 资源链接
<hr> <hr>
文档官网:<a href="http://www.vform666.com/" target="_blank">http://www.vform666.com/</a> 文档官网:<a href="https://www.vform666.com/" target="_blank">https://www.vform666.com/</a>
在线演示:<a href="http://demo.vform666.com/" target="_blank">http://demo.vform666.com/</a> 在线演示:<a href="https://www.vform666.com/demo/" target="_blank">https://www.vform666.com/demo/</a>
VS Code插件<a href="http://www.vform666.com/pages/plugin/" target="_blank">http://www.vform666.com/pages/plugin/</a> VS Code插件<a href="https://www.vform666.com/pages/plugin/" target="_blank">https://www.vform666.com/pages/plugin/</a>
Github仓库<a href="https://github.com/vform666/variant-form" target="_blank">https://github.com/vform666/variant-form</a> Github仓库<a href="https://github.com/vform666/variant-form" target="_blank">https://github.com/vform666/variant-form</a>
Gitee备份仓库<a href="https://gitee.com/vdpadmin/variant-form" target="_blank">https://gitee.com/vdpadmin/variant-form</a> Gitee备份仓库<a href="https://gitee.com/vdpadmin/variant-form" target="_blank">https://gitee.com/vdpadmin/variant-form</a>
更新日志:<a href="http://www.vform666.com/pages/changelog/" target="_blank">http://www.vform666.com/pages/changelog/</a> 更新日志:<a href="https://www.vform666.com/pages/changelog/" target="_blank">https://www.vform666.com/pages/changelog/</a>
技术交流群微信搜索“vformAdmin”或者扫如下二维码加群 技术交流群微信搜索“vformAdmin”或者扫如下二维码加群

View File

@ -13,7 +13,7 @@
<!-- 禁止浏览器缓存index.html end --> <!-- 禁止浏览器缓存index.html end -->
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title> <title><%= htmlWebpackPlugin.options.title %></title>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.15.7/theme-chalk/index.min.css">
</head> </head>
<body> <body>
<noscript> <noscript>
@ -22,7 +22,7 @@
<div id="app"></div> <div id="app"></div>
<!-- built files will be auto injected --> <!-- built files will be auto injected -->
<script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.min.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script> <script src="https://cdn.staticfile.org/element-ui/2.15.7/index.min.js"></script>
</body> </body>
</html> </html>

View File

@ -1,6 +1,6 @@
{ {
"name": "variant-form", "name": "variant-form",
"version": "2.1.8", "version": "2.1.9",
"private": false, "private": false,
"scripts": { "scripts": {
"serve": "vue-cli-service serve --open src/main.js", "serve": "vue-cli-service serve --open src/main.js",

View File

@ -1,7 +1,7 @@
/** /**
* author: vformAdmin * author: vformAdmin
* email: vdpadmin@163.com * email: vdpadmin@163.com
* website: http://www.vform666.com * website: https://www.vform666.com
* date: 2021.08.18 * date: 2021.08.18
* remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息 * remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息
*/ */
@ -79,6 +79,12 @@ export function createDesigner(vueInstance) {
} }
}, },
loadPresetCssCode(preCssCode) {
if ((this.formConfig.cssCode === '') && !!preCssCode) {
this.formConfig.cssCode = preCssCode
}
},
getLayoutType() { getLayoutType() {
return this.formConfig.layoutType || 'PC' return this.formConfig.layoutType || 'PC'
}, },
@ -151,9 +157,13 @@ export function createDesigner(vueInstance) {
return true return true
}, },
insertTableRow(widget, insertPos, cloneRowIdx) { /**
let rowIdx = (insertPos === undefined) ? widget.rows.length : insertPos //确定插入列位置 * 追加表格新行
let newRow = (cloneRowIdx === undefined) ? deepClone(widget.rows[widget.rows.length - 1]) : deepClone( widget.rows[cloneRowIdx] ) * @param widget
*/
appendTableRow(widget) {
let rowIdx = widget.rows.length//确定插入行位置
let newRow = deepClone(widget.rows[widget.rows.length - 1])
newRow.id = 'table-row-' + generateId() newRow.id = 'table-row-' + generateId()
newRow.merged = false newRow.merged = false
newRow.cols.forEach(col => { newRow.cols.forEach(col => {
@ -162,37 +172,19 @@ export function createDesigner(vueInstance) {
col.merged = false col.merged = false
col.options.colspan = 1 col.options.colspan = 1
col.options.rowspan = 1 col.options.rowspan = 1
col.widgetList.length = 0
}) })
widget.rows.splice(rowIdx, 0, newRow) widget.rows.splice(rowIdx, 0, newRow)
let colNo = 0
while ((rowIdx < widget.rows.length - 1) && (colNo < widget.rows[0].cols.length)) { //越界判断
let rowMerged = widget.rows[rowIdx + 1].cols[colNo].merged //确定插入位置的单元格是否为合并单元格
if (!!rowMerged) {
let rowArray = widget.rows
let unMergedCell = {}
let startRowIndex = null
for (let i = rowIdx; i >= 0; i--) { //查找该行已合并的主单元格
if (!rowArray[i].cols[colNo].merged && (rowArray[i].cols[colNo].options.rowspan > 1)) {
startRowIndex = i
unMergedCell = rowArray[i].cols[colNo]
break
}
}
let newRowspan = unMergedCell.options.rowspan + 1
this.setPropsOfMergedRows(widget.rows, startRowIndex, colNo, unMergedCell.options.colspan, newRowspan)
colNo += unMergedCell.options.colspan
} else {
colNo += 1
}
}
this.emitHistoryChange() this.emitHistoryChange()
}, },
insertTableCol(widget, insertPos) { /**
let colIdx = (insertPos === undefined) ? widget.rows[0].cols.length : insertPos //确定插入列位置 * 追加表格新列
* @param widget
*/
appendTableCol(widget) {
let colIdx = widget.rows[0].cols.length //确定插入列位置
widget.rows.forEach(row => { widget.rows.forEach(row => {
let newCol = deepClone(this.getContainerByType('table-cell')) let newCol = deepClone(this.getContainerByType('table-cell'))
newCol.id = 'table-cell-' + generateId() newCol.id = 'table-cell-' + generateId()
@ -200,17 +192,118 @@ export function createDesigner(vueInstance) {
newCol.merged = false newCol.merged = false
newCol.options.colspan = 1 newCol.options.colspan = 1
newCol.options.rowspan = 1 newCol.options.rowspan = 1
newCol.widgetList.length = 0
row.cols.splice(colIdx, 0, newCol) row.cols.splice(colIdx, 0, newCol)
}) })
this.emitHistoryChange()
},
insertTableRow(widget, insertPos, cloneRowIdx, curCol, aboveFlag) {
let newRowIdx = !!aboveFlag ? insertPos : (insertPos + 1) //初步确定插入行位置
if (!aboveFlag) { //继续向下寻找同列第一个未被合并的单元格
let tmpRowIdx = newRowIdx
let rowFoundFlag = false
while (tmpRowIdx < widget.rows.length) {
if (!widget.rows[tmpRowIdx].cols[curCol].merged) {
newRowIdx = tmpRowIdx
rowFoundFlag = true
break
} else {
tmpRowIdx++
}
}
if (!rowFoundFlag) {
newRowIdx = widget.rows.length
}
}
let newRow = deepClone( widget.rows[cloneRowIdx] )
newRow.id = 'table-row-' + generateId()
newRow.merged = false
newRow.cols.forEach(col => {
col.id = 'table-cell-' + generateId()
col.options.name = col.id
col.merged = false
col.options.colspan = 1
col.options.rowspan = 1
col.widgetList.length = 0
})
widget.rows.splice(newRowIdx, 0, newRow)
let colNo = 0
while ((newRowIdx < widget.rows.length - 1) && (colNo < widget.rows[0].cols.length)) { //越界判断
const cellOfNextRow = widget.rows[newRowIdx + 1].cols[colNo]
const rowMerged = cellOfNextRow.merged //确定插入位置下一行的单元格是否为合并单元格
if (!!rowMerged) {
let rowArray = widget.rows
let unMergedCell = {}
let startRowIndex = null
for (let i = newRowIdx; i >= 0; i--) { //查找该行已合并的主单元格
if (!rowArray[i].cols[colNo].merged && (rowArray[i].cols[colNo].options.rowspan > 1)) {
startRowIndex = i
unMergedCell = rowArray[i].cols[colNo]
break
}
}
if (!!unMergedCell.options) { //如果有符合条件的unMergedCell
let newRowspan = unMergedCell.options.rowspan + 1
this.setPropsOfMergedRows(widget.rows, startRowIndex, colNo, unMergedCell.options.colspan, newRowspan)
colNo += unMergedCell.options.colspan
} else {
colNo += 1
}
} else {
//colNo += 1
colNo += cellOfNextRow.options.colspan || 1
}
}
this.emitHistoryChange()
},
insertTableCol(widget, insertPos, curRow, leftFlag) {
let newColIdx = !!leftFlag ? insertPos : (insertPos + 1) //初步确定插入列位置
if (!leftFlag) { //继续向右寻找同行第一个未被合并的单元格
let tmpColIdx = newColIdx
let colFoundFlag = false
while (tmpColIdx < widget.rows[curRow].cols.length) {
if (!widget.rows[curRow].cols[tmpColIdx].merged) {
newColIdx = tmpColIdx
colFoundFlag = true
break
} else {
tmpColIdx++
}
if (!colFoundFlag) {
newColIdx = widget.rows[curRow].cols.length
}
}
}
widget.rows.forEach(row => {
let newCol = deepClone(this.getContainerByType('table-cell'))
newCol.id = 'table-cell-' + generateId()
newCol.options.name = newCol.id
newCol.merged = false
newCol.options.colspan = 1
newCol.options.rowspan = 1
newCol.widgetList.length = 0
row.cols.splice(newColIdx, 0, newCol)
})
let rowNo = 0 let rowNo = 0
while((colIdx < widget.rows[0].cols.length - 1) && (rowNo < widget.rows.length)) { //越界判断 while((newColIdx < widget.rows[0].cols.length - 1) && (rowNo < widget.rows.length)) { //越界判断
let colMerged = widget.rows[rowNo].cols[colIdx + 1].merged //确定插入位置的单元格是否为合并单元格 const cellOfNextCol = widget.rows[rowNo].cols[newColIdx + 1]
const colMerged = cellOfNextCol.merged //确定插入位置右侧列的单元格是否为合并单元格
if (!!colMerged) { if (!!colMerged) {
let colArray = widget.rows[rowNo].cols let colArray = widget.rows[rowNo].cols
let unMergedCell = {} let unMergedCell = {}
let startColIndex = null let startColIndex = null
for (let i = colIdx; i >= 0; i--) { //查找该行已合并的主单元格 for (let i = newColIdx; i >= 0; i--) { //查找该行已合并的主单元格
if (!colArray[i].merged && (colArray[i].options.colspan > 1)) { if (!colArray[i].merged && (colArray[i].options.colspan > 1)) {
startColIndex = i startColIndex = i
unMergedCell = colArray[i] unMergedCell = colArray[i]
@ -218,11 +311,16 @@ export function createDesigner(vueInstance) {
} }
} }
let newColspan = unMergedCell.options.colspan + 1 if (!!unMergedCell.options) { //如果有符合条件的unMergedCell
this.setPropsOfMergedCols(widget.rows, rowNo, startColIndex, newColspan, unMergedCell.options.rowspan) let newColspan = unMergedCell.options.colspan + 1
rowNo += unMergedCell.options.rowspan this.setPropsOfMergedCols(widget.rows, rowNo, startColIndex, newColspan, unMergedCell.options.rowspan)
rowNo += unMergedCell.options.rowspan
} else {
rowNo += 1
}
} else { } else {
rowNo += 1 //rowNo += 1
rowNo += cellOfNextCol.options.rowspan || 1
} }
} }
@ -262,12 +360,8 @@ export function createDesigner(vueInstance) {
setPropsOfSplitCol(rowArray, startRowIndex, startColIndex, colspan, rowspan) { setPropsOfSplitCol(rowArray, startRowIndex, startColIndex, colspan, rowspan) {
for (let i = startRowIndex; i < startRowIndex + rowspan; i++) { for (let i = startRowIndex; i < startRowIndex + rowspan; i++) {
for (let j = startColIndex; j < startColIndex + colspan; j++) { for (let j = startColIndex; j < startColIndex + colspan; j++) {
if ((i === startRowIndex) && (j === startColIndex)) {
rowArray[i].cols[j].options.colspan = 1
continue
}
rowArray[i].cols[j].merged = false; rowArray[i].cols[j].merged = false;
rowArray[i].cols[j].options.rowspan = 1
rowArray[i].cols[j].options.colspan = 1 rowArray[i].cols[j].options.colspan = 1
} }
} }
@ -276,20 +370,30 @@ export function createDesigner(vueInstance) {
setPropsOfSplitRow(rowArray, startRowIndex, startColIndex, colspan, rowspan) { setPropsOfSplitRow(rowArray, startRowIndex, startColIndex, colspan, rowspan) {
for (let i = startRowIndex; i < startRowIndex + rowspan; i++) { for (let i = startRowIndex; i < startRowIndex + rowspan; i++) {
for (let j = startColIndex; j < startColIndex + colspan; j++) { for (let j = startColIndex; j < startColIndex + colspan; j++) {
if ((i === startRowIndex) && (j === startColIndex)) {
rowArray[i].cols[j].options.rowspan = 1 //合并后的主单元格
continue
}
rowArray[i].cols[j].merged = false; rowArray[i].cols[j].merged = false;
rowArray[i].cols[j].options.rowspan = 1 rowArray[i].cols[j].options.rowspan = 1
rowArray[i].cols[j].options.colspan = 1
} }
} }
}, },
mergeTableCol(rowArray, colArray, curRow, curCol, leftFlag, cellWidget) { mergeTableCol(rowArray, colArray, curRow, curCol, leftFlag, cellWidget) {
let mergedColIdx = !!leftFlag ? curCol : curCol + colArray[curCol].options.colspan let mergedColIdx = !!leftFlag ? curCol : curCol + colArray[curCol].options.colspan
let remainedColIdx = !!leftFlag ? curCol - colArray[curCol - 1].options.colspan : curCol
// let remainedColIdx = !!leftFlag ? curCol - colArray[curCol - 1].options.colspan : curCol
let remainedColIdx = !!leftFlag ? curCol - 1 : curCol
if (!!leftFlag) { //继续向左寻找同行未被合并的第一个单元格
let tmpColIdx = remainedColIdx
while (tmpColIdx >= 0) {
if (!rowArray[curRow].cols[tmpColIdx].merged) {
remainedColIdx = tmpColIdx
break;
} else {
tmpColIdx--
}
}
}
if (!!colArray[mergedColIdx].widgetList && (colArray[mergedColIdx].widgetList.length > 0)) { //保留widgetList if (!!colArray[mergedColIdx].widgetList && (colArray[mergedColIdx].widgetList.length > 0)) { //保留widgetList
if (!colArray[remainedColIdx].widgetList || (colArray[remainedColIdx].widgetList.length === 0)) { if (!colArray[remainedColIdx].widgetList || (colArray[remainedColIdx].widgetList.length === 0)) {
colArray[remainedColIdx].widgetList = deepClone(colArray[mergedColIdx].widgetList) colArray[remainedColIdx].widgetList = deepClone(colArray[mergedColIdx].widgetList)
@ -334,7 +438,21 @@ export function createDesigner(vueInstance) {
mergeTableRow(rowArray, curRow, curCol, aboveFlag, cellWidget) { mergeTableRow(rowArray, curRow, curCol, aboveFlag, cellWidget) {
let mergedRowIdx = !!aboveFlag ? curRow : curRow + cellWidget.options.rowspan let mergedRowIdx = !!aboveFlag ? curRow : curRow + cellWidget.options.rowspan
let remainedRowIdx = !!aboveFlag ? curRow - cellWidget.options.rowspan : curRow
//let remainedRowIdx = !!aboveFlag ? curRow - cellWidget.options.rowspan : curRow
let remainedRowIdx = !!aboveFlag ? curRow - 1 : curRow
if (!!aboveFlag) { //继续向上寻找同列未被合并的第一个单元格
let tmpRowIdx = remainedRowIdx
while (tmpRowIdx >= 0) {
if (!rowArray[tmpRowIdx].cols[curCol].merged) {
remainedRowIdx = tmpRowIdx
break;
} else {
tmpRowIdx--
}
}
}
if (!!rowArray[mergedRowIdx].cols[curCol].widgetList && (rowArray[mergedRowIdx].cols[curCol].widgetList.length > 0)) { //保留widgetList if (!!rowArray[mergedRowIdx].cols[curCol].widgetList && (rowArray[mergedRowIdx].cols[curCol].widgetList.length > 0)) { //保留widgetList
if (!rowArray[remainedRowIdx].cols[curCol].widgetList || (rowArray[remainedRowIdx].cols[curCol].widgetList.length === 0)) { if (!rowArray[remainedRowIdx].cols[curCol].widgetList || (rowArray[remainedRowIdx].cols[curCol].widgetList.length === 0)) {
rowArray[remainedRowIdx].cols[curCol].widgetList = deepClone(rowArray[mergedRowIdx].cols[curCol].widgetList) rowArray[remainedRowIdx].cols[curCol].widgetList = deepClone(rowArray[mergedRowIdx].cols[curCol].widgetList)
@ -396,8 +514,15 @@ export function createDesigner(vueInstance) {
}, },
deleteTableWholeCol(rowArray, colIndex) { //需考虑删除的是合并列!! deleteTableWholeCol(rowArray, colIndex) { //需考虑删除的是合并列!!
let onlyOneColFlag = true
rowArray.forEach(ri => {
if (ri.cols[0].options.colspan !== rowArray[0].cols.length) {
onlyOneColFlag = false
}
})
//仅剩一列则不可删除!! //仅剩一列则不可删除!!
if (rowArray[0].cols[0].options.colspan === rowArray[0].cols.length) { if (onlyOneColFlag) {
this.vueInstance.$message.info(this.vueInstance.i18nt('designer.hint.lastColCannotBeDeleted'))
return return
} }
@ -423,8 +548,15 @@ export function createDesigner(vueInstance) {
}, },
deleteTableWholeRow(rowArray, rowIndex) { //需考虑删除的是合并行!! deleteTableWholeRow(rowArray, rowIndex) { //需考虑删除的是合并行!!
let onlyOneRowFlag = true
rowArray[0].cols.forEach(ci => {
if (ci.options.rowspan !== rowArray.length) {
onlyOneRowFlag = false
}
})
//仅剩一行则不可删除!! //仅剩一行则不可删除!!
if (rowArray[0].cols[0].options.rowspan === rowArray.length) { if (onlyOneRowFlag) {
this.vueInstance.$message.info(this.vueInstance.i18nt('designer.hint.lastRowCannotBeDeleted'))
return return
} }
@ -635,7 +767,7 @@ export function createDesigner(vueInstance) {
} }
this.setSelected(newWidget) this.setSelected(newWidget)
this.designer.emitHistoryChange() this.emitHistoryChange()
}, },
deleteColOfGrid(gridWidget, colIdx) { deleteColOfGrid(gridWidget, colIdx) {

View File

@ -2,7 +2,7 @@
/** /**
* author: vformAdmin * author: vformAdmin
* email: vdpadmin@163.com * email: vdpadmin@163.com
* website: http://www.vform666.com * website: https://www.vform666.com
* date: 2021.08.18 * date: 2021.08.18
* remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息 * remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息
*/ */

View File

@ -1,15 +1,11 @@
export default { export default {
methods: { methods: {
insertTableRow(widget) { appendTableRow(widget) {
this.designer.insertTableRow(widget) this.designer.appendTableRow(widget)
this.designer.emitHistoryChange()
}, },
insertTableCol(widget) { appendTableCol(widget) {
this.designer.insertTableCol(widget) this.designer.appendTableCol(widget)
this.designer.emitHistoryChange()
}, },
onContainerDragAdd(evt, subList) { onContainerDragAdd(evt, subList) {

View File

@ -2,7 +2,7 @@
/** /**
* author: vformAdmin * author: vformAdmin
* email: vdpadmin@163.com * email: vdpadmin@163.com
* website: http://www.vform666.com * website: https://www.vform666.com
* date: 2021.08.18 * date: 2021.08.18
* remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息 * remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息
*/ */

View File

@ -2,7 +2,7 @@
/** /**
* author: vformAdmin * author: vformAdmin
* email: vdpadmin@163.com * email: vdpadmin@163.com
* website: http://www.vform666.com * website: https://www.vform666.com
* date: 2021.08.18 * date: 2021.08.18
* remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息 * remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息
*/ */

View File

@ -129,7 +129,7 @@
deleteWholeColDisabled() { deleteWholeColDisabled() {
//return this.colLength === 1 //return this.colLength === 1
return (this.rowLength === 1) || (this.widget.options.colspan === this.colLength) return (this.colLength === 1) || (this.widget.options.colspan === this.colLength)
}, },
deleteWholeRowDisabled() { deleteWholeRowDisabled() {
@ -207,19 +207,19 @@
}, },
insertLeftCol() { insertLeftCol() {
this.designer.insertTableCol(this.parentWidget, this.colIndex) this.designer.insertTableCol(this.parentWidget, this.colIndex, this.rowIndex, true)
}, },
insertRightCol() { insertRightCol() {
this.designer.insertTableCol(this.parentWidget, this.colIndex + 1) this.designer.insertTableCol(this.parentWidget, this.colIndex, this.rowIndex, false)
}, },
insertAboveRow() { insertAboveRow() {
this.designer.insertTableRow(this.parentWidget, this.rowIndex, this.rowIndex) this.designer.insertTableRow(this.parentWidget, this.rowIndex, this.rowIndex, this.colIndex, true)
}, },
insertBelowRow() { insertBelowRow() {
this.designer.insertTableRow(this.parentWidget, this.rowIndex + 1, this.rowIndex) this.designer.insertTableRow(this.parentWidget, this.rowIndex, this.rowIndex, this.colIndex, false)
}, },
mergeLeftCol() { mergeLeftCol() {
@ -285,13 +285,15 @@
.form-widget-list { .form-widget-list {
border: 1px dashed #336699; border: 1px dashed #336699;
margin: 3px; margin: 3px;
//min-height: 36px;
position: absolute; //min-height: 36px;
top: 0; height: 100%;
right: 0;
bottom: 0; /*position: absolute;*/
left: 0; /*top: 0;*/
/*right: 0;*/
/*bottom: 0;*/
/*left: 0;*/
} }
.table-cell-action{ .table-cell-action{

View File

@ -2,7 +2,7 @@
/** /**
* author: vformAdmin * author: vformAdmin
* email: vdpadmin@163.com * email: vdpadmin@163.com
* website: http://www.vform666.com * website: https://www.vform666.com
* date: 2021.08.18 * date: 2021.08.18
* remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息 * remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息
*/ */

View File

@ -179,7 +179,8 @@ export default {
if (!!this.field.options.required) { if (!!this.field.options.required) {
this.rules.push({ this.rules.push({
required: true, required: true,
trigger: ['blur', 'change'], //trigger: ['blur', 'change'],
trigger: ['blur'], /* 去掉change事件触发校验change事件触发时formModel数据尚未更新导致radio/checkbox必填校验出错 */
message: this.i18nt('render.hint.fieldRequired'), message: this.i18nt('render.hint.fieldRequired'),
}) })
} }

View File

@ -2,6 +2,7 @@
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState" <form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList" :parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId"> :sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
<!-- el-upload增加:name="field.options.name"会导致又拍云上传失败故删除之 -->
<el-upload ref="fieldEditor" :disabled="field.options.disabled" <el-upload ref="fieldEditor" :disabled="field.options.disabled"
:style="styleVariables" class="dynamicPseudoAfter" :style="styleVariables" class="dynamicPseudoAfter"
:action="field.options.uploadURL" :headers="uploadHeaders" :data="uploadData" :action="field.options.uploadURL" :headers="uploadHeaders" :data="uploadData"
@ -116,15 +117,14 @@
}, },
methods: { methods: {
handleFileExceed() { handleFileExceed() {
//let uploadLimit = this.field.options.limit let uploadLimit = this.field.options.limit /* 此行不能注释下一行ES6模板字符串需要用到 */
this.$message.warning(eval('`' + this.i18nt('render.hint.uploadExceed') + '`')); this.$message.warning(eval('`' + this.i18nt('render.hint.uploadExceed') + '`'));
}, },
updateUploadFieldModelAndEmitDataChange() { updateUploadFieldModelAndEmitDataChange(fileList) {
let oldValue = deepClone(this.fieldModel) let oldValue = deepClone(this.fieldModel)
this.fieldModel = deepClone(this.fileList) this.fieldModel = deepClone(fileList)
this.syncUpdateFormModel(this.fieldModel) this.syncUpdateFormModel(this.fieldModel)
this.emitFieldDataChange(this.fieldModel, oldValue) this.emitFieldDataChange(this.fieldModel, oldValue)
}, },
@ -180,24 +180,17 @@
mountFunc.call(this, res, file, fileList) mountFunc.call(this, res, file, fileList)
} else { } else {
if (file.status === 'success') { if (file.status === 'success') {
this.fileList.push(file) //this.fileList.push(file) /* this.fileList!! */
this.updateUploadFieldModelAndEmitDataChange() this.updateUploadFieldModelAndEmitDataChange(fileList)
this.uploadBtnHidden = this.fileList.length >= this.field.options.limit this.uploadBtnHidden = fileList.length >= this.field.options.limit
} }
} }
}, },
handleFileRemove(file, fileList) { handleFileRemove(file, fileList) {
let foundIdx = -1
this.fileList.forEach((tf,idx) => {
if (tf.name === file.name) {
foundIdx = idx
}
})
this.fileList = fileList this.fileList = fileList
this.updateUploadFieldModelAndEmitDataChange() this.updateUploadFieldModelAndEmitDataChange(fileList)
this.uploadBtnHidden = fileList.length >= this.field.options.limit this.uploadBtnHidden = fileList.length >= this.field.options.limit
}, },
@ -212,7 +205,7 @@
if (foundIdx >= 0) { if (foundIdx >= 0) {
this.fileList.splice(foundIdx, 1) this.fileList.splice(foundIdx, 1)
this.updateUploadFieldModelAndEmitDataChange() this.updateUploadFieldModelAndEmitDataChange(this.fileList)
this.uploadBtnHidden = this.fileList.length >= this.field.options.limit this.uploadBtnHidden = this.fileList.length >= this.field.options.limit
} }

View File

@ -2,7 +2,7 @@
/** /**
* author: vformAdmin * author: vformAdmin
* email: vdpadmin@163.com * email: vdpadmin@163.com
* website: http://www.vform666.com * website: https://www.vform666.com
* date: 2021.08.18 * date: 2021.08.18
* remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息 * remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息
*/ */

View File

@ -2,6 +2,7 @@
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState" <form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList" :parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId"> :sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
<!-- el-upload增加:name="field.options.name"会导致又拍云上传失败故删除之 -->
<el-upload ref="fieldEditor" :disabled="field.options.disabled" <el-upload ref="fieldEditor" :disabled="field.options.disabled"
:action="field.options.uploadURL" :headers="uploadHeaders" :data="uploadData" :action="field.options.uploadURL" :headers="uploadHeaders" :data="uploadData"
:with-credentials="field.options.withCredentials" :with-credentials="field.options.withCredentials"
@ -107,15 +108,14 @@
}, },
methods: { methods: {
handlePictureExceed() { handlePictureExceed() {
//let uploadLimit = this.field.options.limit let uploadLimit = this.field.options.limit /* 此行不能注释下一行ES6模板字符串需要用到 */
this.$message.warning(eval('`' + this.i18nt('render.hint.uploadExceed') + '`')); this.$message.warning(eval('`' + this.i18nt('render.hint.uploadExceed') + '`'));
}, },
updateUploadFieldModelAndEmitDataChange() { updateUploadFieldModelAndEmitDataChange(fileList) {
let oldValue = deepClone(this.fieldModel) let oldValue = deepClone(this.fieldModel)
this.fieldModel = deepClone(this.fileList) this.fieldModel = deepClone(fileList)
this.syncUpdateFormModel(this.fieldModel) this.syncUpdateFormModel(this.fieldModel)
this.emitFieldDataChange(this.fieldModel, oldValue) this.emitFieldDataChange(this.fieldModel, oldValue)
}, },
@ -170,25 +170,17 @@
customFn.call(this, res, file, fileList) customFn.call(this, res, file, fileList)
} else { } else {
if (file.status === 'success') { if (file.status === 'success') {
this.fileList.push(file) //this.fileList.push(file) /* this.fileList!! */
this.updateUploadFieldModelAndEmitDataChange() this.updateUploadFieldModelAndEmitDataChange(fileList)
this.uploadBtnHidden = this.fileList.length >= this.field.options.limit this.uploadBtnHidden = fileList.length >= this.field.options.limit
//console.log('test========', this.uploadBtnHidden)
} }
} }
}, },
handlePictureRemove(file, fileList) { handlePictureRemove(file, fileList) {
let foundIdx = -1
this.fileList.forEach((tf,idx) => {
if (tf.name === file.name) {
foundIdx = idx
}
})
this.fileList = fileList this.fileList = fileList
this.updateUploadFieldModelAndEmitDataChange() this.updateUploadFieldModelAndEmitDataChange(fileList)
this.uploadBtnHidden = fileList.length >= this.field.options.limit this.uploadBtnHidden = fileList.length >= this.field.options.limit
}, },

View File

@ -61,6 +61,7 @@
} }
} }
}, },
inject: ['getDesignerConfig'],
data() { data() {
return { return {
formModel: {}, formModel: {},
@ -111,6 +112,7 @@
}, },
created() { created() {
this.designer.initDesigner(); this.designer.initDesigner();
this.designer.loadPresetCssCode( this.getDesignerConfig().presetCssCode )
}, },
mounted() { mounted() {
this.disableFirefoxDefaultDrop() /* 禁用Firefox默认拖拽搜索功能!! */ this.disableFirefoxDefaultDrop() /* 禁用Firefox默认拖拽搜索功能!! */

View File

@ -2,7 +2,7 @@
/** /**
* author: vformAdmin * author: vformAdmin
* email: vdpadmin@163.com * email: vdpadmin@163.com
* website: http://www.vform666.com * website: https://www.vform666.com
* date: 2021.08.18 * date: 2021.08.18
* remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息 * remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息
*/ */
@ -104,6 +104,8 @@
exportJsonButton: true, //JSON exportJsonButton: true, //JSON
exportCodeButton: true, // exportCodeButton: true, //
generateSFCButton: true, //SFC generateSFCButton: true, //SFC
presetCssCode: '', //CSS
} }
} }
}, },
@ -117,10 +119,10 @@
vsCodeFlag: false, vsCodeFlag: false,
caseName: '', caseName: '',
docUrl: 'http://www.vform666.com/document.html', docUrl: 'https://www.vform666.com/document.html',
gitUrl: 'https://github.com/vform666/variant-form', gitUrl: 'https://github.com/vform666/variant-form',
chatUrl: 'http://www.vform666.com/chat-group.html', chatUrl: 'https://www.vform666.com/chat-group.html',
subScribeUrl: 'http://www.vform666.com/subscribe.html', subScribeUrl: 'https://www.vform666.com/subscribe.html',
scrollerHeight: 0, scrollerHeight: 0,
@ -168,7 +170,7 @@
const msgObj = { const msgObj = {
cmd: 'openUrl', cmd: 'openUrl',
data: { data: {
url: 'http://www.vform666.com/' url: 'https://www.vform666.com/'
} }
} }
window.parent.postMessage(msgObj, '*') window.parent.postMessage(msgObj, '*')

View File

@ -1,10 +1,15 @@
<template> <template>
<el-form-item :label="i18nt('designer.setting.uniqueName')" :rules="nameRequiredRule"> <el-form-item :rules="nameRequiredRule">
<span slot="label">{{i18nt('designer.setting.uniqueName')}}
<el-tooltip effect="light" :content="i18nt('designer.setting.editNameHelp')">
<i class="el-icon-info"></i></el-tooltip>
</span>
<template v-if="!!selectedWidget.category"> <template v-if="!!selectedWidget.category">
<el-input type="text" v-model="optionModel.name" @change="updateWidgetNameAndRef"></el-input> <el-input type="text" v-model="optionModel.name" @change="updateWidgetNameAndRef"></el-input>
</template> </template>
<template v-else> <template v-else>
<el-select v-model="optionModel.name" allow-create filterable @change="updateWidgetNameAndRef"> <el-select v-model="optionModel.name" allow-create filterable @change="updateWidgetNameAndRef"
:title="i18nt('designer.setting.editNameHelp')">
<el-option v-for="(sf, sfIdx) in serverFieldList" :key="sfIdx" :label="sf.label" :value="sf.name"></el-option> <el-option v-for="(sf, sfIdx) in serverFieldList" :key="sfIdx" :label="sf.label" :value="sf.name"></el-option>
</el-select> </el-select>
</template> </template>

View File

@ -607,7 +607,7 @@
<style lang="scss" scoped> <style lang="scss" scoped>
div.toolbar-container { div.toolbar-container {
min-width: 728px; /* 解决工具按钮栏换行的问题!! */
} }
.left-toolbar { .left-toolbar {
@ -679,7 +679,7 @@
.node-tree-drawer ::v-deep { .node-tree-drawer ::v-deep {
.el-drawer { .el-drawer {
padding: 15px; padding: 10px;
overflow: auto; overflow: auto;
} }
@ -687,6 +687,10 @@
margin-bottom: 12px; margin-bottom: 12px;
padding: 5px 5px 0; padding: 5px 5px 0;
} }
.el-drawer__body {
padding-left: 5px;
}
} }
/*.node-tree-scroll-bar {*/ /*.node-tree-scroll-bar {*/
@ -746,7 +750,7 @@
border-left: 1px dashed #4386c6; border-left: 1px dashed #4386c6;
bottom: 0px; bottom: 0px;
height: 100%; height: 100%;
top: -26px; top: -10px;
width: 1px; width: 1px;
} }
@ -767,15 +771,5 @@
font-size: 16px; font-size: 16px;
} }
.el-tree-node__expand-icon.el-icon-caret-right:before {
//font-size: 16px;
//content: "\e723";
}
.el-tree-node__expand-icon.expanded.el-icon-caret-right:before {
//font-size: 16px;
//content: "\e722";
}
} }
</style> </style>

View File

@ -2,7 +2,7 @@
/** /**
* author: vformAdmin * author: vformAdmin
* email: vdpadmin@163.com * email: vdpadmin@163.com
* website: http://www.vform666.com * website: https://www.vform666.com
* date: 2021.08.18 * date: 2021.08.18
* remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息 * remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息
*/ */

View File

@ -2,7 +2,7 @@
/** /**
* author: vformAdmin * author: vformAdmin
* email: vdpadmin@163.com * email: vdpadmin@163.com
* website: http://www.vform666.com * website: https://www.vform666.com
* date: 2021.08.18 * date: 2021.08.18
* remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息 * remark: 如果要分发VForm源码需在本文件顶部保留此文件头信息
*/ */

View File

@ -140,6 +140,8 @@ export default {
colspanNotConsistentForMergeEntireColumn: 'Cells in this column don\'t have the same colspan, operation failed.', colspanNotConsistentForMergeEntireColumn: 'Cells in this column don\'t have the same colspan, operation failed.',
rowspanNotConsistentForDeleteEntireRow: 'Cells in this row don\'t have the same rowspan, operation failed.', rowspanNotConsistentForDeleteEntireRow: 'Cells in this row don\'t have the same rowspan, operation failed.',
colspanNotConsistentForDeleteEntireColumn: 'Cells in this column don\'t have the same colspan, operation failed.', colspanNotConsistentForDeleteEntireColumn: 'Cells in this column don\'t have the same colspan, operation failed.',
lastColCannotBeDeleted: 'The last col cannot be deleted.',
lastRowCannotBeDeleted: 'The last row cannot be deleted.',
}, },
toolbar: { toolbar: {
@ -166,6 +168,7 @@ export default {
advancedSetting: 'Advanced Setting', advancedSetting: 'Advanced Setting',
eventSetting: 'Event Setting', eventSetting: 'Event Setting',
uniqueName: 'Unique Name', uniqueName: 'Unique Name',
editNameHelp: 'Press enter to confirm the modification',
label: 'Label', label: 'Label',
displayType: 'Type', displayType: 'Type',
defaultValue: 'Default Value', defaultValue: 'Default Value',

View File

@ -140,6 +140,8 @@ export default {
colspanNotConsistentForMergeEntireColumn: '存在列宽不一致的单元格, 无法合并整列.', colspanNotConsistentForMergeEntireColumn: '存在列宽不一致的单元格, 无法合并整列.',
rowspanNotConsistentForDeleteEntireRow: '存在行高不一致的单元格, 不可删除整行.', rowspanNotConsistentForDeleteEntireRow: '存在行高不一致的单元格, 不可删除整行.',
colspanNotConsistentForDeleteEntireColumn: '存在列宽不一致的单元格, 不可删除整列.', colspanNotConsistentForDeleteEntireColumn: '存在列宽不一致的单元格, 不可删除整列.',
lastColCannotBeDeleted: '最后一列不可删除.',
lastRowCannotBeDeleted: '最后一行不可删除.',
}, },
toolbar: { toolbar: {
@ -166,6 +168,7 @@ export default {
advancedSetting: '高级属性', advancedSetting: '高级属性',
eventSetting: '事件属性', eventSetting: '事件属性',
uniqueName: '唯一名称', uniqueName: '唯一名称',
editNameHelp: '修改名称后需按回车确认',
label: '字段标签', label: '字段标签',
displayType: '显示类型', displayType: '显示类型',
defaultValue: '默认值', defaultValue: '默认值',

View File

@ -8,7 +8,7 @@ export const DESIGNER_OPTIONS = {
} }
export const VARIANT_FORM_VERSION = '2.1.8' export const VARIANT_FORM_VERSION = '2.1.9'
//export const MOCK_CASE_URL = 'https://www.fastmock.site/mock/2de212e0dc4b8e0885fea44ab9f2e1d0/vform/' //export const MOCK_CASE_URL = 'https://www.fastmock.site/mock/2de212e0dc4b8e0885fea44ab9f2e1d0/vform/'
export const MOCK_CASE_URL = 'https://ks3-cn-beijing.ksyuncs.com/vform-static/vcase/' export const MOCK_CASE_URL = 'https://ks3-cn-beijing.ksyuncs.com/vform-static/vcase/'

View File

@ -562,7 +562,7 @@ export const genSFC = function (formConfig, widgetList, beautifier, vue3Flag = f
return `<!-- return `<!--
Codes Generated By VForm: Codes Generated By VForm:
http://www.vform666.com https://www.vform666.com
--> -->
<template> <template>