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