feat: 高级筛选样式及交互调整,搜索限制调整

pull/13/head
刘释隆 1 year ago
parent 63356a7179
commit 8370576e21

@ -1,20 +1,29 @@
<script lang="ts"> <script lang="ts">
import { useDialog, useMessage } from 'naive-ui' import { useDialog, useMessage } from "naive-ui";
import { defineComponent, inject, onMounted, reactive, ref, toRefs, unref, watch } from 'vue' import {
import { useRoute, useRouter } from 'vue-router' defineComponent,
import QuillModal from './QuillModal.vue' inject,
import RecycleModal from './RecycleModal.vue' onMounted,
import SearchModal from './SearchModal.vue' reactive,
import ShortcutModal from './ShortcutModal.vue' ref,
import UserSettings from './UserSettings.vue' toRefs,
import { msgPolling } from '@/api/message/message' unref,
import { getImgUrl } from '@/utils/urlUtils' watch,
import { useUser } from '@/store/modules/user' } from "vue";
import { useTaskStore } from '@/store/modules/task' import { useRoute, useRouter } from "vue-router";
import QuillModal from "./QuillModal.vue";
const taskStore = useTaskStore() import RecycleModal from "./RecycleModal.vue";
import SearchModal from "./SearchModal.vue";
import ShortcutModal from "./ShortcutModal.vue";
import UserSettings from "./UserSettings.vue";
import { msgPolling } from "@/api/message/message";
import { getImgUrl } from "@/utils/urlUtils";
import { useUser } from "@/store/modules/user";
import { useTaskStore } from "@/store/modules/task";
const taskStore = useTaskStore();
export default defineComponent({ export default defineComponent({
name: 'PageHeader', name: "PageHeader",
components: { components: {
UserSettings, UserSettings,
QuillModal, QuillModal,
@ -30,139 +39,137 @@ export default defineComponent({
type: Boolean, type: Boolean,
}, },
}, },
emits: ['update:collapsed'], emits: ["update:collapsed"],
setup() { setup() {
const message = useMessage() const message = useMessage();
const dialog = useDialog() const dialog = useDialog();
const userStore = useUser() const userStore = useUser();
const useInfo = userStore.getUserInfo const useInfo = userStore.getUserInfo;
const name = '' const name = "";
const state = reactive({ const state = reactive({
username: name ?? '', username: name ?? "",
fullscreenIcon: 'FullscreenOutlined', fullscreenIcon: "FullscreenOutlined",
}) });
const router = useRouter() const router = useRouter();
const route = useRoute() const route = useRoute();
const routename = ref(route.meta.title) const routename = ref(route.meta.title);
// mm // mm
const iconList = ref([ const iconList = ref([
{ {
icon: 'magnifying-1', icon: "magnifying-1",
handle: searchHandler, handle: searchHandler,
}, },
{ {
icon: 'shortcut-keys', icon: "shortcut-keys",
handle: shortcutHandler, handle: shortcutHandler,
}, },
{ {
icon: 'suspicious-folder', icon: "suspicious-folder",
handle: recycleHandler, handle: recycleHandler,
}, },
{ {
icon: 'memo', icon: "memo",
handle: quillHandler, handle: quillHandler,
}, },
{ {
icon: 'nomessage', icon: "nomessage",
handle: goMessage, handle: goMessage,
}, },
]) ]);
watch( watch(
() => route.fullPath, () => route.fullPath,
() => { () => {
routename.value = route.meta.title routename.value = route.meta.title;
}, }
) );
const handleDragOver = (event, item) => { const handleDragOver = (event, item) => {
taskStore.setInFile(true) taskStore.setInFile(true);
} };
const handleDragLeave = (event, item) => { const handleDragLeave = (event, item) => {
taskStore.setInFile(false) taskStore.setInFile(false);
} };
const dropdownSelect = (key) => { const dropdownSelect = (key) => {
router.push({ name: key }) router.push({ name: key });
} };
// 退 // 退
const doLogout = () => { const doLogout = () => {
dialog.info({ dialog.info({
title: '提示', title: "提示",
content: '您确定要退出登录吗', content: "您确定要退出登录吗",
positiveText: '确定', positiveText: "确定",
negativeText: '取消', negativeText: "取消",
onPositiveClick: () => { onPositiveClick: () => {
userStore.logout().then(() => { userStore.logout().then(() => {
message.success('成功退出登录') message.success("成功退出登录");
router router
.replace({ .replace({
name: 'Login', name: "Login",
query: { query: {
// redirect: route.fullPath, // redirect: route.fullPath,
}, },
}) })
.finally(() => location.reload()) .finally(() => location.reload());
}) });
}, },
onNegativeClick: () => {}, onNegativeClick: () => {},
}) });
} };
const quillModalRef = ref(null) const quillModalRef = ref(null);
const shortcutModal = ref(null) const shortcutModal = ref(null);
const recycleModalRef = ref(null) const recycleModalRef = ref(null);
const SearchModalRef = ref(null) const SearchModalRef = ref(null);
function quillHandler() { function quillHandler() {
const modal = unref(quillModalRef)! as any const modal = unref(quillModalRef)! as any;
modal.showModal() modal.showModal();
} }
function shortcutHandler() { function shortcutHandler() {
const modal = unref(shortcutModal)! as any const modal = unref(shortcutModal)! as any;
modal.showModal() modal.showModal();
} }
function recycleHandler() { function recycleHandler() {
const modal = unref(recycleModalRef)! as any const modal = unref(recycleModalRef)! as any;
modal.showModal() modal.showModal();
} }
function searchHandler() { function searchHandler() {
const modal = unref(SearchModalRef)! as any const modal = unref(SearchModalRef)! as any;
modal.showModal() modal.showModal();
} }
function goMessage() { function goMessage() {
router.push({ name: 'message-main' }) router.push({ name: "message-main" });
} }
async function getMessage() { async function getMessage() {
const res = await msgPolling() const res = await msgPolling();
if (res.data) if (res.data) iconList.value[4].icon = "hasmessage";
iconList.value[4].icon = 'hasmessage' else iconList.value[4].icon = "nomessage";
else
iconList.value[4].icon = 'nomessage'
} }
setInterval(() => { setInterval(() => {
getMessage() getMessage();
}, 5000) }, 5000);
const mousetrap = inject('mousetrap') as any const mousetrap = inject("mousetrap") as any;
onMounted(() => { onMounted(() => {
mousetrap.bind('n r', quillHandler) getMessage();
mousetrap.bind('n t', quillHandler) mousetrap.bind("n r", quillHandler);
mousetrap.bind('n n', recycleHandler) mousetrap.bind("n t", quillHandler);
mousetrap.bind('m m', searchHandler) mousetrap.bind("n n", recycleHandler);
}) mousetrap.bind("m m", searchHandler);
});
return { return {
...toRefs(state), ...toRefs(state),
@ -183,9 +190,9 @@ export default defineComponent({
getMessage, getMessage,
handleDragOver, handleDragOver,
handleDragLeave, handleDragLeave,
} };
}, },
}) });
</script> </script>
<template> <template>
@ -207,8 +214,16 @@ export default defineComponent({
v-for="item in iconList" v-for="item in iconList"
:key="item.icon" :key="item.icon"
class="layout-header-trigger layout-header-trigger-min" class="layout-header-trigger layout-header-trigger-min"
@dragover.prevent="(e) => { handleDragOver(e, item) }" @dragover.prevent="
@dragleave.prevent="(e) => { handleDragLeave(e, item) }" (e) => {
handleDragOver(e, item);
}
"
@dragleave.prevent="
(e) => {
handleDragLeave(e, item);
}
"
> >
<div class="back" @click="item.handle"> <div class="back" @click="item.handle">
<SvgIcon :name="item.icon" size="18" /> <SvgIcon :name="item.icon" size="18" />
@ -326,9 +341,7 @@ export default defineComponent({
} }
.layout-header-left { .layout-header-left {
::v-deep( ::v-deep(.n-breadcrumb .n-breadcrumb-item:last-child .n-breadcrumb-item__link) {
.n-breadcrumb .n-breadcrumb-item:last-child .n-breadcrumb-item__link
) {
color: #515a6e; color: #515a6e;
} }
} }

@ -146,32 +146,32 @@ function rowProps(row: RowData) {
} }
function handleCheck(rowKeys: DataTableRowKey[]) { function handleCheck(rowKeys: DataTableRowKey[]) {
console.log(rowKeys, selectionIds.value, "handleCheck");
selectionIds.value = rowKeys; selectionIds.value = rowKeys;
} }
function select(key: number) { function select(key: number, id: string) {
switch (key) { switch (key) {
case 1: case 1:
editSelection(); editSelection(id);
break; break;
case 2: case 2:
deleteSelection(); deleteSelection(id);
break; break;
default: default:
break; break;
} }
} }
function editSelection() { function editSelection(id = "") {
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
const $message = window["$message"]; // const $message = window["$message"];
// if (selectionIds.value.length === 0 || selectionIds.value.length > 1) {
// $message.error("");
// return;
// }
if (selectionIds.value.length === 0 || selectionIds.value.length > 1) { const selectedId = id;
$message.error("请选中一条过滤");
return;
}
const selectedId = selectionIds.value[0];
const selectedFilter = tableData.value.find((item: any) => { const selectedFilter = tableData.value.find((item: any) => {
return item.id === selectedId; return item.id === selectedId;
}); });
@ -180,12 +180,12 @@ function editSelection() {
closeModal(); closeModal();
} }
function deleteSelection() { function deleteSelection(id = "") {
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
const $message = window["$message"];
if (selectionIds.value.length === 0) { if (selectionIds.value.length === 0) {
$message.error("至少选中一条过滤"); deleteCondition({ ids: id }).then(() => {
query(pagination.page, pagination.pageSize);
});
return; return;
} }
@ -335,12 +335,19 @@ const showSearch = computed(() => {
<div class="del_btn"> <div class="del_btn">
<n-button icon-placement="left" size="medium"> <n-button icon-placement="left" size="medium">
<template #icon> <template #icon>
<SvgIcon name="delete-history" size="16" /> <SvgIcon name="delete-history" size="16" />
</template> </template>
删除</n-button> 删除</n-button
>
</div> </div>
<div class="msg"> <div class="msg">
<span>已选中 <span style="color:#507afd;font-size:16px">{{ selectionIds.length }}</span> </span> <span
>已选中
<span style="color: #507afd; font-size: 16px">{{
selectionIds.length
}}</span>
</span
>
<a @click="selectionIds = []">清空</a> <a @click="selectionIds = []">清空</a>
</div> </div>
</div> </div>
@ -400,11 +407,10 @@ const showSearch = computed(() => {
width: 300px; width: 300px;
border: 1px solid gray; border: 1px solid gray;
} }
.del_btn{ .del_btn {
} }
.msg{ .msg {
a{ a {
margin-left: 30px; margin-left: 30px;
cursor: pointer; cursor: pointer;
color: #507afd; color: #507afd;

@ -1,10 +1,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { DropdownMixedOption } from 'naive-ui/es/dropdown/src/interface' import type { DropdownMixedOption } from "naive-ui/es/dropdown/src/interface";
import type { PropType } from 'vue' import type { PropType } from "vue";
defineOptions({ name: 'Action' }) defineOptions({ name: "Action" });
defineProps({ const props = defineProps({
options: { options: {
type: Array as PropType<DropdownMixedOption[]>, type: Array as PropType<DropdownMixedOption[]>,
default: null, default: null,
@ -12,18 +12,21 @@ defineProps({
}, },
select: { select: {
type: Function as PropType<Function>, type: Function as PropType<Function>,
default: () => { }, default: () => {},
}, },
id: { id: {
type: String, type: String,
default: '', default: "",
}, },
}) });
const fun = (key) => {
props.select(key, props.id);
};
</script> </script>
<template> <template>
<div :data-id="id"> <div :data-id="id">
<n-dropdown trigger="hover" :options="options" @select="(select as any)"> <n-dropdown trigger="hover" :options="options" @select="fun">
<SvgIcon name="more-hor" size="20" /> <SvgIcon name="more-hor" size="20" />
</n-dropdown> </n-dropdown>
</div> </div>

@ -17,7 +17,10 @@ const props = defineProps({
required: true, required: true,
}, },
}); });
const ruleForm = reactive({
keyword: "",
});
const ruleformRef = ref();
const emit = defineEmits<{ const emit = defineEmits<{
(e: "show-filter"): void; (e: "show-filter"): void;
(e: "show-custom"): void; (e: "show-custom"): void;
@ -27,7 +30,7 @@ const emit = defineEmits<{
const data = ref<FilterEntity[]>([]); const data = ref<FilterEntity[]>([]);
const unData = ref<FilterEntity[]>([]); const unData = ref<FilterEntity[]>([]);
const loading = ref(false); const loading = ref(false);
const canloadMore = true; const canloadMore = true;
const el = ref<HTMLDivElement | null>(null); const el = ref<HTMLDivElement | null>(null);
const popover = ref<ComponentRef | null>(null); const popover = ref<ComponentRef | null>(null);
@ -74,8 +77,8 @@ useInfiniteScroll(
}, },
{ distance: 10, interval: 300, canLoadMore: () => false } { distance: 10, interval: 300, canLoadMore: () => false }
); );
const showClick =async () => { const showClick = async () => {
getSearchedList('') getSearchedList("");
}; };
async function loadMore() { async function loadMore() {
@ -92,7 +95,7 @@ async function featchList() {
loading.value = true; loading.value = true;
try { try {
const searchParam: FilterSearchParam = { const searchParam: FilterSearchParam = {
search_searchname: { value: keyword.value, op: "like", type: "string" }, search_searchname: { value: ruleForm.keyword, op: "like", type: "string" },
}; };
const result = await getConditionList(pagination, searchParam, props.type); const result = await getConditionList(pagination, searchParam, props.type);
const { data } = result; const { data } = result;
@ -121,11 +124,8 @@ function generateFilterEntityList(data) {
}; };
}); });
const reg = new RegExp(keyword.value, "gi"); const reg = new RegExp(ruleForm.keyword, "gi");
const hilightText = searchname.replace( const hilightText = searchname.replace(reg, `<span>${ruleForm.keyword}</span>`);
reg,
`<span>${keyword.value}</span>`
);
return { return {
id, id,
@ -134,7 +134,7 @@ function generateFilterEntityList(data) {
isDefaultFilter: false, isDefaultFilter: false,
filterList: list, filterList: list,
reorder, reorder,
searchname searchname,
}; };
}); });
@ -143,12 +143,17 @@ function generateFilterEntityList(data) {
function selectHandler(item: FilterEntity) { function selectHandler(item: FilterEntity) {
(popover.value as any).setShow(false); (popover.value as any).setShow(false);
currentlySelectedAdvanced.value = item.searchname currentlySelectedAdvanced.value = item.searchname;
emit("select", item.id); emit("select", item.id);
} }
const inputHandler = debounce((word) => { const inputHandler = debounce((word) => {
getSearchedList(word) ruleForm.keyword = word;
ruleformRef.value.validate();
if (word.length < 2 && word) {
return;
}
getSearchedList(word);
}, 300); }, 300);
function getSearchedList(word) { function getSearchedList(word) {
@ -157,7 +162,7 @@ function getSearchedList(word) {
} else { } else {
pagination.pageSize = 10; pagination.pageSize = 10;
} }
keyword.value = word; ruleForm.keyword = word;
featchList().then((list) => { featchList().then((list) => {
let dataArr: FilterEntity[] = []; let dataArr: FilterEntity[] = [];
let unDataArr: FilterEntity[] = []; let unDataArr: FilterEntity[] = [];
@ -195,10 +200,26 @@ function favoriteHandler(event: MouseEvent, item: any) {
} }
}); });
inputHandler(keyword.value); inputHandler(ruleForm.keyword);
} }
} }
const rules = {
keyword: [
{
trigger: ["blur", "input", "change"],
level: "error",
validator(_rule, value) {
if (value.length >= 2) {
return true;
} else {
return new Error("搜索关键字最少为两个");
}
},
},
],
};
function unFavoriteHandler(event: MouseEvent, item) { function unFavoriteHandler(event: MouseEvent, item) {
event.stopImmediatePropagation(); event.stopImmediatePropagation();
event.stopPropagation(); event.stopPropagation();
@ -208,7 +229,7 @@ function unFavoriteHandler(event: MouseEvent, item) {
if (!isDefaultFilter) { if (!isDefaultFilter) {
item.favorite = false; item.favorite = false;
unfavorite(id); unfavorite(id);
inputHandler(keyword.value); inputHandler(ruleForm.keyword);
} }
} }
@ -233,29 +254,37 @@ const moveEnd = () => {
> >
<template #trigger> <template #trigger>
<div class="wrapper-left-dropdown" @click="showClick"> <div class="wrapper-left-dropdown" @click="showClick">
<span style="font-size: 20px;color: #333333;font-weight: Medium;">{{currentlySelectedAdvanced}}</span> <span style="font-size: 20px; color: #333333; font-weight: Medium">{{
<SvgIcon :style="{ marginLeft: '5px' }" name="down" size="14" /> currentlySelectedAdvanced
}}</span>
<SvgIcon :style="{ marginLeft: '5px' }" name="down" size="14" color="#999999"/>
</div> </div>
</template> </template>
<n-spin :show="loading"> <n-spin :show="loading">
<div class="wrapper-left-popover"> <div class="wrapper-left-popover">
<n-input <n-form :rules="rules" ref="ruleformRef" :model="ruleForm">
:style="{ '--n-border': '0px' }" <n-form-item path="keyword">
placeholder="请输入关键词" <n-input
@input="inputHandler" :style="{ '--n-border': '0px' }"
> placeholder="请输入关键字"
<template #prefix> @input="inputHandler"
<SvgIcon size="14px" name="magnifying-1" /> :value="ruleForm.keyword"
</template> :minlength="2"
<template #suffix> >
<SvgIcon <template #prefix>
size="14px" <SvgIcon size="14px" name="magnifying-1" />
style="cursor: pointer" </template>
name="setting" <template #suffix>
@click="emit('show-filter')" <SvgIcon
/> size="14px"
</template> style="cursor: pointer"
</n-input> name="setting"
@click="emit('show-filter')"
/>
</template>
</n-input>
</n-form-item>
</n-form>
<ul ref="el" class="wrapper-left-list"> <ul ref="el" class="wrapper-left-list">
<li <li
@ -264,23 +293,28 @@ const moveEnd = () => {
style="display: flex; align-items: center" style="display: flex; align-items: center"
@click="selectHandler(item)" @click="selectHandler(item)"
> >
<SvgIcon name="drag" size="18" color="#333333" style="margin-right:3px"/> <SvgIcon
name="drag"
size="18"
color="#333333"
style="margin-right: 3px"
/>
<SvgIcon <SvgIcon
v-if="item.favorite && !item.isDefaultFilter" v-if="item.favorite && !item.isDefaultFilter"
name="favorite-fill" name="favorite-fill"
color="#fd9b0a" color="#fd9b0a"
size="18" size="18"
style="margin-right:3px" style="margin-right: 3px"
@click="unFavoriteHandler($event, item)" @click="unFavoriteHandler($event, item)"
/> />
<SvgIcon <SvgIcon
v-else-if="!item.favorite && !item.isDefaultFilter" v-else-if="!item.favorite && !item.isDefaultFilter"
name="favorite-unfill" name="favorite-unfill"
size="18" size="18"
style="margin-right:3px" style="margin-right: 3px"
@click="favoriteHandler($event, item)" @click="favoriteHandler($event, item)"
/> />
<div v-html="item.name" style="color: #333333;"/> <div v-html="item.name" style="color: #333333" />
</li> </li>
<!-- filter=".draggable-li[draggable='false']" --> <!-- filter=".draggable-li[draggable='false']" -->
<VueDraggable <VueDraggable
@ -298,14 +332,14 @@ const moveEnd = () => {
class="cursor-move draggable-li fix" class="cursor-move draggable-li fix"
:draggable="true" :draggable="true"
> >
<SvgIcon name="drag" size="18" style="margin-right:3px"/> <SvgIcon name="drag" size="18" style="margin-right: 3px" />
<SvgIcon <SvgIcon
v-if="item.favorite && !item.isDefaultFilter" v-if="item.favorite && !item.isDefaultFilter"
name="favorite-fill" name="favorite-fill"
color="#fd9b0a" color="#fd9b0a"
size="18" size="18"
fill="#666666" fill="#666666"
style="cursor: pointer!important;margin-right:3px;" style="cursor: pointer !important; margin-right: 3px"
@click="unFavoriteHandler($event, item)" @click="unFavoriteHandler($event, item)"
/> />
<SvgIcon <SvgIcon
@ -313,10 +347,10 @@ const moveEnd = () => {
name="favorite-unfill" name="favorite-unfill"
size="18" size="18"
fill="#666666" fill="#666666"
style="cursor: pointer!important;margin-right:3px;" style="cursor: pointer !important; margin-right: 3px"
@click="favoriteHandler($event, item)" @click="favoriteHandler($event, item)"
/> />
<div v-html="item.name" style="color: #333333;"/> <div v-html="item.name" style="color: #333333" />
</li> </li>
</VueDraggable> </VueDraggable>
</ul> </ul>

@ -148,43 +148,41 @@ function handleCheck(rowKeys: DataTableRowKey[]) {
selectionIds.value = rowKeys; selectionIds.value = rowKeys;
} }
function select(key: number) { function select(key: number, id: string) {
switch (key) { switch (key) {
case 1: case 1:
editSelection(); editSelection(id);
break; break;
case 2: case 2:
deleteSelection(); deleteSelection(id);
break; break;
default: default:
break; break;
} }
} }
function editSelection() { function editSelection(id) {
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
const $message = window["$message"]; // const $message = window["$message"];
// if (selectionIds.value.length === 0 || selectionIds.value.length > 1) {
if (selectionIds.value.length === 0 || selectionIds.value.length > 1) { // $message.error("");
$message.error("请选中一条过滤"); // return;
return; // }
} const selectedId = id;
const selectedId = selectionIds.value[0];
const selectedFilter = tableData.value.find((item: any) => { const selectedFilter = tableData.value.find((item: any) => {
return item.id === selectedId; return item.id === selectedId;
}); });
emit("editFilter", selectedFilter); emit("editFilter", selectedFilter);
closeModal(); // closeModal();
} }
function deleteSelection() { function deleteSelection(id = '') {
// eslint-disable-next-line dot-notation // eslint-disable-next-line dot-notation
const $message = window["$message"];
if (selectionIds.value.length === 0) { if (selectionIds.value.length === 0) {
$message.error("至少选中一条过滤"); deleteCondition({ ids: id }).then(() => {
query(pagination.page, pagination.pageSize);
});
return; return;
} }

Loading…
Cancel
Save