refactor: ♻️ 移除项目非常用组件和配置,降低项目上手难度
This commit is contained in:
parent
5e8a96dc21
commit
ca1182cc24
|
|
@ -1,510 +0,0 @@
|
||||||
<template>
|
|
||||||
<div :class="['tagInputarea', className]">
|
|
||||||
<div
|
|
||||||
ref="cmEle"
|
|
||||||
:class="[
|
|
||||||
'tagInputareaIuput',
|
|
||||||
'ThemeBorderColor3',
|
|
||||||
!!readonly ? 'readonlyBg' : '',
|
|
||||||
]"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import CodeMirror from "codemirror";
|
|
||||||
import "codemirror/lib/codemirror.css";
|
|
||||||
import { getRePosFromStr, MODE } from "./util";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
mode: {
|
|
||||||
type: Number,
|
|
||||||
default: MODE.TEXT,
|
|
||||||
},
|
|
||||||
className: {
|
|
||||||
type: String,
|
|
||||||
default: "",
|
|
||||||
},
|
|
||||||
defaultValue: {
|
|
||||||
type: String,
|
|
||||||
default: "",
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
renderTag: {
|
|
||||||
type: Function,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
minHeight: {
|
|
||||||
type: Number,
|
|
||||||
default: 20,
|
|
||||||
},
|
|
||||||
readonly: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
noCursor: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
operatorsSetMargin: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
autoComma: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
// 是否禁用复制
|
|
||||||
disabledCopy: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const emit = defineEmits(["onChange", "onBlur", "onFocus"]);
|
|
||||||
//编辑器挂载dom节点
|
|
||||||
const cmEle = ref();
|
|
||||||
|
|
||||||
//编辑器实例
|
|
||||||
let cmInstance: any = null;
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
if (cmEle.value) {
|
|
||||||
//编辑器初始化
|
|
||||||
cmInstance = CodeMirror(cmEle.value, {
|
|
||||||
value: props.defaultValue,
|
|
||||||
mode: "",
|
|
||||||
lineWrapping: true,
|
|
||||||
cursorHeight: props.noCursor || props.readonly ? 0 : 1,
|
|
||||||
});
|
|
||||||
//最小高度初始化
|
|
||||||
if (props.minHeight) {
|
|
||||||
let height =
|
|
||||||
typeof props.minHeight === "number"
|
|
||||||
? `${props.minHeight}px`
|
|
||||||
: props.minHeight;
|
|
||||||
//编辑器高度
|
|
||||||
cmInstance.setSize("100%", height);
|
|
||||||
//编辑内容高度
|
|
||||||
let codeEle = cmEle.value.getElementsByClassName("CodeMirror-code")[0];
|
|
||||||
codeEle && codeEle.setAttribute("style", `min-height:${height}`);
|
|
||||||
}
|
|
||||||
//默认值初始化
|
|
||||||
if (props.defaultValue) {
|
|
||||||
updateTextareaView();
|
|
||||||
cmInstance.execCommand("goDocEnd");
|
|
||||||
}
|
|
||||||
//监听 value change
|
|
||||||
cmInstance.on("change", cmChange);
|
|
||||||
//监听 value beforeChange
|
|
||||||
cmInstance.on("beforeChange", cmBeforeChange);
|
|
||||||
//监听表单聚焦
|
|
||||||
cmInstance.on("focus", () => {
|
|
||||||
cmEle.value.classList.add("active");
|
|
||||||
cmFocus();
|
|
||||||
});
|
|
||||||
|
|
||||||
//监听表单失焦
|
|
||||||
cmInstance.on("blur", () => {
|
|
||||||
if (cmEle.value) {
|
|
||||||
cmEle.value.classList.remove("active");
|
|
||||||
}
|
|
||||||
cmBlur();
|
|
||||||
});
|
|
||||||
if (props.disabledCopy) {
|
|
||||||
// 禁止复制,防止tag复制的是id
|
|
||||||
cmInstance.on("copy", (cm: any, e: Event) => {
|
|
||||||
e.preventDefault();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//编辑器change
|
|
||||||
const cmChange = (cm: any, obj: any): void => {
|
|
||||||
let value = cm.getValue();
|
|
||||||
if (obj.origin !== "setValue") {
|
|
||||||
emit("onChange", null, value, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateTextareaView();
|
|
||||||
};
|
|
||||||
|
|
||||||
//编辑器beforeChange
|
|
||||||
const cmBeforeChange = (cm: any, obj: any): any => {
|
|
||||||
let { text } = obj;
|
|
||||||
// 如果是自定义公式,只能允许数字+、-、*、/、( \ ) , .,大写字符
|
|
||||||
if (
|
|
||||||
props.mode === MODE.FORMULA &&
|
|
||||||
(obj.origin === "paste" ||
|
|
||||||
obj.origin === "+input" ||
|
|
||||||
obj.origin === "*compose")
|
|
||||||
) {
|
|
||||||
text = text.map((t: string) =>
|
|
||||||
t.replace(/[^+\-*\/0-9/a-z/A-Z\(\)\,\.]/gm, "").toUpperCase()
|
|
||||||
);
|
|
||||||
// 最大输入10000字符
|
|
||||||
if (text.map((t: string) => t).join("").length > 10000) {
|
|
||||||
text = text
|
|
||||||
.map((t: string) => t)
|
|
||||||
.join("")
|
|
||||||
.slice(0, 10000)
|
|
||||||
.split(",");
|
|
||||||
obj.update(obj.from, obj.to, text);
|
|
||||||
obj.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj.origin === "undo" || obj.origin === "redo") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 事件内,mode只能从每次props取,不然取不到最新
|
|
||||||
if (
|
|
||||||
props.readonly ||
|
|
||||||
(props.mode === MODE.ONLYTAG &&
|
|
||||||
obj.origin !== "+delete" &&
|
|
||||||
obj.origin !== "inserttag" &&
|
|
||||||
obj.origin !== "setValue")
|
|
||||||
) {
|
|
||||||
obj.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 事件内,mode只能从每次props取,不然取不到最新
|
|
||||||
if (
|
|
||||||
props.mode === MODE.FORMULA &&
|
|
||||||
obj.origin !== "+delete" &&
|
|
||||||
obj.origin !== "inserttag" &&
|
|
||||||
obj.origin !== "setValue"
|
|
||||||
) {
|
|
||||||
text = text.map((t: any) =>
|
|
||||||
t
|
|
||||||
.toUpperCase()
|
|
||||||
.split("")
|
|
||||||
.filter((t: any) =>
|
|
||||||
(obj.origin === "paste"
|
|
||||||
? /[0-9A-Z\+\-\*\/\(\)\,\.\$]/
|
|
||||||
: /[0-9A-Z\+\-\*\/\(\)\,\.]/
|
|
||||||
).test(t)
|
|
||||||
)
|
|
||||||
.join("")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
props.mode === MODE.DATE &&
|
|
||||||
obj.origin !== "+delete" &&
|
|
||||||
obj.origin !== "inserttag" &&
|
|
||||||
obj.origin !== "setValue"
|
|
||||||
) {
|
|
||||||
text = text.map((t: any) =>
|
|
||||||
t
|
|
||||||
.split("")
|
|
||||||
.filter((t: any) =>
|
|
||||||
(obj.origin === "paste" ? /[0-9YMdhm\+\-\$]/ : /[0-9YMdhm\+\-]/).test(
|
|
||||||
t
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.join("")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
obj.update(obj.from, obj.to, text);
|
|
||||||
};
|
|
||||||
|
|
||||||
//编辑器 foucus
|
|
||||||
const cmFocus = (): void => {
|
|
||||||
emit("onFocus");
|
|
||||||
};
|
|
||||||
|
|
||||||
//编辑器 blur
|
|
||||||
const cmBlur = (): void => {
|
|
||||||
emit("onBlur");
|
|
||||||
};
|
|
||||||
|
|
||||||
//设置 value
|
|
||||||
const setValue = (value: string): void => {
|
|
||||||
// const position = cmInstance.getCursor()
|
|
||||||
cmInstance.setValue(value || "");
|
|
||||||
// const newPosition = {
|
|
||||||
// line: position.line,
|
|
||||||
// ch: position.ch + value.length - 2,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// cmInstance.focus()
|
|
||||||
// cmInstance.setCursor(newPosition)
|
|
||||||
// cmInstance.execCommand('goDocEnd')
|
|
||||||
};
|
|
||||||
const getValue = () => {
|
|
||||||
return cmInstance.getValue();
|
|
||||||
};
|
|
||||||
//回显,更新渲染
|
|
||||||
let markers: any = null;
|
|
||||||
const updateTextareaView = () => {
|
|
||||||
const { mode, operatorsSetMargin } = props;
|
|
||||||
const value = cmInstance.getValue();
|
|
||||||
if (markers) {
|
|
||||||
markers.forEach((marker: any) => marker.clear());
|
|
||||||
}
|
|
||||||
markers = [];
|
|
||||||
markColumns(markers, value);
|
|
||||||
if (mode === MODE.FORMULA || operatorsSetMargin) {
|
|
||||||
markOperators(markers, value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//光标行
|
|
||||||
const markColumns = (markers: any, value: any) => {
|
|
||||||
const poss = getRePosFromStr(value);
|
|
||||||
poss.forEach((pos: any, i: number) => {
|
|
||||||
renderColumnTag(pos.tag, { isLast: i === poss.length - 1 }, (node: any) => {
|
|
||||||
markers.push(
|
|
||||||
cmInstance.markText(
|
|
||||||
{ line: pos.line, ch: pos.start },
|
|
||||||
{ line: pos.line, ch: pos.stop },
|
|
||||||
{ replacedWith: node, handleMouseEvents: true }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//光标操作
|
|
||||||
const markOperators = (markers: any, value: any) => {
|
|
||||||
const poss = getRePosFromStr(value, /\+|\-|\*|\/|\(|\)|,/g);
|
|
||||||
poss.forEach((pos: any, i: number) => {
|
|
||||||
const operatorEle = document.createElement("span");
|
|
||||||
operatorEle.classList.add("operator");
|
|
||||||
operatorEle.innerHTML = pos.tag;
|
|
||||||
markers.push(
|
|
||||||
cmInstance.markText(
|
|
||||||
{ line: pos.line, ch: pos.start },
|
|
||||||
{ line: pos.line, ch: pos.stop },
|
|
||||||
{ replacedWith: operatorEle, handleMouseEvents: true }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
//渲染 tag
|
|
||||||
const renderColumnTag = (id: any, options: any, cb: any) => {
|
|
||||||
const node = document.createElement("div");
|
|
||||||
node.classList.add("columnTagCon");
|
|
||||||
//自定义渲染tag
|
|
||||||
if (props.renderTag) {
|
|
||||||
const tag = props.renderTag(id, options);
|
|
||||||
if (tag instanceof HTMLElement) {
|
|
||||||
node.appendChild(tag);
|
|
||||||
cb(node);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
node.append(id);
|
|
||||||
cb(node);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
//插入 tag
|
|
||||||
const insertColumnTag = (id: string) => {
|
|
||||||
const { mode, autoComma } = props;
|
|
||||||
const position = cmInstance.getCursor();
|
|
||||||
const editorValue = cmInstance.getValue();
|
|
||||||
|
|
||||||
cmInstance.replaceRange(
|
|
||||||
`${
|
|
||||||
mode === MODE.FORMULA && autoComma && editorValue[position.ch - 1] === "$"
|
|
||||||
? ","
|
|
||||||
: ""
|
|
||||||
}$${id}$`,
|
|
||||||
position,
|
|
||||||
undefined,
|
|
||||||
"inserttag"
|
|
||||||
);
|
|
||||||
cmInstance.focus();
|
|
||||||
cmInstance.execCommand("goDocEnd");
|
|
||||||
if (cmEle.value) {
|
|
||||||
cmEle.value.scrollTop = cmEle.value.scrollHeight - cmEle.value.clientHeight;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// 获取光标位置
|
|
||||||
const getCursor = () => {
|
|
||||||
return cmInstance.getCursor();
|
|
||||||
};
|
|
||||||
// 设置光标位置
|
|
||||||
const setCustomCursor = (position: { line: number; ch: number }) => {
|
|
||||||
cmInstance.setCursor(position);
|
|
||||||
};
|
|
||||||
// 插入公式
|
|
||||||
const insertFormula = (value: string) => {
|
|
||||||
const { mode, autoComma } = props;
|
|
||||||
const position = cmInstance.getCursor();
|
|
||||||
|
|
||||||
cmInstance.replaceRange(value, position, undefined, "insertFormula");
|
|
||||||
setTimeout(() => {
|
|
||||||
const newPosition = {
|
|
||||||
line: position.line,
|
|
||||||
ch: position.ch + value.length - 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
cmInstance.focus();
|
|
||||||
cmInstance.setCursor(newPosition);
|
|
||||||
// cmInstance.execCommand('goDocEnd')
|
|
||||||
}, 0);
|
|
||||||
if (cmEle.value) {
|
|
||||||
cmEle.value.scrollTop = cmEle.value.scrollHeight - cmEle.value.clientHeight;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
defineExpose({
|
|
||||||
insertColumnTag,
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.tagInputarea {
|
|
||||||
min-width: 0;
|
|
||||||
|
|
||||||
:deep {
|
|
||||||
.tagInputareaIuput {
|
|
||||||
overflow: auto;
|
|
||||||
border: 1px solid #409eff;
|
|
||||||
border-radius: 3px;
|
|
||||||
|
|
||||||
&:not(.active) {
|
|
||||||
border-color: #ccc !important;
|
|
||||||
}
|
|
||||||
// &.hasRightIcon {
|
|
||||||
// border-radius: 3px 0 0 3px;
|
|
||||||
// }
|
|
||||||
&.readonlyBg {
|
|
||||||
.CodeMirror {
|
|
||||||
background-color: #eee !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// .rightIcon {
|
|
||||||
// background-color: #f5f5f5;
|
|
||||||
// font-size: 20px;
|
|
||||||
// color: #757575;
|
|
||||||
// height: 34px;
|
|
||||||
// line-height: 33px;
|
|
||||||
// padding: 0 7px;
|
|
||||||
// border: 1px solid #ccc;
|
|
||||||
// border-left: none;
|
|
||||||
// border-radius: 0 3px 3px 0;
|
|
||||||
// }
|
|
||||||
.CodeMirror {
|
|
||||||
box-sizing: border-box;
|
|
||||||
height: auto !important;
|
|
||||||
font-family: inherit !important;
|
|
||||||
|
|
||||||
.CodeMirror-vscrollbar {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
// .CodeMirror-scroll {
|
|
||||||
// height: auto;
|
|
||||||
// overflow-y: hidden;
|
|
||||||
// overflow-x: auto;
|
|
||||||
// }
|
|
||||||
|
|
||||||
.CodeMirror-lines {
|
|
||||||
min-height: 35px;
|
|
||||||
padding: 6px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-line {
|
|
||||||
padding: 0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.columnTagCon {
|
|
||||||
position: relative;
|
|
||||||
display: inline-flex;
|
|
||||||
// box-sizing: border-box;
|
|
||||||
// padding: 2px 4px;
|
|
||||||
// max-width: 100%;
|
|
||||||
// background: #d8eeff;
|
|
||||||
// color: #174c76;
|
|
||||||
// border: 1px solid #bbd6ea;
|
|
||||||
// border-radius: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.columnTag {
|
|
||||||
position: relative;
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: inline-flex;
|
|
||||||
height: 24px;
|
|
||||||
font-size: 12px;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 1px solid #90caf9;
|
|
||||||
border-radius: 24px;
|
|
||||||
|
|
||||||
.columnName,
|
|
||||||
.columnValue {
|
|
||||||
display: inline-block;
|
|
||||||
height: 22px;
|
|
||||||
padding: 0 10px;
|
|
||||||
overflow: hidden;
|
|
||||||
line-height: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.columnName {
|
|
||||||
color: #2196f3;
|
|
||||||
background-color: rgb(33 150 243 / 6%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.columnValue {
|
|
||||||
color: #fff;
|
|
||||||
background-color: #249eff;
|
|
||||||
border-radius: 0 22px 22px 0;
|
|
||||||
|
|
||||||
.ellipsis {
|
|
||||||
max-width: 9em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.onlytag {
|
|
||||||
margin-right: 6px;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
position: absolute;
|
|
||||||
top: 6px;
|
|
||||||
right: -6px;
|
|
||||||
content: ",";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.deleted {
|
|
||||||
border-color: #f44336;
|
|
||||||
|
|
||||||
.columnName {
|
|
||||||
color: #f44336;
|
|
||||||
background-color: rgb(244 67 54 / 6%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: #f44336;
|
|
||||||
|
|
||||||
.columnName {
|
|
||||||
color: #f44336;
|
|
||||||
background-color: rgb(244 67 54 / 12%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: #ddd;
|
|
||||||
|
|
||||||
.columnName {
|
|
||||||
color: #9e9e9e;
|
|
||||||
background-color: rgb(158 158 158 / 6%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.columnValue {
|
|
||||||
background-color: #bdbdbd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.operator {
|
|
||||||
margin: 0 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
/**
|
|
||||||
* getRePosFromStr 正则匹配字段返回位置信息
|
|
||||||
* */
|
|
||||||
export function getRePosFromStr(text: any = "", re: any = /\$.+?\$/g) {
|
|
||||||
const lines = text.split("\n");
|
|
||||||
const positions: any = [];
|
|
||||||
let m;
|
|
||||||
for (let i = 0; i < lines.length; i++) {
|
|
||||||
const l = lines[i];
|
|
||||||
while ((m = re.exec(l)) !== null) {
|
|
||||||
const tag = m[0].substring(1, m[0].length - 1);
|
|
||||||
positions.push({
|
|
||||||
line: i,
|
|
||||||
start: m.index,
|
|
||||||
stop: m.index + m[0].length,
|
|
||||||
tag,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return positions;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 输入框模式
|
|
||||||
*/
|
|
||||||
export enum MODE {
|
|
||||||
// 文本
|
|
||||||
TEXT = 1,
|
|
||||||
// 公式
|
|
||||||
FORMULA,
|
|
||||||
// 只允许选择tag
|
|
||||||
ONLYTAG,
|
|
||||||
// 日期
|
|
||||||
DATE,
|
|
||||||
}
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import TagTextInput from "@/components/TagInput/index.vue";
|
|
||||||
|
|
||||||
//假数据
|
|
||||||
let arrName = new Array(20).fill("tag");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* renderTag 渲染 tag
|
|
||||||
* @param {any} id $$匹配到的之间的值
|
|
||||||
* @param {object} options 一些参数
|
|
||||||
* @return {element} 返回一个dom节点
|
|
||||||
* */
|
|
||||||
const renderTag = (id: any, options: any) => {
|
|
||||||
//拼接tag名称
|
|
||||||
let tagName = `${arrName[Number(id)]}-${id}`;
|
|
||||||
//创建tag元素
|
|
||||||
const ele = document.createElement("div");
|
|
||||||
ele.classList.add("tag-demo-con");
|
|
||||||
ele.innerHTML = `<div class="tag-wrap"><div class="tag">${tagName}</div></div>`;
|
|
||||||
return ele;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 触发增加 tag
|
|
||||||
const refTagTextarea = ref();
|
|
||||||
const addTag = (id: any) => {
|
|
||||||
refTagTextarea.value.insertColumnTag(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 编辑器 change 监听
|
|
||||||
* @param {any} error 默认为 null
|
|
||||||
* @param {string} value 返回编辑器内容
|
|
||||||
* @param {object} obj 返回一个编辑事件描述对象
|
|
||||||
* */
|
|
||||||
const onChange = (error: any, value: string, obj: any): void => {
|
|
||||||
console.log("onChange", error, value, obj);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onFocus = (): void => {
|
|
||||||
console.log("onFocus");
|
|
||||||
};
|
|
||||||
|
|
||||||
const onBlur = (): void => {
|
|
||||||
console.log("onBlur");
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<div class="demo-tagInput">
|
|
||||||
<TagTextInput
|
|
||||||
ref="refTagTextarea"
|
|
||||||
class-name="demo"
|
|
||||||
:default-value="`April$18$`"
|
|
||||||
:readonly="false"
|
|
||||||
:no-cursor="false"
|
|
||||||
:min-height="200"
|
|
||||||
:render-tag="renderTag"
|
|
||||||
@on-change="onChange"
|
|
||||||
@on-focus="onFocus"
|
|
||||||
@on-blur="onBlur"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div class="tag-wrap">
|
|
||||||
<el-button v-for="item in 5" :key="item" @click="addTag(item)">
|
|
||||||
{{ item }}</el-button
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.demo-tagInput {
|
|
||||||
width: 500px;
|
|
||||||
height: auto;
|
|
||||||
margin: 10px;
|
|
||||||
|
|
||||||
:deep {
|
|
||||||
.tag-demo-con {
|
|
||||||
.tag-wrap {
|
|
||||||
height: 25px;
|
|
||||||
line-height: 25px;
|
|
||||||
|
|
||||||
.tag {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: inline-block;
|
|
||||||
padding: 2px 8px;
|
|
||||||
margin: 0 4px;
|
|
||||||
color: #174c76;
|
|
||||||
background: #d8eeff;
|
|
||||||
border: 1px solid #bbd6ea;
|
|
||||||
border-radius: 16px;
|
|
||||||
}
|
|
||||||
// padding: 4px;
|
|
||||||
// margin: 4px;
|
|
||||||
// border: 1px solid #ccc;
|
|
||||||
// border-radius: 5px;
|
|
||||||
// line-height: 1em;
|
|
||||||
// min-width: 25px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag-wrap {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -12,15 +12,12 @@ import IconsResolver from "unplugin-icons/resolver";
|
||||||
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
|
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
|
||||||
|
|
||||||
import { viteMockServe } from "vite-plugin-mock";
|
import { viteMockServe } from "vite-plugin-mock";
|
||||||
import visualizer from "rollup-plugin-visualizer";
|
|
||||||
|
|
||||||
import UnoCSS from "unocss/vite";
|
import UnoCSS from "unocss/vite";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
import viteCompression from "vite-plugin-compression";
|
|
||||||
|
|
||||||
const pathSrc = path.resolve(__dirname, "src");
|
const pathSrc = path.resolve(__dirname, "src");
|
||||||
|
/** 参考Vite官方配置: https://cn.vitejs.dev/config */
|
||||||
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
||||||
const env = loadEnv(mode, process.cwd());
|
const env = loadEnv(mode, process.cwd());
|
||||||
|
|
||||||
|
|
@ -102,35 +99,17 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
||||||
// 自动安装图标库
|
// 自动安装图标库
|
||||||
autoInstall: true,
|
autoInstall: true,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
createSvgIconsPlugin({
|
createSvgIconsPlugin({
|
||||||
// 指定需要缓存的图标文件夹
|
// 指定需要缓存的图标文件夹
|
||||||
iconDirs: [path.resolve(pathSrc, "assets/icons")],
|
iconDirs: [path.resolve(pathSrc, "assets/icons")],
|
||||||
// 指定symbolId格式
|
// 指定symbolId格式
|
||||||
symbolId: "icon-[dir]-[name]",
|
symbolId: "icon-[dir]-[name]",
|
||||||
}),
|
}),
|
||||||
// 代码压缩
|
// https://github.com/anncwb/vite-plugin-mock/issues/9
|
||||||
viteCompression({
|
|
||||||
verbose: true, // 默认即可
|
|
||||||
disable: true, // 是否禁用压缩,默认禁用,true为禁用,false为开启,打开压缩需配置nginx支持
|
|
||||||
deleteOriginFile: true, // 删除源文件
|
|
||||||
threshold: 10240, // 压缩前最小文件大小
|
|
||||||
algorithm: "gzip", // 压缩算法
|
|
||||||
ext: ".gz", // 文件类型
|
|
||||||
}),
|
|
||||||
|
|
||||||
viteMockServe({
|
viteMockServe({
|
||||||
ignore: /^\_/,
|
ignore: /^\_/,
|
||||||
mockPath: "mock",
|
mockPath: "mock",
|
||||||
enable: mode === "development",
|
enable: mode === "development",
|
||||||
// https://github.com/anncwb/vite-plugin-mock/issues/9
|
|
||||||
}),
|
|
||||||
|
|
||||||
visualizer({
|
|
||||||
filename: "./stats.html",
|
|
||||||
open: false,
|
|
||||||
gzipSize: true,
|
|
||||||
brotliSize: true,
|
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
// 预加载项目必需的组件
|
// 预加载项目必需的组件
|
||||||
|
|
@ -193,7 +172,6 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
||||||
"@wangeditor/editor",
|
"@wangeditor/editor",
|
||||||
"@wangeditor/editor-for-vue",
|
"@wangeditor/editor-for-vue",
|
||||||
"vue-i18n",
|
"vue-i18n",
|
||||||
"codemirror",
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue