Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev
This commit is contained in:
commit
4dcbf18939
|
@ -2,36 +2,36 @@
|
|||
<div class="indicator-box">
|
||||
<template v-if="['int', 'long', 'double', 'float'].includes(type)">
|
||||
<template v-if="value.range">
|
||||
<a-input-number v-model:value="value.value[0]" :max="value.value[1]" size="small"
|
||||
style="width: 100%;"></a-input-number>
|
||||
<j-input-number v-model:value="value.value[0]" :max="value.value[1]" size="small"
|
||||
style="width: 100%;"></j-input-number>
|
||||
~
|
||||
<a-input-number v-model:value="value.value[1]" :min="value.value[0]" size="small"
|
||||
style="width: 100%;"></a-input-number>
|
||||
<j-input-number v-model:value="value.value[1]" :min="value.value[0]" size="small"
|
||||
style="width: 100%;"></j-input-number>
|
||||
</template>
|
||||
<a-input-number v-else v-model:value="value.value" size="small" style="width: 100%;"></a-input-number>
|
||||
<j-input-number v-else v-model:value="value.value" size="small" style="width: 100%;"></j-input-number>
|
||||
</template>
|
||||
<template v-else-if="type === 'date'">
|
||||
<a-range-picker v-if="value.range" show-time v-model:value="value.value" size="small" />
|
||||
<a-date-picker v-else show-time v-model:value="value.value" size="small" />
|
||||
<j-range-picker v-if="value.range" show-time v-model:value="value.value" size="small" />
|
||||
<j-date-picker v-else show-time v-model:value="value.value" size="small" />
|
||||
</template>
|
||||
<template v-else-if="type === 'boolean'">
|
||||
<a-select v-model:value="value.value[0]" :options="list" size="small" placeholder="请选择"></a-select>
|
||||
<j-select v-model:value="value.value[0]" :options="list" size="small" placeholder="请选择"></j-select>
|
||||
</template>
|
||||
<template v-else-if="type === 'string'">
|
||||
<a-input v-model:value="value.value" size="small" placeholder="请输入"></a-input>
|
||||
<j-input v-model:value="value.value" size="small" placeholder="请输入"></j-input>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-if="value.range">
|
||||
<a-input v-model:value="value.value[0]" :max="value.value[1]" size="small" placeholder="请输入"></a-input>
|
||||
<j-input v-model:value="value.value[0]" :max="value.value[1]" size="small" placeholder="请输入"></j-input>
|
||||
~
|
||||
<a-input v-model:value="value.value[1]" :min="value.value[0]" size="small" placeholder="请输入"></a-input>
|
||||
<j-input v-model:value="value.value[1]" :min="value.value[0]" size="small" placeholder="请输入"></j-input>
|
||||
</template>
|
||||
<a-input-number v-else v-model:value="value.value" size="small" placeholder="请输入"></a-input-number>
|
||||
<j-input-number v-else v-model:value="value.value" size="small" placeholder="请输入"></j-input-number>
|
||||
</template>
|
||||
<div v-if="type !== 'boolean' && type !== 'string'">
|
||||
<a-checkbox style="min-width: 60px; margin-left: 5px;" v-model:checked="value.range" @change="changeChecked">
|
||||
<j-checkbox style="min-width: 60px; margin-left: 5px;" v-model:checked="value.range" @change="changeChecked">
|
||||
范围
|
||||
</a-checkbox>
|
||||
</j-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-popover :visible="visible" placement="left">
|
||||
<j-popover :visible="visible" placement="left">
|
||||
<template #title>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div style="width: 150px;">配置元素</div>
|
||||
|
@ -10,19 +10,19 @@
|
|||
<div style="max-width: 400px;">
|
||||
<div class="ant-form-vertical">
|
||||
<value-type-form v-model:value="_value" :name="name" isSub key="sub"></value-type-form>
|
||||
<a-form-item label="说明" :name="name.concat(['description'])" :rules="[
|
||||
<j-form-item label="说明" :name="name.concat(['description'])" :rules="[
|
||||
{ max: 200, message: '最多可输入200个字符' },
|
||||
]">
|
||||
<a-textarea v-model:value="_value.description" size="small"></a-textarea>
|
||||
</a-form-item>
|
||||
<j-textarea v-model:value="_value.description" size="small"></j-textarea>
|
||||
</j-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<a-button type="dashed" block @click="visible = true">
|
||||
<j-button type="dashed" block @click="visible = true">
|
||||
配置元素
|
||||
<AIcon type="EditOutlined" class="item-icon" />
|
||||
</a-button>
|
||||
</a-popover>
|
||||
</j-button>
|
||||
</j-popover>
|
||||
</template>
|
||||
<script setup lang="ts" name="ArrayParam">
|
||||
import ValueTypeForm from '@/views/device/components/Metadata/Base/Edit/ValueTypeForm.vue';
|
||||
|
@ -33,7 +33,7 @@ type ValueType = Record<any, any>;
|
|||
const props = defineProps({
|
||||
value: {
|
||||
type: Object as PropType<ValueType>,
|
||||
default: () => ({ extends: {} })
|
||||
default: () => ({ expands: {} })
|
||||
},
|
||||
name: {
|
||||
type: Array as PropType<(string | number)[]>,
|
||||
|
|
|
@ -1,35 +1,35 @@
|
|||
<template>
|
||||
<div class="boolean-param">
|
||||
<a-row :gutter="4">
|
||||
<a-col :span="12">
|
||||
<a-form-item label=" " :name="name.concat(['trueText'])" :rules="[
|
||||
<j-row :gutter="4">
|
||||
<j-col :span="12">
|
||||
<j-form-item label=" " :name="name.concat(['trueText'])" :rules="[
|
||||
{ required: true, message: '请输入trueText' },
|
||||
]">
|
||||
<a-input v-model:value="value.trueText" placeholder="trueText" size="small" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="-" :name="name.concat(['trueValue'])" :rules="[
|
||||
<j-input v-model:value="value.trueText" placeholder="trueText" size="small" />
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item label="-" :name="name.concat(['trueValue'])" :rules="[
|
||||
{ required: true, message: '请输入trueValue' },
|
||||
]">
|
||||
<a-input v-model:value="value.trueValue" placeholder="trueValue" size="small"/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label=" " :name="name.concat(['falseText'])" :rules="[
|
||||
<j-input v-model:value="value.trueValue" placeholder="trueValue" size="small"/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item label=" " :name="name.concat(['falseText'])" :rules="[
|
||||
{ required: true, message: '请输入falseText' },
|
||||
]">
|
||||
<a-input v-model:value="value.falseText" placeholder="falseText" size="small" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="-" :name="name.concat(['falseValue'])" :rules="[
|
||||
<j-input v-model:value="value.falseText" placeholder="falseText" size="small" />
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item label="-" :name="name.concat(['falseValue'])" :rules="[
|
||||
{ required: true, message: '请输入falseValue' },
|
||||
]">
|
||||
<a-input v-model:value="value.falseValue" placeholder="falseValue" size="small" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<j-input v-model:value="value.falseValue" placeholder="falseValue" size="small" />
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts" name="BooleanParam">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-popover placement="left" trigger="click">
|
||||
<j-popover placement="left" trigger="click">
|
||||
<template #title>
|
||||
<div class="edit-title" style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div style="width: 150px;">{{ config.name }}</div>
|
||||
|
@ -7,18 +7,18 @@
|
|||
</template>
|
||||
<template #content>
|
||||
<div style="max-width: 400px;" class="ant-form-vertical">
|
||||
<a-form-item v-for="item in config.properties" :name="name.concat([item.property])" :label="item.name">
|
||||
<a-select v-model:value="value[item.property]" :options="item.type?.elements?.map((e: { 'text': string, 'value': string }) => ({
|
||||
<j-form-item v-for="item in config.properties" :name="name.concat([item.property])" :label="item.name">
|
||||
<j-select v-model:value="value[item.property]" :options="item.type?.elements?.map((e: { 'text': string, 'value': string }) => ({
|
||||
label: e.text,
|
||||
value: e.value,
|
||||
}))" size="small"></a-select>
|
||||
</a-form-item>
|
||||
}))" size="small"></j-select>
|
||||
</j-form-item>
|
||||
</div>
|
||||
</template>
|
||||
<a-button type="dashed" block>
|
||||
<j-button type="dashed" block>
|
||||
存储配置<AIcon type="EditOutlined" class="item-icon"/>
|
||||
</a-button>
|
||||
</a-popover>
|
||||
</j-button>
|
||||
</j-popover>
|
||||
</template>
|
||||
<script setup lang="ts" name="ConfigParam">
|
||||
import { PropType } from 'vue';
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<AIcon type="MenuOutlined" class="item-drag item-icon" />
|
||||
</div>
|
||||
<div class="item-middle item-editable">
|
||||
<a-popover :visible="editIndex === index" placement="top">
|
||||
<j-popover :visible="editIndex === index" placement="top">
|
||||
<template #title>
|
||||
<div class="edit-title" style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div style="width: 150px;">枚举项配置</div>
|
||||
|
@ -14,34 +14,34 @@
|
|||
</template>
|
||||
<template #content>
|
||||
<div class="ant-form-vertical">
|
||||
<a-form-item label="Value" :name="name.concat([index, 'value'])" :rules="[
|
||||
<j-form-item label="Value" :name="name.concat([index, 'value'])" :rules="[
|
||||
{ required: true, message: '请输入Value' },
|
||||
]">
|
||||
<a-input v-model:value="_value[index].value" size="small"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="Text" :name="name.concat([index, 'text'])" :rules="[
|
||||
<j-input v-model:value="_value[index].value" size="small"></j-input>
|
||||
</j-form-item>
|
||||
<j-form-item label="Text" :name="name.concat([index, 'text'])" :rules="[
|
||||
{ required: true, message: '请输入Text' },
|
||||
]">
|
||||
<a-input v-model:value="_value[index].text" size="small"></a-input>
|
||||
</a-form-item>
|
||||
<j-input v-model:value="_value[index].text" size="small"></j-input>
|
||||
</j-form-item>
|
||||
</div>
|
||||
</template>
|
||||
<div class="item-edit" @click="handleEdit(index)">
|
||||
{{ item.text || '枚举项配置' }}
|
||||
<AIcon type="EditOutlined" class="item-icon" />
|
||||
</div>
|
||||
</a-popover>
|
||||
</j-popover>
|
||||
</div>
|
||||
<div class="item-right">
|
||||
<AIcon type="DeleteOutlined" @click="handleDelete(index)" />
|
||||
</div>
|
||||
</div>
|
||||
<a-button type="dashed" block @click="handleAdd">
|
||||
<j-button type="dashed" block @click="handleAdd">
|
||||
<template #icon>
|
||||
<AIcon type="PlusOutlined" class="item-icon" />
|
||||
</template>
|
||||
新增枚举型
|
||||
</a-button>
|
||||
</j-button>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts" name="BooleanParam">
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<AIcon type="MenuOutlined" class="item-drag item-icon" />
|
||||
</div>
|
||||
<div class="item-middle item-editable">
|
||||
<a-popover :visible="editIndex === index" placement="left">
|
||||
<j-popover :visible="editIndex === index" placement="left">
|
||||
<template #title>
|
||||
<div class="edit-title" style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div style="width: 150px;">配置参数</div>
|
||||
|
@ -14,7 +14,7 @@
|
|||
</template>
|
||||
<template #content>
|
||||
<div style="max-width: 400px;" class="ant-form-vertical">
|
||||
<a-form-item label="标识" :name="name.concat([index, 'id'])" :rules="[
|
||||
<j-form-item label="标识" :name="name.concat([index, 'id'])" :rules="[
|
||||
{ required: true, message: '请输入标识' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
{
|
||||
|
@ -22,14 +22,14 @@
|
|||
message: 'ID只能由数字、字母、下划线、中划线组成',
|
||||
},
|
||||
]">
|
||||
<a-input v-model:value="_value[index].id" size="small"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="名称" :name="name.concat([index, 'name'])" :rules="[
|
||||
<j-input v-model:value="_value[index].id" size="small"></j-input>
|
||||
</j-form-item>
|
||||
<j-form-item label="名称" :name="name.concat([index, 'name'])" :rules="[
|
||||
{ required: true, message: '请输入名称' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
]">
|
||||
<a-input v-model:value="_value[index].name" size="small"></a-input>
|
||||
</a-form-item>
|
||||
<j-input v-model:value="_value[index].name" size="small"></j-input>
|
||||
</j-form-item>
|
||||
<value-type-form v-model:value="_value[index].valueType" :name="name.concat([index, 'valueType'])" isSub
|
||||
key="json_sub"></value-type-form>
|
||||
</div>
|
||||
|
@ -38,18 +38,18 @@
|
|||
{{ item.name || '配置参数' }}
|
||||
<AIcon type="EditOutlined" class="item-icon" />
|
||||
</div>
|
||||
</a-popover>
|
||||
</j-popover>
|
||||
</div>
|
||||
<div class="item-right">
|
||||
<AIcon type="DeleteOutlined" @click="handleDelete(index)" />
|
||||
</div>
|
||||
</div>
|
||||
<a-button type="dashed" block @click="handleAdd">
|
||||
<j-button type="dashed" block @click="handleAdd">
|
||||
<template #icon>
|
||||
<AIcon type="PlusOutlined" class="item-icon" />
|
||||
</template>
|
||||
添加参数
|
||||
</a-button>
|
||||
</j-button>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts" name="JsonParam">
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{{ `#${index + 1}.` }}
|
||||
</div>
|
||||
<div class="item-middle item-editable">
|
||||
<a-popover :visible="editIndex === index" placement="top" @visible-change="change" trigger="click">
|
||||
<j-popover :visible="editIndex === index" placement="top" @visible-change="change" trigger="click">
|
||||
<template #title>
|
||||
<div class="edit-title" style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div style="width: 150px;">配置参数</div>
|
||||
|
@ -16,7 +16,7 @@
|
|||
<template #content>
|
||||
<div>
|
||||
<div class="ant-form-vertical">
|
||||
<a-form-item label="标识" :name="name.concat([index, 'id'])" :rules="[
|
||||
<j-form-item label="标识" :name="name.concat([index, 'id'])" :rules="[
|
||||
{ required: true, message: '请输入标识' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
{
|
||||
|
@ -24,20 +24,19 @@
|
|||
message: 'ID只能由数字、字母、下划线、中划线组成',
|
||||
},
|
||||
]">
|
||||
<a-input v-model:value="_value[index].id" size="small"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="名称" :name="name.concat([index, 'name'])" :rules="[
|
||||
<j-input v-model:value="_value[index].id" size="small"></j-input>
|
||||
</j-form-item>
|
||||
<j-form-item label="名称" :name="name.concat([index, 'name'])" :rules="[
|
||||
{ required: true, message: '请输入名称' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
]">
|
||||
<a-input v-model:value="_value[index].name" size="small"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="指标值" :name="name.concat([index, 'value'])" :rules="[
|
||||
{ required: true, message: '请输入指标值' },
|
||||
{ validator: () => validateIndicator(_value[index]), message: '请输入指标值' }
|
||||
<j-input v-model:value="_value[index].name" size="small"></j-input>
|
||||
</j-form-item>
|
||||
<j-form-item label="指标值" :name="name.concat([index, 'value'])" :rules="[
|
||||
{ required: true, validator: () => validateIndicator(_value[index]), message: '请输入指标值' }
|
||||
]">
|
||||
<JIndicators v-model:value="_value[index]" :type="type" size="small" :enum="enum" />
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -45,18 +44,18 @@
|
|||
{{ item.name || '配置参数' }}
|
||||
<AIcon type="EditOutlined" class="item-icon" />
|
||||
</div>
|
||||
</a-popover>
|
||||
</j-popover>
|
||||
</div>
|
||||
<div class="item-right">
|
||||
<AIcon type="DeleteOutlined" @click="handleDelete(index)" />
|
||||
</div>
|
||||
</div>
|
||||
<a-button type="dashed" block @click="handleAdd">
|
||||
<j-button type="dashed" block @click="handleAdd">
|
||||
<template #icon>
|
||||
<AIcon type="PlusOutlined" class="item-icon" />
|
||||
</template>
|
||||
添加指标
|
||||
</a-button>
|
||||
</j-button>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts" name="MetricsParam">
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
<template>
|
||||
<a-form-item :name="name.concat(['script'])">
|
||||
<j-form-item :name="name.concat(['script'])">
|
||||
<f-rule-editor v-model:value="value.script" :id="id"></f-rule-editor>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
<template v-if="showWindow">
|
||||
<a-form-item label="规则配置" :name="name.concat(['isVirtualRule'])">
|
||||
<a-switch v-model:checked="value.isVirtualRule" :checked-value="true" :un-checked-value="false"
|
||||
@change="changeWindow"></a-switch>
|
||||
</a-form-item>
|
||||
<j-form-item label="规则配置" :name="name.concat(['isVirtualRule'])">
|
||||
<j-switch v-model:checked="value.isVirtualRule" :checked-value="true" :un-checked-value="false"
|
||||
@change="changeWindow"></j-switch>
|
||||
</j-form-item>
|
||||
<template v-if="value.isVirtualRule">
|
||||
<a-form-item label="窗口" :name="name.concat(['windowType'])" :rules="[
|
||||
<j-form-item label="窗口" :name="name.concat(['windowType'])" :rules="[
|
||||
{ required: true, message: '请选择窗口' },
|
||||
]">
|
||||
<a-select v-model:value="value.windowType" :options="windowTypeEnum" size="small" allow-clear></a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="聚合函数" :name="name.concat(['aggType'])" :rules="[
|
||||
<j-select v-model:value="value.windowType" :options="windowTypeEnum" size="small" allow-clear></j-select>
|
||||
</j-form-item>
|
||||
<j-form-item label="聚合函数" :name="name.concat(['aggType'])" :rules="[
|
||||
{ required: true, message: '请选择聚合函数' },
|
||||
]">
|
||||
<a-select v-model:value="value.aggType" :options="aggTypeOptions" size="small" allow-clear></a-select>
|
||||
</a-form-item>
|
||||
<a-form-item :label="spanLabel" :name="name.concat(['window', 'span'])" :rules="[
|
||||
<j-select v-model:value="value.aggType" :options="aggTypeOptions" size="small" allow-clear></j-select>
|
||||
</j-form-item>
|
||||
<j-form-item :label="spanLabel" :name="name.concat(['window', 'span'])" :rules="[
|
||||
{ required: true, message: '请输入窗口长度' },
|
||||
]">
|
||||
<a-input-number v-model:value="value.window.span" size="small" style="width: 100%;"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item :label="everyLabel" :name="name.concat(['window', 'every'])" :rules="[
|
||||
<j-input-number v-model:value="value.window.span" size="small" style="width: 100%;"></j-input-number>
|
||||
</j-form-item>
|
||||
<j-form-item :label="everyLabel" :name="name.concat(['window', 'every'])" :rules="[
|
||||
{ required: true, message: '请输入步长' },
|
||||
]">
|
||||
<a-input-number v-model:value="value.window.every" size="small" style="width: 100%;"></a-input-number>
|
||||
</a-form-item>
|
||||
<j-input-number v-model:value="value.window.every" size="small" style="width: 100%;"></j-input-number>
|
||||
</j-form-item>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
|
|
|
@ -4,32 +4,32 @@
|
|||
<div class="live-player-content">
|
||||
<!-- 工具栏 -->
|
||||
<div class="player-screen-tool" v-if="showScreen">
|
||||
<a-radio-group
|
||||
<j-radio-group
|
||||
:value="screen"
|
||||
button-style="solid"
|
||||
@change="handleScreenChange"
|
||||
>
|
||||
<a-radio-button :value="1">单屏</a-radio-button>
|
||||
<a-radio-button :value="4">四分屏</a-radio-button>
|
||||
<a-radio-button :value="9">九分屏</a-radio-button>
|
||||
<a-radio-button :value="0">全屏</a-radio-button>
|
||||
</a-radio-group>
|
||||
<j-radio-button :value="1">单屏</j-radio-button>
|
||||
<j-radio-button :value="4">四分屏</j-radio-button>
|
||||
<j-radio-button :value="9">九分屏</j-radio-button>
|
||||
<j-radio-button :value="0">全屏</j-radio-button>
|
||||
</j-radio-group>
|
||||
<div class="screen-tool-save">
|
||||
<a-tooltip title="可保存分屏配置记录">
|
||||
<j-tooltip title="可保存分屏配置记录">
|
||||
<AIcon type="QuestionCircleOutlined" />
|
||||
</a-tooltip>
|
||||
<a-popover
|
||||
</j-tooltip>
|
||||
<j-popover
|
||||
v-model:visible="visible"
|
||||
trigger="click"
|
||||
title="分屏名称"
|
||||
>
|
||||
<template #content>
|
||||
<a-form
|
||||
<j-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
name="name"
|
||||
:rules="[
|
||||
{
|
||||
|
@ -42,37 +42,37 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-textarea v-model:value="formData.name" />
|
||||
</a-form-item>
|
||||
<a-button
|
||||
<j-textarea v-model:value="formData.name" />
|
||||
</j-form-item>
|
||||
<j-button
|
||||
type="primary"
|
||||
@click="saveHistory"
|
||||
:loading="loading"
|
||||
style="width: 100%; margin-top: 16px"
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
</a-form>
|
||||
</j-button>
|
||||
</j-form>
|
||||
</template>
|
||||
<a-dropdown-button
|
||||
<j-dropdown-button
|
||||
type="primary"
|
||||
@click="visible = true"
|
||||
>
|
||||
保存
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-empty
|
||||
<j-menu>
|
||||
<j-empty
|
||||
v-if="!historyList.length"
|
||||
description="暂无数据"
|
||||
/>
|
||||
<a-menu-item
|
||||
<j-menu-item
|
||||
v-for="(item, index) in historyList"
|
||||
:key="`his${index}`"
|
||||
@click="handleHistory(item)"
|
||||
>
|
||||
<a-space>
|
||||
<j-space>
|
||||
<span>{{ item.name }}</span>
|
||||
<a-popconfirm
|
||||
<j-popconfirm
|
||||
title="确认删除?"
|
||||
ok-text="确认"
|
||||
cancel-text="取消"
|
||||
|
@ -89,13 +89,13 @@
|
|||
e?.stopPropagation()
|
||||
"
|
||||
/>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</j-popconfirm>
|
||||
</j-space>
|
||||
</j-menu-item>
|
||||
</j-menu>
|
||||
</template>
|
||||
</a-dropdown-button>
|
||||
</a-popover>
|
||||
</j-dropdown-button>
|
||||
</j-popover>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 播放器 -->
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
:muted="'muted' in props ? props.muted !== false : true"
|
||||
:hide-big-play-button="true"
|
||||
:poster="props.poster || ''"
|
||||
:timeout="props.timeout || 20"
|
||||
:timeout="props.timeout || 30"
|
||||
:video-url="url || ''"
|
||||
@play="props.onPlay"
|
||||
@pause="props.onPause"
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
v-model:value="myValue"
|
||||
>
|
||||
<template #addonAfter>
|
||||
<form-outlined @click="modalVis = true" />
|
||||
<AIcon type="FormOutlined" @click="modalVis = true" />
|
||||
</template>
|
||||
</j-input>
|
||||
<GeoComponent
|
||||
|
@ -50,7 +50,7 @@
|
|||
:showUploadList="false"
|
||||
@change="handleFileChange"
|
||||
>
|
||||
<cloud-upload-outlined />
|
||||
<AIcon type="CloudUploadOutlined" />
|
||||
</j-upload>
|
||||
</template>
|
||||
</j-input>
|
||||
|
|
|
@ -15,6 +15,7 @@ import Ellipsis from './Ellipsis/index.vue'
|
|||
import JEmpty from './Empty/index.vue'
|
||||
import AMapComponent from './AMapComponent/index.vue'
|
||||
import PathSimplifier from './AMapComponent/PathSimplifier.vue'
|
||||
import ValueItem from './ValueItem/index.vue'
|
||||
|
||||
export default {
|
||||
install(app: App) {
|
||||
|
@ -35,5 +36,6 @@ export default {
|
|||
.component('JEmpty', JEmpty)
|
||||
.component('AMapComponent', AMapComponent)
|
||||
.component('PathSimplifier', PathSimplifier)
|
||||
.component('ValueItem', ValueItem)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
在特定场景下,设备无法直接接入阿里云物联网平台时,您可先将设备接入物联网平台,再使用阿里云“云云对接SDK”,快速构建桥接服务,搭建物联网平台与阿里云物联网平台的双向数据通道。
|
||||
</div>
|
||||
<div class="image">
|
||||
<a-image width="100%" :src="getImage('/northbound/aliyun2.png')" />
|
||||
<j-image width="100%" :src="getImage('/northbound/aliyun2.png')" />
|
||||
</div>
|
||||
<h1>2.配置说明</h1>
|
||||
<div>
|
||||
|
@ -26,14 +26,14 @@
|
|||
</div>
|
||||
<div>获取路径:“阿里云物联网平台”--“服务地址”</div>
|
||||
<div class="image">
|
||||
<a-image width="100%" :src="getImage('/northbound/aliyun3.png')" />
|
||||
<j-image width="100%" :src="getImage('/northbound/aliyun3.png')" />
|
||||
</div>
|
||||
<h2> 2、AccesskeyID/Secret</h2>
|
||||
<div>
|
||||
用于程序通知方式调用云服务费API的用户标识和秘钥获取路径:“阿里云管理控制台”--“用户头像”--“”--“AccessKey管理”--“查看”
|
||||
</div>
|
||||
<div class="image">
|
||||
<a-image width="100%" :src="getImage('/northbound/aliyun1.jpg')" />
|
||||
<j-image width="100%" :src="getImage('/northbound/aliyun1.jpg')" />
|
||||
</div>
|
||||
<h2> 3. 网桥产品</h2>
|
||||
<div>
|
||||
|
@ -44,7 +44,7 @@
|
|||
将阿里云物联网平台中的产品实例与物联网平台的产品实例进行关联。关联后需要进入该产品下的每一个设备的实例信息页,填入对应的阿里云物联网平台设备的DeviceName、DeviceSecret进行一对一绑定。
|
||||
</div>
|
||||
<div class="image">
|
||||
<a-image width="100%" :src="getImage('/northbound/aliyun4.png')" />
|
||||
<j-image width="100%" :src="getImage('/northbound/aliyun4.png')" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<a-card>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="16">
|
||||
<j-card>
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="16">
|
||||
<TitleComponent data="基本信息" />
|
||||
<a-form
|
||||
<j-form
|
||||
:layout="'vertical'"
|
||||
ref="formRef"
|
||||
:model="modelRef"
|
||||
>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
label="名称"
|
||||
name="name"
|
||||
:rules="[
|
||||
|
@ -25,14 +25,14 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
placeholder="请输入名称"
|
||||
v-model:value="modelRef.name"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
:name="['accessConfig', 'regionId']"
|
||||
:rules="[
|
||||
{
|
||||
|
@ -44,63 +44,62 @@
|
|||
<template #label>
|
||||
<span>
|
||||
服务地址
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="阿里云内部给每台机器设置的唯一编号"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-select
|
||||
<j-select
|
||||
placeholder="请选择服务地址"
|
||||
v-model:value="
|
||||
modelRef.accessConfig.regionId
|
||||
"
|
||||
show-search
|
||||
:filter-option="filterOption"
|
||||
@blur="productChange"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="item in regionsList"
|
||||
:key="item.id"
|
||||
:value="item.id"
|
||||
:label="item.name"
|
||||
>{{ item.name }}</a-select-option
|
||||
>{{ item.name }}</j-select-option
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
:name="['accessConfig', 'instanceId']"
|
||||
>
|
||||
<template #label>
|
||||
<span>
|
||||
实例ID
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="阿里云物联网平台中的实例ID,没有则不填"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-input
|
||||
<j-input
|
||||
placeholder="请输入实例ID"
|
||||
v-model:value="
|
||||
modelRef.accessConfig.instanceId
|
||||
"
|
||||
@blur="productChange"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
:name="['accessConfig', 'accessKeyId']"
|
||||
:rules="[
|
||||
{
|
||||
|
@ -116,27 +115,27 @@
|
|||
<template #label>
|
||||
<span>
|
||||
accessKey
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="用于程序通知方式调用云服务API的用户标识"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-input
|
||||
<j-input
|
||||
placeholder="请输入accessKey"
|
||||
v-model:value="
|
||||
modelRef.accessConfig.accessKeyId
|
||||
"
|
||||
@blur="productChange"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
:name="['accessConfig', 'accessSecret']"
|
||||
:rules="[
|
||||
{
|
||||
|
@ -152,27 +151,27 @@
|
|||
<template #label>
|
||||
<span>
|
||||
accessSecret
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="用于程序通知方式调用云服务费API的秘钥标识"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-input
|
||||
<j-input
|
||||
placeholder="请输入accessSecret"
|
||||
v-model:value="
|
||||
modelRef.accessConfig.accessSecret
|
||||
"
|
||||
@blur="productChange"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
name="bridgeProductKey"
|
||||
:rules="{
|
||||
required: true,
|
||||
|
@ -182,44 +181,43 @@
|
|||
<template #label>
|
||||
<span>
|
||||
网桥产品
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="物联网平台对应的阿里云产品"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-select
|
||||
<j-select
|
||||
placeholder="请选择网桥产品"
|
||||
v-model:value="
|
||||
modelRef.bridgeProductKey
|
||||
"
|
||||
show-search
|
||||
:filter-option="filterOption"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="item in aliyunProductList"
|
||||
:key="item.productKey"
|
||||
:value="item.productKey"
|
||||
:label="item.productName"
|
||||
>{{
|
||||
item.productName
|
||||
}}</a-select-option
|
||||
}}</j-select-option
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<p>产品映射</p>
|
||||
<a-collapse
|
||||
<j-collapse
|
||||
v-if="modelRef.mappings.length"
|
||||
:activeKey="activeKey"
|
||||
@change="onCollChange"
|
||||
>
|
||||
<a-collapse-panel
|
||||
<j-collapse-panel
|
||||
v-for="(
|
||||
item, index
|
||||
) in modelRef.mappings"
|
||||
|
@ -239,9 +237,9 @@
|
|||
type="DeleteOutlined"
|
||||
@click="delItem(index)"
|
||||
/></template>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="阿里云产品"
|
||||
:name="[
|
||||
'mappings',
|
||||
|
@ -254,19 +252,16 @@
|
|||
'请选择阿里云产品',
|
||||
}"
|
||||
>
|
||||
<a-select
|
||||
<j-select
|
||||
placeholder="请选择阿里云产品"
|
||||
v-model:value="
|
||||
item.productKey
|
||||
"
|
||||
show-search
|
||||
:filter-option="
|
||||
filterOption
|
||||
"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="i in getAliyunProductList(
|
||||
item.productKey,
|
||||
item?.productKey || ''
|
||||
)"
|
||||
:key="i.productKey"
|
||||
:value="
|
||||
|
@ -277,13 +272,13 @@
|
|||
"
|
||||
>{{
|
||||
i.productName
|
||||
}}</a-select-option
|
||||
}}</j-select-option
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="平台产品"
|
||||
:name="[
|
||||
'mappings',
|
||||
|
@ -296,36 +291,36 @@
|
|||
'请选择平台产品',
|
||||
}"
|
||||
>
|
||||
<a-select
|
||||
<j-select
|
||||
placeholder="请选择平台产品"
|
||||
v-model:value="
|
||||
item.productId
|
||||
"
|
||||
show-search
|
||||
:filter-option="
|
||||
filterOption
|
||||
"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="i in getPlatProduct(
|
||||
item.productId,
|
||||
item.productId || ''
|
||||
)"
|
||||
:key="i.id"
|
||||
:value="item.id"
|
||||
:value="i?.id"
|
||||
:label="i.name"
|
||||
>{{
|
||||
i.name
|
||||
}}</a-select-option
|
||||
}}</j-select-option
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-button
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-collapse-panel>
|
||||
</j-collapse>
|
||||
<j-card v-else>
|
||||
<j-empty />
|
||||
</j-card>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-button
|
||||
type="dashed"
|
||||
style="width: 100%; margin-top: 10px"
|
||||
@click="addItem"
|
||||
|
@ -334,10 +329,10 @@
|
|||
type="PlusOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>添加
|
||||
</a-button>
|
||||
</a-col>
|
||||
<a-col :span="24" style="margin-top: 20px">
|
||||
<a-form-item
|
||||
</j-button>
|
||||
</j-col>
|
||||
<j-col :span="24" style="margin-top: 20px">
|
||||
<j-form-item
|
||||
label="说明"
|
||||
name="description"
|
||||
:rules="{
|
||||
|
@ -345,16 +340,16 @@
|
|||
message: '最多输入200个字符',
|
||||
}"
|
||||
>
|
||||
<a-textarea
|
||||
<j-textarea
|
||||
v-model:value="modelRef.description"
|
||||
placeholder="请输入说明"
|
||||
showCount
|
||||
:maxlength="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-form>
|
||||
<div v-if="type === 'edit'">
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
|
@ -365,12 +360,12 @@
|
|||
保存
|
||||
</PermissionButton>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
</j-col>
|
||||
<j-col :span="8">
|
||||
<Doc />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-card>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
@ -384,7 +379,7 @@ import {
|
|||
queryProductList,
|
||||
} from '@/api/northbound/alicloud';
|
||||
import _ from 'lodash';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
@ -430,10 +425,6 @@ const loading = ref<boolean>(false);
|
|||
const type = ref<'edit' | 'view'>('edit');
|
||||
const activeKey = ref<string[]>(['0']);
|
||||
|
||||
const filterOption = (input: string, option: any) => {
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
|
||||
const queryRegionsList = async () => {
|
||||
const resp = await getRegionsList();
|
||||
if (resp.status === 200) {
|
||||
|
@ -503,8 +494,9 @@ const saveBtn = () => {
|
|||
);
|
||||
data.bridgeProductName = product?.productName || '';
|
||||
loading.value = true;
|
||||
const resp = await savePatch({...toRaw(modelRef), ...data});
|
||||
loading.value = false;
|
||||
const resp = await savePatch({...toRaw(modelRef), ...data}).finally(() => {
|
||||
loading.value = false;
|
||||
})
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
formRef.value.resetFields();
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<Search
|
||||
<j-advanced-search
|
||||
:columns="columns"
|
||||
target="northbound-aliyun"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<JTable
|
||||
<JProTable
|
||||
ref="instanceRef"
|
||||
:columns="columns"
|
||||
:request="query"
|
||||
|
@ -13,7 +13,7 @@
|
|||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<a-space>
|
||||
<j-space>
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
|
@ -22,7 +22,7 @@
|
|||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
</a-space>
|
||||
</j-space>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
|
@ -45,20 +45,20 @@
|
|||
>
|
||||
{{ slotProps.name }}
|
||||
</h3>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<j-row>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">
|
||||
网桥产品
|
||||
</div>
|
||||
<div>{{ slotProps?.bridgeProductName }}</div>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">
|
||||
<label>说明</label>
|
||||
</div>
|
||||
<div>{{ slotProps?.description }}</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</template>
|
||||
<template #actions="item">
|
||||
<PermissionButton
|
||||
|
@ -81,13 +81,13 @@
|
|||
</CardBox>
|
||||
</template>
|
||||
<template #state="slotProps">
|
||||
<a-badge
|
||||
<j-badge
|
||||
:text="slotProps.state?.text"
|
||||
:status="statusMap.get(slotProps.state?.value)"
|
||||
/>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space>
|
||||
<j-space>
|
||||
<template
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
:key="i.key"
|
||||
|
@ -104,23 +104,21 @@
|
|||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</j-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</JProTable>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { query, _undeploy, _deploy, _delete } from '@/api/northbound/alicloud';
|
||||
import type { ActionsType } from '@/components/Table/index.vue';
|
||||
import type { ActionsType } from '@/views/device/Instance/typings'
|
||||
import { getImage } from '@/utils/comm';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import { useMenuStore } from 'store/menu';
|
||||
|
||||
const router = useRouter();
|
||||
const instanceRef = ref<Record<string, any>>({});
|
||||
const params = ref<Record<string, any>>({});
|
||||
const current = ref<Record<string, any>>({});
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
|
||||
|
@ -149,6 +147,9 @@ const columns = [
|
|||
title: '说明',
|
||||
dataIndex: 'describe',
|
||||
key: 'describe',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PropType } from "vue-demi";
|
||||
import { PropType } from "vue";
|
||||
|
||||
|
||||
type Emits = {
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
<j-form-item name="messageType" label="指令类型" :rules="{
|
||||
required: true,
|
||||
message: '请选择指令类型',
|
||||
}">
|
||||
<j-select placeholder="请选择指令类型" v-model:value="modelRef.messageType" show-search :filter-option="filterOption">
|
||||
}" class="other">
|
||||
<j-select placeholder="请选择指令类型" v-model:value="modelRef.messageType" show-search>
|
||||
<j-select-option value="READ_PROPERTY">读取属性</j-select-option>
|
||||
<j-select-option value="WRITE_PROPERTY">修改属性</j-select-option>
|
||||
<j-select-option value="INVOKE_FUNCTION">调用功能</j-select-option>
|
||||
|
@ -22,7 +22,7 @@
|
|||
required: true,
|
||||
message: '请选择属性',
|
||||
}">
|
||||
<j-select placeholder="请选择属性" v-model:value="modelRef.message.properties" show-search :filter-option="filterOption">
|
||||
<j-select placeholder="请选择属性" v-model:value="modelRef.message.properties" show-search @change="onPropertyChange">
|
||||
<j-select-option v-for="i in (metadata?.properties) || []" :key="i.id" :value="i.id" :label="i.name">{{i.name}}</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
|
@ -32,7 +32,27 @@
|
|||
required: true,
|
||||
message: '请输入值',
|
||||
}">
|
||||
<j-input />
|
||||
<ValueItem
|
||||
v-model:modelValue="modelRef.message.value"
|
||||
:itemType="property.type || property.valueType?.type || 'int'"
|
||||
:options="
|
||||
property.valueType?.type === 'enum'
|
||||
? (property?.dataType?.elements || []).map(
|
||||
(item) => {
|
||||
return {
|
||||
label: item?.text,
|
||||
value: item?.value,
|
||||
};
|
||||
},
|
||||
)
|
||||
: property.valueType?.type === 'boolean'
|
||||
? [
|
||||
{ label: '是', value: true },
|
||||
{ label: '否', value: false },
|
||||
]
|
||||
: undefined
|
||||
"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24" v-if="modelRef.messageType === 'INVOKE_FUNCTION'">
|
||||
|
@ -40,7 +60,7 @@
|
|||
required: true,
|
||||
message: '请选择功能',
|
||||
}">
|
||||
<j-select placeholder="请选择功能" v-model:value="modelRef.message.functionId" show-search :filter-option="filterOption" @change="funcChange">
|
||||
<j-select placeholder="请选择功能" v-model:value="modelRef.message.functionId" show-search @change="funcChange">
|
||||
<j-select-option v-for="i in (metadata?.functions) || []" :key="i.id" :value="i.id" :label="i.name">{{i.name}}</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
|
@ -62,10 +82,6 @@ import EditTable from './EditTable.vue'
|
|||
|
||||
const formRef = ref();
|
||||
|
||||
const filterOption = (input: string, option: any) => {
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
|
||||
const props = defineProps({
|
||||
actionType: {
|
||||
type: String,
|
||||
|
@ -89,10 +105,12 @@ const props = defineProps({
|
|||
type Emits = {
|
||||
(e: 'update:modelValue', data: any): void;
|
||||
};
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const modelRef = computed({
|
||||
get: () => {
|
||||
onPropertyChange(props.modelValue?.message?.properties)
|
||||
return props.modelValue || {
|
||||
messageType: undefined,
|
||||
message: {
|
||||
|
@ -107,6 +125,8 @@ const modelRef = computed({
|
|||
}
|
||||
})
|
||||
|
||||
const property = ref<any>({})
|
||||
|
||||
const funcChange = (val: string) => {
|
||||
if(val){
|
||||
const arr = props.metadata?.functions.find((item: any) => item.id === val)?.inputs || []
|
||||
|
@ -122,6 +142,13 @@ const funcChange = (val: string) => {
|
|||
}
|
||||
}
|
||||
|
||||
const onPropertyChange = (val: string) => {
|
||||
if(val){
|
||||
const _item = props.metadata?.properties.find((item: any) => item.id === val)
|
||||
property.value = _item?.[0] || {}
|
||||
}
|
||||
}
|
||||
|
||||
const saveBtn = () => new Promise((resolve) => {
|
||||
formRef.value.validate()
|
||||
.then(() => {
|
||||
|
@ -140,3 +167,12 @@ const saveBtn = () => new Promise((resolve) => {
|
|||
defineExpose({ saveBtn })
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
:deep(.ant-form-item){
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.other {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
</style>
|
|
@ -51,7 +51,6 @@
|
|||
placeholder="请选择产品"
|
||||
v-model:value="modelRef.id"
|
||||
show-search
|
||||
:filter-option="filterOption"
|
||||
@change="productChange"
|
||||
>
|
||||
<j-select-option
|
||||
|
@ -89,7 +88,6 @@
|
|||
placeholder="请选择设备类型"
|
||||
v-model:value="modelRef.applianceType"
|
||||
show-search
|
||||
:filter-option="filterOption"
|
||||
@change="typeChange"
|
||||
>
|
||||
<j-select-option
|
||||
|
@ -170,13 +168,10 @@
|
|||
item.action
|
||||
"
|
||||
show-search
|
||||
:filter-option="
|
||||
filterOption
|
||||
"
|
||||
>
|
||||
<j-select-option
|
||||
v-for="i in getTypesActions(
|
||||
item.action,
|
||||
item.action || ''
|
||||
)"
|
||||
:key="i.id"
|
||||
:value="i.id"
|
||||
|
@ -218,9 +213,6 @@
|
|||
item.actionType
|
||||
"
|
||||
show-search
|
||||
:filter-option="
|
||||
filterOption
|
||||
"
|
||||
>
|
||||
<j-select-option
|
||||
value="command"
|
||||
|
@ -261,6 +253,9 @@
|
|||
</j-row>
|
||||
</j-collapse-panel>
|
||||
</j-collapse>
|
||||
<j-card v-else>
|
||||
<j-empty />
|
||||
</j-card>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-button
|
||||
|
@ -323,13 +318,10 @@
|
|||
item.source
|
||||
"
|
||||
show-search
|
||||
:filter-option="
|
||||
filterOption
|
||||
"
|
||||
>
|
||||
<j-select-option
|
||||
v-for="i in getDuerOSProperties(
|
||||
item.source,
|
||||
item.source || '',
|
||||
)"
|
||||
:key="i.id"
|
||||
:value="i.id"
|
||||
|
@ -361,16 +353,13 @@
|
|||
"
|
||||
mode="tags"
|
||||
show-search
|
||||
:filter-option="
|
||||
filterOption
|
||||
"
|
||||
>
|
||||
<j-select-option
|
||||
v-for="i in getProductProperties(
|
||||
item.target,
|
||||
)"
|
||||
:key="i.id"
|
||||
:value="item.id"
|
||||
:value="i.id"
|
||||
>{{
|
||||
i.name
|
||||
}}</j-select-option
|
||||
|
@ -381,6 +370,9 @@
|
|||
</j-row>
|
||||
</j-collapse-panel>
|
||||
</j-collapse>
|
||||
<j-card v-else>
|
||||
<j-empty />
|
||||
</j-card>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-button
|
||||
|
@ -494,10 +486,6 @@ const onActionCollChange = (_key: string[]) => {
|
|||
actionActiveKey.value = _key;
|
||||
};
|
||||
|
||||
const filterOption = (input: string, option: any) => {
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
|
||||
const addItem = () => {
|
||||
actionActiveKey.value.push(String(modelRef.actionMappings.length));
|
||||
modelRef.actionMappings.push({
|
||||
|
@ -636,8 +624,9 @@ const saveBtn = async () => {
|
|||
.then(async (data: any) => {
|
||||
if (tasks.every((item) => item) && data) {
|
||||
loading.value = true;
|
||||
const resp = await savePatch(data);
|
||||
loading.value = false;
|
||||
const resp = await savePatch(data).finally(() => {
|
||||
loading.value = false;
|
||||
})
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
formRef.value.resetFields();
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<template>
|
||||
<div class="wrapper">
|
||||
<a-tabs v-model="activeKey" tab-position="left">
|
||||
<a-tab-pane
|
||||
<j-tabs v-model="activeKey" tab-position="left">
|
||||
<j-tab-pane
|
||||
v-for="func in newFunctions"
|
||||
:key="func.id"
|
||||
:tab="func.name"
|
||||
>
|
||||
<a-row :gutter="30">
|
||||
<a-col :span="15">
|
||||
<j-row :gutter="30">
|
||||
<j-col :span="15">
|
||||
<MonacoEditor
|
||||
:ref="`monacoEditor${func.id}`"
|
||||
v-model="func.json"
|
||||
|
@ -15,31 +15,31 @@
|
|||
style="height: 400px"
|
||||
/>
|
||||
<div class="editor-btn">
|
||||
<a-space>
|
||||
<a-button
|
||||
<j-space>
|
||||
<j-button
|
||||
type="primary"
|
||||
@click="handleExecute(func)"
|
||||
>
|
||||
执行
|
||||
</a-button>
|
||||
<a-button
|
||||
</j-button>
|
||||
<j-button
|
||||
type="default"
|
||||
@click="handleClear(func)"
|
||||
>
|
||||
清空
|
||||
</a-button>
|
||||
</a-space>
|
||||
</j-button>
|
||||
</j-space>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="9">
|
||||
</j-col>
|
||||
<j-col :span="9">
|
||||
<h6>执行结果:</h6>
|
||||
<span class="execute-result">
|
||||
{{ func.executeResult }}
|
||||
</span>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-tab-pane>
|
||||
</j-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
<template>
|
||||
<div class="wrapper">
|
||||
<div class="tips">
|
||||
<a-space>
|
||||
<j-space>
|
||||
<AIcon type="QuestionCircleOutlined" />
|
||||
<span>精简模式下参数只支持输入框的方式录入</span>
|
||||
</a-space>
|
||||
</j-space>
|
||||
</div>
|
||||
<a-tabs v-model="activeKey" tab-position="left">
|
||||
<a-tab-pane
|
||||
<j-tabs v-model="activeKey" tab-position="left">
|
||||
<j-tab-pane
|
||||
v-for="func in newFunctions"
|
||||
:key="func.id"
|
||||
:tab="func.name"
|
||||
>
|
||||
<a-row :gutter="30">
|
||||
<a-col :span="15">
|
||||
<a-form :ref="`${func.id}Ref`" :model="func">
|
||||
<a-table
|
||||
<j-row :gutter="30">
|
||||
<j-col :span="15">
|
||||
<j-form :ref="`${func.id}Ref`" :model="func">
|
||||
<j-table
|
||||
:columns="columns"
|
||||
:data-source="func.table"
|
||||
:pagination="false"
|
||||
|
@ -26,7 +26,7 @@
|
|||
v-if="column.dataIndex === 'type'"
|
||||
>
|
||||
<span>{{ record.type }}</span>
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
v-if="record.type === 'object'"
|
||||
>
|
||||
<template slot="title">
|
||||
|
@ -40,12 +40,12 @@
|
|||
cursor: 'help',
|
||||
}"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
<template
|
||||
v-if="column.dataIndex === 'value'"
|
||||
>
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
:name="['table', index, 'value']"
|
||||
:rules="{
|
||||
required: true,
|
||||
|
@ -82,37 +82,37 @@
|
|||
: undefined
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-form>
|
||||
</j-table>
|
||||
</j-form>
|
||||
<div class="editor-btn">
|
||||
<a-space>
|
||||
<a-button
|
||||
<j-space>
|
||||
<j-button
|
||||
type="primary"
|
||||
@click="handleExecute(func)"
|
||||
>
|
||||
执行
|
||||
</a-button>
|
||||
<a-button
|
||||
</j-button>
|
||||
<j-button
|
||||
type="default"
|
||||
@click="handleClear(func)"
|
||||
>
|
||||
清空
|
||||
</a-button>
|
||||
</a-space>
|
||||
</j-button>
|
||||
</j-space>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="9">
|
||||
</j-col>
|
||||
<j-col :span="9">
|
||||
<h6>执行结果:</h6>
|
||||
<span class="execute-result">
|
||||
{{ func.executeResult }}
|
||||
</span>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-tab-pane>
|
||||
</j-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<a-card>
|
||||
<a-empty
|
||||
<j-card>
|
||||
<j-empty
|
||||
v-if="!metadata || (metadata && !metadata.functions.length)"
|
||||
style="margin-top: 50px"
|
||||
>
|
||||
|
@ -9,15 +9,15 @@
|
|||
<!-- <a @click="emits('onJump', 'Metadata')">物模型属性功能</a> -->
|
||||
<a @click="onJump">物模型属性功能</a>
|
||||
</template>
|
||||
</a-empty>
|
||||
</j-empty>
|
||||
<template v-else>
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="Simple" tab="精简模式" />
|
||||
<a-tab-pane key="Advance" tab="高级模式" />
|
||||
</a-tabs>
|
||||
<j-tabs v-model:activeKey="activeKey">
|
||||
<j-tab-pane key="Simple" tab="精简模式" />
|
||||
<j-tab-pane key="Advance" tab="高级模式" />
|
||||
</j-tabs>
|
||||
<component :is="tabs[activeKey]" />
|
||||
</template>
|
||||
</a-card>
|
||||
</j-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
selectedRowKeys: _selectedRowKeys,
|
||||
onChange: onSelectChange,
|
||||
}"
|
||||
@cancelSelect="cancelSelect"
|
||||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
|
@ -643,10 +642,6 @@ const onSelectChange = (keys: string[]) => {
|
|||
_selectedRowKeys.value = [...keys];
|
||||
};
|
||||
|
||||
const cancelSelect = () => {
|
||||
_selectedRowKeys.value = [];
|
||||
};
|
||||
|
||||
const handleClick = (dt: any) => {
|
||||
if (_selectedRowKeys.value.includes(dt.id)) {
|
||||
const _index = _selectedRowKeys.value.findIndex((i) => i === dt.id);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-form-item label="标识" name="id" :rules="[
|
||||
<j-form-item label="标识" name="id" :rules="[
|
||||
{ required: true, message: '请输入标识' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
{
|
||||
|
@ -7,14 +7,14 @@
|
|||
message: 'ID只能由数字、字母、下划线、中划线组成',
|
||||
},
|
||||
]">
|
||||
<a-input v-model:value="value.id" size="small" @change="asyncOtherConfig" :disabled="metadataStore.model.action === 'edit'"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="名称" name="name" :rules="[
|
||||
<j-input v-model:value="value.id" size="small" @change="asyncOtherConfig" :disabled="metadataStore.model.action === 'edit'"></j-input>
|
||||
</j-form-item>
|
||||
<j-form-item label="名称" name="name" :rules="[
|
||||
{ required: true, message: '请输入名称' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
]">
|
||||
<a-input v-model:value="value.name" size="small"></a-input>
|
||||
</a-form-item>
|
||||
<j-input v-model:value="value.name" size="small"></j-input>
|
||||
</j-form-item>
|
||||
<template v-if="modelType === 'properties'">
|
||||
<value-type-form :name="['valueType']" v-model:value="value.valueType" key="property" title="数据类型"
|
||||
@change-type="changeValueType"></value-type-form>
|
||||
|
@ -22,42 +22,42 @@
|
|||
:valueType="value.valueType"></expands-form>
|
||||
</template>
|
||||
<template v-if="modelType === 'functions'">
|
||||
<a-form-item label="是否异步" name="async" :rules="[
|
||||
<j-form-item label="是否异步" name="async" :rules="[
|
||||
{ required: true, message: '请选择是否异步' },
|
||||
]">
|
||||
<a-radio-group v-model:value="value.async">
|
||||
<a-radio :value="true">是</a-radio>
|
||||
<a-radio :value="false">否</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="输入参数" name="inputs" :rules="[
|
||||
<j-radio-group v-model:value="value.async">
|
||||
<j-radio :value="true">是</j-radio>
|
||||
<j-radio :value="false">否</j-radio>
|
||||
</j-radio-group>
|
||||
</j-form-item>
|
||||
<j-form-item label="输入参数" name="inputs" :rules="[
|
||||
{ required: true, message: '请输入输入参数' },
|
||||
]">
|
||||
<JsonParam v-model:value="value.inputs" :name="['inputs']"></JsonParam>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
<value-type-form :name="['output']" v-model:value="value.output" key="function" title="输出参数"></value-type-form>
|
||||
</template>
|
||||
<template v-if="modelType === 'events'">
|
||||
<a-form-item label="级别" :name="['expands', 'level']" :rules="[
|
||||
<j-form-item label="级别" :name="['expands', 'level']" :rules="[
|
||||
{ required: true, message: '请选择级别' },
|
||||
]">
|
||||
<a-select v-model:value="value.expands.level" :options="EventLevel" size="small"></a-select>
|
||||
</a-form-item>
|
||||
<j-select v-model:value="value.expands.level" :options="EventLevel" size="small"></j-select>
|
||||
</j-form-item>
|
||||
<value-type-form :name="['valueType']" v-model:value="value.valueType" key="function" title="输出参数"></value-type-form>
|
||||
</template>
|
||||
<template v-if="modelType === 'tags'">
|
||||
<value-type-form :name="['valueType']" v-model:value="value.valueType" key="property" title="数据类型"></value-type-form>
|
||||
<a-form-item label="读写类型" :name="['expands', 'type']" :rules="[
|
||||
<j-form-item label="读写类型" :name="['expands', 'type']" :rules="[
|
||||
{ required: true, message: '请选择读写类型' },
|
||||
]">
|
||||
<a-select v-model:value="value.expands.type" :options="ExpandsTypeList" mode="multiple" size="small"></a-select>
|
||||
</a-form-item>
|
||||
<j-select v-model:value="value.expands.type" :options="ExpandsTypeList" mode="multiple" size="small"></j-select>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<a-form-item label="说明" name="description" :rules="[
|
||||
<j-form-item label="说明" name="description" :rules="[
|
||||
{ max: 200, message: '最多可输入200个字符' },
|
||||
]">
|
||||
<a-textarea v-model:value="value.description" size="small"></a-textarea>
|
||||
</a-form-item>
|
||||
<j-textarea v-model:value="value.description" size="small"></j-textarea>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<script setup lang="ts" name="BaseForm">
|
||||
import { PropType } from 'vue';
|
||||
|
|
|
@ -1,26 +1,30 @@
|
|||
<template>
|
||||
<a-form-item label="来源" :name="name.concat(['source'])" v-if="type === 'product'" :rules="[
|
||||
<j-form-item label="来源" :name="name.concat(['source'])" v-if="type === 'product'" :rules="[
|
||||
{ required: true, message: '请选择来源' },
|
||||
]">
|
||||
<a-select v-model:value="_value.source" :options="PropertySource" size="small"
|
||||
:disabled="metadataStore.model.action === 'edit'"></a-select>
|
||||
</a-form-item>
|
||||
<j-select v-model:value="_value.source" :options="PropertySource" size="small"
|
||||
:disabled="metadataStore.model.action === 'edit'"></j-select>
|
||||
</j-form-item>
|
||||
<virtual-rule-param v-if="_value.source === 'rule'" v-model:value="_value.virtualRule"
|
||||
:name="name.concat(['virtualRule'])" :id="id" :showWindow="_value.source === 'rule'"></virtual-rule-param>
|
||||
<a-form-item label="读写类型" :name="name.concat(['type'])" :rules="[
|
||||
<j-form-item label="读写类型" :name="name.concat(['type'])" :rules="[
|
||||
{ required: true, message: '请选择读写类型' },
|
||||
]">
|
||||
<a-select v-model:value="_value.type" :options="ExpandsTypeList" mode="multiple" size="small"></a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="其他配置" v-if="config.length > 0">
|
||||
<a-form-item v-for="(item, index) in config" :key="index">
|
||||
<j-select v-model:value="_value.type" :options="ExpandsTypeList" mode="multiple" size="small"></j-select>
|
||||
</j-form-item>
|
||||
<j-form-item label="其他配置" v-if="config.length > 0">
|
||||
<j-form-item v-for="(item, index) in config" :key="index">
|
||||
<config-param v-model:value="_value" :config="item" :name="name"></config-param>
|
||||
</a-form-item>
|
||||
</a-form-item>
|
||||
<a-form-item v-if="type === 'product' && ['int', 'float', 'double', 'long', 'date', 'string', 'boolean'].includes(valueType.type)"
|
||||
label="指标配置" :name="name.concat(['metrics'])">
|
||||
<metrics-param v-model:value="_value.metrics" :type="valueType.type" :enum="valueType" :name="name.concat(['metrics'])"></metrics-param>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
v-if="type === 'product' && ['int', 'float', 'double', 'long', 'date', 'string', 'boolean'].includes(valueType.type)"
|
||||
label="指标配置" :name="name.concat(['metrics'])" :rules="[
|
||||
{ validator: () => validateMetrics(_value.metrics), message: '请输入指标配置' }
|
||||
]">
|
||||
<metrics-param v-model:value="_value.metrics" :type="valueType.type" :enum="valueType"
|
||||
:name="name.concat(['metrics'])"></metrics-param>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<script setup lang="ts" name="ExpandsForm">
|
||||
import { useMetadataStore } from '@/store/metadata';
|
||||
|
@ -86,5 +90,15 @@ onMounted(() => {
|
|||
}
|
||||
})
|
||||
|
||||
const validateMetrics = (value: Record<any, any>[]) => {
|
||||
const flag = value.every((item) => {
|
||||
return item.id && item.name && item.value;
|
||||
});
|
||||
if (!flag) {
|
||||
return Promise.reject(new Error('请输入指标配置'));
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped></style>
|
|
@ -1,48 +1,54 @@
|
|||
<template>
|
||||
<a-form-item :label="title" :name="name.concat(['type'])" :rules="[
|
||||
<j-form-item :label="title" :name="name.concat(['type'])" :rules="[
|
||||
metadataStore.model.type !== 'functions' ? { required: true, message: `请选择${title}` } : {},
|
||||
]">
|
||||
<a-select v-model:value="_value.type" :options="metadataStore.model.type === 'events' ? eventDataTypeList : _dataTypeList" size="small" @change="changeType"></a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="单位" :name="name.concat(['unit'])" v-if="['int', 'float', 'long', 'double'].includes(_value.type)">
|
||||
<j-select v-model:value="_value.type"
|
||||
:options="metadataStore.model.type === 'events' ? eventDataTypeList : _dataTypeList" size="small"
|
||||
@change="changeType"></j-select>
|
||||
</j-form-item>
|
||||
<j-form-item label="单位" :name="name.concat(['unit'])" v-if="['int', 'float', 'long', 'double'].includes(_value.type)">
|
||||
<InputSelect v-model:value="_value.unit" :options="unit.unitOptions" size="small"></InputSelect>
|
||||
</a-form-item>
|
||||
<a-form-item label="精度" :name="name.concat(['scale'])" v-if="['float', 'double'].includes(_value.type)">
|
||||
<a-input-number v-model:value="_value.scale" size="small" :min="0" :max="2147483647" :precision="0" :default-value="2"
|
||||
style="width: 100%"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label="布尔值" name="booleanConfig" v-if="['boolean'].includes(_value.type)">
|
||||
</j-form-item>
|
||||
<j-form-item label="精度" :name="name.concat(['scale'])" v-if="['float', 'double'].includes(_value.type)">
|
||||
<j-input-number v-model:value="_value.scale" size="small" :min="0" :max="2147483647" :precision="0" :default-value="2"
|
||||
style="width: 100%"></j-input-number>
|
||||
</j-form-item>
|
||||
<j-form-item label="布尔值" name="booleanConfig" v-if="['boolean'].includes(_value.type)">
|
||||
<BooleanParam :name="name" v-model:value="_value"></BooleanParam>
|
||||
</a-form-item>
|
||||
<a-form-item label="枚举项" :name="name.concat(['elements'])" v-if="['enum'].includes(_value.type)" :rules="[
|
||||
{ required: true, message: '请配置枚举项' }
|
||||
</j-form-item>
|
||||
<j-form-item label="枚举项" :name="name.concat(['elements'])" v-if="['enum'].includes(_value.type)" :rules="[
|
||||
{ required: true, validator: validateEnum, message: '请配置枚举项' }
|
||||
]">
|
||||
<EnumParam v-model:value="_value.elements" :name="name.concat(['elements'])"></EnumParam>
|
||||
</a-form-item>
|
||||
<a-form-item :name="name.concat(['expands', 'maxLength'])" v-if="['string', 'password'].includes(_value.type)">
|
||||
</j-form-item>
|
||||
<j-form-item :name="name.concat(['expands', 'maxLength'])" v-if="['string', 'password'].includes(_value.type)">
|
||||
<template #label>
|
||||
<a-space>
|
||||
<j-space>
|
||||
最大长度
|
||||
<a-tooltip title="字节">
|
||||
<j-tooltip title="字节">
|
||||
<question-circle-outlined style="color: rgb(136, 136, 136); font-size: 12px;" />
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</j-tooltip>
|
||||
</j-space>
|
||||
</template>
|
||||
<a-input-number v-model:value="_value.expands.maxLength" size="small" :max="2147483647" :min="1" :precision="0"
|
||||
style="width: 100%;"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label="元素配置" :name="name.concat(['elementType'])" v-if="['array'].includes(_value.type)">
|
||||
<j-input-number v-model:value="_value.expands.maxLength" size="small" :max="2147483647" :min="1" :precision="0"
|
||||
style="width: 100%;"></j-input-number>
|
||||
</j-form-item>
|
||||
<j-form-item label="元素配置" :name="name.concat(['elementType'])" v-if="['array'].includes(_value.type)" :rules="[
|
||||
{ validator: validateArray }
|
||||
]">
|
||||
<ArrayParam v-model:value="_value.elementType" :name="name.concat(['elementType'])"></ArrayParam>
|
||||
</a-form-item>
|
||||
<a-form-item label="JSON对象" :name="name.concat(['properties'])" v-if="['object'].includes(_value.type)" :rules="[]">
|
||||
</j-form-item>
|
||||
<j-form-item label="JSON对象" :name="name.concat(['properties'])" v-if="['object'].includes(_value.type)" :rules="[
|
||||
{ validator: validateJson }
|
||||
]">
|
||||
<JsonParam v-model:value="_value.properties" :name="name.concat(['properties'])"></JsonParam>
|
||||
</a-form-item>
|
||||
<a-form-item label="文件类型" :name="name.concat(['fileType'])" v-if="['file'].includes(_value.type)" initialValue="url"
|
||||
</j-form-item>
|
||||
<j-form-item label="文件类型" :name="name.concat(['fileType'])" v-if="['file'].includes(_value.type)" initialValue="url"
|
||||
:rules="[
|
||||
{ required: true, message: '请选择文件类型' },
|
||||
]">
|
||||
<a-select v-model:value="_value.fileType" :options="FileTypeList" size="small"></a-select>
|
||||
</a-form-item>
|
||||
<j-select v-model:value="_value.fileType" :options="FileTypeList" size="small"></j-select>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<script lang="ts" setup mame="BaseForm">
|
||||
import { DataTypeList, FileTypeList } from '@/views/device/data';
|
||||
|
@ -56,6 +62,8 @@ import EnumParam from '@/components/Metadata/EnumParam/index.vue'
|
|||
import ArrayParam from '@/components/Metadata/ArrayParam/index.vue'
|
||||
import JsonParam from '@/components/Metadata/JsonParam/index.vue'
|
||||
import { useMetadataStore } from '@/store/metadata';
|
||||
import { Rule } from 'ant-design-vue/es/form';
|
||||
import { Form } from 'ant-design-vue/es';
|
||||
|
||||
type ValueType = Record<any, any>;
|
||||
const props = defineProps({
|
||||
|
@ -84,15 +92,8 @@ interface Emits {
|
|||
}
|
||||
const emit = defineEmits<Emits>()
|
||||
|
||||
// emit('update:value', { extends: {}, ...props.value })
|
||||
|
||||
const metadataStore = useMetadataStore()
|
||||
// const _value = computed({
|
||||
// get: () => props.value,
|
||||
// set: val => {
|
||||
// emit('update:value', val)
|
||||
// }
|
||||
// })
|
||||
|
||||
const _value = ref<ValueType>({})
|
||||
watchEffect(() => {
|
||||
_value.value = props.value || {
|
||||
|
@ -142,6 +143,79 @@ const eventDataTypeList = [
|
|||
const changeType = (val: SelectValue) => {
|
||||
emit('changeType', val as string)
|
||||
}
|
||||
|
||||
const validateEnum = async (_rule: Rule, val: Record<any, any>[]) => {
|
||||
if (val.length === 0) return Promise.reject(new Error('请配置枚举项'));
|
||||
const flag = val.every((item) => {
|
||||
return item.value && item.text;
|
||||
});
|
||||
if (!flag) {
|
||||
return Promise.reject(new Error('请配置枚举项'));
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const validateArray = async (_rule: Rule, val: Record<any, any>) => {
|
||||
if (!val) return Promise.reject(new Error('请输入元素配置'));
|
||||
await validateValueType(_rule, val)
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const validateJson = async (_rule: Rule, val: Record<any, any>[]) => {
|
||||
if (!val || val.length === 0) {
|
||||
return Promise.reject(new Error('请输入配置参数'));
|
||||
}
|
||||
for (let item of val) {
|
||||
if (!item) return Promise.reject(new Error('请输入配置参数'));
|
||||
await validateValueType(_rule, item)
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const validateValueType = async (_rule: Rule, val: Record<any, any>) => {
|
||||
if (!val) return Promise.reject(new Error('请输入元素配置'));
|
||||
if (!val.id) {
|
||||
return Promise.reject(new Error('请输入标识'))
|
||||
}
|
||||
if (!val.name) {
|
||||
return Promise.reject(new Error('请输入名称'))
|
||||
}
|
||||
if (metadataStore.model.type !== 'functions' && !val.valueType?.type) {
|
||||
return Promise.reject(new Error(`请选择${props.title}`))
|
||||
}
|
||||
if (['enum'].includes(val.valueType.type)) {
|
||||
await validateEnum(_rule, val.valueType.elements)
|
||||
}
|
||||
if (['array'].includes(val.valueType.type)) {
|
||||
await validateArray(_rule, val.valueType.elementType)
|
||||
}
|
||||
if (['object'].includes(val.valueType.type)) {
|
||||
await validateJson(_rule, val.valueType.properties)
|
||||
}
|
||||
if (['file'].includes(val.valueType.type) && !val.valueType.fileType) {
|
||||
return Promise.reject(new Error('请选择文件类型'))
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
// const rules = ref({
|
||||
// type: [
|
||||
// metadataStore.model.type !== 'functions' ? { required: true, message: `请选择${props.title}` } : {},
|
||||
// ],
|
||||
// elements: [
|
||||
// { required: true, validator: validateEnum, message: '请配置枚举项' }
|
||||
// ],
|
||||
// elementType: [
|
||||
// { validator: validateArray, message: '请输入元素配置' }
|
||||
// ],
|
||||
// properties: [
|
||||
// { validator: validateJson, message: '请输入配置参数' }
|
||||
// ],
|
||||
// fileType: [
|
||||
// { required: true, message: '请选择文件类型' },
|
||||
// ]
|
||||
// })
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
:deep(.ant-form-item-label) {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<template>
|
||||
<a-drawer :mask-closable="false" width="25vw" visible :title="`${title}-${typeMapping[metadataStore.model.type]}`"
|
||||
<j-drawer :mask-closable="false" width="25vw" visible :title="`${title}-${typeMapping[metadataStore.model.type]}`"
|
||||
@close="close" destroy-on-close :z-index="1000" placement="right">
|
||||
<template #extra>
|
||||
<a-button :loading="save.loading" type="primary" @click="save.saveMetadata">保存</a-button>
|
||||
<j-button :loading="save.loading" type="primary" @click="save.saveMetadata">保存</j-button>
|
||||
</template>
|
||||
<a-form ref="formRef" :model="form.model" layout="vertical">
|
||||
<j-form ref="formRef" :model="form.model" layout="vertical">
|
||||
<BaseForm :model-type="metadataStore.model.type" :type="type" v-model:value="form.model"></BaseForm>
|
||||
</a-form>
|
||||
</a-drawer>
|
||||
</j-form>
|
||||
</j-drawer>
|
||||
</template>
|
||||
<script lang="ts" setup name="Edit">
|
||||
import { useInstanceStore } from '@/store/instance';
|
||||
|
@ -22,6 +22,7 @@ import { DeviceInstance } from '@/views/device/Instance/typings';
|
|||
import BaseForm from './BaseForm.vue';
|
||||
import { PropType } from 'vue';
|
||||
import { _deploy } from '@/api/device/product';
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
const props = defineProps({
|
||||
type: {
|
||||
|
@ -60,7 +61,7 @@ const form = reactive({
|
|||
model: {} as any,
|
||||
})
|
||||
if (metadataStore.model.action === 'edit') {
|
||||
form.model = metadataStore.model.item
|
||||
form.model = cloneDeep(metadataStore.model.item)
|
||||
}
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
|
@ -75,7 +76,9 @@ const save = reactive({
|
|||
const type = metadataStore.model.type
|
||||
const _detail: ProductItem | DeviceInstance = props.type === 'device' ? instanceStore.detail : productStore.current
|
||||
const _metadata = JSON.parse(_detail?.metadata || '{}')
|
||||
const list = _metadata[type] as any[]
|
||||
console.log(_metadata)
|
||||
console.log(type)
|
||||
const list = (_metadata[type] as any[]) || []
|
||||
if (formValue.id) {
|
||||
if (metadataStore.model.action === 'add' && list.some(item => item.id === formValue.id)) {
|
||||
message.error('标识已存在')
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<j-pro-table :loading="loading" :data-source="data" size="small" :columns="columns" row-key="id" model="TABLE">
|
||||
<template #headerTitle>
|
||||
<a-input-search v-model:value="searchValue" placeholder="请输入名称" @search="handleSearch"></a-input-search>
|
||||
<j-input-search v-model:value="searchValue" placeholder="请输入名称" @search="handleSearch"></j-input-search>
|
||||
</template>
|
||||
<template #rightExtraRender>
|
||||
<PermissionButton type="primary" :uhas-permission="`${permission}:update`" key="add" @click="handleAddClick"
|
||||
|
@ -135,6 +135,13 @@ const refreshMetadata = () => {
|
|||
watch([route.params.id, type], refreshMetadata, { immediate: true })
|
||||
|
||||
const metadataStore = useMetadataStore()
|
||||
watch(() => metadataStore.model.importMetadata,
|
||||
(val: boolean) => {
|
||||
if (!!val) {
|
||||
refreshMetadata()
|
||||
metadataStore.set('importMetadata', false)
|
||||
}
|
||||
})
|
||||
const handleAddClick = () => {
|
||||
metadataStore.set('edit', true)
|
||||
metadataStore.set('item', undefined)
|
||||
|
@ -189,6 +196,4 @@ const removeItem = async (record: MetadataItem) => {
|
|||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
|
||||
</style>
|
||||
<style scoped lang="less"></style>
|
|
@ -1,13 +1,13 @@
|
|||
<template>
|
||||
<a-drawer :mask-closable="false" title="查看物模型" width="700" v-model:visible="_visible" destroy-on-close @close="close">
|
||||
<j-drawer :mask-closable="false" title="查看物模型" width="700" v-model:visible="_visible" destroy-on-close @close="close">
|
||||
<template #extra>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="handleExport">
|
||||
<j-space>
|
||||
<j-button type="primary" @click="handleExport">
|
||||
导出
|
||||
</a-button>
|
||||
</a-space>
|
||||
</j-button>
|
||||
</j-space>
|
||||
</template>
|
||||
<a-spin :spinning="loading">
|
||||
<j-spin :spinning="loading">
|
||||
<div class="cat-content">
|
||||
<p class="cat-tip">
|
||||
物模型是对设备在云端的功能描述,包括设备的属性、服务和事件。物联网平台通过定义一种物的描述语言来描述物模型,称之为
|
||||
|
@ -15,15 +15,15 @@
|
|||
组装上报设备的数据。您可以导出完整物模型,用于云端应用开发。
|
||||
</p>
|
||||
</div>
|
||||
<a-tabs @change="handleConvertMetadata" destroy-inactive-tab-pane>
|
||||
<a-tab-pane v-for="item in codecs" :key="item.id" :tab="item.name">
|
||||
<j-tabs @change="handleConvertMetadata" destroy-inactive-tab-pane>
|
||||
<j-tab-pane v-for="item in codecs" :key="item.id" :tab="item.name">
|
||||
<div class="cat-panel">
|
||||
<MonacoEditor v-model="value" theme="vs" style="height: 100%"></MonacoEditor>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-spin>
|
||||
</a-drawer>
|
||||
</j-tab-pane>
|
||||
</j-tabs>
|
||||
</j-spin>
|
||||
</j-drawer>
|
||||
</template>
|
||||
<script setup lang="ts" name="Cat">
|
||||
import { message } from 'ant-design-vue/es';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-modal :mask-closable="false" title="导入物模型" destroy-on-close v-model:visible="_visible" @cancel="close"
|
||||
<j-modal :mask-closable="false" title="导入物模型" destroy-on-close v-model:visible="_visible" @cancel="close"
|
||||
@ok="handleImport" :confirm-loading="loading">
|
||||
<div class="import-content">
|
||||
<p class="import-tip">
|
||||
|
@ -7,46 +7,46 @@
|
|||
导入的物模型会覆盖原来的属性、功能、事件、标签,请谨慎操作。
|
||||
</p>
|
||||
</div>
|
||||
<a-form layout="vertical" v-model="formModel">
|
||||
<a-form-item v-if="type === 'product'" label="导入方式" v-bind="validateInfos.type">
|
||||
<a-select v-model:value="formModel.type">
|
||||
<a-select-option value="copy">拷贝产品</a-select-option>
|
||||
<a-select-option value="import">导入物模型</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="选择产品" v-bind="validateInfos.copy" v-if="formModel.type === 'copy'">
|
||||
<a-select :options="productList" v-model:value="formModel.copy" option-filter-prop="label"></a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="物模型类型" v-bind="validateInfos.metadata"
|
||||
<j-form layout="vertical" v-model="formModel">
|
||||
<j-form-item v-if="type === 'product'" label="导入方式" v-bind="validateInfos.type">
|
||||
<j-select v-model:value="formModel.type">
|
||||
<j-select-option value="copy">拷贝产品</j-select-option>
|
||||
<j-select-option value="import">导入物模型</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<j-form-item label="选择产品" v-bind="validateInfos.copy" v-if="formModel.type === 'copy'">
|
||||
<j-select :options="productList" v-model:value="formModel.copy" option-filter-prop="label"></j-select>
|
||||
</j-form-item>
|
||||
<j-form-item label="物模型类型" v-bind="validateInfos.metadata"
|
||||
v-if="type === 'device' || formModel.type === 'import'">
|
||||
<a-select v-model:value="formModel.metadata">
|
||||
<a-select-option value="jetlinks">Jetlinks物模型</a-select-option>
|
||||
<a-select-option value="alink">阿里云物模型TSL</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="导入类型" v-bind="validateInfos.metadataType"
|
||||
<j-select v-model:value="formModel.metadata">
|
||||
<j-select-option value="jetlinks">Jetlinks物模型</j-select-option>
|
||||
<j-select-option value="alink">阿里云物模型TSL</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<j-form-item label="导入类型" v-bind="validateInfos.metadataType"
|
||||
v-if="type === 'device' || formModel.type === 'import'">
|
||||
<a-select v-model:value="formModel.metadataType">
|
||||
<a-select-option value="file">文件上传</a-select-option>
|
||||
<a-select-option value="script">脚本</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="文件上传" v-bind="validateInfos.upload" v-if="formModel.metadataType === 'file'">
|
||||
<a-input v-model:value="formModel.upload">
|
||||
<j-select v-model:value="formModel.metadataType">
|
||||
<j-select-option value="file">文件上传</j-select-option>
|
||||
<j-select-option value="script">脚本</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<j-form-item label="文件上传" v-bind="validateInfos.upload" v-if="formModel.metadataType === 'file'">
|
||||
<j-input v-model:value="formModel.upload">
|
||||
<template #addonAfter>
|
||||
<a-upload v-model:file-list="fileList" :before-upload="beforeUpload" accept=".json"
|
||||
<j-upload v-model:file-list="fileList" :before-upload="beforeUpload" accept=".json"
|
||||
:show-upload-list="false" :action="FILE_UPLOAD" @change="fileChange"
|
||||
:headers="{ 'X-Access-Token': getToken()}">
|
||||
<AIcon type="UploadOutlined" class="upload-button" />
|
||||
</a-upload>
|
||||
</j-upload>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="物模型" v-bind="validateInfos.import" v-if="formModel.metadataType === 'script'">
|
||||
</j-input>
|
||||
</j-form-item>
|
||||
<j-form-item label="物模型" v-bind="validateInfos.import" v-if="formModel.metadataType === 'script'">
|
||||
<MonacoEditor v-model="formModel.import" theme="vs" style="height: 300px"></MonacoEditor>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</j-modal>
|
||||
</template>
|
||||
<script setup lang="ts" name="Import">
|
||||
import { useForm } from 'ant-design-vue/es/form';
|
||||
|
@ -54,13 +54,14 @@ import { saveMetadata } from '@/api/device/instance'
|
|||
import { queryNoPagingPost, convertMetadata, modify } from '@/api/device/product'
|
||||
import type { DefaultOptionType } from 'ant-design-vue/es/select';
|
||||
import type { UploadProps, UploadFile, UploadChangeParam } from 'ant-design-vue/es';
|
||||
import type { DeviceMetadata, ProductItem } from '@/views/device/Product/typings'
|
||||
import { message } from 'ant-design-vue/es';
|
||||
import type { DeviceMetadata } from '@/views/device/Product/typings'
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import { useInstanceStore } from '@/store/instance'
|
||||
import { useProductStore } from '@/store/product';
|
||||
import { FILE_UPLOAD } from '@/api/comm';
|
||||
import { getToken } from '@/utils/comm';
|
||||
import MonacoEditor from '@/components/MonacoEditor/index.vue'
|
||||
import { useMetadataStore } from '@/store/metadata';
|
||||
|
||||
const route = useRoute()
|
||||
const instanceStore = useInstanceStore()
|
||||
|
@ -87,7 +88,6 @@ const _visible = computed({
|
|||
})
|
||||
|
||||
const close = () => {
|
||||
console.log(1)
|
||||
emits('update:visible', false);
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@ const operateLimits = (mdata: DeviceMetadata) => {
|
|||
});
|
||||
return obj;
|
||||
};
|
||||
|
||||
const metadataStore = useMetadataStore()
|
||||
const handleImport = async () => {
|
||||
validate().then(async (data) => {
|
||||
loading.value = true
|
||||
|
@ -224,6 +224,7 @@ const handleImport = async () => {
|
|||
} else {
|
||||
productStore.refresh(id as string)
|
||||
}
|
||||
metadataStore.set('importMetadata', true)
|
||||
// Store.set(SystemConst.GET_METADATA, true)
|
||||
// Store.set(SystemConst.REFRESH_METADATA_TABLE, true)
|
||||
close()
|
||||
|
@ -263,13 +264,14 @@ const handleImport = async () => {
|
|||
message.success('导入成功')
|
||||
}
|
||||
}
|
||||
// Store.set(SystemConst.GET_METADATA, true)
|
||||
// Store.set(SystemConst.REFRESH_METADATA_TABLE, true)
|
||||
if (props?.type === 'device') {
|
||||
instanceStore.refresh(id as string)
|
||||
} else {
|
||||
productStore.refresh(id as string)
|
||||
}
|
||||
metadataStore.set('importMetadata', true)
|
||||
// Store.set(SystemConst.GET_METADATA, true)
|
||||
// Store.set(SystemConst.REFRESH_METADATA_TABLE, true)
|
||||
close();
|
||||
} catch (e) {
|
||||
loading.value = false
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!-- 国标级联-绑定通道 -->
|
||||
<template>
|
||||
<a-modal
|
||||
<j-modal
|
||||
v-model:visible="_vis"
|
||||
title="绑定通道"
|
||||
cancelText="取消"
|
||||
|
@ -51,19 +51,19 @@
|
|||
<h3>通道列表</h3>
|
||||
</template>
|
||||
<template #status="slotProps">
|
||||
<a-space>
|
||||
<a-badge
|
||||
<j-space>
|
||||
<j-badge
|
||||
:status="
|
||||
slotProps.status.value === 'online'
|
||||
? 'success'
|
||||
: 'error'
|
||||
"
|
||||
:text="slotProps.status.text"
|
||||
></a-badge>
|
||||
</a-space>
|
||||
></j-badge>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</a-modal>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -28,34 +28,34 @@
|
|||
<h3>通道列表</h3>
|
||||
</template>
|
||||
<template #rightExtraRender>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="bindVis = true">
|
||||
<j-space>
|
||||
<j-button type="primary" @click="bindVis = true">
|
||||
绑定通道
|
||||
</a-button>
|
||||
<a-popconfirm
|
||||
</j-button>
|
||||
<j-popconfirm
|
||||
title="确认解绑?"
|
||||
@confirm="handleMultipleUnbind"
|
||||
>
|
||||
<a-button> 批量解绑 </a-button>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
<j-button> 批量解绑 </j-button>
|
||||
</j-popconfirm>
|
||||
</j-space>
|
||||
</template>
|
||||
<template #gbChannelIdHeader="title">
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="国标级联有16位、20位两种格式。在当前页面修改不会修改视频设备-通道页面中的国标ID"
|
||||
>
|
||||
<a-space>
|
||||
<j-space>
|
||||
<span>{{ title }}</span>
|
||||
<AIcon type="InfoCircleOutlined" />
|
||||
</a-space>
|
||||
</a-tooltip>
|
||||
</j-space>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
<template #gbChannelId="slotProps">
|
||||
<a-space>
|
||||
<j-space>
|
||||
<Ellipsis>
|
||||
{{ slotProps.gbChannelId }}
|
||||
</Ellipsis>
|
||||
<a-popover
|
||||
<j-popover
|
||||
v-model:visible="slotProps.popVis"
|
||||
trigger="click"
|
||||
>
|
||||
|
@ -70,7 +70,7 @@
|
|||
</template>
|
||||
<template #content>
|
||||
<div class="simple-form">
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="gbID"
|
||||
@change="validField(slotProps)"
|
||||
/>
|
||||
|
@ -82,67 +82,67 @@
|
|||
该国标ID在同一设备下已存在
|
||||
</div>
|
||||
</div>
|
||||
<a-button
|
||||
<j-button
|
||||
type="primary"
|
||||
@click="handleSave(slotProps)"
|
||||
:loading="loading"
|
||||
style="width: 100%"
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
</j-button>
|
||||
</template>
|
||||
<a-button type="link" @click="slotProps.popVis = true">
|
||||
<j-button type="link" @click="slotProps.popVis = true">
|
||||
<AIcon type="EditOutlined" />
|
||||
</a-button>
|
||||
</a-popover>
|
||||
</a-space>
|
||||
</j-button>
|
||||
</j-popover>
|
||||
</j-space>
|
||||
</template>
|
||||
<template #status="slotProps">
|
||||
<a-space>
|
||||
<a-badge
|
||||
<j-space>
|
||||
<j-badge
|
||||
:status="
|
||||
slotProps.status.value === 'online'
|
||||
? 'success'
|
||||
: 'error'
|
||||
"
|
||||
:text="slotProps.status.text"
|
||||
></a-badge>
|
||||
</a-space>
|
||||
></j-badge>
|
||||
</j-space>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
<j-space :size="16">
|
||||
<j-tooltip
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<a-popconfirm
|
||||
<j-popconfirm
|
||||
v-if="i.popConfirm"
|
||||
v-bind="i.popConfirm"
|
||||
:disabled="i.disabled"
|
||||
>
|
||||
<a-button
|
||||
<j-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
/></j-button>
|
||||
</j-popconfirm>
|
||||
<j-button
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
v-else
|
||||
@click="i.onClick && i.onClick(slotProps)"
|
||||
>
|
||||
<a-button
|
||||
<j-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
/></j-button>
|
||||
</j-button>
|
||||
</j-tooltip>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!-- 国标级联-推送 -->
|
||||
<template>
|
||||
<a-modal
|
||||
<j-modal
|
||||
v-model:visible="_vis"
|
||||
title="推送"
|
||||
cancelText="取消"
|
||||
|
@ -9,10 +9,10 @@
|
|||
@ok="_vis = false"
|
||||
@cancel="_vis = false"
|
||||
>
|
||||
<a-row :gutter="20">
|
||||
<a-col :span="8">
|
||||
<j-row :gutter="20">
|
||||
<j-col :span="8">
|
||||
<p>成功:{{ successCount }}</p>
|
||||
<a-space>
|
||||
<j-space>
|
||||
<p>失败:{{ failCount }}</p>
|
||||
<a
|
||||
v-if="errMessage.length"
|
||||
|
@ -24,19 +24,19 @@
|
|||
"
|
||||
>下载</a
|
||||
>
|
||||
</a-space>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
</j-space>
|
||||
</j-col>
|
||||
<j-col :span="8">
|
||||
<p>推送通道数量:{{ data.count }}</p>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
</j-col>
|
||||
<j-col :span="8">
|
||||
<p>已推送通道数量:{{ successCount + failCount }}</p>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</j-col>
|
||||
</j-row>
|
||||
<div v-if="flag">
|
||||
<a-textarea :rows="10" v-model:value="errStr" />
|
||||
<j-textarea :rows="10" v-model:value="errStr" />
|
||||
</div>
|
||||
</a-modal>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<!-- 国标级联新增/编辑 -->
|
||||
<template>
|
||||
<page-container>
|
||||
<a-card>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="12">
|
||||
<a-form ref="formRef" layout="vertical" :model="formData">
|
||||
<a-row :gutter="24">
|
||||
<j-card>
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="12">
|
||||
<j-form ref="formRef" layout="vertical" :model="formData">
|
||||
<j-row :gutter="24">
|
||||
<TitleComponent data="基本信息" />
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="名称"
|
||||
name="cascadeName"
|
||||
:rules="[
|
||||
|
@ -22,14 +22,14 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.cascadeName"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="代理视频流"
|
||||
name="proxyStream"
|
||||
:rules="[
|
||||
|
@ -39,23 +39,23 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-radio-group
|
||||
<j-radio-group
|
||||
button-style="solid"
|
||||
v-model:value="formData.proxyStream"
|
||||
>
|
||||
<a-radio-button :value="true">
|
||||
<j-radio-button :value="true">
|
||||
启用
|
||||
</a-radio-button>
|
||||
<a-radio-button :value="false">
|
||||
</j-radio-button>
|
||||
<j-radio-button :value="false">
|
||||
禁用
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</j-radio-button>
|
||||
</j-radio-group>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
|
||||
<TitleComponent data="信令服务配置" />
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
name="clusterNodeId"
|
||||
:rules="[
|
||||
{
|
||||
|
@ -67,25 +67,25 @@
|
|||
<template #label>
|
||||
<span>
|
||||
集群节点
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="使用此集群节点级联到上级平台"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-select
|
||||
<j-select
|
||||
v-model:value="formData.clusterNodeId"
|
||||
placeholder="请选择集群节点"
|
||||
:options="clustersList"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="信令名称"
|
||||
name="name"
|
||||
:rules="[
|
||||
|
@ -99,14 +99,14 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.name"
|
||||
placeholder="请输入信令名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
label="上级SIP ID"
|
||||
name="sipId"
|
||||
:rules="[
|
||||
|
@ -120,14 +120,14 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.sipId"
|
||||
placeholder="请输入上级SIP ID"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="上级SIP域"
|
||||
name="domain"
|
||||
:rules="[
|
||||
|
@ -141,14 +141,14 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.domain"
|
||||
placeholder="请输入上级平台SIP域"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="上级SIP 地址"
|
||||
name="remoteAddress"
|
||||
:rules="[
|
||||
|
@ -161,17 +161,17 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-row :gutter="10">
|
||||
<a-col :span="14">
|
||||
<a-input
|
||||
<j-row :gutter="10">
|
||||
<j-col :span="14">
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.remoteAddress
|
||||
"
|
||||
placeholder="请输入IP地址"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="10">
|
||||
<a-input-number
|
||||
</j-col>
|
||||
<j-col :span="10">
|
||||
<j-input-number
|
||||
:min="1"
|
||||
:max="65535"
|
||||
v-model:value="
|
||||
|
@ -180,13 +180,13 @@
|
|||
placeholder="请输入端口"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
label="本地SIP ID"
|
||||
name="localSipId"
|
||||
:rules="[
|
||||
|
@ -200,14 +200,14 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.localSipId"
|
||||
placeholder="网关侧的SIP ID"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
name="host"
|
||||
:rules="[
|
||||
{
|
||||
|
@ -222,36 +222,36 @@
|
|||
<template #label>
|
||||
<span>
|
||||
SIP本地地址
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="使用指定的网卡和端口进行请求"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-row :gutter="10">
|
||||
<a-col :span="14">
|
||||
<a-select
|
||||
<j-row :gutter="10">
|
||||
<j-col :span="14">
|
||||
<j-select
|
||||
v-model:value="formData.host"
|
||||
placeholder="请选择IP地址"
|
||||
:options="allList"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="10">
|
||||
<a-select
|
||||
</j-col>
|
||||
<j-col :span="10">
|
||||
<j-select
|
||||
v-model:value="formData.port"
|
||||
placeholder="请选择端口"
|
||||
:options="allListPorts"
|
||||
/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="SIP远程地址"
|
||||
name="publicHost"
|
||||
:rules="[
|
||||
|
@ -264,17 +264,17 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-row :gutter="10">
|
||||
<a-col :span="14">
|
||||
<a-input
|
||||
<j-row :gutter="10">
|
||||
<j-col :span="14">
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.publicHost
|
||||
"
|
||||
placeholder="请输入IP地址"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="10">
|
||||
<a-input-number
|
||||
</j-col>
|
||||
<j-col :span="10">
|
||||
<j-input-number
|
||||
:min="1"
|
||||
:max="65535"
|
||||
v-model:value="
|
||||
|
@ -283,12 +283,12 @@
|
|||
placeholder="请输入端口"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
label="传输协议"
|
||||
name="transport"
|
||||
:rules="[
|
||||
|
@ -298,22 +298,22 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-radio-group
|
||||
<j-radio-group
|
||||
button-style="solid"
|
||||
v-model:value="formData.transport"
|
||||
@change="setPorts"
|
||||
>
|
||||
<a-radio-button value="UDP">
|
||||
<j-radio-button value="UDP">
|
||||
UDP
|
||||
</a-radio-button>
|
||||
<a-radio-button value="TCP">
|
||||
</j-radio-button>
|
||||
<j-radio-button value="TCP">
|
||||
TCP
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-radio-button>
|
||||
</j-radio-group>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="用户"
|
||||
name="user"
|
||||
:rules="[
|
||||
|
@ -327,14 +327,14 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.user"
|
||||
placeholder="请输入用户"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="接入密码"
|
||||
name="password"
|
||||
:rules="[
|
||||
|
@ -348,14 +348,14 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-input-password
|
||||
<j-input-password
|
||||
v-model:value="formData.password"
|
||||
placeholder="请输入接入密码"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="厂商"
|
||||
name="manufacturer"
|
||||
:rules="[
|
||||
|
@ -369,14 +369,14 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.manufacturer"
|
||||
placeholder="请输入厂商"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="型号"
|
||||
name="model"
|
||||
:rules="[
|
||||
|
@ -390,14 +390,14 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.model"
|
||||
placeholder="请输入型号"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="版本号"
|
||||
name="firmware"
|
||||
:rules="[
|
||||
|
@ -411,14 +411,14 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.firmware"
|
||||
placeholder="请输入版本号"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="心跳周期(秒)"
|
||||
name="keepaliveInterval"
|
||||
:rules="[
|
||||
|
@ -428,7 +428,7 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-input-number
|
||||
<j-input-number
|
||||
:min="1"
|
||||
:max="10000"
|
||||
v-model:value="
|
||||
|
@ -437,10 +437,10 @@
|
|||
placeholder="请输入心跳周期"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
label="注册间隔(秒)"
|
||||
name="registerInterval"
|
||||
:rules="[
|
||||
|
@ -450,7 +450,7 @@
|
|||
},
|
||||
]"
|
||||
>
|
||||
<a-input-number
|
||||
<j-input-number
|
||||
:min="1"
|
||||
:max="10000"
|
||||
v-model:value="
|
||||
|
@ -459,29 +459,29 @@
|
|||
placeholder="请输入注册间隔"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
|
||||
<a-form-item>
|
||||
<a-button
|
||||
<j-form-item>
|
||||
<j-button
|
||||
type="primary"
|
||||
@click="handleSubmit"
|
||||
:loading="btnLoading"
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
</j-button>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<div class="doc">
|
||||
<h1>1.概述</h1>
|
||||
<div>
|
||||
配置国标级联,平台可以将已经接入到自身的摄像头共享给第三方调用播放。
|
||||
</div>
|
||||
<div>
|
||||
<a-alert
|
||||
<j-alert
|
||||
message="注:该配置只用于将本平台向上级联至第三方平台,如需第三方平台向上级联至本平台,请在“视频设备”页面新增设备时选择“GB/T28181”接入方式。"
|
||||
type="info"
|
||||
show-icon
|
||||
|
@ -494,7 +494,7 @@
|
|||
<h2>1、上级SIP ID</h2>
|
||||
<div>请填写第三方平台中配置的<b>SIP ID</b>。</div>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/northbound/doc2.png')"
|
||||
/>
|
||||
|
@ -502,7 +502,7 @@
|
|||
<h2>2、上级SIP 域</h2>
|
||||
<div>请填写第三方平台中配置的<b>SIP ID域</b>。</div>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/northbound/doc1.png')"
|
||||
/>
|
||||
|
@ -510,7 +510,7 @@
|
|||
<h2>3、上级SIP 地址</h2>
|
||||
<div>请填写第三方平台中配置的<b>SIP ID地址</b>。</div>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/northbound/doc3.png')"
|
||||
/>
|
||||
|
@ -549,9 +549,9 @@
|
|||
SIP代理与 SIP服务器出现1s误 差所经过的运行时间。
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-card>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
@ -652,7 +652,7 @@ onMounted(() => {
|
|||
});
|
||||
|
||||
const regDomain =
|
||||
/[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?/;
|
||||
/[j-zA-Z0-9][-j-zA-Z0-9]{0,62}(\.[j-zA-Z0-9][-j-zA-Z0-9]{0,62})+\.?/;
|
||||
/**
|
||||
* 上级SIP地址 字段验证
|
||||
* @param _
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
</h3>
|
||||
<p>通道数量:{{ slotProps.count }}</p>
|
||||
<Ellipsis>
|
||||
<a-badge
|
||||
<j-badge
|
||||
:text="`sip:${slotProps.sipConfigs[0]?.sipId}@${slotProps.sipConfigs[0]?.hostAndPort}`"
|
||||
:status="
|
||||
slotProps.status?.value === 'enabled'
|
||||
|
@ -92,7 +92,7 @@
|
|||
{{ slotProps.sipConfigs[0]?.publicHost }}
|
||||
</template>
|
||||
<template #status="slotProps">
|
||||
<a-badge
|
||||
<j-badge
|
||||
:text="slotProps.status?.text"
|
||||
:status="
|
||||
slotProps.status?.value === 'enabled'
|
||||
|
@ -102,7 +102,7 @@
|
|||
/>
|
||||
</template>
|
||||
<template #onlineStatus="slotProps">
|
||||
<a-badge
|
||||
<j-badge
|
||||
:text="slotProps.onlineStatus?.text"
|
||||
:status="
|
||||
slotProps.onlineStatus?.value === 'online'
|
||||
|
@ -112,7 +112,7 @@
|
|||
/>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<j-space :size="16">
|
||||
<template
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
:key="i.key"
|
||||
|
@ -131,7 +131,7 @@
|
|||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
|
||||
|
|
|
@ -3,26 +3,26 @@
|
|||
<div class="card-header">
|
||||
<div class="title">{{ title }}</div>
|
||||
<div class="tools">
|
||||
<a-space>
|
||||
<a-radio-group
|
||||
<j-space>
|
||||
<j-radio-group
|
||||
v-model:value="dimension"
|
||||
button-style="solid"
|
||||
>
|
||||
<a-radio-button value="today">今日</a-radio-button>
|
||||
<a-radio-button value="week">近一周</a-radio-button>
|
||||
<a-radio-button value="month">近一月</a-radio-button>
|
||||
<a-radio-button value="year">近一年</a-radio-button>
|
||||
</a-radio-group>
|
||||
<a-range-picker
|
||||
<j-radio-button value="today">今日</j-radio-button>
|
||||
<j-radio-button value="week">近一周</j-radio-button>
|
||||
<j-radio-button value="month">近一月</j-radio-button>
|
||||
<j-radio-button value="year">近一年</j-radio-button>
|
||||
</j-radio-group>
|
||||
<j-range-picker
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
valueFormat="x"
|
||||
v-model:value="dateRange"
|
||||
/>
|
||||
</a-space>
|
||||
</j-space>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="chartData.length" class="chart" ref="chartRef"></div>
|
||||
<a-empty v-else class="no-data" description="暂无数据"></a-empty>
|
||||
<j-empty v-else class="no-data" description="暂无数据"></j-empty>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -56,52 +56,49 @@ const chartRef = ref();
|
|||
const createChart = () => {
|
||||
nextTick(() => {
|
||||
const myChart = echarts.init(chartRef.value as HTMLElement);
|
||||
|
||||
const sData: number[] = props.chartData.map(
|
||||
(m: any) => m.value && m.value.toFixed(2),
|
||||
);
|
||||
const maxY = Math.max.apply(null, sData.length ? sData : [0]);
|
||||
const options = {
|
||||
grid: {
|
||||
left: '7%',
|
||||
left: maxY > 100000 ? 90 : 50,
|
||||
right: '5%',
|
||||
top: '5%',
|
||||
bottom: '5%',
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
// formatter: '{a}<br>{b}: {c}',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
},
|
||||
formatter: '{b0}<br />{a0}: {c0}',
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: props.chartData.map((m: any) => m.x),
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
// minInterval: 1,
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
data: props.chartData.map((m: any) => m.x),
|
||||
},
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
show: false,
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
type: 'solid',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '播放数量(人次)',
|
||||
data: sData,
|
||||
type: 'bar',
|
||||
barWidth: 16,
|
||||
itemStyle: {
|
||||
color: '#2f54eb',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '播放数量(人次)',
|
||||
type: 'line',
|
||||
symbol: 'circle',
|
||||
showSymbol: false,
|
||||
smooth: true,
|
||||
data: props.chartData.map(
|
||||
(m: any) => m.value && m.value.toFixed(2),
|
||||
),
|
||||
lineStyle: {
|
||||
color: '#a5fff9',
|
||||
},
|
||||
data: sData,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@ -116,8 +113,6 @@ const createChart = () => {
|
|||
watch(
|
||||
() => props.chartData,
|
||||
(val) => {
|
||||
console.log('createChart', val);
|
||||
|
||||
createChart();
|
||||
},
|
||||
{ deep: true },
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
<div class="content-left">
|
||||
<div class="content-left-title">
|
||||
<span>{{ title }}</span>
|
||||
<a-tooltip placement="top" v-if="tooltip">
|
||||
<j-tooltip placement="top" v-if="tooltip">
|
||||
<template #title>
|
||||
<span>{{ tooltip }}</span>
|
||||
</template>
|
||||
<AIcon type="QuestionCircleOutlined" />
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</div>
|
||||
<div class="content-left-value">{{ value }}</div>
|
||||
</div>
|
||||
|
@ -20,7 +20,7 @@
|
|||
<div class="top-card-footer">
|
||||
<template v-for="(item, index) in footer" :key="index">
|
||||
<span v-if="!item.status">{{ item.title }}</span>
|
||||
<a-badge v-else :text="item.title" :status="item.status" />
|
||||
<j-badge v-else :text="item.title" :status="item.status" />
|
||||
<div class="footer-item-value">{{ item.value }}</div>
|
||||
</template>
|
||||
</div>
|
||||
|
|
|
@ -123,6 +123,7 @@ const getAggData = () => {
|
|||
{
|
||||
title: '总时长',
|
||||
value: timestampFormat(res.result.duration),
|
||||
status: '',
|
||||
},
|
||||
];
|
||||
});
|
||||
|
@ -139,6 +140,7 @@ const getAggPlayingData = () => {
|
|||
{
|
||||
title: '播放人数',
|
||||
value: res.result.playerTotal,
|
||||
status: '',
|
||||
},
|
||||
];
|
||||
});
|
||||
|
@ -188,9 +190,11 @@ const getPlayCount = async (params: any) => {
|
|||
])
|
||||
.then((res) => {
|
||||
let result: any = [];
|
||||
res.result.forEach((item: any) => {
|
||||
result = [...result, ...item.data];
|
||||
});
|
||||
res.result
|
||||
.sort((a: any, b: any) => b.data.timestamp - a.data.timestamp)
|
||||
.forEach((item: any) => {
|
||||
result.push({ group: item.group, ...item.data });
|
||||
});
|
||||
chartData.value = result.map((m: any) => ({
|
||||
x: m.timeString,
|
||||
value: m.value,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!-- 视频设备 - 播放 -->
|
||||
<template>
|
||||
<a-modal
|
||||
<j-modal
|
||||
v-model:visible="_vis"
|
||||
title="播放"
|
||||
cancelText="取消"
|
||||
|
@ -33,17 +33,17 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="media-live-tool">
|
||||
<a-radio-group
|
||||
<j-radio-group
|
||||
v-model:value="mediaType"
|
||||
button-style="solid"
|
||||
@change="mediaStart"
|
||||
>
|
||||
<a-radio-button value="mp4">MP4</a-radio-button>
|
||||
<a-radio-button value="flv">FLV</a-radio-button>
|
||||
<a-radio-button value="m3u8">HLS</a-radio-button>
|
||||
</a-radio-group>
|
||||
<j-radio-button value="mp4">MP4</j-radio-button>
|
||||
<j-radio-button value="flv">FLV</j-radio-button>
|
||||
<j-radio-button value="m3u8">HLS</j-radio-button>
|
||||
</j-radio-group>
|
||||
</div>
|
||||
</a-modal>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!-- Modal 弹窗,用于新增、修改数据 -->
|
||||
<template>
|
||||
<a-modal
|
||||
<j-modal
|
||||
v-model:visible="_vis"
|
||||
:title="!!formData.id ? '编辑' : '新增'"
|
||||
width="650px"
|
||||
|
@ -9,10 +9,10 @@
|
|||
@ok="handleSubmit"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<a-form ref="formRef" :model="formData" layout="vertical">
|
||||
<a-row :gutter="10">
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
<j-form ref="formRef" :model="formData" layout="vertical">
|
||||
<j-row :gutter="10">
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
name="channelId"
|
||||
:rules="[
|
||||
{
|
||||
|
@ -26,22 +26,22 @@
|
|||
>
|
||||
<template #label>
|
||||
通道ID
|
||||
<a-tooltip title="若不填写,系统将自动生成唯一ID">
|
||||
<j-tooltip title="若不填写,系统将自动生成唯一ID">
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.channelId"
|
||||
:disabled="!!formData.id"
|
||||
placeholder="请输入通道ID"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
name="name"
|
||||
label="通道名称"
|
||||
:rules="[
|
||||
|
@ -49,14 +49,14 @@
|
|||
{ max: 64, message: '最多可输入64个字符' },
|
||||
]"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.name"
|
||||
placeholder="请输入通道名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
name="media_url"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入视频地址' },
|
||||
|
@ -65,66 +65,66 @@
|
|||
>
|
||||
<template #label>
|
||||
视频地址
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="不同厂家的RTSP固定地址规则不同,请按对应厂家的规则填写"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.media_url"
|
||||
placeholder="请输入视频地址"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
name="media_username"
|
||||
label="用户名"
|
||||
:rules="{ max: 64, message: '最多可输入64个字符' }"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.media_username"
|
||||
placeholder="请输入用户名"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
name="media_password"
|
||||
label="密码"
|
||||
:rules="{ max: 64, message: '最多可输入64个字符' }"
|
||||
>
|
||||
<a-input-password
|
||||
<j-input-password
|
||||
v-model:value="formData.media_password"
|
||||
placeholder="请输入密码"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item name="address" label="安装地址">
|
||||
<a-input
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-form-item name="address" label="安装地址">
|
||||
<j-input
|
||||
v-model:value="formData.address"
|
||||
placeholder="请输入安装地址"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item name="description" label="说明">
|
||||
<a-textarea
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-form-item name="description" label="说明">
|
||||
<j-textarea
|
||||
v-model:value="formData.description"
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
showCount
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-form>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -19,62 +19,62 @@
|
|||
model="table"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
v-if="route?.query.type === 'gb28181-2016'"
|
||||
title="接入方式为GB/T28281时,不支持新增"
|
||||
>
|
||||
<a-button type="primary" disabled> 新增 </a-button>
|
||||
</a-tooltip>
|
||||
<a-button type="primary" @click="handleAdd" v-else>
|
||||
<j-button type="primary" disabled> 新增 </j-button>
|
||||
</j-tooltip>
|
||||
<j-button type="primary" @click="handleAdd" v-else>
|
||||
新增
|
||||
</a-button>
|
||||
</j-button>
|
||||
</template>
|
||||
<template #status="slotProps">
|
||||
<a-space>
|
||||
<a-badge
|
||||
<j-space>
|
||||
<j-badge
|
||||
:status="
|
||||
slotProps.status.value === 'online'
|
||||
? 'success'
|
||||
: 'error'
|
||||
"
|
||||
:text="slotProps.status.text"
|
||||
></a-badge>
|
||||
</a-space>
|
||||
></j-badge>
|
||||
</j-space>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
<j-space :size="16">
|
||||
<j-tooltip
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<a-popconfirm
|
||||
<j-popconfirm
|
||||
v-if="i.popConfirm"
|
||||
v-bind="i.popConfirm"
|
||||
:disabled="i.disabled"
|
||||
>
|
||||
<a-button
|
||||
<j-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
/></j-button>
|
||||
</j-popconfirm>
|
||||
<j-button
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
v-else
|
||||
@click="i.onClick && i.onClick(slotProps)"
|
||||
>
|
||||
<a-button
|
||||
<j-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
/></j-button>
|
||||
</j-button>
|
||||
</j-tooltip>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
|
||||
|
|
|
@ -53,14 +53,14 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="playback-right">
|
||||
<a-spin :spinning="loading">
|
||||
<a-tooltip placement="topLeft">
|
||||
<j-spin :spinning="loading">
|
||||
<j-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
<div>云端:存储在服务器中</div>
|
||||
<div>本地:存储在设备本地</div>
|
||||
</template>
|
||||
<div>类型: <AIcon type="QuestionCircleOutlined" /></div>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
<RadioCard
|
||||
layout="horizontal"
|
||||
:options="[
|
||||
|
@ -80,11 +80,11 @@
|
|||
v-model="type"
|
||||
/>
|
||||
<div class="playback-calendar">
|
||||
<a-calendar
|
||||
<j-calendar
|
||||
v-model:value="time"
|
||||
:fullscreen="false"
|
||||
:disabledDate="
|
||||
(currentDate) => currentDate > dayjs(new Date())
|
||||
(currentDate: Dayjs) => currentDate > dayjs(new Date())
|
||||
"
|
||||
@change="handlePanelChange"
|
||||
/>
|
||||
|
@ -93,20 +93,20 @@
|
|||
class="playback-list"
|
||||
:class="{ 'no-list': !historyList.length }"
|
||||
>
|
||||
<a-empty
|
||||
<j-empty
|
||||
v-if="!historyList.length"
|
||||
description="暂无数据"
|
||||
/>
|
||||
<a-list
|
||||
<j-list
|
||||
v-else
|
||||
class="playback-list-items"
|
||||
itemLayout="horizontal"
|
||||
:dataSource="historyList"
|
||||
>
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item>
|
||||
<j-list-item>
|
||||
<template #actions>
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
key="play-btn"
|
||||
:title="
|
||||
(item.startTime ||
|
||||
|
@ -136,8 +136,8 @@
|
|||
"
|
||||
/>
|
||||
</a>
|
||||
</a-tooltip>
|
||||
<a-tooltip
|
||||
</j-tooltip>
|
||||
<j-tooltip
|
||||
key="download"
|
||||
:title="
|
||||
type !== 'local'
|
||||
|
@ -155,7 +155,7 @@
|
|||
() => downloadClick(item)
|
||||
"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
|
||||
<div>
|
||||
|
@ -173,12 +173,12 @@
|
|||
).format('HH:mm:ss')
|
||||
}}
|
||||
</div>
|
||||
</a-list-item>
|
||||
</j-list-item>
|
||||
</template>
|
||||
<div></div>
|
||||
</a-list>
|
||||
</j-list>
|
||||
</div>
|
||||
</a-spin>
|
||||
</j-spin>
|
||||
</div>
|
||||
</div>
|
||||
</page-container>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-modal
|
||||
<j-modal
|
||||
v-model:visible="_vis"
|
||||
title="快速添加"
|
||||
cancelText="取消"
|
||||
|
@ -9,38 +9,38 @@
|
|||
:confirmLoading="btnLoading"
|
||||
width="660px"
|
||||
>
|
||||
<a-form layout="vertical">
|
||||
<a-form-item label="产品名称" v-bind="validateInfos.name">
|
||||
<a-input
|
||||
<j-form layout="vertical">
|
||||
<j-form-item label="产品名称" v-bind="validateInfos.name">
|
||||
<j-input
|
||||
v-model:value="formData.name"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
<template v-if="channel === 'gb28181-2016' && formData.accessId">
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
label="接入密码"
|
||||
v-bind="validateInfos['configuration.access_pwd']"
|
||||
>
|
||||
<a-input-password
|
||||
<j-input-password
|
||||
v-model:value="formData.configuration.access_pwd"
|
||||
placeholder="请输入接入密码"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="流传输模式">
|
||||
<a-select
|
||||
</j-form-item>
|
||||
<j-form-item label="流传输模式">
|
||||
<j-select
|
||||
v-model:value="formData.configuration.stream_mode"
|
||||
placeholder="请选择流传输模式"
|
||||
:options="streamMode"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<a-form-item label="接入网关" v-bind="validateInfos.accessId">
|
||||
<j-form-item label="接入网关" v-bind="validateInfos.accessId">
|
||||
<div class="gateway-box">
|
||||
<div v-if="!gatewayList.length">
|
||||
暂无数据,请先
|
||||
<a-button type="link">
|
||||
<j-button type="link">
|
||||
添加{{ providerType[props.channel] }} 接入网关
|
||||
</a-button>
|
||||
</j-button>
|
||||
</div>
|
||||
<div
|
||||
class="gateway-item"
|
||||
|
@ -71,20 +71,20 @@
|
|||
{{ item.name }}
|
||||
</h3>
|
||||
<div class="desc">{{ item.description }}</div>
|
||||
<a-row v-if="props.channel === 'gb28181-2016'">
|
||||
<a-col :span="12">
|
||||
<j-row v-if="props.channel === 'gb28181-2016'">
|
||||
<j-col :span="12">
|
||||
{{ item.channelInfo?.name }}
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
{{ item.protocolDetail.name }}
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<p
|
||||
v-for="(i, idx) in item.channelInfo
|
||||
?.addresses"
|
||||
:key="`${i.address}_address${idx}`"
|
||||
>
|
||||
<a-badge
|
||||
<j-badge
|
||||
:text="i.address"
|
||||
:color="
|
||||
i.health === -1
|
||||
|
@ -93,10 +93,10 @@
|
|||
"
|
||||
/>
|
||||
</p>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row v-else>
|
||||
<a-col :span="24">
|
||||
</j-col>
|
||||
</j-row>
|
||||
<j-row v-else>
|
||||
<j-col :span="24">
|
||||
<div class="subtitle">
|
||||
{{ item.protocolDetail.name }}
|
||||
</div>
|
||||
|
@ -105,15 +105,15 @@
|
|||
item.protocolDetail.description
|
||||
}}
|
||||
</p>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</template>
|
||||
</CardBox>
|
||||
</div>
|
||||
</div>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<!-- 视频设备新增/编辑 -->
|
||||
<template>
|
||||
<page-container>
|
||||
<a-card>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="12">
|
||||
<a-form layout="vertical">
|
||||
<a-form-item
|
||||
<j-card>
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="12">
|
||||
<j-form layout="vertical">
|
||||
<j-form-item
|
||||
label="接入方式"
|
||||
v-bind="validateInfos.channel"
|
||||
>
|
||||
|
@ -16,134 +16,134 @@
|
|||
:disabled="!!route.query.id"
|
||||
v-model="formData.channel"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="8">
|
||||
</j-form-item>
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="8">
|
||||
<JUpload
|
||||
v-model:modelValue="formData.photoUrl"
|
||||
:bgImage="formData.photoUrl"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="16">
|
||||
<a-form-item
|
||||
</j-col>
|
||||
<j-col :span="16">
|
||||
<j-form-item
|
||||
label="ID"
|
||||
v-bind="validateInfos.id"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.id"
|
||||
placeholder="请输入"
|
||||
:disabled="!!route.query.id"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="设备名称"
|
||||
v-bind="validateInfos.name"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.name"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
<j-form-item
|
||||
label="所属产品"
|
||||
v-bind="validateInfos.productId"
|
||||
>
|
||||
<a-row :gutter="[0, 10]">
|
||||
<a-col :span="!!route.query.id ? 24 : 22">
|
||||
<a-select
|
||||
<j-row :gutter="[0, 10]">
|
||||
<j-col :span="!!route.query.id ? 24 : 22">
|
||||
<j-select
|
||||
v-model:value="formData.productId"
|
||||
placeholder="请选择所属产品"
|
||||
:disabled="!!route.query.id"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="(item, index) in productList"
|
||||
:key="index"
|
||||
:value="item.id"
|
||||
>
|
||||
{{ item.name }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-col>
|
||||
<a-col :span="2" v-if="!route.query.id">
|
||||
<a-button
|
||||
</j-select-option>
|
||||
</j-select>
|
||||
</j-col>
|
||||
<j-col :span="2" v-if="!route.query.id">
|
||||
<j-button
|
||||
type="link"
|
||||
@click="saveProductVis = true"
|
||||
>
|
||||
<AIcon type="PlusOutlined" />
|
||||
</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-button>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="接入密码"
|
||||
v-bind="validateInfos['others.access_pwd']"
|
||||
v-if="formData.channel === 'gb28181-2016'"
|
||||
>
|
||||
<a-input-password
|
||||
<j-input-password
|
||||
v-model:value="formData.others.access_pwd"
|
||||
placeholder="请输入接入密码"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
<template v-if="!!route.query.id">
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
label="流传输模式"
|
||||
v-bind="validateInfos.streamMode"
|
||||
>
|
||||
<a-radio-group
|
||||
<j-radio-group
|
||||
button-style="solid"
|
||||
v-model:value="formData.streamMode"
|
||||
>
|
||||
<a-radio-button value="UDP">
|
||||
<j-radio-button value="UDP">
|
||||
UDP
|
||||
</a-radio-button>
|
||||
<a-radio-button value="TCP_PASSIVE">
|
||||
</j-radio-button>
|
||||
<j-radio-button value="TCP_PASSIVE">
|
||||
TCP被动
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="设备厂商">
|
||||
<a-input
|
||||
</j-radio-button>
|
||||
</j-radio-group>
|
||||
</j-form-item>
|
||||
<j-form-item label="设备厂商">
|
||||
<j-input
|
||||
v-model:value="formData.manufacturer"
|
||||
placeholder="请输入设备厂商"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="设备型号">
|
||||
<a-input
|
||||
</j-form-item>
|
||||
<j-form-item label="设备型号">
|
||||
<j-input
|
||||
v-model:value="formData.model"
|
||||
placeholder="请输入设备型号"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="固件版本">
|
||||
<a-input
|
||||
</j-form-item>
|
||||
<j-form-item label="固件版本">
|
||||
<j-input
|
||||
v-model:value="formData.firmware"
|
||||
placeholder="请输入固件版本"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
|
||||
<a-form-item label="说明">
|
||||
<a-textarea
|
||||
<j-form-item label="说明">
|
||||
<j-textarea
|
||||
v-model:value="formData.description"
|
||||
show-count
|
||||
:maxlength="200"
|
||||
:rows="5"
|
||||
placeholder="请输入说明"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button
|
||||
</j-form-item>
|
||||
<j-form-item>
|
||||
<j-button
|
||||
type="primary"
|
||||
@click="handleSubmit"
|
||||
:loading="btnLoading"
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
</j-button>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<div v-if="1" class="doc" style="height: 800">
|
||||
<h1>1.概述</h1>
|
||||
<div>
|
||||
|
@ -166,7 +166,7 @@
|
|||
各个厂家、不同设备型号的设备端配置页面布局存在差异,但配置项基本大同小异,此处以大华摄像头为例作为接入配置示例
|
||||
</div>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/media/doc1.png')"
|
||||
/>
|
||||
|
@ -177,7 +177,7 @@
|
|||
SIP域通常为SIP服务器编号的前10位。
|
||||
</div>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/media/doc2.png')"
|
||||
/>
|
||||
|
@ -187,7 +187,7 @@
|
|||
SIP服务器IP/端口填入该设备所属产品-接入方式页面中“连接信息”的IP/端口。
|
||||
</div>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/media/doc3.png')"
|
||||
/>
|
||||
|
@ -201,7 +201,7 @@
|
|||
填入该设备所属产品-接入方式页面中“GB28281配置”处的接入密码
|
||||
</div>
|
||||
<div class="image">
|
||||
<a-image
|
||||
<j-image
|
||||
width="100%"
|
||||
:src="getImage('/media/doc4.png')"
|
||||
/>
|
||||
|
@ -230,9 +230,9 @@
|
|||
只能选择接入方式为固定地址的产品,若当前无对应产品,可点击右侧快速添加按钮,填写产品名称和选择固定地址类型的网关完成产品创建。
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-card>
|
||||
|
||||
<SaveProduct
|
||||
v-model:visible="saveProductVis"
|
||||
|
@ -285,7 +285,7 @@ const formRules = ref({
|
|||
},
|
||||
{ max: 64, message: '最多输入64个字符' },
|
||||
{
|
||||
pattern: /^[a-zA-Z0-9_\-]+$/,
|
||||
pattern: /^[j-zA-Z0-9_\-]+$/,
|
||||
message: '请输入英文或者数字或者-或者_',
|
||||
},
|
||||
],
|
||||
|
|
|
@ -44,30 +44,30 @@
|
|||
<h3 class="card-item-content-title">
|
||||
{{ slotProps.name }}
|
||||
</h3>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<j-row>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">厂商</div>
|
||||
<div>{{ slotProps.manufacturer }}</div>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">
|
||||
通道数量
|
||||
</div>
|
||||
<div>{{ slotProps.channelNumber }}</div>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">型号</div>
|
||||
<div>{{ slotProps.model }}</div>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">
|
||||
接入方式
|
||||
</div>
|
||||
<div>
|
||||
{{ providerType[slotProps.provider] }}
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</template>
|
||||
<template #actions="item">
|
||||
<PermissionButton
|
||||
|
@ -92,7 +92,7 @@
|
|||
</CardBox>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<j-space :size="16">
|
||||
<template
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
:key="i.key"
|
||||
|
@ -111,7 +111,7 @@
|
|||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</page-container>
|
||||
|
|
|
@ -21,6 +21,56 @@
|
|||
/>
|
||||
</j-col>
|
||||
</j-row>
|
||||
|
||||
<!-- 选择设备 -->
|
||||
<j-modal
|
||||
title="选择设备"
|
||||
width="800px"
|
||||
v-model:visible="visible"
|
||||
:maskClosable="false"
|
||||
:destroyOnClose="true"
|
||||
@cancel="visible = false"
|
||||
@ok="handleSubmit"
|
||||
>
|
||||
<j-advanced-search
|
||||
type="simple"
|
||||
:columns="columns"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<JProTable
|
||||
ref="tableRef"
|
||||
model="table"
|
||||
rowKey="id"
|
||||
:columns="columns"
|
||||
:request="deviceApi.list"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
}"
|
||||
:params="params"
|
||||
:rowSelection="{
|
||||
type: 'radio',
|
||||
selectedRowKeys: deviceItem?.id
|
||||
? [deviceItem.id]
|
||||
: undefined,
|
||||
onSelect: (record: any) => {
|
||||
deviceItem = record;
|
||||
}
|
||||
}"
|
||||
>
|
||||
<template #state="slotProps">
|
||||
<a-space>
|
||||
<a-badge
|
||||
:status="
|
||||
slotProps.state.value === 'online'
|
||||
? 'success'
|
||||
: 'error'
|
||||
"
|
||||
:text="slotProps.state.text"
|
||||
/>
|
||||
</a-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</j-modal>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
@ -33,6 +83,13 @@ import BasicCountCard from '@/views/media/Home/components/BasicCountCard.vue';
|
|||
import { usePermissionStore } from '@/store/permission';
|
||||
import type { bootConfig, recommendList } from '@/views/home/typing';
|
||||
|
||||
import deviceApi from '@/api/media/device';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { useMenuStore } from 'store/menu';
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
|
||||
// 权限控制
|
||||
const hasPermission = usePermissionStore().hasPermission;
|
||||
|
||||
|
@ -54,6 +111,7 @@ const deviceBootConfig: bootConfig[] = [
|
|||
link: 'media/Cascade',
|
||||
},
|
||||
];
|
||||
|
||||
const deviceStepDetails: recommendList[] = [
|
||||
{
|
||||
title: '添加视频设备',
|
||||
|
@ -66,8 +124,16 @@ const deviceStepDetails: recommendList[] = [
|
|||
title: '查看通道',
|
||||
details: '查看设备下的通道数据,可以进行直播、录制等操作。',
|
||||
iconUrl: '/images/home/bottom-7.png',
|
||||
linkUrl: 'media/Device/Channel',
|
||||
// linkUrl: 'media/Device/Channel',
|
||||
linkUrl: '',
|
||||
auth: hasPermission('media/Device:view'),
|
||||
onClick: (row: any) => {
|
||||
if (hasPermission('media/Device:view')) {
|
||||
visible.value = true;
|
||||
} else {
|
||||
message.warning('暂无权限,请联系管理员');
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '分屏展示',
|
||||
|
@ -76,4 +142,71 @@ const deviceStepDetails: recommendList[] = [
|
|||
linkUrl: 'media/SplitScreen',
|
||||
},
|
||||
];
|
||||
|
||||
// 选择设备
|
||||
const visible = ref(false);
|
||||
const columns = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '通道数量',
|
||||
dataIndex: 'channelNumber',
|
||||
key: 'channelNumber',
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'state',
|
||||
key: 'state',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '在线', value: 'online' },
|
||||
{ label: '离线', value: 'offline' },
|
||||
],
|
||||
handleValue: (v: any) => {
|
||||
return v;
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
const params = ref<Record<string, any>>({});
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
* @param params
|
||||
*/
|
||||
const handleSearch = (e: any) => {
|
||||
params.value = e;
|
||||
};
|
||||
|
||||
const deviceItem = ref();
|
||||
const handleSubmit = () => {
|
||||
if (deviceItem.value && deviceItem.value.id) {
|
||||
menuStory.jumpPage(
|
||||
'media/Device/Channel',
|
||||
{},
|
||||
{
|
||||
id: deviceItem.value.id,
|
||||
type: deviceItem.value.provider,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
message.warning('请选择设备');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<a-card class="splitScreen">
|
||||
<j-card class="splitScreen">
|
||||
<div class="split-screen">
|
||||
<LeftTree @onSelect="mediaStart" />
|
||||
<div class="right-content">
|
||||
|
@ -17,7 +17,7 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
</a-card>
|
||||
</j-card>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="left-content">
|
||||
<a-tree
|
||||
<j-tree
|
||||
:height="700"
|
||||
:show-line="{ showLeafIcon: false }"
|
||||
:show-icon="true"
|
||||
|
@ -15,7 +15,7 @@
|
|||
v-if="!treeData.find((f: any) => f.id === id)"
|
||||
/>
|
||||
</template>
|
||||
</a-tree>
|
||||
</j-tree>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-modal
|
||||
<j-modal
|
||||
v-model:visible="_vis"
|
||||
title="调试"
|
||||
cancelText="取消"
|
||||
|
@ -8,34 +8,34 @@
|
|||
@cancel="handleCancel"
|
||||
:confirmLoading="btnLoading"
|
||||
>
|
||||
<a-form ref="formRef" layout="vertical" :model="formData">
|
||||
<a-form-item
|
||||
<j-form ref="formRef" layout="vertical" :model="formData">
|
||||
<j-form-item
|
||||
label="通知模版"
|
||||
name="templateId"
|
||||
:rules="{ required: true, message: '该字段为必填字段' }"
|
||||
>
|
||||
<a-select
|
||||
<j-select
|
||||
v-model:value="formData.templateId"
|
||||
placeholder="请选择通知模版"
|
||||
@change="getTemplateDetail"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="(item, index) in templateList"
|
||||
:key="index"
|
||||
:value="item.id"
|
||||
>
|
||||
{{ item.name }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="变量"
|
||||
v-if="
|
||||
formData.templateDetailTable &&
|
||||
formData.templateDetailTable.length
|
||||
"
|
||||
>
|
||||
<a-table
|
||||
<j-table
|
||||
row-key="id"
|
||||
:columns="columns"
|
||||
:data-source="formData.templateDetailTable"
|
||||
|
@ -49,7 +49,7 @@
|
|||
<span>{{ record[column.dataIndex] }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
:name="['templateDetailTable', index, 'value']"
|
||||
:rules="{
|
||||
required: true,
|
||||
|
@ -60,13 +60,13 @@
|
|||
v-model:modelValue="record.value"
|
||||
:itemType="record.type"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</j-table>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!-- webhook请求头可编辑表格 -->
|
||||
<template>
|
||||
<div class="table-wrapper">
|
||||
<a-table
|
||||
<j-table
|
||||
:columns="columns"
|
||||
:data-source="dataSource"
|
||||
bordered
|
||||
|
@ -9,18 +9,18 @@
|
|||
>
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template v-if="['key', 'value'].includes(column.dataIndex)">
|
||||
<a-input v-model:value="record[column.dataIndex]" />
|
||||
<j-input v-model:value="record[column.dataIndex]" />
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'operation'">
|
||||
<a-button type="text">
|
||||
<j-button type="text">
|
||||
<template #icon>
|
||||
<delete-outlined @click="handleDelete(record.id)" />
|
||||
</template>
|
||||
</a-button>
|
||||
</j-button>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-button
|
||||
</j-table>
|
||||
<j-button
|
||||
type="dashed"
|
||||
@click="handleAdd"
|
||||
style="width: 100%; margin-top: 5px"
|
||||
|
@ -29,7 +29,7 @@
|
|||
<plus-outlined />
|
||||
</template>
|
||||
添加
|
||||
</a-button>
|
||||
</j-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
<!-- 通知配置详情 -->
|
||||
<template>
|
||||
<page-container>
|
||||
<a-card>
|
||||
<a-row>
|
||||
<a-col :span="10">
|
||||
<a-form layout="vertical">
|
||||
<a-form-item
|
||||
<j-card>
|
||||
<j-row>
|
||||
<j-col :span="10">
|
||||
<j-form layout="vertical">
|
||||
<j-form-item
|
||||
label="通知方式"
|
||||
v-bind="validateInfos.type"
|
||||
>
|
||||
<a-select
|
||||
<j-select
|
||||
v-model:value="formData.type"
|
||||
placeholder="请选择通知方式"
|
||||
:disabled="!!formData.id"
|
||||
@change="handleTypeChange"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="(item, index) in NOTICE_METHOD"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="名称" v-bind="validateInfos.name">
|
||||
<a-input
|
||||
</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<j-form-item label="名称" v-bind="validateInfos.name">
|
||||
<j-input
|
||||
v-model:value="formData.name"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="类型"
|
||||
v-bind="validateInfos.provider"
|
||||
v-if="formData.type !== 'email'"
|
||||
|
@ -40,144 +40,144 @@
|
|||
v-model="formData.provider"
|
||||
@change="handleProviderChange"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
<!-- 钉钉 -->
|
||||
<template v-if="formData.type === 'dingTalk'">
|
||||
<template
|
||||
v-if="formData.provider === 'dingTalkMessage'"
|
||||
>
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
label="AppKey"
|
||||
v-bind="
|
||||
validateInfos['configuration.appKey']
|
||||
"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.configuration.appKey
|
||||
"
|
||||
placeholder="请输入AppKey"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="AppSecret"
|
||||
v-bind="
|
||||
validateInfos['configuration.appSecret']
|
||||
"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.configuration.appSecret
|
||||
"
|
||||
placeholder="请输入AppSecret"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<template
|
||||
v-if="
|
||||
formData.provider === 'dingTalkRobotWebHook'
|
||||
"
|
||||
>
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
label="webHook"
|
||||
v-bind="validateInfos['configuration.url']"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.configuration.url
|
||||
"
|
||||
placeholder="请输入webHook"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
</template>
|
||||
<!-- 微信 -->
|
||||
<template v-if="formData.type === 'weixin'">
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
label="corpId"
|
||||
v-bind="validateInfos['configuration.corpId']"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.configuration.corpId
|
||||
"
|
||||
placeholder="请输入corpId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="corpSecret"
|
||||
v-bind="
|
||||
validateInfos['configuration.corpSecret']
|
||||
"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.configuration.corpSecret
|
||||
"
|
||||
placeholder="请输入corpSecret"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<!-- 邮件 -->
|
||||
<template v-if="formData.type === 'email'">
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
label="服务器地址"
|
||||
v-bind="validateInfos['configuration.host']"
|
||||
>
|
||||
<a-space>
|
||||
<a-input
|
||||
<j-space>
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.configuration.host
|
||||
"
|
||||
placeholder="请输入服务器地址"
|
||||
/>
|
||||
<a-input-number
|
||||
<j-input-number
|
||||
v-model:value="
|
||||
formData.configuration.port
|
||||
"
|
||||
/>
|
||||
<a-checkbox
|
||||
<j-checkbox
|
||||
v-model:value="
|
||||
formData.configuration.ssl
|
||||
"
|
||||
>
|
||||
开启SSL
|
||||
</a-checkbox>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-checkbox>
|
||||
</j-space>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="发件人"
|
||||
v-bind="validateInfos['configuration.sender']"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.configuration.sender
|
||||
"
|
||||
placeholder="请输入发件人"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="用户名"
|
||||
v-bind="validateInfos['configuration.username']"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.configuration.username
|
||||
"
|
||||
placeholder="请输入用户名"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="密码"
|
||||
v-bind="validateInfos['configuration.password']"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.configuration.password
|
||||
"
|
||||
placeholder="请输入密码"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<!-- 语音/短信 -->
|
||||
<template
|
||||
|
@ -186,94 +186,94 @@
|
|||
formData.type === 'sms'
|
||||
"
|
||||
>
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
label="RegionId"
|
||||
v-bind="validateInfos['configuration.regionId']"
|
||||
>
|
||||
<a-select
|
||||
<j-select
|
||||
v-model:value="
|
||||
formData.configuration.regionId
|
||||
"
|
||||
placeholder="请选择RegionId"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="(item, index) in regionList"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="AccessKeyId"
|
||||
v-bind="
|
||||
validateInfos['configuration.accessKeyId']
|
||||
"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.configuration.accessKeyId
|
||||
"
|
||||
placeholder="请输入AccessKeyId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="Secret"
|
||||
v-bind="validateInfos['configuration.secret']"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.configuration.secret
|
||||
"
|
||||
placeholder="Secret"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<!-- webhook -->
|
||||
<template v-if="formData.type === 'webhook'">
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
label="Webhook"
|
||||
v-bind="validateInfos['configuration.url']"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.configuration.url"
|
||||
placeholder="请输入Webhook"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="请求头">
|
||||
</j-form-item>
|
||||
<j-form-item label="请求头">
|
||||
<EditTable
|
||||
v-model:headers="
|
||||
formData.configuration.headers
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<a-form-item label="说明">
|
||||
<a-textarea
|
||||
<j-form-item label="说明">
|
||||
<j-textarea
|
||||
v-model:value="formData.description"
|
||||
show-count
|
||||
:maxlength="200"
|
||||
:rows="5"
|
||||
placeholder="请输入说明"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button
|
||||
</j-form-item>
|
||||
<j-form-item>
|
||||
<j-button
|
||||
type="primary"
|
||||
@click="handleSubmit"
|
||||
:loading="btnLoading"
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-col>
|
||||
<a-col :span="12" :push="2">
|
||||
</j-button>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</j-col>
|
||||
<j-col :span="12" :push="2">
|
||||
<Doc :docData="formData" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-card>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
@ -395,7 +395,7 @@ const formRules = ref({
|
|||
{ required: true, message: '请输入Webhook' },
|
||||
{
|
||||
pattern:
|
||||
/^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/,
|
||||
/^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[j-z]{2,6}\/?/,
|
||||
message: 'Webhook需要是一个合法的URL',
|
||||
},
|
||||
],
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<template>
|
||||
<a-modal v-model:visible="_vis" title="通知记录" :footer="null" width="70%">
|
||||
<j-search
|
||||
<j-modal v-model:visible="_vis" title="通知记录" :footer="null" width="70%">
|
||||
<j-advanced-search
|
||||
type="simple"
|
||||
:columns="columns"
|
||||
target="product"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
|
||||
|
@ -22,18 +21,18 @@
|
|||
{{ moment(slotProps.notifyTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||
</template>
|
||||
<template #state="slotProps">
|
||||
<a-space>
|
||||
<a-badge
|
||||
<j-space>
|
||||
<j-badge
|
||||
:status="slotProps.state.value"
|
||||
:text="slotProps.state.text"
|
||||
></a-badge>
|
||||
></j-badge>
|
||||
<AIcon
|
||||
v-if="slotProps.state.value === 'error'"
|
||||
type="ExclamationCircleOutlined"
|
||||
style="color: #1d39c4; cursor: pointer"
|
||||
@click="handleError(slotProps.errorStack)"
|
||||
/>
|
||||
</a-space>
|
||||
</j-space>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<AIcon
|
||||
|
@ -43,7 +42,7 @@
|
|||
/>
|
||||
</template>
|
||||
</JProTable>
|
||||
</a-modal>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-modal
|
||||
<j-modal
|
||||
v-model:visible="_vis"
|
||||
title="同步用户"
|
||||
:footer="null"
|
||||
@cancel="_vis = false"
|
||||
width="80%"
|
||||
>
|
||||
<a-row :gutter="10" class="model-body">
|
||||
<a-col :span="4">
|
||||
<a-input
|
||||
<j-row :gutter="10" class="model-body">
|
||||
<j-col :span="4">
|
||||
<j-input
|
||||
v-model:value="deptName"
|
||||
@keyup.enter="getDepartment"
|
||||
allowClear
|
||||
|
@ -23,17 +23,17 @@
|
|||
@click="getDepartment"
|
||||
/>
|
||||
</template>
|
||||
</a-input>
|
||||
<a-tree
|
||||
</j-input>
|
||||
<j-tree
|
||||
:tree-data="deptTreeData"
|
||||
:fieldNames="{ title: 'name', key: 'id' }"
|
||||
:selectedKeys="[deptId]"
|
||||
@select="onTreeSelect"
|
||||
>
|
||||
</a-tree>
|
||||
<a-empty v-if="!deptTreeData.length" />
|
||||
</a-col>
|
||||
<a-col :span="20">
|
||||
</j-tree>
|
||||
<j-empty v-if="!deptTreeData.length" />
|
||||
</j-col>
|
||||
<j-col :span="20">
|
||||
<JProTable
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
|
@ -43,38 +43,38 @@
|
|||
noPagination
|
||||
>
|
||||
<template #headerTitle>
|
||||
<a-button type="primary" @click="handleAutoBind">
|
||||
<j-button type="primary" @click="handleAutoBind">
|
||||
自动绑定
|
||||
</a-button>
|
||||
</j-button>
|
||||
</template>
|
||||
<template #status="slotProps">
|
||||
<a-space>
|
||||
<a-badge
|
||||
<j-space>
|
||||
<j-badge
|
||||
:status="slotProps.status.value"
|
||||
:text="slotProps.status.text"
|
||||
></a-badge>
|
||||
</a-space>
|
||||
></j-badge>
|
||||
</j-space>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
<j-space :size="16">
|
||||
<j-tooltip
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<a-popconfirm
|
||||
<j-popconfirm
|
||||
v-if="i.popConfirm"
|
||||
v-bind="i.popConfirm"
|
||||
:disabled="i.disabled"
|
||||
>
|
||||
<a-button
|
||||
<j-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
/></j-button>
|
||||
</j-popconfirm>
|
||||
<j-button
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
v-else
|
||||
|
@ -82,23 +82,23 @@
|
|||
i.onClick && i.onClick(slotProps)
|
||||
"
|
||||
>
|
||||
<a-button
|
||||
<j-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
/></j-button>
|
||||
</j-button>
|
||||
</j-tooltip>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-modal>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-modal>
|
||||
|
||||
<!-- 绑定用户 -->
|
||||
<a-modal
|
||||
<j-modal
|
||||
v-model:visible="bindVis"
|
||||
title="绑定用户"
|
||||
:maskClosable="false"
|
||||
|
@ -106,9 +106,9 @@
|
|||
@cancel="handleCancel"
|
||||
@ok="handleBindSubmit"
|
||||
>
|
||||
<a-form layout="vertical">
|
||||
<a-form-item label="用户" v-bind="validateInfos.userId">
|
||||
<a-select
|
||||
<j-form layout="vertical">
|
||||
<j-form-item label="用户" v-bind="validateInfos.userId">
|
||||
<j-select
|
||||
v-model:value="formData.userId"
|
||||
:options="allUserList"
|
||||
allowClear
|
||||
|
@ -117,9 +117,9 @@
|
|||
:filter-option="filterOption"
|
||||
placeholder="请选择用户"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</j-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
:gridColumn="3"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<a-space>
|
||||
<j-space>
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
|
@ -34,7 +34,7 @@
|
|||
导入
|
||||
</PermissionButton>
|
||||
</a-upload>
|
||||
<a-popconfirm
|
||||
<j-popconfirm
|
||||
title="确认导出?"
|
||||
ok-text="确定"
|
||||
cancel-text="取消"
|
||||
|
@ -43,8 +43,8 @@
|
|||
<PermissionButton hasPermission="notice/Config:export">
|
||||
导出
|
||||
</PermissionButton>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</j-popconfirm>
|
||||
</j-space>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
|
@ -67,39 +67,39 @@
|
|||
<h3 class="card-item-content-title">
|
||||
{{ slotProps.name }}
|
||||
</h3>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<j-row>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">
|
||||
通知方式
|
||||
</div>
|
||||
<div>
|
||||
{{ getMethodTxt(slotProps.type) }}
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">说明</div>
|
||||
<Ellipsis>
|
||||
{{ slotProps.description }}
|
||||
</Ellipsis>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</template>
|
||||
<template #actions="item">
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
v-bind="item.tooltip"
|
||||
:title="item.disabled && item.tooltip.title"
|
||||
>
|
||||
<a-dropdown
|
||||
<j-dropdown
|
||||
placement="bottomRight"
|
||||
v-if="item.key === 'others'"
|
||||
>
|
||||
<a-button>
|
||||
<j-button>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item.text }}</span>
|
||||
</a-button>
|
||||
</j-button>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item
|
||||
<j-menu>
|
||||
<j-menu-item
|
||||
v-for="(o, i) in item.children"
|
||||
:key="i"
|
||||
>
|
||||
|
@ -113,10 +113,10 @@
|
|||
</template>
|
||||
<span>{{ o.text }}</span>
|
||||
</PermissionButton>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</j-menu-item>
|
||||
</j-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</j-dropdown>
|
||||
<j-popconfirm
|
||||
v-else-if="item.key === 'delete'"
|
||||
v-bind="item.popConfirm"
|
||||
|
@ -143,12 +143,12 @@
|
|||
<span>{{ item.text }}</span>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<j-space :size="16">
|
||||
<template
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
:key="i.key"
|
||||
|
@ -167,7 +167,7 @@
|
|||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-modal
|
||||
<j-modal
|
||||
v-model:visible="_vis"
|
||||
title="调试"
|
||||
cancelText="取消"
|
||||
|
@ -8,33 +8,33 @@
|
|||
@cancel="handleCancel"
|
||||
:confirmLoading="btnLoading"
|
||||
>
|
||||
<a-form ref="formRef" layout="vertical" :model="formData">
|
||||
<a-form-item
|
||||
<j-form ref="formRef" layout="vertical" :model="formData">
|
||||
<j-form-item
|
||||
label="通知配置"
|
||||
name="configId"
|
||||
:rules="{ required: true, message: '该字段为必填字段' }"
|
||||
>
|
||||
<a-select
|
||||
<j-select
|
||||
v-model:value="formData.configId"
|
||||
placeholder="请选择通知配置"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="(item, index) in configList"
|
||||
:key="index"
|
||||
:value="item.id"
|
||||
>
|
||||
{{ item.name }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="变量"
|
||||
v-if="
|
||||
formData.templateDetailTable &&
|
||||
formData.templateDetailTable.length
|
||||
"
|
||||
>
|
||||
<a-table
|
||||
<j-table
|
||||
row-key="id"
|
||||
:columns="columns"
|
||||
:data-source="formData.templateDetailTable"
|
||||
|
@ -48,7 +48,7 @@
|
|||
<span>{{ record[column.dataIndex] }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
:name="['templateDetailTable', index, 'value']"
|
||||
:rules="{
|
||||
required: record.required,
|
||||
|
@ -78,13 +78,13 @@
|
|||
v-model:modelValue="record.value"
|
||||
:itemType="record.type"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</j-table>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
v-for="(item, index) in fileList"
|
||||
:key="index"
|
||||
>
|
||||
<a-input v-model:value="item.name">
|
||||
<j-input v-model:value="item.name">
|
||||
<template #addonAfter>
|
||||
<a-upload
|
||||
name="file"
|
||||
|
@ -20,14 +20,14 @@
|
|||
<upload-outlined />
|
||||
</a-upload>
|
||||
</template>
|
||||
</a-input>
|
||||
</j-input>
|
||||
<delete-outlined
|
||||
@click="handleDelete(item.id)"
|
||||
style="cursor: pointer"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<a-button
|
||||
<j-button
|
||||
type="dashed"
|
||||
@click="handleAdd"
|
||||
style="width: 100%; margin-top: 5px"
|
||||
|
@ -36,7 +36,7 @@
|
|||
<plus-outlined />
|
||||
</template>
|
||||
添加
|
||||
</a-button>
|
||||
</j-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-select
|
||||
<j-select
|
||||
:options="options"
|
||||
@change="change"
|
||||
placeholder="请选择收信部门"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-select
|
||||
<j-select
|
||||
:options="options"
|
||||
@change="change"
|
||||
placeholder="请选择标签推送,多个标签用,号分隔"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-select
|
||||
<j-select
|
||||
:options="options"
|
||||
@change="change"
|
||||
placeholder="请选择收信人"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!-- 模板内容-变量列表 -->
|
||||
<template>
|
||||
<div class="table-wrapper">
|
||||
<a-table
|
||||
<j-table
|
||||
:columns="columns"
|
||||
:data-source="dataSource"
|
||||
bordered
|
||||
|
@ -11,52 +11,52 @@
|
|||
<span v-if="column.dataIndex === 'id'">
|
||||
{{ record[column.dataIndex] }}
|
||||
</span>
|
||||
<a-input
|
||||
<j-input
|
||||
v-if="column.dataIndex === 'name'"
|
||||
v-model:value="record.name"
|
||||
/>
|
||||
<a-select
|
||||
<j-select
|
||||
v-if="column.dataIndex === 'type'"
|
||||
v-model:value="record.type"
|
||||
@change="handleTypeChange(record)"
|
||||
>
|
||||
<a-select-option value="string">字符串</a-select-option>
|
||||
<a-select-option value="date">时间</a-select-option>
|
||||
<a-select-option value="double">数字</a-select-option>
|
||||
</a-select>
|
||||
<j-select-option value="string">字符串</j-select-option>
|
||||
<j-select-option value="date">时间</j-select-option>
|
||||
<j-select-option value="double">数字</j-select-option>
|
||||
</j-select>
|
||||
<template v-if="column.dataIndex === 'format'">
|
||||
<span v-if="record.type === 'string'">
|
||||
{{ record.format }}
|
||||
</span>
|
||||
<a-select
|
||||
<j-select
|
||||
v-if="record.type === 'date'"
|
||||
v-model:value="record.format"
|
||||
>
|
||||
<a-select-option value="timestamp">
|
||||
<j-select-option value="timestamp">
|
||||
timestamp
|
||||
</a-select-option>
|
||||
<a-select-option value="yyyy-MM-dd">
|
||||
</j-select-option>
|
||||
<j-select-option value="yyyy-MM-dd">
|
||||
yyyy-MM-dd
|
||||
</a-select-option>
|
||||
<a-select-option value="yyyy-MM-dd HH:mm:ss">
|
||||
</j-select-option>
|
||||
<j-select-option value="yyyy-MM-dd HH:mm:ss">
|
||||
yyyy-MM-dd HH:mm:ss
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
<a-input
|
||||
</j-select-option>
|
||||
</j-select>
|
||||
<j-input
|
||||
v-if="record.type === 'double'"
|
||||
v-model:value="record.format"
|
||||
>
|
||||
<template #suffix>
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="格式为:%.xf x代表数字保留的小数位数。当x=0时,代表格式为整数"
|
||||
>
|
||||
<AIcon type="QuestionCircleOutlined" />
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</j-input>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</j-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
<!-- 通知模板详情 -->
|
||||
<template>
|
||||
<page-container>
|
||||
<a-card>
|
||||
<a-row>
|
||||
<a-col :span="10">
|
||||
<a-form layout="vertical">
|
||||
<a-form-item
|
||||
<j-card>
|
||||
<j-row>
|
||||
<j-col :span="10">
|
||||
<j-form layout="vertical">
|
||||
<j-form-item
|
||||
label="通知方式"
|
||||
v-bind="validateInfos.type"
|
||||
>
|
||||
<a-select
|
||||
<j-select
|
||||
v-model:value="formData.type"
|
||||
placeholder="请选择通知方式"
|
||||
:disabled="!!formData.id"
|
||||
@change="handleTypeChange"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="(item, index) in NOTICE_METHOD"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="名称" v-bind="validateInfos.name">
|
||||
<a-input
|
||||
</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<j-form-item label="名称" v-bind="validateInfos.name">
|
||||
<j-input
|
||||
v-model:value="formData.name"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
label="类型"
|
||||
v-bind="validateInfos.provider"
|
||||
v-if="
|
||||
|
@ -43,67 +43,67 @@
|
|||
v-model="formData.provider"
|
||||
@change="handleProviderChange"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
v-bind="validateInfos.configId"
|
||||
v-if="formData.type !== 'email'"
|
||||
>
|
||||
<template #label>
|
||||
<span>
|
||||
绑定配置
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="使用固定的通知配置来发送此通知模版"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-select
|
||||
<j-select
|
||||
v-model:value="formData.configId"
|
||||
placeholder="请选择绑定配置"
|
||||
@change="handleConfigChange"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="(item, index) in configList"
|
||||
:key="index"
|
||||
:value="item.id"
|
||||
>
|
||||
{{ item.name }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<!-- 钉钉 -->
|
||||
<template v-if="formData.type === 'dingTalk'">
|
||||
<template
|
||||
v-if="formData.provider === 'dingTalkMessage'"
|
||||
>
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
v-bind="validateInfos['template.agentId']"
|
||||
>
|
||||
<template #label>
|
||||
<span>
|
||||
AgentID
|
||||
<a-tooltip title="应用唯一标识">
|
||||
<j-tooltip title="应用唯一标识">
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.template.agentId
|
||||
"
|
||||
placeholder="请输入AppSecret"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-row :gutter="10">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="收信部门">
|
||||
</j-form-item>
|
||||
<j-row :gutter="10">
|
||||
<j-col :span="12">
|
||||
<j-form-item label="收信部门">
|
||||
<ToOrg
|
||||
v-model:toParty="
|
||||
formData.template
|
||||
|
@ -112,14 +112,14 @@
|
|||
:type="formData.type"
|
||||
:config-id="formData.configId"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
收信人
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="如果不填写该字段,将在使用此模板发送通知时进行指定"
|
||||
>
|
||||
<AIcon
|
||||
|
@ -128,7 +128,7 @@
|
|||
margin-left: 2px;
|
||||
"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<ToUser
|
||||
|
@ -138,29 +138,29 @@
|
|||
:type="formData.type"
|
||||
:config-id="formData.configId"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</template>
|
||||
<template
|
||||
v-if="
|
||||
formData.provider === 'dingTalkRobotWebHook'
|
||||
"
|
||||
>
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
label="消息类型"
|
||||
v-bind="
|
||||
validateInfos['template.messageType']
|
||||
"
|
||||
>
|
||||
<a-select
|
||||
<j-select
|
||||
v-model:value="
|
||||
formData.template.messageType
|
||||
"
|
||||
placeholder="请选择消息类型"
|
||||
@change="handleMessageTypeChange"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="(
|
||||
item, index
|
||||
) in ROBOT_MSG_TYPE"
|
||||
|
@ -168,16 +168,16 @@
|
|||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<template
|
||||
v-if="
|
||||
formData.template.messageType ===
|
||||
'markdown'
|
||||
"
|
||||
>
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
label="标题"
|
||||
v-bind="
|
||||
validateInfos[
|
||||
|
@ -185,34 +185,34 @@
|
|||
]
|
||||
"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.template.markdown.title
|
||||
"
|
||||
placeholder="请输入标题"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<template
|
||||
v-if="
|
||||
formData.template.messageType === 'link'
|
||||
"
|
||||
>
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
label="标题"
|
||||
v-bind="
|
||||
validateInfos['template.link.title']
|
||||
"
|
||||
>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.template.link.title
|
||||
"
|
||||
placeholder="请输入标题"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="图片链接">
|
||||
<a-input
|
||||
</j-form-item>
|
||||
<j-form-item label="图片链接">
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.template.link.picUrl
|
||||
"
|
||||
|
@ -239,55 +239,55 @@
|
|||
/>
|
||||
</a-upload>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="内容链接">
|
||||
<a-input
|
||||
</j-input>
|
||||
</j-form-item>
|
||||
<j-form-item label="内容链接">
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.template.link
|
||||
.messageUrl
|
||||
"
|
||||
placeholder="请输入内容链接"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
<!-- 微信 -->
|
||||
<template v-if="formData.type === 'weixin'">
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
v-bind="validateInfos['template.agentId']"
|
||||
>
|
||||
<template #label>
|
||||
<span>
|
||||
AgentId
|
||||
<a-tooltip title="应用唯一标识">
|
||||
<j-tooltip title="应用唯一标识">
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.template.agentId"
|
||||
placeholder="请输入agentId"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-row :gutter="10">
|
||||
<a-col :span="12">
|
||||
<a-form-item>
|
||||
</j-form-item>
|
||||
<j-row :gutter="10">
|
||||
<j-col :span="12">
|
||||
<j-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
收信人
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="如果不填写该字段,将在使用此模版发送通知时进行指定。"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<ToUser
|
||||
|
@ -297,10 +297,10 @@
|
|||
:type="formData.type"
|
||||
:config-id="formData.configId"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="收信部门">
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item label="收信部门">
|
||||
<ToOrg
|
||||
v-model:toParty="
|
||||
formData.template.toParty
|
||||
|
@ -308,21 +308,21 @@
|
|||
:type="formData.type"
|
||||
:config-id="formData.configId"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
<j-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
标签推送
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="本企业微信的标签ID列表,最多支持100个,如果不填写该字段,将在使用此模版发送通知时进行指定"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<ToTag
|
||||
|
@ -330,62 +330,62 @@
|
|||
:type="formData.type"
|
||||
:config-id="formData.configId"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<!-- 邮件 -->
|
||||
<template v-if="formData.type === 'email'">
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
v-bind="validateInfos['template.subject']"
|
||||
>
|
||||
<template #label>
|
||||
<span>
|
||||
标题
|
||||
<a-tooltip title="邮件标题">
|
||||
<j-tooltip title="邮件标题">
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.template.subject"
|
||||
placeholder="请输入标题"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
</j-form-item>
|
||||
<j-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
收件人
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="多个收件人用换行分隔 最大支持1000个号码"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-select
|
||||
<j-select
|
||||
mode="tags"
|
||||
:options="[]"
|
||||
v-model:value="formData.template.sendTo"
|
||||
placeholder="请选择收件人"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
</j-form-item>
|
||||
<j-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
附件信息
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="附件只输入文件名称将在发送邮件时进行文件上传"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<Attachments
|
||||
|
@ -393,44 +393,44 @@
|
|||
formData.template.attachments
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<!-- 语音 -->
|
||||
<template v-if="formData.type === 'voice'">
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
v-bind="validateInfos['template.templateType']"
|
||||
>
|
||||
<template #label>
|
||||
<span>
|
||||
类型
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="语音验证码类型可配置变量,并且只支持数字和英文字母"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-select
|
||||
<j-select
|
||||
v-model:value="
|
||||
formData.template.templateType
|
||||
"
|
||||
placeholder="请选择类型"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="(item, index) in VOICE_TYPE"
|
||||
:key="index"
|
||||
:value="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-row :gutter="10">
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<j-row :gutter="10">
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
v-bind="
|
||||
validateInfos[
|
||||
'template.templateCode'
|
||||
|
@ -440,49 +440,49 @@
|
|||
<template #label>
|
||||
<span>
|
||||
模板ID
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="阿里云内部分配的唯一ID标识"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.template.templateCode
|
||||
"
|
||||
placeholder="请输入模板ID"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
被叫号码
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="仅支持中国大陆号码"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.template.calledNumber
|
||||
"
|
||||
placeholder="请输入被叫号码"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
<j-form-item
|
||||
v-bind="
|
||||
validateInfos['template.calledShowNumbers']
|
||||
"
|
||||
|
@ -490,92 +490,92 @@
|
|||
<template #label>
|
||||
<span>
|
||||
被叫显号
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="必须是已购买的号码,用于呼叫号码显示"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.template.calledShowNumbers
|
||||
"
|
||||
placeholder="请输入被叫显号"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
</j-form-item>
|
||||
<j-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
播放次数
|
||||
<a-tooltip title="语音文件的播放次数">
|
||||
<j-tooltip title="语音文件的播放次数">
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="formData.template.playTimes"
|
||||
placeholder="请输入播放次数"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
v-if="formData.template.templateType === 'tts'"
|
||||
>
|
||||
<template #label>
|
||||
<span>
|
||||
模版内容
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="语音验证码内容输入框,用于渲染验语音证码变量。"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-textarea
|
||||
<j-textarea
|
||||
v-model:value="formData.template.message"
|
||||
show-count
|
||||
:rows="5"
|
||||
placeholder="内容中的变量将用于阿里云语音验证码"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<!-- 短信 -->
|
||||
<template v-if="formData.type === 'sms'">
|
||||
<a-row :gutter="10">
|
||||
<a-col :span="12">
|
||||
<a-form-item
|
||||
<j-row :gutter="10">
|
||||
<j-col :span="12">
|
||||
<j-form-item
|
||||
v-bind="validateInfos['template.code']"
|
||||
>
|
||||
<template #label>
|
||||
<span>
|
||||
模板
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="阿里云短信平台自定义的模版名称"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-select
|
||||
<j-select
|
||||
v-model:value="
|
||||
formData.template.code
|
||||
"
|
||||
placeholder="请选择模板"
|
||||
@change="handleTemplateChange"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="(
|
||||
item, index
|
||||
) in templateList"
|
||||
|
@ -583,77 +583,77 @@
|
|||
:value="item.templateCode"
|
||||
>
|
||||
{{ item.templateName }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item>
|
||||
</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<j-form-item>
|
||||
<template #label>
|
||||
<span>
|
||||
收信人
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="仅支持中国大陆号码"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-input
|
||||
<j-input
|
||||
v-model:value="
|
||||
formData.template.phoneNumber
|
||||
"
|
||||
placeholder="请输入收信人"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
<j-form-item
|
||||
v-bind="validateInfos['template.signName']"
|
||||
>
|
||||
<template #label>
|
||||
<span>
|
||||
签名
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="用于短信内容签名信息显示"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-select
|
||||
<j-select
|
||||
v-model:value="formData.template.signName"
|
||||
placeholder="请选择签名"
|
||||
>
|
||||
<a-select-option
|
||||
<j-select-option
|
||||
v-for="(item, index) in signsList"
|
||||
:key="index"
|
||||
:value="item.signName"
|
||||
>
|
||||
{{ item.signName }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</j-select-option>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<!-- webhook -->
|
||||
<template v-if="formData.type === 'webhook'">
|
||||
<a-form-item label="请求体">
|
||||
<a-radio-group
|
||||
<j-form-item label="请求体">
|
||||
<j-radio-group
|
||||
v-model:value="
|
||||
formData.template.contextAsBody
|
||||
"
|
||||
style="margin-bottom: 20px"
|
||||
>
|
||||
<a-radio :value="true">默认</a-radio>
|
||||
<a-radio :value="false">自定义</a-radio>
|
||||
</a-radio-group>
|
||||
<a-textarea
|
||||
<j-radio :value="true">默认</j-radio>
|
||||
<j-radio :value="false">自定义</j-radio>
|
||||
</j-radio-group>
|
||||
<j-textarea
|
||||
v-model:value="formData.template.body"
|
||||
placeholder="请求体中的数据来自于发送通知时指定的所有变量"
|
||||
v-if="formData.template.contextAsBody"
|
||||
|
@ -668,7 +668,7 @@
|
|||
"
|
||||
/>
|
||||
</div>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<template
|
||||
v-if="
|
||||
|
@ -676,23 +676,23 @@
|
|||
formData.type !== 'voice'
|
||||
"
|
||||
>
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
v-bind="validateInfos['template.message']"
|
||||
>
|
||||
<template #label>
|
||||
<span>
|
||||
模版内容
|
||||
<a-tooltip
|
||||
<j-tooltip
|
||||
title="发送的内容,支持录入变量"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<a-textarea
|
||||
<j-textarea
|
||||
v-model:value="formData.template.message"
|
||||
:maxlength="200"
|
||||
:rows="5"
|
||||
|
@ -700,9 +700,9 @@
|
|||
placeholder="变量格式:${name};
|
||||
示例:尊敬的${name},${time}有设备触发告警,请注意处理"
|
||||
/>
|
||||
</a-form-item>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<a-form-item
|
||||
<j-form-item
|
||||
label="变量列表"
|
||||
v-if="
|
||||
formData.variableDefinitions &&
|
||||
|
@ -714,32 +714,32 @@
|
|||
formData.variableDefinitions
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="说明">
|
||||
<a-textarea
|
||||
</j-form-item>
|
||||
<j-form-item label="说明">
|
||||
<j-textarea
|
||||
v-model:value="formData.description"
|
||||
show-count
|
||||
:maxlength="200"
|
||||
:rows="5"
|
||||
placeholder="请输入说明"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button
|
||||
</j-form-item>
|
||||
<j-form-item>
|
||||
<j-button
|
||||
type="primary"
|
||||
@click="handleSubmit"
|
||||
:loading="btnLoading"
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-col>
|
||||
<a-col :span="12" :push="2">
|
||||
</j-button>
|
||||
</j-form-item>
|
||||
</j-form>
|
||||
</j-col>
|
||||
<j-col :span="12" :push="2">
|
||||
<Doc :docData="formData" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-card>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<template>
|
||||
<a-modal v-model:visible="_vis" title="通知记录" :footer="null" width="70%">
|
||||
<j-search
|
||||
<j-modal v-model:visible="_vis" title="通知记录" :footer="null" width="70%">
|
||||
<j-advanced-search
|
||||
type="simple"
|
||||
:columns="columns"
|
||||
target="product"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
|
||||
|
@ -22,18 +21,18 @@
|
|||
{{ moment(slotProps.notifyTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||
</template>
|
||||
<template #state="slotProps">
|
||||
<a-space>
|
||||
<a-badge
|
||||
<j-space>
|
||||
<j-badge
|
||||
:status="slotProps.state.value"
|
||||
:text="slotProps.state.text"
|
||||
></a-badge>
|
||||
></j-badge>
|
||||
<AIcon
|
||||
v-if="slotProps.state.value === 'error'"
|
||||
type="ExclamationCircleOutlined"
|
||||
style="color: #1d39c4; cursor: pointer"
|
||||
@click="handleError(slotProps.errorStack)"
|
||||
/>
|
||||
</a-space>
|
||||
</j-space>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<AIcon
|
||||
|
@ -43,7 +42,7 @@
|
|||
/>
|
||||
</template>
|
||||
</JProTable>
|
||||
</a-modal>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
:gridColumn="3"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<a-space>
|
||||
<j-space>
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
|
@ -36,7 +36,7 @@
|
|||
导入
|
||||
</PermissionButton>
|
||||
</a-upload>
|
||||
<a-popconfirm
|
||||
<j-popconfirm
|
||||
title="确认导出?"
|
||||
ok-text="确定"
|
||||
cancel-text="取消"
|
||||
|
@ -47,8 +47,8 @@
|
|||
>
|
||||
导出
|
||||
</PermissionButton>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</j-popconfirm>
|
||||
</j-space>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
|
@ -71,22 +71,22 @@
|
|||
<h3 class="card-item-content-title">
|
||||
{{ slotProps.name }}
|
||||
</h3>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<j-row>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">
|
||||
通知方式
|
||||
</div>
|
||||
<div>
|
||||
{{ getMethodTxt(slotProps.type) }}
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">说明</div>
|
||||
<Ellipsis>
|
||||
{{ slotProps.description }}
|
||||
</Ellipsis>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</template>
|
||||
<template #actions="item">
|
||||
<PermissionButton
|
||||
|
@ -119,7 +119,7 @@
|
|||
</span>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<j-space :size="16">
|
||||
<template
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
:key="i.key"
|
||||
|
@ -138,7 +138,7 @@
|
|||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</a-space>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
|
||||
|
|
|
@ -1,261 +1,278 @@
|
|||
<template>
|
||||
<Search
|
||||
:columns="columns"
|
||||
type='simple'
|
||||
@search="handleSearch"
|
||||
class='search'
|
||||
target="scene-triggrt-device-device"
|
||||
<j-advanced-search
|
||||
:columns="columns"
|
||||
type="simple"
|
||||
@search="handleSearch"
|
||||
class="search"
|
||||
target="scene-trigger-device-product"
|
||||
/>
|
||||
<a-divider style='margin: 0' />
|
||||
<a-divider style="margin: 0" />
|
||||
<j-pro-table
|
||||
ref='actionRef'
|
||||
model='CARD'
|
||||
:columns='columns'
|
||||
:params='params'
|
||||
:request='productQuery'
|
||||
:gridColumn='2'
|
||||
:gridColumns='[2,2,2]'
|
||||
:bodyStyle='{
|
||||
paddingRight: 0,
|
||||
paddingLeft: 0
|
||||
}'
|
||||
ref="actionRef"
|
||||
model="CARD"
|
||||
:columns="columns"
|
||||
:params="params"
|
||||
:request="productQuery"
|
||||
:gridColumn="2"
|
||||
:bodyStyle="{
|
||||
paddingRight: 0,
|
||||
paddingLeft: 0,
|
||||
}"
|
||||
>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
:value='slotProps'
|
||||
:active="rowKey === slotProps.id"
|
||||
:status="slotProps.state"
|
||||
:statusText="slotProps.state === 1 ? '正常' : '禁用'"
|
||||
:statusNames="{ 1: 'success', 0: 'error', }"
|
||||
@click="handleClick"
|
||||
>
|
||||
<template #img>
|
||||
<slot name="img">
|
||||
<img width='88' height='88' :src="slotProps.photoUrl || getImage('/device-product.png')" />
|
||||
</slot>
|
||||
</template>
|
||||
<template #content>
|
||||
<div style='width: calc(100% - 100px)'>
|
||||
<Ellipsis>
|
||||
<span style="font-size: 16px;font-weight: 600" >
|
||||
{{ slotProps.name }}
|
||||
</span>
|
||||
</Ellipsis>
|
||||
</div>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<div class="card-item-content-text">
|
||||
设备类型
|
||||
</div>
|
||||
<div>直连设备</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
:value="slotProps"
|
||||
:active="rowKey === slotProps.id"
|
||||
:status="String(slotProps.state)"
|
||||
:statusText="slotProps.state === 1 ? '正常' : '禁用'"
|
||||
:statusNames="{ '1': 'success', '0': 'error' }"
|
||||
@click="handleClick(slotProps)"
|
||||
>
|
||||
<template #img>
|
||||
<slot name="img">
|
||||
<img
|
||||
:width="88"
|
||||
:height="88"
|
||||
:src="
|
||||
slotProps.photoUrl ||
|
||||
getImage('/device-product.png')
|
||||
"
|
||||
/>
|
||||
</slot>
|
||||
</template>
|
||||
<template #content>
|
||||
<div style="width: calc(100% - 100px)">
|
||||
<Ellipsis>
|
||||
<span style="font-size: 16px; font-weight: 600">
|
||||
{{ slotProps.name }}
|
||||
</span>
|
||||
</Ellipsis>
|
||||
</div>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<div class="card-item-content-text">设备类型</div>
|
||||
<Ellipsis>{{ slotProps.deviceType?.text }}</Ellipsis>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<div class="card-item-content-text">接入方式</div>
|
||||
<Ellipsis>{{ slotProps?.accessName || '未接入' }}</Ellipsis>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name='Product'>
|
||||
import { getProviders, queryGatewayList, queryProductList } from '@/api/device/product'
|
||||
import { queryTree } from '@/api/device/category'
|
||||
import { getTreeData_api } from '@/api/system/department'
|
||||
import { isNoCommunity } from '@/utils/utils'
|
||||
import { getImage } from '@/utils/comm'
|
||||
import {
|
||||
getProviders,
|
||||
queryGatewayList,
|
||||
queryProductList,
|
||||
} from '@/api/device/product';
|
||||
import { queryTree } from '@/api/device/category';
|
||||
import { getTreeData_api } from '@/api/system/department';
|
||||
import { isNoCommunity } from '@/utils/utils';
|
||||
import { getImage } from '@/utils/comm';
|
||||
|
||||
type Emit = {
|
||||
(e: 'update:rowKey', data: string): void
|
||||
(e: 'update:detail', data: string): void
|
||||
(e: 'change', data: string): void
|
||||
}
|
||||
type Emit = {
|
||||
(e: 'update:rowKey', data: string): void;
|
||||
(e: 'update:detail', data: string): void;
|
||||
(e: 'change', data: string): void;
|
||||
};
|
||||
|
||||
const actionRef = ref()
|
||||
const params = ref({})
|
||||
const props = defineProps({
|
||||
const actionRef = ref();
|
||||
const params = ref({});
|
||||
const props = defineProps({
|
||||
rowKey: {
|
||||
type: String,
|
||||
default: ''
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
detail: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
const emit = defineEmits<Emit>();
|
||||
|
||||
const columns = [
|
||||
const columns = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
width: 300,
|
||||
ellipsis: true,
|
||||
fixed: 'left',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
width: 300,
|
||||
ellipsis: true,
|
||||
fixed: 'left',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
first: true
|
||||
}
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
first: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '网关类型',
|
||||
dataIndex: 'accessProvider',
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
hideInTable: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: () => getProviders().then((resp: any) => {
|
||||
if (isNoCommunity) {
|
||||
return (resp?.result || []).map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id
|
||||
}))
|
||||
} else {
|
||||
return (resp?.result || []).filter((item: any) => [
|
||||
'mqtt-server-gateway',
|
||||
'http-server-gateway',
|
||||
'mqtt-client-gateway',
|
||||
'tcp-server-gateway',
|
||||
].includes(item.id))
|
||||
.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '接入方式',
|
||||
dataIndex: 'accessName',
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: () => queryGatewayList().then((resp: any) =>
|
||||
resp.result.map((item: any) => ({
|
||||
label: item.name, value: item.id
|
||||
}))
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '设备类型',
|
||||
dataIndex: 'deviceType',
|
||||
width: 150,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '直连设备', value: 'device' },
|
||||
{ label: '网关子设备', value: 'childrenDevice' },
|
||||
{ label: '网关设备', value: 'gateway' },
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'state',
|
||||
width: '90px',
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '禁用', value: 0 },
|
||||
{ label: '正常', value: 1 },
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '说明',
|
||||
dataIndex: 'describe',
|
||||
ellipsis: true,
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
dataIndex: 'classifiedId',
|
||||
title: '分类',
|
||||
hideInTable: true,
|
||||
search: {
|
||||
type: 'treeSelect',
|
||||
options: queryTree({ paging: false }).then(resp => resp.result),
|
||||
componentProps: {
|
||||
fieldNames: {
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
dataIndex: 'id$dim-assets',
|
||||
title: '所属组织',
|
||||
hideInTable: true,
|
||||
search: {
|
||||
type: 'treeSelect',
|
||||
options: getTreeData_api({ paging: false }).then((resp: any) => {
|
||||
const formatValue = (list: any[]) => {
|
||||
return list.map((item: any) => {
|
||||
if (item.children) {
|
||||
item.children = formatValue(item.children);
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
value: JSON.stringify({
|
||||
assetType: 'product',
|
||||
targets: [
|
||||
{
|
||||
type: 'org',
|
||||
id: item.id,
|
||||
},
|
||||
],
|
||||
title: '网关类型',
|
||||
dataIndex: 'accessProvider',
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
hideInTable: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: () =>
|
||||
getProviders().then((resp: any) => {
|
||||
if (isNoCommunity) {
|
||||
return (resp?.result || []).map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}));
|
||||
} else {
|
||||
return (resp?.result || [])
|
||||
.filter((item: any) =>
|
||||
[
|
||||
'mqtt-server-gateway',
|
||||
'http-server-gateway',
|
||||
'mqtt-client-gateway',
|
||||
'tcp-server-gateway',
|
||||
].includes(item.id),
|
||||
)
|
||||
.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}));
|
||||
}
|
||||
}),
|
||||
}
|
||||
})
|
||||
}
|
||||
return formatValue(resp.result)
|
||||
}),
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '接入方式',
|
||||
dataIndex: 'accessName',
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: () =>
|
||||
queryGatewayList().then((resp: any) =>
|
||||
resp.result.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
})),
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '设备类型',
|
||||
dataIndex: 'deviceType',
|
||||
width: 150,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '直连设备', value: 'device' },
|
||||
{ label: '网关子设备', value: 'childrenDevice' },
|
||||
{ label: '网关设备', value: 'gateway' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'state',
|
||||
width: '90px',
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '禁用', value: 0 },
|
||||
{ label: '正常', value: 1 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '说明',
|
||||
dataIndex: 'describe',
|
||||
ellipsis: true,
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
dataIndex: 'classifiedId',
|
||||
title: '分类',
|
||||
hideInTable: true,
|
||||
search: {
|
||||
type: 'treeSelect',
|
||||
options: queryTree({ paging: false }).then((resp) => resp.result),
|
||||
componentProps: {
|
||||
fieldNames: {
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
dataIndex: 'id$dim-assets',
|
||||
title: '所属组织',
|
||||
hideInTable: true,
|
||||
search: {
|
||||
type: 'treeSelect',
|
||||
options: getTreeData_api({ paging: false }).then((resp: any) => {
|
||||
const formatValue = (list: any[]) => {
|
||||
return list.map((item: any) => {
|
||||
if (item.children) {
|
||||
item.children = formatValue(item.children);
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
value: JSON.stringify({
|
||||
assetType: 'product',
|
||||
targets: [
|
||||
{
|
||||
type: 'org',
|
||||
id: item.id,
|
||||
},
|
||||
],
|
||||
}),
|
||||
};
|
||||
});
|
||||
};
|
||||
return formatValue(resp.result);
|
||||
}),
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const handleSearch = (p: any) => {
|
||||
params.value = p
|
||||
}
|
||||
const handleSearch = (p: any) => {
|
||||
params.value = p;
|
||||
};
|
||||
|
||||
const productQuery = (p: any) => {
|
||||
const productQuery = (p: any) => {
|
||||
const sorts: any = [];
|
||||
|
||||
if (props.rowKey) {
|
||||
sorts.push({
|
||||
name: 'id',
|
||||
value: props.rowKey,
|
||||
});
|
||||
sorts.push({
|
||||
name: 'id',
|
||||
value: props.rowKey,
|
||||
});
|
||||
}
|
||||
sorts.push({ name: 'createTime', order: 'desc' });
|
||||
p.sorts = sorts
|
||||
return queryProductList(p)
|
||||
}
|
||||
p.sorts = sorts;
|
||||
return queryProductList(p);
|
||||
};
|
||||
|
||||
const handleClick = (detail: any) => {
|
||||
emit('update:rowKey', detail.id)
|
||||
emit('update:detail', detail)
|
||||
emit('change', detail)
|
||||
}
|
||||
|
||||
</script>
|
||||
const handleClick = (detail: any) => {
|
||||
emit('update:rowKey', detail.id);
|
||||
emit('update:detail', detail);
|
||||
emit('change', detail);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
.search {
|
||||
.search {
|
||||
margin-bottom: 0;
|
||||
padding-right: 0px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,64 @@
|
|||
<template>
|
||||
<j-table
|
||||
rowKey="id"
|
||||
:columns="columns"
|
||||
:data-source="dataSource"
|
||||
bordered
|
||||
:pagination="false"
|
||||
>
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<div>
|
||||
<template v-if="['valueType', 'name'].includes(column.dataIndex)">
|
||||
<span>{{ text }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<j-input />
|
||||
<!-- TODO -->
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</j-table>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PropType } from "vue";
|
||||
|
||||
type Emits = {
|
||||
(e: 'update:modelValue', data: Record<string, any>[]): void;
|
||||
};
|
||||
const _emit = defineEmits<Emits>();
|
||||
|
||||
const _props = defineProps({
|
||||
modelValue: {
|
||||
type: Array as PropType<Record<string, any>[]>,
|
||||
default: '',
|
||||
}
|
||||
});
|
||||
const columns = [
|
||||
{
|
||||
title: '参数名称',
|
||||
dataIndex: 'name',
|
||||
with: '33%',
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
dataIndex: 'valueType',
|
||||
with: '33%',
|
||||
},
|
||||
{
|
||||
title: '值',
|
||||
dataIndex: 'value',
|
||||
with: '34%',
|
||||
},
|
||||
];
|
||||
|
||||
const dataSource = computed({
|
||||
get: () => {
|
||||
return _props.modelValue || []
|
||||
},
|
||||
set: (val: any) => {
|
||||
_emit('update:modelValue', val);
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
|
@ -0,0 +1,215 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-form :layout="'vertical'" ref="formRef" :model="modelRef">
|
||||
<j-form-item
|
||||
:name="['message', 'messageType']"
|
||||
label="动作类型"
|
||||
:rules="[{ required: true, message: '请选择动作类型' }]"
|
||||
>
|
||||
<TopCard
|
||||
:typeList="TypeList"
|
||||
v-model:value="modelRef.message.messageType"
|
||||
/>
|
||||
</j-form-item>
|
||||
<template v-if="deviceMessageType === 'INVOKE_FUNCTION'">
|
||||
<j-form-item
|
||||
:name="['message', 'functionId']"
|
||||
label="功能调用"
|
||||
:rules="[{ required: true, message: '请选择功能' }]"
|
||||
>
|
||||
<j-select
|
||||
showSearch
|
||||
placeholder="请选择功能"
|
||||
v-model:value="modelRef.message.functionId"
|
||||
@change="onFunctionChange"
|
||||
>
|
||||
<j-select-option
|
||||
v-for="item in metadata?.functions || []"
|
||||
:value="item?.id"
|
||||
:key="item?.id"
|
||||
>{{ item?.name }}</j-select-option
|
||||
>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
v-if="modelRef.message.functionId"
|
||||
:name="['message', 'inputs']"
|
||||
:rules="[{ required: true, message: '请输入功能值' }]"
|
||||
>
|
||||
<EditTable v-model="modelRef.message.inputs" />
|
||||
</j-form-item>
|
||||
</template>
|
||||
<template v-else-if="deviceMessageType === 'READ_PROPERTY'">
|
||||
<j-form-item
|
||||
:name="['message', 'properties']"
|
||||
label="读取属性"
|
||||
:rules="[{ required: true, message: '请选择读取属性' }]"
|
||||
>
|
||||
<j-select
|
||||
showSearch
|
||||
placeholder="请选择属性"
|
||||
v-model:value="modelRef.message.properties"
|
||||
>
|
||||
<j-select-option
|
||||
v-for="item in metadata?.properties || []"
|
||||
:value="item?.id"
|
||||
:key="item?.id"
|
||||
>{{ item?.name }}</j-select-option
|
||||
>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
</template>
|
||||
<template v-else-if="deviceMessageType === 'WRITE_PROPERTY'">
|
||||
<j-row>
|
||||
<j-col :span="11">
|
||||
<j-form-item
|
||||
:name="['message', 'properties']"
|
||||
label="读取属性"
|
||||
:rules="[
|
||||
{ required: true, message: '请选择读取属性' },
|
||||
]"
|
||||
>
|
||||
<j-select
|
||||
showSearch
|
||||
placeholder="请选择属性"
|
||||
v-model:value="modelRef.message.properties"
|
||||
>
|
||||
<j-select-option
|
||||
v-for="item in metadata?.properties || []"
|
||||
:value="item?.id"
|
||||
:key="item?.id"
|
||||
>{{ item?.name }}</j-select-option
|
||||
>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="2"></j-col>
|
||||
<j-col :span="11">
|
||||
<j-form-item
|
||||
:name="['message', 'properties']"
|
||||
label="读取属性"
|
||||
:rules="[
|
||||
{ required: true, message: '请选择读取属性' },
|
||||
]"
|
||||
>
|
||||
<j-select placeholder="请选择">
|
||||
<!-- TODO -->
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</template>
|
||||
</a-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getImage } from '@/utils/comm';
|
||||
import TopCard from '../device/TopCard.vue';
|
||||
import { detail } from '@/api/device/instance';
|
||||
import EditTable from './EditTable.vue';
|
||||
|
||||
const TypeList = [
|
||||
{
|
||||
label: '功能调用',
|
||||
value: 'INVOKE_FUNCTION',
|
||||
image: getImage('/scene/invoke-function.png'),
|
||||
tip: '',
|
||||
},
|
||||
{
|
||||
label: '读取属性',
|
||||
value: 'READ_PROPERTY',
|
||||
image: getImage('/scene/read-property.png'),
|
||||
tip: '',
|
||||
},
|
||||
{
|
||||
label: '设置属性',
|
||||
value: 'WRITE_PROPERTY',
|
||||
image: getImage('/scene/write-property.png'),
|
||||
tip: '',
|
||||
},
|
||||
];
|
||||
|
||||
const props = defineProps({
|
||||
values: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
name: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
thenName: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
branchGroup: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
});
|
||||
|
||||
const formRef = ref();
|
||||
|
||||
const modelRef = reactive({
|
||||
message: {
|
||||
messageType: undefined,
|
||||
functionId: undefined,
|
||||
properties: undefined,
|
||||
inputs: [],
|
||||
},
|
||||
});
|
||||
|
||||
const metadata = ref<{
|
||||
functions: any[];
|
||||
properties: any[];
|
||||
}>({
|
||||
functions: [],
|
||||
properties: [],
|
||||
});
|
||||
|
||||
const deviceMessageType = computed(() => {
|
||||
return modelRef.message.messageType;
|
||||
});
|
||||
|
||||
const onFunctionChange = (val: string) => {
|
||||
const _item = (metadata.value?.functions || []).find((item: any) => {
|
||||
return val === item.id;
|
||||
});
|
||||
const list = (_item?.inputs || []).map((item: any) => {
|
||||
return {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
value: undefined,
|
||||
valueType: item?.valueType?.type,
|
||||
};
|
||||
});
|
||||
modelRef.message.inputs = list;
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
// console.log(props.values)
|
||||
// console.log(metadata.value)
|
||||
// Object.assign()
|
||||
});
|
||||
|
||||
watch(
|
||||
() => [props.values?.productDetail, props.values.deviceDetail],
|
||||
([newVal1, newVal2]) => {
|
||||
if (newVal1) {
|
||||
if (props.values?.selector === 'fixed') {
|
||||
detail(newVal2.id).then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
metadata.value = JSON.parse(
|
||||
resp.result?.metadata || '{}',
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
metadata.value = JSON.parse(newVal1?.metadata || '{}');
|
||||
}
|
||||
}
|
||||
},
|
||||
{ deep: true, immediate: true },
|
||||
);
|
||||
</script>
|
|
@ -0,0 +1,186 @@
|
|||
<template>
|
||||
<!-- <j-advanced-search
|
||||
:columns="columns"
|
||||
type="simple"
|
||||
@search="handleSearch"
|
||||
class="search"
|
||||
target="scene-trigger-device-device"
|
||||
/> -->
|
||||
<a-divider style="margin: 0" />
|
||||
<j-pro-table
|
||||
ref="actionRef"
|
||||
model="CARD"
|
||||
:columns="columns"
|
||||
:params="params"
|
||||
:request="deviceQuery"
|
||||
:gridColumn="2"
|
||||
:bodyStyle="{
|
||||
paddingRight: 0,
|
||||
paddingLeft: 0,
|
||||
}"
|
||||
>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
:value="slotProps"
|
||||
@click="handleClick"
|
||||
:active="value[0]?.value === slotProps.id"
|
||||
:status="slotProps.state?.value"
|
||||
:statusText="slotProps.state?.text"
|
||||
:statusNames="{
|
||||
online: 'success',
|
||||
offline: 'error',
|
||||
notActive: 'warning',
|
||||
}"
|
||||
>
|
||||
<template #img>
|
||||
<slot name="img">
|
||||
<img
|
||||
:src="getImage('/device/instance/device-card.png')"
|
||||
/>
|
||||
</slot>
|
||||
</template>
|
||||
<template #content>
|
||||
<div style="width: calc(100% - 100px)">
|
||||
<Ellipsis>
|
||||
<span style="font-size: 16px; font-weight: 600">
|
||||
{{ slotProps.name }}
|
||||
</span>
|
||||
</Ellipsis>
|
||||
</div>
|
||||
<j-row style="margin-top: 20px">
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">设备类型</div>
|
||||
<div>{{ slotProps.deviceType?.text }}</div>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">产品名称</div>
|
||||
<Ellipsis style="width: 100%">
|
||||
{{ slotProps.productName }}
|
||||
</Ellipsis>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name='Product'>
|
||||
import { query } from '@/api/device/instance';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import { PropType } from 'vue';
|
||||
|
||||
type Emit = {
|
||||
(e: 'update:value', data: any): void;
|
||||
(e: 'change', data: any): void;
|
||||
};
|
||||
|
||||
const actionRef = ref();
|
||||
const params = ref({
|
||||
terms: []
|
||||
});
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Array as PropType<any>,
|
||||
default: []
|
||||
},
|
||||
detail: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
productId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits<Emit>();
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
width: 300,
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '设备名称',
|
||||
dataIndex: 'name',
|
||||
search: {
|
||||
type: 'string',
|
||||
first: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'date',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'state',
|
||||
key: 'state',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '禁用', value: 'notActive' },
|
||||
{ label: '离线', value: 'offline' },
|
||||
{ label: '在线', value: 'online' },
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const handleSearch = (p: any) => {
|
||||
params.value = {
|
||||
...p,
|
||||
terms: [
|
||||
...p.terms,
|
||||
{terms: [{ column: 'productId', value: props?.productId }]}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const deviceQuery = (p: any) => {
|
||||
const sorts: any = [];
|
||||
if (props.value) {
|
||||
sorts.push({
|
||||
name: 'id',
|
||||
value: props.value,
|
||||
});
|
||||
}
|
||||
sorts.push({ name: 'createTime', order: 'desc' });
|
||||
p.sorts = sorts;
|
||||
return query(p);
|
||||
};
|
||||
|
||||
const handleClick = (detail: any) => {
|
||||
emit('update:value', [{ value: detail.id, name: detail.name }]);
|
||||
emit('change', detail);
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
params.value = {
|
||||
...params.value,
|
||||
terms: params.value?.terms ? [
|
||||
...(params.value.terms || []),
|
||||
{terms: [{ column: 'productId', value: props?.productId }]}
|
||||
] : [{terms: [{ column: 'productId', value: props?.productId }]}]
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
.search {
|
||||
margin-bottom: 0;
|
||||
padding-right: 0px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,206 @@
|
|||
<template>
|
||||
<div>
|
||||
<template v-for="(item, index) in tagList" :key="item.id">
|
||||
<j-row :gutter="24" style="margin-bottom: 12px">
|
||||
<j-col :span="4">
|
||||
<span v-if="index === 0" class="tagName">标签选择</span>
|
||||
<j-select
|
||||
:options="[
|
||||
{ label: '并且', value: 'and' },
|
||||
{ label: '或者', value: 'or' },
|
||||
]"
|
||||
v-else
|
||||
:value="item?.type"
|
||||
style="width: 100%"
|
||||
@select="(key) => onTypeSelect(key, index)"
|
||||
/>
|
||||
</j-col>
|
||||
<j-col :span="16">
|
||||
<j-row :gutter="24">
|
||||
<j-col flex="120px">
|
||||
<j-select
|
||||
style="width: 120px"
|
||||
:value="item.id"
|
||||
placeholder="请选择标签"
|
||||
:options="options"
|
||||
@select="
|
||||
(_, _data) => onTagSelect(_data, index)
|
||||
"
|
||||
/>
|
||||
</j-col>
|
||||
<j-col flex="auto">
|
||||
<ValueItem
|
||||
v-model:modelValue="item.value"
|
||||
:itemType="item.valueType"
|
||||
@change="onValueChange"
|
||||
:options="
|
||||
item.valueType === 'enum'
|
||||
? (item?.dataType?.elements || []).map(
|
||||
(i) => {
|
||||
return {
|
||||
label: i.text,
|
||||
value: i.value,
|
||||
};
|
||||
},
|
||||
)
|
||||
: item.valueType === 'boolean'
|
||||
? [
|
||||
{ label: '是', value: true },
|
||||
{ label: '否', value: false },
|
||||
]
|
||||
: undefined
|
||||
"
|
||||
/>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-col>
|
||||
<j-col :span="4">
|
||||
<j-space>
|
||||
<j-button style="padding: 0 8px" @click="addItem">
|
||||
<AIcon type="PlusOutlined" />
|
||||
</j-button>
|
||||
<j-button
|
||||
danger
|
||||
v-if="tagData.length > 1"
|
||||
style="padding: 0 8px"
|
||||
@click="deleteItem(index)"
|
||||
>
|
||||
<AIcon type="DeleteOutlined" />
|
||||
</j-button>
|
||||
</j-space>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PropType } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Array as PropType<any>,
|
||||
default: () => [],
|
||||
},
|
||||
tagData: {
|
||||
type: Array as PropType<any[]>,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits(['update:value', 'change']);
|
||||
|
||||
const options = ref<any[]>([]);
|
||||
const tagList = ref<any[]>([]);
|
||||
|
||||
const handleItem = (data: any) => {
|
||||
return {
|
||||
...data,
|
||||
valueType: data.valueType ? data.valueType.type : '-',
|
||||
format: data.valueType ? data.valueType.format : undefined,
|
||||
options: data.valueType ? data.valueType.elements : undefined,
|
||||
value: data.value,
|
||||
};
|
||||
};
|
||||
|
||||
const addItem = () => {
|
||||
tagList.value.push({ type: 'and' });
|
||||
};
|
||||
|
||||
const deleteItem = (_index: number) => {
|
||||
tagList.value.splice(_index, 1);
|
||||
};
|
||||
|
||||
const onTypeSelect = (key: any, _index: number) => {
|
||||
const indexItem = tagList[_index];
|
||||
indexItem.type = key;
|
||||
tagList.value[_index] = indexItem;
|
||||
};
|
||||
|
||||
const onTagSelect = (_data: any, _index: number) => {
|
||||
const newList = [...unref(tagList)];
|
||||
const indexType = newList[_index].type;
|
||||
newList.splice(
|
||||
_index,
|
||||
1,
|
||||
handleItem({ ..._data, value: undefined, type: indexType }),
|
||||
);
|
||||
tagList.value = newList;
|
||||
};
|
||||
|
||||
watch(
|
||||
() => [props.tagData, props.value],
|
||||
([newTag, newVal]) => {
|
||||
options.value = newTag.map((item: any) => {
|
||||
return { label: item.name, value: item.id, ...item };
|
||||
});
|
||||
if (newVal && newVal[0] && newVal[0].name && newTag && newTag.length) {
|
||||
const names: string[] = [];
|
||||
const newTagList = newVal[0].value
|
||||
.filter((valueItem: any) => {
|
||||
return newTag.some(
|
||||
(item: any) => valueItem.column === item.id,
|
||||
);
|
||||
})
|
||||
.map((valueItem: any) => {
|
||||
const oldItem = newTag.find(
|
||||
(item: any) => item.id === valueItem.column,
|
||||
);
|
||||
if (oldItem) {
|
||||
names.push(oldItem.name);
|
||||
return {
|
||||
...handleItem(oldItem),
|
||||
value: valueItem.value,
|
||||
type: valueItem.type,
|
||||
};
|
||||
}
|
||||
return valueItem;
|
||||
});
|
||||
tagList.value = newTagList;
|
||||
} else {
|
||||
tagList.value = [{}];
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
},
|
||||
);
|
||||
|
||||
const onValueChange = () => {
|
||||
const newValue = tagList.value
|
||||
.filter((item) => !!item.value)
|
||||
.map((item: any) => {
|
||||
return {
|
||||
column: item.id,
|
||||
type: item.type,
|
||||
value: item.value,
|
||||
};
|
||||
});
|
||||
const arr = newValue
|
||||
.filter((item) => !!item.value)
|
||||
.map((item: any) => {
|
||||
return {
|
||||
column: item.name,
|
||||
type: item.type,
|
||||
value: item.value,
|
||||
};
|
||||
});
|
||||
emits('update:value', [{ value: newValue, name: '标签' }]);
|
||||
emits('change', [{ value: newValue, name: '标签' }], undefined);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.tagName::before {
|
||||
position: relative;
|
||||
left: 70px;
|
||||
display: inline-block;
|
||||
margin-right: 4px;
|
||||
color: #ff4d4f;
|
||||
font-size: 14px;
|
||||
font-family: SimSun, sans-serif;
|
||||
line-height: 1;
|
||||
content: '*';
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,149 @@
|
|||
<template>
|
||||
<div class="trigger-way-warp" :class="{ disabled: disabled }">
|
||||
<div
|
||||
v-for="item in typeList"
|
||||
:key="item.value"
|
||||
class="trigger-way-item"
|
||||
:class="{
|
||||
active: _value === item.value,
|
||||
labelBottom: labelBottom,
|
||||
}"
|
||||
@click="onSelect(item.value)"
|
||||
>
|
||||
<div class="'way-item-title">
|
||||
<span class="way-item-label">{{ item.label }}</span>
|
||||
<j-popover v-if="item.tip">
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
class="way-item-icon"
|
||||
/>
|
||||
</j-popover>
|
||||
</div>
|
||||
<div class="way-item-image">
|
||||
<img :width="48" :src="item.image" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PropType } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
typeList: {
|
||||
type: Array as PropType<any>,
|
||||
default: () => [],
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
labelBottom: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits(['update:value', 'change']);
|
||||
const _value = ref(props?.value || '');
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
_value.value = newValue || ""
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
|
||||
const onSelect = (_type: string) => {
|
||||
if (!props.disabled) {
|
||||
_value.value = _type;
|
||||
emits('update:value', _type);
|
||||
emits('change', _type)
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.trigger-way-warp {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px 24px;
|
||||
width: 100%;
|
||||
|
||||
.trigger-way-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 237px;
|
||||
padding: 12px 16px;
|
||||
border: 1px solid #e0e4e8;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
.way-item-title {
|
||||
span {
|
||||
font-size: 16px;
|
||||
}
|
||||
.way-item-label {
|
||||
padding-right: 6px;
|
||||
color: rgba(#000, 0.64);
|
||||
}
|
||||
|
||||
.way-item-icon {
|
||||
color: rgba(#000, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.way-item-image {
|
||||
margin: 0 !important;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.way-item-image {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: @primary-color-active;
|
||||
.way-item-image {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.labelBottom {
|
||||
flex-direction: column-reverse;
|
||||
grid-gap: 16px;
|
||||
gap: 0;
|
||||
align-items: center;
|
||||
width: auto;
|
||||
padding: 8px 16px;
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
.trigger-way-item {
|
||||
cursor: not-allowed;
|
||||
|
||||
&:hover {
|
||||
color: initial;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,14 +1,354 @@
|
|||
|
||||
<template>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<a-form :layout="'vertical'" ref="formRef" :model="modelRef">
|
||||
<j-form-item
|
||||
name="selector"
|
||||
label="选择方式"
|
||||
v-show="!(list.length === 1)"
|
||||
:rules="[{ required: true, message: '请选择方式' }]"
|
||||
>
|
||||
<TopCard
|
||||
:typeList="list"
|
||||
v-model:value="modelRef.selector"
|
||||
@change="onSelectorChange"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
v-if="modelRef.selector === 'fixed'"
|
||||
name="selectorValues"
|
||||
:rules="[{ required: true, message: '请选择设备' }]"
|
||||
>
|
||||
<Device
|
||||
:productId="values.productDetail.id"
|
||||
v-model:value="modelRef.selectorValues"
|
||||
@change="onDeviceChange"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
v-else-if="modelRef.selector === 'relation'"
|
||||
label="关系"
|
||||
name="selectorValues"
|
||||
:rules="[{ required: true, message: '请选择关系' }]"
|
||||
>
|
||||
<j-select
|
||||
placeholder="请选择关系"
|
||||
v-model:value="modelRef.selectorValues"
|
||||
:options="relationList"
|
||||
show-search
|
||||
@change="onRelationChange"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
v-else-if="modelRef.selector === 'tag'"
|
||||
name="selectorValues"
|
||||
:rules="[{ required: true, message: '请选择标签' }]"
|
||||
>
|
||||
<Tag
|
||||
v-model:value="modelRef.selectorValues"
|
||||
:tagData="tagList"
|
||||
@change="onTagChange"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
v-else
|
||||
name="selectorValues"
|
||||
label="变量"
|
||||
:rules="[{ required: true, message: '请选择' }]"
|
||||
>
|
||||
<j-tree-select
|
||||
style="width: 100%; height: 100%"
|
||||
:tree-data="builtInList"
|
||||
v-model:value="modelRef.selectorValues"
|
||||
placeholder="请选择参数"
|
||||
@select="onVariableChange"
|
||||
>
|
||||
<template #title="{ name, description }">
|
||||
<a-space>
|
||||
{{ name }}
|
||||
<span style="color: grey; margin-left: 5px">{{
|
||||
description
|
||||
}}</span>
|
||||
</a-space>
|
||||
</template>
|
||||
</j-tree-select>
|
||||
</j-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name="Device">
|
||||
import { useSceneStore } from '@/store/scene';
|
||||
import TopCard from './TopCard.vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { queryBuiltInParams } from '@/api/rule-engine/scene';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import NoticeApi from '@/api/notice/config';
|
||||
import Device from './Device.vue';
|
||||
import Tag from './Tag.vue';
|
||||
|
||||
const props = defineProps({
|
||||
values: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
name: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
thenName: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
branchGroup: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
parallel: {
|
||||
type: Boolean,
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits(['save', 'cancel']);
|
||||
|
||||
const sceneStore = useSceneStore();
|
||||
const { data } = storeToRefs(sceneStore);
|
||||
|
||||
const formRef = ref();
|
||||
|
||||
const modelRef = reactive({
|
||||
selector: 'fixed',
|
||||
selectorValues: undefined,
|
||||
deviceId: '',
|
||||
source: '',
|
||||
relationName: '',
|
||||
upperKey: '',
|
||||
});
|
||||
|
||||
const list = ref<any[]>([]);
|
||||
const builtInList = ref<any[]>([]);
|
||||
const tagList = ref<any[]>([]);
|
||||
const relationList = ref<any[]>([]);
|
||||
|
||||
const TypeList = [
|
||||
{
|
||||
label: '自定义',
|
||||
value: 'fixed',
|
||||
image: getImage('/scene/device-custom.png'),
|
||||
tip: '自定义选择当前产品下的任意设备',
|
||||
},
|
||||
{
|
||||
label: '按关系',
|
||||
value: 'relation',
|
||||
image: getImage('/scene/device-relation.png'),
|
||||
tip: '选择与触发设备具有相同关系的设备',
|
||||
},
|
||||
{
|
||||
label: '按标签',
|
||||
value: 'tag',
|
||||
image: getImage('/scene/device-tag.png'),
|
||||
tip: '按标签选择产品下具有特定标签的设备',
|
||||
},
|
||||
{
|
||||
label: '按变量',
|
||||
value: 'variable',
|
||||
image: getImage('/scene/device-variable.png'),
|
||||
tip: '选择设备ID为上游变量值的设备',
|
||||
},
|
||||
];
|
||||
|
||||
const filterTree = (nodes: any[]) => {
|
||||
if (!nodes?.length) {
|
||||
return nodes;
|
||||
}
|
||||
return nodes.filter((it) => {
|
||||
if (
|
||||
it.children.find(
|
||||
(item: any) =>
|
||||
item.id.indexOf('deviceId' || 'device_id' || 'device_Id') >
|
||||
-1,
|
||||
) &&
|
||||
!it.children.find((item: any) => item.id.indexOf('boolean') > -1)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
const treeDataFilter = (arr: any[]) => {
|
||||
if (Array.isArray(arr) && arr.length) {
|
||||
const list: any[] = [];
|
||||
arr.map((item: any) => {
|
||||
if (item.children) {
|
||||
const children = treeDataFilter(item.children);
|
||||
if (children.length) {
|
||||
list.push({
|
||||
...item,
|
||||
title: item.name,
|
||||
value: item.id,
|
||||
disabled: true,
|
||||
children,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
item.children.find(
|
||||
(item: any) =>
|
||||
item.id.indexOf(
|
||||
'deviceId' || 'device_id' || 'device_Id',
|
||||
) > -1,
|
||||
) &&
|
||||
!item.children.find(
|
||||
(item: any) => item.id.indexOf('bolaen') > -1,
|
||||
)
|
||||
) {
|
||||
list.push(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
return list;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
const sourceChangeEvent = async () => {
|
||||
const _params = {
|
||||
branch: props.thenName,
|
||||
branchGroup: props.branchGroup,
|
||||
action: props.name - 1,
|
||||
};
|
||||
const resp = await queryBuiltInParams(unref(data), _params);
|
||||
if (resp.status === 200) {
|
||||
// const array = filterTree(resp.result as any[]);
|
||||
//判断相同产品才有按变量
|
||||
// if (props.formProductId === DeviceModel.productId)// TODO
|
||||
console.log(array);
|
||||
const arr = treeDataFilter(resp.result as any[]);
|
||||
builtInList.value = array;
|
||||
}
|
||||
};
|
||||
|
||||
const queryRelationList = () => {
|
||||
NoticeApi.getRelationUsers({
|
||||
paging: false,
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
terms: [{ termType: 'eq', column: 'objectTypeName', value: '设备' }],
|
||||
}).then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
relationList.value = (resp.result as any[]).map((item) => {
|
||||
return {
|
||||
label: item.name,
|
||||
value: item.relation,
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const filterType = async () => {
|
||||
const _list = TypeList.filter((item) => item.value === 'fixed');
|
||||
if (unref(data)?.trigger?.type === 'device') {
|
||||
//关系
|
||||
const res = await NoticeApi.getRelationUsers({
|
||||
paging: false,
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
terms: [
|
||||
{ termType: 'eq', column: 'objectTypeName', value: '设备' },
|
||||
],
|
||||
});
|
||||
if (res.status === 200 && res.result.length !== 0) {
|
||||
const array = TypeList.filter((item) => item.value === 'relation');
|
||||
_list.push(...array);
|
||||
}
|
||||
//标签
|
||||
const tag = JSON.parse(
|
||||
props.values.productDetail?.metadata || '{}',
|
||||
)?.tags;
|
||||
if (tag && tag.length !== 0) {
|
||||
const array = TypeList.filter((item) => item.value === 'tag');
|
||||
_list.push(...array);
|
||||
}
|
||||
//变量
|
||||
if (
|
||||
builtInList.value.length !== 0 &&
|
||||
!props.parallel &&
|
||||
props.name !== 0
|
||||
) {
|
||||
const array = TypeList.filter((item) => item.value === 'variable');
|
||||
_list.push(...array);
|
||||
}
|
||||
list.value = _list;
|
||||
} else {
|
||||
if (
|
||||
builtInList.value.length !== 0 &&
|
||||
!props.parallel &&
|
||||
props.name !== 0
|
||||
) {
|
||||
const array = TypeList.filter((item) => item.value === 'variable');
|
||||
_list.push(...array);
|
||||
}
|
||||
list.value = _list;
|
||||
}
|
||||
};
|
||||
|
||||
const onSelectorChange = (val: string) => {
|
||||
if (val === 'relation') {
|
||||
queryRelationList();
|
||||
}
|
||||
};
|
||||
|
||||
const onDeviceChange = (_detail: any) => {
|
||||
if (_detail) {
|
||||
emits('save', modelRef, _detail);
|
||||
}
|
||||
};
|
||||
|
||||
const onRelationChange = (val: any, options: any) => {
|
||||
modelRef.deviceId = 'deviceId';
|
||||
modelRef.source = 'upper';
|
||||
modelRef.selectorValues = val;
|
||||
modelRef.upperKey = 'scene.deviceId';
|
||||
modelRef.relationName = options.label;
|
||||
emits('save', modelRef, {});
|
||||
};
|
||||
|
||||
const onTagChange = (val: any[], arr: any[]) => {
|
||||
if (val) {
|
||||
modelRef.deviceId = 'deviceId';
|
||||
modelRef.source = 'fixed';
|
||||
}
|
||||
if (arr) {
|
||||
tagList.value = arr;
|
||||
}
|
||||
};
|
||||
|
||||
const onVariableChange = (val: any, node: any) => {
|
||||
modelRef.deviceId = val;
|
||||
// modelRef.deviceDetail = node;
|
||||
modelRef.selectorValues = [{ value: val, name: node.description }] as any;
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
Object.assign(modelRef, props.values);
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.values.productDetail,
|
||||
async (newVal) => {
|
||||
await sourceChangeEvent();
|
||||
if (newVal) {
|
||||
const metadata = JSON.parse(newVal?.metadata || '{}');
|
||||
tagList.value = metadata?.tags || [];
|
||||
filterType();
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
|
||||
</style>
|
|
@ -1,6 +1,13 @@
|
|||
<template>
|
||||
<j-modal title="执行动作" visible :width="860" @cancel="onCancel" @ok="save" :maskClosable="false">
|
||||
<j-steps :current='DeviceModel.current' @change='stepChange'>
|
||||
<j-modal
|
||||
title="执行动作"
|
||||
visible
|
||||
:width="860"
|
||||
@cancel="onCancel"
|
||||
@ok="save"
|
||||
:maskClosable="false"
|
||||
>
|
||||
<j-steps :current="current" @change="stepChange">
|
||||
<j-step>
|
||||
<template #title>选择产品</template>
|
||||
</j-step>
|
||||
|
@ -11,36 +18,82 @@
|
|||
<template #title>执行动作</template>
|
||||
</j-step>
|
||||
</j-steps>
|
||||
<j-divider style='margin-bottom: 10px;' />
|
||||
<div class='steps-content'>
|
||||
<Product v-if='DeviceModel.current === 0' v-model:rowKey='DeviceModel.productId'
|
||||
v-model:detail='DeviceModel.productDetail' />
|
||||
<j-divider style="margin-bottom: 10px" />
|
||||
<div class="steps-content">
|
||||
<Product
|
||||
v-if="current === 0"
|
||||
v-model:rowKey="DeviceModel.productId"
|
||||
v-model:detail="DeviceModel.productDetail"
|
||||
/>
|
||||
<Device
|
||||
v-else-if="current === 1"
|
||||
:name="name"
|
||||
:parallel="parallel"
|
||||
:branchGroup="branchGroup"
|
||||
:thenName="thenName"
|
||||
:values="DeviceModel"
|
||||
@save="onDeviceSave"
|
||||
/>
|
||||
<Action v-else-if="current === 2"
|
||||
:name="name"
|
||||
:branchGroup="branchGroup"
|
||||
:thenName="thenName"
|
||||
:values="DeviceModel"
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class='steps-action'>
|
||||
<j-button v-if='DeviceModel.current === 0' @click='cancel'>取消</j-button>
|
||||
<j-button v-else @click='prev'>上一步</j-button>
|
||||
<j-button type='primary' v-if='DeviceModel.current < 2' @click='saveClick'>下一步</j-button>
|
||||
<j-button type='primary' v-else @click='saveClick'>确定</j-button>
|
||||
</div>
|
||||
</template>
|
||||
<div class="steps-action">
|
||||
<j-button v-if="current === 0" @click="onCancel">取消</j-button>
|
||||
<j-button v-else @click="prev">上一步</j-button>
|
||||
<j-button type="primary" v-if="current < 2" @click="saveClick"
|
||||
>下一步</j-button
|
||||
>
|
||||
<j-button type="primary" v-else @click="saveClick"
|
||||
>确定</j-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { DeviceModelType } from './typings';
|
||||
import Product from './Product.vue';
|
||||
import Device from './device/index.vue';
|
||||
import Action from './actions/index.vue';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
import { detail } from '@/api/device/product'
|
||||
|
||||
type Emit = {
|
||||
(e: 'cancel'): void
|
||||
(e: 'save', data: any, options: Record<string, any>): void
|
||||
}
|
||||
(e: 'cancel'): void;
|
||||
(e: 'save', data: any, options: Record<string, any>): void;
|
||||
};
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
name: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
thenName: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
branchGroup: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
parallel: {
|
||||
type: Boolean,
|
||||
},
|
||||
});
|
||||
|
||||
const current = ref<number>(0);
|
||||
|
||||
const DeviceModel = reactive<DeviceModelType>({
|
||||
steps: [],
|
||||
current: 0,
|
||||
productId: '',
|
||||
deviceId: '',
|
||||
productDetail: {},
|
||||
|
@ -58,38 +111,64 @@ const DeviceModel = reactive<DeviceModelType>({
|
|||
columns: [],
|
||||
actionName: '',
|
||||
tagList: [],
|
||||
})
|
||||
});
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
const cancel = () => {
|
||||
const emit = defineEmits<Emit>();
|
||||
|
||||
const onCancel = () => {
|
||||
emit('cancel');
|
||||
};
|
||||
const save = async(step?: number) => {
|
||||
let _step = step !== undefined ? step : DeviceModel.current
|
||||
if (_step === 0) {
|
||||
DeviceModel.productId ? DeviceModel.current = 1 : onlyMessage('请选择产品', 'error')
|
||||
} else if (_step === 1) {
|
||||
|
||||
} else {
|
||||
|
||||
const save = async (step?: number) => {
|
||||
let _step = step !== undefined ? step : current.value;
|
||||
if (_step === 0) {
|
||||
DeviceModel.productId
|
||||
? (current.value = 1)
|
||||
: onlyMessage('请选择产品', 'error');
|
||||
} else if (_step === 1) {
|
||||
DeviceModel.deviceId
|
||||
? (current.value = 2)
|
||||
: onlyMessage('请选择设备', 'error');
|
||||
} else {
|
||||
}
|
||||
};
|
||||
|
||||
const stepChange = (step: number) => {
|
||||
if (step !== 0) {
|
||||
save(step - 1)
|
||||
save(step - 1);
|
||||
} else {
|
||||
DeviceModel.current = 0
|
||||
current.value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const prev = () => {
|
||||
DeviceModel.current = DeviceModel.current - 1
|
||||
}
|
||||
const saveClick = () => save()
|
||||
current.value -= 1;
|
||||
};
|
||||
|
||||
const saveClick = () => save();
|
||||
|
||||
const onDeviceSave = (_data: any, _detail: any) => {
|
||||
Object.assign(DeviceModel, _data)
|
||||
DeviceModel.deviceId = _detail.id
|
||||
DeviceModel.deviceDetail = _detail
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
Object.assign(DeviceModel, newValue);
|
||||
if(newValue?.productId){
|
||||
detail(newValue.productId).then(resp => {
|
||||
if(resp.status === 200){
|
||||
DeviceModel.productDetail = resp.result
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.steps-steps {
|
||||
width: 100%;
|
||||
|
@ -100,5 +179,8 @@ const saveClick = () => save()
|
|||
|
||||
.steps-content {
|
||||
width: 100%;
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
</style>
|
|
@ -2,12 +2,12 @@ import { ProductItem } from '@/views/device/Product/typings';
|
|||
import { ActionsDeviceProps } from '../../../typings';
|
||||
|
||||
type DeviceModelType = {
|
||||
steps: {
|
||||
key: string;
|
||||
title: string;
|
||||
content: React.ReactNode;
|
||||
}[];
|
||||
current: number;
|
||||
// steps: {
|
||||
// key: string;
|
||||
// title: string;
|
||||
// content: React.ReactNode;
|
||||
// }[];
|
||||
// current: number;
|
||||
productId: string;
|
||||
deviceId: string;
|
||||
productDetail: ProductItem | any;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div>
|
||||
<template v-if="actionType === 'device'">
|
||||
<Device v-bind="props" :value="data?.device" @cancel="onCancel" @save="onPropsOk" />
|
||||
<Device v-bind="props" :value="data?.device" @cancel="onCancel" @save="onPropsOk" :thenName="branchesName" />
|
||||
</template>
|
||||
<template v-else-if="actionType === 'notify'">
|
||||
<Notify v-bind="props" :value="data?.notify" @cancel="onCancel" @save="onPropsOk" />
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<template #title="{ name, description }">
|
||||
<a-space>
|
||||
{{ name }}
|
||||
<spn style="color: grey; margin-left: 5px">{{ description }}</spn>
|
||||
<span style="color: grey; margin-left: 5px">{{ description }}</span>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-tree-select>
|
||||
|
|
Loading…
Reference in New Issue