|
@@ -282,11 +282,11 @@
|
|
<li
|
|
<li
|
|
style="line-height: 14px; margin: 8px 4px"
|
|
style="line-height: 14px; margin: 8px 4px"
|
|
v-for="item in comOptions"
|
|
v-for="item in comOptions"
|
|
- :key="item.addr"
|
|
|
|
|
|
+ :key="item.url"
|
|
@click="() => onOptionClick(item)"
|
|
@click="() => onOptionClick(item)"
|
|
>
|
|
>
|
|
名称: {{ item.name }}<br />
|
|
名称: {{ item.name }}<br />
|
|
- 地址: {{ item.addr }}
|
|
|
|
|
|
+ 地址: {{ item.url }}
|
|
</li>
|
|
</li>
|
|
</ul>
|
|
</ul>
|
|
</template>
|
|
</template>
|
|
@@ -294,7 +294,9 @@
|
|
<t-icon name="search"></t-icon
|
|
<t-icon name="search"></t-icon
|
|
></template>
|
|
></template>
|
|
</t-select-input>
|
|
</t-select-input>
|
|
- <t-button style="height: 30px">添加数据源</t-button>
|
|
|
|
|
|
+ <t-button style="height: 30px" @click="addCom"
|
|
|
|
+ >添加数据源</t-button
|
|
|
|
+ >
|
|
</t-space>
|
|
</t-space>
|
|
</t-row>
|
|
</t-row>
|
|
<t-table
|
|
<t-table
|
|
@@ -316,29 +318,133 @@
|
|
</t-popconfirm>
|
|
</t-popconfirm>
|
|
</template>
|
|
</template>
|
|
</t-table>
|
|
</t-table>
|
|
- <!-- <p style="padding: 25px">选项卡1的内容,使用 t-tab-panel 渲染</p> -->
|
|
|
|
</div>
|
|
</div>
|
|
<div v-show="!comShow">
|
|
<div v-show="!comShow">
|
|
- <t-button theme="primary" variant="text" ghost @click="comBack">
|
|
|
|
- <template #icon>
|
|
|
|
- <t-icon name="rollback"></t-icon>
|
|
|
|
- </template>
|
|
|
|
- 返回
|
|
|
|
- </t-button>
|
|
|
|
- <div class="form-item">
|
|
|
|
|
|
+ <t-row class="mt-8">
|
|
|
|
+ <t-col :span="4">
|
|
|
|
+ <t-button
|
|
|
|
+ theme="primary"
|
|
|
|
+ variant="text"
|
|
|
|
+ ghost
|
|
|
|
+ @click="comBack"
|
|
|
|
+ >
|
|
|
|
+ <template #icon>
|
|
|
|
+ <t-icon name="rollback"></t-icon>
|
|
|
|
+ </template>
|
|
|
|
+ 返回
|
|
|
|
+ </t-button>
|
|
|
|
+ </t-col>
|
|
|
|
+ <t-col :span="4" :offset="4">
|
|
|
|
+ <t-button @click="saveForCurrent" theme="primary"
|
|
|
|
+ >仅当前页面使用</t-button
|
|
|
|
+ >
|
|
|
|
+ <t-button @click="saveToServer" theme="primary" class="ml-4"
|
|
|
|
+ >保存到服务器</t-button
|
|
|
|
+ >
|
|
|
|
+ </t-col>
|
|
|
|
+ </t-row>
|
|
|
|
+ <div class="form-item mt-16">
|
|
<label>名称</label>
|
|
<label>名称</label>
|
|
- <t-input v-model="com.name" class="ml-8" style="width: 200px" />
|
|
|
|
|
|
+ <t-input v-model="com.name" style="width: 200px" />
|
|
</div>
|
|
</div>
|
|
|
|
+
|
|
<div class="form-item">
|
|
<div class="form-item">
|
|
<label>连接类型</label>
|
|
<label>连接类型</label>
|
|
- <t-input v-model="com.type" class="ml-8" style="width: 200px" />
|
|
|
|
- </div>
|
|
|
|
- <div class="form-item">
|
|
|
|
- <label>接口地址</label>
|
|
|
|
- <t-input v-model="com.addr" class="ml-8" style="width: 200px" />
|
|
|
|
|
|
+ <t-select
|
|
|
|
+ v-model="com.type"
|
|
|
|
+ placeholder="请选择"
|
|
|
|
+ style="width: 200px"
|
|
|
|
+ :popup-props="{ overlayInnerStyle: { width: '200px' } }"
|
|
|
|
+ :disabled="comType === 'edit'"
|
|
|
|
+ @change="comTypeChange"
|
|
|
|
+ >
|
|
|
|
+ <t-option key="mqtt" value="mqtt" class="overlay-options">
|
|
|
|
+ </t-option>
|
|
|
|
+ <t-option
|
|
|
|
+ key="websocket"
|
|
|
|
+ value="websocket"
|
|
|
|
+ class="overlay-options"
|
|
|
|
+ >
|
|
|
|
+ </t-option>
|
|
|
|
+ <t-option key="http" value="http" class="overlay-options">
|
|
|
|
+ </t-option>
|
|
|
|
+ </t-select>
|
|
</div>
|
|
</div>
|
|
- <t-button theme="primary">仅当前页面使用</t-button>
|
|
|
|
- <t-button theme="primary">保存到服务器</t-button>
|
|
|
|
|
|
+ <template v-if="com.type === 'mqtt'">
|
|
|
|
+ <div class="form-item">
|
|
|
|
+ <label>接口地址</label>
|
|
|
|
+ <t-input v-model="com.url" style="width: 200px" />
|
|
|
|
+ </div>
|
|
|
|
+ <div class="form-item">
|
|
|
|
+ <label>Client Id</label>
|
|
|
|
+ <t-input
|
|
|
|
+ v-model="com.options.clientId"
|
|
|
|
+ style="width: 200px"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <div class="form-item">
|
|
|
|
+ <label>关闭自动生成</label>
|
|
|
|
+ <t-switch v-model="com.options.customClientId" />
|
|
|
|
+ </div>
|
|
|
|
+ <div class="form-item">
|
|
|
|
+ <label>用户名</label>
|
|
|
|
+ <t-input
|
|
|
|
+ v-model="com.options.username"
|
|
|
|
+ style="width: 200px"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <div class="form-item">
|
|
|
|
+ <label>密码</label>
|
|
|
|
+ <t-input
|
|
|
|
+ v-model="com.options.password"
|
|
|
|
+ style="width: 200px"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <div class="form-item">
|
|
|
|
+ <label>Topics</label>
|
|
|
|
+ <t-input v-model="com.topics" style="width: 200px" />
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ <template v-else-if="com.type === 'http'">
|
|
|
|
+ <div class="form-item">
|
|
|
|
+ <label>请求方式</label>
|
|
|
|
+ <t-select
|
|
|
|
+ v-model="com.method"
|
|
|
|
+ placeholder="请选择"
|
|
|
|
+ style="width: 200px"
|
|
|
|
+ :popup-props="{ overlayInnerStyle: { width: '200px' } }"
|
|
|
|
+ @change="comHttpMethodChange"
|
|
|
|
+ >
|
|
|
|
+ <t-option key="GET" value="GET"> </t-option>
|
|
|
|
+ <t-option key="POST" value="POST"> </t-option>
|
|
|
|
+ </t-select>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="form-item">
|
|
|
|
+ <label>请求头</label>
|
|
|
|
+ <t-textarea
|
|
|
|
+ v-model="com.httpHeaders"
|
|
|
|
+ placeholder="请输入请求头"
|
|
|
|
+ name="description"
|
|
|
|
+ :autosize="{ minRows: 3, maxRows: 5 }"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ <div v-if="com.method === 'POST'" class="form-item">
|
|
|
|
+ <label>请求体</label>
|
|
|
|
+
|
|
|
|
+ <t-textarea
|
|
|
|
+ v-model="com.body"
|
|
|
|
+ placeholder="请输入请求体"
|
|
|
|
+ name="description"
|
|
|
|
+ :autosize="{ minRows: 3, maxRows: 5 }"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ <template v-else>
|
|
|
|
+ <div class="form-item">
|
|
|
|
+ <label>protocol</label>
|
|
|
|
+ <t-input v-model="com.protocols" style="width: 200px" />
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
</t-tab-panel>
|
|
</t-tab-panel>
|
|
@@ -356,10 +462,16 @@
|
|
<t-row class="mt-8">
|
|
<t-row class="mt-8">
|
|
<t-col flex="60px">自定义</t-col>
|
|
<t-col flex="60px">自定义</t-col>
|
|
<t-col flex="auto">
|
|
<t-col flex="auto">
|
|
- <t-button class="ml-8" style="height: 30px"
|
|
|
|
|
|
+ <t-button
|
|
|
|
+ @click="importDataSet"
|
|
|
|
+ class="ml-8"
|
|
|
|
+ style="height: 30px"
|
|
>从Excel导入</t-button
|
|
>从Excel导入</t-button
|
|
>
|
|
>
|
|
- 名称(数据点ID 类型 值
|
|
|
|
|
|
+ <t-button @click="downloadDataSet" variant="text">
|
|
|
|
+ <template #icon><t-icon name="download"></t-icon> </template>
|
|
|
|
+ 下载示例
|
|
|
|
+ </t-button>
|
|
</t-col>
|
|
</t-col>
|
|
</t-row>
|
|
</t-row>
|
|
<t-table
|
|
<t-table
|
|
@@ -409,6 +521,8 @@ import { checkData, Meta2dBackData } from "@/services/utils";
|
|
import { cdn } from "@/services/api";
|
|
import { cdn } from "@/services/api";
|
|
import dayjs from "dayjs";
|
|
import dayjs from "dayjs";
|
|
import ContextMenu from "./ContextMenu.vue";
|
|
import ContextMenu from "./ContextMenu.vue";
|
|
|
|
+import { importExcel, saveAsExcel } from "@/services/excel";
|
|
|
|
+import { it } from "node:test";
|
|
|
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
const route = useRoute();
|
|
const route = useRoute();
|
|
@@ -848,24 +962,47 @@ const changeContextMenuVisible = (e: boolean) => {
|
|
interface Com {
|
|
interface Com {
|
|
name?: string;
|
|
name?: string;
|
|
type: "mqtt" | "websocket" | "http";
|
|
type: "mqtt" | "websocket" | "http";
|
|
- addr: string;
|
|
|
|
|
|
+ url?: string;
|
|
|
|
+ //websocket
|
|
|
|
+ protocols?: string;
|
|
|
|
+ //mqtt
|
|
|
|
+ topics?: string;
|
|
|
|
+ options?: {
|
|
|
|
+ clientId?: string;
|
|
|
|
+ username?: string;
|
|
|
|
+ password?: string;
|
|
|
|
+ customClientId?: boolean;
|
|
|
|
+ };
|
|
|
|
+ //http
|
|
|
|
+ http?: string; // http 请求 Url
|
|
|
|
+ httpTimeInterval?: number; // http 请求间隔
|
|
|
|
+ httpHeaders?: HeadersInit; //请求头
|
|
|
|
+ method?: string;
|
|
|
|
+ body?: BodyInit | null;
|
|
}
|
|
}
|
|
|
|
|
|
const comData = ref<Com[]>([
|
|
const comData = ref<Com[]>([
|
|
{
|
|
{
|
|
name: "连接1",
|
|
name: "连接1",
|
|
type: "mqtt",
|
|
type: "mqtt",
|
|
- addr: "wss://1",
|
|
|
|
|
|
+ url: "wss://1",
|
|
|
|
+ topics: "",
|
|
|
|
+ options: {
|
|
|
|
+ clientId: "",
|
|
|
|
+ username: "",
|
|
|
|
+ password: "",
|
|
|
|
+ customClientId: false,
|
|
|
|
+ },
|
|
},
|
|
},
|
|
{
|
|
{
|
|
name: "连接2",
|
|
name: "连接2",
|
|
- type: "mqtt",
|
|
|
|
- addr: "wss://2",
|
|
|
|
|
|
+ type: "websocket",
|
|
|
|
+ url: "wss://2",
|
|
},
|
|
},
|
|
{
|
|
{
|
|
name: "连接3",
|
|
name: "连接3",
|
|
- type: "mqtt",
|
|
|
|
- addr: "wss://3",
|
|
|
|
|
|
+ type: "http",
|
|
|
|
+ url: "wss://3",
|
|
},
|
|
},
|
|
]);
|
|
]);
|
|
const comColumns = ref([
|
|
const comColumns = ref([
|
|
@@ -891,27 +1028,27 @@ const comOptions = ref<Com[]>([
|
|
{
|
|
{
|
|
name: "连接A",
|
|
name: "连接A",
|
|
type: "mqtt",
|
|
type: "mqtt",
|
|
- addr: "ws://A",
|
|
|
|
|
|
+ url: "ws://A",
|
|
},
|
|
},
|
|
{
|
|
{
|
|
name: "连接B",
|
|
name: "连接B",
|
|
type: "mqtt",
|
|
type: "mqtt",
|
|
- addr: "ws://B",
|
|
|
|
|
|
+ url: "ws://B",
|
|
},
|
|
},
|
|
{
|
|
{
|
|
name: "连接C",
|
|
name: "连接C",
|
|
type: "mqtt",
|
|
type: "mqtt",
|
|
- addr: "ws://C",
|
|
|
|
|
|
+ url: "ws://C",
|
|
},
|
|
},
|
|
{
|
|
{
|
|
name: "连接D",
|
|
name: "连接D",
|
|
type: "mqtt",
|
|
type: "mqtt",
|
|
- addr: "ws://D",
|
|
|
|
|
|
+ url: "ws://D",
|
|
},
|
|
},
|
|
{
|
|
{
|
|
name: "连接E",
|
|
name: "连接E",
|
|
type: "mqtt",
|
|
type: "mqtt",
|
|
- addr: "ws://E",
|
|
|
|
|
|
+ url: "ws://E",
|
|
},
|
|
},
|
|
]);
|
|
]);
|
|
|
|
|
|
@@ -921,19 +1058,79 @@ const onOptionClick = (item: Com) => {
|
|
};
|
|
};
|
|
|
|
|
|
const popupVisible = ref(false);
|
|
const popupVisible = ref(false);
|
|
-const onInputChange = () => {};
|
|
|
|
|
|
+const onInputChange = (e) => {
|
|
|
|
+ console.log("change", e);
|
|
|
|
+};
|
|
const onPopupVisibleChange = (val: boolean) => {
|
|
const onPopupVisibleChange = (val: boolean) => {
|
|
popupVisible.value = val;
|
|
popupVisible.value = val;
|
|
};
|
|
};
|
|
|
|
+
|
|
|
|
+const comType = ref("add"); //or edit
|
|
|
|
+
|
|
|
|
+const addCom = () => {
|
|
|
|
+ comType.value = "add";
|
|
|
|
+ com.value = {
|
|
|
|
+ name: "",
|
|
|
|
+ type: "mqtt", //默认
|
|
|
|
+ url: "",
|
|
|
|
+ options: {
|
|
|
|
+ clientId: "",
|
|
|
|
+ username: "",
|
|
|
|
+ password: "",
|
|
|
|
+ customClientId: false,
|
|
|
|
+ },
|
|
|
|
+ };
|
|
|
|
+ comShow.value = false;
|
|
|
|
+};
|
|
const editCom = (row: Com) => {
|
|
const editCom = (row: Com) => {
|
|
|
|
+ comType.value = "edit";
|
|
com.value = row;
|
|
com.value = row;
|
|
comShow.value = false;
|
|
comShow.value = false;
|
|
};
|
|
};
|
|
|
|
|
|
const deleteCom = (index: number) => {
|
|
const deleteCom = (index: number) => {
|
|
comData.value.splice(index, 1);
|
|
comData.value.splice(index, 1);
|
|
|
|
+ dataToCom(comData.value);
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+//将配置的通信列表转成核心库能识别的格式
|
|
|
|
+const dataToCom = (data: Com[]) => {
|
|
|
|
+ const mqtts: any = [];
|
|
|
|
+ const https: any = [];
|
|
|
|
+ const websockets: any = [];
|
|
|
|
+ data.forEach((item) => {
|
|
|
|
+ if (item.type === "http") {
|
|
|
|
+ https.push({
|
|
|
|
+ http: item.http,
|
|
|
|
+ httpTimeInterval: item.httpTimeInterval,
|
|
|
|
+ httpHeaders: item.httpHeaders,
|
|
|
|
+ method: item.method,
|
|
|
|
+ body: item.body,
|
|
|
|
+ });
|
|
|
|
+ } else if (item.type === "mqtt") {
|
|
|
|
+ mqtts.push({
|
|
|
|
+ url: item.url,
|
|
|
|
+ options: {
|
|
|
|
+ clientId: item.options?.clientId,
|
|
|
|
+ username: item.options?.username,
|
|
|
|
+ password: item.options?.password,
|
|
|
|
+ customClientId: item.options?.customClientId,
|
|
|
|
+ },
|
|
|
|
+ topics: item.topics,
|
|
|
|
+ });
|
|
|
|
+ } else if (item.type === "websocket") {
|
|
|
|
+ websockets.push({
|
|
|
|
+ url: item.url,
|
|
|
|
+ protocols: item.protocols,
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ meta2d.store.data.mqtts = mqtts;
|
|
|
|
+ meta2d.store.data.https = https;
|
|
|
|
+ meta2d.store.data.websockets = websockets;
|
|
|
|
+ //TODO 建立通信连接
|
|
|
|
+ meta2d.connectSocket();
|
|
|
|
+};
|
|
const comShow = ref(true);
|
|
const comShow = ref(true);
|
|
|
|
|
|
const comBack = () => {
|
|
const comBack = () => {
|
|
@@ -943,9 +1140,47 @@ const comBack = () => {
|
|
const com = ref<Com>({
|
|
const com = ref<Com>({
|
|
name: "连接E",
|
|
name: "连接E",
|
|
type: "mqtt",
|
|
type: "mqtt",
|
|
- addr: "ws://E",
|
|
|
|
|
|
+ url: "ws://E",
|
|
|
|
+ options: {
|
|
|
|
+ clientId: "",
|
|
|
|
+ username: "",
|
|
|
|
+ password: "",
|
|
|
|
+ customClientId: false,
|
|
|
|
+ },
|
|
});
|
|
});
|
|
|
|
|
|
|
|
+const comTypeChange = (e: string) => {
|
|
|
|
+ console.log(e, com.value.type);
|
|
|
|
+ if (e === "mqtt") {
|
|
|
|
+ Object.assign(com.value, {
|
|
|
|
+ options: {
|
|
|
|
+ clientId: "",
|
|
|
|
+ username: "",
|
|
|
|
+ password: "",
|
|
|
|
+ customClientId: false,
|
|
|
|
+ },
|
|
|
|
+ });
|
|
|
|
+ } else if (e === "websocket") {
|
|
|
|
+ Object.assign(com.value, {
|
|
|
|
+ protocols: "",
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ Object.assign(com.value, {
|
|
|
|
+ http: "",
|
|
|
|
+ httpTimeInterval: 1000,
|
|
|
|
+ httpHeaders: "",
|
|
|
|
+ method: "GET",
|
|
|
|
+ body: "",
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+const comHttpMethodChange = (e: string) => {
|
|
|
|
+ if (e === "GET") {
|
|
|
|
+ com.value.body = null;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
const dsData = ref([]);
|
|
const dsData = ref([]);
|
|
|
|
|
|
const dsColumns = ref([
|
|
const dsColumns = ref([
|
|
@@ -965,6 +1200,51 @@ const dsColumns = ref([
|
|
ellipsis: true,
|
|
ellipsis: true,
|
|
},
|
|
},
|
|
]);
|
|
]);
|
|
|
|
+
|
|
|
|
+const saveForCurrent = () => {
|
|
|
|
+ comData.value.push(com.value);
|
|
|
|
+ comShow.value = true;
|
|
|
|
+ dataToCom(comData.value);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+const saveToServer = () => {
|
|
|
|
+ //TODO 将com保存到服务器
|
|
|
|
+ comData.value.push(com.value);
|
|
|
|
+ comShow.value = true;
|
|
|
|
+ dataToCom(comData.value);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+const importDataSet = () => {
|
|
|
|
+ importExcel();
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+const downloadDataSet = () => {
|
|
|
|
+ let name = "数据集示例";
|
|
|
|
+ let columns = [
|
|
|
|
+ {
|
|
|
|
+ header: "名称",
|
|
|
|
+ key: "name",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ header: "数据ID",
|
|
|
|
+ key: "id",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ header: "类型",
|
|
|
|
+ key: "type",
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ header: "值",
|
|
|
|
+ key: "value",
|
|
|
|
+ },
|
|
|
|
+ ];
|
|
|
|
+ let data = [
|
|
|
|
+ ["数据集1", "dataId-1", "string", "zzz"],
|
|
|
|
+ ["数据集2", "dataId-2", "boolean", true],
|
|
|
|
+ ["数据集3", "dataId-3", "number", 12],
|
|
|
|
+ ];
|
|
|
|
+ saveAsExcel(name, columns, data);
|
|
|
|
+};
|
|
</script>
|
|
</script>
|
|
<style lang="postcss" scoped>
|
|
<style lang="postcss" scoped>
|
|
.meta2d {
|
|
.meta2d {
|
|
@@ -1016,11 +1296,24 @@ const dsColumns = ref([
|
|
</style>
|
|
</style>
|
|
|
|
|
|
<style lang="postcss">
|
|
<style lang="postcss">
|
|
-
|
|
|
|
.t-dialog {
|
|
.t-dialog {
|
|
- .form-item{
|
|
|
|
- display: flex;
|
|
|
|
-}
|
|
|
|
|
|
+ .t-dialog__body {
|
|
|
|
+ height: 450px;
|
|
|
|
+ /* overflow: auto; */
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .form-item {
|
|
|
|
+ display: flex;
|
|
|
|
+ margin-bottom: 8px;
|
|
|
|
+
|
|
|
|
+ label {
|
|
|
|
+ width: 100px;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .t-textarea {
|
|
|
|
+ width: calc(100% - 150px);
|
|
|
|
+ }
|
|
|
|
+
|
|
.vip-label {
|
|
.vip-label {
|
|
font-size: 10px;
|
|
font-size: 10px;
|
|
background-color: #ff400030;
|
|
background-color: #ff400030;
|
|
@@ -1029,5 +1322,9 @@ const dsColumns = ref([
|
|
margin-left: 4px;
|
|
margin-left: 4px;
|
|
border-radius: 2px;
|
|
border-radius: 2px;
|
|
}
|
|
}
|
|
|
|
+ .t-tab-panel {
|
|
|
|
+ overflow: auto;
|
|
|
|
+ height: 395px;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
</style>
|
|
</style>
|