Commit c483fa56ff52829bcb5c9bdfeb8ebfddab2f05b2

Authored by xp.Huang
2 parents d971016c 7d6ff37f

Merge branch 'perf/main_dev' into 'main_dev'

perf: 优化告警列表组件,少于十条数据时不滚动

See merge request yunteng/thingskit-scada!162
@@ -110,7 +110,7 @@ @@ -110,7 +110,7 @@
110 fill: none; 110 fill: none;
111 stroke: white; 111 stroke: white;
112 stroke-dasharray: 6% 29%; 112 stroke-dasharray: 6% 29%;
113 - stroke-width: 5px; 113 + stroke-width: 3px;
114 stroke-dashoffset: 0%; 114 stroke-dashoffset: 0%;
115 animation: stroke-offset 5.5s infinite linear; 115 animation: stroke-offset 5.5s infinite linear;
116 } 116 }
1 import type { DeviceAttributeItemType, DeviceItemType, DeviceProfileItemType, OrganizationItemType, RpcCommandType, SendValue, ThingsModel, ThingsModelItemType } from './model' 1 import type { DeviceAttributeItemType, DeviceItemType, DeviceProfileItemType, OrganizationItemType, RpcCommandType, SendValue, ThingsModel, ThingsModelItemType } from './model'
2 -import type { CommandWayEnum } from '@/enums/commandEnum' 2 +import { CommandWayEnum } from '@/enums/commandEnum'
3 import type { DeviceTypeEnum } from '@/enums/datasource' 3 import type { DeviceTypeEnum } from '@/enums/datasource'
4 import { isShareMode } from '@/utils/env' 4 import { isShareMode } from '@/utils/env'
5 import { defHttp } from '@/utils/http' 5 import { defHttp } from '@/utils/http'
@@ -15,6 +15,7 @@ enum Api { @@ -15,6 +15,7 @@ enum Api {
15 RPC_COMMAND = '/rpc/', 15 RPC_COMMAND = '/rpc/',
16 GET_DEVICE_ACTIVE = 'plugins/telemetry/DEVICE/', 16 GET_DEVICE_ACTIVE = 'plugins/telemetry/DEVICE/',
17 RPC_ONEWAY = '/rpc/oneway', 17 RPC_ONEWAY = '/rpc/oneway',
  18 + RPC_TWOWAY = '/rpc/twoway',
18 19
19 GEN_MODBUS_COMMAND = '/js/modbus', 20 GEN_MODBUS_COMMAND = '/js/modbus',
20 GET_DEVICE_DETAIL = '/device/', // 获取设备详情 21 GET_DEVICE_DETAIL = '/device/', // 获取设备详情
@@ -88,9 +89,9 @@ export const getDeviceActive = (deviceId: string) => { @@ -88,9 +89,9 @@ export const getDeviceActive = (deviceId: string) => {
88 } 89 }
89 90
90 // 命令下发 91 // 命令下发
91 -export const sendRpcOneway = (param: SendValue | any, deviceId?: string) => { 92 +export const sendRpcOneway = (param: SendValue | any, deviceId?: string, way?: string) => {
92 return defHttp.post({ 93 return defHttp.post({
93 - url: `${Api.RPC_ONEWAY}/${deviceId}`, 94 + url: `${way !== CommandWayEnum.TWO_WAY ? Api.RPC_ONEWAY : Api.RPC_TWOWAY}/${deviceId}`,
94 data: param, 95 data: param,
95 }, 96 },
96 { 97 {
@@ -161,11 +161,13 @@ export interface RangeItemType { @@ -161,11 +161,13 @@ export interface RangeItemType {
161 } 161 }
162 162
163 export interface BasicActDataType { 163 export interface BasicActDataType {
164 - deviceId: string  
165 - attr: string 164 + deviceId?: string
  165 + attr?: string
166 enable?: boolean 166 enable?: boolean
167 deviceProfileId?: string | number 167 deviceProfileId?: string | number
  168 + deviceProfileTemplateId?: string | number
168 attrInfo?: ThingsModelItemType 169 attrInfo?: ThingsModelItemType
  170 + deviceInfo?: DeviceTypeEnum
169 } 171 }
170 172
171 export interface FlashActDataType extends BasicActDataType { 173 export interface FlashActDataType extends BasicActDataType {
@@ -53,9 +53,9 @@ const getTitle = computed(() => { @@ -53,9 +53,9 @@ const getTitle = computed(() => {
53 </p> 53 </p>
54 </div> 54 </div>
55 </template> 55 </template>
56 - <span :class="prefixCls"> 56 + <span :class="prefixCls" class="flex items-center">
57 <component :is="slot as RendererElement" v-if="slots?.default" /> 57 <component :is="slot as RendererElement" v-if="slots?.default" />
58 - <Icon v-if="!slots?.default" icon="ph:question" class="svg:text-base" /> 58 + <Icon v-if="!slots?.default" icon="ph:question" class="cursor-pointer text-base" />
59 </span> 59 </span>
60 </Tooltip> 60 </Tooltip>
61 </template> 61 </template>
@@ -253,7 +253,7 @@ export default defineComponent({ @@ -253,7 +253,7 @@ export default defineComponent({
253 return renderLabel 253 return renderLabel
254 254
255 return ( 255 return (
256 - <span> 256 + <span class='flex items-center'>
257 {renderLabel} 257 {renderLabel}
258 <BasicHelp placement="top" class="mx-1" text={getHelpMessage} {...helpComponentProps} /> 258 <BasicHelp placement="top" class="mx-1" text={getHelpMessage} {...helpComponentProps} />
259 </span> 259 </span>
@@ -79,7 +79,6 @@ const handleDeleteRow = (data: FlashActDataType) => { @@ -79,7 +79,6 @@ const handleDeleteRow = (data: FlashActDataType) => {
79 79
80 const getFieldsValue = () => { 80 const getFieldsValue = () => {
81 const values = getFieldsForm() 81 const values = getFieldsForm()
82 - const { deviceId, attr, deviceProfileId, attrInfo } = values  
83 const rangeList = unref(dataSource).map((item) => { 82 const rangeList = unref(dataSource).map((item) => {
84 return { 83 return {
85 ...item, 84 ...item,
@@ -87,17 +86,14 @@ const getFieldsValue = () => { @@ -87,17 +86,14 @@ const getFieldsValue = () => {
87 } 86 }
88 }) 87 })
89 return { 88 return {
90 - deviceId,  
91 - attr,  
92 - deviceProfileId,  
93 - attrInfo, 89 + ...values,
94 rangeList, 90 rangeList,
95 } as BasicFlashActDataType 91 } as BasicFlashActDataType
96 } 92 }
97 93
98 const setFieldsValue = (list: FlashActDataType) => { 94 const setFieldsValue = (list: FlashActDataType) => {
99 - const { attr, deviceId, rangeList } = list || {}  
100 - setFieldsForm({ attr, deviceId }) 95 + const { rangeList } = list || {}
  96 + setFieldsForm(list || {})
101 clearValidate() 97 clearValidate()
102 dataSource.value = rangeList ? rangeList?.map(item => ({ ...item, uuid: buildUUID() })) : [getInitTableRecord()] 98 dataSource.value = rangeList ? rangeList?.map(item => ({ ...item, uuid: buildUUID() })) : [getInitTableRecord()]
103 } 99 }
@@ -128,3 +128,14 @@ defineExpose<ComponentExposeType>({ @@ -128,3 +128,14 @@ defineExpose<ComponentExposeType>({
128 </template> 128 </template>
129 </BasicTable> 129 </BasicTable>
130 </template> 130 </template>
  131 +
  132 +<style lang="less" scoped>
  133 + .variable-image-form {
  134 + >:deep(.ant-row) {
  135 + >.ant-col {
  136 + @apply px-4;
  137 + }
  138 + }
  139 + }
  140 +</style>
  141 +
@@ -11,6 +11,7 @@ import { genModbusCommand, getDeviceActiveTime, getDeviceInfo, getThingsModelSer @@ -11,6 +11,7 @@ import { genModbusCommand, getDeviceActiveTime, getDeviceInfo, getThingsModelSer
11 import { ThingsModelForm } from '@/core/Library/components/ThingsModelForm' 11 import { ThingsModelForm } from '@/core/Library/components/ThingsModelForm'
12 import { useMessage } from '@/hooks/web/useMessage' 12 import { useMessage } from '@/hooks/web/useMessage'
13 import type { StructJSON } from '@/api/device/model' 13 import type { StructJSON } from '@/api/device/model'
  14 +import { CommandWayEnum } from '@/enums/commandEnum'
14 15
15 interface ServiceInfo { 16 interface ServiceInfo {
16 title?: string 17 title?: string
@@ -19,6 +20,7 @@ interface ServiceInfo { @@ -19,6 +20,7 @@ interface ServiceInfo {
19 transportType?: string 20 transportType?: string
20 callType?: string 21 callType?: string
21 code?: string 22 code?: string
  23 + way?: string
22 } 24 }
23 25
24 const visible = ref<boolean>(false) 26 const visible = ref<boolean>(false)
@@ -49,6 +51,7 @@ const serviceInfo = reactive<ServiceInfo>({ @@ -49,6 +51,7 @@ const serviceInfo = reactive<ServiceInfo>({
49 transportType: '', 51 transportType: '',
50 callType: '', 52 callType: '',
51 code: '', 53 code: '',
  54 + way: '', // 单向还是双向
52 }) 55 })
53 56
54 const [register, { getFieldsValue, validate, setFieldsValue, updateSchema, setProps }] = useForm({ // 自定义下发值 57 const [register, { getFieldsValue, validate, setFieldsValue, updateSchema, setProps }] = useForm({ // 自定义下发值
@@ -88,11 +91,12 @@ const getDeviceDetail = async (deviceId: string) => { @@ -88,11 +91,12 @@ const getDeviceDetail = async (deviceId: string) => {
88 } 91 }
89 92
90 const open = async (_data: SingleClickEventDataType) => { 93 const open = async (_data: SingleClickEventDataType) => {
  94 + console.warn(_data, 'data')
91 const { operationPassword } = _data || {} 95 const { operationPassword } = _data || {}
92 dataSourceJson.value = _data.deviceInfo 96 dataSourceJson.value = _data.deviceInfo
93 isPasswordInfo.value = operationPassword || {} 97 isPasswordInfo.value = operationPassword || {}
94 // commandWay-->命令下发方式 98 // commandWay-->命令下发方式
95 - const { commandWay, customCommand, serviceCommand, service, callType } = _data || {} 99 + const { commandWay, customCommand, serviceCommand, service, callType, way } = _data || {}
96 isCommandWay.value = commandWay 100 isCommandWay.value = commandWay
97 const { attrInfo, deviceId } = unref(dataSourceJson) 101 const { attrInfo, deviceId } = unref(dataSourceJson)
98 const { identifier, extensionDesc, detail, name } = attrInfo || {}// 属性信息 102 const { identifier, extensionDesc, detail, name } = attrInfo || {}// 属性信息
@@ -110,6 +114,7 @@ const open = async (_data: SingleClickEventDataType) => { @@ -110,6 +114,7 @@ const open = async (_data: SingleClickEventDataType) => {
110 formField.value = identifier 114 formField.value = identifier
111 isShowActionType.value = !!actionType // 判断modBUS类型时 物模型是否填写扩展描述 115 isShowActionType.value = !!actionType // 判断modBUS类型时 物模型是否填写扩展描述
112 serviceInfo.callType = callType // 服务命令调用方式 是同步还是异步 116 serviceInfo.callType = callType // 服务命令调用方式 是同步还是异步
  117 + serviceInfo.way = way || 'oneway' // 命令下发是双向还是单向
113 118
114 serviceInfo.transportType = transportType 119 serviceInfo.transportType = transportType
115 serviceInfo.code = code 120 serviceInfo.code = code
@@ -268,7 +273,7 @@ const handleSubmit = async () => { @@ -268,7 +273,7 @@ const handleSubmit = async () => {
268 persistent: true, 273 persistent: true,
269 method: 'methodThingskit', 274 method: 'methodThingskit',
270 params: serviceInfo.transportType !== TransportTypeEnum.TCP && unref(isCommandWay) === CommandDeliveryWayEnum.SERVICE ? { service: unref(sendValue) } : unref(sendValue), 275 params: serviceInfo.transportType !== TransportTypeEnum.TCP && unref(isCommandWay) === CommandDeliveryWayEnum.SERVICE ? { service: unref(sendValue) } : unref(sendValue),
271 - }, dataSourceJson.value.deviceId) 276 + }, dataSourceJson.value.deviceId, serviceInfo.way)
272 createMessage.success('命令下发成功') 277 createMessage.success('命令下发成功')
273 visible.value = false 278 visible.value = false
274 isInputData.value = false 279 isInputData.value = false
@@ -28,7 +28,6 @@ const [registerForm, formActionType] = useForm({ @@ -28,7 +28,6 @@ const [registerForm, formActionType] = useForm({
28 schemas: formSchemas, 28 schemas: formSchemas,
29 showActionButtonGroup: false, 29 showActionButtonGroup: false,
30 layout: FormLayoutEnum.VERTICAL, 30 layout: FormLayoutEnum.VERTICAL,
31 - labelWidth: 70,  
32 getPopupContainer: () => document.body, 31 getPopupContainer: () => document.body,
33 fieldMapToTime: [[AlarmListFieldsEnum.ALARM_LIST_QUERY_DATE, [AlarmListFieldsEnum.START_TIME, AlarmListFieldsEnum.END_TIME], DateFormatEnum.X]], 32 fieldMapToTime: [[AlarmListFieldsEnum.ALARM_LIST_QUERY_DATE, [AlarmListFieldsEnum.START_TIME, AlarmListFieldsEnum.END_TIME], DateFormatEnum.X]],
34 }) 33 })
@@ -82,7 +81,7 @@ onMounted(async () => { @@ -82,7 +81,7 @@ onMounted(async () => {
82 </script> 81 </script>
83 82
84 <template> 83 <template>
85 - <div class="m-1 w-full"> 84 + <div class="m-1 w-full alarm-list-config-from">
86 <Divider orientation="left" class="!text-sm"> 85 <Divider orientation="left" class="!text-sm">
87 数据绑定 86 数据绑定
88 </Divider> 87 </Divider>
@@ -95,6 +94,14 @@ onMounted(async () => { @@ -95,6 +94,14 @@ onMounted(async () => {
95 </div> 94 </div>
96 </template> 95 </template>
97 96
98 -<style>  
99 - 97 +<style lang="less" scoped>
  98 +// .alarm-list-config-form {
  99 +// :deep(.ant-picker-input.ant-picker-input-active) {
  100 +// >input {
  101 +// overflow: hidden;
  102 +// text-overflow: ellipsis;
  103 +// white-space: nowrap;
  104 +// }
  105 +// }
  106 +// }
100 </style> 107 </style>
@@ -133,6 +133,14 @@ export const formSchemas: FormSchema[] = [ @@ -133,6 +133,14 @@ export const formSchemas: FormSchema[] = [
133 label: AlarmListFieldsNameEnum.ALARM_LIST_INTERVAL, 133 label: AlarmListFieldsNameEnum.ALARM_LIST_INTERVAL,
134 component: ComponentEnum.INPUT_NUMBER, 134 component: ComponentEnum.INPUT_NUMBER,
135 required: false, 135 required: false,
  136 + componentProps: {
  137 + min: 0,
  138 + },
  139 + renderComponentContent: () => {
  140 + return {
  141 + addonAfter: () => '秒',
  142 + }
  143 + },
136 }, 144 },
137 { 145 {
138 field: AlarmListFieldsEnum.ALARM_LIST_POLLING, 146 field: AlarmListFieldsEnum.ALARM_LIST_POLLING,
@@ -140,5 +148,13 @@ export const formSchemas: FormSchema[] = [ @@ -140,5 +148,13 @@ export const formSchemas: FormSchema[] = [
140 component: ComponentEnum.INPUT_NUMBER, 148 component: ComponentEnum.INPUT_NUMBER,
141 defaultValue: 30, 149 defaultValue: 30,
142 required: false, 150 required: false,
  151 + componentProps: {
  152 + min: 1,
  153 + },
  154 + renderComponentContent: () => {
  155 + return {
  156 + addonAfter: () => '秒',
  157 + }
  158 + },
143 }, 159 },
144 ] 160 ]
1 <script setup lang="ts"> 1 <script setup lang="ts">
2 import { computed, nextTick, onMounted, reactive, unref } from 'vue' 2 import { computed, nextTick, onMounted, reactive, unref } from 'vue'
3 -import { Divider, Tag } from 'ant-design-vue' 3 +import { Tag } from 'ant-design-vue'
  4 +import { useIntervalFn } from '@vueuse/core'
4 import { ScrollList } from './ScrollList' 5 import { ScrollList } from './ScrollList'
5 import { fetchAlarmList } from '@/api/alarm' 6 import { fetchAlarmList } from '@/api/alarm'
6 import type { AlarmListItemType } from '@/api/alarm/model' 7 import type { AlarmListItemType } from '@/api/alarm/model'
@@ -14,10 +15,6 @@ const props = defineProps<{ @@ -14,10 +15,6 @@ const props = defineProps<{
14 config: CreateComponentType 15 config: CreateComponentType
15 }>() 16 }>()
16 17
17 -const getCellBounds = computed(  
18 - () => props.config.cellBounds || { width: 290, height: 230, x: 0, y: 0 },  
19 -)  
20 -  
21 const contentDataStore = useContentDataStore() 18 const contentDataStore = useContentDataStore()
22 19
23 const initOptions = reactive<{ 20 const initOptions = reactive<{
@@ -67,7 +64,7 @@ onMounted(async () => { @@ -67,7 +64,7 @@ onMounted(async () => {
67 // 预览模式 64 // 预览模式
68 await initFetchAlarmList() 65 await initFetchAlarmList()
69 if (initOptions.polling) 66 if (initOptions.polling)
70 - setInterval(initFetchAlarmList, initOptions.polling * 1000) 67 + useIntervalFn(initFetchAlarmList, (initOptions.polling || 30) * 1000)
71 } 68 }
72 else { 69 else {
73 const statusList = Object.values(AlarmStatusEnum) 70 const statusList = Object.values(AlarmStatusEnum)
@@ -90,16 +87,13 @@ onMounted(async () => { @@ -90,16 +87,13 @@ onMounted(async () => {
90 <div class="seamless-scroll w-full h-full flex justify-center items-center overflow-y-scroll"> 87 <div class="seamless-scroll w-full h-full flex justify-center items-center overflow-y-scroll">
91 <ScrollList 88 <ScrollList
92 v-model="initOptions.scroll" :single-wait-time="initOptions.interval" :list="initOptions.alarmList" 89 v-model="initOptions.scroll" :single-wait-time="initOptions.interval" :list="initOptions.alarmList"
93 - :limit-scroll-num="10" :is-rem-unit="true" :delay="10" :wheel="true" hover :style="{  
94 - width: `${getCellBounds.width}px`,  
95 - height: `${getCellBounds.height}px`,  
96 - }" 90 + :is-rem-unit="true" :delay="10" :wheel="true" hover
97 > 91 >
98 - <div v-for="(item, index) in initOptions.alarmList" :key="index" class="flex flex-col items-start h-15 px-2">  
99 - <p class="text-xs"> 92 + <div v-for="(item, index) in initOptions.alarmList" :key="index" class="flex flex-col items-start p-2 border-gray-600 border-b border-solid border-t-transparent border-l-transparent border-r-transparent">
  93 + <div class="text-xs mb-2">
100 <span>设备:</span> 94 <span>设备:</span>
101 <span class="ml-1">{{ item.deviceAlias || item.deviceName }}</span> 95 <span class="ml-1">{{ item.deviceAlias || item.deviceName }}</span>
102 - </p> 96 + </div>
103 <div class="flex items-center justify-between -mt-2 text-xs"> 97 <div class="flex items-center justify-between -mt-2 text-xs">
104 <span>时间:</span> 98 <span>时间:</span>
105 <span class="ml-1">{{ item.startTs }}</span> 99 <span class="ml-1">{{ item.startTs }}</span>
@@ -107,19 +101,17 @@ onMounted(async () => { @@ -107,19 +101,17 @@ onMounted(async () => {
107 {{ AlarmStatusNameEnum[item.status] }} 101 {{ AlarmStatusNameEnum[item.status] }}
108 </Tag> 102 </Tag>
109 </div> 103 </div>
110 - <Divider class="mt-2 divider" />  
111 </div> 104 </div>
112 </ScrollList> 105 </ScrollList>
113 </div> 106 </div>
114 </template> 107 </template>
115 108
116 <style scoped lang="less"> 109 <style scoped lang="less">
117 -.seamless-scroll::-webkit-scrollbar {  
118 - display: none; 110 +.seamless-scroll {
  111 +
  112 + ::-webkit-scrollbar {
  113 + display: none;
119 114
120 - .divider {  
121 - height: 0.3px;  
122 - background-color: black;  
123 } 115 }
124 } 116 }
125 </style> 117 </style>