diff --git a/example/components.config.js b/example/components.config.js index 05e2559..fb99621 100644 --- a/example/components.config.js +++ b/example/components.config.js @@ -198,7 +198,7 @@ module.exports = { }, { id: 'searchSelect', - name: 'SearchSelect 查询选择器' + name: 'Search 查询搜索' }, { id: 'slider', diff --git a/example/components/changelog/readme.md b/example/components/changelog/readme.md index 175bd3b..ee07372 100644 --- a/example/components/changelog/readme.md +++ b/example/components/changelog/readme.md @@ -8,6 +8,20 @@
+### 2.5.7 {page=#/changelog} +###### 2023.07.24 + +* **[add]**: + - [Select 下拉选框](#/select) 多选新增 [checkbox 模式](#/select?anchor=duo-xuan) + - [SearchSelect 查询选择器](#/searchselect) 新增 [checkbox 模式](#/search-select?anchor=checkbox-mo-shi) + - [SearchSelect 查询选择器](#/searchselect) 新增推荐搜索选择的功能 + - [Message 消息提示](#/message) 支持[规范化高阶使用配置](#/message?anchor=gao-jie-yong-fa) + - [Message 消息提示](#/message) 支持自定义 z-index +* **[fix]**: + - [Cascade 级联选框](#/cascade) 修复 filterable 和 check-any-level 卡死的问题 [#407](https://github.com/TencentBlueKing/bkui-vue2/issues/407) + +--- + ### 2.5.6 {page=#/changelog} ###### 2023.06.21 diff --git a/example/components/message/readme.md b/example/components/message/readme.md index 5173719..2f8a1a4 100644 --- a/example/components/message/readme.md +++ b/example/components/message/readme.md @@ -89,6 +89,52 @@ ellipsisLine: 2, ellipsisCopy: true }) + }, + handleAdvancedMessage () { + this.$bkMessage({ + message: { + code: 10086, + overview: '算法载入失败。', + suggestion: '请确认文件内容是否正确,并和所选框架匹配。请确认文件内容是否正确,并和所选框架匹配。请确认文件内容是否正确,并和所选框架匹配。请确认文件内容是否正确,并和所选框架匹配。请确认文件内容是否正确,并和所选框架匹配。请确认文件内容是否正确,并和所选框架匹配。请确认文件内容是否正确,并和所选框架匹配。请确认文件内容是否正确,并和所选框架匹配。请确认文件内容是否正确,并和所选框架匹配。请确认文件内容是否正确,并和所选框架匹配。请确认文件内容是否正确,并和所选框架匹配。请确认文件内容是否正确,并和所选框架匹配。请确认文件内容是否正确,并和所选框架匹配。请确认文件内容是否正确,并和所选框架匹配。请确认文件内容是否正确,并和所选框架匹配。', + type: 'key-value', + details: `{ + "code": "UNAUTHENTICATED", + "message": "用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)", + "code1": "UNAUTHENTICATED", + "message1": "用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)", + "code2": "UNAUTHENTICATED", + "message2": "用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)", + "code3": "UNAUTHENTICATED", + "message3": "用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)", + "code4": "UNAUTHENTICATED", + "message4": "用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)", + "code5": "UNAUTHENTICATED", + "message5": "用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)", + "code6": "UNAUTHENTICATED", + "message6": "用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)", + "code7": "UNAUTHENTICATED", + "message7": "用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)", + "code8": "UNAUTHENTICATED", + "message8": "用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)", + "code9": "UNAUTHENTICATED", + "message9": "用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)", + "code10": "UNAUTHENTICATED", + "message10": "用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)", + "code81": "UNAUTHENTICATED", + "message81": "用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)", + "code91": "UNAUTHENTICATED", + "message91": "用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)", + "code101": "UNAUTHENTICATED", + "message101": "用户未登录或登录态失效,请使用登录链接重新登录 (UNAUTHORIZED)" + }`, + assistant: '', + }, + theme: 'error', + offsetY: 80, + ellipsisLine: 2, + ellipsisCopy: true + }) + } } } @@ -348,7 +394,7 @@ -### 内容超出被截断时显示复制按钮 +### 内容超出被截断时显示复制按钮 {page=#/message} :::demo 内容超出被截断时显示复制按钮 ```html @@ -386,6 +432,79 @@ } ``` +::: + +### 高阶用法 {page=#/message} + +:::demo 高阶用法 +```html + + + +``` + ::: ### 属性 {page=#/message} | 参数 | 说明 | 类型 | 可选值 | 默认值 | diff --git a/example/components/navigation/demo.vue b/example/components/navigation/demo.vue index 0bb5903..2279513 100644 --- a/example/components/navigation/demo.vue +++ b/example/components/navigation/demo.vue @@ -156,7 +156,7 @@ diff --git a/example/components/search-select/readme.md b/example/components/search-select/readme.md index f3dc26d..b65b1b5 100644 --- a/example/components/search-select/readme.md +++ b/example/components/search-select/readme.md @@ -326,10 +326,10 @@ [[toc]] -## SearchSelect 查询选择器 +## Search 查询搜索 功能组件,用于将搜索查询项集中在一个选择器中,搜索查询更加便捷、简单 -### 基础使用 {page=#/searchselect} +### 基础使用 {page=#/search-select} ::: demo 基础使用 ``` html @@ -419,7 +419,97 @@ ::: -### 自定义过滤列表 {page=#/searchselect} +### CheckBox模式 {page=#/search-select} +::: demo CheckBox模式 + +``` html + + + + + +``` + +::: + +### 自定义过滤列表 {page=#/search-select} ::: demo 自定义过滤列表 ``` html @@ -521,7 +611,7 @@ ::: -### 远程加载列表 {page=#/searchselect} +### 远程加载列表 {page=#/search-select} ::: demo 远程加载列表 ``` html @@ -646,7 +736,7 @@ ::: -### 多选子列表 {page=#/searchselect} +### 多选子列表 {page=#/search-select} ::: demo 多选子列表 ``` html @@ -740,7 +830,7 @@ ::: -### 配置子项搜索条件 {page=#/searchselect} +### 配置子项搜索条件 {page=#/search-select} ::: demo 配置子项搜索条件 此功能与multiable是互斥的 如果同时配置则multiable的权重将更大 ``` html @@ -878,7 +968,7 @@ ``` ::: -### 配置子项校验及自定义placeholder提示 {page=#/searchselect} +### 配置子项校验及自定义placeholder提示 {page=#/search-select} ::: demo 配置子项校验及自定义placeholder提示,校验的信息既可以通过validate函数返回也可以通过validate-message属性传入或者通过validate插槽设置 ``` html @@ -980,7 +1070,7 @@ ``` ::: -### 配置其他属性 {page=#/searchselect} +### 配置其他属性 {page=#/search-select} ::: demo 配置其他属性 ``` html @@ -1079,7 +1169,7 @@ ::: -### 属性 {page=#/searchselect} +### 属性 {page=#/search-select} | 参数 | 说明 | 类型 | 可选值 | 默认值 | |------|------|------|------|------| | data | 显示的数据 | Array | —— | —— | @@ -1113,8 +1203,9 @@ | validate-message | 校验提示文本 | String | —— | '' | | input-unfocus-clear | 当单元格失去焦点时是否清除输入框的内容 | Boolean | —— | false | | ext-cls | 配置自定义样式类名,传入的类会被加在组件最外层的 DOM `.search-select-wrap` 上 | String | —— | —— | +| selected-style | 勾选模式 | String | check/checkbox | check | -### 事件 {page=#/searchselect} +### 事件 {page=#/search-select} | 事件名称 | 说明 | 回调参数 | |------|------|------| | show-menu | 父列表显示时触发的事件 | menuInstance | @@ -1132,7 +1223,7 @@ | clear | 当用户点击清空时触发该事件 | event | | search | 当用户点击搜索图标时触发该事件 | event | -### 方法 {page=#/searchselect} +### 方法 {page=#/search-select} | 方法名 | 说明 | 参数 | |------|------|------| | getMenuInstance | 获取menu实例方法 | —— | @@ -1140,7 +1231,7 @@ | getInputInstance | 获取input框实例 | —— | -### 插槽 {page=#/searchselect} +### 插槽 {page=#/search-select} | 插槽名 | 说明 | 参数 | |------|------|------| | prefix | 输入框前插槽 | —— | diff --git a/example/components/select/readme.md b/example/components/select/readme.md index fbd9bc5..01c8269 100644 --- a/example/components/select/readme.md +++ b/example/components/select/readme.md @@ -321,6 +321,18 @@ + + + + + { + this.tippyInstance() // 回填不需要打开下拉,关闭 + }) + } }, methods: { recurrenceNodes (list) { @@ -538,6 +540,7 @@ export default { this.selectedList = [] this.tmpSelected = [] this.exposedId(this.currentList, oldId) + this.searchContent = '' } this.broadcast('bkCaspanel', 'on-clear') // 关闭下拉面板 diff --git a/src/components/cascade/caspanel.vue b/src/components/cascade/caspanel.vue index b6c11b5..1c936bb 100644 --- a/src/components/cascade/caspanel.vue +++ b/src/components/cascade/caspanel.vue @@ -137,7 +137,7 @@ export default { for (let j = 0; j < this.list.length; j++) { if (valueList[i] === this.list[j].id) { this.handleItemFn(this.list[j], true) - valueList.splice(0, 1) + valueList.splice(i, 1) this.$nextTick(() => { this.broadcast('bkCaspanel', 'change-selected', { idList: valueList diff --git a/src/components/message/advanced.js b/src/components/message/advanced.js new file mode 100644 index 0000000..584cef0 --- /dev/null +++ b/src/components/message/advanced.js @@ -0,0 +1,354 @@ + +/* + * Tencent is pleased to support the open source community by making + * 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) is licensed under the MIT License. + * + * License for 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition): + * + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. +*/ + +/** + * @file message entry + * + * Copyright © 2012-2019 Tencent BlueKing. All Rights Reserved. 蓝鲸智云 版权所有 + */ +import JSONFormatter from 'json-formatter-js' +import ClipboardJS from 'clipboard' +import locale from 'bk-magic-vue/lib/locale' + +const IMessageActionType = { + /** + * 联系助手:默认直接拉起企业微信与助手的聊天,需要在 message.assistant 配置对应的企微群ID + */ + ASSISTANT: 'assistant', + + /** + * 展开详情:展开面向开发的详情 + */ + DETAILS: 'details', + + /** + * 图钉按钮:点击后,Message 不会自动消失 + */ + FIX: 'fix', + + /** + * 关闭:点击关闭,Message 消失 + */ + CLOSE: 'close' +} + +const MessageContentType = { + KEY_VALUE: 'key-value', + JSON: 'json' +} + +const sortActionIdList = [ + IMessageActionType.ASSISTANT, + IMessageActionType.DETAILS, + IMessageActionType.FIX, + IMessageActionType.CLOSE +] + +export default { + name: 'bk-message-advanced', + mixins: [locale.mixin], + props: { + message: { + type: Object, + default: () => ({}) + }, + actions: { + type: Array, + default: () => ([]) + }, + tipsIcon: { + type: String, + default: '' + } + }, + data () { + return { + toolOperation: { + isFix: false, + isDetailShow: false + }, + isInstallClipboardJS: false, + copyStatus: '', + copyStatusTimer: null + } + }, + computed: { + defActionList () { + return { + [IMessageActionType.ASSISTANT]: { + id: IMessageActionType.ASSISTANT, + icon: (h) => h('span', { class: 'bk-icon icon-weixin-pro' }), + text: () => this.t('bk.message.assistant'), + onClick: (e) => this.handleHeplerClick(e) + }, + [IMessageActionType.DETAILS]: { + id: IMessageActionType.DETAILS, + icon: (h) => (this.toolOperation.isDetailShow ? h('span', { class: 'bk-icon icon-angle-double-up' }) : h('span', { class: 'bk-icon icon-angle-double-down' })), + text: () => this.t('bk.message.details'), + onClick: (e) => this.setDetailsShow(e) + }, + [IMessageActionType.FIX]: { + id: IMessageActionType.FIX, + icon: (h) => (this.toolOperation.isFix ? h('span', { class: 'bk-icon icon-fix-shape' }) : h('span', { class: 'bk-icon icon-fix-line' })), + classList: this.toolOperation.isFix ? 'fixed' : '', + onClick: (e) => this.fixMesage(e) + }, + [IMessageActionType.CLOSE]: { + id: IMessageActionType.CLOSE, + classList: 'normal-color', + icon: (h) => h('span', { class: 'bk-message-close' }, [ + h('i', { class: 'bk-icon icon-close' }) + ]), + onClick: this.handleCloseClick + } + } + }, + actionList () { + if (this.actions && this.actions.length > 0) { + const resultList = this.actions.map((action) => { + const id = action.id.toLocaleLowerCase() + const defAction = this.defActionList[id] + const defClickFn = defAction.onClick + const target = Object.assign({}, this.defActionList[id] || {}, action) + target.id = id + + if (action.classList !== undefined) { + const classList = Array.isArray(action.classList) ? action.classList : [action.classList] + let defClassList = [] + if (defAction.classList !== undefined) { + defClassList = Array.isArray(defAction.classList) ? defAction.classList : [defAction.classList] + } + + target.classList = [...defClassList, ...classList] + } + + if (typeof action.onClick === 'function') { + target.onClick = () => { + const resp = Reflect.apply(action.onClick, this, []) + if ((typeof resp === 'undefined' || resp) && typeof defClickFn === 'function') { + Reflect.apply(defClickFn, this, []) + } + } + + return target + } + + target.onClick = defClickFn + return target + }) + const appendList = sortActionIdList + .filter(id => !resultList.some(action => action.id === id)) + .map(id => this.defActionList[id]) + resultList.push(...appendList) + return resultList + } + + return sortActionIdList.map(id => this.defActionList[id]) + } + }, + methods: { + handleCloseClick () { + this.$emit('close') + }, + handleHeplerClick (e) { + if (this.message.assistant) { + window.open(this.message.assistant, '_blank') + } + }, + setDetailsShow (e, isShow) { + this.toolOperation.isDetailShow = isShow !== undefined ? isShow : !this.toolOperation.isDetailShow + this.fixMesage(e, this.toolOperation.isDetailShow) + + if ( + this.toolOperation.isDetailShow + && typeof this.message === 'object' + && (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()) + } + }) + } + }, + fixMesage (e, isFix) { + this.toolOperation.isFix = isFix !== undefined ? isFix : !this.toolOperation.isFix + this.$emit('fix-message', this.toolOperation.isFix) + }, + parseJson (value) { + let targetJson = value + if (typeof value === 'string') { + try { + targetJson = JSON.parse(value) + } catch (e) { + console.error(`Format Json Error: ${e}`) + } + } + + return targetJson + }, + copyMessage () { + if (this.isInstallClipboardJS) { + return + } + + const copyInstance = new ClipboardJS(this.$refs.refCopyMsgDiv, { + text: () => this.message.details + }); + + ['success', 'error'].forEach((theme) => { + copyInstance.on(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() + }) + }) + } + }, + render (h) { + const renderMsgDetail = (msg) => { + if (msg.type === MessageContentType.KEY_VALUE) { + const target = this.parseJson(msg.details || {}) + const keys = Object.keys(target) + return keys.map(key => ( + h('div', { class: 'message-row' }, [ + h('label', key), + target[key] + ]) + )) + } + + return null + } + + const renderMessageActions = () => { + const renderIcon = ({ icon }) => { + if (typeof icon === 'function') { + return Reflect.apply(icon, this, [h]) + } + + return h('span', { class: icon }) + } + + const renderText = ({ text }) => { + let content + if (typeof text === 'function') { + content = Reflect.apply(text, this, [h]) + } + + if (content === undefined) { + return + } + + if (typeof content === 'string') { + return h('span', { class: 'message-action-text' }, [content]) + } + + return content + } + + const handleActionClick = (e, action) => { + if (action.readonly || action.disabled) { + return + } + + if (typeof action.onClick === 'function') { + Reflect.apply(action.onClick, this, [e, action]) + } + } + + const renderActionList = () => this.actionList.map((action) => { + if (action.disabled) { + return null + } + + if (typeof action.render === 'function') { + return Reflect.apply(action.render, this, []) + } + + const classList = Array.isArray(action.classList) ? action.classList.join(' ') : action.classList + + return h('div', { + class: ['tool', action.id, classList], + on: { click: e => handleActionClick(e, action) } + }, [ + renderIcon(action), + renderText(action) + ]) + }) + + return renderActionList() + } + + const iconMap = { + success: 'bk-icon icon-check-circle-shape', + error: 'bk-icon icon-close-circle-shape' + } + + return h('div', { class: 'bk-message-content multi' }, [ + h('div', { class: 'overview' }, [ + h('div', { class: 'left-content' }, [ + h('div', { class: 'bk-message-icon' }, [ + h('i', { class: ['bk-icon', this.tipsIcon] }) + ]), + h('div', { class: 'describe' }, this.message.title || `【${this.message.code}】${this.message.overview} ${this.message.suggestion}`) + ]), + h('div', { class: 'tools' }, [renderMessageActions()]) + ]), + this.toolOperation.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-tree', ref: 'refJsonContent' }, [ + renderMsgDetail(this.message) + ]) + ]) : null + ]) + } +} diff --git a/src/components/message/message.js b/src/components/message/message.js index c6406f9..d1e9759 100644 --- a/src/components/message/message.js +++ b/src/components/message/message.js @@ -39,6 +39,7 @@ const messageList = [] let seed = 0 const BkMessage = function (config) { + const originConfig = typeof config === 'object' ? JSON.parse(JSON.stringify(config)) : config // 限制个数为 0 时,清除所有实例 if (config.limit === 0) { BkMessage.batchClose() @@ -76,14 +77,33 @@ const BkMessage = function (config) { data: config }) - if (config.message !== null - && typeof config.message === 'object' - && config.message.hasOwnProperty('componentOptions') + if (originConfig.message !== null + && typeof originConfig.message === 'object' + && originConfig.message.hasOwnProperty('componentOptions') ) { instance.$slots.default = [config.message] instance.message = null } + if (!originConfig.width) { + instance.width = 560 + } + + if (originConfig.message !== null + && typeof originConfig.message === 'object' + && !originConfig.message.hasOwnProperty('componentOptions')) { + instance.showAdvanced = true + instance.actions = originConfig.actions || [] + + if (!originConfig.width) { + instance.width = 800 + } + + if (!originConfig.delay) { + instance.delay = 8000 + } + } + instance.id = instanceId instance.spacing = spacing instance.ellipsisLine = ellipsisLine diff --git a/src/components/message/message.vue b/src/components/message/message.vue index bbdd790..4bfd831 100644 --- a/src/components/message/message.vue +++ b/src/components/message/message.vue @@ -34,22 +34,29 @@ v-show="visible" @mouseenter="stopCountDown" @mouseleave="startCountDown"> -
- -
-
- {{message}} -
-
- {{localeCopyText}} -
-
- -
+ +
@@ -67,6 +74,7 @@ */ import { copyText, checkOverflow } from '@/utils/util' import locale from 'bk-magic-vue/lib/locale' +import MessageAdvanced from './advanced' const ICONS = { primary: 'icon-info-circle-shape', @@ -77,6 +85,7 @@ const ICONS = { export default { name: 'bk-message', + components: { MessageAdvanced }, mixins: [locale.mixin], data () { return { @@ -86,6 +95,7 @@ export default { icon: '', dismissable: true, verticalOffset: 0, + zIndex: 2500, horizonOffset: 0, visible: false, countID: null, @@ -93,7 +103,11 @@ export default { extCls: '', copied: false, ellipsisCopy: false, - showCopyText: false + showCopyText: false, + showAdvanced: false, + actions: [], + isFixed: false, + width: 560 } }, computed: { @@ -102,7 +116,9 @@ export default { }, verticalStyle () { return { - top: `${this.verticalOffset}px` + top: `${this.verticalOffset}px`, + width: `${this.width}px`, + zIndex: this.zIndex } }, tipsIcon () { @@ -127,18 +143,29 @@ export default { this.startCountDown() }, methods: { + handleFixMessage (isFixed) { + this.isFixed = isFixed + console.log('handleFixMessage', isFixed) + if (isFixed) { + this.stopCountDown() + } else { + this.startCountDown() + } + }, destroyEl () { this.$destroy() this.$el.parentNode && this.$el.parentNode.removeChild(this.$el) }, startCountDown () { - if (this.delay > 0) { + if (this.delay > 0 && !this.isFixed) { this.countID = setTimeout(() => { + console.log('--Close') this.visible && this.close() }, this.delay) } }, stopCountDown () { + console.log('--stopCountDown') clearTimeout(this.countID) }, close () { diff --git a/src/components/search-select/search-select-menu.vue b/src/components/search-select/search-select-menu.vue index ba3006e..e9752e1 100644 --- a/src/components/search-select/search-select-menu.vue +++ b/src/components/search-select/search-select-menu.vue @@ -28,9 +28,13 @@