feat: 高级搜索-视图
This commit is contained in:
parent
4aecb7565f
commit
f536f1ff6e
|
@ -1,3 +1,5 @@
|
|||
import type { ViewDetail, ViewList, ViewParams } from '@/components/pure/ms-advance-filter/type';
|
||||
|
||||
import MSR from '@/api/http/index';
|
||||
import {
|
||||
AddAPIKEYUrl,
|
||||
|
@ -240,3 +242,24 @@ export function getPlatformOrgOption() {
|
|||
export function getDefaultLocale() {
|
||||
return MSR.get<LocaleType>({ url: GetDefaultLocaleUrl });
|
||||
}
|
||||
|
||||
// 视图列表
|
||||
export function getViewList(viewType: string, scopeId: string) {
|
||||
return MSR.get<ViewList>({ url: `/user-view/${viewType}/grouped/list`, params: scopeId });
|
||||
}
|
||||
// 视图详情
|
||||
export function getViewDetail(viewType: string, id: string) {
|
||||
return MSR.get<ViewDetail>({ url: `/user-view/${viewType}/get/${id}` });
|
||||
}
|
||||
// 编辑视图
|
||||
export function updateView(viewType: string, data: ViewParams) {
|
||||
return MSR.post({ url: `/user-view/${viewType}/update`, data });
|
||||
}
|
||||
// 新增视图
|
||||
export function addView(viewType: string, data: ViewParams) {
|
||||
return MSR.post({ url: `/user-view/${viewType}/add`, data });
|
||||
}
|
||||
// 删除视图
|
||||
export function deleteView(viewType: string, id: string) {
|
||||
return MSR.post({ url: `/user-view/${viewType}/delete/${id}` });
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
<template>
|
||||
<a-form ref="formRef" :model="form" layout="vertical">
|
||||
<a-form-item
|
||||
class="hidden-item"
|
||||
hide-asterisk
|
||||
field="name"
|
||||
:validate-trigger="['blur', 'input']"
|
||||
:rules="[{ required: true, message: t('advanceFilter.viewNameRequired') }, { validator: validateName }]"
|
||||
>
|
||||
<a-input
|
||||
ref="inputRef"
|
||||
v-model:model-value="form.name"
|
||||
:max-length="255"
|
||||
:placeholder="t('advanceFilter.viewNamePlaceholder')"
|
||||
show-word-limit
|
||||
@press-enter="handleSubmit"
|
||||
@blur="handleSubmit"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { FormInstance, InputInstance } from '@arco-design/web-vue';
|
||||
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
||||
const props = defineProps<{
|
||||
allNames: string[];
|
||||
}>();
|
||||
const form = defineModel<Record<string, any>>('form', {
|
||||
required: true,
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'handleSubmit'): void;
|
||||
}>();
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
// 校验名称是否重复
|
||||
const validateName = (value: any, callback: (error?: string | undefined) => void) => {
|
||||
if (props.allNames.includes(value)) {
|
||||
callback(t('advanceFilter.viewNameNotRepeat'));
|
||||
}
|
||||
};
|
||||
|
||||
const inputRef = ref<InputInstance>();
|
||||
function inputFocus() {
|
||||
inputRef.value?.focus();
|
||||
}
|
||||
|
||||
function handleSubmit() {
|
||||
formRef.value?.validate(async (errors) => {
|
||||
if (!errors) {
|
||||
emit('handleSubmit');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
inputFocus,
|
||||
});
|
||||
</script>
|
|
@ -1,14 +1,12 @@
|
|||
<template>
|
||||
<MsDrawer v-model:visible="visible" :width="800">
|
||||
<MsDrawer v-model:visible="visible" :mask="false" :width="600">
|
||||
<template #title>
|
||||
<a-input
|
||||
<ViewNameInput
|
||||
v-show="isShowNameInput"
|
||||
ref="nameInputRef"
|
||||
v-model:model-value="formModel.name"
|
||||
class="flex-1"
|
||||
:max-length="255"
|
||||
show-word-limit
|
||||
@blur="isShowNameInput = false"
|
||||
ref="viewNameInputRef"
|
||||
v-model:form="formModel"
|
||||
:all-names="allViewNames"
|
||||
@handle-submit="isShowNameInput = false"
|
||||
/>
|
||||
<div v-show="!isShowNameInput" class="flex flex-1 items-center gap-[8px] overflow-hidden">
|
||||
<a-tooltip :content="formModel.name">
|
||||
|
@ -21,6 +19,9 @@
|
|||
/>
|
||||
</div>
|
||||
</template>
|
||||
<a-alert class="mb-[12px]" closable>
|
||||
{{ t('advanceFilter.filterTip') }}
|
||||
</a-alert>
|
||||
<a-form ref="formRef" :model="formModel" layout="vertical">
|
||||
<a-select v-model="formModel.searchMode" :options="searchModeOptions" class="mb-[12px] w-[170px]">
|
||||
<template #prefix> {{ t('advanceFilter.meetTheFollowingConditions') }} </template>
|
||||
|
@ -63,16 +64,8 @@
|
|||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item class="flex-1 overflow-hidden" :field="`list[${listIndex}].value`" hide-asterisk>
|
||||
<a-input
|
||||
v-if="item.type === FilterType.INPUT"
|
||||
v-model:model-value="item.value"
|
||||
allow-clear
|
||||
:disabled="isValueDisabled(item)"
|
||||
:max-length="255"
|
||||
:placeholder="t('advanceFilter.inputPlaceholder')"
|
||||
/>
|
||||
<a-textarea
|
||||
v-else-if="item.type === FilterType.TEXTAREA"
|
||||
v-if="item.type === FilterType.TEXTAREA"
|
||||
v-model:model-value="item.value"
|
||||
allow-clear
|
||||
:disabled="isValueDisabled(item)"
|
||||
|
@ -163,6 +156,14 @@
|
|||
{{ it[item.checkProps?.labelKey || 'label'] }}
|
||||
</a-checkbox>
|
||||
</a-checkbox-group>
|
||||
<a-input
|
||||
v-else
|
||||
v-model:model-value="item.value"
|
||||
allow-clear
|
||||
:disabled="isValueDisabled(item)"
|
||||
:max-length="255"
|
||||
:placeholder="t('advanceFilter.inputPlaceholder')"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-button
|
||||
v-if="formModel.list.length > 1"
|
||||
|
@ -182,20 +183,26 @@
|
|||
<div v-show="!isSaveAsView" class="flex items-center gap-[8px]">
|
||||
<a-button type="primary" @click="handleFilter">{{ t('common.filter') }}</a-button>
|
||||
<a-button class="mr-[16px]" @click="handleReset">{{ t('common.reset') }}</a-button>
|
||||
<MsButton type="text" class="!text-[var(--color-text-1)]"> {{ t('common.save') }}</MsButton>
|
||||
<MsButton type="text" class="!text-[var(--color-text-1)]" @click="isSaveAsView = true">
|
||||
<MsButton
|
||||
v-if="formModel?.internalViewKey !== 'ALL_DATA'"
|
||||
type="text"
|
||||
class="!text-[var(--color-text-1)]"
|
||||
@click="handleSaveView"
|
||||
>
|
||||
{{ t('common.save') }}
|
||||
</MsButton>
|
||||
<MsButton v-if="formModel?.id" type="text" class="!text-[var(--color-text-1)]" @click="handleToSaveAs">
|
||||
{{ t('advanceFilter.saveAsView') }}
|
||||
</MsButton>
|
||||
</div>
|
||||
<div v-show="isSaveAsView" class="flex items-center gap-[8px]">
|
||||
<a-input
|
||||
v-model:model-value="saveAsViewName"
|
||||
:placeholder="t('advanceFilter.viewNamePlaceholder')"
|
||||
<ViewNameInput
|
||||
ref="saveAsViewNameInputRef"
|
||||
v-model:form="saveAsViewForm"
|
||||
class="w-[240px]"
|
||||
:max-length="255"
|
||||
show-word-limit
|
||||
:all-names="allViewNames"
|
||||
/>
|
||||
<a-button type="primary">{{ t('common.save') }}</a-button>
|
||||
<a-button type="primary" @click="handleAddView">{{ t('common.save') }}</a-button>
|
||||
<a-button @click="handleCancelSaveAsView">{{ t('common.cancel') }}</a-button>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -203,47 +210,74 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { FormInstance, InputInstance } from '@arco-design/web-vue';
|
||||
import { FormInstance, Message } from '@arco-design/web-vue';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import ViewNameInput from './components/viewNameInput.vue';
|
||||
|
||||
import { addView, getViewDetail, updateView } from '@/api/modules/user/index';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
||||
import { SelectValue } from '@/models/projectManagement/menuManagement';
|
||||
import { FilterType, OperatorEnum } from '@/enums/advancedFilterEnum';
|
||||
import { FilterType, OperatorEnum, ViewTypeEnum } from '@/enums/advancedFilterEnum';
|
||||
|
||||
import { defaultFormModelList, operatorOptionsMap } from './index';
|
||||
import { AccordBelowType, FilterFormItem, FilterResult } from './type';
|
||||
import { operatorOptionsMap } from './index';
|
||||
import { ConditionsItem, FilterForm, FilterFormItem, FilterResult } from './type';
|
||||
|
||||
const props = defineProps<{
|
||||
configList: FilterFormItem[]; // 系统字段
|
||||
customList?: FilterFormItem[]; // 自定义字段
|
||||
viewType: ViewTypeEnum;
|
||||
currentView: string; // 当前视图
|
||||
allViewNames: string[];
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'handleFilter', value: FilterResult): void;
|
||||
(e: 'refreshViewList'): void;
|
||||
}>();
|
||||
const visible = defineModel<boolean>('visible', { required: true });
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
// TODO lmy 联调
|
||||
const formModel = ref<{ name: string; searchMode: AccordBelowType; list: FilterFormItem[] }>({
|
||||
name: '111',
|
||||
const defaultFormModel: FilterForm = {
|
||||
name: '',
|
||||
searchMode: 'AND',
|
||||
list: [...defaultFormModelList],
|
||||
});
|
||||
list: [{ dataIndex: '', operator: undefined, value: '', type: FilterType.INPUT }],
|
||||
};
|
||||
const formModel = ref<FilterForm>(cloneDeep(defaultFormModel));
|
||||
const savedFormModel = ref(cloneDeep(formModel.value));
|
||||
function getListItemByDataIndex(dataIndex: string) {
|
||||
return [...props.configList, ...(props.customList || [])].find((item) => item.dataIndex === dataIndex);
|
||||
}
|
||||
async function getUserViewDetail(id: string) {
|
||||
try {
|
||||
const res = await getViewDetail(props.viewType, id);
|
||||
const list: FilterFormItem[] = (res.conditions ?? [])?.map((item: ConditionsItem) => {
|
||||
const listItem = getListItemByDataIndex(item.name ?? '') as FilterFormItem;
|
||||
return {
|
||||
...listItem,
|
||||
operator: item.operator,
|
||||
value: item.value,
|
||||
};
|
||||
});
|
||||
formModel.value = { ...res, list };
|
||||
savedFormModel.value = cloneDeep(formModel.value);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
const isShowNameInput = ref(false);
|
||||
const nameInputRef = ref<InputInstance>();
|
||||
const viewNameInputRef = ref<InstanceType<typeof ViewNameInput>>();
|
||||
function showNameInput() {
|
||||
isShowNameInput.value = true;
|
||||
nextTick(() => {
|
||||
nameInputRef.value?.focus();
|
||||
viewNameInputRef.value?.inputFocus();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -253,9 +287,6 @@
|
|||
];
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
function getListItemByDataIndex(dataIndex: string) {
|
||||
return [...props.configList, ...(props.customList || [])].find((item) => item.dataIndex === dataIndex);
|
||||
}
|
||||
// 第三列值是数组类型的
|
||||
function valueIsArray(listItem: FilterFormItem) {
|
||||
return (
|
||||
|
@ -327,11 +358,11 @@
|
|||
return { searchMode: formModel.value.searchMode, conditions };
|
||||
}
|
||||
|
||||
// TODO lmy 根据视图重置
|
||||
// 重置
|
||||
function handleReset() {
|
||||
formModel.value = cloneDeep(savedFormModel.value);
|
||||
}
|
||||
|
||||
// 过滤
|
||||
function handleFilter() {
|
||||
formRef.value?.validate((errors) => {
|
||||
if (!errors) {
|
||||
|
@ -340,13 +371,77 @@
|
|||
}
|
||||
});
|
||||
}
|
||||
watch(
|
||||
() => props.currentView,
|
||||
async (val) => {
|
||||
await getUserViewDetail(val);
|
||||
handleFilter();
|
||||
}
|
||||
);
|
||||
|
||||
const isSaveAsView = ref(false);
|
||||
const saveAsViewName = ref('');
|
||||
const saveAsViewForm = ref({ name: '' });
|
||||
const saveAsViewNameInputRef = ref<InstanceType<typeof ViewNameInput>>();
|
||||
// 数据改为新建视图的空数据
|
||||
function resetToNewViewForm() {
|
||||
// TODO lmy 命名递增数字
|
||||
formModel.value = {
|
||||
...cloneDeep(defaultFormModel),
|
||||
name: '未命名视图001',
|
||||
};
|
||||
savedFormModel.value = cloneDeep(formModel.value);
|
||||
}
|
||||
// 保存视图
|
||||
function handleSaveView() {
|
||||
// TODO lmy 校验名称
|
||||
formRef.value?.validate(async (errors) => {
|
||||
if (!errors) {
|
||||
try {
|
||||
if (formModel.value.id) {
|
||||
await updateView(props.viewType, { ...getParams(), name: formModel.value.name, id: formModel.value.id });
|
||||
} else {
|
||||
await addView(props.viewType, { ...getParams(), name: formModel.value.name, id: formModel.value.id });
|
||||
}
|
||||
Message.success(t('common.saveSuccess'));
|
||||
savedFormModel.value = cloneDeep(formModel.value);
|
||||
emit('refreshViewList');
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// 开启另存为视图模式
|
||||
function handleToSaveAs() {
|
||||
formRef.value?.validate((errors) => {
|
||||
if (!errors) {
|
||||
isSaveAsView.value = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
// 取消另存为视图模式
|
||||
function handleCancelSaveAsView() {
|
||||
isSaveAsView.value = false;
|
||||
saveAsViewName.value = '';
|
||||
saveAsViewForm.value.name = '';
|
||||
}
|
||||
// 新增视图
|
||||
async function handleAddView() {
|
||||
// TODO lmy 校验名称 saveAsViewNameInputRef
|
||||
try {
|
||||
await addView(props.viewType, { ...getParams(), name: formModel.value.name, id: formModel.value.id });
|
||||
Message.success(t('common.saveSuccess'));
|
||||
emit('refreshViewList');
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
resetToNewViewForm,
|
||||
handleReset,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -31,8 +31,49 @@
|
|||
@search="emit('keywordSearch', keyword)"
|
||||
@clear="handleClear"
|
||||
></a-input-search>
|
||||
<a-select
|
||||
v-if="props.viewType"
|
||||
v-model:model-value="currentView"
|
||||
:trigger-props="{ contentClass: 'view-select-trigger' }"
|
||||
class="w-[160px]"
|
||||
show-footer-on-empty
|
||||
>
|
||||
<template #prefix> {{ t('advanceFilter.view') }} </template>
|
||||
<a-optgroup :label="t('advanceFilter.systemView')">
|
||||
<a-option v-for="item in internalViews" :key="item.id" :value="item.id">
|
||||
{{ item.name }}
|
||||
</a-option>
|
||||
</a-optgroup>
|
||||
<a-optgroup :label="t('advanceFilter.myView')">
|
||||
<a-option v-for="item in customViews" :key="item.id" :value="item.id">
|
||||
{{ item.name }}
|
||||
<div class="flex">
|
||||
<a-tooltip :content="t('common.rename')">
|
||||
<MsButton type="text" status="secondary" class="!mr-[4px]" @click.stop="handleRenameView(item)">
|
||||
<MsIcon type="icon-icon_edit_outlined" class="hover:text-[rgb(var(--primary-4))]" size="12" />
|
||||
</MsButton>
|
||||
</a-tooltip>
|
||||
<a-tooltip :content="t('advanceFilter.deleteView')">
|
||||
<MsButton type="text" status="secondary" @click.stop="handleDeleteView(item)">
|
||||
<MsIcon
|
||||
type="icon-icon_delete-trash_outlined1"
|
||||
class="hover:text-[rgb(var(--primary-4))]"
|
||||
size="12"
|
||||
/>
|
||||
</MsButton>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</a-option>
|
||||
</a-optgroup>
|
||||
<template #footer>
|
||||
<div class="flex cursor-pointer items-center gap-[8px]" @click="toNewView">
|
||||
<MsIcon type="icon-icon_add_outlined" />
|
||||
{{ t('advanceFilter.newView') }}
|
||||
</div>
|
||||
</template>
|
||||
</a-select>
|
||||
<a-button
|
||||
v-if="props.showFilter"
|
||||
v-if="props.viewType"
|
||||
type="outline"
|
||||
:class="`${isAdvancedSearchMode ? '' : 'arco-btn-outline--secondary'} p-[0_8px]`"
|
||||
@click="handleOpenFilter"
|
||||
|
@ -45,6 +86,9 @@
|
|||
</template>
|
||||
{{ t('common.filter') }}
|
||||
</a-button>
|
||||
<MsButton v-show="isAdvancedSearchMode" type="text" @click="clearFilter">
|
||||
{{ t('advanceFilter.clearFilter') }}
|
||||
</MsButton>
|
||||
|
||||
<slot name="right"></slot>
|
||||
<MsTag
|
||||
|
@ -60,21 +104,33 @@
|
|||
</div>
|
||||
</div>
|
||||
<FilterDrawer
|
||||
ref="filterDrawerRef"
|
||||
v-model:visible="visible"
|
||||
:current-view="currentView"
|
||||
:view-type="props.viewType as ViewTypeEnum"
|
||||
:all-view-names="allViewNames"
|
||||
:config-list="props.filterConfigList"
|
||||
:custom-list="props.customFieldsConfigList"
|
||||
@handle-filter="handleFilter"
|
||||
@refresh-view-list="getUserViewList"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||
import MsTag from '../ms-tag/ms-tag.vue';
|
||||
import FilterDrawer from './filterDrawer.vue';
|
||||
|
||||
import { deleteView, getViewList } from '@/api/modules/user/index';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useAppStore from '@/store/modules/app';
|
||||
|
||||
import { FilterFormItem, FilterResult } from './type';
|
||||
import { ViewTypeEnum } from '@/enums/advancedFilterEnum';
|
||||
|
||||
import { FilterFormItem, FilterResult, ViewItem } from './type';
|
||||
|
||||
const props = defineProps<{
|
||||
rowCount: number;
|
||||
|
@ -84,7 +140,7 @@
|
|||
name?: string;
|
||||
count?: number;
|
||||
notShowInputSearch?: boolean;
|
||||
showFilter?: boolean; // 展示高级搜索按钮
|
||||
viewType?: ViewTypeEnum;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -94,15 +150,62 @@
|
|||
}>();
|
||||
|
||||
const { t } = useI18n();
|
||||
const appStore = useAppStore();
|
||||
|
||||
const keyword = defineModel<string>('keyword', { default: '' });
|
||||
const visible = ref(false);
|
||||
const filterResult = ref<FilterResult>({ searchMode: 'AND', conditions: [] });
|
||||
|
||||
const currentView = ref(''); // 当前视图
|
||||
const internalViews = ref<ViewItem[]>([]);
|
||||
const customViews = ref<ViewItem[]>([]);
|
||||
const allViewNames = computed(() => [...internalViews.value, ...customViews.value].map((item) => item.name));
|
||||
async function getUserViewList() {
|
||||
try {
|
||||
const res = await getViewList(props.viewType as ViewTypeEnum, appStore.currentProjectId);
|
||||
internalViews.value = res.internalViews;
|
||||
customViews.value = res.customViews;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
onMounted(async () => {
|
||||
await getUserViewList();
|
||||
currentView.value = internalViews.value[0].id;
|
||||
});
|
||||
|
||||
const filterDrawerRef = ref<InstanceType<typeof FilterDrawer>>();
|
||||
function toNewView() {
|
||||
visible.value = true;
|
||||
filterDrawerRef.value?.resetToNewViewForm();
|
||||
}
|
||||
function handleRenameView(item: ViewItem) {
|
||||
// TODO lmy 重命名
|
||||
}
|
||||
async function handleDeleteView(item: ViewItem) {
|
||||
try {
|
||||
await deleteView(item.viewType, item.id);
|
||||
Message.success(t('common.deleteSuccess'));
|
||||
getUserViewList();
|
||||
currentView.value = internalViews.value[0].id;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
const isAdvancedSearchMode = ref(false);
|
||||
const handleFilter = (filter: FilterResult) => {
|
||||
keyword.value = '';
|
||||
isAdvancedSearchMode.value = !!filter.conditions?.length;
|
||||
const haveConditions: boolean =
|
||||
filter.conditions?.some((item) => {
|
||||
const valueCanEmpty = ['EMPTY', 'NOT_EMPTY'].includes(item.operator as string);
|
||||
const isValidValue = typeof item.value !== 'number' ? item.value?.length : item.value;
|
||||
return valueCanEmpty || isValidValue;
|
||||
}) ?? false;
|
||||
// 开启高级筛选:非默认视图或有筛选条件
|
||||
isAdvancedSearchMode.value = currentView.value !== internalViews.value[0].id || haveConditions;
|
||||
filterResult.value = filter;
|
||||
emit('advSearch', filter);
|
||||
};
|
||||
|
@ -119,4 +222,37 @@
|
|||
const handleOpenFilter = () => {
|
||||
visible.value = !visible.value;
|
||||
};
|
||||
|
||||
// 清除筛选
|
||||
function clearFilter() {
|
||||
if (currentView.value === internalViews.value[0].id) {
|
||||
filterDrawerRef.value?.handleReset();
|
||||
} else {
|
||||
currentView.value = internalViews.value[0].id;
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
isAdvancedSearchMode,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.view-select-trigger .arco-select-dropdown {
|
||||
.arco-select-option-content {
|
||||
@apply flex w-full items-center justify-between;
|
||||
}
|
||||
.arco-select-dropdown-list-wrapper {
|
||||
max-height: 255px;
|
||||
}
|
||||
.arco-select-group-title {
|
||||
margin: 0 2px;
|
||||
padding: 0 8px;
|
||||
color: var(--color-text-brand);
|
||||
}
|
||||
.arco-select-dropdown-footer {
|
||||
padding: 3px 8px;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,33 +1,43 @@
|
|||
export default {
|
||||
'advanceFilter.operator.gt': 'gt',
|
||||
'advanceFilter.operator.ge': 'ge',
|
||||
'advanceFilter.operator.lt': 'lt',
|
||||
'advanceFilter.operator.le': 'le',
|
||||
'advanceFilter.operator.equal': 'equal',
|
||||
'advanceFilter.operator.notEqual': 'not Equal',
|
||||
'advanceFilter.operator.no_check': 'uncheck',
|
||||
'advanceFilter.operator.contains': 'contain',
|
||||
'advanceFilter.operator.not_contains': 'exclude',
|
||||
'advanceFilter.operator.belongTo': 'belong to',
|
||||
'advanceFilter.operator.notBelongTo': 'not belong to',
|
||||
'advanceFilter.operator.start_with': 'with...start',
|
||||
'advanceFilter.operator.end_with': 'with...end',
|
||||
'advanceFilter.operator.empty': 'empty',
|
||||
'advanceFilter.operator.not_empty': 'not empty',
|
||||
'advanceFilter.operator.regexp': 'Regular',
|
||||
'advanceFilter.operator.between': 'between',
|
||||
'advanceFilter.operator.gt': 'Greater than',
|
||||
'advanceFilter.operator.ge': 'Greater than or equal to',
|
||||
'advanceFilter.operator.lt': 'Less than',
|
||||
'advanceFilter.operator.le': 'Less than or equal to',
|
||||
'advanceFilter.operator.equal': 'Equal to',
|
||||
'advanceFilter.operator.notEqual': 'Not equal to',
|
||||
'advanceFilter.operator.no_check': 'No check',
|
||||
'advanceFilter.operator.contains': 'Contain',
|
||||
'advanceFilter.operator.not_contains': 'Does not contain',
|
||||
'advanceFilter.operator.belongTo': 'Belong to',
|
||||
'advanceFilter.operator.notBelongTo': 'Not belong to',
|
||||
'advanceFilter.operator.start_with': 'Starts with',
|
||||
'advanceFilter.operator.end_with': 'Ends with',
|
||||
'advanceFilter.operator.empty': 'Is empty',
|
||||
'advanceFilter.operator.not_empty': 'Is not empty',
|
||||
'advanceFilter.operator.regexp': 'Regular expression match',
|
||||
'advanceFilter.operator.between': 'Between',
|
||||
'advanceFilter.operator.length.equal': 'Length equal to',
|
||||
'advanceFilter.operator.length.gt': 'Length greater than',
|
||||
'advanceFilter.operator.length.ge': 'Length greater than or equal to',
|
||||
'advanceFilter.operator.length.lt': 'Less than',
|
||||
'advanceFilter.operator.length.lt': 'Length less than',
|
||||
'advanceFilter.operator.length.le': 'Length less than or equal to',
|
||||
|
||||
'advanceFilter.view': 'View',
|
||||
'advanceFilter.systemView': 'System view',
|
||||
'advanceFilter.myView': 'My view',
|
||||
'advanceFilter.newView': 'New view',
|
||||
'advanceFilter.deleteView': 'Delete view',
|
||||
'advanceFilter.clearFilter': 'Clear filter',
|
||||
'advanceFilter.saveAsView': 'Save as view',
|
||||
'advanceFilter.viewNamePlaceholder': 'Please enter the view name',
|
||||
'advanceFilter.meetTheFollowingConditions': 'Meet the following conditions',
|
||||
'advanceFilter.and': 'And',
|
||||
'advanceFilter.or': 'Or',
|
||||
'advanceFilter.inputPlaceholder': 'Separate keywords with spaces',
|
||||
'advanceFilter.addCondition': 'Add conditions',
|
||||
'advanceFilter.conditionRequired': 'The query condition cannot be empty',
|
||||
'advanceFilter.filterContentRequired': 'The filtering content cannot be empty',
|
||||
'advanceFilter.addCondition': 'Add condition',
|
||||
'advanceFilter.viewNameRequired': 'View name cannot be empty',
|
||||
'advanceFilter.viewNameNotRepeat': 'View name cannot be repeated',
|
||||
'advanceFilter.conditionRequired': 'Query condition cannot be empty',
|
||||
'advanceFilter.filterContentRequired': 'Filter content cannot be empty',
|
||||
'advanceFilter.filterTip': 'Filter mode, module filtering can only be operated in the current filter',
|
||||
};
|
||||
|
|
|
@ -22,6 +22,12 @@ export default {
|
|||
'advanceFilter.operator.length.lt': '长度小于',
|
||||
'advanceFilter.operator.length.le': '长度小于等于',
|
||||
|
||||
'advanceFilter.view': '视图',
|
||||
'advanceFilter.systemView': '系统视图',
|
||||
'advanceFilter.myView': '我的视图',
|
||||
'advanceFilter.newView': '新建视图',
|
||||
'advanceFilter.deleteView': '删除视图',
|
||||
'advanceFilter.clearFilter': '清空筛选',
|
||||
'advanceFilter.saveAsView': '另存为视图',
|
||||
'advanceFilter.viewNamePlaceholder': '请输入视图名称',
|
||||
'advanceFilter.meetTheFollowingConditions': '符合以下条件',
|
||||
|
@ -29,6 +35,9 @@ export default {
|
|||
'advanceFilter.or': '任一',
|
||||
'advanceFilter.inputPlaceholder': '关键字之间以空格进行分隔',
|
||||
'advanceFilter.addCondition': '添加条件',
|
||||
'advanceFilter.viewNameRequired': '视图名称不能为空',
|
||||
'advanceFilter.viewNameNotRepeat': '视图名称不能重复',
|
||||
'advanceFilter.conditionRequired': '查询条件不能为空',
|
||||
'advanceFilter.filterContentRequired': '筛选内容不能为空',
|
||||
'advanceFilter.filterTip': '筛选模式,模块过滤仅可在当前过滤器中操作',
|
||||
};
|
||||
|
|
|
@ -57,3 +57,37 @@ export interface FilterResult {
|
|||
conditions?: ConditionsItem[];
|
||||
combine?: any; // TODO lmy 此为防报错占位 所有高级筛选都完成后 删除这一行
|
||||
}
|
||||
|
||||
export interface ViewItem {
|
||||
id: string;
|
||||
userId: string;
|
||||
name: string;
|
||||
viewType: string; // 视图类型,例如功能用例视图
|
||||
internal: boolean; // 是否为内置视图
|
||||
scopeId: string; // 视图的应用范围,一般为项目ID
|
||||
searchMode: string;
|
||||
pos?: number; // 自定义排序
|
||||
createTime?: number;
|
||||
updateTime?: number;
|
||||
}
|
||||
export interface ViewList {
|
||||
internalViews: ViewItem[];
|
||||
customViews: ViewItem[];
|
||||
}
|
||||
export interface ViewParams extends FilterResult {
|
||||
id?: string;
|
||||
name: string;
|
||||
scopeId?: string;
|
||||
}
|
||||
export interface ViewDetail extends ViewParams {
|
||||
userId?: string;
|
||||
viewType?: string;
|
||||
internal?: boolean; // 是否为内置视图
|
||||
internalViewKey?: string;
|
||||
createTime?: number;
|
||||
updateTime?: number;
|
||||
}
|
||||
|
||||
export interface FilterForm extends ViewDetail {
|
||||
list: FilterFormItem[];
|
||||
}
|
||||
|
|
|
@ -27,3 +27,7 @@ export enum FilterType {
|
|||
CASCADER = 'Cascader',
|
||||
JIRAKEY = 'JIRAKEY',
|
||||
}
|
||||
|
||||
export enum ViewTypeEnum {
|
||||
FUNCTIONAL_CASE = 'functional-case',
|
||||
}
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
<!-- 用例表开始 -->
|
||||
<template v-if="showType === 'list'">
|
||||
<MsAdvanceFilter
|
||||
ref="msAdvanceFilterRef"
|
||||
v-model:keyword="keyword"
|
||||
show-filter
|
||||
:view-type="ViewTypeEnum.FUNCTIONAL_CASE"
|
||||
:filter-config-list="filterConfigList"
|
||||
:custom-fields-config-list="searchCustomFields"
|
||||
:search-placeholder="t('caseManagement.featureCase.searchPlaceholder')"
|
||||
|
@ -438,7 +439,7 @@
|
|||
DragCase,
|
||||
} from '@/models/caseManagement/featureCase';
|
||||
import { ModuleTreeNode } from '@/models/common';
|
||||
import { FilterType } from '@/enums/advancedFilterEnum';
|
||||
import { FilterType, ViewTypeEnum } from '@/enums/advancedFilterEnum';
|
||||
import { CaseManagementRouteEnum, RouteEnum } from '@/enums/routeEnum';
|
||||
import { ColumnEditTypeEnum, TableKeyEnum } from '@/enums/tableEnum';
|
||||
import { FilterRemoteMethodsEnum, FilterSlotNameEnum } from '@/enums/tableFilterEnum';
|
||||
|
@ -977,7 +978,8 @@
|
|||
};
|
||||
});
|
||||
|
||||
const isAdvancedSearchMode = ref(false);
|
||||
const msAdvanceFilterRef = ref<InstanceType<typeof MsAdvanceFilter>>();
|
||||
const isAdvancedSearchMode = computed(() => msAdvanceFilterRef.value?.isAdvancedSearchMode);
|
||||
async function initTableParams() {
|
||||
let moduleIds: string[] = [];
|
||||
if (props.activeFolder !== 'all' && !isAdvancedSearchMode.value) {
|
||||
|
@ -1613,7 +1615,6 @@
|
|||
}
|
||||
// 高级检索
|
||||
const handleAdvSearch = async (filter: FilterResult) => {
|
||||
isAdvancedSearchMode.value = !!filter.conditions?.length;
|
||||
resetSelector();
|
||||
emit('setActiveFolder');
|
||||
keyword.value = '';
|
||||
|
|
Loading…
Reference in New Issue