Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
basic-vue-admin
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Basic
basic-vue-admin
Commits
3ad1a4f5
提交
3ad1a4f5
authored
1月 11, 2021
作者:
vben
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(tinymce): add image upload #170
上级
18ad1bcc
显示空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
131 行增加
和
35 行删除
+131
-35
CHANGELOG.zh_CN.md
CHANGELOG.zh_CN.md
+2
-0
Editor.vue
src/components/Tinymce/src/Editor.vue
+44
-24
ImgUpload.vue
src/components/Tinymce/src/ImgUpload.vue
+72
-0
props.ts
src/components/Tinymce/src/props.ts
+4
-8
index.vue
...layouts/default/header/components/user-dropdown/index.vue
+7
-2
index.vue
src/layouts/default/header/index.vue
+0
-1
upload.ts
src/locales/lang/en/component/upload.ts
+1
-0
upload.ts
src/locales/lang/zh_CN/component/upload.ts
+1
-0
没有找到文件。
CHANGELOG.zh_CN.md
浏览文件 @
3ad1a4f5
...
@@ -16,6 +16,7 @@
...
@@ -16,6 +16,7 @@
-
新增
`PageWrapper`
组件。并应用于示例页面
-
新增
`PageWrapper`
组件。并应用于示例页面
-
新增标签页折叠功能
-
新增标签页折叠功能
-
兼容旧版浏览器
-
兼容旧版浏览器
-
tinymce 新增图片上传·
### 🐛 Bug Fixes
### 🐛 Bug Fixes
...
@@ -24,6 +25,7 @@
...
@@ -24,6 +25,7 @@
-
修复表格内存溢出问题
-
修复表格内存溢出问题
-
修复
`layout`
收缩展开功能在分割模式下失效
-
修复
`layout`
收缩展开功能在分割模式下失效
-
修复 modal 高度计算错误
-
修复 modal 高度计算错误
-
修复文件上传错误
### 🎫 Chores
### 🎫 Chores
...
...
src/components/Tinymce/src/Editor.vue
浏览文件 @
3ad1a4f5
<
template
>
<
template
>
<div
class=
"tinymce-container"
:style=
"
{ width: containerWidth }">
<div
:class=
"prefixCls"
:style=
"
{ width: containerWidth }">
<ImgUpload
@
uploading=
"handleImageUploading"
@
done=
"handleDone"
v-if=
"showImageUpload"
v-show=
"editorRef"
/>
<textarea
:id=
"tinymceId"
ref=
"elRef"
:style=
"
{ visibility: 'hidden' }">
</textarea>
<textarea
:id=
"tinymceId"
ref=
"elRef"
:style=
"
{ visibility: 'hidden' }">
</textarea>
</div>
</div>
</
template
>
</
template
>
...
@@ -24,6 +30,8 @@
...
@@ -24,6 +30,8 @@
import
{
bindHandlers
}
from
'./helper'
;
import
{
bindHandlers
}
from
'./helper'
;
import
lineHeight
from
'./lineHeight'
;
import
lineHeight
from
'./lineHeight'
;
import
{
onMountedOrActivated
}
from
'/@/hooks/core/onMountedOrActivated'
;
import
{
onMountedOrActivated
}
from
'/@/hooks/core/onMountedOrActivated'
;
import
ImgUpload
from
'./ImgUpload.vue'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
const
CDN_URL
=
'https://cdn.bootcdn.net/ajax/libs/tinymce/5.5.1'
;
const
CDN_URL
=
'https://cdn.bootcdn.net/ajax/libs/tinymce/5.5.1'
;
...
@@ -33,12 +41,15 @@
...
@@ -33,12 +41,15 @@
name
:
'Tinymce'
,
name
:
'Tinymce'
,
inheritAttrs
:
false
,
inheritAttrs
:
false
,
props
:
basicProps
,
props
:
basicProps
,
components
:
{
ImgUpload
},
emits
:
[
'change'
,
'update:modelValue'
],
emits
:
[
'change'
,
'update:modelValue'
],
setup
(
props
,
{
emit
,
attrs
})
{
setup
(
props
,
{
emit
,
attrs
})
{
const
editorRef
=
ref
<
any
>
(
null
);
const
editorRef
=
ref
<
any
>
(
null
);
const
tinymceId
=
ref
<
string
>
(
snowUuid
(
'tiny-vue'
));
const
tinymceId
=
ref
<
string
>
(
snowUuid
(
'tiny-vue'
));
const
elRef
=
ref
<
Nullable
<
HTMLElement
>>
(
null
);
const
elRef
=
ref
<
Nullable
<
HTMLElement
>>
(
null
);
const
{
prefixCls
}
=
useDesign
(
'tinymce-container'
);
const
tinymceContent
=
computed
(()
=>
{
const
tinymceContent
=
computed
(()
=>
{
return
props
.
modelValue
;
return
props
.
modelValue
;
});
});
...
@@ -140,7 +151,7 @@
...
@@ -140,7 +151,7 @@
bindHandlers
(
e
,
attrs
,
unref
(
editorRef
));
bindHandlers
(
e
,
attrs
,
unref
(
editorRef
));
}
}
function
setValue
(
editor
:
any
,
val
:
string
,
prevVal
:
string
)
{
function
setValue
(
editor
:
Recordable
,
val
:
string
,
prevVal
?
:
string
)
{
if
(
if
(
editor
&&
editor
&&
typeof
val
===
'string'
&&
typeof
val
===
'string'
&&
...
@@ -179,45 +190,54 @@
...
@@ -179,45 +190,54 @@
});
});
}
}
function
handleImageUploading
(
name
:
string
)
{
const
editor
=
unref
(
editorRef
);
if
(
!
editor
)
return
;
const
content
=
editor
?.
getContent
()
??
''
;
setValue
(
editor
,
`
${
content
}
\n
${
getImgName
(
name
)}
`
);
}
function
handleDone
(
name
:
string
,
url
:
string
)
{
const
editor
=
unref
(
editorRef
);
if
(
!
editor
)
return
;
const
content
=
editor
?.
getContent
()
??
''
;
const
val
=
content
?.
replace
(
getImgName
(
name
),
`<img src="
${
url
}
"/>`
)
??
''
;
setValue
(
editor
,
val
);
}
function
getImgName
(
name
:
string
)
{
return
`[uploading:
${
name
}
]`
;
}
return
{
return
{
prefixCls
,
containerWidth
,
containerWidth
,
initOptions
,
initOptions
,
tinymceContent
,
tinymceContent
,
tinymceScriptSrc
,
tinymceScriptSrc
,
elRef
,
elRef
,
tinymceId
,
tinymceId
,
handleImageUploading
,
handleDone
,
editorRef
,
};
};
},
},
});
});
</
script
>
</
script
>
<
style
lang=
"less"
scoped
>
<
style
lang=
"less"
scoped
></
style
>
.tinymce-container
{
position
:
relative
;
line-height
:
normal
;
.mce-fullscreen
{
z-index
:
10000
;
}
}
.editor-custom-btn-container
{
position
:
absolute
;
top
:
6px
;
right
:
6px
;
&.fullscreen
{
<
style
lang=
"less"
>
position
:
fixed
;
@prefix-cls
:
~
'@{namespace}-tinymce-container'
;
z-index
:
10000
;
}
}
.
editor-upload-btn
{
.
@
{
prefix-cls
}
{
display
:
inline-block
;
position
:
relative
;
}
line-height
:
normal
;
textarea
{
textarea
{
z-index
:
-1
;
z-index
:
-1
;
visibility
:
hidden
;
visibility
:
hidden
;
}
}
}
</
style
>
</
style
>
src/components/Tinymce/src/ImgUpload.vue
0 → 100644
浏览文件 @
3ad1a4f5
<
template
>
<div
:class=
"prefixCls"
>
<Upload
name=
"file"
multiple
@
change=
"handleChange"
:action=
"uploadUrl"
:showUploadList=
"false"
accept=
".jpg,.jpeg,.gif,.png,.webp"
>
<a-button
type=
"primary"
>
{{
t
(
'component.upload.imgUpload'
)
}}
</a-button>
</Upload>
</div>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
}
from
'vue'
;
import
{
Upload
}
from
'ant-design-vue'
;
import
{
InboxOutlined
}
from
'@ant-design/icons-vue'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
useGlobSetting
}
from
'/@/hooks/setting'
;
import
{
useI18n
}
from
'/@/hooks/web/useI18n'
;
export
default
defineComponent
({
name
:
'TinymceImageUpload'
,
components
:
{
Upload
,
InboxOutlined
},
emits
:
[
'uploading'
,
'done'
,
'error'
],
setup
(
_
,
{
emit
})
{
let
uploading
=
false
;
const
{
uploadUrl
}
=
useGlobSetting
();
const
{
t
}
=
useI18n
();
const
{
prefixCls
}
=
useDesign
(
'tinymce-img-upload'
);
function
handleChange
(
info
:
Recordable
)
{
const
file
=
info
.
file
;
const
status
=
file
?.
status
;
const
url
=
file
?.
response
?.
url
;
const
name
=
file
?.
name
;
if
(
status
===
'uploading'
)
{
if
(
!
uploading
)
{
emit
(
'uploading'
,
name
);
uploading
=
true
;
}
}
else
if
(
status
===
'done'
)
{
emit
(
'done'
,
name
,
url
);
uploading
=
false
;
}
else
if
(
status
===
'error'
)
{
emit
(
'error'
);
uploading
=
false
;
}
}
return
{
prefixCls
,
handleChange
,
uploadUrl
,
t
,
};
},
});
</
script
>
<
style
lang=
"less"
scoped
>
@prefix-cls
:
~
'@{namespace}-tinymce-img-upload'
;
.@
{
prefix-cls
}
{
position
:
absolute
;
top
:
4px
;
right
:
10px
;
z-index
:
20
;
}
</
style
>
src/components/Tinymce/src/props.ts
浏览文件 @
3ad1a4f5
import
{
PropType
}
from
'vue'
;
import
{
PropType
}
from
'vue'
;
import
{
propTypes
}
from
'/@/utils/propTypes'
;
export
const
basicProps
=
{
export
const
basicProps
=
{
options
:
{
options
:
{
type
:
Object
as
PropType
<
any
>
,
type
:
Object
as
PropType
<
any
>
,
default
:
{},
default
:
{},
},
},
value
:
{
value
:
propTypes
.
string
,
type
:
String
as
PropType
<
string
>
,
modelValue
:
propTypes
.
string
,
// default: ''
},
modelValue
:
{
type
:
String
as
PropType
<
string
>
,
// default: ''
},
// 高度
// 高度
height
:
{
height
:
{
type
:
[
Number
,
String
]
as
PropType
<
string
|
number
>
,
type
:
[
Number
,
String
]
as
PropType
<
string
|
number
>
,
...
@@ -26,4 +21,5 @@ export const basicProps = {
...
@@ -26,4 +21,5 @@ export const basicProps = {
required
:
false
,
required
:
false
,
default
:
'auto'
,
default
:
'auto'
,
},
},
showImageUpload
:
propTypes
.
bool
.
def
(
true
),
};
};
src/layouts/default/header/components/user-dropdown/index.vue
浏览文件 @
3ad1a4f5
...
@@ -9,8 +9,13 @@
...
@@ -9,8 +9,13 @@
<template
#
overlay
>
<template
#
overlay
>
<Menu
@
click=
"handleMenuClick"
>
<Menu
@
click=
"handleMenuClick"
>
<MenuItem
key=
"doc"
:text=
"t('layout.header.dropdownItemDoc')"
icon=
"gg:loadbar-doc"
/>
<MenuItem
<MenuDivider
v-if=
"getShowDoc"
/>
key=
"doc"
:text=
"t('layout.header.dropdownItemDoc')"
icon=
"gg:loadbar-doc"
v-if=
"getShowDoc"
/>
<MenuDivider
/>
<MenuItem
<MenuItem
key=
"loginOut"
key=
"loginOut"
:text=
"t('layout.header.dropdownItemLoginOut')"
:text=
"t('layout.header.dropdownItemLoginOut')"
...
...
src/layouts/default/header/index.vue
浏览文件 @
3ad1a4f5
...
@@ -84,7 +84,6 @@
...
@@ -84,7 +84,6 @@
}
from
'./components'
;
}
from
'./components'
;
import
{
useAppInject
}
from
'/@/hooks/web/useAppInject'
;
import
{
useAppInject
}
from
'/@/hooks/web/useAppInject'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
createAsyncComponent
}
from
'/@/utils/factory/createAsyncComponent'
;
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'LayoutHeader'
,
name
:
'LayoutHeader'
,
...
...
src/locales/lang/en/component/upload.ts
浏览文件 @
3ad1a4f5
export
default
{
export
default
{
save
:
'Save'
,
save
:
'Save'
,
upload
:
'Upload'
,
upload
:
'Upload'
,
imgUpload
:
'ImageUpload'
,
uploaded
:
'Uploaded'
,
uploaded
:
'Uploaded'
,
operating
:
'Operating'
,
operating
:
'Operating'
,
...
...
src/locales/lang/zh_CN/component/upload.ts
浏览文件 @
3ad1a4f5
export
default
{
export
default
{
save
:
'保存'
,
save
:
'保存'
,
upload
:
'上传'
,
upload
:
'上传'
,
imgUpload
:
'图片上传'
,
uploaded
:
'已上传'
,
uploaded
:
'已上传'
,
operating
:
'操作'
,
operating
:
'操作'
,
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论