parent
d40fcfc5e0
commit
13e4245fd3
@ -0,0 +1,54 @@
|
|||||||
|
const DRAWING_ITEMS = 'drawingItems'
|
||||||
|
const DRAWING_ITEMS_VERSION = '1.2'
|
||||||
|
const DRAWING_ITEMS_VERSION_KEY = 'DRAWING_ITEMS_VERSION'
|
||||||
|
const DRAWING_ID = 'idGlobal'
|
||||||
|
const TREE_NODE_ID = 'treeNodeId'
|
||||||
|
const FORM_CONF = 'formConf'
|
||||||
|
|
||||||
|
export function getDrawingList() {
|
||||||
|
// 加入缓存版本的概念,保证缓存数据与程序匹配
|
||||||
|
const version = localStorage.getItem(DRAWING_ITEMS_VERSION_KEY)
|
||||||
|
if (version !== DRAWING_ITEMS_VERSION) {
|
||||||
|
localStorage.setItem(DRAWING_ITEMS_VERSION_KEY, DRAWING_ITEMS_VERSION)
|
||||||
|
saveDrawingList([])
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const str = localStorage.getItem(DRAWING_ITEMS)
|
||||||
|
if (str) return JSON.parse(str)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveDrawingList(list) {
|
||||||
|
localStorage.setItem(DRAWING_ITEMS, JSON.stringify(list))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getIdGlobal() {
|
||||||
|
const str = localStorage.getItem(DRAWING_ID)
|
||||||
|
if (str) return parseInt(str, 10)
|
||||||
|
return 100
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveIdGlobal(id) {
|
||||||
|
localStorage.setItem(DRAWING_ID, `${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTreeNodeId() {
|
||||||
|
const str = localStorage.getItem(TREE_NODE_ID)
|
||||||
|
if (str) return parseInt(str, 10)
|
||||||
|
return 100
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveTreeNodeId(id) {
|
||||||
|
localStorage.setItem(TREE_NODE_ID, `${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFormConf() {
|
||||||
|
const str = localStorage.getItem(FORM_CONF)
|
||||||
|
if (str) return JSON.parse(str)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveFormConf(obj) {
|
||||||
|
localStorage.setItem(FORM_CONF, JSON.stringify(obj))
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
import loadScript from './loadScript'
|
||||||
|
import ELEMENT from 'element-ui'
|
||||||
|
import pluginsConfig from './pluginsConfig'
|
||||||
|
|
||||||
|
let beautifierObj
|
||||||
|
|
||||||
|
export default function loadBeautifier(cb) {
|
||||||
|
const { beautifierUrl } = pluginsConfig
|
||||||
|
if (beautifierObj) {
|
||||||
|
cb(beautifierObj)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const loading = ELEMENT.Loading.service({
|
||||||
|
fullscreen: true,
|
||||||
|
lock: true,
|
||||||
|
text: '格式化资源加载中...',
|
||||||
|
spinner: 'el-icon-loading',
|
||||||
|
background: 'rgba(255, 255, 255, 0.5)'
|
||||||
|
})
|
||||||
|
|
||||||
|
loadScript(beautifierUrl, () => {
|
||||||
|
loading.close()
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
beautifierObj = beautifier
|
||||||
|
cb(beautifierObj)
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
const callbacks = {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载一个远程脚本
|
||||||
|
* @param {String} src 一个远程脚本
|
||||||
|
* @param {Function} callback 回调
|
||||||
|
*/
|
||||||
|
function loadScript(src, callback) {
|
||||||
|
const existingScript = document.getElementById(src)
|
||||||
|
const cb = callback || (() => {})
|
||||||
|
if (!existingScript) {
|
||||||
|
callbacks[src] = []
|
||||||
|
const $script = document.createElement('script')
|
||||||
|
$script.src = src
|
||||||
|
$script.id = src
|
||||||
|
$script.async = 1
|
||||||
|
document.body.appendChild($script)
|
||||||
|
const onEnd = 'onload' in $script ? stdOnEnd.bind($script) : ieOnEnd.bind($script)
|
||||||
|
onEnd($script)
|
||||||
|
}
|
||||||
|
|
||||||
|
callbacks[src].push(cb)
|
||||||
|
|
||||||
|
function stdOnEnd(script) {
|
||||||
|
script.onload = () => {
|
||||||
|
this.onerror = this.onload = null
|
||||||
|
callbacks[src].forEach(item => {
|
||||||
|
item(null, script)
|
||||||
|
})
|
||||||
|
delete callbacks[src]
|
||||||
|
}
|
||||||
|
script.onerror = () => {
|
||||||
|
this.onerror = this.onload = null
|
||||||
|
cb(new Error(`Failed to load ${src}`), script)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ieOnEnd(script) {
|
||||||
|
script.onreadystatechange = () => {
|
||||||
|
if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
|
||||||
|
this.onreadystatechange = null
|
||||||
|
callbacks[src].forEach(item => {
|
||||||
|
item(null, script)
|
||||||
|
})
|
||||||
|
delete callbacks[src]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 顺序加载一组远程脚本
|
||||||
|
* @param {Array} list 一组远程脚本
|
||||||
|
* @param {Function} cb 回调
|
||||||
|
*/
|
||||||
|
export function loadScriptQueue(list, cb) {
|
||||||
|
const first = list.shift()
|
||||||
|
list.length ? loadScript(first, () => loadScriptQueue(list, cb)) : loadScript(first, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default loadScript
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
import loadScript from './loadScript'
|
||||||
|
import ELEMENT from 'element-ui'
|
||||||
|
import pluginsConfig from './pluginsConfig'
|
||||||
|
|
||||||
|
let tinymceObj
|
||||||
|
|
||||||
|
export default function loadTinymce(cb) {
|
||||||
|
const { tinymceUrl } = pluginsConfig
|
||||||
|
|
||||||
|
if (tinymceObj) {
|
||||||
|
cb(tinymceObj)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const loading = ELEMENT.Loading.service({
|
||||||
|
fullscreen: true,
|
||||||
|
lock: true,
|
||||||
|
text: '富文本资源加载中...',
|
||||||
|
spinner: 'el-icon-loading',
|
||||||
|
background: 'rgba(255, 255, 255, 0.5)'
|
||||||
|
})
|
||||||
|
|
||||||
|
loadScript(tinymceUrl, () => {
|
||||||
|
loading.close()
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
tinymceObj = tinymce
|
||||||
|
cb(tinymceObj)
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
const CDN = 'https://lib.baomitu.com/' // CDN Homepage: https://cdn.baomitu.com/
|
||||||
|
const publicPath = process.env.BASE_URL
|
||||||
|
|
||||||
|
function splicingPluginUrl(PluginName, version, fileName) {
|
||||||
|
return `${CDN}${PluginName}/${version}/${fileName}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
beautifierUrl: splicingPluginUrl('js-beautify', '1.13.5', 'beautifier.min.js'),
|
||||||
|
// monacoEditorUrl: splicingPluginUrl('monaco-editor', '0.19.3', 'min/vs'), // 使用 monaco-editor CDN 链接
|
||||||
|
monacoEditorUrl: `${publicPath}libs/monaco-editor/vs`, // 使用 monaco-editor 本地代码
|
||||||
|
tinymceUrl: splicingPluginUrl('tinymce', '5.7.0', 'tinymce.min.js')
|
||||||
|
}
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-dialog
|
||||||
|
v-bind="$attrs"
|
||||||
|
width="500px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:modal-append-to-body="false"
|
||||||
|
v-on="$listeners"
|
||||||
|
@open="onOpen"
|
||||||
|
@close="onClose"
|
||||||
|
>
|
||||||
|
<el-row :gutter="15">
|
||||||
|
<el-form
|
||||||
|
ref="elForm"
|
||||||
|
:model="formData"
|
||||||
|
:rules="rules"
|
||||||
|
size="medium"
|
||||||
|
label-width="100px"
|
||||||
|
>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="生成类型" prop="type">
|
||||||
|
<el-radio-group v-model="formData.type">
|
||||||
|
<el-radio-button
|
||||||
|
v-for="(item, index) in typeOptions"
|
||||||
|
:key="index"
|
||||||
|
:label="item.value"
|
||||||
|
:disabled="item.disabled"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="showFileName" label="文件名" prop="fileName">
|
||||||
|
<el-input v-model="formData.fileName" placeholder="请输入文件名" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-form>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<div slot="footer">
|
||||||
|
<el-button @click="close">
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" @click="handleConfirm">
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
inheritAttrs: false,
|
||||||
|
props: ['showFileName'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formData: {
|
||||||
|
fileName: undefined,
|
||||||
|
type: 'file'
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
fileName: [{
|
||||||
|
required: true,
|
||||||
|
message: '请输入文件名',
|
||||||
|
trigger: 'blur'
|
||||||
|
}],
|
||||||
|
type: [{
|
||||||
|
required: true,
|
||||||
|
message: '生成类型不能为空',
|
||||||
|
trigger: 'change'
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
typeOptions: [{
|
||||||
|
label: '页面',
|
||||||
|
value: 'file'
|
||||||
|
}, {
|
||||||
|
label: '弹窗',
|
||||||
|
value: 'dialog'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
},
|
||||||
|
watch: {},
|
||||||
|
mounted() {},
|
||||||
|
methods: {
|
||||||
|
onOpen() {
|
||||||
|
if (this.showFileName) {
|
||||||
|
this.formData.fileName = `${+new Date()}.vue`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onClose() {
|
||||||
|
},
|
||||||
|
close(e) {
|
||||||
|
this.$emit('update:visible', false)
|
||||||
|
},
|
||||||
|
handleConfirm() {
|
||||||
|
this.$refs.elForm.validate(valid => {
|
||||||
|
if (!valid) return
|
||||||
|
this.$emit('confirm', { ...this.formData })
|
||||||
|
this.close()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -0,0 +1,120 @@
|
|||||||
|
<script>
|
||||||
|
import draggable from 'vuedraggable'
|
||||||
|
import render from '@/utils/generator/render'
|
||||||
|
|
||||||
|
const components = {
|
||||||
|
itemBtns(h, currentItem, index, list) {
|
||||||
|
const { copyItem, deleteItem } = this.$listeners
|
||||||
|
return [
|
||||||
|
<span class="drawing-item-copy" title="复制" onClick={event => {
|
||||||
|
copyItem(currentItem, list); event.stopPropagation()
|
||||||
|
}}>
|
||||||
|
<i class="el-icon-copy-document" />
|
||||||
|
</span>,
|
||||||
|
<span class="drawing-item-delete" title="删除" onClick={event => {
|
||||||
|
deleteItem(index, list); event.stopPropagation()
|
||||||
|
}}>
|
||||||
|
<i class="el-icon-delete" />
|
||||||
|
</span>
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const layouts = {
|
||||||
|
colFormItem(h, currentItem, index, list) {
|
||||||
|
const { activeItem } = this.$listeners
|
||||||
|
const config = currentItem.__config__
|
||||||
|
const child = renderChildren.apply(this, arguments)
|
||||||
|
let className = this.activeId === config.formId ? 'drawing-item active-from-item' : 'drawing-item'
|
||||||
|
if (this.formConf.unFocusedComponentBorder) className += ' unfocus-bordered'
|
||||||
|
let labelWidth = config.labelWidth ? `${config.labelWidth}px` : null
|
||||||
|
if (config.showLabel === false) labelWidth = '0'
|
||||||
|
return (
|
||||||
|
<el-col span={config.span} class={className}
|
||||||
|
nativeOnClick={event => { activeItem(currentItem); event.stopPropagation() }}>
|
||||||
|
<el-form-item label-width={labelWidth}
|
||||||
|
label={config.showLabel ? config.label : ''} required={config.required}>
|
||||||
|
<render key={config.renderKey} conf={currentItem} onInput={ event => {
|
||||||
|
this.$set(config, 'defaultValue', event)
|
||||||
|
}}>
|
||||||
|
{child}
|
||||||
|
</render>
|
||||||
|
</el-form-item>
|
||||||
|
{components.itemBtns.apply(this, arguments)}
|
||||||
|
</el-col>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
rowFormItem(h, currentItem, index, list) {
|
||||||
|
const { activeItem } = this.$listeners
|
||||||
|
const config = currentItem.__config__
|
||||||
|
const className = this.activeId === config.formId
|
||||||
|
? 'drawing-row-item active-from-item'
|
||||||
|
: 'drawing-row-item'
|
||||||
|
let child = renderChildren.apply(this, arguments)
|
||||||
|
if (currentItem.type === 'flex') {
|
||||||
|
child = <el-row type={currentItem.type} justify={currentItem.justify} align={currentItem.align}>
|
||||||
|
{child}
|
||||||
|
</el-row>
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<el-col span={config.span}>
|
||||||
|
<el-row gutter={config.gutter} class={className}
|
||||||
|
nativeOnClick={event => { activeItem(currentItem); event.stopPropagation() }}>
|
||||||
|
<span class="component-name">{config.componentName}</span>
|
||||||
|
<draggable list={config.children || []} animation={340}
|
||||||
|
group="componentsGroup" class="drag-wrapper">
|
||||||
|
{child}
|
||||||
|
</draggable>
|
||||||
|
{components.itemBtns.apply(this, arguments)}
|
||||||
|
</el-row>
|
||||||
|
</el-col>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
raw(h, currentItem, index, list) {
|
||||||
|
const config = currentItem.__config__
|
||||||
|
const child = renderChildren.apply(this, arguments)
|
||||||
|
return <render key={config.renderKey} conf={currentItem} onInput={ event => {
|
||||||
|
this.$set(config, 'defaultValue', event)
|
||||||
|
}}>
|
||||||
|
{child}
|
||||||
|
</render>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderChildren(h, currentItem, index, list) {
|
||||||
|
const config = currentItem.__config__
|
||||||
|
if (!Array.isArray(config.children)) return null
|
||||||
|
return config.children.map((el, i) => {
|
||||||
|
const layout = layouts[el.__config__.layout]
|
||||||
|
if (layout) {
|
||||||
|
return layout.call(this, h, el, i, config.children)
|
||||||
|
}
|
||||||
|
return layoutIsNotFound.call(this)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function layoutIsNotFound() {
|
||||||
|
throw new Error(`没有与${this.currentItem.__config__.layout}匹配的layout`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
render,
|
||||||
|
draggable
|
||||||
|
},
|
||||||
|
props: [
|
||||||
|
'currentItem',
|
||||||
|
'index',
|
||||||
|
'drawingList',
|
||||||
|
'activeId',
|
||||||
|
'formConf'
|
||||||
|
],
|
||||||
|
render(h) {
|
||||||
|
const layout = layouts[this.currentItem.__config__.layout]
|
||||||
|
|
||||||
|
if (layout) {
|
||||||
|
return layout.call(this, h, this.currentItem, this.index, this.drawingList)
|
||||||
|
}
|
||||||
|
return layoutIsNotFound.call(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -0,0 +1,123 @@
|
|||||||
|
<template>
|
||||||
|
<div class="icon-dialog">
|
||||||
|
<el-dialog
|
||||||
|
v-bind="$attrs"
|
||||||
|
width="980px"
|
||||||
|
:modal-append-to-body="false"
|
||||||
|
v-on="$listeners"
|
||||||
|
@open="onOpen"
|
||||||
|
@close="onClose"
|
||||||
|
>
|
||||||
|
<div slot="title">
|
||||||
|
选择图标
|
||||||
|
<el-input
|
||||||
|
v-model="key"
|
||||||
|
size="mini"
|
||||||
|
:style="{width: '260px'}"
|
||||||
|
placeholder="请输入图标名称"
|
||||||
|
prefix-icon="el-icon-search"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ul class="icon-ul">
|
||||||
|
<li
|
||||||
|
v-for="icon in iconList"
|
||||||
|
:key="icon"
|
||||||
|
:class="active===icon?'active-item':''"
|
||||||
|
@click="onSelect(icon)"
|
||||||
|
>
|
||||||
|
<i :class="icon" />
|
||||||
|
<div>{{ icon }}</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import iconList from '@/utils/generator/icon.json'
|
||||||
|
|
||||||
|
const originList = iconList.map(name => `el-icon-${name}`)
|
||||||
|
|
||||||
|
export default {
|
||||||
|
inheritAttrs: false,
|
||||||
|
props: ['current'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
iconList: originList,
|
||||||
|
active: null,
|
||||||
|
key: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
key(val) {
|
||||||
|
if (val) {
|
||||||
|
this.iconList = originList.filter(name => name.indexOf(val) > -1)
|
||||||
|
} else {
|
||||||
|
this.iconList = originList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onOpen() {
|
||||||
|
this.active = this.current
|
||||||
|
this.key = ''
|
||||||
|
},
|
||||||
|
onClose() {},
|
||||||
|
onSelect(icon) {
|
||||||
|
this.active = icon
|
||||||
|
this.$emit('select', icon)
|
||||||
|
this.$emit('update:visible', false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.icon-ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 0;
|
||||||
|
li {
|
||||||
|
list-style-type: none;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
display: inline-block;
|
||||||
|
width: 16.66%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: 108px;
|
||||||
|
padding: 15px 6px 6px 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
&:hover {
|
||||||
|
background: #f2f2f2;
|
||||||
|
}
|
||||||
|
&.active-item{
|
||||||
|
background: #e1f3fb;
|
||||||
|
color: #7a6df0
|
||||||
|
}
|
||||||
|
> i {
|
||||||
|
font-size: 30px;
|
||||||
|
line-height: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.icon-dialog {
|
||||||
|
::v-deep .el-dialog {
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
margin-top: 4vh !important;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
max-height: 92vh;
|
||||||
|
overflow: hidden;
|
||||||
|
box-sizing: border-box;
|
||||||
|
.el-dialog__header {
|
||||||
|
padding-top: 14px;
|
||||||
|
}
|
||||||
|
.el-dialog__body {
|
||||||
|
margin: 0 20px 20px 20px;
|
||||||
|
padding: 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,116 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-dialog
|
||||||
|
v-bind="$attrs"
|
||||||
|
title="外部资源引用"
|
||||||
|
width="600px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
v-on="$listeners"
|
||||||
|
@open="onOpen"
|
||||||
|
@close="onClose"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-for="(item, index) in resources"
|
||||||
|
:key="index"
|
||||||
|
v-model="resources[index]"
|
||||||
|
class="url-item"
|
||||||
|
placeholder="请输入 css 或 js 资源路径"
|
||||||
|
prefix-icon="el-icon-link"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
slot="append"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click="deleteOne(index)"
|
||||||
|
/>
|
||||||
|
</el-input>
|
||||||
|
<el-button-group class="add-item">
|
||||||
|
<el-button
|
||||||
|
plain
|
||||||
|
@click="addOne('https://lib.baomitu.com/jquery/1.8.3/jquery.min.js')"
|
||||||
|
>
|
||||||
|
jQuery1.8.3
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
plain
|
||||||
|
@click="addOne('https://unpkg.com/http-vue-loader')"
|
||||||
|
>
|
||||||
|
http-vue-loader
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="el-icon-circle-plus-outline"
|
||||||
|
plain
|
||||||
|
@click="addOne('')"
|
||||||
|
>
|
||||||
|
添加其他
|
||||||
|
</el-button>
|
||||||
|
</el-button-group>
|
||||||
|
<div slot="footer">
|
||||||
|
<el-button @click="close">
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="handelConfirm"
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { deepClone } from '@/utils/index'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
inheritAttrs: false,
|
||||||
|
props: ['originResource'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
resources: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
watch: {},
|
||||||
|
created() {},
|
||||||
|
mounted() {},
|
||||||
|
methods: {
|
||||||
|
onOpen() {
|
||||||
|
this.resources = this.originResource.length ? deepClone(this.originResource) : ['']
|
||||||
|
},
|
||||||
|
onClose() {
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
this.$emit('update:visible', false)
|
||||||
|
},
|
||||||
|
handelConfirm() {
|
||||||
|
const results = this.resources.filter(item => !!item) || []
|
||||||
|
this.$emit('save', results)
|
||||||
|
this.close()
|
||||||
|
if (results.length) {
|
||||||
|
this.resources = results
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteOne(index) {
|
||||||
|
this.resources.splice(index, 1)
|
||||||
|
},
|
||||||
|
addOne(url) {
|
||||||
|
if (this.resources.indexOf(url) > -1) {
|
||||||
|
this.$message('资源已存在')
|
||||||
|
} else {
|
||||||
|
this.resources.push(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.add-item{
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
.url-item{
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,149 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-dialog
|
||||||
|
v-bind="$attrs"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:modal-append-to-body="false"
|
||||||
|
v-on="$listeners"
|
||||||
|
@open="onOpen"
|
||||||
|
@close="onClose"
|
||||||
|
>
|
||||||
|
<el-row :gutter="0">
|
||||||
|
<el-form
|
||||||
|
ref="elForm"
|
||||||
|
:model="formData"
|
||||||
|
:rules="rules"
|
||||||
|
size="small"
|
||||||
|
label-width="100px"
|
||||||
|
>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item
|
||||||
|
label="选项名"
|
||||||
|
prop="label"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="formData.label"
|
||||||
|
placeholder="请输入选项名"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item
|
||||||
|
label="选项值"
|
||||||
|
prop="value"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="formData.value"
|
||||||
|
placeholder="请输入选项值"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<el-select
|
||||||
|
slot="append"
|
||||||
|
v-model="dataType"
|
||||||
|
:style="{width: '100px'}"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="(item, index) in dataTypeOptions"
|
||||||
|
:key="index"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
:disabled="item.disabled"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-form>
|
||||||
|
</el-row>
|
||||||
|
<div slot="footer">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleConfirm"
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="close">
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { isNumberStr } from '@/utils/index'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
inheritAttrs: false,
|
||||||
|
props: [],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
id: 100,
|
||||||
|
formData: {
|
||||||
|
label: undefined,
|
||||||
|
value: undefined
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
label: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入选项名',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入选项值',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
dataType: 'string',
|
||||||
|
dataTypeOptions: [
|
||||||
|
{
|
||||||
|
label: '字符串',
|
||||||
|
value: 'string'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '数字',
|
||||||
|
value: 'number'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
watch: {
|
||||||
|
// eslint-disable-next-line func-names
|
||||||
|
'formData.value': function (val) {
|
||||||
|
this.dataType = isNumberStr(val) ? 'number' : 'string'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {},
|
||||||
|
mounted() {},
|
||||||
|
methods: {
|
||||||
|
onOpen() {
|
||||||
|
this.formData = {
|
||||||
|
label: undefined,
|
||||||
|
value: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onClose() {},
|
||||||
|
close() {
|
||||||
|
this.$emit('update:visible', false)
|
||||||
|
},
|
||||||
|
handleConfirm() {
|
||||||
|
this.$refs.elForm.validate(valid => {
|
||||||
|
if (!valid) return
|
||||||
|
if (this.dataType === 'number') {
|
||||||
|
this.formData.value = parseFloat(this.formData.value)
|
||||||
|
}
|
||||||
|
this.formData.id = this.id++
|
||||||
|
this.$emit('commit', this.formData)
|
||||||
|
this.close()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -0,0 +1,311 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||||
|
<el-form-item label="表单名称" prop="formName">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.formName"
|
||||||
|
placeholder="请输入表单名称"
|
||||||
|
clearable
|
||||||
|
size="small"
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="el-icon-plus"
|
||||||
|
size="mini"
|
||||||
|
@click="handleAdd"
|
||||||
|
v-hasPermi="['workflow:form:add']"
|
||||||
|
>新增</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
plain
|
||||||
|
icon="el-icon-edit"
|
||||||
|
size="mini"
|
||||||
|
:disabled="single"
|
||||||
|
@click="handleUpdate"
|
||||||
|
v-hasPermi="['workflow:form:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
plain
|
||||||
|
icon="el-icon-delete"
|
||||||
|
size="mini"
|
||||||
|
:disabled="multiple"
|
||||||
|
@click="handleDelete"
|
||||||
|
v-hasPermi="['workflow:form:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="1.5">
|
||||||
|
<el-button
|
||||||
|
type="warning"
|
||||||
|
plain
|
||||||
|
icon="el-icon-download"
|
||||||
|
size="mini"
|
||||||
|
@click="handleExport"
|
||||||
|
v-hasPermi="['workflow:form:export']"
|
||||||
|
>导出</el-button>
|
||||||
|
</el-col>
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="formList" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="表单主键" align="center" prop="formId" />
|
||||||
|
<el-table-column label="表单名称" align="center" prop="formName" />
|
||||||
|
<el-table-column label="备注" align="center" prop="remark" />
|
||||||
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-view"
|
||||||
|
@click="handleDetail(scope.row)"
|
||||||
|
>详情</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-edit"
|
||||||
|
@click="handleUpdate(scope.row)"
|
||||||
|
v-hasPermi="['workflow:form:edit']"
|
||||||
|
>修改</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click="handleDelete(scope.row)"
|
||||||
|
v-hasPermi="['workflow:form:remove']"
|
||||||
|
>删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination
|
||||||
|
v-show="total>0"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="queryParams.pageNum"
|
||||||
|
:limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 添加或修改流程表单对话框 -->
|
||||||
|
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||||
|
<el-form-item label="表单名称" prop="formName">
|
||||||
|
<el-input v-model="form.formName" placeholder="请输入表单名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="表单内容">
|
||||||
|
<editor v-model="form.content" :min-height="192"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remark">
|
||||||
|
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!--表单配置详情-->
|
||||||
|
<el-dialog :title="formTitle" :visible.sync="formConfOpen" width="60%" append-to-body>
|
||||||
|
<div class="test-form">
|
||||||
|
<parser :key="new Date().getTime()" :form-conf="formConf" />
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listForm, getForm, delForm, addForm, updateForm } from "@/api/workflow/form";
|
||||||
|
import Editor from '@/components/Editor';
|
||||||
|
import Parser from '@/utils/generator/parser'
|
||||||
|
export default {
|
||||||
|
name: "Form",
|
||||||
|
components: {
|
||||||
|
Editor,
|
||||||
|
Parser
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 遮罩层
|
||||||
|
loading: true,
|
||||||
|
// 选中数组
|
||||||
|
ids: [],
|
||||||
|
// 非单个禁用
|
||||||
|
single: true,
|
||||||
|
// 非多个禁用
|
||||||
|
multiple: true,
|
||||||
|
// 显示搜索条件
|
||||||
|
showSearch: true,
|
||||||
|
// 总条数
|
||||||
|
total: 0,
|
||||||
|
// 流程表单表格数据
|
||||||
|
formList: [],
|
||||||
|
// 弹出层标题
|
||||||
|
title: "",
|
||||||
|
formConf: {}, // 默认表单数据
|
||||||
|
formConfOpen: false,
|
||||||
|
formTitle: "",
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
formName: null,
|
||||||
|
content: null,
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
// 表单校验
|
||||||
|
rules: {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
activated() {
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 查询流程表单列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true;
|
||||||
|
listForm(this.queryParams).then(response => {
|
||||||
|
this.formList = response.list;
|
||||||
|
this.total = response.total;
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 取消按钮
|
||||||
|
cancel() {
|
||||||
|
this.open = false;
|
||||||
|
this.reset();
|
||||||
|
},
|
||||||
|
// 表单重置
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
formId: null,
|
||||||
|
formName: null,
|
||||||
|
content: null,
|
||||||
|
createTime: null,
|
||||||
|
updateTime: null,
|
||||||
|
createBy: null,
|
||||||
|
updateBy: null,
|
||||||
|
remark: null
|
||||||
|
};
|
||||||
|
this.resetForm("form");
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.queryParams.pageNum = 1;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm("queryForm");
|
||||||
|
this.handleQuery();
|
||||||
|
},
|
||||||
|
// 多选框选中数据
|
||||||
|
handleSelectionChange(selection) {
|
||||||
|
this.ids = selection.map(item => item.formId)
|
||||||
|
this.single = selection.length!==1
|
||||||
|
this.multiple = !selection.length
|
||||||
|
},
|
||||||
|
/** 表单配置信息 */
|
||||||
|
handleDetail(row){
|
||||||
|
this.formConfOpen = true;
|
||||||
|
this.formTitle = "流程表单配置详细";
|
||||||
|
this.formConf = JSON.parse(row.content)
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd() {
|
||||||
|
// this.reset();
|
||||||
|
// this.open = true;
|
||||||
|
// this.title = "添加流程表单";
|
||||||
|
this.$router.push({ path: '/flow/form/build', query: {formId: null }})
|
||||||
|
},
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
handleUpdate(row) {
|
||||||
|
// this.reset();
|
||||||
|
// const formId = row.formId || this.ids
|
||||||
|
// getForm(formId).then(response => {
|
||||||
|
// this.form = response.data;
|
||||||
|
// this.open = true;
|
||||||
|
// this.title = "修改流程表单";
|
||||||
|
// });
|
||||||
|
this.$router.push({ path: '/flow/form/build', query: {formId: row.formId }})
|
||||||
|
},
|
||||||
|
/** 提交按钮 */
|
||||||
|
submitForm() {
|
||||||
|
this.$refs["form"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (this.form.formId != null) {
|
||||||
|
updateForm(this.form).then(response => {
|
||||||
|
this.$modal.msgSuccess("修改成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getList();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addForm(this.form).then(response => {
|
||||||
|
this.$modal.msgSuccess("新增成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
handleDelete(row) {
|
||||||
|
const formIds = row.formId || this.ids;
|
||||||
|
this.$confirm('是否确认删除流程表单编号为"' + formIds + '"的数据项?', "警告", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(function() {
|
||||||
|
return delForm(formIds);
|
||||||
|
}).then(() => {
|
||||||
|
this.getList();
|
||||||
|
this.$modal.msgSuccess("删除成功");
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
handleExport() {
|
||||||
|
let _this = this
|
||||||
|
this.$confirm('是否确认导出所有流程表单数据项?', "警告", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(function() {
|
||||||
|
_this.download('/workflow/form/export', {
|
||||||
|
..._this.queryParams
|
||||||
|
}, `form_${new Date().getTime()}.xlsx`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.test-form {
|
||||||
|
margin: 15px auto;
|
||||||
|
width: 800px;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in new issue