Signed-off-by: chy <chy@163.com>

This commit is contained in:
chy
2026-02-02 23:17:44 +08:00
parent e10f2f058c
commit a49878384e
774 changed files with 249821 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
import { downloadByUrl } from '@/utils/filt';
export default function (jsEnhanceObj?: Ref<any>) {
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
//文件大小格式化
const fileSizeFormatter = (fileSize) => {
const unitArr = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
fileSize = parseFloat(fileSize)
const index = Math.floor(Math.log(fileSize) / Math.log(1024))
fileSize = fileSize / Math.pow(1024, index)
//保留的小数位数
if (`${fileSize}`.indexOf('.') != -1) fileSize = fileSize.toFixed(2)
return fileSize + ' ' + unitArr[index]
}
//校验文件类型
const verifyFileType = (fileName) => {
const imgExp = /\.(gif|jpg|jpeg|png|webp|svg|GIF|JPG|JPEG|PNG|WEBP|SVG)/
const videoExp = /\.(swf|avi|flv|mpg|rm|mov|wav|asf|3gp|mkv|rmvb|ogg|mp4)/
const audioExp = /\.(mp3|wav|MP3|WAV)/
if (imgExp.test(fileName)) return 'image/*'
if (videoExp.test(fileName)) return 'video/*'
if (audioExp.test(fileName)) return 'audio/*'
return false
}
const uploadBefore = async (file, done, loading, column) => {
let bool = false
if (column.controlType == 'image') {
if (column.accept == 'image/*' && verifyFileType(file.name) == column.accept) bool = true
else if (column.accept) {
const accept = column.accept instanceof Array ? column.accept : column.accept.split(',')
if (accept.includes(file.type)) bool = true
} else bool = true
}
if (column.controlType == 'file') {
if (column.accept) {
const nameList = file.name.split('.')
const suffix = `.${nameList[nameList.length - 1]}`
const accept = column.accept instanceof Array ? column.accept : column.accept.split(',')
accept.forEach(type => {
if (['image/*', 'video/*', 'audio/*'].includes(type) && verifyFileType(file.name) == type) bool = true
})
if (accept.includes(suffix) || accept.includes(file.type)) bool = true
} else bool = true
}
try {
if (column.verify) {
bool = await column.verify(file).then(() => true).catch(() => false)
}
} catch (error) { }
if (!bool) {
message.info(`请上传正确的${column.label}格式`)
loading()
return
}
try {
if (jsEnhanceObj?.value.beforeUpload) {
const isUpload = await jsEnhanceObj.value.beforeUpload(file)
if (!isUpload) {
loading()
return
}
}
} catch (error) {
console.warn(`'js增强【beforeUpload】方法执行异常请检查'
${error}`)
}
done()
}
const uploadExceed = (limit, files, fileList, column) => {
message.info(`${column.label} 最大可上传 ${limit}${column.controlType == 'image' ? '张' : '件'}`)
}
const uploadSized = (fileSize, files, fileList, column) => {
fileSize = fileSizeFormatter(fileSize)
message.info(`${column.label} 上传大小不可超过 ${fileSize}`)
}
const uploadPreview = (file, column, done) => {
if (column.controlType == 'image') return done()
const bool = verifyFileType(file.url)
if (bool) done()
else downloadByUrl({ url: file.url })
}
return { uploadBefore, uploadExceed, uploadSized, uploadPreview }
}

View File

@@ -0,0 +1,28 @@
import { useClipboard } from '@vueuse/core'
export default function () {
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const copy = async (text: string) => {
if (navigator.clipboard) {
const { copy, copied, isSupported } = useClipboard({ source: text })
if (!isSupported) {
message.error(t('common.copyError'))
return
}
await copy()
if (unref(copied)) {
message.success(t('common.copySuccess'))
}
} else {
const textarea = document.createElement('textarea');
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
message.success(t('common.copySuccess'));
}
}
return { copyText: copy }
}

View File

@@ -0,0 +1,26 @@
import { useWindowSize } from '@vueuse/core'
export const useCrudHeight = (crudRef) => {
const windowSize = useWindowSize()
const crudHeightTimer = ref<any>(null)
const initTableLayout = () => {
if (crudHeightTimer.value) clearTimeout(crudHeightTimer.value)
crudHeightTimer.value = setTimeout(() => {
if (crudRef instanceof Array) {
crudRef.forEach(itemRef => {
if (itemRef.value) itemRef.value.getTableHeight()
})
} else if (crudRef.value) crudRef.value.getTableHeight()
}, 100)
}
watch(
() => windowSize.height.value,
() => {
initTableLayout()
}
)
return { initTableLayout, windowSize }
}

