[Feature][UI Next] Add monaco editor to form (#8241)
This commit is contained in:
parent
a778146ec6
commit
832f7352c9
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
import { h } from 'vue'
|
||||
import { NInput, NRadio, NRadioGroup, NSpace } from 'naive-ui'
|
||||
import Editor from '@/components/monaco-editor'
|
||||
import type { IFieldParams } from './types'
|
||||
|
||||
// TODO Support other widgets later
|
||||
|
|
@ -52,3 +53,13 @@ export function renderRadio(params: IFieldParams) {
|
|||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Editor
|
||||
export function renderEditor(params: IFieldParams) {
|
||||
const { props, fields, field } = params
|
||||
return h(Editor, {
|
||||
...props,
|
||||
value: fields[field],
|
||||
onUpdateValue: (value) => void (fields[field] = value)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,7 @@ import type { IJsonItem } from './types'
|
|||
|
||||
export default function getElementByJson(
|
||||
json: IJsonItem[],
|
||||
fields: { [field: string]: any },
|
||||
t: Function,
|
||||
prefix: string
|
||||
fields: { [field: string]: any }
|
||||
) {
|
||||
const rules: FormRules = {}
|
||||
const initialValues: { [field: string]: any } = {}
|
||||
|
|
@ -41,6 +39,13 @@ export default function getElementByJson(
|
|||
options
|
||||
})
|
||||
}
|
||||
if (type === 'editor') {
|
||||
return Field.renderEditor({
|
||||
field,
|
||||
fields,
|
||||
props
|
||||
})
|
||||
}
|
||||
|
||||
return Field.renderInput({ field, fields, props })
|
||||
}
|
||||
|
|
@ -50,7 +55,7 @@ export default function getElementByJson(
|
|||
initialValues[item.field] = item.value
|
||||
if (item.validate) rules[item.field] = formatValidate(item.validate)
|
||||
elements.push({
|
||||
label: t(prefix + '.' + item.field),
|
||||
label: item.name,
|
||||
path: item.field,
|
||||
widget: () => getElement(item)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import type {
|
|||
SelectOption
|
||||
} from 'naive-ui'
|
||||
|
||||
type IType = 'input' | 'radio'
|
||||
type IType = 'input' | 'radio' | 'editor'
|
||||
|
||||
type IOption = SelectOption
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export function formatValidate(
|
|||
): FormItemRule {
|
||||
if (!validate) return {}
|
||||
if (Array.isArray(validate)) {
|
||||
validate.map((item: FormItemRule) => {
|
||||
validate.forEach((item: FormItemRule) => {
|
||||
if (!item?.message) delete item.message
|
||||
return item
|
||||
})
|
||||
|
|
|
|||
|
|
@ -24,18 +24,26 @@ import {
|
|||
ref,
|
||||
watch
|
||||
} from 'vue'
|
||||
import { useFormItem } from 'naive-ui/es/_mixins'
|
||||
import { call } from 'naive-ui/es/_utils'
|
||||
import * as monaco from 'monaco-editor'
|
||||
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
|
||||
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
|
||||
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
|
||||
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
|
||||
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
|
||||
import type { MaybeArray, OnUpdateValue, OnUpdateValueImpl } from './types'
|
||||
|
||||
const props = {
|
||||
modelValue: {
|
||||
value: {
|
||||
type: String as PropType<string>,
|
||||
default: ''
|
||||
},
|
||||
defaultValue: {
|
||||
type: String as PropType<string>
|
||||
},
|
||||
'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,
|
||||
onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,
|
||||
language: {
|
||||
type: String as PropType<string>,
|
||||
default: 'shell'
|
||||
|
|
@ -72,13 +80,18 @@ window.MonacoEnvironment = {
|
|||
export default defineComponent({
|
||||
name: 'MonacoEditor',
|
||||
props,
|
||||
setup(props) {
|
||||
emits: ['change', 'focus', 'blur'],
|
||||
setup(props, ctx) {
|
||||
let editor = null as monaco.editor.IStandaloneCodeEditor | null
|
||||
const content = ref()
|
||||
|
||||
const editorRef = ref()
|
||||
|
||||
const getValue = () => editor?.getValue()
|
||||
|
||||
const formItem = useFormItem({})
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
() => props.value,
|
||||
(val) => {
|
||||
if (val !== getValue()) {
|
||||
editor?.setValue(val)
|
||||
|
|
@ -87,17 +100,34 @@ export default defineComponent({
|
|||
)
|
||||
|
||||
onMounted(async () => {
|
||||
content.value = props.modelValue
|
||||
|
||||
await nextTick()
|
||||
const dom = document.getElementById('monaco-container')
|
||||
const dom = editorRef.value
|
||||
if (dom) {
|
||||
editor = monaco.editor.create(dom, props.options, {
|
||||
value: props.modelValue,
|
||||
value: props.defaultValue ?? props.value,
|
||||
language: props.language,
|
||||
readOnly: props.readOnly,
|
||||
automaticLayout: true
|
||||
})
|
||||
editor.onDidChangeModelContent(() => {
|
||||
const { onUpdateValue, 'onUpdate:value': _onUpdateValue } = props
|
||||
const value = editor?.getValue() || ''
|
||||
|
||||
if (onUpdateValue) call(onUpdateValue as OnUpdateValueImpl, value)
|
||||
if (_onUpdateValue) call(_onUpdateValue as OnUpdateValueImpl, value)
|
||||
ctx.emit('change', value)
|
||||
|
||||
formItem.nTriggerFormChange()
|
||||
formItem.nTriggerFormInput()
|
||||
})
|
||||
editor.onDidBlurEditorWidget(() => {
|
||||
ctx.emit('blur')
|
||||
formItem.nTriggerFormBlur()
|
||||
})
|
||||
editor.onDidFocusEditorWidget(() => {
|
||||
ctx.emit('focus')
|
||||
formItem.nTriggerFormFocus()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -105,14 +135,17 @@ export default defineComponent({
|
|||
editor?.dispose()
|
||||
})
|
||||
|
||||
return { getValue }
|
||||
ctx.expose({ getValue })
|
||||
|
||||
return { editorRef }
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
id='monaco-container'
|
||||
ref='editorRef'
|
||||
style={{
|
||||
height: '300px',
|
||||
width: '100%',
|
||||
border: '1px solid #eee'
|
||||
}}
|
||||
></div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import type { MaybeArray } from 'naive-ui/es/_utils'
|
||||
|
||||
type OnUpdateValue = <T extends string>(value: T) => void
|
||||
type OnUpdateValueImpl = (value: string) => void
|
||||
|
||||
export { MaybeArray, OnUpdateValue, OnUpdateValueImpl }
|
||||
|
|
@ -91,7 +91,6 @@ export function useColumns(onCallback: Function) {
|
|||
NButton,
|
||||
{
|
||||
circle: true,
|
||||
class: styles['mr-10'],
|
||||
type: 'info',
|
||||
onClick: () => void onCallback(rowData.id, 'edit')
|
||||
},
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ export default defineComponent({
|
|||
setup() {
|
||||
const router: Router = useRouter()
|
||||
|
||||
const codeEditorRef = ref()
|
||||
const { state } = useForm()
|
||||
const { handleCreateFile } = useCreate(state)
|
||||
|
||||
|
|
@ -46,7 +45,6 @@ export default defineComponent({
|
|||
}))
|
||||
|
||||
const handleFile = () => {
|
||||
state.fileForm.content = codeEditorRef.value?.getValue()
|
||||
handleCreateFile()
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +55,6 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
return {
|
||||
codeEditorRef,
|
||||
fileSuffixOptions,
|
||||
handleFile,
|
||||
handleReturn,
|
||||
|
|
@ -105,7 +102,7 @@ export default defineComponent({
|
|||
width: '90%'
|
||||
}}
|
||||
>
|
||||
<MonacoEditor ref='codeEditorRef' />
|
||||
<MonacoEditor v-model={[this.fileForm.content, 'value']} />
|
||||
</div>
|
||||
</NFormItem>
|
||||
<div class={styles['file-edit-content']}>
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ export default defineComponent({
|
|||
const router: Router = useRouter()
|
||||
|
||||
const resourceViewRef = ref()
|
||||
const codeEditorRef = ref()
|
||||
const routeNameRef = ref(router.currentRoute.value.name)
|
||||
const idRef = ref(Number(router.currentRoute.value.params.id))
|
||||
|
||||
|
|
@ -41,7 +40,7 @@ export default defineComponent({
|
|||
const { getResourceView, handleUpdateContent } = useEdit(state)
|
||||
|
||||
const handleFileContent = () => {
|
||||
state.fileForm.content = codeEditorRef.value?.getValue()
|
||||
state.fileForm.content = resourceViewRef.value.content
|
||||
handleUpdateContent(idRef.value)
|
||||
}
|
||||
|
||||
|
|
@ -56,7 +55,6 @@ export default defineComponent({
|
|||
return {
|
||||
idRef,
|
||||
routeNameRef,
|
||||
codeEditorRef,
|
||||
resourceViewRef,
|
||||
handleReturn,
|
||||
handleFileContent,
|
||||
|
|
@ -84,8 +82,7 @@ export default defineComponent({
|
|||
}}
|
||||
>
|
||||
<MonacoEditor
|
||||
ref='codeEditorRef'
|
||||
modelValue={this.resourceViewRef?.value.content}
|
||||
v-model={[this.resourceViewRef?.value.content, 'value']}
|
||||
/>
|
||||
</div>
|
||||
</NFormItem>
|
||||
|
|
|
|||
|
|
@ -83,13 +83,12 @@ const DetailModal = defineComponent({
|
|||
watch(
|
||||
() => state.json,
|
||||
() => {
|
||||
if (state.json?.length) return
|
||||
state.json.forEach((item) => {
|
||||
item.name = t('security.alarm_instance' + '.' + item.field)
|
||||
})
|
||||
const { rules: fieldsRules, elements: fieldsElements } =
|
||||
getElementByJson(
|
||||
state.json,
|
||||
state.detailForm,
|
||||
t,
|
||||
'security.alarm_instance'
|
||||
)
|
||||
getElementByJson(state.json, state.detailForm)
|
||||
rules.value = fieldsRules
|
||||
elements.value = fieldsElements
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue