feat: add globalConfig.status for preview status (#2)

* feat: add globalConst.disabled for disable all form-item

* feat: support dx expression

* feat: add globalConfig.status for form status

* feat: preliminary adapte preview status

* chore: adjust code indent

* feat: tune-up standard components preview status realization

* chore: unified code indent
This commit is contained in:
徒言
2019-12-09 09:28:31 +08:00
committed by Dmitry Nagibin
parent 1617776e91
commit ffd6163523
21 changed files with 732 additions and 213 deletions
@@ -48,6 +48,10 @@ export default {
type: Object
},
globalStatus: {
type: String
},
idxChain: {
type: String,
default: ""
@@ -68,7 +72,7 @@ export default {
computed: {
disabled() {
return this._analyzeVal(this.config.disabled);
return this.globalStatus === 'preview' || this._analyzeVal(this.config.disabled);
},
readonly() {
return this._analyzeVal(this.config.readonly);
@@ -57,6 +57,10 @@ export default {
type: Object
},
globalStatus: {
type: String
},
idxChain: {
type: String,
default: ""
@@ -68,6 +72,7 @@ export default {
collapsed: false,
defaultConfig: {
collapsed: false,
disabled: false,
disableCollapse: false,
disableReorder: false,
disableAdd: false,
@@ -86,6 +91,9 @@ export default {
},
computed: {
disabled() {
return this._analyzeVal(this.config.disabled);
},
mergeConfig() {
let newConfig = extend(
true,
@@ -33,6 +33,10 @@ export default {
type: Object
},
globalStatus: {
type: String
},
idxChain: {
type: String,
default: ""
@@ -135,6 +135,7 @@ const ncformUtils = {
// 根节点
const defaultGlobalConfig = {
// 全局配置
status: "edit",
style: {
formCls: "", // form class
invalidFeedbackCls: "" // invalid feedback class
@@ -0,0 +1,402 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport"
content="width=device-width, initial-scale=1.0,minimum-scale=1.0, maximum-scale=1.0, minimal-ui" />
<title>preview demo</title>
<link rel="stylesheet" href="./demo.css" />
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?027aa17f0e14133f0b8aa5f1f0af3ca7";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</head>
<body>
<!--演示区域-->
<div id="demo" v-cloak>
<div v-for="(item, idx) in formSchemas">
<h4 class="demo_title">{{ item.title }}</h4>
<div class="demo_item-wrapper">
<div>
<ncform :form-schema="item.schema" v-model="item.schema.value"></ncform>
</div>
<div>
<pre>{{ JSON.stringify(originFormSchemas[idx].schema.properties, null, 2) }}</pre>
</div>
<div>
<pre>{{ item.schema.value }}</pre>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="../node_modules/lodash/lodash.min.js"></script>
<script type="text/javascript" src="../node_modules/axios/dist/axios.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/vue@2.6.10/dist/vue.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://unpkg.com/mockjs"></script>
<script src="https://unpkg.com/js-url"></script>
<script type="text/javascript" src="../../node_modules/@ncform/ncform-common/dist/ncformCommon.min.js"></script>
<script type="text/javascript" src="../../node_modules/@ncform/ncform/dist/vueNcform.js"></script>
<script type="text/javascript" src="../dist/object.js"></script>
<script type="text/javascript" src="../dist/array.js"></script>
<script type="text/javascript" src="../dist/arrayTable.js"></script>
<script type="text/javascript" src="../dist/arrayTabs.js"></script>
<script type="text/javascript" src="../dist/checkbox.js"></script>
<script type="text/javascript" src="../dist/colorPicker.js"></script>
<script type="text/javascript" src="../dist/datePicker.js"></script>
<script type="text/javascript" src="../dist/input.js"></script>
<script type="text/javascript" src="../dist/inputNumber.js"></script>
<script type="text/javascript" src="../dist/label.js"></script>
<script type="text/javascript" src="../dist/radio.js"></script>
<script type="text/javascript" src="../dist/rate.js"></script>
<script type="text/javascript" src="../dist/select.js"></script>
<script type="text/javascript" src="../dist/slider.js"></script>
<script type="text/javascript" src="../dist/switch.js"></script>
<script type="text/javascript" src="../dist/textarea.js"></script>
<script type="text/javascript" src="../dist/upload.js"></script>
<script type="text/javascript">
let lang = 'en';
if (location.search.indexOf('lang=cn') >= 0) {
lang = 'cn';
}
Mock.mock(/getDomains/, function (options) {
return [{ id: 1, label: '.cn' }, { id: 2, label: '.com' }, { id: 3, label: '.net' }];
});
Mock.mock(/getKeywords/, function (options) {
let params = url('?', options.url) || {};
console.log('getKeywords:', params);
let result = [{ value: 'oppo' }, { value: 'xiaomi' }, { value: 'iphone' }, { value: 'iphone x' }, { value: 'iphone 6s' }];
return { data: result.filter(item => item.value.indexOf(params.keyword) >= 0) };
});
Vue.use(vueNcform, {
extComponents: {
object: object.default,
array: array.default,
arrayTable: arrayTable.default,
arrayTabs: arrayTabs.default,
checkbox: checkbox.default,
colorPicker: colorPicker.default,
datePicker: datePicker.default,
input: input.default,
inputNumber: inputNumber.default,
label: label.default,
radio: radio.default,
rate: rate.default,
select: select.default,
slider: slider.default,
switch: window.switch.default,
textarea: textarea.default,
upload: upload.default,
}, lang: lang === 'cn' ? 'zh_cn' : 'en'
});
let formSchemas = [
{
title: {
cn: '默认状态',
en: 'Default'
},
schema: {
"root": true,
"type": "object",
"properties": {
"input_1574213906497": {
"type": "string",
"ui": {
"widget": "input"
}
},
"input-number_1574213907169": {
"type": "number",
"ui": {
"widget": "input-number"
}
},
"textarea_1574213908025": {
"type": "string",
"ui": {
"widget": "textarea"
}
},
"select_1574213908817": {
"type": "string",
"ui": {
"widget": "select",
"widgetConfig": {
"enumSource": [
{
"value": 1
},
{
"value": 2
}
]
},
"columns": 12,
"showLabel": true,
"noLabelSpace": false,
"showLegend": false,
"help": {
"show": false,
"text": "?"
},
"linkFields": []
},
"rules": {
"customRule": []
}
},
"color-picker_1574213909840": {
"type": "string",
"ui": {
"widget": "color-picker"
}
},
"date-picker_1574213910480": {
"type": "string",
"ui": {
"widget": "date-picker"
}
},
"slider_1574213911424": {
"type": "number",
"ui": {
"widget": "slider"
}
},
"rate_1574213912088": {
"type": "number",
"ui": {
"widget": "rate"
}
},
"radio_1574213912736": {
"type": "boolean",
"ui": {
"widget": "radio"
}
},
"checkbox_1574213913432": {
"type": "boolean",
"ui": {
"widget": "checkbox"
}
},
"upload_1574213914489": {
"type": "array",
"ui": {
"widget": "upload"
}
},
"label_1574213915336": {
"type": "string",
"default": "ccc",
"ui": {
"widget": "label"
}
},
"switch_1574213915936": {
"type": "boolean",
"ui": {
"widget": "switch"
}
},
"object_1574213917664": {
"type": "object",
"ui": {
"widget": "object",
"showLegend": false
},
"properties": {
"input_1574213923517": {
"type": "string",
"ui": {
"widget": "input"
}
},
"slider_1574213927660": {
"type": "number",
"ui": {
"widget": "slider"
}
}
}
},
"array_1574213918451": {
"type": "array",
"ui": {
"widget": "array",
"showLegend": false
},
"items": {
"type": "object",
"properties": {
"color-picker_1574213937826": {
"type": "string",
"ui": {
"widget": "color-picker"
}
},
"input-number_1574213932330": {
"type": "number",
"ui": {
"widget": "input-number"
}
}
}
}
},
"array-table_1574213919360": {
"type": "array",
"ui": {
"widget": "array-table",
"showLegend": false
},
"items": {
"type": "object",
"properties": {
"radio_1574213946074": {
"type": "boolean",
"ui": {
"widget": "radio"
}
},
"rate_1574213943490": {
"type": "number",
"ui": {
"widget": "rate"
}
}
}
}
},
"array-tabs_1574213920104": {
"type": "array",
"ui": {
"widget": "array-tabs",
"showLegend": false
},
"items": {
"type": "object",
"properties": {
"select_1574213957686": {
"type": "string",
"ui": {
"widget": "select",
"widgetConfig": {
"enumSource": [
{
"value": 1
},
{
"value": 2
}
]
},
"columns": 12,
"showLabel": true,
"noLabelSpace": false,
"showLegend": false,
"help": {
"show": false,
"text": "?"
},
"linkFields": []
},
"rules": {
"customRule": []
}
},
"switch_1574213950890": {
"type": "boolean",
"ui": {
"widget": "switch"
}
}
}
}
}
},
"globalConfig": {
status: 'preview'
},
value: {
"input_1574213906497": "aaa",
"input-number_1574213907169": 3,
"textarea_1574213908025": "bbb",
"select_1574213908817": 2,
"color-picker_1574213909840": "#F10404",
"date-picker_1574213910480": "1573660800000",
"slider_1574213911424": 30,
"rate_1574213912088": 4,
"radio_1574213912736": true,
"checkbox_1574213913432": true,
"upload_1574213914489": [{ "name": "girl.jpg", "url": "//user-gold-cdn.xitu.io/2019/3/15/1697f38df3ba0613?w=570&h=273&f=jpeg&s=40278", "uid": 1574927608606 }],
"label_1574213915336": "",
"switch_1574213915936": true,
"object_1574213917664": {
"input_1574213923517": "111",
"slider_1574213927660": 21
},
"array_1574213918451": [
{
"color-picker_1574213937826": "#57FF04",
"input-number_1574213932330": 5
}
],
"array-table_1574213919360": [
{
"radio_1574213946074": true,
"rate_1574213943490": 2
},
{
"radio_1574213946074": false,
"rate_1574213943490": 4
}
],
"array-tabs_1574213920104": [
{
"select_1574213957686": 1,
"switch_1574213950890": true
}
]
}
}
}
]
// Bootstrap the app
new Vue({
el: '#demo',
data: {
formSchemas: getFormSchemas(),
originFormSchemas: getFormSchemas()
}
});
function getFormSchemas() {
return formSchemas.map(item => ({
title: item.title[lang],
schema: item.schema,
detail: item.detail ? item.detail[lang] : ''
}));
}
</script>
</body>
</html>
@@ -1,7 +1,7 @@
<template>
<div
class="ncform-checkbox"
:style="{display: hidden ? 'none' : ''}"
v-show="!hidden"
>
<el-checkbox
v-if="mergeConfig.selectAll && !readonly"
@@ -1,12 +1,28 @@
<template>
<el-color-picker
v-model="modelVal"
:disabled="disabled || readonly"
v-show="!hidden"
></el-color-picker>
<div v-show="!hidden" class="ncform-color-picker">
<div
v-if="globalStatus === 'preview'"
class="ncform-color-picker-preview"
:style="{ borderColor: modelVal }"
>
{{modelVal}}
</div>
<el-color-picker
v-else
v-model="modelVal"
:disabled="disabled || readonly"
></el-color-picker>
</div>
</template>
<style lang="scss" scoped>
.ncform-color-picker-preview {
margin: 8px 0;
padding: 4px 8px;
font-size: 14px;
color: #606266;
border-left: solid 2px;
}
</style>
<script>
@@ -1,18 +1,22 @@
<template>
<el-date-picker class="ncform-date-picker"
v-if="type && typeOptions[type]"
:placeholder="placeholder || $nclang(typeOptions[type].placeholder)"
:disabled="disabled"
:readonly="readonly"
:size="mergeConfig.size"
:clearable="mergeConfig.clearable"
v-show="!hidden"
v-model="modelVal"
:type="type"
:format="mergeConfig.format || $nclang(typeOptions[type].format)"
:value-format="mergeConfig.valueFormat"
>
</el-date-picker>
<div v-show="!hidden" class="ncform-date-picker">
<div v-if="globalStatus === 'preview'" class="ncform-date-picker-preview">
{{formatter(modelVal, mergeConfig.format)}}
</div>
<el-date-picker
v-else-if="type && typeOptions[type]"
:placeholder="placeholder || $nclang(typeOptions[type].placeholder)"
:disabled="disabled"
:readonly="readonly"
:size="mergeConfig.size"
:clearable="mergeConfig.clearable"
v-model="modelVal"
:type="type"
:format="mergeConfig.format || $nclang(typeOptions[type].format)"
:value-format="mergeConfig.valueFormat"
>
</el-date-picker>
</div>
</template>
<style lang="scss">
@@ -33,14 +37,20 @@
}
.ncform-date-picker {
&.el-date-editor.el-input {
.el-date-editor.el-input {
width: 100%;
}
.ncform-date-picker-preview {
color: #606266;
font-size: 14px;
line-height: 40px;
}
}
</style>
<script>
import ncformCommon from '@ncform/ncform-common';
import { formatDate } from 'element-ui/src/utils/date-util';
const controlMixin = ncformCommon.mixins.vue.controlMixin;
@@ -130,6 +140,10 @@ export default {
// 你可以通过该方法在modelVal传出去之前进行加工处理,即在this.$emit('input')之前
_processModelVal(newVal){
return `${newVal ? (this.mergeConfig.valueFormat ? newVal : +new Date(newVal)) : ''}`;
},
formatter(value, format) {
if (format === 'timestamp') return value.getTime();
return formatDate(value, format);
}
}
};
@@ -1,15 +1,18 @@
<template>
<div class="ncform-input-number">
<el-input-number
:disabled="disabled || readonly"
v-show="!hidden"
v-model="modelVal"
:min="mergeConfig.min"
:max="mergeConfig.max"
:step="mergeConfig.step"
:size="mergeConfig.size"
></el-input-number>
<div v-show="!hidden" class="ncform-input-number">
<div v-if="globalStatus === 'preview'" class="ncform-input-number-preview">
{{modelVal}}
</div>
<el-input-number
v-else
v-model="modelVal"
:disabled="disabled || readonly"
:min="mergeConfig.min"
:max="mergeConfig.max"
:step="mergeConfig.step"
:size="mergeConfig.size"
></el-input-number>
</div>
</template>
<style lang="scss">
@@ -28,6 +31,12 @@
}
}
}
.ncform-input-number-preview {
color: #606266;
font-size: 14px;
line-height: 40px;
}
</style>
<script>
@@ -1,5 +1,5 @@
<template>
<div class="ncform-input">
<div v-show="!hidden" class="ncform-input">
<!-- 没有自动补全 -->
<el-input
v-if="!mergeConfig.autocomplete"
@@ -7,7 +7,6 @@
:disabled="disabled"
:readonly="readonly"
:placeholder="placeholder"
v-show="!hidden"
:clearable="mergeConfig.clearable"
:type="mergeConfig.type === 'file' ? 'text' : mergeConfig.type"
:prefix-icon="mergeConfig.prefixIcon"
@@ -90,7 +89,6 @@
:disabled="disabled"
:readonly="readonly"
:placeholder="placeholder"
v-show="!hidden"
:clearable="mergeConfig.clearable"
:size="mergeConfig.size"
:type="mergeConfig.type"
@@ -1,21 +1,20 @@
<template>
<div class="ncform-radio">
<el-radio-group
v-model="modelVal"
:disabled="disabled"
v-show="!hidden && !readonly"
size="mini"
>
<component :is="'el-radio' + (mergeConfig.type === 'button' ? '-button' : '')"
v-for="opt in dataSource"
:key="opt[mergeConfig.itemValueField]"
:label="opt[mergeConfig.itemValueField]"
:class="mergeConfig.type === 'radio' && mergeConfig.arrangement === 'v' ? 'is-vertical' : ''"
>{{opt[mergeConfig.itemLabelField]}}</component>
</el-radio-group>
<div class="ncform-radio" v-show="!hidden && !readonly">
<el-radio-group
v-model="modelVal"
:disabled="disabled"
size="mini"
>
<component :is="'el-radio' + (mergeConfig.type === 'button' ? '-button' : '')"
v-for="opt in dataSource"
:key="opt[mergeConfig.itemValueField]"
:label="opt[mergeConfig.itemValueField]"
:class="mergeConfig.type === 'radio' && mergeConfig.arrangement === 'v' ? 'is-vertical' : ''"
>{{opt[mergeConfig.itemLabelField]}}</component>
</el-radio-group>
<label v-show="readonly" class="label-read">{{labelRead}}</label>
</div>
<label v-show="readonly" class="label-read">{{labelRead}}</label>
</div>
</template>
<style lang="scss">
@@ -1,24 +1,25 @@
<template>
<el-rate class="ncform-rate"
:disabled="disabled || readonly"
:placeholder="placeholder"
v-show="!hidden"
v-model="modelVal"
:max="mergeConfig.max"
:allow-half="mergeConfig.allowHalf"
:low-threshold="mergeConfig.lowThreshold"
:high-threshold="mergeConfig.highThreshold"
:colors="mergeConfig.colors"
:void-color="mergeConfig.voidColor"
:disabled-void-color="mergeConfig.disabledVoidColor"
:icon-classes="mergeConfig.iconClasses"
:void-icon-class="mergeConfig.voidIconClass"
:disabled-void-icon-class="mergeConfig.disabledVoidIconClass"
:show-text="mergeConfig.showText"
:show-score="mergeConfig.showScore"
:text-color="mergeConfig.textColor"
:texts="mergeConfig.texts"
></el-rate>
<div v-show="!hidden" class="ncform-rate">
<el-rate
v-model="modelVal"
:disabled="disabled || readonly"
:placeholder="placeholder"
:max="mergeConfig.max"
:allow-half="mergeConfig.allowHalf"
:low-threshold="mergeConfig.lowThreshold"
:high-threshold="mergeConfig.highThreshold"
:colors="mergeConfig.colors"
:void-color="mergeConfig.voidColor"
:disabled-void-color="mergeConfig.disabledVoidColor"
:icon-classes="mergeConfig.iconClasses"
:void-icon-class="mergeConfig.voidIconClass"
:disabled-void-icon-class="mergeConfig.disabledVoidIconClass"
:show-text="mergeConfig.showText"
:show-score="mergeConfig.showScore"
:text-color="mergeConfig.textColor"
:texts="mergeConfig.texts"
></el-rate>
</div>
</template>
<style lang="scss">
@@ -1,31 +1,37 @@
<template>
<el-select
v-model="modelVal"
:placeholder="placeholder || $nclang('selectPls')"
v-show="!hidden"
:disabled="disabled || readonly"
:size="mergeConfig.size"
:clearable="mergeConfig.clearable"
:multiple="mergeConfig.multiple"
:filterable="mergeConfig.filterable"
:remote="!isLocalSource && !mergeConfig.filterLocal"
:remote-method="(!isLocalSource && !mergeConfig.filterLocal) ? remoteMethod : null"
:loading="loading"
@change="handleChange"
@visible-change="handleVisibleChange"
>
<el-option
v-for="item in optionsData"
:key="item[mergeConfig.itemValueField]"
:label="item[mergeConfig.itemLabelField]"
:value="item[mergeConfig.itemValueField]"
<div v-show="!hidden" class="ncform-select">
<el-select
v-model="modelVal"
:placeholder="placeholder || $nclang('selectPls')"
:disabled="disabled || readonly"
:size="mergeConfig.size"
:clearable="mergeConfig.clearable"
:multiple="mergeConfig.multiple"
:filterable="mergeConfig.filterable"
:remote="!isLocalSource && !mergeConfig.filterLocal"
:remote-method="(!isLocalSource && !mergeConfig.filterLocal) ? remoteMethod : null"
:loading="loading"
@change="handleChange"
@visible-change="handleVisibleChange"
>
<component v-if="itemTemplate.template" :item="item" :is="itemTemplate"></component>
</el-option>
</el-select>
<el-option
v-for="item in optionsData"
:key="item[mergeConfig.itemValueField]"
:label="item[mergeConfig.itemLabelField]"
:value="item[mergeConfig.itemValueField]"
>
<component v-if="itemTemplate.template" :item="item" :is="itemTemplate"></component>
</el-option>
</el-select>
</div>
</template>
<style lang="scss" scoped>
.ncform-select {
.el-select {
width: 100%;
}
}
</style>
<script>
@@ -97,6 +103,7 @@ export default {
template: '',
props: ["item"]
},
selectedLabel: '',
loading: false
};
@@ -1,20 +1,16 @@
<template>
<div style="float:left;">
<el-slider
:disabled="disabled || readonly"
:placeholder="placeholder"
v-show="!hidden"
v-model="modelVal"
:min="mergeConfig.min"
:max="mergeConfig.max"
:step="mergeConfig.step"
></el-slider>
<div v-show="!hidden" class="ncform-slider" style="float: left;">
<el-slider
v-model="modelVal"
:disabled="disabled || readonly"
:placeholder="placeholder"
:min="mergeConfig.min"
:max="mergeConfig.max"
:step="mergeConfig.step"
></el-slider>
</div>
</template>
<style lang="scss" scoped>
</style>
<script>
import ncformCommon from '@ncform/ncform-common';
@@ -1,19 +1,19 @@
<template>
<el-switch
class="ncform-switch"
v-model="modelVal"
:disabled="disabled || readonly"
:width="mergeConfig.width"
:active-icon-class="mergeConfig.activeIconClass"
:inactive-icon-class="mergeConfig.inactiveIconClass"
:active-text="mergeConfig.activeText"
:inactive-text="mergeConfig.inactiveText"
:active-value="mergeConfig.activeValue"
:inactive-value="mergeConfig.inactiveValue"
:active-color="mergeConfig.activeColor"
:inactive-color="mergeConfig.inactiveColor"
v-show="!hidden"
></el-switch>
<div v-show="!hidden" class="ncform-switch">
<el-switch
v-model="modelVal"
:disabled="disabled || readonly"
:width="mergeConfig.width"
:active-icon-class="mergeConfig.activeIconClass"
:inactive-icon-class="mergeConfig.inactiveIconClass"
:active-text="mergeConfig.activeText"
:inactive-text="mergeConfig.inactiveText"
:active-value="mergeConfig.activeValue"
:inactive-value="mergeConfig.inactiveValue"
:active-color="mergeConfig.activeColor"
:inactive-color="mergeConfig.inactiveColor"
></el-switch>
</div>
</template>
<style lang="scss">
@@ -1,18 +1,28 @@
<template>
<el-input
:disabled="disabled"
:readonly="readonly"
v-show="!hidden"
:placeholder="placeholder"
type="textarea"
v-model="inputVal"
:rows="mergeConfig.rows"
:autosize="mergeConfig.autoSize"
@blur="onBlur"
></el-input>
<div v-show="!hidden" class="ncform-textarea">
<pre v-if="globalStatus === 'preview'" class="ncform-textarea-preview">{{inputVal}}</pre>
<el-input
v-else
v-show="!hidden"
v-model="inputVal"
type="textarea"
:disabled="disabled"
:readonly="readonly"
:placeholder="placeholder"
:rows="mergeConfig.rows"
:autosize="mergeConfig.autoSize"
@blur="onBlur"
></el-input>
</div>
</template>
<style lang="scss" scoped>
.ncform-textarea-preview {
color: #606266;
font-size: 14px;
line-height: 1.5;
margin: 0;
}
</style>
<script>
@@ -1,70 +1,107 @@
<template>
<el-upload
ref="upload"
:class="['ncform-upload', readonly ? 'is-read-only' : '']"
:disabled="readonly || disabled"
:style="{display: hidden ? 'none' : ''}"
:action="mergeConfig.uploadUrl"
:multiple="mergeConfig.multiple"
:data="mergeConfig.data"
:show-file-list="showFileList"
:drag="mergeConfig.drag"
:accept="mergeConfig.accept"
:list-type="mergeConfig.listType"
:auto-upload="mergeConfig.autoUpload"
:limit="mergeConfig.limit"
:on-change="handleUploadChange"
:on-success="handleUploadSucess"
:on-error="handleUploadError"
:on-exceed="handleUploadExceed"
:on-remove="handleUploadRemove"
:file-list="fileList"
:name="mergeConfig.fileField"
:headers="mergeConfig.headers"
>
<!-- 1. 可拖拽 -->
<template v-if="!readonly && mergeConfig.drag" slot="trigger">
<i class="el-icon-upload"></i>
<div class="el-upload__text" v-html="$nclang('uploadTips')"></div>
</template>
<div v-if="mergeConfig.drag && disabled" class="disabled-mask"></div>
<div v-show="!hidden" class="ncform-upload">
<div v-if="globalStatus === 'preview'" class="ncform-upload-preview">
<transition-group
tag="ul"
:class="[
'el-upload-list',
'el-upload-list--' + mergeConfig.listType,
]"
name="el-list"
>
<li
v-for="(file, index) in modelVal"
:class="['el-upload-list__item', 'is-' + file.status, focusing ? 'focusing' : '']"
:key="index"
tabindex="0"
>
<slot :file="file">
<img
class="el-upload-list__item-thumbnail"
v-if="file.status !== 'uploading' && ['picture-card', 'picture'].indexOf(mergeConfig.listType) > -1"
:src="file.url" alt=""
>
<a class="el-upload-list__item-name">
<i class="el-icon-document"></i>{{file.name}}
</a>
<label class="el-upload-list__item-status-label">
<i :class="{
'el-icon-upload-success': true,
'el-icon-circle-check': mergeConfig.listType === 'text',
'el-icon-check': ['picture-card', 'picture'].indexOf(mergeConfig.listType) > -1
}"></i>
</label>
</slot>
</li>
</transition-group>
</div>
<el-upload
v-else
ref="upload"
:class="[readonly ? 'is-read-only' : '']"
:disabled="readonly || disabled"
:action="mergeConfig.uploadUrl"
:multiple="mergeConfig.multiple"
:data="mergeConfig.data"
:show-file-list="showFileList"
:drag="mergeConfig.drag"
:accept="mergeConfig.accept"
:list-type="mergeConfig.listType"
:auto-upload="mergeConfig.autoUpload"
:limit="mergeConfig.limit"
:on-change="handleUploadChange"
:on-success="handleUploadSucess"
:on-error="handleUploadError"
:on-exceed="handleUploadExceed"
:on-remove="handleUploadRemove"
:file-list="fileList"
:name="mergeConfig.fileField"
:headers="mergeConfig.headers"
>
<!-- 1. 可拖拽 -->
<template v-if="!readonly && mergeConfig.drag" slot="trigger">
<i class="el-icon-upload"></i>
<div class="el-upload__text" v-html="$nclang('uploadTips')"></div>
</template>
<div v-if="mergeConfig.drag && disabled" class="disabled-mask"></div>
<!-- 2 可拖拽非自动上传 -->
<el-button
v-if="!readonly && mergeConfig.drag && !mergeConfig.autoUpload"
:disabled="disabled"
class="upload-btn"
size="small"
type="success"
@click="submitUpload"
>{{$nclang('uploadServer')}}</el-button>
<!-- 3. 不可拖拽自动上传-->
<el-button
v-if="!readonly && !mergeConfig.drag && mergeConfig.autoUpload"
:disabled="disabled"
size="small"
type="primary"
>{{$nclang('upload')}}</el-button>
<!-- 4. 不可拖拽非自动上传 -->
<template v-if="!readonly && !mergeConfig.drag && !mergeConfig.autoUpload">
<el-button
:disabled="disabled"
slot="trigger"
size="small"
type="primary"
>{{$nclang('chFile')}}</el-button>
<!-- 2 可拖拽非自动上传 -->
<el-button
v-if="!readonly && mergeConfig.drag && !mergeConfig.autoUpload"
:disabled="disabled"
class="upload-btn"
size="small"
type="success"
@click="submitUpload"
>{{$nclang('uploadServer')}}</el-button>
</template>
</el-upload>
<!-- 3. 不可拖拽自动上传-->
<el-button
v-if="!readonly && !mergeConfig.drag && mergeConfig.autoUpload"
:disabled="disabled"
size="small"
type="primary"
>{{$nclang('upload')}}</el-button>
<!-- 4. 不可拖拽非自动上传 -->
<template v-if="!readonly && !mergeConfig.drag && !mergeConfig.autoUpload">
<el-button
:disabled="disabled"
slot="trigger"
size="small"
type="primary"
>{{$nclang('chFile')}}</el-button>
<el-button
:disabled="disabled"
class="upload-btn"
size="small"
type="success"
@click="submitUpload"
>{{$nclang('uploadServer')}}</el-button>
</template>
</el-upload>
</div>
</template>
<style lang="scss">
@@ -13,7 +13,7 @@
</colgroup>
<colgroup v-else>
<col v-for="(renderSchema, idx) in renderSchemas" :key="idx" v-show="!analyzeItemVal(renderSchema.ui.hidden, idx)"/>
<col v-if="showActionColumn" width="130px"/>
<col v-if="globalStatus !== 'preview' && showActionColumn" width="130px"/>
</colgroup>
<thead>
<th v-for="(renderSchema, idx) in renderSchemas" :key="idx" v-show="!analyzeItemVal(renderSchema.ui.hidden, idx)">
@@ -33,7 +33,7 @@
</small>
</th>
<th v-if="showActionColumn">{{$nclang('action')}}</th>
<th v-if="globalStatus !== 'preview' && showActionColumn">{{$nclang('action')}}</th>
</thead>
<tbody>
<tr v-for="(dataItem, idx) in schema.value" :key="dataItem.__dataSchema.__id">
@@ -41,23 +41,23 @@
<slot :name="fieldName" :schema="fieldSchema" :idx="idx"></slot>
</td>
<td v-if="showActionColumn">
<td v-if="globalStatus !== 'preview' && showActionColumn">
<!-- 项控制按钮 -->
<div class="el-button-group">
<button @click="delItem(idx, mergeConfig.requiredDelConfirm, mergeConfig.delConfirmText.item || $nclang('delItemTips'))" v-if="(!mergeConfig.disableDel && !isDelExceptionRow(dataItem.__dataSchema)) || (mergeConfig.disableDel && isDelExceptionRow(dataItem.__dataSchema))" type="button" class="el-button el-button--danger el-button--mini"><i class="el-icon-remove"></i></button>
<button @click="itemUp(idx)" v-show="idx !== 0" v-if="!mergeConfig.disableReorder" type="button" class="el-button el-button--mini"><i class="el-icon-sort-up"></i></button>
<button @click="itemDown(idx)" v-show="idx !== schema.value.length - 1" v-if="!mergeConfig.disableReorder" type="button" class="el-button el-button--mini"><i class="el-icon-sort-down"></i></button>
<button @click="delItem(idx, mergeConfig.requiredDelConfirm, mergeConfig.delConfirmText.item || $nclang('delItemTips'))" v-if="(!mergeConfig.disableDel && !isDelExceptionRow(dataItem.__dataSchema)) || (mergeConfig.disableDel && isDelExceptionRow(dataItem.__dataSchema))" :disabled="disabled" type="button" class="el-button el-button--danger el-button--mini"><i class="el-icon-remove"></i></button>
<button @click="itemUp(idx)" v-show="idx !== 0" v-if="!mergeConfig.disableReorder" :disabled="disabled" type="button" class="el-button el-button--mini"><i class="el-icon-sort-up"></i></button>
<button @click="itemDown(idx)" v-show="idx !== schema.value.length - 1" v-if="!mergeConfig.disableReorder" :disabled="disabled" type="button" class="el-button el-button--mini"><i class="el-icon-sort-down"></i></button>
</div>
</td>
</tr>
</tbody>
<tfoot v-if="!mergeConfig.disableDel || !mergeConfig.disableAdd">
<tfoot v-if="globalStatus !== 'preview' && (!mergeConfig.disableDel || !mergeConfig.disableAdd)">
<tr>
<td :colspan="renderSchemas.length + 1">
<!-- 列表控制按钮 -->
<div class="el-button-group" v-if="!mergeConfig.disableAdd || !mergeConfig.disableDel">
<button @click="addItem()" v-if="!mergeConfig.disableAdd" type="button" class="el-button el-button--mini"><i class="el-icon-circle-plus-outline"></i> {{mergeConfig.addTxt || $nclang('add')}}</button>
<button @click="delAllItems(mergeConfig.requiredDelConfirm, mergeConfig.delConfirmText.all || $nclang('delAllTips'))" v-if="!mergeConfig.disableDel" type="button" class="el-button el-button--danger el-button--mini"><i class="el-icon-remove"></i> {{mergeConfig.delAllTxt || $nclang('delAll')}}</button>
<button @click="addItem()" v-if="!mergeConfig.disableAdd" :disabled="disabled" type="button" class="el-button el-button--mini"><i class="el-icon-circle-plus-outline"></i> {{mergeConfig.addTxt || $nclang('add')}}</button>
<button @click="delAllItems(mergeConfig.requiredDelConfirm, mergeConfig.delConfirmText.all || $nclang('delAllTips'))" v-if="!mergeConfig.disableDel" :disabled="disabled" type="button" class="el-button el-button--danger el-button--mini"><i class="el-icon-remove"></i> {{mergeConfig.delAllTxt || $nclang('delAll')}}</button>
</div>
</td>
</tr>
@@ -7,8 +7,8 @@
<i v-if="!mergeConfig.disableCollapse" class="el-collapse-item__arrow" :class="{'el-icon-arrow-up': !collapsed, 'el-icon-arrow-down': collapsed}"></i>
</legend>
<el-tabs v-show="!collapsed" :addable="!mergeConfig.disableAdd" type="card" :tab-position="mergeConfig.tabPosition" @edit="handleTabsEdit" v-model="activeName">
<el-tab-pane v-for="(dataItem, idx) in schema.value" :key="dataItem.__dataSchema.__id" :closable="(!mergeConfig.disableDel && !isDelExceptionRow(dataItem.__dataSchema)) || (mergeConfig.disableDel && isDelExceptionRow(dataItem.__dataSchema))" :name="'' + idx">
<el-tabs v-show="!collapsed" :addable="globalStatus !== 'preview' && !disabled && !mergeConfig.disableAdd" type="card" :tab-position="mergeConfig.tabPosition" @edit="handleTabsEdit" v-model="activeName">
<el-tab-pane v-for="(dataItem, idx) in schema.value" :key="dataItem.__dataSchema.__id" :closable="globalStatus !== 'preview' && !disabled && (!mergeConfig.disableDel && !isDelExceptionRow(dataItem.__dataSchema)) || (mergeConfig.disableDel && isDelExceptionRow(dataItem.__dataSchema))" :name="'' + idx">
<span slot="label">
{{_analyzeVal(dataItem.__dataSchema.ui.label) + ' ' + (idx + 1)}}
@@ -14,11 +14,13 @@
<!-- 项控制按钮 -->
<div class="el-button-group">
<button @click="collapseItem(dataItem.__dataSchema)" v-show="dataItem.__dataSchema._expand" v-if="!mergeConfig.disableItemCollapse" type="button" class="el-button el-button--mini"><i class="el-icon-arrow-down"></i></button>
<button @click="collapseItem(dataItem.__dataSchema)" v-show="!dataItem.__dataSchema._expand" v-if="!mergeConfig.disableItemCollapse" type="button" class="el-button el-button--mini"><i class="el-icon-arrow-up"></i></button>
<button @click="delItem(idx, mergeConfig.requiredDelConfirm, mergeConfig.delConfirmText.item || $nclang('delItemTips'))" v-if="(!mergeConfig.disableDel && !isDelExceptionRow(dataItem.__dataSchema)) || (mergeConfig.disableDel && isDelExceptionRow(dataItem.__dataSchema))" type="button" class="el-button el-button--danger el-button--mini"><i class="el-icon-remove"></i></button>
<button @click="itemUp(idx)" v-show="idx !== 0" v-if="!mergeConfig.disableReorder" type="button" class="el-button el-button--mini"><i class="el-icon-sort-up"></i></button>
<button @click="itemDown(idx)" v-show="idx !== schema.value.length - 1" v-if="!mergeConfig.disableReorder" type="button" class="el-button el-button--mini"><i class="el-icon-sort-down"></i></button>
<button @click="collapseItem(dataItem.__dataSchema)" v-show="dataItem.__dataSchema._expand" v-if="!mergeConfig.disableItemCollapse" :disabled="disabled" type="button" class="el-button el-button--mini"><i class="el-icon-arrow-down"></i></button>
<button @click="collapseItem(dataItem.__dataSchema)" v-show="!dataItem.__dataSchema._expand" v-if="!mergeConfig.disableItemCollapse" :disabled="disabled" type="button" class="el-button el-button--mini"><i class="el-icon-arrow-up"></i></button>
<template v-if="globalStatus !== 'preview'">
<button @click="delItem(idx, mergeConfig.requiredDelConfirm, mergeConfig.delConfirmText.item || $nclang('delItemTips'))" v-if="(!mergeConfig.disableDel && !isDelExceptionRow(dataItem.__dataSchema)) || (mergeConfig.disableDel && isDelExceptionRow(dataItem.__dataSchema))" :disabled="disabled" type="button" class="el-button el-button--danger el-button--mini"><i class="el-icon-remove"></i></button>
<button @click="itemUp(idx)" v-show="idx !== 0" v-if="!mergeConfig.disableReorder" :disabled="disabled" type="button" class="el-button el-button--mini"><i class="el-icon-sort-up"></i></button>
<button @click="itemDown(idx)" v-show="idx !== schema.value.length - 1" v-if="!mergeConfig.disableReorder" :disabled="disabled" type="button" class="el-button el-button--mini"><i class="el-icon-sort-down"></i></button>
</template>
</div>
</div>
@@ -43,9 +45,9 @@
</div>
<!-- 列表控制按钮 -->
<div v-show="!collapsed" class="el-button-group" v-if="!mergeConfig.disableAdd || !mergeConfig.disableDel">
<button @click="addItem()" v-if="!mergeConfig.disableAdd" type="button" class="el-button el-button--mini"><i class="el-icon-circle-plus-outline"></i> {{mergeConfig.addTxt || $nclang('add')}}</button>
<button @click="delAllItems(mergeConfig.requiredDelConfirm, mergeConfig.delConfirmText.all || $nclang('delAllTips'))" v-if="!mergeConfig.disableDel" type="button" class="el-button el-button--danger el-button--mini"><i class="el-icon-remove"></i> {{mergeConfig.delAllTxt || $nclang('delAll')}}</button>
<div v-show="!collapsed" class="el-button-group" v-if="globalStatus !== 'preview' && (!mergeConfig.disableAdd || !mergeConfig.disableDel)">
<button @click="addItem()" v-if="!mergeConfig.disableAdd" :disabled="disabled" type="button" class="el-button el-button--mini"><i class="el-icon-circle-plus-outline"></i> {{mergeConfig.addTxt || $nclang('add')}}</button>
<button @click="delAllItems(mergeConfig.requiredDelConfirm, mergeConfig.delConfirmText.all || $nclang('delAllTips'))" v-if="!mergeConfig.disableDel" :disabled="disabled" type="button" class="el-button el-button--danger el-button--mini"><i class="el-icon-remove"></i> {{mergeConfig.delAllTxt || $nclang('delAll')}}</button>
</div>
</div>
@@ -3,7 +3,7 @@
<div :class="[(!!schema.__validationResult && !schema.__validationResult.result) ? 'invalid' : '', schema.ui.itemClass]">
<!-- object 类型 -->
<component v-if="isNormalObjSchema(schema)" :is="'ncform-' + schema.ui.widget" :schema="schema" :form-data="formData" :temp-data="tempData" :global-const="globalConfig.constants" :idx-chain="idxChain" :config="schema.ui.widgetConfig">
<component v-if="isNormalObjSchema(schema)" :is="'ncform-' + schema.ui.widget" :schema="schema" v-bind="commonAttrs">
<template v-for="(fieldSchema, fieldName) in schema.properties" :slot="fieldName">
<form-item :schema="fieldSchema" :form-data="formData" :temp-data="tempData" :global-const="globalConfig.constants" :key="fieldName" :global-config="globalConfig" :idx-chain="idxChain" :complete-schema="completeSchema" :paths="paths ? paths + '.' + fieldName : fieldName" :form-name="formName"></form-item>
@@ -12,7 +12,7 @@
</component>
<!-- array 类型 -->
<component v-else-if="isNormalArrSchema(schema)" :is="'ncform-' + schema.ui.widget" :schema="schema" :form-data="formData" :temp-data="tempData" :global-const="globalConfig.constants" :idx-chain="idxChain" :config="schema.ui.widgetConfig" class="__ncform-control">
<component v-else-if="isNormalArrSchema(schema)" :is="'ncform-' + schema.ui.widget" :schema="schema" v-bind="commonAttrs" class="__ncform-control">
<template v-for="(fieldSchema, fieldName) in (schema.items.properties || {__notObjItem: schema.items})" :slot="fieldName" slot-scope="props">
<form-item :schema="props.schema" :key="fieldName" :form-data="formData" :temp-data="tempData" :global-const="globalConfig.constants" :idx-chain="(idxChain ? idxChain + ',' : '') + props.idx" :global-config="globalConfig" :complete-schema="completeSchema" :paths="paths + '[' + props.idx + ']'" :form-name="formName"></form-item>
@@ -27,12 +27,12 @@
<!-- 特殊类型 COMP -->
<template v-else-if="schema.type === 'COMP'">
<component :is="schema.ui.widget" :config="schema.ui.widgetConfig" :form-data="formData" :temp-data="tempData" :global-const="globalConfig.constants" :idx-chain="idxChain"></component>
<component :is="schema.ui.widget" v-bind="commonAttrs"></component>
</template>
<!-- string / number / integer / boolean 类型 -->
<template v-else>
<component :is="'ncform-' + schema.ui.widget" :config="schema.ui.widgetConfig" v-model="schema.value" :form-data="formData" :temp-data="tempData" :global-const="globalConfig.constants" :idx-chain="idxChain" class="__ncform-control">
<component :is="'ncform-' + schema.ui.widget" v-model="schema.value" v-bind="commonAttrs" class="__ncform-control">
</component>
<div class="__ncform-item-preview" v-if="schema.ui.preview && schema.value"
:style="{width: schema.ui.preview.outward && schema.ui.preview.outward.width ? schema.ui.preview.outward.width + 'px' : 'auto', height: schema.ui.preview.outward && schema.ui.preview.outward.height ? schema.ui.preview.outward.height + 'px' : 'auto'}" >
@@ -159,6 +159,17 @@ export default {
},
computed: {
commonAttrs() {
return {
formData: this.formData,
tempData: this.tempData,
idxChain: this.idxChain,
config: this.schema.ui.widgetConfig,
globalConst: this.globalConfig.constants,
globalStatus: this.globalConfig.status
}
},
valueTemplate() {
if (!this.schema.valueTemplate) return undefined;