merge: merge dev
* fix: 优化设备接入配置 * fix: 兼容2.1版本创建的菜单数据 * fix: 菜单配置兼容2.1菜单 * fix: bug#28524 【产品】产品选择设备接入网关,有多个配置时,只展示了一个 * fix: bug#28520【设备】当配置未开启时,前端应不展示配置按钮 * fix: bug#28533仪表盘本年流量消耗界面展示需优化 * fix: bug#28520、28534【设备】设备详情-物模型-其他配置 在点击配置时界面提示错误、【设备】当配置未开启时,前端应不展示配置按钮 * fix: bug#28531【设备】详情中查看预处理数据时提示错误 * fix: bug#28545【菜单管理】新增菜单,权限控制处无法正常加载出权限 * fix: 菜单配置->菜单权限同步功能 * fix: bug#28520【设备】当配置未开启时,前端应不展示配置按钮 * fix(media): bug#28595屏蔽固定地址通道列表的厂商字段 * fix(NoticeRule): 文字组织替换部门 * fix(Alarm): bug#28571手动触发展示说明 * fix(media): bug#28553界面展示异常 * fix(iotCard): bug#28567 * fix(media): bug#28595屏蔽固定地址通道列表的厂商字段 * fix: bug#28560【通知配置】微信-企业消息的同步用户页面,列表字段展示错误,【钉钉用户名】需改为【企业微信用户名】 * fix: bug#28544【通知配置】用户自己创建的数据,没有权限调试,报错:暂无权限,请联系管理员! * fix: bug#28549【采集器】在点位进行批量操作时,开启推送控制,进行保存异常 * fix: bug#28540【组织管理】设备资产分配页,设备列表形式展示,资产权限显示不完整 * fix: bug#28537【产品】新增的网关设备,接入方式选择"边缘网关接入"时,物模型中功能定义界面展示异常 * fix: bug#28550【远程升级】升级任务中的任务详情列表中文案修改 * fix: bug#28551【通知模版】和【通知配置】两者保存的查询条件共用了 * fix: bug#28560【通知配置】微信-企业消息的同步用户页面,列表字段展示错误,【钉钉用户名】需改为【企业微信用户名】 * fix(media): bug#28602屏蔽onvif相关配置 * fix: 物联卡管理样式优化及运营商状态取值 * fix(AliCloud): bug#28581新增阿里云网桥产品下拉值清空 * fix(media): bug#28602屏蔽onvif相关配置 * fix: bug#28578、28597【产品】物模型-属性定义-其他配置 在只进行选择了数据类型时,界面展示异常 、【产品】在进行更换接入网关时,会增加“预处理数据” * fix: bug#28578、28597【产品】物模型-属性定义-其他配置 在只进行选择了数据类型时,界面展示异常 、【产品】在进行更换接入网关时,会增加“预处理数据” * fix: bug#28538 【角色管理】【97】进入页面提示权限不足 * fix: bug#28605 【产品】产品物模型点击其它配置时,有时候界面会不出现蒙层 * fix: 【告警配置】兼容2.1绑定与取消绑定场景联动 * fix(region): 地区新增屏蔽重复校验及同步下级区域处理 * fix(system): 数据字典新增选中异常修复 * fix: bug#28611.28613 * fix(media): 仪表盘快捷时间没有取消选中效果 * fix(region): 地区新增屏蔽重复校验及同步下级区域处理 * fix: bug#28616【设备】【日志管理页】列表字段过长时,鼠标悬停【内容】展示数据不友好,和别处不一致 * fix: bug#28560【通知配置】微信-企业消息的同步用户页面,列表字段展示错误,【钉钉用户名】需改为【企业微信用户名】 * fix: bug#28559【通知管理】微信同步用户页面,查询无匹配部门时,后端不需要报错 * fix: bug#28563【通知模版】新增/编辑数据页,【绑定配置】的数据后端校验有错误时,也能正常新增保存,后端校验失败时,应不能新增保存,需要前端把后端的报错处理到校验规则内。 * fix: bug#28568【产品】通过导入的属性,其他配置中的存在方式为正确的展示 * fix: bug#28616【设备】【日志管理页】列表字段过长时,鼠标悬停【内容】展示数据不友好,和别处不一致 * fix: 修改预处理数据页面接口 * fix: 配置枚举项必填按钮放在右方 * fix: 【物模型】修复功能定义名称校验异常 * fix: 【运维管理】仪表盘修复jvm中Echarts无法显示服务名称 * fix: 【物模型】修复功能定义名称校验异常 * fix: 【场景联动】校验接口社区版兼容处理 * fix: bug#28615 【产品】【物模型-属性定义-编辑规则页】在屏幕分辦率【1380* 920】的情况下,属性名称下拉框无法正常获取到值 * fix: bug#28559 【通知管理】微信同步用户页面,查询无匹配部门时,后端不需要报错 * fix: bug#28563【通知模版】新增/编辑数据页,【绑定配置】的数据后端校验有错误时,也能正常新增保存,后端校验失败时,应不能新增保存,需要前端把后端的报错处理到校验规则内。 * fix: bug#28604 【产品】产品指标保存后查看,未回显已填入内容(设备运行状态界面查看是有指标的,但是产品配置查看未回显) * fix: bug#28634【产品】【物模型-事件定义-输出参数】当数据类型选择枚举值,不配置必填项【枚举项】,直接点击保存,可成功保存,理应提示必填 * fix: bug#28615 【产品】【物模型-属性定义-编辑规则页】在屏幕分辦率【1380* 920】的情况下,属性名称下拉框无法正常获取到值 * fix: 修改预处理数据查询处理结果接口 * fix: bug#28633新增字典后选中新增项 * fix: bug#28628编辑区域报错 * fix: bug#28526 【场景联动】场景联动文案描述错误,并且关闭执行动作后,应该同步隐藏防抖 * fix: 优化过滤条件开关逻辑条件 * fix: bug#【产品】产品(设备、告警记录),告警源不展示设备ID,展示设备名称 * fix: bug#28652【通知配置】通知配置钉钉(微信)进行用户绑定时,展示需优化 * fix: bug#28575 流媒体服务>>>服务商新增可选项内置流媒体 * fix: bug#28618.28619日历维护相关优化 * fix: bug#28648地区管理新增区域后下级消失 * fix: bug#28575 流媒体服务>>>服务商新增可选项内置流媒体 * fix: bug#28672产品物模型>>>功能定义>>>输入参数,选择类型为Object时,无法选择参数(事件也存在) * fix: bug#28654、28664、28663产品(设备)无效数据修改“告警源”>>>“数据源”,并且设备ID,修改为设备名称、通知模板>>>企业微信和钉钉消息调试时,名称应和模板内变量名称一致 * fix: bug#28663、28659通知模板>>>企业微信进行调试时,需判断收信人、收信人部门,收信人标签三个内容任意填写一个、钉钉消息调试时,需判断收信人或收信人部门任意填写其中一个 * fix: bug#28659【场景联动】场景联动>>>执行动作>>>>消息通知.>>>模板变量需判断收信人或者收信部门任意填写一个 * fix: bug#28661企业微信进行调试时,需判断收信人、收信人部门,收信人标签三个内容任意填写一个 * fix: bug#28672产品物模型>>>功能定义>>>输入参数,选择类型为Object时,无法选择参数(事件也存在) * fix: 修复钉钉调试选择了收信人过不了校验问题 * fix: 阈值处理方式取值修改 * fix: 场景联动执行动作微信显示部门标签 * fix: 修改场景联通通知图标 * fix: bug#28575内嵌流媒体样式优化 * fix: bug28679.28678 * fix: 修改流媒体详情字段 * fix: 场景联动执行动作微信显示部门标签 * fix: 修改场景联通通知图标 * fix: 无效数据数据源跳转功能 * fix: 流媒体详情修改文字 * fix: 修改流媒体详情字段 * fix: bug#28687 【场景联动】场景联动>>>执行动作>>>消息通知>>>清除了收信信息后(有其余可校验内容)但是无法通过校验(企微、钉钉都存在) * fix: bug#28688场景联动>>>执行动作>>>消息发送,当钉钉(企业)选择收信人后,切换收信人类型,然后点击保存,未清空切换前的内容 * fix: api配置调试请求体判断条件修改
This commit is contained in:
parent
2b3e3280ac
commit
827b824451
Binary file not shown.
Before Width: | Height: | Size: 457 B After Width: | Height: | Size: 3.6 KiB |
|
@ -31,7 +31,7 @@ export const saveMetadata = (id: string, data: DeviceMetadata) => server.put(`/d
|
|||
* @param id 设备ID
|
||||
* @returns 设备详情
|
||||
*/
|
||||
export const detail = (id: string) => server.get<DeviceInstance>(`/device-instance/${id}/detail`)
|
||||
export const detail = (id: string, _hideError?: any) => server.get<DeviceInstance>(`/device-instance/${id}/detail`, {}, {} , _hideError)
|
||||
|
||||
/**
|
||||
* 查询数据
|
||||
|
@ -682,4 +682,4 @@ export const deleteDeviceThreshold = (productId:string,deviceId:string,propertyI
|
|||
|
||||
export const getTemplate = (id: string, format: string) => `${BASE_API_PATH}/device/instance/${id}/property-metadata/template.${format}`
|
||||
|
||||
export const uploadAnalyzeMetadata = (data: any) => server.post('/device/instance/property-metadata/file/analyze', data)
|
||||
export const uploadAnalyzeMetadata = (productId:string,data: any) => server.post(`/device/instance/${productId}/property-metadata/file/analyze`, data)
|
||||
|
|
|
@ -37,6 +37,12 @@ export const queryByDevice = (data:any) => server.post(`/alarm/record/device/_qu
|
|||
*/
|
||||
export const handleLog = (data:any) => server.post('/alarm/record/_handle',data);
|
||||
|
||||
/**
|
||||
*
|
||||
* 预处理告警处理
|
||||
*/
|
||||
export const handlePreconditioning = (data:any) => server.post(`/alarm/record/device/_handle`,data)
|
||||
|
||||
/**
|
||||
* 告警记录
|
||||
*/
|
||||
|
@ -58,11 +64,21 @@ export const queryHistoryList = (data:any) => server.post('/alarm/history/_query
|
|||
*/
|
||||
export const queryHandleHistory = (data:any) => server.post('/alarm/record/handle-history/_query',data);
|
||||
|
||||
/**
|
||||
* 获取预处理数据告警处理结果
|
||||
*/
|
||||
export const queryPreHandleHistory = (recordId:any,data:any) => server.post(`/alarm/record/handle-history/device/${recordId}/_query`,data)
|
||||
|
||||
/**
|
||||
* 获取告警日志(新)
|
||||
*/
|
||||
export const queryLogList = (alarmConfigId:any,data:any) => server.post(`/alarm/history/${alarmConfigId}/_query`,data)
|
||||
|
||||
/**
|
||||
* 获取预处理数据告警日志
|
||||
*/
|
||||
export const queryPreconditioningLogList = (alarmConfigId:any,data:any) => server.post(`/alarm/history/device/${alarmConfigId}/_query`,data)
|
||||
|
||||
/**
|
||||
* 查询无效数据
|
||||
*/
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
showSearch
|
||||
:options="options"
|
||||
v-model:value="record.id"
|
||||
:getPopupContainer="(node) => tableWrapperRef || node"
|
||||
:getPopupContainer="getPopupContainer"
|
||||
size="small"
|
||||
style="width: 100%;"
|
||||
:virtual="true"
|
||||
|
@ -105,7 +105,7 @@
|
|||
size="small"
|
||||
style="width: 100%;"
|
||||
:virtual="true"
|
||||
:getPopupContainer="(node) => tableWrapperRef || node"
|
||||
:getPopupContainer="getPopupContainer"
|
||||
:dropdownStyle="{
|
||||
zIndex: 1072
|
||||
}"
|
||||
|
@ -202,6 +202,7 @@ import { getWebSocket } from '@/utils/websocket';
|
|||
import {useTableWrapper} from "@/components/Metadata/Table/context";
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
import {message} from "ant-design-vue";
|
||||
import { useTableFullScreen} from "@/components/Metadata/Table/context";
|
||||
|
||||
const props = defineProps({
|
||||
virtualRule: Object as PropType<Record<any, any>>,
|
||||
|
@ -222,7 +223,7 @@ type propertyType = {
|
|||
const property = ref<propertyType[]>([]);
|
||||
const tag = ref<Array<any>>([]);
|
||||
const tableWrapperRef = useTableWrapper()
|
||||
|
||||
const fullScreen = useTableFullScreen()
|
||||
const columns = [
|
||||
{
|
||||
title: '属性名称',
|
||||
|
@ -287,6 +288,14 @@ const ruleEditorStore = useRuleEditorStore();
|
|||
const time = ref<number>(0);
|
||||
const timer = ref<any>(null);
|
||||
|
||||
//是否全屏监听
|
||||
const getPopupContainer = (node: any) => {
|
||||
if (fullScreen.value) {
|
||||
return tableWrapperRef.value || node
|
||||
}
|
||||
|
||||
return document.body
|
||||
}
|
||||
const runScript = () => {
|
||||
const propertiesList = medataSource?.value || []
|
||||
const _properties = property.value.map((item: any) => {
|
||||
|
|
|
@ -105,7 +105,10 @@ const validateRules = () => {
|
|||
}
|
||||
|
||||
const promise = context.validateItem({ [filedName.value]: get(context.dataSource.value, props.name) }, index)
|
||||
promise.catch(res => {
|
||||
promise.then(() => {
|
||||
hideErrorTip()
|
||||
context.removeFieldError(eventKey.value)
|
||||
}).catch(res => {
|
||||
const error = res?.filter(item => item.field === filedName.value) || []
|
||||
if (error.length === 0) {
|
||||
hideErrorTip()
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<a-form-item :name="name" :rules="rules" :validate-first="true">
|
||||
<template #label>
|
||||
<span style="color: #ff4d4f; padding-right: 4px; padding-top: 2px">*</span>
|
||||
枚举项
|
||||
<span style="color: #ff4d4f; padding-right: 4px; padding-top: 2px">*</span>
|
||||
</template>
|
||||
<Content ref="tableRef" v-model:value="dataSource" @change="change" />
|
||||
</a-form-item>
|
||||
|
|
|
@ -14,52 +14,114 @@
|
|||
:pagination="false"
|
||||
:height="200"
|
||||
>
|
||||
<!-- <template v-for="(_, key) in slots" :key="key" #[key]="slotData">-->
|
||||
<!-- <slot :name="key" v-bind="slotData"/>-->
|
||||
<!-- </template>-->
|
||||
<!-- <template v-for="(_, key) in slots" :key="key" #[key]="slotData">-->
|
||||
<!-- <slot :name="key" v-bind="slotData"/>-->
|
||||
<!-- </template>-->
|
||||
<template #id="{ record, index }">
|
||||
<EditTableFormItem :name="[index, 'id']">
|
||||
<a-input v-model:value="record.id" placeholder="请输入标识"/>
|
||||
<a-input
|
||||
v-model:value="record.id"
|
||||
placeholder="请输入标识"
|
||||
/>
|
||||
</EditTableFormItem>
|
||||
</template>
|
||||
<template #name="{ record, index }">
|
||||
<EditTableFormItem :name="[index, 'name']">
|
||||
<a-input v-model:value="record.name" placeholder="请输入名称"/>
|
||||
<a-input
|
||||
v-model:value="record.name"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</EditTableFormItem>
|
||||
</template>
|
||||
<template #expands="{ record }">
|
||||
<BooleanSelect v-model:value="record.expands.required"/>
|
||||
<BooleanSelect
|
||||
v-model:value="record.expands.required"
|
||||
/>
|
||||
</template>
|
||||
<template #valueType="{ record, index }">
|
||||
<EditTableFormItem :name="[index, 'valueType']">
|
||||
<div style="display: flex; gap: 12px; align-items: center">
|
||||
<TypeSelect v-model:value="record.valueType.type" style="flex: 1 1 0;min-width: 0" />
|
||||
<DoubleParams v-if="['float', 'double'].includes(record.valueType.type)" v-model:value="record.valueType" placement="topRight"/>
|
||||
<StringParams v-else-if="record.valueType.type === 'string'" v-model:value="record.valueType" placement="topRight"/>
|
||||
<DateParams v-else-if="record.valueType.type === 'date'" v-model:value="record.valueType.format" placement="topRight"/>
|
||||
<FileParams v-else-if="record.valueType.type === 'file'" v-model:value="record.valueType.bodyType" placement="topRight"/>
|
||||
<EnumParams v-else-if="record.valueType.type === 'enum'" v-model:value="record.valueType.elements" placement="topRight"/>
|
||||
<BooleanParams
|
||||
v-else-if="record.valueType.type === 'boolean'"
|
||||
v-model:falseText="record.valueType.falseText"
|
||||
v-model:falseValue="record.valueType.falseValue"
|
||||
v-model:trueText="record.valueType.trueText"
|
||||
v-model:trueValue="record.valueType.trueValue"
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
"
|
||||
>
|
||||
<TypeSelect
|
||||
v-model:value="record.valueType.type"
|
||||
style="flex: 1 1 0; min-width: 0"
|
||||
/>
|
||||
<DoubleParams
|
||||
v-if="
|
||||
['float', 'double'].includes(
|
||||
record.valueType.type,
|
||||
)
|
||||
"
|
||||
v-model:value="record.valueType"
|
||||
placement="topRight"
|
||||
/>
|
||||
<StringParams
|
||||
v-else-if="
|
||||
record.valueType.type === 'string'
|
||||
"
|
||||
v-model:value="record.valueType"
|
||||
placement="topRight"
|
||||
/>
|
||||
<DateParams
|
||||
v-else-if="record.valueType.type === 'date'"
|
||||
v-model:value="record.valueType.format"
|
||||
placement="topRight"
|
||||
/>
|
||||
<FileParams
|
||||
v-else-if="record.valueType.type === 'file'"
|
||||
v-model:value="record.valueType.bodyType"
|
||||
placement="topRight"
|
||||
/>
|
||||
<EnumParams
|
||||
v-else-if="record.valueType.type === 'enum'"
|
||||
v-model:value="record.valueType.elements"
|
||||
placement="topRight"
|
||||
/>
|
||||
<BooleanParams
|
||||
v-else-if="
|
||||
record.valueType.type === 'boolean'
|
||||
"
|
||||
v-model:falseText="
|
||||
record.valueType.falseText
|
||||
"
|
||||
v-model:falseValue="
|
||||
record.valueType.falseValue
|
||||
"
|
||||
v-model:trueText="record.valueType.trueText"
|
||||
v-model:trueValue="
|
||||
record.valueType.trueValue
|
||||
"
|
||||
placement="topRight"
|
||||
/>
|
||||
<ArrayParams
|
||||
v-else-if="
|
||||
record.valueType.type === 'array'
|
||||
"
|
||||
v-model:value="record.valueType.elementType"
|
||||
placement="topRight"
|
||||
/>
|
||||
<ArrayParams v-else-if="record.valueType.type === 'array'" v-model:value="record.valueType.elementType" placement="topRight"/>
|
||||
</div>
|
||||
</EditTableFormItem>
|
||||
</template>
|
||||
<template #action="{ index }">
|
||||
<a-button danger type="link" style="padding: 0 5px" @click="() => deleteItem(index)">
|
||||
<a-button
|
||||
danger
|
||||
type="link"
|
||||
style="padding: 0 5px"
|
||||
@click="() => deleteItem(index)"
|
||||
>
|
||||
<template #icon>
|
||||
<AIcon type="DeleteOutlined" />
|
||||
</template>
|
||||
</a-button>
|
||||
</template>
|
||||
</EditTable>
|
||||
<a-button style="width: 100%;margin-top: 4px" @click="addItem">
|
||||
<a-button style="width: 100%; margin-top: 4px" @click="addItem">
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
新增
|
||||
</a-button>
|
||||
|
@ -68,7 +130,10 @@
|
|||
<slot>
|
||||
<a-button type="link" :disabled="disabled" style="padding: 0">
|
||||
<template #icon>
|
||||
<AIcon type="EditOutlined" :class="{'table-form-required-aicon': !value.length}"/>
|
||||
<AIcon
|
||||
type="EditOutlined"
|
||||
:class="{ 'table-form-required-aicon': !value.length }"
|
||||
/>
|
||||
</template>
|
||||
</a-button>
|
||||
</slot>
|
||||
|
@ -76,10 +141,22 @@
|
|||
</template>
|
||||
|
||||
<script setup name="MetadataObject">
|
||||
import { PopoverModal } from '../index'
|
||||
import BooleanSelect from "../BooleanSelect/index.vue";
|
||||
import { EditTable, TypeSelect, EditTableFormItem, StringParams, DateParams, FileParams, EnumParams, BooleanParams, ObjectParams, ArrayParams, DoubleParams } from '@/components/Metadata/Table'
|
||||
import {Form} from "ant-design-vue";
|
||||
import { PopoverModal } from '../index';
|
||||
import BooleanSelect from '../BooleanSelect/index.vue';
|
||||
import {
|
||||
EditTable,
|
||||
TypeSelect,
|
||||
EditTableFormItem,
|
||||
StringParams,
|
||||
DateParams,
|
||||
FileParams,
|
||||
EnumParams,
|
||||
BooleanParams,
|
||||
ObjectParams,
|
||||
ArrayParams,
|
||||
DoubleParams,
|
||||
} from '@/components/Metadata/Table';
|
||||
import { Form } from 'ant-design-vue';
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
|
@ -92,22 +169,53 @@ const props = defineProps({
|
|||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'properties'
|
||||
default: 'properties',
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default:false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const validatorConfig = (value, _isObject = false) => {
|
||||
if (!value) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (value.type === 'enum' && !value.elements?.length) {
|
||||
return Promise.reject('请添加枚举项');
|
||||
}
|
||||
if (value.type === 'array' && !value.elementType?.type) {
|
||||
return Promise.reject('请选择元素类型');
|
||||
}
|
||||
|
||||
// if (_isObject && value.type === 'object' && !value.properties?.length) {
|
||||
// return Promise.reject('请添加参数');
|
||||
// }
|
||||
|
||||
if (value.type === 'date' && !value.format) {
|
||||
return Promise.reject('请选择时间格式');
|
||||
}
|
||||
|
||||
if (
|
||||
value.type === 'file' &&
|
||||
(!value.bodyType ||
|
||||
(isObject(value.bodyType) && !Object.keys(value.bodyType).length))
|
||||
) {
|
||||
return Promise.reject('请选择文件类型');
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
const emit = defineEmits(['update:value', 'confirm', 'cancel']);
|
||||
const formItemContext = Form.useInjectFormItemContext();
|
||||
|
||||
const slots = useSlots()
|
||||
const slots = useSlots();
|
||||
|
||||
const tableRef = ref()
|
||||
const dataSource = ref([])
|
||||
const visible = ref(false)
|
||||
const tableRef = ref();
|
||||
const dataSource = ref([]);
|
||||
const visible = ref(false);
|
||||
|
||||
const defaultColumns = [
|
||||
{
|
||||
|
@ -118,27 +226,30 @@ const defaultColumns = [
|
|||
{
|
||||
asyncValidator(_, value, ...setting) {
|
||||
if (value) {
|
||||
const option = setting[2]
|
||||
const option = setting[2];
|
||||
|
||||
const isSome = dataSource.value.some((item) => {
|
||||
return item.__dataIndex !== option.index && item.id === value
|
||||
})
|
||||
return (
|
||||
item.__dataIndex !== option.index &&
|
||||
item.id === value
|
||||
);
|
||||
});
|
||||
|
||||
if (isSome) {
|
||||
return Promise.reject('该标识已存在')
|
||||
return Promise.reject('该标识已存在');
|
||||
}
|
||||
return Promise.resolve()
|
||||
}
|
||||
return Promise.reject('请输入标识')
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject('请输入标识');
|
||||
},
|
||||
},
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
{
|
||||
pattern: /^[a-zA-Z0-9_]+$/,
|
||||
message: '标识只能由数字、字母、下划线组成',
|
||||
},
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '参数名称',
|
||||
|
@ -147,86 +258,90 @@ const defaultColumns = [
|
|||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入名称'
|
||||
message: '请输入名称',
|
||||
},
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
props.type === 'functions' ? {
|
||||
},
|
||||
props.type === 'functions'
|
||||
? {
|
||||
title: '填写约束',
|
||||
dataIndex: 'expands',
|
||||
width: 120,
|
||||
} : null,
|
||||
}
|
||||
: null,
|
||||
{
|
||||
title: '数据类型',
|
||||
dataIndex: 'valueType',
|
||||
width: 240,
|
||||
form: {
|
||||
required: true,
|
||||
rules: [{
|
||||
rules: [
|
||||
{
|
||||
validator(_, value) {
|
||||
if (!value?.type) {
|
||||
return Promise.reject('请选择数据类型')
|
||||
return Promise.reject('请选择数据类型');
|
||||
}
|
||||
return Promise.resolve()
|
||||
}
|
||||
}]
|
||||
return validatorConfig(value, true);
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const myColumns = computed(() => {
|
||||
|
||||
return [
|
||||
...defaultColumns.filter(item => !!item),
|
||||
...defaultColumns.filter((item) => !!item),
|
||||
{
|
||||
dataIndex: 'action',
|
||||
title: '操作',
|
||||
width: 60,
|
||||
}
|
||||
]
|
||||
})
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const onOk = async () => {
|
||||
const data = await tableRef.value.validate()
|
||||
const data = await tableRef.value.validate();
|
||||
if (data) {
|
||||
visible.value = false
|
||||
emit('update:value', data)
|
||||
emit('confirm', data)
|
||||
formItemContext.onFieldChange()
|
||||
visible.value = false;
|
||||
emit('update:value', data);
|
||||
emit('confirm', data);
|
||||
formItemContext.onFieldChange();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
emit('cancel');
|
||||
};
|
||||
|
||||
const deleteItem = (index) => {
|
||||
dataSource.value.splice(index, 1)
|
||||
}
|
||||
dataSource.value.splice(index, 1);
|
||||
};
|
||||
|
||||
const addItem = () => {
|
||||
dataSource.value.push({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
expands: {
|
||||
required: false
|
||||
required: false,
|
||||
},
|
||||
valueType: {
|
||||
expands: {}
|
||||
}
|
||||
})
|
||||
}
|
||||
expands: {},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
watch(() => [JSON.stringify(props.value), visible.value], (val) => {
|
||||
watch(
|
||||
() => [JSON.stringify(props.value), visible.value],
|
||||
(val) => {
|
||||
if (visible.value) {
|
||||
dataSource.value = JSON.parse(val[0] || '[]')
|
||||
dataSource.value = JSON.parse(val[0] || '[]');
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -48,7 +48,6 @@ const getMaskNode = (id: string, warpClassNames: string) => {
|
|||
})
|
||||
|
||||
const warpNode = document.querySelector(`.${warpClassNames}`) as HTMLDivElement
|
||||
|
||||
if (!warpNode) return undefined
|
||||
|
||||
warpNode.insertAdjacentElement('beforebegin', maskNode)
|
||||
|
@ -64,10 +63,11 @@ export const useMask = (propVisible: boolean, options: { visibleChange: (visible
|
|||
showMask: Function,
|
||||
visibleChange: (visible: boolean) => void
|
||||
} => {
|
||||
const key = randomString(6)
|
||||
const visible = ref(propVisible)
|
||||
const maskDomId = `${maskNodeClassName}-${randomString(6)}`
|
||||
const maskDomId = `${maskNodeClassName}-${key}`
|
||||
|
||||
const warpClassNames = `${maskNodeClassName}-warp-${randomString(4)}`
|
||||
const warpClassNames = `${maskNodeClassName}-warp-${key}`
|
||||
const createMask = () => {
|
||||
if (!maskIds.includes(maskDomId)) {
|
||||
maskIds.push(maskDomId)
|
||||
|
@ -78,13 +78,12 @@ export const useMask = (propVisible: boolean, options: { visibleChange: (visible
|
|||
|
||||
const getLastMask = (): HTMLElement | undefined => {
|
||||
const index = maskIds.findIndex(key => key === maskDomId) // 当前遮罩层下标
|
||||
|
||||
let dom = undefined
|
||||
let lastIndex = 0
|
||||
|
||||
if (maskIds.length > 0) {
|
||||
|
||||
lastIndex = index < 0 ? 0 : index - 1
|
||||
lastIndex = index <= 0 ? 0 : index - 1
|
||||
|
||||
const lastMaskId = maskIds[lastIndex]
|
||||
|
||||
|
@ -116,7 +115,7 @@ export const useMask = (propVisible: boolean, options: { visibleChange: (visible
|
|||
updateStyle(maskNode, {
|
||||
display: 'block'
|
||||
})
|
||||
}, 10)
|
||||
}, 150)
|
||||
}
|
||||
|
||||
const hideMask = () => {
|
||||
|
|
|
@ -45,7 +45,7 @@ export const defaultBranches = [
|
|||
key: 'terms_1',
|
||||
},
|
||||
],
|
||||
key: 'branches_1',
|
||||
key: defaultBranchId,
|
||||
shakeLimit: {
|
||||
enabled: false,
|
||||
time: 1,
|
||||
|
@ -69,7 +69,7 @@ const defaultOptions = {
|
|||
},
|
||||
],
|
||||
branchName:'条件',
|
||||
key: 'branches_1',
|
||||
key:defaultBranchId,
|
||||
executeAnyway: true,
|
||||
groupIndex: 1
|
||||
},
|
||||
|
|
|
@ -537,7 +537,10 @@ const getProduct = async () => {
|
|||
|
||||
const getAliyunProduct = async (data: any) => {
|
||||
if (data.regionId && data.accessKeyId && data.accessSecret) {
|
||||
const resp: any = await getAliyunProductsList(data);
|
||||
const resp: any = await getAliyunProductsList(data).catch(()=>{
|
||||
aliyunProductList.value = [];
|
||||
modelRef.bridgeProductKey = undefined;
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
aliyunProductList.value = resp?.result?.data as Record<
|
||||
string,
|
||||
|
@ -720,6 +723,7 @@ watch(
|
|||
},
|
||||
];
|
||||
modelRef.description = undefined;
|
||||
aliyunProductList.value = [];
|
||||
} else if (props.data?.type === 'noData') {
|
||||
noData.value = true;
|
||||
}
|
||||
|
|
|
@ -33,12 +33,13 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Log :currentId="AlarmData.id" :configId="AlarmData.alarmConfigId" />
|
||||
<Log :currentId="AlarmData.id" :configId="AlarmData.alarmConfigId" :goal="goal"/>
|
||||
</a-drawer>
|
||||
<SolveComponent
|
||||
v-if="solveVisible"
|
||||
@closeSolve="closeSolve"
|
||||
@refresh="refresh"
|
||||
:goal="goal"
|
||||
:data="AlarmData"
|
||||
/>
|
||||
</template>
|
||||
|
@ -53,6 +54,10 @@ const props = defineProps({
|
|||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
goal:{
|
||||
type:String,
|
||||
default:''
|
||||
}
|
||||
});
|
||||
const emit = defineEmits(['closeDrawer', 'refreshTable']);
|
||||
const { levelMap } = useAlarmLevel();
|
||||
|
|
|
@ -26,10 +26,10 @@
|
|||
: '--'
|
||||
}}
|
||||
</template>
|
||||
<template #sourceId="slotProps">
|
||||
<template #sourceName="slotProps">
|
||||
<Ellipsis>
|
||||
设备ID:
|
||||
<span class="deviceId" @click="() => gotoDevice(slotProps.sourceId)">{{ slotProps.sourceId }}</span></Ellipsis
|
||||
设备名称:
|
||||
<span class="deviceId" @click="() => gotoDevice(slotProps.sourceId)">{{ slotProps.sourceName }}</span></Ellipsis
|
||||
>
|
||||
</template>
|
||||
<template #handleType="slotProps">
|
||||
|
@ -65,6 +65,7 @@
|
|||
v-if="solveVisible"
|
||||
:data="currentAlarm"
|
||||
:solveType="solveType"
|
||||
:goal="goal"
|
||||
:handleDes="handleDescription"
|
||||
@closeSolve="closeSolve"
|
||||
@refresh="solveRefresh"
|
||||
|
@ -72,6 +73,7 @@
|
|||
<AlarmLog
|
||||
v-if="visibleDrawer"
|
||||
:data="currentAlarm"
|
||||
:goal="goal"
|
||||
@closeDrawer="visibleDrawer = false"
|
||||
@refreshTable="refresh"
|
||||
/>
|
||||
|
@ -80,7 +82,7 @@
|
|||
<script setup>
|
||||
import {
|
||||
queryByDevice as queryAlarmRecord,
|
||||
queryHandleHistory,
|
||||
queryPreHandleHistory,
|
||||
} from '@/api/rule-engine/log';
|
||||
import { useInstanceStore } from '@/store/instance';
|
||||
import { useProductStore } from '@/store/product';
|
||||
|
@ -204,8 +206,8 @@ const columns =
|
|||
},
|
||||
{
|
||||
title: '告警源',
|
||||
dataIndex: 'sourceId',
|
||||
key: 'sourceId',
|
||||
dataIndex: 'sourceName',
|
||||
key: 'sourceName',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
|
@ -329,16 +331,8 @@ const handleSearch = (e) => {
|
|||
params.value = e;
|
||||
};
|
||||
const queryHandle = async (id) => {
|
||||
const res = await queryHandleHistory({
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
terms: [
|
||||
{
|
||||
column: 'alarmRecordId',
|
||||
termType: 'eq',
|
||||
value: id,
|
||||
type: 'and',
|
||||
},
|
||||
],
|
||||
const res = await queryPreHandleHistory(id,{
|
||||
sorts: [{ name: 'handleTime', order: 'desc' }],
|
||||
});
|
||||
if (res.status === 200 && res.result?.data.length) {
|
||||
handleDescription.value = res.result.data?.[0]?.description;
|
||||
|
|
|
@ -31,12 +31,13 @@
|
|||
><template #createTime="slotProps">
|
||||
{{ dayjs(slotProps.createTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||
</template>
|
||||
<template #thingId="slotProps">
|
||||
<template #thingName="slotProps">
|
||||
<Ellipsis>
|
||||
设备ID:
|
||||
设备名称:
|
||||
<span
|
||||
class="deviceId"
|
||||
>{{ slotProps.thingId }}</span
|
||||
@click="() => gotoDevice(slotProps.thingId)"
|
||||
>{{ slotProps.thingName }}</span
|
||||
></Ellipsis
|
||||
>
|
||||
</template>
|
||||
|
@ -48,12 +49,14 @@ import { queryInvalidData } from '@/api/rule-engine/log';
|
|||
import { useInstanceStore } from '@/store/instance';
|
||||
import { useProductStore } from '@/store/product';
|
||||
import dayjs from 'dayjs';
|
||||
import { useMenuStore } from 'store/menu';
|
||||
const props = defineProps({
|
||||
goal: {
|
||||
type: String,
|
||||
default: 'device',
|
||||
},
|
||||
});
|
||||
const menuStory = useMenuStore();
|
||||
const { current } =
|
||||
props.goal === 'device' ? useInstanceStore() : useProductStore();
|
||||
const columns = props.goal === 'device' ? [
|
||||
|
@ -92,9 +95,9 @@ const columns = props.goal === 'device' ? [
|
|||
scopedSlots: true,
|
||||
},
|
||||
{
|
||||
title: '告警源',
|
||||
dataIndex: 'thingId',
|
||||
key: 'thingId',
|
||||
title: '数据源',
|
||||
dataIndex: 'thingName',
|
||||
key: 'thingName',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
|
@ -114,6 +117,10 @@ const columns = props.goal === 'device' ? [
|
|||
},
|
||||
},
|
||||
]
|
||||
|
||||
const gotoDevice = (id) => {
|
||||
menuStory.jumpPage('device/Instance/Detail', { id, tab: 'Running' });
|
||||
};
|
||||
const handleSearch = (e) => {
|
||||
params.value = e;
|
||||
};
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
<template #type="slotProps">
|
||||
{{ slotProps?.type?.text }}
|
||||
</template>
|
||||
<template #content="slotProps">
|
||||
<Ellipsis style="width:calc(100% - 20px)">{{ slotProps?.content }}</Ellipsis>
|
||||
</template>
|
||||
<template #timestamp="slotProps">
|
||||
{{
|
||||
slotProps.timestamp
|
||||
|
@ -87,7 +90,6 @@ const columns = [
|
|||
},
|
||||
{
|
||||
title: '内容',
|
||||
ellipsis: true,
|
||||
dataIndex: 'content',
|
||||
key: 'content',
|
||||
scopedSlots: true,
|
||||
|
|
|
@ -163,7 +163,7 @@ import { usePermissionStore } from '@/store/permission';
|
|||
import { isNoCommunity } from '@/utils/utils';
|
||||
import { useSystem } from '@/store/system';
|
||||
|
||||
const { showThreshold } = useSystem()
|
||||
const { showThreshold } = useSystem();
|
||||
const permissionStore = usePermissionStore();
|
||||
const menuStory = useMenuStore();
|
||||
const route = useRoute();
|
||||
|
@ -272,6 +272,21 @@ const handleUndeploy = () => {
|
|||
* 是否显示数据解析模块
|
||||
*/
|
||||
const getProtocol = async () => {
|
||||
list.value = [
|
||||
{
|
||||
key: 'Info',
|
||||
tab: '配置信息',
|
||||
},
|
||||
{
|
||||
key: 'Metadata',
|
||||
tab: '物模型',
|
||||
class: 'objectModel',
|
||||
},
|
||||
{
|
||||
key: 'Device',
|
||||
tab: '设备接入',
|
||||
},
|
||||
];
|
||||
if (productStore.current?.messageProtocol) {
|
||||
const res: any = await getProtocolDetail(
|
||||
productStore.current?.messageProtocol,
|
||||
|
@ -294,7 +309,8 @@ const getProtocol = async () => {
|
|||
}
|
||||
if (
|
||||
supportFirmware &&
|
||||
permissionStore.hasPermission('device/Firmware:view') && isNoCommunity
|
||||
permissionStore.hasPermission('device/Firmware:view') &&
|
||||
isNoCommunity
|
||||
) {
|
||||
list.value.push({
|
||||
key: 'Firmware',
|
||||
|
@ -316,7 +332,9 @@ const getProtocol = async () => {
|
|||
if (
|
||||
permissionStore.hasPermission(
|
||||
'rule-engine/Alarm/Configuration:view',
|
||||
) && isNoCommunity && showThreshold
|
||||
) &&
|
||||
isNoCommunity &&
|
||||
showThreshold
|
||||
) {
|
||||
list.value.push({
|
||||
key: 'AlarmRecord',
|
||||
|
|
|
@ -260,7 +260,7 @@ export const useColumns = (dataSource: Ref<MetadataItem[]>, type?: MetadataType,
|
|||
{
|
||||
asyncValidator: async (rule: any, value: any) => {
|
||||
|
||||
const source = value.source
|
||||
const source = value?.source
|
||||
if (source) {
|
||||
if (source === 'device' && !value.type?.length) {
|
||||
return Promise.reject('请选择读写类型');
|
||||
|
|
|
@ -69,6 +69,7 @@ import { getTemplate, uploadAnalyzeMetadata} from '@/api/device/instance'
|
|||
import {getTemplate as getProductTemplate} from '@/api/device/product'
|
||||
import {downloadFileByUrl} from "@/utils/utils";
|
||||
import {useGroupActive, useTableWrapper} from "@/components/Metadata/Table/context";
|
||||
import { useProductStore } from '@/store/product';
|
||||
|
||||
const props = defineProps({
|
||||
target: {
|
||||
|
@ -82,7 +83,7 @@ const props = defineProps({
|
|||
})
|
||||
|
||||
const emit = defineEmits(['ok'])
|
||||
|
||||
const { current } = useProductStore()
|
||||
const visible = ref(false);
|
||||
const successCount = ref(0);
|
||||
const errorCount = ref(0);
|
||||
|
@ -117,7 +118,6 @@ const onCancel = () => {
|
|||
}
|
||||
|
||||
const submitData = async (metadataStr) => {
|
||||
console.log(metadataStr)
|
||||
if (metadataStr) {
|
||||
const _metadataObject = JSON.parse(metadataStr || "{}")
|
||||
const properties = _metadataObject.properties
|
||||
|
@ -176,7 +176,7 @@ const beforeUpload = (file) => {
|
|||
formData.append('file', file)
|
||||
|
||||
step.value = 2
|
||||
uploadAnalyzeMetadata(formData).then(res => {
|
||||
uploadAnalyzeMetadata(current.id , formData).then(res => {
|
||||
if (res.success) {
|
||||
submitData(res.result)
|
||||
}
|
||||
|
@ -189,7 +189,6 @@ const beforeUpload = (file) => {
|
|||
|
||||
|
||||
const uploadChange = async (info) => {
|
||||
console.log(info)
|
||||
if (info.file.status === 'uploading') {
|
||||
step.value = 2
|
||||
}
|
||||
|
|
|
@ -75,9 +75,9 @@ const formData = reactive<{
|
|||
value: ValueType;
|
||||
rangeValue: ValueType;
|
||||
}>({
|
||||
value: props.value?.range === false ? props.value?.value : undefined,
|
||||
rangeValue: props.value?.range === true
|
||||
? cloneDeep(props.value?.value) || [undefined, undefined]
|
||||
value: props.range === false ? props.value : undefined,
|
||||
rangeValue: props.range === true
|
||||
? cloneDeep(props.value) || [undefined, undefined]
|
||||
: [undefined, undefined],
|
||||
});
|
||||
|
||||
|
@ -87,10 +87,10 @@ const showText = computed(() => {
|
|||
if (props.range === false) {
|
||||
switch (type) {
|
||||
case 'date':
|
||||
return props.value?.value;
|
||||
return props.value;
|
||||
case 'boolean':
|
||||
const _value = props.value?.value
|
||||
const item = props.options.find(item => item.value === props.value?.value)
|
||||
const _value = props.value
|
||||
const item = props.options.find(item => item.value === props.value)
|
||||
if (item) {
|
||||
return item.label
|
||||
}else if (_value) {
|
||||
|
@ -99,10 +99,10 @@ const showText = computed(() => {
|
|||
return ''
|
||||
}
|
||||
default:
|
||||
return props.value?.value
|
||||
return props.value
|
||||
}
|
||||
} else {
|
||||
return props.value?.value?.[0] ? props.value.value.join('-') : ''
|
||||
return props.value?.[0] ? props.value.join('-') : ''
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -169,7 +169,7 @@ const confirm = () => {
|
|||
|
||||
watch(() => props.range, (value, oldValue) => {
|
||||
if (value !== oldValue ) {
|
||||
formData.rangeValue = value ? [undefined, undefined] : undefined
|
||||
formData.rangeValue = value ? cloneDeep(props.value) || [undefined, undefined] : undefined
|
||||
}
|
||||
}, { immediate: true})
|
||||
</script>
|
||||
|
|
|
@ -210,7 +210,10 @@
|
|||
v-model:value="extraForm.mode"
|
||||
:options="[
|
||||
{ label: '忽略', value: 'ignore' },
|
||||
{ label: '记录', value: 'record' },
|
||||
{
|
||||
label: '记录',
|
||||
value: 'device-record',
|
||||
},
|
||||
{
|
||||
label: '告警',
|
||||
value: 'device-alarm',
|
||||
|
@ -310,7 +313,7 @@ const props = defineProps({
|
|||
|
||||
const type = inject('_metadataType');
|
||||
|
||||
const { showThreshold } = useSystem()
|
||||
const { showThreshold } = useSystem();
|
||||
const productStore = useProductStore();
|
||||
const deviceStore = useInstanceStore();
|
||||
const tableWrapperRef = useTableWrapper();
|
||||
|
@ -354,7 +357,7 @@ const typeMap = {
|
|||
const handleTip = computed(() => {
|
||||
if (extraForm.mode === 'ignore') {
|
||||
return '平台将忽略超出阈值的数据,无法查看上报记录';
|
||||
} else if (extraForm.mode === 'record') {
|
||||
} else if (extraForm.mode === 'device-record') {
|
||||
return '您可以在预处理数据-无效数据页面查看超出阈值的数据上报记录';
|
||||
}
|
||||
return '您可以在预处理数据-告警数据页面查看告警情况';
|
||||
|
@ -366,7 +369,7 @@ const showContent = computed(() => {
|
|||
return showExtra.value;
|
||||
}
|
||||
|
||||
return showMetrics.value || config.value.length > 0;
|
||||
return (showMetrics.value || config.value.length > 0) && props.id;
|
||||
});
|
||||
|
||||
const showMetrics = computed(() => {
|
||||
|
@ -384,7 +387,8 @@ const showMetrics = computed(() => {
|
|||
const showExtra = computed(() => {
|
||||
return (
|
||||
['int', 'long', 'float', 'double'].includes(props.type as any) &&
|
||||
props.metadataType === 'properties' && showThreshold
|
||||
props.metadataType === 'properties' &&
|
||||
showThreshold
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -485,8 +489,8 @@ const getConfig = async () => {
|
|||
} else if (showMetrics.value) {
|
||||
activeKey.value = ['metrics'];
|
||||
}
|
||||
if(showExtra.value){
|
||||
activeKey.value = ['extra']
|
||||
if (showExtra.value) {
|
||||
activeKey.value = ['extra'];
|
||||
}
|
||||
if (resp.result.length && !configValue.value) {
|
||||
resp.result.forEach((a) => {
|
||||
|
|
|
@ -3844,6 +3844,10 @@ export default [
|
|||
permission: 'role',
|
||||
actions: ['query'],
|
||||
},
|
||||
{
|
||||
permission: "role-group",
|
||||
actions: ["query"]
|
||||
}
|
||||
],
|
||||
buttons: [
|
||||
{
|
||||
|
@ -3912,7 +3916,7 @@ export default [
|
|||
permissions: [
|
||||
{
|
||||
permission: 'role-group',
|
||||
actions: ['query','save']
|
||||
actions: ['save']
|
||||
}
|
||||
],
|
||||
},
|
||||
|
@ -3922,7 +3926,7 @@ export default [
|
|||
permissions: [
|
||||
{
|
||||
permission: 'role-group',
|
||||
actions: ['query','delete']
|
||||
actions: ['delete']
|
||||
}
|
||||
],
|
||||
},
|
||||
|
|
|
@ -217,7 +217,8 @@
|
|||
</template>
|
||||
<template #cardState="slotProps">
|
||||
<BadgeStatus
|
||||
:status="slotProps.cardState?.value"
|
||||
v-if="slotProps.cardState?.state"
|
||||
:status="slotProps.cardState?.state"
|
||||
:text="slotProps.cardState?.text"
|
||||
:statusNames="{
|
||||
using: 'processing',
|
||||
|
@ -508,7 +509,8 @@ const columns = [
|
|||
title: '运营商状态',
|
||||
dataIndex: 'operatorState',
|
||||
key: 'operatorState',
|
||||
hidden: true,
|
||||
// hidden: true,
|
||||
hideInTable: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
|
|
|
@ -101,7 +101,8 @@ const pickerTimeChange = () => {
|
|||
const echartsOptions = computed(() => {
|
||||
const series = serverActive.value.length
|
||||
? serverActive.value.map((key) => setOptions(serverData.data, key))
|
||||
: typeDataLine
|
||||
: typeDataLine;
|
||||
|
||||
return {
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
|
|
|
@ -140,7 +140,7 @@ const getJVMEcharts = async (val: any) => {
|
|||
|
||||
const setOptions = (optionsData: any, key: string) => ({
|
||||
data: arrayReverse(optionsData[key]),
|
||||
// name: key!= 'undefined' ? key : '',
|
||||
name: key !== 'undefined' ? key : '',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
symbol: 'none',
|
||||
|
@ -158,6 +158,7 @@ const echartsOptions = computed(() => {
|
|||
const series = serverActive.value.length
|
||||
? serverActive.value.map((key) => setOptions(serverData.data, key))
|
||||
: typeDataLine
|
||||
|
||||
return {
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
format="YYYY-MM-DD HH:mm:ss"
|
||||
valueFormat="x"
|
||||
v-model:value="dateRange"
|
||||
@change="onChange"
|
||||
/>
|
||||
</j-space>
|
||||
</div>
|
||||
|
@ -144,6 +145,10 @@ const createChart = () => {
|
|||
|
||||
};
|
||||
|
||||
const onChange = ()=>{
|
||||
dimension.value = 'other'
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.chartData,
|
||||
(val) => {
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<div>开始录像</div>
|
||||
<template #overlay>
|
||||
<j-menu @click="recordStart">
|
||||
<j-menu-item key="true" v-if="_type">
|
||||
<j-menu-item key="true" v-if="_type && route.query.type !== 'onvif'">
|
||||
<span style="padding-right: 12px"
|
||||
>本地存储</span
|
||||
>
|
||||
|
@ -129,7 +129,7 @@
|
|||
</MediaTool>
|
||||
</div>
|
||||
<Preset
|
||||
v-if="data.ptzType.value === 0 || data.ptzType.value === 1"
|
||||
v-if="(data.ptzType.value === 0 || data.ptzType.value === 1) && route.query.type !== 'onvif'"
|
||||
:data="data"
|
||||
@refresh="onRefresh"
|
||||
/>
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
</j-tooltip>
|
||||
<RadioCard
|
||||
layout="horizontal"
|
||||
:options="[
|
||||
:options="deviceType !== 'onvif' ?[
|
||||
{
|
||||
label: '云端',
|
||||
value: 'cloud',
|
||||
|
@ -70,7 +70,12 @@
|
|||
logo: getImage('/local.png'),
|
||||
disabled: deviceType === 'fixed-media',
|
||||
},
|
||||
]"
|
||||
]:
|
||||
[{
|
||||
label: '云端',
|
||||
value: 'cloud',
|
||||
logo: getImage('/media/cloud.png'),
|
||||
}]"
|
||||
:checkStyle="true"
|
||||
v-model="type"
|
||||
/>
|
||||
|
@ -319,7 +324,7 @@ onMounted(() => {
|
|||
deviceType.value = _type;
|
||||
const _timeStr = dayjs(new Date());
|
||||
time.value = _timeStr;
|
||||
if (_type === 'fixed-media') {
|
||||
if (_type === 'fixed-media' || _type === 'onvif') {
|
||||
type.value = 'cloud';
|
||||
queryServiceRecords(_timeStr);
|
||||
} else {
|
||||
|
|
|
@ -128,6 +128,263 @@
|
|||
/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
|
||||
<template
|
||||
v-if="formData.provider === 'embedded-zlmedia'"
|
||||
>
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
:name="['configuration', 'rtpIp']"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入IP',
|
||||
},
|
||||
{
|
||||
validator: validateAddress,
|
||||
message:
|
||||
'请输入正确的IP地址或者域名',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<template #label>
|
||||
IP
|
||||
<j-tooltip
|
||||
title="视频设备将流推送到该IP地址下,部分设备仅支持IP地址,建议全是用IP地址"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
<j-input
|
||||
placeholder="请输入IP"
|
||||
style="width: 50%"
|
||||
v-model:value="
|
||||
formData.configuration.rtpIp
|
||||
"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12" class="item">
|
||||
<j-row :gutter="[16, 0]">
|
||||
<j-col :span="20" v-if="!checked">
|
||||
<j-form-item
|
||||
class="form-item"
|
||||
:name="['configuration', 'rtpPort']"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入RTP端口',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<template #label>
|
||||
RTP 端口
|
||||
<j-tooltip
|
||||
title="视频设备将流推送到该IP地址对应的RTP端口下,部分设备仅支持IP地址,建议全是用IP地址"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
|
||||
<j-input-number
|
||||
style="width: 100%"
|
||||
:min="1"
|
||||
:max="65535"
|
||||
:precision="0"
|
||||
placeholder="请输入RTP端口"
|
||||
v-model:value="
|
||||
formData.configuration
|
||||
.rtpPort
|
||||
"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="8" v-if="checked">
|
||||
<j-form-item
|
||||
class="form-item"
|
||||
:name="[
|
||||
'configuration',
|
||||
'dynamicRtpPortRange0',
|
||||
]"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入起始端口',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<template #label>
|
||||
RTP 端口
|
||||
<j-tooltip
|
||||
title="视频设备将流推送到该IP地址对应的RTP端口下,部分设备仅支持IP地址,建议全是用IP地址"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
<j-input-number
|
||||
style="width: 100%"
|
||||
:min="1"
|
||||
:max="
|
||||
formData.configuration
|
||||
.dynamicRtpPortRange1 ||
|
||||
65535
|
||||
"
|
||||
:precision="0"
|
||||
placeholder="起始端口"
|
||||
v-model:value="
|
||||
formData.configuration
|
||||
.dynamicRtpPortRange0
|
||||
"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<div
|
||||
class="form-item-checked"
|
||||
v-if="checked"
|
||||
>
|
||||
至
|
||||
</div>
|
||||
<j-col :span="8" v-if="checked">
|
||||
<j-form-item
|
||||
class="form-item"
|
||||
:name="[
|
||||
'configuration',
|
||||
'dynamicRtpPortRange1',
|
||||
]"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入终止端口',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<div class="form-label"></div>
|
||||
<j-input-number
|
||||
style="width: 100%"
|
||||
:min="
|
||||
formData.configuration
|
||||
.dynamicRtpPortRange0 ||
|
||||
1
|
||||
"
|
||||
:max="65535"
|
||||
:precision="0"
|
||||
placeholder="终止端口"
|
||||
v-model:value="
|
||||
formData.configuration
|
||||
.dynamicRtpPortRange1
|
||||
"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="4">
|
||||
<j-form-item
|
||||
class="form-item-checked2"
|
||||
:name="[
|
||||
'configuration',
|
||||
'dynamicRtpPort',
|
||||
]"
|
||||
>
|
||||
<div class="form-label"></div>
|
||||
<j-checkbox
|
||||
v-model:checked="
|
||||
formData.configuration
|
||||
.dynamicRtpPort
|
||||
"
|
||||
>
|
||||
动态端口
|
||||
</j-checkbox>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
class="form-item"
|
||||
:name="[
|
||||
'configuration',
|
||||
'rtmpPort',
|
||||
]"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入RTMP端口',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<template #label>
|
||||
RTMP 端口
|
||||
<j-tooltip
|
||||
title="对外分享的RTMP视频流地址对应端口"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
<j-input-number
|
||||
style="width: 100%"
|
||||
:min="1"
|
||||
:max="65535"
|
||||
:precision="0"
|
||||
placeholder="RTMP 端口"
|
||||
v-model:value="
|
||||
formData.configuration
|
||||
.rtmpPort
|
||||
"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
:name="[
|
||||
'configuration',
|
||||
'rtspPort',
|
||||
]"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入RTSP端口',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<template #label>
|
||||
RTSP 端口
|
||||
<j-tooltip
|
||||
title="对外分享的RTSP视频流地址对应端口"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
<j-input-number
|
||||
style="width: 100%"
|
||||
:min="1"
|
||||
:max="65535"
|
||||
:precision="0"
|
||||
placeholder="RTSP 端口"
|
||||
v-model:value="
|
||||
formData.configuration
|
||||
.rtspPort
|
||||
"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-col>
|
||||
</template>
|
||||
|
||||
<div v-else style="width: 100%; display: flex">
|
||||
<j-col :span="8" class="form-item">
|
||||
<j-form-item
|
||||
:name="['configuration', 'rtpIp']"
|
||||
|
@ -138,7 +395,8 @@
|
|||
},
|
||||
{
|
||||
validator: validateAddress,
|
||||
message: '请输入正确的IP地址或者域名',
|
||||
message:
|
||||
'请输入正确的IP地址或者域名',
|
||||
},
|
||||
]"
|
||||
>
|
||||
|
@ -155,7 +413,9 @@
|
|||
</template>
|
||||
<j-input
|
||||
placeholder="请输入RTP IP"
|
||||
v-model:value="formData.configuration.rtpIp"
|
||||
v-model:value="
|
||||
formData.configuration.rtpIp
|
||||
"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
|
@ -215,7 +475,9 @@
|
|||
/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<div class="form-item-checked" v-if="checked">至</div>
|
||||
<div class="form-item-checked" v-if="checked">
|
||||
至
|
||||
</div>
|
||||
<j-col :span="4" v-if="checked">
|
||||
<j-form-item
|
||||
class="form-item"
|
||||
|
@ -255,13 +517,15 @@
|
|||
<div class="form-label"></div>
|
||||
<j-checkbox
|
||||
v-model:checked="
|
||||
formData.configuration.dynamicRtpPort
|
||||
formData.configuration
|
||||
.dynamicRtpPort
|
||||
"
|
||||
>
|
||||
动态端口
|
||||
</j-checkbox>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</div>
|
||||
|
||||
<j-col :span="24">
|
||||
<j-form-item>
|
||||
|
@ -309,10 +573,7 @@ const Validator = {
|
|||
|
||||
const validateAddress = (_rule: any, value: string): Promise<any> =>
|
||||
new Promise(async (resolve, reject) => {
|
||||
if (
|
||||
testIpv4_6(value) ||
|
||||
Validator.regDomain.test(value)
|
||||
) {
|
||||
if (testIpv4_6(value) || Validator.regDomain.test(value)) {
|
||||
return resolve('');
|
||||
} else {
|
||||
return value ? reject('请输入正确的IP地址或者域名') : resolve('');
|
||||
|
@ -328,6 +589,8 @@ const formData = ref<FormDataType>({
|
|||
apiPort: '',
|
||||
rtpIp: '',
|
||||
rtpPort: '',
|
||||
rtspPort: '',
|
||||
rtmpPort: '',
|
||||
dynamicRtpPort: false,
|
||||
// dynamicRtpPortRange: [],
|
||||
dynamicRtpPortRange0: '',
|
||||
|
@ -413,5 +676,12 @@ watch(
|
|||
height: 30px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
.item{
|
||||
padding-top: 6px;
|
||||
border: 1px solid #d1d1d1;
|
||||
background-color: #e0e0e007;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -4,6 +4,8 @@ export interface Configuration {
|
|||
apiPort: number | string;
|
||||
rtpIp: string | string;
|
||||
rtpPort: number | string;
|
||||
rtspPort: number | string;
|
||||
rtmpPort: number | string;
|
||||
dynamicRtpPort: boolean;
|
||||
dynamicRtpPortRange?: array<any>;
|
||||
dynamicRtpPortRange0?: number | string | undefined;
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<template>
|
||||
<div>
|
||||
<j-modal
|
||||
v-model:visible="_vis"
|
||||
visible
|
||||
title="同步用户"
|
||||
:footer="null"
|
||||
@cancel="_vis = false"
|
||||
@cancel="$emit('cancel')"
|
||||
width="80%"
|
||||
>
|
||||
<j-row :gutter="10" class="model-body">
|
||||
|
@ -131,34 +131,17 @@ import { onlyMessage } from '@/utils/comm';
|
|||
const useForm = Form.useForm;
|
||||
|
||||
type Emits = {
|
||||
(e: 'update:visible', data: boolean): void;
|
||||
(e: 'cancel'): void;
|
||||
};
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
data: {
|
||||
type: Object as PropType<Partial<Record<string, any>>>,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
const _vis = computed({
|
||||
get: () => props.visible,
|
||||
set: (val) => emit('update:visible', val),
|
||||
});
|
||||
|
||||
watch(
|
||||
() => _vis.value,
|
||||
(val) => {
|
||||
if (val) {
|
||||
getDepartment();
|
||||
} else {
|
||||
dataSource.value = [];
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// 左侧部门
|
||||
const deptTreeData = ref([]);
|
||||
const deptName = ref('');
|
||||
|
@ -182,16 +165,11 @@ const getDepartment = async () => {
|
|||
}
|
||||
|
||||
deptTreeData.value = _result;
|
||||
if(_result.length){
|
||||
deptId.value = _result[0]?.id;
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => deptName.value,
|
||||
(val: any) => {
|
||||
if (!val) getDepartment();
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* 部门点击
|
||||
*/
|
||||
|
@ -336,7 +314,7 @@ const getAllUsers = async (terms?: any) => {
|
|||
};
|
||||
const { result } = await configApi.getPlatformUsers(params);
|
||||
allUserList.value = result.map((m: any) => ({
|
||||
label: m.name,
|
||||
label: m.name + ` (${m.username})`,
|
||||
value: m.id,
|
||||
...m,
|
||||
}));
|
||||
|
@ -357,7 +335,7 @@ const getTableData = (terms?: any) => {
|
|||
(deptUsers || []).forEach((deptUser: any) => {
|
||||
// 未绑定的用户
|
||||
let unBindUser = unBindUsers.find(
|
||||
(f: any) => f.name === deptUser?.name,
|
||||
(f: any) => f.id === deptUser?.id,
|
||||
);
|
||||
// 绑定的用户
|
||||
const bindUser = bindUsers.find(
|
||||
|
@ -399,14 +377,6 @@ const handleTableChange = (pagination: any) => {
|
|||
pageSize.value = pagination.pageSize;
|
||||
};
|
||||
|
||||
watch(
|
||||
() => deptId.value,
|
||||
() => {
|
||||
getTableData();
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
/**
|
||||
* 绑定用户
|
||||
*/
|
||||
|
@ -487,6 +457,23 @@ const handleCancel = () => {
|
|||
bindVis.value = false;
|
||||
resetFields();
|
||||
};
|
||||
|
||||
watch(
|
||||
() => deptId.value,
|
||||
() => {
|
||||
getTableData();
|
||||
},
|
||||
// { immediate: true },
|
||||
);
|
||||
watch(
|
||||
() => deptName.value,
|
||||
(val: any) => {
|
||||
if (!val) getDepartment();
|
||||
},
|
||||
);
|
||||
onMounted(() => {
|
||||
getDepartment();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -194,7 +194,7 @@
|
|||
|
||||
<Debug v-model:visible="debugVis" :data="currentConfig" />
|
||||
<Log v-if="logVis" :data="currentConfig" @cancel="logVis = false" />
|
||||
<SyncUser v-model:visible="syncVis" :data="currentConfig" />
|
||||
<SyncUser v-if="syncVis" :data="currentConfig" @cancel="syncVis = false"/>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -142,62 +142,6 @@ const _vis = computed({
|
|||
* 获取通知模板
|
||||
*/
|
||||
const configList = ref<BindConfig[]>([]);
|
||||
const getConfigList = async () => {
|
||||
const params = {
|
||||
terms: [
|
||||
{ column: 'type', value: props.data.type },
|
||||
{ column: 'provider', value: props.data.provider },
|
||||
],
|
||||
};
|
||||
const { result } = await TemplateApi.getConfig(params);
|
||||
configList.value = result;
|
||||
// 设置默认配置
|
||||
if (configList.value.length) formData.value.configId = props.data.configId;
|
||||
};
|
||||
|
||||
watch(
|
||||
() => _vis.value,
|
||||
(val) => {
|
||||
if (val) {
|
||||
getConfigList();
|
||||
getTemplateDetail();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* 获取模板详情
|
||||
*/
|
||||
const getTemplateDetail = async () => {
|
||||
const { result } = await TemplateApi.getTemplateDetail(props.data.id);
|
||||
formData.value.templateDetailTable = result.variableDefinitions.map(
|
||||
(m: any) => ({
|
||||
...m,
|
||||
type: m.expands?.businessType ? m.expands.businessType : m.type,
|
||||
value: undefined,
|
||||
// 电话字段校验
|
||||
otherRules:
|
||||
m.id === 'calledNumber' || m.id === 'phoneNumber'
|
||||
? [
|
||||
{
|
||||
max: 64,
|
||||
message: '最多可输入64个字符',
|
||||
trigger: 'change',
|
||||
},
|
||||
{
|
||||
trigger: 'change',
|
||||
validator(_rule: Rule, value: string) {
|
||||
if (!value) return Promise.resolve();
|
||||
if (!phoneRegEx(value))
|
||||
return Promise.reject('请输入有效号码');
|
||||
return Promise.resolve();
|
||||
},
|
||||
},
|
||||
]
|
||||
: [],
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
|
@ -236,7 +180,74 @@ const formData = ref<{
|
|||
*/
|
||||
const formRef = ref();
|
||||
const btnLoading = ref(false);
|
||||
|
||||
const getConfigList = async () => {
|
||||
const params = {
|
||||
terms: [
|
||||
{ column: 'type', value: props.data.type },
|
||||
{ column: 'provider', value: props.data.provider },
|
||||
],
|
||||
};
|
||||
const { result } = await TemplateApi.getConfig(params);
|
||||
configList.value = result;
|
||||
// 设置默认配置
|
||||
if (configList.value.length) formData.value.configId = props.data.configId;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取模板详情
|
||||
*/
|
||||
const getTemplateDetail = async () => {
|
||||
const { result } = await TemplateApi.getTemplateDetail(props.data.id);
|
||||
formData.value.templateDetailTable = result.variableDefinitions.map(
|
||||
(m: any) => ({
|
||||
...m,
|
||||
type: m.expands?.businessType ? m.expands.businessType : m.type,
|
||||
value: undefined,
|
||||
// 电话字段校验
|
||||
otherRules:
|
||||
m.id === 'calledNumber' || m.id === 'phoneNumber'
|
||||
? [
|
||||
{
|
||||
max: 64,
|
||||
message: '最多可输入64个字符',
|
||||
trigger: 'change',
|
||||
},
|
||||
{
|
||||
trigger: 'change',
|
||||
validator(_rule: Rule, value: string) {
|
||||
if (!value) return Promise.resolve();
|
||||
if (!phoneRegEx(value))
|
||||
return Promise.reject('请输入有效号码');
|
||||
return Promise.resolve();
|
||||
},
|
||||
},
|
||||
]
|
||||
: [],
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleOk = () => {
|
||||
console.log(formData.value.templateDetailTable)
|
||||
const filterData = formData.value.templateDetailTable.filter((item: any) =>
|
||||
['user', 'org', 'tag', 'userIdList', 'departmentIdList'].includes(
|
||||
item.id,
|
||||
),
|
||||
);
|
||||
const pass = filterData.length
|
||||
? filterData.some((i: any) => {
|
||||
return i.value;
|
||||
})
|
||||
: true;
|
||||
if (!pass && props.data.type === 'dingTalk') {
|
||||
onlyMessage('收信人,收信人部门至少填写一个', 'warning');
|
||||
return;
|
||||
}
|
||||
if (!pass && props.data.type === 'weixin') {
|
||||
onlyMessage('收信人,收信人部门,收信人标签至少填写一个', 'warning');
|
||||
return;
|
||||
}
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(async () => {
|
||||
|
@ -267,6 +278,16 @@ const handleCancel = () => {
|
|||
formRef.value.resetFields();
|
||||
formData.value.templateDetailTable = [];
|
||||
};
|
||||
|
||||
watch(
|
||||
() => _vis.value,
|
||||
(val) => {
|
||||
if (val) {
|
||||
getConfigList();
|
||||
getTemplateDetail();
|
||||
}
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -14,12 +14,13 @@ import templateApi from '@/api/notice/template';
|
|||
|
||||
type Emits = {
|
||||
(e: 'update:toUser', data: string | undefined): void;
|
||||
(e: 'update:canSave', data: boolean): void;
|
||||
};
|
||||
type Props = {
|
||||
toUser: string | undefined;
|
||||
type: string | undefined;
|
||||
configId: string | undefined;
|
||||
}
|
||||
};
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
|
@ -37,14 +38,19 @@ const typeObj = {
|
|||
const options = ref([]);
|
||||
const queryData = async () => {
|
||||
if (!props.configId) return;
|
||||
const { result } = await templateApi.getUser(
|
||||
typeObj[props.type],
|
||||
props.configId,
|
||||
);
|
||||
options.value = result.map((item: any) => ({
|
||||
const res: any = await templateApi
|
||||
.getUser(typeObj[props.type], props.configId)
|
||||
.catch(() => {
|
||||
emit('update:canSave', false);
|
||||
});
|
||||
|
||||
if (res.status === 200) {
|
||||
options.value = res?.result.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}));
|
||||
emit('update:canSave', true);
|
||||
}
|
||||
};
|
||||
queryData();
|
||||
|
||||
|
|
|
@ -24,10 +24,10 @@ const AliyunVoice = () => {
|
|||
<div> 阿里云语音对每一条语音验证码/语音通知分配的唯一ID标识</div>
|
||||
<h2> 4、被叫号码</h2>
|
||||
<div> 当前仅支持国内手机号,此处若不填,则在模板调试和配置告警通知时手动填写。</div>
|
||||
<div>若您使用的语音通知文件为公共模式外呼,则该参数值不填。</div>
|
||||
<div>若您使用的语音通知文件为专属模式外呼,则必须传入已购买的号码,仅支持一个号码。</div>
|
||||
<h2> 5、被叫显号</h2>
|
||||
<div> 用户呼叫号码显示,必须是在阿里云购买的号码。</div>
|
||||
<div>若您使用的语音通知文件为公共模式外呼,则该参数值不填。</div>
|
||||
<div>若您使用的语音通知文件为专属模式外呼,则必须传入已购买的号码,仅支持一个号码。</div>
|
||||
<h2> 6、播放次数</h2>
|
||||
<div> 最多可播放3次</div>
|
||||
<h2> 7、模板内容</h2>
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
</j-form-item>
|
||||
<j-row :gutter="10">
|
||||
<j-col :span="12">
|
||||
<j-form-item label="收信部门">
|
||||
<j-form-item label="收信人部门">
|
||||
<ToOrg
|
||||
v-model:toParty="
|
||||
formData.template
|
||||
|
@ -137,6 +137,7 @@
|
|||
v-model:toUser="
|
||||
formData.template.userIdList
|
||||
"
|
||||
v-model:canSave="canSave"
|
||||
:type="formData.type"
|
||||
:config-id="formData.configId"
|
||||
/>
|
||||
|
@ -294,7 +295,7 @@
|
|||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item label="收信部门">
|
||||
<j-form-item label="收信人部门">
|
||||
<ToOrg
|
||||
v-model:toParty="
|
||||
formData.template.toParty
|
||||
|
@ -308,7 +309,7 @@
|
|||
<j-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
标签推送
|
||||
收信人标签
|
||||
<j-tooltip
|
||||
title="本企业微信的标签ID列表,最多支持100个,如果不填写该字段,将在使用此模板发送通知时进行指定"
|
||||
>
|
||||
|
@ -722,6 +723,7 @@
|
|||
</j-form-item>
|
||||
<j-form-item>
|
||||
<j-button
|
||||
:disabled="!canSave"
|
||||
type="primary"
|
||||
@click="handleSubmit"
|
||||
:loading="btnLoading"
|
||||
|
@ -771,7 +773,7 @@ const router = useRouter();
|
|||
const route = useRoute();
|
||||
const useForm = Form.useForm;
|
||||
const formRef = ref()
|
||||
|
||||
const canSave = ref(true)
|
||||
const flag = ref<boolean>(false)
|
||||
// 消息类型
|
||||
const msgType = ref([
|
||||
|
@ -1184,8 +1186,13 @@ const templateList = ref();
|
|||
const getTemplateList = async () => {
|
||||
if (!formData.value.configId) return
|
||||
const id = formData.value.configId || undefined;
|
||||
const { result } = await templateApi.getAliTemplate(id);
|
||||
templateList.value = result;
|
||||
const res:any = await templateApi.getAliTemplate(id).catch(()=>{
|
||||
canSave.value = false
|
||||
})
|
||||
if(res.status === 200){
|
||||
canSave.value = true
|
||||
templateList.value = res.result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
</template>
|
||||
{{ selectedKeys.some(selectKey => selectKey === item.actionId) ? '已关联' : '关联' }}
|
||||
</a-button>
|
||||
<a-button v-else-if="activeKeys.some(active => active === item.actionId)" type="link" @click.stop="onSelect(item)">
|
||||
<a-button v-else-if="activeKeys.some(active => active === item.actionId || active === -1)" type="link" @click.stop="onSelect(item)">
|
||||
<template #icon>
|
||||
<AIcon type="icon-jiebang"/>
|
||||
</template>
|
||||
|
@ -254,8 +254,8 @@ const onBind = (record) => {
|
|||
}
|
||||
|
||||
const onSelect = (record) => {
|
||||
const selected = props.activeKeys.some(item => item === record.actionId)
|
||||
emit('select', record.actionId, !selected)
|
||||
const id = props.activeKeys.find(active => active === record.actionId || active === -1)
|
||||
emit('select', id, false)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -188,6 +188,10 @@ const props = defineProps({
|
|||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showHistory: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
maskStyle: {
|
||||
type: Object,
|
||||
default: undefined
|
||||
|
@ -221,7 +225,7 @@ const branchesGroup = computed(() => {
|
|||
const activeBranches = computed(() => {
|
||||
const { data, invalid } = handleActiveBranches(branchesGroup.value, props.activeKeys)
|
||||
|
||||
isInvalid.value = invalid
|
||||
isInvalid.value = invalid && props.showHistory
|
||||
return data
|
||||
})
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
<script setup name="SceneDrawer">
|
||||
import {useRequest} from "@/hook";
|
||||
import {queryBindScene} from "@/api/rule-engine/configuration";
|
||||
import {queryBindScene, unbindScene} from "@/api/rule-engine/configuration";
|
||||
import {handleGroupAndFilter, typeMap} from "./Save/utils";
|
||||
import BranchesTabs from './Save/BranchesTabs.vue'
|
||||
import { unBindAlarm, bindScene } from "@/api/rule-engine/configuration";
|
||||
|
@ -97,11 +97,13 @@ const handleBind = (id, selected) => {
|
|||
loading.value = false
|
||||
})
|
||||
} else {
|
||||
unBindAlarm(props.detail.id, props.id, [id]).then(res => {
|
||||
const request = id === -1 ? unbindScene(props.id, [props.detail.id]) : unBindAlarm(props.detail.id, props.id, [id])
|
||||
request.then(res => {
|
||||
activeKeys.value = activeKeys.value.filter(key => key !== id)
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
:showBranches="false"
|
||||
:showBindTags="true"
|
||||
:showRule="false"
|
||||
:showHistory="false"
|
||||
@click="handleView(slotProps)"
|
||||
>
|
||||
<div class="scene-view">
|
||||
|
@ -116,32 +117,32 @@ const {data: activeKeys, reload} = useRequest(queryBindScene, {
|
|||
defaultValue: {}
|
||||
})
|
||||
|
||||
const getActions = (
|
||||
data: Partial<Record<string, any>>,
|
||||
type: 'card' | 'table',
|
||||
): ActionsType[] => {
|
||||
if (!data) return [];
|
||||
const actions: ActionsType[] = [
|
||||
{
|
||||
key: 'action',
|
||||
text: '解绑',
|
||||
icon: 'DisconnectOutlined',
|
||||
popConfirm: {
|
||||
title: '确认解绑?',
|
||||
onConfirm: async () => {
|
||||
// const res = await unbindScene(id, [data.id], data.branchIndex);
|
||||
const res = await unbindScene(id, [data.id]);
|
||||
if (res.status === 200) {
|
||||
onlyMessage('操作成功');
|
||||
actionRef.value.reload();
|
||||
}
|
||||
return
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
return actions;
|
||||
};
|
||||
// const getActions = (
|
||||
// data: Partial<Record<string, any>>,
|
||||
// type: 'card' | 'table',
|
||||
// ): ActionsType[] => {
|
||||
// if (!data) return [];
|
||||
// const actions: ActionsType[] = [
|
||||
// {
|
||||
// key: 'action',
|
||||
// text: '解绑',
|
||||
// icon: 'DisconnectOutlined',
|
||||
// popConfirm: {
|
||||
// title: '确认解绑?',
|
||||
// onConfirm: async () => {
|
||||
// // const res = await unbindScene(id, [data.id], data.branchIndex);
|
||||
// const res = await unbindScene(id, [data.id]);
|
||||
// if (res.status === 200) {
|
||||
// onlyMessage('操作成功');
|
||||
// actionRef.value.reload();
|
||||
// }
|
||||
// return
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// ];
|
||||
// return actions;
|
||||
// };
|
||||
|
||||
const queryTable = (_terms: any) => {
|
||||
return query(_terms, id)
|
||||
|
|
|
@ -20,11 +20,11 @@
|
|||
<template #alarmTime="slotProps">{{
|
||||
dayjs(slotProps.alarmTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
}}</template>
|
||||
<template #sourceId="slotProps"
|
||||
>设备ID:<a-button
|
||||
<template #sourceName="slotProps"
|
||||
>设备名称:<a-button
|
||||
type="link"
|
||||
@click="() => gotoDevice(slotProps.sourceId)"
|
||||
>{{ slotProps.sourceId }}</a-button
|
||||
>{{ slotProps.sourceName }}</a-button
|
||||
></template
|
||||
>
|
||||
<template #action="slotProps">
|
||||
|
@ -213,8 +213,8 @@ watch(
|
|||
},
|
||||
{
|
||||
title: '告警源',
|
||||
dataIndex: 'sourceId',
|
||||
key: 'sourceId',
|
||||
dataIndex: 'sourceName',
|
||||
key: 'sourceName',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { handleLog } from '@/api/rule-engine/log';
|
||||
import { handleLog, handlePreconditioning } from '@/api/rule-engine/log';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
const props = defineProps({
|
||||
data: {
|
||||
|
@ -39,6 +39,10 @@ const props = defineProps({
|
|||
type: String,
|
||||
default: '',
|
||||
},
|
||||
goal: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
const loading = ref<boolean>(false);
|
||||
const formRef = ref();
|
||||
|
@ -66,14 +70,17 @@ const handleSave = () => {
|
|||
formRef.value
|
||||
.validate()
|
||||
.then(async () => {
|
||||
const res = await handleLog({
|
||||
const params = {
|
||||
describe: form.describe,
|
||||
type: 'user',
|
||||
state: 'normal',
|
||||
alarmRecordId: props.data?.id || '',
|
||||
alarmConfigId: props.data?.alarmConfigId || '',
|
||||
alarmTime: props?.data?.alarmTime || '',
|
||||
});
|
||||
};
|
||||
const res = props.goal
|
||||
? await handlePreconditioning(params)
|
||||
: await handleLog(params);
|
||||
if (res.status === 200) {
|
||||
onlyMessage('操作成功!');
|
||||
emit('refresh');
|
||||
|
@ -82,13 +89,13 @@ const handleSave = () => {
|
|||
}
|
||||
loading.value = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
.catch((error:any) => {
|
||||
console.log(error);
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
onMounted(() => {
|
||||
props.solveType === 'view' ? form.describe = props.handleDes : '';
|
||||
props.solveType === 'view' ? (form.describe = props.handleDes) : '';
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped></style>
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
>{{ dayjs(text).format('YYYY-MM-DD HH:mm:ss')
|
||||
}}</span
|
||||
></template>
|
||||
<template v-if="column.dataIndex === 'sourceId'">
|
||||
<template v-if="column.dataIndex === 'sourceName'">
|
||||
<Ellipsis>
|
||||
设备ID:
|
||||
设备名称:
|
||||
<span class="deviceId" @click="() => gotoDevice(text)">{{
|
||||
text
|
||||
}}</span></Ellipsis
|
||||
|
@ -49,7 +49,7 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { queryLogList } from '@/api/rule-engine/log';
|
||||
import { queryLogList ,queryPreconditioningLogList } from '@/api/rule-engine/log';
|
||||
import dayjs from 'dayjs';
|
||||
import { useMenuStore } from 'store/menu';
|
||||
import LogDetail from './LogDetail.vue';
|
||||
|
@ -62,6 +62,10 @@ const props = defineProps({
|
|||
type: String,
|
||||
default: '',
|
||||
},
|
||||
goal:{
|
||||
type:String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
const menuStory = useMenuStore();
|
||||
const exceed = ref();
|
||||
|
@ -81,8 +85,8 @@ const columns = [
|
|||
},
|
||||
{
|
||||
title: '告警源',
|
||||
dataIndex: 'sourceId',
|
||||
key: 'sourceId',
|
||||
dataIndex: 'sourceName',
|
||||
key: 'sourceName',
|
||||
},
|
||||
{
|
||||
title: '告警原因',
|
||||
|
@ -97,7 +101,7 @@ const columns = [
|
|||
}
|
||||
];
|
||||
const queryData = async () => {
|
||||
const res = await queryLogList(props.configId, {
|
||||
const params = {
|
||||
pageIndex: 0,
|
||||
pageSize: 51,
|
||||
terms: [
|
||||
|
@ -114,7 +118,8 @@ const queryData = async () => {
|
|||
order: 'desc',
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
const res = props.goal ? await queryPreconditioningLogList(props.configId,params) : await queryLogList(props.configId, params);
|
||||
if (res.success) {
|
||||
if (res.result.data?.length > 50) {
|
||||
exceed.value = true;
|
||||
|
|
|
@ -7,7 +7,7 @@ import { storeToRefs } from 'pinia';
|
|||
import { useSceneStore } from '@/store/scene'
|
||||
import { Form } from 'jetlinks-ui-components'
|
||||
import { queryProductList } from '@/api/device/product'
|
||||
import {query as deviceQuery, detail as deviceDetailQuery} from '@/api/device/instance'
|
||||
import {query as deviceQuery, detail as deviceDetailQuery, queryNoPagingPost} from '@/api/device/instance'
|
||||
import { getTreeData_api } from '@/api/system/department'
|
||||
import {queryDetailListNoPaging} from "@/api/device/firmware";
|
||||
|
||||
|
@ -36,24 +36,29 @@ const check = async (): Promise<boolean> => {
|
|||
|
||||
// 判断设备是否删除
|
||||
if (deviceTrigger.selector === 'fixed') { // 设备
|
||||
const deviceResp = await queryDetailListNoPaging({
|
||||
terms: [{ column: 'id', termType: 'in', value: selectorValues?.toString() }],
|
||||
context: {
|
||||
"includeTags": false,
|
||||
"includeBind": false,
|
||||
"includeRelations": false,
|
||||
"includeFirmwareInfos": false
|
||||
}
|
||||
// const deviceResp = await queryDetailListNoPaging({
|
||||
// terms: [{ column: 'id', termType: 'in', value: selectorValues?.toString() }],
|
||||
// context: {
|
||||
// "includeTags": false,
|
||||
// "includeBind": false,
|
||||
// "includeRelations": false,
|
||||
// "includeFirmwareInfos": false
|
||||
// }
|
||||
// })
|
||||
const deviceResp = await queryNoPagingPost(
|
||||
{
|
||||
terms: [{ terms: [{ column: 'id', termType: 'in', value: selectorValues?.toString() }]}],
|
||||
})
|
||||
|
||||
if (deviceResp.success && deviceResp.result.length !== (selectorValues!.length)) {
|
||||
data.value.trigger!.device!.selectorValues = undefined
|
||||
return false
|
||||
}
|
||||
|
||||
if (selectorValues!.length === 1) {
|
||||
// const deviceDetailResp = await deviceDetailQuery(selectorValues![0])
|
||||
// const deviceDetail = deviceDetailResp?.result
|
||||
const deviceDetail = deviceResp.result[0]
|
||||
const deviceDetailResp = await deviceDetailQuery(selectorValues![0])
|
||||
const deviceDetail = deviceDetailResp?.result
|
||||
// const deviceDetail = deviceResp.result[0]
|
||||
metadata = JSON.parse(deviceDetail?.metadata || '{}') // 只选中一个设备,以设备物模型为准
|
||||
}
|
||||
} else if (deviceTrigger.selector === 'org') { // 组织
|
||||
|
|
|
@ -14,7 +14,7 @@ import { EventEmitter, EventSubscribeKeys, getParams } from '@/views/rule-engine
|
|||
import { getOption } from '@/views/rule-engine/Scene/Save/components/DropdownButton/util'
|
||||
import { getBuildInData, getNotifyVariablesUser } from './util'
|
||||
import { defineExpose } from 'vue'
|
||||
import {queryDetailListNoPaging} from "@/api/device/firmware";
|
||||
import {detail as getDeviceDetail, queryNoPagingPost} from "@/api/device/instance";
|
||||
|
||||
|
||||
const sceneStore = useSceneStore();
|
||||
|
@ -62,22 +62,17 @@ const checkDeviceDelete = async () => {
|
|||
let hasDevice = false
|
||||
if (item!.selectorValues) {
|
||||
const deviceList = item!.selectorValues?.map(item => item.value) || []
|
||||
const deviceResp = await queryDetailListNoPaging(
|
||||
const deviceResp = await queryNoPagingPost(
|
||||
{
|
||||
terms: [{ terms: [{ column: 'id', termType: 'in', value: deviceList.toString() }]}],
|
||||
context: {
|
||||
"includeTags": false,
|
||||
"includeBind": false,
|
||||
"includeRelations": false,
|
||||
"includeFirmwareInfos": false
|
||||
}
|
||||
})
|
||||
|
||||
hasDevice = deviceResp.success && deviceResp.result.length === (item!.selectorValues?.length || 0)
|
||||
|
||||
if (item!.selectorValues!.length === 1 && hasDevice) {
|
||||
const deviceDetail = deviceResp.result?.[0]
|
||||
// const deviceDetailResp = await getDeviceDetail(deviceList[0])
|
||||
const deviceDetailResp = await getDeviceDetail(deviceList[0])
|
||||
// const deviceDetail = deviceResp.result?.[0]
|
||||
const deviceDetail = deviceDetailResp.result
|
||||
metadata = JSON.parse(deviceDetail?.metadata || productDetail?.metadata || '{}') // 只选中一个设备,以设备物模型为准
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,6 +167,18 @@ const queryOrgList = async (id: string) => {
|
|||
}
|
||||
};
|
||||
|
||||
const queryTagList = async (id:string) =>{
|
||||
if (! props.notifierId) return '';
|
||||
const resp = await TemplateApi.getTags(
|
||||
props.notifierId,
|
||||
);
|
||||
if (resp.status === 200) {
|
||||
return resp.result?.find((item: any) => item.id === id)?.name;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
const getOptions = async (dt: any) => {
|
||||
const obj = {};
|
||||
// 钉钉,微信
|
||||
|
@ -177,6 +189,9 @@ const getOptions = async (dt: any) => {
|
|||
if (dt?.template?.toUser) {
|
||||
obj['sendTo'] = await queryUserList(dt?.template?.toUser);
|
||||
}
|
||||
if (dt?.template?.toTag) {
|
||||
obj['tagName'] = await queryTagList(dt?.template?.toTag);
|
||||
}
|
||||
}
|
||||
if (props.notifyType === 'dingTalk') {
|
||||
if (dt?.template?.departmentIdList) {
|
||||
|
@ -190,10 +205,11 @@ const getOptions = async (dt: any) => {
|
|||
};
|
||||
|
||||
const handleClick = async (dt: any) => {
|
||||
console.log(dt,'dt')
|
||||
if (_selectedRowKeys.value.includes(dt.id)) {
|
||||
_selectedRowKeys.value = [];
|
||||
emit('update:value', undefined);
|
||||
emit('change', { templateName: undefined, orgName: undefined, sendTo: undefined });
|
||||
emit('change', { templateName: undefined, orgName: undefined, sendTo: undefined ,tagName: undefined });
|
||||
emit('update:detail', undefined);
|
||||
} else {
|
||||
const obj = await getOptions(dt)
|
||||
|
|
|
@ -23,7 +23,7 @@ import notice from '@/api/notice/config';
|
|||
|
||||
const iconMap = new Map();
|
||||
iconMap.set('dingTalk', getImage('/notice/dingtalk.png'));
|
||||
iconMap.set('weixin', getImage('/notice/wechat.png'));
|
||||
iconMap.set('weixin', getImage('/notice/weixin-corp.png'));
|
||||
iconMap.set('email', getImage('/notice/email.png'));
|
||||
iconMap.set('voice', getImage('/notice/voice.png'));
|
||||
iconMap.set('sms', getImage('/notice/sms.png'));
|
||||
|
|
|
@ -10,7 +10,12 @@
|
|||
:label="item?.name"
|
||||
v-for="(item, index) in variableDefinitions"
|
||||
:key="item.id"
|
||||
:required="!['file', 'user', 'org', 'tag'].includes(getType(item)) ? true : false"
|
||||
:required="
|
||||
!['file', 'user', 'org', 'tag'].includes(getType(item)) ||
|
||||
item.id === 'calledNumber'
|
||||
? true
|
||||
: false
|
||||
"
|
||||
:rules="[
|
||||
{
|
||||
validator: (_rule, value) => checkValue(_rule, value, item),
|
||||
|
@ -48,7 +53,10 @@
|
|||
v-else
|
||||
:item="item"
|
||||
v-model:value="modelRef[item.id]"
|
||||
@change="(val, _options) => onChange(val, 'build-in', index, _options)"
|
||||
@change="
|
||||
(val, _options) =>
|
||||
onChange(val, 'build-in', index, _options)
|
||||
"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
|
@ -83,8 +91,8 @@ const props = defineProps({
|
|||
},
|
||||
options: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:value', 'change']);
|
||||
|
@ -92,15 +100,23 @@ const emit = defineEmits(['update:value', 'change']);
|
|||
const formRef = ref();
|
||||
|
||||
const modelRef = reactive({});
|
||||
const otherColumns = ref<(string | undefined)[]>(props.options?.otherColumns || [])
|
||||
const otherColumns = ref<(string | undefined)[]>(
|
||||
props.options?.otherColumns || [],
|
||||
);
|
||||
|
||||
watchEffect(() => {
|
||||
Object.assign(modelRef, props?.value);
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
if(props?.template?.template?.sendTo && Array.isArray(props?.template?.template?.sendTo) && props?.template?.template?.sendTo?.length) {
|
||||
emit('change', { sendTo: props?.template?.template?.sendTo?.join(' ') });
|
||||
if (
|
||||
props?.template?.template?.sendTo &&
|
||||
Array.isArray(props?.template?.template?.sendTo) &&
|
||||
props?.template?.template?.sendTo?.length
|
||||
) {
|
||||
emit('change', {
|
||||
sendTo: props?.template?.template?.sendTo?.join(' '),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -109,10 +125,15 @@ const getType = (item: any) => {
|
|||
};
|
||||
|
||||
const checkValue = (_rule: any, value: any, item: any) => {
|
||||
if(!value){
|
||||
if (!value) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const type = item.expands?.businessType || item?.type;
|
||||
if (
|
||||
['user', 'org', 'tag', 'userIdList', 'departmentIdList'].includes(type)
|
||||
) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (type === 'file') {
|
||||
return Promise.resolve();
|
||||
} else if (type === 'link') {
|
||||
|
@ -142,9 +163,9 @@ const checkValue = (_rule: any, value: any, item: any) => {
|
|||
}
|
||||
}
|
||||
} else if (value?.source === 'fixed' && !value?.value) {
|
||||
let tip = '请输入' + item.name
|
||||
let tip = '请输入' + item.name;
|
||||
if (props.notify.notifyType === 'email') {
|
||||
tip = '请输入收件人'
|
||||
tip = '请输入收件人';
|
||||
}
|
||||
return Promise.reject(new Error(tip));
|
||||
} else if (
|
||||
|
@ -181,7 +202,8 @@ const checkValue = (_rule: any, value: any, item: any) => {
|
|||
if (
|
||||
props.notify.notifyType &&
|
||||
['sms', 'voice'].includes(props?.notify?.notifyType) &&
|
||||
value?.source !== 'relation' && value?.value
|
||||
value?.source !== 'relation' &&
|
||||
value?.value
|
||||
) {
|
||||
const reg = /^[1][3-9]\d{9}$/;
|
||||
if (!reg.test(value?.value)) {
|
||||
|
@ -196,9 +218,9 @@ const checkValue = (_rule: any, value: any, item: any) => {
|
|||
|
||||
const onChange = (val: any, type: any, index: number, options?: string) => {
|
||||
if (type === 'build-in') {
|
||||
otherColumns.value[index] = options
|
||||
otherColumns.value[index] = options;
|
||||
} else {
|
||||
otherColumns.value[index] = undefined
|
||||
otherColumns.value[index] = undefined;
|
||||
}
|
||||
|
||||
if (type === 'org') {
|
||||
|
@ -214,18 +236,52 @@ const onChange = (val: any, type: any, index: number, options?: string) => {
|
|||
|
||||
const onSave = () =>
|
||||
new Promise((resolve, reject) => {
|
||||
const pass = props.variableDefinitions.filter(item => ['user', 'org', 'tag'].includes(getType(item))).some(item => {
|
||||
return modelRef[item.id]
|
||||
})
|
||||
if(!pass && props.notify.notifyType === 'weixin') {
|
||||
onlyMessage('收信人,收信人部门,收信人标签至少填写一个', 'warning')
|
||||
return reject(false)
|
||||
const filterData = props.variableDefinitions.filter((item) =>
|
||||
['user', 'org', 'tag', 'userIdList', 'departmentIdList'].includes(
|
||||
getType(item),
|
||||
),
|
||||
);
|
||||
const pass = filterData.length
|
||||
? filterData.some((item) => {
|
||||
|
||||
if (
|
||||
item.id === 'toUser' &&
|
||||
modelRef[item.id]?.source === 'relation'
|
||||
) {
|
||||
|
||||
return (
|
||||
modelRef[item.id].relation?.objectId ||
|
||||
modelRef[item.id].relation?.related
|
||||
);
|
||||
} else if (item.id === 'userIdList') {
|
||||
return (
|
||||
modelRef[item.id]?.value ||
|
||||
modelRef[item.id]?.relation?.objectId
|
||||
);
|
||||
} else {
|
||||
return modelRef[item.id]?.value;
|
||||
}
|
||||
formRef.value?.validate().then((_data: any) => {
|
||||
resolve(_data);
|
||||
}).catch(() => {
|
||||
reject(false)
|
||||
})
|
||||
: true;
|
||||
if (!pass && props.notify.notifyType === 'weixin') {
|
||||
onlyMessage(
|
||||
'收信人,收信人部门,收信人标签至少填写一个',
|
||||
'warning',
|
||||
);
|
||||
return reject(false);
|
||||
}
|
||||
if (!pass && props.notify.notifyType === 'dingTalk') {
|
||||
onlyMessage('收信人,收信人部门至少填写一个', 'warning');
|
||||
return reject(false);
|
||||
}
|
||||
formRef.value
|
||||
?.validate()
|
||||
.then((_data: any) => {
|
||||
resolve(_data);
|
||||
})
|
||||
.catch(() => {
|
||||
reject(false);
|
||||
});
|
||||
});
|
||||
|
||||
defineExpose({ onSave });
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
placeholder="请选择组织"
|
||||
:tree-data="departmentTree"
|
||||
@change="onChange"
|
||||
allowClear
|
||||
:fieldNames="{
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
v-model:value="keys"
|
||||
placeholder="请选择标签"
|
||||
:options="tagsList"
|
||||
allowClear
|
||||
@change="onChange"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||
:value="relationData"
|
||||
showSearch
|
||||
allowClear
|
||||
treeNodeFilterProp="title"
|
||||
>
|
||||
<template #title="{ key, username, title }">
|
||||
|
@ -72,6 +73,7 @@
|
|||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||
:value="relationData"
|
||||
showSearch
|
||||
allowClear
|
||||
treeNodeFilterProp="title"
|
||||
>
|
||||
<template #title="{ key, username, title }">
|
||||
|
@ -97,6 +99,7 @@
|
|||
placeholder="请选择收信人"
|
||||
:value="value?.value"
|
||||
showSearch
|
||||
allowClear
|
||||
@change="
|
||||
(val, option) =>
|
||||
onChange(
|
||||
|
@ -219,6 +222,7 @@ const treeData = ref<any[]>([
|
|||
const mySource = ref<string>('relation');
|
||||
const treeDataMap = new Map()
|
||||
|
||||
|
||||
const getRelationUsers = async (notifyType: string, notifierId: string) => {
|
||||
let resp = undefined;
|
||||
if (notifyType === 'dingTalk') {
|
||||
|
@ -294,6 +298,7 @@ const sourceChange = (v: any) => {
|
|||
emit('update:value', {
|
||||
source: v,
|
||||
});
|
||||
emit('change',undefined)
|
||||
};
|
||||
|
||||
const getObj = (
|
||||
|
@ -375,7 +380,6 @@ const onChange = (
|
|||
const _isRelation = item?.isRelation
|
||||
_values = getObj(_source, _value, _isRelation);
|
||||
}
|
||||
|
||||
emit('update:value', _values);
|
||||
emit('change', _names.filter((item) => !!item).join(','));
|
||||
};
|
||||
|
|
|
@ -100,10 +100,10 @@
|
|||
<script setup lang="ts">
|
||||
import { queryAlarmPage } from '@/api/rule-engine/scene';
|
||||
import AlarmModal from "./AlarmModal.vue";
|
||||
import {unBindAlarm} from "@/api/rule-engine/configuration";
|
||||
import {queryBindScene, unBindAlarm, unbindScene} from "@/api/rule-engine/configuration";
|
||||
import {onlyMessage} from "@/utils/comm";
|
||||
import { EventEmitter } from '@/views/rule-engine/Scene/Save/util'
|
||||
import {useAlarmLevel} from "@/hook";
|
||||
import {useAlarmLevel, useRequest} from "@/hook";
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
|
@ -131,6 +131,18 @@ const visible = ref(false)
|
|||
const tableRef = ref()
|
||||
const { levelMap } = useAlarmLevel();
|
||||
|
||||
const { data: activeKeys } = useRequest<any, Record<string, any>>(queryBindScene, {
|
||||
defaultParams: { terms: [{ column: 'ruleId', value: props.id}]},
|
||||
onSuccess(res) {
|
||||
const _result = res.result.data || []
|
||||
return _result.reduce((prev: Record<string, any>, next: { branchIndex: string, ruleId: string }) => {
|
||||
prev[next.ruleId] = next.branchIndex
|
||||
return prev
|
||||
}, {})
|
||||
},
|
||||
defaultValue: []
|
||||
})
|
||||
|
||||
const map = {
|
||||
product: '产品',
|
||||
device: '设备',
|
||||
|
@ -193,7 +205,8 @@ const showAlarm = () => {
|
|||
}
|
||||
|
||||
const unBind = async (record: any) => {
|
||||
const res = await unBindAlarm(props.id, record.id, [props.actionId])
|
||||
const branchId = activeKeys.value![props.id]
|
||||
const res = branchId === -1 ? await unbindScene(record.id, [props.id]) : await unBindAlarm(props.id, record.id, [props.actionId || props.branchId])
|
||||
if (res.success) {
|
||||
tableRef.value.reload()
|
||||
onlyMessage('操作成功!')
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
<template>
|
||||
<div class='actions-terms'>
|
||||
<TitleComponent data='执行动作' style='font-size: 14px;' >
|
||||
<template #extra>
|
||||
<j-switch
|
||||
v-model:checked='open'
|
||||
@change='change'
|
||||
checkedChildren='开'
|
||||
unCheckedChildren='关'
|
||||
style='margin-left: 4px;'
|
||||
/>
|
||||
</template>
|
||||
</TitleComponent>
|
||||
<!-- <template v-if='open'>-->
|
||||
<div>
|
||||
|
@ -25,6 +16,16 @@
|
|||
{{ b.branchName || `条件${i+1}` }}
|
||||
</TermsTabPane>
|
||||
</template>
|
||||
<div class="filterConditionSwitch">
|
||||
<span>执行</span>
|
||||
<j-switch
|
||||
v-model:checked='b.openFilter'
|
||||
@change='(e)=>change(e,b,i)'
|
||||
checkedChildren='开'
|
||||
unCheckedChildren='关'
|
||||
style='margin-left: 4px;'
|
||||
/>
|
||||
</div>
|
||||
<template v-for='(item, index) in data.branches'>
|
||||
<template v-if="index >= b.start && index < (b.start + b.len)">
|
||||
<Branches
|
||||
|
@ -94,7 +95,6 @@ import {queryBindScene, unBindAlarmMultiple} from "@/api/rule-engine/configurati
|
|||
|
||||
const sceneStore = useSceneStore()
|
||||
const { data } = storeToRefs(sceneStore)
|
||||
const open = ref<boolean>(false)
|
||||
const columnOptions = ref<any>([])
|
||||
const group = ref<Array<{ id: string, len: number}>>([])
|
||||
const activeKey = ref('')
|
||||
|
@ -103,15 +103,42 @@ const conditionName = ref<any>()
|
|||
|
||||
provide(ContextKey, columnOptions)
|
||||
|
||||
const change = (e: boolean) => {
|
||||
group.value = []
|
||||
activeKey.value = ''
|
||||
if (!e) {
|
||||
data.value.branches!.length = 1
|
||||
data.value.branches![0].when = []
|
||||
} else {
|
||||
data.value.branches!.push(null as any)
|
||||
data.value.branches![0].when = [
|
||||
const change = (e: boolean,groupItem:any,index:number) => {
|
||||
// group.value = []
|
||||
// activeKey.value = ''
|
||||
// if (!e) {
|
||||
// data.value.branches!.length = 1
|
||||
// data.value.branches![0].when = []
|
||||
// } else {
|
||||
// data.value.branches!.push(null as any)
|
||||
// data.value.branches![0].when = [
|
||||
// {
|
||||
// terms: [
|
||||
// {
|
||||
// column: undefined,
|
||||
// value: {
|
||||
// source: 'fixed',
|
||||
// value: undefined
|
||||
// },
|
||||
// termType: undefined,
|
||||
// key: `params_${randomString()}`,
|
||||
// type: 'and',
|
||||
// },
|
||||
// ],
|
||||
// type: 'and',
|
||||
// key: `terms_${randomString()}`,
|
||||
// },
|
||||
// ]
|
||||
// }
|
||||
const start = groupItem.start
|
||||
const len = groupItem.len
|
||||
if(!e){
|
||||
data.value.branches?.splice(start + 1 , len - 1)
|
||||
data.value.branches![start].when = []
|
||||
data.value.options!.when.splice(start,len - 1)
|
||||
}else{
|
||||
data.value.branches!.splice(start + 1,0,null)
|
||||
data.value.branches![start].when = [
|
||||
{
|
||||
terms: [
|
||||
{
|
||||
|
@ -141,9 +168,10 @@ const queryColumn = (dataModel: FormModelType) => {
|
|||
}
|
||||
|
||||
const addBranches = (len: number) => {
|
||||
const key = randomNumber()
|
||||
const branchesItem = {
|
||||
when: [],
|
||||
key: randomNumber(),
|
||||
key: key,
|
||||
shakeLimit: {
|
||||
enabled: false,
|
||||
time: 1,
|
||||
|
@ -151,12 +179,13 @@ const addBranches = (len: number) => {
|
|||
alarmFirst: false,
|
||||
},
|
||||
then: [],
|
||||
branchId: randomNumber()
|
||||
branchId: key
|
||||
}
|
||||
// const lastIndex = data.value.branches!.length - 1 || 0
|
||||
data.value.branches?.splice(len - 1, 1, branchesItem)
|
||||
data.value.options!.when.splice(len - 1, 1, {
|
||||
terms: []
|
||||
terms: [],
|
||||
key
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -378,12 +407,6 @@ watchEffect(() => {
|
|||
|
||||
watchEffect(() => {
|
||||
const branches = data.value.branches
|
||||
if (data.value.branches?.filter(item => item).length) {
|
||||
open.value = !!data.value.branches[0].when.length
|
||||
} else {
|
||||
open.value = true
|
||||
}
|
||||
|
||||
let _group = []
|
||||
let _branchesIndex = 0
|
||||
if (branches) {
|
||||
|
@ -407,8 +430,10 @@ watchEffect(() => {
|
|||
branchId: item.branchId,
|
||||
// branchName: item.branchName || whenItem?.branchName || `条件 ${_branchesIndex + 1}`,
|
||||
branchName: item.branchName || whenItem?.branchName || `条件`,
|
||||
groupIndex: _branchesIndex
|
||||
groupIndex: _branchesIndex,
|
||||
openFilter: !!item.when.length
|
||||
}
|
||||
|
||||
} else {
|
||||
_group[lastIndex].len += 1
|
||||
}
|
||||
|
@ -444,4 +469,13 @@ defineExpose({
|
|||
}
|
||||
}
|
||||
}
|
||||
.filterConditionSwitch{
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
font-weight: 800;
|
||||
font-size: 14px;
|
||||
line-height: 32px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
:hex="tagInfo.color"
|
||||
:rgba="tagInfo.color"
|
||||
:themeColor="themeColor"
|
||||
:show-opacity="false"
|
||||
@change="changeColor"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
@ -84,8 +85,8 @@ const themeColor = [
|
|||
'#FF85C0'
|
||||
]
|
||||
const submit = () => {
|
||||
loading.value = true
|
||||
form.value.validate().then(async () => {
|
||||
loading.value = true
|
||||
let id;
|
||||
if (props.editType === 'add') {
|
||||
id = randomString();
|
||||
|
@ -96,7 +97,9 @@ const submit = () => {
|
|||
id,
|
||||
name: tagInfo.name,
|
||||
};
|
||||
const res = await saveTag(submitData);
|
||||
const res = await saveTag(submitData).finally(()=>{
|
||||
loading.value = false
|
||||
});
|
||||
if (res.success) {
|
||||
colorData.value[id] = tagInfo.color;
|
||||
const saveRes = await saveTagsColor(colorData.value).catch(()=>{
|
||||
|
|
|
@ -83,6 +83,11 @@ const addTag = () => {
|
|||
editType.value = 'add';
|
||||
};
|
||||
const buildInTag = ['weekend', 'holiday', 'workday'];
|
||||
const defaultColor = new Map()
|
||||
defaultColor.set('weekend', 'rgb(149, 222, 100)')
|
||||
defaultColor.set('holiday', 'rgb(161, 180, 204)')
|
||||
defaultColor.set('workday', 'rgba(105,177,255,1')
|
||||
|
||||
const createDrag = () => {
|
||||
new Draggable(tags.value, {
|
||||
itemSelector: '.tagName',
|
||||
|
@ -111,6 +116,7 @@ const queryTagsData = async () => {
|
|||
}
|
||||
if (buildInTag.includes(i.id)) {
|
||||
disabled = true;
|
||||
color = defaultColor.get(i.id);
|
||||
}
|
||||
return {
|
||||
...i,
|
||||
|
|
|
@ -202,8 +202,9 @@ const queryData = (first?: Boolean, searchName?: any) => {
|
|||
if (first && res.result.length) {
|
||||
selectDic(res.result[0]);
|
||||
}else if(selectedKeys.value){
|
||||
console.log(selectedKeys.value)
|
||||
selectDic(res.result.find(i=>{
|
||||
return i.id = selectedKeys.value[0]
|
||||
return i.id === selectedKeys.value[0]
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -228,10 +229,10 @@ const showEdit = (data: any) => {
|
|||
const reload = () => {
|
||||
queryData();
|
||||
};
|
||||
const saveSuccess = () => {
|
||||
const saveSuccess = (id?: string) => {
|
||||
saveShow.value = false;
|
||||
selectedKeys.value = [id] ;
|
||||
reload();
|
||||
|
||||
};
|
||||
/**
|
||||
*
|
||||
|
@ -270,7 +271,7 @@ const updateDic = (data: any) => {
|
|||
* 切换选中字典
|
||||
*/
|
||||
const selectDic = (selectKeys: any) => {
|
||||
selectedKeys.value = [selectKeys.id];
|
||||
selectedKeys.value = [selectKeys.id]
|
||||
emit('selectData', selectKeys);
|
||||
};
|
||||
/**
|
||||
|
|
|
@ -109,7 +109,7 @@ const submitData = () =>{
|
|||
const res = await addDictionary(form)
|
||||
if(res.status === 200){
|
||||
onlyMessage('保存成功!')
|
||||
emit('success')
|
||||
emit('success',form.id)
|
||||
}else{
|
||||
onlyMessage('操作失败!','error')
|
||||
}
|
||||
|
|
|
@ -215,11 +215,13 @@ const handleOk = async () => {
|
|||
_dataSorts.push(USER_CENTER_MENU_DATA);
|
||||
const res = await updateMenus(_dataSorts).catch(() => {});
|
||||
if (res?.status === 200) {
|
||||
onlyMessage('操作成功', 'success');
|
||||
location.reload();
|
||||
}
|
||||
loading.value = false;
|
||||
visible.value = false;
|
||||
onlyMessage('操作成功', 'success');
|
||||
setTimeout(() => {
|
||||
location.reload();
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
const handleCancel = () => {
|
||||
visible.value = false;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<h5>接口描述</h5>
|
||||
<div>{{ props.selectApi.description }}</div>
|
||||
</div>
|
||||
<div class="api-card" v-if="requestCard.codeText">
|
||||
<div class="api-card" v-if="requestCard.codeText !== undefined">
|
||||
<h5>请求示例</h5>
|
||||
<JsonViewer :value="requestCard.codeText" copyable />
|
||||
</div>
|
||||
|
@ -154,7 +154,9 @@ const requestCard = reactive<cardType>({
|
|||
// schema不是Java中的类的话则不进行解析,直接结束
|
||||
if (!_ref) {
|
||||
const type = schema.type || '';
|
||||
console.log(type,'type')
|
||||
requestCard.codeText = dealNoRef(type, schema);
|
||||
console.log(requestCard.codeText)
|
||||
} else {
|
||||
const schemaName = _ref?.split('/').pop();
|
||||
const type = schema.type || '';
|
||||
|
|
|
@ -66,10 +66,10 @@
|
|||
max: 64,
|
||||
message: '最多输入64个字符',
|
||||
},
|
||||
{
|
||||
validator: vailName,
|
||||
trigger: 'blur',
|
||||
},
|
||||
// {
|
||||
// validator: vailName,
|
||||
// trigger: 'blur',
|
||||
// },
|
||||
]"
|
||||
>
|
||||
<j-input
|
||||
|
@ -86,10 +86,10 @@
|
|||
required: true,
|
||||
message: '请输入区划代码',
|
||||
},
|
||||
{
|
||||
validator: vailCode,
|
||||
trigger: 'blur',
|
||||
},
|
||||
// {
|
||||
// validator: vailCode,
|
||||
// trigger: 'blur',
|
||||
// },
|
||||
]"
|
||||
>
|
||||
<j-input-number
|
||||
|
@ -156,7 +156,7 @@ import type {PropType} from 'vue';
|
|||
import {reactive, ref, watch} from 'vue';
|
||||
import BuildIn from './BuildIn.vue';
|
||||
import {updateRegion, validateName, validateCode} from '@/api/system/region';
|
||||
import {omit} from "lodash-es";
|
||||
import {cloneDeep, omit} from "lodash-es";
|
||||
import {onlyMessage} from "@/utils/comm";
|
||||
import RadioButton from '@/components/CardSelect/RadioButton.vue'
|
||||
import GeoJsonModal from './GeoJsonModal.vue'
|
||||
|
@ -293,8 +293,8 @@ const handleSave = () => {
|
|||
newData.parentId = newData.parentId || ''
|
||||
|
||||
if (newData.properties.sync) {
|
||||
const _syncChildren = syncChildren(newData.code, props.areaTree)
|
||||
|
||||
const arr = cloneDeep(props.areaTree)
|
||||
const _syncChildren = syncChildren(newData.code, arr)
|
||||
const different = _syncChildren.filter(item => {
|
||||
if (newData.children && newData.children.some(oldItem => oldItem.code === item.code)) {
|
||||
return false
|
||||
|
@ -310,7 +310,10 @@ const handleSave = () => {
|
|||
newData.children = [
|
||||
...(newData.children || []),
|
||||
...different
|
||||
]
|
||||
].map(item=>{
|
||||
const {id,...extra} =item
|
||||
return extra
|
||||
})
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
|
|
|
@ -95,8 +95,8 @@ function openEdit() {
|
|||
}
|
||||
|
||||
function layerSetData(geoJson: Record<string, any>, edit = true) {
|
||||
regionState.type = geoJson.features[0].properties.type
|
||||
mapRef.value?.showGeoJson(geoJson.features[0].geometry.coordinates)
|
||||
regionState.type = geoJson?.features?.[0]?.properties?.type
|
||||
mapRef.value?.showGeoJson(geoJson?.features?.[0]?.geometry?.coordinates)
|
||||
if (edit) {
|
||||
mapRef.value?.openEdit()
|
||||
}
|
||||
|
|
|
@ -46,8 +46,9 @@
|
|||
}}</Ellipsis>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@click="(e) => e.stopPropagation()"
|
||||
v-if="item.id !== 'default_group'"
|
||||
v-if="item.id !== 'default_group' && admin"
|
||||
>
|
||||
<PermissionButton
|
||||
type="text"
|
||||
|
@ -94,6 +95,7 @@ import {
|
|||
import { randomString } from '@/utils/utils';
|
||||
import { useUserInfo } from '@/store/userInfo';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
const emit = defineEmits(['selectData']);
|
||||
const userInfoStore = useUserInfo();
|
||||
const { userInfos } = storeToRefs(userInfoStore);
|
||||
|
|
Loading…
Reference in New Issue