diff --git a/build/config.js b/build/config.js index d6c7ad3..eeb1c1d 100644 --- a/build/config.js +++ b/build/config.js @@ -41,7 +41,7 @@ module.exports = { }, dev: { env: devEnv, - port: 8002, + port: 8003, proxyTable: {} } } diff --git a/example/components/changelog/readme.md b/example/components/changelog/readme.md index ee07372..2a0137d 100644 --- a/example/components/changelog/readme.md +++ b/example/components/changelog/readme.md @@ -8,6 +8,27 @@
基本使用
-transfer
-datetime
-datetimerange
-daterange
-快捷方式 daterange
-快捷方式 datetime
-快捷方式 datetime(快捷方式关闭弹层)
-快捷方式 datetimerange
-快捷方式 datetimerange(快捷方式关闭弹层)
-不可选日期1
- -不可选日期2
- -format1
-自定义样式
-选择多个日期
- -禁用
-只读
-自定义出现位置
-placeholder
-placeholder
-datetimerange
-快捷选择区域插槽
-年选择器
-月选择器
-
{{ (curValue && curValue.length) || 0 }}
*/
import emitter from '@/mixins/emitter'
-import locale from 'bk-magic-vue/lib/locale'
import { getStyle } from '@/utils/dom'
+import locale from 'bk-magic-vue/lib/locale'
// const toString = Object.prototype.toString
@@ -267,6 +267,10 @@ export default {
showClearOnlyHover: {
type: Boolean,
default: false
+ },
+ allowNumberPaste: {
+ type: Boolean,
+ default: false
}
},
data () {
@@ -587,11 +591,14 @@ export default {
const keyCode = event.keyCode
const target = event.currentTarget
const value = target.value
+ const isPaste = (event.ctrlKey || event.metaKey) && keyCode === 86
if (this.inputType === 'number') {
- // 键盘按下不允许的按钮
- if (this.validKeyCodeList.indexOf(keyCode) < 0
- || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey
+ // 非粘贴且键盘按下不允许的按钮
+ if (
+ !(this.allowNumberPaste && isPaste)
+ && (this.validKeyCodeList.indexOf(keyCode) < 0
+ || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey)
) {
event.stopPropagation()
event.preventDefault()
diff --git a/src/components/message/advanced.js b/src/components/message/advanced.js
index 584cef0..b08bf46 100644
--- a/src/components/message/advanced.js
+++ b/src/components/message/advanced.js
@@ -96,12 +96,18 @@ export default {
copyStatusTimer: null
}
},
+ mounted () {
+ this.addMouseKeyEvent()
+ },
+ beforeDestroy () {
+ this.addMouseKeyEvent(true)
+ },
computed: {
defActionList () {
return {
[IMessageActionType.ASSISTANT]: {
id: IMessageActionType.ASSISTANT,
- icon: (h) => h('span', { class: 'bk-icon icon-weixin-pro' }),
+ icon: (h) => h('span', { class: 'bk-icon icon-assistant' }),
text: () => this.t('bk.message.assistant'),
onClick: (e) => this.handleHeplerClick(e)
},
@@ -168,9 +174,32 @@ export default {
}
return sortActionIdList.map(id => this.defActionList[id])
+ },
+ isDetailShow () {
+ return this.toolOperation.isDetailShow
}
},
methods: {
+ addMouseKeyEvent (remove = false) {
+ if (remove) {
+ document.removeEventListener('keydown', this.handleMouseKeyEvent)
+ return
+ }
+
+ document.addEventListener('keydown', this.handleMouseKeyEvent)
+ },
+ handleMouseKeyEvent (e) {
+ const { ctrlKey, altKey, keyCode } = e
+ const { isFix } = this.toolOperation
+ if (ctrlKey && altKey && keyCode === 80) {
+ isFix && this.fixMesage(e, false)
+ return
+ }
+
+ if (altKey && keyCode === 80) {
+ !isFix && this.fixMesage(e, true)
+ }
+ },
handleCloseClick () {
this.$emit('close')
},
@@ -180,22 +209,34 @@ export default {
}
},
setDetailsShow (e, isShow) {
- this.toolOperation.isDetailShow = isShow !== undefined ? isShow : !this.toolOperation.isDetailShow
- this.fixMesage(e, this.toolOperation.isDetailShow)
+ this.toolOperation.isDetailShow = isShow !== undefined ? isShow : !this.isDetailShow
+ this.$emit('message-show', this.isDetailShow)
+ this.fixMesage(e, this.isDetailShow)
if (
- this.toolOperation.isDetailShow
+ this.isDetailShow
&& typeof this.message === 'object'
- && (this.message.type === MessageContentType.JSON || !this.message.type)
+ && !this.message.hasOwnProperty('componentOptions')
) {
- const targetJson = this.parseJson(this.message.details)
- const formatter = new JSONFormatter(targetJson)
- setTimeout(() => {
- if (this.$refs.refJsonContent) {
- this.$refs.refJsonContent.innerHTML = ''
- this.$refs.refJsonContent.append(formatter.render())
- }
- })
+ if (this.message.type === MessageContentType.JSON || !this.message.type) {
+ const targetJson = this.parseJson(this.message.details)
+ const formatter = new JSONFormatter(targetJson)
+ setTimeout(() => {
+ if (this.$refs.refJsonContent) {
+ this.$refs.refJsonContent.innerHTML = ''
+ this.$refs.refJsonContent.append(formatter.render())
+ }
+
+ this.copyMessage()
+ })
+ }
+
+ if (this.message.type === MessageContentType.KEY_VALUE) {
+ setTimeout(() => {
+ this.copyMessage()
+ this.setCopyValueItems()
+ })
+ }
}
},
fixMesage (e, isFix) {
@@ -214,34 +255,62 @@ export default {
return targetJson
},
- copyMessage () {
- if (this.isInstallClipboardJS) {
- return
- }
-
- const copyInstance = new ClipboardJS(this.$refs.refCopyMsgDiv, {
- text: () => this.message.details
- });
+ setCopyValueItems () {
+ const copyInstance = new ClipboardJS(this.$refs.refJsonContent.querySelectorAll('span.copy-value'), {
+ text: trigger => trigger.innerHTML
+ })
+ this.registerCopyCallback(copyInstance)
+ },
+ registerCopyCallback (copyInstance, complete) {
['success', 'error'].forEach((theme) => {
- copyInstance.on(theme, () => {
+ copyInstance.on(theme, (e) => {
+ console.log('registerCopyCallback theme', theme)
const target = this.$refs.refCopyStatus
this.copyStatus = theme
- if (target) {
- target.classList.remove(...['success', 'error', 'is-hidden'])
- target.classList.add(...[theme, 'is-show'])
- this.copyStatusTimer && clearTimeout(this.copyStatusTimer)
- this.copyStatusTimer = setTimeout(() => {
- target.classList.remove(...['is-show'])
- target.classList.add(...['is-hidden'])
- }, 2000)
- }
- })
- this.isInstallClipboardJS = true
- setTimeout(() => {
- this.$refs.refCopyMsgDiv.click()
+ this.$nextTick(() => {
+ if (target) {
+ const { offsetLeft, offsetWidth, offsetTop } = e.trigger
+ target.classList.remove(...['success', 'error', 'is-hidden'])
+ target.classList.add(...[theme, 'is-show'])
+ const msgTree = e.trigger.closest('.message-tree')
+ const msgTreeScrollTop = msgTree ? msgTree.scrollTop : 0
+ const transX = offsetLeft + offsetWidth / 2 - 41
+ const transY = offsetTop - msgTreeScrollTop - 40
+ target.style.setProperty('transform', `translate(${transX}px, ${transY}px`)
+
+ this.copyStatusTimer && clearTimeout(this.copyStatusTimer)
+ this.copyStatusTimer = setTimeout(() => {
+ target.classList.remove(...['is-show'])
+ target.classList.add(...['is-hidden'])
+ }, 2000)
+ }
+
+ if (typeof complete === 'function') {
+ complete()
+ }
+ })
})
})
+ },
+ parseToString (value) {
+ let targetStr = value
+ if (typeof value === 'object') {
+ try {
+ targetStr = JSON.stringify(value)
+ } catch (e) {
+ console.error(`JSON.stringify Error: ${e}`)
+ }
+ }
+
+ return targetStr
+ },
+ copyMessage () {
+ const copyInstance = new ClipboardJS(this.$refs.refCopyMsgDiv, {
+ text: () => this.parseToString(this.message.details)
+ })
+
+ this.registerCopyCallback(copyInstance)
}
},
render (h) {
@@ -252,7 +321,7 @@ export default {
return keys.map(key => (
h('div', { class: 'message-row' }, [
h('label', key),
- target[key]
+ h('span', { class: 'copy-value' }, target[key])
])
))
}
@@ -334,15 +403,15 @@ export default {
]),
h('div', { class: 'tools' }, [renderMessageActions()])
]),
- this.toolOperation.isDetailShow
+ this.isDetailShow
? h('div', { class: 'message-detail' }, [
- h('div', { class: 'message-copy', ref: 'refCopyMsgDiv', on: { click: this.copyMessage } }, [
- h('span', { class: 'bk-icon icon-copy-shape' }),
- h('div', { class: ['copy-status', this.copyStatus], ref: 'refCopyStatus' }, [
- h('div', { class: 'inner' }, [
- h('span', { class: [iconMap[this.copyStatus], this.copyStatus] }),
- this.copyStatus === 'success' ? this.t('bk.message.copySuccess') : this.t('bk.message.copyFailed')
- ])
+ h('div', { class: 'message-copy', ref: 'refCopyMsgDiv' }, [
+ h('span', { class: 'bk-icon icon-copy-shape' })
+ ]),
+ h('div', { class: ['copy-status', this.copyStatus], ref: 'refCopyStatus' }, [
+ h('div', { class: 'inner' }, [
+ h('span', { class: [iconMap[this.copyStatus], this.copyStatus] }),
+ this.copyStatus === 'success' ? this.t('bk.message.copySuccess') : this.t('bk.message.copyFailed')
])
]),
h('div', { class: 'message-tree', ref: 'refJsonContent' }, [
diff --git a/src/components/message/message.js b/src/components/message/message.js
index d1e9759..7c41cce 100644
--- a/src/components/message/message.js
+++ b/src/components/message/message.js
@@ -33,13 +33,64 @@
import Vue from 'vue'
import Message from './message.vue'
+class MessageQueueMaker {
+ constructor () {
+ this.timer = null
+ this.store = []
+ this.maskMap = new WeakMap()
+ }
+
+ appendMaker (fn) {
+ this.store.push(fn)
+ this.executeMaker()
+ }
+
+ executeMaker () {
+ this.timer && cancelAnimationFrame(this.timer)
+ this.timer = requestAnimationFrame(() => {
+ const fn = this.store.pop()
+ if (typeof fn === 'function') {
+ Reflect.apply(fn, this, [])
+ this.executeMaker()
+ }
+ })
+ }
+}
+
+const messageQueueMaker = new MessageQueueMaker()
+
const MessageComponent = Vue.extend(Message)
+const getAdvanceMessageContainer = (parent = document.body) => {
+ const zIndexArr = messageList.map((message) => message.zIndex) || []
+ const maxZIndex = Math.max.apply(null, zIndexArr) || 2500
+
+ let target = parent.querySelector('[data-msg-advanced-conmtainer]')
+ if (!target) {
+ target = document.createElement('div')
+ target.setAttribute('data-msg-advanced-conmtainer', 'true')
+ target.style.setProperty('position', 'fixed')
+ parent.append(target)
+ }
+
+ target.style.zIndex = maxZIndex
+ target.style.setProperty('display', 'block')
+ return target
+}
const messageList = []
let seed = 0
const BkMessage = function (config) {
- const originConfig = typeof config === 'object' ? JSON.parse(JSON.stringify(config)) : config
+ const formatConfig = () => {
+ if (typeof config === 'object') {
+ if (config.message && !config.message.hasOwnProperty('componentOptions')) {
+ return JSON.parse(JSON.stringify(config))
+ }
+ }
+
+ return config
+ }
+ const originConfig = formatConfig()
// 限制个数为 0 时,清除所有实例
if (config.limit === 0) {
BkMessage.batchClose()
@@ -110,15 +161,48 @@ const BkMessage = function (config) {
instance.verticalOffset = 0
instance.$mount()
instance.dom = instance.$el
- document.body.appendChild(instance.$el)
- messageList.forEach(item => {
- verticalOffset += parseInt(item.$el.offsetHeight) + parseInt(spacing)
- })
- instance.verticalOffset = verticalOffset
- instance.horizonOffset = spacing
- instance.visible = true
- messageList.push(instance)
+ const mountedElementToTarget = () => {
+ messageList.forEach(item => {
+ verticalOffset += parseInt(item.$el.offsetHeight) + parseInt(spacing)
+ })
+ instance.verticalOffset = verticalOffset
+ instance.horizonOffset = spacing
+ instance.visible = true
+ messageList.push(instance)
+
+ const target = instance.showAdvanced ? getAdvanceMessageContainer(document.body) : document.body
+ target.appendChild(instance.$el)
+
+ if (instance.showAdvanced) {
+ if (instance.$el) {
+ target.style.setProperty('top', `${offsetY}px`)
+
+ target.style.setProperty('left', '50%')
+ target.style.setProperty('transform', 'translateX(-50%)')
+ instance.$el.style.setProperty('position', 'relative')
+ instance.$el.style.setProperty('margin-bottom', `${spacing}px`)
+ instance.verticalOffset = 0
+ instance.$on('message-show', isShow => {
+ if (isShow) {
+ messageList.forEach((item, i) => {
+ if (item.id !== instanceId && item.showAdvanced) {
+ if (item.$refs.refMessageAdvanced && item.$refs.refMessageAdvanced.isDetailShow) {
+ item.$refs.refMessageAdvanced.setDetailsShow(null, false)
+ }
+ }
+ })
+ }
+ })
+ }
+ }
+ }
+
+ if (instance.showAdvanced) {
+ messageQueueMaker.appendMaker(mountedElementToTarget)
+ } else {
+ mountedElementToTarget()
+ }
return instance
}
@@ -141,11 +225,17 @@ BkMessage.close = function (id, configClose) {
messageList.forEach((item, i) => {
if (i > instanceIndex) {
- item.verticalOffset -= (instance.dom.offsetHeight + instance.spacing)
+ const targetVal = item.verticalOffset - (instance.dom.offsetHeight + instance.spacing)
+ item.verticalOffset = targetVal > 0 ? targetVal : 0
}
})
messageList.splice(instanceIndex, 1)
+
+ if (!messageList.some(msg => msg.showAdvanced)) {
+ const target = getAdvanceMessageContainer(document.body)
+ target.style.setProperty('display', 'none')
+ }
}
}
// 批量清除实例
diff --git a/src/components/message/message.vue b/src/components/message/message.vue
index 4bfd831..3aa63b8 100644
--- a/src/components/message/message.vue
+++ b/src/components/message/message.vue
@@ -36,6 +36,8 @@
@mouseleave="startCountDown">