right panel
This commit is contained in:
10
jsconfig.json
Normal file
10
jsconfig.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
// ...
|
||||
"types": ["element-plus/global"],
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
95
public/preview.html
Normal file
95
public/preview.html
Normal file
@ -0,0 +1,95 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title>form-generator-preview</title>
|
||||
<link href="https://unpkg.com/browse/element-plus@2.2.26/dist/index.css" rel="stylesheet">
|
||||
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
||||
<script src="https://unpkg.com/browse/vue-router@4.1.6/dist/vue-router.global.prod.js"></script>
|
||||
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
||||
<script src="https://unpkg.com/browse/element-plus@2.2.26/dist/index.full.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow-x: hidden;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
height: calc(100vh - 33px);
|
||||
padding: 12px;
|
||||
box-sizing: border-box;
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;
|
||||
}
|
||||
|
||||
input,
|
||||
textarea {
|
||||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>抱歉,javascript被禁用,请开启后重试。</strong>
|
||||
</noscript>
|
||||
<div id="previewApp"></div>
|
||||
<script type="text/javascript">
|
||||
Vue.prototype.$axios = axios
|
||||
const childAttrs = {
|
||||
file: '',
|
||||
dialog: ' width="600px" class="dialog-width" v-if="visible" :visible.sync="visible" :modal-append-to-body="false" '
|
||||
}
|
||||
|
||||
window.addEventListener('message', init, false)
|
||||
function init(event) {
|
||||
if (event.data.type === 'refreshFrame') {
|
||||
const code = event.data.data
|
||||
const attrs = childAttrs[code.generateConf.type]
|
||||
let links = ''
|
||||
|
||||
if (Array.isArray(code.links) && code.links.length > 0) {
|
||||
links = buildLinks(code.links)
|
||||
}
|
||||
|
||||
document.getElementById('previewApp').innerHTML = `${links}<style>${code.css}</style><div id="app"></div>`
|
||||
|
||||
if (Array.isArray(code.scripts) && code.scripts.length > 0) {
|
||||
this.loadScriptQueue(code.scripts, () => {
|
||||
newVue(attrs, code.js, code.html)
|
||||
})
|
||||
} else {
|
||||
newVue(attrs, code.js, code.html)
|
||||
}
|
||||
}
|
||||
}
|
||||
function buildLinks(links) {
|
||||
let strs = ''
|
||||
links.forEach(url => {
|
||||
strs += `<link href="${url}" rel="stylesheet">`
|
||||
})
|
||||
return strs
|
||||
}
|
||||
function newVue(attrs, main, html) {
|
||||
main = eval(`(${main})`)
|
||||
main.template = `<div>${html}</div>`
|
||||
new Vue({
|
||||
components: {
|
||||
child: main
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: true
|
||||
}
|
||||
},
|
||||
template: `<div><child ${attrs}/></div>`
|
||||
}).$mount('#app')
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -44,23 +44,51 @@
|
||||
border-bottom: $color-border-style;
|
||||
border-left: $transparent-border-style;
|
||||
border-right: $transparent-border-style;
|
||||
}
|
||||
|
||||
@else if $direction==right {
|
||||
} @else if $direction==right {
|
||||
border-left: $color-border-style;
|
||||
border-top: $transparent-border-style;
|
||||
border-bottom: $transparent-border-style;
|
||||
}
|
||||
|
||||
@else if $direction==down {
|
||||
} @else if $direction==down {
|
||||
border-top: $color-border-style;
|
||||
border-left: $transparent-border-style;
|
||||
border-right: $transparent-border-style;
|
||||
}
|
||||
|
||||
@else if $direction==left {
|
||||
} @else if $direction==left {
|
||||
border-right: $color-border-style;
|
||||
border-top: $transparent-border-style;
|
||||
border-bottom: $transparent-border-style;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin action-bar {
|
||||
.action-bar {
|
||||
height: 33px;
|
||||
background: #f2fafb;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.bar-btn {
|
||||
display: inline-block;
|
||||
padding: 0 6px;
|
||||
line-height: 32px;
|
||||
color: #8285f5;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
user-select: none;
|
||||
& i {
|
||||
font-size: 20px;
|
||||
}
|
||||
&:hover {
|
||||
color: #4348d4;
|
||||
}
|
||||
}
|
||||
.bar-btn + .bar-btn {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.delete-btn {
|
||||
color: #f56c6c;
|
||||
&:hover {
|
||||
color: #ea0b30;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -290,10 +290,12 @@ export const selectComponents = [
|
||||
{
|
||||
label: "选项一",
|
||||
value: 1,
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
label: "选项二",
|
||||
value: 2,
|
||||
disabled: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -554,7 +556,7 @@ export const layoutComponents = [
|
||||
default: "主要按钮",
|
||||
},
|
||||
type: "primary",
|
||||
icon: "el-icon-search",
|
||||
icon: "search",
|
||||
round: false,
|
||||
size: "default",
|
||||
plain: false,
|
||||
|
@ -1,8 +1,8 @@
|
||||
/* eslint-disable max-len */
|
||||
import ruleTrigger from './ruleTrigger'
|
||||
import ruleTrigger from "./ruleTrigger";
|
||||
|
||||
let confGlobal
|
||||
let someSpanIsNot24
|
||||
let confGlobal;
|
||||
let someSpanIsNot24;
|
||||
|
||||
export function dialogWrapper(str) {
|
||||
return `<el-dialog v-bind="$attrs" v-on="$listeners" @open="onOpen" @close="onClose" title="Dialog Title">
|
||||
@ -11,7 +11,7 @@ export function dialogWrapper(str) {
|
||||
<el-button @click="close">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>`
|
||||
</el-dialog>`;
|
||||
}
|
||||
|
||||
export function vueTemplate(str) {
|
||||
@ -19,53 +19,57 @@ export function vueTemplate(str) {
|
||||
<div>
|
||||
${str}
|
||||
</div>
|
||||
</template>`
|
||||
</template>`;
|
||||
}
|
||||
|
||||
export function vueScript(str) {
|
||||
return `<script>
|
||||
export function vueScript(str, isSetup) {
|
||||
return `<script ${isSetup ? "setup" : ""}>
|
||||
${str}
|
||||
</script>`
|
||||
</script>`;
|
||||
}
|
||||
|
||||
export function cssStyle(cssStr) {
|
||||
return `<style>
|
||||
${cssStr}
|
||||
</style>`
|
||||
</style>`;
|
||||
}
|
||||
|
||||
function buildFormTemplate(scheme, child, type) {
|
||||
let labelPosition = ''
|
||||
if (scheme.labelPosition !== 'right') {
|
||||
labelPosition = `label-position="${scheme.labelPosition}"`
|
||||
let labelPosition = "";
|
||||
if (scheme.labelPosition !== "right") {
|
||||
labelPosition = `label-position="${scheme.labelPosition}"`;
|
||||
}
|
||||
const disabled = scheme.disabled ? `:disabled="${scheme.disabled}"` : ''
|
||||
let str = `<el-form ref="${scheme.formRef}" :model="${scheme.formModel}" :rules="${scheme.formRules}" size="${scheme.size}" ${disabled} label-width="${scheme.labelWidth}px" ${labelPosition}>
|
||||
const disabled = scheme.disabled ? `:disabled="${scheme.disabled}"` : "";
|
||||
let str = `<el-form ref="${scheme.formRef}" :model="${
|
||||
scheme.formModel
|
||||
}" :rules="${scheme.formRules}" size="${
|
||||
scheme.size
|
||||
}" ${disabled} label-width="${scheme.labelWidth}px" ${labelPosition}>
|
||||
${child}
|
||||
${buildFromBtns(scheme, type)}
|
||||
</el-form>`
|
||||
</el-form>`;
|
||||
if (someSpanIsNot24) {
|
||||
str = `<el-row :gutter="${scheme.gutter}">
|
||||
${str}
|
||||
</el-row>`
|
||||
</el-row>`;
|
||||
}
|
||||
return str
|
||||
return str;
|
||||
}
|
||||
|
||||
function buildFromBtns(scheme, type) {
|
||||
let str = ''
|
||||
if (scheme.formBtns && type === 'file') {
|
||||
let str = "";
|
||||
if (scheme.formBtns && type === "file") {
|
||||
str = `<el-form-item size="large">
|
||||
<el-button type="primary" @click="submitForm">提交</el-button>
|
||||
<el-button @click="resetForm">重置</el-button>
|
||||
</el-form-item>`
|
||||
</el-form-item>`;
|
||||
if (someSpanIsNot24) {
|
||||
str = `<el-col :span="24">
|
||||
${str}
|
||||
</el-col>`
|
||||
</el-col>`;
|
||||
}
|
||||
}
|
||||
return str
|
||||
return str;
|
||||
}
|
||||
|
||||
// span不为24的用el-col包裹
|
||||
@ -73,304 +77,360 @@ function colWrapper(scheme, str) {
|
||||
if (someSpanIsNot24 || scheme.__config__.span !== 24) {
|
||||
return `<el-col :span="${scheme.__config__.span}">
|
||||
${str}
|
||||
</el-col>`
|
||||
</el-col>`;
|
||||
}
|
||||
return str
|
||||
return str;
|
||||
}
|
||||
|
||||
const layouts = {
|
||||
colFormItem(scheme) {
|
||||
const config = scheme.__config__
|
||||
let labelWidth = ''
|
||||
let label = `label="${config.label}"`
|
||||
const config = scheme.__config__;
|
||||
let labelWidth = "";
|
||||
let label = `label="${config.label}"`;
|
||||
if (config.labelWidth && config.labelWidth !== confGlobal.labelWidth) {
|
||||
labelWidth = `label-width="${config.labelWidth}px"`
|
||||
labelWidth = `label-width="${config.labelWidth}px"`;
|
||||
}
|
||||
if (config.showLabel === false) {
|
||||
labelWidth = 'label-width="0"'
|
||||
label = ''
|
||||
labelWidth = 'label-width="0"';
|
||||
label = "";
|
||||
}
|
||||
const required = !ruleTrigger[config.tag] && config.required ? 'required' : ''
|
||||
const tagDom = tags[config.tag] ? tags[config.tag](scheme) : null
|
||||
const required =
|
||||
!ruleTrigger[config.tag] && config.required ? "required" : "";
|
||||
const tagDom = tags[config.tag] ? tags[config.tag](scheme) : null;
|
||||
let str = `<el-form-item ${labelWidth} ${label} prop="${scheme.__vModel__}" ${required}>
|
||||
${tagDom}
|
||||
</el-form-item>`
|
||||
str = colWrapper(scheme, str)
|
||||
return str
|
||||
</el-form-item>`;
|
||||
str = colWrapper(scheme, str);
|
||||
return str;
|
||||
},
|
||||
rowFormItem(scheme) {
|
||||
const config = scheme.__config__
|
||||
const type = scheme.type === 'default' ? '' : `type="${scheme.type}"`
|
||||
const justify = scheme.type === 'default' ? '' : `justify="${scheme.justify}"`
|
||||
const align = scheme.type === 'default' ? '' : `align="${scheme.align}"`
|
||||
const gutter = scheme.gutter ? `:gutter="${scheme.gutter}"` : ''
|
||||
const children = config.children.map(el => layouts[el.__config__.layout](el))
|
||||
const config = scheme.__config__;
|
||||
const type = scheme.type === "default" ? "" : `type="${scheme.type}"`;
|
||||
const justify =
|
||||
scheme.type === "default" ? "" : `justify="${scheme.justify}"`;
|
||||
const align = scheme.type === "default" ? "" : `align="${scheme.align}"`;
|
||||
const gutter = scheme.gutter ? `:gutter="${scheme.gutter}"` : "";
|
||||
const children = config.children.map((el) =>
|
||||
layouts[el.__config__.layout](el)
|
||||
);
|
||||
let str = `<el-row ${type} ${justify} ${align} ${gutter}>
|
||||
${children.join('\n')}
|
||||
</el-row>`
|
||||
str = colWrapper(scheme, str)
|
||||
return str
|
||||
}
|
||||
}
|
||||
${children.join("\n")}
|
||||
</el-row>`;
|
||||
str = colWrapper(scheme, str);
|
||||
return str;
|
||||
},
|
||||
};
|
||||
|
||||
const tags = {
|
||||
'el-button': el => {
|
||||
const {
|
||||
tag, disabled
|
||||
} = attrBuilder(el)
|
||||
const type = el.type ? `type="${el.type}"` : ''
|
||||
const icon = el.icon ? `icon="${el.icon}"` : ''
|
||||
const round = el.round ? 'round' : ''
|
||||
const size = el.size ? `size="${el.size}"` : ''
|
||||
const plain = el.plain ? 'plain' : ''
|
||||
const circle = el.circle ? 'circle' : ''
|
||||
let child = buildElButtonChild(el)
|
||||
"el-button": (el) => {
|
||||
const { tag, disabled } = attrBuilder(el);
|
||||
const type = el.type ? `type="${el.type}"` : "";
|
||||
const icon = el.icon ? `icon="${el.icon}"` : "";
|
||||
const round = el.round ? "round" : "";
|
||||
const size = el.size ? `size="${el.size}"` : "";
|
||||
const plain = el.plain ? "plain" : "";
|
||||
const circle = el.circle ? "circle" : "";
|
||||
let child = buildElButtonChild(el);
|
||||
|
||||
if (child) child = `\n${child}\n` // 换行
|
||||
return `<${tag} ${type} ${icon} ${round} ${size} ${plain} ${disabled} ${circle}>${child}</${tag}>`
|
||||
if (child) child = `\n${child}\n`; // 换行
|
||||
return `<${tag} ${type} ${icon} ${round} ${size} ${plain} ${disabled} ${circle}>${child}</${tag}>`;
|
||||
},
|
||||
'el-input': el => {
|
||||
const {
|
||||
tag, disabled, vModel, clearable, placeholder, width
|
||||
} = attrBuilder(el)
|
||||
const maxlength = el.maxlength ? `:maxlength="${el.maxlength}"` : ''
|
||||
const showWordLimit = el['show-word-limit'] ? 'show-word-limit' : ''
|
||||
const readonly = el.readonly ? 'readonly' : ''
|
||||
const prefixIcon = el['prefix-icon'] ? `prefix-icon='${el['prefix-icon']}'` : ''
|
||||
const suffixIcon = el['suffix-icon'] ? `suffix-icon='${el['suffix-icon']}'` : ''
|
||||
const showPassword = el['show-password'] ? 'show-password' : ''
|
||||
const type = el.type ? `type="${el.type}"` : ''
|
||||
const autosize = el.autosize && el.autosize.minRows
|
||||
? `:autosize="{minRows: ${el.autosize.minRows}, maxRows: ${el.autosize.maxRows}}"`
|
||||
: ''
|
||||
let child = buildElInputChild(el)
|
||||
"el-input": (el) => {
|
||||
const { tag, disabled, vModel, clearable, placeholder, width } =
|
||||
attrBuilder(el);
|
||||
const maxlength = el.maxlength ? `:maxlength="${el.maxlength}"` : "";
|
||||
const showWordLimit = el["show-word-limit"] ? "show-word-limit" : "";
|
||||
const readonly = el.readonly ? "readonly" : "";
|
||||
const prefixIcon = el["prefix-icon"]
|
||||
? `prefix-icon='${el["prefix-icon"]}'`
|
||||
: "";
|
||||
const suffixIcon = el["suffix-icon"]
|
||||
? `suffix-icon='${el["suffix-icon"]}'`
|
||||
: "";
|
||||
const showPassword = el["show-password"] ? "show-password" : "";
|
||||
const type = el.type ? `type="${el.type}"` : "";
|
||||
const autosize =
|
||||
el.autosize && el.autosize.minRows
|
||||
? `:autosize="{minRows: ${el.autosize.minRows}, maxRows: ${el.autosize.maxRows}}"`
|
||||
: "";
|
||||
let child = buildElInputChild(el);
|
||||
|
||||
if (child) child = `\n${child}\n` // 换行
|
||||
return `<${tag} ${vModel} ${type} ${placeholder} ${maxlength} ${showWordLimit} ${readonly} ${disabled} ${clearable} ${prefixIcon} ${suffixIcon} ${showPassword} ${autosize} ${width}>${child}</${tag}>`
|
||||
if (child) child = `\n${child}\n`; // 换行
|
||||
return `<${tag} ${vModel} ${type} ${placeholder} ${maxlength} ${showWordLimit} ${readonly} ${disabled} ${clearable} ${prefixIcon} ${suffixIcon} ${showPassword} ${autosize} ${width}>${child}</${tag}>`;
|
||||
},
|
||||
'el-input-number': el => {
|
||||
const {
|
||||
tag, disabled, vModel, placeholder
|
||||
} = attrBuilder(el)
|
||||
const controlsPosition = el['controls-position'] ? `controls-position=${el['controls-position']}` : ''
|
||||
const min = el.min ? `:min='${el.min}'` : ''
|
||||
const max = el.max ? `:max='${el.max}'` : ''
|
||||
const step = el.step ? `:step='${el.step}'` : ''
|
||||
const stepStrictly = el['step-strictly'] ? 'step-strictly' : ''
|
||||
const precision = el.precision ? `:precision='${el.precision}'` : ''
|
||||
"el-input-number": (el) => {
|
||||
const { tag, disabled, vModel, placeholder } = attrBuilder(el);
|
||||
const controlsPosition = el["controls-position"]
|
||||
? `controls-position=${el["controls-position"]}`
|
||||
: "";
|
||||
const min = el.min ? `:min='${el.min}'` : "";
|
||||
const max = el.max ? `:max='${el.max}'` : "";
|
||||
const step = el.step ? `:step='${el.step}'` : "";
|
||||
const stepStrictly = el["step-strictly"] ? "step-strictly" : "";
|
||||
const precision = el.precision ? `:precision='${el.precision}'` : "";
|
||||
|
||||
return `<${tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${disabled}></${tag}>`
|
||||
return `<${tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${disabled}></${tag}>`;
|
||||
},
|
||||
'el-select': el => {
|
||||
const {
|
||||
tag, disabled, vModel, clearable, placeholder, width
|
||||
} = attrBuilder(el)
|
||||
const filterable = el.filterable ? 'filterable' : ''
|
||||
const multiple = el.multiple ? 'multiple' : ''
|
||||
let child = buildElSelectChild(el)
|
||||
"el-select": (el) => {
|
||||
const { tag, disabled, vModel, clearable, placeholder, width } =
|
||||
attrBuilder(el);
|
||||
const filterable = el.filterable ? "filterable" : "";
|
||||
const multiple = el.multiple ? "multiple" : "";
|
||||
let child = buildElSelectChild(el);
|
||||
|
||||
if (child) child = `\n${child}\n` // 换行
|
||||
return `<${tag} ${vModel} ${placeholder} ${disabled} ${multiple} ${filterable} ${clearable} ${width}>${child}</${tag}>`
|
||||
if (child) child = `\n${child}\n`; // 换行
|
||||
return `<${tag} ${vModel} ${placeholder} ${disabled} ${multiple} ${filterable} ${clearable} ${width}>${child}</${tag}>`;
|
||||
},
|
||||
'el-radio-group': el => {
|
||||
const { tag, disabled, vModel } = attrBuilder(el)
|
||||
const size = `size="${el.size}"`
|
||||
let child = buildElRadioGroupChild(el)
|
||||
"el-radio-group": (el) => {
|
||||
const { tag, disabled, vModel } = attrBuilder(el);
|
||||
const size = `size="${el.size}"`;
|
||||
let child = buildElRadioGroupChild(el);
|
||||
|
||||
if (child) child = `\n${child}\n` // 换行
|
||||
return `<${tag} ${vModel} ${size} ${disabled}>${child}</${tag}>`
|
||||
if (child) child = `\n${child}\n`; // 换行
|
||||
return `<${tag} ${vModel} ${size} ${disabled}>${child}</${tag}>`;
|
||||
},
|
||||
'el-checkbox-group': el => {
|
||||
const { tag, disabled, vModel } = attrBuilder(el)
|
||||
const size = `size="${el.size}"`
|
||||
const min = el.min ? `:min="${el.min}"` : ''
|
||||
const max = el.max ? `:max="${el.max}"` : ''
|
||||
let child = buildElCheckboxGroupChild(el)
|
||||
"el-checkbox-group": (el) => {
|
||||
const { tag, disabled, vModel } = attrBuilder(el);
|
||||
const size = `size="${el.size}"`;
|
||||
const min = el.min ? `:min="${el.min}"` : "";
|
||||
const max = el.max ? `:max="${el.max}"` : "";
|
||||
let child = buildElCheckboxGroupChild(el);
|
||||
|
||||
if (child) child = `\n${child}\n` // 换行
|
||||
return `<${tag} ${vModel} ${min} ${max} ${size} ${disabled}>${child}</${tag}>`
|
||||
if (child) child = `\n${child}\n`; // 换行
|
||||
return `<${tag} ${vModel} ${min} ${max} ${size} ${disabled}>${child}</${tag}>`;
|
||||
},
|
||||
'el-switch': el => {
|
||||
const { tag, disabled, vModel } = attrBuilder(el)
|
||||
const activeText = el['active-text'] ? `active-text="${el['active-text']}"` : ''
|
||||
const inactiveText = el['inactive-text'] ? `inactive-text="${el['inactive-text']}"` : ''
|
||||
const activeColor = el['active-color'] ? `active-color="${el['active-color']}"` : ''
|
||||
const inactiveColor = el['inactive-color'] ? `inactive-color="${el['inactive-color']}"` : ''
|
||||
const activeValue = el['active-value'] !== true ? `:active-value='${JSON.stringify(el['active-value'])}'` : ''
|
||||
const inactiveValue = el['inactive-value'] !== false ? `:inactive-value='${JSON.stringify(el['inactive-value'])}'` : ''
|
||||
"el-switch": (el) => {
|
||||
const { tag, disabled, vModel } = attrBuilder(el);
|
||||
const activeText = el["active-text"]
|
||||
? `active-text="${el["active-text"]}"`
|
||||
: "";
|
||||
const inactiveText = el["inactive-text"]
|
||||
? `inactive-text="${el["inactive-text"]}"`
|
||||
: "";
|
||||
const activeColor = el["active-color"]
|
||||
? `active-color="${el["active-color"]}"`
|
||||
: "";
|
||||
const inactiveColor = el["inactive-color"]
|
||||
? `inactive-color="${el["inactive-color"]}"`
|
||||
: "";
|
||||
const activeValue =
|
||||
el["active-value"] !== true
|
||||
? `:active-value='${JSON.stringify(el["active-value"])}'`
|
||||
: "";
|
||||
const inactiveValue =
|
||||
el["inactive-value"] !== false
|
||||
? `:inactive-value='${JSON.stringify(el["inactive-value"])}'`
|
||||
: "";
|
||||
|
||||
return `<${tag} ${vModel} ${activeText} ${inactiveText} ${activeColor} ${inactiveColor} ${activeValue} ${inactiveValue} ${disabled}></${tag}>`
|
||||
return `<${tag} ${vModel} ${activeText} ${inactiveText} ${activeColor} ${inactiveColor} ${activeValue} ${inactiveValue} ${disabled}></${tag}>`;
|
||||
},
|
||||
'el-cascader': el => {
|
||||
const {
|
||||
tag, disabled, vModel, clearable, placeholder, width
|
||||
} = attrBuilder(el)
|
||||
const options = el.options ? `:options="${el.__vModel__}Options"` : ''
|
||||
const props = el.props ? `:props="${el.__vModel__}Props"` : ''
|
||||
const showAllLevels = el['show-all-levels'] ? '' : ':show-all-levels="false"'
|
||||
const filterable = el.filterable ? 'filterable' : ''
|
||||
const separator = el.separator === '/' ? '' : `separator="${el.separator}"`
|
||||
"el-cascader": (el) => {
|
||||
const { tag, disabled, vModel, clearable, placeholder, width } =
|
||||
attrBuilder(el);
|
||||
const options = el.options ? `:options="${el.__vModel__}Options"` : "";
|
||||
const props = el.props ? `:props="${el.__vModel__}Props"` : "";
|
||||
const showAllLevels = el["show-all-levels"]
|
||||
? ""
|
||||
: ':show-all-levels="false"';
|
||||
const filterable = el.filterable ? "filterable" : "";
|
||||
const separator = el.separator === "/" ? "" : `separator="${el.separator}"`;
|
||||
|
||||
return `<${tag} ${vModel} ${options} ${props} ${width} ${showAllLevels} ${placeholder} ${separator} ${filterable} ${clearable} ${disabled}></${tag}>`
|
||||
return `<${tag} ${vModel} ${options} ${props} ${width} ${showAllLevels} ${placeholder} ${separator} ${filterable} ${clearable} ${disabled}></${tag}>`;
|
||||
},
|
||||
'el-slider': el => {
|
||||
const { tag, disabled, vModel } = attrBuilder(el)
|
||||
const min = el.min ? `:min='${el.min}'` : ''
|
||||
const max = el.max ? `:max='${el.max}'` : ''
|
||||
const step = el.step ? `:step='${el.step}'` : ''
|
||||
const range = el.range ? 'range' : ''
|
||||
const showStops = el['show-stops'] ? `:show-stops="${el['show-stops']}"` : ''
|
||||
"el-slider": (el) => {
|
||||
const { tag, disabled, vModel } = attrBuilder(el);
|
||||
const min = el.min ? `:min='${el.min}'` : "";
|
||||
const max = el.max ? `:max='${el.max}'` : "";
|
||||
const step = el.step ? `:step='${el.step}'` : "";
|
||||
const range = el.range ? "range" : "";
|
||||
const showStops = el["show-stops"]
|
||||
? `:show-stops="${el["show-stops"]}"`
|
||||
: "";
|
||||
|
||||
return `<${tag} ${min} ${max} ${step} ${vModel} ${range} ${showStops} ${disabled}></${tag}>`
|
||||
return `<${tag} ${min} ${max} ${step} ${vModel} ${range} ${showStops} ${disabled}></${tag}>`;
|
||||
},
|
||||
'el-time-picker': el => {
|
||||
const {
|
||||
tag, disabled, vModel, clearable, placeholder, width
|
||||
} = attrBuilder(el)
|
||||
const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : ''
|
||||
const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : ''
|
||||
const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : ''
|
||||
const isRange = el['is-range'] ? 'is-range' : ''
|
||||
const format = el.format ? `format="${el.format}"` : ''
|
||||
const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : ''
|
||||
const pickerOptions = el['picker-options'] ? `:picker-options='${JSON.stringify(el['picker-options'])}'` : ''
|
||||
"el-time-picker": (el) => {
|
||||
const { tag, disabled, vModel, clearable, placeholder, width } =
|
||||
attrBuilder(el);
|
||||
const startPlaceholder = el["start-placeholder"]
|
||||
? `start-placeholder="${el["start-placeholder"]}"`
|
||||
: "";
|
||||
const endPlaceholder = el["end-placeholder"]
|
||||
? `end-placeholder="${el["end-placeholder"]}"`
|
||||
: "";
|
||||
const rangeSeparator = el["range-separator"]
|
||||
? `range-separator="${el["range-separator"]}"`
|
||||
: "";
|
||||
const isRange = el["is-range"] ? "is-range" : "";
|
||||
const format = el.format ? `format="${el.format}"` : "";
|
||||
const valueFormat = el["value-format"]
|
||||
? `value-format="${el["value-format"]}"`
|
||||
: "";
|
||||
const pickerOptions = el["picker-options"]
|
||||
? `:picker-options='${JSON.stringify(el["picker-options"])}'`
|
||||
: "";
|
||||
|
||||
return `<${tag} ${vModel} ${isRange} ${format} ${valueFormat} ${pickerOptions} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${disabled}></${tag}>`
|
||||
return `<${tag} ${vModel} ${isRange} ${format} ${valueFormat} ${pickerOptions} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${disabled}></${tag}>`;
|
||||
},
|
||||
'el-date-picker': el => {
|
||||
const {
|
||||
tag, disabled, vModel, clearable, placeholder, width
|
||||
} = attrBuilder(el)
|
||||
const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : ''
|
||||
const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : ''
|
||||
const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : ''
|
||||
const format = el.format ? `format="${el.format}"` : ''
|
||||
const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : ''
|
||||
const type = el.type === 'date' ? '' : `type="${el.type}"`
|
||||
const readonly = el.readonly ? 'readonly' : ''
|
||||
"el-date-picker": (el) => {
|
||||
const { tag, disabled, vModel, clearable, placeholder, width } =
|
||||
attrBuilder(el);
|
||||
const startPlaceholder = el["start-placeholder"]
|
||||
? `start-placeholder="${el["start-placeholder"]}"`
|
||||
: "";
|
||||
const endPlaceholder = el["end-placeholder"]
|
||||
? `end-placeholder="${el["end-placeholder"]}"`
|
||||
: "";
|
||||
const rangeSeparator = el["range-separator"]
|
||||
? `range-separator="${el["range-separator"]}"`
|
||||
: "";
|
||||
const format = el.format ? `format="${el.format}"` : "";
|
||||
const valueFormat = el["value-format"]
|
||||
? `value-format="${el["value-format"]}"`
|
||||
: "";
|
||||
const type = el.type === "date" ? "" : `type="${el.type}"`;
|
||||
const readonly = el.readonly ? "readonly" : "";
|
||||
|
||||
return `<${tag} ${type} ${vModel} ${format} ${valueFormat} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${readonly} ${disabled}></${tag}>`
|
||||
return `<${tag} ${type} ${vModel} ${format} ${valueFormat} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${readonly} ${disabled}></${tag}>`;
|
||||
},
|
||||
'el-rate': el => {
|
||||
const { tag, disabled, vModel } = attrBuilder(el)
|
||||
const max = el.max ? `:max='${el.max}'` : ''
|
||||
const allowHalf = el['allow-half'] ? 'allow-half' : ''
|
||||
const showText = el['show-text'] ? 'show-text' : ''
|
||||
const showScore = el['show-score'] ? 'show-score' : ''
|
||||
"el-rate": (el) => {
|
||||
const { tag, disabled, vModel } = attrBuilder(el);
|
||||
const max = el.max ? `:max='${el.max}'` : "";
|
||||
const allowHalf = el["allow-half"] ? "allow-half" : "";
|
||||
const showText = el["show-text"] ? "show-text" : "";
|
||||
const showScore = el["show-score"] ? "show-score" : "";
|
||||
|
||||
return `<${tag} ${vModel} ${max} ${allowHalf} ${showText} ${showScore} ${disabled}></${tag}>`
|
||||
return `<${tag} ${vModel} ${max} ${allowHalf} ${showText} ${showScore} ${disabled}></${tag}>`;
|
||||
},
|
||||
'el-color-picker': el => {
|
||||
const { tag, disabled, vModel } = attrBuilder(el)
|
||||
const size = `size="${el.size}"`
|
||||
const showAlpha = el['show-alpha'] ? 'show-alpha' : ''
|
||||
const colorFormat = el['color-format'] ? `color-format="${el['color-format']}"` : ''
|
||||
"el-color-picker": (el) => {
|
||||
const { tag, disabled, vModel } = attrBuilder(el);
|
||||
const size = `size="${el.size}"`;
|
||||
const showAlpha = el["show-alpha"] ? "show-alpha" : "";
|
||||
const colorFormat = el["color-format"]
|
||||
? `color-format="${el["color-format"]}"`
|
||||
: "";
|
||||
|
||||
return `<${tag} ${vModel} ${size} ${showAlpha} ${colorFormat} ${disabled}></${tag}>`
|
||||
return `<${tag} ${vModel} ${size} ${showAlpha} ${colorFormat} ${disabled}></${tag}>`;
|
||||
},
|
||||
'el-upload': el => {
|
||||
const { tag } = el.__config__
|
||||
const disabled = el.disabled ? ':disabled=\'true\'' : ''
|
||||
const action = el.action ? `:action="${el.__vModel__}Action"` : ''
|
||||
const multiple = el.multiple ? 'multiple' : ''
|
||||
const listType = el['list-type'] !== 'text' ? `list-type="${el['list-type']}"` : ''
|
||||
const accept = el.accept ? `accept="${el.accept}"` : ''
|
||||
const name = el.name !== 'file' ? `name="${el.name}"` : ''
|
||||
const autoUpload = el['auto-upload'] === false ? ':auto-upload="false"' : ''
|
||||
const beforeUpload = `:before-upload="${el.__vModel__}BeforeUpload"`
|
||||
const fileList = `:file-list="${el.__vModel__}fileList"`
|
||||
const ref = `ref="${el.__vModel__}"`
|
||||
let child = buildElUploadChild(el)
|
||||
"el-upload": (el) => {
|
||||
const { tag } = el.__config__;
|
||||
const disabled = el.disabled ? ":disabled='true'" : "";
|
||||
const action = el.action ? `:action="${el.__vModel__}Action"` : "";
|
||||
const multiple = el.multiple ? "multiple" : "";
|
||||
const listType =
|
||||
el["list-type"] !== "text" ? `list-type="${el["list-type"]}"` : "";
|
||||
const accept = el.accept ? `accept="${el.accept}"` : "";
|
||||
const name = el.name !== "file" ? `name="${el.name}"` : "";
|
||||
const autoUpload =
|
||||
el["auto-upload"] === false ? ':auto-upload="false"' : "";
|
||||
const beforeUpload = `:before-upload="${el.__vModel__}BeforeUpload"`;
|
||||
const fileList = `:file-list="${el.__vModel__}fileList"`;
|
||||
const ref = `ref="${el.__vModel__}"`;
|
||||
let child = buildElUploadChild(el);
|
||||
|
||||
if (child) child = `\n${child}\n` // 换行
|
||||
return `<${tag} ${ref} ${fileList} ${action} ${autoUpload} ${multiple} ${beforeUpload} ${listType} ${accept} ${name} ${disabled}>${child}</${tag}>`
|
||||
if (child) child = `\n${child}\n`; // 换行
|
||||
return `<${tag} ${ref} ${fileList} ${action} ${autoUpload} ${multiple} ${beforeUpload} ${listType} ${accept} ${name} ${disabled}>${child}</${tag}>`;
|
||||
},
|
||||
tinymce: el => {
|
||||
const { tag, vModel, placeholder } = attrBuilder(el)
|
||||
const height = el.height ? `:height="${el.height}"` : ''
|
||||
const branding = el.branding ? `:branding="${el.branding}"` : ''
|
||||
return `<${tag} ${vModel} ${placeholder} ${height} ${branding}></${tag}>`
|
||||
}
|
||||
}
|
||||
tinymce: (el) => {
|
||||
const { tag, vModel, placeholder } = attrBuilder(el);
|
||||
const height = el.height ? `:height="${el.height}"` : "";
|
||||
const branding = el.branding ? `:branding="${el.branding}"` : "";
|
||||
return `<${tag} ${vModel} ${placeholder} ${height} ${branding}></${tag}>`;
|
||||
},
|
||||
};
|
||||
|
||||
function attrBuilder(el) {
|
||||
return {
|
||||
tag: el.__config__.tag,
|
||||
vModel: `v-model="${confGlobal.formModel}.${el.__vModel__}"`,
|
||||
clearable: el.clearable ? 'clearable' : '',
|
||||
placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : '',
|
||||
width: el.style && el.style.width ? ':style="{width: \'100%\'}"' : '',
|
||||
disabled: el.disabled ? ':disabled=\'true\'' : ''
|
||||
}
|
||||
clearable: el.clearable ? "clearable" : "",
|
||||
placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : "",
|
||||
width: el.style && el.style.width ? ":style=\"{width: '100%'}\"" : "",
|
||||
disabled: el.disabled ? ":disabled='true'" : "",
|
||||
};
|
||||
}
|
||||
|
||||
// el-buttin 子级
|
||||
function buildElButtonChild(scheme) {
|
||||
const children = []
|
||||
const slot = scheme.__slot__ || {}
|
||||
const children = [];
|
||||
const slot = scheme.__slot__ || {};
|
||||
if (slot.default) {
|
||||
children.push(slot.default)
|
||||
children.push(slot.default);
|
||||
}
|
||||
return children.join('\n')
|
||||
return children.join("\n");
|
||||
}
|
||||
|
||||
// el-input 子级
|
||||
function buildElInputChild(scheme) {
|
||||
const children = []
|
||||
const slot = scheme.__slot__
|
||||
const children = [];
|
||||
const slot = scheme.__slot__;
|
||||
if (slot && slot.prepend) {
|
||||
children.push(`<template slot="prepend">${slot.prepend}</template>`)
|
||||
children.push(`<template slot="prepend">${slot.prepend}</template>`);
|
||||
}
|
||||
if (slot && slot.append) {
|
||||
children.push(`<template slot="append">${slot.append}</template>`)
|
||||
children.push(`<template slot="append">${slot.append}</template>`);
|
||||
}
|
||||
return children.join('\n')
|
||||
return children.join("\n");
|
||||
}
|
||||
|
||||
// el-select 子级
|
||||
function buildElSelectChild(scheme) {
|
||||
const children = []
|
||||
const slot = scheme.__slot__
|
||||
const children = [];
|
||||
const slot = scheme.__slot__;
|
||||
if (slot && slot.options && slot.options.length) {
|
||||
children.push(`<el-option v-for="(item, index) in ${scheme.__vModel__}Options" :key="index" :label="item.label" :value="item.value" :disabled="item.disabled"></el-option>`)
|
||||
children.push(
|
||||
`<el-option v-for="(item, index) in ${scheme.__vModel__}Options" :key="index" :label="item.label" :value="item.value" :disabled="item.disabled"></el-option>`
|
||||
);
|
||||
}
|
||||
return children.join('\n')
|
||||
return children.join("\n");
|
||||
}
|
||||
|
||||
// el-radio-group 子级
|
||||
function buildElRadioGroupChild(scheme) {
|
||||
const children = []
|
||||
const slot = scheme.__slot__
|
||||
const config = scheme.__config__
|
||||
const children = [];
|
||||
const slot = scheme.__slot__;
|
||||
const config = scheme.__config__;
|
||||
if (slot && slot.options && slot.options.length) {
|
||||
const tag = config.optionType === 'button' ? 'el-radio-button' : 'el-radio'
|
||||
const border = config.border ? 'border' : ''
|
||||
children.push(`<${tag} v-for="(item, index) in ${scheme.__vModel__}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`)
|
||||
const tag = config.optionType === "button" ? "el-radio-button" : "el-radio";
|
||||
const border = config.border ? "border" : "";
|
||||
children.push(
|
||||
`<${tag} v-for="(item, index) in ${scheme.__vModel__}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`
|
||||
);
|
||||
}
|
||||
return children.join('\n')
|
||||
return children.join("\n");
|
||||
}
|
||||
|
||||
// el-checkbox-group 子级
|
||||
function buildElCheckboxGroupChild(scheme) {
|
||||
const children = []
|
||||
const slot = scheme.__slot__
|
||||
const config = scheme.__config__
|
||||
const children = [];
|
||||
const slot = scheme.__slot__;
|
||||
const config = scheme.__config__;
|
||||
if (slot && slot.options && slot.options.length) {
|
||||
const tag = config.optionType === 'button' ? 'el-checkbox-button' : 'el-checkbox'
|
||||
const border = config.border ? 'border' : ''
|
||||
children.push(`<${tag} v-for="(item, index) in ${scheme.__vModel__}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`)
|
||||
const tag =
|
||||
config.optionType === "button" ? "el-checkbox-button" : "el-checkbox";
|
||||
const border = config.border ? "border" : "";
|
||||
children.push(
|
||||
`<${tag} v-for="(item, index) in ${scheme.__vModel__}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`
|
||||
);
|
||||
}
|
||||
return children.join('\n')
|
||||
return children.join("\n");
|
||||
}
|
||||
|
||||
// el-upload 子级
|
||||
function buildElUploadChild(scheme) {
|
||||
const list = []
|
||||
const config = scheme.__config__
|
||||
if (scheme['list-type'] === 'picture-card') list.push('<i class="el-icon-plus"></i>')
|
||||
else list.push(`<el-button size="small" type="primary" icon="el-icon-upload">${config.buttonText}</el-button>`)
|
||||
if (config.showTip) list.push(`<div slot="tip" class="el-upload__tip">只能上传不超过 ${config.fileSize}${config.sizeUnit} 的${scheme.accept}文件</div>`)
|
||||
return list.join('\n')
|
||||
const list = [];
|
||||
const config = scheme.__config__;
|
||||
if (scheme["list-type"] === "picture-card")
|
||||
list.push('<i class="el-icon-plus"></i>');
|
||||
else
|
||||
list.push(
|
||||
`<el-button size="small" type="primary" icon="el-icon-upload">${config.buttonText}</el-button>`
|
||||
);
|
||||
if (config.showTip)
|
||||
list.push(
|
||||
`<div slot="tip" class="el-upload__tip">只能上传不超过 ${config.fileSize}${config.sizeUnit} 的${scheme.accept}文件</div>`
|
||||
);
|
||||
return list.join("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -379,21 +439,23 @@ function buildElUploadChild(scheme) {
|
||||
* @param {String} type 生成类型,文件或弹窗等
|
||||
*/
|
||||
export function makeUpHtml(formConfig, type) {
|
||||
const htmlList = []
|
||||
confGlobal = formConfig
|
||||
const htmlList = [];
|
||||
confGlobal = formConfig;
|
||||
// 判断布局是否都沾满了24个栅格,以备后续简化代码结构
|
||||
someSpanIsNot24 = formConfig.fields.some(item => item.__config__.span !== 24)
|
||||
someSpanIsNot24 = formConfig.fields.some(
|
||||
(item) => item.__config__.span !== 24
|
||||
);
|
||||
// 遍历渲染每个组件成html
|
||||
formConfig.fields.forEach(el => {
|
||||
htmlList.push(layouts[el.__config__.layout](el))
|
||||
})
|
||||
const htmlStr = htmlList.join('\n')
|
||||
formConfig.fields.forEach((el) => {
|
||||
htmlList.push(layouts[el.__config__.layout](el));
|
||||
});
|
||||
const htmlStr = htmlList.join("\n");
|
||||
// 将组件代码放进form标签
|
||||
let temp = buildFormTemplate(formConfig, htmlStr, type)
|
||||
let temp = buildFormTemplate(formConfig, htmlStr, type);
|
||||
// dialog标签包裹代码
|
||||
if (type === 'dialog') {
|
||||
temp = dialogWrapper(temp)
|
||||
if (type === "dialog") {
|
||||
temp = dialogWrapper(temp);
|
||||
}
|
||||
confGlobal = null
|
||||
return temp
|
||||
confGlobal = null;
|
||||
return temp;
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
import { isArray } from 'util'
|
||||
import { exportDefault, titleCase, deepClone } from '@/utils/index'
|
||||
import ruleTrigger from './ruleTrigger'
|
||||
// import { Array.isArray } from 'util'
|
||||
import { exportDefault, titleCase, deepClone } from "@/utils/index";
|
||||
import ruleTrigger from "./ruleTrigger";
|
||||
|
||||
const units = {
|
||||
KB: '1024',
|
||||
MB: '1024 / 1024',
|
||||
GB: '1024 / 1024 / 1024'
|
||||
}
|
||||
let confGlobal
|
||||
KB: "1024",
|
||||
MB: "1024 / 1024",
|
||||
GB: "1024 / 1024 / 1024",
|
||||
};
|
||||
let confGlobal;
|
||||
const inheritAttrs = {
|
||||
file: '',
|
||||
dialog: 'inheritAttrs: false,'
|
||||
}
|
||||
file: "",
|
||||
dialog: "inheritAttrs: false,",
|
||||
};
|
||||
|
||||
/**
|
||||
* 组装js 【入口函数】
|
||||
@ -19,212 +19,263 @@ const inheritAttrs = {
|
||||
* @param {String} type 生成类型,文件或弹窗等
|
||||
*/
|
||||
export function makeUpJs(formConfig, type) {
|
||||
confGlobal = formConfig = deepClone(formConfig)
|
||||
const dataList = []
|
||||
const ruleList = []
|
||||
const optionsList = []
|
||||
const propsList = []
|
||||
const methodList = mixinMethod(type)
|
||||
const uploadVarList = []
|
||||
const created = []
|
||||
|
||||
formConfig.fields.forEach(el => {
|
||||
buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created)
|
||||
})
|
||||
confGlobal = formConfig = deepClone(formConfig);
|
||||
const dataList = [];
|
||||
const ruleList = [];
|
||||
const optionsList = [];
|
||||
const propsList = [];
|
||||
const methodList = mixinMethod(type);
|
||||
const uploadVarList = [];
|
||||
const created = [];
|
||||
|
||||
formConfig.fields.forEach((el) => {
|
||||
buildAttributes(
|
||||
el,
|
||||
dataList,
|
||||
ruleList,
|
||||
optionsList,
|
||||
methodList,
|
||||
propsList,
|
||||
uploadVarList,
|
||||
created
|
||||
);
|
||||
});
|
||||
console.log(
|
||||
dataList,
|
||||
ruleList,
|
||||
optionsList,
|
||||
methodList,
|
||||
propsList,
|
||||
uploadVarList,
|
||||
created
|
||||
);
|
||||
const script = buildexport(
|
||||
formConfig,
|
||||
type,
|
||||
dataList.join('\n'),
|
||||
ruleList.join('\n'),
|
||||
optionsList.join('\n'),
|
||||
uploadVarList.join('\n'),
|
||||
propsList.join('\n'),
|
||||
methodList.join('\n'),
|
||||
created.join('\n')
|
||||
)
|
||||
confGlobal = null
|
||||
return script
|
||||
dataList.join("\n"),
|
||||
ruleList.join("\n"),
|
||||
optionsList.join("\n"),
|
||||
uploadVarList.join("\n"),
|
||||
propsList.join("\n"),
|
||||
methodList.join("\n"),
|
||||
created.join("\n")
|
||||
);
|
||||
confGlobal = null;
|
||||
return script;
|
||||
}
|
||||
|
||||
// 构建组件属性
|
||||
function buildAttributes(scheme, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created) {
|
||||
const config = scheme.__config__
|
||||
const slot = scheme.__slot__
|
||||
buildData(scheme, dataList)
|
||||
buildRules(scheme, ruleList)
|
||||
function buildAttributes(
|
||||
scheme,
|
||||
dataList,
|
||||
ruleList,
|
||||
optionsList,
|
||||
methodList,
|
||||
propsList,
|
||||
uploadVarList,
|
||||
created
|
||||
) {
|
||||
const config = scheme.__config__;
|
||||
const slot = scheme.__slot__;
|
||||
buildData(scheme, dataList);
|
||||
buildRules(scheme, ruleList);
|
||||
|
||||
// 特殊处理options属性
|
||||
if (scheme.options || (slot && slot.options && slot.options.length)) {
|
||||
buildOptions(scheme, optionsList)
|
||||
if (config.dataType === 'dynamic') {
|
||||
const model = `${scheme.__vModel__}Options`
|
||||
const options = titleCase(model)
|
||||
const methodName = `get${options}`
|
||||
buildOptionMethod(methodName, model, methodList, scheme)
|
||||
callInCreated(methodName, created)
|
||||
buildOptions(scheme, optionsList);
|
||||
if (config.dataType === "dynamic") {
|
||||
const model = `${scheme.__vModel__}Options`;
|
||||
const options = titleCase(model);
|
||||
const methodName = `get${options}`;
|
||||
buildOptionMethod(methodName, model, methodList, scheme);
|
||||
callInCreated(methodName, created);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理props
|
||||
if (scheme.props && scheme.props.props) {
|
||||
buildProps(scheme, propsList)
|
||||
buildProps(scheme, propsList);
|
||||
}
|
||||
|
||||
// 处理el-upload的action
|
||||
if (scheme.action && config.tag === 'el-upload') {
|
||||
if (scheme.action && config.tag === "el-upload") {
|
||||
uploadVarList.push(
|
||||
`${scheme.__vModel__}Action: '${scheme.action}',
|
||||
${scheme.__vModel__}fileList: [],`
|
||||
)
|
||||
methodList.push(buildBeforeUpload(scheme))
|
||||
);
|
||||
methodList.push(buildBeforeUpload(scheme));
|
||||
// 非自动上传时,生成手动上传的函数
|
||||
if (!scheme['auto-upload']) {
|
||||
methodList.push(buildSubmitUpload(scheme))
|
||||
if (!scheme["auto-upload"]) {
|
||||
methodList.push(buildSubmitUpload(scheme));
|
||||
}
|
||||
}
|
||||
|
||||
// 构建子级组件属性
|
||||
if (config.children) {
|
||||
config.children.forEach(item => {
|
||||
buildAttributes(item, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created)
|
||||
})
|
||||
config.children.forEach((item) => {
|
||||
buildAttributes(
|
||||
item,
|
||||
dataList,
|
||||
ruleList,
|
||||
optionsList,
|
||||
methodList,
|
||||
propsList,
|
||||
uploadVarList,
|
||||
created
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 在Created调用函数
|
||||
function callInCreated(methodName, created) {
|
||||
created.push(`this.${methodName}()`)
|
||||
created.push(`this.${methodName}()`);
|
||||
}
|
||||
|
||||
// 混入处理函数
|
||||
function mixinMethod(type) {
|
||||
const list = []; const
|
||||
minxins = {
|
||||
file: confGlobal.formBtns ? {
|
||||
submitForm: `submitForm() {
|
||||
this.$refs['${confGlobal.formRef}'].validate(valid => {
|
||||
const list = [];
|
||||
const minxins = {
|
||||
file: confGlobal.formBtns
|
||||
? {
|
||||
submitForm: `const submitForm = () => {
|
||||
${confGlobal.formRef}.value.validate(valid => {
|
||||
if(!valid) return
|
||||
// TODO 提交表单
|
||||
})
|
||||
}`,
|
||||
resetForm: `const resetForm = () => {
|
||||
${confGlobal.formRef}.value.resetFields()
|
||||
}`,
|
||||
}
|
||||
: null,
|
||||
dialog: {
|
||||
onOpen: "const onOpen = () => {},",
|
||||
onClose: `const onClose = () => {
|
||||
${confGlobal.formRef}.value.resetFields()
|
||||
},`,
|
||||
resetForm: `resetForm() {
|
||||
this.$refs['${confGlobal.formRef}'].resetFields()
|
||||
},`
|
||||
} : null,
|
||||
dialog: {
|
||||
onOpen: 'onOpen() {},',
|
||||
onClose: `onClose() {
|
||||
this.$refs['${confGlobal.formRef}'].resetFields()
|
||||
},`,
|
||||
close: `close() {
|
||||
close: `const close = () => {
|
||||
this.$emit('update:visible', false)
|
||||
},`,
|
||||
handelConfirm: `handelConfirm() {
|
||||
this.$refs['${confGlobal.formRef}'].validate(valid => {
|
||||
handelConfirm: `const handelConfirm = () => {
|
||||
${confGlobal.formRef}.value.validate(valid => {
|
||||
if(!valid) return
|
||||
this.close()
|
||||
})
|
||||
},`
|
||||
}
|
||||
}
|
||||
},`,
|
||||
},
|
||||
};
|
||||
|
||||
const methods = minxins[type]
|
||||
const methods = minxins[type];
|
||||
if (methods) {
|
||||
Object.keys(methods).forEach(key => {
|
||||
list.push(methods[key])
|
||||
})
|
||||
Object.keys(methods).forEach((key) => {
|
||||
list.push(methods[key]);
|
||||
});
|
||||
}
|
||||
|
||||
return list
|
||||
return list;
|
||||
}
|
||||
|
||||
// 构建data
|
||||
function buildData(scheme, dataList) {
|
||||
const config = scheme.__config__
|
||||
if (scheme.__vModel__ === undefined) return
|
||||
const defaultValue = JSON.stringify(config.defaultValue)
|
||||
dataList.push(`${scheme.__vModel__}: ${defaultValue},`)
|
||||
const config = scheme.__config__;
|
||||
if (scheme.__vModel__ === undefined) return;
|
||||
const defaultValue = JSON.stringify(config.defaultValue);
|
||||
dataList.push(`${scheme.__vModel__}: ${defaultValue},`);
|
||||
}
|
||||
|
||||
// 构建校验规则
|
||||
function buildRules(scheme, ruleList) {
|
||||
const config = scheme.__config__
|
||||
if (scheme.__vModel__ === undefined) return
|
||||
const rules = []
|
||||
const config = scheme.__config__;
|
||||
if (scheme.__vModel__ === undefined) return;
|
||||
const rules = [];
|
||||
if (ruleTrigger[config.tag]) {
|
||||
if (config.required) {
|
||||
const type = isArray(config.defaultValue) ? 'type: \'array\',' : ''
|
||||
let message = isArray(config.defaultValue) ? `请至少选择一个${config.label}` : scheme.placeholder
|
||||
if (message === undefined) message = `${config.label}不能为空`
|
||||
rules.push(`{ required: true, ${type} message: '${message}', trigger: '${ruleTrigger[config.tag]}' }`)
|
||||
const type = Array.isArray(config.defaultValue) ? "type: 'array'," : "";
|
||||
let message = Array.isArray(config.defaultValue)
|
||||
? `请至少选择一个${config.label}`
|
||||
: scheme.placeholder;
|
||||
if (message === undefined) message = `${config.label}不能为空`;
|
||||
rules.push(
|
||||
`{ required: true, ${type} message: '${message}', trigger: '${
|
||||
ruleTrigger[config.tag]
|
||||
}' }`
|
||||
);
|
||||
}
|
||||
if (config.regList && isArray(config.regList)) {
|
||||
config.regList.forEach(item => {
|
||||
if (config.regList && Array.isArray(config.regList)) {
|
||||
config.regList.forEach((item) => {
|
||||
if (item.pattern) {
|
||||
rules.push(
|
||||
`{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${ruleTrigger[config.tag]}' }`
|
||||
)
|
||||
`{ pattern: ${eval(item.pattern)}, message: '${
|
||||
item.message
|
||||
}', trigger: '${ruleTrigger[config.tag]}' }`
|
||||
);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
ruleList.push(`${scheme.__vModel__}: [${rules.join(',')}],`)
|
||||
ruleList.push(`${scheme.__vModel__}: [${rules.join(",")}],`);
|
||||
}
|
||||
}
|
||||
|
||||
// 构建options
|
||||
function buildOptions(scheme, optionsList) {
|
||||
if (scheme.__vModel__ === undefined) return
|
||||
if (scheme.__vModel__ === undefined) return;
|
||||
// el-cascader直接有options属性,其他组件都是定义在slot中,所以有两处判断
|
||||
let { options } = scheme
|
||||
if (!options) options = scheme.__slot__.options
|
||||
if (scheme.__config__.dataType === 'dynamic') { options = [] }
|
||||
const str = `${scheme.__vModel__}Options: ${JSON.stringify(options)},`
|
||||
optionsList.push(str)
|
||||
let { options } = scheme;
|
||||
if (!options) options = scheme.__slot__.options;
|
||||
if (scheme.__config__.dataType === "dynamic") {
|
||||
options = [];
|
||||
}
|
||||
const str = `${scheme.__vModel__}Options: ${JSON.stringify(options)},`;
|
||||
optionsList.push(str);
|
||||
}
|
||||
|
||||
function buildProps(scheme, propsList) {
|
||||
const str = `${scheme.__vModel__}Props: ${JSON.stringify(scheme.props.props)},`
|
||||
propsList.push(str)
|
||||
const str = `${scheme.__vModel__}Props: ${JSON.stringify(
|
||||
scheme.props.props
|
||||
)},`;
|
||||
propsList.push(str);
|
||||
}
|
||||
|
||||
// el-upload的BeforeUpload
|
||||
function buildBeforeUpload(scheme) {
|
||||
const config = scheme.__config__
|
||||
const unitNum = units[config.sizeUnit]; let rightSizeCode = ''; let acceptCode = ''; const
|
||||
returnList = []
|
||||
const config = scheme.__config__;
|
||||
const unitNum = units[config.sizeUnit];
|
||||
let rightSizeCode = "";
|
||||
let acceptCode = "";
|
||||
const returnList = [];
|
||||
if (config.fileSize) {
|
||||
rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${config.fileSize}
|
||||
if(!isRightSize){
|
||||
this.$message.error('文件大小超过 ${config.fileSize}${config.sizeUnit}')
|
||||
}`
|
||||
returnList.push('isRightSize')
|
||||
}`;
|
||||
returnList.push("isRightSize");
|
||||
}
|
||||
if (scheme.accept) {
|
||||
acceptCode = `let isAccept = new RegExp('${scheme.accept}').test(file.type)
|
||||
if(!isAccept){
|
||||
this.$message.error('应该选择${scheme.accept}类型的文件')
|
||||
}`
|
||||
returnList.push('isAccept')
|
||||
}`;
|
||||
returnList.push("isAccept");
|
||||
}
|
||||
const str = `${scheme.__vModel__}BeforeUpload(file) {
|
||||
${rightSizeCode}
|
||||
${acceptCode}
|
||||
return ${returnList.join('&&')}
|
||||
},`
|
||||
return returnList.length ? str : ''
|
||||
return ${returnList.join("&&")}
|
||||
},`;
|
||||
return returnList.length ? str : "";
|
||||
}
|
||||
|
||||
// el-upload的submit
|
||||
function buildSubmitUpload(scheme) {
|
||||
const str = `submitUpload() {
|
||||
this.$refs['${scheme.__vModel__}'].submit()
|
||||
},`
|
||||
return str
|
||||
},`;
|
||||
return str;
|
||||
}
|
||||
|
||||
function buildOptionMethod(methodName, model, methodList, scheme) {
|
||||
const config = scheme.__config__
|
||||
const config = scheme.__config__;
|
||||
const str = `${methodName}() {
|
||||
// 注意:this.$axios是通过Vue.prototype.$axios = axios挂载产生的
|
||||
this.$axios({
|
||||
@ -234,12 +285,42 @@ function buildOptionMethod(methodName, model, methodList, scheme) {
|
||||
var { data } = resp
|
||||
this.${model} = data.${config.dataKey}
|
||||
})
|
||||
},`
|
||||
methodList.push(str)
|
||||
},`;
|
||||
methodList.push(str);
|
||||
}
|
||||
|
||||
// js整体拼接
|
||||
function buildexport(conf, type, data, rules, selectOptions, uploadVar, props, methods, created) {
|
||||
function buildexport(
|
||||
conf,
|
||||
type,
|
||||
data,
|
||||
rules,
|
||||
selectOptions,
|
||||
uploadVar,
|
||||
props,
|
||||
methods,
|
||||
created
|
||||
) {
|
||||
const newStr = `
|
||||
import { ref, reactive, toRefs } from "vue";
|
||||
|
||||
const data = reactive({
|
||||
${conf.formModel}: {
|
||||
${data}
|
||||
},
|
||||
${conf.formRules}: {
|
||||
${rules}
|
||||
},
|
||||
})
|
||||
|
||||
const { ${conf.formModel}, ${conf.formRules} } = toRefs(data);
|
||||
const ${confGlobal.formRef} = ref();
|
||||
${methods}
|
||||
|
||||
${created}
|
||||
`;
|
||||
return newStr;
|
||||
|
||||
const str = `${exportDefault}{
|
||||
${inheritAttrs[type]}
|
||||
components: {},
|
||||
@ -266,6 +347,6 @@ function buildexport(conf, type, data, rules, selectOptions, uploadVar, props, m
|
||||
methods: {
|
||||
${methods}
|
||||
}
|
||||
}`
|
||||
return str
|
||||
}`;
|
||||
return str;
|
||||
}
|
||||
|
@ -1,33 +1,39 @@
|
||||
import { deepClone } from "@/utils/index";
|
||||
import {
|
||||
ElButton,
|
||||
ElColorPicker,
|
||||
ElDatePicker,
|
||||
ElInput,
|
||||
ElInputNumber,
|
||||
ElRate,
|
||||
ElRow,
|
||||
ElSelect,
|
||||
ElRate,
|
||||
ElInput,
|
||||
ElSlider,
|
||||
ElSelect,
|
||||
ElButton,
|
||||
ElSwitch,
|
||||
ElTimePicker,
|
||||
ElUpload,
|
||||
ElCascader,
|
||||
ElDatePicker,
|
||||
ElTimePicker,
|
||||
ElRadioGroup,
|
||||
ElColorPicker,
|
||||
ElInputNumber,
|
||||
ElCheckboxGroup,
|
||||
} from "element-plus";
|
||||
import { h, defineComponent } from "vue";
|
||||
// import "element-plus/es/components/input";
|
||||
|
||||
const formComponentsMap = {
|
||||
"el-row": ElRow,
|
||||
"el-rate": ElRate,
|
||||
"el-input": ElInput,
|
||||
"el-input-number": ElInputNumber,
|
||||
"el-switch": ElSwitch,
|
||||
"el-select": ElSelect,
|
||||
"el-time-picker": ElTimePicker,
|
||||
"el-color-picker": ElColorPicker,
|
||||
"el-date-picker": ElDatePicker,
|
||||
"el-button": ElButton,
|
||||
"el-row": ElRow,
|
||||
"el-slider": ElSlider,
|
||||
"el-rate": ElRate,
|
||||
"el-upload": ElUpload,
|
||||
"el-button": ElButton,
|
||||
"el-slider": ElSlider,
|
||||
"el-cascader": ElCascader,
|
||||
"el-time-picker": ElTimePicker,
|
||||
"el-radio-group": ElRadioGroup,
|
||||
"el-date-picker": ElDatePicker,
|
||||
"el-input-number": ElInputNumber,
|
||||
"el-color-picker": ElColorPicker,
|
||||
"el-checkbox-group": ElCheckboxGroup,
|
||||
};
|
||||
|
||||
const componentChild = {};
|
||||
@ -46,11 +52,7 @@ keys.forEach((key) => {
|
||||
|
||||
function vModel(dataObject, defaultValue) {
|
||||
dataObject.props.value = defaultValue;
|
||||
// dataObject.onInput = (val) => {
|
||||
// this.$emit("input", val);
|
||||
// };
|
||||
dataObject.on.input = (val) => {
|
||||
console.log(val, "input");
|
||||
this.$emit("input", val);
|
||||
};
|
||||
dataObject.on.change = (val) => {
|
||||
@ -59,13 +61,13 @@ function vModel(dataObject, defaultValue) {
|
||||
};
|
||||
}
|
||||
|
||||
function mountSlotFiles(h, confClone, children) {
|
||||
function mountSlotFiles(confClone, children) {
|
||||
const childObjs = componentChild[confClone.__config__.tag];
|
||||
if (childObjs) {
|
||||
Object.keys(childObjs).forEach((key) => {
|
||||
const childFunc = childObjs[key];
|
||||
if (confClone.__slot__ && confClone.__slot__[key]) {
|
||||
children.push(childFunc(h, confClone, key));
|
||||
children.push(childFunc(confClone, key));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -172,105 +174,141 @@ export default defineComponent({
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
arr: [],
|
||||
tempTime: "",
|
||||
};
|
||||
},
|
||||
emits: ["input"],
|
||||
// setup(props, { slots, emit }) {
|
||||
// const dataObject = makeDataObject();
|
||||
// const confClone = deepClone(props.conf);
|
||||
// // const children = [this.$slots.default] || [];
|
||||
// console.log(slots, "slots");
|
||||
// const children = [];
|
||||
// // 如果slots文件夹存在与当前tag同名的文件,则执行文件中的代码
|
||||
// mountSlotFiles(h, confClone, children);
|
||||
|
||||
// // 将字符串类型的事件,发送为消息
|
||||
// emitEvents(emit, confClone);
|
||||
// setTimeout(() => {
|
||||
// emit("input", "4ww3243");
|
||||
// }, 3000);
|
||||
// // 将json表单配置转化为vue render可以识别的 “数据对象(dataObject)”
|
||||
// const update = (val) => {
|
||||
// console.log(val, "update");
|
||||
// emit("input", val);
|
||||
// };
|
||||
// buildDataObject(update, confClone, dataObject);
|
||||
|
||||
// const Tag = formComponentsMap[props.conf.__config__.tag];
|
||||
|
||||
// return () => (
|
||||
// <Tag
|
||||
// {...dataObject.attrs}
|
||||
// on={dataObject.on}
|
||||
// modelValue={confClone.__config__.defaultValue}
|
||||
// >
|
||||
// {children}
|
||||
// </Tag>
|
||||
// );
|
||||
// },
|
||||
render() {
|
||||
const dataObject = makeDataObject();
|
||||
const confClone = deepClone(this.conf);
|
||||
|
||||
// const children = [this.$slots.default] || [];
|
||||
const confClone = deepClone(this.$props.conf);
|
||||
const children = [];
|
||||
// 如果slots文件夹存在与当前tag同名的文件,则执行文件中的代码
|
||||
mountSlotFiles(h, confClone, children);
|
||||
|
||||
mountSlotFiles(confClone, children);
|
||||
// 将字符串类型的事件,发送为消息
|
||||
emitEvents.call(this, confClone);
|
||||
|
||||
// 将json表单配置转化为vue render可以识别的 “数据对象(dataObject)”
|
||||
buildDataObject.call(this, confClone, dataObject);
|
||||
console.log(dataObject);
|
||||
// return () => h("el-input", dataObject.attrs);
|
||||
|
||||
const Tag = formComponentsMap[this.conf.__config__.tag];
|
||||
const Tag = formComponentsMap[this.$props.conf.__config__.tag];
|
||||
return (
|
||||
<Tag
|
||||
{...dataObject.attrs}
|
||||
on={dataObject.on}
|
||||
modelValue={confClone.__config__.defaultValue}
|
||||
v-model={this.$props.conf.__config__.defaultValue}
|
||||
>
|
||||
{children}
|
||||
</Tag>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{tag == "el-input" ? (
|
||||
<el-input
|
||||
{...dataObject.attrs}
|
||||
on={dataObject.on}
|
||||
modelValue={confClone.__config__.defaultValue}
|
||||
>
|
||||
{children}
|
||||
</el-input>
|
||||
) : tag == "el-input-number" ? (
|
||||
<el-input-number
|
||||
{...dataObject.attrs}
|
||||
on={dataObject.on}
|
||||
modelValue={confClone.__config__.defaultValue}
|
||||
>
|
||||
{children}
|
||||
</el-input-number>
|
||||
) : tag == "el-slider" ? (
|
||||
<el-slider
|
||||
{...dataObject.attrs}
|
||||
on={dataObject.on}
|
||||
modelValue={confClone.__config__.defaultValue}
|
||||
>
|
||||
{children}
|
||||
</el-slider>
|
||||
) : tag == "el-time-picker" ? (
|
||||
<el-date-picker
|
||||
type="datetimerange"
|
||||
on={dataObject.on}
|
||||
modelValue={confClone.__config__.defaultValue}
|
||||
/>
|
||||
) : tag === "el-switch" ? (
|
||||
<el-switch
|
||||
{...dataObject.attrs}
|
||||
on={dataObject.on}
|
||||
modelValue={confClone.__config__.defaultValue}
|
||||
></el-switch>
|
||||
) : tag === "el-color-picker" ? (
|
||||
<el-color-picker
|
||||
{...dataObject.attrs}
|
||||
on={dataObject.on}
|
||||
modelValue={confClone.__config__.defaultValue}
|
||||
></el-color-picker>
|
||||
) : tag === "el-button" ? (
|
||||
<el-button
|
||||
{...dataObject.attrs}
|
||||
on={dataObject.on}
|
||||
modelValue={confClone.__config__.defaultValue}
|
||||
>
|
||||
{children[1]}
|
||||
</el-button>
|
||||
) : tag === "el-select" ? (
|
||||
<el-select
|
||||
{...dataObject.attrs}
|
||||
on={dataObject.on}
|
||||
modelValue={confClone.__config__.defaultValue}
|
||||
>
|
||||
{children}
|
||||
</el-select>
|
||||
) : tag === "el-date-picker" ? (
|
||||
<el-date-picker
|
||||
{...dataObject.attrs}
|
||||
on={dataObject.on}
|
||||
modelValue={confClone.__config__.defaultValue}
|
||||
>
|
||||
{children}
|
||||
</el-date-picker>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
},
|
||||
// render() {
|
||||
|
||||
// return (
|
||||
// <>
|
||||
// {tag == "el-input" ? (
|
||||
// <el-input
|
||||
// {...dataObject.attrs}
|
||||
// on={dataObject.on}
|
||||
// modelValue={confClone.__config__.defaultValue}
|
||||
// >
|
||||
// {children}
|
||||
// </el-input>
|
||||
// ) : tag == "el-input-number" ? (
|
||||
// <el-input-number
|
||||
// {...dataObject.attrs}
|
||||
// on={dataObject.on}
|
||||
// modelValue={confClone.__config__.defaultValue}
|
||||
// >
|
||||
// {children}
|
||||
// </el-input-number>
|
||||
// ) : tag == "el-slider" ? (
|
||||
// <el-slider
|
||||
// {...dataObject.attrs}
|
||||
// on={dataObject.on}
|
||||
// modelValue={confClone.__config__.defaultValue}
|
||||
// >
|
||||
// {children}
|
||||
// </el-slider>
|
||||
// ) : tag == "el-time-picker" ? (
|
||||
// <el-date-picker
|
||||
// type="datetimerange"
|
||||
// on={dataObject.on}
|
||||
// modelValue={confClone.__config__.defaultValue}
|
||||
// />
|
||||
// ) : tag === "el-switch" ? (
|
||||
// <el-switch
|
||||
// {...dataObject.attrs}
|
||||
// on={dataObject.on}
|
||||
// modelValue={confClone.__config__.defaultValue}
|
||||
// ></el-switch>
|
||||
// ) : tag === "el-color-picker" ? (
|
||||
// <el-color-picker
|
||||
// {...dataObject.attrs}
|
||||
// on={dataObject.on}
|
||||
// modelValue={confClone.__config__.defaultValue}
|
||||
// ></el-color-picker>
|
||||
// ) : tag === "el-button" ? (
|
||||
// <el-button
|
||||
// {...dataObject.attrs}
|
||||
// on={dataObject.on}
|
||||
// modelValue={confClone.__config__.defaultValue}
|
||||
// >
|
||||
// {children[1]}
|
||||
// </el-button>
|
||||
// ) : tag === "el-select" ? (
|
||||
// <el-select
|
||||
// {...dataObject.attrs}
|
||||
// on={dataObject.on}
|
||||
// modelValue={confClone.__config__.defaultValue}
|
||||
// >
|
||||
// {children}
|
||||
// </el-select>
|
||||
// ) : tag === "el-date-picker" ? (
|
||||
// <el-date-picker
|
||||
// {...dataObject.attrs}
|
||||
// on={dataObject.on}
|
||||
// modelValue={confClone.__config__.defaultValue}
|
||||
// >
|
||||
// {children}
|
||||
// </el-date-picker>
|
||||
// ) : null}
|
||||
// </>
|
||||
// );
|
||||
// },
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
export default {
|
||||
default(h, conf, key) {
|
||||
return conf.__slot__[key]
|
||||
}
|
||||
}
|
||||
default(conf, key) {
|
||||
return conf.__slot__[key];
|
||||
},
|
||||
};
|
||||
|
@ -1,13 +1,21 @@
|
||||
export default {
|
||||
options(h, conf, key) {
|
||||
const list = []
|
||||
conf.__slot__.options.forEach(item => {
|
||||
if (conf.__config__.optionType === 'button') {
|
||||
list.push(<el-checkbox-button label={item.value}>{item.label}</el-checkbox-button>)
|
||||
options(conf, key) {
|
||||
const list = [];
|
||||
conf.__slot__.options.forEach((item) => {
|
||||
if (conf.__config__.optionType === "button") {
|
||||
list.push(
|
||||
<el-checkbox-button label={item.value}>
|
||||
{item.label}
|
||||
</el-checkbox-button>
|
||||
);
|
||||
} else {
|
||||
list.push(<el-checkbox label={item.value} border={conf.border}>{item.label}</el-checkbox>)
|
||||
list.push(
|
||||
<el-checkbox label={item.value} border={conf.border}>
|
||||
{item.label}
|
||||
</el-checkbox>
|
||||
);
|
||||
}
|
||||
})
|
||||
return list
|
||||
}
|
||||
}
|
||||
});
|
||||
return list;
|
||||
},
|
||||
};
|
||||
|
@ -1,8 +1,8 @@
|
||||
export default {
|
||||
prepend(h, conf, key) {
|
||||
return <template slot="prepend">{conf.__slot__[key]}</template>
|
||||
prepend(conf, key) {
|
||||
return <template slot="prepend">{conf.__slot__[key]}</template>;
|
||||
},
|
||||
append(h, conf, key) {
|
||||
return <template slot="append">{conf.__slot__[key]}</template>
|
||||
}
|
||||
}
|
||||
append(conf, key) {
|
||||
return <template slot="append">{conf.__slot__[key]}</template>;
|
||||
},
|
||||
};
|
||||
|
@ -1,13 +1,19 @@
|
||||
export default {
|
||||
options(h, conf, key) {
|
||||
const list = []
|
||||
conf.__slot__.options.forEach(item => {
|
||||
if (conf.__config__.optionType === 'button') {
|
||||
list.push(<el-radio-button label={item.value}>{item.label}</el-radio-button>)
|
||||
options(conf, key) {
|
||||
const list = [];
|
||||
conf.__slot__.options.forEach((item) => {
|
||||
if (conf.__config__.optionType === "button") {
|
||||
list.push(
|
||||
<el-radio-button label={item.value}>{item.label}</el-radio-button>
|
||||
);
|
||||
} else {
|
||||
list.push(<el-radio label={item.value} border={conf.border}>{item.label}</el-radio>)
|
||||
list.push(
|
||||
<el-radio label={item.value} border={conf.border}>
|
||||
{item.label}
|
||||
</el-radio>
|
||||
);
|
||||
}
|
||||
})
|
||||
return list
|
||||
}
|
||||
}
|
||||
});
|
||||
return list;
|
||||
},
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
export default {
|
||||
options(h, conf, key) {
|
||||
options(conf, key) {
|
||||
const list = [];
|
||||
conf.__slot__.options.forEach((item) => {
|
||||
list.push(
|
||||
|
@ -1,17 +1,24 @@
|
||||
export default {
|
||||
'list-type': (h, conf, key) => {
|
||||
const list = []
|
||||
const config = conf.__config__
|
||||
if (conf['list-type'] === 'picture-card') {
|
||||
list.push(<i class="el-icon-plus"></i>)
|
||||
"list-type": (conf, key) => {
|
||||
const list = [];
|
||||
const config = conf.__config__;
|
||||
if (conf["list-type"] === "picture-card") {
|
||||
list.push(<i class="el-icon-plus"></i>);
|
||||
} else {
|
||||
list.push(<el-button size="small" type="primary" icon="el-icon-upload">{config.buttonText}</el-button>)
|
||||
list.push(
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">
|
||||
{config.buttonText}
|
||||
</el-button>
|
||||
);
|
||||
}
|
||||
if (config.showTip) {
|
||||
list.push(
|
||||
<div slot="tip" class="el-upload__tip">只能上传不超过 {config.fileSize}{config.sizeUnit} 的{conf.accept}文件</div>
|
||||
)
|
||||
<div slot="tip" class="el-upload__tip">
|
||||
只能上传不超过 {config.fileSize}
|
||||
{config.sizeUnit} 的{conf.accept}文件
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return list
|
||||
}
|
||||
}
|
||||
return list;
|
||||
},
|
||||
};
|
||||
|
@ -22,7 +22,6 @@ export default function loadBeautifier(cb) {
|
||||
loadScript(beautifierUrl, () => {
|
||||
loading.close();
|
||||
// eslint-disable-next-line no-undef
|
||||
console.log(beautifier);
|
||||
beautifierObj = beautifier;
|
||||
cb(beautifierObj);
|
||||
});
|
||||
|
@ -5,16 +5,15 @@
|
||||
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"
|
||||
ref="elFormRef"
|
||||
size="default"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-col :span="24">
|
||||
@ -31,76 +30,116 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="showFileName" label="文件名" prop="fileName">
|
||||
<el-input v-model="formData.fileName" placeholder="请输入文件名" clearable />
|
||||
<el-input
|
||||
v-model="formData.fileName"
|
||||
placeholder="请输入文件名"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-form>
|
||||
|
||||
<!-- <el-form
|
||||
ref="elForm"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
size="default"
|
||||
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>
|
||||
<el-button @click="close"> 取消 </el-button>
|
||||
<el-button type="primary" @click="handleConfirm"> 确定 </el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, toRefs } from "vue";
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "confirm"]);
|
||||
const props = defineProps(["showFileName"]);
|
||||
|
||||
const { showFileName } = toRefs(props);
|
||||
const data = reactive({
|
||||
formData: {
|
||||
fileName: undefined,
|
||||
type: "file",
|
||||
},
|
||||
rules: {
|
||||
fileName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入文件名",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
type: [
|
||||
{
|
||||
required: true,
|
||||
message: "生成类型不能为空",
|
||||
trigger: "change",
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const { formData, rules } = toRefs(data);
|
||||
const elFormRef = ref();
|
||||
const typeOptions = ref([
|
||||
{
|
||||
label: "页面",
|
||||
value: "file",
|
||||
},
|
||||
{
|
||||
label: "弹窗",
|
||||
value: "dialog",
|
||||
},
|
||||
]);
|
||||
|
||||
const onOpen = () => {
|
||||
if (showFileName.value) {
|
||||
formData.value.fileName = `${+new Date()}.vue`;
|
||||
}
|
||||
};
|
||||
const onClose = () => {};
|
||||
const close = (e) => {
|
||||
emit("update:modelValue", false);
|
||||
};
|
||||
const handleConfirm = () => {
|
||||
elFormRef.value.validate((valid) => {
|
||||
if (!valid) return;
|
||||
emit("confirm", { ...formData.value });
|
||||
close();
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<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>
|
||||
|
@ -37,13 +37,13 @@ const components = {
|
||||
const layouts = {
|
||||
colFormItem(
|
||||
// h,
|
||||
currentItem,
|
||||
index,
|
||||
list
|
||||
currentItem
|
||||
// index,
|
||||
// list
|
||||
) {
|
||||
const { onActiveItem } = this.$attrs;
|
||||
const config = currentItem.__config__;
|
||||
console.log(arguments, "argu");
|
||||
// console.log(arguments, "argu");
|
||||
const child = renderChildren.apply(this, arguments);
|
||||
let className =
|
||||
this.activeId === config.formId
|
||||
@ -53,7 +53,7 @@ const layouts = {
|
||||
className += " unfocus-bordered";
|
||||
let labelWidth = config.labelWidth ? `${config.labelWidth}px` : null;
|
||||
if (config.showLabel === false) labelWidth = "0";
|
||||
console.log(child);
|
||||
// console.log(child);
|
||||
return (
|
||||
<el-col
|
||||
span={config.span}
|
||||
@ -72,10 +72,10 @@ const layouts = {
|
||||
key={config.renderKey}
|
||||
conf={currentItem}
|
||||
onInput={(event) => {
|
||||
console.log(event);
|
||||
// console.log(this.currentItem.__config__.defaultValue);
|
||||
// console.log(event);
|
||||
// // console.log(this.currentItem.__config__.defaultValue);
|
||||
// this.$set(config, "defaultValue", event);
|
||||
// console.log(this.currentItem.__config__.defaultValue);
|
||||
// // console.log(this.currentItem.__config__.defaultValue);
|
||||
this.currentItem.__config__.defaultValue = event;
|
||||
// config.defaultValue = event;
|
||||
// config.defaultValue = event;
|
||||
@ -90,12 +90,13 @@ const layouts = {
|
||||
},
|
||||
rowFormItem(
|
||||
// h,
|
||||
currentItem,
|
||||
index,
|
||||
list
|
||||
currentItem
|
||||
// index,
|
||||
// list
|
||||
) {
|
||||
const { onActiveItem } = this.$attrs;
|
||||
const config = currentItem.__config__;
|
||||
// console.log(config);
|
||||
const className =
|
||||
this.activeId === config.formId
|
||||
? "drawing-row-item active-from-item"
|
||||
@ -113,7 +114,6 @@ const layouts = {
|
||||
</el-row>
|
||||
);
|
||||
}
|
||||
console.log(child, "row");
|
||||
return (
|
||||
<el-col span={config.span}>
|
||||
<el-row
|
||||
@ -127,6 +127,11 @@ const layouts = {
|
||||
<span class="component-name">{config.componentName}</span>
|
||||
<draggable
|
||||
list={config.children || []}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
}}
|
||||
animation={340}
|
||||
group="componentsGroup"
|
||||
class="drag-wrapper"
|
||||
@ -134,7 +139,18 @@ const layouts = {
|
||||
draggable
|
||||
>
|
||||
{{
|
||||
item: () => child,
|
||||
item: ({ element, index }) => {
|
||||
const layout = layouts[element.__config__.layout];
|
||||
if (layout) {
|
||||
return layout.call(
|
||||
this,
|
||||
element,
|
||||
index,
|
||||
element.__config__.children
|
||||
);
|
||||
}
|
||||
return layoutIsNotFound.call(this);
|
||||
},
|
||||
}}
|
||||
</draggable>
|
||||
{components.itemBtns.apply(this, arguments)}
|
||||
@ -144,9 +160,9 @@ const layouts = {
|
||||
},
|
||||
raw(
|
||||
// h,
|
||||
currentItem,
|
||||
index,
|
||||
list
|
||||
currentItem
|
||||
// index,
|
||||
// list
|
||||
) {
|
||||
const config = currentItem.__config__;
|
||||
const child = renderChildren.apply(this, arguments);
|
||||
@ -155,8 +171,9 @@ const layouts = {
|
||||
key={config.renderKey}
|
||||
conf={currentItem}
|
||||
onInput={(event) => {
|
||||
// this.$set(config, "defaultValue", event);
|
||||
// console.log(this.currentItem.__config__.defaultValue);
|
||||
// console.log(event, "oninput");
|
||||
// // this.$set(config, "defaultValue", event);
|
||||
// // console.log(this.currentItem.__config__.defaultValue);
|
||||
this.currentItem.__config__.defaultValue = event;
|
||||
}}
|
||||
>
|
||||
@ -167,20 +184,21 @@ const layouts = {
|
||||
};
|
||||
|
||||
function renderChildren(
|
||||
// h,
|
||||
currentItem,
|
||||
index,
|
||||
list
|
||||
// // h,
|
||||
currentItem
|
||||
// // index,
|
||||
// // list
|
||||
) {
|
||||
const config = currentItem.__config__;
|
||||
console.log(config, "config");
|
||||
// // console.log(config, "config");
|
||||
if (!Array.isArray(config.children)) return null;
|
||||
return config.children.map((el, i) => {
|
||||
const layout = layouts[el.__config__.layout];
|
||||
// console.log(el.__config__.layout, `row's child`);
|
||||
if (layout) {
|
||||
return layout.call(
|
||||
this,
|
||||
// h,
|
||||
// // h,
|
||||
el,
|
||||
i,
|
||||
config.children
|
||||
@ -207,14 +225,14 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
render() {
|
||||
// console.log(this.currentItem.__config__.layout);
|
||||
// // console.log(this.currentItem.__config__.layout);
|
||||
const layout = layouts[this.currentItem.__config__.layout];
|
||||
// console.log(this.currentItem);
|
||||
console.log(layout, "layout");
|
||||
// // console.log(this.currentItem);
|
||||
// // console.log(layout, "layout");
|
||||
if (layout) {
|
||||
return layout.call(
|
||||
this,
|
||||
// h,
|
||||
// // h,
|
||||
this.currentItem,
|
||||
this.index,
|
||||
this.drawingList
|
||||
|
@ -1,11 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-drawer
|
||||
v-bind="$attrs"
|
||||
v-on="$listeners"
|
||||
@opened="onOpen"
|
||||
@close="onClose"
|
||||
>
|
||||
<el-drawer v-bind="$attrs" @opened="onOpen" @close="onClose">
|
||||
<div style="height: 100%">
|
||||
<el-row style="height: 100%; overflow: auto">
|
||||
<el-col :md="24" :lg="12" class="left-editor">
|
||||
@ -17,22 +12,34 @@
|
||||
<el-tabs v-model="activeTab" type="card" class="editor-tabs">
|
||||
<el-tab-pane name="html">
|
||||
<span slot="label">
|
||||
<i v-if="activeTab === 'html'" class="el-icon-edit" />
|
||||
<i v-else class="el-icon-document" />
|
||||
<el-icon>
|
||||
<Edit v-if="activeTab === 'html'" />
|
||||
<Document v-else />
|
||||
</el-icon>
|
||||
<!-- <i v-if="activeTab === 'html'" class="el-icon-edit" />
|
||||
<i v-else class="el-icon-document" /> -->
|
||||
template
|
||||
</span>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="js">
|
||||
<span slot="label">
|
||||
<i v-if="activeTab === 'js'" class="el-icon-edit" />
|
||||
<i v-else class="el-icon-document" />
|
||||
<el-icon>
|
||||
<Edit v-if="activeTab === 'js'" />
|
||||
<Document v-else />
|
||||
</el-icon>
|
||||
<!-- <i v-if="activeTab === 'js'" class="el-icon-edit" />
|
||||
<i v-else class="el-icon-document" /> -->
|
||||
script
|
||||
</span>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="css">
|
||||
<span slot="label">
|
||||
<i v-if="activeTab === 'css'" class="el-icon-edit" />
|
||||
<i v-else class="el-icon-document" />
|
||||
<el-icon>
|
||||
<Edit v-if="activeTab === 'css'" />
|
||||
<Document v-else />
|
||||
</el-icon>
|
||||
<!-- <i v-if="activeTab === 'css'" class="el-icon-edit" />
|
||||
<i v-else class="el-icon-document" /> -->
|
||||
css
|
||||
</span>
|
||||
</el-tab-pane>
|
||||
@ -65,7 +72,7 @@
|
||||
</span>
|
||||
<span
|
||||
class="bar-btn delete-btn"
|
||||
@click="$emit('update:visible', false)"
|
||||
@click="$emit('update:modelValue', false)"
|
||||
>
|
||||
<i class="el-icon-circle-close" />
|
||||
关闭
|
||||
@ -95,7 +102,8 @@
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
<script setup>
|
||||
import { parse } from "@babel/parser";
|
||||
import ClipboardJS from "clipboard";
|
||||
import { saveAs } from "file-saver";
|
||||
@ -111,7 +119,9 @@ import { exportDefault, beautifierConf, titleCase } from "@/utils/index";
|
||||
import ResourceDialog from "./ResourceDialog";
|
||||
import loadMonaco from "@/utils/loadMonaco";
|
||||
import loadBeautifier from "@/utils/loadBeautifier";
|
||||
|
||||
import { computed, onBeforeUnmount, onMounted } from "vue";
|
||||
import { ElMessage, ElMessageBox, ElNotification } from "element-plus";
|
||||
import { Document, Edit } from "@element-plus/icons-vue";
|
||||
const editorObj = {
|
||||
html: null,
|
||||
js: null,
|
||||
@ -123,193 +133,177 @@ const mode = {
|
||||
css: "css",
|
||||
};
|
||||
let beautifier;
|
||||
let monaco;
|
||||
// let monaco;
|
||||
const props = defineProps(["formData", "generateConf"]);
|
||||
const { formData, generateConf } = toRefs(props);
|
||||
const activeTab = ref("html");
|
||||
const htmlCode = ref("");
|
||||
const jsCode = ref("");
|
||||
const cssCode = ref("");
|
||||
const codeFrame = ref("");
|
||||
const isIframeLoaded = ref(false);
|
||||
const isInitcode = ref(false); // 保证open后两个异步只执行一次runcode
|
||||
const isRefreshCode = ref(false); // 每次打开都需要重新刷新代码
|
||||
const resourceVisible = ref(false);
|
||||
const scripts = ref([]);
|
||||
const links = ref([]);
|
||||
const monaco = ref(null);
|
||||
|
||||
export default {
|
||||
components: { ResourceDialog },
|
||||
props: ["formData", "generateConf"],
|
||||
data() {
|
||||
return {
|
||||
activeTab: "html",
|
||||
htmlCode: "",
|
||||
jsCode: "",
|
||||
cssCode: "",
|
||||
codeFrame: "",
|
||||
isIframeLoaded: false,
|
||||
isInitcode: false, // 保证open后两个异步只执行一次runcode
|
||||
isRefreshCode: false, // 每次打开都需要重新刷新代码
|
||||
resourceVisible: false,
|
||||
scripts: [],
|
||||
links: [],
|
||||
monaco: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
resources() {
|
||||
return this.scripts.concat(this.links);
|
||||
},
|
||||
},
|
||||
watch: {},
|
||||
created() {},
|
||||
mounted() {
|
||||
window.addEventListener("keydown", this.preventDefaultSave);
|
||||
const clipboard = new ClipboardJS(".copy-btn", {
|
||||
text: (trigger) => {
|
||||
const codeStr = this.generateCode();
|
||||
this.$notify({
|
||||
title: "成功",
|
||||
message: "代码已复制到剪切板,可粘贴。",
|
||||
type: "success",
|
||||
});
|
||||
return codeStr;
|
||||
},
|
||||
});
|
||||
clipboard.on("error", (e) => {
|
||||
this.$message.error("代码复制失败");
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener("keydown", this.preventDefaultSave);
|
||||
},
|
||||
methods: {
|
||||
preventDefaultSave(e) {
|
||||
if (e.key === "s" && (e.metaKey || e.ctrlKey)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
},
|
||||
onOpen() {
|
||||
const { type } = this.generateConf;
|
||||
this.htmlCode = makeUpHtml(this.formData, type);
|
||||
this.jsCode = makeUpJs(this.formData, type);
|
||||
this.cssCode = makeUpCss(this.formData);
|
||||
|
||||
loadBeautifier((btf) => {
|
||||
beautifier = btf;
|
||||
this.htmlCode = beautifier.html(this.htmlCode, beautifierConf.html);
|
||||
this.jsCode = beautifier.js(this.jsCode, beautifierConf.js);
|
||||
this.cssCode = beautifier.css(this.cssCode, beautifierConf.html);
|
||||
|
||||
loadMonaco((val) => {
|
||||
monaco = val;
|
||||
this.setEditorValue("editorHtml", "html", this.htmlCode);
|
||||
this.setEditorValue("editorJs", "js", this.jsCode);
|
||||
this.setEditorValue("editorCss", "css", this.cssCode);
|
||||
if (!this.isInitcode) {
|
||||
this.isRefreshCode = true;
|
||||
this.isIframeLoaded && (this.isInitcode = true) && this.runCode();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
onClose() {
|
||||
this.isInitcode = false;
|
||||
this.isRefreshCode = false;
|
||||
},
|
||||
iframeLoad() {
|
||||
if (!this.isInitcode) {
|
||||
this.isIframeLoaded = true;
|
||||
this.isRefreshCode && (this.isInitcode = true) && this.runCode();
|
||||
}
|
||||
},
|
||||
setEditorValue(id, type, codeStr) {
|
||||
if (editorObj[type]) {
|
||||
editorObj[type].setValue(codeStr);
|
||||
} else {
|
||||
editorObj[type] = monaco.editor.create(document.getElementById(id), {
|
||||
value: codeStr,
|
||||
theme: "vs-dark",
|
||||
language: mode[type],
|
||||
automaticLayout: true,
|
||||
});
|
||||
}
|
||||
// ctrl + s 刷新
|
||||
editorObj[type].onKeyDown((e) => {
|
||||
if (e.keyCode === 49 && (e.metaKey || e.ctrlKey)) {
|
||||
this.runCode();
|
||||
}
|
||||
});
|
||||
},
|
||||
runCode() {
|
||||
const jsCodeStr = editorObj.js.getValue();
|
||||
try {
|
||||
const ast = parse(jsCodeStr, { sourceType: "module" });
|
||||
const astBody = ast.program.body;
|
||||
if (astBody.length > 1) {
|
||||
this.$confirm(
|
||||
"js格式不能识别,仅支持修改export default的对象内容",
|
||||
"提示",
|
||||
{
|
||||
type: "warning",
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (astBody[0].type === "ExportDefaultDeclaration") {
|
||||
const postData = {
|
||||
type: "refreshFrame",
|
||||
data: {
|
||||
generateConf: this.generateConf,
|
||||
html: editorObj.html.getValue(),
|
||||
js: jsCodeStr.replace(exportDefault, ""),
|
||||
css: editorObj.css.getValue(),
|
||||
scripts: this.scripts,
|
||||
links: this.links,
|
||||
},
|
||||
};
|
||||
|
||||
this.$refs.previewPage.contentWindow.postMessage(
|
||||
postData,
|
||||
location.origin
|
||||
);
|
||||
} else {
|
||||
this.$message.error("请使用export default");
|
||||
}
|
||||
} catch (err) {
|
||||
this.$message.error(`js错误:${err}`);
|
||||
console.error(err);
|
||||
}
|
||||
},
|
||||
generateCode() {
|
||||
const html = vueTemplate(editorObj.html.getValue());
|
||||
const script = vueScript(editorObj.js.getValue());
|
||||
const css = cssStyle(editorObj.css.getValue());
|
||||
return beautifier.html(html + script + css, beautifierConf.html);
|
||||
},
|
||||
exportFile() {
|
||||
this.$prompt("文件名:", "导出文件", {
|
||||
inputValue: `${+new Date()}.vue`,
|
||||
closeOnClickModal: false,
|
||||
inputPlaceholder: "请输入文件名",
|
||||
}).then(({ value }) => {
|
||||
if (!value) value = `${+new Date()}.vue`;
|
||||
const codeStr = this.generateCode();
|
||||
const blob = new Blob([codeStr], { type: "text/plain;charset=utf-8" });
|
||||
saveAs(blob, value);
|
||||
});
|
||||
},
|
||||
showResource() {
|
||||
this.resourceVisible = true;
|
||||
},
|
||||
setResource(arr) {
|
||||
const scripts = [];
|
||||
const links = [];
|
||||
if (Array.isArray(arr)) {
|
||||
arr.forEach((item) => {
|
||||
if (item.endsWith(".css")) {
|
||||
links.push(item);
|
||||
} else {
|
||||
scripts.push(item);
|
||||
}
|
||||
});
|
||||
this.scripts = scripts;
|
||||
this.links = links;
|
||||
} else {
|
||||
this.scripts = [];
|
||||
this.links = [];
|
||||
}
|
||||
},
|
||||
},
|
||||
const preventDefaultSave = (e) => {
|
||||
if (e.key === "s" && (e.metaKey || e.ctrlKey)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
const onOpen = () => {
|
||||
const { type } = generateConf.value;
|
||||
htmlCode.value = makeUpHtml(formData.value, type);
|
||||
jsCode.value = makeUpJs(formData.value, type);
|
||||
cssCode.value = makeUpCss(formData.value);
|
||||
|
||||
loadBeautifier((btf) => {
|
||||
beautifier = btf;
|
||||
htmlCode.value = beautifier.html(htmlCode.value, beautifierConf.html);
|
||||
jsCode.value = beautifier.js(jsCode.value, beautifierConf.js);
|
||||
cssCode.value = beautifier.css(cssCode.value, beautifierConf.html);
|
||||
|
||||
loadMonaco((val) => {
|
||||
monaco.value = val;
|
||||
setEditorValue("editorHtml", "html", htmlCode.value);
|
||||
setEditorValue("editorJs", "js", jsCode.value);
|
||||
setEditorValue("editorCss", "css", cssCode.value);
|
||||
if (!isInitcode.value) {
|
||||
isRefreshCode.value = true;
|
||||
isIframeLoaded.value && (isInitcode.value = true) && runCode();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
const onClose = () => {
|
||||
isInitcode.value = false;
|
||||
isRefreshCode.value = false;
|
||||
};
|
||||
const iframeLoad = () => {
|
||||
if (!isInitcode.value) {
|
||||
isIframeLoaded.value = true;
|
||||
isRefreshCode.value && (isInitcode.value = true) && runCode();
|
||||
}
|
||||
};
|
||||
const setEditorValue = (id, type, codeStr) => {
|
||||
if (editorObj[type]) {
|
||||
editorObj[type].setValue(codeStr);
|
||||
} else {
|
||||
editorObj[type] = monaco.value.editor.create(document.getElementById(id), {
|
||||
value: codeStr,
|
||||
theme: "vs-dark",
|
||||
language: mode[type],
|
||||
automaticLayout: true,
|
||||
});
|
||||
}
|
||||
// ctrl + s 刷新
|
||||
editorObj[type].onKeyDown((e) => {
|
||||
if (e.keyCode === 49 && (e.metaKey || e.ctrlKey)) {
|
||||
runCode();
|
||||
}
|
||||
});
|
||||
};
|
||||
const previewPage = ref();
|
||||
const runCode = () => {
|
||||
const jsCodeStr = editorObj.js.getValue();
|
||||
try {
|
||||
const ast = parse(jsCodeStr, { sourceType: "module" });
|
||||
const astBody = ast.program.body;
|
||||
if (astBody.length > 1) {
|
||||
ElMessageBox.confirm(
|
||||
"js格式不能识别,仅支持修改export default的对象内容",
|
||||
"提示",
|
||||
{
|
||||
type: "warning",
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (astBody[0].type === "ExportDefaultDeclaration") {
|
||||
const postData = {
|
||||
type: "refreshFrame",
|
||||
data: {
|
||||
generateConf: generateConf.value,
|
||||
html: editorObj.html.getValue(),
|
||||
js: jsCodeStr.replace(exportDefault, ""),
|
||||
css: editorObj.css.getValue(),
|
||||
scripts: scripts.value,
|
||||
links: links.value,
|
||||
},
|
||||
};
|
||||
|
||||
previewPage.value.contentWindow.postMessage(postData, location.origin);
|
||||
} else {
|
||||
ElMessage.error("请使用export default");
|
||||
}
|
||||
} catch (err) {
|
||||
ElMessage.error(`js错误:${err}`);
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
const generateCode = () => {
|
||||
const html = vueTemplate(editorObj.html.getValue());
|
||||
const script = vueScript(editorObj.js.getValue());
|
||||
const css = cssStyle(editorObj.css.getValue());
|
||||
return beautifier.html(html + script + css, beautifierConf.html);
|
||||
};
|
||||
const exportFile = () => {
|
||||
ElMessageBox.prompt("文件名:", "导出文件", {
|
||||
inputValue: `${+new Date()}.vue`,
|
||||
closeOnClickModal: false,
|
||||
inputPlaceholder: "请输入文件名",
|
||||
}).then(({ value }) => {
|
||||
if (!value) value = `${+new Date()}.vue`;
|
||||
const codeStr = generateCode();
|
||||
const blob = new Blob([codeStr], { type: "text/plain;charset=utf-8" });
|
||||
saveAs(blob, value);
|
||||
});
|
||||
};
|
||||
const showResource = () => {
|
||||
resourceVisible.value = true;
|
||||
};
|
||||
const setResource = (arr) => {
|
||||
const _scripts = [];
|
||||
const _links = [];
|
||||
if (Array.isArray(arr)) {
|
||||
arr.forEach((item) => {
|
||||
if (item.endsWith(".css")) {
|
||||
links.push(item);
|
||||
} else {
|
||||
scripts.push(item);
|
||||
}
|
||||
});
|
||||
scripts.value = _scripts;
|
||||
links.value = _links;
|
||||
} else {
|
||||
scripts.value = [];
|
||||
links.value = [];
|
||||
}
|
||||
};
|
||||
const resources = computed(() => scripts.value.concat(links.value));
|
||||
onMounted(() => {
|
||||
window.addEventListener("keydown", preventDefaultSave);
|
||||
const clipboard = new ClipboardJS(".copy-btn", {
|
||||
text: (trigger) => {
|
||||
const codeStr = generateCode();
|
||||
ElNotification({
|
||||
title: "成功",
|
||||
message: "代码已复制到剪切板,可粘贴。",
|
||||
type: "success",
|
||||
});
|
||||
return codeStr;
|
||||
},
|
||||
});
|
||||
clipboard.on("error", (e) => {
|
||||
ElMessage.error("代码复制失败");
|
||||
});
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener("keydown", preventDefaultSave);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -59,7 +59,6 @@ const preventDefaultSave = (e) => {
|
||||
const onOpen = () => {
|
||||
loadBeautifier((btf) => {
|
||||
beautifier = btf;
|
||||
console.log(btf.js);
|
||||
beautifierJson.value = beautifier.js(jsonStr.value, beautifierConf.js);
|
||||
|
||||
loadMonaco((val) => {
|
||||
@ -154,7 +153,7 @@ export default {
|
||||
::v-deep .el-drawer__header {
|
||||
display: none;
|
||||
}
|
||||
// @include action-bar;
|
||||
@include action-bar;
|
||||
|
||||
.json-editor {
|
||||
height: calc(100vh - 33px);
|
||||
|
@ -5,7 +5,6 @@
|
||||
title="外部资源引用"
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
v-on="$listeners"
|
||||
@open="onOpen"
|
||||
@close="onClose"
|
||||
>
|
||||
@ -31,45 +30,31 @@
|
||||
>
|
||||
jQuery1.8.3
|
||||
</el-button>
|
||||
<el-button
|
||||
plain
|
||||
@click="addOne('https://unpkg.com/http-vue-loader')"
|
||||
>
|
||||
<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 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>
|
||||
<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'
|
||||
import { deepClone } from "@/utils/index";
|
||||
|
||||
export default {
|
||||
components: {},
|
||||
inheritAttrs: false,
|
||||
props: ['originResource'],
|
||||
props: ["originResource"],
|
||||
data() {
|
||||
return {
|
||||
resources: null
|
||||
}
|
||||
resources: null,
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
watch: {},
|
||||
@ -77,40 +62,40 @@ export default {
|
||||
mounted() {},
|
||||
methods: {
|
||||
onOpen() {
|
||||
this.resources = this.originResource.length ? deepClone(this.originResource) : ['']
|
||||
},
|
||||
onClose() {
|
||||
this.resources = this.originResource.length
|
||||
? deepClone(this.originResource)
|
||||
: [""];
|
||||
},
|
||||
onClose() {},
|
||||
close() {
|
||||
this.$emit('update:visible', false)
|
||||
this.$emit("update:visible", false);
|
||||
},
|
||||
handelConfirm() {
|
||||
const results = this.resources.filter(item => !!item) || []
|
||||
this.$emit('save', results)
|
||||
this.close()
|
||||
const results = this.resources.filter((item) => !!item) || [];
|
||||
this.$emit("save", results);
|
||||
this.close();
|
||||
if (results.length) {
|
||||
this.resources = results
|
||||
this.resources = results;
|
||||
}
|
||||
},
|
||||
deleteOne(index) {
|
||||
this.resources.splice(index, 1)
|
||||
this.resources.splice(index, 1);
|
||||
},
|
||||
addOne(url) {
|
||||
if (this.resources.indexOf(url) > -1) {
|
||||
this.$message('资源已存在')
|
||||
this.$message("资源已存在");
|
||||
} else {
|
||||
this.resources.push(url)
|
||||
this.resources.push(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.add-item{
|
||||
.add-item {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.url-item{
|
||||
.url-item {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
</style>
|
||||
|
@ -193,7 +193,7 @@
|
||||
label="默认值"
|
||||
>
|
||||
<el-input
|
||||
:value="setDefaultValue(activeData.__config__.defaultValue)"
|
||||
:modelValue="setDefaultValue(activeData.__config__.defaultValue)"
|
||||
placeholder="请输入默认值"
|
||||
@input="onDefaultValueInput"
|
||||
/>
|
||||
@ -203,7 +203,7 @@
|
||||
label="至少应选"
|
||||
>
|
||||
<el-input-number
|
||||
:value="activeData.min"
|
||||
:modelValue="activeData.min"
|
||||
:min="0"
|
||||
placeholder="至少应选"
|
||||
@input="$set(activeData, 'min', $event ? $event : undefined)"
|
||||
@ -214,7 +214,7 @@
|
||||
label="最多可选"
|
||||
>
|
||||
<el-input-number
|
||||
:value="activeData.max"
|
||||
:modelValue="activeData.max"
|
||||
:min="0"
|
||||
placeholder="最多可选"
|
||||
@input="$set(activeData, 'max', $event ? $event : undefined)"
|
||||
@ -394,7 +394,7 @@
|
||||
label="开启值"
|
||||
>
|
||||
<el-input
|
||||
:value="setDefaultValue(activeData['active-value'])"
|
||||
:modelValue="setDefaultValue(activeData['active-value'])"
|
||||
placeholder="请输入开启值"
|
||||
@input="onSwitchValueInput($event, 'active-value')"
|
||||
/>
|
||||
@ -404,7 +404,7 @@
|
||||
label="关闭值"
|
||||
>
|
||||
<el-input
|
||||
:value="setDefaultValue(activeData['inactive-value'])"
|
||||
:modelValue="setDefaultValue(activeData['inactive-value'])"
|
||||
placeholder="请输入关闭值"
|
||||
@input="onSwitchValueInput($event, 'inactive-value')"
|
||||
/>
|
||||
@ -545,7 +545,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item v-if="activeData.format !== undefined" label="时间格式">
|
||||
<el-input
|
||||
:value="activeData.format"
|
||||
:modelValue="activeData.format"
|
||||
placeholder="请输入时间格式"
|
||||
@input="setTimeValue($event)"
|
||||
/>
|
||||
@ -671,15 +671,30 @@
|
||||
:data="activeData.options"
|
||||
node-key="id"
|
||||
:expand-on-click-node="false"
|
||||
:render-content="renderContent"
|
||||
/>
|
||||
>
|
||||
<!-- :render-content="renderContent" -->
|
||||
<template #default="{ node, data }">
|
||||
<div class="custom-tree-node">
|
||||
<span>{{ node.label }}</span>
|
||||
<span class="node-operation">
|
||||
<ElIcon @click="append(data)" title="添加">
|
||||
<Plus />
|
||||
</ElIcon>
|
||||
|
||||
<ElIcon @click="remove(node, data)" title="删除">
|
||||
<Delete />
|
||||
</ElIcon>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
<div
|
||||
v-if="activeData.__config__.dataType === 'static'"
|
||||
style="margin-left: 20px"
|
||||
>
|
||||
<el-button
|
||||
style="padding-bottom: 0"
|
||||
icon="el-icon-circle-plus-outline"
|
||||
icon="circle-plus"
|
||||
link
|
||||
@click="addTreeItem"
|
||||
>
|
||||
@ -1010,22 +1025,24 @@
|
||||
</div>
|
||||
|
||||
<treeNode-dialog
|
||||
:visible.sync="dialogVisible"
|
||||
v-model="dialogVisible"
|
||||
title="添加选项"
|
||||
@commit="addNode"
|
||||
/>
|
||||
<icons-dialog
|
||||
:visible.sync="iconsVisible"
|
||||
v-model="iconsVisible"
|
||||
:current="activeData[currentIconModel]"
|
||||
@select="setIcon"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Link } from "@element-plus/icons-vue";
|
||||
import { Link, Plus } from "@element-plus/icons-vue";
|
||||
import TreeNodeDialog from "./TreeNodeDialog.vue";
|
||||
import { isNumberStr } from "@/utils/index";
|
||||
import IconsDialog from "./IconsDialog.vue";
|
||||
import { getIdGlobal } from "@/utils/db";
|
||||
|
||||
import {
|
||||
inputComponents,
|
||||
selectComponents,
|
||||
@ -1047,6 +1064,7 @@ const dateTimeFormat = {
|
||||
// const size = ref("small");
|
||||
// 使changeRenderKey在目标组件改变时可用
|
||||
const needRerenderList = ["tinymce"];
|
||||
const idGlobal = ref(getIdGlobal());
|
||||
const props = defineProps({
|
||||
showField: {
|
||||
type: Boolean,
|
||||
@ -1087,39 +1105,38 @@ const addTreeItem = () => {
|
||||
dialogVisible.value = true;
|
||||
currentNode.value = activeData.value.options;
|
||||
};
|
||||
const renderContent = (h, { node, data, store }) => {
|
||||
return `<div class="custom-tree-node">
|
||||
<span>{node.label}</span>
|
||||
<span class="node-operation">
|
||||
<i
|
||||
onClick={() => this.append(data)}
|
||||
class="el-icon-plus"
|
||||
title="添加"
|
||||
></i>
|
||||
<i
|
||||
onClick={() => this.remove(node, data)}
|
||||
class="el-icon-delete"
|
||||
title="删除"
|
||||
></i>
|
||||
</span>
|
||||
</div>`;
|
||||
};
|
||||
|
||||
// const renderContent = (h, { node, data, store }) => {
|
||||
// return (
|
||||
// <div class="custom-tree-node">
|
||||
// <span>{node.label}</span>
|
||||
// <span class="node-operation">
|
||||
// <i onClick={() => append(data)} class="el-icon-plus" title="添加"></i>
|
||||
// <i
|
||||
// onClick={() => remove(node, data)}
|
||||
// class="el-icon-delete"
|
||||
// title="删除"
|
||||
// ></i>
|
||||
// </span>
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
const append = (data) => {
|
||||
if (!data.children) {
|
||||
this.$set(data, "children", []);
|
||||
data.children = [];
|
||||
}
|
||||
this.dialogVisible = true;
|
||||
this.currentNode = data.children;
|
||||
dialogVisible.value = true;
|
||||
currentNode.value = data.children;
|
||||
};
|
||||
const remove = (node, data) => {
|
||||
this.activeData.__config__.defaultValue = []; // 避免删除时报错
|
||||
activeData.value.__config__.defaultValue = []; // 避免删除时报错
|
||||
const { parent } = node;
|
||||
const children = parent.data.children || parent.data;
|
||||
const index = children.findIndex((d) => d.id === data.id);
|
||||
children.splice(index, 1);
|
||||
};
|
||||
const addNode = (data) => {
|
||||
this.currentNode.push(data);
|
||||
currentNode.value.push(data);
|
||||
};
|
||||
const setOptionValue = (item, val) => {
|
||||
item.value = isNumberStr(val) ? +val : val;
|
||||
@ -1128,80 +1145,69 @@ const setDefaultValue = (val) => {
|
||||
if (Array.isArray(val)) {
|
||||
return val.join(",");
|
||||
}
|
||||
// if (['string', 'number'].indexOf(typeof val) > -1) {
|
||||
// return val
|
||||
// }
|
||||
if (typeof val === "boolean") {
|
||||
return `${val}`;
|
||||
}
|
||||
return val;
|
||||
};
|
||||
const onDefaultValueInput = (str) => {
|
||||
if (Array.isArray(this.activeData.__config__.defaultValue)) {
|
||||
if (Array.isArray(activeData.value.__config__.defaultValue)) {
|
||||
// 数组
|
||||
this.$set(
|
||||
this.activeData.__config__,
|
||||
"defaultValue",
|
||||
str.split(",").map((val) => (isNumberStr(val) ? +val : val))
|
||||
);
|
||||
activeData.value.__config__.defaultValue = str
|
||||
.split(",")
|
||||
.map((val) => (isNumberStr(val) ? +val : val));
|
||||
} else if (["true", "false"].indexOf(str) > -1) {
|
||||
// 布尔
|
||||
this.$set(this.activeData.__config__, "defaultValue", JSON.parse(str));
|
||||
activeData.value.__config__.defaultValue = JSON.parse(str);
|
||||
} else {
|
||||
// 字符串和数字
|
||||
this.$set(
|
||||
this.activeData.__config__,
|
||||
"defaultValue",
|
||||
isNumberStr(str) ? +str : str
|
||||
);
|
||||
activeData.value.__config__.defaultValue = isNumberStr(str) ? +str : str;
|
||||
}
|
||||
};
|
||||
const onSwitchValueInput = (val, name) => {
|
||||
if (["true", "false"].indexOf(val) > -1) {
|
||||
this.$set(this.activeData, name, JSON.parse(val));
|
||||
activeData.value.name = JSON.parse(val);
|
||||
} else {
|
||||
this.$set(this.activeData, name, isNumberStr(val) ? +val : val);
|
||||
activeData.value.name = isNumberStr(val) ? +val : val;
|
||||
}
|
||||
};
|
||||
const setTimeValue = (val, type) => {
|
||||
const valueFormat = type === "week" ? dateTimeFormat.date : val;
|
||||
this.$set(this.activeData.__config__, "defaultValue", null);
|
||||
this.$set(this.activeData, "value-format", valueFormat);
|
||||
this.$set(this.activeData, "format", val);
|
||||
activeData.value.__config__.defaultValue = null;
|
||||
activeData.value.__config__["value-format"] = valueFormat;
|
||||
activeData.value.format = val;
|
||||
};
|
||||
const spanChange = (val) => {
|
||||
formConf.value.span = val;
|
||||
};
|
||||
const multipleChange = (val) => {
|
||||
this.$set(this.activeData.__config__, "defaultValue", val ? [] : "");
|
||||
activeData.value.__config__.defaultValue = val ? [] : "";
|
||||
};
|
||||
const dateTypeChange = (val) => {
|
||||
this.setTimeValue(dateTimeFormat[val], val);
|
||||
setTimeValue(dateTimeFormat[val], val);
|
||||
};
|
||||
const rangeChange = (val) => {
|
||||
this.$set(
|
||||
this.activeData.__config__,
|
||||
"defaultValue",
|
||||
val ? [this.activeData.min, this.activeData.max] : this.activeData.min
|
||||
);
|
||||
activeData.value.__config__.defaultValue = val
|
||||
? [activeData.value.min, activeData.value.max]
|
||||
: activeData.value.min;
|
||||
};
|
||||
const rateTextChange = (val) => {
|
||||
if (val) this.activeData["show-score"] = false;
|
||||
if (val) activeData.value["show-score"] = false;
|
||||
};
|
||||
const rateScoreChange = (val) => {
|
||||
if (val) this.activeData["show-text"] = false;
|
||||
if (val) activeData.value["show-text"] = false;
|
||||
};
|
||||
const colorFormatChange = (val) => {
|
||||
this.activeData.__config__.defaultValue = null;
|
||||
this.activeData["show-alpha"] = val.indexOf("a") > -1;
|
||||
this.activeData.__config__.renderKey = +new Date(); // 更新renderKey,重新渲染该组件
|
||||
activeData.value.__config__.defaultValue = null;
|
||||
activeData.value["show-alpha"] = val.indexOf("a") > -1;
|
||||
activeData.value.__config__.renderKey = +new Date(); // 更新renderKey,重新渲染该组件
|
||||
};
|
||||
const openIconsDialog = (model) => {
|
||||
this.iconsVisible = true;
|
||||
this.currentIconModel = model;
|
||||
iconsVisible.value = true;
|
||||
currentIconModel.value = model;
|
||||
};
|
||||
const setIcon = (val) => {
|
||||
this.activeData[this.currentIconModel] = val;
|
||||
activeData.value[currentIconModel.value] = val;
|
||||
};
|
||||
const tagChange = (tagIcon) => {
|
||||
let target = inputComponents.find(
|
||||
@ -1214,8 +1220,8 @@ const tagChange = (tagIcon) => {
|
||||
emit("tag-change", target);
|
||||
};
|
||||
const changeRenderKey = () => {
|
||||
if (needRerenderList.includes(this.activeData.__config__.tag)) {
|
||||
this.activeData.__config__.renderKey = +new Date();
|
||||
if (needRerenderList.includes(activeData.value.__config__.tag)) {
|
||||
activeData.value.__config__.renderKey = +new Date();
|
||||
}
|
||||
};
|
||||
|
||||
@ -1302,7 +1308,6 @@ const justifyOptions = ref([
|
||||
const data = reactive({
|
||||
layoutTreeProps: {
|
||||
label(data, node) {
|
||||
console.log(data);
|
||||
const config = data.__config__;
|
||||
return data.componentName || `${config.label}: ${data.__vModel__}`;
|
||||
},
|
||||
|
@ -7,13 +7,12 @@
|
||||
@open="onOpen"
|
||||
@close="onClose"
|
||||
>
|
||||
<!-- v-on="$listeners" -->
|
||||
<el-row :gutter="0">
|
||||
<el-form
|
||||
ref="elForm"
|
||||
ref="elFormRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
size="small"
|
||||
size="default"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-col :span="24">
|
||||
@ -61,7 +60,8 @@
|
||||
<script setup>
|
||||
import { isNumberStr } from "@/utils/index";
|
||||
import { reactive, ref, toRefs, watch } from "vue";
|
||||
const emit = defineEmits(["update:visible", "commit"]);
|
||||
const emit = defineEmits(["update:modelValue", "commit"]);
|
||||
// const props = defineProps(["modelValue"]);
|
||||
const id = ref(100);
|
||||
const dataType = ref("string");
|
||||
let inheritAttrs = false;
|
||||
@ -106,11 +106,14 @@ const onOpen = () => {
|
||||
};
|
||||
};
|
||||
const onClose = () => {};
|
||||
|
||||
const close = () => {
|
||||
emit("update:visible", false);
|
||||
emit("update:modelValue", false);
|
||||
};
|
||||
|
||||
const elFormRef = ref();
|
||||
const handleConfirm = () => {
|
||||
this.$refs.elForm.validate((valid) => {
|
||||
elFormRef.value.validate((valid) => {
|
||||
if (!valid) return;
|
||||
if (dataType.value === "number") {
|
||||
formData.value.value = parseFloat(formData.value.value);
|
||||
|
@ -19,6 +19,7 @@
|
||||
:clone="cloneComponent"
|
||||
item-key="id"
|
||||
:sort="false"
|
||||
@end="onEnd"
|
||||
>
|
||||
<template #item="{ element }">
|
||||
<div class="components-item" @click="addComponent(element)">
|
||||
@ -119,30 +120,27 @@
|
||||
@tag-change="tagChange"
|
||||
@fetch-data="fetchData"
|
||||
/>
|
||||
<!-- <el-input v-model="formConf.size"></el-input> -->
|
||||
<!--
|
||||
<form-drawer
|
||||
:visible.sync="drawerVisible"
|
||||
v-model="drawerVisible"
|
||||
:form-data="formData"
|
||||
size="100%"
|
||||
:generate-conf="generateConf"
|
||||
/>
|
||||
-->
|
||||
<json-drawer
|
||||
size="60%"
|
||||
v-model="jsonDrawerVisible"
|
||||
:json-str="JSON.stringify(formData)"
|
||||
@refresh="refreshJson"
|
||||
/>
|
||||
<!--
|
||||
|
||||
<code-type-dialog
|
||||
:visible.sync="dialogVisible"
|
||||
v-model="dialogVisible"
|
||||
title="选择生成类型"
|
||||
:show-file-name="showFileName"
|
||||
@confirm="generate"
|
||||
/>
|
||||
<input id="copyNode" type="hidden" />
|
||||
-->
|
||||
|
||||
<!-- 表单配置详情 -->
|
||||
<el-dialog
|
||||
:title="formTitle"
|
||||
@ -168,21 +166,33 @@
|
||||
|
||||
<script setup>
|
||||
import { debounce } from "throttle-debounce";
|
||||
// import ClipboardJS from "clipboard";
|
||||
import ClipboardJS from "clipboard";
|
||||
import draggable from "vuedraggable";
|
||||
import CodeTypeDialog from "./CodeTypeDialog.vue";
|
||||
import logo from "@/assets/logo/logo.png";
|
||||
import { beautifierConf, titleCase, deepClone } from "@/utils/index";
|
||||
import drawingDefault from "@/utils/generator/drawingDefault";
|
||||
import draggableItem from "./DraggableItem";
|
||||
import RightPanel from "./RightPanel.vue";
|
||||
import loadBeautifier from "@/utils/loadBeautifier";
|
||||
import JsonDrawer from "./JsonDrawer";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import FormDrawer from "./FormDrawer.vue";
|
||||
import { ElMessage, ElMessageBox, ElNotification } from "element-plus";
|
||||
import $download from "@/plugins/download.js";
|
||||
import {
|
||||
inputComponents,
|
||||
selectComponents,
|
||||
layoutComponents,
|
||||
formConf as formConfig,
|
||||
} from "@/utils/generator/config";
|
||||
import {
|
||||
makeUpHtml,
|
||||
vueTemplate,
|
||||
vueScript,
|
||||
cssStyle,
|
||||
} from "@/utils/generator/html";
|
||||
import { makeUpJs } from "@/utils/generator/js";
|
||||
import { makeUpCss } from "@/utils/generator/css";
|
||||
import {
|
||||
getDrawingList,
|
||||
saveDrawingList,
|
||||
@ -192,8 +202,11 @@ import {
|
||||
} from "@/utils/db";
|
||||
import { nextTick, onMounted, reactive, ref, toRefs, watch } from "vue";
|
||||
import axios from "axios";
|
||||
import { useRoute } from "vue-router";
|
||||
let tempActiveData;
|
||||
let oldActiveId;
|
||||
|
||||
const route = useRoute();
|
||||
const drawingListInDB = getDrawingList();
|
||||
const formConfInDB = getFormConf();
|
||||
const idGlobal = ref(getIdGlobal());
|
||||
@ -218,6 +231,7 @@ const jsonDrawerVisible = ref(false);
|
||||
const generateConf = ref(null);
|
||||
const showFileName = ref(false);
|
||||
const drawingList = ref([]);
|
||||
const operationType = ref(null);
|
||||
const activeData = ref(drawingDefault[0]);
|
||||
const activeId = ref(drawingDefault[0].formId);
|
||||
const formOpen = ref(false);
|
||||
@ -228,7 +242,7 @@ const data = reactive({
|
||||
// 表单参数
|
||||
formObj: {
|
||||
formId: undefined,
|
||||
formName: "332",
|
||||
formName: undefined,
|
||||
content: undefined,
|
||||
remark: undefined,
|
||||
},
|
||||
@ -274,10 +288,10 @@ const setRespData = (component, resp) => {
|
||||
// 此时赋值代码可写成 component[dataConsumer] = respData;
|
||||
// 但为支持更深层级的赋值(如:dataConsumer的值为'options.data'),使用setObjectValueReduce
|
||||
setObjectValueReduce(component, dataConsumer, respData);
|
||||
const i = drawingList.findIndex(
|
||||
const i = drawingList.value.findIndex(
|
||||
(item) => item.__config__.renderKey === renderKey
|
||||
);
|
||||
if (i > -1) this.$set(drawingList, i, component);
|
||||
if (i > -1) drawingList.value[i] = component;
|
||||
};
|
||||
|
||||
const fetchData = (component) => {
|
||||
@ -308,7 +322,6 @@ const cloneComponent = (origin) => {
|
||||
const clone = deepClone(origin);
|
||||
const config = clone.__config__;
|
||||
config.span = formConf.value.span; // 生成代码时,会根据span做精简判断
|
||||
console.log(formConf.value);
|
||||
createIdAndKey(clone);
|
||||
clone.placeholder !== undefined && (clone.placeholder += config.label);
|
||||
tempActiveData = clone;
|
||||
@ -339,20 +352,20 @@ const showJson = () => {
|
||||
jsonDrawerVisible.value = true;
|
||||
};
|
||||
const download = () => {
|
||||
this.dialogVisible = true;
|
||||
this.showFileName = true;
|
||||
this.operationType = "download";
|
||||
dialogVisible.value = true;
|
||||
showFileName.value = true;
|
||||
operationType.value = "download";
|
||||
};
|
||||
const run = () => {
|
||||
// TODO 弹窗类型异常
|
||||
// this.dialogVisible = true
|
||||
// this.showFileName = false
|
||||
this.operationType = "run";
|
||||
operationType.value = "run";
|
||||
let data = {
|
||||
fileName: undefined,
|
||||
type: "file",
|
||||
};
|
||||
this.generate(data);
|
||||
generate(data);
|
||||
};
|
||||
const saveIdGlobalDebounce = debounce(340, saveIdGlobal);
|
||||
const saveDrawingListDebounce = debounce(340, saveDrawingList);
|
||||
@ -389,18 +402,18 @@ const AssembleFormData = () => {
|
||||
};
|
||||
};
|
||||
const generate = (data) => {
|
||||
const func = this[`exec${titleCase(this.operationType)}`];
|
||||
this.generateConf = data;
|
||||
func && func(data);
|
||||
const func = `exec${titleCase(operationType.value)}`;
|
||||
generateConf.value = data;
|
||||
func && eval(`${func}(data)`);
|
||||
};
|
||||
const execRun = (data) => {
|
||||
this.AssembleFormData();
|
||||
this.drawerVisible = true;
|
||||
AssembleFormData();
|
||||
drawerVisible.value = true;
|
||||
};
|
||||
const execDownload = (data) => {
|
||||
const codeStr = this.generateCode();
|
||||
const codeStr = generateCode();
|
||||
const blob = new Blob([codeStr], { type: "text/plain;charset=utf-8" });
|
||||
this.$download.saveAs(blob, data.fileName);
|
||||
$download.saveAs(blob, data.fileName);
|
||||
};
|
||||
const execCopy = (data) => {
|
||||
document.getElementById("copyNode").click();
|
||||
@ -424,17 +437,25 @@ const drawingItemDelete = (index, list) => {
|
||||
nextTick(() => {
|
||||
const len = drawingList.value.length;
|
||||
if (len) {
|
||||
activeFormItem(this.drawingList[len - 1]);
|
||||
activeFormItem(drawingList.value[len - 1]);
|
||||
}
|
||||
});
|
||||
};
|
||||
const generateCode = () => {
|
||||
const { type } = this.generateConf;
|
||||
const { type } = generateConf.value;
|
||||
AssembleFormData();
|
||||
const script = vueScript(makeUpJs(this.formData, type));
|
||||
const html = vueTemplate(makeUpHtml(this.formData, type));
|
||||
const css = cssStyle(makeUpCss(this.formData));
|
||||
return beautifier.html(html + script + css, beautifierConf.html);
|
||||
const extraScript = vueScript(`
|
||||
export default {
|
||||
inheritAttrs: false
|
||||
}
|
||||
`);
|
||||
const script = vueScript(makeUpJs(formData.value, type), true);
|
||||
const html = vueTemplate(makeUpHtml(formData.value, type));
|
||||
const css = cssStyle(makeUpCss(formData.value));
|
||||
return beautifier.html(
|
||||
html + extraScript + script + css,
|
||||
beautifierConf.html
|
||||
);
|
||||
};
|
||||
|
||||
const copy = () => {
|
||||
@ -443,57 +464,59 @@ const copy = () => {
|
||||
operationType.value = "copy";
|
||||
};
|
||||
const tagChange = (newTag) => {
|
||||
newTag = this.cloneComponent(newTag);
|
||||
newTag = cloneComponent(newTag);
|
||||
const config = newTag.__config__;
|
||||
newTag.__vModel__ = this.activeData.__vModel__;
|
||||
config.formId = this.activeId;
|
||||
config.span = this.activeData.__config__.span;
|
||||
this.activeData.__config__.tag = config.tag;
|
||||
this.activeData.__config__.tagIcon = config.tagIcon;
|
||||
this.activeData.__config__.document = config.document;
|
||||
newTag.__vModel__ = activeData.value.__vModel__;
|
||||
config.formId = activeId.value;
|
||||
config.span = activeData.value.__config__.span;
|
||||
activeData.value.__config__.tag = config.tag;
|
||||
activeData.value.__config__.tagIcon = config.tagIcon;
|
||||
activeData.value.__config__.document = config.document;
|
||||
if (
|
||||
typeof this.activeData.__config__.defaultValue ===
|
||||
typeof activeData.value.__config__.defaultValue ===
|
||||
typeof config.defaultValue
|
||||
) {
|
||||
config.defaultValue = this.activeData.__config__.defaultValue;
|
||||
config.defaultValue = activeData.value.__config__.defaultValue;
|
||||
}
|
||||
Object.keys(newTag).forEach((key) => {
|
||||
if (this.activeData[key] !== undefined) {
|
||||
newTag[key] = this.activeData[key];
|
||||
if (activeData.value[key] !== undefined) {
|
||||
newTag[key] = activeData.value[key];
|
||||
}
|
||||
});
|
||||
this.activeData = newTag;
|
||||
this.updateDrawingList(newTag, this.drawingList);
|
||||
activeData.value = newTag;
|
||||
updateDrawingList(newTag, drawingList.value);
|
||||
};
|
||||
const updateDrawingList = (newTag, list) => {
|
||||
const index = list.findIndex(
|
||||
(item) => item.__config__.formId === this.activeId
|
||||
(item) => item.__config__.formId === activeId.value
|
||||
);
|
||||
if (index > -1) {
|
||||
list.splice(index, 1, newTag);
|
||||
} else {
|
||||
list.forEach((item) => {
|
||||
if (Array.isArray(item.__config__.children))
|
||||
this.updateDrawingList(newTag, item.__config__.children);
|
||||
updateDrawingList(newTag, item.__config__.children);
|
||||
});
|
||||
}
|
||||
};
|
||||
const refreshJson = (data) => {
|
||||
drawingList.value = deepClone(data.fields);
|
||||
delete data.fields;
|
||||
this.formConf = data;
|
||||
formConf.value = data;
|
||||
};
|
||||
|
||||
/** 保存表单信息 */
|
||||
const submitForm = () => {
|
||||
formRef.value.validate((valid) => {
|
||||
console.log(formObj.value);
|
||||
return;
|
||||
if (valid) {
|
||||
if (this.form.formId != null) {
|
||||
updateForm(this.form).then((response) => {
|
||||
if (formObj.value.formId != null) {
|
||||
updateForm(formObj.value).then((response) => {
|
||||
ElMessage.success("修改成功");
|
||||
});
|
||||
} else {
|
||||
addForm(this.form).then((response) => {
|
||||
addForm(formObj.value).then((response) => {
|
||||
ElMessage.success("新增成功");
|
||||
});
|
||||
}
|
||||
@ -517,36 +540,36 @@ onMounted(() => {
|
||||
activeFormItem(drawingList.value[0]);
|
||||
|
||||
drawingList.value = [];
|
||||
// const formId = that.$route.query && that.$route.query.formId;
|
||||
// if (formId) {
|
||||
// getForm(formId).then((res) => {
|
||||
// that.formConf = JSON.parse(res.data.content);
|
||||
// that.drawingList = that.formConf.fields;
|
||||
// that.form = res.data;
|
||||
// });
|
||||
// } else {
|
||||
// if (formConfInDB) {
|
||||
// that.formConf = formConfInDB;
|
||||
// that.formConf.fields = null;
|
||||
// }
|
||||
// }
|
||||
// loadBeautifier((btf) => {
|
||||
// beautifier = btf;
|
||||
// });
|
||||
// const clipboard = new ClipboardJS("#copyNode", {
|
||||
// text: (trigger) => {
|
||||
// const codeStr = this.generateCode();
|
||||
// this.$notify({
|
||||
// title: "成功",
|
||||
// message: "代码已复制到剪切板,可粘贴。",
|
||||
// type: "success",
|
||||
// });
|
||||
// return codeStr;
|
||||
// },
|
||||
// });
|
||||
// clipboard.on("error", (e) => {
|
||||
// this.$message.error("代码复制失败");
|
||||
// });
|
||||
const formId = route.query && route.query.formId;
|
||||
if (formId) {
|
||||
getForm(formId).then((res) => {
|
||||
formConf.value = JSON.parse(res.data.content);
|
||||
drawingList.value = formConf.value.fields;
|
||||
formObj.value = res.data;
|
||||
});
|
||||
} else {
|
||||
if (formConfInDB) {
|
||||
formConf.value = formConfInDB;
|
||||
formConf.value.fields = null;
|
||||
}
|
||||
}
|
||||
loadBeautifier((btf) => {
|
||||
beautifier = btf;
|
||||
});
|
||||
const clipboard = new ClipboardJS("#copyNode", {
|
||||
text: (trigger) => {
|
||||
const codeStr = generateCode();
|
||||
ElNotification({
|
||||
title: "成功",
|
||||
message: "代码已复制到剪切板,可粘贴。",
|
||||
type: "success",
|
||||
});
|
||||
return codeStr;
|
||||
},
|
||||
});
|
||||
clipboard.on("error", (e) => {
|
||||
ElMessage.error("代码复制失败");
|
||||
});
|
||||
});
|
||||
|
||||
watch(
|
||||
@ -574,7 +597,6 @@ watch(
|
||||
watch(
|
||||
drawingList,
|
||||
(val) => {
|
||||
// console.log(val);
|
||||
saveDrawingListDebounce(val);
|
||||
if (val.length === 0) idGlobal.value = 100;
|
||||
},
|
||||
@ -587,120 +609,13 @@ watch(
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<!-- <script>
|
||||
import { debounce } from "throttle-debounce";
|
||||
import ClipboardJS from "clipboard";
|
||||
import render from "@/utils/generator/render";
|
||||
import FormDrawer from "./FormDrawer";
|
||||
|
||||
|
||||
import {
|
||||
inputComponents,
|
||||
selectComponents,
|
||||
layoutComponents,
|
||||
formConf,
|
||||
} from "@/utils/generator/config";
|
||||
import { beautifierConf, titleCase, deepClone } from "@/utils/index";
|
||||
import {
|
||||
makeUpHtml,
|
||||
vueTemplate,
|
||||
vueScript,
|
||||
cssStyle,
|
||||
} from "@/utils/generator/html";
|
||||
import { makeUpJs } from "@/utils/generator/js";
|
||||
import { makeUpCss } from "@/utils/generator/css";
|
||||
|
||||
|
||||
import CodeTypeDialog from "./CodeTypeDialog";
|
||||
import DraggableItem from "./DraggableItem";
|
||||
|
||||
import loadBeautifier from "@/utils/loadBeautifier";
|
||||
import { getForm, addForm, updateForm } from "@/api/workflow/form";
|
||||
import axios from "axios";
|
||||
import Vue from "vue";
|
||||
|
||||
let beautifier;
|
||||
const emptyActiveData = { style: {}, autosize: {} };
|
||||
let oldActiveId;
|
||||
|
||||
const drawingListInDB = getDrawingList();
|
||||
const formConfInDB = getFormConf();
|
||||
|
||||
Vue.prototype.$axios = axios;
|
||||
|
||||
export default {
|
||||
components: {
|
||||
draggable,
|
||||
render,
|
||||
FormDrawer,
|
||||
JsonDrawer,
|
||||
RightPanel,
|
||||
CodeTypeDialog,
|
||||
DraggableItem,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
logo,
|
||||
idGlobal,
|
||||
formConf,
|
||||
inputComponents,
|
||||
selectComponents,
|
||||
layoutComponents,
|
||||
labelWidth: 100,
|
||||
|
||||
drawingData: {},
|
||||
|
||||
|
||||
|
||||
saveDrawingListDebounce: debounce(340, saveDrawingList),
|
||||
saveIdGlobalDebounce: debounce(340, saveIdGlobal),
|
||||
leftComponents: [
|
||||
{
|
||||
title: "输入型组件",
|
||||
list: inputComponents,
|
||||
},
|
||||
{
|
||||
title: "选择型组件",
|
||||
list: selectComponents,
|
||||
},
|
||||
{
|
||||
title: "布局型组件",
|
||||
list: layoutComponents,
|
||||
},
|
||||
],
|
||||
|
||||
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// 防止 firefox 下 拖拽 会新打卡一个选项卡
|
||||
document.body.ondrop = (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
},
|
||||
// 防止 firefox 下 拖拽 会新打卡一个选项卡
|
||||
document.body.ondrop = (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
};
|
||||
</script> -->
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
body,
|
||||
|
@ -11,6 +11,7 @@ export default function createVitePlugins(viteEnv, isBuild = false) {
|
||||
vue(),
|
||||
vueJsx({
|
||||
transformOn: true,
|
||||
// include: ["src/**/*.vue", "src/**/*.jsx"],
|
||||
}),
|
||||
];
|
||||
vitePlugins.push(createAutoImport());
|
||||
|
Reference in New Issue
Block a user