Skip to content

Commit c0f4517

Browse files
feat: JsonEditor
1 parent 2c99cd2 commit c0f4517

File tree

13 files changed

+219
-6
lines changed

13 files changed

+219
-6
lines changed

mock/role/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,14 @@ const adminList = [
179179
meta: {
180180
title: 'router.richText'
181181
}
182+
},
183+
{
184+
path: 'json-editor',
185+
component: 'views/Components/Editor/JsonEditor',
186+
name: 'JsonEditor',
187+
meta: {
188+
title: 'router.jsonEditor'
189+
}
182190
}
183191
]
184192
},
@@ -588,6 +596,7 @@ const testList: string[] = [
588596
'/components/table/ref-table',
589597
'/components/editor-demo',
590598
'/components/editor-demo/editor',
599+
'/components/editor-demo/json-editor',
591600
'/components/search',
592601
'/components/descriptions',
593602
'/components/image-viewer',

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"url": "^0.11.1",
5252
"vue": "3.3.4",
5353
"vue-i18n": "9.2.2",
54+
"vue-json-pretty": "^2.2.4",
5455
"vue-router": "^4.2.4",
5556
"vue-types": "^5.1.1"
5657
},

src/components/Form/src/helper/componentMap.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
} from 'element-plus'
2323
import { InputPassword } from '@/components/InputPassword'
2424
import { Editor } from '@/components/Editor'
25+
import { JsonEditor } from '@/components/JsonEditor'
2526
import { ComponentName } from '../types'
2627

2728
const componentMap: Recordable<Component, ComponentName> = {
@@ -47,7 +48,8 @@ const componentMap: Recordable<Component, ComponentName> = {
4748
InputPassword: InputPassword,
4849
Editor: Editor,
4950
TreeSelect: ElTreeSelect,
50-
Upload: ElUpload
51+
Upload: ElUpload,
52+
JsonEditor: JsonEditor
5153
}
5254

5355
export { componentMap }

src/components/Form/src/types/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
UploadProps
2222
} from 'element-plus'
2323
import { IEditorConfig } from '@wangeditor/editor'
24+
import { JsonEditorProps } from '@/components/JsonEditor'
2425
import { CSSProperties } from 'vue'
2526

