feat: 增加自定义基础属性的功能

This commit is contained in:
albert
2024-03-21 12:44:00 +08:00
parent e8ebd2606a
commit ae5d9f7d39
4 changed files with 135 additions and 80 deletions

View File

@@ -1,21 +1,37 @@
<template> <template>
<div id="app"> <div id="app">
<div class="title"> <div class="title">
<a href="https://github.com/zyqwst/json-schema-editor-vue" target="_blank">json-schema-editor-vue</a> <a href="https://github.com/zyqwst/json-schema-editor-vue" target="_blank"
>json-schema-editor-vue</a
>
<span class="version"> version{{ version }}</span> <span class="version"> version{{ version }}</span>
</div> </div>
<div class="desc"> <div class="desc">
<div>A json-schema editor of high efficient and easy-to-use, base on Vue. <div>
A json-schema editor of high efficient and easy-to-use, base on Vue.
<a @click="visible = true">import json</a> <a @click="visible = true">import json</a>
</div> </div>
</div> </div>
<div class="container"> <div class="container">
<codemirror class="code" v-model="jsonStr" :readOnly="false"/> <codemirror class="code" v-model="jsonStr" :readOnly="false" />
<json-schema-editor class="schema" :value="tree" disabledType lang="zh_CN" custom/> <json-schema-editor
class="schema"
:value="tree"
disabledType
lang="zh_CN"
custom
:extra="extraSetting"
/>
</div> </div>
<a-modal v-model="visible" title="import json" width="800px" height="600x" @ok="handleImportJson"> <a-modal
v-model="visible"
title="import json"
width="800px"
height="600x"
@ok="handleImportJson"
>
<div class="code-container"> <div class="code-container">
<codemirror class="code" v-model="importJson" :readOnly="false"/> <codemirror class="code" v-model="importJson" :readOnly="false" />
</div> </div>
</a-modal> </a-modal>
</div> </div>
@@ -23,122 +39,132 @@
<script> <script>
var app = require("../package.json"); var app = require("../package.json");
import Codemirror from './components/Codemirror.vue' import Codemirror from "./components/Codemirror.vue";
import GenerateSchema from 'generate-schema' import GenerateSchema from "generate-schema";
export default { export default {
name: 'App', name: "App",
components: { Codemirror }, components: { Codemirror },
computed: { computed: {
jsonStr: { jsonStr: {
get: function () { get: function () {
return JSON.stringify(this.tree, null, 2) return JSON.stringify(this.tree, null, 2);
}, },
set: function (newVal) { set: function (newVal) {
this.tree = JSON.parse(newVal) this.tree = JSON.parse(newVal);
} },
} },
}, },
data() { data() {
return { return {
version: app.version, version: app.version,
importJson: '', importJson: "",
visible: false, visible: false,
tree: extraSetting: {
{ integer: {
"root": { default: {
"type": "object", name: "默认值",
"title": "条件", type: "integer",
"properties": { },
"name": { },
"type": "string", string: {
"title": "名称", default: {
"maxLength": 10, name: "默认值",
"minLength": 2 type: "integer",
},
},
}, },
"appId": { tree: {
"type": "integer", root: {
"title": "应用ID" type: "object",
title: "条件",
properties: {
name: {
type: "string",
title: "名称",
maxLength: 10,
minLength: 2,
},
appId: {
type: "integer",
title: "应用ID",
default: 3,
},
credate: {
type: "string",
title: "创建日期",
format: "date",
},
},
required: ["name", "appId", "credate"],
},
}, },
"credate": { };
"type": "string",
"title": "创建日期",
"format": "date"
}
},
"required": [
"name",
"appId",
"credate"
]
}
}
}
}, },
methods: { methods: {
handleImportJson () { handleImportJson() {
const t = GenerateSchema.json(JSON.parse(this.importJson)) const t = GenerateSchema.json(JSON.parse(this.importJson));
delete t.$schema delete t.$schema;
this.tree.root = t this.tree.root = t;
this.visible = false this.visible = false;
} },
} },
} };
</script> </script>
<style> <style>
*{ * {
padding:0; padding: 0;
margin:0; margin: 0;
box-sizing: border-box; box-sizing: border-box;
} }
.title{ .title {
text-align: center; text-align: center;
font-size: 40px; font-size: 40px;
font-weight: bold; font-weight: bold;
height:100px; height: 100px;
line-height: 100px; line-height: 100px;
} }
.version{ .version {
font-size: 16px; font-size: 16px;
} }
.desc{ .desc {
padding:20px; padding: 20px;
width:80vw; width: 80vw;
min-width:800px; min-width: 800px;
margin:auto; margin: auto;
padding: 0 3em; padding: 0 3em;
font-size: 1.2em; font-size: 1.2em;
} }
.container{ .container {
display: flex; display: flex;
padding:20px; padding: 20px;
width:80vw; width: 80vw;
min-width:800px; min-width: 800px;
justify-content:center; justify-content: center;
height: calc(100vh - 150px); height: calc(100vh - 150px);
margin:auto; margin: auto;
} }
.code-container{ .code-container {
max-height: 600px; max-height: 600px;
overflow: auto; overflow: auto;
} }
.schema{ .schema {
margin-left: 20px; margin-left: 20px;
width:50%; width: 50%;
height: 100%; height: 100%;
overflow-y: auto; overflow-y: auto;
overflow-x:hidden; overflow-x: hidden;
border:1px solid rgba(0,0,0,.1); border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 8px; border-radius: 8px;
padding: 12px; padding: 12px;
} }
.CodeMirror { .CodeMirror {
height: 100% !important; height: 100% !important;
} }
.vue-codemirror{ .vue-codemirror {
flex:1; flex: 1;
margin: 0 24px; margin: 0 24px;
border: 1px solid rgba(0,0,0,.1); border: 1px solid rgba(0, 0, 0, 0.1);
min-height:300px; min-height: 300px;
overflow: auto; overflow: auto;
border-radius: 6px; border-radius: 6px;
} }

