fix: 修改设备列表为protable

This commit is contained in:
100011797 2023-03-02 17:55:28 +08:00
parent dcf0b05bc7
commit f7fac41743
37 changed files with 1333 additions and 226 deletions

View File

@ -34,5 +34,9 @@ export default {
// 微信绑定用户
weChatBindUser: (data: any, id: string) => patch(`/user/third-party/weixin_corpMessage/${id}`, data),
// 解绑
unBindUser: (data: any, id: string) => post(`/user/third-party/${id}/_unbind`, data)
unBindUser: (data: any, id: string) => post(`/user/third-party/${id}/_unbind`, data),
//通知类型
queryMessageType: () => get(`/notifier/config/types`),
// 不分页-列表
queryListNoPaging: (data: any) => post(`/notifier/config/_query/no-paging?paging=false`, data)
}

View File

@ -23,5 +23,6 @@ export default {
// 语音/短信获取阿里云模板
getAliTemplate: (id: any) => get(`/notifier/sms/aliyun/${id}/templates`),
// 短信获取签名
getSigns: (id: any) => get(`/notifier/sms/aliyun/${id}/signs`)
getSigns: (id: any) => get(`/notifier/sms/aliyun/${id}/signs`),
getListByConfigId: (id: string, data: any): any => post(`/notifier/template/${id}/_query`, data),
}

View File

@ -1,8 +1,8 @@
<template>
<a-badge
<j-badge
:status="statusNames ? statusNames[status] : 'default'"
:text="text"
></a-badge>
></j-badge>
</template>
<script setup lang="ts">

View File

@ -21,7 +21,7 @@
<!-- 勾选 -->
<div v-if="active" class="checked-icon">
<div>
<CheckOutlined />
<AIcon type="CheckOutlined" />
</div>
</div>
@ -62,24 +62,6 @@
}"
>
<slot name="actions" v-bind="item"></slot>
<!-- <a-popconfirm v-if="item.popConfirm" v-bind="item.popConfirm">
<a-button :disabled="item.disabled">
<DeleteOutlined v-if="item.key === 'delete'" />
<template v-else>
<AIcon :type="item.icon" />
<span>{{ item.text }}</span>
</template>
</a-button>
</a-popconfirm>
<template v-else>
<a-button :disabled="item.disabled">
<DeleteOutlined v-if="item.key === 'delete'" />
<template v-else>
<AIcon :type="item.icon" />
<span>{{ item.text }}</span>
</template>
</a-button>
</template> -->
</div>
</div>
</slot>
@ -87,13 +69,7 @@
</template>
<script setup lang="ts">
import {
SearchOutlined,
CheckOutlined,
DeleteOutlined,
} from '@ant-design/icons-vue';
import BadgeStatus from '@/components/BadgeStatus/index.vue';
import { StatusColorEnum } from '@/utils/consts.ts';
import type { ActionsType } from '@/components/Table/index.vue';
import { PropType } from 'vue';

View File

@ -1,54 +1,54 @@
<template>
<template v-if="isPermission">
<template v-if="popConfirm">
<a-popconfirm v-bind="popConfirm" :disabled="!isPermission || props.disabled">
<a-tooltip v-if="tooltip" v-bind="tooltip">
<j-popconfirm v-bind="popConfirm" :disabled="!isPermission || props.disabled">
<j-tooltip v-if="tooltip" v-bind="tooltip">
<slot v-if="noButton"></slot>
<a-button v-else v-bind="props" :disabled="_isPermission" :style="props.style">
<j-button v-else v-bind="props" :disabled="_isPermission" :style="props.style">
<slot></slot>
<template #icon>
<slot name="icon"></slot>
</template>
</a-button>
</a-tooltip>
<a-button v-else v-bind="props" :disabled="_isPermission" >
</j-button>
</j-tooltip>
<j-button v-else v-bind="props" :disabled="_isPermission" >
<slot></slot>
<template #icon>
<slot name="icon"></slot>
</template>
</a-button>
</a-popconfirm>
</j-button>
</j-popconfirm>
</template>
<template v-else-if="tooltip">
<a-tooltip v-bind="tooltip">
<j-tooltip v-bind="tooltip">
<slot v-if="noButton"></slot>
<a-button v-else v-bind="props" :disabled="_isPermission" :style="props.style">
<j-button v-else v-bind="props" :disabled="_isPermission" :style="props.style">
<slot></slot>
<template #icon>
<slot name="icon"></slot>
</template>
</a-button>
</a-tooltip>
</j-button>
</j-tooltip>
</template>
<template v-else>
<slot v-if="noButton"></slot>
<a-button v-else v-bind="props" :disabled="_isPermission" :style="props.style">
<j-button v-else v-bind="props" :disabled="_isPermission" :style="props.style">
<slot></slot>
<template #icon>
<slot name="icon"></slot>
</template>
</a-button>
</j-button>
</template>
</template>
<a-tooltip v-else title="没有权限">
<j-tooltip v-else title="没有权限">
<slot v-if="noButton"></slot>
<a-button v-else v-bind="props" :disabled="_isPermission" :style="props.style">
<j-button v-else v-bind="props" :disabled="_isPermission" :style="props.style">
<slot></slot>
<template #icon>
<slot name="icon"></slot>
</template>
</a-button>
</a-tooltip>
</j-button>
</j-tooltip>
</template>
<script setup lang="ts" name="PermissionButton">
import { CSSProperties, PropType } from 'vue'

View File

@ -1,5 +1,5 @@
<template>
<a-drawer placement="right" :closable="false" :visible="true">
<j-drawer placement="right" :closable="false" :visible="true">
<template #title>
<div
style="
@ -15,21 +15,21 @@
@click="onClose"
/></span
>
<a-button type="primary" @click="saveBtn">保存</a-button>
<j-button type="primary" @click="saveBtn">保存</j-button>
</div>
</template>
<a-form layout="vertical" ref="formRef" :model="modelRef">
<j-form layout="vertical" ref="formRef" :model="modelRef">
<template v-for="(item, index) in props.config" :key="index">
<a-form-item
<j-form-item
:name="item.property"
v-for="i in item.properties"
:key="i.property"
>
<template #label>
<span style="margin-right: 5px">{{ i.name }}</span>
<a-tooltip v-if="i.description" :title="i.description"
<j-tooltip v-if="i.description" :title="i.description"
><AIcon type="QuestionCircleOutlined"
/></a-tooltip>
/></j-tooltip>
</template>
<ValueItem
v-model:modelValue="modelRef[i.property]"
@ -45,10 +45,10 @@
: undefined
"
/>
</a-form-item>
</j-form-item>
</template>
</a-form>
</a-drawer>
</j-form>
</j-drawer>
</template>
<script lang="ts" setup>

View File

@ -2,7 +2,7 @@
<div style="margin-top: 20px" v-if="config.length">
<div style="display: flex; margin-bottom: 20px; align-items: center">
<div style="font-size: 16px; font-weight: 700">配置</div>
<a-space>
<j-space>
<PermissionButton
type="link"
@click="visible = true"
@ -20,10 +20,10 @@
}"
hasPermission="device/Instance:update"
>
<AIcon type="CheckOutlined" />应用配置<a-tooltip
<AIcon type="CheckOutlined" />应用配置<j-tooltip
title="修改配置后需重新应用后才能生效。"
><AIcon type="QuestionCircleOutlined"
/></a-tooltip>
/></j-tooltip>
</PermissionButton>
<PermissionButton
type="link"
@ -34,26 +34,26 @@
}"
hasPermission="device/Instance:update"
>
<AIcon type="SyncOutlined" />恢复默认<a-tooltip
<AIcon type="SyncOutlined" />恢复默认<j-tooltip
title="该设备单独编辑过配置信息,点击此将恢复成默认的配置信息,请谨慎操作。"
><AIcon type="QuestionCircleOutlined"
/></a-tooltip>
/></j-tooltip>
</PermissionButton>
</a-space>
</j-space>
</div>
<a-descriptions bordered size="small" v-for="i in config" :key="i.name">
<j-descriptions bordered size="small" v-for="i in config" :key="i.name">
<template #title
><h4 style="font-size: 15px">{{ i.name }}</h4></template
>
<a-descriptions-item
<j-descriptions-item
v-for="item in i.properties"
:key="item.property"
>
<template #label>
<span style="margin-right: 5px">{{ item.name }}</span>
<a-tooltip v-if="item.description" :title="item.description"
<j-tooltip v-if="item.description" :title="item.description"
><AIcon type="QuestionCircleOutlined"
/></a-tooltip>
/></j-tooltip>
</template>
<span
v-if="
@ -68,7 +68,7 @@
instanceStore.current?.configuration?.[item.property] ||
''
}}</span>
<a-tooltip
<j-tooltip
v-if="isExit(item.property)"
:title="`有效值:${
instanceStore.current?.configuration?.[
@ -76,10 +76,10 @@
]
}`"
><AIcon type="QuestionCircleOutlined"
/></a-tooltip>
/></j-tooltip>
</span>
</a-descriptions-item>
</a-descriptions>
</j-descriptions-item>
</j-descriptions>
<Save
v-if="visible"
@save="saveBtn"

View File

@ -1,5 +1,5 @@
<template>
<a-drawer placement="right" :closable="false" :visible="true">
<j-drawer placement="right" :closable="false" :visible="true">
<template #title>
<div
style="
@ -15,32 +15,32 @@
@click="onClose"
/></span
>
<a-button type="primary" @click="saveBtn">保存</a-button>
<j-button type="primary" @click="saveBtn">保存</j-button>
</div>
</template>
<a-form layout="vertical" ref="formRef" :model="modelRef">
<a-form-item
<j-form layout="vertical" ref="formRef" :model="modelRef">
<j-form-item
:name="item.relation"
:label="item.relationName"
v-for="(item, index) in dataSource"
:key="index"
>
<a-select
<j-select
showSearch
mode="multiple"
v-model:value="modelRef[item.relation]"
:placeholder="`请选择${item.relationName}`"
>
<a-select-option
<j-select-option
:value="item.value"
v-for="item in userList"
:key="item.id"
>{{ item.name }}</a-select-option
>{{ item.name }}</j-select-option
>
</a-select>
</a-form-item>
</a-form>
</a-drawer>
</j-select>
</j-form-item>
</j-form>
</j-drawer>
</template>
<script lang="ts" setup>

View File

@ -1,6 +1,6 @@
<template>
<div style="margin-top: 20px">
<a-descriptions bordered>
<j-descriptions bordered>
<template #title>
关系信息
<PermissionButton
@ -8,13 +8,13 @@
@click="visible = true"
hasPermission="device/Instance:update"
>
<AIcon type="EditOutlined" />编辑<a-tooltip
<AIcon type="EditOutlined" />编辑<j-tooltip
title="管理设备与其他业务的关联关系,关系来源于关系配置"
><AIcon type="QuestionCircleOutlined"
/></a-tooltip>
/></j-tooltip>
</PermissionButton>
</template>
<a-descriptions-item
<j-descriptions-item
:span="1"
v-for="item in dataSource"
:key="item.objectId"
@ -23,9 +23,9 @@
item?.related
? (item?.related || []).map((i) => i.name).join(',')
: ''
}}</a-descriptions-item
}}</j-descriptions-item
>
</a-descriptions>
</j-descriptions>
<Save v-if="visible" @save="saveBtn" @close="visible = false" />
</div>
</template>

View File

@ -1,15 +1,15 @@
<template>
<a-modal
<j-modal
:width="1000"
:visible="true"
title="编辑标签"
@ok="handleOk"
@cancel="handleCancel"
>
<a-table
<j-table
rowKey="id"
:columns="columns"
:data-source="dataSource"
:datj-source="dataSource"
bordered
:pagination="false"
>
@ -43,8 +43,8 @@
</template>
</div>
</template>
</a-table>
</a-modal>
</j-table>
</j-modal>
</template>
<script lang="ts" setup>

View File

@ -1,6 +1,6 @@
<template>
<div style="margin-top: 20px">
<a-descriptions bordered>
<j-descriptions bordered>
<template #title>
标签
<PermissionButton
@ -11,14 +11,14 @@
<AIcon type="EditOutlined" />编辑
</PermissionButton>
</template>
<a-descriptions-item
<j-descriptions-item
:span="1"
v-for="item in dataSource"
:key="item.key"
:label="`${item.name}${item.key})`"
>{{ item?.value }}</a-descriptions-item
>{{ item?.value }}</j-descriptions-item
>
</a-descriptions>
</j-descriptions>
<Save v-if="visible" @close="visible = false" @save="saveBtn" />
</div>
</template>

View File

@ -1,6 +1,6 @@
<template>
<a-card>
<a-descriptions bordered>
<j-card>
<j-descriptions bordered>
<template #title>
设备信息
<PermissionButton
@ -12,59 +12,59 @@
编辑
</PermissionButton>
</template>
<a-descriptions-item label="设备ID">{{
<j-descriptions-item label="设备ID">{{
instanceStore.current.id
}}</a-descriptions-item>
<a-descriptions-item label="产品名称">{{
}}</j-descriptions-item>
<j-descriptions-item label="产品名称">{{
instanceStore.current.productName
}}</a-descriptions-item>
<a-descriptions-item label="产品分类">{{
}}</j-descriptions-item>
<j-descriptions-item label="产品分类">{{
instanceStore.current.classifiedName
}}</a-descriptions-item>
<a-descriptions-item label="设备类型">{{
}}</j-descriptions-item>
<j-descriptions-item label="设备类型">{{
instanceStore.current.deviceType?.text
}}</a-descriptions-item>
<a-descriptions-item label="固件版本">{{
}}</j-descriptions-item>
<j-descriptions-item label="固件版本">{{
instanceStore.current.firmwareInfo?.version
}}</a-descriptions-item>
<a-descriptions-item label="连接协议">{{
}}</j-descriptions-item>
<j-descriptions-item label="连接协议">{{
instanceStore.current?.protocolName
}}</a-descriptions-item>
<a-descriptions-item label="消息协议">{{
}}</j-descriptions-item>
<j-descriptions-item label="消息协议">{{
instanceStore.current.transport
}}</a-descriptions-item>
<a-descriptions-item label="创建时间">{{
}}</j-descriptions-item>
<j-descriptions-item label="创建时间">{{
instanceStore.current.createTime
? moment(instanceStore.current.createTime).format(
'YYYY-MM-DD HH:mm:ss',
)
: ''
}}</a-descriptions-item>
<a-descriptions-item label="注册时间">{{
}}</j-descriptions-item>
<j-descriptions-item label="注册时间">{{
instanceStore.current.registerTime
? moment(instanceStore.current.registerTime).format(
'YYYY-MM-DD HH:mm:ss',
)
: ''
}}</a-descriptions-item>
<a-descriptions-item label="最后上线时间">{{
}}</j-descriptions-item>
<j-descriptions-item label="最后上线时间">{{
instanceStore.current.onlineTime
? moment(instanceStore.current.onlineTime).format(
'YYYY-MM-DD HH:mm:ss',
)
: ''
}}</a-descriptions-item>
<a-descriptions-item
}}</j-descriptions-item>
<j-descriptions-item
label="父设备"
v-if="
instanceStore.current.deviceType?.value === 'childrenDevice'
"
>{{ instanceStore.current.parentId }}</a-descriptions-item
>{{ instanceStore.current.parentId }}</j-descriptions-item
>
<a-descriptions-item label="说明">{{
<j-descriptions-item label="说明">{{
instanceStore.current.description
}}</a-descriptions-item>
</a-descriptions>
}}</j-descriptions-item>
</j-descriptions>
<Config />
<Tags
v-if="
@ -84,7 +84,7 @@
@close="visible = false"
@save="saveBtn"
/>
</a-card>
</j-card>
</template>
<script lang="ts" setup>

View File

@ -1,11 +1,11 @@
<template>
<a-card>
<j-card>
<Search
:columns="columns"
target="device-instance-log"
@search="handleSearch"
/>
<JTable
<JProTable
ref="instanceRefLog"
:columns="columns"
:request="(e: Record<string, any>) => queryLog(instanceStore.current.id, e)"
@ -26,23 +26,23 @@
}}
</template>
<template #action="slotProps">
<a-space>
<j-space>
<template
v-for="i in getActions(slotProps, 'table')"
:key="i.key"
>
<a-button
<j-button
@click="i.onClick"
type="link"
style="padding: 0px"
>
<template #icon><AIcon :type="i.icon" /></template>
</a-button>
</j-button>
</template>
</a-space>
</j-space>
</template>
</JTable>
</a-card>
</JProTable>
</j-card>
</template>
<script lang="ts" setup>

View File

@ -1,12 +1,12 @@
<template>
<a-spin :spinning="loading">
<JTable
<j-spin :spinning="loading">
<JProTable
:columns="columns"
:dataSource="dataSource"
:bodyStyle="{ padding: '0 0 0 20px' }"
>
<template #headerTitle>
<a-input-search
<j-input-search
placeholder="请输入名称"
style="width: 300px; margin-bottom: 10px"
@search="onSearch"
@ -31,18 +31,18 @@
{{ propertyValue[slotProps?.id]?.timeString || '--' }}
</template>
<template #action="slotProps">
<a-space :size="16">
<j-space :size="16">
<template v-for="i in getActions(slotProps)" :key="i.key">
<a-tooltip v-bind="i.tooltip" v-if="i.key !== 'edit'">
<a-button
<j-tooltip v-bind="i.tooltip" v-if="i.key !== 'edit'">
<j-button
style="padding: 0"
type="link"
:disabled="i.disabled"
@click="i.onClick && i.onClick(slotProps)"
>
<AIcon :type="i.icon" />
</a-button>
</a-tooltip>
</j-button>
</j-tooltip>
<PermissionButton
:disabled="i.disabled"
v-else
@ -56,10 +56,10 @@
<template #icon><AIcon :type="i.icon" /></template>
</PermissionButton>
</template>
</a-space>
</j-space>
</template>
<template #paginationRender>
<a-pagination
<j-pagination
size="small"
:total="total"
:showQuickJumper="false"
@ -78,8 +78,8 @@
@change="pageChange"
/>
</template>
</JTable>
</a-spin>
</JProTable>
</j-spin>
<Save v-if="editVisible" @close="editVisible = false" :data="currentInfo" />
<Indicators
v-if="indicatorVisible"

View File

@ -1,15 +1,15 @@
<template>
<a-card>
<j-card>
<div class="property-box">
<div class="property-box-left">
<a-input-search
<j-input-search
v-model:value="value"
placeholder="请输入事件名称"
style="width: 200px; margin-bottom: 10px"
@search="onSearch"
:allowClear="true"
/>
<a-tabs
<j-tabs
tab-position="left"
style="height: 600px"
v-if="tabList.length"
@ -17,12 +17,12 @@
:tabBarStyle="{ width: '200px' }"
@change="tabChange"
>
<a-tab-pane
<j-tab-pane
v-for="i in tabList"
:key="i.key"
:tab="i.tab"
/>
</a-tabs>
</j-tabs>
<JEmpty v-else style="margin: 250px 0" />
</div>
<div class="property-box-right">
@ -30,7 +30,7 @@
<Property v-else :data="properties" />
</div>
</div>
</a-card>
</j-card>
</template>
<script lang="ts" setup>

View File

@ -1,88 +1,88 @@
<template>
<a-modal
<j-modal
:maskClosable="false"
width="650px"
:visible="true"
:title="!!props.data.id ? '编辑' : '新增'"
:title="!!data?.id ? '编辑' : '新增'"
@ok="handleSave"
@cancel="handleCancel"
:confirmLoading="loading"
>
<div style="margin-top: 10px">
<a-form
<j-form
:layout="'vertical'"
ref="formRef"
:rules="rules"
:model="modelRef"
>
<a-row type="flex">
<a-col flex="180px">
<a-form-item name="photoUrl">
<j-row type="flex">
<j-col flex="180px">
<j-form-item name="photoUrl">
<JUpload v-model="modelRef.photoUrl" />
</a-form-item>
</a-col>
<a-col flex="auto">
<a-form-item name="id">
</j-form-item>
</j-col>
<j-col flex="auto">
<j-form-item name="id">
<template #label>
<span>
ID
<a-tooltip title="若不填写系统将自动生成唯一ID">
<j-tooltip title="若不填写系统将自动生成唯一ID">
<AIcon
type="QuestionCircleOutlined"
style="margin-left: 2px;" />
</a-tooltip>
</j-tooltip>
</span>
</template>
<a-input
<j-input
v-model:value="modelRef.id"
placeholder="请输入ID"
:disabled="!!props.data.id"
:disabled="!!data?.id"
/>
</a-form-item>
<a-form-item label="名称" name="name">
<a-input
</j-form-item>
<j-form-item label="名称" name="name">
<j-input
v-model:value="modelRef.name"
placeholder="请输入名称"
/>
</a-form-item>
</a-col>
</a-row>
<a-form-item name="productId">
</j-form-item>
</j-col>
</j-row>
<j-form-item name="productId">
<template #label>
<span>所属产品
<a-tooltip title="只能选择“正常”状态的产品">
<j-tooltip title="只能选择“正常”状态的产品">
<AIcon
type="QuestionCircleOutlined"
style="margin-left: 2px" />
</a-tooltip>
</j-tooltip>
</span>
</template>
<a-select
<j-select
showSearch
v-model:value="modelRef.productId"
placeholder="请选择所属产品"
:filter-option="filterOption"
>
<a-select-option
<j-select-option
:value="item.id"
v-for="item in productList"
:key="item.id"
:label="item.name"
:disabled="!!props.data.id"
>{{item.name}}</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="说明" name="describe">
<a-textarea
:disabled="!!data?.id"
>{{item.name}}</j-select-option>
</j-select>
</j-form-item>
<j-form-item label="说明" name="describe">
<j-textarea
v-model:value="modelRef.describe"
placeholder="请输入说明"
showCount
:maxlength="200"
/>
</a-form-item>
</a-form>
</j-form-item>
</j-form>
</div>
</a-modal>
</j-modal>
</template>
<script lang="ts" setup>
@ -157,7 +157,7 @@ const rules = {
message: '最多输入64个字符',
},
{
pattern: /^[a-zA-Z0-9_\-]+$/,
pattern: /^[j-zA-Z0-9_\-]+$/,
message: '请输入英文或者数字或者-或者_',
},
{

View File

@ -1,11 +1,11 @@
<template>
<page-container>
<Search
<JSearch
:columns="columns"
target="device-instance"
@search="handleSearch"
/>
<JTable
<JProTable
ref="instanceRef"
:columns="columns"
:request="query"
@ -18,7 +18,7 @@
:params="params"
>
<template #headerTitle>
<a-space>
<j-space>
<PermissionButton
type="primary"
@click="handleAdd"
@ -27,13 +27,13 @@
<template #icon><AIcon type="PlusOutlined" /></template>
新增
</PermissionButton>
<a-dropdown>
<a-button
<j-dropdown>
<j-button
>批量操作 <AIcon type="DownOutlined"
/></a-button>
/></j-button>
<template #overlay>
<a-menu>
<a-menu-item>
<j-menu>
<j-menu-item>
<PermissionButton
@click="exportVisible = true"
hasPermission="device/Instance:export"
@ -43,8 +43,8 @@
/></template>
批量导出设备
</PermissionButton>
</a-menu-item>
<a-menu-item>
</j-menu-item>
<j-menu-item>
<PermissionButton
@click="importVisible = true"
hasPermission="device/Instance:import"
@ -54,8 +54,8 @@
/></template>
批量导入设备
</PermissionButton>
</a-menu-item>
<a-menu-item>
</j-menu-item>
<j-menu-item>
<PermissionButton
ghost
type="primary"
@ -70,8 +70,8 @@
/></template>
激活全部设备
</PermissionButton>
</a-menu-item>
<a-menu-item>
</j-menu-item>
<j-menu-item>
<PermissionButton
type="primary"
@click="syncDeviceStatus"
@ -82,8 +82,8 @@
/></template>
同步设备状态
</PermissionButton>
</a-menu-item>
<a-menu-item v-if="_selectedRowKeys.length">
</j-menu-item>
<j-menu-item v-if="_selectedRowKeys.length">
<PermissionButton
type="primary"
danger
@ -98,8 +98,8 @@
/></template>
删除选中设备
</PermissionButton>
</a-menu-item>
<a-menu-item v-if="_selectedRowKeys.length">
</j-menu-item>
<j-menu-item v-if="_selectedRowKeys.length">
<PermissionButton
type="primary"
:popConfirm="{
@ -113,8 +113,8 @@
/></template>
激活选中设备
</PermissionButton>
</a-menu-item>
<a-menu-item v-if="_selectedRowKeys.length">
</j-menu-item>
<j-menu-item v-if="_selectedRowKeys.length">
<PermissionButton
type="primary"
danger
@ -129,11 +129,11 @@
/></template>
禁用选中设备
</PermissionButton>
</a-menu-item>
</a-menu>
</j-menu-item>
</j-menu>
</template>
</a-dropdown>
</a-space>
</j-dropdown>
</j-space>
</template>
<template #card="slotProps">
<CardBox
@ -160,22 +160,22 @@
{{ slotProps.name }}
</span>
</Ellipsis>
<a-row style="margin-top: 20px">
<a-col :span="12">
<j-row style="margin-top: 20px">
<j-col :span="12">
<div class="card-item-content-text">
设备类型
</div>
<div>{{ slotProps.deviceType?.text }}</div>
</a-col>
<a-col :span="12">
</j-col>
<j-col :span="12">
<div class="card-item-content-text">
产品名称
</div>
<Ellipsis style="width: 100%">
{{ slotProps.productName }}
</Ellipsis>
</a-col>
</a-row>
</j-col>
</j-row>
</template>
<template #actions="item">
<PermissionButton
@ -200,13 +200,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"
@ -225,9 +225,9 @@
<template #icon><AIcon :type="i.icon" /></template>
</PermissionButton>
</template>
</a-space>
</j-space>
</template>
</JTable>
</JProTable>
</page-container>
<Import v-if="importVisible" @close="importVisible = false" />
<Export

View File

@ -14,6 +14,7 @@
<Title :options='data.options.trigger' />
</AddButton>
</a-form-item>
<Action />
<AddModel v-if='visible' @cancel='visible = false' v-model='data.device' v-model:options='data.options.trigger' />
</div>
</template>
@ -24,6 +25,7 @@ import { useSceneStore } from '@/store/scene'
import AddModel from './AddModal.vue'
import AddButton from '../components/AddButton.vue'
import Title from '../components/Title.vue'
import Action from '../action/index.vue'
const sceneStore = useSceneStore()
const { data } = storeToRefs<any>(sceneStore)

View File

@ -0,0 +1,63 @@
<template>
<j-modal
title="延迟执行"
visible
:width="400"
@cancel="onCancel"
@ok="onOk"
:maskClosable="false"
>
<a-input-number
style="max-width: 220px"
placeholder="请输入时间"
v-model:value="value"
:precision="3"
:min="0"
:max="6535"
>
<template #addonAfter>
<a-select
:options="[
{ label: '秒', value: 'seconds' },
{ label: '分', value: 'minutes' },
{ label: '小时', value: 'hours' },
]"
v-model:value="unit"
/>
</template>
</a-input-number>
</j-modal>
</template>
<script lang="ts" setup>
import { onlyMessage } from '@/utils/comm';
const timeUnitEnum = {
seconds: '秒',
minutes: '分',
hours: '小时',
};
const emit = defineEmits(['cancel', 'save']);
const value = ref<number>(0);
const unit = ref<'seconds' | 'minutes' | 'hours'>('seconds');
const onCancel = () => {
emit('cancel');
};
const onOk = () => {
if (unref(value) || unref(value) === 0) {
} else {
onlyMessage('请输入时间', 'error');
}
emit(
'save',
{
time: value.value,
unit: unit.value,
},
{ name: `${value.value} ${timeUnitEnum[unit.value]}后,执行后续动作` },
);
};
</script>

View File

@ -0,0 +1,22 @@
<template>
<j-modal
title="执行动作"
visible
:width="860"
@cancel="onCancel"
@ok="onOk"
:maskClosable="false"
>
device
</j-modal>
</template>
<script lang="ts" setup>
const emit = defineEmits(['cancel', 'save']);
const onCancel = () => {
emit('cancel');
};
const onOk = () => {
emit('save');
};
</script>

View File

@ -0,0 +1,3 @@
<template>
<div>ITEM</div>
</template>

View File

@ -0,0 +1,74 @@
<template>
<div class="action-list-content">
<div class="actions-add-list" :class="{'border': props.actions.length}">
<j-button type="primary" ghost style="width: 100%" @click="onAdd">
<template #icon><AIcon type="PlusOutlined" /></template>
添加执行动作
</j-button>
</div>
<Modal v-if="visible" @cancel="visible = false" />
</div>
</template>
<script lang="ts" setup>
import { PropType } from 'vue';
import { ActionsType, ParallelType } from '../../../typings';
import Modal from '../Modal/index.vue'
interface ListProps {
branchesName: number;
type: ParallelType;
actions: ActionsType[];
parallel: boolean;
}
const props = defineProps({
branchesName: Number,
type: {
type: String as PropType<ListProps['type']>,
default: 'serial',
},
actions: {
type: Array as PropType<ListProps['actions']>,
default: () => [],
},
parallel: Boolean,
});
const visible = ref<boolean>(false)
const onAdd = () => {
visible.value = true
}
</script>
<style lang="less" scoped>
.action-list-content {
padding: 8px;
.actions-list_form {
.action-list-add {
display: flex;
justify-content: flex-end;
margin-top: 16px;
padding-top: 16px;
border-top: 1px solid @primary-color;
}
}
.filter-add-button {
width: 100%;
color: rgba(0, 0, 0, 0.3);
text-align: center;
cursor: pointer;
}
.actions-add-list {
&.border {
padding-top: 16px;
border-top: 1px solid @primary-color;
}
}
}
</style>

View File

@ -0,0 +1,2 @@
export { default as List } from './List.vue';
export { default as Item } from './Item.vue';

View File

@ -0,0 +1,105 @@
<template>
<j-modal
title="类型"
visible
:width="860"
@cancel="onCancel"
@ok="onOk"
:maskClosable="false"
>
<a-form ref="actionForm" :model="formModel" layout="vertical">
<a-form-item
label="类型"
name="type"
:rules="[
{
required: true,
message: '请选择类型',
},
]"
>
<j-card-select
v-model:value="formModel.type"
:options="options"
type="horizontal"
float="right"
/>
</a-form-item>
<template v-if="actionType === 'device'">
<Device @cancel="onCancel" @save="onPropsOk" />
</template>
<template v-else-if="actionType === 'notify'">
<Notify @cancel="onCancel" @save="onPropsOk" />
</template>
<template v-else-if="actionType === 'delay'">
<Delay @cancel="onCancel" @save="onPropsOk" />
</template>
</a-form>
</j-modal>
</template>
<script lang="ts" setup>
import { getImage } from '@/utils/comm';
import Delay from '../Delay/index.vue'
import Notify from '../Notify/index.vue'
import Device from '../Device/index.vue'
const emit = defineEmits(['cancel', 'save']);
const options = [
{
label: '设备输出',
value: 'device',
iconUrl: getImage('/scene/device-type.png'),
subLabel: '配置设备调用功能、读取属性、设置属性规则',
},
{
label: '消息通知',
value: 'notify',
iconUrl: getImage('/scene/message-type.png'),
subLabel: '配置向指定用户发邮件、钉钉、微信、短信等通知',
},
{
label: '延迟执行',
value: 'delay',
iconUrl: getImage('/scene/delay-type.png'),
subLabel: '等待一段时间后,再执行后续动作',
},
{
label: '触发告警',
value: 'trigger',
iconUrl: getImage('/scene/trigger-type.png'),
subLabel: '配置触发告警规则,需配合“告警配置”使用',
},
{
label: '解除告警',
value: 'relieve',
iconUrl: getImage('/scene/cancel-type.png'),
subLabel: '配置解除告警规则,需配合“告警配置”使用',
},
];
const actionForm = ref();
const formModel = reactive({
type: '',
});
const actionType = ref<string>('')
const onCancel = () => {
emit('cancel');
};
const onOk = () => {
actionForm.value.validate().then((values: any) => {
actionType.value = values?.type
if (values?.type === 'relieve' || values?.type === 'trigger') {
// emit('save');
// props.save({ ...props.data, executor: 'alarm', alarm: { mode: values.type } }, {});
}
});
};
const onPropsOk = (data: any, option: any) => {
console.log(data, option)
}
</script>

View File

@ -0,0 +1,178 @@
<template>
<Search
:columns="columns"
type="simple"
target="action-notice-config"
@search="handleSearch"
class="search"
/>
<div style="height: 400px; overflow-y: auto">
<JTable
:columns="columns"
:request="ConfigApi.list"
model="CARD"
:bodyStyle="{
paddingRight: 0,
paddingLeft: 0,
}"
:defaultParams="{
terms: [
{
terms: [
{
termType: 'eq',
column: 'type',
value: props.notifyType,
},
],
},
],
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:params="params"
:gridColumn="2"
:gridColumns="[2, 2, 2]"
:rowSelection="{
selectedRowKeys: _selectedRowKeys,
}"
@cancelSelect="cancelSelect"
>
<template #card="slotProps">
<CardBox
:showStatus="false"
:value="slotProps"
:showTool="false"
:actions="[]"
v-bind="slotProps"
@click="handleClick"
:active="_selectedRowKeys.includes(slotProps.id)"
>
<template #img>
<slot name="img">
<img
:src="
getLogo(slotProps.type, slotProps.provider)
"
class="logo"
/>
</slot>
</template>
<template #content>
<Ellipsis style="width: calc(100% - 100px)">
<span style="font-size: 16px; font-weight: 600">
{{ slotProps.name }}
</span>
</Ellipsis>
<a-row>
<a-col :span="12">
<div class="card-item-content-text">
通知方式
</div>
<div>
{{ getMethodTxt(slotProps.type) }}
</div>
</a-col>
<a-col :span="12">
<div class="card-item-content-text">说明</div>
<Ellipsis>
{{ slotProps.description }}
</Ellipsis>
</a-col>
</a-row>
</template>
</CardBox>
</template>
</JTable>
</div>
</template>
<script lang="ts" setup>
import ConfigApi from '@/api/notice/config';
import { MSG_TYPE, NOTICE_METHOD } from '@/views/notice/const';
const props = defineProps({
notifyType: {
type: String,
default: '',
},
value: {
type: String,
default: '',
},
});
const emit = defineEmits(['update:value']);
const getLogo = (type: string, provider: string) => {
return MSG_TYPE[type].find((f: any) => f.value === provider)?.logo;
};
const getMethodTxt = (type: string) => {
return NOTICE_METHOD.find((f) => f.value === type)?.label;
};
const params = ref<Record<string, any>>({});
const _selectedRowKeys = ref<string[]>([]);
const columns = [
{
title: '名称',
dataIndex: 'name',
key: 'name',
search: {
type: 'string',
},
},
{
title: 'ID',
dataIndex: 'id',
key: 'id',
search: {
type: 'string',
},
},
{
title: '说明',
dataIndex: 'description',
key: 'description',
search: {
type: 'string',
},
},
];
const handleSearch = (_params: any) => {
params.value = _params;
};
const cancelSelect = () => {
_selectedRowKeys.value = [];
};
const handleClick = (dt: any) => {
_selectedRowKeys.value = [dt.id];
emit('update:value', dt.id);
};
watch(
() => props.value,
(newValue) => {
if (newValue) {
_selectedRowKeys.value = [newValue];
} else {
_selectedRowKeys.value = [];
}
},
{
deep: true,
immediate: true,
},
);
</script>
<style lang="less" scoped>
.search {
margin-bottom: 0;
padding-right: 0px;
padding-left: 0px;
}
</style>

View File

@ -0,0 +1,167 @@
<template>
<Search
:columns="columns"
type="simple"
target="action-notice-template"
@search="handleSearch"
class="search"
/>
<div style="height: 400px; overflow-y: auto">
<JTable
:columns="columns"
:request="(e) => TemplateApi.getListByConfigId(props.notifierId, e)"
model="CARD"
:bodyStyle="{
paddingRight: 0,
paddingLeft: 0,
}"
:defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:params="params"
:gridColumn="2"
:gridColumns="[2, 2, 2]"
:rowSelection="{
selectedRowKeys: _selectedRowKeys,
}"
@cancelSelect="cancelSelect"
>
<template #card="slotProps">
<CardBox
:showStatus="false"
:value="slotProps"
:showTool="false"
:actions="[]"
v-bind="slotProps"
@click="handleClick"
:active="_selectedRowKeys.includes(slotProps.id)"
>
<template #img>
<slot name="img">
<img
:src="
getLogo(slotProps.type, slotProps.provider)
"
class="logo"
/>
</slot>
</template>
<template #content>
<Ellipsis style="width: calc(100% - 100px)">
<span style="font-size: 16px; font-weight: 600">
{{ slotProps.name }}
</span>
</Ellipsis>
<a-row>
<a-col :span="12">
<div class="card-item-content-text">
通知方式
</div>
<div>
{{ getMethodTxt(slotProps.type) }}
</div>
</a-col>
<a-col :span="12">
<div class="card-item-content-text">说明</div>
<Ellipsis>
{{ slotProps.description }}
</Ellipsis>
</a-col>
</a-row>
</template>
</CardBox>
</template>
</JTable>
</div>
</template>
<script lang="ts" setup>
import TemplateApi from '@/api/notice/template';
import { MSG_TYPE, NOTICE_METHOD } from '@/views/notice/const';
const props = defineProps({
notifierId: {
type: String,
default: '',
},
value: {
type: String,
default: '',
},
});
const emit = defineEmits(['update:value']);
const getLogo = (type: string, provider: string) => {
return MSG_TYPE[type].find((f: any) => f.value === provider)?.logo;
};
const getMethodTxt = (type: string) => {
return NOTICE_METHOD.find((f) => f.value === type)?.label;
};
const params = ref<Record<string, any>>({});
const _selectedRowKeys = ref<string[]>([]);
const columns = [
{
title: '名称',
dataIndex: 'name',
key: 'name',
search: {
type: 'string',
},
},
{
title: 'ID',
dataIndex: 'id',
key: 'id',
search: {
type: 'string',
},
},
{
title: '说明',
dataIndex: 'description',
key: 'description',
search: {
type: 'string',
},
},
];
const handleSearch = (_params: any) => {
params.value = _params;
};
const cancelSelect = () => {
_selectedRowKeys.value = [];
};
const handleClick = (dt: any) => {
_selectedRowKeys.value = [dt.id];
emit('update:value', dt.id);
};
watch(
() => props.value,
(newValue) => {
if (newValue) {
_selectedRowKeys.value = [newValue];
} else {
_selectedRowKeys.value = [];
}
},
{
deep: true,
immediate: true,
},
);
</script>
<style lang="less" scoped>
.search {
margin-bottom: 0;
padding-right: 0px;
padding-left: 0px;
}
</style>

View File

@ -0,0 +1,61 @@
<template>
<a-spin :spinning="loading">
<j-card-select
v-model:value="notifyType"
:options="options"
:icon-size="106"
/>
</a-spin>
</template>
<script lang="ts" setup>
import { getImage } from '@/utils/comm';
import notice from '@/api/notice/config';
const iconMap = new Map();
iconMap.set('dingTalk', getImage('/notice/dingtalk.png'));
iconMap.set('weixin', getImage('/notice/wechat.png'));
iconMap.set('email', getImage('/notice/email.png'));
iconMap.set('voice', getImage('/notice/voice.png'));
iconMap.set('sms', getImage('/notice/sms.png'));
iconMap.set('webhook', getImage('/notice/webhook.png'));
const props = defineProps({
value: {
type: String,
default: '',
},
});
const emit = defineEmits(['update:value'])
const loading = ref<boolean>(false);
const notifyType = ref('');
const options = ref<any[]>([]);
watch(
() => notifyType,
(newVal) => {
emit('update:value', newVal)
},
{ deep: true, immediate: true },
);
onMounted(() => {
notice.queryMessageType().then((resp) => {
if (resp.status === 200) {
options.value = (resp.result as any[]).map((item) => {
return {
label: item.name,
value: item.id,
iconUrl: iconMap.get(item.id),
};
});
}
});
notifyType.value = props.value
});
</script>
<style lang="less" scoped>
</style>

View File

@ -0,0 +1,70 @@
<template>
<a-form
v-if="variableDefinitions.length"
:layout="'vertical'"
ref="formRef"
:model="modelRef"
>
<template v-for="item in variableDefinitions" :key="item.id">
<a-form-item
:name="item.id"
:label="item.name"
:rules="[{ required: true, message: `请输入${item.name}` }]"
>
<User
v-if="getType(item) === 'user'"
v-model="modelRef[`${item.id}`]"
/>
<Org
v-else-if="getType(item) === 'org'"
v-model="modelRef[`${item.id}`]"
/>
<Tag
v-else-if="getType(item) === 'tag'"
v-model="modelRef[`${item.id}`]"
/>
<InputFile
v-else-if="getType(item) === 'file'"
v-model="modelRef[`${item.id}`]"
/>
<a-input
v-else-if="getType(item) === 'link'"
v-model="modelRef[`${item.id}`]"
/>
<BuildIn
v-else
v-model="modelRef[`${item.id}`]"
/>
</a-form-item>
</template>
</a-form>
</template>
<script lang="ts" setup>
import BuildIn from './variableItem/BuildIn.vue';
import Org from './variableItem/Org.vue';
import Tag from './variableItem/Tag.vue';
import InputFile from './variableItem/InputFile.vue';
import User from './variableItem/User.vue';
const props = defineProps({
variableDefinitions: {
type: Array,
default: () => [],
},
value: {
type: Object,
default: () => {},
},
});
const formRef = ref();
const modelRef = reactive({});
Object.assign(formRef, props.value);
const getType = (item: any) => {
return item.expands?.businessType || item.type;
};
</script>

View File

@ -0,0 +1,146 @@
<template>
<j-modal
title="执行动作"
visible
:width="860"
@cancel="onCancel"
@ok="onOk"
:maskClosable="false"
>
<div class="steps-steps">
<a-steps :current="current" size="small" @change="onChange">
<a-step title="通知方式" key="way" />
<a-step title="通知配置" key="config" />
<a-step title="通知模板" key="template" />
<a-step title="模板变量" key="variable" />
</a-steps>
</div>
<div class="steps-content">
<a-form ref="actionForm" :model="formModel" layout="vertical">
<template v-if="current === 0">
<a-form-item
label="应用"
name="notifyType"
:rules="[
{
required: true,
message: '请选择通知方式',
},
]"
>
<NotifyWay v-model:value="formModel.notifyType" />
</a-form-item>
</template>
<template v-if="current === 1">
<a-form-item name="notifierId">
<NotifyConfig v-model:value="formModel.notifierId" :notifyType="formModel.notifyType" />
</a-form-item>
</template>
<template v-if="current === 2">
<a-form-item name="templateId">
<NotifyTemplate v-model:value="formModel.templateId" :notifierId="formModel.notifierId" />
</a-form-item>
</template>
<template v-if="current === 3">
<a-form-item name="variables">
<VariableDefinitions
:variableDefinitions="variable"
v-model:value="formModel.variables"
/>
</a-form-item>
</template>
</a-form>
</div>
<template #footer>
<a-space>
<j-button v-if="current === 0" @click="onCancel">取消</j-button>
<j-button v-if="current > 0" @click="prev">上一步</j-button>
<j-button v-if="current < 3" type="primary" @click="next">下一步</j-button>
<j-button v-if="current === 3" type="primary" @click="onOk">确定</j-button>
</a-space>
</template>
</j-modal>
</template>
<script lang="ts" setup>
import NotifyWay from './NotifyWay.vue';
import NotifyConfig from './NotifyConfig.vue';
import NotifyTemplate from './NotifyTemplate.vue';
import VariableDefinitions from './VariableDefinitions.vue';
import { onlyMessage } from '@/utils/comm';
import Template from '@/api/notice/template';
const emit = defineEmits(['cancel', 'save']);
const current = ref(0);
const formModel = reactive({
notifyType: '',
notifierId: '',
templateId: '',
variables: [],
});
const variable = ref([]);
const jumpStep = async (val: number) => {
if (val === 0) {
current.value = val;
} else if (val === 1) {
if (formModel.notifyType) {
current.value = val
} else {
onlyMessage('请选择通知方式', 'error');
}
} else if (val === 2) {
if (formModel.notifierId) {
current.value = val
} else {
onlyMessage('请选择通知配置', 'error');
}
} else if (val === 3) {
formModel.templateId = '1628943618904956928'
if (formModel.templateId) {
const resp = await Template.getTemplateDetail(formModel.templateId);
if (resp.status === 200) {
variable.value = resp.result?.variableDefinitions || [];
current.value = val
}
} else {
onlyMessage('请选择通知模板', 'error');
}
}
};
const onChange = (cur: number) => {
jumpStep(cur)
};
const prev = () => {
current.value -= 1;
};
const next = async () => {
jumpStep(current.value + 1)
};
const onCancel = () => {
emit('cancel');
};
const onOk = () => {
emit('save');
};
</script>
<style lang="less" scoped>
.steps-steps {
width: 100%;
margin-bottom: 17px;
padding-bottom: 17px;
border-bottom: 1px solid #f0f0f0;
}
.steps-content {
width: 100%;
}
</style>

View File

@ -0,0 +1,3 @@
<template>
build-in
</template>

View File

@ -0,0 +1,3 @@
<template>
input-file
</template>

View File

@ -0,0 +1,3 @@
<template>
org
</template>

View File

@ -0,0 +1,3 @@
<template>
tag
</template>

View File

@ -0,0 +1,3 @@
<template>
user
</template>

View File

@ -0,0 +1,133 @@
<template>
<div class="actions">
<div class="actions-title">
<span>执行</span>
<ShakeLimit
v-if="props.openShakeLimit"
v-model:value="shakeLimit"
/>
</div>
<div class="actions-warp">
<a-collapse v-model:activeKey="activeKeys">
<a-collapse-panel key="1">
<template #header>
<span>
串行
<span class="panel-tip">
按顺序依次执行动作适用于基于动作输出参数判断是否执行后续动作的场景
</span>
</span>
</template>
<div class="actions-list">
<List
type="serial"
:branchesName="props.name"
:parallel="false"
:actions="serialArray.length ? serialArray[0].actions : []"
/>
</div>
</a-collapse-panel>
<a-collapse-panel key="2">
<template #header>
<span>
并行
<span class="panel-tip">
同时执行所有动作适用于不需要关注执行动作先后顺序和结果的场景
</span>
</span>
</template>
<div class="actions-list">
<List
type="parallel"
:branchesName="props.name"
:parallel="true"
:actions="parallelArray.length ? parallelArray[0].actions : []"
/>
</div>
</a-collapse-panel>
</a-collapse>
</div>
</div>
</template>
<script lang="ts" setup>
import ShakeLimit from '../components/ShakeLimit/index.vue';
import { List } from './ListItem';
import { storeToRefs } from 'pinia';
import { useSceneStore } from '@/store/scene';
import { BranchesThen } from '../../typings';
import { PropType } from 'vue';
interface ActionsProps {
name: number;
openShakeLimit?: boolean;
thenOptions: BranchesThen[];
}
const props = defineProps({
name: Number,
thenOptions: {
type: Array as PropType<ActionsProps['thenOptions']>,
default: () => [],
},
openShakeLimit: Boolean,
});
const shakeLimit = ref({});
const activeKeys = ref<string[]>(['1']);
const parallelArray = ref<BranchesThen[]>([]);
const serialArray = ref<BranchesThen[]>([]);
const lock = ref<boolean>(false)
watch(
() => props.thenOptions,
(newVal) => {
parallelArray.value = newVal.filter((item) => item.parallel);
serialArray.value = newVal.filter((item) => !item.parallel);
const isSerialActions = serialArray.value.some((item) => {
return !!item.actions.length;
});
if (
!lock.value &&
parallelArray.value.length &&
(!serialArray.value.length || !isSerialActions)
) {
activeKeys.value = ['2']
lock.value = true
}
//TODO
},
{
deep: true,
immediate: true,
},
);
</script>
<style lang="less" scoped>
.actions {
.actions-title {
display: flex;
gap: 16px;
align-items: center;
margin-bottom: 16px;
font-weight: 800;
font-size: 14px;
line-height: 32px;
}
.actions-warp {
.actions-list {
width: 100%;
}
}
.panel-tip {
padding-left: 8px;
color: rgba(#000, 0.45);
}
}
</style>

View File

@ -0,0 +1,85 @@
<template>
<div class="shakeLimit">
<a-switch
checkedChildren="开启防抖"
unCheckedChildren="关闭防抖"
v-model:checked="shakeLimit.enabled"
style="margin-right: 12px"
/>
<template v-if="shakeLimit.enabled">
<a-input-number :min="1" :max="100" :precision="0" size="small" v-model:value="shakeLimit.time" style="width: 32px" />
<span>秒内发送</span>
<a-input-number :min="1" :max="100" :precision="0" size="small" v-model:value="shakeLimit.threshold" style="width: 32px" />
<span>次及以上时处理</span>
<a-radio-group :options="alarmFirstOptions" optionType="button" v-model:value="shakeLimit.alarmFirst" size="small" />
</template>
</div>
</template>
<script lang="ts" setup>
import { cloneDeep } from "lodash-es";
import { PropType } from "vue";
type ShakeLimitType = {
enabled: boolean | undefined,
time?: number | undefined | null,
threshold?: number | undefined | null,
alarmFirst?: boolean | undefined
}
type Emit = {
(e: 'update:value', data: ShakeLimitType): void
}
const alarmFirstOptions = [
{ label: '第一次', value: true },
{ label: '最后一次', value: false },
];
const props = defineProps({
value: {
type: Object as PropType<ShakeLimitType>,
default: () => ({})
}
})
const emit = defineEmits<Emit>()
const shakeLimit = reactive<ShakeLimitType>({
enabled: undefined,
time: 1,
threshold: 1,
alarmFirst: undefined
})
Object.assign(shakeLimit, props.value)
watch(() => shakeLimit, () => {
const cloneValue = cloneDeep(shakeLimit)
emit('update:value', cloneValue)
}, {
deep: true
})
</script>
<style lang="less" scoped>
.shakeLimit {
display: flex;
gap: 4px;
align-items: center;
font-weight: 400;
font-size: 14px;
:deep(.ant-input-number-handler-wrap) {
display: none;
}
:deep(.ant-radio-button-wrapper) {
padding: 0 16px;
}
input {
padding: 0 4px;
}
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<page-container>
<Search :columns="columns" target="scene" @search="handleSearch" />
<JTable
<JProTable
ref="sceneRef"
:columns="columns"
:request="query"
@ -9,7 +9,7 @@
:params="params"
>
<template #headerTitle>
<a-space>
<j-space>
<PermissionButton
type="primary"
@click="handleAdd"
@ -18,7 +18,7 @@
<template #icon><AIcon type="PlusOutlined" /></template>
新增
</PermissionButton>
</a-space>
</j-space>
</template>
<template #card="slotProps">
<SceneCard
@ -90,13 +90,13 @@
{{ typeMap.get(slotProps.triggerType)?.text }}
</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"
@ -115,9 +115,9 @@
<template #icon><AIcon :type="i.icon" /></template>
</PermissionButton>
</template>
</a-space>
</j-space>
</template>
</JTable>
</JProTable>
<SaveModal v-if="visible" @close="visible = false" :data="current" />
</page-container>
</template>