Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev

This commit is contained in:
easy 2023-03-16 11:19:55 +08:00
commit db3c66d3b7
24 changed files with 1151 additions and 1388 deletions

View File

@ -13,8 +13,10 @@ export default {
del: (id: string) => server.remove(`/media/device/${id}`), del: (id: string) => server.remove(`/media/device/${id}`),
// 更新通道 // 更新通道
updateChannels: (id: string) => server.post(`/media/device/${id}/channels/_sync`), updateChannels: (id: string) => server.post(`/media/device/${id}/channels/_sync`),
// 查询产品列表 // post查询产品列表
queryProductList: (data: any) => server.post<ProductType[]>(`/device/product/_query/no-paging`, data), queryProductList: (data: any) => server.post<ProductType[]>(`/device/product/_query/no-paging`, data),
// get获取产品
getProductList: (data: any) => server.get(`/device/product/_query/no-paging?paging=false`, data),
// 快速添加产品 // 快速添加产品
saveProduct: (data: any) => server.post<any>(`/device/product`, data), saveProduct: (data: any) => server.post<any>(`/device/product`, data),
// 产品发布 // 产品发布

View File

@ -4,6 +4,7 @@
:type='type' :type='type'
:request='saveSearchHistory' :request='saveSearchHistory'
:historyRequest='getSearchHistory' :historyRequest='getSearchHistory'
:deleteRequest='deleteSearchHistory'
:columns='columns' :columns='columns'
:class='props.class' :class='props.class'
@search='searchSubmit' @search='searchSubmit'
@ -13,7 +14,7 @@
<script setup lang='ts' name='ProSearch'> <script setup lang='ts' name='ProSearch'>
import { PropType } from 'vue' import { PropType } from 'vue'
import { JColumnsProps } from 'components/Table/types' import { JColumnsProps } from 'components/Table/types'
import { saveSearchHistory, getSearchHistory } from '@/api/comm' import { saveSearchHistory, getSearchHistory, deleteSearchHistory } from '@/api/comm'
interface Emit { interface Emit {
(e: 'search', data: any): void (e: 'search', data: any): void

View File

@ -86,8 +86,8 @@
@cancel="modalVis = false" @cancel="modalVis = false"
@ok="handleItemModalSubmit" @ok="handleItemModalSubmit"
> >
<div style="width: 100%; height: 400px"> <div style="width: 100%; height: 300px">
<MonacoEditor v-model:modelValue="objectValue" /> <JMonacoEditor v-model:modelValue="objectValue" />
</div> </div>
</j-modal> </j-modal>
</div> </div>
@ -97,7 +97,6 @@
import { PropType } from 'vue'; import { PropType } from 'vue';
import { UploadChangeParam, UploadFile } from 'ant-design-vue'; import { UploadChangeParam, UploadFile } from 'ant-design-vue';
import { DefaultOptionType } from 'ant-design-vue/lib/select'; import { DefaultOptionType } from 'ant-design-vue/lib/select';
import MonacoEditor from '@/components/MonacoEditor/index.vue';
import GeoComponent from '@/components/GeoComponent/index.vue'; import GeoComponent from '@/components/GeoComponent/index.vue';
import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable'; import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable';
import { LocalStore } from '@/utils/comm'; import { LocalStore } from '@/utils/comm';
@ -196,7 +195,7 @@ const timeChange = (e: any) => {
} }
const inputChange = (e: any) => { const inputChange = (e: any) => {
emit('change', e.target.value) emit('change', e.target ? e.target.value : e)
} }
const dateChange = (e: any) => { const dateChange = (e: any) => {

View File

@ -1,14 +1,14 @@
<template> <template>
<a-select allowClear v-model:value="_value" @change="onChange" placeholder="请选择" style="width: 100%"> <j-select allowClear v-model:value="_value" @change="onChange" placeholder="请选择" style="width: 100%">
<a-select-option <j-select-option
v-for="item in list" v-for="item in list"
:key="item.id" :key="item.id"
:value="item.id" :value="item.id"
:label="item.name" :label="item.name"
:filter-option="filterOption" :filter-option="filterOption"
>{{ item.name }}</a-select-option >{{ item.name }}</j-select-option
> >
</a-select> </j-select>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -1,5 +1,5 @@
<template> <template>
<a-modal <j-modal
width="900px" width="900px"
title="批量映射" title="批量映射"
visible visible
@ -10,49 +10,49 @@
<div class="map-tree-top"> <div class="map-tree-top">
采集器的点位名称与属性名称一致时将自动映射绑定有多个采集器点位名称与属性名称一致时以第1个采集器的点位数据进行绑定 采集器的点位名称与属性名称一致时将自动映射绑定有多个采集器点位名称与属性名称一致时以第1个采集器的点位数据进行绑定
</div> </div>
<a-spin :spinning="loading"> <j-spin :spinning="loading">
<div class="map-tree-content"> <div class="map-tree-content">
<a-card class="map-tree-content-card" title="源数据"> <j-card class="map-tree-content-card" title="源数据">
<a-tree <j-tree
checkable checkable
:height="300" :height="300"
:tree-data="dataSource" :tree-data="dataSource"
:checkedKeys="checkedKeys" :checkedKeys="checkedKeys"
@check="onCheck" @check="onCheck"
/> />
</a-card> </j-card>
<div style="width: 100px"> <div style="width: 100px">
<a-button <j-button
:disabled="rightList.length >= leftList.length" :disabled="rightList.length >= leftList.length"
@click="onRight" @click="onRight"
>加入右侧</a-button >加入右侧</j-button
> >
</div> </div>
<a-card class="map-tree-content-card" title="采集器"> <j-card class="map-tree-content-card" title="采集器">
<a-list <j-list
size="small" size="small"
:data-source="rightList" :data-source="rightList"
class="map-tree-content-card-list" class="map-tree-content-card-list"
> >
<template #renderItem="{ item }"> <template #renderItem="{ item }">
<a-list-item> <j-list-item>
{{ item.title }} {{ item.title }}
<template #actions> <template #actions>
<a-popconfirm <j-popconfirm
title="确定删除?" title="确定删除?"
@confirm="_delete(item.key)" @confirm="_delete(item.key)"
> >
<AIcon type="DeleteOutlined" /> <AIcon type="DeleteOutlined" />
</a-popconfirm> </j-popconfirm>
</template> </template>
</a-list-item> </j-list-item>
</template> </template>
</a-list> </j-list>
</a-card> </j-card>
</div> </div>
</a-spin> </j-spin>
</div> </div>
</a-modal> </j-modal>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -1,46 +1,46 @@
<template> <template>
<a-spin :spinning="loading" v-if="metadata.properties.length"> <j-spin :spinning="loading" v-if="metadata.properties.length">
<a-card> <j-card>
<template #extra> <template #extra>
<a-space> <j-space>
<a-button @click="visible = true">批量映射</a-button> <j-button @click="visible = true">批量映射</j-button>
<a-button type="primary" @click="onSave">保存</a-button> <j-button type="primary" @click="onSave">保存</j-button>
</a-space> </j-space>
</template> </template>
<a-form ref="formRef" :model="modelRef"> <j-form ref="formRef" :model="modelRef">
<a-table :dataSource="modelRef.dataSource" :columns="columns"> <j-table :dataSource="modelRef.dataSource" :columns="columns">
<template #headerCell="{ column }"> <template #headerCell="{ column }">
<template v-if="column.key === 'collectorId'"> <template v-if="column.key === 'collectorId'">
采集器 采集器
<a-tooltip title="边缘网关代理的真实物理设备"> <j-tooltip title="边缘网关代理的真实物理设备">
<AIcon type="QuestionCircleOutlined" /> <AIcon type="QuestionCircleOutlined" />
</a-tooltip> </j-tooltip>
</template> </template>
</template> </template>
<template #bodyCell="{ column, record, index }"> <template #bodyCell="{ column, record, index }">
<template v-if="column.dataIndex === 'channelId'"> <template v-if="column.dataIndex === 'channelId'">
<a-form-item <j-form-item
:name="['dataSource', index, 'channelId']" :name="['dataSource', index, 'channelId']"
> >
<a-select <j-select
style="width: 100%" style="width: 100%"
v-model:value="record[column.dataIndex]" v-model:value="record[column.dataIndex]"
placeholder="请选择" placeholder="请选择"
allowClear allowClear
:filter-option="filterOption" :filter-option="filterOption"
> >
<a-select-option <j-select-option
v-for="item in channelList" v-for="item in channelList"
:key="item.value" :key="item.value"
:value="item.value" :value="item.value"
:label="item.label" :label="item.label"
>{{ item.label }}</a-select-option >{{ item.label }}</j-select-option
> >
</a-select> </j-select>
</a-form-item> </j-form-item>
</template> </template>
<template v-if="column.dataIndex === 'collectorId'"> <template v-if="column.dataIndex === 'collectorId'">
<a-form-item <j-form-item
:name="['dataSource', index, 'collectorId']" :name="['dataSource', index, 'collectorId']"
:rules="[ :rules="[
{ {
@ -55,10 +55,10 @@
type="COLLECTOR" type="COLLECTOR"
:edgeId="instanceStore.current.parentId" :edgeId="instanceStore.current.parentId"
/> />
</a-form-item> </j-form-item>
</template> </template>
<template v-if="column.dataIndex === 'pointId'"> <template v-if="column.dataIndex === 'pointId'">
<a-form-item <j-form-item
:name="['dataSource', index, 'pointId']" :name="['dataSource', index, 'pointId']"
:rules="[ :rules="[
{ {
@ -73,33 +73,33 @@
type="POINT" type="POINT"
:edgeId="instanceStore.current.parentId" :edgeId="instanceStore.current.parentId"
/> />
</a-form-item> </j-form-item>
</template> </template>
<template v-if="column.dataIndex === 'id'"> <template v-if="column.dataIndex === 'id'">
<a-badge <j-badge
v-if="record[column.dataIndex]" v-if="record[column.dataIndex]"
status="success" status="success"
text="已绑定" text="已绑定"
/> />
<a-badge v-else status="error" text="未绑定" /> <j-badge v-else status="error" text="未绑定" />
</template> </template>
<template v-if="column.key === 'action'"> <template v-if="column.key === 'action'">
<a-tooltip title="解绑"> <j-tooltip title="解绑">
<a-popconfirm <j-popconfirm
title="确认解绑" title="确认解绑"
:disabled="!record.id" :disabled="!record.id"
@confirm="unbind(record.id)" @confirm="unbind(record.id)"
> >
<a-button type="link" :disabled="!record.id" <j-button type="link" :disabled="!record.id"
><AIcon type="icon-jiebang" ><AIcon type="icon-jiebang"
/></a-button> /></j-button>
</a-popconfirm> </j-popconfirm>
</a-tooltip> </j-tooltip>
</template> </template>
</template> </template>
</a-table> </j-table>
</a-form> </j-form>
</a-card> </j-card>
<PatchMapping <PatchMapping
:deviceId="instanceStore.current.id" :deviceId="instanceStore.current.id"
v-if="visible" v-if="visible"
@ -108,10 +108,10 @@
:metaData="modelRef.dataSource" :metaData="modelRef.dataSource"
:edgeId="instanceStore.current.parentId" :edgeId="instanceStore.current.parentId"
/> />
</a-spin> </j-spin>
<a-card v-else> <j-card v-else>
<JEmpty description='暂无数据,请配置物模型' style="margin: 10% 0" /> <JEmpty description='暂无数据,请配置物模型' style="margin: 10% 0" />
</a-card> </j-card>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -8,7 +8,7 @@
> >
<j-row :gutter="30"> <j-row :gutter="30">
<j-col :span="15"> <j-col :span="15">
<MonacoEditor <JMonacoEditor
:ref="`monacoEditor${func.id}`" :ref="`monacoEditor${func.id}`"
v-model="func.json" v-model="func.json"
theme="vs-dark" theme="vs-dark"

View File

@ -25,7 +25,7 @@
</div> </div>
<div> <div>
脚本语言: 脚本语言:
<j-select :defaultValue="'JavaScript'" style="width: 200;margin-left: 5px;"> <j-select :defaultValue="'JavaScript'" style="width: 200px;margin-left: 5px;">
<j-select-option value="JavaScript">JavaScript(ECMAScript 5)</j-select-option> <j-select-option value="JavaScript">JavaScript(ECMAScript 5)</j-select-option>
</j-select> </j-select>
<AIcon type="ExpandOutlined" style="margin-left: 20px;" @click="toggle" /> <AIcon type="ExpandOutlined" style="margin-left: 20px;" @click="toggle" />
@ -52,8 +52,7 @@
<template v-if="instanceStore.current.transport === 'MQTT'"> <template v-if="instanceStore.current.transport === 'MQTT'">
<div style="margin-right: 5px;">Topic:</div> <div style="margin-right: 5px;">Topic:</div>
<j-auto-complete placeholder="请输入Topic" style="width: 300px" :options="topicList" <j-auto-complete placeholder="请输入Topic" style="width: 300px" :options="topicList"
:allowClear="true" :filterOption="(inputValue: any, option: any) => :allowClear="true" :filterOption="filterOption" v-model:value="topic" />
option!.value.indexOf(inputValue) !== -1" v-model:value="topic" />
</template> </template>
<template v-else> <template v-else>
<div style="margin-right: 5px;">URL:</div> <div style="margin-right: 5px;">URL:</div>
@ -134,6 +133,7 @@ const resStyle = computed(() => (isBoolean(resultValue.value.success) ? {
} : { } : {
'margin-top': '10px', 'margin-top': '10px',
})) }))
const filterOption = (inputValue: any, option: any) => option!.value.indexOf(inputValue) !== -1
const isDisabled = computed(() => simulation.value === '') const isDisabled = computed(() => simulation.value === '')

View File

@ -20,9 +20,8 @@
</div> </div>
<div class="right"> <div class="right">
<pro-search <pro-search
type="simple"
:columns="columns" :columns="columns"
target="product" target="channel"
@search="handleSearch" @search="handleSearch"
/> />

View File

@ -125,6 +125,7 @@ import { message } from 'ant-design-vue';
import { getImage } from '@/utils/comm'; import { getImage } from '@/utils/comm';
import { PROVIDER_OPTIONS } from '@/views/media/Device/const'; import { PROVIDER_OPTIONS } from '@/views/media/Device/const';
import { providerType } from './const'; import { providerType } from './const';
import encodeQuery from '@/utils/encodeQuery';
import { useMenuStore } from 'store/menu'; import { useMenuStore } from 'store/menu';
@ -153,14 +154,14 @@ const columns = [
}, },
{ {
title: '接入方式', title: '接入方式',
dataIndex: 'type', dataIndex: 'provider',
key: 'type', key: 'provider',
scopedSlots: true, scopedSlots: true,
search: { search: {
type: 'select', type: 'select',
options: PROVIDER_OPTIONS, options: PROVIDER_OPTIONS,
handleValue: (v: any) => { handleValue: (v: any) => {
return '123'; return v;
}, },
}, },
}, },
@ -184,12 +185,28 @@ const columns = [
scopedSlots: true, scopedSlots: true,
search: { search: {
type: 'select', type: 'select',
options: [ options: () =>
{ label: '固定地址', value: 'fixed-media' }, new Promise((resolve) => {
{ label: 'GB/T28181', value: 'gb28181-2016' }, DeviceApi.getProductList(
encodeQuery({
terms: {
messageProtocol$in: [
'gb28181-2016',
'fixed-media',
], ],
},
}),
).then((resp: any) => {
resolve(
resp.result.map((pItem: any) => ({
label: pItem.name,
value: pItem.id,
})),
);
});
}),
handleValue: (v: any) => { handleValue: (v: any) => {
return '123'; return v;
}, },
}, },
}, },
@ -206,7 +223,7 @@ const columns = [
{ label: '在线', value: 'online' }, { label: '在线', value: 'online' },
], ],
handleValue: (v: any) => { handleValue: (v: any) => {
return '123'; return v;
}, },
}, },
}, },

View File

@ -7,41 +7,31 @@
:pagination="false" :pagination="false"
> >
<template #bodyCell="{ column, text, record }"> <template #bodyCell="{ column, text, record }">
<div> <template v-if="column.dataIndex === 'name'">
<template
v-if="['valueType', 'name'].includes(column.dataIndex)"
>
<span>{{ text }}</span> <span>{{ text }}</span>
</template> </template>
<template v-else-if="column.dataIndex === 'valueType'">
<span>{{ record.valueType.type }}</span>
</template>
<template v-else> <template v-else>
<ParamsDropdown <FunctionItem
placeholder="请选择" :builtInList="builtInList"
:options="[]" @change="onChange"
:tabsOptions="tabOptions" :source="record.source"
:metricOption="upperOptions(record.valueType)" :data="record"
v-model:value="record.value" v-model:value="record.value"
> />
<template v-slot="{label}">
<j-input :value="label" />
</template> </template>
</ParamsDropdown>
</template>
</div>
</template> </template>
</j-table> </j-table>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { PropType } from 'vue'; import { PropType } from 'vue';
import ParamsDropdown from '../../../components/ParamsDropdown'; import FunctionItem from './FunctionItem.vue';
type Emits = {
(e: 'update:modelValue', data: Record<string, any>[]): void;
};
const _emit = defineEmits<Emits>();
const _props = defineProps({ const _props = defineProps({
modelValue: { value: {
type: Array as PropType<Record<string, any>[]>, type: Array as PropType<Record<string, any>[]>,
default: () => undefined, default: () => undefined,
}, },
@ -49,20 +39,13 @@ const _props = defineProps({
type: Array, type: Array,
default: () => [], default: () => [],
}, },
functions: {
type: Array,
default: () => [],
},
}); });
const tabOptions = [ const emit = defineEmits(['update:value']);
{
label: '手动输入',
component: 'string',
key: 'fixed',
},
{
label: '内置参数',
component: 'tree',
key: 'upper',
},
];
const columns = [ const columns = [
{ {
@ -82,33 +65,29 @@ const columns = [
}, },
]; ];
const dataSource = computed({ const dataSource = ref<any[]>([]);
get: () => {
return _props.modelValue || [];
},
set: (val: any) => {
_emit('update:modelValue', val);
},
});
const filterParamsData = (type?: string, data?: any[]): any[] => { watchEffect(() => {
if (type && data) { const list = (_props.functions || []).map((item: any) => {
return data.filter((item) => { const _item = _props.value?.find((i) => i.name === item?.id) || {};
if (item.children) { return {
const _children = filterParamsData(type, item.children); ...item,
item.children = _children; ..._item,
return _children.length ? true : false; name: item.name,
} else if (item.type === type) {
// optionMap.current.set(item.id, item);
return true;
}
return false;
});
}
return data || [];
}; };
});
dataSource.value = list;
});
const upperOptions = (_type: string) => { const onChange = () => {
return filterParamsData(_type, _props?.builtInList) || []; const arr = [...dataSource.value].map((item) => {
return {
name: item.id,
source: item.source,
upperKey: item.upperKey || item.value,
value: item.value,
};
});
emit('update:value', arr);
}; };
</script> </script>

View File

@ -0,0 +1,117 @@
<template>
<ParamsDropdown
placeholder="请选择"
:options="handleOptions"
:tabsOptions="tabOptions"
:metricOptions="upperOptions"
v-model:value="_value"
v-model:source="_source"
@select="onChange"
>
<template v-slot="{ label }">
<j-input :value="label" />
</template>
</ParamsDropdown>
</template>
<script lang="ts" setup>
import ParamsDropdown from '../../../components/ParamsDropdown';
import { handleParamsData } from './index';
const props = defineProps({
data: {
type: Object,
default: () => {},
},
builtInList: {
type: Array,
default: () => [],
},
value: {
type: String,
},
source: {
type: String,
default: 'fixed',
},
});
const emit = defineEmits(['update:value', 'update:source', 'change']);
const _value = ref();
const _source = ref();
const tabOptions = computed(() => {
return [
{
label: '手动输入',
component: props.data?.valueType?.type,
key: 'fixed',
},
{
label: '内置参数',
component: 'tree',
key: 'upper',
},
];
});
const handleOptions = computed(() => {
const _item = props.data?.valueType || 'int';
const _type = _item?.type;
if (_type === 'boolean') {
return [
{
label: _item.trueText || true,
value: _item.trueValue || true,
},
{
label: _item.falseText || false,
value: _item.falseValue || false,
},
];
}
if (_type === 'enum') {
return _item?.elements.map((i: any) => {
return {
label: i.text,
value: i.value,
};
});
}
return [];
});
const filterParamsData = (type?: string, data?: any[]): any[] => {
if (type && data) {
const list = data.filter((item) => {
if (item.children) {
const _children = filterParamsData(type, item.children);
item.children = _children;
return _children.length ? true : false;
} else if (item.type === type) {
// optionMap.current.set(item.id, item);
return true;
}
return false;
});
return handleParamsData(list);
}
return data || [];
};
const upperOptions = computed(() => {
return filterParamsData(props.data.valueType?.type, props?.builtInList);
});
const onChange = () => {
emit('update:value', _value.value);
emit('update:source', _source.value);
emit('change', { source: _source.value, value: _value.value });
};
watchEffect(() => {
_value.value = props.value;
_source.value = props.source || 'fixed';
});
</script>

View File

@ -1,17 +1,21 @@
<template> <template>
<div> <j-form
<j-form :layout="'vertical'" ref="formRef" :model="modelRef"> :layout="'vertical'"
<j-row> ref="propertyFormRef"
<j-col :span="11"> :model="propertyModelRef"
>
<j-row :gutter="24">
<j-col :span="12">
<j-form-item <j-form-item
:name="['message', 'properties']" name="properties"
label="读取属性" label="读取属性"
:rules="[{ required: true, message: '请选择读取属性' }]" :rules="[{ required: true, message: '请选择读取属性' }]"
> >
<j-select <j-select
showSearch showSearch
placeholder="请选择属性" placeholder="请选择属性"
v-model:value="modelRef.properties" v-model:value="propertyModelRef.properties"
@change="onChange"
> >
<j-select-option <j-select-option
v-for="item in metadata?.properties || []" v-for="item in metadata?.properties || []"
@ -22,29 +26,34 @@
</j-select> </j-select>
</j-form-item> </j-form-item>
</j-col> </j-col>
<j-col :span="2"></j-col> <j-col :span="12" v-if="propertyModelRef.properties">
<j-col :span="11">
<j-form-item <j-form-item
:name="['message', 'propertiesValue']" name="propertiesValue"
label="属性值" label="属性值"
:rules="[{ required: true, message: '请选择' }]" :rules="[{ required: true, message: '请选择' }]"
> >
<ParamsDropdown <ParamsDropdown
icon="icon-canshu"
placeholder="请选择" placeholder="请选择"
:options="[]" :options="handleOptions"
:tabsOptions="tabOptions" :tabsOptions="tabOptions"
:metricOption="upperOptions(getType)" :metricOption="upperOptions"
v-model:value="modelRef.propertiesValue" v-model:value="propertyModelRef.propertiesValue"
/> v-model:source="propertyModelRef.source"
@change="onValueChange"
>
<template v-slot="{ label }">
<j-input :value="label" />
</template>
</ParamsDropdown>
</j-form-item> </j-form-item>
</j-col> </j-col>
</j-row> </j-row>
</j-form> </j-form>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import ParamsDropdown from '../../../components/ParamsDropdown';
import { handleParamsData } from './index';
const props = defineProps({ const props = defineProps({
value: { value: {
type: Object, type: Object,
@ -60,22 +69,31 @@ const props = defineProps({
}, },
builtInList: { builtInList: {
type: Array, type: Array,
default: () => [] default: () => [],
}, },
}); });
const formRef = ref(); const emit = defineEmits(['update:value']);
const modelRef = reactive({ const propertyFormRef = ref();
properties: '',
propertiesValue: '', const propertyModelRef = reactive({
source: '', properties: undefined,
propertiesValue: undefined,
source: 'fixed',
}); });
const tabOptions = [ const getType = computed(() => {
return props.metadata.properties.find(
(item: any) => item.id === propertyModelRef.properties,
);
});
const tabOptions = computed(() => {
return [
{ {
label: '手动输入', label: '手动输入',
component: 'string', component: getType.value?.valueType?.type,
key: 'fixed', key: 'fixed',
}, },
{ {
@ -84,13 +102,11 @@ const tabOptions = [
key: 'upper', key: 'upper',
}, },
]; ];
const getType = computed(() => { });
return props.metadata.properties.find((item: any) => item.id === modelRef.properties)?.valueType?.type
})
const filterParamsData = (type?: string, data?: any[]): any[] => { const filterParamsData = (type?: string, data?: any[]): any[] => {
if (type && data) { if (type && data) {
return data.filter((item) => { const list = data.filter((item) => {
if (item.children) { if (item.children) {
const _children = filterParamsData(type, item.children); const _children = filterParamsData(type, item.children);
item.children = _children; item.children = _children;
@ -101,40 +117,74 @@ const filterParamsData = (type?: string, data?: any[]): any[] => {
} }
return false; return false;
}); });
return handleParamsData(list);
} }
return data || []; return data || [];
}; };
const upperOptions = (type: string) => { const upperOptions = computed(() => {
return filterParamsData(type, props?.builtInList) || [] return filterParamsData(getType.value?.valueType?.type, props?.builtInList);
});
const handleOptions = computed(() => {
const _item = getType.value?.valueType;
const _type = _item?.type;
if (_type === 'boolean') {
return [
{
label: _item.trueText,
value: _item.trueValue,
},
{
label: _item.falseText,
value: _item.falseValue,
},
];
} }
if (_type === 'enum') {
return _item?.elements.map((i: any) => {
return {
label: i.text,
value: i.value,
};
});
}
return [];
});
const onChange = () => {
propertyModelRef.propertiesValue = undefined;
propertyModelRef.source = 'fixed'
emit('update:value', {
[`${propertyModelRef.properties}`]: {
value: propertyModelRef?.propertiesValue,
source: propertyModelRef?.source,
},
});
};
const onValueChange = () => {
const obj = {
[`${propertyModelRef.properties}`]: {
value: propertyModelRef?.propertiesValue,
source: propertyModelRef?.source,
},
}
emit('update:value', obj);
};
watch( watch(
() => props.value, () => props.value,
(newVal) => { (newVal) => {
if (newVal) {
const _keys = Object.keys(newVal)?.[0]; const _keys = Object.keys(newVal)?.[0];
if (_keys) { if (_keys) {
(modelRef.properties = _keys), propertyModelRef.properties = _keys as any;
(modelRef.propertiesValue = newVal[_keys]?.value); propertyModelRef.propertiesValue = newVal[_keys]?.value;
modelRef.source = newVal[_keys]?.source; propertyModelRef.source = newVal[_keys]?.source;
}
} }
}, },
{ deep: true, immediate: true }, { deep: true, immediate: true },
); );
const onFormSave = () => {
return new Promise((resolve, reject) => {
formRef.value
.validate()
.then(async (_data: any) => {
//
resolve(_data);
})
.catch((err: any) => {
reject(err);
});
});
};
defineExpose({ onFormSave });
</script> </script>

View File

@ -0,0 +1,10 @@
export const handleParamsData = (data: any[]): any[] => {
return data?.map(item => {
return {
...item,
key: item.column,
disabled: !!item.children?.length,
children: handleParamsData(item.children)
}
}) || []
}

View File

@ -22,7 +22,6 @@
showSearch showSearch
placeholder="请选择功能" placeholder="请选择功能"
v-model:value="modelRef.message.functionId" v-model:value="modelRef.message.functionId"
@change="(val) => onFunctionChange(val, [])"
> >
<j-select-option <j-select-option
v-for="item in metadata?.functions || []" v-for="item in metadata?.functions || []"
@ -37,7 +36,11 @@
:name="['message', 'inputs']" :name="['message', 'inputs']"
:rules="[{ required: true, message: '请输入功能值' }]" :rules="[{ required: true, message: '请输入功能值' }]"
> >
<EditTable v-model:modelValue="modelRef.message.inputs" :builtInList="builtInList" /> <EditTable
:functions="functions"
v-model:value="modelRef.message.inputs"
:builtInList="builtInList"
/>
</j-form-item> </j-form-item>
</template> </template>
<template v-else-if="deviceMessageType === 'READ_PROPERTY'"> <template v-else-if="deviceMessageType === 'READ_PROPERTY'">
@ -79,7 +82,7 @@ import EditTable from './EditTable.vue';
import WriteProperty from './WriteProperty.vue'; import WriteProperty from './WriteProperty.vue';
import { queryBuiltInParams } from '@/api/rule-engine/scene'; import { queryBuiltInParams } from '@/api/rule-engine/scene';
import { useSceneStore } from '@/store/scene'; import { useSceneStore } from '@/store/scene';
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia';
const sceneStore = useSceneStore(); const sceneStore = useSceneStore();
const { data } = storeToRefs(sceneStore); const { data } = storeToRefs(sceneStore);
@ -149,22 +152,31 @@ const deviceMessageType = computed(() => {
const builtInList = ref<any[]>([]); const builtInList = ref<any[]>([]);
const onFunctionChange = (val: string, values?: any[]) => { const functions = computed(() => {
const _item = (metadata.value?.functions || []).find((item: any) => { const _item = (metadata.value?.functions || []).find((item: any) => {
return val === item.id; return modelRef.message?.functionId === item.id;
}); });
const list = (_item?.inputs || []).map((item: any) => { return _item?.inputs || [];
const _a = values?.find((i) => i.name === item.id); });
return {
id: item.id, const _property = computed(() => {
value: _a?.value, const _item = (metadata.value?.properties || []).find((item: any) => {
valueType: item?.valueType?.type, if (deviceMessageType.value === 'WRITE_PROPERTY') {
..._a, return (
name: item.name, Object.keys(modelRef.message.properties || {})?.[0] === item.id
}; );
}
return modelRef.message?.properties === item.id;
});
return _item;
});
const _function = computed(() => {
const _item = (metadata.value?.functions || []).find((item: any) => {
return modelRef.message?.functionId === item.id;
});
return _item;
}); });
modelRef.message.inputs = list;
};
const onMessageTypeChange = (val: string) => { const onMessageTypeChange = (val: string) => {
if (['WRITE_PROPERTY', 'INVOKE_FUNCTION'].includes(val)) { if (['WRITE_PROPERTY', 'INVOKE_FUNCTION'].includes(val)) {
@ -175,22 +187,18 @@ const onMessageTypeChange = (val: string) => {
}; };
queryBuiltInParams(unref(data), _params).then((res: any) => { queryBuiltInParams(unref(data), _params).then((res: any) => {
if (res.status === 200) { if (res.status === 200) {
builtInList.value = res.result builtInList.value = res.result;
} }
}); });
} }
}; };
watch( watch(
() => [ () => props.values,
props.values?.productDetail, (newVal) => {
props.values.selectorValues, if (newVal?.productDetail?.id) {
props.values?.selector, if (newVal?.selector === 'fixed') {
], const id = newVal?.selectorValues?.[0]?.value;
([newVal1, newVal2, newVal3]) => {
if (newVal1?.id) {
if (newVal3?.selector === 'fixed') {
const id = newVal2?.[0]?.value;
if (id) { if (id) {
detail(id).then((resp) => { detail(id).then((resp) => {
if (resp.status === 200) { if (resp.status === 200) {
@ -201,7 +209,9 @@ watch(
}); });
} }
} else { } else {
metadata.value = JSON.parse(newVal1?.metadata || '{}'); metadata.value = JSON.parse(
newVal?.productDetail?.metadata || '{}',
);
} }
} }
}, },
@ -211,24 +221,36 @@ watch(
watch( watch(
() => props.values?.message, () => props.values?.message,
(newVal) => { (newVal) => {
console.log(newVal)
if (newVal?.messageType) { if (newVal?.messageType) {
modelRef.message = newVal; modelRef.message = newVal;
if (newVal.messageType === 'INVOKE_FUNCTION' && newVal.functionId) { if (newVal.messageType === 'READ_PROPERTY') {
onFunctionChange(newVal.functionId, newVal?.inputs); modelRef.message.properties = newVal.properties?.[0];
} }
onMessageTypeChange(newVal.messageType) onMessageTypeChange(newVal.messageType);
} }
}, },
{ deep: true, immediate: true }, { immediate: true },
); );
const onFormSave = () => { const onFormSave = () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
formRef.value formRef.value
.validate() .validate()
.then(async (_data: any) => { .then((_data: any) => {
resolve(_data); //
const _properties = _data.message.properties || modelRef.message.properties
const obj = {
message: {
...modelRef.message,
..._data.message,
properties: _data.message.messageType === 'READ_PROPERTY' ? [_properties] : _properties,
propertiesName:
deviceMessageType.value === 'INVOKE_FUNCTION'
? _function.value?.name
: _property.value?.name,
},
}
resolve(obj);
}) })
.catch((err: any) => { .catch((err: any) => {
reject(err); reject(err);

View File

@ -7,7 +7,7 @@
target="scene-trigger-device-device" target="scene-trigger-device-device"
/> />
<j-divider style="margin: 0" /> <j-divider style="margin: 0" />
<j-pro-table <JProTable
ref="actionRef" ref="actionRef"
model="CARD" model="CARD"
:columns="columns" :columns="columns"
@ -62,7 +62,7 @@
</template> </template>
</CardBox> </CardBox>
</template> </template>
</j-pro-table> </JProTable>
</template> </template>
<script setup lang='ts' name='Product'> <script setup lang='ts' name='Product'>
@ -180,7 +180,6 @@ watchEffect(() => {
<style scoped lang='less'> <style scoped lang='less'>
.search { .search {
margin-bottom: 0; margin-bottom: 0;
padding-right: 0px; padding: 0 0 24px 0;
padding-left: 0px;
} }
</style> </style>

View File

@ -0,0 +1,56 @@
<template>
<j-select
placeholder="请选择关系"
:options="relationList"
show-search
:value="value ? value[0]?.value?.relation : undefined"
@change="onRelationChange"
/>
</template>
<script lang="ts" setup>
import NoticeApi from '@/api/notice/config';
const props = defineProps({
value: {
type: Array,
default: () => [{value: {}}]
},
});
const emit = defineEmits(['update:value', 'change']);
const relationList = ref<any[]>([]);
onMounted(() => {
queryRelationList()
})
const queryRelationList = () => {
NoticeApi.getRelationUsers({
paging: false,
sorts: [{ name: 'createTime', order: 'desc' }],
terms: [{ termType: 'eq', column: 'objectTypeName', value: '设备' }],
}).then((resp) => {
if (resp.status === 200) {
relationList.value = (resp.result as any[]).map((item) => {
return {
label: item.name,
value: item.relation,
};
});
}
});
};
const onRelationChange = (val: any, options: any) => {
const _values = [
{
value: {
objectType: 'user',
relation: val,
},
},
];
emit('update:value', _values);
emit('change', _values, options);
};
</script>

View File

@ -30,13 +30,7 @@
name="selectorValues" name="selectorValues"
:rules="[{ required: true, message: '请选择关系' }]" :rules="[{ required: true, message: '请选择关系' }]"
> >
<j-select <RelationSelect @change="onRelationChange" v-model:value="modelRef.selectorValues" />
placeholder="请选择关系"
v-model:value="modelRef.selectorValues"
:options="relationList"
show-search
@change="onRelationChange"
/>
</j-form-item> </j-form-item>
<j-form-item <j-form-item
v-else-if="modelRef.selector === 'tag'" v-else-if="modelRef.selector === 'tag'"
@ -86,6 +80,7 @@ import { getImage } from '@/utils/comm';
import NoticeApi from '@/api/notice/config'; import NoticeApi from '@/api/notice/config';
import Device from './Device.vue'; import Device from './Device.vue';
import Tag from './Tag.vue'; import Tag from './Tag.vue';
import RelationSelect from './RelationSelect.vue'
const props = defineProps({ const props = defineProps({
values: { values: {
@ -130,7 +125,6 @@ const modelRef = reactive({
const list = ref<any[]>([]); const list = ref<any[]>([]);
const builtInList = ref<any[]>([]); const builtInList = ref<any[]>([]);
const tagList = ref<any[]>([]); const tagList = ref<any[]>([]);
const relationList = ref<any[]>([]);
const TypeList = [ const TypeList = [
{ {
@ -199,27 +193,10 @@ const sourceChangeEvent = async () => {
const array = filterTree(resp.result as any[]); const array = filterTree(resp.result as any[]);
// //
// if (props.formProductId === DeviceModel.productId)// TODO // if (props.formProductId === DeviceModel.productId)// TODO
builtInList.value = array; builtInList.value = [] // array;
} }
}; };
const queryRelationList = () => {
NoticeApi.getRelationUsers({
paging: false,
sorts: [{ name: 'createTime', order: 'desc' }],
terms: [{ termType: 'eq', column: 'objectTypeName', value: '设备' }],
}).then((resp) => {
if (resp.status === 200) {
relationList.value = (resp.result as any[]).map((item) => {
return {
label: item.name,
value: item.relation,
};
});
}
});
};
const filterType = async () => { const filterType = async () => {
const _list = TypeList.filter((item) => item.value === 'fixed'); const _list = TypeList.filter((item) => item.value === 'fixed');
if (unref(data)?.trigger?.type === 'device') { if (unref(data)?.trigger?.type === 'device') {
@ -266,11 +243,8 @@ const filterType = async () => {
} }
}; };
const onSelectorChange = (val: string) => { const onSelectorChange = () => {
modelRef.selectorValues = undefined; modelRef.selectorValues = undefined;
if (val === 'relation') {
queryRelationList();
}
}; };
const onDeviceChange = (_detail: any) => { const onDeviceChange = (_detail: any) => {
@ -306,7 +280,7 @@ const onTagChange = (val: any[], arr: any[]) => {
if (arr) { if (arr) {
tagList.value = arr; tagList.value = arr;
} }
emits('save', unref(modelRef), {}); emits('save', unref(modelRef), {}, {tagList: tagList.value});
}; };
const onVariableChange = (val: any, node: any) => { const onVariableChange = (val: any, node: any) => {

View File

@ -154,23 +154,23 @@ const onSave = (_data: any) => {
productName: DeviceModel.productDetail.name, productName: DeviceModel.productDetail.name,
relationName: DeviceModel.relationName, relationName: DeviceModel.relationName,
triggerName: data.value.options?.trigger?.name || '触发设备', triggerName: data.value.options?.trigger?.name || '触发设备',
taglist: [], tagList: [],
columns: [], columns: [],
otherColumns: [], otherColumns: [],
}; };
_options.name = DeviceModel.deviceDetail?.name; _options.name = DeviceModel.deviceDetail?.name || DeviceModel.selectorValues?.[0]?.name;
const _type = _data.message.messageType; const _type = _data.message.messageType;
if (_type === 'INVOKE_FUNCTION') { if (_type === 'INVOKE_FUNCTION') {
_options.type = '执行'; _options.type = '执行';
_options.properties = DeviceModel.propertiesName; _options.properties = _data.message.propertiesName;
} }
if (_type === 'READ_PROPERTY') { if (_type === 'READ_PROPERTY') {
_options.type = '读取'; _options.type = '读取';
_options.properties = DeviceModel.propertiesName; _options.properties = _data.message.propertiesName;
} }
if (_type === 'WRITE_PROPERTY') { if (_type === 'WRITE_PROPERTY') {
_options.type = '设置'; _options.type = '设置';
_options.properties = DeviceModel.propertiesName; _options.properties = _data.message.propertiesName;
_options.propertiesValue = _options.propertiesValue =
typeof DeviceModel.propertiesValue === 'object' typeof DeviceModel.propertiesValue === 'object'
? JSON.stringify(DeviceModel.propertiesValue) ? JSON.stringify(DeviceModel.propertiesValue)
@ -183,7 +183,7 @@ const onSave = (_data: any) => {
} }
} }
if (_options.selector === 'tag') { if (_options.selector === 'tag') {
_options.taglist = DeviceModel.tagList.map((it) => ({ _options.tagList = DeviceModel.tagList.map((it) => ({
name: it.column || it.name, name: it.column || it.name,
type: it.type ? (it.type === 'and' ? '并且' : '或者') : '', type: it.type ? (it.type === 'and' ? '并且' : '或者') : '',
value: it.value, value: it.value,
@ -205,6 +205,10 @@ const save = async (step?: number) => {
if (deviceRef.value) { if (deviceRef.value) {
await deviceRef.value?.onFormSave(); await deviceRef.value?.onFormSave();
current.value = 2; current.value = 2;
} else {
if(DeviceModel.selector === 'fixed' && DeviceModel.selectorValues?.length){
current.value = 2;
}
} }
} else { } else {
if (actionRef.value) { if (actionRef.value) {
@ -228,8 +232,8 @@ const prev = () => {
const saveClick = () => save(); const saveClick = () => save();
const onDeviceSave = (_data: any, _detail: any) => { const onDeviceSave = (_data: any, _detail: any, obj?: any) => {
Object.assign(DeviceModel, _data); Object.assign(DeviceModel, {..._data, ...obj});
DeviceModel.deviceDetail = _detail; DeviceModel.deviceDetail = _detail;
}; };

View File

@ -19,7 +19,7 @@
:options='columnOptions' :options='columnOptions'
icon='icon-zhihangdongzuoxie-1' icon='icon-zhihangdongzuoxie-1'
type='column' type='column'
value-name='column' value-name='id'
label-name='fullName' label-name='fullName'
placeholder='请选择参数' placeholder='请选择参数'
v-model:value='paramsValue.column' v-model:value='paramsValue.column'
@ -144,7 +144,7 @@ const paramsValue = reactive<TermsType>({
}) })
const showDelete = ref(false) const showDelete = ref(false)
const columnOptions: any = inject(ContextKey) // const columnOptions: any = inject('filter-params') //
const termTypeOptions = ref<Array<{ id: string, name: string}>>([]) // const termTypeOptions = ref<Array<{ id: string, name: string}>>([]) //
const valueOptions = ref<any[]>([]) // const valueOptions = ref<any[]>([]) //
const metricOption = ref<any[]>([]) // const metricOption = ref<any[]>([]) //
@ -183,7 +183,8 @@ const handOptionByColumn = (option: any) => {
} }
watchEffect(() => { watchEffect(() => {
const option = getOption(columnOptions.value, paramsValue.column, 'column') const option = getOption(columnOptions.value, paramsValue.column, 'id')
console.log(option)
handOptionByColumn(option) handOptionByColumn(option)
}) })

View File

@ -1,11 +1,180 @@
<template> <template>
<div class='terms-params filter-group'>
<div class='terms-params-warp'>
<div v-if='!isFirst' class='term-type-warp'>
<DropdownButton
:options='[
{ label: "并且", value: "and" },
{ label: "或者", value: "or" },
]'
type='type'
v-model:value='formModel.branches[branchName].then[thenName].actions[actionName].terms[name].type'
/>
</div>
<div
class='terms-params-content'
@mouseover='mouseover'
@mouseout='mouseout'
>
<j-popconfirm
title='确认删除?'
@confirm='onDelete'
>
<div v-show='showDelete' class='terms-params-delete'>
<AIcon type='CloseOutlined' />
</div>
</j-popconfirm>
<j-form-item
v-for='(item, index) in termsOptions'
:name='["branches", branchName, "then", thenName, "actions", actionName, "terms", name, "terms", index]'
:rules='rules'
>
<FilterItem
v-model:value='formModel.branches[branchName].then[thenName].actions[actionName].terms[name].terms[index]'
:isFirst='index === 0'
:isLast='index === termsOptions.length - 1'
:showDeleteBtn='termsOptions.length !== 1'
:name='index'
:termsName='name'
:actionName='actionName'
:thenName='thenName'
:branchName='branchName'
/>
</j-form-item>
</div>
<div v-if='isLast' class='terms-group-add'>
<div class='terms-content'>
<AIcon type='PlusOutlined' style='font-size: 12px;padding-right: 4px;' />
<span>分组</span>
</div>
</div>
</div>
</div>
</template> </template>
<script setup lang='ts' name='FilterGroup'> <script setup lang='ts' name='FilterGroup'>
export default { import { storeToRefs } from 'pinia';
name: 'FilterGroup' import { useSceneStore } from 'store/scene'
import DropdownButton from '../../components/DropdownButton'
import FilterItem from './FilterCondition.vue'
import { isArray } from 'lodash-es'
import { queryBuiltInParams } from '@/api/rule-engine/scene'
import { provide } from 'vue'
const sceneStore = useSceneStore()
const { data: formModel } = storeToRefs(sceneStore)
const columnOptions = ref<any>([])
provide('filter-params', columnOptions)
const props = defineProps({
isFirst: {
type: Boolean,
default: true
},
isLast: {
type: Boolean,
default: true
},
showDeleteBtn: {
type: Boolean,
default: true
},
name: {
type: Number,
default: 0
},
branchName: {
type: Number,
default: 0
},
thenName: {
type: Number,
default: 0
},
actionName: {
type: Number,
default: 0
} }
})
const termsOptions = computed(() => {
return formModel.value.branches![props.branchName].then[props.thenName].actions[props.actionName].terms?.[props.name].terms
})
const showDelete = ref(false)
const mouseover = () => {
showDelete.value = true
}
const mouseout = () => {
showDelete.value = false
}
const onDelete = () => {
}
const getParams = () => {
const params = {
branch: props.branchName,
branchGroup: props.thenName,
action: props.actionName
}
const data = formModel.value.branches!.filter(item => !!item)
queryBuiltInParams({
...formModel.value,
branches: data,
}, params).then(res => {
if (res.success) {
columnOptions.value = res.result
}
})
}
const rules = [
{
validator(_: any, v?: Record<string, any>) {
// console.log('-----v',v)
if (v !== undefined) {
if (!Object.keys(v).length) {
return Promise.reject(new Error('该数据已发生变更,请重新配置'));
}
if (!v.column) {
return Promise.reject(new Error('请选择参数'));
}
if (!v.termType) {
return Promise.reject(new Error('请选择操作符'));
}
if (v.value === undefined) {
return Promise.reject(new Error('请选择或输入参数值'));
} else {
if (
isArray(v.value.value) &&
v.value.value.some((_v: any) => _v === undefined)
) {
return Promise.reject(new Error('请选择或输入参数值'));
} else if (v.value.value === undefined) {
return Promise.reject(new Error('请选择或输入参数值'));
}
}
} else {
return Promise.reject(new Error('请选择参数'));
}
return Promise.resolve();
},
},
]
nextTick(() => {
getParams()
})
</script> </script>
<style scoped> <style scoped>

View File

@ -324,7 +324,15 @@
满足此条件后执行后续动作 满足此条件后执行后续动作
</div> </div>
<div class='actions-item-filter-overflow'> <div class='actions-item-filter-overflow'>
<FilterGroup
v-for='(item, index) in termsOptions'
:branchName='branchesName'
:thenName='thenName'
:actionName='name'
:name='index'
:isLast='index === termsOptions.length - 1'
:isFirst='index === 0'
/>
</div> </div>
</template> </template>
<div v-else class='filter-add-button'> <div v-else class='filter-add-button'>
@ -371,6 +379,7 @@ import TriggerAlarm from '../TriggerAlarm/index.vue';
import { useSceneStore } from '@/store/scene'; import { useSceneStore } from '@/store/scene';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { iconMap, itemNotifyIconMap, typeIconMap } from './util' import { iconMap, itemNotifyIconMap, typeIconMap } from './util'
import FilterGroup from './FilterGroup.vue'
const sceneStore = useSceneStore(); const sceneStore = useSceneStore();
const { data: _data } = storeToRefs(sceneStore); const { data: _data } = storeToRefs(sceneStore);
@ -454,6 +463,12 @@ const onPropsCancel = () => {
actionType.value = ''; actionType.value = '';
}; };
watch(() => props.data, () => {
if (props.data) {
}
}, { immediate: true, deep: true})
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@ -615,27 +630,31 @@ const onPropsCancel = () => {
align-items: baseline; align-items: baseline;
} }
.terms-params-content { //.terms-params-content {
position: relative; // position: relative;
display: flex; // display: flex;
background-color: #fafafa; // background-color: #fafafa;
border: unset; // border: unset;
row-gap: 16px; // row-gap: 16px;
//
.terms-params-item { // &.no-border {
display: flex; // border: none;
align-items: center; // }
} //
// .terms-params-item {
.ant-form-item { // display: flex;
margin-bottom: 8px; // align-items: center;
&:not(:first-child) { // }
.ant-form-item-explain-error { //
padding-left: 80px !important; // .ant-form-item {
} // margin-bottom: 8px;
} // &:not(:first-child) {
} // .ant-form-item-explain-error {
} // padding-left: 80px !important;
// }
// }
// }
//}
.term-type-warp { .term-type-warp {
// display: inline-block; // display: inline-block;

View File

@ -33,6 +33,19 @@
} }
} }
.terms-params-delete {
.deleteBtn();
&.danger {
color: #e50012;
background-color: rgba(229, 0, 18, 0.1);
}
&.filter-terms-params-delete {
transform: translateY(6px);
}
}
.actions-terms { .actions-terms {
.actions-terms-warp { .actions-terms-warp {
display: flex; display: flex;
@ -115,11 +128,8 @@
.terms-params-content { .terms-params-content {
position: relative; position: relative;
display: flex; display: flex;
// flex-wrap: wrap; padding: 8px 8px 0px 8px;
padding: 8px;
padding-bottom: 0;
border: 1px dashed #e0e0e0; border: 1px dashed #e0e0e0;
//background-color: #fafafa;
border-radius: 6px; border-radius: 6px;
row-gap: 16px; row-gap: 16px;
.terms-params-item { .terms-params-item {
@ -162,6 +172,19 @@
border-radius: 2px; border-radius: 2px;
} }
} }
&.filter-group {
.terms-params-content {
background-color: #fafafa;
border: none;
}
.terms-params-delete {
transform: translateY(6px);
}
}
} }
.terms-params-item { .terms-params-item {
@ -189,15 +212,4 @@
} }
} }
.terms-params-delete {
.deleteBtn();
&.danger {
color: #e50012;
background-color: rgba(229, 0, 18, 0.1);
}
&.filter-terms-params-delete {
transform: translateY(6px);
}
}

1417
yarn.lock

File diff suppressed because it is too large Load Diff