feat(公共): 筛选面板组件调整
This commit is contained in:
parent
4ee10e11dc
commit
7a191e2c40
|
@ -1,4 +1,5 @@
|
|||
import { OPERATORS } from './operator';
|
||||
import type { SearchKeyType } from './type';
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
export enum CaseKeyEnum {
|
||||
|
@ -17,7 +18,7 @@ export enum CaseKeyEnum {
|
|||
}
|
||||
|
||||
// 名称
|
||||
export const NAME = {
|
||||
export const NAME: SearchKeyType = {
|
||||
key: CaseKeyEnum.NAME, // 对应字段key
|
||||
type: 'a-input', // Vue控件名称
|
||||
label: '显示名称', // 显示名称
|
||||
|
@ -28,7 +29,7 @@ export const NAME = {
|
|||
};
|
||||
|
||||
// 标签
|
||||
export const TAGS = {
|
||||
export const TAGS: SearchKeyType = {
|
||||
key: CaseKeyEnum.TAGS,
|
||||
type: 'a-input',
|
||||
label: '标签',
|
||||
|
@ -39,7 +40,7 @@ export const TAGS = {
|
|||
};
|
||||
|
||||
// 所属模块
|
||||
export const MODULE = {
|
||||
export const MODULE: SearchKeyType = {
|
||||
key: 'module',
|
||||
type: 'a-tree-select',
|
||||
label: '所属模块',
|
||||
|
@ -50,23 +51,27 @@ export const MODULE = {
|
|||
};
|
||||
|
||||
// 创建时间
|
||||
export const CREATE_TIME = {
|
||||
export const CREATE_TIME: SearchKeyType = {
|
||||
key: CaseKeyEnum.CREATE_TIME,
|
||||
type: 'time-select', // 时间选择器
|
||||
label: '创建时间',
|
||||
rules: [{ required: true, message: '请选择创建时间!' }],
|
||||
props: {},
|
||||
operator: {
|
||||
value: '',
|
||||
options: [OPERATORS.BETWEEN, OPERATORS.GT, OPERATORS.LT],
|
||||
},
|
||||
};
|
||||
|
||||
// 更新时间
|
||||
export const UPDATE_TIME = {
|
||||
export const UPDATE_TIME: SearchKeyType = {
|
||||
key: CaseKeyEnum.UPDATE_TIME,
|
||||
type: 'time-select',
|
||||
label: '更新时间',
|
||||
rules: [{ required: true, message: '请选择更新时间!' }],
|
||||
props: {},
|
||||
operator: {
|
||||
value: '',
|
||||
options: [OPERATORS.BETWEEN, OPERATORS.GT, OPERATORS.LT],
|
||||
},
|
||||
};
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
:is="form.searchKey.type"
|
||||
v-bind="form.searchKey.props"
|
||||
v-model="form.searchKey.value"
|
||||
@change="cate1ChangeHandler"
|
||||
@change="searchKeyChange"
|
||||
>
|
||||
<a-optgroup
|
||||
v-for="(group, index) of props.selectGroupList"
|
||||
:key="`${group.label as string + index}`"
|
||||
v-for="(group, i) of props.selectGroupList"
|
||||
:key="`${group.label as string}-${i}`"
|
||||
:label="group.label"
|
||||
>
|
||||
<a-option
|
||||
|
@ -36,35 +36,46 @@
|
|||
</component>
|
||||
</div>
|
||||
<div class="flex flex-1">
|
||||
<TimerSelect
|
||||
v-if="getQueryContentType('time-select')"
|
||||
:model-value="form.queryContent.value"
|
||||
v-bind="form.queryContent.props"
|
||||
:operation-type="form.operatorCondition.value"
|
||||
@update-time="updateTimeValue"
|
||||
/>
|
||||
<component
|
||||
:is="form.queryContent.type"
|
||||
v-else
|
||||
v-bind="form.queryContent.props"
|
||||
v-model="form.queryContent.value"
|
||||
@change="filterKeyChange"
|
||||
>
|
||||
<template v-if="form.queryContent.type === 'a-select'">
|
||||
<a-option v-for="opt of form.queryContent.options" :key="opt.value" :value="opt.value">{{
|
||||
opt.label
|
||||
}}</a-option>
|
||||
</template>
|
||||
<template v-else-if="form.queryContent.type === 'a-select-group'">
|
||||
<a-select v-model="form.queryContent.value" v-bind="form.queryContent.props">
|
||||
<a-optgroup v-for="group of form.searchKey.options" :key="group.id" :label="group.label">
|
||||
<a-option v-for="groupOptions of group.options" :key="groupOptions.id" :value="groupOptions.id">{{
|
||||
groupOptions.label
|
||||
<a-form ref="queryContentFormRef" :model="form.queryContent">
|
||||
<a-form-item
|
||||
required
|
||||
field="value"
|
||||
:rules="form.queryContent.rules || [{ required: true, message: '请输入筛选内容' }]"
|
||||
hide-label
|
||||
hide-asterisk
|
||||
class="mb-0"
|
||||
>
|
||||
<TimerSelect
|
||||
v-if="form.queryContent.type === 'time-select'"
|
||||
:model-value="form.queryContent.value"
|
||||
v-bind="form.queryContent.props"
|
||||
:operation-type="form.operatorCondition.value"
|
||||
@update-time="updateTimeValue"
|
||||
/>
|
||||
<component
|
||||
:is="form.queryContent.type"
|
||||
v-else
|
||||
v-bind="form.queryContent.props"
|
||||
v-model="form.queryContent.value"
|
||||
@change="filterKeyChange"
|
||||
>
|
||||
<template v-if="form.queryContent.type === 'a-select'">
|
||||
<a-option v-for="opt of form.queryContent.options" :key="opt.value" :value="opt.value">{{
|
||||
opt.label
|
||||
}}</a-option>
|
||||
</a-optgroup>
|
||||
</a-select>
|
||||
</template>
|
||||
</component>
|
||||
</template>
|
||||
<template v-else-if="form.queryContent.type === 'a-select-group'">
|
||||
<a-select v-model="form.queryContent.value" v-bind="form.queryContent.props">
|
||||
<a-optgroup v-for="group of form.searchKey.options" :key="group.id" :label="group.label">
|
||||
<a-option v-for="groupOptions of group.options" :key="groupOptions.id" :value="groupOptions.id">{{
|
||||
groupOptions.label
|
||||
}}</a-option>
|
||||
</a-optgroup>
|
||||
</a-select>
|
||||
</template>
|
||||
</component>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<div class="minus"> <slot></slot></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -78,6 +89,8 @@
|
|||
import { TEST_PLAN_TEST_CASE } from './caseUtils';
|
||||
import TimerSelect from './time-select.vue';
|
||||
import { SelectOptionData } from '@arco-design/web-vue';
|
||||
import type { FormInstance } from '@arco-design/web-vue';
|
||||
import type { SearchKeyType } from './type';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
|
@ -93,20 +106,24 @@
|
|||
const form = ref({ ...cloneDeep(props.formItem) });
|
||||
|
||||
watchEffect(() => {
|
||||
form.value.queryContent.value = props.formItem.queryContent.value;
|
||||
form.value = { ...cloneDeep(props.formItem) };
|
||||
});
|
||||
|
||||
// 一级属性变化回调
|
||||
const cate1ChangeHandler = (value: string) => {
|
||||
const searchKeyChange = (value: string) => {
|
||||
const { operatorCondition, queryContent } = form.value;
|
||||
operatorCondition.value = '';
|
||||
operatorCondition.options = [];
|
||||
queryContent.value = '';
|
||||
// 获取当前选中查询Key属性的配置项
|
||||
const currentKeysConfig = TEST_PLAN_TEST_CASE.find((item) => item.key === value);
|
||||
const currentKeysConfig = TEST_PLAN_TEST_CASE.find((item: any) => item.key === value);
|
||||
if (currentKeysConfig) {
|
||||
operatorCondition.options = currentKeysConfig.operator.options;
|
||||
operatorCondition.value = currentKeysConfig.operator.options[0].value;
|
||||
queryContent.type = currentKeysConfig.type;
|
||||
if (currentKeysConfig.rules) {
|
||||
queryContent.rules = currentKeysConfig.rules;
|
||||
}
|
||||
}
|
||||
emits('dataUpdated', form.value, props.index);
|
||||
};
|
||||
|
@ -132,17 +149,22 @@
|
|||
form.value.queryContent.value = time;
|
||||
emits('dataUpdated', form.value, props.index);
|
||||
};
|
||||
const queryContentFormRef = ref<FormInstance>();
|
||||
|
||||
// 判断当前情况
|
||||
const getQueryContentType = (type: string) => {
|
||||
switch (type) {
|
||||
// 时间选择面板
|
||||
case 'time-select':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
// 校验表单
|
||||
const validateQueryContent = (callBack: (isSuccess: string) => void) => {
|
||||
queryContentFormRef.value?.validate((errors) => {
|
||||
if (!errors) {
|
||||
callBack('ok');
|
||||
} else {
|
||||
callBack('no');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
validateQueryContent,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<div v-for="(formItem, index) in formModels" :key="index" class="mb-[8px]">
|
||||
<a-scrollbar class="overflow-y-auto" :style="{ 'max-height': props.maxHeight || '300px' }">
|
||||
<QueryFromItem
|
||||
ref="queryFromRef"
|
||||
:form-item="formItem"
|
||||
:form-list="formModels"
|
||||
:select-group-list="selectGroupList"
|
||||
|
@ -162,6 +163,11 @@
|
|||
type: 'a-input',
|
||||
value: '',
|
||||
field: 'condition',
|
||||
props: {
|
||||
'max-length': 60,
|
||||
'show-word-limit': true,
|
||||
'allow-clear': true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -169,17 +175,37 @@
|
|||
|
||||
// 移除查询条件项
|
||||
const removeField = (index: number) => {
|
||||
debugger;
|
||||
formModels.value.splice(index, 1);
|
||||
};
|
||||
|
||||
// 校验结果列表
|
||||
const allValidateResult = ref<string[]>([]);
|
||||
|
||||
const queryFromRef = ref();
|
||||
|
||||
// 添加查询条件项
|
||||
const addField = () => {
|
||||
const addField = async () => {
|
||||
allValidateResult.value = [];
|
||||
// 全部校验通过可进行添加
|
||||
await Promise.all(
|
||||
queryFromRef.value.map((item: any) => {
|
||||
return new Promise<void>((resolve) => {
|
||||
item.validateQueryContent(async (isValidated: string) => {
|
||||
allValidateResult.value.push(isValidated);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
const isValidateSuccess = allValidateResult.value.every((item: string) => item === 'ok');
|
||||
const ishasCondition = formModels.value.some((item) => !item.searchKey.value);
|
||||
if (ishasCondition) {
|
||||
Message.warning(t('searchPanel.selectTip'));
|
||||
return;
|
||||
}
|
||||
formModels.value.push(deaultTemplate);
|
||||
if (isValidateSuccess && !ishasCondition) {
|
||||
formModels.value.push(deaultTemplate);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理更新后的数据
|
||||
|
@ -223,4 +249,7 @@
|
|||
background: rgb(var(--primary-9));
|
||||
}
|
||||
}
|
||||
:deep(.arco-scrollbar-track-direction-vertical .arco-scrollbar-thumb-bar) {
|
||||
margin: 7px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
v-model:model-value="timeValue"
|
||||
class="w-[100%]"
|
||||
show-time
|
||||
allow-clear
|
||||
:time-picker-props="{ defaultValue: '00:00:00' }"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
position="br"
|
||||
|
@ -15,6 +14,7 @@
|
|||
v-model:model-value="timeRangeValue"
|
||||
position="br"
|
||||
show-time
|
||||
:allow-clear="false"
|
||||
class="w-[100%]"
|
||||
format="YYYY-MM-DD HH:mm"
|
||||
:time-picker-props="{
|
||||
|
@ -26,12 +26,12 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { CalendarValue } from '@arco-design/web-vue/es/date-picker/interface';
|
||||
import { ref, watch } from 'vue';
|
||||
import { ref, watch, watchEffect } from 'vue';
|
||||
|
||||
type PickerType = 'between' | 'gt' | 'lt'; // 之间 | 大于 | 小于
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: [] | string; // 传入当前值
|
||||
modelValue: string[] | string; // 传入当前值
|
||||
operationType: PickerType; // 查询运算符条件类型
|
||||
}>();
|
||||
|
||||
|
@ -39,12 +39,19 @@
|
|||
|
||||
const timeValue = ref<string>('');
|
||||
|
||||
const timeRangeValue = ref([]);
|
||||
const timeRangeValue = ref<string[]>([]);
|
||||
|
||||
const changeHandler = (value: Date | string | number | undefined | (CalendarValue | undefined)[] | undefined) => {
|
||||
emits('updateTime', value);
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
if (props.operationType === 'between') {
|
||||
timeRangeValue.value = props.modelValue as string[];
|
||||
}
|
||||
timeValue.value = props.modelValue as string;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { SelectOptionData } from '@arco-design/web-vue';
|
||||
import { SelectOptionData, FieldRule } from '@arco-design/web-vue';
|
||||
|
||||
export interface ConditionOptions {
|
||||
id: string;
|
||||
|
@ -17,8 +17,8 @@ export interface QueryField {
|
|||
type: 'a-select' | 'a-input' | 'a-input-number' | 'time-select' | 'a-tree-select';
|
||||
value: string;
|
||||
field: string;
|
||||
rules?: FieldRule[];
|
||||
props?: {
|
||||
placeholder: string;
|
||||
[key: string]: string | number | boolean;
|
||||
};
|
||||
options?: SelectOptionData[];
|
||||
|
@ -29,3 +29,23 @@ export interface QueryTemplate {
|
|||
operatorCondition: QueryField;
|
||||
queryContent: QueryField;
|
||||
}
|
||||
|
||||
export interface OptionsType {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
export interface OperatorValue {
|
||||
value: string; // 如果未设置value初始值,则value初始值为options[0]
|
||||
options: OptionsType[]; // 运算符选项
|
||||
}
|
||||
|
||||
export interface SearchKeyType {
|
||||
key: string; // 对应字段key
|
||||
type: string; // Vue控件名称
|
||||
label: string; // 显示名称
|
||||
rules?: FieldRule[];
|
||||
props?: {
|
||||
[key: string]: string | number | boolean;
|
||||
};
|
||||
operator: OperatorValue;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
<div class="page-header h-[34px]">
|
||||
<div class="text-[var(--color-text-1)]"
|
||||
>{{ t('featureTest.featureCase.allCase') }}
|
||||
<span class="text-[var(--color-text-4)]"> ({{ allCaseCount }})</span></div
|
||||
<span class="text-[var(--color-text-4)]"> ({{ allCaseCount }})</span></div
|
||||
>
|
||||
<div>
|
||||
<div class="flex w-[80%] items-center justify-end">
|
||||
<a-select class="w-[240px]" :placeholder="t('featureTest.featureCase.versionPlaceholder')">
|
||||
<a-option v-for="version of versionOptions" :key="version.id" :value="version.id">{{ version.name }}</a-option>
|
||||
</a-select>
|
||||
|
@ -28,7 +28,7 @@
|
|||
</MsTag>
|
||||
<a-radio-group v-model:model-value="showType" type="button" class="file-show-type ml-[4px]">
|
||||
<a-radio value="list" class="show-type-icon p-[2px]"><MsIcon type="icon-icon_view-list_outlined" /></a-radio>
|
||||
<a-radio value="xmind" class="show-type-icon p-[2px]"><icon-mind-mapping /></a-radio>
|
||||
<a-radio value="xmind" class="show-type-icon p-[2px]"><MsIcon type="icon-icon_mindnote_outlined" /></a-radio>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue