Commit 66892ba1a626018e4ca117ba796fcf9f162ba7c4

Authored by ww
1 parent 299f7534

fix: DEFECT-1118 修复控制组件绑定tcp设备时无法下发字符串命令

@@ -6895,11 +6895,26 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6895,11 +6895,26 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6895 TCP_COMMAND: 'tcpCommand', 6895 TCP_COMMAND: 'tcpCommand',
6896 6896
6897 /** 6897 /**
  6898 + * @description json命令
  6899 + */
  6900 + JSON_COMMAND: 'jsonCommand',
  6901 +
  6902 + /**
6898 * @description 命令下发方式 6903 * @description 命令下发方式
6899 */ 6904 */
6900 COMMAND_TYPE: 'commandType', 6905 COMMAND_TYPE: 'commandType',
6901 6906
6902 /** 6907 /**
  6908 + * @description 服务命令
  6909 + */
  6910 + SERVICE_COMMAND: 'serviceCommand',
  6911 +
  6912 + /**
  6913 + * @description 服务原始配置
  6914 + */
  6915 + SERVICE_ORIGINAL_CONFIGURATION: 'serviceOriginalConfiguration',
  6916 +
  6917 + /**
6903 * @description 服务 6918 * @description 服务
6904 */ 6919 */
6905 SERVICE: 'service', 6920 SERVICE: 'service',
@@ -7028,22 +7043,28 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7028,22 +7043,28 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7028 */ 7043 */
7029 function echoFormData(data) { 7044 function echoFormData(data) {
7030 const { content = {} } = data 7045 const { content = {} } = data
  7046 + console.log(data)
7031 const val = { 7047 const val = {
7032 [enumConst.ACTION]: content.type, 7048 [enumConst.ACTION]: content.type,
7033 [enumGetValue[content.type]]: content.value, 7049 [enumGetValue[content.type]]: content.value,
  7050 +
  7051 + // 参数设置
  7052 + [enumConst.JSON_COMMAND]: content[enumConst.JSON_COMMAND],
7034 [enumConst.WAY]: content[enumConst.WAY], 7053 [enumConst.WAY]: content[enumConst.WAY],
7035 [enumConst.COMMAND_TYPE]: content[enumConst.COMMAND_TYPE], 7054 [enumConst.COMMAND_TYPE]: content[enumConst.COMMAND_TYPE],
7036 - [enumConst.SERVICE]: content[enumConst.SERVICE],  
7037 - [enumConst.COMMAND]: content[enumConst.COMMAND],  
7038 [enumConst.TCP_COMMAND]: content[enumConst.TCP_COMMAND], 7055 [enumConst.TCP_COMMAND]: content[enumConst.TCP_COMMAND],
  7056 + [enumConst.TRANSPORTTYPE]: content[enumConst.TRANSPORTTYPE],
  7057 + [enumConst.SERVICE]: content[enumConst.SERVICE],
  7058 + [enumConst.SERVICE_COMMAND]: content[enumConst.SERVICE_COMMAND],
  7059 + [enumConst.SERVICE_ORIGINAL_CONFIGURATION]: content[enumConst.SERVICE_ORIGINAL_CONFIGURATION],
7039 } 7060 }
7040 7061
7041 7062
7042 - const isTCPTransportType = !!content[enumConst.TCP_COMMAND] 7063 + const isTCPTransportType = content[enumConst.TRANSPORTTYPE] === 'TCP'
7043 const isCustom = content[enumConst.COMMAND_TYPE] === COMMAND_TYPE_ENUM.CUSTOM 7064 const isCustom = content[enumConst.COMMAND_TYPE] === COMMAND_TYPE_ENUM.CUSTOM
7044 7065
7045 if (content[enumConst.SERVICE] && !isCustom) { 7066 if (content[enumConst.SERVICE] && !isCustom) {
7046 - form.val(enumActionEl.INPUT_DATA_FORM_FILTER, content[enumConst.COMMAND]) 7067 + form.val(enumActionEl.INPUT_DATA_FORM_FILTER, content[enumConst.SERVICE_COMMAND])
7047 } 7068 }
7048 7069
7049 controlFormDisplay(content.type, isTCPTransportType, isCustom) 7070 controlFormDisplay(content.type, isTCPTransportType, isCustom)
@@ -7111,31 +7132,29 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7111,31 +7132,29 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7111 if (isParamsSetting) { 7132 if (isParamsSetting) {
7112 const isTCPTransportType = formVal[enumConst.TRANSPORTTYPE] === 'TCP' 7133 const isTCPTransportType = formVal[enumConst.TRANSPORTTYPE] === 'TCP'
7113 const isCustom = formVal[enumConst.COMMAND_TYPE] === COMMAND_TYPE_ENUM.CUSTOM 7134 const isCustom = formVal[enumConst.COMMAND_TYPE] === COMMAND_TYPE_ENUM.CUSTOM
7114 - const inputData = form.val(enumActionEl.INPUT_DATA_FORM_FILTER) 7135 + let inputData = form.val(enumActionEl.INPUT_DATA_FORM_FILTER)
7115 7136
7116 const validateParamsSetting = () => { 7137 const validateParamsSetting = () => {
7117 if (isCustom) { 7138 if (isCustom) {
7118 - if (isTCPTransportType && !formVal[enumConst.TCP_COMMAND]) {  
7119 - UseLayUi.topErrorMsg('请输入自定义下发指令')  
7120 - return false  
7121 - }  
7122 - if (!isTCPTransportType && !isJson(formVal[enumConst.COMMAND])) {  
7123 - UseLayUi.topErrorMsg('命令配置存在错误')  
7124 - return false 7139 + if (isTCPTransportType) {
  7140 + if (!formVal[enumConst.TCP_COMMAND]) {
  7141 + UseLayUi.topErrorMsg('请输入自定义下发指令')
  7142 + return false
  7143 + }
  7144 + if (!isJson(formVal[enumConst.JSON_COMMAND])) {
  7145 + UseLayUi.topErrorMsg('命令配置存在错误')
  7146 + return false
  7147 + }
7125 } 7148 }
7126 } else { 7149 } else {
7127 if (!formVal[enumConst.SERVICE]) { 7150 if (!formVal[enumConst.SERVICE]) {
7128 UseLayUi.topErrorMsg('请选择服务') 7151 UseLayUi.topErrorMsg('请选择服务')
7129 return false 7152 return false
  7153 + } else {
  7154 + const { flag, value } = UseLayUi.validateThingsModelInputDataForm(Utils.stringToJSON(formVal[enumConst.SERVICE_ORIGINAL_CONFIGURATION], []), inputData)
  7155 + inputData = value
  7156 + return flag
7130 } 7157 }
7131 - // if ((!inputData && !isTCPTransportType) || (!formVal[enumConst.TCP_COMMAND] && isTCPTransportType)) {  
7132 - // UseLayUi.topErrorMsg('请选择服务')  
7133 - // return false  
7134 - // }  
7135 - // if (!inputData || !formVal[enumConst.TCP_COMMAND]) {  
7136 - // UseLayUi.topErrorMsg('请选择服务')  
7137 - // return false  
7138 - // }  
7139 } 7158 }
7140 return true 7159 return true
7141 } 7160 }
@@ -7143,8 +7162,8 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7143,8 +7162,8 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7143 if (!validateParamsSetting()) return 7162 if (!validateParamsSetting()) return
7144 7163
7145 // 选择服务的方式下发命令 7164 // 选择服务的方式下发命令
7146 - if (!isCustom && formVal[enumConst.SERVICE]) {  
7147 - formVal[enumConst.COMMAND] = inputData 7165 + if (!isCustom && formVal[enumConst.SERVICE] && !isTCPTransportType) {
  7166 + formVal[enumConst.SERVICE_COMMAND] = inputData
7148 } 7167 }
7149 } 7168 }
7150 7169
@@ -7159,11 +7178,14 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7159,11 +7178,14 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7159 type: formVal[enumConst.ACTION], 7178 type: formVal[enumConst.ACTION],
7160 value: formVal[enumGetValue[formVal[enumConst.ACTION]]], 7179 value: formVal[enumGetValue[formVal[enumConst.ACTION]]],
7161 ...(isParamsSetting ? { 7180 ...(isParamsSetting ? {
7162 - [enumConst.COMMAND]: formVal[enumConst.COMMAND], 7181 + [enumConst.JSON_COMMAND]: formVal[enumConst.JSON_COMMAND],
7163 [enumConst.WAY]: formVal[enumConst.WAY], 7182 [enumConst.WAY]: formVal[enumConst.WAY],
7164 [enumConst.COMMAND_TYPE]: formVal[enumConst.COMMAND_TYPE], 7183 [enumConst.COMMAND_TYPE]: formVal[enumConst.COMMAND_TYPE],
7165 - [enumConst.SERVICE]: formVal[enumConst.SERVICE],  
7166 [enumConst.TCP_COMMAND]: formVal[enumConst.TCP_COMMAND], 7184 [enumConst.TCP_COMMAND]: formVal[enumConst.TCP_COMMAND],
  7185 + [enumConst.TRANSPORTTYPE]: formVal[enumConst.TRANSPORTTYPE],
  7186 + [enumConst.SERVICE]: formVal[enumConst.SERVICE],
  7187 + [enumConst.SERVICE_COMMAND]: formVal[enumConst.SERVICE_COMMAND],
  7188 + [enumConst.SERVICE_ORIGINAL_CONFIGURATION]: formVal[enumConst.SERVICE_ORIGINAL_CONFIGURATION],
7167 } : {}), 7189 } : {}),
7168 }, 7190 },
7169 } 7191 }
@@ -7195,8 +7217,8 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7195,8 +7217,8 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7195 */ 7217 */
7196 function generateCommandTypeOptions() { 7218 function generateCommandTypeOptions() {
7197 const options = [ 7219 const options = [
7198 - { name: '自定义', id: COMMAND_TYPE_ENUM.CUSTOM },  
7199 - { name: '服务', id: COMMAND_TYPE_ENUM.SERVICE }, 7220 + { name: '自定义命令', id: COMMAND_TYPE_ENUM.CUSTOM },
  7221 + { name: '服务调用', id: COMMAND_TYPE_ENUM.SERVICE },
7200 ] 7222 ]
7201 return UseLayUi.generateOptionTemplate({ dataSource: options, addPlaceholderOption: false }) 7223 return UseLayUi.generateOptionTemplate({ dataSource: options, addPlaceholderOption: false })
7202 } 7224 }
@@ -7216,6 +7238,9 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7216,6 +7238,9 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7216 let transportType 7238 let transportType
7217 let deviceProfileServices = [] 7239 let deviceProfileServices = []
7218 7240
  7241 + /**
  7242 + * @description 动作下拉 change event
  7243 + */
7219 form.on(`select(${enumActionEl.ACTION_SELECT_FILTER})`, (data) => { 7244 form.on(`select(${enumActionEl.ACTION_SELECT_FILTER})`, (data) => {
7220 const { value } = data 7245 const { value } = data
7221 if (value === enumActionType.PARAMS_SETTING && !dataSource.deviceProfileId) { 7246 if (value === enumActionType.PARAMS_SETTING && !dataSource.deviceProfileId) {
@@ -7228,6 +7253,9 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7228,6 +7253,9 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7228 controlFormDisplay(value, transportType, isCustom) 7253 controlFormDisplay(value, transportType, isCustom)
7229 }) 7254 })
7230 7255
  7256 + /**
  7257 + * @description 命令类型下拉 change event
  7258 + */
7231 form.on(`select(${enumActionEl.COMMAND_TYPE_EL})`, (data) => { 7259 form.on(`select(${enumActionEl.COMMAND_TYPE_EL})`, (data) => {
7232 const { value } = data 7260 const { value } = data
7233 const flag = value === COMMAND_TYPE_ENUM.CUSTOM 7261 const flag = value === COMMAND_TYPE_ENUM.CUSTOM
@@ -7237,8 +7265,12 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7237,8 +7265,12 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7237 $(`#${enumActionEl.TCP_COMMAND_INPUT}`).css({ display: isTCPTransportType && flag ? 'block' : 'none' }) 7265 $(`#${enumActionEl.TCP_COMMAND_INPUT}`).css({ display: isTCPTransportType && flag ? 'block' : 'none' })
7238 $(`#${enumActionEl.EDITOR_CONTAINER}`).css({ display: !isTCPTransportType && flag ? 'flex' : 'none' }) 7266 $(`#${enumActionEl.EDITOR_CONTAINER}`).css({ display: !isTCPTransportType && flag ? 'flex' : 'none' })
7239 form.val(enumActionEl.FORM_FILTER, { [enumConst.TCP_COMMAND]: '', [enumConst.SERVICE]: '', [enumConst.COMMAND]: '' }) 7267 form.val(enumActionEl.FORM_FILTER, { [enumConst.TCP_COMMAND]: '', [enumConst.SERVICE]: '', [enumConst.COMMAND]: '' })
  7268 + $(`#${enumActionEl.INPUT_DATA_FORM}`).html('')
7240 }) 7269 })
7241 7270
  7271 + /**
  7272 + * @description 服务下拉选择change event
  7273 + */
7242 form.on(`select(${enumActionEl.SERVICE_EL})`, (data) => { 7274 form.on(`select(${enumActionEl.SERVICE_EL})`, (data) => {
7243 const { value } = data 7275 const { value } = data
7244 const needRender = deviceProfileServices.find(item => item.identifier === value) || {} 7276 const needRender = deviceProfileServices.find(item => item.identifier === value) || {}
@@ -7248,10 +7280,9 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7248,10 +7280,9 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7248 const template = UseLayUi.genThingsModelInputDataForm(needRender.functionJson?.inputData || [], 120) 7280 const template = UseLayUi.genThingsModelInputDataForm(needRender.functionJson?.inputData || [], 120)
7249 $(`#${enumActionEl.INPUT_DATA_FORM}`).html(template) 7281 $(`#${enumActionEl.INPUT_DATA_FORM}`).html(template)
7250 } else { 7282 } else {
7251 - console.log(needRender)  
7252 - form.val(enumActionEl.FORM_FILTER, { [enumConst.TCP_COMMAND]: needRender.functionJson?.inputData?.[0]?.serviceCommand || '' })  
7253 - console.log(form.val(enumActionEl.FORM_FILTER)) 7283 + form.val(enumActionEl.FORM_FILTER, { [enumConst.SERVICE_COMMAND]: needRender.functionJson?.inputData?.[0]?.serviceCommand || '' })
7254 } 7284 }
  7285 + form.val(enumActionEl.FORM_FILTER, { [enumConst.SERVICE_ORIGINAL_CONFIGURATION]: JSON.stringify(needRender.functionJson?.inputData || []) })
7255 }) 7286 })
7256 7287
7257 try { 7288 try {
@@ -7272,7 +7303,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7272,7 +7303,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7272 if (transportType !== 'TCP') { 7303 if (transportType !== 'TCP') {
7273 const template = UseLayUi.genThingsModelInputDataForm(needRender.functionJson?.inputData || [], 120) 7304 const template = UseLayUi.genThingsModelInputDataForm(needRender.functionJson?.inputData || [], 120)
7274 $(`#${enumActionEl.INPUT_DATA_FORM}`).html(template) 7305 $(`#${enumActionEl.INPUT_DATA_FORM}`).html(template)
7275 - form.val(enumActionEl.INPUT_DATA_FORM_FILTER, content[enumConst.COMMAND]) 7306 + form.val(enumActionEl.INPUT_DATA_FORM_FILTER, content[enumConst.SERVICE_COMMAND])
7276 } 7307 }
7277 } 7308 }
7278 7309
@@ -7318,13 +7349,13 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7318,13 +7349,13 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7318 fontSize: 14, // 编辑器内字体大小 7349 fontSize: 14, // 编辑器内字体大小
7319 tabSize: 2, // 制表符设置为 4 个空格大小 7350 tabSize: 2, // 制表符设置为 4 个空格大小
7320 }); 7351 });
7321 - if (record.content && record.content[enumConst.COMMAND]) defaultValue = jsonParse(record.content[enumConst.COMMAND]) 7352 + if (record.content && record.content[enumConst.JSON_COMMAND]) defaultValue = jsonParse(record.content[enumConst.JSON_COMMAND])
7322 const stringValue = JSON.stringify(defaultValue, null, 2) 7353 const stringValue = JSON.stringify(defaultValue, null, 2)
7323 editor.insert(stringValue) 7354 editor.insert(stringValue)
7324 - $(`#${enumActionEl.EDITOR_CONTAINER}`).parent().find(`textarea[name="${enumConst.COMMAND}"]`).val(stringValue) 7355 + $(`#${enumActionEl.EDITOR_CONTAINER}`).parent().find(`textarea[name="${enumConst.JSON_COMMAND}"]`).val(stringValue)
7325 editor.session.setMode("ace/mode/json"); 7356 editor.session.setMode("ace/mode/json");
7326 editor.getSession().on('change', (event, editor) => { 7357 editor.getSession().on('change', (event, editor) => {
7327 - $(`#${enumActionEl.EDITOR_CONTAINER}`).parent().find(`textarea[name="${enumConst.COMMAND}"]`).val(editor.getValue()) 7358 + $(`#${enumActionEl.EDITOR_CONTAINER}`).parent().find(`textarea[name="${enumConst.JSON_COMMAND}"]`).val(editor.getValue())
7328 }) 7359 })
7329 } 7360 }
7330 7361
@@ -7387,10 +7418,16 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7387,10 +7418,16 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7387 </select> 7418 </select>
7388 </div> 7419 </div>
7389 </div> 7420 </div>
7390 - <div id="${enumActionEl.EDITOR_CONTAINER}" style="display: none; margin-bottom: 15px;"> 7421 + <div style="display: none;">
  7422 + <input type="text" name="${enumConst.SERVICE_COMMAND}" placeholder="服务命令" />
  7423 + </div>
  7424 + <div style="display: none;">
  7425 + <input type="text" name="${enumConst.SERVICE_ORIGINAL_CONFIGURATION}" placeholder="服务命令" />
  7426 + </div>
  7427 + <div id="${enumActionEl.EDITOR_CONTAINER}" class="layui-form-item" style="display: none; margin-bottom: 15px;">
7391 <div style="width: 120px; text-align: right; padding: 9px 15px;flex: 0 0 120px;">命令 ${createHelpMessage('用户预览模式下,点击参数设置后。输入的变量值将作为"attrPlaceholder"的值,并以JSON格式下发给服务器。', 'command')}</div> 7428 <div style="width: 120px; text-align: right; padding: 9px 15px;flex: 0 0 120px;">命令 ${createHelpMessage('用户预览模式下,点击参数设置后。输入的变量值将作为"attrPlaceholder"的值,并以JSON格式下发给服务器。', 'command')}</div>
7392 <div id="${enumActionEl.EDITOR}" style="width: 100%; height: 100%;border: 2px solid #eee;"></div> 7429 <div id="${enumActionEl.EDITOR}" style="width: 100%; height: 100%;border: 2px solid #eee;"></div>
7393 - <textarea name="${enumConst.COMMAND}" style="display: none;" /> 7430 + <textarea name="${enumConst.JSON_COMMAND}" class="layui-textarea" style="display: none;" />
7394 </div> 7431 </div>
7395 <div id="${enumActionEl.TCP_COMMAND_INPUT}" style="display: none;"> 7432 <div id="${enumActionEl.TCP_COMMAND_INPUT}" style="display: none;">
7396 <label class="layui-form-label" style="width: 120px;">命令 ${createHelpMessage('用户预览模式下,点击参数设置后。输入的变量值将作为"attrPlaceholder"的值,并以JSON格式下发给服务器。', 'command')}</label> 7433 <label class="layui-form-label" style="width: 120px;">命令 ${createHelpMessage('用户预览模式下,点击参数设置后。输入的变量值将作为"attrPlaceholder"的值,并以JSON格式下发给服务器。', 'command')}</label>
@@ -12486,6 +12523,19 @@ class UseLayUi { @@ -12486,6 +12523,19 @@ class UseLayUi {
12486 12523
12487 static dynamicAttr = (attr, value) => value ? `${attr}="${value}"` : '' 12524 static dynamicAttr = (attr, value) => value ? `${attr}="${value}"` : ''
12488 12525
  12526 +
  12527 + static createHelpMessage(message, className) {
  12528 + return `
  12529 + <div class="thingskit-help-message ${className}">
  12530 + <img src="${Proxy_Prefix}/images/thingskit/question.svg"/>
  12531 + <div class="thingskit-help-container">
  12532 + <div class="thingskit-help-content">${message}</div>
  12533 + <div class="thingskit-help-arrow"></div>
  12534 + </div>
  12535 + </div>
  12536 + `
  12537 + }
  12538 +
12489 /** 12539 /**
12490 * @description 生成输入框控件 12540 * @description 生成输入框控件
12491 * @param {{label: string, value: string, labelWidth: number, numberInput: boolean}} params 12541 * @param {{label: string, value: string, labelWidth: number, numberInput: boolean}} params
@@ -12536,6 +12586,67 @@ class UseLayUi { @@ -12536,6 +12586,67 @@ class UseLayUi {
12536 </form>` 12586 </form>`
12537 return template 12587 return template
12538 } 12588 }
  12589 + /**
  12590 + *
  12591 + * @param {{
  12592 + * accessMode: 'r' | 'w',
  12593 + * functionName: string,
  12594 + * id: string,
  12595 + * identifier: string,
  12596 + * dataType: {
  12597 + * type: 'TEXT' | 'INT' | 'DOUBLE' | 'STRUCT',
  12598 + * specs: { unit: {value: string, label: string},
  12599 + * unitName: string,
  12600 + * valueRange: {min: number, max: number},
  12601 + * length: number
  12602 + * }}}[]} inputData
  12603 + * @param {Record<string, any>} value = 80
  12604 + */
  12605 + static validateThingsModelInputDataForm(inputData, value, needFormat = false) {
  12606 + let flag = true
  12607 + const error = (message) => {
  12608 + UseLayUi.topErrorMsg(message)
  12609 + return false
  12610 + }
  12611 +
  12612 + const validate = (item) => {
  12613 + const { dataType, identifier, functionName } = item
  12614 + const { type } = dataType || {}
  12615 + const identifierValue = value[identifier]
  12616 + switch (type) {
  12617 + case UseLayUi.thingsModelType.INT:
  12618 + if (isNaN(identifierValue)) return error(`${functionName}字段需要一个数字`)
  12619 + needFormat && (value[identifier] = parseInt(identifierValue))
  12620 + break
  12621 + case UseLayUi.thingsModelType.DOUBLE:
  12622 + if (isNaN(identifierValue)) return error(`${functionName}字段需要一个数字`)
  12623 + needFormat && (value[identifier] = Number(identifierValue))
  12624 + break
  12625 + case UseLayUi.thingsModelType.STRUCT:
  12626 + if (!Utils.stringIsJSON(identifierValue)) return error(`${functionName}字段需要一个JSON对象`)
  12627 + needFormat && (value[identifier] = Utils.stringToJSON(identifierValue))
  12628 + break
  12629 + default:
  12630 + break
  12631 + }
  12632 + return true
  12633 + }
  12634 +
  12635 + for (const item of inputData) {
  12636 + if (!validate(item)) return { flag: false, value }
  12637 +
  12638 + }
  12639 +
  12640 + return { flag, value }
  12641 +
  12642 + }
  12643 +
  12644 + static thingsModelType = {
  12645 + TEXT: 'TEXT',
  12646 + INT: 'INT',
  12647 + DOUBLE: 'DOUBLE',
  12648 + STRUCT: 'STRUCT',
  12649 + }
12539 12650
12540 /** 12651 /**
12541 * @description format data source to tree structure 12652 * @description format data source to tree structure
@@ -12985,6 +13096,33 @@ class UseLayUi { @@ -12985,6 +13096,33 @@ class UseLayUi {
12985 } 13096 }
12986 } 13097 }
12987 13098
  13099 +class Utils {
  13100 + /**
  13101 + * @description 字符串是否能转换为对象
  13102 + * @param {string} value
  13103 + */
  13104 + static stringIsJSON(value) {
  13105 + try {
  13106 + JSON.parse(value)
  13107 + return true
  13108 + } catch (error) {
  13109 + return false
  13110 + }
  13111 + }
  13112 +
  13113 + /**
  13114 + * @description 字符串转对象
  13115 + * @param {string} value
  13116 + * @returns
  13117 + */
  13118 + static stringToJSON(value, defaultValue = {}) {
  13119 + try {
  13120 + return JSON.parse(value)
  13121 + } catch (error) {
  13122 + return defaultValue
  13123 + }
  13124 + }
  13125 +}
12988 13126
12989 /** 13127 /**
12990 * @description use to function capture await throw error 13128 * @description use to function capture await throw error
@@ -14841,25 +14979,153 @@ class HandleDataInteraction { @@ -14841,25 +14979,153 @@ class HandleDataInteraction {
14841 const enumActionEl = { 14979 const enumActionEl = {
14842 CONTAINER: 'container', 14980 CONTAINER: 'container',
14843 EDITOR: 'editor', 14981 EDITOR: 'editor',
14844 - ISSUED_WAY_FILTER: 'wayFilter' 14982 + ISSUED_WAY_FILTER: 'wayFilter',
  14983 +
  14984 + /**
  14985 + * @description 表单filter
  14986 + */
  14987 + FORM_FILTER: 'formFilter',
  14988 +
  14989 + /**
  14990 + * @description 编辑器容器
  14991 + */
  14992 + EDITOR_CONTAINER: 'editorContainer',
  14993 +
  14994 + /**
  14995 + * @description 编辑器
  14996 + */
  14997 + EDITOR: 'editor',
  14998 +
  14999 + /**
  15000 + * @description 自定义TCP下发命令
  15001 + */
  15002 + CUSTOM_TCP_COMMAND: 'customTCPCommand',
  15003 +
  15004 + /**
  15005 + * @description 自定义JSON下发命令
  15006 + */
  15007 + CUSTOM_JSON_COMMAND: 'customJSONCommand',
14845 15008
  15009 + /**
  15010 + * @description 服务TCP命令
  15011 + */
  15012 + SERVICE_TCP_COMMAND: 'serviceTCPCommand',
  15013 +
  15014 + /**
  15015 + * @description 服务JSON命令
  15016 + */
  15017 + SERVICE_JSON_COMMAND: 'serviceTCPCommand',
14846 } 15018 }
14847 15019
14848 - function createContent() {  
14849 - const { command, tcpCommand, } = content 15020 + function createCustomTCPParams() {
14850 return ` 15021 return `
14851 - <div>  
14852 - <div class="layui-form" lay-filter="${enumActionEl.ISSUED_WAY_FILTER}">  
14853 - <div class="layui-form-item">  
14854 - <label class="layui-form-label">下发值</label>  
14855 - <div class="layui-input-block">  
14856 - <input type="text" name="${enumConst.VALUE}" lay-verify="required" autocomplete="off" placeholder="请输入下发值" class="layui-input"> 15022 + <div>
  15023 + <div class="layui-form" lay-filter="${enumActionEl.CUSTOM_TCP_COMMAND}">
  15024 + <div class="layui-form-item">
  15025 + <label class="layui-form-label" style="width: 120px;">自定义下发值</label>
  15026 + <div class="layui-input-block" style="margin-left: 150px;">
  15027 + <input type="text" name="${enumActionEl.CUSTOM_TCP_COMMAND}" lay-verify="required" autocomplete="off" placeholder="请输入下发值" class="layui-input">
  15028 + </div>
14857 </div> 15029 </div>
14858 </div> 15030 </div>
14859 </div> 15031 </div>
14860 - </div>` 15032 + `
14861 } 15033 }
14862 15034
  15035 + function createEditor() {
  15036 + if (content.transportType === 'TCP' || content.commandType === '1') return
  15037 + console.log('enter')
  15038 + const jsonCommand = content.jsonCommand || ''
  15039 + let defaultValue = { [enumConst.ATTR_PLACEHOLDER]: 0 }
  15040 + const editor = ace.edit(enumActionEl.EDITOR, {
  15041 + maxLines: 18, // 最大行数,超过会自动出现滚动条
  15042 + minLines: 10, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小
  15043 + fontSize: 14, // 编辑器内字体大小
  15044 + tabSize: 2, // 制表符设置为 4 个空格大小
  15045 + });
  15046 + if (jsonCommand) defaultValue = jsonParse(jsonCommand)
  15047 + const stringValue = JSON.stringify(defaultValue, null, 2)
  15048 + editor.insert(stringValue)
  15049 + $(`#${enumActionEl.EDITOR_CONTAINER}`).parent().find(`textarea[name="${enumActionEl.CUSTOM_JSON_COMMAND}"]`).val(stringValue)
  15050 + editor.session.setMode("ace/mode/json");
  15051 + editor.getSession().on('change', (event, editor) => {
  15052 + $(`#${enumActionEl.EDITOR_CONTAINER}`).parent().find(`textarea[name="${enumActionEl.CUSTOM_JSON_COMMAND}"]`).val(editor.getValue())
  15053 + })
  15054 + console.log(editor)
  15055 + }
  15056 +
  15057 + function createCustomJSONParams() {
  15058 + return `
  15059 + <div id="${enumActionEl.EDITOR_CONTAINER}" class="layui-form-item" style="disable: flex;">
  15060 + <div style="width: 120px; text-align: right; padding: 9px 15px;flex: 0 0 120px;text-align: left;">命令</div>
  15061 + <div id="${enumActionEl.EDITOR}" style="width: 100%; height: 100%;border: 2px solid #eee;"></div>
  15062 + <textarea name="${enumActionEl.CUSTOM_JSON_COMMAND}" class="layui-textarea" style="display: none;" />
  15063 + </div>
  15064 + `
  15065 + }
  15066 +
  15067 + function createServiceTCPParams() {
  15068 + return `
  15069 + <div>
  15070 + <div class="layui-form" lay-filter="${enumActionEl.SERVICE_TCP_COMMAND}">
  15071 + <div class="layui-form-item">
  15072 + <label class="layui-form-label" style="width: 120px;">自定义下发值</label>
  15073 + <div class="layui-input-block" style="margin-left: 150px;">
  15074 + <input type="text" name="${enumActionEl.SERVICE_TCP_COMMAND}" lay-verify="required" autocomplete="off" placeholder="请输入下发值" class="layui-input">
  15075 + </div>
  15076 + </div>
  15077 + </div>
  15078 + </div>
  15079 + `
  15080 + }
  15081 +
  15082 + function createServiceInputDataParams() {
  15083 + const inputData = jsonParse(content.serviceOriginalConfiguration)
  15084 + return UseLayUi.genThingsModelInputDataForm(inputData)
  15085 + }
  15086 +
  15087 + function createContent() {
  15088 + const { commandType, tcpCommand, jsonCommand, serviceCommand, serviceOriginalConfiguration, transportType } = content
  15089 + const isCustom = commandType === '0'
  15090 + const isTCP = transportType === 'TCP'
  15091 +
  15092 + let template
  15093 + if (isCustom) {
  15094 + if (isTCP) {
  15095 + template = createCustomTCPParams()
  15096 + } else {
  15097 + template = createCustomJSONParams()
  15098 + }
  15099 + } else {
  15100 + if (isTCP) {
  15101 + template = createServiceTCPParams()
  15102 + } else {
  15103 + template = createServiceInputDataParams()
  15104 + }
  15105 + }
  15106 + return `<form class="layui-form" lay-filter="${enumActionEl.FORM_FILTER}">${template}</form>`
  15107 + }
  15108 +
  15109 + function echoPresetValue() {
  15110 + form.val(enumActionEl.FORM_FILTER, {
  15111 + // 如果是自定义并且不是TCP设备 回显inputData
  15112 + ...(content.commandType === '1' && content.transportType !== 'TCP' ? content.serviceCommand : {}),
  15113 + [enumActionEl.CUSTOM_JSON_COMMAND]: content.jsonCommand,
  15114 + [enumActionEl.CUSTOM_TCP_COMMAND]: content.tcpCommand,
  15115 + [enumActionEl.SERVICE_TCP_COMMAND]: content.serviceCommand,
  15116 + })
  15117 + }
  15118 +
  15119 + function isJson(value) {
  15120 + try {
  15121 + JSON.parse(value)
  15122 + return true
  15123 + } catch (error) {
  15124 + return false
  15125 + }
  15126 + }
  15127 +
  15128 +
14863 function jsonParse(value) { 15129 function jsonParse(value) {
14864 try { 15130 try {
14865 return JSON.parse(value) 15131 return JSON.parse(value)
@@ -14868,12 +15134,49 @@ class HandleDataInteraction { @@ -14868,12 +15134,49 @@ class HandleDataInteraction {
14868 } 15134 }
14869 } 15135 }
14870 15136
  15137 + const validateSwitchCommand = () => {
  15138 + const { commandType, transportType } = content
  15139 + const isCustom = commandType === '0'
  15140 + const isTCP = transportType === 'TCP'
  15141 + let { attr } = contentData.dataSources.find(item => item.nodeId === nodeId) || {}
  15142 +
  15143 + let flag = false
  15144 + let value
  15145 +
  15146 + if (isCustom) {
  15147 + if (isTCP) {
  15148 + value = content.tcpCommand
  15149 + if (value) flag = true
  15150 + } else {
  15151 + const replaceValue = currentNode.getAttribute(SWITCH_SEND_VALUE)
  15152 + value = jsonParse(content.jsonCommand)
  15153 + value = replaceAttrPlaceholder(value, attr, replaceValue)
  15154 + if (value) flag = true
  15155 + }
  15156 + } else {
  15157 + if (isTCP) {
  15158 + value = content.serviceCommand
  15159 + if (value) flag = true
  15160 + } else {
  15161 + value = content.serviceCommand
  15162 + const { flag: validateFlag, value: validateValue } = UseLayUi.validateThingsModelInputDataForm(Utils.stringToJSON(content.serviceOriginalConfiguration), value, true)
  15163 + if (validateFlag) {
  15164 + value = validateValue
  15165 + flag = true
  15166 + }
  15167 + }
  15168 + }
  15169 + return { flag, value }
  15170 + }
  15171 +
14871 function handleSwitchComponent() { 15172 function handleSwitchComponent() {
14872 const state = currentNode.getAttribute(SWITCH_STATE) 15173 const state = currentNode.getAttribute(SWITCH_STATE)
14873 - const value = currentNode.getAttribute(SWITCH_SEND_VALUE)  
14874 if (state === SWITCH_STATE_NONE) { 15174 if (state === SWITCH_STATE_NONE) {
14875 return 15175 return
14876 } 15176 }
  15177 + const { flag, value } = validateSwitchCommand()
  15178 + if (!flag) return
  15179 +
14877 layer.confirm('是否确认下发命令?', async function (index) { 15180 layer.confirm('是否确认下发命令?', async function (index) {
14878 defaultHandler(value, () => layer.close(index)) 15181 defaultHandler(value, () => layer.close(index))
14879 }); 15182 });
@@ -14886,7 +15189,7 @@ class HandleDataInteraction { @@ -14886,7 +15189,7 @@ class HandleDataInteraction {
14886 15189
14887 for (const key of Object.keys(oldValue)) { 15190 for (const key of Object.keys(oldValue)) {
14888 if (key === enumConst.ATTR_PLACEHOLDER) { 15191 if (key === enumConst.ATTR_PLACEHOLDER) {
14889 - newValue[replaceAttr] = replaceValue 15192 + newValue[replaceAttr] = replaceValue ? replaceValue : oldValue[key]
14890 continue 15193 continue
14891 } 15194 }
14892 if (typeof oldValue[key] === 'object') { 15195 if (typeof oldValue[key] === 'object') {
@@ -14899,38 +15202,79 @@ class HandleDataInteraction { @@ -14899,38 +15202,79 @@ class HandleDataInteraction {
14899 return newValue 15202 return newValue
14900 } 15203 }
14901 15204
  15205 + const validate = (data) => {
  15206 + const { commandType, transportType } = content
  15207 + let { attr } = contentData.dataSources.find(item => item.nodeId === nodeId) || {}
  15208 + let flag = false
  15209 + let value
  15210 +
  15211 + const isCustom = commandType === '0'
  15212 + const isTCP = transportType === 'TCP'
  15213 +
  15214 + let template
  15215 + if (isCustom) {
  15216 + if (isTCP) {
  15217 + value = data[enumActionEl.CUSTOM_TCP_COMMAND]
  15218 + const validate = new Validate([
  15219 + { value, required: true, message: '下发值是必填项' },
  15220 + ])
  15221 + if (validate.begin()) flag = true
  15222 + } else {
  15223 + value = data[enumActionEl.CUSTOM_JSON_COMMAND]
  15224 + const validate = new Validate([
  15225 + { value, required: true, message: '下发值是必填项' },
  15226 + { value, message: 'json格式校验不正确', validator: isJson },
  15227 + ])
  15228 + if (validate.begin()) {
  15229 + const replaceValue = currentNode.getAttribute(SWITCH_SEND_VALUE)
  15230 + flag = true
  15231 + value = jsonParse(value)
  15232 + value = replaceAttrPlaceholder(value, attr)
  15233 + }
  15234 + template = createCustomJSONParams()
  15235 + }
  15236 + } else {
  15237 + if (isTCP) {
  15238 + value = data[enumActionEl.SERVICE_TCP_COMMAND]
  15239 + const validate = new Validate([
  15240 + { value, required: true, message: '下发值是必填项' },
  15241 + ])
  15242 + if (validate.begin()) flag = true
  15243 + } else {
  15244 + value = data
  15245 + const { flag: validateFlag, value: validateValue } = UseLayUi.validateThingsModelInputDataForm(Utils.stringToJSON(content.serviceOriginalConfiguration), value, true)
  15246 + if (validateFlag) {
  15247 + flag = true
  15248 + value = validateValue
  15249 + }
  15250 + }
  15251 + }
  15252 +
  15253 + return { flag, value }
  15254 + }
  15255 +
14902 const submitThrottle = this.throttle(submit) 15256 const submitThrottle = this.throttle(submit)
14903 async function submit(callback) { 15257 async function submit(callback) {
14904 - const { value } = form.val(enumActionEl.ISSUED_WAY_FILTER)  
14905 - defaultHandler(value, callback) 15258 + const value = form.val(enumActionEl.FORM_FILTER)
  15259 + const { flag, value: result } = validate(value)
  15260 + if (!flag) return
  15261 + defaultHandler(result, callback)
14906 } 15262 }
14907 15263
14908 async function defaultHandler(value, callback) { 15264 async function defaultHandler(value, callback) {
14909 let { deviceId, attr } = contentData.dataSources.find(item => item.nodeId === nodeId) || {} 15265 let { deviceId, attr } = contentData.dataSources.find(item => item.nodeId === nodeId) || {}
  15266 + console.log({ attr, value })
14910 15267
14911 /** 15268 /**
14912 * @type {command: string , commandType: string, service: string, wary: string, tcpCommand: string} 15269 * @type {command: string , commandType: string, service: string, wary: string, tcpCommand: string}
14913 */ 15270 */
14914 let { command, way, tcpCommand } = content 15271 let { command, way, tcpCommand } = content
14915 - const validate = new Validate([  
14916 - // { value, required: true, message: '下发值是必填项' },  
14917 - // { value: deviceId, required: true, message: '未绑定设备' },  
14918 - // { value: way, required: true, message: '未绑定指令下发方式(单向/双向)' },  
14919 - // { value: command, required: true, message: '未设置下发命令' },  
14920 - // { value: attr, required: true, message: '未绑定设备属性' },  
14921 - ])  
14922 -  
14923 - if (!validate.begin()) return  
14924 - if (typeof command === 'string') command = jsonParse(command)  
14925 - let data = replaceAttrPlaceholder(command, attr, value)  
14926 - if (tcpCommand) {  
14927 - data = tcpCommand  
14928 - } 15272 +
14929 const instructionData = { 15273 const instructionData = {
14930 method: "methodThingskit", 15274 method: "methodThingskit",
14931 additionalInfo: { cmdType: 'API' }, 15275 additionalInfo: { cmdType: 'API' },
14932 persistent: true, 15276 persistent: true,
14933 - params: data, 15277 + params: value,
14934 } 15278 }
14935 15279
14936 const [err, res = []] = way === 'twoway' ? await to(ConfigurationNodeApi.deviceIsOnLine(deviceId)) : [null, [{ value: true }]] 15280 const [err, res = []] = way === 'twoway' ? await to(ConfigurationNodeApi.deviceIsOnLine(deviceId)) : [null, [{ value: true }]]
@@ -14941,13 +15285,15 @@ class HandleDataInteraction { @@ -14941,13 +15285,15 @@ class HandleDataInteraction {
14941 UseLayUi.topSuccessMsg('操作成功') 15285 UseLayUi.topSuccessMsg('操作成功')
14942 callback && typeof callback === 'function' && callback() 15286 callback && typeof callback === 'function' && callback()
14943 } 15287 }
  15288 + if (err) {
  15289 + UseLayUi.topErrorMsg(err?.response?.data || err)
  15290 + }
14944 } else { 15291 } else {
14945 UseLayUi.topErrorMsg('设备不在线!') 15292 UseLayUi.topErrorMsg('设备不在线!')
14946 } 15293 }
14947 } 15294 }
14948 15295
14949 function createLayer() { 15296 function createLayer() {
14950 -  
14951 layer.open({ 15297 layer.open({
14952 title: '参数设置', 15298 title: '参数设置',
14953 content: createContent(), 15299 content: createContent(),
@@ -14961,7 +15307,9 @@ class HandleDataInteraction { @@ -14961,7 +15307,9 @@ class HandleDataInteraction {
14961 but2(index, layero) { 15307 but2(index, layero) {
14962 15308
14963 }, 15309 },
14964 - async success(layero, index) { 15310 + success(layero, index) {
  15311 + createEditor()
  15312 + echoPresetValue()
14965 $('.layui-layer-setwin a').removeAttr('href') 15313 $('.layui-layer-setwin a').removeAttr('href')
14966 form.render() 15314 form.render()
14967 }, 15315 },
@@ -14977,10 +15325,9 @@ class HandleDataInteraction { @@ -14977,10 +15325,9 @@ class HandleDataInteraction {
14977 } 15325 }
14978 15326
14979 try { 15327 try {
14980 - // handle[componentType]()  
14981 - handleSwitchComponent() 15328 + handle[componentType]()
14982 } catch (error) { 15329 } catch (error) {
14983 - 15330 + throw error
14984 } 15331 }
14985 } 15332 }
14986 startProcess() 15333 startProcess()
@@ -15742,6 +16089,10 @@ class Validate { @@ -15742,6 +16089,10 @@ class Validate {
15742 this.list = ruleList 16089 this.list = ruleList
15743 } 16090 }
15744 16091
  16092 + static isFunction(value) {
  16093 + return Object.prototype.toString.call(value) === '[object Function]'
  16094 + }
  16095 +
15745 /** 16096 /**
15746 * @description 设置规则 16097 * @description 设置规则
15747 * @param {{value: any, message: string, required?: boolean, validator?: any}} rule 16098 * @param {{value: any, message: string, required?: boolean, validator?: any}} rule
@@ -15757,6 +16108,12 @@ class Validate { @@ -15757,6 +16108,12 @@ class Validate {
15757 UseLayUi.topErrorMsg(message) 16108 UseLayUi.topErrorMsg(message)
15758 return false 16109 return false
15759 } 16110 }
  16111 +
  16112 + if (validator && Validate.isFunction(validator) && !validator(value)) {
  16113 + UseLayUi.topErrorMsg(message)
  16114 + return false
  16115 + }
  16116 +
15760 } 16117 }
15761 return true 16118 return true
15762 } 16119 }