mirror of
https://github.com/veops/cmdb.git
synced 2025-08-25 12:39:06 +08:00
222 lines
6.3 KiB
Python
222 lines
6.3 KiB
Python
<template>
|
||
<a-config-provider :locale="antdLocale">
|
||
<div id="app" :class="{ 'ops-fullscreen': isOpsFullScreen, 'ops-only-topmenu': isOpsOnlyTopMenu }">
|
||
<router-view v-if="alive" />
|
||
</div>
|
||
</a-config-provider>
|
||
</template>
|
||
|
||
<script>
|
||
import { mapState, mapActions, mapMutations } from 'vuex'
|
||
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
|
||
import enUS from 'ant-design-vue/lib/locale-provider/en_US'
|
||
import { AppDeviceEnquire } from '@/utils/mixin'
|
||
import { debounce } from './utils/util'
|
||
import { getSystemLanguage } from '@/api/system.js'
|
||
|
||
import { h } from 'snabbdom'
|
||
import { DomEditor, Boot } from '@wangeditor/editor'
|
||
|
||
export default {
|
||
mixins: [AppDeviceEnquire],
|
||
provide() {
|
||
return {
|
||
reload: this.reload,
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
alive: true,
|
||
timer: null,
|
||
}
|
||
},
|
||
computed: {
|
||
...mapState(['locale']),
|
||
antdLocale() {
|
||
if (this.locale === 'zh') {
|
||
return zhCN
|
||
}
|
||
return enUS
|
||
},
|
||
isOpsFullScreen() {
|
||
return ['cmdb_screen'].includes(this.$route.name)
|
||
},
|
||
isOpsOnlyTopMenu() {
|
||
return ['fullscreen_index', 'setting_person', 'notice_center'].includes(this.$route.name)
|
||
},
|
||
},
|
||
created() {
|
||
this.initLanguage()
|
||
this.timer = setInterval(() => {
|
||
this.setTime(new Date().getTime())
|
||
}, 1000)
|
||
},
|
||
mounted() {
|
||
this.$store.dispatch('setWindowSize')
|
||
window.addEventListener(
|
||
'resize',
|
||
debounce(() => {
|
||
this.$store.dispatch('setWindowSize')
|
||
})
|
||
)
|
||
|
||
this.handleEditor()
|
||
},
|
||
beforeDestroy() {
|
||
clearInterval(this.timer)
|
||
},
|
||
methods: {
|
||
...mapActions(['setTime']),
|
||
...mapMutations(['SET_LOCALE']),
|
||
reload() {
|
||
this.alive = false
|
||
this.$nextTick(() => {
|
||
this.alive = true
|
||
})
|
||
},
|
||
async initLanguage() {
|
||
let saveLocale = localStorage.getItem('ops_locale')
|
||
if (!saveLocale) {
|
||
let requestLanguage = ''
|
||
try {
|
||
const languageRes = await getSystemLanguage()
|
||
requestLanguage = languageRes?.language || ''
|
||
} catch (e) {
|
||
console.error('getSystemLanguage error:', e)
|
||
}
|
||
|
||
// request language variable || user local system language
|
||
const userLanguage = requestLanguage || navigator.language || navigator.userLanguage
|
||
if (userLanguage.includes('zh')) {
|
||
saveLocale = 'zh'
|
||
} else {
|
||
saveLocale = 'en'
|
||
}
|
||
}
|
||
this.SET_LOCALE(saveLocale)
|
||
this.$i18n.locale = saveLocale
|
||
},
|
||
|
||
handleEditor() {
|
||
// register custom rich text element: attachment
|
||
function withAttachment(editor) {
|
||
const { isInline, isVoid } = editor
|
||
const newEditor = editor
|
||
|
||
newEditor.isInline = (elem) => {
|
||
const type = DomEditor.getNodeType(elem)
|
||
if (type === 'attachment') return true // For type: attachment, set to inline
|
||
return isInline(elem)
|
||
}
|
||
|
||
newEditor.isVoid = (elem) => {
|
||
const type = DomEditor.getNodeType(elem)
|
||
if (type === 'attachment') return true // For type: attachment ,set to void
|
||
return isVoid(elem)
|
||
}
|
||
|
||
return newEditor // Must return, important!!!
|
||
}
|
||
Boot.registerPlugin(withAttachment)
|
||
/**
|
||
* Render "attachment" element in editor
|
||
* @param elem Attachment element
|
||
* @param children Child nodes (ignored for void elements)
|
||
* @param editor Editor instance
|
||
* @returns vnode (generated by snabbdom's h function)
|
||
*/
|
||
function renderAttachment(elem, children, editor) {
|
||
const { attachmentLabel = '', attachmentValue = '' } = elem
|
||
|
||
const attachVnode = h(
|
||
// HTML tag
|
||
'span',
|
||
// HTML attr, style, event
|
||
{
|
||
props: { contentEditable: false },
|
||
style: {
|
||
display: 'inline-block',
|
||
margin: '0 3px',
|
||
padding: '0 3px',
|
||
backgroundColor: '#e6f7ff',
|
||
border: '1px solid #91d5ff',
|
||
borderRadius: '2px',
|
||
color: '#1890ff',
|
||
},
|
||
on: {
|
||
click() {
|
||
console.log('clicked', attachmentValue)
|
||
}
|
||
},
|
||
},
|
||
// child node
|
||
[attachmentLabel]
|
||
)
|
||
|
||
return attachVnode
|
||
}
|
||
const renderElemConf = {
|
||
type: 'attachment',
|
||
renderElem: renderAttachment,
|
||
}
|
||
Boot.registerRenderElem(renderElemConf)
|
||
|
||
/**
|
||
* Generate HTML for "attachment" element
|
||
* @param elem Attachment element
|
||
* @param childrenHtml Child HTML (ignored for void elements)
|
||
* @returns HTML string
|
||
*/
|
||
function attachmentToHtml(elem, childrenHtml) {
|
||
// Getting data for attached elements
|
||
const { attachmentValue = '', attachmentLabel = '' } = elem
|
||
|
||
// generate HTML
|
||
const html = `<span data-w-e-type="attachment" data-w-e-is-void data-w-e-is-inline data-attachmentValue="${attachmentValue}" data-attachmentLabel="${attachmentLabel}">${attachmentLabel}</span>`
|
||
|
||
return html
|
||
}
|
||
const elemToHtmlConf = {
|
||
type: 'attachment',
|
||
elemToHtml: attachmentToHtml,
|
||
}
|
||
Boot.registerElemToHtml(elemToHtmlConf)
|
||
|
||
/**
|
||
* Parse HTML to generate "attachment" element
|
||
* @param domElem DOM element
|
||
* @param children Children
|
||
* @param editor Editor instance
|
||
* @returns Attachment element
|
||
*/
|
||
function parseAttachmentHtml(domElem, children, editor) {
|
||
// Getting “attachment” information from DOM element
|
||
const attachmentValue = domElem.getAttribute('data-attachmentValue') || ''
|
||
const attachmentLabel = domElem.getAttribute('data-attachmentLabel') || ''
|
||
|
||
const myResume = {
|
||
type: 'attachment',
|
||
attachmentValue,
|
||
attachmentLabel,
|
||
children: [{ text: '' }], // The void node must have children with an empty string in it, important!!!!
|
||
}
|
||
|
||
return myResume
|
||
}
|
||
const parseHtmlConf = {
|
||
selector: 'span[data-w-e-type="attachment"]', // CSS selector to match specific HTML tags
|
||
parseElemHtml: parseAttachmentHtml,
|
||
}
|
||
Boot.registerParseElemHtml(parseHtmlConf)
|
||
}
|
||
},
|
||
}
|
||
</script>
|
||
<style lang="less">
|
||
@import './style/index.less';
|
||
|
||
#app {
|
||
height: 100%;
|
||
}
|
||
</style>
|