View File

@@ -17,7 +17,7 @@ const langs = {
'cancel':'Cancel', 'cancel':'Cancel',
'minLength':'Min length', 'minLength':'Min length',
'maxLength': 'Max length', 'maxLength': 'Max length',
'pattern':'MUST be a valid regular expression.', 'pattern':'Must be a valid regular expression.',
'exclusiveMinimum': 'Value strictly less than', 'exclusiveMinimum': 'Value strictly less than',
'exclusiveMaximum': 'Value strictly more than', 'exclusiveMaximum': 'Value strictly more than',
'minimum': 'Min', 'minimum': 'Min',

View File

@@ -61,7 +61,7 @@
<a-row :gutter="6"> <a-row :gutter="6">
<a-col :span="8" v-for="(item,key) in advancedValue" :key="key"> <a-col :span="8" v-for="(item,key) in advancedValue" :key="key">
<a-form-item> <a-form-item>
<span>{{ local[key] }}</span> <span>{{ advancedAttr[key].extra ? (lang=='en_US'? key : advancedAttr[key].name):local[key] }}</span>
<a-input-number v-model="advancedValue[key]" v-if="advancedAttr[key].type === 'integer' || advancedAttr[key].type === 'number'" style="width:100%" :placeholder="key"/> <a-input-number v-model="advancedValue[key]" v-if="advancedAttr[key].type === 'integer' || advancedAttr[key].type === 'number'" style="width:100%" :placeholder="key"/>
<span v-else-if="advancedAttr[key].type === 'boolean'" style="display:inline-block;width:100%"> <span v-else-if="advancedAttr[key].type === 'boolean'" style="display:inline-block;width:100%">
<a-switch v-model="advancedValue[key]"/> <a-switch v-model="advancedValue[key]"/>
@@ -115,7 +115,7 @@
</template> </template>
<script> <script>
import Vue from 'vue' import Vue from 'vue'
import { isNull, renamePropertyAndKeepKeyPrecedence } from './util' import { isNull, renamePropertyAndKeepKeyPrecedence, arrayDifference } from './util'
import {TYPE_NAME, TYPE} from './type/type' import {TYPE_NAME, TYPE} from './type/type'
import { Row,Col,Button,Input,InputNumber, Icon,Checkbox,Select,Tooltip,Modal,Form,Switch} from 'ant-design-vue' import { Row,Col,Button,Input,InputNumber, Icon,Checkbox,Select,Tooltip,Modal,Form,Switch} from 'ant-design-vue'
import LocalProvider from './LocalProvider' import LocalProvider from './LocalProvider'
@@ -173,6 +173,10 @@ export default {
lang: { // i18n language lang: { // i18n language
type: String, type: String,
default: 'zh_CN' default: 'zh_CN'
},
extra: { // 基础设置里追加的设置
type: Object,
default: null
} }
}, },
computed: { computed: {
@@ -236,7 +240,28 @@ export default {
local: LocalProvider(this.lang) local: LocalProvider(this.lang)
} }
}, },
mounted () {
this.init()
},
methods: { methods: {
init(){
if (!this.extra || JSON.stringify(this.extra) === '{}') return
const keys = Object.keys(this.extra)
const nonCompliant = arrayDifference(TYPE_NAME, keys);
if (nonCompliant.length>0 ){
console.warn('not compliant extraSupports only the following keysstring, number, integer,object, array, boolean' ,nonCompliant);
}
for(let item in this.extra){
const setting = this.extra[item]
const basicSetting = TYPE[item]
Object.entries(setting).forEach(([key, value]) => {
value.extra=true
basicSetting.attr[key] = value
basicSetting.value[key] = null
});
}
},
onInputName(e){ onInputName(e){
const oldKey = this.pickKey const oldKey = this.pickKey
const newKey = e.target.value const newKey = e.target.value

View File

@@ -39,4 +39,8 @@ export function renamePropertyAndKeepKeyPrecedence(_this, obj, [oldKey, newKey])
}, obj) }, obj)
} }
return obj return obj
}
/**过滤数组元素 */
export function arrayDifference(basicArr, arr) {
return arr.filter(item => !basicArr.includes(item));
} }