View File

@@ -0,0 +1,24 @@
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
export const useCrudPermi = () => {
const { wsCache } = useCache()
const all_permission = '*:*'
const permissions = wsCache.get(CACHE_KEY.USER).permissions
const crudBtnObj = {
query: 'viewBtn',
create: 'addBtn',
update: 'editBtn',
delete: 'delBtn',
}
const getCurrPermi = (permiArr: string[]) => {
const crudPermission = {}
permiArr.forEach(permiKey => {
for (const key in crudBtnObj) {
crudPermission[crudBtnObj[key]] = permiKey === all_permission || permissions[`${permiKey}:${key}`]
}
})
return crudPermission
}
return { getCurrPermi }
}

View File

@@ -0,0 +1,83 @@
export default function () {
const onMove = (e) => {
const type = e.draggedContext.element.type
const toClassName = e.to.className.split(' ')
// console.log(type, toClassName)
if (
type == 'layoutGroup' &&
['layout-group__body', 'layout-table__body'].includes(toClassName[0])
) {
//禁止 group 拖拽进 group\table
return false
}
if (type == 'layoutTable' && ['layout-table__body'].includes(toClassName[0])) {
//禁止 table 拖拽进 table
return false
}
if (
type == 'layoutTabs' &&
['layout-tabs__body', 'layout-table__body', 'layout-grid__body'].includes(toClassName[0])
) {
//禁止 tabs 拖拽进 tabs/table/grid
return false
}
if (type == 'layoutGrid' && ['layout-grid__body', 'layout-table__body'].includes(toClassName[0])) {
//禁止 grid 拖拽进 grid/table
return false
}
if (['layoutTabs', 'layoutGrid'].includes(type) && ['tabs-layout-group__body', 'grid-layout-group__body'].includes(toClassName[3])) {
//禁止 tabs|grid 拖拽进 tabs内的group grid内的group
return false
}
if (type == 'comboBox' && ['layout-table__body'].includes(toClassName[0])) {
//禁止 comboBox 拖拽进 table
return false
}
if (
['ueditor', 'buttonList', 'title'].includes(type) &&
['layout-table__body'].includes(toClassName[0])
) {
//禁止 富文本、按钮组、文本 拖拽进 table
return false
}
// 限制组合框可拖拽控件
if (['combo-box__body'].includes(toClassName[0])) {
if (['input', 'select', 'date', 'time'].includes(e.draggedContext.element.controlType)) {
if (['textarea', 'radio', 'checkbox', 'switch'].includes(type)) return false
} else {
if (!['buttonList'].includes(type)) return false
}
if (type == 'comboBox') return false
}
return true
}
const handleDragPosition = (newIndex, columnData) => {
let isGroup = false
if (columnData[newIndex]) isGroup = columnData[newIndex].type == 'layoutGroup'
let repIndex: number | undefined = undefined
columnData.forEach((item, index) => {
if (repIndex === undefined && item.type == 'layoutGroup') {
if (isGroup && index > newIndex) repIndex = index != 0 ? index - 1 : index
else if (!isGroup && index <= newIndex) repIndex = index
}
})
if (isGroup && repIndex !== newIndex) {
const column = columnData.splice(newIndex, 1)
if (repIndex === undefined) repIndex = columnData.length
if (column[0]) columnData.splice(repIndex, 0, column[0])
} else if (!isGroup && repIndex !== undefined && repIndex < newIndex) {
const column = columnData.splice(newIndex, 1)
if (column[0]) columnData.splice(repIndex, 0, column[0])
}
}
return {
onMove,
handleDragPosition
}
}

View File

@@ -0,0 +1,128 @@
import { listToTree, findNode, treeMap } from '@/utils/tree'
import { cloneDeep } from 'lodash-es'
export const useGroup = (treeRef, DataApi, resetChange, isView?, isOneLevel?) => {
const message = useMessage() // 消息弹窗
const treeForm = ref<any>({})
const treeOption = ref({
nodeKey: 'id',
defaultExpandAll: true,
filterText: '输入名称进行过滤',
props: { label: 'name', value: 'id' },
formOption: {
labelWidth: 100,
column: {
pid: { label: '上级分组', type: 'tree', value: 0, disabled: isOneLevel, dicData: [], filterable: true, defaultExpandAll: true, props: { label: 'name', value: 'id' } },
name: { label: '分组名称', rules: [{ required: true, message: '请输入 分组名称', trigger: "blur" }] }
}
}
})
if (isOneLevel) treeOption.value.formOption['filterParams'] = ['pid']
const treeData = ref<any>([])
const groupValue = ref<string | number>(0)
const currMenuNodeData = ref<any>({})
if (isView) {
treeOption.value['addBtn'] = false
treeOption.value['editBtn'] = false
treeOption.value['delBtn'] = false
treeOption.value['menu'] = false
}
const treePermission = (key, data) => {
if (key != 'addBtn' && data.id === 0) return false
return true
}
const treeNodeContextmenu = (data) => {
currMenuNodeData.value = data
}
const treeBeforeOpen = (done, type) => {
setTimeout(() => {
const treeList = cloneDeep(treeData.value)
if (type == 'edit') {
const disabledArr = [treeForm.value.id]
treeMap(treeList, {
children: 'children',
conversion: (item) => {
if (item.id == disabledArr[0]) item.disabled = true
if (disabledArr.includes(item.pid)) {
item.disabled = true
disabledArr.push(item.id)
}
return item
}
})
treeForm.value.oldPid = treeForm.value.pid
} else {
treeForm.value.pid = currMenuNodeData.value.id
}
treeOption.value.formOption.column.pid.dicData = treeList
if (isOneLevel) treeForm.value.pid = 0
}, 30)
done()
}
const treeNodeClick = (data) => {
if (data.id == groupValue.value) {
treeRef.value.setCurrentKey(null)
groupValue.value = ''
} else groupValue.value = data.id
resetChange()
}
const getTreeData = async () => {
const data = await DataApi.getGroupData({})
treeData.value = [{ name: '全部', id: 0, children: listToTree(data) }]
}
const treeUpdate = (node, data, done, loading) => {
DataApi.updateGroupData(data)
.then(() => {
if (data.oldPid != data.pid) {
const oldPNode = findNode(treeData.value, (node) => node.id == data.oldPid)
oldPNode.children = oldPNode.children.filter((item) => item.id != data.id)
const pNode = findNode(treeData.value, (node) => node.id == data.pid)
delete data.oldPid
if (pNode.children) pNode.children.push(data)
else pNode.children = [data]
}
done()
})
.catch(() => loading())
}
const treeSave = async (node, data, done, loading) => {
treeForm.value['children'] = []
await DataApi.saveGroupData(data)
.then((res) => {
treeForm.value.id = res
done()
setTimeout(() => {
if (treeData.value.length > 1) {
const currData = treeData.value.splice(1, 1)
const pNode = findNode(treeData.value, (node) => node.id == currData[0].pid)
if (pNode) pNode.children.push(currData[0])
}
if (isOneLevel && treeData.value[0]?.children.length) {
for (const index in treeData.value[0].children) {
const child = treeData.value[0].children[index]
if (child.children?.length) {
const addData = cloneDeep(child.children[0])
treeRef.value.updateKeyChildren(child.id, [])
treeRef.value.updateKeyChildren(treeData.value[0].id, [...treeData.value[0].children, addData])
break
}
}
}
}, 0)
})
.catch(() => loading())
}
const treeDel = async (node, done) => {
await message.delConfirm()
await DataApi.deleteGroupData([node.data.id])
done()
}
return { treeForm, treeOption, treeData, groupValue, treePermission, treeNodeContextmenu, treeBeforeOpen, treeNodeClick, getTreeData, treeUpdate, treeSave, treeDel }
}

View File

@@ -0,0 +1,57 @@
export default function () {
interface MEDialog {
value: boolean
title?: string
params?: object
otherParams?: object
handleClose?: any
}
interface MEData {
value: string
language?: string
editorOption?: object
params?: object
setFormValue?: (value: string) => void
}
const MEDialog = ref<MEDialog>({ value: false })
const MEData = ref<MEData>({ value: '' })
const openMEDialog = (column, tableForm) => {
const { prop, label, params } = column
const dialogParams = {}
const meParams = {}
let otherParams = {}
if (typeof params == 'object') {
for (const key in params) {
if (['title', 'width', 'controlType', 'fullscreen', 'headerBtn', 'footerBtn', 'dialogParams'].includes(key)) dialogParams[key] = params[key]
else if (['language', 'editorOption', 'providerType', 'oldValue'].includes(key)) meParams[key] = params[key]
if (key == 'otherParams') otherParams = params[key]
}
}
dialogParams['handleClose'] = (done) => {
if (MEData.value.setFormValue) MEData.value.setFormValue(MEData.value.value)
if (params && params.handleClose) params.handleClose(done)
else done()
}
MEDialog.value = {
value: true,
params: {
destroyOnClose: true,
title: label,
...dialogParams,
},
otherParams: Object.keys(otherParams).length ? otherParams : false
}
MEData.value = {
value: prop ? tableForm[prop] : tableForm || '',
params: meParams,
setFormValue: (value: string) => {
if (tableForm && prop) tableForm[prop] = value
},
}
}
return {
MEDialog, MEData, openMEDialog
}
}

View File

