Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Simoje丶
vue-vben-admin
提交
f75425d1
V
vue-vben-admin
项目概览
Simoje丶
/
vue-vben-admin
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vue-vben-admin
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
f75425d1
编写于
10月 22, 2020
作者:
V
vben
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
perf: review tinymce code
上级
9c02d8ec
变更
25
显示空白变更内容
内联
并排
Showing
25 changed file
with
349 addition
and
383 deletion
+349
-383
src/components/Tinymce/src/Editor.vue
src/components/Tinymce/src/Editor.vue
+129
-19
src/components/Tinymce/src/getTinymce.ts
src/components/Tinymce/src/getTinymce.ts
+1
-4
src/components/Tinymce/src/helper.ts
src/components/Tinymce/src/helper.ts
+81
-0
src/components/Tinymce/src/lib/ScriptLoader.ts
src/components/Tinymce/src/lib/ScriptLoader.ts
+0
-72
src/components/Tinymce/src/lib/components/Editor.ts
src/components/Tinymce/src/lib/components/Editor.ts
+0
-111
src/components/Tinymce/src/lib/components/EditorPropTypes.ts
src/components/Tinymce/src/lib/components/EditorPropTypes.ts
+0
-46
src/components/Tinymce/src/lib/global.d.ts
src/components/Tinymce/src/lib/global.d.ts
+0
-4
src/components/Tinymce/src/lib/index.ts
src/components/Tinymce/src/lib/index.ts
+0
-3
src/components/Tinymce/src/props.ts
src/components/Tinymce/src/props.ts
+4
-6
src/router/menus/modules/demo/charts.ts
src/router/menus/modules/demo/charts.ts
+5
-5
src/router/menus/modules/demo/comp.ts
src/router/menus/modules/demo/comp.ts
+11
-25
src/router/menus/modules/demo/editor.ts
src/router/menus/modules/demo/editor.ts
+15
-1
src/router/menus/modules/demo/excel.ts
src/router/menus/modules/demo/excel.ts
+4
-6
src/router/menus/modules/demo/exception.ts
src/router/menus/modules/demo/exception.ts
+6
-6
src/router/menus/modules/demo/feat.ts
src/router/menus/modules/demo/feat.ts
+13
-13
src/router/menus/modules/demo/form.ts
src/router/menus/modules/demo/form.ts
+7
-7
src/router/menus/modules/demo/iframe.ts
src/router/menus/modules/demo/iframe.ts
+3
-3
src/router/menus/modules/demo/permission.ts
src/router/menus/modules/demo/permission.ts
+8
-8
src/router/menus/modules/demo/table.ts
src/router/menus/modules/demo/table.ts
+14
-14
src/router/routes/modules/demo/comp.ts
src/router/routes/modules/demo/comp.ts
+0
-26
src/router/routes/modules/demo/editor.ts
src/router/routes/modules/demo/editor.ts
+27
-0
src/utils/is.ts
src/utils/is.ts
+4
-0
src/utils/uuid.ts
src/utils/uuid.ts
+8
-0
src/views/demo/editor/tinymce/Editor.vue
src/views/demo/editor/tinymce/Editor.vue
+1
-1
src/views/demo/editor/tinymce/index.vue
src/views/demo/editor/tinymce/index.vue
+8
-3
未找到文件。
src/components/Tinymce/src/Editor.vue
浏览文件 @
f75425d1
<
template
>
<div
class=
"tinymce-container"
:style=
"
{ width: containerWidth }">
<tinymce-editor
:id=
"id"
:init=
"initOptions"
:modelValue=
"tinymceContent"
@
update:modelValue=
"handleChange"
:tinymceScriptSrc=
"tinymceScriptSrc"
></tinymce-editor>
<textarea
:id=
"tinymceId"
visibility=
"hidden"
ref=
"elRef"
></textarea>
</div>
</
template
>
<
script
lang=
"ts"
>
import
TinymceEditor
from
'
./lib
'
;
// TinyMCE vue wrapper
import
{
defineComponent
,
computed
}
from
'
vue
'
;
import
{
defineComponent
,
computed
,
onMounted
,
nextTick
,
ref
,
unref
,
watch
,
onUnmounted
,
onDeactivated
,
}
from
'
vue
'
;
import
{
basicProps
}
from
'
./props
'
;
import
toolbar
from
'
./toolbar
'
;
import
plugins
from
'
./plugins
'
;
import
{
getTinymce
}
from
'
./getTinymce
'
;
import
{
useScript
}
from
'
/@/hooks/web/useScript
'
;
import
{
snowUuid
}
from
'
/@/utils/uuid
'
;
import
{
bindHandlers
}
from
'
./helper
'
;
const
CDN_URL
=
'
https://cdn.bootcdn.net/ajax/libs/tinymce/5.5.1
'
;
const
tinymceScriptSrc
=
`
${
CDN_URL
}
/tinymce.min.js`
;
export
default
defineComponent
({
name
:
'
Tinymce
'
,
components
:
{
TinymceEditor
},
props
:
basicProps
,
setup
(
props
,
{
emit
})
{
emits
:
[
'
change
'
,
'
update:modelValue
'
],
setup
(
props
,
{
emit
,
attrs
})
{
const
editorRef
=
ref
<
any
>
(
null
);
const
elRef
=
ref
<
Nullable
<
HTMLElement
>>
(
null
);
const
tinymceId
=
computed
(()
=>
{
return
snowUuid
(
'
tiny-vue
'
);
});
const
tinymceContent
=
computed
(()
=>
{
return
props
.
v
alue
;
return
props
.
modelV
alue
;
});
function
handleChange
(
value
:
string
)
{
emit
(
'
change
'
,
value
);
}
const
containerWidth
=
computed
(()
=>
{
const
width
=
props
.
width
;
// Test matches `100`, `'100'`
if
(
/^
[\d]
+
(\.[\d]
+
)?
$/
.
test
(
width
.
toString
()))
{
return
`
${
width
}
px`
;
}
return
width
;
});
const
initOptions
=
computed
(()
=>
{
const
{
id
,
height
,
menubar
}
=
props
;
const
{
height
,
menubar
}
=
props
;
return
{
selector
:
`#
${
id
}
`
,
selector
:
`#
${
unref
(
tinymceId
)
}
`
,
height
:
height
,
toolbar
:
toolbar
,
theme
:
'
silver
'
,
menubar
:
menubar
,
plugins
:
plugins
,
// 语言包
language_url
:
'
resource/tinymce/langs/zh_CN.js
'
,
// 中文
language
:
'
zh_CN
'
,
default_link_target
:
'
_blank
'
,
link_title
:
false
,
advlist_bullet_styles
:
'
square
'
,
advlist_number_styles
:
'
default
'
,
object_resizing
:
false
,
setup
:
(
editor
:
any
)
=>
{
editorRef
.
value
=
editor
;
editor
.
on
(
'
init
'
,
(
e
:
Event
)
=>
initSetup
(
e
));
},
};
});
return
{
containerWidth
,
initOptions
,
tinymceContent
,
handleChange
,
tinymceScriptSrc
};
const
{
toPromise
}
=
useScript
({
src
:
tinymceScriptSrc
,
});
watch
(
()
=>
attrs
.
disabled
,
()
=>
{
const
editor
=
unref
(
editorRef
);
if
(
!
editor
)
return
;
editor
.
setMode
(
attrs
.
disabled
?
'
readonly
'
:
'
design
'
);
}
);
onMounted
(()
=>
{
nextTick
(()
=>
{
init
();
});
});
onUnmounted
(()
=>
{
destory
();
});
onDeactivated
(()
=>
{
destory
();
});
function
destory
()
{
if
(
getTinymce
()
!==
null
)
{
getTinymce
().
remove
(
unref
(
editorRef
));
}
}
function
init
()
{
toPromise
().
then
(()
=>
{
initEditor
();
});
}
function
initEditor
()
{
getTinymce
().
init
(
unref
(
initOptions
));
}
function
initSetup
(
e
:
Event
)
{
const
editor
=
unref
(
editorRef
);
if
(
!
editor
)
return
;
const
value
=
props
.
modelValue
||
''
;
editor
.
setContent
(
value
);
bindModelHandlers
(
editor
);
bindHandlers
(
e
,
attrs
,
unref
(
editorRef
));
}
function
bindModelHandlers
(
editor
:
any
)
{
const
modelEvents
=
attrs
.
modelEvents
?
attrs
.
modelEvents
:
null
;
const
normalizedEvents
=
Array
.
isArray
(
modelEvents
)
?
modelEvents
.
join
(
'
'
)
:
modelEvents
;
watch
(
()
=>
props
.
modelValue
,
(
val
:
string
,
prevVal
:
string
)
=>
{
if
(
editor
&&
typeof
val
===
'
string
'
&&
val
!==
prevVal
&&
val
!==
editor
.
getContent
({
format
:
attrs
.
outputFormat
})
)
{
editor
.
setContent
(
val
);
}
}
);
editor
.
on
(
normalizedEvents
?
normalizedEvents
:
'
change keyup undo redo
'
,
()
=>
{
emit
(
'
update:modelValue
'
,
editor
.
getContent
({
format
:
attrs
.
outputFormat
}));
});
}
function
handleChange
(
value
:
string
)
{
emit
(
'
change
'
,
value
);
}
return
{
containerWidth
,
initOptions
,
tinymceContent
,
handleChange
,
tinymceScriptSrc
,
elRef
,
tinymceId
,
};
},
});
</
script
>
...
...
src/components/Tinymce/src/
lib/TinyMCE
.ts
→
src/components/Tinymce/src/
getTinymce
.ts
浏览文件 @
f75425d1
const
getGlobal
=
():
any
=>
(
typeof
window
!==
'
undefined
'
?
window
:
global
);
const
getTinymce
=
()
=>
{
export
const
getTinymce
=
()
=>
{
const
global
=
getGlobal
();
return
global
&&
global
.
tinymce
?
global
.
tinymce
:
null
;
};
export
{
getTinymce
};
src/components/Tinymce/src/
lib/Utils
.ts
→
src/components/Tinymce/src/
helper
.ts
浏览文件 @
f75425d1
import
{
ComponentPublicInstance
}
from
'
vue
'
;
const
validEvents
=
[
'
onActivate
'
,
'
onAddUndo
'
,
...
...
@@ -62,12 +60,12 @@ const validEvents = [
'
onShow
'
,
'
onSubmit
'
,
'
onUndo
'
,
'
onVisualAid
'
'
onVisualAid
'
,
];
const
isValidKey
=
(
key
:
string
)
=>
validEvents
.
indexOf
(
key
)
!==
-
1
;
const
bindHandlers
=
(
initEvent
:
Event
,
listeners
:
any
,
editor
:
any
):
void
=>
{
export
const
bindHandlers
=
(
initEvent
:
Event
,
listeners
:
any
,
editor
:
any
):
void
=>
{
Object
.
keys
(
listeners
)
.
filter
(
isValidKey
)
.
forEach
((
key
:
string
)
=>
{
...
...
@@ -81,71 +79,3 @@ const bindHandlers = (initEvent: Event, listeners: any, editor: any): void => {
}
});
};
const
bindModelHandlers
=
(
ctx
:
ComponentPublicInstance
,
editor
:
any
)
=>
{
const
modelEvents
=
ctx
.
$props
.
modelEvents
?
ctx
.
$props
.
modelEvents
:
null
;
const
normalizedEvents
=
Array
.
isArray
(
modelEvents
)
?
modelEvents
.
join
(
'
'
)
:
modelEvents
;
// @ts-ignore
ctx
.
$watch
(
'
modelValue
'
,
(
val
:
string
,
prevVal
:
string
)
=>
{
if
(
editor
&&
typeof
val
===
'
string
'
&&
val
!==
prevVal
&&
val
!==
editor
.
getContent
({
format
:
ctx
.
$props
.
outputFormat
}))
{
editor
.
setContent
(
val
);
}
});
editor
.
on
(
normalizedEvents
?
normalizedEvents
:
'
change keyup undo redo
'
,
()
=>
{
ctx
.
$emit
(
'
update:modelValue
'
,
editor
.
getContent
({
format
:
ctx
.
$props
.
outputFormat
}));
});
};
const
initEditor
=
(
initEvent
:
Event
,
ctx
:
ComponentPublicInstance
,
editor
:
any
)
=>
{
const
value
=
ctx
.
$props
.
modelValue
?
ctx
.
$props
.
modelValue
:
''
;
const
initialValue
=
ctx
.
$props
.
initialValue
?
ctx
.
$props
.
initialValue
:
''
;
editor
.
setContent
(
value
||
initialValue
);
// checks if the v-model shorthand is used (which sets an v-on:input listener) and then binds either
// specified the events or defaults to "change keyup" event and emits the editor content on that event
if
(
ctx
.
$attrs
[
'
onUpdate:modelValue
'
])
{
bindModelHandlers
(
ctx
,
editor
);
}
bindHandlers
(
initEvent
,
ctx
.
$attrs
,
editor
);
};
let
unique
=
0
;
const
uuid
=
(
prefix
:
string
):
string
=>
{
const
time
=
Date
.
now
();
const
random
=
Math
.
floor
(
Math
.
random
()
*
1000000000
);
unique
++
;
return
prefix
+
'
_
'
+
random
+
unique
+
String
(
time
);
};
const
isTextarea
=
(
element
:
Element
|
null
):
element
is
HTMLTextAreaElement
=>
{
return
element
!==
null
&&
element
.
tagName
.
toLowerCase
()
===
'
textarea
'
;
};
const
normalizePluginArray
=
(
plugins
?:
string
|
string
[]):
string
[]
=>
{
if
(
typeof
plugins
===
'
undefined
'
||
plugins
===
''
)
{
return
[];
}
return
Array
.
isArray
(
plugins
)
?
plugins
:
plugins
.
split
(
'
'
);
};
const
mergePlugins
=
(
initPlugins
:
string
|
string
[],
inputPlugins
?:
string
|
string
[])
=>
normalizePluginArray
(
initPlugins
).
concat
(
normalizePluginArray
(
inputPlugins
));
const
isNullOrUndefined
=
(
value
:
any
):
value
is
null
|
undefined
=>
value
===
null
||
value
===
undefined
;
export
{
bindHandlers
,
bindModelHandlers
,
initEditor
,
uuid
,
isTextarea
,
mergePlugins
,
isNullOrUndefined
};
\ No newline at end of file
src/components/Tinymce/src/lib/ScriptLoader.ts
已删除
100644 → 0
浏览文件 @
9c02d8ec
import
{
uuid
}
from
'
./Utils
'
;
export
type
callbackFn
=
()
=>
void
;
export
interface
IStateObj
{
listeners
:
callbackFn
[];
scriptId
:
string
;
scriptLoaded
:
boolean
;
}
const
createState
=
():
IStateObj
=>
{
return
{
listeners
:
[],
scriptId
:
uuid
(
'
tiny-script
'
),
scriptLoaded
:
false
};
};
interface
ScriptLoader
{
load
:
(
doc
:
Document
,
url
:
string
,
callback
:
callbackFn
)
=>
void
;
reinitialize
:
()
=>
void
;
}
const
CreateScriptLoader
=
():
ScriptLoader
=>
{
let
state
:
IStateObj
=
createState
();
const
injectScriptTag
=
(
scriptId
:
string
,
doc
:
Document
,
url
:
string
,
callback
:
callbackFn
)
=>
{
const
scriptTag
=
doc
.
createElement
(
'
script
'
);
scriptTag
.
referrerPolicy
=
'
origin
'
;
scriptTag
.
type
=
'
application/javascript
'
;
scriptTag
.
id
=
scriptId
;
scriptTag
.
src
=
url
;
const
handler
=
()
=>
{
scriptTag
.
removeEventListener
(
'
load
'
,
handler
);
callback
();
};
scriptTag
.
addEventListener
(
'
load
'
,
handler
);
if
(
doc
.
head
)
{
doc
.
head
.
appendChild
(
scriptTag
);
}
};
const
load
=
(
doc
:
Document
,
url
:
string
,
callback
:
callbackFn
)
=>
{
if
(
state
.
scriptLoaded
)
{
callback
();
}
else
{
state
.
listeners
.
push
(
callback
);
if
(
!
doc
.
getElementById
(
state
.
scriptId
))
{
injectScriptTag
(
state
.
scriptId
,
doc
,
url
,
()
=>
{
state
.
listeners
.
forEach
((
fn
)
=>
fn
());
state
.
scriptLoaded
=
true
;
});
}
}
};
// Only to be used by tests.
const
reinitialize
=
()
=>
{
state
=
createState
();
};
return
{
load
,
reinitialize
};
};
const
ScriptLoader
=
CreateScriptLoader
();
export
{
ScriptLoader
};
\ No newline at end of file
src/components/Tinymce/src/lib/components/Editor.ts
已删除
100644 → 0
浏览文件 @
9c02d8ec
/**
* Copyright (c) 2018-present, Ephox, Inc.
*
* This source code is licensed under the Apache 2 license found in the
* LICENSE file in the root directory of this source tree.
*
*/
// import { ThisTypedComponentOptionsWithRecordProps } from 'vue/types/options';
// import { CreateElement, Vue } from 'vue/types/vue';
import
{
ScriptLoader
}
from
'
../ScriptLoader
'
;
import
{
getTinymce
}
from
'
../TinyMCE
'
;
import
{
initEditor
,
isTextarea
,
mergePlugins
,
uuid
,
isNullOrUndefined
}
from
'
../Utils
'
;
import
{
editorProps
,
IPropTypes
}
from
'
./EditorPropTypes
'
;
import
{
h
,
defineComponent
,
ComponentPublicInstance
}
from
'
vue
'
export
interface
IEditor
{
$props
:
Partial
<
IPropTypes
>
}
declare
module
'
@vue/runtime-core
'
{
interface
ComponentCustomProperties
{
elementId
:
string
;
element
:
Element
|
null
;
editor
:
any
;
inlineEditor
:
boolean
;
$props
:
Partial
<
IPropTypes
>
;
}
}
const
renderInline
=
(
id
:
string
,
tagName
?:
string
)
=>
{
return
h
(
tagName
?
tagName
:
'
div
'
,
{
id
});
};
const
renderIframe
=
(
id
:
string
)
=>
{
return
h
(
'
textarea
'
,
{
id
,
visibility
:
'
hidden
'
});
};
const
initialise
=
(
ctx
:
ComponentPublicInstance
)
=>
()
=>
{
const
finalInit
=
{
...
ctx
.
$props
.
init
,
readonly
:
ctx
.
$props
.
disabled
,
selector
:
`#
${
ctx
.
elementId
}
`
,
plugins
:
mergePlugins
(
ctx
.
$props
.
init
&&
ctx
.
$props
.
init
.
plugins
,
ctx
.
$props
.
plugins
),
toolbar
:
ctx
.
$props
.
toolbar
||
(
ctx
.
$props
.
init
&&
ctx
.
$props
.
init
.
toolbar
),
inline
:
ctx
.
inlineEditor
,
setup
:
(
editor
:
any
)
=>
{
ctx
.
editor
=
editor
;
editor
.
on
(
'
init
'
,
(
e
:
Event
)
=>
initEditor
(
e
,
ctx
,
editor
));
if
(
ctx
.
$props
.
init
&&
typeof
ctx
.
$props
.
init
.
setup
===
'
function
'
)
{
ctx
.
$props
.
init
.
setup
(
editor
);
}
}
};
if
(
isTextarea
(
ctx
.
element
))
{
ctx
.
element
.
style
.
visibility
=
''
;
}
getTinymce
().
init
(
finalInit
);
};
export
const
Editor
=
defineComponent
({
props
:
editorProps
,
created
()
{
this
.
elementId
=
this
.
$props
.
id
||
uuid
(
'
tiny-vue
'
);
this
.
inlineEditor
=
(
this
.
$props
.
init
&&
this
.
$props
.
init
.
inline
)
||
this
.
$props
.
inline
;
},
watch
:
{
disabled
()
{
(
this
as
any
).
editor
.
setMode
(
this
.
disabled
?
'
readonly
'
:
'
design
'
);
}
},
mounted
()
{
this
.
element
=
this
.
$el
;
if
(
getTinymce
()
!==
null
)
{
initialise
(
this
)();
}
else
if
(
this
.
element
&&
this
.
element
.
ownerDocument
)
{
const
channel
=
this
.
$props
.
cloudChannel
?
this
.
$props
.
cloudChannel
:
'
5
'
;
const
apiKey
=
this
.
$props
.
apiKey
?
this
.
$props
.
apiKey
:
'
no-api-key
'
;
const
scriptSrc
=
isNullOrUndefined
(
this
.
$props
.
tinymceScriptSrc
)
?
`https://cdn.tiny.cloud/1/
${
apiKey
}
/tinymce/
${
channel
}
/tinymce.min.js`
:
this
.
$props
.
tinymceScriptSrc
;
ScriptLoader
.
load
(
this
.
element
.
ownerDocument
,
scriptSrc
,
initialise
(
this
)
);
}
},
beforeUnmount
()
{
if
(
getTinymce
()
!==
null
)
{
getTinymce
().
remove
(
this
.
editor
);
}
},
render
()
{
return
this
.
inlineEditor
?
renderInline
(
this
.
elementId
,
this
.
$props
.
tagName
)
:
renderIframe
(
this
.
elementId
);
}
})
src/components/Tinymce/src/lib/components/EditorPropTypes.ts
已删除
100644 → 0
浏览文件 @
9c02d8ec
/**
* Copyright (c) 2018-present, Ephox, Inc.
*
* This source code is licensed under the Apache 2 license found in the
* LICENSE file in the root directory of this source tree.
*
*/
export
type
CopyProps
<
T
>
=
{
[
P
in
keyof
T
]:
any
};
export
interface
IPropTypes
{
apiKey
:
string
;
cloudChannel
:
string
;
id
:
string
;
init
:
any
;
initialValue
:
string
;
outputFormat
:
'
html
'
|
'
text
'
;
inline
:
boolean
;
modelEvents
:
string
[]
|
string
;
plugins
:
string
[]
|
string
;
tagName
:
string
;
toolbar
:
string
[]
|
string
;
modelValue
:
string
;
disabled
:
boolean
;
tinymceScriptSrc
:
string
;
}
export
const
editorProps
:
CopyProps
<
IPropTypes
>
=
{
apiKey
:
String
,
cloudChannel
:
String
,
id
:
String
,
init
:
Object
,
initialValue
:
String
,
inline
:
Boolean
,
modelEvents
:
[
String
,
Array
],
plugins
:
[
String
,
Array
],
tagName
:
String
,
toolbar
:
[
String
,
Array
],
modelValue
:
String
,
disabled
:
Boolean
,
tinymceScriptSrc
:
String
,
outputFormat
:
{
type
:
String
,
validator
:
(
prop
:
string
)
=>
prop
===
'
html
'
||
prop
===
'
text
'
},
};
src/components/Tinymce/src/lib/global.d.ts
已删除
100644 → 0
浏览文件 @
9c02d8ec
// Global compile-time constants
declare
var
__DEV__
:
boolean
declare
var
__BROWSER__
:
boolean
declare
var
__CI__
:
boolean
src/components/Tinymce/src/lib/index.ts
已删除
100644 → 0
浏览文件 @
9c02d8ec
import
{
Editor
}
from
'
./components/Editor
'
;
export
default
Editor
;
src/components/Tinymce/src/props.ts
浏览文件 @
f75425d1
import
{
PropType
}
from
'
vue
'
;
export
const
basicProps
=
{
id
:
{
type
:
String
as
PropType
<
string
>
,
default
:
()
=>
{
return
`tinymce-
${
new
Date
().
getTime
()}${(
Math
.
random
()
*
1000
).
toFixed
(
0
)}
`
;
},
},
menubar
:
{
type
:
String
as
PropType
<
string
>
,
default
:
'
file edit insert view format table
'
,
...
...
@@ -15,6 +9,10 @@ export const basicProps = {
type
:
String
as
PropType
<
string
>
,
// default: ''
},
modelValue
:
{
type
:
String
as
PropType
<
string
>
,
// default: ''
},
// 高度
height
:
{
type
:
[
Number
,
String
]
as
PropType
<
string
|
number
>
,
...
...
src/router/menus/modules/demo/charts.ts
浏览文件 @
f75425d1
...
...
@@ -6,23 +6,23 @@ const menu: MenuModule = {
path
:
'
/charts
'
,
children
:
[
{
path
:
'
/
apexChart
'
,
path
:
'
apexChart
'
,
name
:
'
ApexChart
'
,
},
{
path
:
'
/
echarts
'
,
path
:
'
echarts
'
,
name
:
'
Echarts
'
,
children
:
[
{
path
:
'
/
map
'
,
path
:
'
map
'
,
name
:
'
地图
'
,
},
{
path
:
'
/
line
'
,
path
:
'
line
'
,
name
:
'
折线图
'
,
},
{
path
:
'
/
pie
'
,
path
:
'
pie
'
,
name
:
'
饼图
'
,
},
],
...
...
src/router/menus/modules/demo/comp.ts
浏览文件 @
f75425d1
...
...
@@ -6,16 +6,16 @@ const menu: MenuModule = {
path
:
'
/comp
'
,
children
:
[
{
path
:
'
/
basic
'
,
path
:
'
basic
'
,
name
:
'
基础组件
'
,
},
{
path
:
'
/
countTo
'
,
path
:
'
countTo
'
,
name
:
'
数字动画
'
,
},
{
path
:
'
/
scroll
'
,
path
:
'
scroll
'
,
name
:
'
滚动组件
'
,
children
:
[
{
...
...
@@ -33,53 +33,39 @@ const menu: MenuModule = {
],
},
{
path
:
'
/
modal
'
,
path
:
'
modal
'
,
name
:
'
弹窗扩展
'
,
},
{
path
:
'
/
drawer
'
,
path
:
'
drawer
'
,
name
:
'
抽屉扩展
'
,
},
{
path
:
'
/
desc
'
,
path
:
'
desc
'
,
name
:
'
详情组件
'
,
},
{
path
:
'
/
verify
'
,
path
:
'
verify
'
,
name
:
'
验证组件
'
,
children
:
[
{
path
:
'
/
drag
'
,
path
:
'
drag
'
,
name
:
'
拖拽校验
'
,
},
{
path
:
'
/
rotate
'
,
path
:
'
rotate
'
,
name
:
'
图片还原校验
'
,
},
],
},
{
path
:
'
/
qrcode
'
,
path
:
'
qrcode
'
,
name
:
'
二维码组件
'
,
},
{
path
:
'
/
strength-meter
'
,
path
:
'
strength-meter
'
,
name
:
'
密码强度组件
'
,
},
{
path
:
'
/tinymce
'
,
name
:
'
富文本
'
,
children
:
[
{
path
:
'
/index
'
,
name
:
'
基础使用
'
,
},
{
path
:
'
/editor
'
,
name
:
'
嵌入form使用
'
,
},
],
},
],
},
};
...
...
src/router/menus/modules/demo/editor.ts
浏览文件 @
f75425d1
...
...
@@ -6,9 +6,23 @@ const menu: MenuModule = {
path
:
'
/editor
'
,
children
:
[
{
path
:
'
/
markdown
'
,
path
:
'
markdown
'
,
name
:
'
markdown编辑器
'
,
},
{
path
:
'
tinymce
'
,
name
:
'
富文本
'
,
children
:
[
{
path
:
'
index
'
,
name
:
'
基础使用
'
,
},
// {
// path: 'editor',
// name: '嵌入form使用',
// },
],
},
],
},
};
...
...
src/router/menus/modules/demo/excel.ts
浏览文件 @
f75425d1
...
...
@@ -6,23 +6,21 @@ const menu: MenuModule = {
path
:
'
/excel
'
,
children
:
[
{
path
:
'
/
customExport
'
,
path
:
'
customExport
'
,
name
:
'
选择导出格式
'
,
},
{
path
:
'
/
jsonExport
'
,
path
:
'
jsonExport
'
,
name
:
'
JSON数据导出
'
,
},
{
path
:
'
/
arrayExport
'
,
path
:
'
arrayExport
'
,
name
:
'
Array数据导出
'
,
},
{
path
:
'
/
importExcel
'
,
path
:
'
importExcel
'
,
name
:
'
导入
'
,
},
// ],
// },
],
},
};
...
...
src/router/menus/modules/demo/exception.ts
浏览文件 @
f75425d1
...
...
@@ -6,27 +6,27 @@ const menu: MenuModule = {
path
:
'
/exception
'
,
children
:
[
{
path
:
'
/
404
'
,
path
:
'
404
'
,
name
:
'
404
'
,
},
{
path
:
'
/
500
'
,
path
:
'
500
'
,
name
:
'
500
'
,
},
{
path
:
'
/
net-work-error
'
,
path
:
'
net-work-error
'
,
name
:
'
网络错误
'
,
},
{
path
:
'
/
page-time-out
'
,
path
:
'
page-time-out
'
,
name
:
'
页面超时
'
,
},
{
path
:
'
/
not-data
'
,
path
:
'
not-data
'
,
name
:
'
无数据
'
,
},
{
path
:
'
/
error-log
'
,
path
:
'
error-log
'
,
name
:
'
错误日志
'
,
},
],
...
...
src/router/menus/modules/demo/feat.ts
浏览文件 @
f75425d1
...
...
@@ -6,55 +6,55 @@ const menu: MenuModule = {
path
:
'
/feat
'
,
children
:
[
{
path
:
'
/
icon
'
,
path
:
'
icon
'
,
name
:
'
图标
'
,
},
{
path
:
'
/
tabs
'
,
path
:
'
tabs
'
,
name
:
'
标签页操作
'
,
},
{
path
:
'
/
context-menu
'
,
path
:
'
context-menu
'
,
name
:
'
右键菜单
'
,
},
{
path
:
'
/
click-out-side
'
,
path
:
'
click-out-side
'
,
name
:
'
ClickOutSide
'
,
},
{
path
:
'
/
img-preview
'
,
path
:
'
img-preview
'
,
name
:
'
图片预览
'
,
},
{
path
:
'
/
i18n
'
,
path
:
'
i18n
'
,
name
:
'
国际化
'
,
},
{
path
:
'
/
copy
'
,
path
:
'
copy
'
,
name
:
'
剪切板
'
,
},
{
path
:
'
/
msg
'
,
path
:
'
msg
'
,
name
:
'
消息提示
'
,
},
{
path
:
'
/
watermark
'
,
path
:
'
watermark
'
,
name
:
'
水印
'
,
},
{
path
:
'
/
full-screen
'
,
path
:
'
full-screen
'
,
name
:
'
全屏
'
,
},
{
path
:
'
/
testTab
'
,
path
:
'
testTab
'
,
name
:
'
带参Tab
'
,
children
:
[
{
path
:
'
/
id1
'
,
path
:
'
id1
'
,
name
:
'
带参tab1
'
,
},
{
path
:
'
/
id2
'
,
path
:
'
id2
'
,
name
:
'
带参tab2
'
,
},
],
...
...
src/router/menus/modules/demo/form.ts
浏览文件 @
f75425d1
...
...
@@ -6,31 +6,31 @@ const menu: MenuModule = {
name
:
'
Form
'
,
children
:
[
{
path
:
'
/
basic
'
,
path
:
'
basic
'
,
name
:
'
基础表单
'
,
},
{
path
:
'
/
useForm
'
,
path
:
'
useForm
'
,
name
:
'
useForm
'
,
},
{
path
:
'
/
refForm
'
,
path
:
'
refForm
'
,
name
:
'
RefForm
'
,
},
{
path
:
'
/
advancedForm
'
,
path
:
'
advancedForm
'
,
name
:
'
可收缩表单
'
,
},
{
path
:
'
/
ruleForm
'
,
path
:
'
ruleForm
'
,
name
:
'
表单校验
'
,
},
{
path
:
'
/
dynamicForm
'
,
path
:
'
dynamicForm
'
,
name
:
'
动态表单
'
,
},
{
path
:
'
/
customerForm
'
,
path
:
'
customerForm
'
,
name
:
'
自定义组件
'
,
},
],
...
...
src/router/menus/modules/demo/iframe.ts
浏览文件 @
f75425d1
...
...
@@ -6,15 +6,15 @@ const menu: MenuModule = {
path
:
'
/frame
'
,
children
:
[
{
path
:
'
/
antv
'
,
path
:
'
antv
'
,
name
:
'
antVue文档(内嵌)
'
,
},
{
path
:
'
/
doc
'
,
path
:
'
doc
'
,
name
:
'
项目文档(内嵌)
'
,
},
{
path
:
'
/
docExternal
'
,
path
:
'
docExternal
'
,
name
:
'
项目文档(外链)
'
,
},
],
...
...
src/router/menus/modules/demo/permission.ts
浏览文件 @
f75425d1
...
...
@@ -6,37 +6,37 @@ const menu: MenuModule = {
path
:
'
/permission
'
,
children
:
[
{
path
:
'
/
front
'
,
path
:
'
front
'
,
name
:
'
基于前端
'
,
children
:
[
{
path
:
'
/
page
'
,
path
:
'
page
'
,
name
:
'
页面权限
'
,
},
{
path
:
'
/
btn
'
,
path
:
'
btn
'
,
name
:
'
按钮权限
'
,
},
{
path
:
'
/
auth-pageA
'
,
path
:
'
auth-pageA
'
,
name
:
'
权限测试页A
'
,
},
{
path
:
'
/
auth-pageB
'
,
path
:
'
auth-pageB
'
,
name
:
'
权限测试页B
'
,
},
],
},
{
path
:
'
/
back
'
,
path
:
'
back
'
,
name
:
'
基于后台
'
,
children
:
[
{
path
:
'
/
page
'
,
path
:
'
page
'
,
name
:
'
页面权限
'
,
},
{
path
:
'
/
btn
'
,
path
:
'
btn
'
,
name
:
'
按钮权限
'
,
},
],
...
...
src/router/menus/modules/demo/table.ts
浏览文件 @
f75425d1
...
...
@@ -6,59 +6,59 @@ const menu: MenuModule = {
name
:
'
Table
'
,
children
:
[
{
path
:
'
/
basic
'
,
path
:
'
basic
'
,
name
:
'
基础表格
'
,
},
{
path
:
'
/
treeTable
'
,
path
:
'
treeTable
'
,
name
:
'
树形表格
'
,
},
{
path
:
'
/
fetchTable
'
,
path
:
'
fetchTable
'
,
name
:
'
远程加载
'
,
},
{
path
:
'
/
fixedColumn
'
,
path
:
'
fixedColumn
'
,
name
:
'
固定列
'
,
},
{
path
:
'
/
customerCell
'
,
path
:
'
customerCell
'
,
name
:
'
自定义列
'
,
},
{
path
:
'
/
formTable
'
,
path
:
'
formTable
'
,
name
:
'
开启搜索区域
'
,
},
{
path
:
'
/
useTable
'
,
path
:
'
useTable
'
,
name
:
'
UseTable
'
,
},
{
path
:
'
/
refTable
'
,
path
:
'
refTable
'
,
name
:
'
RefTable
'
,
},
{
path
:
'
/
multipleHeader
'
,
path
:
'
multipleHeader
'
,
name
:
'
多级表头
'
,
},
{
path
:
'
/
mergeHeader
'
,
path
:
'
mergeHeader
'
,
name
:
'
合并单元格
'
,
},
{
path
:
'
/
expandTable
'
,
path
:
'
expandTable
'
,
name
:
'
可展开表格
'
,
},
{
path
:
'
/
fixedHeight
'
,
path
:
'
fixedHeight
'
,
name
:
'
定高/头部自定义
'
,
},
{
path
:
'
/
footerTable
'
,
path
:
'
footerTable
'
,
name
:
'
表尾行合计
'
,
},
{
path
:
'
/
editCellTable
'
,
path
:
'
editCellTable
'
,
name
:
'
可编辑单元格
'
,
},
],
...
...
src/router/routes/modules/demo/comp.ts
浏览文件 @
f75425d1
...
...
@@ -136,31 +136,5 @@ export default {
title
:
'
密码强度组件
'
,
},
},
{
path
:
'
/tinymce
'
,
name
:
'
TinymceDemo
'
,
meta
:
{
title
:
'
富文本
'
,
},
redirect
:
'
/comp/tinymce/index
'
,
children
:
[
{
path
:
'
index
'
,
name
:
'
Tinymce
'
,
component
:
()
=>
import
(
'
/@/views/demo/comp/tinymce/index.vue
'
),
meta
:
{
title
:
'
基础使用
'
,
},
},
{
path
:
'
editor
'
,
name
:
'
TinymceEditor
'
,
component
:
()
=>
import
(
'
/@/views/demo/comp/tinymce/Editor.vue
'
),
meta
:
{
title
:
'
嵌入form使用
'
,
},
},
],
},
],
}
as
AppRouteModule
;
src/router/routes/modules/demo/editor.ts
浏览文件 @
f75425d1
...
...
@@ -23,5 +23,32 @@ export default {
title
:
'
markdown编辑器
'
,
},
},
{
path
:
'
/tinymce
'
,
name
:
'
TinymceDemo
'
,
meta
:
{
title
:
'
富文本
'
,
},
redirect
:
'
/editor/tinymce/index
'
,
children
:
[
{
path
:
'
index
'
,
name
:
'
TinymceBasicDemo
'
,
component
:
()
=>
import
(
'
/@/views/demo/editor/tinymce/index.vue
'
),
meta
:
{
title
:
'
基础使用
'
,
},
},
// TODO
// {
// path: 'editor',
// name: 'TinymceFormDemo',
// component: () => import('/@/views/demo/comp/tinymce/Editor.vue'),
// meta: {
// title: '嵌入form使用',
// },
// },
],
},
],
}
as
AppRouteModule
;
src/utils/is.ts
浏览文件 @
f75425d1
...
...
@@ -67,3 +67,7 @@ export const isServer = typeof window === 'undefined';
export
function
isImageDom
(
o
:
Element
)
{
return
o
&&
[
'
IMAGE
'
,
'
IMG
'
].
includes
(
o
.
tagName
);
}
export
const
isTextarea
=
(
element
:
Element
|
null
):
element
is
HTMLTextAreaElement
=>
{
return
element
!==
null
&&
element
.
tagName
.
toLowerCase
()
===
'
textarea
'
;
};
src/utils/uuid.ts
浏览文件 @
f75425d1
...
...
@@ -17,3 +17,11 @@ export function buildUUID(): string {
}
return
uuid
.
replace
(
/-/g
,
''
);
}
let
unique
=
0
;
export
function
snowUuid
(
prefix
:
string
):
string
{
const
time
=
Date
.
now
();
const
random
=
Math
.
floor
(
Math
.
random
()
*
1000000000
);
unique
++
;
return
prefix
+
'
_
'
+
random
+
unique
+
String
(
time
);
}
src/views/demo/
comp
/tinymce/Editor.vue
→
src/views/demo/
editor
/tinymce/Editor.vue
浏览文件 @
f75425d1
...
...
@@ -43,7 +43,7 @@
},
];
export
default
defineComponent
({
components
:
{
BasicForm
,
CollapseContainer
,
Tinymce
},
components
:
{
BasicForm
,
CollapseContainer
},
setup
()
{
const
{
createMessage
}
=
useMessage
();
...
...
src/views/demo/
comp
/tinymce/index.vue
→
src/views/demo/
editor
/tinymce/index.vue
浏览文件 @
f75425d1
<
template
>
<div
class=
"flex p-4"
>
<Tinymce
value=
"Hello, World!"
@
change=
"handleChange"
width=
"100%"
/>
{{
value
}}
<Tinymce
v-model=
"value"
@
change=
"handleChange"
width=
"100%"
/>
</div>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
}
from
'
vue
'
;
import
{
defineComponent
,
ref
}
from
'
vue
'
;
import
{
Tinymce
}
from
'
/@/components/Tinymce/index
'
;
export
default
defineComponent
({
components
:
{
Tinymce
},
setup
()
{
const
value
=
ref
(
'
hello world!
'
);
function
handleChange
(
value
:
string
)
{
console
.
log
(
value
);
}
return
{
handleChange
};
// setTimeout(() => {
// value.value = '1233';
// }, 5000);
return
{
handleChange
,
value
};
},
});
</
script
>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录