ananzhusen преди 3 месеца
родител
ревизия
b273b83337
променени са 3 файла, в които са добавени 304 реда и са изтрити 37 реда
  1. 8 3
      src/services/defaults.ts
  2. 229 11
      src/views/components/Actions.vue
  3. 67 23
      src/views/components/Network.vue

+ 8 - 3
src/services/defaults.ts

@@ -2246,9 +2246,14 @@ export const formComponents = [
                   },
                   "params": "",
                   "targetType": "id",
-                  "value": {
-                    "shared": true
-                  }
+                  // "value": {
+                  //   "shared": true
+                  // }
+                  data:[{
+                    prop:'shared',
+                    value:true,
+                    id: "固定值"
+                  }]
                 }
               ],
               "conditionType": "and",

+ 229 - 11
src/views/components/Actions.vue

@@ -204,7 +204,66 @@
           </div>
         </template>
         <template v-else-if="a.action == 15">
-          <Network v-model="a.network" mode="1"></Network>
+          <Network v-model="a.network" mode="1" />
+          <div class="flex middle mt-16">
+            <t-tooltip content="json格式">
+              <div class="flex middle mr-8" style="font-size:12px;color:var(--color)">数据</div>
+            </t-tooltip>
+            <add-circle-icon @click="addSendData(a)" class="hover"/>
+          </div>
+          <template v-for="(d,idx) in a.data">
+            <div class="flex middle actions-data mt-16" style="position:relative" >
+              <t-input class="actions-prop" style="width: 70px;" v-model="d.prop" />
+              <Edit1Icon style="position:absolute;left:56px;height: 32px;" class="hover" @click="selectDeviceProps(d)"/>
+              <!-- <t-input style="width: 100px;" v-model="item.value" /> -->
+              :
+              <t-tree-select
+                placeholder="固定值"
+                style="width: 90px;"
+                v-model="d.id"
+                :data="propTree"
+                filterable
+                @change="getAProps(d)"
+              />
+              <t-select-input
+                v-if="d.id&&d.id!=='固定值'"
+                placeholder="可自定义输入"
+                v-model:inputValue="d.key"
+                :value="d.keyLabel"
+                v-model:popupVisible="d.keyPopupVisible"
+                allow-input
+                clearable
+                @clear="d.keyLabel = undefined"
+                @focus="d.keyPopupVisible = true"
+                @blur="d.keyPopupVisible = false"
+                @input-change="onKeyInput(d)"
+                class="shrink-0 actions-key"
+                style="width: 82px"
+              >
+                <template #panel>
+                  <ul style="padding: 8px 12px">                  
+                    <li
+                      v-for="item in dprops"
+                      :key="item.value"
+                      @click="
+                        d.key = item.value;
+                        d.keyLabel = item.label;
+                        d.keyPopupVisible = false;
+                      "
+                    >
+                      {{ item.label }}
+                    </li>
+                    <t-divider style="border-top: 1px solid var(--color-border-input);"/> 
+                    <li @click="getKeyMore(d)">
+                      更多 
+                    </li>
+                  </ul>
+                </template>
+              </t-select-input>
+              <t-input v-else class="actions-value"  placeholder="输入值" style="width: 82px;" v-model="d.value" @change="valueDChange($event,d)" />
+              <delete-icon  class="hover" @click="delSendData(a.data,idx)"/>
+            </div>
+          </template>
           <template v-for="(item,idx) in a.list">
           <div class="flex middle between mt-16">
             <div class="flex middle" style="font-size:12px">{{$t('数据')}}{{ idx+1 }}</div>
@@ -266,12 +325,12 @@
           </div>
           
           </template>
-          <div class="form-item mt-8">
+          <!-- <div class="form-item mt-8">
             <label></label>
             <t-button style="width:150px" @click="addData(a)">
               {{$t('添加数据')}}
             </t-button>
-          </div>
+          </div> -->
           <div class="form-item mt-8" v-if="a.network&&a.network.protocol==='http'">
             <label>{{$t('回调')}}</label>
             <CodeEditor v-model="a.callback" class="mt-4" style="height: 50px"></CodeEditor>
@@ -514,18 +573,23 @@
       <a @click="data.actions.push({})"> + {{$t('添加动作')}} </a>
     </div>
   </div>
