1、打开 vue-element-admin官方文档 拉取vue-admin-template(用于二次开发模板)vue-element-admin(用与相关组件的查看与使用),如图:
2、使用ide打开vue-element-admin(注意拉去时应当拉取i18n
分支,该分支为中文版),如图:
3、打开vue-admin-template,在src目录下的main.js里将
import locale from 'element-ui/lib/locale/lang/en' 修改为:
import locale from 'element-ui/lib/locale/lang/zh-CN'
这里会将各类组件修改为中文版的,不过侧边栏的菜单栏并没有修改为中文版的,
在src目录下的router中的index.js手动将左侧菜单栏修改为中文的名称,如图:
4、在.env.development文件中编写一个全局变量:
BACKGROUND_APPLICATION_URL = 'http://localhost:8080'
如图:
5、加入图形验证码:
1)在views的login里的index.js里写入如下代码:
<div class="verifybox">
<input v-model="loginForm.verifycode" type="text" placeholder="请输入验证码" class="verifyinput" @keyup.enter.native="handleLogin">
<!-- 随机验证码 -->
<img class="identifybox" src="../../assets/code/code.jpg" onclick="this.src=this.src+'?'">
</div>
如图:
2)加入样式:
// 验证码
.verifybox {
width: 450px;
height: 60px;
display: inline-block;
text-align: right;
}
.verifyinput {
width: 116px;
height: 36px;
vertical-align: middle;
background: transparent;
border: 0px;
-webkit-appearance: none;
border-radius: 0px;
color: #fff;
height: 47px;
caret-color: #fff;
}
.identifybox {
width: 116px;
height: 36px;
vertical-align: middle;
margin-left: 10px;
}
如图:
3)调整请求的参数,最后显示的结果,如图:
6、在vue.config.js中编写跨域代理
proxy: {
'/dev-api': {
target: process.env.BACKGROUND_APPLICATION_URL,
changeOrigin: true,
pathRewrite: {
'^/dev-api': ''
}
}
}
如图:
2022-1-21:
后台页面添加tagview:
参考文章:https://www.cnblogs.com/flypig666/p/11854538.html?tdsourcetag=s_pctim_aiomsg
2022-05-29:
start:
tinymce采用cdn.jsdelivr.net cdn经常挂怎么办?
end
2022-06-01:
start:
打包命令:npm run build:prod
执行命令:npm run dev
发现一个bug:
当点击编辑的时候,会发现数据无法反显,解决方案如下:
代码如下:
<template>
<div :class="{fullscreen:fullscreen}" class="tinymce-container" :style="{width:containerWidth}">
<textarea :id="tinymceId" class="tinymce-textarea"></textarea>
<div class="editor-custom-btn-container">
<editorImage color="#1890ff" class="editor-upload-btn" @successCBK="imageSuccessCBK" />
</div>
</div>
</template>
<script>
/**
* docs:
* https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce
*/
import editorImage from './components/EditorImage'
import plugins from './plugins'
import toolbar from './toolbar'
import load from './dynamicLoadScript'
// why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
const tinymceCDN = 'https://cdn.staticfile.org/tinymce/4.9.3/tinymce.min.js'
export default {
name: 'Tinymce',
components: { editorImage },
props: {
id: {
type: String,
default: function() {
return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
}
},
value: {
type: String,
default: ''
},
dValue: {
type: String,
default: ''
},
toolbar: {
type: Array,
required: false,
default() {
return []
}
},
menubar: {
type: String,
default: 'file edit insert view format table'
},
height: {
type: [Number, String],
required: false,
default: 360
},
width: {
type: [Number, String],
required: false,
default: 'auto'
}
},
data() {
return {
hasChange: false,
hasInit: false,
tinymceId: this.id,
fullscreen: false,
languageTypeList: {
'en': 'en',
'zh': 'zh_CN',
'es': 'es_MX',
'ja': 'ja'
}
}
},
computed: {
language() {
return this.languageTypeList[this.$store.getters.language]
},
containerWidth() {
const width = this.width
if (/^[\d]+(\.[\d]+)?$/.test(width)) { // matches `100`, `'100'`
return `${width}px`
}
return width
}
},
watch: {
value(val) {
if (!this.hasChange && this.hasInit) {
this.$nextTick(() =>
window.tinymce.get(this.tinymceId).setContent(val || ''))
}
},
dValue(val) {
if (this.hasChange && this.hasInit && !window.tinymce.get(this.tinymceId).getContent()) {
this.$nextTick(() =>
window.tinymce.get(this.tinymceId).setContent(val || ''))
}
},
language() {
this.destroyTinymce()
this.$nextTick(() => this.initTinymce())
}
},
mounted() {
this.init()
},
activated() {
if (window.tinymce) {
this.initTinymce()
}
},
deactivated() {
this.destroyTinymce()
},
destroyed() {
this.destroyTinymce()
},
methods: {
init() {
// dynamic load tinymce from cdn
load(tinymceCDN, (err) => {
if (err) {
this.$message.error(err.message)
return
}
this.initTinymce()
})
},
initTinymce() {
const _this = this
window.tinymce.init({
language: 'zh_CN',
language_url: require( './zh_CN.js'),
selector: `#${this.tinymceId}`,
height: this.height,
body_class: 'panel-body ',
object_resizing: false,
toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
menubar: this.menubar,
plugins: plugins,
end_container_on_empty_block: true,
powerpaste_word_import: 'clean',
code_dialog_height: 450,
code_dialog_width: 1000,
advlist_bullet_styles: 'square',
advlist_number_styles: 'default',
imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
default_link_target: '_blank',
link_title: false,
nonbreaking_force_tab: true, // inserting nonbreaking space need Nonbreaking Space Plugin
init_instance_callback: editor => {
if (_this.value) {
editor.setContent(_this.value)
}
_this.hasInit = true
editor.on('NodeChange Change KeyUp SetContent', () => {
this.hasChange = true
this.$emit('input', editor.getContent())
})
},
setup(editor) {
editor.on('FullscreenStateChanged', (e) => {
_this.fullscreen = e.state
})
},
// it will try to keep these URLs intact
// https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@convert_urls/
// https://stackoverflow.com/questions/5196205/disable-tinymce-absolute-to-relative-url-conversions
convert_urls: false
// 整合七牛上传
// images_dataimg_filter(img) {
// setTimeout(() => {
// const $image = $(img);
// $image.removeAttr('width');
// $image.removeAttr('height');
// if ($image[0].height && $image[0].width) {
// $image.attr('data-wscntype', 'image');
// $image.attr('data-wscnh', $image[0].height);
// $image.attr('data-wscnw', $image[0].width);
// $image.addClass('wscnph');
// }
// }, 0);
// return img
// },
// images_upload_handler(blobInfo, success, failure, progress) {
// progress(0);
// const token = _this.$store.getters.token;
// getToken(token).then(response => {
// const url = response.data.qiniu_url;
// const formData = new FormData();
// formData.append('token', response.data.qiniu_token);
// formData.append('key', response.data.qiniu_key);
// formData.append('file', blobInfo.blob(), url);
// upload(formData).then(() => {
// success(url);
// progress(100);
// })
// }).catch(err => {
// failure('出现未知问题,刷新页面,或者联系程序员')
// console.log(err);
// });
// },
})
},
destroyTinymce() {
const tinymce = window.tinymce.get(this.tinymceId)
if (this.fullscreen) {
tinymce.execCommand('mceFullScreen')
}
if (tinymce) {
tinymce.destroy()
}
},
setContent(value) {
window.tinymce.get(this.tinymceId).setContent(value)
},
getContent() {
window.tinymce.get(this.tinymceId).getContent()
},
imageSuccessCBK(arr) {
arr.forEach(v => window.tinymce.get(this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`))
}
}
}
</script>
<style lang="scss" scoped>
.tinymce-container {
position: relative;
line-height: normal;
}
.tinymce-container {
::v-deep {
.mce-fullscreen {
z-index: 10000;
}
}
}
.tinymce-textarea {
visibility: hidden;
z-index: -1;
}
.editor-custom-btn-container {
position: absolute;
right: 4px;
top: 4px;
/*z-index: 2005;*/
}
.fullscreen .editor-custom-btn-container {
z-index: 10000;
position: fixed;
}
.editor-upload-btn {
display: inline-block;
}
</style>
end
2022-08-04
start:
end
2023-09-07 start
end
2023-09-08 start:
vue-cli 关闭 Uncaught error 的全屏提示
end
2023-10-08 start:
富文本编辑器的展示:安装 | v-md-editor (gitee.io)
import { createApp } from 'vue'
import './style.css'
import 'uno.css'
import App from './App.vue'
// 预览组件以及样式
// @ts-ignore
import VMdPreview from '@kangc/v-md-editor/lib/preview';
import '@kangc/v-md-editor/lib/style/preview.css';
// VuePress主题以及样式(这里也可以选择github主题)
// @ts-ignore
import vuepressTheme from '@kangc/v-md-editor/lib/theme/vuepress.js';
import '@kangc/v-md-editor/lib/theme/style/vuepress.css';
// Prism
import Prism from 'prismjs';
// 代码高亮
import 'prismjs/components/prism-json';
// 选择使用主题
VMdPreview.use(vuepressTheme, {
Prism,
});
createApp(App).use(VMdPreview).mount('#app')
end