feat: 重构图标选择器组件

Former-commit-id: c47cd1e04c56da514d3649c36a8d15ce890078f4
This commit is contained in:
haoxr
2023-01-14 17:31:28 +08:00
parent 00c52cf5ce
commit ed7afec7c6
6 changed files with 84 additions and 195 deletions

View File

@@ -1 +0,0 @@
<svg t="1662278390164" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9866" width="200" height="200"><path d="M544.059897 959.266898h-64.949141c-228.633593 0-415.697442-187.063849-415.697442-415.697442v-64.949141c0-228.633593 187.063849-415.697442 415.697442-415.697442h64.949141c228.633593 0 415.697442 187.063849 415.697442 415.697442v64.949141c-0.001024 228.633593-187.064873 415.697442-415.697442 415.697442z" fill="#5EAADE" p-id="9867"></path><path d="M729.459932 627.30075c-3.156638-39.628458-24.044923-83.747676-32.624058-105.910698l-22.084182-57.046794c-0.701361-23.73059 6.312253-78.322108-30.510759-146.611164s-110.820228-74.444654-124.497288-75.146016c-13.67706-0.701361-99.247252-1.402723-141.330987 72.944663-42.083735 74.347385-30.744205 148.812517-30.744205 148.812517l-23.523765 57.47785c-0.001024 0.002048-10.961716 26.222727-20.429584 58.135185-9.468891 31.913482-18.937783 82.063385-9.468892 92.233638 9.468891 10.170253 43.836626-46.643096 46.993265-51.902795 0 0 2.455277 27.179036 8.942615 41.382373l0.809893 1.776441 0.330715 0.722863 0.378837 0.826276 0.299999 0.652215 0.444366 0.960404 0.202729 0.435151a281.465052 281.465052 0 0 0 1.917738 4.024893l0.188394 0.386005c0.231398 0.473035 0.467916 0.953237 0.711601 1.442655l0.145391 0.291807c6.886653 13.807094 18.611164 33.823028 37.443487 50.420209l0.017406 0.015358-1.183612 0.387029c-10.666837 3.516022-31.69437 11.209497-40.624698 19.819348-1.717056 1.655623-2.987697 3.345033-3.650151 5.045707-5.376422 13.793783 4.208169 15.430976 20.574976 16.365783 16.365783 0.934807 94.922361 3.039916 132.563457-2.220807 0.407506-0.056314 0.787368-0.113651 1.171325-0.170989 2.710224 0.094197 5.32318 0.14232 7.828627 0.16075l0.151535 0.001024c0.83549 0.005119 1.66279 0.008191 2.474731 0.008191 0.496584 0 1.01467-0.002048 1.541971-0.006144l0.209896-0.001023a222.59267 222.59267 0 0 0 5.462429-0.106484c0.260067 0.037884 0.507847 0.075768 0.778152 0.113651 37.64212 5.260723 116.197674 3.156638 132.563457 2.220807 16.365783-0.934807 25.951397-2.572 20.573952-16.365783-4.301342-11.03646-34.17422-21.619339-45.956069-25.412834a141.388325 141.388325 0 0 0 7.958661-7.645351l0.236517-0.244709a142.494121 142.494121 0 0 0 2.531045-2.702033c42.433903-46.643096 38.927096-76.101301 40.681011-92.935 0 0 35.775577 51.552626 43.488506 53.306542 7.712928 1.753916 10.168205-6.311229 7.011566-45.940711z" fill="#FFFFFF" p-id="9868"></path></svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -1 +0,0 @@
<svg t="1662278315988" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3147" width="200" height="200"><path d="M347.729118 353.0242c-16.487119 0-29.776737 13.389539-29.776737 29.776737S331.241998 412.677596 347.729118 412.677596s29.776737-13.389539 29.776737-29.776737-13.289617-29.876659-29.776737-29.876659zM577.749415 511.800156c-13.689305 0-24.880562 11.091335-24.880563 24.880562 0 13.689305 11.091335 24.880562 24.880563 24.880562 13.689305 0 24.880562-11.191257 24.880562-24.880562s-11.191257-24.880562-24.880562-24.880562zM500.909446 412.677596c16.487119 0 29.776737-13.389539 29.776737-29.776737s-13.389539-29.776737-29.776737-29.776737c-16.487119 0-29.776737 13.389539-29.776737 29.776737s13.289617 29.776737 29.776737 29.776737zM698.455113 511.600312c-13.689305 0-24.880562 11.091335-24.880562 24.880562 0 13.689305 11.091335 24.880562 24.880562 24.880562 13.689305 0 24.880562-11.091335 24.880562-24.880562-0.099922-13.689305-11.191257-24.880562-24.880562-24.880562z" fill="#00C800" p-id="3148"></path><path d="M511.601093 0.799375C229.12178 0.799375 0.000781 229.820453 0.000781 512.399688s229.021077 511.600312 511.600312 511.600312 511.600312-229.021077 511.600312-511.600312S794.180328 0.799375 511.601093 0.799375z m-90.229508 634.504294c-27.37861 0-49.361436-5.595628-76.839969-10.991413l-76.640125 38.469945 21.882904-65.948477c-54.957065-38.370023-87.73146-87.831382-87.73146-148.084309 0-104.318501 98.722873-186.554254 219.32865-186.554255 107.815769 0 202.34192 65.648712 221.327088 153.979703-6.994536-0.799375-13.989071-1.298985-21.083529-1.298985-104.118657 0-186.454333 77.739266-186.454332 173.564403 0 15.98751 2.498048 31.275566 6.794692 45.964091-6.794692 0.599532-13.689305 0.899297-20.583919 0.899297z m323.547228 76.839969l16.48712 54.757221-60.153006-32.874317c-21.882904 5.495706-43.965652 10.991413-65.848555 10.991413-104.318501 0-186.554254-71.344262-186.554255-159.175644 0-87.631538 82.135831-159.175644 186.554255-159.175644 98.523029 0 186.254489 71.444184 186.254488 159.175644 0.099922 49.461358-32.774395 93.227166-76.740047 126.301327z" fill="#00C800" p-id="3149"></path></svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -3,24 +3,57 @@ const props = defineProps({
modelValue: {
type: String,
require: false
},
/**
* 选择器宽度
*/
width: {
type: String,
require: false,
default: '400px'
}
});
const emit = defineEmits(['update:modelValue']);
const visible = ref(false);
const inputValue = toRef(props, 'modelValue');
const iconList = ref<string[]>([]);
const width = toRef(props, 'width');
const iconNames: string[] = [];
const filterIconNames = ref<string[]>([]);
const filterValue = ref('');
const icon = ref('perm');
function loadIcons() {
const modules = import.meta.glob('../../assets/icons/*.svg');
for (const path in modules) {
const icon = path.split('assets/icons/')[1].split('.svg')[0];
iconList.value.push(icon);
const icons = import.meta.glob('../../assets/icons/*.svg');
for (const icon in icons) {
const iconName = icon.split('assets/icons/')[1].split('.svg')[0];
iconNames.push(iconName);
}
filterIconNames.value = iconNames;
}
/**
* 筛选图标
*/
function handleIconFilter() {
console.log('筛选关键字', filterValue.value);
if (filterValue.value) {
filterIconNames.value = filterIconNames.value.filter(iconName =>
iconName.includes(filterValue.value)
);
} else {
filterIconNames.value = iconNames;
}
}
/**
* 选择图标
*
* @param iconName 选择的图标名称
*/
function onIconSelect(iconName: string) {
emit('update:modelValue', iconName);
visible.value = false;
}
onMounted(() => {
@@ -29,9 +62,16 @@ onMounted(() => {
</script>
<template>
<div class="w-[400px] relative">
<el-input v-model="inputValue" readonly>
<template #prepend> <svg-icon :iconName="icon"></svg-icon> </template>
<div class="relative" :style="{ width: width }">
<el-input
v-model="inputValue"
readonly
@click="visible = !visible"
placeholder="点击选择图标"
>
<template #prepend>
<svg-icon :iconName="inputValue"></svg-icon>
</template>
</el-input>
<el-popover
@@ -39,6 +79,7 @@ onMounted(() => {
:visible="visible"
placement="bottom-end"
trigger="click"
:width="400"
>
<template #reference>
<div
@@ -56,14 +97,21 @@ onMounted(() => {
v-model="filterValue"
placeholder="搜索图标"
clearable
@input="handleIconFilter"
/>
<el-divider border-style="dashed" />
<el-scrollbar height="300px">
<ul class="icon-list">
<li class="icon-item" v-for="(item, index) in iconList" :key="index">
<svg-icon color="#999" :icon-name="item" />
<span>{{ item }}</span>
<li
class="icon-item"
v-for="(iconName, index) in filterIconNames"
:key="index"
@click="onIconSelect(iconName)"
>
<el-tooltip :content="iconName" placement="bottom" effect="light">
<svg-icon color="#999" :icon-name="iconName" />
</el-tooltip>
</li>
</ul>
</el-scrollbar>
@@ -72,13 +120,30 @@ onMounted(() => {
</template>
<style scoped lang="scss">
.el-divider--horizontal {
margin: 10px auto !important;
}
.icon-list {
display: flex;
flex-wrap: wrap;
padding-left: 10px;
margin-top: 10px;
.icon-item {
cursor: pointer;
width: 10%;
margin: 0 10px 10px 0;
padding: 5px;
display: flex;
flex-direction: column;
justify-items: center;
align-items: center;
border: 1px solid #ccc;
&:hover {
border-color: var(--el-color-primary);
color: var(--el-color-primary);
transition: all 0.4s;
transform: scaleX(1.05);
transition: all 0.2s;
transform: scaleX(1.1);
}
}
}

View File

@@ -54,24 +54,10 @@ function logout() {
<breadcrumb />
</div>
<mix-nav v-if="device !== 'mobile' && layout === 'mix'" />
<!-- 宽屏或左侧模式显示 -->
<div
v-if="device === 'desktop' || layout === 'left'"
class="flex justify-start"
>
<!-- 左侧窄屏不显示 -->
<!-- 宽屏显示 -->
<div class="flex justify-start">
<!-- 窄屏不显示 -->
<div v-if="device !== 'mobile'" class="flex justify-center items-center">
<i-ep-add-location />
<i-ep-aim />
<div i-ep-check />
<el-button>
<template #icon><i-ep-circle-check-filled /></template>
Hello world
</el-button>
<!--全屏 -->
<screenfull id="screenfull" />

View File

@@ -1,153 +0,0 @@
<script setup lang="ts">
import { computed, onMounted } from 'vue';
import { RouterLink, useRoute, useRouter } from 'vue-router';
import {
ElDropdown,
ElDropdownItem,
ElDropdownMenu,
ElMenu,
ElMessageBox,
ElTooltip
} from 'element-plus';
import Screenfull from '@/components/Screenfull/index.vue';
import SizeSelect from '@/components/SizeSelect/index.vue';
import LangSelect from '@/components/LangSelect/index.vue';
import { CaretBottom } from '@element-plus/icons-vue';
import SidebarItem from './SidebarItem.vue';
import variables from '@/styles/variables.module.scss';
import { useTagsViewStore } from '@/store/modules/tagsView';
import { useUserStore } from '@/store/modules/user';
import { usePermissionStore } from '@/store/modules/permission';
const tagsViewStore = useTagsViewStore();
const userStore = useUserStore();
const permissionStore = usePermissionStore();
const route = useRoute();
const router = useRouter();
const routes = [] as any[];
onMounted(() => {
console.log('origin routes', permissionStore.routes);
permissionStore.routes.forEach(item => {
const { children, ...newItem } = item;
routes.push(newItem);
});
console.log('routes', routes);
});
const activeMenu = computed<string>(() => {
const { meta, path } = route;
if (meta?.activeMenu) {
return meta.activeMenu as string;
}
return path;
});
function logout() {
ElMessageBox.confirm('确定注销并退出系统吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
userStore
.logout()
.then(() => {
tagsViewStore.delAllViews();
})
.then(() => {
router.push(`/login?redirect=${route.fullPath}`);
});
});
}
</script>
<template>
<div class="horizontal-header">
<el-menu
class="horizontal-header-menu"
:default-active="activeMenu"
:background-color="variables.menuBg"
:text-color="variables.menuText"
:active-text-color="variables.menuActiveText"
mode="horizontal"
>
<sidebar-item
v-for="route in routes"
:item="route"
:key="route.path"
:base-path="route.path"
/>
</el-menu>
<div class="horizontal-header-right">
<!--全屏 -->
<screenfull id="screenfull" />
<!-- 布局大小 -->
<el-tooltip content="布局大小" effect="dark" placement="bottom">
<size-select />
</el-tooltip>
<!--语言选择-->
<lang-select />
<el-dropdown trigger="click">
<div class="flex justify-center items-center pr-[20px]">
<img
:src="userStore.avatar + '?imageView2/1/w/80/h/80'"
class="w-[40px] h-[40px] rounded-lg"
/>
<CaretBottom class="w-3 h-3" />
</div>
<template #dropdown>
<el-dropdown-menu>
<router-link to="/">
<el-dropdown-item>{{ $t('navbar.dashboard') }}</el-dropdown-item>
</router-link>
<a target="_blank" href="https://github.com/hxrui">
<el-dropdown-item>Github</el-dropdown-item>
</a>
<a target="_blank" href="https://gitee.com/haoxr">
<el-dropdown-item>{{ $t('navbar.gitee') }}</el-dropdown-item>
</a>
<a target="_blank" href="https://www.cnblogs.com/haoxianrui/">
<el-dropdown-item>{{ $t('navbar.document') }}</el-dropdown-item>
</a>
<el-dropdown-item divided @click="logout">
{{ $t('navbar.logout') }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</template>
<style lang="scss" scoped>
.horizontal-header {
display: flex;
width: 100%;
align-items: center;
justify-content: space-around;
background: #001529;
&-menu {
height: 100%;
width: 100%;
border: none;
background-color: transparent;
}
&-right {
display: flex;
min-width: 340px;
align-items: center;
justify-content: flex-end;
color: #fff;
}
}
</style>

View File

@@ -127,6 +127,7 @@
:title="dialog.title"
v-model="dialog.visible"
@close="cancel"
destroy-on-close
width="750px"
>
<el-form
@@ -469,14 +470,6 @@ function cancel() {
state.dialog.visible = false;
}
/**
* 选择图标后事件
*/
function selected(name: string) {
state.formData.icon = name;
state.iconSelectVisible = false;
}
onMounted(() => {
handleQuery();
});