+  <PropModal v-model:visible="propModal.visible" @change="getProp" />
+  <MoreModal v-model:visible="more.visible" @change="getMProp" />
 </template>
 
 <script lang="ts" setup>
-import {getCurrentInstance} from 'vue';
-import { onBeforeMount, ref } from 'vue';
-
+import { onBeforeMount, ref, reactive, getCurrentInstance } from 'vue';
+import PropModal from '@/views/components/common/PropModal.vue';
+import MoreModal from '@/views/components/common/MoreModal.vue';
 import CodeEditor from '@/views/components/common/CodeEditor.vue';
 import Network from './Network.vue';
-import { CloseIcon,AddCircleIcon,DeleteIcon,CheckIcon} from 'tdesign-icons-vue-next';
+import { CloseIcon, AddCircleIcon, DeleteIcon, CheckIcon, Edit1Icon, LinkIcon} from 'tdesign-icons-vue-next';
 import { getPenAnimations, getPenTree ,changeType, getIframeTree} from '@/services/common';
+import { deepClone } from '@meta2d/core';
+
 const { proxy } = getCurrentInstance();
 const $t = proxy.$t
+
 const { data } = defineProps<{
   data: any;
 }>();
@@ -619,6 +683,11 @@ onBeforeMount(() => {
   });
 
   penTree.value = getPenTree();
+  propTree.value = deepClone(penTree.value);
+  propTree.value.unshift({
+    label:"固定值",
+    value:"固定值"
+  })
   iframeTree.value = getIframeTree();
   groups.value = [];
   const d = meta2d.store.data as any;
@@ -659,13 +728,13 @@ const onChangeAction = (action: any) => {
       }
       break;
     case 15:
-      action.network = {type: 'publish',protocol: 'mqtt', options: {}};
+      action.network = {}// {type: 'publish',protocol: 'mqtt', options: {}};
       // action.params = '';
       // action.value = {};
       action.targetType = 'id';
-      action.list = [
-        {params:undefined,value:{}}
-      ];
+      // action.list = [
+      //   {params:undefined,value:{}}
+      // ];
       getProps(action);
       break;
     default:
@@ -842,6 +911,132 @@ const addData = (a:any)=>{
   a.list.push({params:undefined,value:{}})
 }
 
+const addSendData = (a:any)=>{
+  if(!a.data){
+    a.data = [];
+  }
+  a.data.push({
+    key:'',
+    value:''
+  });
+}
+
+const delSendData = (data:any[] ,i:number)=>{
+  data.splice(i,1);
+}
+
+let dprops = ref<any>([{
+    value: 'text',
+    label: '文字',
+  },
+  {
+    value: 'visible',
+    label: '显示',
+  },
+  {
+    value: 'progress',
+    label: '进度',
+  },
+  {
+    value: 'showChild',
+    label: '状态',
+  },
+  {
+    value: 'checked',
+    label: '选中',
+  },
+  {
+    value: 'selectedKey',
+    label: '单选选中值',
+  }]);
+
+const propTree = ref([]);
+const getAProps = (a)=>{
+  let props = [{
+    value: 'text',
+    label: '文字',
+  },
+  {
+    value: 'visible',
+    label: '显示',
+  },
+  {
+    value: 'progress',
+    label: '进度',
+  },
+  {
+    value: 'showChild',
+    label: '状态',
+  },
+  {
+    value: 'checked',
+    label: '选中',
+  },
+  {
+    value: 'selectedKey',
+    label: '单选选中值',
+  },]
+  let target: any;
+  if (a.id && a.id!=='固定值') {
+    target = meta2d.findOne(a.id);
+  } else {
+    return;
+  }
+  if (target?.realTimes) {
+    for (const item of target.realTimes) {
+      const found = props.findIndex((elem: any) => elem.value === item.key);
+      if (found < 0) {
+        props.push({
+          value: item.key,
+          label: item.label,
+        });
+      }
+    }
+  }
+  dprops.value = props;
+}
+
+const propModal = reactive({
+  visible:false,
+  data:null
+})
+
+const selectDeviceProps = (i)=>{
+  propModal.visible = true;
+  propModal.data = i;
+}
+
+const getProp = (e)=>{
+  propModal.data.prop = e;
+  propModal.visible = false;
+}
+
+const more = ref({
+  visible:false,
+  data:null,
+});
+
+const getKeyMore = (d)=>{
+  more.value.data = d;
+  more.value.visible = true;
+}
+
+const getMProp = (e)=>{
+  let d = deepClone(e);
+  more.value.data.key = d.value;
+  more.value.data.keyLabel = d.label;
+  more.value.data.keyPopupVisible = false;
+  more.value.visible = false;
+}
+
+const valueDChange = (e,c:any)=>{
+  c.value= changeType(e);
+}
+
+const onKeyInput = (item: any) => {
+  item.keyLabel = item.key;
+};
+
 const themeOptions = [
   {
     label: '普通消息',
@@ -884,5 +1079,28 @@ const themeOptions = [
       border: none;
     }
   }
+  .actions-data{
+    :deep(.t-input){
+      border-color:transparent;
+      &:hover {
+        border-color: var(--color-primary);
+      }
+    }
+    .actions-prop{
+      :deep(.t-input){
+        width: 70px;
+      }
+    }
+    .actions-key{
+      :deep(.t-input){
+        width: 82px;
+      }
+    }
+    .actions-value{
+      :deep(.t-input){
+        width: 82px;
+      }
+    }
+  }
 }
 </style>

+ 67 - 23
src/views/components/Network.vue

@@ -2,7 +2,7 @@
   <div class="network-component">
     <div class="form-item mt-8">
       <label>
-        {{ modelValue.type === 'subscribe' ? $t('数据获取') : $t('数据发送') }}
+        {{ modelValue.type === 'subscribe' ? $t('数据获取') : $t('发送') }}
       </label>
       <t-select-input
         v-if="mode"
@@ -16,20 +16,31 @@
         @blur="popupVisible = false"
         @input-change="onInput"
         @clear="
-          modelValue.id = undefined;
-          modelValue._id = undefined;
+          modelValue.name = undefined;
         "
       >
         <template #panel>
           <ul style="padding: 4px">
-            <li class="hover-background item" style="line-height: 1.5; padding: 8px; border-radius: 2px" v-for="(item, i) in networkList" :key="item.url" @click="() => onSelect(item)">
-{{$t('              名称: ')}}{{ item.name }}
-              <div class="desc">{{$t('地址: ')}}{{ item.url }}</div>
+            <li class="hover-background item"  @click="() => onSelect({protocol:'http',name:'自定义'})">
+                自定义
+            </li>
+            <t-divider></t-divider>
+            <li v-if="hasIot" class="hover-background item"  @click="() => onSelect({protocol:'iot',name:'物联网平台'})">
+                物联网平台
+            </li>
+            <li
+              class="hover-background item"
+              style="line-height: 1.5; padding: 8px; border-radius: 2px"
+              v-for="(item, i) in networkList"
+              :key="item.url"
+              @click="() => onSelect(item)"
+            >
+              名称: {{ item.name }}
+              <div v-if="item.url" class="desc">地址: {{ item.url }}</div>
 
-              <span class="del" @click.stop="onDelNetWork(item, i)">
+              <!-- <span class="del" @click.stop="onDelNetWork(item, i)">
                 <delete-icon />
-                <!-- <t-icon name="delete" /> -->
-              </span>
+              </span> -->
             </li>
             <li
               v-if="networkList.length >= 10"
@@ -46,9 +57,9 @@
       </t-select-input>
       <t-input v-else v-model="modelValue.name" :placeholder="$t('名称')"></t-input>
     </div>
-
-    <div class="form-item mt-8">
-      <label>{{$t( '通信方式' )}}</label>
+    <template v-if="modelValue.protocol&&modelValue.protocol!=='iot'">
+    <div v-if="!modelValue.unmodifiable"  class="form-item mt-8">
+      <label>通信方式</label>
       <t-select
         v-model="modelValue.protocol"
         placeholder="MQTT"
@@ -59,26 +70,28 @@
         <t-option key="http" value="http" label="HTTP" />
       </t-select>
     </div>