2627
export interface PlaceholderModel {
@@ -53,7 +54,8 @@ export enum ComponentNameEnum {
5354
INPUT_PASSWORD = 'InputPassword',
5455
EDITOR = 'Editor',
5556
TREE_SELECT = 'TreeSelect',
56-
UPLOAD = 'Upload'
57+
UPLOAD = 'Upload',
58+
JSON_EDITOR = 'JsonEditor'
5759
}
5860

5961
type CamelCaseComponentName = keyof typeof ComponentNameEnum extends infer K
@@ -620,6 +622,7 @@ export interface FormSchema {
620622
| InputPasswordComponentProps
621623
| TreeSelectComponentProps
622624
| UploadComponentProps
625+
| JsonEditorProps
623626
| any
624627

625628
/**

src/components/JsonEditor/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import JsonEditor from './src/JsonEditor.vue'
2+
export type { JsonEditorProps } from './src/types'
3+
4+
export { JsonEditor }
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<script setup lang="ts">
2+
import VueJsonPretty from 'vue-json-pretty'
3+
import 'vue-json-pretty/lib/styles.css'
4+
import { propTypes } from '@/utils/propTypes'
5+
import { computed } from 'vue'
6+
7+
const emits = defineEmits([
8+
'update:modelValue',
9+
'node-click',
10+
'brackets-click',
11+
'icon-click',
12+
'selected-value'
13+
])
14+
15+
const props = defineProps({
16+
modelValue: {
17+
type: Object,
18+
default: () => ({})
19+
},
20+
deep: propTypes.number.def(1),
21+
showLength: propTypes.bool.def(true),
22+
showLineNumbers: propTypes.bool.def(true),
23+
showLineNumber: propTypes.bool.def(true),
24+
showIcon: propTypes.bool.def(true),
25+
showDoubleQuotes: propTypes.bool.def(true),
26+
virtual: propTypes.bool.def(false),
27+
height: propTypes.number.def(400),
28+
itemHeight: propTypes.number.def(20),
29+
rootPath: propTypes.string.def('root'),
30+
nodeSelectable: propTypes.func.def(),
31+
selectableType: propTypes.oneOf<'multiple' | 'single'>(['multiple', 'single']).def(),
32+
showSelectController: propTypes.bool.def(false),
33+
selectOnClickNode: propTypes.bool.def(true),
34+
highlightSelectedNode: propTypes.bool.def(true),
35+
collapsedOnClickBrackets: propTypes.bool.def(true),
36+
renderNodeKey: propTypes.func.def(),
37+
renderNodeValue: propTypes.func.def(),
38+
editable: propTypes.bool.def(true),
39+
editableTrigger: propTypes.oneOf<'click' | 'dblclick'>(['click', 'dblclick']).def('click')
40+
})
41+
42+
const data = computed(() => props.modelValue)
43+
44+
const localModelValue = computed({
45+
get: () => data.value,
46+
set: (val) => {
47+
console.log(val)
48+
emits('update:modelValue', val)
49+
}
50+
})
51+
52+
const nodeClick = (node: any) => {
53+
emits('node-click', node)
54+
}
55+
56+
const bracketsClick = (collapsed: boolean) => {
57+
emits('brackets-click', collapsed)
58+
}
59+
60+
const iconClick = (collapsed: boolean) => {
61+
emits('icon-click', collapsed)
62+
}
63+
64+
const selectedChange = (newVal: any, oldVal: any) => {
65+
console.log(newVal, oldVal)
66+
emits('selected-value', newVal, oldVal)
67+
}
68+
</script>
69+
70+
<template>
71+
<VueJsonPretty
72+
v-model:data="localModelValue"
73+
:deep="deep"
74+
:show-length="showLength"
75+
:show-line-numbers="showLineNumbers"
76+
:show-line-number="showLineNumber"
77+
:show-icon="showIcon"
78+
:show-double-quotes="showDoubleQuotes"
79+
:virtual="virtual"
80+
:height="height"
81+
:item-height="itemHeight"
82+
:root-path="rootPath"
83+
:node-selectable="nodeSelectable"
84+
:selectable-type="selectableType"
85+
:show-select-controller="showSelectController"
86+
:select-on-click-node="selectOnClickNode"
87+
:highlight-selected-node="highlightSelectedNode"
88+
:collapsed-on-click-brackets="collapsedOnClickBrackets"
89+
:render-node-key="renderNodeKey"
90+
:render-node-value="renderNodeValue"
91+
:editable="editable"
92+
:editable-trigger="editableTrigger"
93+
@node-click="nodeClick"
94+
@brackets-click="bracketsClick"
95+
@icon-click="iconClick"
96+
@selected-change="selectedChange"
97+
/>
98+
</template>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export interface JsonEditorProps {
2+
value: any
3+
deep?: number
4+
showLength?: boolean
5+
showLineNumbers?: boolean
6+
showLineNumber?: boolean
7+
showIcon?: boolean
8+
showDoubleQuotes?: boolean
9+
virtual?: boolean
10+
height?: number
11+
itemHeight?: number
12+
rootPath?: string
13+
nodeSelectable?: (...args: any[]) => boolean
14+
selectableType?: 'multiple' | 'single'
15+
showSelectController?: boolean
16+
selectOnClickNode?: boolean
17+
highlightSelectedNode?: boolean
18+
collapsedOnClickBrackets?: boolean
19+
renderNodeKey?: (...args: any[]) => any
20+
renderNodeValue?: (...args: any[]) => any
21+
editable?: boolean
22+
editableTrigger?: 'click' | 'dblclick'
23+
}

src/locales/en.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ export default {
147147
defaultTable: 'Basic example',
148148
editor: 'Editor',
149149
richText: 'Rich text',
150+
jsonEditor: 'JSON Editor',
150151
dialog: 'Dialog',
151152
imageViewer: 'Image viewer',
152153
descriptions: 'Descriptions',
@@ -300,6 +301,7 @@ export default {
300301
verifyReset: 'Verify reset',
301302
// 富文本编辑器
302303
richText: 'Rich text',
304+
jsonEditor: 'JSON Editor',
303305
form: 'Form',
304306
// 远程加载
305307
remoteLoading: 'Remote loading',
@@ -448,7 +450,9 @@ export default {
448450
},
449451
richText: {
450452
richText: 'Rich text',
451-
richTextDes: 'Secondary packaging based on wangeditor'
453+
richTextDes: 'Secondary packaging based on wangeditor',
454+
jsonEditor: 'JSON Editor',
455+
jsonEditorDes: 'Secondary packaging based on vue-json-pretty'
452456
},
453457
dialogDemo: {
454458
dialog: 'Dialog',

src/locales/zh-CN.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ export default {
147147
defaultTable: '基础示例',
148148
editor: '编辑器',
149149
richText: '富文本',
150+
jsonEditor: 'JSON编辑器',
150151
dialog: '弹窗',
151152
imageViewer: '图片预览',
152153
descriptions: '描述',
@@ -298,6 +299,8 @@ export default {
298299
verifyReset: '验证重置',
299300
// 富文本编辑器
300301
richText: '富文本编辑器',
302+
// JSON编辑器
303+
jsonEditor: 'JSON编辑器',
301304
form: '表单',
302305
// 远程加载
303306
remoteLoading: '远程加载',
@@ -441,7 +444,9 @@ export default {
441444
},
442445
richText: {
443446
richText: '富文本',
444-
richTextDes: '基于 wangeditor 二次封装'
447+
richTextDes: '基于 wangeditor 二次封装',
448+
jsonEditor: 'JSON编辑器',
449+
jsonEditorDes: '基于 vue-json-pretty 二次封装'
445450
},
446451
dialogDemo: {
447452
dialog: '弹窗',

src/router/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,14 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
220220
meta: {
221221
title: t('router.richText')
222222
}
223+
},
224+
{
225+
path: 'json-editor',
226+
component: () => import('@/views/Components/Editor/JsonEditor.vue'),
227+
name: 'JsonEditor',
228+
meta: {
229+
title: t('router.jsonEditor')
230+
}
223231
}
224232
]
225233
},
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<script setup lang="ts">
2+
import { ContentWrap } from '@/components/ContentWrap'
3+
import { JsonEditor } from '@/components/JsonEditor'
4+
import { useI18n } from '@/hooks/web/useI18n'
5+
import { ref, watch } from 'vue'
6+
7+
const { t } = useI18n()
8+
9+
const defaultData = ref({
10+
title: '标题',
11+
content: '内容'
12+
})
13+
14+
watch(
15+
() => defaultData.value,
16+
(val) => {
17+
console.log(val)
18+
},
19+
{
20+
deep: true
21+
}
22+
)
23+
24+
setTimeout(() => {
25+
defaultData.value = {
26+
title: '异步标题',
27+
content: '异步内容'
28+
}
29+
}, 4000)
30+
</script>
31+
32+
<template>
33+
<ContentWrap :title="t('richText.jsonEditor')" :message="t('richText.jsonEditorDes')">
34+
<JsonEditor v-model="defaultData" />
35+
</ContentWrap>
36+
</template>

src/views/Components/Form/DefaultForm.vue

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,6 +1760,20 @@ const schema = reactive<FormSchema[]>([
17601760
)
17611761
}
17621762
}
1763+
},
1764+
{
1765+
field: 'field85',
1766+
component: 'Divider',
1767+
label: t('formDemo.jsonEditor')
1768+
},
1769+
{
1770+
field: 'field86',
1771+
component: 'JsonEditor',
1772+
label: t('formDemo.default'),
1773+
value: {
1774+
a: 1,
1775+
b: 2
1776+
}
17631777
}
17641778
])
17651779
</script>

vite.config.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
3131
return {
3232
base: env.VITE_BASE_PATH,
3333
plugins: [
34-
Vue(),
34+
Vue({
35+
script: {
36+
// 开启defineModel
37+
defineModel: true
38+
}
39+
}),
3540
VueJsx(),
3641
// WindiCSS(),
3742
progress(),
@@ -145,7 +150,8 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
145150
'intro.js',
146151
'qrcode',
147152
'@wangeditor/editor',
148-
'@wangeditor/editor-for-vue'
153+
'@wangeditor/editor-for-vue',
154+
'vue-json-pretty'
149155
]
150156
}
151157
}

0 commit comments

Comments
 (0)