├── .gitignore
├── .npmignore
├── README.md
├── build
├── config.js
└── webpack.common.js
├── dist
└── json-schema-editor.min.js
├── docs
├── css
│ ├── app.478317e2.css
│ └── chunk-vendors.c470e980.css
├── favicon.ico
├── fonts
│ ├── element-icons.535877f5.woff
│ └── element-icons.732389de.ttf
├── index.html
└── js
│ ├── app.51aae14f.js
│ ├── app.51aae14f.js.map
│ ├── chunk-vendors.d43c2cc5.js
│ └── chunk-vendors.d43c2cc5.js.map
├── example
├── .eslintignore
├── README.md
├── babel.config.js
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── App.vue
│ ├── assets
│ │ └── logo.png
│ ├── components
│ │ └── HelloWorld.vue
│ └── main.js
└── yarn.lock
├── json-schema-editor.png
├── package.json
├── src
├── MockSelect
│ └── index.vue
├── Schema
│ ├── DropPlus.vue
│ ├── SchemaArray.vue
│ ├── SchemaItem.vue
│ ├── SchemaObject.vue
│ └── index.vue
├── common.js
├── dialog
│ ├── ArrayDialog.vue
│ ├── BasicDialog.vue
│ ├── BooleanDialog.vue
│ ├── NumberDialog.vue
│ ├── ObjectDialog.vue
│ ├── RawDialog.vue
│ ├── StringDialog.vue
│ └── index.js
├── event.js
├── index.js
├── json-editor
│ ├── index.js
│ └── src
│ │ └── json-editor.vue
├── json-schema-editor.vue
├── jsonschema.scss
└── utils.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 |
4 | # local env files
5 | .env.local
6 | .env.*.local
7 |
8 | # Log files
9 | lerna-debug.log*
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 | pnpm-debug.log*
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 |
4 | # local env files
5 | .env.local
6 | .env.*.local
7 | docs/*
8 | # Log files
9 | lerna-debug.log*
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 | pnpm-debug.log*
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-json-schema-editor-visual
2 |
3 | [](https://www.npmjs.com/package/vue-json-schema-editor-visual)
4 |
5 | A json-schema editor of high efficient and easy-to-use, base on Vue & Element UI.
6 |
7 | 一个高效易用的基于 Vue + Element UI 的 json-schema 编辑器。 模仿 Yapi React 版本 [json-schema-editor-visual](https://github.com/YMFE/json-schema-editor-visual) 实现
8 |
9 | 
10 |
11 | ## Usage
12 |
13 | ```js
14 | import JsonSchemaEditor from 'vue-json-schema-editor-visual';
15 |
16 | Vue.use(JsonSchemaEditor);
17 | ```
18 |
19 | 在线 Demo
20 |
21 | - [Sinokit json-schema-editor](http://blog.giscafer.com/sinokit/#/./components/jsonschema-editor)
22 | - [CodeSandbox Demo](https://codesandbox.io/s/practical-pond-jpteu?file=/src/App.vue)
23 |
24 | ## API
25 |
26 | ### Attributes
27 |
28 | | 参数 | 说明 | 类型 | 默认值 |
29 | | :------------------: | ------------------------------------- | :-------: | :-----: |
30 | | `schema` | json schema 对象 | `Object` | - |
31 | | `show-raw` | 是否显示 RAW 弹窗,可查看 json schema | `Boolean` | `false` |
32 | | `is-mock` | 是否支持 mock (WIP) | `Boolean` | `false` |
33 | | `show-default-value` | 是否展示默认值输入框 | `Boolean` | `false` |
34 |
35 | ### Events
36 |
37 | | 事件名称 | 说明 | 回调参数 |
38 | | :-------------: | --------------------------- | :-------------------: |
39 | | `schema-change` | schema 发生变化时的回调函数 | 新的 json schema 对象 |
40 |
41 | ## Related
42 |
43 | - [json-schema-editor-vue](https://github.com/zyqwst/json-schema-editor-vue) vue + ant-design-vue
44 |
45 | 其他 json editor
46 |
47 | - [jsoneditor](https://github.com/josdejong/jsoneditor)
48 | - [json-editor/json-editor](https://github.com/json-editor/json-editor)
49 | - [jinkin1995/vue-json-edit](https://github.com/jinkin1995/vue-json-edit)
50 |
51 | ## License
52 |
53 | MIT
54 |
--------------------------------------------------------------------------------
/build/config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var nodeExternals = require('webpack-node-externals');
3 |
4 | externals = [
5 | Object.assign({
6 | vue: 'vue',
7 | }),
8 | nodeExternals(),
9 | ];
10 |
11 | exports.externals = externals;
12 |
13 | exports.alias = {
14 | main: path.resolve(__dirname, '../src'),
15 | };
16 |
17 | exports.vue = {
18 | root: 'Vue',
19 | commonjs: 'vue',
20 | commonjs2: 'vue',
21 | amd: 'vue',
22 | };
23 |
24 | exports.jsexclude = /node_modules|utils\/popper\.js|utils\/date\.js/;
25 |
--------------------------------------------------------------------------------
/build/webpack.common.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const ProgressBarPlugin = require('progress-bar-webpack-plugin');
3 | const VueLoaderPlugin = require('vue-loader/lib/plugin');
4 |
5 | const config = require('./config');
6 |
7 | module.exports = {
8 | mode: 'production',
9 | entry: {
10 | app: ['./src/index.js'],
11 | },
12 | output: {
13 | path: path.resolve(__dirname, '../dist'),
14 | publicPath: '../dist/',
15 | filename: 'json-schema-editor.min.js',
16 | library: 'JsonSchemaEditor',
17 | libraryTarget: 'umd',
18 | umdNamedDefine: true,
19 | },
20 | resolve: {
21 | extensions: ['.js', '.vue', '.json'],
22 | alias: config.alias,
23 | modules: ['node_modules'],
24 | },
25 | externals: {
26 | vue: config.vue,
27 | },
28 | performance: {
29 | hints: false,
30 | },
31 | stats: {
32 | children: false,
33 | },
34 | optimization: {
35 | minimize: true,
36 | },
37 |
38 | module: {
39 | rules: [
40 | {
41 | test: /\.(jsx?|babel|es6)$/,
42 | include: process.cwd(),
43 | exclude: config.jsexclude,
44 | loader: 'babel-loader',
45 | },
46 | {
47 | test: /\.vue$/,
48 | loader: 'vue-loader',
49 | options: {
50 | compilerOptions: {
51 | preserveWhitespace: false,
52 | },
53 | },
54 | },
55 | {
56 | test: /\.css$/,
57 | use: [
58 | {
59 | loader: 'style-loader', // 将 JS 字符串生成为 style 节点
60 | },
61 | {
62 | loader: 'css-loader',
63 | options: {
64 | import: true,
65 | },
66 | },
67 | ],
68 | },
69 | {
70 | test: /\.scss$/,
71 | loaders: ['style-loader', 'css-loader', 'sass-loader'],
72 | },
73 | {
74 | test: /\.(svg|otf|ttf|woff2?|eot|gif|png|jpe?g)(\?\S*)?$/,
75 | loader: 'url-loader',
76 | query: {
77 | limit: 10000,
78 | name: path.posix.join('static', '[name].[hash:7].[ext]'),
79 | },
80 | },
81 | ],
82 | },
83 | plugins: [new ProgressBarPlugin(), new VueLoaderPlugin()],
84 | };
85 |
--------------------------------------------------------------------------------
/docs/css/app.478317e2.css:
--------------------------------------------------------------------------------
1 | #app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50;margin-top:100px}
--------------------------------------------------------------------------------
/docs/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/giscafer/vue-json-schema-editor-visual/72c7dd1b359ee8104844de17e73b00ba563c0b4d/docs/favicon.ico
--------------------------------------------------------------------------------
/docs/fonts/element-icons.535877f5.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/giscafer/vue-json-schema-editor-visual/72c7dd1b359ee8104844de17e73b00ba563c0b4d/docs/fonts/element-icons.535877f5.woff
--------------------------------------------------------------------------------
/docs/fonts/element-icons.732389de.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/giscafer/vue-json-schema-editor-visual/72c7dd1b359ee8104844de17e73b00ba563c0b4d/docs/fonts/element-icons.732389de.ttf
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | vue-demo
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/example/.eslintignore:
--------------------------------------------------------------------------------
1 |
2 |
3 | **/*/*.min.js
4 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # vue-json-schema-editor-visual-demo
2 |
3 | ## Project setup
4 |
5 | ```
6 | npm install
7 | ```
8 |
9 | ### Compiles and hot-reloads for development
10 |
11 | ```
12 | npm run serve
13 | ```
14 |
15 | ### Compiles and minifies for production
16 |
17 | ```
18 | npm run build
19 | ```
20 |
21 | ### Lints and fixes files
22 |
23 | ```
24 | npm run lint
25 | ```
26 |
27 | ### Customize configuration
28 |
29 | See [Configuration Reference](https://cli.vuejs.org/config/).
30 |
--------------------------------------------------------------------------------
/example/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-demo",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "@sinokit/components": "^0.1.23",
12 | "core-js": "^3.6.5",
13 | "element-ui": "^2.15.1",
14 | "vue": "^2.6.11"
15 | },
16 | "devDependencies": {
17 | "@vue/cli-plugin-babel": "~4.5.0",
18 | "@vue/cli-plugin-eslint": "~4.5.0",
19 | "@vue/cli-service": "~4.5.0",
20 | "babel-eslint": "^10.1.0",
21 | "eslint": "^6.7.2",
22 | "eslint-plugin-vue": "^6.2.2",
23 | "vue-template-compiler": "^2.6.11"
24 | },
25 | "eslintConfig": {
26 | "root": true,
27 | "env": {
28 | "node": true
29 | },
30 | "extends": [
31 | "plugin:vue/essential",
32 | "eslint:recommended"
33 | ],
34 | "parserOptions": {
35 | "parser": "babel-eslint"
36 | },
37 | "rules": {}
38 | },
39 | "browserslist": [
40 | "> 1%",
41 | "last 2 versions",
42 | "not dead"
43 | ]
44 | }
45 |
--------------------------------------------------------------------------------
/example/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/giscafer/vue-json-schema-editor-visual/72c7dd1b359ee8104844de17e73b00ba563c0b4d/example/public/favicon.ico
--------------------------------------------------------------------------------
/example/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
23 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/example/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
vue-json-schema-editor-visual example
4 |
5 |
6 |
15 |
16 |
17 |
18 |
28 |
29 |
39 |
--------------------------------------------------------------------------------
/example/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/giscafer/vue-json-schema-editor-visual/72c7dd1b359ee8104844de17e73b00ba563c0b4d/example/src/assets/logo.png
--------------------------------------------------------------------------------
/example/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 改变Schema
9 | Toggle 分页参数
12 |
13 |
14 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/example/src/main.js:
--------------------------------------------------------------------------------
1 | import ElementUI from 'element-ui';
2 | import 'element-ui/lib/theme-chalk/index.css';
3 | import Vue from 'vue';
4 | import JsonSchemaEditor from '../../dist/json-schema-editor.min.js';
5 | import App from './App.vue';
6 |
7 | Vue.use(ElementUI, { size: 'small' });
8 | Vue.use(JsonSchemaEditor);
9 |
10 | Vue.config.productionTip = false;
11 |
12 | new Vue({
13 | render: (h) => h(App),
14 | }).$mount('#app');
15 |
--------------------------------------------------------------------------------
/json-schema-editor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/giscafer/vue-json-schema-editor-visual/72c7dd1b359ee8104844de17e73b00ba563c0b4d/json-schema-editor.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-json-schema-editor-visual",
3 | "version": "0.2.6",
4 | "description": "A json-schema editor of high efficient and easy-to-use, base on Vue.",
5 | "keywords": [
6 | "json-schema"
7 | ],
8 | "author": "giscafer ",
9 | "homepage": "https://github.com/giscafer/vue-json-schema-editor-visual",
10 | "license": "MIT",
11 | "main": "dist/json-schema-editor.min.js",
12 | "unpkg": "dist/json-schema-editor.min.js",
13 | "directories": {
14 | "dist": "dist",
15 | "src": "src",
16 | "test": "__tests__"
17 | },
18 | "files": [
19 | "dist",
20 | "src"
21 | ],
22 | "publishConfig": {
23 | "access": "public",
24 | "registry": "https://registry.npmjs.org/"
25 | },
26 | "repository": {
27 | "type": "git",
28 | "url": "https://github.com/giscafer/vue-json-schema-editor-visual.git"
29 | },
30 | "scripts": {
31 | "clean": "rimraf dist",
32 | "build": "npm run clean && webpack --config build/webpack.common.js --optimize-max-chunks 1",
33 | "lint": "eslint lib/**/* build/**/* --quiet",
34 | "test": "echo \"Error: run tests from root\" && exit 1"
35 | },
36 | "dependencies": {
37 | "codemirror": "^5.58.1",
38 | "element-ui": "2.13.2",
39 | "json-schema-faker": "^0.5.0-rcv.24",
40 | "lodash": "^4.17.19",
41 | "mockjs": "^1.1.0",
42 | "vue": "^2.6.11",
43 | "json-templater": "^1.2.0",
44 | "jsonlint": "^1.6.3"
45 | },
46 | "devDependencies": {
47 | "@babel/core": "^7.11.6",
48 | "babel": "^6.23.0",
49 | "babel-loader": "^8.1.0",
50 | "css-loader": "^4.1.0",
51 | "node-sass": "^4.14.1",
52 | "progress-bar-webpack-plugin": "^2.1.0",
53 | "sass-loader": "^9.0.2",
54 | "script-loader": "^0.7.2",
55 | "style-loader": "^1.2.1",
56 | "terser-webpack-plugin": "^3.0.8",
57 | "uppercamelcase": "^3.0.0",
58 | "url-loader": "^4.1.0",
59 | "vue-loader": "^15.9.3",
60 | "vue-template-compiler": "^2.6.12",
61 | "webpack": "^4.44.0",
62 | "webpack-cli": "^3.3.12",
63 | "webpack-node-externals": "^2.5.0"
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/MockSelect/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
15 |
16 |
17 |
62 |
63 |
65 |
--------------------------------------------------------------------------------
/src/Schema/DropPlus.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 兄弟节点
8 |
9 |
10 | 子节点
11 |
12 |
13 |
14 |
15 |
16 |
17 |
43 |
44 |
46 |
--------------------------------------------------------------------------------
/src/Schema/SchemaArray.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
38 |
44 |
45 |
46 |
47 |
48 |
53 |
54 |
55 |
60 |
61 |
66 |
67 |
68 |
73 |
74 |
79 |
80 |
81 |
82 |
83 |
84 |
91 |
92 |
93 |
94 |
100 |
101 |
102 |
103 |
104 |
105 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
126 |
127 |
128 |
136 |
137 |
138 |
139 |
140 |
225 |
--------------------------------------------------------------------------------
/src/Schema/SchemaItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
16 |
17 |
18 |
19 |
20 |
21 |
29 |
30 |
31 |
32 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
51 |
57 |
58 |
59 |
60 |
61 |
66 |
67 |
68 |
73 |
79 |
84 |
85 |
86 |
87 |
92 |
100 |
105 |
106 |
107 |
108 |
109 |
115 |
122 |
123 |
124 |
125 |
126 |
132 |
133 |
134 |
135 |
136 |
141 |
142 |
143 |
149 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
170 |
171 |
172 |
180 |
181 |
182 |
183 |
184 |
291 |
--------------------------------------------------------------------------------
/src/Schema/SchemaObject.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
55 |
--------------------------------------------------------------------------------
/src/Schema/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
14 |
22 |
23 |
24 |
25 |
66 |
--------------------------------------------------------------------------------
/src/common.js:
--------------------------------------------------------------------------------
1 | const Mock = require('mockjs');
2 | const jsf = require('json-schema-faker');
3 |
4 | jsf.extend('mock', function() {
5 | return {
6 | mock: function(xx) {
7 | return Mock.mock(xx);
8 | }
9 | };
10 | });
11 |
12 | const defaultOptions = {
13 | failOnInvalidTypes: false,
14 | failOnInvalidFormat: false,
15 | alwaysFakeOptionals: true,
16 | useDefaultValue: true
17 | };
18 |
19 | export const schemaToJson = (schema, options = {}) => {
20 | Object.assign(options, defaultOptions);
21 |
22 | jsf.option(options);
23 | let result;
24 | try {
25 | result = jsf.generate(schema);
26 | } catch (err) {
27 | result = err.message;
28 | }
29 | jsf.option(defaultOptions);
30 | return result;
31 | };
32 |
--------------------------------------------------------------------------------
/src/dialog/ArrayDialog.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
30 |
31 |
32 |
33 |
34 |
35 | 取消
36 | 确定
37 |
38 |
39 |
40 |
41 |
83 |
--------------------------------------------------------------------------------
/src/dialog/BasicDialog.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
15 |
16 |
17 |
18 |
19 |
63 |
64 |
66 |
--------------------------------------------------------------------------------
/src/dialog/BooleanDialog.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
18 |
25 |
26 |
27 |
28 |
29 | 取消
30 | 确定
31 |
32 |
33 |
34 |
84 |
--------------------------------------------------------------------------------
/src/dialog/NumberDialog.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
19 |
20 |
21 |
29 |
30 |
31 |
32 |
33 |
40 |
41 |
42 |
43 |
44 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | :
59 |
60 |
61 |
62 |
63 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
86 |
87 |
88 |
89 |
90 |
91 | 取消
92 | 确定
93 |
94 |
95 |
96 |
97 |
170 |
--------------------------------------------------------------------------------
/src/dialog/ObjectDialog.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 | {{ item.label }}
20 |
21 |
22 |
23 |
24 | 取消
25 | 确定
26 |
27 |
28 |
29 |
79 |
--------------------------------------------------------------------------------
/src/dialog/RawDialog.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
42 |
44 |
--------------------------------------------------------------------------------
/src/dialog/StringDialog.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
19 |
20 |
21 |
28 |
29 |
30 |
31 |
32 |
38 |
39 |
40 |
41 |
42 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | :
56 |
57 |
58 |
59 |
60 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
83 |
84 |
85 |
86 |
87 |
88 | 取消
89 | 确定
90 |
91 |
92 |
93 |
94 |
164 |
--------------------------------------------------------------------------------
/src/dialog/index.js:
--------------------------------------------------------------------------------
1 | import BasicDialog from './BasicDialog';
2 | import StringDialog from './StringDialog';
3 | import NumberDialog from './NumberDialog';
4 | import ArrayDialog from './ArrayDialog';
5 | import BooleanDialog from './BooleanDialog';
6 | import ObjectDialog from './ObjectDialog';
7 | import RawDialog from './RawDialog';
8 |
9 | export {
10 | BasicDialog,
11 | StringDialog,
12 | NumberDialog,
13 | ArrayDialog,
14 | BooleanDialog,
15 | ObjectDialog,
16 | RawDialog
17 | };
18 |
--------------------------------------------------------------------------------
/src/event.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: giscafer ,https://github.com/giscafer
3 | * @date: 2020-05-21 17:21:29
4 | * @description: 用一个Vue实例封装事件常用的方法并赋值给全局的变量,以便在任何一个组件都可调用这些方法来实现全局事件管理
5 | *
6 | * 使用如下:
7 | * mounted(){
8 | this.$jsEditorEvent.on('change_value',id);
9 | this.$jsEditorEvent.emit('change_value',1);
10 | ...
11 | }
12 | */
13 |
14 | import Vue from 'vue';
15 |
16 | const eventHub = new Vue({
17 | methods: {
18 | on(...args) {
19 | this.$on.apply(this, args);
20 | },
21 | emit(...args) {
22 | this.$emit.apply(this, args);
23 | },
24 | off(...args) {
25 | this.$off.apply(this, args);
26 | },
27 | once(...args) {
28 | this.$once.apply(this, args);
29 | },
30 | },
31 | });
32 |
33 | /* const CustomEventPlugin = V =>
34 | Object.defineProperty(V.prototype, '$event', {
35 | value: eventHub,
36 | writable: true
37 | }); */
38 |
39 | const CustomEventPlugin = {
40 | install: function(V) {
41 | Object.defineProperty(V.prototype, '$jsEditorEvent', {
42 | value: eventHub,
43 | writable: true,
44 | });
45 | },
46 | };
47 |
48 | export default CustomEventPlugin;
49 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import JsonSchemaEditor from './json-schema-editor.vue';
2 | import CustomEventPlugin from './event';
3 |
4 | const install = function(Vue) {
5 | Vue.use(CustomEventPlugin);
6 |
7 | Vue.component(JsonSchemaEditor.name, JsonSchemaEditor);
8 | };
9 |
10 | JsonSchemaEditor.install = install;
11 |
12 | /* istanbul ignore if */
13 | if (typeof window !== 'undefined' && window.Vue) {
14 | install(window.Vue);
15 | }
16 |
17 | export default JsonSchemaEditor;
18 |
--------------------------------------------------------------------------------
/src/json-editor/index.js:
--------------------------------------------------------------------------------
1 | import JsonEditor from './src/json-editor';
2 |
3 | /* istanbul ignore next */
4 | JsonEditor.install = function(Vue) {
5 | Vue.component(JsonEditor.name, JsonEditor);
6 | };
7 |
8 | export default JsonEditor;
9 |
--------------------------------------------------------------------------------
/src/json-editor/src/json-editor.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
74 |
75 |
91 |
--------------------------------------------------------------------------------
/src/json-schema-editor.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
RAW查看
11 |
12 |
13 |
14 |
15 |
16 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
35 |
36 |
37 |
38 |
39 |
40 |
47 |
53 |
54 |
55 |
56 |
61 |
62 |
67 |
73 |
85 |
86 |
87 |
92 |
102 |
114 |
115 |
116 |
117 |
118 |
124 |
136 |
137 |
138 |
139 |
150 |
151 |
152 |
153 |
154 |
155 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
179 |
180 |
185 |
186 |
190 |
194 |
198 |
202 |
206 |
210 |
214 |
215 |
216 |
217 |
619 |
--------------------------------------------------------------------------------
/src/jsonschema.scss:
--------------------------------------------------------------------------------
1 | .json-schema-vue-editor {
2 | cursor: pointer;
3 | .el-input--medium {
4 | height: 36px;
5 | }
6 | .el-input.is-disabled {
7 | background-color: #f5f7fa;
8 | border-color: #dfe4ed;
9 | color: #c0c4cc;
10 | cursor: not-allowed;
11 | }
12 | .hidden {
13 | display: none;
14 | }
15 | }
16 | .json-schema-vue-editor .option-formStyle {
17 | /* padding-left: 25px; */
18 | padding-top: 8px;
19 | }
20 |
21 | .json-schema-vue-editor .required-icon {
22 | font-size: 1em;
23 | color: red;
24 | font-weight: bold;
25 | padding-left: 5px;
26 | }
27 |
28 | .json-schema-vue-editor .object-style {
29 | /* border-left: 2px dotted gray; */
30 | /* padding-left: 8px; */
31 | padding-top: 6px;
32 | /* margin-left: 20px; */
33 | margin-top: 8px;
34 | }
35 |
36 | .json-schema-vue-editor .col-item-type {
37 | text-align: center;
38 | }
39 |
40 | .json-schema-vue-editor .down-style {
41 | cursor: pointer;
42 | }
43 |
44 | .json-schema-vue-editor .col-item-desc {
45 | text-align: center;
46 | }
47 |
48 | .json-schema-vue-editor .col-item-mock {
49 | text-align: center;
50 | padding-right: 6px;
51 | }
52 |
53 | .json-schema-vue-editor .col-item-setting {
54 | padding-left: 6px;
55 | cursor: pointer;
56 | }
57 |
58 | .json-schema-vue-editor .plus {
59 | color: #2395f1;
60 | }
61 |
62 | .json-schema-vue-editor .close {
63 | color: #ff561b;
64 | }
65 |
66 | .json-schema-vue-editor .array-type {
67 | margin-top: 8px;
68 | }
69 |
70 | .json-schema-vue-editor .delete-item {
71 | padding-right: 8px;
72 | }
73 |
74 | .json-schema-vue-editor .object-style .name-item .ant-input-group-addon {
75 | background-color: unset;
76 | border: unset;
77 | }
78 |
79 | .json-schema-vue-editor
80 | .object-style
81 | .name-item
82 | .ant-input-group
83 | > .ant-input:first-child,
84 | .ant-input-group-addon:first-child {
85 | border-bottom-right-radius: 4px;
86 | border-top-right-radius: 4px;
87 | }
88 |
89 | .json-schema-vue-editor .icon-object {
90 | color: #0d1b3ea6;
91 | font-weight: 400;
92 | font-size: 12px;
93 | }
94 |
95 | .json-schema-vue-editor .down-style-col {
96 | width: 10px;
97 | }
98 |
99 | .json-schema-vue-editor .wrapper {
100 | padding-left: 8px;
101 | }
102 |
103 | /* .schema-content {
104 | margin-left: 20px;
105 | } */
106 |
107 | .json-schema-vue-editor .adv-set {
108 | padding-right: 8px;
109 | color: #00a854;
110 | }
111 |
112 | .json-schema-vue-editor .type-select-style {
113 | width: 90%;
114 | }
115 |
116 | .json-schema-vue-editor-import-modal .ant-tabs-nav .ant-tabs-tab {
117 | height: auto;
118 | }
119 |
120 | .json-schema-vue-editor-adv-modal .other-row {
121 | margin-bottom: 16px;
122 | }
123 |
124 | .json-schema-vue-editor-adv-modal .other-label {
125 | text-align: right;
126 | padding-right: 8px;
127 | }
128 |
129 | .json-schema-vue-editor-adv-modal .default-setting {
130 | font-size: 16px;
131 | font-weight: 400;
132 | margin-bottom: 16px;
133 | border-left: 3px solid #2395f1;
134 | padding-left: 8px;
135 | }
136 |
137 | .json-schema-vue-editor-adv-modal .ant-modal-body {
138 | min-height: 400px;
139 | }
140 |
141 | .json-schema-vue-editor-adv-modal .ant-modal-body .ace_editor {
142 | min-height: 350px;
143 | }
144 |
145 | .json-schema-vue-editor-adv-modal-select .format-items-title {
146 | color: #999;
147 | position: absolute;
148 | right: 16px;
149 | }
150 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 |
3 | export const JSONPATH_JOIN_CHAR = '.';
4 | export const lang = 'zh_CN';
5 | export const format = [
6 | { name: 'date-time' },
7 | { name: 'date' },
8 | { name: 'email' },
9 | { name: 'hostname' },
10 | { name: 'ipv4' },
11 | { name: 'ipv6' },
12 | { name: 'uri' }
13 | ];
14 | export const SCHEMA_TYPE = [
15 | 'string',
16 | 'number',
17 | 'array',
18 | 'object',
19 | 'boolean',
20 | 'integer'
21 | ];
22 | export const defaultInitSchemaData = {
23 | type: 'object',
24 | title: 'title',
25 | properties: {}
26 | };
27 | export const defaultSchema = {
28 | string: {
29 | type: 'string'
30 | },
31 | number: {
32 | type: 'number'
33 | },
34 | array: {
35 | type: 'array',
36 | items: {
37 | type: 'string'
38 | }
39 | },
40 | object: {
41 | type: 'object',
42 | properties: {}
43 | },
44 | boolean: {
45 | type: 'boolean'
46 | },
47 | integer: {
48 | type: 'integer'
49 | }
50 | };
51 |
52 | // 防抖函数,减少高频触发的函数执行的频率
53 | // 请在 constructor 里使用:
54 |
55 | // this.func = debounce(this.func, 400);
56 | export const debounce = (func, wait) => {
57 | let timeout;
58 | return function() {
59 | clearTimeout(timeout);
60 | timeout = setTimeout(func, wait);
61 | };
62 | };
63 |
64 | export const getData = (state, keys) => {
65 | let curState = state;
66 | for (let i = 0; i < keys.length; i++) {
67 | curState = curState[keys[i]];
68 | }
69 | return curState;
70 | };
71 |
72 | export const setData = function(state, keys, value) {
73 | let curState = state;
74 | for (let i = 0; i < keys.length - 1; i++) {
75 | curState = curState[keys[i]];
76 | }
77 | curState[keys[keys.length - 1]] = value;
78 | };
79 |
80 | export const deleteData = function(state, keys) {
81 | let curState = state;
82 | for (let i = 0; i < keys.length - 1; i++) {
83 | curState = curState[keys[i]];
84 | }
85 |
86 | delete curState[keys[keys.length - 1]];
87 | };
88 |
89 | export const getParentKeys = function(keys) {
90 | if (keys.length === 1) return [];
91 | const arr = [].concat(keys);
92 | arr.splice(keys.length - 1, 1);
93 | return arr;
94 | };
95 |
96 | export const clearSomeFields = function(keys, data) {
97 | const newData = Object.assign({}, data);
98 | keys.forEach(key => {
99 | delete newData[key];
100 | });
101 | return newData;
102 | };
103 |
104 | function getFieldstitle(data) {
105 | const requiredtitle = [];
106 | Object.keys(data).map(title => {
107 | requiredtitle.push(title);
108 | });
109 |
110 | return requiredtitle;
111 | }
112 |
113 | export function handleSchemaRequired(schema, checked) {
114 | if (schema.type === 'object') {
115 | const requiredtitle = getFieldstitle(schema.properties);
116 |
117 | // schema.required = checked ? [].concat(requiredtitle) : [];
118 | if (checked) {
119 | schema.required = [].concat(requiredtitle);
120 | } else {
121 | delete schema.required;
122 | }
123 |
124 | handleObject(schema.properties, checked);
125 | } else if (schema.type === 'array') {
126 | handleSchemaRequired(schema.items, checked);
127 | } else {
128 | return schema;
129 | }
130 | }
131 |
132 | function handleObject(properties, checked) {
133 | for (var key in properties) {
134 | if (properties[key].type === 'array' || properties[key].type === 'object') {
135 | handleSchemaRequired(properties[key], checked);
136 | }
137 | }
138 | }
139 |
140 | export function cloneObject(obj) {
141 | if (typeof obj === 'object') {
142 | if (Array.isArray(obj)) {
143 | var newArr = [];
144 | obj.forEach(function(item, index) {
145 | newArr[index] = cloneObject(item);
146 | });
147 | return newArr;
148 | } else {
149 | var newObj = {};
150 | for (var key in obj) {
151 | newObj[key] = cloneObject(obj[key]);
152 | }
153 | return newObj;
154 | }
155 | } else {
156 | return obj;
157 | }
158 | }
159 |
160 | export const uuid = () => {
161 | return Math.random()
162 | .toString(16)
163 | .substr(2, 5);
164 | };
165 |
166 | export const log = (...args) => {
167 | if (process && process.env && process.env.NODE_ENV !== 'production') {
168 | if (
169 | args[0] &&
170 | args[0] instanceof Vue &&
171 | args[0].$vnode['componentOptions']
172 | ) {
173 | console.log(
174 | `component[${args[0].$vnode['componentOptions']['tag']}]:`,
175 | ...args.slice(1)
176 | );
177 | } else {
178 | console.log(`LOG>>>`, ...args);
179 | }
180 | }
181 | };
182 |
183 | /**
184 | * val值不为空字符,null,undefined
185 | */
186 | export const isNotNil = val => {
187 | const arr = [undefined, null, ''];
188 | return !arr.includes(val);
189 | };
190 |
191 | /**
192 | * form表单值校验是否为空,有值为空则返回true,值都正确则返回false
193 | */
194 | export const isFormValid = obj => {
195 | if (typeof obj !== 'object') return true;
196 | const keys = Object.keys(obj);
197 | return keys.some(key => {
198 | return !isNotNil(obj[key]);
199 | });
200 | };
201 | /**
202 | * 只返回有值得属性新对象
203 | * @param {Object} formData 表单对象
204 | */
205 | export const getValidFormVal = formData => {
206 | const obj = {};
207 | const keys = Object.keys(formData);
208 | keys.forEach(key => {
209 | if (isNotNil(formData[key])) {
210 | obj[key] = formData[key];
211 | }
212 | });
213 |
214 | return obj;
215 | };
216 |
--------------------------------------------------------------------------------