feat: 🚀 菜单图标搜索

This commit is contained in:
Bunny 2024-10-05 21:10:19 +08:00
parent 87e46ca1e2
commit 824efa6b51
8 changed files with 165 additions and 6 deletions

View File

@ -153,6 +153,7 @@ export default defineFlatConfig([
'no-undef': 'off',
'no-unused-vars': 'off',
'vue/no-v-html': 'off',
'vue/no-mutating-props': 'off',
'vue/require-default-prop': 'off',
'vue/require-explicit-emits': 'off',
'vue/multi-word-component-names': 'off',

View File

@ -28,3 +28,11 @@ export const fetchUpdateMenuIcon = (data: any) => {
export const fetchDeleteMenuIcon = (data: any) => {
return http.request<BaseResult<object>>('delete', 'menuIcon/deleteMenuIcon', { data });
};
/**
* ---iconName搜索menuIc
* @param data
*/
export const fetchGetIconNameList = (data: any) => {
return http.request<BaseResult<object>>('get', 'menuIcon/getIconNameList', { params: data });
};

View File

@ -0,0 +1,12 @@
<svg class="circular" viewBox="0 0 20 20">
<g
class="path2 loading-path"
stroke-width="0"
style="animation: none; stroke: none"
>
<circle r="3.375" class="dot1" rx="0" ry="0"/>
<circle r="3.375" class="dot2" rx="0" ry="0"/>
<circle r="3.375" class="dot4" rx="0" ry="0"/>
<circle r="3.375" class="dot3" rx="0" ry="0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 364 B

View File

@ -14,13 +14,13 @@ import userAvatar from '@/assets/user.jpg';
import { fetchForcedOffline, fetchUploadAvatarByAdmin } from '@/api/v1/user';
import { useUserStore } from '@/store/system/user';
const adminUserStore = useAdminUserStore();
const userStore = useUserStore();
export const formRef = ref();
const cropRef = ref();
const assignRolesRef = ref();
const userStore = useUserStore();
// 上传头像信息
const avatarInfo = ref();
const adminUserStore = useAdminUserStore();
// 重置密码表单校验Ref
const ruleFormByRestPasswordRef = ref();
// 重置密码表单

View File

@ -105,9 +105,9 @@ onMounted(() => {
@page-current-change="onCurrentPageChange"
@selection-change="onSelectionChange"
>
<template #iconName="{ row }">
<div class="flex justify-center">
<component :is="useRenderIcon(row.iconName)" class="flex justify-center" style="font-size: 30px" />
<template #iconCode="{ row }">
<div v-tippy="{ content: row.iconCode }" class="flex justify-center">
<component :is="useRenderIcon(row.iconCode)" class="flex justify-center" style="font-size: 30px" />
</div>
</template>

View File

@ -5,6 +5,7 @@ import { rules } from '@/views/system/menuIcon/utils/columns';
import { FormProps } from '@/views/system/menuIcon/utils/types';
import { $t } from '@/plugins/i18n';
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
import MenuIconSelectIconName from '@/views/system/menuIcon/menu-icon-select-icon-name.vue';
const props = withDefaults(defineProps<FormProps>(), {
formInline: () => ({
@ -25,7 +26,7 @@ defineExpose({ formRef });
<el-input v-model="form.iconCode" autocomplete="off" type="text" />
</el-form-item>
<el-form-item :label="$t('menuIcon_iconName')" prop="iconName">
<el-input v-model="form.iconName" autocomplete="off" type="text" />
<MenuIconSelectIconName :form="form" />
</el-form-item>
<el-form-item v-show="form.iconCode" :label="$t('menuIcon_preview')">

View File

@ -0,0 +1,135 @@
<script lang="ts" setup>
import { $t } from '@/plugins/i18n';
import { ref } from 'vue';
import { fetchGetIconNameList } from '@/api/v1/menuIcon';
import LoadingSvg from '@/assets/svg/loading.svg';
defineProps({
form: { type: Object as PropType<any> },
});
const loading = ref(false);
const iconNameList = ref([]);
/**
* * 搜索
*/
const onRequestIconName = async (iconName: string) => {
const data = { currentPage: 1, pageSize: 20, iconName };
loading.value = true;
if (iconName) {
const result = await fetchGetIconNameList(data);
if (result.code === 200) iconNameList.value = result.data;
} else iconNameList.value = [];
loading.value = false;
};
</script>
<template>
<el-select
v-model="form.iconName"
:loading="loading"
:placeholder="$t('input') + $t('menuIcon_iconName')"
:remote-method="onRequestIconName"
allow-create
clearable
filterable
remote
remote-show-suffix
>
<el-option v-for="menuIcon in iconNameList" :key="menuIcon.id" :label="menuIcon.iconName" :value="menuIcon.iconName" />
<template #loading>
<el-icon class="is-loading">
<LoadingSvg />
</el-icon>
</template>
</el-select>
</template>
<style>
.el-select-dropdown__loading {
display: flex;
align-items: center;
justify-content: center;
height: 100px;
font-size: 20px;
}
.circular {
display: inline;
width: 30px;
height: 30px;
animation: loading-rotate 2s linear infinite;
}
.path {
stroke: var(--el-color-primary);
stroke-dasharray: 90, 150;
stroke-dashoffset: 0;
stroke-linecap: round;
stroke-width: 2;
animation: loading-dash 1.5s ease-in-out infinite;
}
.loading-path .dot1 {
opacity: 0.3;
fill: var(--el-color-primary);
transform: translate(3.75px, 3.75px);
animation: custom-spin-move 1s infinite linear alternate;
}
.loading-path .dot2 {
opacity: 0.3;
fill: var(--el-color-primary);
transform: translate(calc(100% - 3.75px), 3.75px);
animation: custom-spin-move 1s infinite linear alternate;
animation-delay: 0.4s;
}
.loading-path .dot3 {
opacity: 0.3;
fill: var(--el-color-primary);
transform: translate(3.75px, calc(100% - 3.75px));
animation: custom-spin-move 1s infinite linear alternate;
animation-delay: 1.2s;
}
.loading-path .dot4 {
opacity: 0.3;
fill: var(--el-color-primary);
transform: translate(calc(100% - 3.75px), calc(100% - 3.75px));
animation: custom-spin-move 1s infinite linear alternate;
animation-delay: 0.8s;
}
@keyframes loading-rotate {
to {
transform: rotate(360deg);
}
}
@keyframes loading-dash {
0% {
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -40px;
}
100% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -120px;
}
}
@keyframes custom-spin-move {
to {
opacity: 1;
}
}
</style>

View File

@ -1,5 +1,7 @@
// 添加或者修改表单元素
export interface FormItemProps {
// icon类名
iconCode: string;
// icon 名称
iconName: string;
}