fix(公共): 调整公共组件和去掉多余未使用文件
This commit is contained in:
parent
29dcd4d422
commit
c0ade8e3aa
|
@ -1,81 +0,0 @@
|
||||||
import { OPERATORS } from './operator';
|
|
||||||
import type { SearchKeyType } from './type';
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-shadow
|
|
||||||
export enum CaseKeyEnum {
|
|
||||||
NAME = 'name',
|
|
||||||
UPDATE_TIME = 'updateTime',
|
|
||||||
MODULES = 'modules',
|
|
||||||
CREATE_TIME = 'createTime',
|
|
||||||
CREATOR = 'creator',
|
|
||||||
TAGS = 'tags',
|
|
||||||
REVIEW_RESULT = 'reviewResults',
|
|
||||||
FOLLOW_PEOPLE = 'followPeople',
|
|
||||||
ASSOCIATED_REQUIREMENTS = 'associated_requirements',
|
|
||||||
CASE_LEVEL = 'caseLevel',
|
|
||||||
CASE_STATUS = 'caseStatus',
|
|
||||||
PRINCIPAL = 'principal', // 责任人
|
|
||||||
}
|
|
||||||
|
|
||||||
// 名称
|
|
||||||
export const NAME: SearchKeyType = {
|
|
||||||
key: CaseKeyEnum.NAME, // 对应字段key
|
|
||||||
type: 'a-input', // Vue控件名称
|
|
||||||
label: '显示名称', // 显示名称
|
|
||||||
operator: {
|
|
||||||
value: OPERATORS.LIKE.value, // 如果未设置value初始值,则value初始值为options[0]
|
|
||||||
options: [OPERATORS.LIKE, OPERATORS.NOT_LIKE], // 运算符选项
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// 标签
|
|
||||||
export const TAGS: SearchKeyType = {
|
|
||||||
key: CaseKeyEnum.TAGS,
|
|
||||||
type: 'a-input',
|
|
||||||
label: '标签',
|
|
||||||
operator: {
|
|
||||||
value: OPERATORS.LIKE.value,
|
|
||||||
options: [OPERATORS.LIKE, OPERATORS.NOT_LIKE],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// 所属模块
|
|
||||||
export const MODULE: SearchKeyType = {
|
|
||||||
key: 'module',
|
|
||||||
type: 'a-tree-select',
|
|
||||||
label: '所属模块',
|
|
||||||
operator: {
|
|
||||||
value: OPERATORS.LIKE.value,
|
|
||||||
options: [OPERATORS.LIKE, OPERATORS.NOT_LIKE],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// 创建时间
|
|
||||||
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: SearchKeyType = {
|
|
||||||
key: CaseKeyEnum.UPDATE_TIME,
|
|
||||||
type: 'time-select',
|
|
||||||
label: '更新时间',
|
|
||||||
rules: [{ required: true, message: '请选择更新时间!' }],
|
|
||||||
props: {},
|
|
||||||
operator: {
|
|
||||||
value: '',
|
|
||||||
options: [OPERATORS.BETWEEN, OPERATORS.GT, OPERATORS.LT],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
// 功能用例所需要列表
|
|
||||||
export const TEST_PLAN_TEST_CASE = [NAME, TAGS, MODULE, CREATE_TIME, UPDATE_TIME];
|
|
||||||
|
|
||||||
export default {};
|
|
|
@ -1,28 +0,0 @@
|
||||||
export default {
|
|
||||||
operators: {
|
|
||||||
is_empty: 'Is empty',
|
|
||||||
is_not_empty: 'Is not empty',
|
|
||||||
like: 'Contains',
|
|
||||||
not_like: 'Not included',
|
|
||||||
in: 'Belong to',
|
|
||||||
not_in: 'Not belonging',
|
|
||||||
gt: 'Greater than',
|
|
||||||
ge: 'Greater than or equal to',
|
|
||||||
lt: 'Less than',
|
|
||||||
le: 'Less than or equal to',
|
|
||||||
equals: 'Equal to',
|
|
||||||
not_equals: 'Not Equal to',
|
|
||||||
between: 'Between',
|
|
||||||
current_user: 'Current user',
|
|
||||||
},
|
|
||||||
condition: {
|
|
||||||
all: 'all',
|
|
||||||
oneOf: 'or',
|
|
||||||
},
|
|
||||||
searchPanel: {
|
|
||||||
addCondition: 'Add Conditions',
|
|
||||||
reset: 'reset',
|
|
||||||
filter: 'filter',
|
|
||||||
selectTip: 'Please select the query field',
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -1,29 +0,0 @@
|
||||||
export default {
|
|
||||||
// 操作符号
|
|
||||||
operators: {
|
|
||||||
is_empty: '空',
|
|
||||||
is_not_empty: '非空',
|
|
||||||
like: '包含',
|
|
||||||
not_like: '不包含',
|
|
||||||
in: '属于',
|
|
||||||
not_in: '不属于',
|
|
||||||
gt: '大于',
|
|
||||||
ge: '大于等于',
|
|
||||||
lt: '小于',
|
|
||||||
le: '小于等于',
|
|
||||||
equals: '等于',
|
|
||||||
not_equals: '不等于',
|
|
||||||
between: '之间',
|
|
||||||
current_user: '是当前用户',
|
|
||||||
},
|
|
||||||
condition: {
|
|
||||||
all: '所有',
|
|
||||||
oneOf: '任一',
|
|
||||||
},
|
|
||||||
searchPanel: {
|
|
||||||
addCondition: '添加条件',
|
|
||||||
reset: '重置',
|
|
||||||
filter: '筛选',
|
|
||||||
selectTip: '请选择查询字段',
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -1,49 +0,0 @@
|
||||||
// 运算符号
|
|
||||||
export const OPERATORS = {
|
|
||||||
LIKE: {
|
|
||||||
label: 'operators.like',
|
|
||||||
value: 'like',
|
|
||||||
},
|
|
||||||
NOT_LIKE: {
|
|
||||||
label: 'operators.not_like',
|
|
||||||
value: 'not like',
|
|
||||||
},
|
|
||||||
IN: {
|
|
||||||
label: 'operators.in',
|
|
||||||
value: 'in',
|
|
||||||
},
|
|
||||||
NOT_IN: {
|
|
||||||
label: 'operators.not_in',
|
|
||||||
value: 'not in',
|
|
||||||
},
|
|
||||||
GT: {
|
|
||||||
label: 'operators.gt',
|
|
||||||
value: 'gt',
|
|
||||||
},
|
|
||||||
GE: {
|
|
||||||
label: 'operators.ge',
|
|
||||||
value: 'ge',
|
|
||||||
},
|
|
||||||
LT: {
|
|
||||||
label: 'operators.lt',
|
|
||||||
value: 'lt',
|
|
||||||
},
|
|
||||||
LE: {
|
|
||||||
label: 'operators.le',
|
|
||||||
value: 'le',
|
|
||||||
},
|
|
||||||
EQ: {
|
|
||||||
label: 'operators.equals',
|
|
||||||
value: 'eq',
|
|
||||||
},
|
|
||||||
BETWEEN: {
|
|
||||||
label: 'operators.between',
|
|
||||||
value: 'between',
|
|
||||||
},
|
|
||||||
CURRENT_USER: {
|
|
||||||
label: 'operators.current_user',
|
|
||||||
value: 'current user',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {};
|
|
|
@ -1,172 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="overflow-y-auto">
|
|
||||||
<div class="flex flex-wrap items-start gap-[8px]">
|
|
||||||
<div class="flex-1">
|
|
||||||
<component
|
|
||||||
:is="form.searchKey.type"
|
|
||||||
v-bind="form.searchKey.props"
|
|
||||||
v-model="form.searchKey.value"
|
|
||||||
@change="searchKeyChange"
|
|
||||||
>
|
|
||||||
<a-optgroup
|
|
||||||
v-for="(group, i) of props.selectGroupList"
|
|
||||||
:key="`${group.label as string}-${i}`"
|
|
||||||
:label="group.label"
|
|
||||||
>
|
|
||||||
<a-option
|
|
||||||
v-for="groupOptions of group.options"
|
|
||||||
:key="groupOptions.value"
|
|
||||||
:value="groupOptions.value"
|
|
||||||
:disabled="isDisabledList.indexOf(groupOptions.value) > -1"
|
|
||||||
>{{ groupOptions.label }}</a-option
|
|
||||||
>
|
|
||||||
</a-optgroup>
|
|
||||||
</component>
|
|
||||||
</div>
|
|
||||||
<div class="w-[100px]">
|
|
||||||
<component
|
|
||||||
:is="form.operatorCondition.type"
|
|
||||||
v-bind="form.operatorCondition.props"
|
|
||||||
v-model="form.operatorCondition.value"
|
|
||||||
@change="operatorChangeHandler"
|
|
||||||
>
|
|
||||||
<a-option v-for="operator of form.operatorCondition.options" :key="operator.value" :value="operator.value">
|
|
||||||
{{ t(operator.label) }}
|
|
||||||
</a-option>
|
|
||||||
</component>
|
|
||||||
</div>
|
|
||||||
<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
|
|
||||||
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>
|
|
||||||
</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>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed, ref, watchEffect } from 'vue';
|
|
||||||
import { SelectOptionData } from '@arco-design/web-vue';
|
|
||||||
import { cloneDeep } from 'lodash-es';
|
|
||||||
|
|
||||||
import TimerSelect from './time-select.vue';
|
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
|
||||||
|
|
||||||
import { TEST_PLAN_TEST_CASE } from './caseUtils';
|
|
||||||
import type { FormInstance } from '@arco-design/web-vue';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
formItem: Record<string, any>; // 当前筛选项
|
|
||||||
index: number; // 当前操作的项索引
|
|
||||||
formList: Record<string, any>[]; // 全部项列表筛选项列表
|
|
||||||
selectGroupList: SelectOptionData[]; // 条件字段筛选下拉列表
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const emits = defineEmits(['dataUpdated']);
|
|
||||||
|
|
||||||
const form = ref({ ...cloneDeep(props.formItem) });
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
form.value = { ...cloneDeep(props.formItem) };
|
|
||||||
});
|
|
||||||
|
|
||||||
// 一级属性变化回调
|
|
||||||
const searchKeyChange = (value: string) => {
|
|
||||||
const { operatorCondition, queryContent } = form.value;
|
|
||||||
operatorCondition.value = '';
|
|
||||||
operatorCondition.options = [];
|
|
||||||
queryContent.value = '';
|
|
||||||
// 获取当前选中查询Key属性的配置项
|
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 禁用已选择选项
|
|
||||||
const isDisabledList = computed(() => {
|
|
||||||
return props.formList.map((item) => item.searchKey.value) || [];
|
|
||||||
});
|
|
||||||
|
|
||||||
// 运算符条件发生变化回调
|
|
||||||
const operatorChangeHandler = (value: string) => {
|
|
||||||
form.value.queryContent.value = value === 'between' ? [] : '';
|
|
||||||
emits('dataUpdated', form.value, props.index);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 更新数据
|
|
||||||
const filterKeyChange = () => {
|
|
||||||
emits('dataUpdated', form.value, props.index);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 更新时间值
|
|
||||||
const updateTimeValue = (time: string | []) => {
|
|
||||||
form.value.queryContent.value = time;
|
|
||||||
emits('dataUpdated', form.value, props.index);
|
|
||||||
};
|
|
||||||
const queryContentFormRef = ref<FormInstance>();
|
|
||||||
|
|
||||||
// 校验表单
|
|
||||||
const validateQueryContent = (callBack: (isSuccess: string) => void) => {
|
|
||||||
queryContentFormRef.value?.validate((errors) => {
|
|
||||||
if (!errors) {
|
|
||||||
callBack('ok');
|
|
||||||
} else {
|
|
||||||
callBack('no');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
validateQueryContent,
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
|
@ -1,257 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="filter-panel">
|
|
||||||
<div class="mb-4 flex items-center justify-between">
|
|
||||||
<div class="condition-text">{{ t('caseManagement.featureCase.setFilterCondition') }}</div>
|
|
||||||
<div>
|
|
||||||
<span class="condition-text">{{ t('caseManagement.featureCase.followingCondition') }}</span>
|
|
||||||
<a-select v-model="filterConditions.unit" class="mx-4 w-[68px]" size="small">
|
|
||||||
<a-option v-for="version of conditionOptions" :key="version.id" :value="version.value">{{
|
|
||||||
version.name
|
|
||||||
}}</a-option>
|
|
||||||
</a-select>
|
|
||||||
<span class="condition-text">{{ t('caseManagement.featureCase.condition') }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<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"
|
|
||||||
:index="index"
|
|
||||||
@data-updated="handleDataUpdated"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-show="formModels.length > 1"
|
|
||||||
class="remove-button ml-[8px] h-[32px] w-[32px] p-[2px]"
|
|
||||||
@click="removeField(index)"
|
|
||||||
>
|
|
||||||
<icon-minus-circle />
|
|
||||||
</div>
|
|
||||||
</QueryFromItem>
|
|
||||||
</a-scrollbar>
|
|
||||||
</div>
|
|
||||||
<div class="flex w-full items-center justify-between">
|
|
||||||
<a-button class="px-0" type="text" :disabled="isDisabledAdd" @click="addField">
|
|
||||||
<template #icon>
|
|
||||||
<icon-plus class="text-[14px]" />
|
|
||||||
</template>
|
|
||||||
{{ t('searchPanel.addCondition') }}
|
|
||||||
</a-button>
|
|
||||||
<div>
|
|
||||||
<a-button type="secondary" @click="resetField">{{ t('searchPanel.reset') }}</a-button>
|
|
||||||
<a-button class="ml-3" type="primary">{{ t('searchPanel.filter') }}</a-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed, ref } from 'vue';
|
|
||||||
import { Message } from '@arco-design/web-vue';
|
|
||||||
|
|
||||||
import QueryFromItem from './query-form-item.vue';
|
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
|
||||||
|
|
||||||
import type { ConditionOptions, QueryTemplate } from './type';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
const props = defineProps<{
|
|
||||||
maxHeight?: string; // 查询区域高度 默认300px
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const filterConditions = ref({
|
|
||||||
unit: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const conditionOptions = ref<ConditionOptions[]>([
|
|
||||||
{
|
|
||||||
id: '1001',
|
|
||||||
name: t('condition.all'),
|
|
||||||
value: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '1002',
|
|
||||||
name: t('condition.oneOf'),
|
|
||||||
value: 'oneOf',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 查询字段列表
|
|
||||||
const selectGroupList = ref([
|
|
||||||
{
|
|
||||||
label: '系统字段',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
value: 'name',
|
|
||||||
label: '名称',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'updateTime',
|
|
||||||
label: '更新时间',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '模版字段',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
value: 'tags',
|
|
||||||
label: '标签',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'module',
|
|
||||||
label: '模块',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 默认模版
|
|
||||||
const deaultTemplate: QueryTemplate = {
|
|
||||||
// 查询关键字段
|
|
||||||
searchKey: {
|
|
||||||
label: '',
|
|
||||||
type: 'a-select',
|
|
||||||
value: '',
|
|
||||||
field: 'nameKey',
|
|
||||||
props: {
|
|
||||||
placeholder: '请选择字段',
|
|
||||||
},
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: '系统字段',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
value: 'name',
|
|
||||||
label: '名称',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'updateTime',
|
|
||||||
label: '更新时间',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '模版字段',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
value: 'tags',
|
|
||||||
label: '标签',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'module',
|
|
||||||
label: '模块',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// 查询运算符条件
|
|
||||||
operatorCondition: {
|
|
||||||
label: '',
|
|
||||||
type: 'a-select',
|
|
||||||
value: '',
|
|
||||||
field: 'operator',
|
|
||||||
props: {
|
|
||||||
placeholder: '请选择条件',
|
|
||||||
},
|
|
||||||
options: [],
|
|
||||||
},
|
|
||||||
// 查询内容
|
|
||||||
queryContent: {
|
|
||||||
label: '',
|
|
||||||
type: 'a-input',
|
|
||||||
value: '',
|
|
||||||
field: 'condition',
|
|
||||||
props: {
|
|
||||||
'max-length': 60,
|
|
||||||
'show-word-limit': true,
|
|
||||||
'allow-clear': true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const formModels = ref<QueryTemplate[]>([{ ...deaultTemplate }]);
|
|
||||||
|
|
||||||
// 移除查询条件项
|
|
||||||
const removeField = (index: number) => {
|
|
||||||
formModels.value.splice(index, 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 校验结果列表
|
|
||||||
const allValidateResult = ref<string[]>([]);
|
|
||||||
|
|
||||||
const queryFromRef = ref();
|
|
||||||
|
|
||||||
// 添加查询条件项
|
|
||||||
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'));
|
|
||||||
}
|
|
||||||
if (isValidateSuccess && !ishasCondition) {
|
|
||||||
formModels.value.push(deaultTemplate);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 处理更新后的数据
|
|
||||||
const handleDataUpdated = (newFromData: any, index: number) => {
|
|
||||||
formModels.value.splice(index, 1, newFromData);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 计算所有条件都选中不能再添加条件
|
|
||||||
const isDisabledAdd = computed(() => {
|
|
||||||
const isSelectValueKeys = formModels.value.map((item) => item.searchKey.value).filter((item) => item);
|
|
||||||
const allOptions = selectGroupList.value.flatMap((group) => group.options).map((item) => item.value);
|
|
||||||
const isAllExistValue = allOptions.every((item) => isSelectValueKeys.indexOf(item) > -1);
|
|
||||||
return isAllExistValue;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 重置三级查询条件
|
|
||||||
const resetField = () => {
|
|
||||||
formModels.value = formModels.value.map((item) => ({
|
|
||||||
...item,
|
|
||||||
queryContent: {
|
|
||||||
...item.queryContent,
|
|
||||||
value: '',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="less">
|
|
||||||
.filter-panel {
|
|
||||||
background: var(--color-text-n9);
|
|
||||||
@apply mt-1 rounded-md p-3;
|
|
||||||
.condition-text {
|
|
||||||
color: var(--color-text-2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.remove-button {
|
|
||||||
color: var(--color-text-4);
|
|
||||||
@apply flex cursor-pointer items-center justify-center rounded;
|
|
||||||
&:hover {
|
|
||||||
color: rgb(var(--primary-5));
|
|
||||||
background: rgb(var(--primary-9));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
:deep(.arco-scrollbar-track-direction-vertical .arco-scrollbar-thumb-bar) {
|
|
||||||
margin: 7px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,67 +0,0 @@
|
||||||
<template>
|
|
||||||
<a-date-picker
|
|
||||||
v-if="props.operationType !== 'between'"
|
|
||||||
v-model:model-value="timeValue"
|
|
||||||
class="w-[100%]"
|
|
||||||
show-time
|
|
||||||
:time-picker-props="{ defaultValue: '00:00:00' }"
|
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
position="br"
|
|
||||||
@change="changeHandler"
|
|
||||||
/>
|
|
||||||
<a-range-picker
|
|
||||||
v-else
|
|
||||||
v-model:model-value="timeRangeValue"
|
|
||||||
position="br"
|
|
||||||
show-time
|
|
||||||
:allow-clear="false"
|
|
||||||
class="w-[100%]"
|
|
||||||
format="YYYY-MM-DD HH:mm"
|
|
||||||
:time-picker-props="{
|
|
||||||
defaultValue: ['00:00:00', '00:00:00'],
|
|
||||||
}"
|
|
||||||
@change="changeHandler"
|
|
||||||
></a-range-picker>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, watch, watchEffect } from 'vue';
|
|
||||||
|
|
||||||
import { CalendarValue } from '@arco-design/web-vue/es/date-picker/interface';
|
|
||||||
|
|
||||||
type PickerType = 'between' | 'gt' | 'lt'; // 之间 | 大于 | 小于
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
modelValue: string[] | string; // 传入当前值
|
|
||||||
operationType: PickerType; // 查询运算符条件类型
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const emits = defineEmits(['updateTime']);
|
|
||||||
|
|
||||||
const timeValue = ref<string>('');
|
|
||||||
|
|
||||||
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) => {
|
|
||||||
if (!val) {
|
|
||||||
if (props.operationType === 'between') timeRangeValue.value = [];
|
|
||||||
timeValue.value = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
|
@ -1,52 +0,0 @@
|
||||||
import { FieldRule, SelectOptionData } from '@arco-design/web-vue';
|
|
||||||
|
|
||||||
export interface ConditionOptions {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
value: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 选项组下拉options
|
|
||||||
export interface Option {
|
|
||||||
value: string;
|
|
||||||
label: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface QueryField {
|
|
||||||
label: string;
|
|
||||||
type: 'a-select' | 'a-input' | 'a-input-number' | 'time-select' | 'a-tree-select';
|
|
||||||
value: string;
|
|
||||||
field: string;
|
|
||||||
rules?: FieldRule[];
|
|
||||||
props?: {
|
|
||||||
[key: string]: string | number | boolean;
|
|
||||||
};
|
|
||||||
options?: SelectOptionData[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface QueryTemplate {
|
|
||||||
searchKey: QueryField;
|
|
||||||
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[];
|
|
||||||
request?: any;
|
|
||||||
props?: {
|
|
||||||
[key: string]: string | number | boolean;
|
|
||||||
};
|
|
||||||
operator: OperatorValue;
|
|
||||||
}
|
|
|
@ -1,157 +0,0 @@
|
||||||
<template>
|
|
||||||
<FormCreate v-model:api="formApi" :rule="formRuleList" :option="props.options || option"></FormCreate>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, watch } from 'vue';
|
|
||||||
import { debounce } from 'lodash-es';
|
|
||||||
|
|
||||||
import JiraKey from './comp/jiraKey.vue';
|
|
||||||
import PassWord from './formcreate-password.vue';
|
|
||||||
import SearchSelect from './searchSelect.vue';
|
|
||||||
|
|
||||||
import useFormCreateStore from '@/store/modules/form-create/form-create';
|
|
||||||
|
|
||||||
import { FormCreateKeyEnum } from '@/enums/formCreateEnum';
|
|
||||||
|
|
||||||
import type { FormItem } from './types';
|
|
||||||
import { FormRuleItem } from './types';
|
|
||||||
import formCreate, { Rule } from '@form-create/arco-design';
|
|
||||||
|
|
||||||
const formCreateStore = useFormCreateStore();
|
|
||||||
|
|
||||||
formCreate.component('PassWord', PassWord);
|
|
||||||
formCreate.component('SearchSelect', SearchSelect);
|
|
||||||
formCreate.component('JiraKey', JiraKey);
|
|
||||||
|
|
||||||
const FormCreate = formCreate.$form();
|
|
||||||
const option = {
|
|
||||||
resetBtn: false, // 不展示默认配置的重置和提交
|
|
||||||
submitBtn: false,
|
|
||||||
on: false, // 取消绑定on事件
|
|
||||||
form: {
|
|
||||||
layout: 'vertical',
|
|
||||||
labelAlign: 'left',
|
|
||||||
},
|
|
||||||
// 暂时默认
|
|
||||||
row: {
|
|
||||||
gutter: 0,
|
|
||||||
},
|
|
||||||
wrap: {
|
|
||||||
'asterisk-position': 'end',
|
|
||||||
'validate-trigger': ['change'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
// 处理配置项
|
|
||||||
const props = defineProps<{
|
|
||||||
options?: any; // 自定义配置
|
|
||||||
formRule: FormItem[]; // 表单的规则
|
|
||||||
formCreateKey: FormCreateKeyEnum[keyof FormCreateKeyEnum]; // 唯一表单Key
|
|
||||||
}>();
|
|
||||||
|
|
||||||
// const emit = defineEmits(['update:form-rule']);
|
|
||||||
|
|
||||||
const formApi = ref<any>({});
|
|
||||||
|
|
||||||
// 计算被级联的项
|
|
||||||
const cascadeItem = computed(() => {
|
|
||||||
const currentFormCreateRules = formCreateStore.formCreateRuleMap.get(props.formCreateKey);
|
|
||||||
// 获取当前列表里边所有包含cascade的item
|
|
||||||
if (currentFormCreateRules) {
|
|
||||||
const cascade = currentFormCreateRules
|
|
||||||
.map((item) => item.link)
|
|
||||||
.filter((item) => item)
|
|
||||||
.flatMap((flatItem: any) => flatItem);
|
|
||||||
// 给所有的link上边关联的某个item 进行绑定监视
|
|
||||||
return currentFormCreateRules.filter((item) => {
|
|
||||||
return cascade.indexOf(item.field) > -1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 计算远程检索的表单项
|
|
||||||
const getOptionsRequest = debounce((val: FormRuleItem) => {
|
|
||||||
// 获取当前变化的一项 监视到被级联的表单项
|
|
||||||
// 从所有的列表项里边获取所有的link到的那一项
|
|
||||||
const totalFormList = formCreateStore.formCreateRuleMap.get(props.formCreateKey);
|
|
||||||
if (totalFormList) {
|
|
||||||
const resultItem = totalFormList.find(
|
|
||||||
(item: any) => item.link && (item.link as string[]).indexOf(val.field as string) > -1
|
|
||||||
);
|
|
||||||
if (resultItem) {
|
|
||||||
formCreateStore.getOptions(val, props.formCreateKey, resultItem as FormRuleItem, formApi.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 300);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
cascadeItem,
|
|
||||||
(val) => {
|
|
||||||
// 监视当前改变请求获取当前方法下边的options 和获取多有的字段值
|
|
||||||
if (val) {
|
|
||||||
val.forEach((item) => {
|
|
||||||
if (item.value) {
|
|
||||||
getOptionsRequest(item as FormRuleItem);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ deep: true, immediate: false }
|
|
||||||
);
|
|
||||||
|
|
||||||
const formRuleList = ref<FormRuleItem[]>([]); // 存放转换格式后
|
|
||||||
const formRules = ref<FormItem[]>([]);
|
|
||||||
watch(
|
|
||||||
() => props.formRule,
|
|
||||||
() => {
|
|
||||||
formRules.value = props.formRule;
|
|
||||||
formCreateStore.setInitFormCreate(props.formCreateKey, props.formRule);
|
|
||||||
formCreateStore.initFormCreateFormRules(props.formCreateKey);
|
|
||||||
formRuleList.value = formCreateStore.formCreateRuleMap.get(props.formCreateKey) as FormRuleItem[];
|
|
||||||
},
|
|
||||||
{ deep: true, immediate: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
const formData = computed(() => {
|
|
||||||
return formCreateStore.formRuleMap.get(props.formCreateKey);
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => formData.value,
|
|
||||||
() => {
|
|
||||||
formRuleList.value = formCreateStore.formCreateRuleMap.get(props.formCreateKey) as FormRuleItem[];
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => formRuleList.value,
|
|
||||||
() => {
|
|
||||||
// 处理数据格式更新
|
|
||||||
const result = formRuleList.value.map((item: any) => {
|
|
||||||
const type = props.formRule.find((it: any) => it.name === item.field)?.type;
|
|
||||||
const formItemRule = {
|
|
||||||
name: item.field,
|
|
||||||
type,
|
|
||||||
label: item.title,
|
|
||||||
value: item.value,
|
|
||||||
required: item?.effect?.required,
|
|
||||||
inputSearch: item.props.inputSearch || false,
|
|
||||||
instructionsIcon: item.props.instructionsIcon || '',
|
|
||||||
optionMethod: item.props.optionMethod || '',
|
|
||||||
couplingConfig: {
|
|
||||||
...item.props.couplingConfig,
|
|
||||||
},
|
|
||||||
sourceType: item.sourceType || '',
|
|
||||||
};
|
|
||||||
return formItemRule;
|
|
||||||
});
|
|
||||||
formCreateStore.setInitFormCreate(props.formCreateKey, result as FormItem[]);
|
|
||||||
},
|
|
||||||
{ deep: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
formApi, // 对外暴漏用于表单校验和清除校验状态 具体参考form-create文档API
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
|
@ -3,6 +3,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 用于原生字段form-create
|
||||||
|
*/
|
||||||
import { ref, watch, watchEffect } from 'vue';
|
import { ref, watch, watchEffect } from 'vue';
|
||||||
|
|
||||||
import JiraKey from './comp/jiraKey.vue';
|
import JiraKey from './comp/jiraKey.vue';
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
/**
|
||||||
|
* @description 用于自己扩展功能的form-create
|
||||||
|
*/
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
import { FieldTypeFormRules } from '@/components/pure/ms-form-create/form-create';
|
import { FieldTypeFormRules } from '@/components/pure/ms-form-create/form-create';
|
||||||
|
@ -149,7 +152,12 @@
|
||||||
(formItemType: any) => item.type?.toUpperCase() === formItemType
|
(formItemType: any) => item.type?.toUpperCase() === formItemType
|
||||||
);
|
);
|
||||||
if (currentTypeForm) {
|
if (currentTypeForm) {
|
||||||
fieldType = FieldTypeFormRules[currentTypeForm].type;
|
if (currentTypeForm === 'INPUT' && item.subDesc) {
|
||||||
|
// 如果是input类型并且有subDesc说明是JiraKey 类型
|
||||||
|
fieldType = 'JiraKey';
|
||||||
|
} else {
|
||||||
|
fieldType = FieldTypeFormRules[currentTypeForm].type;
|
||||||
|
}
|
||||||
const options = item?.options;
|
const options = item?.options;
|
||||||
const currentOptions = options?.map((optionsItem: any) => {
|
const currentOptions = options?.map((optionsItem: any) => {
|
||||||
return {
|
return {
|
||||||
|
@ -188,6 +196,7 @@
|
||||||
'disabled': item?.props?.disabled,
|
'disabled': item?.props?.disabled,
|
||||||
'type': item.control?.length && item.type === 'RADIO' ? 'button' : '',
|
'type': item.control?.length && item.type === 'RADIO' ? 'button' : '',
|
||||||
},
|
},
|
||||||
|
sourceType: item.type || '',
|
||||||
control: [],
|
control: [],
|
||||||
update: item.update,
|
update: item.update,
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,16 +17,13 @@
|
||||||
import { getPluginOptions } from '@/api/modules/setting/pluginManger';
|
import { getPluginOptions } from '@/api/modules/setting/pluginManger';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
import useFormCreateStore from '@/store/modules/form-create/form-create';
|
|
||||||
|
|
||||||
import type { OptionsParams } from '@/models/setting/plugin';
|
import type { OptionsParams } from '@/models/setting/plugin';
|
||||||
import { FormCreateKeyEnum } from '@/enums/formCreateEnum';
|
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const organizationId = computed(() => appStore.currentOrgId);
|
const organizationId = computed(() => appStore.currentOrgId);
|
||||||
|
|
||||||
const attrs = useAttrs();
|
const attrs = useAttrs();
|
||||||
const formCreateStore = useFormCreateStore();
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
|
|
|
@ -1,128 +0,0 @@
|
||||||
import { defineStore } from 'pinia';
|
|
||||||
|
|
||||||
import { FieldTypeFormRules } from '@/components/pure/ms-form-create/form-create';
|
|
||||||
import type { FormItem, FormRuleItem } from '@/components/pure/ms-form-create/types';
|
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
|
||||||
|
|
||||||
import { FormCreateKeyEnum } from '@/enums/formCreateEnum';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
const useFormCreateStore = defineStore('form-create', {
|
|
||||||
persist: false,
|
|
||||||
state: (): {
|
|
||||||
formRuleMap: Map<FormCreateKeyEnum[keyof FormCreateKeyEnum], FormItem[]>;
|
|
||||||
formCreateRuleMap: Map<FormCreateKeyEnum[keyof FormCreateKeyEnum], FormRuleItem[]>;
|
|
||||||
} => ({
|
|
||||||
formRuleMap: new Map(),
|
|
||||||
formCreateRuleMap: new Map(),
|
|
||||||
}),
|
|
||||||
actions: {
|
|
||||||
// 存储外边传递初始化数据格式存储form-item
|
|
||||||
setInitFormCreate(key: FormCreateKeyEnum[keyof FormCreateKeyEnum], formRule: FormItem[]) {
|
|
||||||
this.formRuleMap = new Map();
|
|
||||||
this.formRuleMap.set(key, formRule);
|
|
||||||
},
|
|
||||||
// 根据不同的类型初始化数据
|
|
||||||
initFormCreateFormRules(key: FormCreateKeyEnum[keyof FormCreateKeyEnum]) {
|
|
||||||
const currentFormRule = this.formRuleMap.get(key);
|
|
||||||
// 处理数据结构
|
|
||||||
const result = currentFormRule?.map((item: FormItem) => {
|
|
||||||
// 当前类型
|
|
||||||
let fieldType;
|
|
||||||
// 从总form类型里边配置:参考form-create.ts里边配置
|
|
||||||
const currentTypeForm = Object.keys(FieldTypeFormRules).find(
|
|
||||||
(formItemType: any) => item.type?.toUpperCase() === formItemType
|
|
||||||
);
|
|
||||||
if (currentTypeForm) {
|
|
||||||
if (currentTypeForm === 'INPUT' && item.subDesc) {
|
|
||||||
// 如果是input类型并且有subDesc说明是JiraKey 类型
|
|
||||||
fieldType = 'JiraKey';
|
|
||||||
} else {
|
|
||||||
fieldType = FieldTypeFormRules[currentTypeForm].type;
|
|
||||||
}
|
|
||||||
const options = item?.options;
|
|
||||||
const currentOptions = options?.map((optionsItem) => {
|
|
||||||
return {
|
|
||||||
label: optionsItem.text,
|
|
||||||
value: optionsItem.value,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const ruleItem = {
|
|
||||||
type: fieldType, // 表单类型
|
|
||||||
field: item.name, // 字段
|
|
||||||
title: t(item.label), // label 表单标签
|
|
||||||
value: item.value || FieldTypeFormRules[currentTypeForm].value, // 目前的值
|
|
||||||
effect: {
|
|
||||||
required: item.required, // 是否必填
|
|
||||||
},
|
|
||||||
// 级联关联到某一个form上 可能存在多个级联
|
|
||||||
options: !item.optionMethod ? currentOptions : [],
|
|
||||||
link: item.couplingConfig?.cascade,
|
|
||||||
rule: item.validate || [],
|
|
||||||
sourceType: item.type, // 原始表单类型
|
|
||||||
// 梳理表单所需要属性
|
|
||||||
props: {
|
|
||||||
...FieldTypeFormRules[currentTypeForm].props,
|
|
||||||
'tooltip': item.tooltip,
|
|
||||||
// 表单后边展示图片
|
|
||||||
'instructionsIcon': item.instructionsIcon,
|
|
||||||
// 下拉选项请求 必须是开启远程搜索才有该方法
|
|
||||||
'subDesc': item.subDesc,
|
|
||||||
// 级联匹配规则
|
|
||||||
'couplingConfig': { ...item.couplingConfig },
|
|
||||||
'optionMethod': item.inputSearch && item.optionMethod ? item.optionMethod : '',
|
|
||||||
'inputSearch': item.inputSearch,
|
|
||||||
'allow-search': item.inputSearch,
|
|
||||||
'keyword': '', // SearchSelect组件变化值
|
|
||||||
'modelValue': item.value,
|
|
||||||
'options': currentOptions, // 当前已经存在的options
|
|
||||||
'formKey': key, // 对应pinia-form-create里边初始化的KEY
|
|
||||||
'disabled': item?.props?.disabled,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
// 如果不存在关联name删除link关联属性
|
|
||||||
if (ruleItem.link === '') {
|
|
||||||
delete ruleItem.link;
|
|
||||||
}
|
|
||||||
// 如果不是等于下拉多选或者单选等
|
|
||||||
if (ruleItem.type !== 'SearchSelect') {
|
|
||||||
delete ruleItem.props.inputSearch;
|
|
||||||
}
|
|
||||||
return ruleItem;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
});
|
|
||||||
this.setInitdRules(key, result as FormRuleItem[]);
|
|
||||||
},
|
|
||||||
// 初始化好了的格式给formCreate
|
|
||||||
setInitdRules(key: FormCreateKeyEnum[keyof FormCreateKeyEnum], result: FormRuleItem[]) {
|
|
||||||
this.formCreateRuleMap.set(key, result);
|
|
||||||
},
|
|
||||||
|
|
||||||
/** **
|
|
||||||
* @description 处理监视联动获取请求
|
|
||||||
* @param key: 对应Map的Key
|
|
||||||
* @param item: 当前对应关联项-请求改变options
|
|
||||||
* @param formValueApi: 当前表单值实例可以获取表单的当前已经设置的值
|
|
||||||
*/
|
|
||||||
async getOptions(
|
|
||||||
val: FormRuleItem,
|
|
||||||
key: FormCreateKeyEnum[keyof FormCreateKeyEnum],
|
|
||||||
cascadeItem: FormRuleItem,
|
|
||||||
formValueApi: any
|
|
||||||
) {
|
|
||||||
const formValue = formValueApi.formData();
|
|
||||||
// 设置自定义属性给到searchSelect
|
|
||||||
const formCreateRuleArr = this.formCreateRuleMap.get(key);
|
|
||||||
const formCreateItem = formCreateRuleArr?.find((items) => cascadeItem.field === items.field);
|
|
||||||
if (formCreateItem) {
|
|
||||||
formCreateItem.props.keyword = val.value;
|
|
||||||
formCreateItem.props.formValue = formValue;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
getters: {},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default useFormCreateStore;
|
|
|
@ -94,8 +94,9 @@
|
||||||
<MsFormCreate
|
<MsFormCreate
|
||||||
v-if="formRules.length"
|
v-if="formRules.length"
|
||||||
ref="formCreateRef"
|
ref="formCreateRef"
|
||||||
|
v-model:formItem="formItem"
|
||||||
|
v-model:api="fApi"
|
||||||
:form-rule="formRules"
|
:form-rule="formRules"
|
||||||
:form-create-key="FormCreateKeyEnum.BUG_DETAIL"
|
|
||||||
/>
|
/>
|
||||||
<a-form-item field="tag" :label="t('bugManagement.tag')">
|
<a-form-item field="tag" :label="t('bugManagement.tag')">
|
||||||
<a-input-tag
|
<a-input-tag
|
||||||
|
@ -137,8 +138,8 @@
|
||||||
import { FileItem, Message } from '@arco-design/web-vue';
|
import { FileItem, Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
import MsFormCreate from '@/components/pure/ms-form-create/form-create.vue';
|
import MsFormCreate from '@/components/pure/ms-form-create/ms-form-create.vue';
|
||||||
import { FormItem } from '@/components/pure/ms-form-create/types';
|
import { FormItem, FormRuleItem } from '@/components/pure/ms-form-create/types';
|
||||||
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
|
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
|
||||||
import FileList from '@/components/pure/ms-upload/fileList.vue';
|
import FileList from '@/components/pure/ms-upload/fileList.vue';
|
||||||
import MsUpload from '@/components/pure/ms-upload/index.vue';
|
import MsUpload from '@/components/pure/ms-upload/index.vue';
|
||||||
|
@ -157,7 +158,6 @@
|
||||||
import { getModules, getModulesCount } from '@/api/modules/project-management/fileManagement';
|
import { getModules, getModulesCount } from '@/api/modules/project-management/fileManagement';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
import useFormCreateStore from '@/store/modules/form-create/form-create';
|
|
||||||
import { scrollIntoView } from '@/utils/dom';
|
import { scrollIntoView } from '@/utils/dom';
|
||||||
|
|
||||||
import { BugEditCustomField, BugEditCustomFieldItem, BugEditFormObject } from '@/models/bug-management';
|
import { BugEditCustomField, BugEditCustomFieldItem, BugEditFormObject } from '@/models/bug-management';
|
||||||
|
@ -175,7 +175,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const formCreateStore = useFormCreateStore();
|
// const formCreateStore = useFormCreateStore();
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const templateOption = ref<TemplateOption[]>([]);
|
const templateOption = ref<TemplateOption[]>([]);
|
||||||
|
@ -191,6 +191,8 @@
|
||||||
|
|
||||||
const fileList = ref<FileItem[]>([]);
|
const fileList = ref<FileItem[]>([]);
|
||||||
const formRules = ref<FormItem[]>([]);
|
const formRules = ref<FormItem[]>([]);
|
||||||
|
const formItem = ref<FormRuleItem[]>([]);
|
||||||
|
const fApi = ref({});
|
||||||
const associatedDrawer = ref(false);
|
const associatedDrawer = ref(false);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const acceptType = ref('none'); // 模块-上传文件类型
|
const acceptType = ref('none'); // 模块-上传文件类型
|
||||||
|
@ -324,9 +326,8 @@
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const customFields: BugEditCustomFieldItem[] = [];
|
const customFields: BugEditCustomFieldItem[] = [];
|
||||||
const formRuleList = formCreateStore.formCreateRuleMap.get(FormCreateKeyEnum.BUG_DETAIL);
|
if (formItem.value && formItem.value.length) {
|
||||||
if (formRuleList && formRuleList.length) {
|
formItem.value.forEach((item: FormRuleItem) => {
|
||||||
formRuleList.forEach((item) => {
|
|
||||||
customFields.push({
|
customFields.push({
|
||||||
id: item.field as string,
|
id: item.field as string,
|
||||||
name: item.title as string,
|
name: item.title as string,
|
||||||
|
|
|
@ -178,7 +178,7 @@
|
||||||
<inputComment :content="content" is-show-avatar is-use-bottom @publish="publishHandler" />
|
<inputComment :content="content" is-show-avatar is-use-bottom @publish="publishHandler" />
|
||||||
</template>
|
</template>
|
||||||
</MsDetailDrawer>
|
</MsDetailDrawer>
|
||||||
<SettingDrawer v-model:visible="showSettingDrawer" />
|
<SettingDrawer ref="settingDrawerRef" v-model:visible="showSettingDrawer" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -268,6 +268,7 @@
|
||||||
activeTab.value = key;
|
activeTab.value = key;
|
||||||
switch (activeTab.value) {
|
switch (activeTab.value) {
|
||||||
case 'setting':
|
case 'setting':
|
||||||
|
activeTab.value = 'detail';
|
||||||
showMenuSetting();
|
showMenuSetting();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -449,11 +450,14 @@
|
||||||
},
|
},
|
||||||
{ deep: true }
|
{ deep: true }
|
||||||
);
|
);
|
||||||
|
const settingDrawerRef = ref();
|
||||||
watch(
|
watch(
|
||||||
() => props.visible,
|
() => props.visible,
|
||||||
(val) => {
|
(val) => {
|
||||||
showDrawerVisible.value = val;
|
showDrawerVisible.value = val;
|
||||||
|
if (val) {
|
||||||
|
settingDrawerRef.value.getTabModule();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -500,7 +504,6 @@
|
||||||
background: none !important;
|
background: none !important;
|
||||||
.arco-menu-inner {
|
.arco-menu-inner {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 14px 2px;
|
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,9 @@
|
||||||
|
|
||||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
|
|
||||||
|
import { postTabletList } from '@/api/modules/project-management/menuManagement';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import { useAppStore } from '@/store';
|
||||||
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
||||||
|
|
||||||
import type { TabItemType } from '@/models/caseManagement/featureCase';
|
import type { TabItemType } from '@/models/caseManagement/featureCase';
|
||||||
|
@ -58,6 +60,9 @@
|
||||||
|
|
||||||
const featureCaseStore = useFeatureCaseStore();
|
const featureCaseStore = useFeatureCaseStore();
|
||||||
|
|
||||||
|
const appStore = useAppStore();
|
||||||
|
|
||||||
|
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
@ -69,22 +74,36 @@
|
||||||
const showSettingVisible = ref<boolean>(false);
|
const showSettingVisible = ref<boolean>(false);
|
||||||
const detailEnable = ref<boolean>(true);
|
const detailEnable = ref<boolean>(true);
|
||||||
|
|
||||||
|
const moduleTab = ref<Record<string, TabItemType[]>>({
|
||||||
|
bugManagement: [
|
||||||
|
{
|
||||||
|
key: 'requirement',
|
||||||
|
title: 'caseManagement.featureCase.requirement',
|
||||||
|
enable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'bug',
|
||||||
|
title: 'caseManagement.featureCase.bug',
|
||||||
|
enable: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
testPlan: [
|
||||||
|
{
|
||||||
|
key: 'testPlan',
|
||||||
|
title: 'caseManagement.featureCase.testPlan',
|
||||||
|
enable: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const buggerTab: TabItemType[] = [];
|
||||||
|
const testPlanTab: TabItemType[] = [];
|
||||||
const tabDefaultSettingList = ref<TabItemType[]>([
|
const tabDefaultSettingList = ref<TabItemType[]>([
|
||||||
{
|
{
|
||||||
key: 'case',
|
key: 'case',
|
||||||
title: 'caseManagement.featureCase.case',
|
title: 'caseManagement.featureCase.case',
|
||||||
enable: true,
|
enable: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
key: 'requirement',
|
|
||||||
title: 'caseManagement.featureCase.requirement',
|
|
||||||
enable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'bug',
|
|
||||||
title: 'caseManagement.featureCase.bug',
|
|
||||||
enable: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: 'dependency',
|
key: 'dependency',
|
||||||
title: 'caseManagement.featureCase.dependency',
|
title: 'caseManagement.featureCase.dependency',
|
||||||
|
@ -95,11 +114,6 @@
|
||||||
title: 'caseManagement.featureCase.caseReview',
|
title: 'caseManagement.featureCase.caseReview',
|
||||||
enable: true,
|
enable: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
key: 'testPlan',
|
|
||||||
title: 'caseManagement.featureCase.testPlan',
|
|
||||||
enable: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
key: 'comments',
|
key: 'comments',
|
||||||
title: 'caseManagement.featureCase.comments',
|
title: 'caseManagement.featureCase.comments',
|
||||||
|
@ -111,10 +125,22 @@
|
||||||
enable: true,
|
enable: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
async function getTabModule() {
|
||||||
|
const result = await postTabletList({ projectId: currentProjectId.value });
|
||||||
|
const enableModuleArr = result.filter((item: any) => item.module === 'testPlan' || item.module === 'bugManagement');
|
||||||
|
enableModuleArr.forEach((item) => {
|
||||||
|
if (item.module === 'bugManagement') {
|
||||||
|
buggerTab.push(...moduleTab.value[item.module]);
|
||||||
|
} else if (item.module === 'testPlan') {
|
||||||
|
testPlanTab.push(...moduleTab.value[item.module]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tabDefaultSettingList.value.splice(1, 0, buggerTab[0], buggerTab[1]);
|
||||||
|
tabDefaultSettingList.value.splice(-2, 0, testPlanTab[0]);
|
||||||
|
featureCaseStore.setTab(tabDefaultSettingList.value);
|
||||||
|
}
|
||||||
|
|
||||||
const tabList = computed(() => {
|
const tabList = computed(() => featureCaseStore.tabSettingList);
|
||||||
return featureCaseStore.tabSettingList;
|
|
||||||
});
|
|
||||||
|
|
||||||
const tabSettingList = ref([...tabList.value]);
|
const tabSettingList = ref([...tabList.value]);
|
||||||
|
|
||||||
|
@ -151,10 +177,8 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
onMounted(() => {
|
defineExpose({
|
||||||
if (tabList.value.length < 1) {
|
getTabModule,
|
||||||
featureCaseStore.setTab(tabDefaultSettingList.value);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue