Commit 66892ba1a626018e4ca117ba796fcf9f162ba7c4

Authored by ww
1 parent 299f7534

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

... ... @@ -6895,11 +6895,26 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6895 6895 TCP_COMMAND: 'tcpCommand',
6896 6896
6897 6897 /**
  6898 + * @description json命令
  6899 + */
  6900 + JSON_COMMAND: 'jsonCommand',
  6901 +
  6902 + /**
6898 6903 * @description 命令下发方式
6899 6904 */
6900 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 6918 * @description 服务
6904 6919 */
6905 6920 SERVICE: 'service',
... ... @@ -7028,22 +7043,28 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7028 7043 */
7029 7044 function echoFormData(data) {
7030 7045 const { content = {} } = data
  7046 + console.log(data)
7031 7047 const val = {
7032 7048 [enumConst.ACTION]: content.type,
7033 7049 [enumGetValue[content.type]]: content.value,
  7050 +
  7051 + // 参数设置
  7052 + [enumConst.JSON_COMMAND]: content[enumConst.JSON_COMMAND],
7034 7053 [enumConst.WAY]: content[enumConst.WAY],
7035 7054 [enumConst.COMMAND_TYPE]: content[enumConst.COMMAND_TYPE],
7036   - [enumConst.SERVICE]: content[enumConst.SERVICE],
7037   - [enumConst.COMMAND]: content[enumConst.COMMAND],
7038 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 7064 const isCustom = content[enumConst.COMMAND_TYPE] === COMMAND_TYPE_ENUM.CUSTOM
7044 7065
7045 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 7070 controlFormDisplay(content.type, isTCPTransportType, isCustom)
... ... @@ -7111,31 +7132,29 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7111 7132 if (isParamsSetting) {
7112 7133 const isTCPTransportType = formVal[enumConst.TRANSPORTTYPE] === 'TCP'
7113 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 7137 const validateParamsSetting = () => {
7117 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 7149 } else {
7127 7150 if (!formVal[enumConst.SERVICE]) {
7128 7151 UseLayUi.topErrorMsg('请选择服务')
7129 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 7159 return true
7141 7160 }
... ... @@ -7143,8 +7162,8 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7143 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 7178 type: formVal[enumConst.ACTION],
7160 7179 value: formVal[enumGetValue[formVal[enumConst.ACTION]]],
7161 7180 ...(isParamsSetting ? {
7162   - [enumConst.COMMAND]: formVal[enumConst.COMMAND],
  7181 + [enumConst.JSON_COMMAND]: formVal[enumConst.JSON_COMMAND],
7163 7182 [enumConst.WAY]: formVal[enumConst.WAY],
7164 7183 [enumConst.COMMAND_TYPE]: formVal[enumConst.COMMAND_TYPE],
7165   - [enumConst.SERVICE]: formVal[enumConst.SERVICE],
7166 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 7217 */
7196 7218 function generateCommandTypeOptions() {
7197 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 7223 return UseLayUi.generateOptionTemplate({ dataSource: options, addPlaceholderOption: false })
7202 7224 }
... ... @@ -7216,6 +7238,9 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7216 7238 let transportType
7217 7239 let deviceProfileServices = []
7218 7240
  7241 + /**
  7242 + * @description 动作下拉 change event
  7243 + */
7219 7244 form.on(`select(${enumActionEl.ACTION_SELECT_FILTER})`, (data) => {
7220 7245 const { value } = data
7221 7246 if (value === enumActionType.PARAMS_SETTING && !dataSource.deviceProfileId) {
... ... @@ -7228,6 +7253,9 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7228 7253 controlFormDisplay(value, transportType, isCustom)
7229 7254 })
7230 7255
  7256 + /**
  7257 + * @description 命令类型下拉 change event
  7258 + */
7231 7259 form.on(`select(${enumActionEl.COMMAND_TYPE_EL})`, (data) => {
7232 7260 const { value } = data
7233 7261 const flag = value === COMMAND_TYPE_ENUM.CUSTOM
... ... @@ -7237,8 +7265,12 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7237 7265 $(`#${enumActionEl.TCP_COMMAND_INPUT}`).css({ display: isTCPTransportType && flag ? 'block' : 'none' })
7238 7266 $(`#${enumActionEl.EDITOR_CONTAINER}`).css({ display: !isTCPTransportType && flag ? 'flex' : 'none' })
7239 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 7274 form.on(`select(${enumActionEl.SERVICE_EL})`, (data) => {
7243 7275 const { value } = data
7244 7276 const needRender = deviceProfileServices.find(item => item.identifier === value) || {}
... ... @@ -7248,10 +7280,9 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7248 7280 const template = UseLayUi.genThingsModelInputDataForm(needRender.functionJson?.inputData || [], 120)
7249 7281 $(`#${enumActionEl.INPUT_DATA_FORM}`).html(template)
7250 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 7288 try {
... ... @@ -7272,7 +7303,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7272 7303 if (transportType !== 'TCP') {
7273 7304 const template = UseLayUi.genThingsModelInputDataForm(needRender.functionJson?.inputData || [], 120)
7274 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 7349 fontSize: 14, // 编辑器内字体大小
7319 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 7353 const stringValue = JSON.stringify(defaultValue, null, 2)
7323 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 7356 editor.session.setMode("ace/mode/json");
7326 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 7418 </select>
7388 7419 </div>
7389 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 7428 <div style="width: 120px; text-align: right; padding: 9px 15px;flex: 0 0 120px;">命令 ${createHelpMessage('用户预览模式下,点击参数设置后。输入的变量值将作为"attrPlaceholder"的值,并以JSON格式下发给服务器。', 'command')}</div>
7392 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 7431 </div>
7395 7432 <div id="${enumActionEl.TCP_COMMAND_INPUT}" style="display: none;">
7396 7433 <label class="layui-form-label" style="width: 120px;">命令 ${createHelpMessage('用户预览模式下,点击参数设置后。输入的变量值将作为"attrPlaceholder"的值,并以JSON格式下发给服务器。', 'command')}</label>
... ... @@ -12486,6 +12523,19 @@ class UseLayUi {
12486 12523
12487 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 12540 * @description 生成输入框控件
12491 12541 * @param {{label: string, value: string, labelWidth: number, numberInput: boolean}} params
... ... @@ -12536,6 +12586,67 @@ class UseLayUi {
12536 12586 </form>`
12537 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 12652 * @description format data source to tree structure
... ... @@ -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 13128 * @description use to function capture await throw error
... ... @@ -14841,25 +14979,153 @@ class HandleDataInteraction {
14841 14979 const enumActionEl = {
14842 14980 CONTAINER: 'container',
14843 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 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 15029 </div>
14858 15030 </div>
14859 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 15129 function jsonParse(value) {
14864 15130 try {
14865 15131 return JSON.parse(value)
... ... @@ -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 15172 function handleSwitchComponent() {
14872 15173 const state = currentNode.getAttribute(SWITCH_STATE)
14873   - const value = currentNode.getAttribute(SWITCH_SEND_VALUE)
14874 15174 if (state === SWITCH_STATE_NONE) {
14875 15175 return
14876 15176 }
  15177 + const { flag, value } = validateSwitchCommand()
  15178 + if (!flag) return
  15179 +
14877 15180 layer.confirm('是否确认下发命令?', async function (index) {
14878 15181 defaultHandler(value, () => layer.close(index))
14879 15182 });
... ... @@ -14886,7 +15189,7 @@ class HandleDataInteraction {
14886 15189
14887 15190 for (const key of Object.keys(oldValue)) {
14888 15191 if (key === enumConst.ATTR_PLACEHOLDER) {
14889   - newValue[replaceAttr] = replaceValue
  15192 + newValue[replaceAttr] = replaceValue ? replaceValue : oldValue[key]
14890 15193 continue
14891 15194 }
14892 15195 if (typeof oldValue[key] === 'object') {
... ... @@ -14899,38 +15202,79 @@ class HandleDataInteraction {
14899 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 15256 const submitThrottle = this.throttle(submit)
14903 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 15264 async function defaultHandler(value, callback) {
14909 15265 let { deviceId, attr } = contentData.dataSources.find(item => item.nodeId === nodeId) || {}
  15266 + console.log({ attr, value })
14910 15267
14911 15268 /**
14912 15269 * @type {command: string , commandType: string, service: string, wary: string, tcpCommand: string}
14913 15270 */
14914 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 15273 const instructionData = {
14930 15274 method: "methodThingskit",
14931 15275 additionalInfo: { cmdType: 'API' },
14932 15276 persistent: true,
14933   - params: data,
  15277 + params: value,
14934 15278 }
14935 15279
14936 15280 const [err, res = []] = way === 'twoway' ? await to(ConfigurationNodeApi.deviceIsOnLine(deviceId)) : [null, [{ value: true }]]
... ... @@ -14941,13 +15285,15 @@ class HandleDataInteraction {
14941 15285 UseLayUi.topSuccessMsg('操作成功')
14942 15286 callback && typeof callback === 'function' && callback()
14943 15287 }
  15288 + if (err) {
  15289 + UseLayUi.topErrorMsg(err?.response?.data || err)
  15290 + }
14944 15291 } else {
14945 15292 UseLayUi.topErrorMsg('设备不在线!')
14946 15293 }
14947 15294 }
14948 15295
14949 15296 function createLayer() {
14950   -
14951 15297 layer.open({
14952 15298 title: '参数设置',
14953 15299 content: createContent(),
... ... @@ -14961,7 +15307,9 @@ class HandleDataInteraction {
14961 15307 but2(index, layero) {
14962 15308
14963 15309 },
14964   - async success(layero, index) {
  15310 + success(layero, index) {
  15311 + createEditor()
  15312 + echoPresetValue()
14965 15313 $('.layui-layer-setwin a').removeAttr('href')
14966 15314 form.render()
14967 15315 },
... ... @@ -14977,10 +15325,9 @@ class HandleDataInteraction {
14977 15325 }
14978 15326
14979 15327 try {
14980   - // handle[componentType]()
14981   - handleSwitchComponent()
  15328 + handle[componentType]()
14982 15329 } catch (error) {
14983   -
  15330 + throw error
14984 15331 }
14985 15332 }
14986 15333 startProcess()
... ... @@ -15742,6 +16089,10 @@ class Validate {
15742 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 16097 * @description 设置规则
15747 16098 * @param {{value: any, message: string, required?: boolean, validator?: any}} rule
... ... @@ -15757,6 +16108,12 @@ class Validate {
15757 16108 UseLayUi.topErrorMsg(message)
15758 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 16118 return true
15762 16119 }
... ...