@@ -0,0 +1,389 @@
// import * as monaco from 'monaco-editor'
import { ref, nextTick, onBeforeUnmount } from 'vue'
//语言
// import 'monaco-editor/esm/vs/basic-languages/scss/scss.contribution';
// import 'monaco-editor/esm/vs/basic-languages/java/java.contribution';
// import * as MySql from 'monaco-editor/esm/vs/basic-languages/mysql/mysql.js';
// import * as JavaScript from 'monaco-editor/esm/vs/basic-languages/javascript/javascript.js';
// import * as Java from 'monaco-editor/esm/vs/basic-languages/java/java.js';
// 查找控件
import 'monaco-editor/esm/vs/editor/contrib/find/browser/findController';
import enhanceTip from '@/components/LowDesign/src/utils/enhanceTip';
import * as sqlFormatter from 'sql-formatter'
interface completions {
label: string
insertText: string
detail?: string
kind?: any
sortText?: string
}
let MySql: any = null
let JavaScript: any = null
let Java: any = null
let monaco: any = null
const monacoProviderRef = ref<any>({})
const providerType = ref('')
let disposeArr: any[] = []
// 动态加载 monaco-editor 和相关语言包
async function initMonaco() {
if (!monaco) {
monaco = await import('monaco-editor')
MySql = await import('monaco-editor/esm/vs/basic-languages/mysql/mysql.js')
JavaScript = await import('monaco-editor/esm/vs/basic-languages/javascript/javascript.js')
Java = await import('monaco-editor/esm/vs/basic-languages/java/java.js')
}
return monaco
}
//清除提示
function clearProvider() {
for (const key in monacoProviderRef.value) monacoProviderRef.value[key]?.dispose()
}
function initLanguageProvider() {
if (!monaco) return
clearProvider()
const sqlProvider: any = {
provideCompletionItems: (model, position) => {
const suggestions: completions[] = []
const { lineNumber, column } = position
const textBeforePointer = model.getValueInRange({
startLineNumber: lineNumber,
startColumn: 0,
endLineNumber: lineNumber,
endColumn: column,
})
const contents = textBeforePointer.trim().split(/\s+/)
const lastContents = contents[contents?.length - 1] // 获取最后一段非空字符串
if (lastContents) {
const sqlConfigKey = ['builtinFunctions', 'keywords', 'operators']
sqlConfigKey.forEach(key => {
MySql.language[key].forEach(sql => suggestions.push({ label: sql, insertText: sql, kind: monaco.languages.CompletionItemKind.Value }))
})
}
return { suggestions }
}
}
const javaProvider: any = {
provideCompletionItems: (model, position) => {
const suggestions: completions[] = []
const { lineNumber, column } = position
const textBeforePointer = model.getValueInRange({
startLineNumber: lineNumber,
startColumn: 0,
endLineNumber: lineNumber,
endColumn: column,
})
const contents = textBeforePointer.trim().split(/\s+/)
const lastContents = contents[contents?.length - 1] // 获取最后一段非空字符串
if (lastContents) {
const javaConfigKey = ['keywords', 'operators']
javaConfigKey.forEach(key => {
Java.language[key].forEach(java => suggestions.push({ label: java, insertText: java, kind: monaco.languages.CompletionItemKind.Value }))
})
}
return { suggestions }
}
}
let javaScriptDesign: any = []
const { tipList, triggerObj } = enhanceTip[providerType.value] || {}
if (tipList) javaScriptDesign = tipList
const javaScriptProvider: any = {
provideCompletionItems: (model, position) => {
if (!providerType.value) return { suggestions: [] }
const suggestions: completions[] = []
const { lineNumber, column } = position
const textBeforePointer = model.getValueInRange({
startLineNumber: lineNumber,
startColumn: 0,
endLineNumber: lineNumber,
endColumn: column,
})
const contents = textBeforePointer.trim().split(/\s+/)
const lastContents = contents[contents?.length - 1] // 获取最后一段非空字符串
const setTipFun = (bool) => {
javaScriptDesign.forEach((javaScript) => {
const item = { ...javaScript, sortText: bool ? '100' : '' }
suggestions.push(item)
})
}
let triggerKey = ''
if (triggerObj && lastContents) {
const lastLeng = lastContents.length
for (const key in triggerObj) {
if (triggerKey) break
const findIndex = lastContents.lastIndexOf(key)
if (findIndex != -1) {
const keyLeng = key.length
if (lastLeng - keyLeng == findIndex) triggerKey = key
}
}
}
if (triggerKey) {
javaScriptDesign = triggerObj[triggerKey]
setTipFun(true)
return { incomplete: false, suggestions }
}
javaScriptDesign = tipList || []
if (lastContents) {
const javaScriptConfigKey = ['operators']
javaScriptConfigKey.forEach(key => {
JavaScript.language[key].forEach(javaScript => suggestions.push({ label: javaScript, insertText: javaScript }))
})
setTipFun(false)
}
return { incomplete: false, suggestions }
},
triggerCharacters: ['.'],
}
monacoProviderRef.value.mysql = monaco.languages.registerCompletionItemProvider('mysql', sqlProvider);
monacoProviderRef.value.java = monaco.languages.registerCompletionItemProvider('java', javaProvider);
monacoProviderRef.value.javascript = monaco.languages.registerCompletionItemProvider('javascript', javaScriptProvider);
}
function addMySqlFormat() {
if (!monaco) return
const sqlFormatDisposable = monaco.editor.addEditorAction({
id: 'format-sql',
label: '格式化 SQL',
contextMenuGroupId: 'navigation',
contextMenuOrder: 1.5,
run: (ed) => {
const original = ed.getValue();
const formatted = sqlFormatter.format(original, {
language: 'mysql',
params: ['#\\{[^}]+\\}']
});
ed.setValue(formatted)
}
})
const list = [...(sqlFormatDisposable['_toDispose'] || [])]
disposeArr.push(...list)
}
function emptyDispose() {
if (disposeArr.length) {
disposeArr.forEach(item => item.dispose && item.dispose())
disposeArr = []
}
}
export function useMonacoEditor(language: string = 'javascript') {
// 编辑器示例
let monacoEditor: any = null
// 目标元素
const monacoEditorRef = ref<HTMLElement | null>(null)
// 创建实例
async function createEditor(editorOption: any = {}, type = '') {
providerType.value = type
// 动态加载 monaco
await initMonaco()
if (!monacoEditorRef.value) return
initLanguageProvider()
if (language) {
monacoEditor = monaco.editor.create(monacoEditorRef.value, {
// 初始模型
model: monaco.editor.createModel('', language),
minimap: { enabled: true },
// 圆角
roundedSelection: true,
// 主题
theme: 'vs-dark',
multiCursorModifier: 'ctrlCmd',
// 滚动条
scrollbar: {
verticalScrollbarSize: 8,
horizontalScrollbarSize: 8
},
// 行号
lineNumbers: 'on',
// tab大小
tabSize: 2,
//字体大小
fontSize: 14,
// 控制编辑器在用户键入、粘贴、移动或缩进行时是否应自动调整缩进
autoIndent: 'advanced',
autoClosingBrackets: 'always',//补全括号
autoClosingQuotes: 'always', //补全冒号
// 自动布局
automaticLayout: true,
fixedOverflowWidgets: true,
...editorOption,
})
}
return monacoEditor
}
emptyDispose()
if (language == 'mysql') addMySqlFormat()
// 格式化
async function formatDoc() {
await monacoEditor?.getAction('editor.action.formatDocument')?.run()
}
// 数据更新
function updateVal(val: string) {
nextTick(() => {
monacoEditor?.setValue(val)
setTimeout(async () => {
await formatDoc()
}, 10)
})
}
// 配置更新
async function updateOptions(opt: any, type = '') {
// 确保 monaco 已加载
await initMonaco()
providerType.value = type
initLanguageProvider()
monacoEditor?.updateOptions(opt)
}
// 获取配置
function getOption(name: any) {
return monacoEditor?.getOption(name)
}
// 获取实例
function getEditor() {
return monacoEditor
}
// 设置语言
async function setLanguage(language: string, type = '') {
// 确保 monaco 已加载
await initMonaco()
providerType.value = type
const text = monacoEditor?.getModel()?.getValue() || ''
const model = monaco.editor.createModel(text, language)
monacoEditor?.setModel(model)
emptyDispose()
if (language == 'mysql') addMySqlFormat()
}
onBeforeUnmount(() => {
if (monacoEditor) {
clearProvider()
emptyDispose()
monacoEditor.dispose()
}
})
return {
monacoEditorRef,
createEditor,
getEditor,
setLanguage,
updateVal,
updateOptions,
getOption,
formatDoc,
}
}
export function useDiffEditor(language: string = 'javascript', newValue: string, oldValue: string) {
// 编辑器示例
let diffEditor: any = null
let originalModel: any = null
let modifiedModel: any = null
// 目标元素
const deffEditorRef = ref<HTMLElement | null>(null)
// 创建实例
async function createDeffEditor(editorOption: any = {}, type = '') {
// 动态加载 monaco
await initMonaco()
providerType.value = type
if (!deffEditorRef.value) return
initLanguageProvider()
diffEditor = monaco.editor.createDiffEditor(deffEditorRef.value, {
fontSize: 14, // 字体大小
theme: 'vs-dark', //主题
readOnly: false, // 是否只读
overviewRulerBorder: false, // 滚动是否有边框
cursorSmoothCaretAnimation: 'off', // 控制光标平滑动画的开启与关闭。当开启时,光标移动会有平滑的动画效果。
mouseWheelZoom: true, //设置是否开启鼠标滚轮缩放功能
folding: true, //控制是否开启代码折叠功能
automaticLayout: true, // 控制编辑器是否自动调整布局以适应容器大小的变化
// 是否启用预览图
minimap: { enabled: true },
// 滚动条
scrollbar: {
verticalScrollbarSize: 8,
horizontalScrollbarSize: 8
},
wordWrap: "off", // 关闭自动换行
scrollBeyondLastLine: false,
roundedSelection: true, // 右侧不显示编辑器预览框
originalEditable: false, // 是否允许修改原始文本
...editorOption,
})
originalModel = monaco.editor.createModel(oldValue, language);
modifiedModel = monaco.editor.createModel(newValue, language);
diffEditor.setModel({ original: originalModel, modified: modifiedModel });
return { diffEditor, originalModel, modifiedModel }
}
//获取实例
function getEditor(type: string) {
if (type == 'diff') return diffEditor
if (type == 'original') return originalModel
if (type == 'modified') return modifiedModel
}
// 格式化
async function formatDoc() {
await originalModel?.getAction('editor.action.formatDocument')?.run()
await modifiedModel?.getAction('editor.action.formatDocument')?.run()
}
// 数据更新
function updateVal(val: string, type: string) {
nextTick(() => {
if (type == 'original') return originalModel?.setValue(val)
if (type == 'modified') return modifiedModel?.setValue(val)
setTimeout(async () => {
await formatDoc()
}, 10)
})
}
// 设置语言
async function setLanguage(language: string, type = '') {
// 确保 monaco 已加载
await initMonaco()
providerType.value = type
const originalText = originalModel?.getValue() || ''
const modifiedText = modifiedModel?.getValue() || ''
originalModel = monaco.editor.createModel(originalText, language)
modifiedModel = monaco.editor.createModel(modifiedText, language)
diffEditor?.setModel({ original: originalModel, modified: modifiedModel })
}
return {
deffEditorRef,
createDeffEditor,
getEditor,
updateVal,
setLanguage
}
}