豆包输入框功能组件
在豆包的输入框中有这么一个功能,是输入框内存在输入框和下拉菜单的组件,图片所示,暂时模拟了一个一样在输入框组件。type:dropdown下拉input输入框text普通文本。selectedValue默认选中。placeholder 输入框提示。options下拉菜单的选项。
·
在豆包的输入框中有这么一个功能,是输入框内存在输入框和下拉菜单的组件,图片所示,暂时模拟了一个一样在输入框组件

<template>
<div class="rich-input-container">
<div
ref="editor"
class="rich-input-editor"
contenteditable="true"
@keydown="handleKeydown"
@input="handleInput"
@click="handleClick"
@compositionstart="isComposing = true"
@compositionend="isComposing = false"
></div>
</div>
</template>
<script>
export default {
name: "RichInputWithDropdown",
data() {
return {
isEmpty: true,
dropdownId: 0,
inputBoxId: 0,
isComposing: false,
debugContent: ""
};
},
methods: {
handleInput(e) {
const editor = this.$refs.editor;
this.isEmpty =
!editor.textContent.trim() &&
editor.querySelectorAll(".dropdown-wrapper, .input-box-wrapper")
.length === 0;
this.updateDebugContent();
},
handleKeydown(e) {
// 输入法组合中不处理
if (this.isComposing) return;
// 处理 Backspace 删除
if (e.key === "Backspace") {
const selection = window.getSelection();
if (!selection.rangeCount) return;
const range = selection.getRangeAt(0);
// 情况1: 选区不是折叠的(有选中内容),让浏览器默认处理
if (!range.collapsed) return;
const editor = this.$refs.editor;
// 情况2: 光标在编辑器最开头
if (range.startOffset === 0 && range.startContainer === editor) {
const firstChild = editor.firstChild;
if (firstChild && this.isCustomComponent(firstChild)) {
e.preventDefault();
firstChild.remove();
this.handleInput(e);
return;
}
}
// 情况3: 光标在文本节点开头
if (
range.startContainer.nodeType === Node.TEXT_NODE &&
range.startOffset === 0
) {
const textNode = range.startContainer;
const prevSibling = textNode.previousSibling;
if (prevSibling && this.isCustomComponent(prevSibling)) {
e.preventDefault();
prevSibling.remove();
this.handleInput(e);
return;
}
}
// 情况4: 光标紧跟在组件后面的元素节点
if (range.startContainer.nodeType === Node.ELEMENT_NODE) {
const container = range.startContainer;
const offset = range.startOffset;
if (offset > 0) {
const prevNode = container.childNodes[offset - 1];
if (prevNode && this.isCustomComponent(prevNode)) {
e.preventDefault();
prevNode.remove();
this.handleInput(e);
return;
}
}
}
}
// Delete 键向前删除
if (e.key === "Delete") {
const selection = window.getSelection();
if (!selection.rangeCount) return;
const range = selection.getRangeAt(0);
if (!range.collapsed) return;
// 光标在文本节点末尾
if (range.startContainer.nodeType === Node.TEXT_NODE) {
const textNode = range.startContainer;
if (range.startOffset === textNode.length) {
const nextSibling = textNode.nextSibling;
if (nextSibling && this.isCustomComponent(nextSibling)) {
e.preventDefault();
nextSibling.remove();
this.handleInput(e);
return;
}
}
}
// 光标在元素节点中
if (range.startContainer.nodeType === Node.ELEMENT_NODE) {
const container = range.startContainer;
const offset = range.startOffset;
const nextNode = container.childNodes[offset];
if (nextNode && this.isCustomComponent(nextNode)) {
e.preventDefault();
nextNode.remove();
this.handleInput(e);
return;
}
}
}
},
handleClick(e) {
// 阻止组件内部点击冒泡
if (e.target.tagName === "SELECT" || e.target.tagName === "INPUT") {
e.stopPropagation();
}
// 处理自定义下拉菜单的点击
const editor = this.$refs.editor;
const dropdownWrapper = e.target.closest(".dropdown-wrapper");
if (dropdownWrapper) {
const dropdownButton = dropdownWrapper.querySelector(
".dropdown-button"
);
const dropdownMenu = dropdownWrapper.querySelector(".dropdown-menu");
// 如果点击的是下拉按钮
if (
dropdownButton &&
(e.target === dropdownButton || dropdownButton.contains(e.target))
) {
e.stopPropagation();
// 关闭其他所有下拉菜单
editor.querySelectorAll(".dropdown-menu.open").forEach(menu => {
if (menu !== dropdownMenu) {
menu.classList.remove("open");
// 重置箭头状态
const otherWrapper = menu.closest(".dropdown-wrapper");
if (otherWrapper) {
const otherArrow = otherWrapper.querySelector(
".dropdown-arrow"
);
if (otherArrow) {
otherArrow.style.transform = "rotate(0deg)";
}
}
}
});
// 切换当前下拉菜单
if (dropdownMenu) {
const isOpen = dropdownMenu.classList.toggle("open");
// 更新箭头旋转状态
const arrow = dropdownWrapper.querySelector(".dropdown-arrow");
if (arrow) {
arrow.style.transform = isOpen
? "rotate(180deg)"
: "rotate(0deg)";
}
// 如果打开菜单,动态计算位置
if (isOpen) {
this.updateDropdownPosition(dropdownButton, dropdownMenu);
}
}
}
// 如果点击的是下拉菜单选项
else if (dropdownMenu && dropdownMenu.contains(e.target)) {
e.stopPropagation();
}
// 如果点击的是下拉菜单外部,关闭菜单
else if (dropdownMenu && dropdownMenu.classList.contains("open")) {
dropdownMenu.classList.remove("open");
// 重置箭头状态
const arrow = dropdownWrapper.querySelector(".dropdown-arrow");
if (arrow) {
arrow.style.transform = "rotate(0deg)";
}
}
} else {
// 点击编辑器其他区域,关闭所有下拉菜单
editor.querySelectorAll(".dropdown-menu.open").forEach(menu => {
menu.classList.remove("open");
// 重置箭头状态
const wrapper = menu.closest(".dropdown-wrapper");
if (wrapper) {
const arrow = wrapper.querySelector(".dropdown-arrow");
if (arrow) {
arrow.style.transform = "rotate(0deg)";
}
}
});
}
},
// 判断是否是自定义组件(下拉框或输入框)
isCustomComponent(node) {
return (
node &&
node.classList &&
(node.classList.contains("dropdown-wrapper") ||
node.classList.contains("input-box-wrapper"))
);
},
// 更新下拉菜单位置(使用 fixed 定位避免被遮挡)
updateDropdownPosition(button, menu) {
// 使用 nextTick 确保菜单已渲染
this.$nextTick(() => {
const buttonRect = button.getBoundingClientRect();
const menuHeight = menu.offsetHeight || 200; // 实际高度
const viewportHeight = window.innerHeight;
// 计算位置
let top = buttonRect.bottom + 6; // 按钮底部 + 间距
let left = buttonRect.left;
// 如果下方空间不足,显示在上方
if (top + menuHeight > viewportHeight && buttonRect.top > menuHeight) {
top = buttonRect.top - menuHeight - 6;
}
// 如果右侧超出视口,调整位置
const menuWidth = menu.offsetWidth || 118;
if (left + menuWidth > window.innerWidth) {
left = window.innerWidth - menuWidth - 10;
}
// 确保不超出左侧
if (left < 10) {
left = 10;
}
// 应用位置
menu.style.position = "fixed";
menu.style.top = `${top}px`;
menu.style.left = `${left}px`;
menu.style.width = `${Math.max(menuWidth, buttonRect.width)}px`;
});
},
insertDropdown(options = null) {
const editor = this.$refs.editor;
editor.focus();
const selection = window.getSelection();
let range;
if (selection.rangeCount > 0) {
range = selection.getRangeAt(0);
} else {
range = document.createRange();
range.selectNodeContents(editor);
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
}
// 创建下拉框包装器
const wrapper = document.createElement("span");
wrapper.className = "dropdown-wrapper";
wrapper.contentEditable = "false";
wrapper.setAttribute("data-id", `dropdown-${this.dropdownId++}`);
wrapper.setAttribute("data-type", "dropdown");
// 使用传入的options,如果没有则使用默认值
const dropdownOptions = options || [
{ value: "1:1", text: "1:1 正方形,头像" },
{ value: "3:2", text: "3:2 比例" },
{ value: "16:9", text: "16:9 横屏" },
{ value: "9:16", text: "9:16 竖屏" }
];
// 创建下拉按钮
const button = document.createElement("button");
button.className = "dropdown-button";
button.type = "button";
button.setAttribute("data-value", dropdownOptions[0].value);
button.appendChild(document.createTextNode(dropdownOptions[0].text));
// 添加下拉箭头图标
const arrow = document.createElement("span");
arrow.className = "dropdown-arrow";
arrow.innerHTML = "▼";
button.appendChild(arrow);
// 创建下拉菜单
const menu = document.createElement("div");
menu.className = "dropdown-menu";
dropdownOptions.forEach((opt, index) => {
const menuItem = document.createElement("div");
menuItem.className = "dropdown-menu-item";
menuItem.setAttribute("data-value", opt.value);
menuItem.textContent = opt.text;
// 默认选中第一个
if (index === 0) {
menuItem.classList.add("selected");
}
// 点击选项时更新按钮文本和值
menuItem.addEventListener("click", e => {
e.stopPropagation();
const value = menuItem.getAttribute("data-value");
const text = menuItem.textContent;
// 更新按钮
button.setAttribute("data-value", value);
// 更新文本(保留箭头节点)
const textNode = Array.from(button.childNodes).find(
node => node.nodeType === Node.TEXT_NODE
);
if (textNode) {
textNode.textContent = text;
} else {
// 如果没有文本节点,在箭头前插入文本
const arrow = button.querySelector(".dropdown-arrow");
if (arrow) {
button.insertBefore(document.createTextNode(text), arrow);
} else {
button.textContent = text;
const newArrow = document.createElement("span");
newArrow.className = "dropdown-arrow";
newArrow.innerHTML = "▼";
button.appendChild(newArrow);
}
}
// 更新选中状态
menu.querySelectorAll(".dropdown-menu-item").forEach(item => {
item.classList.remove("selected");
});
menuItem.classList.add("selected");
// 关闭菜单
menu.classList.remove("open");
this.updateDebugContent();
});
// hover效果
menuItem.addEventListener("mouseenter", () => {
menuItem.classList.add("hover");
});
menuItem.addEventListener("mouseleave", () => {
menuItem.classList.remove("hover");
});
menu.appendChild(menuItem);
});
wrapper.appendChild(button);
wrapper.appendChild(menu);
this.insertComponent(wrapper, range, selection);
},
insertInputBox(placeholder = "某某购人", value = "") {
const editor = this.$refs.editor;
editor.focus();
const selection = window.getSelection();
let range;
if (selection.rangeCount > 0) {
range = selection.getRangeAt(0);
} else {
range = document.createRange();
range.selectNodeContents(editor);
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
}
// 创建输入框包装器
const wrapper = document.createElement("span");
wrapper.className = "input-box-wrapper";
wrapper.contentEditable = "false";
wrapper.setAttribute("data-id", `inputbox-${this.inputBoxId++}`);
wrapper.setAttribute("data-type", "inputbox");
// 创建输入框
const input = document.createElement("input");
input.type = "text";
input.className = "inline-input";
input.placeholder = placeholder;
input.value = value;
// 自动调整输入框宽度
input.addEventListener("input", e => {
const target = e.target;
const minWidth = 60;
const maxWidth = 200;
// 创建临时span测量文本宽度
const temp = document.createElement("span");
temp.style.visibility = "hidden";
temp.style.position = "absolute";
temp.style.whiteSpace = "pre";
temp.style.font = window.getComputedStyle(target).font;
temp.textContent = target.value || target.placeholder;
document.body.appendChild(temp);
const width = Math.min(
Math.max(temp.offsetWidth + 20, minWidth),
maxWidth
);
document.body.removeChild(temp);
target.style.width = width + "px";
});
// 初始化宽度
setTimeout(() => {
input.dispatchEvent(new Event("input"));
}, 0);
wrapper.appendChild(input);
this.insertComponent(wrapper, range, selection);
// 聚焦到输入框
setTimeout(() => {
input.focus();
}, 10);
},
// 统一的组件插入方法
insertComponent(wrapper, range, selection) {
// 插入组件
range.deleteContents();
range.insertNode(wrapper);
// 在组件后添加零宽空格
const space = document.createTextNode("\u200B");
if (wrapper.nextSibling) {
wrapper.parentNode.insertBefore(space, wrapper.nextSibling);
} else {
wrapper.parentNode.appendChild(space);
}
// 移动光标到空格后
range.setStartAfter(space);
range.collapse(true);
selection.removeAllRanges();
selection.addRange(range);
this.isEmpty = false;
this.updateDebugContent();
},
getValue() {
const editor = this.$refs.editor;
let result = "";
const traverse = node => {
if (node.nodeType === Node.TEXT_NODE) {
// 过滤零宽字符
result += node.textContent.replace(/\u200B/g, "");
} else if (
node.classList &&
node.classList.contains("dropdown-wrapper")
) {
const button = node.querySelector(".dropdown-button");
if (button) {
const value = button.getAttribute("data-value");
result += `[下拉:${value}]`;
}
} else if (
node.classList &&
node.classList.contains("input-box-wrapper")
) {
const input = node.querySelector("input");
if (input) {
result += `[输入:${input.value || input.placeholder}]`;
}
} else if (node.childNodes) {
node.childNodes.forEach(child => traverse(child));
}
};
traverse(editor);
const finalResult = result.trim();
console.log("输入框内容:", finalResult);
alert("输入框内容: " + finalResult);
return finalResult;
},
updateDebugContent() {
const editor = this.$refs.editor;
let result = "";
const traverse = node => {
if (node.nodeType === Node.TEXT_NODE) {
result += node.textContent.replace(/\u200B/g, "");
} else if (
node.classList &&
node.classList.contains("dropdown-wrapper")
) {
const button = node.querySelector(".dropdown-button");
if (button) {
const value = button.getAttribute("data-value");
result += `[下拉:${value}]`;
}
} else if (
node.classList &&
node.classList.contains("input-box-wrapper")
) {
const input = node.querySelector("input");
if (input) {
result += `[输入:${input.value || "空"}]`;
}
} else if (node.childNodes) {
node.childNodes.forEach(child => traverse(child));
}
};
traverse(editor);
this.debugContent = result.trim();
},
/**
* 设置编辑器内容
* @param {Array} content - 内容数组,每个元素格式:
* { type: 'text', value: '文本内容' }
* { type: 'input', placeholder: '占位符', value: '初始值' }
* { type: 'dropdown', options: [{value: 'val', text: '显示文本'}, ...], selectedValue: 'val' }
* @param {Object} dropdownOptionsMap - 下拉框选项映射(可选,如果content中已包含options则不需要)
*/
setContent(content = [], dropdownOptionsMap = {}) {
const editor = this.$refs.editor;
// 清空编辑器
editor.innerHTML = "";
// 重置ID计数器
this.dropdownId = 0;
this.inputBoxId = 0;
if (!Array.isArray(content) || content.length === 0) {
this.isEmpty = true;
this.updateDebugContent();
return;
}
// 遍历内容数组,依次插入
content.forEach((item, index) => {
if (item.type === "text") {
// 插入文本
const textNode = document.createTextNode(item.value || "");
editor.appendChild(textNode);
} else if (item.type === "input") {
// 插入输入框
const wrapper = document.createElement("span");
wrapper.className = "input-box-wrapper";
wrapper.contentEditable = "false";
wrapper.setAttribute("data-id", `inputbox-${this.inputBoxId++}`);
wrapper.setAttribute("data-type", "inputbox");
const input = document.createElement("input");
input.type = "text";
input.className = "inline-input";
input.placeholder = item.placeholder || "某某购人";
input.value = item.value || "";
// 自动调整输入框宽度
input.addEventListener("input", e => {
const target = e.target;
const minWidth = 60;
const maxWidth = 200;
const temp = document.createElement("span");
temp.style.visibility = "hidden";
temp.style.position = "absolute";
temp.style.whiteSpace = "pre";
temp.style.font = window.getComputedStyle(target).font;
temp.textContent = target.value || target.placeholder;
document.body.appendChild(temp);
const width = Math.min(
Math.max(temp.offsetWidth + 20, minWidth),
maxWidth
);
document.body.removeChild(temp);
target.style.width = width + "px";
});
wrapper.appendChild(input);
editor.appendChild(wrapper);
// 初始化宽度
setTimeout(() => {
input.dispatchEvent(new Event("input"));
}, 0);
} else if (item.type === "dropdown") {
// 插入下拉框
const wrapper = document.createElement("span");
wrapper.className = "dropdown-wrapper";
wrapper.contentEditable = "false";
wrapper.setAttribute("data-id", `dropdown-${this.dropdownId++}`);
wrapper.setAttribute("data-type", "dropdown");
// 优先使用item中的options,其次使用dropdownOptionsMap,最后使用默认值
let options = item.options;
if (
!options &&
item.dropdownKey &&
dropdownOptionsMap[item.dropdownKey]
) {
options = dropdownOptionsMap[item.dropdownKey];
}
if (!options) {
options = [
{ value: "1:1", text: "1:1 正方形,头像" },
{ value: "3:2", text: "3:2 比例" },
{ value: "16:9", text: "16:9 横屏" },
{ value: "9:16", text: "9:16 竖屏" }
];
}
// 获取要选中的值(优先使用selectedValue,其次使用value)
const selectedValue = item.selectedValue || item.value;
// 检查传入的选中值是否存在于选项中
const hasSelectedValue =
selectedValue && options.some(opt => opt.value === selectedValue);
// 找到要选中的选项
const selectedOption = hasSelectedValue
? options.find(opt => opt.value === selectedValue)
: options[0];
// 创建下拉按钮
const button = document.createElement("button");
button.className = "dropdown-button";
button.type = "button";
button.setAttribute("data-value", selectedOption.value);
button.appendChild(document.createTextNode(selectedOption.text));
// 添加下拉箭头图标
const arrow = document.createElement("span");
arrow.className = "dropdown-arrow";
arrow.innerHTML = "▼";
button.appendChild(arrow);
// 创建下拉菜单
const menu = document.createElement("div");
menu.className = "dropdown-menu";
options.forEach((opt, optIndex) => {
const menuItem = document.createElement("div");
menuItem.className = "dropdown-menu-item";
menuItem.setAttribute("data-value", opt.value);
menuItem.textContent = opt.text;
// 设置选中状态
if (hasSelectedValue && opt.value === selectedValue) {
menuItem.classList.add("selected");
} else if (!hasSelectedValue && optIndex === 0) {
menuItem.classList.add("selected");
}
// 点击选项时更新按钮文本和值
menuItem.addEventListener("click", e => {
e.stopPropagation();
const value = menuItem.getAttribute("data-value");
const text = menuItem.textContent;
// 更新按钮
button.setAttribute("data-value", value);
// 更新文本(保留箭头节点)
const textNode = Array.from(button.childNodes).find(
node => node.nodeType === Node.TEXT_NODE
);
if (textNode) {
textNode.textContent = text;
} else {
const arrow = button.querySelector(".dropdown-arrow");
if (arrow) {
button.insertBefore(document.createTextNode(text), arrow);
} else {
button.textContent = text;
const newArrow = document.createElement("span");
newArrow.className = "dropdown-arrow";
newArrow.innerHTML = "▼";
button.appendChild(newArrow);
}
}
// 更新选中状态
menu.querySelectorAll(".dropdown-menu-item").forEach(item => {
item.classList.remove("selected");
});
menuItem.classList.add("selected");
// 关闭菜单
menu.classList.remove("open");
// 重置箭头状态
const wrapper = menu.closest(".dropdown-wrapper");
if (wrapper) {
const arrow = wrapper.querySelector(".dropdown-arrow");
if (arrow) {
arrow.style.transform = "rotate(0deg)";
}
}
this.updateDebugContent();
});
// hover效果
menuItem.addEventListener("mouseenter", () => {
menuItem.classList.add("hover");
});
menuItem.addEventListener("mouseleave", () => {
menuItem.classList.remove("hover");
});
menu.appendChild(menuItem);
});
wrapper.appendChild(button);
wrapper.appendChild(menu);
editor.appendChild(wrapper);
}
// 在组件后添加零宽空格(除了最后一个元素)
if (index < content.length - 1) {
const space = document.createTextNode("\u200B");
editor.appendChild(space);
}
});
// 更新状态
this.isEmpty = false;
this.updateDebugContent();
// 将光标放在末尾
this.$nextTick(() => {
const range = document.createRange();
const selection = window.getSelection();
range.selectNodeContents(editor);
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
});
}
},
mounted() {
// 组件挂载后保持空状态,等待外部调用setContent方法
// 关闭所有下拉菜单的方法
this.closeAllDropdowns = () => {
const editor = this.$refs.editor;
if (editor) {
editor.querySelectorAll(".dropdown-menu.open").forEach(menu => {
menu.classList.remove("open");
// 重置箭头状态
const wrapper = menu.closest(".dropdown-wrapper");
if (wrapper) {
const arrow = wrapper.querySelector(".dropdown-arrow");
if (arrow) {
arrow.style.transform = "rotate(0deg)";
}
}
});
}
};
// 监听窗口滚动和调整大小,关闭所有下拉菜单
this.handleWindowEvent = this.closeAllDropdowns;
// 监听全局点击事件,点击组件外部时关闭下拉菜单
this.handleGlobalClick = e => {
const editor = this.$refs.editor;
if (!editor) return;
// 检查点击的目标是否在下拉菜单内部
const clickedDropdown = e.target.closest(".dropdown-menu");
const clickedButton = e.target.closest(".dropdown-button");
const clickedWrapper = e.target.closest(".dropdown-wrapper");
// 如果点击的是下拉菜单、按钮或包装器内部,不关闭
if (clickedDropdown || clickedButton || clickedWrapper) {
return;
}
// 检查是否有打开的下拉菜单
const openMenus = editor.querySelectorAll(".dropdown-menu.open");
if (openMenus.length === 0) {
return;
}
// 如果点击的是编辑器外部,或者点击的不是下拉菜单相关元素,关闭所有下拉菜单
if (!editor.contains(e.target)) {
this.closeAllDropdowns();
}
};
window.addEventListener("scroll", this.handleWindowEvent, true);
window.addEventListener("resize", this.handleWindowEvent);
document.addEventListener("click", this.handleGlobalClick, true);
},
beforeDestroy() {
// 清理事件监听器
if (this.handleWindowEvent) {
window.removeEventListener("scroll", this.handleWindowEvent, true);
window.removeEventListener("resize", this.handleWindowEvent);
}
if (this.handleGlobalClick) {
document.removeEventListener("click", this.handleGlobalClick, true);
}
}
};
</script>
<style scoped>
.toolbar {
display: flex;
gap: 8px;
padding: 12px;
background: #fafafa;
border-bottom: 1px solid #e8e8e8;
border-radius: 8px 8px 0 0;
}
.toolbar-btn {
display: flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
border: 1px solid #d9d9d9;
border-radius: 4px;
background: white;
cursor: pointer;
font-size: 13px;
color: #333;
transition: all 0.2s;
}
.toolbar-btn:hover {
border-color: #1890ff;
color: #1890ff;
background: #f0f5ff;
}
.toolbar-btn:active {
transform: translateY(1px);
}
.rich-input-editor {
height: 110px;
padding: 0 20px;
font-size: 14px;
line-height: 26px;
outline: none;
position: relative;
word-wrap: break-word;
white-space: pre-wrap;
overflow-y: auto;
overflow-x: hidden;
box-sizing: border-box;
}
.placeholder {
color: #bbb;
position: absolute;
pointer-events: none;
}
/* 使用 ::v-deep 来修改动态创建的元素样式 */
/* 下拉框样式 */
::v-deep .dropdown-wrapper {
display: inline-flex;
align-items: center;
margin: 0 2px;
vertical-align: middle;
user-select: none;
position: relative;
height: 26px;
box-sizing: border-box;
}
::v-deep .dropdown-button {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 0 12px;
margin: 0;
border: none;
background: #d8e7ff;
border-radius: 6px;
font-size: 14px;
line-height: 26px;
height: 26px;
color: #0062ff;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
outline: none;
white-space: nowrap;
vertical-align: middle;
box-sizing: border-box;
font-family: inherit;
}
::v-deep .dropdown-button:hover {
background: #c5d9ff;
}
::v-deep .dropdown-arrow {
font-size: 10px;
color: #0062ff;
transition: transform 0.2s;
}
/* 气泡式下拉菜单 */
::v-deep .dropdown-menu {
position: fixed;
min-width: 118px;
box-sizing: border-box;
padding: 8px;
border-radius: 12px;
background-color: #fff;
border: 1px solid rgba(201, 201, 201, 1);
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.25);
z-index: 9999;
display: none;
overflow: hidden;
}
::v-deep .dropdown-menu.open {
display: block;
}
::v-deep .dropdown-menu-item {
height: 38px;
font-size: 14px;
color: #000;
display: flex;
border-radius: 8px;
cursor: pointer;
align-items: center;
box-sizing: border-box;
padding: 0 12px;
transition: background-color 0.15s, color 0.15s;
white-space: nowrap;
}
::v-deep .dropdown-menu-item:hover,
::v-deep .dropdown-menu-item.hover {
background-color: rgb(235, 243, 255);
color: rgb(2, 109, 252);
}
/* 输入框样式 */
::v-deep .input-box-wrapper {
display: inline-flex;
align-items: center;
margin: 0 2px;
vertical-align: middle;
user-select: none;
background: #e0ebfb;
border-radius: 4px;
padding: 0;
transition: all 0.2s;
cursor: text;
height: 26px;
box-sizing: border-box;
line-height: 26px;
}
::v-deep .input-box-wrapper:hover {
background: #e0ebfb;
border-color: #40a9ff;
}
::v-deep .input-box-wrapper:focus-within {
background: #e0ebfb;
border-color: #1890ff;
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);
}
::v-deep .inline-input {
border: none;
background: transparent;
font-size: 14px;
line-height: 26px;
padding: 0 8px;
margin: 0;
outline: none;
color: #0062ff;
font-weight: 400;
width: 80px;
min-width: 60px;
max-width: 200px;
height: 26px;
vertical-align: middle;
box-sizing: border-box;
font-family: inherit;
}
::v-deep .inline-input::placeholder {
color: #7492c2;
}
.debug-info {
padding: 12px 16px;
font-size: 12px;
color: #666;
background: #f5f5f5;
border-top: 1px solid #e8e8e8;
border-radius: 0 0 8px 8px;
font-family: "Courier New", monospace;
}
.debug-info div {
padding: 4px 0;
}
.rich-input-editor::-webkit-scrollbar {
width: 6px;
}
.rich-input-editor::-webkit-scrollbar-thumb {
background: #d9d9d9;
border-radius: 3px;
}
.rich-input-editor::-webkit-scrollbar-thumb:hover {
background: #bfbfbf;
}
</style>
调用方法
<template>
<step-input ref="stepInputRef" />
</template>
<script>
//调用方法
this.$refs.stepInputRef.setContent([
{
type: "dropdown",
options: [
{ value: "添加订阅", text: "添加订阅" },
{ value: "取消订阅", text: "取消订阅" }
],
selectedValue:"添加订阅"
},
{ type: "input", placeholder: "地区", value: "" },
{ type: "input", placeholder: "关键词", value: "" },
{ type: "text", value: "有关的标讯" }
]);
</script>
type:dropdown下拉 input输入框 text普通文本
options下拉菜单的选项
selectedValue默认选中
placeholder 输入框提示
效果如图
更多推荐

所有评论(0)