'admin-21.03.04:新增图标选择器、优化图标自动载入逻辑等'

This commit is contained in:
lyt-Top 2021-03-04 21:57:25 +08:00
parent f3643271a7
commit c7c5bb7b94
7 changed files with 271 additions and 73 deletions

View File

@ -0,0 +1,95 @@
<template>
<div class="icon-selector">
<el-popover placement="bottom" :width="fontIconWidth" v-model:visible="fontIconVisible"
popper-class="icon-selector-popper">
<template #reference>
<el-input v-model="fontIcon" placeholder="请点击选择图标" clearable size="small" ref="inputWidthRef"
:prefix-icon="fontIconPrefix" @clear="onClearFontIcon"></el-input>
</template>
<transition name="el-zoom-in-top">
<div class="icon-selector-warp" v-show="fontIconVisible">
<div class="icon-selector-warp-title">请选择一个图标</div>
<el-row class="icon-selector-warp-row">
<el-col :xs="4" :sm="2" :md="2" :lg="2" :xl="2" v-for="(v,k) in sheetsIconList" :key="k"
@click="onColClick(v)">
<div class="icon-selector-warp-item">
<div class="flex-margin">
<div class="icon-selector-warp-item-value">
<i :class="v" class="iconfont fa"></i>
</div>
</div>
</div>
</el-col>
</el-row>
</div>
</transition>
</el-popover>
</div>
</template>
<script lang="ts">
import { ref, toRefs, reactive, onMounted, nextTick } from "vue";
import initIconfont from "/@/utils/getStyleSheets.ts";
import { stat } from "node:fs";
export default {
name: "iconSelector",
props: {
isAllOn: {
type: Boolean,
default: () => false,
},
},
setup(props, { emit }) {
console.log(props);
const inputWidthRef = ref();
const state = reactive({
fontIcon: "",
fontIconPrefix: "",
fontIconVisible: false,
fontIconWidth: 0,
sheetsIconList: [],
});
// input
const getInputWidth = () => {
nextTick(() => {
state.fontIconWidth = inputWidthRef.value.$el.offsetWidth;
});
};
//
const initResize = () => {
window.addEventListener("resize", () => {
getInputWidth();
});
};
//
const initFontIconData = () => {
initIconfont.ali().then((res) => {
state.sheetsIconList = res;
});
};
//
const onColClick = (v) => {
state.fontIcon = v;
state.fontIconPrefix = `iconfont fa ${v}`;
state.fontIconVisible = false;
emit("get", state.fontIconPrefix);
};
// input
const onClearFontIcon = () => {
state.fontIconPrefix = "";
};
//
onMounted(() => {
initFontIconData();
initResize();
getInputWidth();
});
return {
inputWidthRef,
onColClick,
onClearFontIcon,
...toRefs(state),
};
},
};
</script>

View File

@ -957,3 +957,44 @@
height: 100%; height: 100%;
overflow: auto; overflow: auto;
} }
/* Popover 弹出框
------------------------------- */
.icon-selector-popper {
padding: 0 !important;
.icon-selector-warp-title {
height: 40px;
line-height: 40px;
padding: 0 15px;
}
.icon-selector-warp {
.icon-selector-warp-row {
border-top: 1px solid #ebeef5;
border-left: 1px solid #ebeef5;
max-height: 260px;
overflow-y: auto;
.icon-selector-warp-item {
display: flex;
border-right: 1px solid #ebeef5;
border-bottom: 1px solid #ebeef5;
padding: 10px;
.icon-selector-warp-item-value {
transition: all 0.3s ease;
i {
font-size: 20px;
color: #606266;
}
}
&:hover {
cursor: pointer;
.icon-selector-warp-item-value {
i {
color: var(--color-primary);
transition: all 0.3s ease;
}
}
}
}
}
}
}

111
src/utils/getStyleSheets.ts Normal file
View File

@ -0,0 +1,111 @@
import { nextTick } from "vue"
// 获取阿里字体图标
const getAlicdnIconfont = () => {
return new Promise((resolve, reject) => {
nextTick(() => {
const styles: any = document.styleSheets
let sheetsList = []
let sheetsIconList = []
for (let i = 0; i < styles.length; i++) {
if (styles[i].href && styles[i].href.indexOf("at.alicdn.com") > -1) {
sheetsList.push(styles[i])
}
}
for (let i = 0; i < sheetsList.length; i++) {
for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
if (
sheetsList[i].cssRules[j].selectorText &&
sheetsList[i].cssRules[j].selectorText.indexOf(".icon-") > -1
) {
sheetsIconList.push(
`${sheetsList[i].cssRules[j].selectorText
.substring(1, sheetsList[i].cssRules[j].selectorText.length)
.replace(/\:\:before/gi, "")}`
)
}
}
}
if (sheetsIconList.length > 0) resolve(sheetsIconList)
else reject('未获取到值,请刷新重试')
})
})
}
// 初始化获取 css 样式,获取 element plus 自带图标
const elementPlusIconfont = () => {
return new Promise((resolve, reject) => {
nextTick(() => {
const styles: any = document.styleSheets
let sheetsIconList = []
for (let i = 0; i < styles.length; i++) {
for (let j = 0; j < styles[i].cssRules.length; j++) {
if (
styles[i].cssRules[j].selectorText &&
styles[i].cssRules[j].selectorText.indexOf(".el-icon-") === 0
) {
sheetsIconList.push(
`${styles[i].cssRules[j].selectorText
.substring(1, styles[i].cssRules[j].selectorText.length)
.replace(/\:\:before/gi, "")}`
)
}
}
}
if (sheetsIconList.length > 0) resolve(sheetsIconList)
else reject('未获取到值,请刷新重试')
})
})
}
// 初始化获取 css 样式,这里使用 fontawesome 的图标
const awesomeIconfont = () => {
return new Promise((resolve, reject) => {
nextTick(() => {
const styles: any = document.styleSheets
let sheetsList = []
let sheetsIconList = []
for (let i = 0; i < styles.length; i++) {
if (
styles[i].href &&
styles[i].href.indexOf("netdna.bootstrapcdn.com") > -1
) {
sheetsList.push(styles[i])
}
}
for (let i = 0; i < sheetsList.length; i++) {
for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
if (
sheetsList[i].cssRules[j].selectorText &&
sheetsList[i].cssRules[j].selectorText.indexOf(".fa-") === 0 &&
sheetsList[i].cssRules[j].selectorText.indexOf(",") === -1
) {
sheetsIconList.push(
`${sheetsList[i].cssRules[j].selectorText
.substring(1, sheetsList[i].cssRules[j].selectorText.length)
.replace(/\:\:before/gi, "")}`
)
}
}
}
if (sheetsIconList.length > 0) resolve(sheetsIconList)
else reject('未获取到值,请刷新重试')
})
})
}
// 定义导出方法集合
const initIconfont = {
ali: () => {
return getAlicdnIconfont()
},
ele: () => {
return elementPlusIconfont()
},
awe: () => {
return awesomeIconfont()
}
}
// 导出方法
export default initIconfont

View File