-    <div class="form-item mt-8">
-      <label>URL{{$t('地址')}}</label>
-      <t-input :format="urlFormat" :placeholder="
-          modelValue.protocol !== $t('http')
+    <div v-if="!modelValue.unmodifiable"  class="form-item mt-8">
+      <label>URL地址</label>
+      <t-input
+        :format="urlFormat"
+        :placeholder="
+          modelValue.protocol !== 'http'
             ? isSafeProtocol()
               ? $t('必须是wss协议')
               : $t('必须是ws协议')
             : $t('请输入')
         " v-model="modelValue.url"></t-input>
     </div>
-    <template v-if="modelValue.protocol === 'websocket'">
-      <div class="form-item mt-8">
+    <template v-if="modelValue.protocol === 'websocket'&&modelValue.options">
+      <div v-if="!modelValue.unmodifiable" class="form-item mt-8">
         <label>protocols</label>
         <t-input v-model="modelValue.options.protocols" />
       </div>
     </template>
     <template v-else-if="modelValue.protocol === 'http'">
       <div class="form-item mt-8">
-        <label>{{$t('请求方式')}}</label>
-        <t-select v-model="modelValue.method" @change="httpMethodChange">
+        <label>请求方式</label>
+        <t-select :disabled="modelValue.unmodifiable" v-model="modelValue.method" @change="httpMethodChange">
           <t-option key="GET" value="GET" label="GET" />
           <t-option key="POST" value="POST" label="POST" />
         </t-select>
@@ -129,7 +142,8 @@
         {{$t('支持设置动态参数')}},{{$t('例如')}}:{"value": "${value}"}
       </div>
     </template>
-    <template v-else>
+    <template v-else-if="modelValue.protocol === 'mqtt'">
+      <template  v-if="modelValue.options&&!modelValue.unmodifiable">
       <div class="form-item mt-8">
         <label>Client Id</label>
         <t-input v-model="modelValue.options.clientId" />
@@ -146,17 +160,19 @@
         <label>{{$t('密码')}}</label>
         <t-input v-model="modelValue.options.password"></t-input>
       </div>
+      </template>
       <div class="form-item mt-8">
         <label>Topics</label>
         <t-input v-model="modelValue.topics" />
       </div>
     </template>
-    <div class="form-item mt-8" v-if="mode">
+    </template>
+    <!-- <div class="form-item mt-8" v-if="mode">
       <label> </label>
       <div>
         <t-button @click="onSave">{{$t('保存到我的数据发送')}}</t-button>
       </div>
-    </div>
+    </div> -->
   </div>
 </template>
 
@@ -168,6 +184,7 @@ import { MessagePlugin } from 'tdesign-vue-next';
 import CodeEditor from '@/views/components/common/CodeEditor.vue';
 import { DeleteIcon } from 'tdesign-icons-vue-next';
 import { transformData } from '@/services/utils';
+import { deepClone } from '@meta2d/core';
 
 const { modelValue, mode } = defineProps<{
   modelValue: any;
@@ -237,8 +254,30 @@ const onInput = (text: string) => {
   debounce(getNetworks, 300);
 };
 
+const hasIot = ref(false);
+
 // 请求我的数据源接口
 const getNetworks = async () => {
+  let arr = [];
+  meta2d.store.data.networks.forEach((network)=>{
+     if(['mqtt','websocket','http'].includes(network.protocol)&&network.method!=="POST"){
+        let net:any = deepClone(network);
+        if(net.protocol === 'http'){
+          net.method = 'POST'
+        }
+        net.unmodifiable = true;
+        net.type = '';
+        net.value ='';
+        net.tem_index='';
+        net.label = '';
+        arr.push(net);
+     }
+  });
+  if(meta2d.store.data.iot?.tree?.length){
+    hasIot.value = true;
+  }
+  networkList.value =arr;// deepClone(meta2d.store.data.networks);
+  return;
   const body: any = {
     type: modelValue.type,
     projection: "id,data,name,type",
@@ -263,6 +302,11 @@ const getNetworks = async () => {
 };
 
 const onSelect = (item: any) => {
+  for (let key in modelValue) {
+    if (modelValue.hasOwnProperty(key)) {
+      delete modelValue[key];
+    }
+  }
   Object.assign(modelValue, item);
   popupVisible.value = false;
 };