Commit 64b137e4a5483e3134ce926338e92b4ebad7ab35

Authored by xp.Huang
2 parents 51d5576c 13c29cba

Merge branch 'main_dev' into 'main'

Main dev

See merge request yunteng/thingskit-scada!208
... ... @@ -4351,9 +4351,11 @@ App.prototype.loadFile = function (id, sameWindow, file, success, force) {
4351 4351 if (success != null)
4352 4352 success()
4353 4353 // TODO Thingskkit socket连接
4354   - const lightboxWebsocketService = useLightboxModeService(this)
4355   - this.lightboxWebsocketService = lightboxWebsocketService
4356   - this.lightboxWebsocketService?.init?.()
  4354 + if (!result?.isTemplate) {
  4355 + const lightboxWebsocketService = useLightboxModeService(this)
  4356 + this.lightboxWebsocketService = lightboxWebsocketService
  4357 + this.lightboxWebsocketService?.init?.()
  4358 + }
4357 4359 }
4358 4360
4359 4361 handleLoadContent()
... ... @@ -5137,7 +5139,7 @@ App.prototype.addPreviewButton = function () {
5137 5139 this.previewButton.style.border = '1px solid transparent'
5138 5140 this.previewButton.style.color = '#fff'
5139 5141
5140   - const icon = document.createElement('img')
  5142 + const icon = document.createElement('img')
5141 5143 icon.setAttribute('src', this.previewImage)
5142 5144 icon.setAttribute('align', 'absmiddle')
5143 5145 icon.style.marginRight = '4px'
... ...
... ... @@ -27,7 +27,7 @@ export interface GenModbusCommandType {
27 27 crc: string
28 28 deviceCode: string
29 29 method: string
30   - registerAddress: string
  30 + registerAddress: number
31 31 registerNumber?: number
32 32 registerValues?: number[]
33 33 }
... ...
1   -import type { FunctionType, TransportTypeEnum } from '@/enums/datasource'
  1 +import type { DataTypeEnum, FunctionType, TransportTypeEnum } from '@/enums/datasource'
2 2
3 3 export interface DeviceProfileItemType {
4 4 id: string
... ... @@ -147,6 +147,7 @@ export interface Detail {
147 147 export interface DataType {
148 148 type: string
149 149 specs: Specs | StructJSON[]
  150 + specsList: Specs[]
150 151 }
151 152
152 153 export interface Specs {
... ... @@ -158,6 +159,9 @@ export interface Specs {
158 159 length?: string
159 160 min: string
160 161 max: string
  162 + name?: string
  163 + value?: string
  164 + dataType?: DataTypeEnum
161 165 }
162 166
163 167 export interface ValueRange {
... ...
  1 +import type { Specs, StructJSON } from '@/api/device/model'
  2 +import type { NodeDataDataSourceJsonType } from '@/api/node/model'
  3 +import { type FormSchema, useComponentRegister } from '@/components/Form'
  4 +import { ComponentEnum } from '@/components/Form/src/enum'
  5 +import { ThingsModelForm, validateTCPCustomCommand } from '@/core/Library/components/ThingsModelForm'
  6 +import { getFormSchemas } from '@/core/Library/components/ThingsModelForm/config'
  7 +import { CodeTypeEnum, DataTypeEnum, TransportTypeEnum } from '@/enums/datasource'
  8 +import { TCPObjectModelActionTypeEnum } from '@/enums/objectModelEnum'
  9 +
  10 +useComponentRegister(ComponentEnum.THINGS_MODEL_FORM, ThingsModelForm)
  11 +
  12 +export enum FormFieldsEnum {
  13 + ATTR_VALUE = 'attrValue',
  14 + PASSWORD = 'password',
  15 +}
  16 +
  17 +export interface AttributeDeliverModalOpenParamsType {
  18 + title?: string
  19 + operationPassword?: string
  20 + operationPasswordEnable?: boolean
  21 + dataSourceJson: NodeDataDataSourceJsonType
  22 +}
  23 +
  24 +function getStructJsonFromDataSourceJson(dataSourceJson: NodeDataDataSourceJsonType): StructJSON {
  25 + const { attrInfo } = dataSourceJson
  26 + const { identifier, name, detail } = attrInfo || {}
  27 + return {
  28 + functionName: name,
  29 + identifier,
  30 + dataType: detail.dataType,
  31 + }
  32 +}
  33 +
  34 +function getTCPModbusSchemas({ structJson, required, actionType }: { structJson: StructJSON; required?: boolean; actionType: string }): FormSchema {
  35 + const { dataType } = structJson
  36 + const { specs, type } = dataType || {}
  37 + const { valueRange, length = 10240 } = specs! as Specs
  38 + const { max = Number.MAX_SAFE_INTEGER, min = Number.MIN_SAFE_INTEGER } = valueRange || {}
  39 +
  40 + function createInputNumber({
  41 + identifier,
  42 + functionName,
  43 + }: StructJSON): FormSchema {
  44 + return {
  45 + field: identifier,
  46 + label: functionName,
  47 + component: ComponentEnum.INPUT_NUMBER,
  48 + required,
  49 + componentProps: {
  50 + max: actionType === TCPObjectModelActionTypeEnum.BOOL ? 1 : max,
  51 + min: actionType === TCPObjectModelActionTypeEnum.BOOL ? 0 : min,
  52 + precision: actionType === TCPObjectModelActionTypeEnum.BOOL ? 0 : 2,
  53 + },
  54 + }
  55 + }
  56 +
  57 + const createInput = ({ identifier, functionName }: StructJSON): FormSchema => {
  58 + return {
  59 + field: identifier,
  60 + label: functionName,
  61 + component: ComponentEnum.INPUT,
  62 + rules: [
  63 + {
  64 + required,
  65 + message: `${functionName}是必填项`,
  66 + },
  67 + {
  68 + validator: validateTCPCustomCommand,
  69 + },
  70 + ],
  71 + componentProps: {
  72 + maxLength: length,
  73 + },
  74 + } as FormSchema
  75 + }
  76 +
  77 + return type === DataTypeEnum.STRING ? createInput(structJson) : createInputNumber(structJson)
  78 +}
  79 +
  80 +export const createFormSchemas = ({ operationPassword, operationPasswordEnable, dataSourceJson }: AttributeDeliverModalOpenParamsType): FormSchema[] => {
  81 + const schemas: FormSchema[] = []
  82 +
  83 + const { deviceInfo } = dataSourceJson
  84 + if (deviceInfo?.transportType === TransportTypeEnum.TCP && deviceInfo.codeType === CodeTypeEnum.MODBUS_RTU && dataSourceJson.deviceInfo?.codeType) {
  85 + schemas.push(getTCPModbusSchemas({ required: true, structJson: getStructJsonFromDataSourceJson(dataSourceJson), actionType: dataSourceJson.deviceInfo?.codeType }))
  86 + }
  87 + else {
  88 + const isStructType = dataSourceJson.attrInfo?.detail?.dataType?.type === DataTypeEnum.STRUCT
  89 + schemas.push(
  90 + ...getFormSchemas({ structJSON: isStructType ? dataSourceJson?.attrInfo?.detail?.dataType?.specs as StructJSON[] || [] : [getStructJsonFromDataSourceJson(dataSourceJson)], required: !isStructType }),
  91 + )
  92 + }
  93 +
  94 + if (operationPassword && operationPasswordEnable) {
  95 + schemas.unshift({
  96 + field: FormFieldsEnum.PASSWORD,
  97 + label: '操作密码',
  98 + component: ComponentEnum.INPUT_PAWSSWORD,
  99 + required: true,
  100 + rules: [
  101 + {
  102 + validator(_rule, value) {
  103 + if (value && value !== operationPassword) return Promise.reject(new Error('操作密码不正确'))
  104 + return Promise.resolve()
  105 + },
  106 + },
  107 + ],
  108 + })
  109 + }
  110 +
  111 + return schemas
  112 +}
... ...
1 1 <script setup lang="ts">
2 2 import { Modal } from 'ant-design-vue'
3 3 import { nextTick, ref, unref } from 'vue'
4   -import type { FormSchema } from '@/components/Form'
  4 +import type { AttributeDeliverModalOpenParamsType } from './AttributeDeliverModal.config'
  5 +import { createFormSchemas } from './AttributeDeliverModal.config'
  6 +import { useGetModbusCommand } from './useGetModbusCommand'
5 7 import { BasicForm, useForm } from '@/components/Form'
6   -import { ComponentEnum, FormLayoutEnum } from '@/components/Form/src/enum'
  8 +import { FormLayoutEnum } from '@/components/Form/src/enum'
  9 +import type { NodeDataDataSourceJsonType } from '@/api/node/model'
  10 +import { CodeTypeEnum, DataTypeEnum, TransportTypeEnum } from '@/enums/datasource'
7 11
8 12 const resolveFn = ref<Fn>()
9 13
... ... @@ -11,61 +15,50 @@ const visible = ref(false)
11 15
12 16 const password = ref()
13 17
  18 +const currentDataSourceJson = ref<NodeDataDataSourceJsonType>()
  19 +
14 20 const [register, { getFieldsValue, resetFields, validate, setProps, clearValidate }] = useForm({
15 21 layout: FormLayoutEnum.VERTICAL,
16 22 showActionButtonGroup: false,
17 23 })
18 24
19   -enum FormFieldsEnum {
20   - ATTR_VALUE = 'attrValue',
21   - PASSWORD = 'password',
22   -}
23   -
24   -const createFormSchemas = (title?: string, password?: string, operationPasswordEnable?: boolean): FormSchema[] => {
25   - const schemas: FormSchema[] = [
26   - {
27   - field: FormFieldsEnum.ATTR_VALUE,
28   - label: title || '属性值',
29   - component: ComponentEnum.INPUT,
30   - required: true,
31   - },
32   - ]
33   -
34   - if (password && operationPasswordEnable) {
35   - schemas.unshift({
36   - field: FormFieldsEnum.PASSWORD,
37   - label: '操作密码',
38   - component: ComponentEnum.INPUT_PAWSSWORD,
39   - required: true,
40   - rules: [
41   - {
42   - validator(_rule, value) {
43   - if (value && value !== password) return Promise.reject(new Error('操作密码不正确'))
44   - return Promise.resolve()
45   - },
46   - },
47   - ],
48   - })
49   - }
50   -
51   - return schemas
52   -}
53   -
54   -const open = async ({ title, operationPassword, operationPasswordEnable }: Partial<Record<'operationPassword' | 'title', string>> & { operationPasswordEnable: boolean }) => {
  25 +const open = async ({ title, operationPassword, operationPasswordEnable, dataSourceJson }: AttributeDeliverModalOpenParamsType) => {
55 26 visible.value = true
56 27 password.value = operationPassword
  28 + currentDataSourceJson.value = dataSourceJson
57 29 return new Promise((resolve) => {
58 30 resolveFn.value = resolve
59 31 nextTick(() => {
60   - setProps({ schemas: createFormSchemas(title, operationPassword, operationPasswordEnable) })
  32 + setProps({ schemas: createFormSchemas({ title, operationPassword, operationPasswordEnable, dataSourceJson }) })
61 33 })
62 34 })
63 35 }
64 36
  37 +async function getResult() {
  38 + const result = getFieldsValue()
  39 + const isTCPModbusDevice = unref(currentDataSourceJson)?.deviceInfo?.transportType === TransportTypeEnum.TCP && unref(currentDataSourceJson)?.deviceInfo?.codeType === CodeTypeEnum.MODBUS_RTU
  40 + const isStructJSON = unref(currentDataSourceJson)?.attrInfo?.detail?.dataType?.type === DataTypeEnum.STRUCT
  41 + const attrKey = unref(currentDataSourceJson)!.attr
  42 + if (!isTCPModbusDevice) { return isStructJSON ? result : result[attrKey] }
  43 + else {
  44 + const value = result[attrKey]
  45 + const isString = unref(currentDataSourceJson)?.attrInfo?.detail?.dataType?.type === DataTypeEnum.STRING
  46 +
  47 + if (isString) return value
  48 +
  49 + const { getModbusCommand, validateCanGetCommand } = useGetModbusCommand()
  50 + if (!validateCanGetCommand(unref(currentDataSourceJson)!.attrInfo.extensionDesc, unref(currentDataSourceJson)!.deviceInfo?.code).flag) return
  51 +
  52 + const res = await getModbusCommand(value as unknown as number, unref(currentDataSourceJson)!.attrInfo.extensionDesc!, unref(currentDataSourceJson)!.deviceInfo!.code!)
  53 + return res
  54 + }
  55 +}
  56 +
65 57 const handleOk = async () => {
66 58 await validate()
67   - const value = getFieldsValue()
68   - unref(resolveFn)?.(value[FormFieldsEnum.ATTR_VALUE])
  59 + const result = await getResult()
  60 + if (!result) return
  61 + unref(resolveFn)?.(result)
69 62 visible.value = false
70 63 resetFields()
71 64 }
... ... @@ -80,17 +73,9 @@ defineExpose({ open })
80 73
81 74 <template>
82 75 <Modal
83   - v-model:open="visible" title="属性下发" ok-text="确认" :width="400" cancel-text="取消" @cancel="handleCancel" @ok="handleOk"
  76 + v-model:open="visible" title="属性下发" ok-text="确认" :width="400" cancel-text="取消" @cancel="handleCancel"
  77 + @ok="handleOk"
84 78 >
85   - <!-- <section>
86   - <FormItem label="操作密码" :label-col="{ span: 24 }">
87   - <Input v-model:value="value" placeholder="请输入下发值" />
88   - </FormItem>
89   - <FormItem :label="fieldTitle" :label-col="{ span: 24 }">
90   - <Input v-model:value="value" placeholder="请输入下发值" />
91   - </FormItem>
92   - </section> -->
93   -
94 79 <BasicForm @register="register" />
95 80 </Modal>
96 81 </template>
... ...
  1 +import { SingleToHex, getArray } from './config'
  2 +import { type GenModbusCommandType, genModbusCommand } from '@/api/device'
  3 +import type { ExtensionDesc } from '@/api/device/model'
  4 +import { TCPObjectModelActionTypeEnum } from '@/enums/objectModelEnum'
  5 +import { useMessage } from '@/hooks/web/useMessage'
  6 +
  7 +const getFloatPart = (number: string | number) => {
  8 + const isLessZero = Number(number) < 0
  9 + number = number.toString()
  10 + const floatPartStartIndex = number.indexOf('.')
  11 + const value = ~floatPartStartIndex
  12 + ? `${isLessZero ? '-' : ''}0.${number.substring(floatPartStartIndex + 1)}`
  13 + : '0'
  14 + return Number(value)
  15 +}
  16 +
  17 +const REGISTER_MAX_VALUE = Number(0xffff)
  18 +
  19 +export function useGetModbusCommand() {
  20 + const { createMessage } = useMessage()
  21 +
  22 + const getModbusCommand = async (value: number, extensionDesc: ExtensionDesc, deviceAddressCode: string) => {
  23 + const { registerAddress, actionType, zoomFactor } = extensionDesc as Required<ExtensionDesc>
  24 + const params: GenModbusCommandType = {
  25 + crc: 'CRC_16_LOWER',
  26 + registerNumber: 1,
  27 + deviceCode: deviceAddressCode,
  28 + registerAddress,
  29 + method: actionType,
  30 + registerValues: [value],
  31 + }
  32 +
  33 + if (actionType === TCPObjectModelActionTypeEnum.INT) {
  34 + const newValue
  35 + = Math.trunc(value) * zoomFactor
  36 + + getFloatPart(value) * zoomFactor
  37 +
  38 + if (newValue % 1 !== 0) {
  39 + createMessage.warning(`属性下发类型必须是整数,缩放因子为${zoomFactor}`)
  40 + return
  41 + }
  42 +
  43 + if (value * zoomFactor > REGISTER_MAX_VALUE) {
  44 + createMessage.warning(`属性下发值不能超过${REGISTER_MAX_VALUE},缩放因子是${zoomFactor}`)
  45 + return
  46 + }
  47 +
  48 + params.registerValues = [newValue]
  49 + }
  50 + else if (actionType === TCPObjectModelActionTypeEnum.DOUBLE) {
  51 + const regex = /^-?\d+(\.\d{0,2})?$/
  52 + const values
  53 + = Math.trunc(value) * zoomFactor
  54 + + getFloatPart(value) * zoomFactor
  55 +
  56 + if (!regex.test(values.toString())) {
  57 + createMessage.warning(`属性下发值精确到两位小数,缩放因子是${zoomFactor}`)
  58 + return
  59 + }
  60 +
  61 + const newValue
  62 + = values === 0 ? [0, 0] : getArray(SingleToHex(values))
  63 + params.registerValues = newValue
  64 + params.registerNumber = 2
  65 + }
  66 +
  67 + return await genModbusCommand(params)
  68 + }
  69 +
  70 + /**
  71 + *
  72 + * @param extensionDesc 物模型拓展描述符
  73 + * @param deviceAddressCode 设备地址码
  74 + */
  75 + const validateCanGetCommand = (extensionDesc?: ExtensionDesc, deviceAddressCode?: string, createValidateMessage = true) => {
  76 + const result = { flag: true, message: '' }
  77 + if (!extensionDesc) {
  78 + result.flag = false
  79 + result.message = '当前物模型扩展描述没有填写'
  80 + }
  81 +
  82 + if (!deviceAddressCode) {
  83 + result.flag = false
  84 + result.message = '当前设备未绑定设备地址码'
  85 + }
  86 +
  87 + if (result.message && createValidateMessage)
  88 + createMessage.warning(result.message)
  89 +
  90 + return result
  91 + }
  92 +
  93 + return {
  94 + getModbusCommand,
  95 + validateCanGetCommand,
  96 + }
  97 +}
... ...
... ... @@ -9,9 +9,9 @@ export const getFormSchemas = ({ structJSON: structJson, required, transportType
9 9 functionName,
10 10 dataType,
11 11 }: StructJSON): FormSchema => {
12   - const { specs } = dataType || {}
  12 + const { specs, type } = dataType || {}
13 13 const { valueRange } = specs! as Specs
14   - const { max = 2147483647, min = -2147483648 } = valueRange || {}
  14 + const { max = Number.MAX_SAFE_INTEGER, min = Number.MIN_SAFE_INTEGER } = valueRange || {}
15 15 return {
16 16 field: identifier,
17 17 label: functionName,
... ... @@ -21,22 +21,11 @@ export const getFormSchemas = ({ structJSON: structJson, required, transportType
21 21 required,
22 22 message: `${functionName}是必填项`,
23 23 },
24   - {
25   - type: 'number',
26   - trigger: 'change',
27   - validator: (_rule, value) => {
28   - const reg = /^[0-9]*$/
29   - if (!reg.test(value)) return Promise.reject(new Error(`${functionName}不是一个有效的数字`))
30   - if (value < min || value > max)
31   - return Promise.reject(new Error(`${functionName}取值范围在${min}~${max}之间`))
32   -
33   - return Promise.resolve(value)
34   - },
35   - },
36 24 ],
37 25 componentProps: {
38 26 max,
39 27 min,
  28 + precision: type === DataTypeEnum.NUMBER_INT ? 0 : 2,
40 29 },
41 30 } as FormSchema
42 31 }
... ... @@ -93,6 +82,27 @@ export const getFormSchemas = ({ structJSON: structJson, required, transportType
93 82 }
94 83 }
95 84
  85 + const createEnumSelect = ({ identifier, functionName, dataType }: StructJSON): FormSchema => {
  86 + const { specsList } = dataType || {}
  87 +
  88 + return {
  89 + field: identifier,
  90 + label: functionName,
  91 + component: ComponentEnum.SELECT,
  92 + rules: [
  93 + {
  94 + required,
  95 + message: `${functionName}是必填项`,
  96 + type: 'number',
  97 + },
  98 + ],
  99 + componentProps: {
  100 + options: specsList,
  101 + fieldNames: { label: 'name', value: 'value' },
  102 + },
  103 + }
  104 + }
  105 +
96 106 const createStructJson = ({ identifier, functionName, dataType }: StructJSON): FormSchema => {
97 107 return {
98 108 field: identifier,
... ... @@ -121,7 +131,6 @@ export const getFormSchemas = ({ structJSON: structJson, required, transportType
121 131 }
122 132
123 133 const schemas: FormSchema[] = []
124   -
125 134 for (const item of structJson) {
126 135 const { dataType } = item
127 136 const { type } = dataType || {}
... ... @@ -129,6 +138,8 @@ export const getFormSchemas = ({ structJSON: structJson, required, transportType
129 138 schemas.push(createTCPServiceCommandInput(item))
130 139 if (type === DataTypeEnum.BOOL)
131 140 schemas.push(createSelect(item))
  141 + else if (type === DataTypeEnum.ENUM)
  142 + schemas.push(createEnumSelect(item))
132 143 else if (type === DataTypeEnum.NUMBER_INT)
133 144 schemas.push(createInputNumber(item))
134 145 else if (type === DataTypeEnum.NUMBER_DOUBLE)
... ...
  1 +import type { ValidatorRule } from 'ant-design-vue/lib/form/interface'
  2 +
1 3 export { default as ThingsModelForm } from './index.vue'
  4 +
  5 +export const validateTCPCustomCommand: ValidatorRule['validator'] = (_rule, value) => {
  6 + const reg = /^[\s0-9a-fA-F]+$/
  7 + if (reg.test(value)) return Promise.resolve()
  8 + return Promise.reject(new Error('请输入ASCII或HEX服务命令(0~9/A~F)'))
  9 +}
... ...
... ... @@ -22,14 +22,10 @@ const props = withDefaults(defineProps<{
22 22
23 23 const thingsModelFormListElMap = reactive<Record<string, { el: InstanceType<typeof ThingsModelForm>; structJSON: StructJSON }>>({})
24 24
25   -// const getLabelWidth = () => {
26   -// return Math.max(...((props.inputData || [])?.map(item => item?.functionName?.length))) * 12
27   -// }
28   -
29 25 const [register, formActionType] = useForm({
30 26 schemas: getFormSchemas({ structJSON: props.inputData || [], required: props.required, transportType: props.transportType }),
31 27 showActionButtonGroup: false,
32   - // labelWidth: getLabelWidth() || 80,
  28 + labelWidth: 100,
33 29 labelAlign: FormLabelAlignEnum.RIGHT,
34 30 layout: FormLayoutEnum.HORIZONTAL,
35 31 })
... ... @@ -105,19 +101,34 @@ defineExpose<ComponentExposeType>({
105 101 <Card class="!border-2 !border-dashed" :title="title">
106 102 <BasicForm class="things-model-form" @register="register">
107 103 <template v-for="item in getStructFormItem" #[item.identifier]="{ model, field }" :key="item.identifier">
108   - <ThingsModelForm :ref="(el) => setFormElRef(el as InstanceType<typeof ThingsModelForm>, item) " v-model:value="model[field]" :input-data="(item.dataType?.specs as StructJSON[]) || []" :title="item.functionName" />
  104 + <ThingsModelForm
  105 + :ref="(el) => setFormElRef(el as InstanceType<typeof ThingsModelForm>, item)"
  106 + v-model:value="model[field]" :input-data="(item.dataType?.specs as StructJSON[]) || []"
  107 + :title="item.functionName"
  108 + />
109 109 </template>
110 110 </BasicForm>
111 111 </Card>
112 112 </template>
113 113
114 114 <style lang="less" scoped>
115   - .things-model-form {
116   - :deep(.ant-input-number) {
117   - width: 100%;
118   - }
  115 +.things-model-form {
  116 + :deep(.ant-input-number) {
  117 + width: 100%;
119 118 }
120   - :deep(.ant-form-item-control){
121   - margin-left: 6px;
  119 +
  120 + :deep(.ant-form-item-label) {
  121 + >label {
  122 + display: block;
  123 + text-align: right;
  124 + white-space: nowrap;
  125 + text-overflow: ellipsis;
  126 + overflow: hidden;
  127 + }
122 128 }
  129 +}
  130 +
  131 +:deep(.ant-form-item-control) {
  132 + margin-left: 6px;
  133 +}
123 134 </style>
... ...
1   -import { h, render } from 'vue'
  1 +import { h, render, unref } from 'vue'
2 2 import { ControlComponentEnum } from '../packages/Control'
  3 +import { useGetModbusCommand } from '../components/PublicForm/components/DataEvents/CommandDeliveryModal/useGetModbusCommand'
3 4 import { doCommandDelivery, getDeviceActive, getDeviceInfo } from '@/api/device'
4 5 import type { MouseUpEventDataType, NodeDataDataSourceJsonType, NodeDataEventJsonType, SingleClickEventDataType } from '@/api/node/model'
5 6 import { CommandWayEnum } from '@/enums/commandEnum'
6   -import { ActRangListItemTypeEnum, EventActionTypeEnum, TransportTypeEnum } from '@/enums/datasource'
  7 +import { ActRangListItemTypeEnum, CodeTypeEnum, EventActionTypeEnum, TransportTypeEnum } from '@/enums/datasource'
7 8 import { useMessage } from '@/hooks/web/useMessage'
8 9 import { AttributeDeliverModal, CommandDeliveryConfirmModal, CommandDeliveryModal, ConfirmModal } from '@/core/Library/components/PublicForm/components/DataEvents/CommandDeliveryModal'
9 10 import type { MxCell } from '@/fitCore/types'
... ... @@ -76,7 +77,7 @@ export function useNodeEvent(eventJson: NodeDataEventJsonType, dataSourceJson: N
76 77 const nodeUtils = new NodeUtils()
77 78 const { way = CommandWayEnum.ONE_WAY } = data
78 79 const { attr, deviceId, attrInfo } = dataSourceJson
79   - const { transportType, alias, name: deviceName } = await getDeviceInfo(dataSourceJson.deviceId) || {}// 设备信息
  80 + const { transportType, alias, name: deviceName, code, codeType } = await getDeviceInfo(dataSourceJson.deviceId) || {}// 设备信息
80 81 const contentDataStore = useContentDataStoreWithOut()
81 82 const currentData = contentDataStore.contentData.find(item => item.id === cell.getId())
82 83 if (!currentData) return
... ... @@ -95,6 +96,7 @@ export function useNodeEvent(eventJson: NodeDataEventJsonType, dataSourceJson: N
95 96 const res = rangeList.find(item => item.type === (status === ActRangListItemTypeEnum.OPEN ? ActRangListItemTypeEnum.CLOSE : ActRangListItemTypeEnum.OPEN))
96 97 if (!res) return
97 98 const { statusValue } = res
  99 +
98 100 command.params = transportType === TransportTypeEnum.TCP
99 101 ? statusValue!
100 102 : {
... ... @@ -104,7 +106,7 @@ export function useNodeEvent(eventJson: NodeDataEventJsonType, dataSourceJson: N
104 106 if (operationPasswordEnable) {
105 107 const instance = h(CommandDeliveryConfirmModal)
106 108 render(instance, document.body)
107   - await (instance.component?.exposed as InstanceType<typeof CommandDeliveryConfirmModal>)?.open(operationPassword)
  109 + await (instance.component?.exposed as InstanceType<typeof CommandDeliveryConfirmModal>)?.open(operationPassword!)
108 110 }
109 111 else {
110 112 const instance = h(ConfirmModal)
... ... @@ -112,15 +114,23 @@ export function useNodeEvent(eventJson: NodeDataEventJsonType, dataSourceJson: N
112 114 await (instance.component?.exposed as InstanceType<typeof ConfirmModal>)?.open()
113 115 }
114 116
  117 + if (transportType === TransportTypeEnum.TCP && codeType === CodeTypeEnum.MODBUS_RTU) {
  118 + const { validateCanGetCommand, getModbusCommand } = useGetModbusCommand()
  119 + if (!validateCanGetCommand(unref(dataSourceJson).attrInfo.extensionDesc, code).flag) return
  120 + const res = await getModbusCommand(statusValue!, unref(dataSourceJson).attrInfo.extensionDesc!, code)
  121 + if (!res) return
  122 + command.params = res
  123 + }
  124 +
115 125 await doCommandDelivery({ way, command, deviceId })
116 126 createMessage.success('命令下发成功')
117 127 }
118 128 else {
119 129 const instance = h(AttributeDeliverModal)
120 130 render(instance, document.body)
121   - const value = await (instance.component?.exposed as InstanceType<typeof AttributeDeliverModal>)?.open({ title: `${alias || deviceName}-${attrInfo.name}`, operationPassword, operationPasswordEnable }) as string
122   -
  131 + const value = await (instance.component?.exposed as InstanceType<typeof AttributeDeliverModal>)?.open({ title: `${alias || deviceName}-${attrInfo.name}`, operationPassword, operationPasswordEnable, dataSourceJson }) as string
123 132 command.params = transportType === TransportTypeEnum.TCP ? value : { [attr]: value }
  133 + if (!command.params) return
124 134 await doCommandDelivery({ way, command, deviceId })
125 135 createMessage.success('命令下发成功')
126 136 }
... ...
... ... @@ -53,7 +53,7 @@ const initFetchAlarmList = async () => {
53 53 }))
54 54
55 55 initOptions.alarmList = resp.items || []
56   - initOptions.interval = interval || 0
  56 + initOptions.interval = interval * 1000 || 0
57 57 initOptions.scroll = autoPlay || false
58 58 initOptions.polling = polling || 30
59 59 }
... ... @@ -87,10 +87,10 @@ onMounted(async () => {
87 87 <div class="seamless-scroll w-full h-full flex justify-center items-center overflow-y-scroll">
88 88 <ScrollList
89 89 v-if="initOptions.alarmList.length"
90   - v-model="initOptions.scroll" :single-wait-time="initOptions.interval" :list="initOptions.alarmList"
91   - :is-rem-unit="true" :delay="10" :wheel="true" hover
  90 + v-model="initOptions.scroll" :single-wait-time="initOptions.interval" :single-height="58" :list="initOptions.alarmList"
  91 + :delay="10" hover
92 92 >
93   - <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 v-for="(item, index) in initOptions.alarmList" :key="index" class="flex flex-col items-start p-2 border-gray-600 border-t border-solid border-b-transparent border-l-transparent border-r-transparent">
94 94 <div class="text-xs mb-2">
95 95 <span>设备:</span>
96 96 <span class="ml-1">{{ item.deviceAlias || item.deviceName }}</span>
... ...
... ... @@ -73,7 +73,6 @@ const handleGetVideoPlay = async () => {
73 73 }
74 74
75 75 const instance = unref(basicVideoPlayEl)?.customInit((options) => {
76   - withToken.value = true
77 76 if (unref(withToken)) {
78 77 (options as any).flvjs.config.headers = {
79 78 'X-Authorization': `Bearer ${isShareMode() ? getShareJwtToken() : getJwtToken()}`,
... ... @@ -109,7 +108,7 @@ const handleSelectPreview = () => {
109 108
110 109 onMounted(async () => {
111 110 await nextTick()
112   - isLightboxMode()
  111 + isLightboxMode() || isShareMode()
113 112 ? handleGetVideoPlay()
114 113 : handleSelectPreview()
115 114 })
... ...
... ... @@ -78,6 +78,7 @@ export class EventHandler {
78 78 }
79 79
80 80 const { handlerMouseDown, handlerMouseClick, handlerMouseDoubleClick, handlerMouseUp } = useNodeEvent(node.eventJson, node.dataSourceJson, cell)
  81 +
81 82 switch (eventName) {
82 83 case EventTypeEnum.DOWN:
83 84 handlerMouseDown()
... ...
... ... @@ -314,6 +314,7 @@ export enum DataTypeEnum {
314 314 STRING = 'TEXT',
315 315 STRUCT = 'STRUCT',
316 316 BOOL = 'BOOL',
  317 + ENUM = 'ENUM',
317 318 }
318 319
319 320 export enum AggregateTypeEnum {
... ...
  1 +/**
  2 + * @description TCP物模型拓展描述符数据格式
  3 + */
  4 +export enum TCPObjectModelActionTypeEnum {
  5 + BOOL = '05',
  6 + INT = '06',
  7 + DOUBLE = '16',
  8 +}
... ...