@ -1,14 +1,26 @@
<template> <template>
<div class="selector-container"></div> <div class="selector-container">
<el-card shadow="hover" header="1、图标选择器简单版本">
<IconSelector @get="ongetCurrentIcon" />
</el-card>
<el-card shadow="hover" header="2、图标选择器高级版本" class="mt15"></el-card>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { toRefs, reactive } from "vue"; import { toRefs, reactive } from "vue";
import IconSelector from "/@/components/iconSelector/index.vue";
export default { export default {
name: "selector", name: "selector",
components: { IconSelector },
setup() { setup() {
const state = reactive({}); const state = reactive({});
// icon
const ongetCurrentIcon = (v) => {
console.log(v);
};
return { return {
ongetCurrentIcon,
...toRefs(state), ...toRefs(state),
}; };
}, },

View File

@ -20,42 +20,17 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { toRefs, reactive, nextTick, onMounted } from "vue"; import { toRefs, reactive, onMounted } from "vue";
import initIconfont from "/@/utils/getStyleSheets.ts";
export default { export default {
name: "awesome", name: "awesome",
setup() { setup() {
const state = reactive({ const state = reactive({
sheetsIconList: [], sheetsIconList: [],
}); });
// css 使( `iconfont`) // css 使fontawesome( `fa`)
const initGetStyleSheets = () => { const initGetStyleSheets = () => {
nextTick(() => { initIconfont.awe().then((res) => (state.sheetsIconList = res));
const styles = document.styleSheets;
let sheetsList = [];
for (let i = 0; i < styles.length; i++) {
if (
styles[i].href &&
styles[i].href.indexOf("netdna.bootstrapcdn.com") > -1
) {
sheetsList.push(styles[i]);
}
}
for (let i = 0; i < sheetsList.length; i++) {
for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
if (
sheetsList[i].cssRules[j].selectorText &&
sheetsList[i].cssRules[j].selectorText.indexOf(".fa-") === 0 &&
sheetsList[i].cssRules[j].selectorText.indexOf(",") === -1
) {
state.sheetsIconList.push(
`${sheetsList[i].cssRules[j].selectorText
.substring(1, sheetsList[i].cssRules[j].selectorText.length)
.replace(/\:\:before/gi, "")}`
);
}
}
}
});
}; };
// //
onMounted(() => { onMounted(() => {

View File

@ -20,32 +20,17 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { toRefs, reactive, nextTick, onMounted } from "vue"; import { toRefs, reactive, onMounted } from "vue";
import initIconfont from "/@/utils/getStyleSheets.ts";
export default { export default {
name: "element", name: "element",
setup() { setup() {
const state = reactive({ const state = reactive({
sheetsIconList: [], sheetsIconList: [],
}); });
// css 使( `iconfont`) // css element plus
const initGetStyleSheets = () => { const initGetStyleSheets = () => {
nextTick(() => { initIconfont.ele().then((res) => (state.sheetsIconList = res));
const styles = document.styleSheets;
for (let i = 0; i < styles.length; i++) {
for (let j = 0; j < styles[i].cssRules.length; j++) {
if (
styles[i].cssRules[j].selectorText &&
styles[i].cssRules[j].selectorText.indexOf(".el-icon-") === 0
) {
state.sheetsIconList.push(
`${styles[i].cssRules[j].selectorText
.substring(1, styles[i].cssRules[j].selectorText.length)
.replace(/\:\:before/gi, "")}`
);
}
}
}
});
}; };
// //
onMounted(() => { onMounted(() => {

View File

@ -18,7 +18,8 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { toRefs, reactive, nextTick, onMounted } from "vue"; import { toRefs, reactive, onMounted } from "vue";
import initIconfont from "/@/utils/getStyleSheets.ts";
export default { export default {
name: "iconfont", name: "iconfont",
setup() { setup() {
@ -27,29 +28,7 @@ export default {
}); });
// css 使( `iconfont`) // css 使( `iconfont`)
const initGetStyleSheets = () => { const initGetStyleSheets = () => {
nextTick(() => { initIconfont.ali().then((res) => (state.sheetsIconList = res));
const styles = document.styleSheets;
let sheetsList = [];
for (let i = 0; i < styles.length; i++) {
if (styles[i].href && styles[i].href.indexOf("at.alicdn.com") > -1) {
sheetsList.push(styles[i]);
}
}
for (let i = 0; i < sheetsList.length; i++) {
for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
if (
sheetsList[i].cssRules[j].selectorText &&
sheetsList[i].cssRules[j].selectorText.indexOf(".icon-") > -1
) {
state.sheetsIconList.push(
`${sheetsList[i].cssRules[j].selectorText
.substring(1, sheetsList[i].cssRules[j].selectorText.length)
.replace(/\:\:before/gi, "")}`
);
}
}
}
});
}; };
// //
onMounted(() => { onMounted(() => {